Completed
Branch BUG-10489-non-trashed-regs-onl... (a7561f)
by
unknown
46:07 queued 34:09
created
core/EE_Load_Espresso_Core.core.php 2 patches
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\core\exceptions\InvalidInterfaceException;
4 4
 use EventEspresso\core\services\loaders\LoaderFactory;
5 5
 
6
-if (! defined('EVENT_ESPRESSO_VERSION')) {
6
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
7 7
     exit('No direct script access allowed');
8 8
 }
9 9
 
@@ -51,7 +51,7 @@  discard block
 block discarded – undo
51 51
      */
52 52
     public function __construct()
53 53
     {
54
-        espresso_load_required('EventEspresso\core\Factory', EE_CORE . 'Factory.php');
54
+        espresso_load_required('EventEspresso\core\Factory', EE_CORE.'Factory.php');
55 55
     }
56 56
 
57 57
 
@@ -105,9 +105,9 @@  discard block
 block discarded – undo
105 105
         $this->_load_class_tools();
106 106
         // load interfaces
107 107
         espresso_load_required('EEI_Payment_Method_Interfaces',
108
-            EE_LIBRARIES . 'payment_methods' . DS . 'EEI_Payment_Method_Interfaces.php');
108
+            EE_LIBRARIES.'payment_methods'.DS.'EEI_Payment_Method_Interfaces.php');
109 109
         // deprecated functions
110
-        espresso_load_required('EE_Deprecated', EE_CORE . 'EE_Deprecated.core.php');
110
+        espresso_load_required('EE_Deprecated', EE_CORE.'EE_Deprecated.core.php');
111 111
         // WP cron jobs
112 112
         $loader->getShared('EE_Cron_Tasks');
113 113
         $loader->getShared('EE_Request_Handler');
@@ -143,7 +143,7 @@  discard block
 block discarded – undo
143 143
      */
144 144
     public function dependency_map()
145 145
     {
146
-        if (! $this->dependency_map instanceof EE_Dependency_Map) {
146
+        if ( ! $this->dependency_map instanceof EE_Dependency_Map) {
147 147
             throw new EE_Error(
148 148
                 sprintf(
149 149
                     __('Invalid EE_Dependency_Map: "%1$s"', 'event_espresso'),
@@ -162,7 +162,7 @@  discard block
 block discarded – undo
162 162
      */
163 163
     public function registry()
164 164
     {
165
-        if (! $this->registry instanceof EE_Registry) {
165
+        if ( ! $this->registry instanceof EE_Registry) {
166 166
             throw new EE_Error(
167 167
                 sprintf(
168 168
                     __('Invalid EE_Registry: "%1$s"', 'event_espresso'),
@@ -180,14 +180,14 @@  discard block
 block discarded – undo
180 180
      */
181 181
     private function _load_dependency_map()
182 182
     {
183
-        if (! is_readable(EE_CORE . 'EE_Dependency_Map.core.php')) {
183
+        if ( ! is_readable(EE_CORE.'EE_Dependency_Map.core.php')) {
184 184
             EE_Error::add_error(
185 185
                 __('The EE_Dependency_Map core class could not be loaded.', 'event_espresso'),
186 186
                 __FILE__, __FUNCTION__, __LINE__
187 187
             );
188 188
             wp_die(EE_Error::get_notices());
189 189
         }
190
-        require_once(EE_CORE . 'EE_Dependency_Map.core.php');
190
+        require_once(EE_CORE.'EE_Dependency_Map.core.php');
191 191
         return EE_Dependency_Map::instance($this->request, $this->response);
192 192
     }
193 193
 
@@ -198,14 +198,14 @@  discard block
 block discarded – undo
198 198
      */
199 199
     private function _load_registry()
200 200
     {
201
-        if (! is_readable(EE_CORE . 'EE_Registry.core.php')) {
201
+        if ( ! is_readable(EE_CORE.'EE_Registry.core.php')) {
202 202
             EE_Error::add_error(
203 203
                 __('The EE_Registry core class could not be loaded.', 'event_espresso'),
204 204
                 __FILE__, __FUNCTION__, __LINE__
205 205
             );
206 206
             wp_die(EE_Error::get_notices());
207 207
         }
208
-        require_once(EE_CORE . 'EE_Registry.core.php');
208
+        require_once(EE_CORE.'EE_Registry.core.php');
209 209
         return EE_Registry::instance($this->dependency_map);
210 210
     }
211 211
 
@@ -216,13 +216,13 @@  discard block
 block discarded – undo
216 216
      */
217 217
     private function _load_class_tools()
218 218
     {
219
-        if (! is_readable(EE_HELPERS . 'EEH_Class_Tools.helper.php')) {
219
+        if ( ! is_readable(EE_HELPERS.'EEH_Class_Tools.helper.php')) {
220 220
             EE_Error::add_error(
221 221
                 __('The EEH_Class_Tools helper could not be loaded.', 'event_espresso'),
222 222
                 __FILE__, __FUNCTION__, __LINE__
223 223
             );
224 224
         }
225
-        require_once(EE_HELPERS . 'EEH_Class_Tools.helper.php');
225
+        require_once(EE_HELPERS.'EEH_Class_Tools.helper.php');
226 226
     }
227 227
 
228 228
 
Please login to merge, or discard this patch.
Indentation   +203 added lines, -203 removed lines patch added patch discarded remove patch
@@ -4,7 +4,7 @@  discard block
 block discarded – undo
4 4
 use EventEspresso\core\services\loaders\LoaderFactory;
5 5
 
6 6
 if (! defined('EVENT_ESPRESSO_VERSION')) {
7
-    exit('No direct script access allowed');
7
+	exit('No direct script access allowed');
8 8
 }
9 9
 
10 10
 
@@ -24,208 +24,208 @@  discard block
 block discarded – undo
24 24
 class EE_Load_Espresso_Core implements EEI_Request_Decorator, EEI_Request_Stack_Core_App
25 25
 {
26 26
 
27
-    /**
28
-     * @var EE_Request $request
29
-     */
30
-    protected $request;
31
-
32
-    /**
33
-     * @var EE_Response $response
34
-     */
35
-    protected $response;
36
-
37
-    /**
38
-     * @var EE_Dependency_Map $dependency_map
39
-     */
40
-    protected $dependency_map;
41
-
42
-    /**
43
-     * @var EE_Registry $registry
44
-     */
45
-    protected $registry;
46
-
47
-
48
-
49
-    /**
50
-     * EE_Load_Espresso_Core constructor
51
-     */
52
-    public function __construct()
53
-    {
54
-        espresso_load_required('EventEspresso\core\Factory', EE_CORE . 'Factory.php');
55
-    }
56
-
57
-
58
-
59
-    /**
60
-     * handle
61
-     * sets hooks for running rest of system
62
-     * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
63
-     * starting EE Addons from any other point may lead to problems
64
-     *
65
-     * @param EE_Request  $request
66
-     * @param EE_Response $response
67
-     * @return EE_Response
68
-     * @throws EE_Error
69
-     * @throws InvalidDataTypeException
70
-     * @throws InvalidInterfaceException
71
-     * @throws InvalidArgumentException
72
-     */
73
-    public function handle_request(EE_Request $request, EE_Response $response)
74
-    {
75
-        $this->request = $request;
76
-        $this->response = $response;
77
-        // info about how to load classes required by other classes
78
-        $this->dependency_map = $this->_load_dependency_map();
79
-        // central repository for classes
80
-        $this->registry = $this->_load_registry();
81
-        // PSR4 Autoloaders
82
-        $this->registry->load_core('EE_Psr4AutoloaderInit');
83
-        do_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading');
84
-        $loader = LoaderFactory::getLoader($this->registry);
85
-        $this->dependency_map->setLoader($loader);
86
-        // build DI container
87
-        // $OpenCoffeeShop = new EventEspresso\core\services\container\OpenCoffeeShop();
88
-        // $OpenCoffeeShop->addRecipes();
89
-        // $CoffeeShop = $OpenCoffeeShop->CoffeeShop();
90
-        // workarounds for PHP < 5.3
91
-        $this->_load_class_tools();
92
-        // load interfaces
93
-        espresso_load_required('EEI_Payment_Method_Interfaces',
94
-            EE_LIBRARIES . 'payment_methods' . DS . 'EEI_Payment_Method_Interfaces.php');
95
-        // deprecated functions
96
-        espresso_load_required('EE_Deprecated', EE_CORE . 'EE_Deprecated.core.php');
97
-        // WP cron jobs
98
-        $loader->getShared('EE_Cron_Tasks');
99
-        $loader->getShared('EE_Request_Handler');
100
-        $loader->getShared('EE_System');
101
-        return $this->response;
102
-    }
103
-
104
-
105
-
106
-    /**
107
-     * @return EE_Request
108
-     */
109
-    public function request()
110
-    {
111
-        return $this->request;
112
-    }
113
-
114
-
115
-
116
-    /**
117
-     * @return EE_Response
118
-     */
119
-    public function response()
120
-    {
121
-        return $this->response;
122
-    }
123
-
124
-
125
-
126
-    /**
127
-     * @return EE_Dependency_Map
128
-     * @throws EE_Error
129
-     */
130
-    public function dependency_map()
131
-    {
132
-        if (! $this->dependency_map instanceof EE_Dependency_Map) {
133
-            throw new EE_Error(
134
-                sprintf(
135
-                    __('Invalid EE_Dependency_Map: "%1$s"', 'event_espresso'),
136
-                    print_r($this->dependency_map, true)
137
-                )
138
-            );
139
-        }
140
-        return $this->dependency_map;
141
-    }
142
-
143
-
144
-
145
-    /**
146
-     * @return EE_Registry
147
-     * @throws EE_Error
148
-     */
149
-    public function registry()
150
-    {
151
-        if (! $this->registry instanceof EE_Registry) {
152
-            throw new EE_Error(
153
-                sprintf(
154
-                    __('Invalid EE_Registry: "%1$s"', 'event_espresso'),
155
-                    print_r($this->registry, true)
156
-                )
157
-            );
158
-        }
159
-        return $this->registry;
160
-    }
161
-
162
-
163
-
164
-    /**
165
-     * @return EE_Dependency_Map
166
-     */
167
-    private function _load_dependency_map()
168
-    {
169
-        if (! is_readable(EE_CORE . 'EE_Dependency_Map.core.php')) {
170
-            EE_Error::add_error(
171
-                __('The EE_Dependency_Map core class could not be loaded.', 'event_espresso'),
172
-                __FILE__, __FUNCTION__, __LINE__
173
-            );
174
-            wp_die(EE_Error::get_notices());
175
-        }
176
-        require_once(EE_CORE . 'EE_Dependency_Map.core.php');
177
-        return EE_Dependency_Map::instance($this->request, $this->response);
178
-    }
179
-
180
-
181
-
182
-    /**
183
-     * @return EE_Registry
184
-     */
185
-    private function _load_registry()
186
-    {
187
-        if (! is_readable(EE_CORE . 'EE_Registry.core.php')) {
188
-            EE_Error::add_error(
189
-                __('The EE_Registry core class could not be loaded.', 'event_espresso'),
190
-                __FILE__, __FUNCTION__, __LINE__
191
-            );
192
-            wp_die(EE_Error::get_notices());
193
-        }
194
-        require_once(EE_CORE . 'EE_Registry.core.php');
195
-        return EE_Registry::instance($this->dependency_map);
196
-    }
197
-
198
-
199
-
200
-    /**
201
-     * @return void
202
-     */
203
-    private function _load_class_tools()
204
-    {
205
-        if (! is_readable(EE_HELPERS . 'EEH_Class_Tools.helper.php')) {
206
-            EE_Error::add_error(
207
-                __('The EEH_Class_Tools helper could not be loaded.', 'event_espresso'),
208
-                __FILE__, __FUNCTION__, __LINE__
209
-            );
210
-        }
211
-        require_once(EE_HELPERS . 'EEH_Class_Tools.helper.php');
212
-    }
213
-
214
-
215
-
216
-    /**
217
-     * called after the request stack has been fully processed
218
-     * if any of the middleware apps has requested the plugin be deactivated, then we do that now
219
-     *
220
-     * @param EE_Request  $request
221
-     * @param EE_Response $response
222
-     */
223
-    public function handle_response(EE_Request $request, EE_Response $response)
224
-    {
225
-        if ($response->plugin_deactivated()) {
226
-            espresso_deactivate_plugin(EE_PLUGIN_BASENAME);
227
-        }
228
-    }
27
+	/**
28
+	 * @var EE_Request $request
29
+	 */
30
+	protected $request;
31
+
32
+	/**
33
+	 * @var EE_Response $response
34
+	 */
35
+	protected $response;
36
+
37
+	/**
38
+	 * @var EE_Dependency_Map $dependency_map
39
+	 */
40
+	protected $dependency_map;
41
+
42
+	/**
43
+	 * @var EE_Registry $registry
44
+	 */
45
+	protected $registry;
46
+
47
+
48
+
49
+	/**
50
+	 * EE_Load_Espresso_Core constructor
51
+	 */
52
+	public function __construct()
53
+	{
54
+		espresso_load_required('EventEspresso\core\Factory', EE_CORE . 'Factory.php');
55
+	}
56
+
57
+
58
+
59
+	/**
60
+	 * handle
61
+	 * sets hooks for running rest of system
62
+	 * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
63
+	 * starting EE Addons from any other point may lead to problems
64
+	 *
65
+	 * @param EE_Request  $request
66
+	 * @param EE_Response $response
67
+	 * @return EE_Response
68
+	 * @throws EE_Error
69
+	 * @throws InvalidDataTypeException
70
+	 * @throws InvalidInterfaceException
71
+	 * @throws InvalidArgumentException
72
+	 */
73
+	public function handle_request(EE_Request $request, EE_Response $response)
74
+	{
75
+		$this->request = $request;
76
+		$this->response = $response;
77
+		// info about how to load classes required by other classes
78
+		$this->dependency_map = $this->_load_dependency_map();
79
+		// central repository for classes
80
+		$this->registry = $this->_load_registry();
81
+		// PSR4 Autoloaders
82
+		$this->registry->load_core('EE_Psr4AutoloaderInit');
83
+		do_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading');
84
+		$loader = LoaderFactory::getLoader($this->registry);
85
+		$this->dependency_map->setLoader($loader);
86
+		// build DI container
87
+		// $OpenCoffeeShop = new EventEspresso\core\services\container\OpenCoffeeShop();
88
+		// $OpenCoffeeShop->addRecipes();
89
+		// $CoffeeShop = $OpenCoffeeShop->CoffeeShop();
90
+		// workarounds for PHP < 5.3
91
+		$this->_load_class_tools();
92
+		// load interfaces
93
+		espresso_load_required('EEI_Payment_Method_Interfaces',
94
+			EE_LIBRARIES . 'payment_methods' . DS . 'EEI_Payment_Method_Interfaces.php');
95
+		// deprecated functions
96
+		espresso_load_required('EE_Deprecated', EE_CORE . 'EE_Deprecated.core.php');
97
+		// WP cron jobs
98
+		$loader->getShared('EE_Cron_Tasks');
99
+		$loader->getShared('EE_Request_Handler');
100
+		$loader->getShared('EE_System');
101
+		return $this->response;
102
+	}
103
+
104
+
105
+
106
+	/**
107
+	 * @return EE_Request
108
+	 */
109
+	public function request()
110
+	{
111
+		return $this->request;
112
+	}
113
+
114
+
115
+
116
+	/**
117
+	 * @return EE_Response
118
+	 */
119
+	public function response()
120
+	{
121
+		return $this->response;
122
+	}
123
+
124
+
125
+
126
+	/**
127
+	 * @return EE_Dependency_Map
128
+	 * @throws EE_Error
129
+	 */
130
+	public function dependency_map()
131
+	{
132
+		if (! $this->dependency_map instanceof EE_Dependency_Map) {
133
+			throw new EE_Error(
134
+				sprintf(
135
+					__('Invalid EE_Dependency_Map: "%1$s"', 'event_espresso'),
136
+					print_r($this->dependency_map, true)
137
+				)
138
+			);
139
+		}
140
+		return $this->dependency_map;
141
+	}
142
+
143
+
144
+
145
+	/**
146
+	 * @return EE_Registry
147
+	 * @throws EE_Error
148
+	 */
149
+	public function registry()
150
+	{
151
+		if (! $this->registry instanceof EE_Registry) {
152
+			throw new EE_Error(
153
+				sprintf(
154
+					__('Invalid EE_Registry: "%1$s"', 'event_espresso'),
155
+					print_r($this->registry, true)
156
+				)
157
+			);
158
+		}
159
+		return $this->registry;
160
+	}
161
+
162
+
163
+
164
+	/**
165
+	 * @return EE_Dependency_Map
166
+	 */
167
+	private function _load_dependency_map()
168
+	{
169
+		if (! is_readable(EE_CORE . 'EE_Dependency_Map.core.php')) {
170
+			EE_Error::add_error(
171
+				__('The EE_Dependency_Map core class could not be loaded.', 'event_espresso'),
172
+				__FILE__, __FUNCTION__, __LINE__
173
+			);
174
+			wp_die(EE_Error::get_notices());
175
+		}
176
+		require_once(EE_CORE . 'EE_Dependency_Map.core.php');
177
+		return EE_Dependency_Map::instance($this->request, $this->response);
178
+	}
179
+
180
+
181
+
182
+	/**
183
+	 * @return EE_Registry
184
+	 */
185
+	private function _load_registry()
186
+	{
187
+		if (! is_readable(EE_CORE . 'EE_Registry.core.php')) {
188
+			EE_Error::add_error(
189
+				__('The EE_Registry core class could not be loaded.', 'event_espresso'),
190
+				__FILE__, __FUNCTION__, __LINE__
191
+			);
192
+			wp_die(EE_Error::get_notices());
193
+		}
194
+		require_once(EE_CORE . 'EE_Registry.core.php');
195
+		return EE_Registry::instance($this->dependency_map);
196
+	}
197
+
198
+
199
+
200
+	/**
201
+	 * @return void
202
+	 */
203
+	private function _load_class_tools()
204
+	{
205
+		if (! is_readable(EE_HELPERS . 'EEH_Class_Tools.helper.php')) {
206
+			EE_Error::add_error(
207
+				__('The EEH_Class_Tools helper could not be loaded.', 'event_espresso'),
208
+				__FILE__, __FUNCTION__, __LINE__
209
+			);
210
+		}
211
+		require_once(EE_HELPERS . 'EEH_Class_Tools.helper.php');
212
+	}
213
+
214
+
215
+
216
+	/**
217
+	 * called after the request stack has been fully processed
218
+	 * if any of the middleware apps has requested the plugin be deactivated, then we do that now
219
+	 *
220
+	 * @param EE_Request  $request
221
+	 * @param EE_Response $response
222
+	 */
223
+	public function handle_response(EE_Request $request, EE_Response $response)
224
+	{
225
+		if ($response->plugin_deactivated()) {
226
+			espresso_deactivate_plugin(EE_PLUGIN_BASENAME);
227
+		}
228
+	}
229 229
 
230 230
 
231 231
 
Please login to merge, or discard this patch.
core/db_models/EEM_Transaction.model.php 2 patches
Indentation   +363 added lines, -363 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
4
-    exit('No direct script access allowed');
4
+	exit('No direct script access allowed');
5 5
 }
6 6
 require_once(EE_MODELS . 'EEM_Base.model.php');
7 7
 
@@ -17,193 +17,193 @@  discard block
 block discarded – undo
17 17
 class EEM_Transaction extends EEM_Base
18 18
 {
19 19
 
20
-    // private instance of the Transaction object
21
-    protected static $_instance;
22
-
23
-    /**
24
-     * Status ID(STS_ID on esp_status table) to indicate the transaction is complete,
25
-     * but payment is pending. This is the state for transactions where payment is promised
26
-     * from an offline gateway.
27
-     */
28
-    //	const open_status_code = 'TPN';
29
-
30
-    /**
31
-     * Status ID(STS_ID on esp_status table) to indicate the transaction failed,
32
-     * either due to a technical reason (server or computer crash during registration),
33
-     *  or some other reason that prevent the collection of any useful contact information from any of the registrants
34
-     */
35
-    const failed_status_code = 'TFL';
36
-
37
-    /**
38
-     * Status ID(STS_ID on esp_status table) to indicate the transaction was abandoned,
39
-     * either due to a technical reason (server or computer crash during registration),
40
-     * or due to an abandoned cart after registrant chose not to complete the registration process
41
-     * HOWEVER...
42
-     * an abandoned TXN differs from a failed TXN in that it was able to capture contact information for at least one
43
-     * registrant
44
-     */
45
-    const abandoned_status_code = 'TAB';
46
-
47
-    /**
48
-     * Status ID(STS_ID on esp_status table) to indicate an incomplete transaction,
49
-     * meaning that monies are still owing: TXN_paid < TXN_total
50
-     */
51
-    const incomplete_status_code = 'TIN';
52
-
53
-    /**
54
-     * Status ID (STS_ID on esp_status table) to indicate a complete transaction.
55
-     * meaning that NO monies are owing: TXN_paid == TXN_total
56
-     */
57
-    const complete_status_code = 'TCM';
58
-
59
-    /**
60
-     *  Status ID(STS_ID on esp_status table) to indicate the transaction is overpaid.
61
-     *  This is the same as complete, but site admins actually owe clients the moneys!  TXN_paid > TXN_total
62
-     */
63
-    const overpaid_status_code = 'TOP';
64
-
65
-
66
-    /**
67
-     *    private constructor to prevent direct creation
68
-     *
69
-     * @Constructor
70
-     * @access protected
71
-     *
72
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
73
-     *                         incoming timezone data that gets saved). Note this just sends the timezone info to the
74
-     *                         date time model field objects.  Default is NULL (and will be assumed using the set
75
-     *                         timezone in the 'timezone_string' wp option)
76
-     *
77
-     * @return EEM_Transaction
78
-     * @throws \EE_Error
79
-     */
80
-    protected function __construct($timezone)
81
-    {
82
-        $this->singular_item = __('Transaction', 'event_espresso');
83
-        $this->plural_item   = __('Transactions', 'event_espresso');
84
-
85
-        $this->_tables                 = array(
86
-            'TransactionTable' => new EE_Primary_Table('esp_transaction', 'TXN_ID')
87
-        );
88
-        $this->_fields                 = array(
89
-            'TransactionTable' => array(
90
-                'TXN_ID'           => new EE_Primary_Key_Int_Field('TXN_ID', __('Transaction ID', 'event_espresso')),
91
-                'TXN_timestamp'    => new EE_Datetime_Field('TXN_timestamp',
92
-                    __('date when transaction was created', 'event_espresso'), false, EE_Datetime_Field::now,
93
-                    $timezone),
94
-                'TXN_total'        => new EE_Money_Field('TXN_total',
95
-                    __('Total value of Transaction', 'event_espresso'), false, 0),
96
-                'TXN_paid'         => new EE_Money_Field('TXN_paid',
97
-                    __('Amount paid towards transaction to date', 'event_espresso'), false, 0),
98
-                'STS_ID'           => new EE_Foreign_Key_String_Field('STS_ID', __('Status ID', 'event_espresso'),
99
-                    false, EEM_Transaction::failed_status_code, 'Status'),
100
-                'TXN_session_data' => new EE_Serialized_Text_Field('TXN_session_data',
101
-                    __('Serialized session data', 'event_espresso'), true, ''),
102
-                'TXN_hash_salt'    => new EE_Plain_Text_Field('TXN_hash_salt',
103
-                    __('Transaction Hash Salt', 'event_espresso'), true, ''),
104
-                'PMD_ID'           => new EE_Foreign_Key_Int_Field('PMD_ID',
105
-                    __("Last Used Payment Method", 'event_espresso'), true, null, 'Payment_Method'),
106
-                'TXN_reg_steps'    => new EE_Serialized_Text_Field('TXN_reg_steps',
107
-                    __('Registration Steps', 'event_espresso'), false, array()),
108
-            )
109
-        );
110
-        $this->_model_relations        = array(
111
-            'Registration'   => new EE_Has_Many_Relation(),
112
-            'Payment'        => new EE_Has_Many_Relation(),
113
-            'Status'         => new EE_Belongs_To_Relation(),
114
-            'Line_Item'      => new EE_Has_Many_Relation(false),
115
-            //you can delete a transaction without needing to delete its line items
116
-            'Payment_Method' => new EE_Belongs_To_Relation(),
117
-            'Message'        => new EE_Has_Many_Relation()
118
-        );
119
-        $this->_model_chain_to_wp_user = 'Registration.Event';
120
-        parent::__construct($timezone);
121
-
122
-    }
123
-
124
-
125
-    /**
126
-     *    txn_status_array
127
-     * get list of transaction statuses
128
-     *
129
-     * @access public
130
-     * @return array
131
-     */
132
-    public static function txn_status_array()
133
-    {
134
-        return apply_filters(
135
-            'FHEE__EEM_Transaction__txn_status_array',
136
-            array(
137
-                EEM_Transaction::overpaid_status_code,
138
-                EEM_Transaction::complete_status_code,
139
-                EEM_Transaction::incomplete_status_code,
140
-                EEM_Transaction::abandoned_status_code,
141
-                EEM_Transaction::failed_status_code,
142
-            )
143
-        );
144
-    }
145
-
146
-    /**
147
-     *        get the revenue per day  for the Transaction Admin page Reports Tab
148
-     *
149
-     * @access        public
150
-     *
151
-     * @param string $period
152
-     *
153
-     * @return \stdClass[]
154
-     */
155
-    public function get_revenue_per_day_report($period = '-1 month')
156
-    {
157
-        $sql_date = $this->convert_datetime_for_query('TXN_timestamp', date('Y-m-d H:i:s', strtotime($period)),
158
-            'Y-m-d H:i:s', 'UTC');
159
-
160
-        $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'TXN_timestamp');
161
-
162
-        return $this->_get_all_wpdb_results(
163
-            array(
164
-                array(
165
-                    'TXN_timestamp' => array('>=', $sql_date)
166
-                ),
167
-                'group_by' => 'txnDate',
168
-                'order_by' => array('TXN_timestamp' => 'ASC')
169
-            ),
170
-            OBJECT,
171
-            array(
172
-                'txnDate' => array('DATE(' . $query_interval . ')', '%s'),
173
-                'revenue' => array('SUM(TransactionTable.TXN_paid)', '%d')
174
-            )
175
-        );
176
-    }
177
-
178
-
179
-    /**
180
-     *        get the revenue per event  for the Transaction Admin page Reports Tab
181
-     *
182
-     * @access        public
183
-     *
184
-     * @param string $period
185
-     *
186
-     * @throws \EE_Error
187
-     * @return mixed
188
-     */
189
-    public function get_revenue_per_event_report($period = '-1 month')
190
-    {
191
-        global $wpdb;
192
-        $transaction_table          = $wpdb->prefix . 'esp_transaction';
193
-        $registration_table         = $wpdb->prefix . 'esp_registration';
194
-        $registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
195
-        $event_table                = $wpdb->posts;
196
-        $payment_table              = $wpdb->prefix . 'esp_payment';
197
-        $sql_date                   = date('Y-m-d H:i:s', strtotime($period));
198
-        $approved_payment_status    = EEM_Payment::status_id_approved;
199
-        $extra_event_on_join        = '';
200
-        //exclude events not authored by user if permissions in effect
201
-        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
202
-            $extra_event_on_join = ' AND Event.post_author = ' . get_current_user_id();
203
-        }
204
-
205
-        return $wpdb->get_results(
206
-            "SELECT
20
+	// private instance of the Transaction object
21
+	protected static $_instance;
22
+
23
+	/**
24
+	 * Status ID(STS_ID on esp_status table) to indicate the transaction is complete,
25
+	 * but payment is pending. This is the state for transactions where payment is promised
26
+	 * from an offline gateway.
27
+	 */
28
+	//	const open_status_code = 'TPN';
29
+
30
+	/**
31
+	 * Status ID(STS_ID on esp_status table) to indicate the transaction failed,
32
+	 * either due to a technical reason (server or computer crash during registration),
33
+	 *  or some other reason that prevent the collection of any useful contact information from any of the registrants
34
+	 */
35
+	const failed_status_code = 'TFL';
36
+
37
+	/**
38
+	 * Status ID(STS_ID on esp_status table) to indicate the transaction was abandoned,
39
+	 * either due to a technical reason (server or computer crash during registration),
40
+	 * or due to an abandoned cart after registrant chose not to complete the registration process
41
+	 * HOWEVER...
42
+	 * an abandoned TXN differs from a failed TXN in that it was able to capture contact information for at least one
43
+	 * registrant
44
+	 */
45
+	const abandoned_status_code = 'TAB';
46
+
47
+	/**
48
+	 * Status ID(STS_ID on esp_status table) to indicate an incomplete transaction,
49
+	 * meaning that monies are still owing: TXN_paid < TXN_total
50
+	 */
51
+	const incomplete_status_code = 'TIN';
52
+
53
+	/**
54
+	 * Status ID (STS_ID on esp_status table) to indicate a complete transaction.
55
+	 * meaning that NO monies are owing: TXN_paid == TXN_total
56
+	 */
57
+	const complete_status_code = 'TCM';
58
+
59
+	/**
60
+	 *  Status ID(STS_ID on esp_status table) to indicate the transaction is overpaid.
61
+	 *  This is the same as complete, but site admins actually owe clients the moneys!  TXN_paid > TXN_total
62
+	 */
63
+	const overpaid_status_code = 'TOP';
64
+
65
+
66
+	/**
67
+	 *    private constructor to prevent direct creation
68
+	 *
69
+	 * @Constructor
70
+	 * @access protected
71
+	 *
72
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
73
+	 *                         incoming timezone data that gets saved). Note this just sends the timezone info to the
74
+	 *                         date time model field objects.  Default is NULL (and will be assumed using the set
75
+	 *                         timezone in the 'timezone_string' wp option)
76
+	 *
77
+	 * @return EEM_Transaction
78
+	 * @throws \EE_Error
79
+	 */
80
+	protected function __construct($timezone)
81
+	{
82
+		$this->singular_item = __('Transaction', 'event_espresso');
83
+		$this->plural_item   = __('Transactions', 'event_espresso');
84
+
85
+		$this->_tables                 = array(
86
+			'TransactionTable' => new EE_Primary_Table('esp_transaction', 'TXN_ID')
87
+		);
88
+		$this->_fields                 = array(
89
+			'TransactionTable' => array(
90
+				'TXN_ID'           => new EE_Primary_Key_Int_Field('TXN_ID', __('Transaction ID', 'event_espresso')),
91
+				'TXN_timestamp'    => new EE_Datetime_Field('TXN_timestamp',
92
+					__('date when transaction was created', 'event_espresso'), false, EE_Datetime_Field::now,
93
+					$timezone),
94
+				'TXN_total'        => new EE_Money_Field('TXN_total',
95
+					__('Total value of Transaction', 'event_espresso'), false, 0),
96
+				'TXN_paid'         => new EE_Money_Field('TXN_paid',
97
+					__('Amount paid towards transaction to date', 'event_espresso'), false, 0),
98
+				'STS_ID'           => new EE_Foreign_Key_String_Field('STS_ID', __('Status ID', 'event_espresso'),
99
+					false, EEM_Transaction::failed_status_code, 'Status'),
100
+				'TXN_session_data' => new EE_Serialized_Text_Field('TXN_session_data',
101
+					__('Serialized session data', 'event_espresso'), true, ''),
102
+				'TXN_hash_salt'    => new EE_Plain_Text_Field('TXN_hash_salt',
103
+					__('Transaction Hash Salt', 'event_espresso'), true, ''),
104
+				'PMD_ID'           => new EE_Foreign_Key_Int_Field('PMD_ID',
105
+					__("Last Used Payment Method", 'event_espresso'), true, null, 'Payment_Method'),
106
+				'TXN_reg_steps'    => new EE_Serialized_Text_Field('TXN_reg_steps',
107
+					__('Registration Steps', 'event_espresso'), false, array()),
108
+			)
109
+		);
110
+		$this->_model_relations        = array(
111
+			'Registration'   => new EE_Has_Many_Relation(),
112
+			'Payment'        => new EE_Has_Many_Relation(),
113
+			'Status'         => new EE_Belongs_To_Relation(),
114
+			'Line_Item'      => new EE_Has_Many_Relation(false),
115
+			//you can delete a transaction without needing to delete its line items
116
+			'Payment_Method' => new EE_Belongs_To_Relation(),
117
+			'Message'        => new EE_Has_Many_Relation()
118
+		);
119
+		$this->_model_chain_to_wp_user = 'Registration.Event';
120
+		parent::__construct($timezone);
121
+
122
+	}
123
+
124
+
125
+	/**
126
+	 *    txn_status_array
127
+	 * get list of transaction statuses
128
+	 *
129
+	 * @access public
130
+	 * @return array
131
+	 */
132
+	public static function txn_status_array()
133
+	{
134
+		return apply_filters(
135
+			'FHEE__EEM_Transaction__txn_status_array',
136
+			array(
137
+				EEM_Transaction::overpaid_status_code,
138
+				EEM_Transaction::complete_status_code,
139
+				EEM_Transaction::incomplete_status_code,
140
+				EEM_Transaction::abandoned_status_code,
141
+				EEM_Transaction::failed_status_code,
142
+			)
143
+		);
144
+	}
145
+
146
+	/**
147
+	 *        get the revenue per day  for the Transaction Admin page Reports Tab
148
+	 *
149
+	 * @access        public
150
+	 *
151
+	 * @param string $period
152
+	 *
153
+	 * @return \stdClass[]
154
+	 */
155
+	public function get_revenue_per_day_report($period = '-1 month')
156
+	{
157
+		$sql_date = $this->convert_datetime_for_query('TXN_timestamp', date('Y-m-d H:i:s', strtotime($period)),
158
+			'Y-m-d H:i:s', 'UTC');
159
+
160
+		$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'TXN_timestamp');
161
+
162
+		return $this->_get_all_wpdb_results(
163
+			array(
164
+				array(
165
+					'TXN_timestamp' => array('>=', $sql_date)
166
+				),
167
+				'group_by' => 'txnDate',
168
+				'order_by' => array('TXN_timestamp' => 'ASC')
169
+			),
170
+			OBJECT,
171
+			array(
172
+				'txnDate' => array('DATE(' . $query_interval . ')', '%s'),
173
+				'revenue' => array('SUM(TransactionTable.TXN_paid)', '%d')
174
+			)
175
+		);
176
+	}
177
+
178
+
179
+	/**
180
+	 *        get the revenue per event  for the Transaction Admin page Reports Tab
181
+	 *
182
+	 * @access        public
183
+	 *
184
+	 * @param string $period
185
+	 *
186
+	 * @throws \EE_Error
187
+	 * @return mixed
188
+	 */
189
+	public function get_revenue_per_event_report($period = '-1 month')
190
+	{
191
+		global $wpdb;
192
+		$transaction_table          = $wpdb->prefix . 'esp_transaction';
193
+		$registration_table         = $wpdb->prefix . 'esp_registration';
194
+		$registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
195
+		$event_table                = $wpdb->posts;
196
+		$payment_table              = $wpdb->prefix . 'esp_payment';
197
+		$sql_date                   = date('Y-m-d H:i:s', strtotime($period));
198
+		$approved_payment_status    = EEM_Payment::status_id_approved;
199
+		$extra_event_on_join        = '';
200
+		//exclude events not authored by user if permissions in effect
201
+		if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
202
+			$extra_event_on_join = ' AND Event.post_author = ' . get_current_user_id();
203
+		}
204
+
205
+		return $wpdb->get_results(
206
+			"SELECT
207 207
 			Transaction_Event.event_name AS event_name,
208 208
 			SUM(Transaction_Event.paid) AS revenue
209 209
 			FROM
@@ -230,185 +230,185 @@  discard block
 block discarded – undo
230 230
 					$extra_event_on_join
231 231
 				) AS Transaction_Event
232 232
 			GROUP BY event_name",
233
-            OBJECT
234
-        );
235
-    }
236
-
237
-
238
-    /**
239
-     * Gets the current transaction given the reg_url_link, or assumes the reg_url_link is in the
240
-     * $_REQUEST global variable. Either way, tries to find the current transaction (through
241
-     * the registration pointed to by reg_url_link), if not returns null
242
-     *
243
-     * @param string $reg_url_link
244
-     *
245
-     * @return EE_Transaction
246
-     */
247
-    public function get_transaction_from_reg_url_link($reg_url_link = '')
248
-    {
249
-        return $this->get_one(array(
250
-            array(
251
-                'Registration.REG_url_link' => ! empty($reg_url_link) ? $reg_url_link : EE_Registry::instance()->REQ->get('e_reg_url_link',
252
-                    '')
253
-            )
254
-        ));
255
-    }
256
-
257
-
258
-    /**
259
-     * Updates the provided EE_Transaction with all the applicable payments
260
-     * (or fetch the EE_Transaction from its ID)
261
-     *
262
-     * @deprecated
263
-     *
264
-     * @param EE_Transaction|int $transaction_obj_or_id
265
-     * @param boolean            $save_txn whether or not to save the transaction during this function call
266
-     *
267
-     * @return boolean
268
-     * @throws \EE_Error
269
-     */
270
-    public function update_based_on_payments($transaction_obj_or_id, $save_txn = true)
271
-    {
272
-        EE_Error::doing_it_wrong(
273
-            __CLASS__ . '::' . __FUNCTION__,
274
-            sprintf(__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
275
-                'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'),
276
-            '4.6.0'
277
-        );
278
-        /** @type EE_Transaction_Processor $transaction_processor */
279
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
280
-
281
-        return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
282
-            $this->ensure_is_obj($transaction_obj_or_id)
283
-        );
284
-    }
285
-
286
-    /**
287
-     * Deletes "junk" transactions that were probably added by bots. There might be TONS
288
-     * of these, so we are very careful to NOT select (which the models do even when deleting),
289
-     * and so we only use wpdb directly and only do minimal joins.
290
-     * Transactions are considered "junk" if they're failed for longer than a week.
291
-     * Also, there is an extra check for payments related to the transaction, because if a transaction has a payment on
292
-     * it, it's probably not junk (regardless of what status it has).
293
-     * The downside to this approach is that is addons are listening for object deletions
294
-     * on EEM_Base::delete() they won't be notified of this.  However, there is an action that plugins can hook into
295
-     * to catch these types of deletions.
296
-     *
297
-     * @global WPDB $wpdb
298
-     * @return mixed
299
-     */
300
-    public function delete_junk_transactions()
301
-    {
302
-        /** @type WPDB $wpdb */
303
-        global $wpdb;
304
-        $deleted             = false;
305
-        $time_to_leave_alone = apply_filters(
306
-            'FHEE__EEM_Transaction__delete_junk_transactions__time_to_leave_alone'
307
-            , WEEK_IN_SECONDS
308
-        );
309
-
310
-
311
-        /**
312
-         * This allows code to filter the query arguments used for retrieving the transaction IDs to delete.
313
-         * Useful for plugins that want to exclude transactions matching certain query parameters.
314
-         * The query parameters should be in the format accepted by the EEM_Base model queries.
315
-         */
316
-        $ids_query = apply_filters(
317
-            'FHEE__EEM_Transaction__delete_junk_transactions__initial_query_args',
318
-            array(
319
-                0 => array(
320
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
321
-                    'Payment.PAY_ID' => array( 'IS NULL' ),
322
-                    'TXN_timestamp' => array('<', time() - $time_to_leave_alone)
323
-                )
324
-            ),
325
-            $time_to_leave_alone
326
-        );
327
-
328
-
329
-        /**
330
-         * This filter is for when code needs to filter the list of transaction ids that represent transactions
331
-         * about to be deleted based on some other criteria that isn't easily done via the query args filter.
332
-         */
333
-        $txn_ids = apply_filters(
334
-            'FHEE__EEM_Transaction__delete_junk_transactions__transaction_ids_to_delete',
335
-            EEM_Transaction::instance()->get_col($ids_query, 'TXN_ID'),
336
-            $time_to_leave_alone
337
-        );
338
-        //now that we have the ids to delete
339
-        if (! empty($txn_ids) && is_array($txn_ids)) {
340
-            // first, make sure these TXN's are removed the "ee_locked_transactions" array
341
-            EEM_Transaction::unset_locked_transactions($txn_ids);
342
-            // let's get deletin'...
343
-            // Why no wpdb->prepare?  Because the data is trusted.
344
-            // We got the ids from the original query to get them FROM
345
-            // the db (which is sanitized) so no need to prepare them again.
346
-            $query   = '
233
+			OBJECT
234
+		);
235
+	}
236
+
237
+
238
+	/**
239
+	 * Gets the current transaction given the reg_url_link, or assumes the reg_url_link is in the
240
+	 * $_REQUEST global variable. Either way, tries to find the current transaction (through
241
+	 * the registration pointed to by reg_url_link), if not returns null
242
+	 *
243
+	 * @param string $reg_url_link
244
+	 *
245
+	 * @return EE_Transaction
246
+	 */
247
+	public function get_transaction_from_reg_url_link($reg_url_link = '')
248
+	{
249
+		return $this->get_one(array(
250
+			array(
251
+				'Registration.REG_url_link' => ! empty($reg_url_link) ? $reg_url_link : EE_Registry::instance()->REQ->get('e_reg_url_link',
252
+					'')
253
+			)
254
+		));
255
+	}
256
+
257
+
258
+	/**
259
+	 * Updates the provided EE_Transaction with all the applicable payments
260
+	 * (or fetch the EE_Transaction from its ID)
261
+	 *
262
+	 * @deprecated
263
+	 *
264
+	 * @param EE_Transaction|int $transaction_obj_or_id
265
+	 * @param boolean            $save_txn whether or not to save the transaction during this function call
266
+	 *
267
+	 * @return boolean
268
+	 * @throws \EE_Error
269
+	 */
270
+	public function update_based_on_payments($transaction_obj_or_id, $save_txn = true)
271
+	{
272
+		EE_Error::doing_it_wrong(
273
+			__CLASS__ . '::' . __FUNCTION__,
274
+			sprintf(__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
275
+				'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'),
276
+			'4.6.0'
277
+		);
278
+		/** @type EE_Transaction_Processor $transaction_processor */
279
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
280
+
281
+		return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
282
+			$this->ensure_is_obj($transaction_obj_or_id)
283
+		);
284
+	}
285
+
286
+	/**
287
+	 * Deletes "junk" transactions that were probably added by bots. There might be TONS
288
+	 * of these, so we are very careful to NOT select (which the models do even when deleting),
289
+	 * and so we only use wpdb directly and only do minimal joins.
290
+	 * Transactions are considered "junk" if they're failed for longer than a week.
291
+	 * Also, there is an extra check for payments related to the transaction, because if a transaction has a payment on
292
+	 * it, it's probably not junk (regardless of what status it has).
293
+	 * The downside to this approach is that is addons are listening for object deletions
294
+	 * on EEM_Base::delete() they won't be notified of this.  However, there is an action that plugins can hook into
295
+	 * to catch these types of deletions.
296
+	 *
297
+	 * @global WPDB $wpdb
298
+	 * @return mixed
299
+	 */
300
+	public function delete_junk_transactions()
301
+	{
302
+		/** @type WPDB $wpdb */
303
+		global $wpdb;
304
+		$deleted             = false;
305
+		$time_to_leave_alone = apply_filters(
306
+			'FHEE__EEM_Transaction__delete_junk_transactions__time_to_leave_alone'
307
+			, WEEK_IN_SECONDS
308
+		);
309
+
310
+
311
+		/**
312
+		 * This allows code to filter the query arguments used for retrieving the transaction IDs to delete.
313
+		 * Useful for plugins that want to exclude transactions matching certain query parameters.
314
+		 * The query parameters should be in the format accepted by the EEM_Base model queries.
315
+		 */
316
+		$ids_query = apply_filters(
317
+			'FHEE__EEM_Transaction__delete_junk_transactions__initial_query_args',
318
+			array(
319
+				0 => array(
320
+					'STS_ID'        => EEM_Transaction::failed_status_code,
321
+					'Payment.PAY_ID' => array( 'IS NULL' ),
322
+					'TXN_timestamp' => array('<', time() - $time_to_leave_alone)
323
+				)
324
+			),
325
+			$time_to_leave_alone
326
+		);
327
+
328
+
329
+		/**
330
+		 * This filter is for when code needs to filter the list of transaction ids that represent transactions
331
+		 * about to be deleted based on some other criteria that isn't easily done via the query args filter.
332
+		 */
333
+		$txn_ids = apply_filters(
334
+			'FHEE__EEM_Transaction__delete_junk_transactions__transaction_ids_to_delete',
335
+			EEM_Transaction::instance()->get_col($ids_query, 'TXN_ID'),
336
+			$time_to_leave_alone
337
+		);
338
+		//now that we have the ids to delete
339
+		if (! empty($txn_ids) && is_array($txn_ids)) {
340
+			// first, make sure these TXN's are removed the "ee_locked_transactions" array
341
+			EEM_Transaction::unset_locked_transactions($txn_ids);
342
+			// let's get deletin'...
343
+			// Why no wpdb->prepare?  Because the data is trusted.
344
+			// We got the ids from the original query to get them FROM
345
+			// the db (which is sanitized) so no need to prepare them again.
346
+			$query   = '
347 347
 				DELETE
348 348
 				FROM ' . $this->table() . '
349 349
 				WHERE
350 350
 					TXN_ID IN ( ' . implode(",", $txn_ids) . ')';
351
-            $deleted = $wpdb->query($query);
352
-        }
353
-        if ($deleted) {
354
-            /**
355
-             * Allows code to do something after the transactions have been deleted.
356
-             */
357
-            do_action('AHEE__EEM_Transaction__delete_junk_transactions__successful_deletion', $txn_ids);
358
-        }
359
-
360
-        return $deleted;
361
-    }
362
-
363
-
364
-    /**
365
-     * @param array $transaction_IDs
366
-     *
367
-     * @return bool
368
-     */
369
-    public static function unset_locked_transactions(array $transaction_IDs)
370
-    {
371
-        $locked_transactions = get_option('ee_locked_transactions', array());
372
-        $update              = false;
373
-        foreach ($transaction_IDs as $TXN_ID) {
374
-            if (isset($locked_transactions[$TXN_ID])) {
375
-                unset($locked_transactions[$TXN_ID]);
376
-                $update = true;
377
-            }
378
-        }
379
-        if ($update) {
380
-            update_option('ee_locked_transactions', $locked_transactions);
381
-        }
382
-
383
-        return $update;
384
-    }
385
-
386
-
387
-
388
-    /**
389
-     * returns an array of EE_Transaction objects whose timestamp is less than
390
-     * the current time minus the session lifespan, which defaults to 60 minutes
391
-     *
392
-     * @return EE_Base_Class[]|EE_Transaction[]
393
-     * @throws \EE_Error
394
-     */
395
-    public function get_transactions_in_progress()
396
-    {
397
-        return $this->get_all(
398
-            array(
399
-                array(
400
-                    'TXN_timestamp' => array(
401
-                        '>',
402
-                        time() - EE_Registry::instance()->SSN->lifespan()
403
-                    ),
404
-                    'STS_ID' => array(
405
-                        '!=',
406
-                        EEM_Transaction::complete_status_code
407
-                    ),
408
-                )
409
-            )
410
-        );
411
-    }
351
+			$deleted = $wpdb->query($query);
352
+		}
353
+		if ($deleted) {
354
+			/**
355
+			 * Allows code to do something after the transactions have been deleted.
356
+			 */
357
+			do_action('AHEE__EEM_Transaction__delete_junk_transactions__successful_deletion', $txn_ids);
358
+		}
359
+
360
+		return $deleted;
361
+	}
362
+
363
+
364
+	/**
365
+	 * @param array $transaction_IDs
366
+	 *
367
+	 * @return bool
368
+	 */
369
+	public static function unset_locked_transactions(array $transaction_IDs)
370
+	{
371
+		$locked_transactions = get_option('ee_locked_transactions', array());
372
+		$update              = false;
373
+		foreach ($transaction_IDs as $TXN_ID) {
374
+			if (isset($locked_transactions[$TXN_ID])) {
375
+				unset($locked_transactions[$TXN_ID]);
376
+				$update = true;
377
+			}
378
+		}
379
+		if ($update) {
380
+			update_option('ee_locked_transactions', $locked_transactions);
381
+		}
382
+
383
+		return $update;
384
+	}
385
+
386
+
387
+
388
+	/**
389
+	 * returns an array of EE_Transaction objects whose timestamp is less than
390
+	 * the current time minus the session lifespan, which defaults to 60 minutes
391
+	 *
392
+	 * @return EE_Base_Class[]|EE_Transaction[]
393
+	 * @throws \EE_Error
394
+	 */
395
+	public function get_transactions_in_progress()
396
+	{
397
+		return $this->get_all(
398
+			array(
399
+				array(
400
+					'TXN_timestamp' => array(
401
+						'>',
402
+						time() - EE_Registry::instance()->SSN->lifespan()
403
+					),
404
+					'STS_ID' => array(
405
+						'!=',
406
+						EEM_Transaction::complete_status_code
407
+					),
408
+				)
409
+			)
410
+		);
411
+	}
412 412
 
413 413
 
414 414
 }
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
4 4
     exit('No direct script access allowed');
5 5
 }
6
-require_once(EE_MODELS . 'EEM_Base.model.php');
6
+require_once(EE_MODELS.'EEM_Base.model.php');
7 7
 
8 8
 /**
9 9
  *
@@ -107,7 +107,7 @@  discard block
 block discarded – undo
107 107
                     __('Registration Steps', 'event_espresso'), false, array()),
108 108
             )
109 109
         );
110
-        $this->_model_relations        = array(
110
+        $this->_model_relations = array(
111 111
             'Registration'   => new EE_Has_Many_Relation(),
112 112
             'Payment'        => new EE_Has_Many_Relation(),
113 113
             'Status'         => new EE_Belongs_To_Relation(),
@@ -169,7 +169,7 @@  discard block
 block discarded – undo
169 169
             ),
170 170
             OBJECT,
171 171
             array(
172
-                'txnDate' => array('DATE(' . $query_interval . ')', '%s'),
172
+                'txnDate' => array('DATE('.$query_interval.')', '%s'),
173 173
                 'revenue' => array('SUM(TransactionTable.TXN_paid)', '%d')
174 174
             )
175 175
         );
@@ -189,17 +189,17 @@  discard block
 block discarded – undo
189 189
     public function get_revenue_per_event_report($period = '-1 month')
190 190
     {
191 191
         global $wpdb;
192
-        $transaction_table          = $wpdb->prefix . 'esp_transaction';
193
-        $registration_table         = $wpdb->prefix . 'esp_registration';
194
-        $registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
192
+        $transaction_table          = $wpdb->prefix.'esp_transaction';
193
+        $registration_table         = $wpdb->prefix.'esp_registration';
194
+        $registration_payment_table = $wpdb->prefix.'esp_registration_payment';
195 195
         $event_table                = $wpdb->posts;
196
-        $payment_table              = $wpdb->prefix . 'esp_payment';
196
+        $payment_table              = $wpdb->prefix.'esp_payment';
197 197
         $sql_date                   = date('Y-m-d H:i:s', strtotime($period));
198 198
         $approved_payment_status    = EEM_Payment::status_id_approved;
199 199
         $extra_event_on_join        = '';
200 200
         //exclude events not authored by user if permissions in effect
201 201
         if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
202
-            $extra_event_on_join = ' AND Event.post_author = ' . get_current_user_id();
202
+            $extra_event_on_join = ' AND Event.post_author = '.get_current_user_id();
203 203
         }
204 204
 
205 205
         return $wpdb->get_results(
@@ -270,7 +270,7 @@  discard block
 block discarded – undo
270 270
     public function update_based_on_payments($transaction_obj_or_id, $save_txn = true)
271 271
     {
272 272
         EE_Error::doing_it_wrong(
273
-            __CLASS__ . '::' . __FUNCTION__,
273
+            __CLASS__.'::'.__FUNCTION__,
274 274
             sprintf(__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
275 275
                 'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'),
276 276
             '4.6.0'
@@ -318,7 +318,7 @@  discard block
 block discarded – undo
318 318
             array(
319 319
                 0 => array(
320 320
                     'STS_ID'        => EEM_Transaction::failed_status_code,
321
-                    'Payment.PAY_ID' => array( 'IS NULL' ),
321
+                    'Payment.PAY_ID' => array('IS NULL'),
322 322
                     'TXN_timestamp' => array('<', time() - $time_to_leave_alone)
323 323
                 )
324 324
             ),
@@ -336,18 +336,18 @@  discard block
 block discarded – undo
336 336
             $time_to_leave_alone
337 337
         );
338 338
         //now that we have the ids to delete
339
-        if (! empty($txn_ids) && is_array($txn_ids)) {
339
+        if ( ! empty($txn_ids) && is_array($txn_ids)) {
340 340
             // first, make sure these TXN's are removed the "ee_locked_transactions" array
341 341
             EEM_Transaction::unset_locked_transactions($txn_ids);
342 342
             // let's get deletin'...
343 343
             // Why no wpdb->prepare?  Because the data is trusted.
344 344
             // We got the ids from the original query to get them FROM
345 345
             // the db (which is sanitized) so no need to prepare them again.
346
-            $query   = '
346
+            $query = '
347 347
 				DELETE
348
-				FROM ' . $this->table() . '
348
+				FROM ' . $this->table().'
349 349
 				WHERE
350
-					TXN_ID IN ( ' . implode(",", $txn_ids) . ')';
350
+					TXN_ID IN ( ' . implode(",", $txn_ids).')';
351 351
             $deleted = $wpdb->query($query);
352 352
         }
353 353
         if ($deleted) {
Please login to merge, or discard this patch.
core/db_models/EEM_Answer.model.php 2 patches
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -125,14 +125,14 @@
 block discarded – undo
125 125
 	public function get_attendee_property_answer_value( EE_Registration $registration, $question_system_id = NULL, $pretty_answer = FALSE ){
126 126
 		$field_name = NULL;
127 127
 		$value = NULL;
128
-                //backward compat: we still want to find the question's ID
129
-                if( is_numeric( $question_system_id ) ) {
130
-                    //find this question's QST_system value
131
-                    $question_id = $question_system_id;
132
-                    $question_system_id = EEM_Question::instance()->get_var( array( array( 'QST_ID' => $question_system_id ) ), 'QST_system' );
133
-                } else {
134
-                    $question_id = (int) EEM_Question::instance()->get_var( array( array( 'QST_system' => $question_system_id ) ), 'QST_ID' );
135
-                }
128
+				//backward compat: we still want to find the question's ID
129
+				if( is_numeric( $question_system_id ) ) {
130
+					//find this question's QST_system value
131
+					$question_id = $question_system_id;
132
+					$question_system_id = EEM_Question::instance()->get_var( array( array( 'QST_ID' => $question_system_id ) ), 'QST_system' );
133
+				} else {
134
+					$question_id = (int) EEM_Question::instance()->get_var( array( array( 'QST_system' => $question_system_id ) ), 'QST_ID' );
135
+				}
136 136
 		//only bother checking if the registration has an attendee
137 137
 		if( $registration->attendee() instanceof EE_Attendee ) {
138 138
 			$field_name = EEM_Attendee::instance()->get_attendee_field_for_system_question( $question_system_id );
Please login to merge, or discard this patch.
Spacing   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -51,18 +51,18 @@  discard block
 block discarded – undo
51 51
 	/**
52 52
 	 * 	constructor
53 53
 	 */
54
-	protected function __construct( $timezone = NULL ){
55
-		$this->singular_item = __('Answer','event_espresso');
56
-		$this->plural_item = __('Answers','event_espresso');
54
+	protected function __construct($timezone = NULL) {
55
+		$this->singular_item = __('Answer', 'event_espresso');
56
+		$this->plural_item = __('Answers', 'event_espresso');
57 57
 		$this->_tables = array(
58 58
 			'Answer'=> new EE_Primary_Table('esp_answer', 'ANS_ID')
59 59
 		);
60 60
 		$this->_fields = array(
61 61
 			'Answer'=>array(
62
-				'ANS_ID'=> new EE_Primary_Key_Int_Field('ANS_ID', __('Answer ID','event_espresso')),
63
-				'REG_ID'=>new EE_Foreign_Key_Int_Field('REG_ID', __('Registration ID','event_espresso'), false, 0, 'Registration'),
64
-				'QST_ID'=>new EE_Foreign_Key_Int_Field('QST_ID', __('Question ID','event_espresso'), false, 0, 'Question'),
65
-				'ANS_value'=>new EE_Maybe_Serialized_Simple_HTML_Field('ANS_value', __('Answer Value','event_espresso'), false, '')
62
+				'ANS_ID'=> new EE_Primary_Key_Int_Field('ANS_ID', __('Answer ID', 'event_espresso')),
63
+				'REG_ID'=>new EE_Foreign_Key_Int_Field('REG_ID', __('Registration ID', 'event_espresso'), false, 0, 'Registration'),
64
+				'QST_ID'=>new EE_Foreign_Key_Int_Field('QST_ID', __('Question ID', 'event_espresso'), false, 0, 'Question'),
65
+				'ANS_value'=>new EE_Maybe_Serialized_Simple_HTML_Field('ANS_value', __('Answer Value', 'event_espresso'), false, '')
66 66
 			));
67 67
 		$this->_model_relations = array(
68 68
 			'Registration'=>new EE_Belongs_To_Relation(),
@@ -70,7 +70,7 @@  discard block
 block discarded – undo
70 70
 		);
71 71
 		$this->_model_chain_to_wp_user = 'Registration.Event';
72 72
 		$this->_caps_slug = 'registrations';
73
-		parent::__construct( $timezone );
73
+		parent::__construct($timezone);
74 74
 	}
75 75
 
76 76
 
@@ -83,19 +83,19 @@  discard block
 block discarded – undo
83 83
 	 * @param boolean $pretty_answer whether to call 'pretty_value' or just 'value'
84 84
 	 * @return string
85 85
 	 */
86
-	public function get_answer_value_to_question( EE_Registration $registration, $question_id = NULL,$pretty_answer = FALSE ){
87
-		$value = $this->get_attendee_property_answer_value( $registration, $question_id, $pretty_answer );
88
-		if (  $value === NULL ){
89
-			$answer_obj = $this->get_registration_question_answer_object( $registration, $question_id);
90
-			if( $answer_obj instanceof EE_Answer ){
91
-				if($pretty_answer){
86
+	public function get_answer_value_to_question(EE_Registration $registration, $question_id = NULL, $pretty_answer = FALSE) {
87
+		$value = $this->get_attendee_property_answer_value($registration, $question_id, $pretty_answer);
88
+		if ($value === NULL) {
89
+			$answer_obj = $this->get_registration_question_answer_object($registration, $question_id);
90
+			if ($answer_obj instanceof EE_Answer) {
91
+				if ($pretty_answer) {
92 92
 					$value = $answer_obj->pretty_value();
93
-				}else{
93
+				} else {
94 94
 					$value = $answer_obj->value();
95 95
 				}
96 96
 			}
97 97
 		}
98
-		return apply_filters( 'FHEE__EEM_Answer__get_answer_value_to_question__answer_value', $value, $registration, $question_id );
98
+		return apply_filters('FHEE__EEM_Answer__get_answer_value_to_question__answer_value', $value, $registration, $question_id);
99 99
 	}
100 100
 
101 101
 
@@ -106,9 +106,9 @@  discard block
 block discarded – undo
106 106
 	 * @param int $question_id
107 107
 	 * @return EE_Answer
108 108
 	 */
109
-	public function get_registration_question_answer_object( EE_Registration $registration, $question_id = NULL){
110
-		$answer_obj = $this->get_one( array( array( 'QST_ID'=>$question_id, 'REG_ID'=>$registration->ID() )));
111
-		return apply_filters( 'FHEE__EEM_Answer__get_registration_question_answer_object__answer_obj', $answer_obj, $registration, $question_id );
109
+	public function get_registration_question_answer_object(EE_Registration $registration, $question_id = NULL) {
110
+		$answer_obj = $this->get_one(array(array('QST_ID'=>$question_id, 'REG_ID'=>$registration->ID())));
111
+		return apply_filters('FHEE__EEM_Answer__get_registration_question_answer_object__answer_obj', $answer_obj, $registration, $question_id);
112 112
 	}
113 113
 
114 114
 
@@ -122,39 +122,39 @@  discard block
 block discarded – undo
122 122
 	 * @return string|null (if the registration has no attendee, or the question_system_id is not a QST_ID or QST_system for
123 123
 	 * a question corresponding to an attendee field, returns null)
124 124
 	 */
125
-	public function get_attendee_property_answer_value( EE_Registration $registration, $question_system_id = NULL, $pretty_answer = FALSE ){
125
+	public function get_attendee_property_answer_value(EE_Registration $registration, $question_system_id = NULL, $pretty_answer = FALSE) {
126 126
 		$field_name = NULL;
127 127
 		$value = NULL;
128 128
                 //backward compat: we still want to find the question's ID
129
-                if( is_numeric( $question_system_id ) ) {
129
+                if (is_numeric($question_system_id)) {
130 130
                     //find this question's QST_system value
131 131
                     $question_id = $question_system_id;
132
-                    $question_system_id = EEM_Question::instance()->get_var( array( array( 'QST_ID' => $question_system_id ) ), 'QST_system' );
132
+                    $question_system_id = EEM_Question::instance()->get_var(array(array('QST_ID' => $question_system_id)), 'QST_system');
133 133
                 } else {
134
-                    $question_id = (int) EEM_Question::instance()->get_var( array( array( 'QST_system' => $question_system_id ) ), 'QST_ID' );
134
+                    $question_id = (int) EEM_Question::instance()->get_var(array(array('QST_system' => $question_system_id)), 'QST_ID');
135 135
                 }
136 136
 		//only bother checking if the registration has an attendee
137
-		if( $registration->attendee() instanceof EE_Attendee ) {
138
-			$field_name = EEM_Attendee::instance()->get_attendee_field_for_system_question( $question_system_id );
139
-			if( $field_name ) {
140
-				if( $pretty_answer ) {
141
-					if( $field_name === 'STA_ID' ) {
137
+		if ($registration->attendee() instanceof EE_Attendee) {
138
+			$field_name = EEM_Attendee::instance()->get_attendee_field_for_system_question($question_system_id);
139
+			if ($field_name) {
140
+				if ($pretty_answer) {
141
+					if ($field_name === 'STA_ID') {
142 142
 						$state = $registration->attendee()->state_obj();
143
-						$value = $state instanceof EE_State ? $state->name() : sprintf( __('Unknown State (%s)', 'event_espresso'), $registration->attendee()->state_ID() );
144
-					} else if($field_name === 'CNT_ISO') {
143
+						$value = $state instanceof EE_State ? $state->name() : sprintf(__('Unknown State (%s)', 'event_espresso'), $registration->attendee()->state_ID());
144
+					} else if ($field_name === 'CNT_ISO') {
145 145
 						$country = $registration->attendee()->country_obj();
146
-						$value = $country instanceof EE_Country ? $country->name() : sprintf(__('Unknown Country (%s)', "event_espresso"),$registration->attendee()->country_ID());
146
+						$value = $country instanceof EE_Country ? $country->name() : sprintf(__('Unknown Country (%s)', "event_espresso"), $registration->attendee()->country_ID());
147 147
 					} else {
148
-						$value = $registration->attendee()->get_pretty( $field_name );
148
+						$value = $registration->attendee()->get_pretty($field_name);
149 149
 					}
150 150
 					//if field name is blank, leave the value as null too
151
-				}else{
152
-					$value = $registration->attendee()->get( $field_name );
151
+				} else {
152
+					$value = $registration->attendee()->get($field_name);
153 153
 				}
154 154
 			}
155 155
 			//if no field was found, leave value blank
156 156
 		}
157
-		return apply_filters( 'FHEE__EEM_Answer__get_attendee_question_answer_value__answer_value', $value, $registration, $question_id, $question_system_id );
157
+		return apply_filters('FHEE__EEM_Answer__get_attendee_question_answer_value__answer_value', $value, $registration, $question_id, $question_system_id);
158 158
 	}
159 159
 
160 160
 
Please login to merge, or discard this patch.
core/services/collections/CollectionInterface.php 1 patch
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -113,12 +113,12 @@  discard block
 block discarded – undo
113 113
 	public function previous();
114 114
 
115 115
 		/**
116
-	 * Returns the index of a given object, or false if not found
117
-	 *
118
-	 * @see http://stackoverflow.com/a/8736013
119
-	 * @param $object
120
-	 * @return boolean|int|string
121
-	 */
116
+		 * Returns the index of a given object, or false if not found
117
+		 *
118
+		 * @see http://stackoverflow.com/a/8736013
119
+		 * @param $object
120
+		 * @return boolean|int|string
121
+		 */
122 122
 	public function indexOf( $object );
123 123
 
124 124
 
@@ -160,17 +160,17 @@  discard block
 block discarded – undo
160 160
 
161 161
 
162 162
 
163
-    /**
164
-     * detaches ALL objects from the Collection
165
-     */
166
-    public function detachAll();
163
+	/**
164
+	 * detaches ALL objects from the Collection
165
+	 */
166
+	public function detachAll();
167 167
 
168 168
 
169 169
 
170
-    /**
171
-     * unsets and detaches ALL objects from the Collection
172
-     */
173
-    public function trashAndDetachAll();
170
+	/**
171
+	 * unsets and detaches ALL objects from the Collection
172
+	 */
173
+	public function trashAndDetachAll();
174 174
 
175 175
 }
176 176
 // End of file CollectionInterface.php
Please login to merge, or discard this patch.
core/services/collections/Collection.php 1 patch
Indentation   +28 added lines, -29 removed lines patch added patch discarded remove patch
@@ -83,7 +83,6 @@  discard block
 block discarded – undo
83 83
 
84 84
 	 /**
85 85
 	  * setIdentifier
86
-
87 86
 	  * Sets the data associated with an object in the Collection
88 87
 	  * if no $identifier is supplied, then the spl_object_hash() is used
89 88
 	  *
@@ -352,34 +351,34 @@  discard block
 block discarded – undo
352 351
 
353 352
 
354 353
 
355
-     /**
356
-      * detaches ALL objects from the Collection
357
-      */
358
-     public function detachAll()
359
-     {
360
-         $this->rewind();
361
-         while ($this->valid()) {
362
-             $object = $this->current();
363
-             $this->next();
364
-             $this->detach($object);
365
-         }
366
-     }
367
-
368
-
369
-
370
-     /**
371
-      * unsets and detaches ALL objects from the Collection
372
-      */
373
-     public function trashAndDetachAll()
374
-     {
375
-         $this->rewind();
376
-         while ($this->valid()) {
377
-             $object = $this->current();
378
-             $this->next();
379
-             $this->detach($object);
380
-             unset($object);
381
-         }
382
-     }
354
+	 /**
355
+	  * detaches ALL objects from the Collection
356
+	  */
357
+	 public function detachAll()
358
+	 {
359
+		 $this->rewind();
360
+		 while ($this->valid()) {
361
+			 $object = $this->current();
362
+			 $this->next();
363
+			 $this->detach($object);
364
+		 }
365
+	 }
366
+
367
+
368
+
369
+	 /**
370
+	  * unsets and detaches ALL objects from the Collection
371
+	  */
372
+	 public function trashAndDetachAll()
373
+	 {
374
+		 $this->rewind();
375
+		 while ($this->valid()) {
376
+			 $object = $this->current();
377
+			 $this->next();
378
+			 $this->detach($object);
379
+			 unset($object);
380
+		 }
381
+	 }
383 382
 
384 383
 
385 384
 
Please login to merge, or discard this patch.
core/services/loaders/LoaderFactory.php 2 patches
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -79,37 +79,37 @@
 block discarded – undo
79 79
 class LoaderFactory
80 80
 {
81 81
 
82
-    /**
83
-     * @var LoaderInterface $loader ;
84
-     */
85
-    private static $loader;
82
+	/**
83
+	 * @var LoaderInterface $loader ;
84
+	 */
85
+	private static $loader;
86 86
 
87 87
 
88 88
 
89
-    /**
90
-     * @param mixed $generator      provided during  very first instantiation in
91
-     *                              EE_Load_Espresso_Core::handle_request()
92
-     *                              otherwise can be left null
93
-     * @return LoaderInterface
94
-     * @throws InvalidArgumentException
95
-     * @throws InvalidInterfaceException
96
-     * @throws InvalidDataTypeException
97
-     */
98
-    public static function getLoader($generator = null)
99
-    {
100
-        if (! LoaderFactory::$loader instanceof LoaderInterface) {
101
-            $generator = $generator !== null ? $generator : EE_Registry::instance();
102
-            $core_loader = new CoreLoader($generator);
103
-            LoaderFactory::$loader = new Loader(
104
-                $core_loader,
105
-                new CachingLoader(
106
-                    $core_loader,
107
-                    new LooseCollection('')
108
-                )
109
-            );
110
-        }
111
-        return LoaderFactory::$loader;
112
-    }
89
+	/**
90
+	 * @param mixed $generator      provided during  very first instantiation in
91
+	 *                              EE_Load_Espresso_Core::handle_request()
92
+	 *                              otherwise can be left null
93
+	 * @return LoaderInterface
94
+	 * @throws InvalidArgumentException
95
+	 * @throws InvalidInterfaceException
96
+	 * @throws InvalidDataTypeException
97
+	 */
98
+	public static function getLoader($generator = null)
99
+	{
100
+		if (! LoaderFactory::$loader instanceof LoaderInterface) {
101
+			$generator = $generator !== null ? $generator : EE_Registry::instance();
102
+			$core_loader = new CoreLoader($generator);
103
+			LoaderFactory::$loader = new Loader(
104
+				$core_loader,
105
+				new CachingLoader(
106
+					$core_loader,
107
+					new LooseCollection('')
108
+				)
109
+			);
110
+		}
111
+		return LoaderFactory::$loader;
112
+	}
113 113
 
114 114
 
115 115
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -97,7 +97,7 @@
 block discarded – undo
97 97
      */
98 98
     public static function getLoader($generator = null)
99 99
     {
100
-        if (! LoaderFactory::$loader instanceof LoaderInterface) {
100
+        if ( ! LoaderFactory::$loader instanceof LoaderInterface) {
101 101
             $generator = $generator !== null ? $generator : EE_Registry::instance();
102 102
             $core_loader = new CoreLoader($generator);
103 103
             LoaderFactory::$loader = new Loader(
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Processor.lib.php 1 patch
Spacing   +108 added lines, -108 removed lines patch added patch discarded remove patch
@@ -35,7 +35,7 @@  discard block
 block discarded – undo
35 35
 	 *
36 36
 	 * @param EE_Message_Resource_Manager $message_resource_manager
37 37
 	 */
38
-	public function __construct( EE_Message_Resource_Manager $message_resource_manager ) {
38
+	public function __construct(EE_Message_Resource_Manager $message_resource_manager) {
39 39
 		$this->_message_resource_manager = $message_resource_manager;
40 40
 		$this->_init_queue_and_generator();
41 41
 	}
@@ -50,7 +50,7 @@  discard block
 block discarded – undo
50 50
 	 * - $_generator = holds the messages generator
51 51
 	 */
52 52
 	protected function _init_queue_and_generator() {
53
-		$this->_generator = EE_Registry::factory( 'EE_Messages_Generator' );
53
+		$this->_generator = EE_Registry::factory('EE_Messages_Generator');
54 54
 		$this->_queue = $this->_generator->generation_queue();
55 55
 	}
56 56
 
@@ -75,31 +75,31 @@  discard block
 block discarded – undo
75 75
 	 * @param EE_Messages_Queue $queue_to_process
76 76
 	 * @return bool  true for success false for error.
77 77
 	 */
78
-	public function process_immediately_from_queue( EE_Messages_Queue $queue_to_process ) {
78
+	public function process_immediately_from_queue(EE_Messages_Queue $queue_to_process) {
79 79
 		$success = false;
80 80
 		$messages_to_send = array();
81 81
 		$messages_to_generate = array();
82 82
 		//loop through and setup the various messages from the queue so we know what is being processed
83 83
 		$queue_to_process->get_message_repository()->rewind();
84
-		foreach ( $queue_to_process->get_message_repository() as $message ) {
85
-			if ( $message->STS_ID() === EEM_Message::status_incomplete ) {
84
+		foreach ($queue_to_process->get_message_repository() as $message) {
85
+			if ($message->STS_ID() === EEM_Message::status_incomplete) {
86 86
 				$messages_to_generate[] = $message;
87 87
 				continue;
88 88
 			}
89 89
 
90
-			if ( in_array( $message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send() ) ) {
90
+			if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
91 91
 				$messages_to_send[] = $message;
92 92
 				continue;
93 93
 			}
94 94
 		}
95 95
 
96 96
 		//do generation/sends
97
-		if ( $messages_to_generate ) {
98
-			$success = $this->batch_generate_from_queue( $messages_to_generate, true );
97
+		if ($messages_to_generate) {
98
+			$success = $this->batch_generate_from_queue($messages_to_generate, true);
99 99
 		}
100 100
 
101
-		if ( $messages_to_send ) {
102
-			$sent = $this->batch_send_from_queue( $messages_to_send, true );
101
+		if ($messages_to_send) {
102
+			$sent = $this->batch_send_from_queue($messages_to_send, true);
103 103
 			//if there was messages to generate and it failed, then we override any success value for the sending process
104 104
 			//otherwise we just use the return from batch send.  The intent is that there is a simple response for success/fail.
105 105
 			//Either everything was successful or we consider it a fail.  To be clear, this is a limitation of doing
@@ -119,13 +119,13 @@  discard block
 block discarded – undo
119 119
 	 * @return bool|EE_Messages_Queue return false if nothing generated.  This returns a new EE_Message_Queue with
120 120
 	 *                                   generated messages.
121 121
 	 */
122
-	public function batch_generate_from_queue( $messages = array(), $clear_queue = false ) {
123
-		if ( $this->_build_queue_for_generation( $messages, $clear_queue ) ) {
122
+	public function batch_generate_from_queue($messages = array(), $clear_queue = false) {
123
+		if ($this->_build_queue_for_generation($messages, $clear_queue)) {
124 124
 			$new_queue = $this->_generator->generate();
125
-			if ( $new_queue instanceof EE_Messages_Queue ) {
125
+			if ($new_queue instanceof EE_Messages_Queue) {
126 126
 				//unlock queue
127 127
 				$this->_queue->unlock_queue();
128
-				$new_queue->initiate_request_by_priority( 'send' );
128
+				$new_queue->initiate_request_by_priority('send');
129 129
 				return $new_queue;
130 130
 			}
131 131
 		}
@@ -146,24 +146,24 @@  discard block
 block discarded – undo
146 146
 	 *
147 147
 	 * @return bool true means queue prepped, false means there was a lock so no generation please.
148 148
 	 */
149
-	protected function _build_queue_for_generation( $messages = array(), $clear_queue = false ) {
149
+	protected function _build_queue_for_generation($messages = array(), $clear_queue = false) {
150 150
 
151
-		if ( $clear_queue ) {
151
+		if ($clear_queue) {
152 152
 			$this->_init_queue_and_generator();
153 153
 		}
154 154
 
155
-		if ( $messages ) {
155
+		if ($messages) {
156 156
 			//if generation is locked then get out now because that means processing is already happening.
157
-			if ( $this->_queue->is_locked() ) {
157
+			if ($this->_queue->is_locked()) {
158 158
 				return false;
159 159
 			}
160 160
 
161 161
 			$this->_queue->lock_queue();
162
-			$messages = is_array( $messages ) ? $messages : array( $messages );
163
-			foreach ( $messages as $message ) {
164
-				if ( $message instanceof EE_Message ) {
162
+			$messages = is_array($messages) ? $messages : array($messages);
163
+			foreach ($messages as $message) {
164
+				if ($message instanceof EE_Message) {
165 165
 					$data = $message->all_extra_meta_array();
166
-					$this->_queue->add( $message, $data );
166
+					$this->_queue->add($message, $data);
167 167
 				}
168 168
 			}
169 169
 			return true;
@@ -181,22 +181,22 @@  discard block
 block discarded – undo
181 181
 	 *
182 182
 	 * @return bool true means queue prepped, false means there was a lock so no queue prepped.
183 183
 	 */
184
-	protected function _build_queue_for_sending( $messages, $clear_queue = false ) {
184
+	protected function _build_queue_for_sending($messages, $clear_queue = false) {
185 185
 		//if sending is locked then get out now because that means processing is already happening.
186
-		if ( $this->_queue->is_locked( EE_Messages_Queue::action_sending ) ) {
186
+		if ($this->_queue->is_locked(EE_Messages_Queue::action_sending)) {
187 187
 			return false;
188 188
 		}
189 189
 
190
-		$this->_queue->lock_queue( EE_Messages_Queue::action_sending );
190
+		$this->_queue->lock_queue(EE_Messages_Queue::action_sending);
191 191
 
192
-		if ( $clear_queue ) {
192
+		if ($clear_queue) {
193 193
 			$this->_init_queue_and_generator();
194 194
 		}
195 195
 
196
-		$messages = is_array( $messages ) ? $messages : array( $messages );
196
+		$messages = is_array($messages) ? $messages : array($messages);
197 197
 
198
-		foreach ( $messages as $message ) {
199
-			$this->_queue->add( $message );
198
+		foreach ($messages as $message) {
199
+			$this->_queue->add($message);
200 200
 		}
201 201
 		return true;
202 202
 	}
@@ -212,11 +212,11 @@  discard block
 block discarded – undo
212 212
 	 *
213 213
 	 * @return EE_Messages_Queue
214 214
 	 */
215
-	public function batch_send_from_queue( $messages = array(), $clear_queue = false ) {
215
+	public function batch_send_from_queue($messages = array(), $clear_queue = false) {
216 216
 
217
-		if ( $messages && $this->_build_queue_for_sending( $messages, $clear_queue ) ) {
217
+		if ($messages && $this->_build_queue_for_sending($messages, $clear_queue)) {
218 218
 			$this->_queue->execute();
219
-			$this->_queue->unlock_queue( EE_Messages_Queue::action_sending );
219
+			$this->_queue->unlock_queue(EE_Messages_Queue::action_sending);
220 220
 		} else {
221 221
 			//get messages to send and execute.
222 222
 			$this->_queue->get_to_send_batch_and_send();
@@ -239,10 +239,10 @@  discard block
 block discarded – undo
239 239
 	 * @param EE_Message_To_Generate[] $messages_to_generate
240 240
 	 * @return EE_Messages_Queue
241 241
 	 */
242
-	public function generate_and_return(  $messages_to_generate ) {
242
+	public function generate_and_return($messages_to_generate) {
243 243
 		$this->_init_queue_and_generator();
244
-		$this->_queue_for_generation_loop( $messages_to_generate );
245
-		return $this->_generator->generate( false );
244
+		$this->_queue_for_generation_loop($messages_to_generate);
245
+		return $this->_generator->generate(false);
246 246
 	}
247 247
 
248 248
 
@@ -253,8 +253,8 @@  discard block
 block discarded – undo
253 253
 	 * @param  bool     $persist    Indicate whether to instruct the generator to persist the generated queue (true) or not (false).
254 254
 	 * @return EE_Messages_Queue
255 255
 	 */
256
-	public function generate_queue( $persist = true ) {
257
-		return $this->_generator->generate( $persist );
256
+	public function generate_queue($persist = true) {
257
+		return $this->_generator->generate($persist);
258 258
 	}
259 259
 
260 260
 
@@ -267,9 +267,9 @@  discard block
 block discarded – undo
267 267
 	 * @param bool                   $test_send             Whether this item is for a test send or not.
268 268
 	 * @return  EE_Messages_Queue
269 269
 	 */
270
-	public function queue_for_generation( EE_Message_To_Generate $message_to_generate, $test_send = false ) {
271
-		if ( $message_to_generate->valid() ) {
272
-			$this->_generator->create_and_add_message_to_queue( $message_to_generate, $test_send );
270
+	public function queue_for_generation(EE_Message_To_Generate $message_to_generate, $test_send = false) {
271
+		if ($message_to_generate->valid()) {
272
+			$this->_generator->create_and_add_message_to_queue($message_to_generate, $test_send);
273 273
 		}
274 274
 	}
275 275
 
@@ -285,9 +285,9 @@  discard block
 block discarded – undo
285 285
 	 *
286 286
 	 * @param EE_Message_To_Generate[] $messages_to_generate
287 287
 	 */
288
-	public function batch_queue_for_generation_and_persist( $messages_to_generate ) {
288
+	public function batch_queue_for_generation_and_persist($messages_to_generate) {
289 289
 		$this->_init_queue_and_generator();
290
-		$this->_queue_for_generation_loop( $messages_to_generate );
290
+		$this->_queue_for_generation_loop($messages_to_generate);
291 291
 		$this->_queue->save();
292 292
 	}
293 293
 
@@ -303,9 +303,9 @@  discard block
 block discarded – undo
303 303
 	 *
304 304
 	 * @param EE_Message_To_Generate[]  $messages_to_generate
305 305
 	 */
306
-	public function batch_queue_for_generation_no_persist( $messages_to_generate ) {
306
+	public function batch_queue_for_generation_no_persist($messages_to_generate) {
307 307
 		$this->_init_queue_and_generator();
308
-		$this->_queue_for_generation_loop( $messages_to_generate );
308
+		$this->_queue_for_generation_loop($messages_to_generate);
309 309
 	}
310 310
 
311 311
 
@@ -317,15 +317,15 @@  discard block
 block discarded – undo
317 317
 	 *
318 318
 	 * @param EE_Message_To_Generate[] $messages_to_generate
319 319
 	 */
320
-	protected function _queue_for_generation_loop( $messages_to_generate ) {
320
+	protected function _queue_for_generation_loop($messages_to_generate) {
321 321
 		//make sure is in an array.
322
-		if ( ! is_array( $messages_to_generate ) ) {
323
-			$messages_to_generate = array( $messages_to_generate );
322
+		if ( ! is_array($messages_to_generate)) {
323
+			$messages_to_generate = array($messages_to_generate);
324 324
 		}
325 325
 
326
-		foreach ( $messages_to_generate as $message_to_generate ) {
327
-			if ( $message_to_generate instanceof EE_Message_To_Generate && $message_to_generate->valid() ) {
328
-				$this->queue_for_generation( $message_to_generate );
326
+		foreach ($messages_to_generate as $message_to_generate) {
327
+			if ($message_to_generate instanceof EE_Message_To_Generate && $message_to_generate->valid()) {
328
+				$this->queue_for_generation($message_to_generate);
329 329
 			}
330 330
 		}
331 331
 	}
@@ -340,10 +340,10 @@  discard block
 block discarded – undo
340 340
 	 * @param  EE_Message_To_Generate[]
341 341
 	 * @return EE_Messages_Queue
342 342
 	 */
343
-	public function generate_and_queue_for_sending( $messages_to_generate ) {
343
+	public function generate_and_queue_for_sending($messages_to_generate) {
344 344
 		$this->_init_queue_and_generator();
345
-		$this->_queue_for_generation_loop( $messages_to_generate );
346
-		return $this->_generator->generate( true );
345
+		$this->_queue_for_generation_loop($messages_to_generate);
346
+		return $this->_generator->generate(true);
347 347
 	}
348 348
 
349 349
 
@@ -357,10 +357,10 @@  discard block
 block discarded – undo
357 357
 	 * @param   bool                   $test_send                Whether this is a test send or not.
358 358
 	 * @return  EE_Messages_Queue | bool   false if unable to generate otherwise the generated queue.
359 359
 	 */
360
-	public function generate_for_preview( EE_Message_To_Generate $message_to_generate, $test_send = false ) {
361
-		if ( ! $message_to_generate->valid() ) {
360
+	public function generate_for_preview(EE_Message_To_Generate $message_to_generate, $test_send = false) {
361
+		if ( ! $message_to_generate->valid()) {
362 362
 			EE_Error::add_error(
363
-				__( 'Unable to generate preview because of invalid data', 'event_espresso' ),
363
+				__('Unable to generate preview because of invalid data', 'event_espresso'),
364 364
 				__FILE__,
365 365
 				__FUNCTION__,
366 366
 				__LINE__
@@ -368,14 +368,14 @@  discard block
 block discarded – undo
368 368
 			return false;
369 369
 		}
370 370
 		//just make sure preview is set on the $message_to_generate (in case client forgot)
371
-		$message_to_generate->set_preview( true );
371
+		$message_to_generate->set_preview(true);
372 372
 		$this->_init_queue_and_generator();
373
-		$this->queue_for_generation( $message_to_generate, $test_send );
374
-		$generated_queue = $this->_generator->generate( false );
375
-		if ( $generated_queue->execute( false ) ) {
373
+		$this->queue_for_generation($message_to_generate, $test_send);
374
+		$generated_queue = $this->_generator->generate(false);
375
+		if ($generated_queue->execute(false)) {
376 376
 			//the first queue item should be the preview
377 377
 			$generated_queue->get_message_repository()->rewind();
378
-			if ( ! $generated_queue->get_message_repository()->valid() ) {
378
+			if ( ! $generated_queue->get_message_repository()->valid()) {
379 379
 				return $generated_queue;
380 380
 			}
381 381
 			return $generated_queue;
@@ -392,15 +392,15 @@  discard block
 block discarded – undo
392 392
 	 * @param EE_Message_To_Generate $message_to_generate
393 393
 	 * @return bool true or false for success.
394 394
 	 */
395
-	public function queue_for_sending( EE_Message_To_Generate $message_to_generate ) {
396
-		if ( ! $message_to_generate->valid() ) {
395
+	public function queue_for_sending(EE_Message_To_Generate $message_to_generate) {
396
+		if ( ! $message_to_generate->valid()) {
397 397
 			return false;
398 398
 		}
399 399
 		$this->_init_queue_and_generator();
400 400
 		$message = $message_to_generate->get_EE_Message();
401
-		$this->_queue->add( $message );
402
-		if ( $message->send_now() ) {
403
-			$this->_queue->execute( false );
401
+		$this->_queue->add($message);
402
+		if ($message->send_now()) {
403
+			$this->_queue->execute(false);
404 404
 		} else {
405 405
 			$this->_queue->save();
406 406
 		}
@@ -413,12 +413,12 @@  discard block
 block discarded – undo
413 413
 	 * @param EE_Message_To_Generate $message_to_generate
414 414
 	 * @return EE_Messages_Queue | null
415 415
 	 */
416
-	public function generate_and_send_now( EE_Message_To_Generate $message_to_generate ) {
417
-		if ( ! $message_to_generate->valid() ) {
416
+	public function generate_and_send_now(EE_Message_To_Generate $message_to_generate) {
417
+		if ( ! $message_to_generate->valid()) {
418 418
 			return null;
419 419
 		}
420 420
 		// is there supposed to be a sending messenger for this message?
421
-		if ( $message_to_generate instanceof EEI_Has_Sending_Messenger ) {
421
+		if ($message_to_generate instanceof EEI_Has_Sending_Messenger) {
422 422
 			// make sure it's valid, but if it's not,
423 423
 			// then set the value of $sending_messenger to an EE_Error object
424 424
 			// so that downstream code can easily see that things went wrong.
@@ -434,14 +434,14 @@  discard block
 block discarded – undo
434 434
 			$sending_messenger = null;
435 435
 		}
436 436
 
437
-		if ( $message_to_generate->get_EE_Message()->STS_ID() === EEM_Message::status_idle ) {
437
+		if ($message_to_generate->get_EE_Message()->STS_ID() === EEM_Message::status_idle) {
438 438
 			$this->_init_queue_and_generator();
439
-			$this->_queue->add( $message_to_generate->get_EE_Message() );
440
-			$this->_queue->execute( false, $sending_messenger );
439
+			$this->_queue->add($message_to_generate->get_EE_Message());
440
+			$this->_queue->execute(false, $sending_messenger);
441 441
 			return $this->_queue;
442
-		} elseif ( $message_to_generate->get_EE_Message()->STS_ID() === EEM_Message::status_incomplete ) {
443
-			$generated_queue = $this->generate_and_return( array( $message_to_generate ) );
444
-			$generated_queue->execute( false, $sending_messenger );
442
+		} elseif ($message_to_generate->get_EE_Message()->STS_ID() === EEM_Message::status_incomplete) {
443
+			$generated_queue = $this->generate_and_return(array($message_to_generate));
444
+			$generated_queue->execute(false, $sending_messenger);
445 445
 			return $generated_queue;
446 446
 		}
447 447
 		return null;
@@ -458,13 +458,13 @@  discard block
 block discarded – undo
458 458
 	 * @param mixed  $data   The data being used for generation.
459 459
 	 * @param bool   $persist   Whether to persist the queued messages to the db or not.
460 460
 	 */
461
-	public function generate_for_all_active_messengers( $message_type, $data, $persist = true ) {
462
-		$messages_to_generate = $this->setup_mtgs_for_all_active_messengers( $message_type, $data );
463
-		if ( $persist ) {
464
-			$this->batch_queue_for_generation_and_persist( $messages_to_generate );
461
+	public function generate_for_all_active_messengers($message_type, $data, $persist = true) {
462
+		$messages_to_generate = $this->setup_mtgs_for_all_active_messengers($message_type, $data);
463
+		if ($persist) {
464
+			$this->batch_queue_for_generation_and_persist($messages_to_generate);
465 465
 			$this->_queue->initiate_request_by_priority();
466 466
 		} else {
467
-			$this->batch_queue_for_generation_no_persist( $messages_to_generate );
467
+			$this->batch_queue_for_generation_no_persist($messages_to_generate);
468 468
 		}
469 469
 	}
470 470
 
@@ -479,11 +479,11 @@  discard block
 block discarded – undo
479 479
 	 *
480 480
 	 * @return EE_Message_To_Generate[]
481 481
 	 */
482
-	public function setup_mtgs_for_all_active_messengers( $message_type, $data ) {
482
+	public function setup_mtgs_for_all_active_messengers($message_type, $data) {
483 483
 		$messages_to_generate = array();
484
-		foreach ( $this->_message_resource_manager->active_messengers() as $messenger_slug => $messenger_object  ) {
485
-			$message_to_generate = new EE_Message_To_Generate( $messenger_slug, $message_type, $data );
486
-			if ( $message_to_generate->valid() ) {
484
+		foreach ($this->_message_resource_manager->active_messengers() as $messenger_slug => $messenger_object) {
485
+			$message_to_generate = new EE_Message_To_Generate($messenger_slug, $message_type, $data);
486
+			if ($message_to_generate->valid()) {
487 487
 				$messages_to_generate[] = $message_to_generate;
488 488
 			}
489 489
 		}
@@ -498,29 +498,29 @@  discard block
 block discarded – undo
498 498
 	 * and send.
499 499
 	 * @param array $message_ids
500 500
 	 */
501
-	public function setup_messages_from_ids_and_send( $message_ids ) {
501
+	public function setup_messages_from_ids_and_send($message_ids) {
502 502
 		$this->_init_queue_and_generator();
503
-		$messages = EEM_Message::instance()->get_all( array(
503
+		$messages = EEM_Message::instance()->get_all(array(
504 504
 			array(
505
-				'MSG_ID' => array( 'IN', $message_ids ),
505
+				'MSG_ID' => array('IN', $message_ids),
506 506
 				'STS_ID' => array(
507 507
 					'IN',
508 508
 					array_merge(
509 509
 						EEM_Message::instance()->stati_indicating_sent(),
510
-						array( EEM_Message::status_retry )
510
+						array(EEM_Message::status_retry)
511 511
 					),
512 512
 				),
513 513
 			),
514 514
 		));
515 515
 		//set the Messages to resend.
516
-		foreach ( $messages as $message ) {
517
-			if ( $message instanceof EE_Message ) {
518
-				$message->set_STS_ID( EEM_Message::status_resend );
519
-				$this->_queue->add( $message );
516
+		foreach ($messages as $message) {
517
+			if ($message instanceof EE_Message) {
518
+				$message->set_STS_ID(EEM_Message::status_resend);
519
+				$this->_queue->add($message);
520 520
 			}
521 521
 		}
522 522
 
523
-		$this->_queue->initiate_request_by_priority( 'send' );
523
+		$this->_queue->initiate_request_by_priority('send');
524 524
 	}
525 525
 
526 526
 
@@ -534,23 +534,23 @@  discard block
 block discarded – undo
534 534
 	 *
535 535
 	 * @return EE_Message_To_Generate[]
536 536
 	 */
537
-	public function setup_messages_to_generate_from_registration_ids_in_request( $registration_ids_key = '_REG_ID' ) {
538
-		EE_Registry::instance()->load_core( 'Request_Handler' );
539
-		EE_Registry::instance()->load_helper( 'MSG_Template' );
537
+	public function setup_messages_to_generate_from_registration_ids_in_request($registration_ids_key = '_REG_ID') {
538
+		EE_Registry::instance()->load_core('Request_Handler');
539
+		EE_Registry::instance()->load_helper('MSG_Template');
540 540
 		$regs_to_send = array();
541
-		$regIDs = EE_Registry::instance()->REQ->get( $registration_ids_key );
542
-		if ( empty( $regIDs ) ) {
543
-			EE_Error::add_error( __('Something went wrong because we\'re missing the registration ID', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__ );
541
+		$regIDs = EE_Registry::instance()->REQ->get($registration_ids_key);
542
+		if (empty($regIDs)) {
543
+			EE_Error::add_error(__('Something went wrong because we\'re missing the registration ID', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
544 544
 			return false;
545 545
 		}
546 546
 
547 547
 		//make sure is an array
548
-		$regIDs = is_array( $regIDs ) ? $regIDs : array( $regIDs );
548
+		$regIDs = is_array($regIDs) ? $regIDs : array($regIDs);
549 549
 
550
-		foreach( $regIDs as $regID ) {
551
-			$reg = EEM_Registration::instance()->get_one_by_ID( $regID );
552
-			if ( ! $reg instanceof EE_Registration ) {
553
-				EE_Error::add_error( sprintf( __('Unable to retrieve a registration object for the given reg id (%s)', 'event_espresso'), $regID ) );
550
+		foreach ($regIDs as $regID) {
551
+			$reg = EEM_Registration::instance()->get_one_by_ID($regID);
552
+			if ( ! $reg instanceof EE_Registration) {
553
+				EE_Error::add_error(sprintf(__('Unable to retrieve a registration object for the given reg id (%s)', 'event_espresso'), $regID));
554 554
 				return false;
555 555
 			}
556 556
 			$regs_to_send[$reg->transaction_ID()][$reg->status_ID()][] = $reg;
@@ -558,13 +558,13 @@  discard block
 block discarded – undo
558 558
 
559 559
 		$messages_to_generate = array();
560 560
 
561
-		foreach ( $regs_to_send as $status_group ) {
562
-			foreach ( $status_group as $status_id => $registrations ) {
561
+		foreach ($regs_to_send as $status_group) {
562
+			foreach ($status_group as $status_id => $registrations) {
563 563
 				$messages_to_generate = array_merge(
564 564
 					$messages_to_generate,
565 565
 					$this->setup_mtgs_for_all_active_messengers(
566
-						EEH_MSG_Template::convert_reg_status_to_message_type( $status_id ),
567
-						array( $registrations, $status_id )
566
+						EEH_MSG_Template::convert_reg_status_to_message_type($status_id),
567
+						array($registrations, $status_id)
568 568
 					)
569 569
 				);
570 570
 			}
Please login to merge, or discard this patch.
core/db_models/fields/EE_Datetime_Field.php 1 patch
Indentation   +755 added lines, -755 removed lines patch added patch discarded remove patch
@@ -15,760 +15,760 @@
 block discarded – undo
15 15
 class EE_Datetime_Field extends EE_Model_Field_Base
16 16
 {
17 17
 
18
-    /**
19
-     * The pattern we're looking for is if only the characters 0-9 are found and there are only
20
-     * 10 or more numbers (because 9 numbers even with all 9's would be sometime in 2001 )
21
-     *
22
-     * @type string unix_timestamp_regex
23
-     */
24
-    const unix_timestamp_regex = '/[0-9]{10,}/';
25
-
26
-    /**
27
-     * @type string mysql_timestamp_format
28
-     */
29
-    const mysql_timestamp_format = 'Y-m-d H:i:s';
30
-
31
-    /**
32
-     * @type string mysql_date_format
33
-     */
34
-    const mysql_date_format = 'Y-m-d';
35
-
36
-    /**
37
-     * @type string mysql_time_format
38
-     */
39
-    const mysql_time_format = 'H:i:s';
40
-
41
-    /**
42
-     * Const for using in the default value. If the field's default is set to this,
43
-     * then we will return the time of calling `get_default_value()`, not
44
-     * just the current time at construction
45
-     */
46
-    const now = 'now';
47
-
48
-    /**
49
-     * The following properties hold the default formats for date and time.
50
-     * Defaults are set via the constructor and can be overridden on class instantiation.
51
-     * However they can also be overridden later by the set_format() method
52
-     * (and corresponding set_date_format, set_time_format methods);
53
-     */
54
-    /**
55
-     * @type string $_date_format
56
-     */
57
-    protected $_date_format = '';
58
-
59
-    /**
60
-     * @type string $_time_format
61
-     */
62
-    protected $_time_format = '';
63
-
64
-    /**
65
-     * @type string $_pretty_date_format
66
-     */
67
-    protected $_pretty_date_format = '';
68
-
69
-    /**
70
-     * @type string $_pretty_time_format
71
-     */
72
-    protected $_pretty_time_format = '';
73
-
74
-    /**
75
-     * @type DateTimeZone $_DateTimeZone
76
-     */
77
-    protected $_DateTimeZone;
78
-
79
-    /**
80
-     * @type DateTimeZone $_UTC_DateTimeZone
81
-     */
82
-    protected $_UTC_DateTimeZone;
83
-
84
-    /**
85
-     * @type DateTimeZone $_blog_DateTimeZone
86
-     */
87
-    protected $_blog_DateTimeZone;
88
-
89
-
90
-    /**
91
-     * This property holds how we want the output returned when getting a datetime string.  It is set for the
92
-     * set_date_time_output() method.  By default this is empty.  When empty, we are assuming that we want both date
93
-     * and time returned via getters.
94
-     *
95
-     * @var mixed (null|string)
96
-     */
97
-    protected $_date_time_output;
98
-
99
-
100
-    /**
101
-     * timezone string
102
-     * This gets set by the constructor and can be changed by the "set_timezone()" method so that we know what timezone
103
-     * incoming strings|timestamps are in.  This can also be used before a get to set what timezone you want strings
104
-     * coming out of the object to be in.  Default timezone is the current WP timezone option setting
105
-     *
106
-     * @var string
107
-     */
108
-    protected $_timezone_string;
109
-
110
-
111
-    /**
112
-     * This holds whatever UTC offset for the blog (we automatically convert timezone strings into their related
113
-     * offsets for comparison purposes).
114
-     *
115
-     * @var int
116
-     */
117
-    protected $_blog_offset;
118
-
119
-
120
-
121
-    /**
122
-     * @param string $table_column
123
-     * @param string $nice_name
124
-     * @param bool   $nullable
125
-     * @param string $default_value
126
-     * @param string $timezone_string
127
-     * @param string $date_format
128
-     * @param string $time_format
129
-     * @param string $pretty_date_format
130
-     * @param string $pretty_time_format
131
-     * @throws EE_Error
132
-     * @throws InvalidArgumentException
133
-     */
134
-    public function __construct(
135
-        $table_column,
136
-        $nice_name,
137
-        $nullable,
138
-        $default_value,
139
-        $timezone_string = '',
140
-        $date_format = '',
141
-        $time_format = '',
142
-        $pretty_date_format = '',
143
-        $pretty_time_format = ''
144
-    ) {
145
-
146
-        $this->_date_format        = ! empty($date_format) ? $date_format : get_option('date_format');
147
-        $this->_time_format        = ! empty($time_format) ? $time_format : get_option('time_format');
148
-        $this->_pretty_date_format = ! empty($pretty_date_format) ? $pretty_date_format : get_option('date_format');
149
-        $this->_pretty_time_format = ! empty($pretty_time_format) ? $pretty_time_format : get_option('time_format');
150
-
151
-        parent::__construct($table_column, $nice_name, $nullable, $default_value);
152
-        $this->set_timezone($timezone_string);
153
-        $this->setSchemaFormat('date-time');
154
-    }
155
-
156
-
157
-    /**
158
-     * @return DateTimeZone
159
-     * @throws \EE_Error
160
-     */
161
-    public function get_UTC_DateTimeZone()
162
-    {
163
-        return $this->_UTC_DateTimeZone instanceof DateTimeZone
164
-            ? $this->_UTC_DateTimeZone
165
-            : $this->_create_timezone_object_from_timezone_string('UTC');
166
-    }
167
-
168
-
169
-    /**
170
-     * @return DateTimeZone
171
-     * @throws \EE_Error
172
-     */
173
-    public function get_blog_DateTimeZone()
174
-    {
175
-        return $this->_blog_DateTimeZone instanceof DateTimeZone
176
-            ? $this->_blog_DateTimeZone
177
-            : $this->_create_timezone_object_from_timezone_string('');
178
-    }
179
-
180
-
181
-    /**
182
-     * this prepares any incoming date data and make sure its converted to a utc unix timestamp
183
-     *
184
-     * @param  string|int $value_inputted_for_field_on_model_object could be a string formatted date time or int unix
185
-     *                                                              timestamp
186
-     * @return DateTime
187
-     */
188
-    public function prepare_for_set($value_inputted_for_field_on_model_object)
189
-    {
190
-        return $this->_get_date_object($value_inputted_for_field_on_model_object);
191
-    }
192
-
193
-
194
-    /**
195
-     * This returns the format string to be used by getters depending on what the $_date_time_output property is set at.
196
-     * getters need to know whether we're just returning the date or the time or both.  By default we return both.
197
-     *
198
-     * @param bool $pretty If we're returning the pretty formats or standard format string.
199
-     * @return string    The final assembled format string.
200
-     */
201
-    protected function _get_date_time_output($pretty = false)
202
-    {
203
-
204
-        switch ($this->_date_time_output) {
205
-            case 'time' :
206
-                return $pretty ? $this->_pretty_time_format : $this->_time_format;
207
-                break;
208
-
209
-            case 'date' :
210
-                return $pretty ? $this->_pretty_date_format : $this->_date_format;
211
-                break;
212
-
213
-            default :
214
-                return $pretty
215
-                    ? $this->_pretty_date_format . ' ' . $this->_pretty_time_format
216
-                    : $this->_date_format . ' ' . $this->_time_format;
217
-        }
218
-    }
219
-
220
-
221
-    /**
222
-     * This just sets the $_date_time_output property so we can flag how date and times are formatted before being
223
-     * returned (using the format properties)
224
-     *
225
-     * @param string $what acceptable values are 'time' or 'date'.
226
-     *                     Any other value will be set but will always result
227
-     *                     in both 'date' and 'time' being returned.
228
-     * @return void
229
-     */
230
-    public function set_date_time_output($what = null)
231
-    {
232
-        $this->_date_time_output = $what;
233
-    }
234
-
235
-
236
-    /**
237
-     * See $_timezone property for description of what the timezone property is for.  This SETS the timezone internally
238
-     * for being able to reference what timezone we are running conversions on when converting TO the internal timezone
239
-     * (UTC Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp).
240
-     * We also set some other properties in this method.
241
-     *
242
-     * @param string $timezone_string A valid timezone string as described by @link
243
-     *                                http://www.php.net/manual/en/timezones.php
244
-     * @return void
245
-     * @throws \EE_Error
246
-     */
247
-    public function set_timezone($timezone_string)
248
-    {
249
-        if (empty($timezone_string) && $this->_timezone_string !== null) {
250
-            // leave the timezone AS-IS if we already have one and
251
-            // the function arg didn't provide one
252
-            return;
253
-        }
254
-        $timezone_string        = EEH_DTT_Helper::get_valid_timezone_string($timezone_string);
255
-        $this->_timezone_string = ! empty($timezone_string) ? $timezone_string : 'UTC';
256
-        $this->_DateTimeZone    = $this->_create_timezone_object_from_timezone_string($this->_timezone_string);
257
-    }
258
-
259
-
260
-    /**
261
-     * _create_timezone_object_from_timezone_name
262
-     *
263
-     * @access protected
264
-     * @param string $timezone_string
265
-     * @return \DateTimeZone
266
-     * @throws \EE_Error
267
-     */
268
-    protected function _create_timezone_object_from_timezone_string($timezone_string = '')
269
-    {
270
-        return new DateTimeZone(EEH_DTT_Helper::get_valid_timezone_string($timezone_string));
271
-    }
272
-
273
-
274
-    /**
275
-     * This just returns whatever is set for the current timezone.
276
-     *
277
-     * @access public
278
-     * @return string timezone string
279
-     */
280
-    public function get_timezone()
281
-    {
282
-        return $this->_timezone_string;
283
-    }
284
-
285
-
286
-    /**
287
-     * set the $_date_format property
288
-     *
289
-     * @access public
290
-     * @param string $format a new date format (corresponding to formats accepted by PHP date() function)
291
-     * @param bool   $pretty Whether to set pretty format or not.
292
-     * @return void
293
-     */
294
-    public function set_date_format($format, $pretty = false)
295
-    {
296
-        if ($pretty) {
297
-            $this->_pretty_date_format = $format;
298
-        } else {
299
-            $this->_date_format = $format;
300
-        }
301
-    }
302
-
303
-
304
-    /**
305
-     * return the $_date_format property value.
306
-     *
307
-     * @param bool $pretty Whether to get pretty format or not.
308
-     * @return string
309
-     */
310
-    public function get_date_format($pretty = false)
311
-    {
312
-        return $pretty ? $this->_pretty_date_format : $this->_date_format;
313
-    }
314
-
315
-
316
-    /**
317
-     * set the $_time_format property
318
-     *
319
-     * @access public
320
-     * @param string $format a new time format (corresponding to formats accepted by PHP date() function)
321
-     * @param bool   $pretty Whether to set pretty format or not.
322
-     * @return void
323
-     */
324
-    public function set_time_format($format, $pretty = false)
325
-    {
326
-        if ($pretty) {
327
-            $this->_pretty_time_format = $format;
328
-        } else {
329
-            $this->_time_format = $format;
330
-        }
331
-    }
332
-
333
-
334
-    /**
335
-     * return the $_time_format property value.
336
-     *
337
-     * @param bool $pretty Whether to get pretty format or not.
338
-     * @return string
339
-     */
340
-    public function get_time_format($pretty = false)
341
-    {
342
-        return $pretty ? $this->_pretty_time_format : $this->_time_format;
343
-    }
344
-
345
-
346
-    /**
347
-     * set the $_pretty_date_format property
348
-     *
349
-     * @access public
350
-     * @param string $format a new pretty date format (corresponding to formats accepted by PHP date() function)
351
-     * @return void
352
-     */
353
-    public function set_pretty_date_format($format)
354
-    {
355
-        $this->_pretty_date_format = $format;
356
-    }
357
-
358
-
359
-    /**
360
-     * set the $_pretty_time_format property
361
-     *
362
-     * @access public
363
-     * @param string $format a new pretty time format (corresponding to formats accepted by PHP date() function)
364
-     * @return void
365
-     */
366
-    public function set_pretty_time_format($format)
367
-    {
368
-        $this->_pretty_time_format = $format;
369
-    }
370
-
371
-
372
-    /**
373
-     * Only sets the time portion of the datetime.
374
-     *
375
-     * @param string|DateTime $time_to_set_string like 8am OR a DateTime object.
376
-     * @param DateTime        $current            current DateTime object for the datetime field
377
-     * @return DateTime
378
-     */
379
-    public function prepare_for_set_with_new_time($time_to_set_string, DateTime $current)
380
-    {
381
-        // if $time_to_set_string is datetime object, then let's use it to set the parse array.
382
-        // Otherwise parse the string.
383
-        if ($time_to_set_string instanceof DateTime) {
384
-            $parsed = array(
385
-                'hour'   => $time_to_set_string->format('H'),
386
-                'minute' => $time_to_set_string->format('i'),
387
-                'second' => $time_to_set_string->format('s'),
388
-            );
389
-        } else {
390
-            //parse incoming string
391
-            $parsed = date_parse_from_format($this->_time_format, $time_to_set_string);
392
-        }
393
-
394
-        //make sure $current is in the correct timezone.
395
-        $current->setTimezone($this->_DateTimeZone);
396
-
397
-        return $current->setTime($parsed['hour'], $parsed['minute'], $parsed['second']);
398
-    }
399
-
400
-
401
-    /**
402
-     * Only sets the date portion of the datetime.
403
-     *
404
-     * @param string|DateTime $date_to_set_string like Friday, January 8th or a DateTime object.
405
-     * @param DateTime        $current            current DateTime object for the datetime field
406
-     * @return DateTime
407
-     */
408
-    public function prepare_for_set_with_new_date($date_to_set_string, DateTime $current)
409
-    {
410
-        // if $time_to_set_string is datetime object, then let's use it to set the parse array.
411
-        // Otherwise parse the string.
412
-        if ($date_to_set_string instanceof DateTime) {
413
-            $parsed = array(
414
-                'year'  => $date_to_set_string->format('Y'),
415
-                'month' => $date_to_set_string->format('m'),
416
-                'day'   => $date_to_set_string->format('d'),
417
-            );
418
-        } else {
419
-            //parse incoming string
420
-            $parsed = date_parse_from_format($this->_date_format, $date_to_set_string);
421
-        }
422
-
423
-        //make sure $current is in the correct timezone
424
-        $current->setTimezone($this->_DateTimeZone);
425
-
426
-        return $current->setDate($parsed['year'], $parsed['month'], $parsed['day']);
427
-    }
428
-
429
-
430
-    /**
431
-     * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0 timezone).  When the
432
-     * datetime gets to this stage it should ALREADY be in UTC time
433
-     *
434
-     * @param  DateTime $DateTime
435
-     * @return string formatted date time for given timezone
436
-     * @throws \EE_Error
437
-     */
438
-    public function prepare_for_get($DateTime)
439
-    {
440
-        return $this->_prepare_for_display($DateTime);
441
-    }
442
-
443
-
444
-    /**
445
-     * This differs from prepare_for_get in that it considers whether the internal $_timezone differs
446
-     * from the set wp timezone.  If so, then it returns the datetime string formatted via
447
-     * _pretty_date_format, and _pretty_time_format.  However, it also appends a timezone
448
-     * abbreviation to the date_string.
449
-     *
450
-     * @param mixed $DateTime
451
-     * @param null  $schema
452
-     * @return string
453
-     * @throws \EE_Error
454
-     */
455
-    public function prepare_for_pretty_echoing($DateTime, $schema = null)
456
-    {
457
-        return $this->_prepare_for_display($DateTime, $schema ? $schema : true);
458
-    }
459
-
460
-
461
-    /**
462
-     * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0
463
-     * timezone).
464
-     *
465
-     * @param DateTime    $DateTime
466
-     * @param bool|string $schema
467
-     * @return string
468
-     * @throws \EE_Error
469
-     */
470
-    protected function _prepare_for_display($DateTime, $schema = false)
471
-    {
472
-        if (! $DateTime instanceof DateTime) {
473
-            if ($this->_nullable) {
474
-                return '';
475
-            } else {
476
-                if (WP_DEBUG) {
477
-                    throw new EE_Error(
478
-                        sprintf(
479
-                            __(
480
-                                'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable.',
481
-                                'event_espresso'
482
-                            ),
483
-                            $this->_nicename
484
-                        )
485
-                    );
486
-                } else {
487
-                    $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now);
488
-                    EE_Error::add_error(
489
-                        sprintf(
490
-                            __(
491
-                                'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable.  When WP_DEBUG is false, the value is set to "now" instead of throwing an exception.',
492
-                                'event_espresso'
493
-                            ),
494
-                            $this->_nicename
495
-                        )
496
-                    );
497
-                }
498
-            }
499
-        }
500
-        $format_string = $this->_get_date_time_output($schema);
501
-        //make sure datetime_value is in the correct timezone (in case that's been updated).
502
-        $DateTime->setTimezone($this->_DateTimeZone);
503
-        if ($schema) {
504
-            if ($this->_display_timezone()) {
505
-                //must be explicit because schema could equal true.
506
-                if ($schema === 'no_html') {
507
-                    $timezone_string = ' (' . $DateTime->format('T') . ')';
508
-                } else {
509
-                    $timezone_string = ' <span class="ee_dtt_timezone_string">(' . $DateTime->format('T') . ')</span>';
510
-                }
511
-            } else {
512
-                $timezone_string = '';
513
-            }
514
-
515
-            return $DateTime->format($format_string) . $timezone_string;
516
-        } else {
517
-            return $DateTime->format($format_string);
518
-        }
519
-    }
520
-
521
-
522
-    /**
523
-     * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0
524
-     * timezone).
525
-     *
526
-     * @param  mixed $datetime_value u
527
-     * @return string mysql timestamp in UTC
528
-     * @throws \EE_Error
529
-     */
530
-    public function prepare_for_use_in_db($datetime_value)
531
-    {
532
-        //we allow an empty value or DateTime object, but nothing else.
533
-        if (! empty($datetime_value) && ! $datetime_value instanceof DateTime) {
534
-            throw new EE_Error(
535
-            	sprintf(
536
-            	    __(
537
-            		    'The incoming value being prepared for setting in the database must either be empty or a php 
18
+	/**
19
+	 * The pattern we're looking for is if only the characters 0-9 are found and there are only
20
+	 * 10 or more numbers (because 9 numbers even with all 9's would be sometime in 2001 )
21
+	 *
22
+	 * @type string unix_timestamp_regex
23
+	 */
24
+	const unix_timestamp_regex = '/[0-9]{10,}/';
25
+
26
+	/**
27
+	 * @type string mysql_timestamp_format
28
+	 */
29
+	const mysql_timestamp_format = 'Y-m-d H:i:s';
30
+
31
+	/**
32
+	 * @type string mysql_date_format
33
+	 */
34
+	const mysql_date_format = 'Y-m-d';
35
+
36
+	/**
37
+	 * @type string mysql_time_format
38
+	 */
39
+	const mysql_time_format = 'H:i:s';
40
+
41
+	/**
42
+	 * Const for using in the default value. If the field's default is set to this,
43
+	 * then we will return the time of calling `get_default_value()`, not
44
+	 * just the current time at construction
45
+	 */
46
+	const now = 'now';
47
+
48
+	/**
49
+	 * The following properties hold the default formats for date and time.
50
+	 * Defaults are set via the constructor and can be overridden on class instantiation.
51
+	 * However they can also be overridden later by the set_format() method
52
+	 * (and corresponding set_date_format, set_time_format methods);
53
+	 */
54
+	/**
55
+	 * @type string $_date_format
56
+	 */
57
+	protected $_date_format = '';
58
+
59
+	/**
60
+	 * @type string $_time_format
61
+	 */
62
+	protected $_time_format = '';
63
+
64
+	/**
65
+	 * @type string $_pretty_date_format
66
+	 */
67
+	protected $_pretty_date_format = '';
68
+
69
+	/**
70
+	 * @type string $_pretty_time_format
71
+	 */
72
+	protected $_pretty_time_format = '';
73
+
74
+	/**
75
+	 * @type DateTimeZone $_DateTimeZone
76
+	 */
77
+	protected $_DateTimeZone;
78
+
79
+	/**
80
+	 * @type DateTimeZone $_UTC_DateTimeZone
81
+	 */
82
+	protected $_UTC_DateTimeZone;
83
+
84
+	/**
85
+	 * @type DateTimeZone $_blog_DateTimeZone
86
+	 */
87
+	protected $_blog_DateTimeZone;
88
+
89
+
90
+	/**
91
+	 * This property holds how we want the output returned when getting a datetime string.  It is set for the
92
+	 * set_date_time_output() method.  By default this is empty.  When empty, we are assuming that we want both date
93
+	 * and time returned via getters.
94
+	 *
95
+	 * @var mixed (null|string)
96
+	 */
97
+	protected $_date_time_output;
98
+
99
+
100
+	/**
101
+	 * timezone string
102
+	 * This gets set by the constructor and can be changed by the "set_timezone()" method so that we know what timezone
103
+	 * incoming strings|timestamps are in.  This can also be used before a get to set what timezone you want strings
104
+	 * coming out of the object to be in.  Default timezone is the current WP timezone option setting
105
+	 *
106
+	 * @var string
107
+	 */
108
+	protected $_timezone_string;
109
+
110
+
111
+	/**
112
+	 * This holds whatever UTC offset for the blog (we automatically convert timezone strings into their related
113
+	 * offsets for comparison purposes).
114
+	 *
115
+	 * @var int
116
+	 */
117
+	protected $_blog_offset;
118
+
119
+
120
+
121
+	/**
122
+	 * @param string $table_column
123
+	 * @param string $nice_name
124
+	 * @param bool   $nullable
125
+	 * @param string $default_value
126
+	 * @param string $timezone_string
127
+	 * @param string $date_format
128
+	 * @param string $time_format
129
+	 * @param string $pretty_date_format
130
+	 * @param string $pretty_time_format
131
+	 * @throws EE_Error
132
+	 * @throws InvalidArgumentException
133
+	 */
134
+	public function __construct(
135
+		$table_column,
136
+		$nice_name,
137
+		$nullable,
138
+		$default_value,
139
+		$timezone_string = '',
140
+		$date_format = '',
141
+		$time_format = '',
142
+		$pretty_date_format = '',
143
+		$pretty_time_format = ''
144
+	) {
145
+
146
+		$this->_date_format        = ! empty($date_format) ? $date_format : get_option('date_format');
147
+		$this->_time_format        = ! empty($time_format) ? $time_format : get_option('time_format');
148
+		$this->_pretty_date_format = ! empty($pretty_date_format) ? $pretty_date_format : get_option('date_format');
149
+		$this->_pretty_time_format = ! empty($pretty_time_format) ? $pretty_time_format : get_option('time_format');
150
+
151
+		parent::__construct($table_column, $nice_name, $nullable, $default_value);
152
+		$this->set_timezone($timezone_string);
153
+		$this->setSchemaFormat('date-time');
154
+	}
155
+
156
+
157
+	/**
158
+	 * @return DateTimeZone
159
+	 * @throws \EE_Error
160
+	 */
161
+	public function get_UTC_DateTimeZone()
162
+	{
163
+		return $this->_UTC_DateTimeZone instanceof DateTimeZone
164
+			? $this->_UTC_DateTimeZone
165
+			: $this->_create_timezone_object_from_timezone_string('UTC');
166
+	}
167
+
168
+
169
+	/**
170
+	 * @return DateTimeZone
171
+	 * @throws \EE_Error
172
+	 */
173
+	public function get_blog_DateTimeZone()
174
+	{
175
+		return $this->_blog_DateTimeZone instanceof DateTimeZone
176
+			? $this->_blog_DateTimeZone
177
+			: $this->_create_timezone_object_from_timezone_string('');
178
+	}
179
+
180
+
181
+	/**
182
+	 * this prepares any incoming date data and make sure its converted to a utc unix timestamp
183
+	 *
184
+	 * @param  string|int $value_inputted_for_field_on_model_object could be a string formatted date time or int unix
185
+	 *                                                              timestamp
186
+	 * @return DateTime
187
+	 */
188
+	public function prepare_for_set($value_inputted_for_field_on_model_object)
189
+	{
190
+		return $this->_get_date_object($value_inputted_for_field_on_model_object);
191
+	}
192
+
193
+
194
+	/**
195
+	 * This returns the format string to be used by getters depending on what the $_date_time_output property is set at.
196
+	 * getters need to know whether we're just returning the date or the time or both.  By default we return both.
197
+	 *
198
+	 * @param bool $pretty If we're returning the pretty formats or standard format string.
199
+	 * @return string    The final assembled format string.
200
+	 */
201
+	protected function _get_date_time_output($pretty = false)
202
+	{
203
+
204
+		switch ($this->_date_time_output) {
205
+			case 'time' :
206
+				return $pretty ? $this->_pretty_time_format : $this->_time_format;
207
+				break;
208
+
209
+			case 'date' :
210
+				return $pretty ? $this->_pretty_date_format : $this->_date_format;
211
+				break;
212
+
213
+			default :
214
+				return $pretty
215
+					? $this->_pretty_date_format . ' ' . $this->_pretty_time_format
216
+					: $this->_date_format . ' ' . $this->_time_format;
217
+		}
218
+	}
219
+
220
+
221
+	/**
222
+	 * This just sets the $_date_time_output property so we can flag how date and times are formatted before being
223
+	 * returned (using the format properties)
224
+	 *
225
+	 * @param string $what acceptable values are 'time' or 'date'.
226
+	 *                     Any other value will be set but will always result
227
+	 *                     in both 'date' and 'time' being returned.
228
+	 * @return void
229
+	 */
230
+	public function set_date_time_output($what = null)
231
+	{
232
+		$this->_date_time_output = $what;
233
+	}
234
+
235
+
236
+	/**
237
+	 * See $_timezone property for description of what the timezone property is for.  This SETS the timezone internally
238
+	 * for being able to reference what timezone we are running conversions on when converting TO the internal timezone
239
+	 * (UTC Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp).
240
+	 * We also set some other properties in this method.
241
+	 *
242
+	 * @param string $timezone_string A valid timezone string as described by @link
243
+	 *                                http://www.php.net/manual/en/timezones.php
244
+	 * @return void
245
+	 * @throws \EE_Error
246
+	 */
247
+	public function set_timezone($timezone_string)
248
+	{
249
+		if (empty($timezone_string) && $this->_timezone_string !== null) {
250
+			// leave the timezone AS-IS if we already have one and
251
+			// the function arg didn't provide one
252
+			return;
253
+		}
254
+		$timezone_string        = EEH_DTT_Helper::get_valid_timezone_string($timezone_string);
255
+		$this->_timezone_string = ! empty($timezone_string) ? $timezone_string : 'UTC';
256
+		$this->_DateTimeZone    = $this->_create_timezone_object_from_timezone_string($this->_timezone_string);
257
+	}
258
+
259
+
260
+	/**
261
+	 * _create_timezone_object_from_timezone_name
262
+	 *
263
+	 * @access protected
264
+	 * @param string $timezone_string
265
+	 * @return \DateTimeZone
266
+	 * @throws \EE_Error
267
+	 */
268
+	protected function _create_timezone_object_from_timezone_string($timezone_string = '')
269
+	{
270
+		return new DateTimeZone(EEH_DTT_Helper::get_valid_timezone_string($timezone_string));
271
+	}
272
+
273
+
274
+	/**
275
+	 * This just returns whatever is set for the current timezone.
276
+	 *
277
+	 * @access public
278
+	 * @return string timezone string
279
+	 */
280
+	public function get_timezone()
281
+	{
282
+		return $this->_timezone_string;
283
+	}
284
+
285
+
286
+	/**
287
+	 * set the $_date_format property
288
+	 *
289
+	 * @access public
290
+	 * @param string $format a new date format (corresponding to formats accepted by PHP date() function)
291
+	 * @param bool   $pretty Whether to set pretty format or not.
292
+	 * @return void
293
+	 */
294
+	public function set_date_format($format, $pretty = false)
295
+	{
296
+		if ($pretty) {
297
+			$this->_pretty_date_format = $format;
298
+		} else {
299
+			$this->_date_format = $format;
300
+		}
301
+	}
302
+
303
+
304
+	/**
305
+	 * return the $_date_format property value.
306
+	 *
307
+	 * @param bool $pretty Whether to get pretty format or not.
308
+	 * @return string
309
+	 */
310
+	public function get_date_format($pretty = false)
311
+	{
312
+		return $pretty ? $this->_pretty_date_format : $this->_date_format;
313
+	}
314
+
315
+
316
+	/**
317
+	 * set the $_time_format property
318
+	 *
319
+	 * @access public
320
+	 * @param string $format a new time format (corresponding to formats accepted by PHP date() function)
321
+	 * @param bool   $pretty Whether to set pretty format or not.
322
+	 * @return void
323
+	 */
324
+	public function set_time_format($format, $pretty = false)
325
+	{
326
+		if ($pretty) {
327
+			$this->_pretty_time_format = $format;
328
+		} else {
329
+			$this->_time_format = $format;
330
+		}
331
+	}
332
+
333
+
334
+	/**
335
+	 * return the $_time_format property value.
336
+	 *
337
+	 * @param bool $pretty Whether to get pretty format or not.
338
+	 * @return string
339
+	 */
340
+	public function get_time_format($pretty = false)
341
+	{
342
+		return $pretty ? $this->_pretty_time_format : $this->_time_format;
343
+	}
344
+
345
+
346
+	/**
347
+	 * set the $_pretty_date_format property
348
+	 *
349
+	 * @access public
350
+	 * @param string $format a new pretty date format (corresponding to formats accepted by PHP date() function)
351
+	 * @return void
352
+	 */
353
+	public function set_pretty_date_format($format)
354
+	{
355
+		$this->_pretty_date_format = $format;
356
+	}
357
+
358
+
359
+	/**
360
+	 * set the $_pretty_time_format property
361
+	 *
362
+	 * @access public
363
+	 * @param string $format a new pretty time format (corresponding to formats accepted by PHP date() function)
364
+	 * @return void
365
+	 */
366
+	public function set_pretty_time_format($format)
367
+	{
368
+		$this->_pretty_time_format = $format;
369
+	}
370
+
371
+
372
+	/**
373
+	 * Only sets the time portion of the datetime.
374
+	 *
375
+	 * @param string|DateTime $time_to_set_string like 8am OR a DateTime object.
376
+	 * @param DateTime        $current            current DateTime object for the datetime field
377
+	 * @return DateTime
378
+	 */
379
+	public function prepare_for_set_with_new_time($time_to_set_string, DateTime $current)
380
+	{
381
+		// if $time_to_set_string is datetime object, then let's use it to set the parse array.
382
+		// Otherwise parse the string.
383
+		if ($time_to_set_string instanceof DateTime) {
384
+			$parsed = array(
385
+				'hour'   => $time_to_set_string->format('H'),
386
+				'minute' => $time_to_set_string->format('i'),
387
+				'second' => $time_to_set_string->format('s'),
388
+			);
389
+		} else {
390
+			//parse incoming string
391
+			$parsed = date_parse_from_format($this->_time_format, $time_to_set_string);
392
+		}
393
+
394
+		//make sure $current is in the correct timezone.
395
+		$current->setTimezone($this->_DateTimeZone);
396
+
397
+		return $current->setTime($parsed['hour'], $parsed['minute'], $parsed['second']);
398
+	}
399
+
400
+
401
+	/**
402
+	 * Only sets the date portion of the datetime.
403
+	 *
404
+	 * @param string|DateTime $date_to_set_string like Friday, January 8th or a DateTime object.
405
+	 * @param DateTime        $current            current DateTime object for the datetime field
406
+	 * @return DateTime
407
+	 */
408
+	public function prepare_for_set_with_new_date($date_to_set_string, DateTime $current)
409
+	{
410
+		// if $time_to_set_string is datetime object, then let's use it to set the parse array.
411
+		// Otherwise parse the string.
412
+		if ($date_to_set_string instanceof DateTime) {
413
+			$parsed = array(
414
+				'year'  => $date_to_set_string->format('Y'),
415
+				'month' => $date_to_set_string->format('m'),
416
+				'day'   => $date_to_set_string->format('d'),
417
+			);
418
+		} else {
419
+			//parse incoming string
420
+			$parsed = date_parse_from_format($this->_date_format, $date_to_set_string);
421
+		}
422
+
423
+		//make sure $current is in the correct timezone
424
+		$current->setTimezone($this->_DateTimeZone);
425
+
426
+		return $current->setDate($parsed['year'], $parsed['month'], $parsed['day']);
427
+	}
428
+
429
+
430
+	/**
431
+	 * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0 timezone).  When the
432
+	 * datetime gets to this stage it should ALREADY be in UTC time
433
+	 *
434
+	 * @param  DateTime $DateTime
435
+	 * @return string formatted date time for given timezone
436
+	 * @throws \EE_Error
437
+	 */
438
+	public function prepare_for_get($DateTime)
439
+	{
440
+		return $this->_prepare_for_display($DateTime);
441
+	}
442
+
443
+
444
+	/**
445
+	 * This differs from prepare_for_get in that it considers whether the internal $_timezone differs
446
+	 * from the set wp timezone.  If so, then it returns the datetime string formatted via
447
+	 * _pretty_date_format, and _pretty_time_format.  However, it also appends a timezone
448
+	 * abbreviation to the date_string.
449
+	 *
450
+	 * @param mixed $DateTime
451
+	 * @param null  $schema
452
+	 * @return string
453
+	 * @throws \EE_Error
454
+	 */
455
+	public function prepare_for_pretty_echoing($DateTime, $schema = null)
456
+	{
457
+		return $this->_prepare_for_display($DateTime, $schema ? $schema : true);
458
+	}
459
+
460
+
461
+	/**
462
+	 * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0
463
+	 * timezone).
464
+	 *
465
+	 * @param DateTime    $DateTime
466
+	 * @param bool|string $schema
467
+	 * @return string
468
+	 * @throws \EE_Error
469
+	 */
470
+	protected function _prepare_for_display($DateTime, $schema = false)
471
+	{
472
+		if (! $DateTime instanceof DateTime) {
473
+			if ($this->_nullable) {
474
+				return '';
475
+			} else {
476
+				if (WP_DEBUG) {
477
+					throw new EE_Error(
478
+						sprintf(
479
+							__(
480
+								'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable.',
481
+								'event_espresso'
482
+							),
483
+							$this->_nicename
484
+						)
485
+					);
486
+				} else {
487
+					$DateTime = new DbSafeDateTime(\EE_Datetime_Field::now);
488
+					EE_Error::add_error(
489
+						sprintf(
490
+							__(
491
+								'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable.  When WP_DEBUG is false, the value is set to "now" instead of throwing an exception.',
492
+								'event_espresso'
493
+							),
494
+							$this->_nicename
495
+						)
496
+					);
497
+				}
498
+			}
499
+		}
500
+		$format_string = $this->_get_date_time_output($schema);
501
+		//make sure datetime_value is in the correct timezone (in case that's been updated).
502
+		$DateTime->setTimezone($this->_DateTimeZone);
503
+		if ($schema) {
504
+			if ($this->_display_timezone()) {
505
+				//must be explicit because schema could equal true.
506
+				if ($schema === 'no_html') {
507
+					$timezone_string = ' (' . $DateTime->format('T') . ')';
508
+				} else {
509
+					$timezone_string = ' <span class="ee_dtt_timezone_string">(' . $DateTime->format('T') . ')</span>';
510
+				}
511
+			} else {
512
+				$timezone_string = '';
513
+			}
514
+
515
+			return $DateTime->format($format_string) . $timezone_string;
516
+		} else {
517
+			return $DateTime->format($format_string);
518
+		}
519
+	}
520
+
521
+
522
+	/**
523
+	 * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0
524
+	 * timezone).
525
+	 *
526
+	 * @param  mixed $datetime_value u
527
+	 * @return string mysql timestamp in UTC
528
+	 * @throws \EE_Error
529
+	 */
530
+	public function prepare_for_use_in_db($datetime_value)
531
+	{
532
+		//we allow an empty value or DateTime object, but nothing else.
533
+		if (! empty($datetime_value) && ! $datetime_value instanceof DateTime) {
534
+			throw new EE_Error(
535
+				sprintf(
536
+					__(
537
+						'The incoming value being prepared for setting in the database must either be empty or a php 
538 538
             		    DateTime object, instead of: %1$s %2$s',
539
-                        'event_espresso'
540
-	                ),
541
-                    '<br />',
542
-                    print_r($datetime_value, true)
543
-                )
544
-            );
545
-        }
546
-
547
-        if ($datetime_value instanceof DateTime) {
548
-            if ( ! $datetime_value instanceof DbSafeDateTime) {
549
-                $datetime_value = DbSafeDateTime::createFromDateTime($datetime_value);
550
-            }
551
-
552
-            return $datetime_value->setTimezone($this->get_UTC_DateTimeZone())->format(
553
-                EE_Datetime_Field::mysql_timestamp_format
554
-            );
555
-        }
556
-
557
-        // if $datetime_value is empty, and ! $this->_nullable, use current_time() but set the GMT flag to true
558
-        return ! $this->_nullable && empty($datetime_value) ? current_time('mysql', true) : null;
559
-    }
560
-
561
-
562
-    /**
563
-     * This prepares the datetime for internal usage as a PHP DateTime object OR null (if nullable is
564
-     * allowed)
565
-     *
566
-     * @param string $datetime_string mysql timestamp in UTC
567
-     * @return  mixed null | DateTime
568
-     * @throws \EE_Error
569
-     */
570
-    public function prepare_for_set_from_db($datetime_string)
571
-    {
572
-        //if $datetime_value is empty, and ! $this->_nullable, just use time()
573
-        if (empty($datetime_string) && $this->_nullable) {
574
-            return null;
575
-        }
576
-        // datetime strings from the db should ALWAYS be in UTC+0, so use UTC_DateTimeZone when creating
577
-        if (empty($datetime_string)) {
578
-            $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone());
579
-        } else {
580
-            $DateTime = DateTime::createFromFormat(
581
-                EE_Datetime_Field::mysql_timestamp_format,
582
-                $datetime_string,
583
-                $this->get_UTC_DateTimeZone()
584
-            );
585
-            if ($DateTime instanceof \DateTime) {
586
-                $DateTime = new DbSafeDateTime(
587
-                    $DateTime->format(\EE_Datetime_Field::mysql_timestamp_format),
588
-                    $this->get_UTC_DateTimeZone()
589
-                );
590
-            }
591
-        }
592
-
593
-        if (! $DateTime instanceof DbSafeDateTime) {
594
-            // if still no datetime object, then let's just use now
595
-            $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone());
596
-        }
597
-        // THEN apply the field's set DateTimeZone
598
-        $DateTime->setTimezone($this->_DateTimeZone);
599
-
600
-        return $DateTime;
601
-    }
602
-
603
-
604
-    /**
605
-     * All this method does is determine if we're going to display the timezone string or not on any output.
606
-     * To determine this we check if the set timezone offset is different than the blog's set timezone offset.
607
-     * If so, then true.
608
-     *
609
-     * @return bool true for yes false for no
610
-     * @throws \EE_Error
611
-     */
612
-    protected function _display_timezone()
613
-    {
614
-
615
-        // first let's do a comparison of timezone strings.
616
-        // If they match then we can get out without any further calculations
617
-        $blog_string = get_option('timezone_string');
618
-        if ($blog_string === $this->_timezone_string) {
619
-            return false;
620
-        }
621
-        // now we need to calc the offset for the timezone string so we can compare with the blog offset.
622
-        $this_offset = $this->get_timezone_offset($this->_DateTimeZone);
623
-        $blog_offset = $this->get_timezone_offset($this->get_blog_DateTimeZone());
624
-        // now compare
625
-        return $blog_offset !== $this_offset;
626
-    }
627
-
628
-
629
-    /**
630
-     * This method returns a php DateTime object for setting on the EE_Base_Class model.
631
-     * EE passes around DateTime objects because they are MUCH easier to manipulate and deal
632
-     * with.
633
-     *
634
-     * @param int|string|DateTime $date_string            This should be the incoming date string.  It's assumed to be
635
-     *                                                    in the format that is set on the date_field (or DateTime
636
-     *                                                    object)!
637
-     * @return DateTime
638
-     */
639
-    protected function _get_date_object($date_string)
640
-    {
641
-        //first if this is an empty date_string and nullable is allowed, just return null.
642
-        if ($this->_nullable && empty($date_string)) {
643
-            return null;
644
-        }
645
-
646
-        // if incoming date
647
-        if ($date_string instanceof DateTime) {
648
-            $date_string->setTimezone($this->_DateTimeZone);
649
-
650
-            return $date_string;
651
-        }
652
-        // if empty date_string and made it here.
653
-        // Return a datetime object for now in the given timezone.
654
-        if (empty($date_string)) {
655
-            return new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
656
-        }
657
-        // if $date_string is matches something that looks like a Unix timestamp let's just use it.
658
-        if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $date_string)) {
659
-            try {
660
-                // This is operating under the assumption that the incoming Unix timestamp
661
-                // is an ACTUAL Unix timestamp and not the calculated one output by current_time('timestamp');
662
-                $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
663
-                $DateTime->setTimestamp($date_string);
664
-
665
-                return $DateTime;
666
-            } catch (Exception $e) {
667
-                // should be rare, but if things got fooled then let's just continue
668
-            }
669
-        }
670
-        //not a unix timestamp.  So we will use the set format on this object and set timezone to
671
-        //create the DateTime object.
672
-        $format = $this->_date_format . ' ' . $this->_time_format;
673
-        try {
674
-            $DateTime = DateTime::createFromFormat($format, $date_string, $this->_DateTimeZone);
675
-            if ($DateTime instanceof DateTime) {
676
-                $DateTime = new DbSafeDateTime(
677
-                    $DateTime->format(\EE_Datetime_Field::mysql_timestamp_format),
678
-                    $this->_DateTimeZone
679
-                );
680
-            }
681
-            if (! $DateTime instanceof DbSafeDateTime) {
682
-                throw new EE_Error(
683
-                    sprintf(
684
-                        __('"%1$s" does not represent a valid Date Time in the format "%2$s".', 'event_espresso'),
685
-                        $date_string,
686
-                        $format
687
-                    )
688
-                );
689
-            }
690
-        } catch (Exception $e) {
691
-            // if we made it here then likely then something went really wrong.
692
-            // Instead of throwing an exception, let's just return a DateTime object for now, in the set timezone.
693
-            $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
694
-        }
695
-
696
-        return $DateTime;
697
-    }
698
-
699
-
700
-
701
-    /**
702
-     * get_timezone_transitions
703
-     *
704
-     * @param \DateTimeZone $DateTimeZone
705
-     * @param int           $time
706
-     * @param bool          $first_only
707
-     * @return mixed
708
-     */
709
-    public function get_timezone_transitions(DateTimeZone $DateTimeZone, $time = null, $first_only = true)
710
-    {
711
-        $time = is_int($time) || $time === null ? $time : strtotime($time);
712
-        $time = preg_match(EE_Datetime_Field::unix_timestamp_regex, $time) ? $time : time();
713
-        $transitions = $DateTimeZone->getTransitions($time);
714
-        return $first_only && ! isset($transitions['ts']) ? reset($transitions) : $transitions;
715
-    }
716
-
717
-
718
-
719
-    /**
720
-     * get_timezone_offset
721
-     *
722
-     * @param \DateTimeZone $DateTimeZone
723
-     * @param int           $time
724
-     * @return mixed
725
-     * @throws \DomainException
726
-     */
727
-    public function get_timezone_offset(DateTimeZone $DateTimeZone, $time = null)
728
-    {
729
-        $transitions = $this->get_timezone_transitions($DateTimeZone, $time);
730
-        if ( ! isset($transitions['offset'])) {
731
-            throw new DomainException();
732
-        }
733
-        return $transitions['offset'];
734
-    }
735
-
736
-
737
-    /**
738
-     * This will take an incoming timezone string and return the abbreviation for that timezone
739
-     *
740
-     * @param  string $timezone_string
741
-     * @return string           abbreviation
742
-     * @throws \EE_Error
743
-     */
744
-    public function get_timezone_abbrev($timezone_string)
745
-    {
746
-        $timezone_string = EEH_DTT_Helper::get_valid_timezone_string($timezone_string);
747
-        $dateTime        = new DateTime(\EE_Datetime_Field::now, new DateTimeZone($timezone_string));
748
-
749
-        return $dateTime->format('T');
750
-    }
751
-
752
-    /**
753
-     * Overrides the parent to allow for having a dynamic "now" value
754
-     *
755
-     * @return mixed
756
-     */
757
-    public function get_default_value()
758
-    {
759
-        if ($this->_default_value === EE_Datetime_Field::now) {
760
-            return time();
761
-        } else {
762
-            return parent::get_default_value();
763
-        }
764
-    }
765
-
766
-
767
-    public function getSchemaDescription()
768
-    {
769
-        return sprintf(
770
-            esc_html__('%s - the value for this field is in the timezone of the site.', 'event_espresso'),
771
-            $this->get_nicename()
772
-        );
773
-    }
539
+						'event_espresso'
540
+					),
541
+					'<br />',
542
+					print_r($datetime_value, true)
543
+				)
544
+			);
545
+		}
546
+
547
+		if ($datetime_value instanceof DateTime) {
548
+			if ( ! $datetime_value instanceof DbSafeDateTime) {
549
+				$datetime_value = DbSafeDateTime::createFromDateTime($datetime_value);
550
+			}
551
+
552
+			return $datetime_value->setTimezone($this->get_UTC_DateTimeZone())->format(
553
+				EE_Datetime_Field::mysql_timestamp_format
554
+			);
555
+		}
556
+
557
+		// if $datetime_value is empty, and ! $this->_nullable, use current_time() but set the GMT flag to true
558
+		return ! $this->_nullable && empty($datetime_value) ? current_time('mysql', true) : null;
559
+	}
560
+
561
+
562
+	/**
563
+	 * This prepares the datetime for internal usage as a PHP DateTime object OR null (if nullable is
564
+	 * allowed)
565
+	 *
566
+	 * @param string $datetime_string mysql timestamp in UTC
567
+	 * @return  mixed null | DateTime
568
+	 * @throws \EE_Error
569
+	 */
570
+	public function prepare_for_set_from_db($datetime_string)
571
+	{
572
+		//if $datetime_value is empty, and ! $this->_nullable, just use time()
573
+		if (empty($datetime_string) && $this->_nullable) {
574
+			return null;
575
+		}
576
+		// datetime strings from the db should ALWAYS be in UTC+0, so use UTC_DateTimeZone when creating
577
+		if (empty($datetime_string)) {
578
+			$DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone());
579
+		} else {
580
+			$DateTime = DateTime::createFromFormat(
581
+				EE_Datetime_Field::mysql_timestamp_format,
582
+				$datetime_string,
583
+				$this->get_UTC_DateTimeZone()
584
+			);
585
+			if ($DateTime instanceof \DateTime) {
586
+				$DateTime = new DbSafeDateTime(
587
+					$DateTime->format(\EE_Datetime_Field::mysql_timestamp_format),
588
+					$this->get_UTC_DateTimeZone()
589
+				);
590
+			}
591
+		}
592
+
593
+		if (! $DateTime instanceof DbSafeDateTime) {
594
+			// if still no datetime object, then let's just use now
595
+			$DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone());
596
+		}
597
+		// THEN apply the field's set DateTimeZone
598
+		$DateTime->setTimezone($this->_DateTimeZone);
599
+
600
+		return $DateTime;
601
+	}
602
+
603
+
604
+	/**
605
+	 * All this method does is determine if we're going to display the timezone string or not on any output.
606
+	 * To determine this we check if the set timezone offset is different than the blog's set timezone offset.
607
+	 * If so, then true.
608
+	 *
609
+	 * @return bool true for yes false for no
610
+	 * @throws \EE_Error
611
+	 */
612
+	protected function _display_timezone()
613
+	{
614
+
615
+		// first let's do a comparison of timezone strings.
616
+		// If they match then we can get out without any further calculations
617
+		$blog_string = get_option('timezone_string');
618
+		if ($blog_string === $this->_timezone_string) {
619
+			return false;
620
+		}
621
+		// now we need to calc the offset for the timezone string so we can compare with the blog offset.
622
+		$this_offset = $this->get_timezone_offset($this->_DateTimeZone);
623
+		$blog_offset = $this->get_timezone_offset($this->get_blog_DateTimeZone());
624
+		// now compare
625
+		return $blog_offset !== $this_offset;
626
+	}
627
+
628
+
629
+	/**
630
+	 * This method returns a php DateTime object for setting on the EE_Base_Class model.
631
+	 * EE passes around DateTime objects because they are MUCH easier to manipulate and deal
632
+	 * with.
633
+	 *
634
+	 * @param int|string|DateTime $date_string            This should be the incoming date string.  It's assumed to be
635
+	 *                                                    in the format that is set on the date_field (or DateTime
636
+	 *                                                    object)!
637
+	 * @return DateTime
638
+	 */
639
+	protected function _get_date_object($date_string)
640
+	{
641
+		//first if this is an empty date_string and nullable is allowed, just return null.
642
+		if ($this->_nullable && empty($date_string)) {
643
+			return null;
644
+		}
645
+
646
+		// if incoming date
647
+		if ($date_string instanceof DateTime) {
648
+			$date_string->setTimezone($this->_DateTimeZone);
649
+
650
+			return $date_string;
651
+		}
652
+		// if empty date_string and made it here.
653
+		// Return a datetime object for now in the given timezone.
654
+		if (empty($date_string)) {
655
+			return new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
656
+		}
657
+		// if $date_string is matches something that looks like a Unix timestamp let's just use it.
658
+		if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $date_string)) {
659
+			try {
660
+				// This is operating under the assumption that the incoming Unix timestamp
661
+				// is an ACTUAL Unix timestamp and not the calculated one output by current_time('timestamp');
662
+				$DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
663
+				$DateTime->setTimestamp($date_string);
664
+
665
+				return $DateTime;
666
+			} catch (Exception $e) {
667
+				// should be rare, but if things got fooled then let's just continue
668
+			}
669
+		}
670
+		//not a unix timestamp.  So we will use the set format on this object and set timezone to
671
+		//create the DateTime object.
672
+		$format = $this->_date_format . ' ' . $this->_time_format;
673
+		try {
674
+			$DateTime = DateTime::createFromFormat($format, $date_string, $this->_DateTimeZone);
675
+			if ($DateTime instanceof DateTime) {
676
+				$DateTime = new DbSafeDateTime(
677
+					$DateTime->format(\EE_Datetime_Field::mysql_timestamp_format),
678
+					$this->_DateTimeZone
679
+				);
680
+			}
681
+			if (! $DateTime instanceof DbSafeDateTime) {
682
+				throw new EE_Error(
683
+					sprintf(
684
+						__('"%1$s" does not represent a valid Date Time in the format "%2$s".', 'event_espresso'),
685
+						$date_string,
686
+						$format
687
+					)
688
+				);
689
+			}
690
+		} catch (Exception $e) {
691
+			// if we made it here then likely then something went really wrong.
692
+			// Instead of throwing an exception, let's just return a DateTime object for now, in the set timezone.
693
+			$DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
694
+		}
695
+
696
+		return $DateTime;
697
+	}
698
+
699
+
700
+
701
+	/**
702
+	 * get_timezone_transitions
703
+	 *
704
+	 * @param \DateTimeZone $DateTimeZone
705
+	 * @param int           $time
706
+	 * @param bool          $first_only
707
+	 * @return mixed
708
+	 */
709
+	public function get_timezone_transitions(DateTimeZone $DateTimeZone, $time = null, $first_only = true)
710
+	{
711
+		$time = is_int($time) || $time === null ? $time : strtotime($time);
712
+		$time = preg_match(EE_Datetime_Field::unix_timestamp_regex, $time) ? $time : time();
713
+		$transitions = $DateTimeZone->getTransitions($time);
714
+		return $first_only && ! isset($transitions['ts']) ? reset($transitions) : $transitions;
715
+	}
716
+
717
+
718
+
719
+	/**
720
+	 * get_timezone_offset
721
+	 *
722
+	 * @param \DateTimeZone $DateTimeZone
723
+	 * @param int           $time
724
+	 * @return mixed
725
+	 * @throws \DomainException
726
+	 */
727
+	public function get_timezone_offset(DateTimeZone $DateTimeZone, $time = null)
728
+	{
729
+		$transitions = $this->get_timezone_transitions($DateTimeZone, $time);
730
+		if ( ! isset($transitions['offset'])) {
731
+			throw new DomainException();
732
+		}
733
+		return $transitions['offset'];
734
+	}
735
+
736
+
737
+	/**
738
+	 * This will take an incoming timezone string and return the abbreviation for that timezone
739
+	 *
740
+	 * @param  string $timezone_string
741
+	 * @return string           abbreviation
742
+	 * @throws \EE_Error
743
+	 */
744
+	public function get_timezone_abbrev($timezone_string)
745
+	{
746
+		$timezone_string = EEH_DTT_Helper::get_valid_timezone_string($timezone_string);
747
+		$dateTime        = new DateTime(\EE_Datetime_Field::now, new DateTimeZone($timezone_string));
748
+
749
+		return $dateTime->format('T');
750
+	}
751
+
752
+	/**
753
+	 * Overrides the parent to allow for having a dynamic "now" value
754
+	 *
755
+	 * @return mixed
756
+	 */
757
+	public function get_default_value()
758
+	{
759
+		if ($this->_default_value === EE_Datetime_Field::now) {
760
+			return time();
761
+		} else {
762
+			return parent::get_default_value();
763
+		}
764
+	}
765
+
766
+
767
+	public function getSchemaDescription()
768
+	{
769
+		return sprintf(
770
+			esc_html__('%s - the value for this field is in the timezone of the site.', 'event_espresso'),
771
+			$this->get_nicename()
772
+		);
773
+	}
774 774
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 1 patch
Indentation   +2689 added lines, -2689 removed lines patch added patch discarded remove patch
@@ -15,2696 +15,2696 @@
 block discarded – undo
15 15
 class Events_Admin_Page extends EE_Admin_Page_CPT
16 16
 {
17 17
 
18
-    /**
19
-     * This will hold the event object for event_details screen.
20
-     *
21
-     * @access protected
22
-     * @var EE_Event $_event
23
-     */
24
-    protected $_event;
25
-
26
-
27
-    /**
28
-     * This will hold the category object for category_details screen.
29
-     *
30
-     * @var stdClass $_category
31
-     */
32
-    protected $_category;
33
-
34
-
35
-    /**
36
-     * This will hold the event model instance
37
-     *
38
-     * @var EEM_Event $_event_model
39
-     */
40
-    protected $_event_model;
41
-
42
-
43
-
44
-    /**
45
-     * @var EE_Event
46
-     */
47
-    protected $_cpt_model_obj = false;
48
-
49
-
50
-    /**
51
-     * Initialize page props for this admin page group.
52
-     */
53
-    protected function _init_page_props()
54
-    {
55
-        $this->page_slug = EVENTS_PG_SLUG;
56
-        $this->page_label = EVENTS_LABEL;
57
-        $this->_admin_base_url = EVENTS_ADMIN_URL;
58
-        $this->_admin_base_path = EVENTS_ADMIN;
59
-        $this->_cpt_model_names = array(
60
-            'create_new' => 'EEM_Event',
61
-            'edit'       => 'EEM_Event',
62
-        );
63
-        $this->_cpt_edit_routes = array(
64
-            'espresso_events' => 'edit',
65
-        );
66
-        add_action(
67
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
68
-            array($this, 'verify_event_edit'), 10, 2
69
-        );
70
-    }
71
-
72
-
73
-    /**
74
-     * Sets the ajax hooks used for this admin page group.
75
-     */
76
-    protected function _ajax_hooks()
77
-    {
78
-        add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
79
-    }
80
-
81
-
82
-    /**
83
-     * Sets the page properties for this admin page group.
84
-     */
85
-    protected function _define_page_props()
86
-    {
87
-        $this->_admin_page_title = EVENTS_LABEL;
88
-        $this->_labels = array(
89
-            'buttons'      => array(
90
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
91
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
92
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
93
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
94
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
95
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
96
-            ),
97
-            'editor_title' => array(
98
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
99
-            ),
100
-            'publishbox'   => array(
101
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
102
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
103
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
104
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
105
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
106
-            ),
107
-        );
108
-    }
109
-
110
-
111
-    /**
112
-     * Sets the page routes property for this admin page group.
113
-     */
114
-    protected function _set_page_routes()
115
-    {
116
-        //load formatter helper
117
-        //load field generator helper
118
-        //is there a evt_id in the request?
119
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
120
-            ? $this->_req_data['EVT_ID']
121
-            : 0;
122
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
123
-        $this->_page_routes = array(
124
-            'default'                       => array(
125
-                'func'       => '_events_overview_list_table',
126
-                'capability' => 'ee_read_events',
127
-            ),
128
-            'create_new'                    => array(
129
-                'func'       => '_create_new_cpt_item',
130
-                'capability' => 'ee_edit_events',
131
-            ),
132
-            'edit'                          => array(
133
-                'func'       => '_edit_cpt_item',
134
-                'capability' => 'ee_edit_event',
135
-                'obj_id'     => $evt_id,
136
-            ),
137
-            'copy_event'                    => array(
138
-                'func'       => '_copy_events',
139
-                'capability' => 'ee_edit_event',
140
-                'obj_id'     => $evt_id,
141
-                'noheader'   => true,
142
-            ),
143
-            'trash_event'                   => array(
144
-                'func'       => '_trash_or_restore_event',
145
-                'args'       => array('event_status' => 'trash'),
146
-                'capability' => 'ee_delete_event',
147
-                'obj_id'     => $evt_id,
148
-                'noheader'   => true,
149
-            ),
150
-            'trash_events'                  => array(
151
-                'func'       => '_trash_or_restore_events',
152
-                'args'       => array('event_status' => 'trash'),
153
-                'capability' => 'ee_delete_events',
154
-                'noheader'   => true,
155
-            ),
156
-            'restore_event'                 => array(
157
-                'func'       => '_trash_or_restore_event',
158
-                'args'       => array('event_status' => 'draft'),
159
-                'capability' => 'ee_delete_event',
160
-                'obj_id'     => $evt_id,
161
-                'noheader'   => true,
162
-            ),
163
-            'restore_events'                => array(
164
-                'func'       => '_trash_or_restore_events',
165
-                'args'       => array('event_status' => 'draft'),
166
-                'capability' => 'ee_delete_events',
167
-                'noheader'   => true,
168
-            ),
169
-            'delete_event'                  => array(
170
-                'func'       => '_delete_event',
171
-                'capability' => 'ee_delete_event',
172
-                'obj_id'     => $evt_id,
173
-                'noheader'   => true,
174
-            ),
175
-            'delete_events'                 => array(
176
-                'func'       => '_delete_events',
177
-                'capability' => 'ee_delete_events',
178
-                'noheader'   => true,
179
-            ),
180
-            'view_report'                   => array(
181
-                'func'      => '_view_report',
182
-                'capablity' => 'ee_edit_events',
183
-            ),
184
-            'default_event_settings'        => array(
185
-                'func'       => '_default_event_settings',
186
-                'capability' => 'manage_options',
187
-            ),
188
-            'update_default_event_settings' => array(
189
-                'func'       => '_update_default_event_settings',
190
-                'capability' => 'manage_options',
191
-                'noheader'   => true,
192
-            ),
193
-            'template_settings'             => array(
194
-                'func'       => '_template_settings',
195
-                'capability' => 'manage_options',
196
-            ),
197
-            //event category tab related
198
-            'add_category'                  => array(
199
-                'func'       => '_category_details',
200
-                'capability' => 'ee_edit_event_category',
201
-                'args'       => array('add'),
202
-            ),
203
-            'edit_category'                 => array(
204
-                'func'       => '_category_details',
205
-                'capability' => 'ee_edit_event_category',
206
-                'args'       => array('edit'),
207
-            ),
208
-            'delete_categories'             => array(
209
-                'func'       => '_delete_categories',
210
-                'capability' => 'ee_delete_event_category',
211
-                'noheader'   => true,
212
-            ),
213
-            'delete_category'               => array(
214
-                'func'       => '_delete_categories',
215
-                'capability' => 'ee_delete_event_category',
216
-                'noheader'   => true,
217
-            ),
218
-            'insert_category'               => array(
219
-                'func'       => '_insert_or_update_category',
220
-                'args'       => array('new_category' => true),
221
-                'capability' => 'ee_edit_event_category',
222
-                'noheader'   => true,
223
-            ),
224
-            'update_category'               => array(
225
-                'func'       => '_insert_or_update_category',
226
-                'args'       => array('new_category' => false),
227
-                'capability' => 'ee_edit_event_category',
228
-                'noheader'   => true,
229
-            ),
230
-            'category_list'                 => array(
231
-                'func'       => '_category_list_table',
232
-                'capability' => 'ee_manage_event_categories',
233
-            ),
234
-        );
235
-    }
236
-
237
-
238
-    /**
239
-     * Set the _page_config property for this admin page group.
240
-     */
241
-    protected function _set_page_config()
242
-    {
243
-        $this->_page_config = array(
244
-            'default'                => array(
245
-                'nav'           => array(
246
-                    'label' => esc_html__('Overview', 'event_espresso'),
247
-                    'order' => 10,
248
-                ),
249
-                'list_table'    => 'Events_Admin_List_Table',
250
-                'help_tabs'     => array(
251
-                    'events_overview_help_tab'                       => array(
252
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
253
-                        'filename' => 'events_overview',
254
-                    ),
255
-                    'events_overview_table_column_headings_help_tab' => array(
256
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
257
-                        'filename' => 'events_overview_table_column_headings',
258
-                    ),
259
-                    'events_overview_filters_help_tab'               => array(
260
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
261
-                        'filename' => 'events_overview_filters',
262
-                    ),
263
-                    'events_overview_view_help_tab'                  => array(
264
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
265
-                        'filename' => 'events_overview_views',
266
-                    ),
267
-                    'events_overview_other_help_tab'                 => array(
268
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
269
-                        'filename' => 'events_overview_other',
270
-                    ),
271
-                ),
272
-                'help_tour'     => array(
273
-                    'Event_Overview_Help_Tour',
274
-                    //'New_Features_Test_Help_Tour' for testing multiple help tour
275
-                ),
276
-                'qtips'         => array(
277
-                    'EE_Event_List_Table_Tips',
278
-                ),
279
-                'require_nonce' => false,
280
-            ),
281
-            'create_new'             => array(
282
-                'nav'           => array(
283
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
284
-                    'order'      => 5,
285
-                    'persistent' => false,
286
-                ),
287
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
288
-                'help_tabs'     => array(
289
-                    'event_editor_help_tab'                            => array(
290
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
291
-                        'filename' => 'event_editor',
292
-                    ),
293
-                    'event_editor_title_richtexteditor_help_tab'       => array(
294
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
295
-                        'filename' => 'event_editor_title_richtexteditor',
296
-                    ),
297
-                    'event_editor_venue_details_help_tab'              => array(
298
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
299
-                        'filename' => 'event_editor_venue_details',
300
-                    ),
301
-                    'event_editor_event_datetimes_help_tab'            => array(
302
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
303
-                        'filename' => 'event_editor_event_datetimes',
304
-                    ),
305
-                    'event_editor_event_tickets_help_tab'              => array(
306
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
307
-                        'filename' => 'event_editor_event_tickets',
308
-                    ),
309
-                    'event_editor_event_registration_options_help_tab' => array(
310
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
311
-                        'filename' => 'event_editor_event_registration_options',
312
-                    ),
313
-                    'event_editor_tags_categories_help_tab'            => array(
314
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
315
-                        'filename' => 'event_editor_tags_categories',
316
-                    ),
317
-                    'event_editor_questions_registrants_help_tab'      => array(
318
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
319
-                        'filename' => 'event_editor_questions_registrants',
320
-                    ),
321
-                    'event_editor_save_new_event_help_tab'             => array(
322
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
323
-                        'filename' => 'event_editor_save_new_event',
324
-                    ),
325
-                    'event_editor_other_help_tab'                      => array(
326
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
327
-                        'filename' => 'event_editor_other',
328
-                    ),
329
-                ),
330
-                'help_tour'     => array(
331
-                    'Event_Editor_Help_Tour',
332
-                ),
333
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
334
-                'require_nonce' => false,
335
-            ),
336
-            'edit'                   => array(
337
-                'nav'           => array(
338
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
339
-                    'order'      => 5,
340
-                    'persistent' => false,
341
-                    'url'        => isset($this->_req_data['post'])
342
-                        ? EE_Admin_Page::add_query_args_and_nonce(
343
-                            array('post' => $this->_req_data['post'], 'action' => 'edit'),
344
-                            $this->_current_page_view_url
345
-                        )
346
-                        : $this->_admin_base_url,
347
-                ),
348
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
349
-                'help_tabs'     => array(
350
-                    'event_editor_help_tab'                            => array(
351
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
352
-                        'filename' => 'event_editor',
353
-                    ),
354
-                    'event_editor_title_richtexteditor_help_tab'       => array(
355
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
356
-                        'filename' => 'event_editor_title_richtexteditor',
357
-                    ),
358
-                    'event_editor_venue_details_help_tab'              => array(
359
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
360
-                        'filename' => 'event_editor_venue_details',
361
-                    ),
362
-                    'event_editor_event_datetimes_help_tab'            => array(
363
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
364
-                        'filename' => 'event_editor_event_datetimes',
365
-                    ),
366
-                    'event_editor_event_tickets_help_tab'              => array(
367
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
368
-                        'filename' => 'event_editor_event_tickets',
369
-                    ),
370
-                    'event_editor_event_registration_options_help_tab' => array(
371
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
372
-                        'filename' => 'event_editor_event_registration_options',
373
-                    ),
374
-                    'event_editor_tags_categories_help_tab'            => array(
375
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
376
-                        'filename' => 'event_editor_tags_categories',
377
-                    ),
378
-                    'event_editor_questions_registrants_help_tab'      => array(
379
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
380
-                        'filename' => 'event_editor_questions_registrants',
381
-                    ),
382
-                    'event_editor_save_new_event_help_tab'             => array(
383
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
384
-                        'filename' => 'event_editor_save_new_event',
385
-                    ),
386
-                    'event_editor_other_help_tab'                      => array(
387
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
388
-                        'filename' => 'event_editor_other',
389
-                    ),
390
-                ),
391
-                /*'help_tour' => array(
18
+	/**
19
+	 * This will hold the event object for event_details screen.
20
+	 *
21
+	 * @access protected
22
+	 * @var EE_Event $_event
23
+	 */
24
+	protected $_event;
25
+
26
+
27
+	/**
28
+	 * This will hold the category object for category_details screen.
29
+	 *
30
+	 * @var stdClass $_category
31
+	 */
32
+	protected $_category;
33
+
34
+
35
+	/**
36
+	 * This will hold the event model instance
37
+	 *
38
+	 * @var EEM_Event $_event_model
39
+	 */
40
+	protected $_event_model;
41
+
42
+
43
+
44
+	/**
45
+	 * @var EE_Event
46
+	 */
47
+	protected $_cpt_model_obj = false;
48
+
49
+
50
+	/**
51
+	 * Initialize page props for this admin page group.
52
+	 */
53
+	protected function _init_page_props()
54
+	{
55
+		$this->page_slug = EVENTS_PG_SLUG;
56
+		$this->page_label = EVENTS_LABEL;
57
+		$this->_admin_base_url = EVENTS_ADMIN_URL;
58
+		$this->_admin_base_path = EVENTS_ADMIN;
59
+		$this->_cpt_model_names = array(
60
+			'create_new' => 'EEM_Event',
61
+			'edit'       => 'EEM_Event',
62
+		);
63
+		$this->_cpt_edit_routes = array(
64
+			'espresso_events' => 'edit',
65
+		);
66
+		add_action(
67
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
68
+			array($this, 'verify_event_edit'), 10, 2
69
+		);
70
+	}
71
+
72
+
73
+	/**
74
+	 * Sets the ajax hooks used for this admin page group.
75
+	 */
76
+	protected function _ajax_hooks()
77
+	{
78
+		add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
79
+	}
80
+
81
+
82
+	/**
83
+	 * Sets the page properties for this admin page group.
84
+	 */
85
+	protected function _define_page_props()
86
+	{
87
+		$this->_admin_page_title = EVENTS_LABEL;
88
+		$this->_labels = array(
89
+			'buttons'      => array(
90
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
91
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
92
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
93
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
94
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
95
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
96
+			),
97
+			'editor_title' => array(
98
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
99
+			),
100
+			'publishbox'   => array(
101
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
102
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
103
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
104
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
105
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
106
+			),
107
+		);
108
+	}
109
+
110
+
111
+	/**
112
+	 * Sets the page routes property for this admin page group.
113
+	 */
114
+	protected function _set_page_routes()
115
+	{
116
+		//load formatter helper
117
+		//load field generator helper
118
+		//is there a evt_id in the request?
119
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
120
+			? $this->_req_data['EVT_ID']
121
+			: 0;
122
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
123
+		$this->_page_routes = array(
124
+			'default'                       => array(
125
+				'func'       => '_events_overview_list_table',
126
+				'capability' => 'ee_read_events',
127
+			),
128
+			'create_new'                    => array(
129
+				'func'       => '_create_new_cpt_item',
130
+				'capability' => 'ee_edit_events',
131
+			),
132
+			'edit'                          => array(
133
+				'func'       => '_edit_cpt_item',
134
+				'capability' => 'ee_edit_event',
135
+				'obj_id'     => $evt_id,
136
+			),
137
+			'copy_event'                    => array(
138
+				'func'       => '_copy_events',
139
+				'capability' => 'ee_edit_event',
140
+				'obj_id'     => $evt_id,
141
+				'noheader'   => true,
142
+			),
143
+			'trash_event'                   => array(
144
+				'func'       => '_trash_or_restore_event',
145
+				'args'       => array('event_status' => 'trash'),
146
+				'capability' => 'ee_delete_event',
147
+				'obj_id'     => $evt_id,
148
+				'noheader'   => true,
149
+			),
150
+			'trash_events'                  => array(
151
+				'func'       => '_trash_or_restore_events',
152
+				'args'       => array('event_status' => 'trash'),
153
+				'capability' => 'ee_delete_events',
154
+				'noheader'   => true,
155
+			),
156
+			'restore_event'                 => array(
157
+				'func'       => '_trash_or_restore_event',
158
+				'args'       => array('event_status' => 'draft'),
159
+				'capability' => 'ee_delete_event',
160
+				'obj_id'     => $evt_id,
161
+				'noheader'   => true,
162
+			),
163
+			'restore_events'                => array(
164
+				'func'       => '_trash_or_restore_events',
165
+				'args'       => array('event_status' => 'draft'),
166
+				'capability' => 'ee_delete_events',
167
+				'noheader'   => true,
168
+			),
169
+			'delete_event'                  => array(
170
+				'func'       => '_delete_event',
171
+				'capability' => 'ee_delete_event',
172
+				'obj_id'     => $evt_id,
173
+				'noheader'   => true,
174
+			),
175
+			'delete_events'                 => array(
176
+				'func'       => '_delete_events',
177
+				'capability' => 'ee_delete_events',
178
+				'noheader'   => true,
179
+			),
180
+			'view_report'                   => array(
181
+				'func'      => '_view_report',
182
+				'capablity' => 'ee_edit_events',
183
+			),
184
+			'default_event_settings'        => array(
185
+				'func'       => '_default_event_settings',
186
+				'capability' => 'manage_options',
187
+			),
188
+			'update_default_event_settings' => array(
189
+				'func'       => '_update_default_event_settings',
190
+				'capability' => 'manage_options',
191
+				'noheader'   => true,
192
+			),
193
+			'template_settings'             => array(
194
+				'func'       => '_template_settings',
195
+				'capability' => 'manage_options',
196
+			),
197
+			//event category tab related
198
+			'add_category'                  => array(
199
+				'func'       => '_category_details',
200
+				'capability' => 'ee_edit_event_category',
201
+				'args'       => array('add'),
202
+			),
203
+			'edit_category'                 => array(
204
+				'func'       => '_category_details',
205
+				'capability' => 'ee_edit_event_category',
206
+				'args'       => array('edit'),
207
+			),
208
+			'delete_categories'             => array(
209
+				'func'       => '_delete_categories',
210
+				'capability' => 'ee_delete_event_category',
211
+				'noheader'   => true,
212
+			),
213
+			'delete_category'               => array(
214
+				'func'       => '_delete_categories',
215
+				'capability' => 'ee_delete_event_category',
216
+				'noheader'   => true,
217
+			),
218
+			'insert_category'               => array(
219
+				'func'       => '_insert_or_update_category',
220
+				'args'       => array('new_category' => true),
221
+				'capability' => 'ee_edit_event_category',
222
+				'noheader'   => true,
223
+			),
224
+			'update_category'               => array(
225
+				'func'       => '_insert_or_update_category',
226
+				'args'       => array('new_category' => false),
227
+				'capability' => 'ee_edit_event_category',
228
+				'noheader'   => true,
229
+			),
230
+			'category_list'                 => array(
231
+				'func'       => '_category_list_table',
232
+				'capability' => 'ee_manage_event_categories',
233
+			),
234
+		);
235
+	}
236
+
237
+
238
+	/**
239
+	 * Set the _page_config property for this admin page group.
240
+	 */
241
+	protected function _set_page_config()
242
+	{
243
+		$this->_page_config = array(
244
+			'default'                => array(
245
+				'nav'           => array(
246
+					'label' => esc_html__('Overview', 'event_espresso'),
247
+					'order' => 10,
248
+				),
249
+				'list_table'    => 'Events_Admin_List_Table',
250
+				'help_tabs'     => array(
251
+					'events_overview_help_tab'                       => array(
252
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
253
+						'filename' => 'events_overview',
254
+					),
255
+					'events_overview_table_column_headings_help_tab' => array(
256
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
257
+						'filename' => 'events_overview_table_column_headings',
258
+					),
259
+					'events_overview_filters_help_tab'               => array(
260
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
261
+						'filename' => 'events_overview_filters',
262
+					),
263
+					'events_overview_view_help_tab'                  => array(
264
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
265
+						'filename' => 'events_overview_views',
266
+					),
267
+					'events_overview_other_help_tab'                 => array(
268
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
269
+						'filename' => 'events_overview_other',
270
+					),
271
+				),
272
+				'help_tour'     => array(
273
+					'Event_Overview_Help_Tour',
274
+					//'New_Features_Test_Help_Tour' for testing multiple help tour
275
+				),
276
+				'qtips'         => array(
277
+					'EE_Event_List_Table_Tips',
278
+				),
279
+				'require_nonce' => false,
280
+			),
281
+			'create_new'             => array(
282
+				'nav'           => array(
283
+					'label'      => esc_html__('Add Event', 'event_espresso'),
284
+					'order'      => 5,
285
+					'persistent' => false,
286
+				),
287
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
288
+				'help_tabs'     => array(
289
+					'event_editor_help_tab'                            => array(
290
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
291
+						'filename' => 'event_editor',
292
+					),
293
+					'event_editor_title_richtexteditor_help_tab'       => array(
294
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
295
+						'filename' => 'event_editor_title_richtexteditor',
296
+					),
297
+					'event_editor_venue_details_help_tab'              => array(
298
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
299
+						'filename' => 'event_editor_venue_details',
300
+					),
301
+					'event_editor_event_datetimes_help_tab'            => array(
302
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
303
+						'filename' => 'event_editor_event_datetimes',
304
+					),
305
+					'event_editor_event_tickets_help_tab'              => array(
306
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
307
+						'filename' => 'event_editor_event_tickets',
308
+					),
309
+					'event_editor_event_registration_options_help_tab' => array(
310
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
311
+						'filename' => 'event_editor_event_registration_options',
312
+					),
313
+					'event_editor_tags_categories_help_tab'            => array(
314
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
315
+						'filename' => 'event_editor_tags_categories',
316
+					),
317
+					'event_editor_questions_registrants_help_tab'      => array(
318
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
319
+						'filename' => 'event_editor_questions_registrants',
320
+					),
321
+					'event_editor_save_new_event_help_tab'             => array(
322
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
323
+						'filename' => 'event_editor_save_new_event',
324
+					),
325
+					'event_editor_other_help_tab'                      => array(
326
+						'title'    => esc_html__('Event Other', 'event_espresso'),
327
+						'filename' => 'event_editor_other',
328
+					),
329
+				),
330
+				'help_tour'     => array(
331
+					'Event_Editor_Help_Tour',
332
+				),
333
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
334
+				'require_nonce' => false,
335
+			),
336
+			'edit'                   => array(
337
+				'nav'           => array(
338
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
339
+					'order'      => 5,
340
+					'persistent' => false,
341
+					'url'        => isset($this->_req_data['post'])
342
+						? EE_Admin_Page::add_query_args_and_nonce(
343
+							array('post' => $this->_req_data['post'], 'action' => 'edit'),
344
+							$this->_current_page_view_url
345
+						)
346
+						: $this->_admin_base_url,
347
+				),
348
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
349
+				'help_tabs'     => array(
350
+					'event_editor_help_tab'                            => array(
351
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
352
+						'filename' => 'event_editor',
353
+					),
354
+					'event_editor_title_richtexteditor_help_tab'       => array(
355
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
356
+						'filename' => 'event_editor_title_richtexteditor',
357
+					),
358
+					'event_editor_venue_details_help_tab'              => array(
359
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
360
+						'filename' => 'event_editor_venue_details',
361
+					),
362
+					'event_editor_event_datetimes_help_tab'            => array(
363
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
364
+						'filename' => 'event_editor_event_datetimes',
365
+					),
366
+					'event_editor_event_tickets_help_tab'              => array(
367
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
368
+						'filename' => 'event_editor_event_tickets',
369
+					),
370
+					'event_editor_event_registration_options_help_tab' => array(
371
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
372
+						'filename' => 'event_editor_event_registration_options',
373
+					),
374
+					'event_editor_tags_categories_help_tab'            => array(
375
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
376
+						'filename' => 'event_editor_tags_categories',
377
+					),
378
+					'event_editor_questions_registrants_help_tab'      => array(
379
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
380
+						'filename' => 'event_editor_questions_registrants',
381
+					),
382
+					'event_editor_save_new_event_help_tab'             => array(
383
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
384
+						'filename' => 'event_editor_save_new_event',
385
+					),
386
+					'event_editor_other_help_tab'                      => array(
387
+						'title'    => esc_html__('Event Other', 'event_espresso'),
388
+						'filename' => 'event_editor_other',
389
+					),
390
+				),
391
+				/*'help_tour' => array(
392 392
 					'Event_Edit_Help_Tour'
393 393
 				),*/
394
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
395
-                'require_nonce' => false,
396
-            ),
397
-            'default_event_settings' => array(
398
-                'nav'           => array(
399
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
400
-                    'order' => 40,
401
-                ),
402
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
403
-                'labels'        => array(
404
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
405
-                ),
406
-                'help_tabs'     => array(
407
-                    'default_settings_help_tab'        => array(
408
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
409
-                        'filename' => 'events_default_settings',
410
-                    ),
411
-                    'default_settings_status_help_tab' => array(
412
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
413
-                        'filename' => 'events_default_settings_status',
414
-                    ),
415
-                    'default_maximum_tickets_help_tab' => array(
416
-                        'title' => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
417
-                        'filename' => 'events_default_settings_max_tickets',
418
-                    )
419
-                ),
420
-                'help_tour'     => array('Event_Default_Settings_Help_Tour'),
421
-                'require_nonce' => false,
422
-            ),
423
-            //template settings
424
-            'template_settings'      => array(
425
-                'nav'           => array(
426
-                    'label' => esc_html__('Templates', 'event_espresso'),
427
-                    'order' => 30,
428
-                ),
429
-                'metaboxes'     => $this->_default_espresso_metaboxes,
430
-                'help_tabs'     => array(
431
-                    'general_settings_templates_help_tab' => array(
432
-                        'title'    => esc_html__('Templates', 'event_espresso'),
433
-                        'filename' => 'general_settings_templates',
434
-                    ),
435
-                ),
436
-                'help_tour'     => array('Templates_Help_Tour'),
437
-                'require_nonce' => false,
438
-            ),
439
-            //event category stuff
440
-            'add_category'           => array(
441
-                'nav'           => array(
442
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
443
-                    'order'      => 15,
444
-                    'persistent' => false,
445
-                ),
446
-                'help_tabs'     => array(
447
-                    'add_category_help_tab' => array(
448
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
449
-                        'filename' => 'events_add_category',
450
-                    ),
451
-                ),
452
-                'help_tour'     => array('Event_Add_Category_Help_Tour'),
453
-                'metaboxes'     => array('_publish_post_box'),
454
-                'require_nonce' => false,
455
-            ),
456
-            'edit_category'          => array(
457
-                'nav'           => array(
458
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
459
-                    'order'      => 15,
460
-                    'persistent' => false,
461
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
462
-                        ? add_query_arg(
463
-                            array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
464
-                            $this->_current_page_view_url
465
-                        )
466
-                        : $this->_admin_base_url,
467
-                ),
468
-                'help_tabs'     => array(
469
-                    'edit_category_help_tab' => array(
470
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
471
-                        'filename' => 'events_edit_category',
472
-                    ),
473
-                ),
474
-                /*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
475
-                'metaboxes'     => array('_publish_post_box'),
476
-                'require_nonce' => false,
477
-            ),
478
-            'category_list'          => array(
479
-                'nav'           => array(
480
-                    'label' => esc_html__('Categories', 'event_espresso'),
481
-                    'order' => 20,
482
-                ),
483
-                'list_table'    => 'Event_Categories_Admin_List_Table',
484
-                'help_tabs'     => array(
485
-                    'events_categories_help_tab'                       => array(
486
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
487
-                        'filename' => 'events_categories',
488
-                    ),
489
-                    'events_categories_table_column_headings_help_tab' => array(
490
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
491
-                        'filename' => 'events_categories_table_column_headings',
492
-                    ),
493
-                    'events_categories_view_help_tab'                  => array(
494
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
495
-                        'filename' => 'events_categories_views',
496
-                    ),
497
-                    'events_categories_other_help_tab'                 => array(
498
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
499
-                        'filename' => 'events_categories_other',
500
-                    ),
501
-                ),
502
-                'help_tour'     => array(
503
-                    'Event_Categories_Help_Tour',
504
-                ),
505
-                'metaboxes'     => $this->_default_espresso_metaboxes,
506
-                'require_nonce' => false,
507
-            ),
508
-        );
509
-    }
510
-
511
-
512
-    /**
513
-     * Used to register any global screen options if necessary for every route in this admin page group.
514
-     */
515
-    protected function _add_screen_options()
516
-    {
517
-    }
518
-
519
-
520
-    /**
521
-     * Implementing the screen options for the 'default' route.
522
-     */
523
-    protected function _add_screen_options_default()
524
-    {
525
-        $this->_per_page_screen_option();
526
-    }
527
-
528
-
529
-    /**
530
-     * Implementing screen options for the category list route.
531
-     */
532
-    protected function _add_screen_options_category_list()
533
-    {
534
-        $page_title = $this->_admin_page_title;
535
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
536
-        $this->_per_page_screen_option();
537
-        $this->_admin_page_title = $page_title;
538
-    }
539
-
540
-
541
-    /**
542
-     * Used to register any global feature pointers for the admin page group.
543
-     */
544
-    protected function _add_feature_pointers()
545
-    {
546
-    }
547
-
548
-
549
-    /**
550
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
551
-     */
552
-    public function load_scripts_styles()
553
-    {
554
-        wp_register_style(
555
-            'events-admin-css',
556
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
557
-            array(),
558
-            EVENT_ESPRESSO_VERSION
559
-        );
560
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
561
-        wp_enqueue_style('events-admin-css');
562
-        wp_enqueue_style('ee-cat-admin');
563
-        //todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
564
-        //registers for all views
565
-        //scripts
566
-        wp_register_script(
567
-            'event_editor_js',
568
-            EVENTS_ASSETS_URL . 'event_editor.js',
569
-            array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
570
-            EVENT_ESPRESSO_VERSION,
571
-            true
572
-        );
573
-    }
574
-
575
-
576
-
577
-    /**
578
-     * Enqueuing scripts and styles specific to this view
579
-     */
580
-    public function load_scripts_styles_create_new()
581
-    {
582
-        $this->load_scripts_styles_edit();
583
-    }
584
-
585
-
586
-
587
-    /**
588
-     * Enqueuing scripts and styles specific to this view
589
-     */
590
-    public function load_scripts_styles_edit()
591
-    {
592
-        //styles
593
-        wp_enqueue_style('espresso-ui-theme');
594
-        wp_register_style(
595
-            'event-editor-css',
596
-            EVENTS_ASSETS_URL . 'event-editor.css',
597
-            array('ee-admin-css'),
598
-            EVENT_ESPRESSO_VERSION
599
-        );
600
-        wp_enqueue_style('event-editor-css');
601
-        //scripts
602
-        wp_register_script(
603
-            'event-datetime-metabox',
604
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
605
-            array('event_editor_js', 'ee-datepicker'),
606
-            EVENT_ESPRESSO_VERSION
607
-        );
608
-        wp_enqueue_script('event-datetime-metabox');
609
-    }
610
-
611
-
612
-    /**
613
-     * Populating the _views property for the category list table view.
614
-     */
615
-    protected function _set_list_table_views_category_list()
616
-    {
617
-        $this->_views = array(
618
-            'all' => array(
619
-                'slug'        => 'all',
620
-                'label'       => esc_html__('All', 'event_espresso'),
621
-                'count'       => 0,
622
-                'bulk_action' => array(
623
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
624
-                ),
625
-            ),
626
-        );
627
-    }
628
-
629
-
630
-    /**
631
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
632
-     */
633
-    public function admin_init()
634
-    {
635
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
636
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
637
-            'event_espresso'
638
-        );
639
-    }
640
-
641
-
642
-    /**
643
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page group.
644
-     */
645
-    public function admin_notices()
646
-    {
647
-    }
648
-
649
-
650
-    /**
651
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
652
-     * this admin page group.
653
-     */
654
-    public function admin_footer_scripts()
655
-    {
656
-    }
657
-
658
-
659
-
660
-    /**
661
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
662
-     * warning (via EE_Error::add_error());
663
-     *
664
-     * @param  EE_Event $event Event object
665
-     * @param string    $req_type
666
-     * @return void
667
-     * @throws EE_Error
668
-     * @access public
669
-     */
670
-    public function verify_event_edit($event = null, $req_type = '')
671
-    {
672
-        // don't need to do this when processing
673
-        if(!empty($req_type)) {
674
-            return;
675
-        }
676
-        // no event?
677
-        if (empty($event)) {
678
-            // set event
679
-            $event = $this->_cpt_model_obj;
680
-        }
681
-        // STILL no event?
682
-        if (! $event instanceof EE_Event) {
683
-            return;
684
-        }
685
-        $orig_status = $event->status();
686
-        // first check if event is active.
687
-        if (
688
-            $orig_status === EEM_Event::cancelled
689
-            || $orig_status === EEM_Event::postponed
690
-            || $event->is_expired()
691
-            || $event->is_inactive()
692
-        ) {
693
-            return;
694
-        }
695
-        //made it here so it IS active... next check that any of the tickets are sold.
696
-        if ($event->is_sold_out(true)) {
697
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
698
-                EE_Error::add_attention(
699
-                    sprintf(
700
-                        esc_html__(
701
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
702
-                            'event_espresso'
703
-                        ),
704
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
705
-                    )
706
-                );
707
-            }
708
-            return;
709
-        } else if ($orig_status === EEM_Event::sold_out) {
710
-            EE_Error::add_attention(
711
-                sprintf(
712
-                    esc_html__(
713
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
714
-                        'event_espresso'
715
-                    ),
716
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
717
-                )
718
-            );
719
-        }
720
-        //now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
721
-        if ( ! $event->tickets_on_sale()) {
722
-            return;
723
-        }
724
-        //made it here so show warning
725
-        $this->_edit_event_warning();
726
-    }
727
-
728
-
729
-
730
-    /**
731
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
732
-     * When needed, hook this into a EE_Error::add_error() notice.
733
-     *
734
-     * @access protected
735
-     * @return void
736
-     */
737
-    protected function _edit_event_warning()
738
-    {
739
-        // we don't want to add warnings during these requests
740
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
741
-            return;
742
-        }
743
-        EE_Error::add_attention(
744
-            esc_html__(
745
-                'Please be advised that this event has been published and is open for registrations on your website. If you update any registration-related details (i.e. custom questions, messages, tickets, datetimes, etc.) while a registration is in process, the registration process could be interrupted and result in errors for the person registering and potentially incorrect registration or transaction data inside Event Espresso. We recommend editing events during a period of slow traffic, or even temporarily changing the status of an event to "Draft" until your edits are complete.',
746
-                'event_espresso'
747
-            )
748
-        );
749
-    }
750
-
751
-
752
-
753
-    /**
754
-     * When a user is creating a new event, notify them if they haven't set their timezone.
755
-     * Otherwise, do the normal logic
756
-     *
757
-     * @return string
758
-     * @throws \EE_Error
759
-     */
760
-    protected function _create_new_cpt_item()
761
-    {
762
-        $has_timezone_string = get_option('timezone_string');
763
-        //only nag them about setting their timezone if it's their first event, and they haven't already done it
764
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
765
-            EE_Error::add_attention(
766
-                sprintf(
767
-                    __(
768
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
769
-                        'event_espresso'
770
-                    ),
771
-                    '<br>',
772
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
773
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
774
-                    . '</select>',
775
-                    '<button class="button button-secondary timezone-submit">',
776
-                    '</button><span class="spinner"></span>'
777
-                ),
778
-                __FILE__,
779
-                __FUNCTION__,
780
-                __LINE__
781
-            );
782
-        }
783
-        return parent::_create_new_cpt_item();
784
-    }
785
-
786
-
787
-    /**
788
-     * Sets the _views property for the default route in this admin page group.
789
-     */
790
-    protected function _set_list_table_views_default()
791
-    {
792
-        $this->_views = array(
793
-            'all'   => array(
794
-                'slug'        => 'all',
795
-                'label'       => esc_html__('View All Events', 'event_espresso'),
796
-                'count'       => 0,
797
-                'bulk_action' => array(
798
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
799
-                ),
800
-            ),
801
-            'draft' => array(
802
-                'slug'        => 'draft',
803
-                'label'       => esc_html__('Draft', 'event_espresso'),
804
-                'count'       => 0,
805
-                'bulk_action' => array(
806
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
807
-                ),
808
-            ),
809
-        );
810
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
811
-            $this->_views['trash'] = array(
812
-                'slug'        => 'trash',
813
-                'label'       => esc_html__('Trash', 'event_espresso'),
814
-                'count'       => 0,
815
-                'bulk_action' => array(
816
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
817
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
818
-                ),
819
-            );
820
-        }
821
-    }
822
-
823
-
824
-
825
-    /**
826
-     * Provides the legend item array for the default list table view.
827
-     * @return array
828
-     */
829
-    protected function _event_legend_items()
830
-    {
831
-        $items = array(
832
-            'view_details'   => array(
833
-                'class' => 'dashicons dashicons-search',
834
-                'desc'  => esc_html__('View Event', 'event_espresso'),
835
-            ),
836
-            'edit_event'     => array(
837
-                'class' => 'ee-icon ee-icon-calendar-edit',
838
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
839
-            ),
840
-            'view_attendees' => array(
841
-                'class' => 'dashicons dashicons-groups',
842
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
843
-            ),
844
-        );
845
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
846
-        $statuses = array(
847
-            'sold_out_status'  => array(
848
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
849
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
850
-            ),
851
-            'active_status'    => array(
852
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
853
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
854
-            ),
855
-            'upcoming_status'  => array(
856
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
857
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
858
-            ),
859
-            'postponed_status' => array(
860
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
861
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
862
-            ),
863
-            'cancelled_status' => array(
864
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
865
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
866
-            ),
867
-            'expired_status'   => array(
868
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
869
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
870
-            ),
871
-            'inactive_status'  => array(
872
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
873
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
874
-            ),
875
-        );
876
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
877
-        return array_merge($items, $statuses);
878
-    }
879
-
880
-
881
-
882
-    /**
883
-     * @return EEM_Event
884
-     */
885
-    private function _event_model()
886
-    {
887
-        if ( ! $this->_event_model instanceof EEM_Event) {
888
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
889
-        }
890
-        return $this->_event_model;
891
-    }
892
-
893
-
894
-
895
-    /**
896
-     * Adds extra buttons to the WP CPT permalink field row.
897
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
898
-     *
899
-     * @param  string $return    the current html
900
-     * @param  int    $id        the post id for the page
901
-     * @param  string $new_title What the title is
902
-     * @param  string $new_slug  what the slug is
903
-     * @return string            The new html string for the permalink area
904
-     */
905
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
906
-    {
907
-        //make sure this is only when editing
908
-        if ( ! empty($id)) {
909
-            $post = get_post($id);
910
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
911
-                       . esc_html__('Shortcode', 'event_espresso')
912
-                       . '</a> ';
913
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
914
-                       . $post->ID
915
-                       . ']">';
916
-        }
917
-        return $return;
918
-    }
919
-
920
-
921
-
922
-    /**
923
-     * _events_overview_list_table
924
-     * This contains the logic for showing the events_overview list
925
-     *
926
-     * @access protected
927
-     * @return void
928
-     * @throws \EE_Error
929
-     */
930
-    protected function _events_overview_list_table()
931
-    {
932
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
933
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
934
-            ? (array)$this->_template_args['after_list_table']
935
-            : array();
936
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
937
-                                                                              . EEH_Template::get_button_or_link(
938
-                get_post_type_archive_link('espresso_events'),
939
-                esc_html__("View Event Archive Page", "event_espresso"),
940
-                'button'
941
-            );
942
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
943
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
944
-                'create_new',
945
-                'add',
946
-                array(),
947
-                'add-new-h2'
948
-            );
949
-        $this->display_admin_list_table_page_with_no_sidebar();
950
-    }
951
-
952
-
953
-
954
-    /**
955
-     * this allows for extra misc actions in the default WP publish box
956
-     *
957
-     * @return void
958
-     */
959
-    public function extra_misc_actions_publish_box()
960
-    {
961
-        $this->_generate_publish_box_extra_content();
962
-    }
963
-
964
-
965
-
966
-    /**
967
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been saved.
968
-     * Typically you would use this to save any additional data.
969
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
970
-     * ALSO very important.  When a post transitions from scheduled to published,
971
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from other meta saves.
972
-     * So MAKE sure that you handle this accordingly.
973
-     *
974
-     * @access protected
975
-     * @abstract
976
-     * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
977
-     * @param  object $post    The post object of the cpt that was saved.
978
-     * @return void
979
-     * @throws \EE_Error
980
-     */
981
-    protected function _insert_update_cpt_item($post_id, $post)
982
-    {
983
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
984
-            //get out we're not processing an event save.
985
-            return;
986
-        }
987
-        $event_values = array(
988
-            'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
989
-            'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
990
-            'EVT_additional_limit'            => min(
991
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
992
-                ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
993
-            ),
994
-            'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
995
-                ? $this->_req_data['EVT_default_registration_status']
996
-                : EE_Registry::instance()->CFG->registration->default_STS_ID,
997
-            'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
998
-            'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
999
-            'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1000
-                ? $this->_req_data['timezone_string'] : null,
1001
-            'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1002
-                ? $this->_req_data['externalURL'] : null,
1003
-            'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1004
-                ? $this->_req_data['event_phone'] : null,
1005
-        );
1006
-        //update event
1007
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1008
-        //get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1009
-        $get_one_where = array(
1010
-            $this->_event_model()->primary_key_name() => $post_id,
1011
-            'OR' => array(
1012
-                'status' => $post->post_status,
1013
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1014
-                // but the returned object here has a status of "publish", so use the original post status as well
1015
-                'status*1' => $this->_req_data['original_post_status'],
1016
-            )
1017
-        );
1018
-        $event = $this->_event_model()->get_one(array($get_one_where));
1019
-        //the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1020
-        $event_update_callbacks = apply_filters(
1021
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1022
-            array(
1023
-                array($this, '_default_venue_update'),
1024
-                array($this, '_default_tickets_update')
1025
-            )
1026
-        );
1027
-        $att_success = true;
1028
-        foreach ($event_update_callbacks as $e_callback) {
1029
-            $_success = is_callable($e_callback)
1030
-                ? call_user_func($e_callback, $event, $this->_req_data)
1031
-                : false;
1032
-            //if ANY of these updates fail then we want the appropriate global error message
1033
-            $att_success = ! $att_success ? $att_success : $_success;
1034
-        }
1035
-        //any errors?
1036
-        if ($success && false === $att_success) {
1037
-            EE_Error::add_error(
1038
-                esc_html__(
1039
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1040
-                    'event_espresso'
1041
-                ),
1042
-                __FILE__,
1043
-                __FUNCTION__,
1044
-                __LINE__
1045
-            );
1046
-        } else if ($success === false) {
1047
-            EE_Error::add_error(
1048
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1049
-                __FILE__,
1050
-                __FUNCTION__,
1051
-                __LINE__
1052
-            );
1053
-        }
1054
-    }
1055
-
1056
-
1057
-
1058
-    /**
1059
-     * @see parent::restore_item()
1060
-     * @param int $post_id
1061
-     * @param int $revision_id
1062
-     */
1063
-    protected function _restore_cpt_item($post_id, $revision_id)
1064
-    {
1065
-        //copy existing event meta to new post
1066
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1067
-        if ($post_evt instanceof EE_Event) {
1068
-            //meta revision restore
1069
-            $post_evt->restore_revision($revision_id);
1070
-            //related objs restore
1071
-            $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1072
-        }
1073
-    }
1074
-
1075
-
1076
-
1077
-    /**
1078
-     * Attach the venue to the Event
1079
-     *
1080
-     * @param  \EE_Event $evtobj Event Object to add the venue to
1081
-     * @param  array     $data   The request data from the form
1082
-     * @return bool           Success or fail.
1083
-     */
1084
-    protected function _default_venue_update(\EE_Event $evtobj, $data)
1085
-    {
1086
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1087
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1088
-        $rows_affected = null;
1089
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1090
-        // very important.  If we don't have a venue name...
1091
-        // then we'll get out because not necessary to create empty venue
1092
-        if (empty($data['venue_title'])) {
1093
-            return false;
1094
-        }
1095
-        $venue_array = array(
1096
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1097
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1098
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1099
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1100
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1101
-                : null,
1102
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1103
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1104
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1105
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1106
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1107
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1108
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1109
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1110
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1111
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1112
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1113
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1114
-            'status'              => 'publish',
1115
-        );
1116
-        //if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1117
-        if ( ! empty($venue_id)) {
1118
-            $update_where = array($venue_model->primary_key_name() => $venue_id);
1119
-            $rows_affected = $venue_model->update($venue_array, array($update_where));
1120
-            //we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1121
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1122
-            return $rows_affected > 0 ? true : false;
1123
-        } else {
1124
-            //we insert the venue
1125
-            $venue_id = $venue_model->insert($venue_array);
1126
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1127
-            return ! empty($venue_id) ? true : false;
1128
-        }
1129
-        //when we have the ancestor come in it's already been handled by the revision save.
1130
-    }
1131
-
1132
-
1133
-
1134
-    /**
1135
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1136
-     *
1137
-     * @param  EE_Event $evtobj The Event object we're attaching data to
1138
-     * @param  array    $data   The request data from the form
1139
-     * @return array
1140
-     */
1141
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1142
-    {
1143
-        $success = true;
1144
-        $saved_dtt = null;
1145
-        $saved_tickets = array();
1146
-        $incoming_date_formats = array('Y-m-d', 'h:i a');
1147
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1148
-            //trim all values to ensure any excess whitespace is removed.
1149
-            $dtt = array_map('trim', $dtt);
1150
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1151
-                : $dtt['DTT_EVT_start'];
1152
-            $datetime_values = array(
1153
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1154
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1155
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1156
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1157
-                'DTT_order'     => $row,
1158
-            );
1159
-            //if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1160
-            if ( ! empty($dtt['DTT_ID'])) {
1161
-                $DTM = EE_Registry::instance()
1162
-                                  ->load_model('Datetime', array($evtobj->get_timezone()))
1163
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1164
-                $DTM->set_date_format($incoming_date_formats[0]);
1165
-                $DTM->set_time_format($incoming_date_formats[1]);
1166
-                foreach ($datetime_values as $field => $value) {
1167
-                    $DTM->set($field, $value);
1168
-                }
1169
-                //make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1170
-                $saved_dtts[$DTM->ID()] = $DTM;
1171
-            } else {
1172
-                $DTM = EE_Registry::instance()->load_class(
1173
-                    'Datetime',
1174
-                    array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1175
-                    false,
1176
-                    false
1177
-                );
1178
-                foreach ($datetime_values as $field => $value) {
1179
-                    $DTM->set($field, $value);
1180
-                }
1181
-            }
1182
-            $DTM->save();
1183
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1184
-            //load DTT helper
1185
-            //before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1186
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1187
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1188
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1189
-                $DTT->save();
1190
-            }
1191
-            //now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1192
-            $saved_dtt = $DTT;
1193
-            $success = ! $success ? $success : $DTT;
1194
-            //if ANY of these updates fail then we want the appropriate global error message.
1195
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1196
-        }
1197
-        //no dtts get deleted so we don't do any of that logic here.
1198
-        //update tickets next
1199
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1200
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1201
-            $incoming_date_formats = array('Y-m-d', 'h:i a');
1202
-            $update_prices = false;
1203
-            $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1204
-                ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1205
-            // trim inputs to ensure any excess whitespace is removed.
1206
-            $tkt = array_map('trim', $tkt);
1207
-            if (empty($tkt['TKT_start_date'])) {
1208
-                //let's use now in the set timezone.
1209
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1210
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1211
-            }
1212
-            if (empty($tkt['TKT_end_date'])) {
1213
-                //use the start date of the first datetime
1214
-                $dtt = $evtobj->first_datetime();
1215
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1216
-                    $incoming_date_formats[0],
1217
-                    $incoming_date_formats[1]
1218
-                );
1219
-            }
1220
-            $TKT_values = array(
1221
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1222
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1223
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1224
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1225
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1226
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1227
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1228
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1229
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1230
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1231
-                'TKT_row'         => $row,
1232
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1233
-                'TKT_price'       => $ticket_price,
1234
-            );
1235
-            //if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1236
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1237
-                $TKT_values['TKT_ID'] = 0;
1238
-                $TKT_values['TKT_is_default'] = 0;
1239
-                $TKT_values['TKT_price'] = $ticket_price;
1240
-                $update_prices = true;
1241
-            }
1242
-            //if we have a TKT_ID then we need to get that existing TKT_obj and update it
1243
-            //we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1244
-            //keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1245
-            if ( ! empty($tkt['TKT_ID'])) {
1246
-                $TKT = EE_Registry::instance()
1247
-                                  ->load_model('Ticket', array($evtobj->get_timezone()))
1248
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1249
-                if ($TKT instanceof EE_Ticket) {
1250
-                    $ticket_sold = $TKT->count_related(
1251
-                        'Registration',
1252
-                        array(
1253
-                            array(
1254
-                                'STS_ID' => array(
1255
-                                    'NOT IN',
1256
-                                    array(EEM_Registration::status_id_incomplete),
1257
-                                ),
1258
-                            ),
1259
-                        )
1260
-                    ) > 0 ? true : false;
1261
-                    //let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1262
-                    $create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1263
-                                      && ! $TKT->get(
1264
-                        'TKT_deleted'
1265
-                    ) ? true : false;
1266
-                    $TKT->set_date_format($incoming_date_formats[0]);
1267
-                    $TKT->set_time_format($incoming_date_formats[1]);
1268
-                    //set new values
1269
-                    foreach ($TKT_values as $field => $value) {
1270
-                        if ($field == 'TKT_qty') {
1271
-                            $TKT->set_qty($value);
1272
-                        } else {
1273
-                            $TKT->set($field, $value);
1274
-                        }
1275
-                    }
1276
-                    //if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1277
-                    if ($create_new_TKT) {
1278
-                        //archive the old ticket first
1279
-                        $TKT->set('TKT_deleted', 1);
1280
-                        $TKT->save();
1281
-                        //make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1282
-                        $saved_tickets[$TKT->ID()] = $TKT;
1283
-                        //create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1284
-                        $TKT = clone $TKT;
1285
-                        $TKT->set('TKT_ID', 0);
1286
-                        $TKT->set('TKT_deleted', 0);
1287
-                        $TKT->set('TKT_price', $ticket_price);
1288
-                        $TKT->set('TKT_sold', 0);
1289
-                        //now we need to make sure that $new prices are created as well and attached to new ticket.
1290
-                        $update_prices = true;
1291
-                    }
1292
-                    //make sure price is set if it hasn't been already
1293
-                    $TKT->set('TKT_price', $ticket_price);
1294
-                }
1295
-            } else {
1296
-                //no TKT_id so a new TKT
1297
-                $TKT_values['TKT_price'] = $ticket_price;
1298
-                $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1299
-                if ($TKT instanceof EE_Ticket) {
1300
-                    //need to reset values to properly account for the date formats
1301
-                    $TKT->set_date_format($incoming_date_formats[0]);
1302
-                    $TKT->set_time_format($incoming_date_formats[1]);
1303
-                    $TKT->set_timezone($evtobj->get_timezone());
1304
-                    //set new values
1305
-                    foreach ($TKT_values as $field => $value) {
1306
-                        if ($field == 'TKT_qty') {
1307
-                            $TKT->set_qty($value);
1308
-                        } else {
1309
-                            $TKT->set($field, $value);
1310
-                        }
1311
-                    }
1312
-                    $update_prices = true;
1313
-                }
1314
-            }
1315
-            // cap ticket qty by datetime reg limits
1316
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1317
-            //update ticket.
1318
-            $TKT->save();
1319
-            //before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1320
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1321
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1322
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1323
-                $TKT->save();
1324
-            }
1325
-            //initially let's add the ticket to the dtt
1326
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1327
-            $saved_tickets[$TKT->ID()] = $TKT;
1328
-            //add prices to ticket
1329
-            $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1330
-        }
1331
-        //however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1332
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1333
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1334
-        foreach ($tickets_removed as $id) {
1335
-            $id = absint($id);
1336
-            //get the ticket for this id
1337
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1338
-            //need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1339
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1340
-            foreach ($dtts as $dtt) {
1341
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1342
-            }
1343
-            //need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1344
-            $tkt_to_remove->delete_related_permanently('Price');
1345
-            //finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1346
-            $tkt_to_remove->delete_permanently();
1347
-        }
1348
-        return array($saved_dtt, $saved_tickets);
1349
-    }
1350
-
1351
-
1352
-
1353
-    /**
1354
-     * This attaches a list of given prices to a ticket.
1355
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1356
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1357
-     * price info and prices are automatically "archived" via the ticket.
1358
-     *
1359
-     * @access  private
1360
-     * @param array     $prices     Array of prices from the form.
1361
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1362
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1363
-     * @return  void
1364
-     */
1365
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1366
-    {
1367
-        foreach ($prices as $row => $prc) {
1368
-            $PRC_values = array(
1369
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1370
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1371
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1372
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1373
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1374
-                'PRC_is_default' => 0, //make sure prices are NOT set as default from this context
1375
-                'PRC_order'      => $row,
1376
-            );
1377
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1378
-                $PRC_values['PRC_ID'] = 0;
1379
-                $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1380
-            } else {
1381
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1382
-                //update this price with new values
1383
-                foreach ($PRC_values as $field => $newprc) {
1384
-                    $PRC->set($field, $newprc);
1385
-                }
1386
-                $PRC->save();
1387
-            }
1388
-            $ticket->_add_relation_to($PRC, 'Price');
1389
-        }
1390
-    }
1391
-
1392
-
1393
-
1394
-    /**
1395
-     * Add in our autosave ajax handlers
1396
-     *
1397
-     */
1398
-    protected function _ee_autosave_create_new()
1399
-    {
1400
-    }
1401
-
1402
-
1403
-    /**
1404
-     * More autosave handlers.
1405
-     */
1406
-    protected function _ee_autosave_edit()
1407
-    {
1408
-        return; //TEMPORARILY EXITING CAUSE THIS IS A TODO
1409
-    }
1410
-
1411
-
1412
-
1413
-    /**
1414
-     *    _generate_publish_box_extra_content
1415
-     */
1416
-    private function _generate_publish_box_extra_content()
1417
-    {
1418
-        //load formatter helper
1419
-        //args for getting related registrations
1420
-        $approved_query_args = array(
1421
-            array(
1422
-                'REG_deleted' => 0,
1423
-                'STS_ID'      => EEM_Registration::status_id_approved,
1424
-            ),
1425
-        );
1426
-        $not_approved_query_args = array(
1427
-            array(
1428
-                'REG_deleted' => 0,
1429
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1430
-            ),
1431
-        );
1432
-        $pending_payment_query_args = array(
1433
-            array(
1434
-                'REG_deleted' => 0,
1435
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1436
-            ),
1437
-        );
1438
-        // publish box
1439
-        $publish_box_extra_args = array(
1440
-            'view_approved_reg_url'        => add_query_arg(
1441
-                array(
1442
-                    'action'      => 'default',
1443
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1444
-                    '_reg_status' => EEM_Registration::status_id_approved,
1445
-                ),
1446
-                REG_ADMIN_URL
1447
-            ),
1448
-            'view_not_approved_reg_url'    => add_query_arg(
1449
-                array(
1450
-                    'action'      => 'default',
1451
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1452
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1453
-                ),
1454
-                REG_ADMIN_URL
1455
-            ),
1456
-            'view_pending_payment_reg_url' => add_query_arg(
1457
-                array(
1458
-                    'action'      => 'default',
1459
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1460
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1461
-                ),
1462
-                REG_ADMIN_URL
1463
-            ),
1464
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1465
-                'Registration',
1466
-                $approved_query_args
1467
-            ),
1468
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1469
-                'Registration',
1470
-                $not_approved_query_args
1471
-            ),
1472
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1473
-                'Registration',
1474
-                $pending_payment_query_args
1475
-            ),
1476
-            'misc_pub_section_class'       => apply_filters(
1477
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1478
-                'misc-pub-section'
1479
-            ),
1480
-        );
1481
-        ob_start();
1482
-        do_action(
1483
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1484
-            $this->_cpt_model_obj
1485
-        );
1486
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1487
-        // load template
1488
-        EEH_Template::display_template(
1489
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1490
-            $publish_box_extra_args
1491
-        );
1492
-    }
1493
-
1494
-
1495
-
1496
-    /**
1497
-     * @return EE_Event
1498
-     */
1499
-    public function get_event_object()
1500
-    {
1501
-        return $this->_cpt_model_obj;
1502
-    }
1503
-
1504
-
1505
-
1506
-
1507
-    /** METABOXES * */
1508
-    /**
1509
-     * _register_event_editor_meta_boxes
1510
-     * add all metaboxes related to the event_editor
1511
-     *
1512
-     * @return void
1513
-     */
1514
-    protected function _register_event_editor_meta_boxes()
1515
-    {
1516
-        $this->verify_cpt_object();
1517
-        add_meta_box(
1518
-            'espresso_event_editor_tickets',
1519
-            esc_html__('Event Datetime & Ticket', 'event_espresso'),
1520
-            array($this, 'ticket_metabox'),
1521
-            $this->page_slug,
1522
-            'normal',
1523
-            'high'
1524
-        );
1525
-        add_meta_box(
1526
-            'espresso_event_editor_event_options',
1527
-            esc_html__('Event Registration Options', 'event_espresso'),
1528
-            array($this, 'registration_options_meta_box'),
1529
-            $this->page_slug,
1530
-            'side',
1531
-            'default'
1532
-        );
1533
-        // NOTE: if you're looking for other metaboxes in here,
1534
-        // where a metabox has a related management page in the admin
1535
-        // you will find it setup in the related management page's "_Hooks" file.
1536
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1537
-    }
1538
-
1539
-
1540
-    /**
1541
-     * @throws DomainException
1542
-     * @throws EE_Error
1543
-     */
1544
-    public function ticket_metabox()
1545
-    {
1546
-        $existing_datetime_ids = $existing_ticket_ids = array();
1547
-        //defaults for template args
1548
-        $template_args = array(
1549
-            'existing_datetime_ids'    => '',
1550
-            'event_datetime_help_link' => '',
1551
-            'ticket_options_help_link' => '',
1552
-            'time'                     => null,
1553
-            'ticket_rows'              => '',
1554
-            'existing_ticket_ids'      => '',
1555
-            'total_ticket_rows'        => 1,
1556
-            'ticket_js_structure'      => '',
1557
-            'trash_icon'               => 'ee-lock-icon',
1558
-            'disabled'                 => '',
1559
-        );
1560
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1561
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1562
-        /**
1563
-         * 1. Start with retrieving Datetimes
1564
-         * 2. Fore each datetime get related tickets
1565
-         * 3. For each ticket get related prices
1566
-         */
1567
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1568
-        /** @type EE_Datetime $first_datetime */
1569
-        $first_datetime = reset($times);
1570
-        //do we get related tickets?
1571
-        if ($first_datetime instanceof EE_Datetime
1572
-            && $first_datetime->ID() !== 0
1573
-        ) {
1574
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1575
-            $template_args['time'] = $first_datetime;
1576
-            $related_tickets = $first_datetime->tickets(
1577
-                array(
1578
-                    array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1579
-                    'default_where_conditions' => 'none',
1580
-                )
1581
-            );
1582
-            if ( ! empty($related_tickets)) {
1583
-                $template_args['total_ticket_rows'] = count($related_tickets);
1584
-                $row = 0;
1585
-                foreach ($related_tickets as $ticket) {
1586
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1587
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1588
-                    $row++;
1589
-                }
1590
-            } else {
1591
-                $template_args['total_ticket_rows'] = 1;
1592
-                /** @type EE_Ticket $ticket */
1593
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1594
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1595
-            }
1596
-        } else {
1597
-            $template_args['time'] = $times[0];
1598
-            /** @type EE_Ticket $ticket */
1599
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1600
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1601
-            // NOTE: we're just sending the first default row
1602
-            // (decaf can't manage default tickets so this should be sufficient);
1603
-        }
1604
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1605
-            'event_editor_event_datetimes_help_tab'
1606
-        );
1607
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1608
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1609
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1610
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1611
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1612
-            true
1613
-        );
1614
-        $template = apply_filters(
1615
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1616
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1617
-        );
1618
-        EEH_Template::display_template($template, $template_args);
1619
-    }
1620
-
1621
-
1622
-
1623
-    /**
1624
-     * Setup an individual ticket form for the decaf event editor page
1625
-     *
1626
-     * @access private
1627
-     * @param  EE_Ticket $ticket   the ticket object
1628
-     * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1629
-     * @param int        $row
1630
-     * @return string generated html for the ticket row.
1631
-     */
1632
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1633
-    {
1634
-        $template_args = array(
1635
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1636
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1637
-                : '',
1638
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1639
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1640
-            'TKT_name'            => $ticket->get('TKT_name'),
1641
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1642
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1643
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1644
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1645
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1646
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1647
-            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1648
-                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1649
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1650
-            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1651
-                : ' disabled=disabled',
1652
-        );
1653
-        $price = $ticket->ID() !== 0
1654
-            ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1655
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1656
-        $price_args = array(
1657
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1658
-            'PRC_amount'            => $price->get('PRC_amount'),
1659
-            'PRT_ID'                => $price->get('PRT_ID'),
1660
-            'PRC_ID'                => $price->get('PRC_ID'),
1661
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1662
-        );
1663
-        //make sure we have default start and end dates if skeleton
1664
-        //handle rows that should NOT be empty
1665
-        if (empty($template_args['TKT_start_date'])) {
1666
-            //if empty then the start date will be now.
1667
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1668
-        }
1669
-        if (empty($template_args['TKT_end_date'])) {
1670
-            //get the earliest datetime (if present);
1671
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1672
-                ? $this->_cpt_model_obj->get_first_related(
1673
-                    'Datetime',
1674
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1675
-                )
1676
-                : null;
1677
-            if ( ! empty($earliest_dtt)) {
1678
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1679
-            } else {
1680
-                $template_args['TKT_end_date'] = date(
1681
-                    'Y-m-d h:i a',
1682
-                    mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1683
-                );
1684
-            }
1685
-        }
1686
-        $template_args = array_merge($template_args, $price_args);
1687
-        $template = apply_filters(
1688
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1689
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1690
-            $ticket
1691
-        );
1692
-        return EEH_Template::display_template($template, $template_args, true);
1693
-    }
1694
-
1695
-
1696
-    /**
1697
-     * @throws DomainException
1698
-     */
1699
-    public function registration_options_meta_box()
1700
-    {
1701
-        $yes_no_values = array(
1702
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1703
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1704
-        );
1705
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1706
-            array(
1707
-                EEM_Registration::status_id_cancelled,
1708
-                EEM_Registration::status_id_declined,
1709
-                EEM_Registration::status_id_incomplete,
1710
-            ),
1711
-            true
1712
-        );
1713
-        //$template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1714
-        $template_args['_event'] = $this->_cpt_model_obj;
1715
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1716
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1717
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1718
-            'default_reg_status',
1719
-            $default_reg_status_values,
1720
-            $this->_cpt_model_obj->default_registration_status()
1721
-        );
1722
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1723
-            'display_desc',
1724
-            $yes_no_values,
1725
-            $this->_cpt_model_obj->display_description()
1726
-        );
1727
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1728
-            'display_ticket_selector',
1729
-            $yes_no_values,
1730
-            $this->_cpt_model_obj->display_ticket_selector(),
1731
-            '',
1732
-            '',
1733
-            false
1734
-        );
1735
-        $template_args['additional_registration_options'] = apply_filters(
1736
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1737
-            '',
1738
-            $template_args,
1739
-            $yes_no_values,
1740
-            $default_reg_status_values
1741
-        );
1742
-        EEH_Template::display_template(
1743
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1744
-            $template_args
1745
-        );
1746
-    }
1747
-
1748
-
1749
-
1750
-    /**
1751
-     * _get_events()
1752
-     * This method simply returns all the events (for the given _view and paging)
1753
-     *
1754
-     * @access public
1755
-     * @param int  $per_page     count of items per page (20 default);
1756
-     * @param int  $current_page what is the current page being viewed.
1757
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1758
-     *                           If FALSE then we return an array of event objects
1759
-     *                           that match the given _view and paging parameters.
1760
-     * @return array an array of event objects.
1761
-     */
1762
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1763
-    {
1764
-        $EEME = $this->_event_model();
1765
-        $offset = ($current_page - 1) * $per_page;
1766
-        $limit = $count ? null : $offset . ',' . $per_page;
1767
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1768
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1769
-        if (isset($this->_req_data['month_range'])) {
1770
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1771
-            //simulate the FIRST day of the month, that fixes issues for months like February
1772
-            //where PHP doesn't know what to assume for date.
1773
-            //@see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1774
-            $month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1775
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1776
-        }
1777
-        $where = array();
1778
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1779
-        //determine what post_status our condition will have for the query.
1780
-        switch ($status) {
1781
-            case 'month' :
1782
-            case 'today' :
1783
-            case null :
1784
-            case 'all' :
1785
-                break;
1786
-            case 'draft' :
1787
-                $where['status'] = array('IN', array('draft', 'auto-draft'));
1788
-                break;
1789
-            default :
1790
-                $where['status'] = $status;
1791
-        }
1792
-        //categories?
1793
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1794
-            ? $this->_req_data['EVT_CAT'] : null;
1795
-        if ( ! empty ($category)) {
1796
-            $where['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1797
-            $where['Term_Taxonomy.term_id'] = $category;
1798
-        }
1799
-        //date where conditions
1800
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1801
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1802
-            $DateTime = new DateTime(
1803
-                $year_r . '-' . $month_r . '-01 00:00:00',
1804
-                new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1805
-            );
1806
-            $start = $DateTime->format(implode(' ', $start_formats));
1807
-            $end = $DateTime->setDate($year_r, $month_r, $DateTime
1808
-                ->format('t'))->setTime(23, 59, 59)
1809
-                            ->format(implode(' ', $start_formats));
1810
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1811
-        } else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1812
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1813
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1814
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1815
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1816
-        } else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1817
-            $now = date('Y-m-01');
1818
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1819
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1820
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1821
-                            ->setTime(23, 59, 59)
1822
-                            ->format(implode(' ', $start_formats));
1823
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1824
-        }
1825
-        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1826
-            $where['EVT_wp_user'] = get_current_user_id();
1827
-        } else {
1828
-            if ( ! isset($where['status'])) {
1829
-                if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1830
-                    $where['OR'] = array(
1831
-                        'status*restrict_private' => array('!=', 'private'),
1832
-                        'AND'                     => array(
1833
-                            'status*inclusive' => array('=', 'private'),
1834
-                            'EVT_wp_user'      => get_current_user_id(),
1835
-                        ),
1836
-                    );
1837
-                }
1838
-            }
1839
-        }
1840
-        if (isset($this->_req_data['EVT_wp_user'])) {
1841
-            if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1842
-                && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1843
-            ) {
1844
-                $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1845
-            }
1846
-        }
1847
-        //search query handling
1848
-        if (isset($this->_req_data['s'])) {
1849
-            $search_string = '%' . $this->_req_data['s'] . '%';
1850
-            $where['OR'] = array(
1851
-                'EVT_name'       => array('LIKE', $search_string),
1852
-                'EVT_desc'       => array('LIKE', $search_string),
1853
-                'EVT_short_desc' => array('LIKE', $search_string),
1854
-            );
1855
-        }
1856
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1857
-        $query_params = apply_filters(
1858
-            'FHEE__Events_Admin_Page__get_events__query_params',
1859
-            array(
1860
-                $where,
1861
-                'limit'    => $limit,
1862
-                'order_by' => $orderby,
1863
-                'order'    => $order,
1864
-                'group_by' => 'EVT_ID',
1865
-            ),
1866
-            $this->_req_data
1867
-        );
1868
-        //let's first check if we have special requests coming in.
1869
-        if (isset($this->_req_data['active_status'])) {
1870
-            switch ($this->_req_data['active_status']) {
1871
-                case 'upcoming' :
1872
-                    return $EEME->get_upcoming_events($query_params, $count);
1873
-                    break;
1874
-                case 'expired' :
1875
-                    return $EEME->get_expired_events($query_params, $count);
1876
-                    break;
1877
-                case 'active' :
1878
-                    return $EEME->get_active_events($query_params, $count);
1879
-                    break;
1880
-                case 'inactive' :
1881
-                    return $EEME->get_inactive_events($query_params, $count);
1882
-                    break;
1883
-            }
1884
-        }
1885
-        $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1886
-        return $events;
1887
-    }
1888
-
1889
-
1890
-
1891
-    /**
1892
-     * handling for WordPress CPT actions (trash, restore, delete)
1893
-     *
1894
-     * @param string $post_id
1895
-     */
1896
-    public function trash_cpt_item($post_id)
1897
-    {
1898
-        $this->_req_data['EVT_ID'] = $post_id;
1899
-        $this->_trash_or_restore_event('trash', false);
1900
-    }
1901
-
1902
-
1903
-
1904
-    /**
1905
-     * @param string $post_id
1906
-     */
1907
-    public function restore_cpt_item($post_id)
1908
-    {
1909
-        $this->_req_data['EVT_ID'] = $post_id;
1910
-        $this->_trash_or_restore_event('draft', false);
1911
-    }
1912
-
1913
-
1914
-
1915
-    /**
1916
-     * @param string $post_id
1917
-     */
1918
-    public function delete_cpt_item($post_id)
1919
-    {
1920
-        $this->_req_data['EVT_ID'] = $post_id;
1921
-        $this->_delete_event(false);
1922
-    }
1923
-
1924
-
1925
-
1926
-    /**
1927
-     * _trash_or_restore_event
1928
-     *
1929
-     * @access protected
1930
-     * @param  string $event_status
1931
-     * @param bool    $redirect_after
1932
-     */
1933
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1934
-    {
1935
-        //determine the event id and set to array.
1936
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1937
-        // loop thru events
1938
-        if ($EVT_ID) {
1939
-            // clean status
1940
-            $event_status = sanitize_key($event_status);
1941
-            // grab status
1942
-            if ( ! empty($event_status)) {
1943
-                $success = $this->_change_event_status($EVT_ID, $event_status);
1944
-            } else {
1945
-                $success = false;
1946
-                $msg = esc_html__(
1947
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1948
-                    'event_espresso'
1949
-                );
1950
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1951
-            }
1952
-        } else {
1953
-            $success = false;
1954
-            $msg = esc_html__(
1955
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1956
-                'event_espresso'
1957
-            );
1958
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1959
-        }
1960
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1961
-        if ($redirect_after) {
1962
-            $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1963
-        }
1964
-    }
1965
-
1966
-
1967
-
1968
-    /**
1969
-     * _trash_or_restore_events
1970
-     *
1971
-     * @access protected
1972
-     * @param  string $event_status
1973
-     * @return void
1974
-     */
1975
-    protected function _trash_or_restore_events($event_status = 'trash')
1976
-    {
1977
-        // clean status
1978
-        $event_status = sanitize_key($event_status);
1979
-        // grab status
1980
-        if ( ! empty($event_status)) {
1981
-            $success = true;
1982
-            //determine the event id and set to array.
1983
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
1984
-            // loop thru events
1985
-            foreach ($EVT_IDs as $EVT_ID) {
1986
-                if ($EVT_ID = absint($EVT_ID)) {
1987
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
1988
-                    $success = $results !== false ? $success : false;
1989
-                } else {
1990
-                    $msg = sprintf(
1991
-                        esc_html__(
1992
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
1993
-                            'event_espresso'
1994
-                        ),
1995
-                        $EVT_ID
1996
-                    );
1997
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1998
-                    $success = false;
1999
-                }
2000
-            }
2001
-        } else {
2002
-            $success = false;
2003
-            $msg = esc_html__(
2004
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2005
-                'event_espresso'
2006
-            );
2007
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2008
-        }
2009
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2010
-        $success = $success ? 2 : false;
2011
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2012
-        $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2013
-    }
2014
-
2015
-
2016
-
2017
-    /**
2018
-     * _trash_or_restore_events
2019
-     *
2020
-     * @access  private
2021
-     * @param  int    $EVT_ID
2022
-     * @param  string $event_status
2023
-     * @return bool
2024
-     */
2025
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2026
-    {
2027
-        // grab event id
2028
-        if ( ! $EVT_ID) {
2029
-            $msg = esc_html__(
2030
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2031
-                'event_espresso'
2032
-            );
2033
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2034
-            return false;
2035
-        }
2036
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2037
-        // clean status
2038
-        $event_status = sanitize_key($event_status);
2039
-        // grab status
2040
-        if (empty($event_status)) {
2041
-            $msg = esc_html__(
2042
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2043
-                'event_espresso'
2044
-            );
2045
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2046
-            return false;
2047
-        }
2048
-        // was event trashed or restored ?
2049
-        switch ($event_status) {
2050
-            case 'draft' :
2051
-                $action = 'restored from the trash';
2052
-                $hook = 'AHEE_event_restored_from_trash';
2053
-                break;
2054
-            case 'trash' :
2055
-                $action = 'moved to the trash';
2056
-                $hook = 'AHEE_event_moved_to_trash';
2057
-                break;
2058
-            default :
2059
-                $action = 'updated';
2060
-                $hook = false;
2061
-        }
2062
-        //use class to change status
2063
-        $this->_cpt_model_obj->set_status($event_status);
2064
-        $success = $this->_cpt_model_obj->save();
2065
-        if ($success === false) {
2066
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2067
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2068
-            return false;
2069
-        }
2070
-        if ($hook) {
2071
-            do_action($hook);
2072
-        }
2073
-        return true;
2074
-    }
2075
-
2076
-
2077
-
2078
-    /**
2079
-     * _delete_event
2080
-     *
2081
-     * @access protected
2082
-     * @param bool $redirect_after
2083
-     */
2084
-    protected function _delete_event($redirect_after = true)
2085
-    {
2086
-        //determine the event id and set to array.
2087
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2088
-        $EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2089
-        // loop thru events
2090
-        if ($EVT_ID) {
2091
-            $success = $this->_permanently_delete_event($EVT_ID);
2092
-            // get list of events with no prices
2093
-            $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2094
-            // remove this event from the list of events with no prices
2095
-            if (isset($espresso_no_ticket_prices[$EVT_ID])) {
2096
-                unset($espresso_no_ticket_prices[$EVT_ID]);
2097
-            }
2098
-            update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2099
-        } else {
2100
-            $success = false;
2101
-            $msg = esc_html__(
2102
-                'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2103
-                'event_espresso'
2104
-            );
2105
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2106
-        }
2107
-        if ($redirect_after) {
2108
-            $this->_redirect_after_action(
2109
-                $success,
2110
-                'Event',
2111
-                'deleted',
2112
-                array('action' => 'default', 'status' => 'trash')
2113
-            );
2114
-        }
2115
-    }
2116
-
2117
-
2118
-
2119
-    /**
2120
-     * _delete_events
2121
-     *
2122
-     * @access protected
2123
-     * @return void
2124
-     */
2125
-    protected function _delete_events()
2126
-    {
2127
-        $success = true;
2128
-        // get list of events with no prices
2129
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2130
-        //determine the event id and set to array.
2131
-        $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
2132
-        // loop thru events
2133
-        foreach ($EVT_IDs as $EVT_ID) {
2134
-            $EVT_ID = absint($EVT_ID);
2135
-            if ($EVT_ID) {
2136
-                $results = $this->_permanently_delete_event($EVT_ID);
2137
-                $success = $results !== false ? $success : false;
2138
-                // remove this event from the list of events with no prices
2139
-                unset($espresso_no_ticket_prices[$EVT_ID]);
2140
-            } else {
2141
-                $success = false;
2142
-                $msg = esc_html__(
2143
-                    'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2144
-                    'event_espresso'
2145
-                );
2146
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2147
-            }
2148
-        }
2149
-        update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2150
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2151
-        $success = $success ? 2 : false;
2152
-        $this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2153
-    }
2154
-
2155
-
2156
-
2157
-    /**
2158
-     * _permanently_delete_event
2159
-     *
2160
-     * @access  private
2161
-     * @param  int $EVT_ID
2162
-     * @return bool
2163
-     */
2164
-    private function _permanently_delete_event($EVT_ID = 0)
2165
-    {
2166
-        // grab event id
2167
-        if ( ! $EVT_ID) {
2168
-            $msg = esc_html__(
2169
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2170
-                'event_espresso'
2171
-            );
2172
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2173
-            return false;
2174
-        }
2175
-        if (
2176
-            ! $this->_cpt_model_obj instanceof EE_Event
2177
-            || $this->_cpt_model_obj->ID() !== $EVT_ID
2178
-        ) {
2179
-            $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2180
-        }
2181
-        if ( ! $this->_cpt_model_obj instanceof EE_Event) {
2182
-            return false;
2183
-        }
2184
-        //need to delete related tickets and prices first.
2185
-        $datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2186
-        foreach ($datetimes as $datetime) {
2187
-            $this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2188
-            $tickets = $datetime->get_many_related('Ticket');
2189
-            foreach ($tickets as $ticket) {
2190
-                $ticket->_remove_relation_to($datetime, 'Datetime');
2191
-                $ticket->delete_related_permanently('Price');
2192
-                $ticket->delete_permanently();
2193
-            }
2194
-            $datetime->delete();
2195
-        }
2196
-        //what about related venues or terms?
2197
-        $venues = $this->_cpt_model_obj->get_many_related('Venue');
2198
-        foreach ($venues as $venue) {
2199
-            $this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2200
-        }
2201
-        //any attached question groups?
2202
-        $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2203
-        if ( ! empty($question_groups)) {
2204
-            foreach ($question_groups as $question_group) {
2205
-                $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2206
-            }
2207
-        }
2208
-        //Message Template Groups
2209
-        $this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2210
-        /** @type EE_Term_Taxonomy[] $term_taxonomies */
2211
-        $term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2212
-        foreach ($term_taxonomies as $term_taxonomy) {
2213
-            $this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2214
-        }
2215
-        $success = $this->_cpt_model_obj->delete_permanently();
2216
-        // did it all go as planned ?
2217
-        if ($success) {
2218
-            $msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2219
-            EE_Error::add_success($msg);
2220
-        } else {
2221
-            $msg = sprintf(
2222
-                esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2223
-                $EVT_ID
2224
-            );
2225
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2226
-            return false;
2227
-        }
2228
-        do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2229
-        return true;
2230
-    }
2231
-
2232
-
2233
-
2234
-    /**
2235
-     * get total number of events
2236
-     *
2237
-     * @access public
2238
-     * @return int
2239
-     */
2240
-    public function total_events()
2241
-    {
2242
-        $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2243
-        return $count;
2244
-    }
2245
-
2246
-
2247
-
2248
-    /**
2249
-     * get total number of draft events
2250
-     *
2251
-     * @access public
2252
-     * @return int
2253
-     */
2254
-    public function total_events_draft()
2255
-    {
2256
-        $where = array(
2257
-            'status' => array('IN', array('draft', 'auto-draft')),
2258
-        );
2259
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2260
-        return $count;
2261
-    }
2262
-
2263
-
2264
-
2265
-    /**
2266
-     * get total number of trashed events
2267
-     *
2268
-     * @access public
2269
-     * @return int
2270
-     */
2271
-    public function total_trashed_events()
2272
-    {
2273
-        $where = array(
2274
-            'status' => 'trash',
2275
-        );
2276
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2277
-        return $count;
2278
-    }
2279
-
2280
-
2281
-    /**
2282
-     *    _default_event_settings
2283
-     *    This generates the Default Settings Tab
2284
-     *
2285
-     * @return void
2286
-     * @throws EE_Error
2287
-     */
2288
-    protected function _default_event_settings()
2289
-    {
2290
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2291
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2292
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2293
-        $this->display_admin_page_with_sidebar();
2294
-    }
2295
-
2296
-
2297
-    /**
2298
-     * Return the form for event settings.
2299
-     * @return EE_Form_Section_Proper
2300
-     */
2301
-    protected function _default_event_settings_form()
2302
-    {
2303
-        $registration_config = EE_Registry::instance()->CFG->registration;
2304
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2305
-        //exclude
2306
-            array(
2307
-                EEM_Registration::status_id_cancelled,
2308
-                EEM_Registration::status_id_declined,
2309
-                EEM_Registration::status_id_incomplete,
2310
-                EEM_Registration::status_id_wait_list,
2311
-            ),
2312
-            true
2313
-        );
2314
-        return new EE_Form_Section_Proper(
2315
-            array(
2316
-                'name' => 'update_default_event_settings',
2317
-                'html_id' => 'update_default_event_settings',
2318
-                'html_class' => 'form-table',
2319
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2320
-                'subsections' => apply_filters(
2321
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2322
-                    array(
2323
-                        'default_reg_status' => new EE_Select_Input(
2324
-                            $registration_stati_for_selection,
2325
-                            array(
2326
-                                'default' => isset($registration_config->default_STS_ID)
2327
-                                             && array_key_exists(
2328
-                                                $registration_config->default_STS_ID,
2329
-                                                $registration_stati_for_selection
2330
-                                             )
2331
-                                            ? sanitize_text_field($registration_config->default_STS_ID)
2332
-                                            : EEM_Registration::status_id_pending_payment,
2333
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2334
-                                                    . EEH_Template::get_help_tab_link(
2335
-                                                        'default_settings_status_help_tab'
2336
-                                                    ),
2337
-                                'html_help_text' => esc_html__(
2338
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2339
-                                    'event_espresso'
2340
-                                )
2341
-                            )
2342
-                        ),
2343
-                        'default_max_tickets' => new EE_Integer_Input(
2344
-                            array(
2345
-                                'default' => isset($registration_config->default_maximum_number_of_tickets)
2346
-                                    ? $registration_config->default_maximum_number_of_tickets
2347
-                                    : EEM_Event::get_default_additional_limit(),
2348
-                                'html_label_text' => esc_html__(
2349
-                                    'Default Maximum Tickets Allowed Per Order:',
2350
-                                    'event_espresso'
2351
-                                ) . EEH_Template::get_help_tab_link(
2352
-                                    'default_maximum_tickets_help_tab"'
2353
-                                    ),
2354
-                                'html_help_text' => esc_html__(
2355
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2356
-                                    'event_espresso'
2357
-                                )
2358
-                            )
2359
-                        )
2360
-                    )
2361
-                )
2362
-            )
2363
-        );
2364
-    }
2365
-
2366
-
2367
-    /**
2368
-     * _update_default_event_settings
2369
-     *
2370
-     * @access protected
2371
-     * @return void
2372
-     * @throws EE_Error
2373
-     */
2374
-    protected function _update_default_event_settings()
2375
-    {
2376
-        $registration_config = EE_Registry::instance()->CFG->registration;
2377
-        $form = $this->_default_event_settings_form();
2378
-        if ($form->was_submitted()) {
2379
-            $form->receive_form_submission();
2380
-            if ($form->is_valid()) {
2381
-                $valid_data = $form->valid_data();
2382
-                if (isset($valid_data['default_reg_status'])) {
2383
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2384
-                }
2385
-                if (isset($valid_data['default_max_tickets'])) {
2386
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2387
-                }
2388
-                //update because data was valid!
2389
-                EE_Registry::instance()->CFG->update_espresso_config();
2390
-                EE_Error::overwrite_success();
2391
-                EE_Error::add_success(
2392
-                    __('Default Event Settings were updated', 'event_espresso')
2393
-                );
2394
-            }
2395
-        }
2396
-        $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2397
-    }
2398
-
2399
-
2400
-
2401
-    /*************        Templates        *************/
2402
-    protected function _template_settings()
2403
-    {
2404
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2405
-        $this->_template_args['preview_img'] = '<img src="'
2406
-                                               . EVENTS_ASSETS_URL
2407
-                                               . DS
2408
-                                               . 'images'
2409
-                                               . DS
2410
-                                               . 'caffeinated_template_features.jpg" alt="'
2411
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2412
-                                               . '" />';
2413
-        $this->_template_args['preview_text'] = '<strong>' . esc_html__(
2414
-                'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2415
-                'event_espresso'
2416
-            ) . '</strong>';
2417
-        $this->display_admin_caf_preview_page('template_settings_tab');
2418
-    }
2419
-
2420
-
2421
-    /** Event Category Stuff **/
2422
-    /**
2423
-     * set the _category property with the category object for the loaded page.
2424
-     *
2425
-     * @access private
2426
-     * @return void
2427
-     */
2428
-    private function _set_category_object()
2429
-    {
2430
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2431
-            return;
2432
-        } //already have the category object so get out.
2433
-        //set default category object
2434
-        $this->_set_empty_category_object();
2435
-        //only set if we've got an id
2436
-        if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2437
-            return;
2438
-        }
2439
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2440
-        $term = get_term($category_id, 'espresso_event_categories');
2441
-        if ( ! empty($term)) {
2442
-            $this->_category->category_name = $term->name;
2443
-            $this->_category->category_identifier = $term->slug;
2444
-            $this->_category->category_desc = $term->description;
2445
-            $this->_category->id = $term->term_id;
2446
-            $this->_category->parent = $term->parent;
2447
-        }
2448
-    }
2449
-
2450
-
2451
-    /**
2452
-     * Clears out category properties.
2453
-     */
2454
-    private function _set_empty_category_object()
2455
-    {
2456
-        $this->_category = new stdClass();
2457
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2458
-        $this->_category->id = $this->_category->parent = 0;
2459
-    }
2460
-
2461
-
2462
-    /**
2463
-     * @throws EE_Error
2464
-     */
2465
-    protected function _category_list_table()
2466
-    {
2467
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2468
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2469
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2470
-                'add_category',
2471
-                'add_category',
2472
-                array(),
2473
-                'add-new-h2'
2474
-            );
2475
-        $this->display_admin_list_table_page_with_sidebar();
2476
-    }
2477
-
2478
-
2479
-
2480
-    /**
2481
-     * Output category details view.
2482
-     */
2483
-    protected function _category_details($view)
2484
-    {
2485
-        //load formatter helper
2486
-        //load field generator helper
2487
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
2488
-        $this->_set_add_edit_form_tags($route);
2489
-        $this->_set_category_object();
2490
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2491
-        $delete_action = 'delete_category';
2492
-        //custom redirect
2493
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2494
-            array('action' => 'category_list'),
2495
-            $this->_admin_base_url
2496
-        );
2497
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2498
-        //take care of contents
2499
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2500
-        $this->display_admin_page_with_sidebar();
2501
-    }
2502
-
2503
-
2504
-
2505
-    /**
2506
-     * Output category details content.
2507
-     */
2508
-    protected function _category_details_content()
2509
-    {
2510
-        $editor_args['category_desc'] = array(
2511
-            'type'          => 'wp_editor',
2512
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2513
-            'class'         => 'my_editor_custom',
2514
-            'wpeditor_args' => array('media_buttons' => false),
2515
-        );
2516
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2517
-        $all_terms = get_terms(
2518
-            array('espresso_event_categories'),
2519
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2520
-        );
2521
-        //setup category select for term parents.
2522
-        $category_select_values[] = array(
2523
-            'text' => esc_html__('No Parent', 'event_espresso'),
2524
-            'id'   => 0,
2525
-        );
2526
-        foreach ($all_terms as $term) {
2527
-            $category_select_values[] = array(
2528
-                'text' => $term->name,
2529
-                'id'   => $term->term_id,
2530
-            );
2531
-        }
2532
-        $category_select = EEH_Form_Fields::select_input(
2533
-            'category_parent',
2534
-            $category_select_values,
2535
-            $this->_category->parent
2536
-        );
2537
-        $template_args = array(
2538
-            'category'                 => $this->_category,
2539
-            'category_select'          => $category_select,
2540
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2541
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2542
-            'disable'                  => '',
2543
-            'disabled_message'         => false,
2544
-        );
2545
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2546
-        return EEH_Template::display_template($template, $template_args, true);
2547
-    }
2548
-
2549
-
2550
-    /**
2551
-     * Handles deleting categories.
2552
-     */
2553
-    protected function _delete_categories()
2554
-    {
2555
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array)$this->_req_data['EVT_CAT_ID']
2556
-            : (array)$this->_req_data['category_id'];
2557
-        foreach ($cat_ids as $cat_id) {
2558
-            $this->_delete_category($cat_id);
2559
-        }
2560
-        //doesn't matter what page we're coming from... we're going to the same place after delete.
2561
-        $query_args = array(
2562
-            'action' => 'category_list',
2563
-        );
2564
-        $this->_redirect_after_action(0, '', '', $query_args);
2565
-    }
2566
-
2567
-
2568
-
2569
-    /**
2570
-     * Handles deleting specific category.
2571
-     * @param int $cat_id
2572
-     */
2573
-    protected function _delete_category($cat_id)
2574
-    {
2575
-        $cat_id = absint($cat_id);
2576
-        wp_delete_term($cat_id, 'espresso_event_categories');
2577
-    }
2578
-
2579
-
2580
-
2581
-    /**
2582
-     * Handles triggering the update or insertion of a new category.
2583
-     * @param bool $new_category  true means we're triggering the insert of a new category.
2584
-     */
2585
-    protected function _insert_or_update_category($new_category)
2586
-    {
2587
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2588
-        $success = 0; //we already have a success message so lets not send another.
2589
-        if ($cat_id) {
2590
-            $query_args = array(
2591
-                'action'     => 'edit_category',
2592
-                'EVT_CAT_ID' => $cat_id,
2593
-            );
2594
-        } else {
2595
-            $query_args = array('action' => 'add_category');
2596
-        }
2597
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2598
-    }
2599
-
2600
-
2601
-
2602
-    /**
2603
-     * Inserts or updates category
2604
-     * @param bool $update (true indicates we're updating a category).
2605
-     * @return bool|mixed|string
2606
-     */
2607
-    private function _insert_category($update = false)
2608
-    {
2609
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2610
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2611
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2612
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2613
-        if (empty($category_name)) {
2614
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2615
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2616
-            return false;
2617
-        }
2618
-        $term_args = array(
2619
-            'name'        => $category_name,
2620
-            'description' => $category_desc,
2621
-            'parent'      => $category_parent,
2622
-        );
2623
-        //was the category_identifier input disabled?
2624
-        if (isset($this->_req_data['category_identifier'])) {
2625
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2626
-        }
2627
-        $insert_ids = $update
2628
-            ? wp_update_term($cat_id, 'espresso_event_categories', $term_args)
2629
-            : wp_insert_term($category_name, 'espresso_event_categories', $term_args);
2630
-        if ( ! is_array($insert_ids)) {
2631
-            $msg = esc_html__(
2632
-                'An error occurred and the category has not been saved to the database.',
2633
-                'event_espresso'
2634
-            );
2635
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2636
-        } else {
2637
-            $cat_id = $insert_ids['term_id'];
2638
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2639
-            EE_Error::add_success($msg);
2640
-        }
2641
-        return $cat_id;
2642
-    }
2643
-
2644
-
2645
-
2646
-    /**
2647
-     * Gets categories or count of categories matching the arguments in the request.
2648
-     * @param int  $per_page
2649
-     * @param int  $current_page
2650
-     * @param bool $count
2651
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2652
-     */
2653
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2654
-    {
2655
-        //testing term stuff
2656
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2657
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2658
-        $limit = ($current_page - 1) * $per_page;
2659
-        $where = array('taxonomy' => 'espresso_event_categories');
2660
-        if (isset($this->_req_data['s'])) {
2661
-            $sstr = '%' . $this->_req_data['s'] . '%';
2662
-            $where['OR'] = array(
2663
-                'Term.name'   => array('LIKE', $sstr),
2664
-                'description' => array('LIKE', $sstr),
2665
-            );
2666
-        }
2667
-        $query_params = array(
2668
-            $where,
2669
-            'order_by'   => array($orderby => $order),
2670
-            'limit'      => $limit . ',' . $per_page,
2671
-            'force_join' => array('Term'),
2672
-        );
2673
-        $categories = $count
2674
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2675
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2676
-        return $categories;
2677
-    }
2678
-
2679
-    /* end category stuff */
2680
-    /**************/
2681
-
2682
-
2683
-    /**
2684
-     * Callback for the `ee_save_timezone_setting` ajax action.
2685
-     * @throws EE_Error
2686
-     */
2687
-    public function save_timezonestring_setting()
2688
-    {
2689
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2690
-            ? $this->_req_data['timezone_selected']
2691
-            : '';
2692
-        if  (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false))
2693
-        {
2694
-            EE_Error::add_error(
2695
-                esc_html('An invalid timezone string submitted.', 'event_espresso'),
2696
-                __FILE__, __FUNCTION__, __LINE__
2697
-            );
2698
-            $this->_template_args['error'] = true;
2699
-            $this->_return_json();
2700
-        }
2701
-
2702
-        update_option('timezone_string', $timezone_string);
2703
-        EE_Error::add_success(
2704
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2705
-        );
2706
-        $this->_template_args['success'] = true;
2707
-        $this->_return_json(true, array('action' => 'create_new'));
2708
-    }
394
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
395
+				'require_nonce' => false,
396
+			),
397
+			'default_event_settings' => array(
398
+				'nav'           => array(
399
+					'label' => esc_html__('Default Settings', 'event_espresso'),
400
+					'order' => 40,
401
+				),
402
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
403
+				'labels'        => array(
404
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
405
+				),
406
+				'help_tabs'     => array(
407
+					'default_settings_help_tab'        => array(
408
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
409
+						'filename' => 'events_default_settings',
410
+					),
411
+					'default_settings_status_help_tab' => array(
412
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
413
+						'filename' => 'events_default_settings_status',
414
+					),
415
+					'default_maximum_tickets_help_tab' => array(
416
+						'title' => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
417
+						'filename' => 'events_default_settings_max_tickets',
418
+					)
419
+				),
420
+				'help_tour'     => array('Event_Default_Settings_Help_Tour'),
421
+				'require_nonce' => false,
422
+			),
423
+			//template settings
424
+			'template_settings'      => array(
425
+				'nav'           => array(
426
+					'label' => esc_html__('Templates', 'event_espresso'),
427
+					'order' => 30,
428
+				),
429
+				'metaboxes'     => $this->_default_espresso_metaboxes,
430
+				'help_tabs'     => array(
431
+					'general_settings_templates_help_tab' => array(
432
+						'title'    => esc_html__('Templates', 'event_espresso'),
433
+						'filename' => 'general_settings_templates',
434
+					),
435
+				),
436
+				'help_tour'     => array('Templates_Help_Tour'),
437
+				'require_nonce' => false,
438
+			),
439
+			//event category stuff
440
+			'add_category'           => array(
441
+				'nav'           => array(
442
+					'label'      => esc_html__('Add Category', 'event_espresso'),
443
+					'order'      => 15,
444
+					'persistent' => false,
445
+				),
446
+				'help_tabs'     => array(
447
+					'add_category_help_tab' => array(
448
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
449
+						'filename' => 'events_add_category',
450
+					),
451
+				),
452
+				'help_tour'     => array('Event_Add_Category_Help_Tour'),
453
+				'metaboxes'     => array('_publish_post_box'),
454
+				'require_nonce' => false,
455
+			),
456
+			'edit_category'          => array(
457
+				'nav'           => array(
458
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
459
+					'order'      => 15,
460
+					'persistent' => false,
461
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
462
+						? add_query_arg(
463
+							array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
464
+							$this->_current_page_view_url
465
+						)
466
+						: $this->_admin_base_url,
467
+				),
468
+				'help_tabs'     => array(
469
+					'edit_category_help_tab' => array(
470
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
471
+						'filename' => 'events_edit_category',
472
+					),
473
+				),
474
+				/*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
475
+				'metaboxes'     => array('_publish_post_box'),
476
+				'require_nonce' => false,
477
+			),
478
+			'category_list'          => array(
479
+				'nav'           => array(
480
+					'label' => esc_html__('Categories', 'event_espresso'),
481
+					'order' => 20,
482
+				),
483
+				'list_table'    => 'Event_Categories_Admin_List_Table',
484
+				'help_tabs'     => array(
485
+					'events_categories_help_tab'                       => array(
486
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
487
+						'filename' => 'events_categories',
488
+					),
489
+					'events_categories_table_column_headings_help_tab' => array(
490
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
491
+						'filename' => 'events_categories_table_column_headings',
492
+					),
493
+					'events_categories_view_help_tab'                  => array(
494
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
495
+						'filename' => 'events_categories_views',
496
+					),
497
+					'events_categories_other_help_tab'                 => array(
498
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
499
+						'filename' => 'events_categories_other',
500
+					),
501
+				),
502
+				'help_tour'     => array(
503
+					'Event_Categories_Help_Tour',
504
+				),
505
+				'metaboxes'     => $this->_default_espresso_metaboxes,
506
+				'require_nonce' => false,
507
+			),
508
+		);
509
+	}
510
+
511
+
512
+	/**
513
+	 * Used to register any global screen options if necessary for every route in this admin page group.
514
+	 */
515
+	protected function _add_screen_options()
516
+	{
517
+	}
518
+
519
+
520
+	/**
521
+	 * Implementing the screen options for the 'default' route.
522
+	 */
523
+	protected function _add_screen_options_default()
524
+	{
525
+		$this->_per_page_screen_option();
526
+	}
527
+
528
+
529
+	/**
530
+	 * Implementing screen options for the category list route.
531
+	 */
532
+	protected function _add_screen_options_category_list()
533
+	{
534
+		$page_title = $this->_admin_page_title;
535
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
536
+		$this->_per_page_screen_option();
537
+		$this->_admin_page_title = $page_title;
538
+	}
539
+
540
+
541
+	/**
542
+	 * Used to register any global feature pointers for the admin page group.
543
+	 */
544
+	protected function _add_feature_pointers()
545
+	{
546
+	}
547
+
548
+
549
+	/**
550
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
551
+	 */
552
+	public function load_scripts_styles()
553
+	{
554
+		wp_register_style(
555
+			'events-admin-css',
556
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
557
+			array(),
558
+			EVENT_ESPRESSO_VERSION
559
+		);
560
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
561
+		wp_enqueue_style('events-admin-css');
562
+		wp_enqueue_style('ee-cat-admin');
563
+		//todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
564
+		//registers for all views
565
+		//scripts
566
+		wp_register_script(
567
+			'event_editor_js',
568
+			EVENTS_ASSETS_URL . 'event_editor.js',
569
+			array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
570
+			EVENT_ESPRESSO_VERSION,
571
+			true
572
+		);
573
+	}
574
+
575
+
576
+
577
+	/**
578
+	 * Enqueuing scripts and styles specific to this view
579
+	 */
580
+	public function load_scripts_styles_create_new()
581
+	{
582
+		$this->load_scripts_styles_edit();
583
+	}
584
+
585
+
586
+
587
+	/**
588
+	 * Enqueuing scripts and styles specific to this view
589
+	 */
590
+	public function load_scripts_styles_edit()
591
+	{
592
+		//styles
593
+		wp_enqueue_style('espresso-ui-theme');
594
+		wp_register_style(
595
+			'event-editor-css',
596
+			EVENTS_ASSETS_URL . 'event-editor.css',
597
+			array('ee-admin-css'),
598
+			EVENT_ESPRESSO_VERSION
599
+		);
600
+		wp_enqueue_style('event-editor-css');
601
+		//scripts
602
+		wp_register_script(
603
+			'event-datetime-metabox',
604
+			EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
605
+			array('event_editor_js', 'ee-datepicker'),
606
+			EVENT_ESPRESSO_VERSION
607
+		);
608
+		wp_enqueue_script('event-datetime-metabox');
609
+	}
610
+
611
+
612
+	/**
613
+	 * Populating the _views property for the category list table view.
614
+	 */
615
+	protected function _set_list_table_views_category_list()
616
+	{
617
+		$this->_views = array(
618
+			'all' => array(
619
+				'slug'        => 'all',
620
+				'label'       => esc_html__('All', 'event_espresso'),
621
+				'count'       => 0,
622
+				'bulk_action' => array(
623
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
624
+				),
625
+			),
626
+		);
627
+	}
628
+
629
+
630
+	/**
631
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
632
+	 */
633
+	public function admin_init()
634
+	{
635
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
636
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
637
+			'event_espresso'
638
+		);
639
+	}
640
+
641
+
642
+	/**
643
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page group.
644
+	 */
645
+	public function admin_notices()
646
+	{
647
+	}
648
+
649
+
650
+	/**
651
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
652
+	 * this admin page group.
653
+	 */
654
+	public function admin_footer_scripts()
655
+	{
656
+	}
657
+
658
+
659
+
660
+	/**
661
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
662
+	 * warning (via EE_Error::add_error());
663
+	 *
664
+	 * @param  EE_Event $event Event object
665
+	 * @param string    $req_type
666
+	 * @return void
667
+	 * @throws EE_Error
668
+	 * @access public
669
+	 */
670
+	public function verify_event_edit($event = null, $req_type = '')
671
+	{
672
+		// don't need to do this when processing
673
+		if(!empty($req_type)) {
674
+			return;
675
+		}
676
+		// no event?
677
+		if (empty($event)) {
678
+			// set event
679
+			$event = $this->_cpt_model_obj;
680
+		}
681
+		// STILL no event?
682
+		if (! $event instanceof EE_Event) {
683
+			return;
684
+		}
685
+		$orig_status = $event->status();
686
+		// first check if event is active.
687
+		if (
688
+			$orig_status === EEM_Event::cancelled
689
+			|| $orig_status === EEM_Event::postponed
690
+			|| $event->is_expired()
691
+			|| $event->is_inactive()
692
+		) {
693
+			return;
694
+		}
695
+		//made it here so it IS active... next check that any of the tickets are sold.
696
+		if ($event->is_sold_out(true)) {
697
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
698
+				EE_Error::add_attention(
699
+					sprintf(
700
+						esc_html__(
701
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
702
+							'event_espresso'
703
+						),
704
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
705
+					)
706
+				);
707
+			}
708
+			return;
709
+		} else if ($orig_status === EEM_Event::sold_out) {
710
+			EE_Error::add_attention(
711
+				sprintf(
712
+					esc_html__(
713
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
714
+						'event_espresso'
715
+					),
716
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
717
+				)
718
+			);
719
+		}
720
+		//now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
721
+		if ( ! $event->tickets_on_sale()) {
722
+			return;
723
+		}
724
+		//made it here so show warning
725
+		$this->_edit_event_warning();
726
+	}
727
+
728
+
729
+
730
+	/**
731
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
732
+	 * When needed, hook this into a EE_Error::add_error() notice.
733
+	 *
734
+	 * @access protected
735
+	 * @return void
736
+	 */
737
+	protected function _edit_event_warning()
738
+	{
739
+		// we don't want to add warnings during these requests
740
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
741
+			return;
742
+		}
743
+		EE_Error::add_attention(
744
+			esc_html__(
745
+				'Please be advised that this event has been published and is open for registrations on your website. If you update any registration-related details (i.e. custom questions, messages, tickets, datetimes, etc.) while a registration is in process, the registration process could be interrupted and result in errors for the person registering and potentially incorrect registration or transaction data inside Event Espresso. We recommend editing events during a period of slow traffic, or even temporarily changing the status of an event to "Draft" until your edits are complete.',
746
+				'event_espresso'
747
+			)
748
+		);
749
+	}
750
+
751
+
752
+
753
+	/**
754
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
755
+	 * Otherwise, do the normal logic
756
+	 *
757
+	 * @return string
758
+	 * @throws \EE_Error
759
+	 */
760
+	protected function _create_new_cpt_item()
761
+	{
762
+		$has_timezone_string = get_option('timezone_string');
763
+		//only nag them about setting their timezone if it's their first event, and they haven't already done it
764
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
765
+			EE_Error::add_attention(
766
+				sprintf(
767
+					__(
768
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
769
+						'event_espresso'
770
+					),
771
+					'<br>',
772
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
773
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
774
+					. '</select>',
775
+					'<button class="button button-secondary timezone-submit">',
776
+					'</button><span class="spinner"></span>'
777
+				),
778
+				__FILE__,
779
+				__FUNCTION__,
780
+				__LINE__
781
+			);
782
+		}
783
+		return parent::_create_new_cpt_item();
784
+	}
785
+
786
+
787
+	/**
788
+	 * Sets the _views property for the default route in this admin page group.
789
+	 */
790
+	protected function _set_list_table_views_default()
791
+	{
792
+		$this->_views = array(
793
+			'all'   => array(
794
+				'slug'        => 'all',
795
+				'label'       => esc_html__('View All Events', 'event_espresso'),
796
+				'count'       => 0,
797
+				'bulk_action' => array(
798
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
799
+				),
800
+			),
801
+			'draft' => array(
802
+				'slug'        => 'draft',
803
+				'label'       => esc_html__('Draft', 'event_espresso'),
804
+				'count'       => 0,
805
+				'bulk_action' => array(
806
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
807
+				),
808
+			),
809
+		);
810
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
811
+			$this->_views['trash'] = array(
812
+				'slug'        => 'trash',
813
+				'label'       => esc_html__('Trash', 'event_espresso'),
814
+				'count'       => 0,
815
+				'bulk_action' => array(
816
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
817
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
818
+				),
819
+			);
820
+		}
821
+	}
822
+
823
+
824
+
825
+	/**
826
+	 * Provides the legend item array for the default list table view.
827
+	 * @return array
828
+	 */
829
+	protected function _event_legend_items()
830
+	{
831
+		$items = array(
832
+			'view_details'   => array(
833
+				'class' => 'dashicons dashicons-search',
834
+				'desc'  => esc_html__('View Event', 'event_espresso'),
835
+			),
836
+			'edit_event'     => array(
837
+				'class' => 'ee-icon ee-icon-calendar-edit',
838
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
839
+			),
840
+			'view_attendees' => array(
841
+				'class' => 'dashicons dashicons-groups',
842
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
843
+			),
844
+		);
845
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
846
+		$statuses = array(
847
+			'sold_out_status'  => array(
848
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
849
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
850
+			),
851
+			'active_status'    => array(
852
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
853
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
854
+			),
855
+			'upcoming_status'  => array(
856
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
857
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
858
+			),
859
+			'postponed_status' => array(
860
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
861
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
862
+			),
863
+			'cancelled_status' => array(
864
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
865
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
866
+			),
867
+			'expired_status'   => array(
868
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
869
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
870
+			),
871
+			'inactive_status'  => array(
872
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
873
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
874
+			),
875
+		);
876
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
877
+		return array_merge($items, $statuses);
878
+	}
879
+
880
+
881
+
882
+	/**
883
+	 * @return EEM_Event
884
+	 */
885
+	private function _event_model()
886
+	{
887
+		if ( ! $this->_event_model instanceof EEM_Event) {
888
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
889
+		}
890
+		return $this->_event_model;
891
+	}
892
+
893
+
894
+
895
+	/**
896
+	 * Adds extra buttons to the WP CPT permalink field row.
897
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
898
+	 *
899
+	 * @param  string $return    the current html
900
+	 * @param  int    $id        the post id for the page
901
+	 * @param  string $new_title What the title is
902
+	 * @param  string $new_slug  what the slug is
903
+	 * @return string            The new html string for the permalink area
904
+	 */
905
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
906
+	{
907
+		//make sure this is only when editing
908
+		if ( ! empty($id)) {
909
+			$post = get_post($id);
910
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
911
+					   . esc_html__('Shortcode', 'event_espresso')
912
+					   . '</a> ';
913
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
914
+					   . $post->ID
915
+					   . ']">';
916
+		}
917
+		return $return;
918
+	}
919
+
920
+
921
+
922
+	/**
923
+	 * _events_overview_list_table
924
+	 * This contains the logic for showing the events_overview list
925
+	 *
926
+	 * @access protected
927
+	 * @return void
928
+	 * @throws \EE_Error
929
+	 */
930
+	protected function _events_overview_list_table()
931
+	{
932
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
933
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
934
+			? (array)$this->_template_args['after_list_table']
935
+			: array();
936
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
937
+																			  . EEH_Template::get_button_or_link(
938
+				get_post_type_archive_link('espresso_events'),
939
+				esc_html__("View Event Archive Page", "event_espresso"),
940
+				'button'
941
+			);
942
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
943
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
944
+				'create_new',
945
+				'add',
946
+				array(),
947
+				'add-new-h2'
948
+			);
949
+		$this->display_admin_list_table_page_with_no_sidebar();
950
+	}
951
+
952
+
953
+
954
+	/**
955
+	 * this allows for extra misc actions in the default WP publish box
956
+	 *
957
+	 * @return void
958
+	 */
959
+	public function extra_misc_actions_publish_box()
960
+	{
961
+		$this->_generate_publish_box_extra_content();
962
+	}
963
+
964
+
965
+
966
+	/**
967
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been saved.
968
+	 * Typically you would use this to save any additional data.
969
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
970
+	 * ALSO very important.  When a post transitions from scheduled to published,
971
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from other meta saves.
972
+	 * So MAKE sure that you handle this accordingly.
973
+	 *
974
+	 * @access protected
975
+	 * @abstract
976
+	 * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
977
+	 * @param  object $post    The post object of the cpt that was saved.
978
+	 * @return void
979
+	 * @throws \EE_Error
980
+	 */
981
+	protected function _insert_update_cpt_item($post_id, $post)
982
+	{
983
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
984
+			//get out we're not processing an event save.
985
+			return;
986
+		}
987
+		$event_values = array(
988
+			'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
989
+			'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
990
+			'EVT_additional_limit'            => min(
991
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
992
+				! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
993
+			),
994
+			'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
995
+				? $this->_req_data['EVT_default_registration_status']
996
+				: EE_Registry::instance()->CFG->registration->default_STS_ID,
997
+			'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
998
+			'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
999
+			'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1000
+				? $this->_req_data['timezone_string'] : null,
1001
+			'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1002
+				? $this->_req_data['externalURL'] : null,
1003
+			'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1004
+				? $this->_req_data['event_phone'] : null,
1005
+		);
1006
+		//update event
1007
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1008
+		//get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1009
+		$get_one_where = array(
1010
+			$this->_event_model()->primary_key_name() => $post_id,
1011
+			'OR' => array(
1012
+				'status' => $post->post_status,
1013
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1014
+				// but the returned object here has a status of "publish", so use the original post status as well
1015
+				'status*1' => $this->_req_data['original_post_status'],
1016
+			)
1017
+		);
1018
+		$event = $this->_event_model()->get_one(array($get_one_where));
1019
+		//the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1020
+		$event_update_callbacks = apply_filters(
1021
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1022
+			array(
1023
+				array($this, '_default_venue_update'),
1024
+				array($this, '_default_tickets_update')
1025
+			)
1026
+		);
1027
+		$att_success = true;
1028
+		foreach ($event_update_callbacks as $e_callback) {
1029
+			$_success = is_callable($e_callback)
1030
+				? call_user_func($e_callback, $event, $this->_req_data)
1031
+				: false;
1032
+			//if ANY of these updates fail then we want the appropriate global error message
1033
+			$att_success = ! $att_success ? $att_success : $_success;
1034
+		}
1035
+		//any errors?
1036
+		if ($success && false === $att_success) {
1037
+			EE_Error::add_error(
1038
+				esc_html__(
1039
+					'Event Details saved successfully but something went wrong with saving attachments.',
1040
+					'event_espresso'
1041
+				),
1042
+				__FILE__,
1043
+				__FUNCTION__,
1044
+				__LINE__
1045
+			);
1046
+		} else if ($success === false) {
1047
+			EE_Error::add_error(
1048
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1049
+				__FILE__,
1050
+				__FUNCTION__,
1051
+				__LINE__
1052
+			);
1053
+		}
1054
+	}
1055
+
1056
+
1057
+
1058
+	/**
1059
+	 * @see parent::restore_item()
1060
+	 * @param int $post_id
1061
+	 * @param int $revision_id
1062
+	 */
1063
+	protected function _restore_cpt_item($post_id, $revision_id)
1064
+	{
1065
+		//copy existing event meta to new post
1066
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1067
+		if ($post_evt instanceof EE_Event) {
1068
+			//meta revision restore
1069
+			$post_evt->restore_revision($revision_id);
1070
+			//related objs restore
1071
+			$post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1072
+		}
1073
+	}
1074
+
1075
+
1076
+
1077
+	/**
1078
+	 * Attach the venue to the Event
1079
+	 *
1080
+	 * @param  \EE_Event $evtobj Event Object to add the venue to
1081
+	 * @param  array     $data   The request data from the form
1082
+	 * @return bool           Success or fail.
1083
+	 */
1084
+	protected function _default_venue_update(\EE_Event $evtobj, $data)
1085
+	{
1086
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1087
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1088
+		$rows_affected = null;
1089
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1090
+		// very important.  If we don't have a venue name...
1091
+		// then we'll get out because not necessary to create empty venue
1092
+		if (empty($data['venue_title'])) {
1093
+			return false;
1094
+		}
1095
+		$venue_array = array(
1096
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1097
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1098
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1099
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1100
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1101
+				: null,
1102
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1103
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1104
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1105
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1106
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1107
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1108
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1109
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1110
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1111
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1112
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1113
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1114
+			'status'              => 'publish',
1115
+		);
1116
+		//if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1117
+		if ( ! empty($venue_id)) {
1118
+			$update_where = array($venue_model->primary_key_name() => $venue_id);
1119
+			$rows_affected = $venue_model->update($venue_array, array($update_where));
1120
+			//we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1121
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1122
+			return $rows_affected > 0 ? true : false;
1123
+		} else {
1124
+			//we insert the venue
1125
+			$venue_id = $venue_model->insert($venue_array);
1126
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1127
+			return ! empty($venue_id) ? true : false;
1128
+		}
1129
+		//when we have the ancestor come in it's already been handled by the revision save.
1130
+	}
1131
+
1132
+
1133
+
1134
+	/**
1135
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1136
+	 *
1137
+	 * @param  EE_Event $evtobj The Event object we're attaching data to
1138
+	 * @param  array    $data   The request data from the form
1139
+	 * @return array
1140
+	 */
1141
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1142
+	{
1143
+		$success = true;
1144
+		$saved_dtt = null;
1145
+		$saved_tickets = array();
1146
+		$incoming_date_formats = array('Y-m-d', 'h:i a');
1147
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1148
+			//trim all values to ensure any excess whitespace is removed.
1149
+			$dtt = array_map('trim', $dtt);
1150
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1151
+				: $dtt['DTT_EVT_start'];
1152
+			$datetime_values = array(
1153
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1154
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1155
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1156
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1157
+				'DTT_order'     => $row,
1158
+			);
1159
+			//if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1160
+			if ( ! empty($dtt['DTT_ID'])) {
1161
+				$DTM = EE_Registry::instance()
1162
+								  ->load_model('Datetime', array($evtobj->get_timezone()))
1163
+								  ->get_one_by_ID($dtt['DTT_ID']);
1164
+				$DTM->set_date_format($incoming_date_formats[0]);
1165
+				$DTM->set_time_format($incoming_date_formats[1]);
1166
+				foreach ($datetime_values as $field => $value) {
1167
+					$DTM->set($field, $value);
1168
+				}
1169
+				//make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1170
+				$saved_dtts[$DTM->ID()] = $DTM;
1171
+			} else {
1172
+				$DTM = EE_Registry::instance()->load_class(
1173
+					'Datetime',
1174
+					array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1175
+					false,
1176
+					false
1177
+				);
1178
+				foreach ($datetime_values as $field => $value) {
1179
+					$DTM->set($field, $value);
1180
+				}
1181
+			}
1182
+			$DTM->save();
1183
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1184
+			//load DTT helper
1185
+			//before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1186
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1187
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1188
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1189
+				$DTT->save();
1190
+			}
1191
+			//now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1192
+			$saved_dtt = $DTT;
1193
+			$success = ! $success ? $success : $DTT;
1194
+			//if ANY of these updates fail then we want the appropriate global error message.
1195
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1196
+		}
1197
+		//no dtts get deleted so we don't do any of that logic here.
1198
+		//update tickets next
1199
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1200
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1201
+			$incoming_date_formats = array('Y-m-d', 'h:i a');
1202
+			$update_prices = false;
1203
+			$ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1204
+				? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1205
+			// trim inputs to ensure any excess whitespace is removed.
1206
+			$tkt = array_map('trim', $tkt);
1207
+			if (empty($tkt['TKT_start_date'])) {
1208
+				//let's use now in the set timezone.
1209
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1210
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1211
+			}
1212
+			if (empty($tkt['TKT_end_date'])) {
1213
+				//use the start date of the first datetime
1214
+				$dtt = $evtobj->first_datetime();
1215
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1216
+					$incoming_date_formats[0],
1217
+					$incoming_date_formats[1]
1218
+				);
1219
+			}
1220
+			$TKT_values = array(
1221
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1222
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1223
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1224
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1225
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1226
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1227
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1228
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1229
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1230
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1231
+				'TKT_row'         => $row,
1232
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1233
+				'TKT_price'       => $ticket_price,
1234
+			);
1235
+			//if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1236
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1237
+				$TKT_values['TKT_ID'] = 0;
1238
+				$TKT_values['TKT_is_default'] = 0;
1239
+				$TKT_values['TKT_price'] = $ticket_price;
1240
+				$update_prices = true;
1241
+			}
1242
+			//if we have a TKT_ID then we need to get that existing TKT_obj and update it
1243
+			//we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1244
+			//keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1245
+			if ( ! empty($tkt['TKT_ID'])) {
1246
+				$TKT = EE_Registry::instance()
1247
+								  ->load_model('Ticket', array($evtobj->get_timezone()))
1248
+								  ->get_one_by_ID($tkt['TKT_ID']);
1249
+				if ($TKT instanceof EE_Ticket) {
1250
+					$ticket_sold = $TKT->count_related(
1251
+						'Registration',
1252
+						array(
1253
+							array(
1254
+								'STS_ID' => array(
1255
+									'NOT IN',
1256
+									array(EEM_Registration::status_id_incomplete),
1257
+								),
1258
+							),
1259
+						)
1260
+					) > 0 ? true : false;
1261
+					//let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1262
+					$create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1263
+									  && ! $TKT->get(
1264
+						'TKT_deleted'
1265
+					) ? true : false;
1266
+					$TKT->set_date_format($incoming_date_formats[0]);
1267
+					$TKT->set_time_format($incoming_date_formats[1]);
1268
+					//set new values
1269
+					foreach ($TKT_values as $field => $value) {
1270
+						if ($field == 'TKT_qty') {
1271
+							$TKT->set_qty($value);
1272
+						} else {
1273
+							$TKT->set($field, $value);
1274
+						}
1275
+					}
1276
+					//if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1277
+					if ($create_new_TKT) {
1278
+						//archive the old ticket first
1279
+						$TKT->set('TKT_deleted', 1);
1280
+						$TKT->save();
1281
+						//make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1282
+						$saved_tickets[$TKT->ID()] = $TKT;
1283
+						//create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1284
+						$TKT = clone $TKT;
1285
+						$TKT->set('TKT_ID', 0);
1286
+						$TKT->set('TKT_deleted', 0);
1287
+						$TKT->set('TKT_price', $ticket_price);
1288
+						$TKT->set('TKT_sold', 0);
1289
+						//now we need to make sure that $new prices are created as well and attached to new ticket.
1290
+						$update_prices = true;
1291
+					}
1292
+					//make sure price is set if it hasn't been already
1293
+					$TKT->set('TKT_price', $ticket_price);
1294
+				}
1295
+			} else {
1296
+				//no TKT_id so a new TKT
1297
+				$TKT_values['TKT_price'] = $ticket_price;
1298
+				$TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1299
+				if ($TKT instanceof EE_Ticket) {
1300
+					//need to reset values to properly account for the date formats
1301
+					$TKT->set_date_format($incoming_date_formats[0]);
1302
+					$TKT->set_time_format($incoming_date_formats[1]);
1303
+					$TKT->set_timezone($evtobj->get_timezone());
1304
+					//set new values
1305
+					foreach ($TKT_values as $field => $value) {
1306
+						if ($field == 'TKT_qty') {
1307
+							$TKT->set_qty($value);
1308
+						} else {
1309
+							$TKT->set($field, $value);
1310
+						}
1311
+					}
1312
+					$update_prices = true;
1313
+				}
1314
+			}
1315
+			// cap ticket qty by datetime reg limits
1316
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1317
+			//update ticket.
1318
+			$TKT->save();
1319
+			//before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1320
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1321
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1322
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1323
+				$TKT->save();
1324
+			}
1325
+			//initially let's add the ticket to the dtt
1326
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1327
+			$saved_tickets[$TKT->ID()] = $TKT;
1328
+			//add prices to ticket
1329
+			$this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1330
+		}
1331
+		//however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1332
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1333
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1334
+		foreach ($tickets_removed as $id) {
1335
+			$id = absint($id);
1336
+			//get the ticket for this id
1337
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1338
+			//need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1339
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1340
+			foreach ($dtts as $dtt) {
1341
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1342
+			}
1343
+			//need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1344
+			$tkt_to_remove->delete_related_permanently('Price');
1345
+			//finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1346
+			$tkt_to_remove->delete_permanently();
1347
+		}
1348
+		return array($saved_dtt, $saved_tickets);
1349
+	}
1350
+
1351
+
1352
+
1353
+	/**
1354
+	 * This attaches a list of given prices to a ticket.
1355
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1356
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1357
+	 * price info and prices are automatically "archived" via the ticket.
1358
+	 *
1359
+	 * @access  private
1360
+	 * @param array     $prices     Array of prices from the form.
1361
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1362
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1363
+	 * @return  void
1364
+	 */
1365
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1366
+	{
1367
+		foreach ($prices as $row => $prc) {
1368
+			$PRC_values = array(
1369
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1370
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1371
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1372
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1373
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1374
+				'PRC_is_default' => 0, //make sure prices are NOT set as default from this context
1375
+				'PRC_order'      => $row,
1376
+			);
1377
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1378
+				$PRC_values['PRC_ID'] = 0;
1379
+				$PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1380
+			} else {
1381
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1382
+				//update this price with new values
1383
+				foreach ($PRC_values as $field => $newprc) {
1384
+					$PRC->set($field, $newprc);
1385
+				}
1386
+				$PRC->save();
1387
+			}
1388
+			$ticket->_add_relation_to($PRC, 'Price');
1389
+		}
1390
+	}
1391
+
1392
+
1393
+
1394
+	/**
1395
+	 * Add in our autosave ajax handlers
1396
+	 *
1397
+	 */
1398
+	protected function _ee_autosave_create_new()
1399
+	{
1400
+	}
1401
+
1402
+
1403
+	/**
1404
+	 * More autosave handlers.
1405
+	 */
1406
+	protected function _ee_autosave_edit()
1407
+	{
1408
+		return; //TEMPORARILY EXITING CAUSE THIS IS A TODO
1409
+	}
1410
+
1411
+
1412
+
1413
+	/**
1414
+	 *    _generate_publish_box_extra_content
1415
+	 */
1416
+	private function _generate_publish_box_extra_content()
1417
+	{
1418
+		//load formatter helper
1419
+		//args for getting related registrations
1420
+		$approved_query_args = array(
1421
+			array(
1422
+				'REG_deleted' => 0,
1423
+				'STS_ID'      => EEM_Registration::status_id_approved,
1424
+			),
1425
+		);
1426
+		$not_approved_query_args = array(
1427
+			array(
1428
+				'REG_deleted' => 0,
1429
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1430
+			),
1431
+		);
1432
+		$pending_payment_query_args = array(
1433
+			array(
1434
+				'REG_deleted' => 0,
1435
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1436
+			),
1437
+		);
1438
+		// publish box
1439
+		$publish_box_extra_args = array(
1440
+			'view_approved_reg_url'        => add_query_arg(
1441
+				array(
1442
+					'action'      => 'default',
1443
+					'event_id'    => $this->_cpt_model_obj->ID(),
1444
+					'_reg_status' => EEM_Registration::status_id_approved,
1445
+				),
1446
+				REG_ADMIN_URL
1447
+			),
1448
+			'view_not_approved_reg_url'    => add_query_arg(
1449
+				array(
1450
+					'action'      => 'default',
1451
+					'event_id'    => $this->_cpt_model_obj->ID(),
1452
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1453
+				),
1454
+				REG_ADMIN_URL
1455
+			),
1456
+			'view_pending_payment_reg_url' => add_query_arg(
1457
+				array(
1458
+					'action'      => 'default',
1459
+					'event_id'    => $this->_cpt_model_obj->ID(),
1460
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1461
+				),
1462
+				REG_ADMIN_URL
1463
+			),
1464
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1465
+				'Registration',
1466
+				$approved_query_args
1467
+			),
1468
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1469
+				'Registration',
1470
+				$not_approved_query_args
1471
+			),
1472
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1473
+				'Registration',
1474
+				$pending_payment_query_args
1475
+			),
1476
+			'misc_pub_section_class'       => apply_filters(
1477
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1478
+				'misc-pub-section'
1479
+			),
1480
+		);
1481
+		ob_start();
1482
+		do_action(
1483
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1484
+			$this->_cpt_model_obj
1485
+		);
1486
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1487
+		// load template
1488
+		EEH_Template::display_template(
1489
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1490
+			$publish_box_extra_args
1491
+		);
1492
+	}
1493
+
1494
+
1495
+
1496
+	/**
1497
+	 * @return EE_Event
1498
+	 */
1499
+	public function get_event_object()
1500
+	{
1501
+		return $this->_cpt_model_obj;
1502
+	}
1503
+
1504
+
1505
+
1506
+
1507
+	/** METABOXES * */
1508
+	/**
1509
+	 * _register_event_editor_meta_boxes
1510
+	 * add all metaboxes related to the event_editor
1511
+	 *
1512
+	 * @return void
1513
+	 */
1514
+	protected function _register_event_editor_meta_boxes()
1515
+	{
1516
+		$this->verify_cpt_object();
1517
+		add_meta_box(
1518
+			'espresso_event_editor_tickets',
1519
+			esc_html__('Event Datetime & Ticket', 'event_espresso'),
1520
+			array($this, 'ticket_metabox'),
1521
+			$this->page_slug,
1522
+			'normal',
1523
+			'high'
1524
+		);
1525
+		add_meta_box(
1526
+			'espresso_event_editor_event_options',
1527
+			esc_html__('Event Registration Options', 'event_espresso'),
1528
+			array($this, 'registration_options_meta_box'),
1529
+			$this->page_slug,
1530
+			'side',
1531
+			'default'
1532
+		);
1533
+		// NOTE: if you're looking for other metaboxes in here,
1534
+		// where a metabox has a related management page in the admin
1535
+		// you will find it setup in the related management page's "_Hooks" file.
1536
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1537
+	}
1538
+
1539
+
1540
+	/**
1541
+	 * @throws DomainException
1542
+	 * @throws EE_Error
1543
+	 */
1544
+	public function ticket_metabox()
1545
+	{
1546
+		$existing_datetime_ids = $existing_ticket_ids = array();
1547
+		//defaults for template args
1548
+		$template_args = array(
1549
+			'existing_datetime_ids'    => '',
1550
+			'event_datetime_help_link' => '',
1551
+			'ticket_options_help_link' => '',
1552
+			'time'                     => null,
1553
+			'ticket_rows'              => '',
1554
+			'existing_ticket_ids'      => '',
1555
+			'total_ticket_rows'        => 1,
1556
+			'ticket_js_structure'      => '',
1557
+			'trash_icon'               => 'ee-lock-icon',
1558
+			'disabled'                 => '',
1559
+		);
1560
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1561
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1562
+		/**
1563
+		 * 1. Start with retrieving Datetimes
1564
+		 * 2. Fore each datetime get related tickets
1565
+		 * 3. For each ticket get related prices
1566
+		 */
1567
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1568
+		/** @type EE_Datetime $first_datetime */
1569
+		$first_datetime = reset($times);
1570
+		//do we get related tickets?
1571
+		if ($first_datetime instanceof EE_Datetime
1572
+			&& $first_datetime->ID() !== 0
1573
+		) {
1574
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1575
+			$template_args['time'] = $first_datetime;
1576
+			$related_tickets = $first_datetime->tickets(
1577
+				array(
1578
+					array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1579
+					'default_where_conditions' => 'none',
1580
+				)
1581
+			);
1582
+			if ( ! empty($related_tickets)) {
1583
+				$template_args['total_ticket_rows'] = count($related_tickets);
1584
+				$row = 0;
1585
+				foreach ($related_tickets as $ticket) {
1586
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1587
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1588
+					$row++;
1589
+				}
1590
+			} else {
1591
+				$template_args['total_ticket_rows'] = 1;
1592
+				/** @type EE_Ticket $ticket */
1593
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1594
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1595
+			}
1596
+		} else {
1597
+			$template_args['time'] = $times[0];
1598
+			/** @type EE_Ticket $ticket */
1599
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1600
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1601
+			// NOTE: we're just sending the first default row
1602
+			// (decaf can't manage default tickets so this should be sufficient);
1603
+		}
1604
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1605
+			'event_editor_event_datetimes_help_tab'
1606
+		);
1607
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1608
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1609
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1610
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1611
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1612
+			true
1613
+		);
1614
+		$template = apply_filters(
1615
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1616
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1617
+		);
1618
+		EEH_Template::display_template($template, $template_args);
1619
+	}
1620
+
1621
+
1622
+
1623
+	/**
1624
+	 * Setup an individual ticket form for the decaf event editor page
1625
+	 *
1626
+	 * @access private
1627
+	 * @param  EE_Ticket $ticket   the ticket object
1628
+	 * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1629
+	 * @param int        $row
1630
+	 * @return string generated html for the ticket row.
1631
+	 */
1632
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1633
+	{
1634
+		$template_args = array(
1635
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1636
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1637
+				: '',
1638
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1639
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1640
+			'TKT_name'            => $ticket->get('TKT_name'),
1641
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1642
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1643
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1644
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1645
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1646
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1647
+			'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1648
+									 && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1649
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1650
+			'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1651
+				: ' disabled=disabled',
1652
+		);
1653
+		$price = $ticket->ID() !== 0
1654
+			? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1655
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1656
+		$price_args = array(
1657
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1658
+			'PRC_amount'            => $price->get('PRC_amount'),
1659
+			'PRT_ID'                => $price->get('PRT_ID'),
1660
+			'PRC_ID'                => $price->get('PRC_ID'),
1661
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1662
+		);
1663
+		//make sure we have default start and end dates if skeleton
1664
+		//handle rows that should NOT be empty
1665
+		if (empty($template_args['TKT_start_date'])) {
1666
+			//if empty then the start date will be now.
1667
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1668
+		}
1669
+		if (empty($template_args['TKT_end_date'])) {
1670
+			//get the earliest datetime (if present);
1671
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1672
+				? $this->_cpt_model_obj->get_first_related(
1673
+					'Datetime',
1674
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1675
+				)
1676
+				: null;
1677
+			if ( ! empty($earliest_dtt)) {
1678
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1679
+			} else {
1680
+				$template_args['TKT_end_date'] = date(
1681
+					'Y-m-d h:i a',
1682
+					mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1683
+				);
1684
+			}
1685
+		}
1686
+		$template_args = array_merge($template_args, $price_args);
1687
+		$template = apply_filters(
1688
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1689
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1690
+			$ticket
1691
+		);
1692
+		return EEH_Template::display_template($template, $template_args, true);
1693
+	}
1694
+
1695
+
1696
+	/**
1697
+	 * @throws DomainException
1698
+	 */
1699
+	public function registration_options_meta_box()
1700
+	{
1701
+		$yes_no_values = array(
1702
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1703
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1704
+		);
1705
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1706
+			array(
1707
+				EEM_Registration::status_id_cancelled,
1708
+				EEM_Registration::status_id_declined,
1709
+				EEM_Registration::status_id_incomplete,
1710
+			),
1711
+			true
1712
+		);
1713
+		//$template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1714
+		$template_args['_event'] = $this->_cpt_model_obj;
1715
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1716
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1717
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1718
+			'default_reg_status',
1719
+			$default_reg_status_values,
1720
+			$this->_cpt_model_obj->default_registration_status()
1721
+		);
1722
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1723
+			'display_desc',
1724
+			$yes_no_values,
1725
+			$this->_cpt_model_obj->display_description()
1726
+		);
1727
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1728
+			'display_ticket_selector',
1729
+			$yes_no_values,
1730
+			$this->_cpt_model_obj->display_ticket_selector(),
1731
+			'',
1732
+			'',
1733
+			false
1734
+		);
1735
+		$template_args['additional_registration_options'] = apply_filters(
1736
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1737
+			'',
1738
+			$template_args,
1739
+			$yes_no_values,
1740
+			$default_reg_status_values
1741
+		);
1742
+		EEH_Template::display_template(
1743
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1744
+			$template_args
1745
+		);
1746
+	}
1747
+
1748
+
1749
+
1750
+	/**
1751
+	 * _get_events()
1752
+	 * This method simply returns all the events (for the given _view and paging)
1753
+	 *
1754
+	 * @access public
1755
+	 * @param int  $per_page     count of items per page (20 default);
1756
+	 * @param int  $current_page what is the current page being viewed.
1757
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1758
+	 *                           If FALSE then we return an array of event objects
1759
+	 *                           that match the given _view and paging parameters.
1760
+	 * @return array an array of event objects.
1761
+	 */
1762
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1763
+	{
1764
+		$EEME = $this->_event_model();
1765
+		$offset = ($current_page - 1) * $per_page;
1766
+		$limit = $count ? null : $offset . ',' . $per_page;
1767
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1768
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1769
+		if (isset($this->_req_data['month_range'])) {
1770
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1771
+			//simulate the FIRST day of the month, that fixes issues for months like February
1772
+			//where PHP doesn't know what to assume for date.
1773
+			//@see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1774
+			$month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1775
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1776
+		}
1777
+		$where = array();
1778
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1779
+		//determine what post_status our condition will have for the query.
1780
+		switch ($status) {
1781
+			case 'month' :
1782
+			case 'today' :
1783
+			case null :
1784
+			case 'all' :
1785
+				break;
1786
+			case 'draft' :
1787
+				$where['status'] = array('IN', array('draft', 'auto-draft'));
1788
+				break;
1789
+			default :
1790
+				$where['status'] = $status;
1791
+		}
1792
+		//categories?
1793
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1794
+			? $this->_req_data['EVT_CAT'] : null;
1795
+		if ( ! empty ($category)) {
1796
+			$where['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1797
+			$where['Term_Taxonomy.term_id'] = $category;
1798
+		}
1799
+		//date where conditions
1800
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1801
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1802
+			$DateTime = new DateTime(
1803
+				$year_r . '-' . $month_r . '-01 00:00:00',
1804
+				new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1805
+			);
1806
+			$start = $DateTime->format(implode(' ', $start_formats));
1807
+			$end = $DateTime->setDate($year_r, $month_r, $DateTime
1808
+				->format('t'))->setTime(23, 59, 59)
1809
+							->format(implode(' ', $start_formats));
1810
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1811
+		} else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1812
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1813
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1814
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1815
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1816
+		} else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1817
+			$now = date('Y-m-01');
1818
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1819
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1820
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1821
+							->setTime(23, 59, 59)
1822
+							->format(implode(' ', $start_formats));
1823
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1824
+		}
1825
+		if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1826
+			$where['EVT_wp_user'] = get_current_user_id();
1827
+		} else {
1828
+			if ( ! isset($where['status'])) {
1829
+				if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1830
+					$where['OR'] = array(
1831
+						'status*restrict_private' => array('!=', 'private'),
1832
+						'AND'                     => array(
1833
+							'status*inclusive' => array('=', 'private'),
1834
+							'EVT_wp_user'      => get_current_user_id(),
1835
+						),
1836
+					);
1837
+				}
1838
+			}
1839
+		}
1840
+		if (isset($this->_req_data['EVT_wp_user'])) {
1841
+			if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1842
+				&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1843
+			) {
1844
+				$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1845
+			}
1846
+		}
1847
+		//search query handling
1848
+		if (isset($this->_req_data['s'])) {
1849
+			$search_string = '%' . $this->_req_data['s'] . '%';
1850
+			$where['OR'] = array(
1851
+				'EVT_name'       => array('LIKE', $search_string),
1852
+				'EVT_desc'       => array('LIKE', $search_string),
1853
+				'EVT_short_desc' => array('LIKE', $search_string),
1854
+			);
1855
+		}
1856
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1857
+		$query_params = apply_filters(
1858
+			'FHEE__Events_Admin_Page__get_events__query_params',
1859
+			array(
1860
+				$where,
1861
+				'limit'    => $limit,
1862
+				'order_by' => $orderby,
1863
+				'order'    => $order,
1864
+				'group_by' => 'EVT_ID',
1865
+			),
1866
+			$this->_req_data
1867
+		);
1868
+		//let's first check if we have special requests coming in.
1869
+		if (isset($this->_req_data['active_status'])) {
1870
+			switch ($this->_req_data['active_status']) {
1871
+				case 'upcoming' :
1872
+					return $EEME->get_upcoming_events($query_params, $count);
1873
+					break;
1874
+				case 'expired' :
1875
+					return $EEME->get_expired_events($query_params, $count);
1876
+					break;
1877
+				case 'active' :
1878
+					return $EEME->get_active_events($query_params, $count);
1879
+					break;
1880
+				case 'inactive' :
1881
+					return $EEME->get_inactive_events($query_params, $count);
1882
+					break;
1883
+			}
1884
+		}
1885
+		$events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1886
+		return $events;
1887
+	}
1888
+
1889
+
1890
+
1891
+	/**
1892
+	 * handling for WordPress CPT actions (trash, restore, delete)
1893
+	 *
1894
+	 * @param string $post_id
1895
+	 */
1896
+	public function trash_cpt_item($post_id)
1897
+	{
1898
+		$this->_req_data['EVT_ID'] = $post_id;
1899
+		$this->_trash_or_restore_event('trash', false);
1900
+	}
1901
+
1902
+
1903
+
1904
+	/**
1905
+	 * @param string $post_id
1906
+	 */
1907
+	public function restore_cpt_item($post_id)
1908
+	{
1909
+		$this->_req_data['EVT_ID'] = $post_id;
1910
+		$this->_trash_or_restore_event('draft', false);
1911
+	}
1912
+
1913
+
1914
+
1915
+	/**
1916
+	 * @param string $post_id
1917
+	 */
1918
+	public function delete_cpt_item($post_id)
1919
+	{
1920
+		$this->_req_data['EVT_ID'] = $post_id;
1921
+		$this->_delete_event(false);
1922
+	}
1923
+
1924
+
1925
+
1926
+	/**
1927
+	 * _trash_or_restore_event
1928
+	 *
1929
+	 * @access protected
1930
+	 * @param  string $event_status
1931
+	 * @param bool    $redirect_after
1932
+	 */
1933
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1934
+	{
1935
+		//determine the event id and set to array.
1936
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1937
+		// loop thru events
1938
+		if ($EVT_ID) {
1939
+			// clean status
1940
+			$event_status = sanitize_key($event_status);
1941
+			// grab status
1942
+			if ( ! empty($event_status)) {
1943
+				$success = $this->_change_event_status($EVT_ID, $event_status);
1944
+			} else {
1945
+				$success = false;
1946
+				$msg = esc_html__(
1947
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1948
+					'event_espresso'
1949
+				);
1950
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1951
+			}
1952
+		} else {
1953
+			$success = false;
1954
+			$msg = esc_html__(
1955
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1956
+				'event_espresso'
1957
+			);
1958
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1959
+		}
1960
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1961
+		if ($redirect_after) {
1962
+			$this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1963
+		}
1964
+	}
1965
+
1966
+
1967
+
1968
+	/**
1969
+	 * _trash_or_restore_events
1970
+	 *
1971
+	 * @access protected
1972
+	 * @param  string $event_status
1973
+	 * @return void
1974
+	 */
1975
+	protected function _trash_or_restore_events($event_status = 'trash')
1976
+	{
1977
+		// clean status
1978
+		$event_status = sanitize_key($event_status);
1979
+		// grab status
1980
+		if ( ! empty($event_status)) {
1981
+			$success = true;
1982
+			//determine the event id and set to array.
1983
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
1984
+			// loop thru events
1985
+			foreach ($EVT_IDs as $EVT_ID) {
1986
+				if ($EVT_ID = absint($EVT_ID)) {
1987
+					$results = $this->_change_event_status($EVT_ID, $event_status);
1988
+					$success = $results !== false ? $success : false;
1989
+				} else {
1990
+					$msg = sprintf(
1991
+						esc_html__(
1992
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
1993
+							'event_espresso'
1994
+						),
1995
+						$EVT_ID
1996
+					);
1997
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1998
+					$success = false;
1999
+				}
2000
+			}
2001
+		} else {
2002
+			$success = false;
2003
+			$msg = esc_html__(
2004
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2005
+				'event_espresso'
2006
+			);
2007
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2008
+		}
2009
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2010
+		$success = $success ? 2 : false;
2011
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2012
+		$this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2013
+	}
2014
+
2015
+
2016
+
2017
+	/**
2018
+	 * _trash_or_restore_events
2019
+	 *
2020
+	 * @access  private
2021
+	 * @param  int    $EVT_ID
2022
+	 * @param  string $event_status
2023
+	 * @return bool
2024
+	 */
2025
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2026
+	{
2027
+		// grab event id
2028
+		if ( ! $EVT_ID) {
2029
+			$msg = esc_html__(
2030
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2031
+				'event_espresso'
2032
+			);
2033
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2034
+			return false;
2035
+		}
2036
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2037
+		// clean status
2038
+		$event_status = sanitize_key($event_status);
2039
+		// grab status
2040
+		if (empty($event_status)) {
2041
+			$msg = esc_html__(
2042
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2043
+				'event_espresso'
2044
+			);
2045
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2046
+			return false;
2047
+		}
2048
+		// was event trashed or restored ?
2049
+		switch ($event_status) {
2050
+			case 'draft' :
2051
+				$action = 'restored from the trash';
2052
+				$hook = 'AHEE_event_restored_from_trash';
2053
+				break;
2054
+			case 'trash' :
2055
+				$action = 'moved to the trash';
2056
+				$hook = 'AHEE_event_moved_to_trash';
2057
+				break;
2058
+			default :
2059
+				$action = 'updated';
2060
+				$hook = false;
2061
+		}
2062
+		//use class to change status
2063
+		$this->_cpt_model_obj->set_status($event_status);
2064
+		$success = $this->_cpt_model_obj->save();
2065
+		if ($success === false) {
2066
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2067
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2068
+			return false;
2069
+		}
2070
+		if ($hook) {
2071
+			do_action($hook);
2072
+		}
2073
+		return true;
2074
+	}
2075
+
2076
+
2077
+
2078
+	/**
2079
+	 * _delete_event
2080
+	 *
2081
+	 * @access protected
2082
+	 * @param bool $redirect_after
2083
+	 */
2084
+	protected function _delete_event($redirect_after = true)
2085
+	{
2086
+		//determine the event id and set to array.
2087
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2088
+		$EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2089
+		// loop thru events
2090
+		if ($EVT_ID) {
2091
+			$success = $this->_permanently_delete_event($EVT_ID);
2092
+			// get list of events with no prices
2093
+			$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2094
+			// remove this event from the list of events with no prices
2095
+			if (isset($espresso_no_ticket_prices[$EVT_ID])) {
2096
+				unset($espresso_no_ticket_prices[$EVT_ID]);
2097
+			}
2098
+			update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2099
+		} else {
2100
+			$success = false;
2101
+			$msg = esc_html__(
2102
+				'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2103
+				'event_espresso'
2104
+			);
2105
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2106
+		}
2107
+		if ($redirect_after) {
2108
+			$this->_redirect_after_action(
2109
+				$success,
2110
+				'Event',
2111
+				'deleted',
2112
+				array('action' => 'default', 'status' => 'trash')
2113
+			);
2114
+		}
2115
+	}
2116
+
2117
+
2118
+
2119
+	/**
2120
+	 * _delete_events
2121
+	 *
2122
+	 * @access protected
2123
+	 * @return void
2124
+	 */
2125
+	protected function _delete_events()
2126
+	{
2127
+		$success = true;
2128
+		// get list of events with no prices
2129
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2130
+		//determine the event id and set to array.
2131
+		$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
2132
+		// loop thru events
2133
+		foreach ($EVT_IDs as $EVT_ID) {
2134
+			$EVT_ID = absint($EVT_ID);
2135
+			if ($EVT_ID) {
2136
+				$results = $this->_permanently_delete_event($EVT_ID);
2137
+				$success = $results !== false ? $success : false;
2138
+				// remove this event from the list of events with no prices
2139
+				unset($espresso_no_ticket_prices[$EVT_ID]);
2140
+			} else {
2141
+				$success = false;
2142
+				$msg = esc_html__(
2143
+					'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2144
+					'event_espresso'
2145
+				);
2146
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2147
+			}
2148
+		}
2149
+		update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2150
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2151
+		$success = $success ? 2 : false;
2152
+		$this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2153
+	}
2154
+
2155
+
2156
+
2157
+	/**
2158
+	 * _permanently_delete_event
2159
+	 *
2160
+	 * @access  private
2161
+	 * @param  int $EVT_ID
2162
+	 * @return bool
2163
+	 */
2164
+	private function _permanently_delete_event($EVT_ID = 0)
2165
+	{
2166
+		// grab event id
2167
+		if ( ! $EVT_ID) {
2168
+			$msg = esc_html__(
2169
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2170
+				'event_espresso'
2171
+			);
2172
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2173
+			return false;
2174
+		}
2175
+		if (
2176
+			! $this->_cpt_model_obj instanceof EE_Event
2177
+			|| $this->_cpt_model_obj->ID() !== $EVT_ID
2178
+		) {
2179
+			$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2180
+		}
2181
+		if ( ! $this->_cpt_model_obj instanceof EE_Event) {
2182
+			return false;
2183
+		}
2184
+		//need to delete related tickets and prices first.
2185
+		$datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2186
+		foreach ($datetimes as $datetime) {
2187
+			$this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2188
+			$tickets = $datetime->get_many_related('Ticket');
2189
+			foreach ($tickets as $ticket) {
2190
+				$ticket->_remove_relation_to($datetime, 'Datetime');
2191
+				$ticket->delete_related_permanently('Price');
2192
+				$ticket->delete_permanently();
2193
+			}
2194
+			$datetime->delete();
2195
+		}
2196
+		//what about related venues or terms?
2197
+		$venues = $this->_cpt_model_obj->get_many_related('Venue');
2198
+		foreach ($venues as $venue) {
2199
+			$this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2200
+		}
2201
+		//any attached question groups?
2202
+		$question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2203
+		if ( ! empty($question_groups)) {
2204
+			foreach ($question_groups as $question_group) {
2205
+				$this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2206
+			}
2207
+		}
2208
+		//Message Template Groups
2209
+		$this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2210
+		/** @type EE_Term_Taxonomy[] $term_taxonomies */
2211
+		$term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2212
+		foreach ($term_taxonomies as $term_taxonomy) {
2213
+			$this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2214
+		}
2215
+		$success = $this->_cpt_model_obj->delete_permanently();
2216
+		// did it all go as planned ?
2217
+		if ($success) {
2218
+			$msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2219
+			EE_Error::add_success($msg);
2220
+		} else {
2221
+			$msg = sprintf(
2222
+				esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2223
+				$EVT_ID
2224
+			);
2225
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2226
+			return false;
2227
+		}
2228
+		do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2229
+		return true;
2230
+	}
2231
+
2232
+
2233
+
2234
+	/**
2235
+	 * get total number of events
2236
+	 *
2237
+	 * @access public
2238
+	 * @return int
2239
+	 */
2240
+	public function total_events()
2241
+	{
2242
+		$count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2243
+		return $count;
2244
+	}
2245
+
2246
+
2247
+
2248
+	/**
2249
+	 * get total number of draft events
2250
+	 *
2251
+	 * @access public
2252
+	 * @return int
2253
+	 */
2254
+	public function total_events_draft()
2255
+	{
2256
+		$where = array(
2257
+			'status' => array('IN', array('draft', 'auto-draft')),
2258
+		);
2259
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2260
+		return $count;
2261
+	}
2262
+
2263
+
2264
+
2265
+	/**
2266
+	 * get total number of trashed events
2267
+	 *
2268
+	 * @access public
2269
+	 * @return int
2270
+	 */
2271
+	public function total_trashed_events()
2272
+	{
2273
+		$where = array(
2274
+			'status' => 'trash',
2275
+		);
2276
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2277
+		return $count;
2278
+	}
2279
+
2280
+
2281
+	/**
2282
+	 *    _default_event_settings
2283
+	 *    This generates the Default Settings Tab
2284
+	 *
2285
+	 * @return void
2286
+	 * @throws EE_Error
2287
+	 */
2288
+	protected function _default_event_settings()
2289
+	{
2290
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2291
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2292
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2293
+		$this->display_admin_page_with_sidebar();
2294
+	}
2295
+
2296
+
2297
+	/**
2298
+	 * Return the form for event settings.
2299
+	 * @return EE_Form_Section_Proper
2300
+	 */
2301
+	protected function _default_event_settings_form()
2302
+	{
2303
+		$registration_config = EE_Registry::instance()->CFG->registration;
2304
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2305
+		//exclude
2306
+			array(
2307
+				EEM_Registration::status_id_cancelled,
2308
+				EEM_Registration::status_id_declined,
2309
+				EEM_Registration::status_id_incomplete,
2310
+				EEM_Registration::status_id_wait_list,
2311
+			),
2312
+			true
2313
+		);
2314
+		return new EE_Form_Section_Proper(
2315
+			array(
2316
+				'name' => 'update_default_event_settings',
2317
+				'html_id' => 'update_default_event_settings',
2318
+				'html_class' => 'form-table',
2319
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2320
+				'subsections' => apply_filters(
2321
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2322
+					array(
2323
+						'default_reg_status' => new EE_Select_Input(
2324
+							$registration_stati_for_selection,
2325
+							array(
2326
+								'default' => isset($registration_config->default_STS_ID)
2327
+											 && array_key_exists(
2328
+												$registration_config->default_STS_ID,
2329
+												$registration_stati_for_selection
2330
+											 )
2331
+											? sanitize_text_field($registration_config->default_STS_ID)
2332
+											: EEM_Registration::status_id_pending_payment,
2333
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2334
+													. EEH_Template::get_help_tab_link(
2335
+														'default_settings_status_help_tab'
2336
+													),
2337
+								'html_help_text' => esc_html__(
2338
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2339
+									'event_espresso'
2340
+								)
2341
+							)
2342
+						),
2343
+						'default_max_tickets' => new EE_Integer_Input(
2344
+							array(
2345
+								'default' => isset($registration_config->default_maximum_number_of_tickets)
2346
+									? $registration_config->default_maximum_number_of_tickets
2347
+									: EEM_Event::get_default_additional_limit(),
2348
+								'html_label_text' => esc_html__(
2349
+									'Default Maximum Tickets Allowed Per Order:',
2350
+									'event_espresso'
2351
+								) . EEH_Template::get_help_tab_link(
2352
+									'default_maximum_tickets_help_tab"'
2353
+									),
2354
+								'html_help_text' => esc_html__(
2355
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2356
+									'event_espresso'
2357
+								)
2358
+							)
2359
+						)
2360
+					)
2361
+				)
2362
+			)
2363
+		);
2364
+	}
2365
+
2366
+
2367
+	/**
2368
+	 * _update_default_event_settings
2369
+	 *
2370
+	 * @access protected
2371
+	 * @return void
2372
+	 * @throws EE_Error
2373
+	 */
2374
+	protected function _update_default_event_settings()
2375
+	{
2376
+		$registration_config = EE_Registry::instance()->CFG->registration;
2377
+		$form = $this->_default_event_settings_form();
2378
+		if ($form->was_submitted()) {
2379
+			$form->receive_form_submission();
2380
+			if ($form->is_valid()) {
2381
+				$valid_data = $form->valid_data();
2382
+				if (isset($valid_data['default_reg_status'])) {
2383
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2384
+				}
2385
+				if (isset($valid_data['default_max_tickets'])) {
2386
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2387
+				}
2388
+				//update because data was valid!
2389
+				EE_Registry::instance()->CFG->update_espresso_config();
2390
+				EE_Error::overwrite_success();
2391
+				EE_Error::add_success(
2392
+					__('Default Event Settings were updated', 'event_espresso')
2393
+				);
2394
+			}
2395
+		}
2396
+		$this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2397
+	}
2398
+
2399
+
2400
+
2401
+	/*************        Templates        *************/
2402
+	protected function _template_settings()
2403
+	{
2404
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2405
+		$this->_template_args['preview_img'] = '<img src="'
2406
+											   . EVENTS_ASSETS_URL
2407
+											   . DS
2408
+											   . 'images'
2409
+											   . DS
2410
+											   . 'caffeinated_template_features.jpg" alt="'
2411
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2412
+											   . '" />';
2413
+		$this->_template_args['preview_text'] = '<strong>' . esc_html__(
2414
+				'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2415
+				'event_espresso'
2416
+			) . '</strong>';
2417
+		$this->display_admin_caf_preview_page('template_settings_tab');
2418
+	}
2419
+
2420
+
2421
+	/** Event Category Stuff **/
2422
+	/**
2423
+	 * set the _category property with the category object for the loaded page.
2424
+	 *
2425
+	 * @access private
2426
+	 * @return void
2427
+	 */
2428
+	private function _set_category_object()
2429
+	{
2430
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2431
+			return;
2432
+		} //already have the category object so get out.
2433
+		//set default category object
2434
+		$this->_set_empty_category_object();
2435
+		//only set if we've got an id
2436
+		if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2437
+			return;
2438
+		}
2439
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2440
+		$term = get_term($category_id, 'espresso_event_categories');
2441
+		if ( ! empty($term)) {
2442
+			$this->_category->category_name = $term->name;
2443
+			$this->_category->category_identifier = $term->slug;
2444
+			$this->_category->category_desc = $term->description;
2445
+			$this->_category->id = $term->term_id;
2446
+			$this->_category->parent = $term->parent;
2447
+		}
2448
+	}
2449
+
2450
+
2451
+	/**
2452
+	 * Clears out category properties.
2453
+	 */
2454
+	private function _set_empty_category_object()
2455
+	{
2456
+		$this->_category = new stdClass();
2457
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2458
+		$this->_category->id = $this->_category->parent = 0;
2459
+	}
2460
+
2461
+
2462
+	/**
2463
+	 * @throws EE_Error
2464
+	 */
2465
+	protected function _category_list_table()
2466
+	{
2467
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2468
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2469
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2470
+				'add_category',
2471
+				'add_category',
2472
+				array(),
2473
+				'add-new-h2'
2474
+			);
2475
+		$this->display_admin_list_table_page_with_sidebar();
2476
+	}
2477
+
2478
+
2479
+
2480
+	/**
2481
+	 * Output category details view.
2482
+	 */
2483
+	protected function _category_details($view)
2484
+	{
2485
+		//load formatter helper
2486
+		//load field generator helper
2487
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
2488
+		$this->_set_add_edit_form_tags($route);
2489
+		$this->_set_category_object();
2490
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2491
+		$delete_action = 'delete_category';
2492
+		//custom redirect
2493
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2494
+			array('action' => 'category_list'),
2495
+			$this->_admin_base_url
2496
+		);
2497
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2498
+		//take care of contents
2499
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2500
+		$this->display_admin_page_with_sidebar();
2501
+	}
2502
+
2503
+
2504
+
2505
+	/**
2506
+	 * Output category details content.
2507
+	 */
2508
+	protected function _category_details_content()
2509
+	{
2510
+		$editor_args['category_desc'] = array(
2511
+			'type'          => 'wp_editor',
2512
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2513
+			'class'         => 'my_editor_custom',
2514
+			'wpeditor_args' => array('media_buttons' => false),
2515
+		);
2516
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2517
+		$all_terms = get_terms(
2518
+			array('espresso_event_categories'),
2519
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2520
+		);
2521
+		//setup category select for term parents.
2522
+		$category_select_values[] = array(
2523
+			'text' => esc_html__('No Parent', 'event_espresso'),
2524
+			'id'   => 0,
2525
+		);
2526
+		foreach ($all_terms as $term) {
2527
+			$category_select_values[] = array(
2528
+				'text' => $term->name,
2529
+				'id'   => $term->term_id,
2530
+			);
2531
+		}
2532
+		$category_select = EEH_Form_Fields::select_input(
2533
+			'category_parent',
2534
+			$category_select_values,
2535
+			$this->_category->parent
2536
+		);
2537
+		$template_args = array(
2538
+			'category'                 => $this->_category,
2539
+			'category_select'          => $category_select,
2540
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2541
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2542
+			'disable'                  => '',
2543
+			'disabled_message'         => false,
2544
+		);
2545
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2546
+		return EEH_Template::display_template($template, $template_args, true);
2547
+	}
2548
+
2549
+
2550
+	/**
2551
+	 * Handles deleting categories.
2552
+	 */
2553
+	protected function _delete_categories()
2554
+	{
2555
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array)$this->_req_data['EVT_CAT_ID']
2556
+			: (array)$this->_req_data['category_id'];
2557
+		foreach ($cat_ids as $cat_id) {
2558
+			$this->_delete_category($cat_id);
2559
+		}
2560
+		//doesn't matter what page we're coming from... we're going to the same place after delete.
2561
+		$query_args = array(
2562
+			'action' => 'category_list',
2563
+		);
2564
+		$this->_redirect_after_action(0, '', '', $query_args);
2565
+	}
2566
+
2567
+
2568
+
2569
+	/**
2570
+	 * Handles deleting specific category.
2571
+	 * @param int $cat_id
2572
+	 */
2573
+	protected function _delete_category($cat_id)
2574
+	{
2575
+		$cat_id = absint($cat_id);
2576
+		wp_delete_term($cat_id, 'espresso_event_categories');
2577
+	}
2578
+
2579
+
2580
+
2581
+	/**
2582
+	 * Handles triggering the update or insertion of a new category.
2583
+	 * @param bool $new_category  true means we're triggering the insert of a new category.
2584
+	 */
2585
+	protected function _insert_or_update_category($new_category)
2586
+	{
2587
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2588
+		$success = 0; //we already have a success message so lets not send another.
2589
+		if ($cat_id) {
2590
+			$query_args = array(
2591
+				'action'     => 'edit_category',
2592
+				'EVT_CAT_ID' => $cat_id,
2593
+			);
2594
+		} else {
2595
+			$query_args = array('action' => 'add_category');
2596
+		}
2597
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2598
+	}
2599
+
2600
+
2601
+
2602
+	/**
2603
+	 * Inserts or updates category
2604
+	 * @param bool $update (true indicates we're updating a category).
2605
+	 * @return bool|mixed|string
2606
+	 */
2607
+	private function _insert_category($update = false)
2608
+	{
2609
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2610
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2611
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2612
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2613
+		if (empty($category_name)) {
2614
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2615
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2616
+			return false;
2617
+		}
2618
+		$term_args = array(
2619
+			'name'        => $category_name,
2620
+			'description' => $category_desc,
2621
+			'parent'      => $category_parent,
2622
+		);
2623
+		//was the category_identifier input disabled?
2624
+		if (isset($this->_req_data['category_identifier'])) {
2625
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2626
+		}
2627
+		$insert_ids = $update
2628
+			? wp_update_term($cat_id, 'espresso_event_categories', $term_args)
2629
+			: wp_insert_term($category_name, 'espresso_event_categories', $term_args);
2630
+		if ( ! is_array($insert_ids)) {
2631
+			$msg = esc_html__(
2632
+				'An error occurred and the category has not been saved to the database.',
2633
+				'event_espresso'
2634
+			);
2635
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2636
+		} else {
2637
+			$cat_id = $insert_ids['term_id'];
2638
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2639
+			EE_Error::add_success($msg);
2640
+		}
2641
+		return $cat_id;
2642
+	}
2643
+
2644
+
2645
+
2646
+	/**
2647
+	 * Gets categories or count of categories matching the arguments in the request.
2648
+	 * @param int  $per_page
2649
+	 * @param int  $current_page
2650
+	 * @param bool $count
2651
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2652
+	 */
2653
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2654
+	{
2655
+		//testing term stuff
2656
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2657
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2658
+		$limit = ($current_page - 1) * $per_page;
2659
+		$where = array('taxonomy' => 'espresso_event_categories');
2660
+		if (isset($this->_req_data['s'])) {
2661
+			$sstr = '%' . $this->_req_data['s'] . '%';
2662
+			$where['OR'] = array(
2663
+				'Term.name'   => array('LIKE', $sstr),
2664
+				'description' => array('LIKE', $sstr),
2665
+			);
2666
+		}
2667
+		$query_params = array(
2668
+			$where,
2669
+			'order_by'   => array($orderby => $order),
2670
+			'limit'      => $limit . ',' . $per_page,
2671
+			'force_join' => array('Term'),
2672
+		);
2673
+		$categories = $count
2674
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2675
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2676
+		return $categories;
2677
+	}
2678
+
2679
+	/* end category stuff */
2680
+	/**************/
2681
+
2682
+
2683
+	/**
2684
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2685
+	 * @throws EE_Error
2686
+	 */
2687
+	public function save_timezonestring_setting()
2688
+	{
2689
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2690
+			? $this->_req_data['timezone_selected']
2691
+			: '';
2692
+		if  (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false))
2693
+		{
2694
+			EE_Error::add_error(
2695
+				esc_html('An invalid timezone string submitted.', 'event_espresso'),
2696
+				__FILE__, __FUNCTION__, __LINE__
2697
+			);
2698
+			$this->_template_args['error'] = true;
2699
+			$this->_return_json();
2700
+		}
2701
+
2702
+		update_option('timezone_string', $timezone_string);
2703
+		EE_Error::add_success(
2704
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2705
+		);
2706
+		$this->_template_args['success'] = true;
2707
+		$this->_return_json(true, array('action' => 'create_new'));
2708
+	}
2709 2709
 }
2710 2710
 //end class Events_Admin_Page
Please login to merge, or discard this patch.