Completed
Branch FET-10785-ee-system-loader (68156e)
by
unknown
158:02 queued 146:22
created
shortcodes/espresso_events/EES_Espresso_Events.shortcode.php 1 patch
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -10,15 +10,15 @@  discard block
 block discarded – undo
10 10
 class EES_Espresso_Events  extends EES_Shortcode {
11 11
 
12 12
 	/**
13
-     * @deprecated 4.9.27
14
-     *  @return 	void
13
+	 * @deprecated 4.9.27
14
+	 *  @return 	void
15 15
 	 */
16 16
 	public static function set_hooks() {
17 17
 	}
18 18
 
19 19
 	/**
20
-     * @deprecated 4.9.27
21
-     *  @return 	void
20
+	 * @deprecated 4.9.27
21
+	 *  @return 	void
22 22
 	 */
23 23
 	public static function set_hooks_admin() {
24 24
 	}
@@ -26,8 +26,8 @@  discard block
 block discarded – undo
26 26
 
27 27
 
28 28
 	/**
29
-     * @deprecated 4.9.27
30
-     * @param WP $WP
29
+	 * @deprecated 4.9.27
30
+	 * @param WP $WP
31 31
 	 * @return    void
32 32
 	 */
33 33
 	public function run( WP $WP ) {
@@ -36,21 +36,21 @@  discard block
 block discarded – undo
36 36
 
37 37
 
38 38
 	/**
39
-     * @deprecated 4.9.27
40
-     *  @param 	array 	$attributes
39
+	 * @deprecated 4.9.27
40
+	 *  @param 	array 	$attributes
41 41
 	 *  @return 	string
42 42
 	 */
43 43
 	public function process_shortcode( $attributes = array() ) {
44
-        \EE_Error::doing_it_wrong(
45
-            __METHOD__,
46
-            __(
47
-                'Usage is deprecated. Please use \EventEspresso\core\domain\entities\shortcodes\EspressoEvents instead.',
48
-                'event_espresso'
49
-            ),
50
-            '4.9.27'
51
-        );
52
-        return '';
53
-    }
44
+		\EE_Error::doing_it_wrong(
45
+			__METHOD__,
46
+			__(
47
+				'Usage is deprecated. Please use \EventEspresso\core\domain\entities\shortcodes\EspressoEvents instead.',
48
+				'event_espresso'
49
+			),
50
+			'4.9.27'
51
+		);
52
+		return '';
53
+	}
54 54
 
55 55
 
56 56
 
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Generator.lib.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -443,7 +443,7 @@  discard block
 block discarded – undo
443 443
      * there's a single shared message template group among all the events.  Otherwise it returns null.
444 444
      *
445 445
      * @param array $event_ids
446
-     * @return EE_Message_Template_Group|null
446
+     * @return null|EE_Base_Class
447 447
      * @throws EE_Error
448 448
      */
449 449
     protected function _get_shared_message_template_for_events(array $event_ids)
@@ -476,7 +476,7 @@  discard block
 block discarded – undo
476 476
     /**
477 477
      * Retrieves the global message template group for the current messenger and message type.
478 478
      *
479
-     * @return EE_Message_Template_Group|null
479
+     * @return null|EE_Base_Class
480 480
      * @throws EE_Error
481 481
      */
482 482
     protected function _get_global_message_template_group_for_current_messenger_and_message_type()
@@ -617,7 +617,7 @@  discard block
 block discarded – undo
617 617
      * @param EE_Messages_Addressee     $recipient
618 618
      * @param array                     $templates formatted array of templates used for parsing data.
619 619
      * @param EE_Message_Template_Group $message_template_group
620
-     * @return bool|EE_Message
620
+     * @return EE_Message
621 621
      * @throws EE_Error
622 622
      */
623 623
     protected function _setup_message_object(
Please login to merge, or discard this patch.
Indentation   +931 added lines, -931 removed lines patch added patch discarded remove patch
@@ -13,935 +13,935 @@
 block discarded – undo
13 13
 {
14 14
 
15 15
 
16
-    /**
17
-     * @type EE_Messages_Data_Handler_Collection
18
-     */
19
-    protected $_data_handler_collection;
20
-
21
-    /**
22
-     * @type  EE_Message_Template_Group_Collection
23
-     */
24
-    protected $_template_collection;
25
-
26
-    /**
27
-     * This will hold the data handler for the current EE_Message being generated.
28
-     *
29
-     * @type EE_Messages_incoming_data
30
-     */
31
-    protected $_current_data_handler;
32
-
33
-    /**
34
-     * This holds the EE_Messages_Queue that contains the messages to generate.
35
-     *
36
-     * @type EE_Messages_Queue
37
-     */
38
-    protected $_generation_queue;
39
-
40
-    /**
41
-     * This holds the EE_Messages_Queue that will store the generated EE_Message objects.
42
-     *
43
-     * @type EE_Messages_Queue
44
-     */
45
-    protected $_ready_queue;
46
-
47
-    /**
48
-     * This is a container for any error messages that get created through the generation
49
-     * process.
50
-     *
51
-     * @type array
52
-     */
53
-    protected $_error_msg = array();
54
-
55
-    /**
56
-     * Flag used to set when the current EE_Message in the generation queue has been verified.
57
-     *
58
-     * @type bool
59
-     */
60
-    protected $_verified = false;
61
-
62
-    /**
63
-     * This will hold the current messenger object corresponding with the current EE_Message in the generation queue.
64
-     *
65
-     * @type EE_messenger
66
-     */
67
-    protected $_current_messenger;
68
-
69
-    /**
70
-     * This will hold the current message type object corresponding with the current EE_Message in the generation queue.
71
-     *
72
-     * @type EE_message_type
73
-     */
74
-    protected $_current_message_type;
75
-
76
-    /**
77
-     * @type EEH_Parse_Shortcodes
78
-     */
79
-    protected $_shortcode_parser;
80
-
81
-
82
-    /**
83
-     * @param EE_Messages_Queue                     $generation_queue
84
-     * @param \EE_Messages_Queue                    $ready_queue
85
-     * @param \EE_Messages_Data_Handler_Collection  $data_handler_collection
86
-     * @param \EE_Message_Template_Group_Collection $template_collection
87
-     * @param \EEH_Parse_Shortcodes                 $shortcode_parser
88
-     */
89
-    public function __construct(
90
-        EE_Messages_Queue $generation_queue,
91
-        EE_Messages_Queue $ready_queue,
92
-        EE_Messages_Data_Handler_Collection $data_handler_collection,
93
-        EE_Message_Template_Group_Collection $template_collection,
94
-        EEH_Parse_Shortcodes $shortcode_parser
95
-    ) {
96
-        $this->_generation_queue        = $generation_queue;
97
-        $this->_ready_queue             = $ready_queue;
98
-        $this->_data_handler_collection = $data_handler_collection;
99
-        $this->_template_collection     = $template_collection;
100
-        $this->_shortcode_parser        = $shortcode_parser;
101
-    }
102
-
103
-
104
-    /**
105
-     * @return EE_Messages_Queue
106
-     */
107
-    public function generation_queue()
108
-    {
109
-        return $this->_generation_queue;
110
-    }
111
-
112
-
113
-    /**
114
-     *  This iterates through the provided queue and generates the EE_Message objects.
115
-     *  When iterating through the queue, the queued item that served as the base for generating other EE_Message
116
-     *  objects gets removed and the new EE_Message objects get added to a NEW queue.  The NEW queue is then returned
117
-     *  for the caller to decide what to do with it.
118
-     *
119
-     * @param   bool $save Whether to save the EE_Message objects in the new queue or just return.
120
-     * @return EE_Messages_Queue  The new queue for holding generated EE_Message objects.
121
-     */
122
-    public function generate($save = true)
123
-    {
124
-        //iterate through the messages in the queue, generate, and add to new queue.
125
-        $this->_generation_queue->get_message_repository()->rewind();
126
-        while ($this->_generation_queue->get_message_repository()->valid()) {
127
-            //reset "current" properties
128
-            $this->_reset_current_properties();
129
-
130
-            /** @type EE_Message $msg */
131
-            $msg = $this->_generation_queue->get_message_repository()->current();
132
-
133
-            /**
134
-             * need to get the next object and capture it for setting manually after deletes.  The reason is that when
135
-             * an object is removed from the repo then valid for the next object will fail.
136
-             */
137
-            $this->_generation_queue->get_message_repository()->next();
138
-            $next_msg = $this->_generation_queue->get_message_repository()->current();
139
-            //restore pointer to current item
140
-            $this->_generation_queue->get_message_repository()->set_current($msg);
141
-
142
-            //skip and delete if the current $msg is NOT incomplete (queued for generation)
143
-            if ($msg->STS_ID() !== EEM_Message::status_incomplete) {
144
-                //we keep this item in the db just remove from the repo.
145
-                $this->_generation_queue->get_message_repository()->remove($msg);
146
-                //next item
147
-                $this->_generation_queue->get_message_repository()->set_current($next_msg);
148
-                continue;
149
-            }
150
-
151
-            if ($this->_verify()) {
152
-                //let's get generating!
153
-                $this->_generate();
154
-            }
155
-
156
-            //don't persist debug_only messages if the messages system is not in debug mode.
157
-            if ($msg->STS_ID() === EEM_Message::status_debug_only
158
-                && ! EEM_Message::debug()
159
-            ) {
160
-                do_action(
161
-                    'AHEE__EE_Messages_Generator__generate__before_debug_delete',
162
-                    $msg,
163
-                    $this->_error_msg,
164
-                    $this->_current_messenger,
165
-                    $this->_current_message_type,
166
-                    $this->_current_data_handler
167
-                );
168
-                $this->_generation_queue->get_message_repository()->delete();
169
-                $this->_generation_queue->get_message_repository()->set_current($next_msg);
170
-                continue;
171
-            }
172
-
173
-            //if there are error messages then let's set the status and the error message.
174
-            if ($this->_error_msg) {
175
-                //if the status is already debug only, then let's leave it at that.
176
-                if ($msg->STS_ID() !== EEM_Message::status_debug_only) {
177
-                    $msg->set_STS_ID(EEM_Message::status_failed);
178
-                }
179
-                do_action(
180
-                    'AHEE__EE_Messages_Generator__generate__processing_failed_message',
181
-                    $msg,
182
-                    $this->_error_msg,
183
-                    $this->_current_messenger,
184
-                    $this->_current_message_type,
185
-                    $this->_current_data_handler
186
-                );
187
-                $msg->set_error_message(
188
-                    esc_html__('Message failed to generate for the following reasons: ', 'event_espresso')
189
-                    . "\n"
190
-                    . implode("\n", $this->_error_msg)
191
-                );
192
-                $msg->set_modified(time());
193
-            } else {
194
-                do_action(
195
-                    'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete',
196
-                    $msg,
197
-                    $this->_error_msg,
198
-                    $this->_current_messenger,
199
-                    $this->_current_message_type,
200
-                    $this->_current_data_handler
201
-                );
202
-                //remove from db
203
-                $this->_generation_queue->get_message_repository()->delete();
204
-            }
205
-            //next item
206
-            $this->_generation_queue->get_message_repository()->set_current($next_msg);
207
-        }
208
-
209
-        //generation queue is ALWAYS saved to record any errors in the generation process.
210
-        $this->_generation_queue->save();
211
-
212
-        /**
213
-         * save _ready_queue if flag set.
214
-         * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method.  This
215
-         * means if a field was added that is not a valid database column.  The EE_Message was already saved to the db
216
-         * so a EE_Extra_Meta entry could be created and attached to the EE_Message.  In those cases the save flag is
217
-         * irrelevant.
218
-         */
219
-        if ($save) {
220
-            $this->_ready_queue->save();
221
-        }
222
-
223
-        //final reset of properties
224
-        $this->_reset_current_properties();
225
-
226
-        return $this->_ready_queue;
227
-    }
228
-
229
-
230
-    /**
231
-     * This resets all the properties used for holding "current" values corresponding to the current EE_Message object
232
-     * in the generation queue.
233
-     */
234
-    protected function _reset_current_properties()
235
-    {
236
-        $this->_verified = false;
237
-        //make sure any _data value in the current message type is reset
238
-        if ($this->_current_message_type instanceof EE_message_type) {
239
-            $this->_current_message_type->reset_data();
240
-        }
241
-        $this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null;
242
-    }
243
-
244
-
245
-    /**
246
-     * This proceeds with the actual generation of a message.  By the time this is called, there should already be a
247
-     * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the
248
-     * _generating_queue.
249
-     *
250
-     * @return bool Whether the message was successfully generated or not.
251
-     * @throws EE_Error
252
-     */
253
-    protected function _generate()
254
-    {
255
-        //double check verification has run and that everything is ready to work with (saves us having to validate
256
-        // everything again).
257
-        if (! $this->_verified) {
258
-            return false; //get out because we don't have a valid setup to work with.
259
-        }
260
-
261
-
262
-        try {
263
-            $addressees = $this->_current_message_type->get_addressees(
264
-                $this->_current_data_handler,
265
-                $this->_generation_queue->get_message_repository()->current()->context()
266
-            );
267
-        } catch (EE_Error $e) {
268
-            $this->_error_msg[] = $e->getMessage();
269
-            return false;
270
-        }
271
-
272
-
273
-        //if no addressees then get out because there is nothing to generation (possible bad data).
274
-        if (! $this->_valid_addressees($addressees)) {
275
-            do_action(
276
-                'AHEE__EE_Messages_Generator___generate__invalid_addressees',
277
-                $this->_generation_queue->get_message_repository()->current(),
278
-                $addressees,
279
-                $this->_current_messenger,
280
-                $this->_current_message_type,
281
-                $this->_current_data_handler
282
-            );
283
-            $this->_generation_queue->get_message_repository()->current()->set_STS_ID(
284
-                EEM_Message::status_debug_only
285
-            );
286
-            $this->_error_msg[] = esc_html__(
287
-                'This is not a critical error but an informational notice. Unable to generate messages EE_Messages_Addressee objects.  There were no attendees prepared by the data handler. Sometimes this is because messages only get generated for certain registration statuses. For example, the ticket notice message type only goes to approved registrations.',
288
-                'event_espresso'
289
-            );
290
-            return false;
291
-        }
292
-
293
-        $message_template_group = $this->_get_message_template_group();
294
-
295
-        //in the unlikely event there is no EE_Message_Template_Group available, get out!
296
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
297
-            $this->_error_msg[] = esc_html__(
298
-                'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
299
-                'event_espresso'
300
-            );
301
-            return false;
302
-        }
303
-
304
-        //get formatted templates for using to parse and setup EE_Message objects.
305
-        $templates = $this->_get_templates($message_template_group);
306
-
307
-
308
-        //setup new EE_Message objects (and add to _ready_queue)
309
-        return $this->_assemble_messages($addressees, $templates, $message_template_group);
310
-    }
311
-
312
-
313
-    /**
314
-     * Retrieves the message template group being used for generating messages.
315
-     * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times.
316
-     *
317
-     * @return EE_Message_Template_Group|null
318
-     * @throws EE_Error
319
-     */
320
-    protected function _get_message_template_group()
321
-    {
322
-        //first see if there is a specific message template group requested (current message in the queue has a specific
323
-        //GRP_ID
324
-        $message_template_group = $this->_specific_message_template_group_from_queue();
325
-        if ($message_template_group instanceof EE_Message_Template_Group) {
326
-            return $message_template_group;
327
-        }
328
-
329
-        //get event_ids from the datahandler so we can check to see if there's already a message template group for them
330
-        //in the collection.
331
-        $event_ids              = $this->_get_event_ids_from_current_data_handler();
332
-        $message_template_group = $this->_template_collection->get_by_key(
333
-            $this->_template_collection->getKey(
334
-                $this->_current_messenger->name,
335
-                $this->_current_message_type->name,
336
-                $event_ids
337
-            )
338
-        );
339
-
340
-        //if we have a message template group then no need to hit the database, just return it.
341
-        if ($message_template_group instanceof EE_Message_Template_Group) {
342
-            return $message_template_group;
343
-        }
344
-
345
-        //okay made it here, so let's get the global group first for this messenger and message type to ensure
346
-        //there is no override set.
347
-        $global_message_template_group = $this->_get_global_message_template_group_for_current_messenger_and_message_type();
348
-
349
-        if ($global_message_template_group instanceof EE_Message_Template_Group
350
-            && $global_message_template_group->get('MTP_is_override')
351
-        ) {
352
-            return $global_message_template_group;
353
-        }
354
-
355
-        //if we're still here, that means there was no message template group for the events in the collection and
356
-        //the global message template group for the messenger and message type is not set for override.  So next step is
357
-        //to see if there is a common shared custom message template group for this set of events.
358
-        $message_template_group = $this->_get_shared_message_template_for_events($event_ids);
359
-        if ($message_template_group instanceof EE_Message_Template_Group) {
360
-            return $message_template_group;
361
-        }
362
-
363
-        //STILL here?  Okay that means the fallback is to just use the global message template group for this event set.
364
-        //So we'll cache the global group for this event set (so this logic doesn't have to be repeated in this request)
365
-        //and return it.
366
-        if ($global_message_template_group instanceof EE_Message_Template_Group) {
367
-            $this->_template_collection->add(
368
-                $global_message_template_group,
369
-                $event_ids
370
-            );
371
-            return $global_message_template_group;
372
-        }
373
-
374
-        //if we land here that means there's NO active message template group for this set.
375
-        //TODO this will be a good target for some optimization down the road.  Whenever there is no active message
376
-        //template group for a given event set then cache that result so we don't repeat the logic.  However, for now,
377
-        //this should likely bit hit rarely enough that it's not a significant issue.
378
-        return null;
379
-    }
380
-
381
-
382
-    /**
383
-     * This checks the current message in the queue and determines if there is a specific Message Template Group
384
-     * requested for that message.
385
-     *
386
-     * @return EE_Message_Template_Group|null
387
-     */
388
-    protected function _specific_message_template_group_from_queue()
389
-    {
390
-        //is there a GRP_ID already on the EE_Message object?  If there is, then a specific template has been requested
391
-        //so let's use that.
392
-        $GRP_ID = $this->_generation_queue->get_message_repository()->current()->GRP_ID();
393
-
394
-        if ($GRP_ID) {
395
-            //attempt to retrieve from repo first
396
-            $message_template_group = $this->_template_collection->get_by_ID($GRP_ID);
397
-            if ($message_template_group instanceof EE_Message_Template_Group) {
398
-                return $message_template_group;  //got it!
399
-            }
400
-
401
-            //nope don't have it yet.  Get from DB then add to repo if its not here, then that means the current GRP_ID
402
-            //is not valid, so we'll continue on in the code assuming there's NO GRP_ID.
403
-            $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
404
-            if ($message_template_group instanceof EE_Message_Template_Group) {
405
-                $this->_template_collection->add($message_template_group);
406
-                return $message_template_group;
407
-            }
408
-        }
409
-        return null;
410
-    }
411
-
412
-
413
-    /**
414
-     * Returns whether the event ids passed in all share the same message template group for the current message type
415
-     * and messenger.
416
-     *
417
-     * @param array $event_ids
418
-     * @return bool true means they DO share the same message template group, false means they don't.
419
-     * @throws EE_Error
420
-     */
421
-    protected function _queue_shares_same_message_template_group_for_events(array $event_ids)
422
-    {
423
-        foreach ($this->_current_data_handler->events as $event) {
424
-            $event_ids[$event['ID']] = $event['ID'];
425
-        }
426
-        $count_of_message_template_groups = EEM_Message_Template_Group::instance()->count(
427
-            array(
428
-                array(
429
-                    'Event.EVT_ID'           => array('IN', $event_ids),
430
-                    'MTP_messenger'    => $this->_current_messenger->name,
431
-                    'MTP_message_type' => $this->_current_message_type->name,
432
-                ),
433
-            ),
434
-            'GRP_ID',
435
-            true
436
-        );
437
-        return $count_of_message_template_groups === 1;
438
-    }
439
-
440
-
441
-    /**
442
-     * This will get the shared message template group for events that are in the current data handler but ONLY if
443
-     * there's a single shared message template group among all the events.  Otherwise it returns null.
444
-     *
445
-     * @param array $event_ids
446
-     * @return EE_Message_Template_Group|null
447
-     * @throws EE_Error
448
-     */
449
-    protected function _get_shared_message_template_for_events(array $event_ids)
450
-    {
451
-        $message_template_group = null;
452
-        if ($this->_queue_shares_same_message_template_group_for_events($event_ids)) {
453
-            $message_template_group = EEM_Message_Template_Group::instance()->get_one(
454
-                array(
455
-                    array(
456
-                        'Event.EVT_ID'           => array('IN', $event_ids),
457
-                        'MTP_messenger'    => $this->_current_messenger->name,
458
-                        'MTP_message_type' => $this->_current_message_type->name,
459
-                        'MTP_is_active'    => true,
460
-                    ),
461
-                    'group_by' => 'GRP_ID',
462
-                )
463
-            );
464
-            //store this in the collection if its valid
465
-            if ($message_template_group instanceof EE_Message_Template_Group) {
466
-                $this->_template_collection->add(
467
-                    $message_template_group,
468
-                    $event_ids
469
-                );
470
-            }
471
-        }
472
-        return $message_template_group;
473
-    }
474
-
475
-
476
-    /**
477
-     * Retrieves the global message template group for the current messenger and message type.
478
-     *
479
-     * @return EE_Message_Template_Group|null
480
-     * @throws EE_Error
481
-     */
482
-    protected function _get_global_message_template_group_for_current_messenger_and_message_type()
483
-    {
484
-        //first check the collection (we use an array with 0 in it to represent global groups).
485
-        $global_message_template_group = $this->_template_collection->get_by_key(
486
-            $this->_template_collection->getKey(
487
-                $this->_current_messenger->name,
488
-                $this->_current_message_type->name,
489
-                array(0)
490
-            )
491
-        );
492
-
493
-        //if we don't have a group lets hit the db.
494
-        if (! $global_message_template_group instanceof EE_Message_Template_Group) {
495
-            $global_message_template_group = EEM_Message_Template_Group::instance()->get_one(
496
-                array(
497
-                    array(
498
-                        'MTP_messenger'    => $this->_current_messenger->name,
499
-                        'MTP_message_type' => $this->_current_message_type->name,
500
-                        'MTP_is_active'    => true,
501
-                        'MTP_is_global'    => true,
502
-                    ),
503
-                )
504
-            );
505
-            //if we have a group, add it to the collection.
506
-            if ($global_message_template_group instanceof EE_Message_Template_Group) {
507
-                $this->_template_collection->add(
508
-                    $global_message_template_group,
509
-                    array(0)
510
-                );
511
-            }
512
-        }
513
-        return $global_message_template_group;
514
-    }
515
-
516
-
517
-    /**
518
-     * Returns an array of event ids for all the events within the current data handler.
519
-     *
520
-     * @return array
521
-     */
522
-    protected function _get_event_ids_from_current_data_handler()
523
-    {
524
-        $event_ids = array();
525
-        foreach ($this->_current_data_handler->events as $event) {
526
-            $event_ids[$event['ID']] = $event['ID'];
527
-        }
528
-        return $event_ids;
529
-    }
530
-
531
-
532
-    /**
533
-     *  Retrieves formatted array of template information for each context specific to the given
534
-     *  EE_Message_Template_Group
535
-     *
536
-     * @param EE_Message_Template_Group $message_template_group
537
-     * @return array The returned array is in this structure:
538
-     *                          array(
539
-     *                          'field_name' => array(
540
-     *                          'context' => 'content'
541
-     *                          )
542
-     *                          )
543
-     * @throws EE_Error
544
-     */
545
-    protected function _get_templates(EE_Message_Template_Group $message_template_group)
546
-    {
547
-        $templates         = array();
548
-        $context_templates = $message_template_group->context_templates();
549
-        foreach ($context_templates as $context => $template_fields) {
550
-            foreach ($template_fields as $template_field => $template_obj) {
551
-                if (! $template_obj instanceof EE_Message_Template) {
552
-                    continue;
553
-                }
554
-                $templates[$template_field][$context] = $template_obj->get('MTP_content');
555
-            }
556
-        }
557
-        return $templates;
558
-    }
559
-
560
-
561
-    /**
562
-     * Assembles new fully generated EE_Message objects and adds to _ready_queue
563
-     *
564
-     * @param array                     $addressees  Array of EE_Messages_Addressee objects indexed by message type
565
-     *                                               context.
566
-     * @param array                     $templates   formatted array of templates used for parsing data.
567
-     * @param EE_Message_Template_Group $message_template_group
568
-     * @return bool   true if message generation went a-ok.  false if some sort of exception occurred.  Note: The
569
-     *                                               method will attempt to generate ALL EE_Message objects and add to
570
-     *                                               the _ready_queue.  Successfully generated messages get added to the
571
-     *                                               queue with EEM_Message::status_idle, unsuccessfully generated
572
-     *                                               messages will get added to the queue as EEM_Message::status_failed.
573
-     *                                               Very rarely should "false" be returned from this method.
574
-     */
575
-    protected function _assemble_messages($addressees, $templates, EE_Message_Template_Group $message_template_group)
576
-    {
577
-
578
-        //if templates are empty then get out because we can't generate anything.
579
-        if (! $templates) {
580
-            $this->_error_msg[] = esc_html__(
581
-                'Unable to assemble messages because there are no templates retrieved for generating the messages with',
582
-                'event_espresso'
583
-            );
584
-            return false;
585
-        }
586
-
587
-        //We use this as the counter for generated messages because don't forget we may be executing this inside of a
588
-        //generation_queue.  So _ready_queue may have generated EE_Message objects already.
589
-        $generated_count = 0;
590
-        foreach ($addressees as $context => $recipients) {
591
-            foreach ($recipients as $recipient) {
592
-                $message = $this->_setup_message_object($context, $recipient, $templates, $message_template_group);
593
-                if ($message instanceof EE_Message) {
594
-                    $this->_ready_queue->add(
595
-                        $message,
596
-                        array(),
597
-                        $this->_generation_queue->get_message_repository()->is_preview(),
598
-                        $this->_generation_queue->get_message_repository()->is_test_send()
599
-                    );
600
-                    $generated_count++;
601
-                }
602
-
603
-                //if the current MSG being generated is for a test send then we'll only use ONE message in the generation.
604
-                if ($this->_generation_queue->get_message_repository()->is_test_send()) {
605
-                    break 2;
606
-                }
607
-            }
608
-        }
609
-
610
-        //if there are no generated messages then something else fatal went wrong.
611
-        return $generated_count > 0;
612
-    }
613
-
614
-
615
-    /**
616
-     * @param string                    $context   The context for the generated message.
617
-     * @param EE_Messages_Addressee     $recipient
618
-     * @param array                     $templates formatted array of templates used for parsing data.
619
-     * @param EE_Message_Template_Group $message_template_group
620
-     * @return bool|EE_Message
621
-     * @throws EE_Error
622
-     */
623
-    protected function _setup_message_object(
624
-        $context,
625
-        EE_Messages_Addressee $recipient,
626
-        $templates,
627
-        EE_Message_Template_Group $message_template_group
628
-    ) {
629
-        //stuff we already know
630
-        $transaction_id = $recipient->txn instanceof EE_Transaction ? $recipient->txn->ID() : 0;
631
-        $transaction_id = empty($transaction_id) && $this->_current_data_handler->txn instanceof EE_Transaction
632
-            ? $this->_current_data_handler->txn->ID()
633
-            : $transaction_id;
634
-        $message_fields = array(
635
-            'GRP_ID'           => $message_template_group->ID(),
636
-            'TXN_ID'           => $transaction_id,
637
-            'MSG_messenger'    => $this->_current_messenger->name,
638
-            'MSG_message_type' => $this->_current_message_type->name,
639
-            'MSG_context'      => $context,
640
-        );
641
-
642
-        //recipient id and type should be on the EE_Messages_Addressee object but if this is empty, let's try to grab
643
-        // the info from the att_obj found in the EE_Messages_Addressee object.
644
-        if (empty($recipient->recipient_id) || empty($recipient->recipient_type)) {
645
-            $message_fields['MSG_recipient_ID']   = $recipient->att_obj instanceof EE_Attendee
646
-                ? $recipient->att_obj->ID()
647
-                : 0;
648
-            $message_fields['MSG_recipient_type'] = 'Attendee';
649
-        } else {
650
-            $message_fields['MSG_recipient_ID']   = $recipient->recipient_id;
651
-            $message_fields['MSG_recipient_type'] = $recipient->recipient_type;
652
-        }
653
-        $message = EE_Message_Factory::create($message_fields);
654
-
655
-        //grab valid shortcodes for shortcode parser
656
-        $mt_shortcodes = $this->_current_message_type->get_valid_shortcodes();
657
-        $m_shortcodes  = $this->_current_messenger->get_valid_shortcodes();
658
-
659
-        //if the 'to' field is empty (messages will ALWAYS have a "to" field, then we get out because that means this
660
-        //context is turned off) EXCEPT if we're previewing
661
-        if (empty($templates['to'][$context])
662
-            && ! $this->_generation_queue->get_message_repository()->is_preview()
663
-            && ! $this->_current_messenger->allow_empty_to_field()
664
-        ) {
665
-            //we silently exit here and do NOT record a fail because the message is "turned off" by having no "to"
666
-            //field.
667
-            return false;
668
-        }
669
-        $error_msg = array();
670
-        foreach ($templates as $field => $field_context) {
671
-            $error_msg = array();
672
-            //let's setup the valid shortcodes for the incoming context.
673
-            $valid_shortcodes = $mt_shortcodes[$context];
674
-            //merge in valid shortcodes for the field.
675
-            $shortcodes = isset($m_shortcodes[$field]) ? $m_shortcodes[$field] : $valid_shortcodes;
676
-            if (isset($templates[$field][$context])) {
677
-                //prefix field.
678
-                $column_name = 'MSG_' . $field;
679
-                try {
680
-                    $content = $this->_shortcode_parser->parse_message_template(
681
-                        $templates[$field][$context],
682
-                        $recipient,
683
-                        $shortcodes,
684
-                        $this->_current_message_type,
685
-                        $this->_current_messenger,
686
-                        $message
687
-                    );
688
-                    $message->set_field_or_extra_meta($column_name, $content);
689
-                } catch (EE_Error $e) {
690
-                    $error_msg[] = sprintf(
691
-                        esc_html__(
692
-                            'There was a problem generating the content for the field %s: %s',
693
-                            'event_espresso'
694
-                        ),
695
-                        $field,
696
-                        $e->getMessage()
697
-                    );
698
-                    $message->set_STS_ID(EEM_Message::status_failed);
699
-                }
700
-            }
701
-        }
702
-
703
-        if ($message->STS_ID() === EEM_Message::status_failed) {
704
-            $error_msg = esc_html__('There were problems generating this message:', 'event_espresso')
705
-                         . "\n"
706
-                         . implode("\n", $error_msg);
707
-            $message->set_error_message($error_msg);
708
-        } else {
709
-            $message->set_STS_ID(EEM_Message::status_idle);
710
-        }
711
-        return $message;
712
-    }
713
-
714
-
715
-    /**
716
-     * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate
717
-     * error message if either is missing.
718
-     *
719
-     * @return bool         true means there were no errors, false means there were errors.
720
-     */
721
-    protected function _verify()
722
-    {
723
-        //reset error message to an empty array.
724
-        $this->_error_msg = array();
725
-        $valid            = true;
726
-        $valid            = $valid ? $this->_validate_messenger_and_message_type() : $valid;
727
-        $valid            = $valid ? $this->_validate_and_setup_data() : $valid;
728
-
729
-        //set the verified flag so we know everything has been validated.
730
-        $this->_verified = $valid;
731
-
732
-        return $valid;
733
-    }
734
-
735
-
736
-    /**
737
-     * This accepts an array and validates that it is an array indexed by context with each value being an array of
738
-     * EE_Messages_Addressee objects.
739
-     *
740
-     * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[]
741
-     * @return bool
742
-     */
743
-    protected function _valid_addressees($addressees)
744
-    {
745
-        if (! $addressees || ! is_array($addressees)) {
746
-            return false;
747
-        }
748
-
749
-        foreach ($addressees as $addressee_array) {
750
-            foreach ($addressee_array as $addressee) {
751
-                if (! $addressee instanceof EE_Messages_Addressee) {
752
-                    return false;
753
-                }
754
-            }
755
-        }
756
-        return true;
757
-    }
758
-
759
-
760
-    /**
761
-     * This validates the messenger, message type, and presences of generation data for the current EE_Message in the
762
-     * queue. This process sets error messages if something is wrong.
763
-     *
764
-     * @return bool   true is if there are no errors.  false is if there is.
765
-     */
766
-    protected function _validate_messenger_and_message_type()
767
-    {
768
-
769
-        //first are there any existing error messages?  If so then return.
770
-        if ($this->_error_msg) {
771
-            return false;
772
-        }
773
-        /** @type EE_Message $message */
774
-        $message = $this->_generation_queue->get_message_repository()->current();
775
-        try {
776
-            $this->_current_messenger = $message->valid_messenger(true)
777
-                ? $message->messenger_object()
778
-                : null;
779
-        } catch (Exception $e) {
780
-            $this->_error_msg[] = $e->getMessage();
781
-        }
782
-        try {
783
-            $this->_current_message_type = $message->valid_message_type(true)
784
-                ? $message->message_type_object()
785
-                : null;
786
-        } catch (Exception $e) {
787
-            $this->_error_msg[] = $e->getMessage();
788
-        }
789
-
790
-        /**
791
-         * Check if there is any generation data, but only if this is not for a preview.
792
-         */
793
-        if (! $this->_generation_queue->get_message_repository()->get_generation_data()
794
-            && (
795
-                ! $this->_generation_queue->get_message_repository()->is_preview()
796
-                && $this->_generation_queue->get_message_repository()->get_data_handler()
797
-                   !== 'EE_Messages_Preview_incoming_data'
798
-            )
799
-        ) {
800
-            $this->_error_msg[] = esc_html__(
801
-                'There is no generation data for this message. Unable to generate.',
802
-                'event_espresso'
803
-            );
804
-        }
805
-
806
-        return empty($this->_error_msg);
807
-    }
808
-
809
-
810
-    /**
811
-     * This method retrieves the expected data handler for the message type and validates the generation data for that
812
-     * data handler.
813
-     *
814
-     * @return bool true means there are no errors.  false means there were errors (and handler did not get setup).
815
-     */
816
-    protected function _validate_and_setup_data()
817
-    {
818
-
819
-        //First, are there any existing error messages?  If so, return because if there were errors elsewhere this can't
820
-        //be used anyways.
821
-        if ($this->_error_msg) {
822
-            return false;
823
-        }
824
-
825
-        $generation_data = $this->_generation_queue->get_message_repository()->get_generation_data();
826
-
827
-        /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually */
828
-        $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
829
-            ? $this->_generation_queue->get_message_repository()->get_data_handler()
830
-            : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
831
-
832
-        //If this EE_Message is for a preview, then let's switch out to the preview data handler.
833
-        if ($this->_generation_queue->get_message_repository()->is_preview()) {
834
-            $data_handler_class_name = 'EE_Messages_Preview_incoming_data';
835
-        }
836
-
837
-        //First get the class name for the data handler (and also verifies it exists.
838
-        if (! class_exists($data_handler_class_name)) {
839
-            $this->_error_msg[] = sprintf(
840
-                esc_html__(
841
-                    'The included data handler class name does not match any valid, accessible, "%1$s" classes.  Looking for %2$s.',
842
-                    'event_espresso'
843
-                ),
844
-                'EE_Messages_incoming_data',
845
-                $data_handler_class_name
846
-            );
847
-            return false;
848
-        }
849
-
850
-        //convert generation_data for data_handler_instantiation.
851
-        $generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data);
852
-
853
-        //note, this may set error messages as well.
854
-        $this->_set_data_handler($generation_data, $data_handler_class_name);
855
-
856
-        return empty($this->_error_msg);
857
-    }
858
-
859
-
860
-    /**
861
-     * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and
862
-     * adds it to the _data repository.
863
-     *
864
-     * @param mixed  $generating_data           This is data expected by the instantiated data handler.
865
-     * @param string $data_handler_class_name   This is the reference string indicating what data handler is being
866
-     *                                          instantiated.
867
-     * @return void .
868
-     * @throws EE_Error
869
-     * @throws ReflectionException
870
-     */
871
-    protected function _set_data_handler($generating_data, $data_handler_class_name)
872
-    {
873
-        //valid classname for the data handler.  Now let's setup the key for the data handler repository to see if there
874
-        //is already a ready data handler in the repository.
875
-        $this->_current_data_handler = $this->_data_handler_collection->get_by_key(
876
-            $this->_data_handler_collection->get_key(
877
-                $data_handler_class_name,
878
-                $generating_data
879
-            )
880
-        );
881
-        if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
882
-            //no saved data_handler in the repo so let's set one up and add it to the repo.
883
-            try {
884
-                $this->_current_data_handler = new $data_handler_class_name($generating_data);
885
-                $this->_data_handler_collection->add($this->_current_data_handler, $generating_data);
886
-            } catch (EE_Error $e) {
887
-                $this->_error_msg[] = $e->get_error();
888
-            }
889
-        }
890
-    }
891
-
892
-
893
-    /**
894
-     * The queued EE_Message for generation does not save the data used for generation as objects
895
-     * because serialization of those objects could be problematic if the data is saved to the db.
896
-     * So this method calls the static method on the associated data_handler for the given message_type
897
-     * and that preps the data for later instantiation when generating.
898
-     *
899
-     * @param EE_Message_To_Generate $message_to_generate
900
-     * @param bool                   $preview Indicate whether this is being used for a preview or not.
901
-     * @return mixed Prepped data for persisting to the queue.  false is returned if unable to prep data.
902
-     */
903
-    protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview)
904
-    {
905
-        /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
906
-        $data_handler = $message_to_generate->get_data_handler_class_name($preview);
907
-        if (! $message_to_generate->valid()) {
908
-            return false; //unable to get the data because the info in the EE_Message_To_Generate class is invalid.
909
-        }
910
-        return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
911
-    }
912
-
913
-
914
-    /**
915
-     * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue.
916
-     *
917
-     * @param EE_Message_To_Generate $message_to_generate
918
-     * @param bool                   $test_send Whether this is just a test send or not.  Typically used for previews.
919
-     */
920
-    public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false)
921
-    {
922
-        //prep data
923
-        $data = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview());
924
-
925
-        $message = $message_to_generate->get_EE_Message();
926
-
927
-        //is there a GRP_ID in the request?
928
-        if ($GRP_ID = EE_Registry::instance()->REQ->get('GRP_ID')) {
929
-            $message->set_GRP_ID($GRP_ID);
930
-        }
931
-
932
-        if ($data === false) {
933
-            $message->set_STS_ID(EEM_Message::status_failed);
934
-            $message->set_error_message(
935
-                esc_html__(
936
-                    'Unable to prepare data for persistence to the database.',
937
-                    'event_espresso'
938
-                )
939
-            );
940
-        } else {
941
-            //make sure that the data handler is cached on the message as well
942
-            $data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name();
943
-        }
944
-
945
-        $this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send);
946
-    }
16
+	/**
17
+	 * @type EE_Messages_Data_Handler_Collection
18
+	 */
19
+	protected $_data_handler_collection;
20
+
21
+	/**
22
+	 * @type  EE_Message_Template_Group_Collection
23
+	 */
24
+	protected $_template_collection;
25
+
26
+	/**
27
+	 * This will hold the data handler for the current EE_Message being generated.
28
+	 *
29
+	 * @type EE_Messages_incoming_data
30
+	 */
31
+	protected $_current_data_handler;
32
+
33
+	/**
34
+	 * This holds the EE_Messages_Queue that contains the messages to generate.
35
+	 *
36
+	 * @type EE_Messages_Queue
37
+	 */
38
+	protected $_generation_queue;
39
+
40
+	/**
41
+	 * This holds the EE_Messages_Queue that will store the generated EE_Message objects.
42
+	 *
43
+	 * @type EE_Messages_Queue
44
+	 */
45
+	protected $_ready_queue;
46
+
47
+	/**
48
+	 * This is a container for any error messages that get created through the generation
49
+	 * process.
50
+	 *
51
+	 * @type array
52
+	 */
53
+	protected $_error_msg = array();
54
+
55
+	/**
56
+	 * Flag used to set when the current EE_Message in the generation queue has been verified.
57
+	 *
58
+	 * @type bool
59
+	 */
60
+	protected $_verified = false;
61
+
62
+	/**
63
+	 * This will hold the current messenger object corresponding with the current EE_Message in the generation queue.
64
+	 *
65
+	 * @type EE_messenger
66
+	 */
67
+	protected $_current_messenger;
68
+
69
+	/**
70
+	 * This will hold the current message type object corresponding with the current EE_Message in the generation queue.
71
+	 *
72
+	 * @type EE_message_type
73
+	 */
74
+	protected $_current_message_type;
75
+
76
+	/**
77
+	 * @type EEH_Parse_Shortcodes
78
+	 */
79
+	protected $_shortcode_parser;
80
+
81
+
82
+	/**
83
+	 * @param EE_Messages_Queue                     $generation_queue
84
+	 * @param \EE_Messages_Queue                    $ready_queue
85
+	 * @param \EE_Messages_Data_Handler_Collection  $data_handler_collection
86
+	 * @param \EE_Message_Template_Group_Collection $template_collection
87
+	 * @param \EEH_Parse_Shortcodes                 $shortcode_parser
88
+	 */
89
+	public function __construct(
90
+		EE_Messages_Queue $generation_queue,
91
+		EE_Messages_Queue $ready_queue,
92
+		EE_Messages_Data_Handler_Collection $data_handler_collection,
93
+		EE_Message_Template_Group_Collection $template_collection,
94
+		EEH_Parse_Shortcodes $shortcode_parser
95
+	) {
96
+		$this->_generation_queue        = $generation_queue;
97
+		$this->_ready_queue             = $ready_queue;
98
+		$this->_data_handler_collection = $data_handler_collection;
99
+		$this->_template_collection     = $template_collection;
100
+		$this->_shortcode_parser        = $shortcode_parser;
101
+	}
102
+
103
+
104
+	/**
105
+	 * @return EE_Messages_Queue
106
+	 */
107
+	public function generation_queue()
108
+	{
109
+		return $this->_generation_queue;
110
+	}
111
+
112
+
113
+	/**
114
+	 *  This iterates through the provided queue and generates the EE_Message objects.
115
+	 *  When iterating through the queue, the queued item that served as the base for generating other EE_Message
116
+	 *  objects gets removed and the new EE_Message objects get added to a NEW queue.  The NEW queue is then returned
117
+	 *  for the caller to decide what to do with it.
118
+	 *
119
+	 * @param   bool $save Whether to save the EE_Message objects in the new queue or just return.
120
+	 * @return EE_Messages_Queue  The new queue for holding generated EE_Message objects.
121
+	 */
122
+	public function generate($save = true)
123
+	{
124
+		//iterate through the messages in the queue, generate, and add to new queue.
125
+		$this->_generation_queue->get_message_repository()->rewind();
126
+		while ($this->_generation_queue->get_message_repository()->valid()) {
127
+			//reset "current" properties
128
+			$this->_reset_current_properties();
129
+
130
+			/** @type EE_Message $msg */
131
+			$msg = $this->_generation_queue->get_message_repository()->current();
132
+
133
+			/**
134
+			 * need to get the next object and capture it for setting manually after deletes.  The reason is that when
135
+			 * an object is removed from the repo then valid for the next object will fail.
136
+			 */
137
+			$this->_generation_queue->get_message_repository()->next();
138
+			$next_msg = $this->_generation_queue->get_message_repository()->current();
139
+			//restore pointer to current item
140
+			$this->_generation_queue->get_message_repository()->set_current($msg);
141
+
142
+			//skip and delete if the current $msg is NOT incomplete (queued for generation)
143
+			if ($msg->STS_ID() !== EEM_Message::status_incomplete) {
144
+				//we keep this item in the db just remove from the repo.
145
+				$this->_generation_queue->get_message_repository()->remove($msg);
146
+				//next item
147
+				$this->_generation_queue->get_message_repository()->set_current($next_msg);
148
+				continue;
149
+			}
150
+
151
+			if ($this->_verify()) {
152
+				//let's get generating!
153
+				$this->_generate();
154
+			}
155
+
156
+			//don't persist debug_only messages if the messages system is not in debug mode.
157
+			if ($msg->STS_ID() === EEM_Message::status_debug_only
158
+				&& ! EEM_Message::debug()
159
+			) {
160
+				do_action(
161
+					'AHEE__EE_Messages_Generator__generate__before_debug_delete',
162
+					$msg,
163
+					$this->_error_msg,
164
+					$this->_current_messenger,
165
+					$this->_current_message_type,
166
+					$this->_current_data_handler
167
+				);
168
+				$this->_generation_queue->get_message_repository()->delete();
169
+				$this->_generation_queue->get_message_repository()->set_current($next_msg);
170
+				continue;
171
+			}
172
+
173
+			//if there are error messages then let's set the status and the error message.
174
+			if ($this->_error_msg) {
175
+				//if the status is already debug only, then let's leave it at that.
176
+				if ($msg->STS_ID() !== EEM_Message::status_debug_only) {
177
+					$msg->set_STS_ID(EEM_Message::status_failed);
178
+				}
179
+				do_action(
180
+					'AHEE__EE_Messages_Generator__generate__processing_failed_message',
181
+					$msg,
182
+					$this->_error_msg,
183
+					$this->_current_messenger,
184
+					$this->_current_message_type,
185
+					$this->_current_data_handler
186
+				);
187
+				$msg->set_error_message(
188
+					esc_html__('Message failed to generate for the following reasons: ', 'event_espresso')
189
+					. "\n"
190
+					. implode("\n", $this->_error_msg)
191
+				);
192
+				$msg->set_modified(time());
193
+			} else {
194
+				do_action(
195
+					'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete',
196
+					$msg,
197
+					$this->_error_msg,
198
+					$this->_current_messenger,
199
+					$this->_current_message_type,
200
+					$this->_current_data_handler
201
+				);
202
+				//remove from db
203
+				$this->_generation_queue->get_message_repository()->delete();
204
+			}
205
+			//next item
206
+			$this->_generation_queue->get_message_repository()->set_current($next_msg);
207
+		}
208
+
209
+		//generation queue is ALWAYS saved to record any errors in the generation process.
210
+		$this->_generation_queue->save();
211
+
212
+		/**
213
+		 * save _ready_queue if flag set.
214
+		 * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method.  This
215
+		 * means if a field was added that is not a valid database column.  The EE_Message was already saved to the db
216
+		 * so a EE_Extra_Meta entry could be created and attached to the EE_Message.  In those cases the save flag is
217
+		 * irrelevant.
218
+		 */
219
+		if ($save) {
220
+			$this->_ready_queue->save();
221
+		}
222
+
223
+		//final reset of properties
224
+		$this->_reset_current_properties();
225
+
226
+		return $this->_ready_queue;
227
+	}
228
+
229
+
230
+	/**
231
+	 * This resets all the properties used for holding "current" values corresponding to the current EE_Message object
232
+	 * in the generation queue.
233
+	 */
234
+	protected function _reset_current_properties()
235
+	{
236
+		$this->_verified = false;
237
+		//make sure any _data value in the current message type is reset
238
+		if ($this->_current_message_type instanceof EE_message_type) {
239
+			$this->_current_message_type->reset_data();
240
+		}
241
+		$this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null;
242
+	}
243
+
244
+
245
+	/**
246
+	 * This proceeds with the actual generation of a message.  By the time this is called, there should already be a
247
+	 * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the
248
+	 * _generating_queue.
249
+	 *
250
+	 * @return bool Whether the message was successfully generated or not.
251
+	 * @throws EE_Error
252
+	 */
253
+	protected function _generate()
254
+	{
255
+		//double check verification has run and that everything is ready to work with (saves us having to validate
256
+		// everything again).
257
+		if (! $this->_verified) {
258
+			return false; //get out because we don't have a valid setup to work with.
259
+		}
260
+
261
+
262
+		try {
263
+			$addressees = $this->_current_message_type->get_addressees(
264
+				$this->_current_data_handler,
265
+				$this->_generation_queue->get_message_repository()->current()->context()
266
+			);
267
+		} catch (EE_Error $e) {
268
+			$this->_error_msg[] = $e->getMessage();
269
+			return false;
270
+		}
271
+
272
+
273
+		//if no addressees then get out because there is nothing to generation (possible bad data).
274
+		if (! $this->_valid_addressees($addressees)) {
275
+			do_action(
276
+				'AHEE__EE_Messages_Generator___generate__invalid_addressees',
277
+				$this->_generation_queue->get_message_repository()->current(),
278
+				$addressees,
279
+				$this->_current_messenger,
280
+				$this->_current_message_type,
281
+				$this->_current_data_handler
282
+			);
283
+			$this->_generation_queue->get_message_repository()->current()->set_STS_ID(
284
+				EEM_Message::status_debug_only
285
+			);
286
+			$this->_error_msg[] = esc_html__(
287
+				'This is not a critical error but an informational notice. Unable to generate messages EE_Messages_Addressee objects.  There were no attendees prepared by the data handler. Sometimes this is because messages only get generated for certain registration statuses. For example, the ticket notice message type only goes to approved registrations.',
288
+				'event_espresso'
289
+			);
290
+			return false;
291
+		}
292
+
293
+		$message_template_group = $this->_get_message_template_group();
294
+
295
+		//in the unlikely event there is no EE_Message_Template_Group available, get out!
296
+		if (! $message_template_group instanceof EE_Message_Template_Group) {
297
+			$this->_error_msg[] = esc_html__(
298
+				'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
299
+				'event_espresso'
300
+			);
301
+			return false;
302
+		}
303
+
304
+		//get formatted templates for using to parse and setup EE_Message objects.
305
+		$templates = $this->_get_templates($message_template_group);
306
+
307
+
308
+		//setup new EE_Message objects (and add to _ready_queue)
309
+		return $this->_assemble_messages($addressees, $templates, $message_template_group);
310
+	}
311
+
312
+
313
+	/**
314
+	 * Retrieves the message template group being used for generating messages.
315
+	 * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times.
316
+	 *
317
+	 * @return EE_Message_Template_Group|null
318
+	 * @throws EE_Error
319
+	 */
320
+	protected function _get_message_template_group()
321
+	{
322
+		//first see if there is a specific message template group requested (current message in the queue has a specific
323
+		//GRP_ID
324
+		$message_template_group = $this->_specific_message_template_group_from_queue();
325
+		if ($message_template_group instanceof EE_Message_Template_Group) {
326
+			return $message_template_group;
327
+		}
328
+
329
+		//get event_ids from the datahandler so we can check to see if there's already a message template group for them
330
+		//in the collection.
331
+		$event_ids              = $this->_get_event_ids_from_current_data_handler();
332
+		$message_template_group = $this->_template_collection->get_by_key(
333
+			$this->_template_collection->getKey(
334
+				$this->_current_messenger->name,
335
+				$this->_current_message_type->name,
336
+				$event_ids
337
+			)
338
+		);
339
+
340
+		//if we have a message template group then no need to hit the database, just return it.
341
+		if ($message_template_group instanceof EE_Message_Template_Group) {
342
+			return $message_template_group;
343
+		}
344
+
345
+		//okay made it here, so let's get the global group first for this messenger and message type to ensure
346
+		//there is no override set.
347
+		$global_message_template_group = $this->_get_global_message_template_group_for_current_messenger_and_message_type();
348
+
349
+		if ($global_message_template_group instanceof EE_Message_Template_Group
350
+			&& $global_message_template_group->get('MTP_is_override')
351
+		) {
352
+			return $global_message_template_group;
353
+		}
354
+
355
+		//if we're still here, that means there was no message template group for the events in the collection and
356
+		//the global message template group for the messenger and message type is not set for override.  So next step is
357
+		//to see if there is a common shared custom message template group for this set of events.
358
+		$message_template_group = $this->_get_shared_message_template_for_events($event_ids);
359
+		if ($message_template_group instanceof EE_Message_Template_Group) {
360
+			return $message_template_group;
361
+		}
362
+
363
+		//STILL here?  Okay that means the fallback is to just use the global message template group for this event set.
364
+		//So we'll cache the global group for this event set (so this logic doesn't have to be repeated in this request)
365
+		//and return it.
366
+		if ($global_message_template_group instanceof EE_Message_Template_Group) {
367
+			$this->_template_collection->add(
368
+				$global_message_template_group,
369
+				$event_ids
370
+			);
371
+			return $global_message_template_group;
372
+		}
373
+
374
+		//if we land here that means there's NO active message template group for this set.
375
+		//TODO this will be a good target for some optimization down the road.  Whenever there is no active message
376
+		//template group for a given event set then cache that result so we don't repeat the logic.  However, for now,
377
+		//this should likely bit hit rarely enough that it's not a significant issue.
378
+		return null;
379
+	}
380
+
381
+
382
+	/**
383
+	 * This checks the current message in the queue and determines if there is a specific Message Template Group
384
+	 * requested for that message.
385
+	 *
386
+	 * @return EE_Message_Template_Group|null
387
+	 */
388
+	protected function _specific_message_template_group_from_queue()
389
+	{
390
+		//is there a GRP_ID already on the EE_Message object?  If there is, then a specific template has been requested
391
+		//so let's use that.
392
+		$GRP_ID = $this->_generation_queue->get_message_repository()->current()->GRP_ID();
393
+
394
+		if ($GRP_ID) {
395
+			//attempt to retrieve from repo first
396
+			$message_template_group = $this->_template_collection->get_by_ID($GRP_ID);
397
+			if ($message_template_group instanceof EE_Message_Template_Group) {
398
+				return $message_template_group;  //got it!
399
+			}
400
+
401
+			//nope don't have it yet.  Get from DB then add to repo if its not here, then that means the current GRP_ID
402
+			//is not valid, so we'll continue on in the code assuming there's NO GRP_ID.
403
+			$message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
404
+			if ($message_template_group instanceof EE_Message_Template_Group) {
405
+				$this->_template_collection->add($message_template_group);
406
+				return $message_template_group;
407
+			}
408
+		}
409
+		return null;
410
+	}
411
+
412
+
413
+	/**
414
+	 * Returns whether the event ids passed in all share the same message template group for the current message type
415
+	 * and messenger.
416
+	 *
417
+	 * @param array $event_ids
418
+	 * @return bool true means they DO share the same message template group, false means they don't.
419
+	 * @throws EE_Error
420
+	 */
421
+	protected function _queue_shares_same_message_template_group_for_events(array $event_ids)
422
+	{
423
+		foreach ($this->_current_data_handler->events as $event) {
424
+			$event_ids[$event['ID']] = $event['ID'];
425
+		}
426
+		$count_of_message_template_groups = EEM_Message_Template_Group::instance()->count(
427
+			array(
428
+				array(
429
+					'Event.EVT_ID'           => array('IN', $event_ids),
430
+					'MTP_messenger'    => $this->_current_messenger->name,
431
+					'MTP_message_type' => $this->_current_message_type->name,
432
+				),
433
+			),
434
+			'GRP_ID',
435
+			true
436
+		);
437
+		return $count_of_message_template_groups === 1;
438
+	}
439
+
440
+
441
+	/**
442
+	 * This will get the shared message template group for events that are in the current data handler but ONLY if
443
+	 * there's a single shared message template group among all the events.  Otherwise it returns null.
444
+	 *
445
+	 * @param array $event_ids
446
+	 * @return EE_Message_Template_Group|null
447
+	 * @throws EE_Error
448
+	 */
449
+	protected function _get_shared_message_template_for_events(array $event_ids)
450
+	{
451
+		$message_template_group = null;
452
+		if ($this->_queue_shares_same_message_template_group_for_events($event_ids)) {
453
+			$message_template_group = EEM_Message_Template_Group::instance()->get_one(
454
+				array(
455
+					array(
456
+						'Event.EVT_ID'           => array('IN', $event_ids),
457
+						'MTP_messenger'    => $this->_current_messenger->name,
458
+						'MTP_message_type' => $this->_current_message_type->name,
459
+						'MTP_is_active'    => true,
460
+					),
461
+					'group_by' => 'GRP_ID',
462
+				)
463
+			);
464
+			//store this in the collection if its valid
465
+			if ($message_template_group instanceof EE_Message_Template_Group) {
466
+				$this->_template_collection->add(
467
+					$message_template_group,
468
+					$event_ids
469
+				);
470
+			}
471
+		}
472
+		return $message_template_group;
473
+	}
474
+
475
+
476
+	/**
477
+	 * Retrieves the global message template group for the current messenger and message type.
478
+	 *
479
+	 * @return EE_Message_Template_Group|null
480
+	 * @throws EE_Error
481
+	 */
482
+	protected function _get_global_message_template_group_for_current_messenger_and_message_type()
483
+	{
484
+		//first check the collection (we use an array with 0 in it to represent global groups).
485
+		$global_message_template_group = $this->_template_collection->get_by_key(
486
+			$this->_template_collection->getKey(
487
+				$this->_current_messenger->name,
488
+				$this->_current_message_type->name,
489
+				array(0)
490
+			)
491
+		);
492
+
493
+		//if we don't have a group lets hit the db.
494
+		if (! $global_message_template_group instanceof EE_Message_Template_Group) {
495
+			$global_message_template_group = EEM_Message_Template_Group::instance()->get_one(
496
+				array(
497
+					array(
498
+						'MTP_messenger'    => $this->_current_messenger->name,
499
+						'MTP_message_type' => $this->_current_message_type->name,
500
+						'MTP_is_active'    => true,
501
+						'MTP_is_global'    => true,
502
+					),
503
+				)
504
+			);
505
+			//if we have a group, add it to the collection.
506
+			if ($global_message_template_group instanceof EE_Message_Template_Group) {
507
+				$this->_template_collection->add(
508
+					$global_message_template_group,
509
+					array(0)
510
+				);
511
+			}
512
+		}
513
+		return $global_message_template_group;
514
+	}
515
+
516
+
517
+	/**
518
+	 * Returns an array of event ids for all the events within the current data handler.
519
+	 *
520
+	 * @return array
521
+	 */
522
+	protected function _get_event_ids_from_current_data_handler()
523
+	{
524
+		$event_ids = array();
525
+		foreach ($this->_current_data_handler->events as $event) {
526
+			$event_ids[$event['ID']] = $event['ID'];
527
+		}
528
+		return $event_ids;
529
+	}
530
+
531
+
532
+	/**
533
+	 *  Retrieves formatted array of template information for each context specific to the given
534
+	 *  EE_Message_Template_Group
535
+	 *
536
+	 * @param EE_Message_Template_Group $message_template_group
537
+	 * @return array The returned array is in this structure:
538
+	 *                          array(
539
+	 *                          'field_name' => array(
540
+	 *                          'context' => 'content'
541
+	 *                          )
542
+	 *                          )
543
+	 * @throws EE_Error
544
+	 */
545
+	protected function _get_templates(EE_Message_Template_Group $message_template_group)
546
+	{
547
+		$templates         = array();
548
+		$context_templates = $message_template_group->context_templates();
549
+		foreach ($context_templates as $context => $template_fields) {
550
+			foreach ($template_fields as $template_field => $template_obj) {
551
+				if (! $template_obj instanceof EE_Message_Template) {
552
+					continue;
553
+				}
554
+				$templates[$template_field][$context] = $template_obj->get('MTP_content');
555
+			}
556
+		}
557
+		return $templates;
558
+	}
559
+
560
+
561
+	/**
562
+	 * Assembles new fully generated EE_Message objects and adds to _ready_queue
563
+	 *
564
+	 * @param array                     $addressees  Array of EE_Messages_Addressee objects indexed by message type
565
+	 *                                               context.
566
+	 * @param array                     $templates   formatted array of templates used for parsing data.
567
+	 * @param EE_Message_Template_Group $message_template_group
568
+	 * @return bool   true if message generation went a-ok.  false if some sort of exception occurred.  Note: The
569
+	 *                                               method will attempt to generate ALL EE_Message objects and add to
570
+	 *                                               the _ready_queue.  Successfully generated messages get added to the
571
+	 *                                               queue with EEM_Message::status_idle, unsuccessfully generated
572
+	 *                                               messages will get added to the queue as EEM_Message::status_failed.
573
+	 *                                               Very rarely should "false" be returned from this method.
574
+	 */
575
+	protected function _assemble_messages($addressees, $templates, EE_Message_Template_Group $message_template_group)
576
+	{
577
+
578
+		//if templates are empty then get out because we can't generate anything.
579
+		if (! $templates) {
580
+			$this->_error_msg[] = esc_html__(
581
+				'Unable to assemble messages because there are no templates retrieved for generating the messages with',
582
+				'event_espresso'
583
+			);
584
+			return false;
585
+		}
586
+
587
+		//We use this as the counter for generated messages because don't forget we may be executing this inside of a
588
+		//generation_queue.  So _ready_queue may have generated EE_Message objects already.
589
+		$generated_count = 0;
590
+		foreach ($addressees as $context => $recipients) {
591
+			foreach ($recipients as $recipient) {
592
+				$message = $this->_setup_message_object($context, $recipient, $templates, $message_template_group);
593
+				if ($message instanceof EE_Message) {
594
+					$this->_ready_queue->add(
595
+						$message,
596
+						array(),
597
+						$this->_generation_queue->get_message_repository()->is_preview(),
598
+						$this->_generation_queue->get_message_repository()->is_test_send()
599
+					);
600
+					$generated_count++;
601
+				}
602
+
603
+				//if the current MSG being generated is for a test send then we'll only use ONE message in the generation.
604
+				if ($this->_generation_queue->get_message_repository()->is_test_send()) {
605
+					break 2;
606
+				}
607
+			}
608
+		}
609
+
610
+		//if there are no generated messages then something else fatal went wrong.
611
+		return $generated_count > 0;
612
+	}
613
+
614
+
615
+	/**
616
+	 * @param string                    $context   The context for the generated message.
617
+	 * @param EE_Messages_Addressee     $recipient
618
+	 * @param array                     $templates formatted array of templates used for parsing data.
619
+	 * @param EE_Message_Template_Group $message_template_group
620
+	 * @return bool|EE_Message
621
+	 * @throws EE_Error
622
+	 */
623
+	protected function _setup_message_object(
624
+		$context,
625
+		EE_Messages_Addressee $recipient,
626
+		$templates,
627
+		EE_Message_Template_Group $message_template_group
628
+	) {
629
+		//stuff we already know
630
+		$transaction_id = $recipient->txn instanceof EE_Transaction ? $recipient->txn->ID() : 0;
631
+		$transaction_id = empty($transaction_id) && $this->_current_data_handler->txn instanceof EE_Transaction
632
+			? $this->_current_data_handler->txn->ID()
633
+			: $transaction_id;
634
+		$message_fields = array(
635
+			'GRP_ID'           => $message_template_group->ID(),
636
+			'TXN_ID'           => $transaction_id,
637
+			'MSG_messenger'    => $this->_current_messenger->name,
638
+			'MSG_message_type' => $this->_current_message_type->name,
639
+			'MSG_context'      => $context,
640
+		);
641
+
642
+		//recipient id and type should be on the EE_Messages_Addressee object but if this is empty, let's try to grab
643
+		// the info from the att_obj found in the EE_Messages_Addressee object.
644
+		if (empty($recipient->recipient_id) || empty($recipient->recipient_type)) {
645
+			$message_fields['MSG_recipient_ID']   = $recipient->att_obj instanceof EE_Attendee
646
+				? $recipient->att_obj->ID()
647
+				: 0;
648
+			$message_fields['MSG_recipient_type'] = 'Attendee';
649
+		} else {
650
+			$message_fields['MSG_recipient_ID']   = $recipient->recipient_id;
651
+			$message_fields['MSG_recipient_type'] = $recipient->recipient_type;
652
+		}
653
+		$message = EE_Message_Factory::create($message_fields);
654
+
655
+		//grab valid shortcodes for shortcode parser
656
+		$mt_shortcodes = $this->_current_message_type->get_valid_shortcodes();
657
+		$m_shortcodes  = $this->_current_messenger->get_valid_shortcodes();
658
+
659
+		//if the 'to' field is empty (messages will ALWAYS have a "to" field, then we get out because that means this
660
+		//context is turned off) EXCEPT if we're previewing
661
+		if (empty($templates['to'][$context])
662
+			&& ! $this->_generation_queue->get_message_repository()->is_preview()
663
+			&& ! $this->_current_messenger->allow_empty_to_field()
664
+		) {
665
+			//we silently exit here and do NOT record a fail because the message is "turned off" by having no "to"
666
+			//field.
667
+			return false;
668
+		}
669
+		$error_msg = array();
670
+		foreach ($templates as $field => $field_context) {
671
+			$error_msg = array();
672
+			//let's setup the valid shortcodes for the incoming context.
673
+			$valid_shortcodes = $mt_shortcodes[$context];
674
+			//merge in valid shortcodes for the field.
675
+			$shortcodes = isset($m_shortcodes[$field]) ? $m_shortcodes[$field] : $valid_shortcodes;
676
+			if (isset($templates[$field][$context])) {
677
+				//prefix field.
678
+				$column_name = 'MSG_' . $field;
679
+				try {
680
+					$content = $this->_shortcode_parser->parse_message_template(
681
+						$templates[$field][$context],
682
+						$recipient,
683
+						$shortcodes,
684
+						$this->_current_message_type,
685
+						$this->_current_messenger,
686
+						$message
687
+					);
688
+					$message->set_field_or_extra_meta($column_name, $content);
689
+				} catch (EE_Error $e) {
690
+					$error_msg[] = sprintf(
691
+						esc_html__(
692
+							'There was a problem generating the content for the field %s: %s',
693
+							'event_espresso'
694
+						),
695
+						$field,
696
+						$e->getMessage()
697
+					);
698
+					$message->set_STS_ID(EEM_Message::status_failed);
699
+				}
700
+			}
701
+		}
702
+
703
+		if ($message->STS_ID() === EEM_Message::status_failed) {
704
+			$error_msg = esc_html__('There were problems generating this message:', 'event_espresso')
705
+						 . "\n"
706
+						 . implode("\n", $error_msg);
707
+			$message->set_error_message($error_msg);
708
+		} else {
709
+			$message->set_STS_ID(EEM_Message::status_idle);
710
+		}
711
+		return $message;
712
+	}
713
+
714
+
715
+	/**
716
+	 * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate
717
+	 * error message if either is missing.
718
+	 *
719
+	 * @return bool         true means there were no errors, false means there were errors.
720
+	 */
721
+	protected function _verify()
722
+	{
723
+		//reset error message to an empty array.
724
+		$this->_error_msg = array();
725
+		$valid            = true;
726
+		$valid            = $valid ? $this->_validate_messenger_and_message_type() : $valid;
727
+		$valid            = $valid ? $this->_validate_and_setup_data() : $valid;
728
+
729
+		//set the verified flag so we know everything has been validated.
730
+		$this->_verified = $valid;
731
+
732
+		return $valid;
733
+	}
734
+
735
+
736
+	/**
737
+	 * This accepts an array and validates that it is an array indexed by context with each value being an array of
738
+	 * EE_Messages_Addressee objects.
739
+	 *
740
+	 * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[]
741
+	 * @return bool
742
+	 */
743
+	protected function _valid_addressees($addressees)
744
+	{
745
+		if (! $addressees || ! is_array($addressees)) {
746
+			return false;
747
+		}
748
+
749
+		foreach ($addressees as $addressee_array) {
750
+			foreach ($addressee_array as $addressee) {
751
+				if (! $addressee instanceof EE_Messages_Addressee) {
752
+					return false;
753
+				}
754
+			}
755
+		}
756
+		return true;
757
+	}
758
+
759
+
760
+	/**
761
+	 * This validates the messenger, message type, and presences of generation data for the current EE_Message in the
762
+	 * queue. This process sets error messages if something is wrong.
763
+	 *
764
+	 * @return bool   true is if there are no errors.  false is if there is.
765
+	 */
766
+	protected function _validate_messenger_and_message_type()
767
+	{
768
+
769
+		//first are there any existing error messages?  If so then return.
770
+		if ($this->_error_msg) {
771
+			return false;
772
+		}
773
+		/** @type EE_Message $message */
774
+		$message = $this->_generation_queue->get_message_repository()->current();
775
+		try {
776
+			$this->_current_messenger = $message->valid_messenger(true)
777
+				? $message->messenger_object()
778
+				: null;
779
+		} catch (Exception $e) {
780
+			$this->_error_msg[] = $e->getMessage();
781
+		}
782
+		try {
783
+			$this->_current_message_type = $message->valid_message_type(true)
784
+				? $message->message_type_object()
785
+				: null;
786
+		} catch (Exception $e) {
787
+			$this->_error_msg[] = $e->getMessage();
788
+		}
789
+
790
+		/**
791
+		 * Check if there is any generation data, but only if this is not for a preview.
792
+		 */
793
+		if (! $this->_generation_queue->get_message_repository()->get_generation_data()
794
+			&& (
795
+				! $this->_generation_queue->get_message_repository()->is_preview()
796
+				&& $this->_generation_queue->get_message_repository()->get_data_handler()
797
+				   !== 'EE_Messages_Preview_incoming_data'
798
+			)
799
+		) {
800
+			$this->_error_msg[] = esc_html__(
801
+				'There is no generation data for this message. Unable to generate.',
802
+				'event_espresso'
803
+			);
804
+		}
805
+
806
+		return empty($this->_error_msg);
807
+	}
808
+
809
+
810
+	/**
811
+	 * This method retrieves the expected data handler for the message type and validates the generation data for that
812
+	 * data handler.
813
+	 *
814
+	 * @return bool true means there are no errors.  false means there were errors (and handler did not get setup).
815
+	 */
816
+	protected function _validate_and_setup_data()
817
+	{
818
+
819
+		//First, are there any existing error messages?  If so, return because if there were errors elsewhere this can't
820
+		//be used anyways.
821
+		if ($this->_error_msg) {
822
+			return false;
823
+		}
824
+
825
+		$generation_data = $this->_generation_queue->get_message_repository()->get_generation_data();
826
+
827
+		/** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually */
828
+		$data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
829
+			? $this->_generation_queue->get_message_repository()->get_data_handler()
830
+			: 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
831
+
832
+		//If this EE_Message is for a preview, then let's switch out to the preview data handler.
833
+		if ($this->_generation_queue->get_message_repository()->is_preview()) {
834
+			$data_handler_class_name = 'EE_Messages_Preview_incoming_data';
835
+		}
836
+
837
+		//First get the class name for the data handler (and also verifies it exists.
838
+		if (! class_exists($data_handler_class_name)) {
839
+			$this->_error_msg[] = sprintf(
840
+				esc_html__(
841
+					'The included data handler class name does not match any valid, accessible, "%1$s" classes.  Looking for %2$s.',
842
+					'event_espresso'
843
+				),
844
+				'EE_Messages_incoming_data',
845
+				$data_handler_class_name
846
+			);
847
+			return false;
848
+		}
849
+
850
+		//convert generation_data for data_handler_instantiation.
851
+		$generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data);
852
+
853
+		//note, this may set error messages as well.
854
+		$this->_set_data_handler($generation_data, $data_handler_class_name);
855
+
856
+		return empty($this->_error_msg);
857
+	}
858
+
859
+
860
+	/**
861
+	 * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and
862
+	 * adds it to the _data repository.
863
+	 *
864
+	 * @param mixed  $generating_data           This is data expected by the instantiated data handler.
865
+	 * @param string $data_handler_class_name   This is the reference string indicating what data handler is being
866
+	 *                                          instantiated.
867
+	 * @return void .
868
+	 * @throws EE_Error
869
+	 * @throws ReflectionException
870
+	 */
871
+	protected function _set_data_handler($generating_data, $data_handler_class_name)
872
+	{
873
+		//valid classname for the data handler.  Now let's setup the key for the data handler repository to see if there
874
+		//is already a ready data handler in the repository.
875
+		$this->_current_data_handler = $this->_data_handler_collection->get_by_key(
876
+			$this->_data_handler_collection->get_key(
877
+				$data_handler_class_name,
878
+				$generating_data
879
+			)
880
+		);
881
+		if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
882
+			//no saved data_handler in the repo so let's set one up and add it to the repo.
883
+			try {
884
+				$this->_current_data_handler = new $data_handler_class_name($generating_data);
885
+				$this->_data_handler_collection->add($this->_current_data_handler, $generating_data);
886
+			} catch (EE_Error $e) {
887
+				$this->_error_msg[] = $e->get_error();
888
+			}
889
+		}
890
+	}
891
+
892
+
893
+	/**
894
+	 * The queued EE_Message for generation does not save the data used for generation as objects
895
+	 * because serialization of those objects could be problematic if the data is saved to the db.
896
+	 * So this method calls the static method on the associated data_handler for the given message_type
897
+	 * and that preps the data for later instantiation when generating.
898
+	 *
899
+	 * @param EE_Message_To_Generate $message_to_generate
900
+	 * @param bool                   $preview Indicate whether this is being used for a preview or not.
901
+	 * @return mixed Prepped data for persisting to the queue.  false is returned if unable to prep data.
902
+	 */
903
+	protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview)
904
+	{
905
+		/** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
906
+		$data_handler = $message_to_generate->get_data_handler_class_name($preview);
907
+		if (! $message_to_generate->valid()) {
908
+			return false; //unable to get the data because the info in the EE_Message_To_Generate class is invalid.
909
+		}
910
+		return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
911
+	}
912
+
913
+
914
+	/**
915
+	 * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue.
916
+	 *
917
+	 * @param EE_Message_To_Generate $message_to_generate
918
+	 * @param bool                   $test_send Whether this is just a test send or not.  Typically used for previews.
919
+	 */
920
+	public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false)
921
+	{
922
+		//prep data
923
+		$data = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview());
924
+
925
+		$message = $message_to_generate->get_EE_Message();
926
+
927
+		//is there a GRP_ID in the request?
928
+		if ($GRP_ID = EE_Registry::instance()->REQ->get('GRP_ID')) {
929
+			$message->set_GRP_ID($GRP_ID);
930
+		}
931
+
932
+		if ($data === false) {
933
+			$message->set_STS_ID(EEM_Message::status_failed);
934
+			$message->set_error_message(
935
+				esc_html__(
936
+					'Unable to prepare data for persistence to the database.',
937
+					'event_espresso'
938
+				)
939
+			);
940
+		} else {
941
+			//make sure that the data handler is cached on the message as well
942
+			$data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name();
943
+		}
944
+
945
+		$this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send);
946
+	}
947 947
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -254,7 +254,7 @@  discard block
 block discarded – undo
254 254
     {
255 255
         //double check verification has run and that everything is ready to work with (saves us having to validate
256 256
         // everything again).
257
-        if (! $this->_verified) {
257
+        if ( ! $this->_verified) {
258 258
             return false; //get out because we don't have a valid setup to work with.
259 259
         }
260 260
 
@@ -271,7 +271,7 @@  discard block
 block discarded – undo
271 271
 
272 272
 
273 273
         //if no addressees then get out because there is nothing to generation (possible bad data).
274
-        if (! $this->_valid_addressees($addressees)) {
274
+        if ( ! $this->_valid_addressees($addressees)) {
275 275
             do_action(
276 276
                 'AHEE__EE_Messages_Generator___generate__invalid_addressees',
277 277
                 $this->_generation_queue->get_message_repository()->current(),
@@ -293,7 +293,7 @@  discard block
 block discarded – undo
293 293
         $message_template_group = $this->_get_message_template_group();
294 294
 
295 295
         //in the unlikely event there is no EE_Message_Template_Group available, get out!
296
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
296
+        if ( ! $message_template_group instanceof EE_Message_Template_Group) {
297 297
             $this->_error_msg[] = esc_html__(
298 298
                 'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
299 299
                 'event_espresso'
@@ -395,7 +395,7 @@  discard block
 block discarded – undo
395 395
             //attempt to retrieve from repo first
396 396
             $message_template_group = $this->_template_collection->get_by_ID($GRP_ID);
397 397
             if ($message_template_group instanceof EE_Message_Template_Group) {
398
-                return $message_template_group;  //got it!
398
+                return $message_template_group; //got it!
399 399
             }
400 400
 
401 401
             //nope don't have it yet.  Get from DB then add to repo if its not here, then that means the current GRP_ID
@@ -491,7 +491,7 @@  discard block
 block discarded – undo
491 491
         );
492 492
 
493 493
         //if we don't have a group lets hit the db.
494
-        if (! $global_message_template_group instanceof EE_Message_Template_Group) {
494
+        if ( ! $global_message_template_group instanceof EE_Message_Template_Group) {
495 495
             $global_message_template_group = EEM_Message_Template_Group::instance()->get_one(
496 496
                 array(
497 497
                     array(
@@ -548,7 +548,7 @@  discard block
 block discarded – undo
548 548
         $context_templates = $message_template_group->context_templates();
549 549
         foreach ($context_templates as $context => $template_fields) {
550 550
             foreach ($template_fields as $template_field => $template_obj) {
551
-                if (! $template_obj instanceof EE_Message_Template) {
551
+                if ( ! $template_obj instanceof EE_Message_Template) {
552 552
                     continue;
553 553
                 }
554 554
                 $templates[$template_field][$context] = $template_obj->get('MTP_content');
@@ -576,7 +576,7 @@  discard block
 block discarded – undo
576 576
     {
577 577
 
578 578
         //if templates are empty then get out because we can't generate anything.
579
-        if (! $templates) {
579
+        if ( ! $templates) {
580 580
             $this->_error_msg[] = esc_html__(
581 581
                 'Unable to assemble messages because there are no templates retrieved for generating the messages with',
582 582
                 'event_espresso'
@@ -675,7 +675,7 @@  discard block
 block discarded – undo
675 675
             $shortcodes = isset($m_shortcodes[$field]) ? $m_shortcodes[$field] : $valid_shortcodes;
676 676
             if (isset($templates[$field][$context])) {
677 677
                 //prefix field.
678
-                $column_name = 'MSG_' . $field;
678
+                $column_name = 'MSG_'.$field;
679 679
                 try {
680 680
                     $content = $this->_shortcode_parser->parse_message_template(
681 681
                         $templates[$field][$context],
@@ -742,13 +742,13 @@  discard block
 block discarded – undo
742 742
      */
743 743
     protected function _valid_addressees($addressees)
744 744
     {
745
-        if (! $addressees || ! is_array($addressees)) {
745
+        if ( ! $addressees || ! is_array($addressees)) {
746 746
             return false;
747 747
         }
748 748
 
749 749
         foreach ($addressees as $addressee_array) {
750 750
             foreach ($addressee_array as $addressee) {
751
-                if (! $addressee instanceof EE_Messages_Addressee) {
751
+                if ( ! $addressee instanceof EE_Messages_Addressee) {
752 752
                     return false;
753 753
                 }
754 754
             }
@@ -790,7 +790,7 @@  discard block
 block discarded – undo
790 790
         /**
791 791
          * Check if there is any generation data, but only if this is not for a preview.
792 792
          */
793
-        if (! $this->_generation_queue->get_message_repository()->get_generation_data()
793
+        if ( ! $this->_generation_queue->get_message_repository()->get_generation_data()
794 794
             && (
795 795
                 ! $this->_generation_queue->get_message_repository()->is_preview()
796 796
                 && $this->_generation_queue->get_message_repository()->get_data_handler()
@@ -827,7 +827,7 @@  discard block
 block discarded – undo
827 827
         /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually */
828 828
         $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
829 829
             ? $this->_generation_queue->get_message_repository()->get_data_handler()
830
-            : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
830
+            : 'EE_Messages_'.$this->_current_message_type->get_data_handler($generation_data).'_incoming_data';
831 831
 
832 832
         //If this EE_Message is for a preview, then let's switch out to the preview data handler.
833 833
         if ($this->_generation_queue->get_message_repository()->is_preview()) {
@@ -835,7 +835,7 @@  discard block
 block discarded – undo
835 835
         }
836 836
 
837 837
         //First get the class name for the data handler (and also verifies it exists.
838
-        if (! class_exists($data_handler_class_name)) {
838
+        if ( ! class_exists($data_handler_class_name)) {
839 839
             $this->_error_msg[] = sprintf(
840 840
                 esc_html__(
841 841
                     'The included data handler class name does not match any valid, accessible, "%1$s" classes.  Looking for %2$s.',
@@ -878,7 +878,7 @@  discard block
 block discarded – undo
878 878
                 $generating_data
879 879
             )
880 880
         );
881
-        if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
881
+        if ( ! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
882 882
             //no saved data_handler in the repo so let's set one up and add it to the repo.
883 883
             try {
884 884
                 $this->_current_data_handler = new $data_handler_class_name($generating_data);
@@ -904,7 +904,7 @@  discard block
 block discarded – undo
904 904
     {
905 905
         /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
906 906
         $data_handler = $message_to_generate->get_data_handler_class_name($preview);
907
-        if (! $message_to_generate->valid()) {
907
+        if ( ! $message_to_generate->valid()) {
908 908
             return false; //unable to get the data because the info in the EE_Message_To_Generate class is invalid.
909 909
         }
910 910
         return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
Please login to merge, or discard this patch.
acceptance_tests/tests/c-TestCustomMessageTemplateCept.php 1 patch
Indentation   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -18,14 +18,14 @@  discard block
 block discarded – undo
18 18
 $event_one_link = $event_two_link = $event_three_link = '';
19 19
 
20 20
 $I->wantTo(
21
-    'Test that when registrations for multiple events are completed, and those events share the same custom'
22
-    . 'template, that that custom template will be used.'
21
+	'Test that when registrations for multiple events are completed, and those events share the same custom'
22
+	. 'template, that that custom template will be used.'
23 23
 );
24 24
 
25 25
 //need the MER plugin active for this test (we'll deactivate it after).
26 26
 $I->ensurePluginActive(
27
-    'event-espresso-mer-multi-event-registration',
28
-    'activated'
27
+	'event-espresso-mer-multi-event-registration',
28
+	'activated'
29 29
 );
30 30
 
31 31
 $I->loginAsAdmin();
@@ -83,9 +83,9 @@  discard block
 block discarded – undo
83 83
 
84 84
 
85 85
 $test_registration_details = array(
86
-    'fname' => 'CTGuy',
87
-    'lname' => 'Dude',
88
-    'email' => '[email protected]'
86
+	'fname' => 'CTGuy',
87
+	'lname' => 'Dude',
88
+	'email' => '[email protected]'
89 89
 );
90 90
 
91 91
 $I->amGoingTo('Register for Event One and Event Two and verify Custom Template A was used.');
@@ -111,24 +111,24 @@  discard block
 block discarded – undo
111 111
 $I->loginAsAdmin();
112 112
 $I->amOnMessagesActivityListTablePage();
113 113
 $I->viewMessageInMessagesListTableFor(
114
-    'Registration Approved',
115
-    MessagesAdmin::MESSAGE_STATUS_SENT,
116
-    'Email',
117
-    'Registrant'
114
+	'Registration Approved',
115
+	MessagesAdmin::MESSAGE_STATUS_SENT,
116
+	'Email',
117
+	'Registrant'
118 118
 );
119 119
 $I->seeTextInViewMessageModal($custom_template_a_label);
120 120
 //closes view window
121 121
 $I->click('#espresso-admin-page-overlay-dv');
122 122
 $I->deleteMessageInMessagesListTableFor(
123
-    'Registration Approved',
124
-    MessagesAdmin::MESSAGE_STATUS_SENT,
125
-    'Email',
126
-    'Registrant'
123
+	'Registration Approved',
124
+	MessagesAdmin::MESSAGE_STATUS_SENT,
125
+	'Email',
126
+	'Registrant'
127 127
 );
128 128
 
129 129
 //verify admin context
130 130
 $I->viewMessageInMessagesListTableFor(
131
-    'Registration Approved'
131
+	'Registration Approved'
132 132
 );
133 133
 $I->seeTextInViewMessageModal($custom_template_a_label);
134 134
 $I->click('#espresso-admin-page-overlay-dv');
@@ -157,10 +157,10 @@  discard block
 block discarded – undo
157 157
 $I->loginAsAdmin();
158 158
 $I->amOnMessagesActivityListTablePage();
159 159
 $I->viewMessageInMessagesListTableFor(
160
-    'Registration Approved',
161
-    MessagesAdmin::MESSAGE_STATUS_SENT,
162
-    'Email',
163
-    'Registrant'
160
+	'Registration Approved',
161
+	MessagesAdmin::MESSAGE_STATUS_SENT,
162
+	'Email',
163
+	'Registrant'
164 164
 );
165 165
 $I->waitForElementVisible(MessagesAdmin::MESSAGES_LIST_TABLE_VIEW_MESSAGE_DIALOG_CONTAINER_SELECTOR);
166 166
 $I->dontSeeTextInViewMessageModal($custom_template_a_label);
@@ -168,15 +168,15 @@  discard block
 block discarded – undo
168 168
 //closes view window
169 169
 $I->click('#espresso-admin-page-overlay-dv');
170 170
 $I->deleteMessageInMessagesListTableFor(
171
-    'Registration Approved',
172
-    MessagesAdmin::MESSAGE_STATUS_SENT,
173
-    'Email',
174
-    'Registrant'
171
+	'Registration Approved',
172
+	MessagesAdmin::MESSAGE_STATUS_SENT,
173
+	'Email',
174
+	'Registrant'
175 175
 );
176 176
 
177 177
 //verify admin context
178 178
 $I->viewMessageInMessagesListTableFor(
179
-    'Registration Approved'
179
+	'Registration Approved'
180 180
 );
181 181
 $I->waitForElementVisible(MessagesAdmin::MESSAGES_LIST_TABLE_VIEW_MESSAGE_DIALOG_CONTAINER_SELECTOR);
182 182
 $I->dontSee($custom_template_a_label);
@@ -188,6 +188,6 @@  discard block
 block discarded – undo
188 188
 
189 189
 //deactivate MER plugin so its not active for future tests
190 190
 $I->ensurePluginDeactivated(
191
-    'event-espresso-mer-multi-event-registration',
192
-    'Plugin deactivated'
191
+	'event-espresso-mer-multi-event-registration',
192
+	'Plugin deactivated'
193 193
 );
194 194
\ No newline at end of file
Please login to merge, or discard this patch.
core/libraries/messages/EE_Message_Template_Group_Collection.lib.php 2 patches
Indentation   +100 added lines, -100 removed lines patch added patch discarded remove patch
@@ -14,115 +14,115 @@
 block discarded – undo
14 14
 {
15 15
 
16 16
 
17
-    /**
18
-     * EE_Message_Template_Group_Collection constructor.
19
-     */
20
-    public function __construct()
21
-    {
22
-        $this->interface = 'EE_Message_Template_Group';
23
-    }
17
+	/**
18
+	 * EE_Message_Template_Group_Collection constructor.
19
+	 */
20
+	public function __construct()
21
+	{
22
+		$this->interface = 'EE_Message_Template_Group';
23
+	}
24 24
 
25 25
 
26
-    /**
27
-     * Adds the Message Template Group object to the repository.
28
-     *
29
-     * @param           $message_template_group
30
-     * @param array|int $EVT_ID    Some templates are specific to EVT, so this is provided as a way of
31
-     *                         indexing the template by key.  If this template is shared among multiple events then
32
-     *                         include the events as an array.
33
-     * @return bool
34
-     */
35
-    public function add($message_template_group, $EVT_ID = array())
36
-    {
37
-        $EVT_ID = is_array($EVT_ID) ? $EVT_ID : (array) $EVT_ID;
38
-        if ($message_template_group instanceof $this->interface) {
39
-            $data['key'] = $this->getKey(
40
-                $message_template_group->messenger(),
41
-                $message_template_group->message_type(),
42
-                $EVT_ID
43
-            );
44
-            return parent::add($message_template_group, $data);
45
-        }
46
-        return false;
47
-    }
26
+	/**
27
+	 * Adds the Message Template Group object to the repository.
28
+	 *
29
+	 * @param           $message_template_group
30
+	 * @param array|int $EVT_ID    Some templates are specific to EVT, so this is provided as a way of
31
+	 *                         indexing the template by key.  If this template is shared among multiple events then
32
+	 *                         include the events as an array.
33
+	 * @return bool
34
+	 */
35
+	public function add($message_template_group, $EVT_ID = array())
36
+	{
37
+		$EVT_ID = is_array($EVT_ID) ? $EVT_ID : (array) $EVT_ID;
38
+		if ($message_template_group instanceof $this->interface) {
39
+			$data['key'] = $this->getKey(
40
+				$message_template_group->messenger(),
41
+				$message_template_group->message_type(),
42
+				$EVT_ID
43
+			);
44
+			return parent::add($message_template_group, $data);
45
+		}
46
+		return false;
47
+	}
48 48
 
49 49
 
50
-    /**
51
-     * This retrieves any EE_Message_Template_Group in the repo by its ID.
52
-     *
53
-     * @param $GRP_ID
54
-     * @return EE_Message_Template_Group | null
55
-     */
56
-    public function get_by_ID($GRP_ID)
57
-    {
58
-        $this->rewind();
59
-        while ($this->valid()) {
60
-            if ($this->current()->ID() === $GRP_ID) {
61
-                /** @var EE_Message_Template_Group $message_template_group */
62
-                $message_template_group = $this->current();
63
-                $this->rewind();
64
-                return $message_template_group;
65
-            }
66
-            $this->next();
67
-        }
68
-        return null;
69
-    }
50
+	/**
51
+	 * This retrieves any EE_Message_Template_Group in the repo by its ID.
52
+	 *
53
+	 * @param $GRP_ID
54
+	 * @return EE_Message_Template_Group | null
55
+	 */
56
+	public function get_by_ID($GRP_ID)
57
+	{
58
+		$this->rewind();
59
+		while ($this->valid()) {
60
+			if ($this->current()->ID() === $GRP_ID) {
61
+				/** @var EE_Message_Template_Group $message_template_group */
62
+				$message_template_group = $this->current();
63
+				$this->rewind();
64
+				return $message_template_group;
65
+			}
66
+			$this->next();
67
+		}
68
+		return null;
69
+	}
70 70
 
71 71
 
72
-    /**
73
-     * Generates a hash used to identify a given Message Template Group.
74
-     *
75
-     * @param string $messenger    The EE_messenger->name
76
-     * @param string $message_type The EE_message_type->name
77
-     * @param int    $EVT_ID       Optional.  If the template is for a specific EVT then that should be included.
78
-     * @deprecated 4.9.40.rc.017  Use getKey instead.
79
-     * @return string
80
-     */
81
-    public function get_key($messenger, $message_type, $EVT_ID = 0)
82
-    {
83
-        $EVT_ID = (array) $EVT_ID;
84
-        return $this->getKey($messenger, $message_type, $EVT_ID);
85
-    }
72
+	/**
73
+	 * Generates a hash used to identify a given Message Template Group.
74
+	 *
75
+	 * @param string $messenger    The EE_messenger->name
76
+	 * @param string $message_type The EE_message_type->name
77
+	 * @param int    $EVT_ID       Optional.  If the template is for a specific EVT then that should be included.
78
+	 * @deprecated 4.9.40.rc.017  Use getKey instead.
79
+	 * @return string
80
+	 */
81
+	public function get_key($messenger, $message_type, $EVT_ID = 0)
82
+	{
83
+		$EVT_ID = (array) $EVT_ID;
84
+		return $this->getKey($messenger, $message_type, $EVT_ID);
85
+	}
86 86
 
87 87
 
88
-    /**
89
-     * Generates a hash used to identify a given Message Template Group
90
-     * @param string    $messenger      The EE_messenger->name
91
-     * @param string    $message_type   The EE_message_type->name
92
-     * @param array     $EVT_ID         Optional.  If the template is for a specific EVT_ID (or events) then that should
93
-     *                                  be included.
94
-     * @since 4.9.40.rc.017
95
-     * @return string
96
-     */
97
-    public function getKey($messenger, $message_type, array $EVT_ID = array())
98
-    {
99
-        sort($EVT_ID);
100
-        $EVT_ID = implode(',', array_unique($EVT_ID));
101
-        return md5($messenger . $message_type . $EVT_ID);
102
-    }
88
+	/**
89
+	 * Generates a hash used to identify a given Message Template Group
90
+	 * @param string    $messenger      The EE_messenger->name
91
+	 * @param string    $message_type   The EE_message_type->name
92
+	 * @param array     $EVT_ID         Optional.  If the template is for a specific EVT_ID (or events) then that should
93
+	 *                                  be included.
94
+	 * @since 4.9.40.rc.017
95
+	 * @return string
96
+	 */
97
+	public function getKey($messenger, $message_type, array $EVT_ID = array())
98
+	{
99
+		sort($EVT_ID);
100
+		$EVT_ID = implode(',', array_unique($EVT_ID));
101
+		return md5($messenger . $message_type . $EVT_ID);
102
+	}
103 103
 
104 104
 
105
-    /**
106
-     * This returns a saved EE_Message_Template_Group object if there is one in the repository indexed by a key matching
107
-     * the given string.
108
-     *
109
-     * @param string $key @see EE_Message_Template_Group::get_key() to setup a key formatted for searching.
110
-     * @return null|EE_Message_Template_Group
111
-     */
112
-    public function get_by_key($key)
113
-    {
114
-        $this->rewind();
115
-        while ($this->valid()) {
116
-            $data = $this->getInfo();
117
-            if (isset($data['key']) && $data['key'] === $key) {
118
-                /** @var EE_Message_Template_Group $message_template_group */
119
-                $message_template_group = $this->current();
120
-                $this->rewind();
121
-                return $message_template_group;
122
-            }
123
-            $this->next();
124
-        }
125
-        return null;
126
-    }
105
+	/**
106
+	 * This returns a saved EE_Message_Template_Group object if there is one in the repository indexed by a key matching
107
+	 * the given string.
108
+	 *
109
+	 * @param string $key @see EE_Message_Template_Group::get_key() to setup a key formatted for searching.
110
+	 * @return null|EE_Message_Template_Group
111
+	 */
112
+	public function get_by_key($key)
113
+	{
114
+		$this->rewind();
115
+		while ($this->valid()) {
116
+			$data = $this->getInfo();
117
+			if (isset($data['key']) && $data['key'] === $key) {
118
+				/** @var EE_Message_Template_Group $message_template_group */
119
+				$message_template_group = $this->current();
120
+				$this->rewind();
121
+				return $message_template_group;
122
+			}
123
+			$this->next();
124
+		}
125
+		return null;
126
+	}
127 127
 
128 128
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -98,7 +98,7 @@
 block discarded – undo
98 98
     {
99 99
         sort($EVT_ID);
100 100
         $EVT_ID = implode(',', array_unique($EVT_ID));
101
-        return md5($messenger . $message_type . $EVT_ID);
101
+        return md5($messenger.$message_type.$EVT_ID);
102 102
     }
103 103
 
104 104
 
Please login to merge, or discard this patch.
acceptance_tests/tests/b-TestRegistrationSummaryCept.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -14,8 +14,8 @@  discard block
 block discarded – undo
14 14
 
15 15
 //need the MER plugin active for this test (we'll deactivate it after).
16 16
 $I->ensurePluginActive(
17
-    'event-espresso-mer-multi-event-registration',
18
-    'activated'
17
+	'event-espresso-mer-multi-event-registration',
18
+	'activated'
19 19
 );
20 20
 
21 21
 //k now we need to make sure the registration multi-status message type is active because it isn't by default
@@ -76,38 +76,38 @@  discard block
 block discarded – undo
76 76
 $I->loginAsAdmin();
77 77
 $I->amOnMessagesActivityListTablePage();
78 78
 $I->see(
79
-    '[email protected]',
80
-    MessagesAdmin::messagesActivityListTableCellSelectorFor(
81
-        'to',
82
-        'Registration Multi-status Summary',
83
-        MessagesAdmin::MESSAGE_STATUS_SENT,
84
-        '',
85
-        'Primary Registrant'
86
-    )
79
+	'[email protected]',
80
+	MessagesAdmin::messagesActivityListTableCellSelectorFor(
81
+		'to',
82
+		'Registration Multi-status Summary',
83
+		MessagesAdmin::MESSAGE_STATUS_SENT,
84
+		'',
85
+		'Primary Registrant'
86
+	)
87 87
 );
88 88
 $I->see(
89
-    '[email protected]',
90
-    MessagesAdmin::messagesActivityListTableCellSelectorFor(
91
-        'to',
92
-        'Registration Multi-status Summary',
93
-        MessagesAdmin::MESSAGE_STATUS_SENT
94
-    )
89
+	'[email protected]',
90
+	MessagesAdmin::messagesActivityListTableCellSelectorFor(
91
+		'to',
92
+		'Registration Multi-status Summary',
93
+		MessagesAdmin::MESSAGE_STATUS_SENT
94
+	)
95 95
 );
96 96
 //verify count
97 97
 $I->verifyMatchingCountofTextInMessageActivityListTableFor(
98
-    1,
99
-    '[email protected]',
100
-    'to',
101
-    'Registration Multi-status Summary',
102
-    MessagesAdmin::MESSAGE_STATUS_SENT,
103
-    'Email',
104
-    'Primary Registrant'
98
+	1,
99
+	'[email protected]',
100
+	'to',
101
+	'Registration Multi-status Summary',
102
+	MessagesAdmin::MESSAGE_STATUS_SENT,
103
+	'Email',
104
+	'Primary Registrant'
105 105
 );
106 106
 $I->verifyMatchingCountofTextInMessageActivityListTableFor(
107
-    1,
108
-    '[email protected]',
109
-    'to',
110
-    'Registration Multi-status Summary'
107
+	1,
108
+	'[email protected]',
109
+	'to',
110
+	'Registration Multi-status Summary'
111 111
 );
112 112
 
113 113
 //okay now let's do some registrations for just the first event and verify that registration multi-status summary is NOT
@@ -137,25 +137,25 @@  discard block
 block discarded – undo
137 137
 $I->loginAsAdmin();
138 138
 $I->amOnMessagesActivityListTablePage();
139 139
 $I->dontSee(
140
-    '[email protected]',
141
-    MessagesAdmin::messagesActivityListTableCellSelectorFor(
142
-        'to',
143
-        'Registration Multi-status Summary',
144
-        MessagesAdmin::MESSAGE_STATUS_SENT,
145
-        '',
146
-        'Primary Registrant'
147
-    )
140
+	'[email protected]',
141
+	MessagesAdmin::messagesActivityListTableCellSelectorFor(
142
+		'to',
143
+		'Registration Multi-status Summary',
144
+		MessagesAdmin::MESSAGE_STATUS_SENT,
145
+		'',
146
+		'Primary Registrant'
147
+	)
148 148
 );
149 149
 //there should still only be one admin multi-status summary thing.
150 150
 $I->verifyMatchingCountofTextInMessageActivityListTableFor(
151
-    1,
152
-    '[email protected]',
153
-    'to',
154
-    'Registration Multi-status Summary'
151
+	1,
152
+	'[email protected]',
153
+	'to',
154
+	'Registration Multi-status Summary'
155 155
 );
156 156
 
157 157
 //deactivate MER plugin so its not active for future tests
158 158
 $I->ensurePluginDeactivated(
159
-    'event-espresso-mer-multi-event-registration',
160
-    'Plugin deactivated'
159
+	'event-espresso-mer-multi-event-registration',
160
+	'Plugin deactivated'
161 161
 );
162 162
\ No newline at end of file
Please login to merge, or discard this patch.
modules/messages/EED_Messages.module.php 1 patch
Indentation   +1071 added lines, -1071 removed lines patch added patch discarded remove patch
@@ -13,1086 +13,1086 @@
 block discarded – undo
13 13
 class EED_Messages extends EED_Module
14 14
 {
15 15
 
16
-    /**
17
-     * This holds the EE_messages controller
18
-     *
19
-     * @deprecated 4.9.0
20
-     * @var EE_messages $_EEMSG
21
-     */
22
-    protected static $_EEMSG;
23
-
24
-    /**
25
-     * @type EE_Message_Resource_Manager $_message_resource_manager
26
-     */
27
-    protected static $_message_resource_manager;
28
-
29
-    /**
30
-     * This holds the EE_Messages_Processor business class.
31
-     *
32
-     * @type EE_Messages_Processor
33
-     */
34
-    protected static $_MSG_PROCESSOR;
35
-
36
-    /**
37
-     * holds all the paths for various messages components.
38
-     * Utilized by autoloader registry
39
-     *
40
-     * @var array
41
-     */
42
-    protected static $_MSG_PATHS;
43
-
44
-
45
-    /**
46
-     * This will hold an array of messages template packs that are registered in the messages system.
47
-     * Format is:
48
-     * array(
49
-     *    'template_pack_dbref' => EE_Messages_Template_Pack (instance)
50
-     * )
51
-     *
52
-     * @var EE_Messages_Template_Pack[]
53
-     */
54
-    protected static $_TMP_PACKS = array();
55
-
56
-
57
-    /**
58
-     * @return EED_Messages
59
-     */
60
-    public static function instance()
61
-    {
62
-        return parent::get_instance(__CLASS__);
63
-    }
64
-
65
-
66
-    /**
67
-     *  set_hooks - for hooking into EE Core, other modules, etc
68
-     *
69
-     * @since 4.5.0
70
-     * @return    void
71
-     */
72
-    public static function set_hooks()
73
-    {
74
-        //actions
75
-        add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', array('EED_Messages', 'payment'), 10, 2);
76
-        add_action('AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
77
-            array('EED_Messages', 'maybe_registration'), 10, 2);
78
-        //filters
79
-        add_filter('FHEE__EE_Registration__receipt_url__receipt_url',
80
-            array('EED_Messages', 'registration_message_trigger_url'), 10, 4);
81
-        add_filter('FHEE__EE_Registration__invoice_url__invoice_url',
82
-            array('EED_Messages', 'registration_message_trigger_url'), 10, 4);
83
-        //register routes
84
-        self::_register_routes();
85
-    }
86
-
87
-    /**
88
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
89
-     *
90
-     * @access    public
91
-     * @return    void
92
-     */
93
-    public static function set_hooks_admin()
94
-    {
95
-        //actions
96
-        add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', array('EED_Messages', 'payment'), 10, 2);
97
-        add_action('AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
98
-            array('EED_Messages', 'payment_reminder'), 10);
99
-        add_action('AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
100
-            array('EED_Messages', 'maybe_registration'), 10, 3);
101
-        add_action('AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
102
-            array('EED_Messages', 'send_newsletter_message'), 10, 2);
103
-        add_action('AHEE__EES_Espresso_Cancelled__process_shortcode__transaction',
104
-            array('EED_Messages', 'cancelled_registration'), 10);
105
-        add_action('AHEE__EE_Admin_Page___process_admin_payment_notification',
106
-            array('EED_Messages', 'process_admin_payment'), 10, 1);
107
-        //filters
108
-        add_filter('FHEE__EE_Admin_Page___process_resend_registration__success',
109
-            array('EED_Messages', 'process_resend'), 10, 2);
110
-        add_filter('FHEE__EE_Registration__receipt_url__receipt_url',
111
-            array('EED_Messages', 'registration_message_trigger_url'), 10, 4);
112
-        add_filter('FHEE__EE_Registration__invoice_url__invoice_url',
113
-            array('EED_Messages', 'registration_message_trigger_url'), 10, 4);
114
-    }
115
-
116
-
117
-    /**
118
-     * All the message triggers done by route go in here.
119
-     *
120
-     * @since 4.5.0
121
-     * @return void
122
-     */
123
-    protected static function _register_routes()
124
-    {
125
-        EE_Config::register_route('msg_url_trigger', 'Messages', 'run');
126
-        EE_Config::register_route('msg_cron_trigger', 'Messages', 'execute_batch_request');
127
-        EE_Config::register_route('msg_browser_trigger', 'Messages', 'browser_trigger');
128
-        EE_Config::register_route('msg_browser_error_trigger', 'Messages', 'browser_error_trigger');
129
-        do_action('AHEE__EED_Messages___register_routes');
130
-    }
131
-
132
-
133
-    /**
134
-     * This is called when a browser display trigger is executed.
135
-     * The browser display trigger is typically used when a already generated message is displayed directly in the
136
-     * browser.
137
-     *
138
-     * @since 4.9.0
139
-     * @param WP $WP
140
-     */
141
-    public function browser_trigger($WP)
142
-    {
143
-        //ensure controller is loaded
144
-        self::_load_controller();
145
-        $token = EE_Registry::instance()->REQ->get('token');
146
-        try {
147
-            $mtg = new EE_Message_Generated_From_Token($token, 'html', self::$_message_resource_manager);
148
-            self::$_MSG_PROCESSOR->generate_and_send_now($mtg);
149
-        } catch (EE_Error $e) {
150
-            $error_msg = __('Please note that a system message failed to send due to a technical issue.',
151
-                'event_espresso');
152
-            // add specific message for developers if WP_DEBUG in on
153
-            $error_msg .= '||' . $e->getMessage();
154
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
155
-        }
156
-    }
157
-
158
-
159
-    /**
160
-     * This is called when a browser error trigger is executed.
161
-     * When triggered this will grab the EE_Message matching the token in the request and use that to get the error
162
-     * message and display it.
163
-     *
164
-     * @since 4.9.0
165
-     * @param $WP
166
-     */
167
-    public function browser_error_trigger($WP)
168
-    {
169
-        $token = EE_Registry::instance()->REQ->get('token');
170
-        if ($token) {
171
-            $message = EEM_Message::instance()->get_one_by_token($token);
172
-            if ($message instanceof EE_Message) {
173
-                header('HTTP/1.1 200 OK');
174
-                $error_msg = nl2br($message->error_message());
175
-                ?>
16
+	/**
17
+	 * This holds the EE_messages controller
18
+	 *
19
+	 * @deprecated 4.9.0
20
+	 * @var EE_messages $_EEMSG
21
+	 */
22
+	protected static $_EEMSG;
23
+
24
+	/**
25
+	 * @type EE_Message_Resource_Manager $_message_resource_manager
26
+	 */
27
+	protected static $_message_resource_manager;
28
+
29
+	/**
30
+	 * This holds the EE_Messages_Processor business class.
31
+	 *
32
+	 * @type EE_Messages_Processor
33
+	 */
34
+	protected static $_MSG_PROCESSOR;
35
+
36
+	/**
37
+	 * holds all the paths for various messages components.
38
+	 * Utilized by autoloader registry
39
+	 *
40
+	 * @var array
41
+	 */
42
+	protected static $_MSG_PATHS;
43
+
44
+
45
+	/**
46
+	 * This will hold an array of messages template packs that are registered in the messages system.
47
+	 * Format is:
48
+	 * array(
49
+	 *    'template_pack_dbref' => EE_Messages_Template_Pack (instance)
50
+	 * )
51
+	 *
52
+	 * @var EE_Messages_Template_Pack[]
53
+	 */
54
+	protected static $_TMP_PACKS = array();
55
+
56
+
57
+	/**
58
+	 * @return EED_Messages
59
+	 */
60
+	public static function instance()
61
+	{
62
+		return parent::get_instance(__CLASS__);
63
+	}
64
+
65
+
66
+	/**
67
+	 *  set_hooks - for hooking into EE Core, other modules, etc
68
+	 *
69
+	 * @since 4.5.0
70
+	 * @return    void
71
+	 */
72
+	public static function set_hooks()
73
+	{
74
+		//actions
75
+		add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', array('EED_Messages', 'payment'), 10, 2);
76
+		add_action('AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
77
+			array('EED_Messages', 'maybe_registration'), 10, 2);
78
+		//filters
79
+		add_filter('FHEE__EE_Registration__receipt_url__receipt_url',
80
+			array('EED_Messages', 'registration_message_trigger_url'), 10, 4);
81
+		add_filter('FHEE__EE_Registration__invoice_url__invoice_url',
82
+			array('EED_Messages', 'registration_message_trigger_url'), 10, 4);
83
+		//register routes
84
+		self::_register_routes();
85
+	}
86
+
87
+	/**
88
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
89
+	 *
90
+	 * @access    public
91
+	 * @return    void
92
+	 */
93
+	public static function set_hooks_admin()
94
+	{
95
+		//actions
96
+		add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', array('EED_Messages', 'payment'), 10, 2);
97
+		add_action('AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
98
+			array('EED_Messages', 'payment_reminder'), 10);
99
+		add_action('AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
100
+			array('EED_Messages', 'maybe_registration'), 10, 3);
101
+		add_action('AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
102
+			array('EED_Messages', 'send_newsletter_message'), 10, 2);
103
+		add_action('AHEE__EES_Espresso_Cancelled__process_shortcode__transaction',
104
+			array('EED_Messages', 'cancelled_registration'), 10);
105
+		add_action('AHEE__EE_Admin_Page___process_admin_payment_notification',
106
+			array('EED_Messages', 'process_admin_payment'), 10, 1);
107
+		//filters
108
+		add_filter('FHEE__EE_Admin_Page___process_resend_registration__success',
109
+			array('EED_Messages', 'process_resend'), 10, 2);
110
+		add_filter('FHEE__EE_Registration__receipt_url__receipt_url',
111
+			array('EED_Messages', 'registration_message_trigger_url'), 10, 4);
112
+		add_filter('FHEE__EE_Registration__invoice_url__invoice_url',
113
+			array('EED_Messages', 'registration_message_trigger_url'), 10, 4);
114
+	}
115
+
116
+
117
+	/**
118
+	 * All the message triggers done by route go in here.
119
+	 *
120
+	 * @since 4.5.0
121
+	 * @return void
122
+	 */
123
+	protected static function _register_routes()
124
+	{
125
+		EE_Config::register_route('msg_url_trigger', 'Messages', 'run');
126
+		EE_Config::register_route('msg_cron_trigger', 'Messages', 'execute_batch_request');
127
+		EE_Config::register_route('msg_browser_trigger', 'Messages', 'browser_trigger');
128
+		EE_Config::register_route('msg_browser_error_trigger', 'Messages', 'browser_error_trigger');
129
+		do_action('AHEE__EED_Messages___register_routes');
130
+	}
131
+
132
+
133
+	/**
134
+	 * This is called when a browser display trigger is executed.
135
+	 * The browser display trigger is typically used when a already generated message is displayed directly in the
136
+	 * browser.
137
+	 *
138
+	 * @since 4.9.0
139
+	 * @param WP $WP
140
+	 */
141
+	public function browser_trigger($WP)
142
+	{
143
+		//ensure controller is loaded
144
+		self::_load_controller();
145
+		$token = EE_Registry::instance()->REQ->get('token');
146
+		try {
147
+			$mtg = new EE_Message_Generated_From_Token($token, 'html', self::$_message_resource_manager);
148
+			self::$_MSG_PROCESSOR->generate_and_send_now($mtg);
149
+		} catch (EE_Error $e) {
150
+			$error_msg = __('Please note that a system message failed to send due to a technical issue.',
151
+				'event_espresso');
152
+			// add specific message for developers if WP_DEBUG in on
153
+			$error_msg .= '||' . $e->getMessage();
154
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
155
+		}
156
+	}
157
+
158
+
159
+	/**
160
+	 * This is called when a browser error trigger is executed.
161
+	 * When triggered this will grab the EE_Message matching the token in the request and use that to get the error
162
+	 * message and display it.
163
+	 *
164
+	 * @since 4.9.0
165
+	 * @param $WP
166
+	 */
167
+	public function browser_error_trigger($WP)
168
+	{
169
+		$token = EE_Registry::instance()->REQ->get('token');
170
+		if ($token) {
171
+			$message = EEM_Message::instance()->get_one_by_token($token);
172
+			if ($message instanceof EE_Message) {
173
+				header('HTTP/1.1 200 OK');
174
+				$error_msg = nl2br($message->error_message());
175
+				?>
176 176
                 <!DOCTYPE html>
177 177
                 <html>
178 178
                 <head></head>
179 179
                 <body>
180 180
                 <?php echo empty($error_msg)
181
-                    ? esc_html__('Unfortunately, we were unable to capture the error message for this message.',
182
-                        'event_espresso')
183
-                    : wp_kses(
184
-                        $error_msg,
185
-                        array(
186
-                            'a'      => array(
187
-                                'href'  => array(),
188
-                                'title' => array(),
189
-                            ),
190
-                            'span'   => array(),
191
-                            'div'    => array(),
192
-                            'p'      => array(),
193
-                            'strong' => array(),
194
-                            'em'     => array(),
195
-                            'br'     => array(),
196
-                        )
197
-                    ); ?>
181
+					? esc_html__('Unfortunately, we were unable to capture the error message for this message.',
182
+						'event_espresso')
183
+					: wp_kses(
184
+						$error_msg,
185
+						array(
186
+							'a'      => array(
187
+								'href'  => array(),
188
+								'title' => array(),
189
+							),
190
+							'span'   => array(),
191
+							'div'    => array(),
192
+							'p'      => array(),
193
+							'strong' => array(),
194
+							'em'     => array(),
195
+							'br'     => array(),
196
+						)
197
+					); ?>
198 198
                 </body>
199 199
                 </html>
200 200
                 <?php
201
-                exit;
202
-            }
203
-        }
204
-        return;
205
-    }
206
-
207
-
208
-    /**
209
-     *  This runs when the msg_url_trigger route has initiated.
210
-     *
211
-     * @since 4.5.0
212
-     * @param WP $WP
213
-     * @throws EE_Error
214
-     * @return    void
215
-     */
216
-    public function run($WP)
217
-    {
218
-        //ensure controller is loaded
219
-        self::_load_controller();
220
-        // attempt to process message
221
-        try {
222
-            /** @type EE_Message_To_Generate_From_Request $message_to_generate */
223
-            $message_to_generate = EE_Registry::instance()->load_lib('Message_To_Generate_From_Request');
224
-            self::$_MSG_PROCESSOR->generate_and_send_now($message_to_generate);
225
-        } catch (EE_Error $e) {
226
-            $error_msg = __('Please note that a system message failed to send due to a technical issue.',
227
-                'event_espresso');
228
-            // add specific message for developers if WP_DEBUG in on
229
-            $error_msg .= '||' . $e->getMessage();
230
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
231
-        }
232
-    }
233
-
234
-
235
-    /**
236
-     * This is triggered by the 'msg_cron_trigger' route.
237
-     *
238
-     * @param WP $WP
239
-     */
240
-    public function execute_batch_request($WP)
241
-    {
242
-        $this->run_cron();
243
-        header('HTTP/1.1 200 OK');
244
-        exit();
245
-    }
246
-
247
-
248
-    /**
249
-     * This gets executed on wp_cron jobs or when a batch request is initiated on its own separate non regular wp
250
-     * request.
251
-     */
252
-    public function run_cron()
253
-    {
254
-        self::_load_controller();
255
-        //get required vars
256
-        $cron_type     = EE_Registry::instance()->REQ->get('type');
257
-        $transient_key = EE_Registry::instance()->REQ->get('key');
258
-
259
-        //now let's verify transient, if not valid exit immediately
260
-        if (! get_transient($transient_key)) {
261
-            /**
262
-             * trigger error so this gets in the error logs.  This is important because it happens on a non-user request.
263
-             */
264
-            trigger_error(esc_attr__('Invalid Request (Transient does not exist)', 'event_espresso'));
265
-        }
266
-
267
-        //if made it here, lets' delete the transient to keep the db clean
268
-        delete_transient($transient_key);
269
-
270
-        if (apply_filters('FHEE__EED_Messages__run_cron__use_wp_cron', true)) {
271
-
272
-            $method = 'batch_' . $cron_type . '_from_queue';
273
-            if (method_exists(self::$_MSG_PROCESSOR, $method)) {
274
-                self::$_MSG_PROCESSOR->$method();
275
-            } else {
276
-                //no matching task
277
-                /**
278
-                 * trigger error so this gets in the error logs.  This is important because it happens on a non user request.
279
-                 */
280
-                trigger_error(esc_attr(sprintf(__('There is no task corresponding to this route %s', 'event_espresso'),
281
-                    $cron_type)));
282
-            }
283
-        }
284
-
285
-        do_action('FHEE__EED_Messages__run_cron__end');
286
-    }
287
-
288
-
289
-    /**
290
-     * This is used to retrieve the template pack for the given name.
291
-     * Retrieved packs are cached on the static $_TMP_PACKS array.  If there is no class matching the given name then
292
-     * the default template pack is returned.
293
-     *
294
-     * @deprecated 4.9.0  @see EEH_MSG_Template::get_template_pack()
295
-     * @param string $template_pack_name This should correspond to the dbref of the template pack (which is also used
296
-     *                                   in generating the Pack class name).
297
-     * @return EE_Messages_Template_Pack
298
-     */
299
-    public static function get_template_pack($template_pack_name)
300
-    {
301
-        EE_Registry::instance()->load_helper('MSG_Template');
302
-        return EEH_MSG_Template::get_template_pack($template_pack_name);
303
-    }
304
-
305
-
306
-    /**
307
-     * Retrieves an array of all template packs.
308
-     * Array is in the format array( 'dbref' => EE_Messages_Template_Pack )
309
-     *
310
-     * @deprecated 4.9.0  @see EEH_MSG_Template_Pack::get_template_pack_collection
311
-     * @return EE_Messages_Template_Pack[]
312
-     */
313
-    public static function get_template_packs()
314
-    {
315
-        EE_Registry::instance()->load_helper('MSG_Template');
316
-
317
-        //for backward compat, let's make sure this returns in the same format as originally.
318
-        $template_pack_collection = EEH_MSG_Template::get_template_pack_collection();
319
-        $template_pack_collection->rewind();
320
-        $template_packs = array();
321
-        while ($template_pack_collection->valid()) {
322
-            $template_packs[$template_pack_collection->current()->dbref] = $template_pack_collection->current();
323
-            $template_pack_collection->next();
324
-        }
325
-        return $template_packs;
326
-    }
327
-
328
-
329
-    /**
330
-     * This simply makes sure the autoloaders are registered for the EE_messages system.
331
-     *
332
-     * @since 4.5.0
333
-     * @return void
334
-     */
335
-    public static function set_autoloaders()
336
-    {
337
-        if (empty(self::$_MSG_PATHS)) {
338
-            self::_set_messages_paths();
339
-            foreach (self::$_MSG_PATHS as $path) {
340
-                EEH_Autoloader::register_autoloaders_for_each_file_in_folder($path);
341
-            }
342
-            // add aliases
343
-            EEH_Autoloader::add_alias('EE_messages', 'EE_messages');
344
-            EEH_Autoloader::add_alias('EE_messenger', 'EE_messenger');
345
-        }
346
-    }
347
-
348
-
349
-    /**
350
-     * Take care of adding all the paths for the messages components to the $_MSG_PATHS property
351
-     * for use by the Messages Autoloaders
352
-     *
353
-     * @since 4.5.0
354
-     * @return void.
355
-     */
356
-    protected static function _set_messages_paths()
357
-    {
358
-        $dir_ref = array(
359
-            'messages/message_type',
360
-            'messages/messenger',
361
-            'messages/defaults',
362
-            'messages/defaults/email',
363
-            'messages/data_class',
364
-            'messages/validators',
365
-            'messages/validators/email',
366
-            'messages/validators/html',
367
-            'shortcodes',
368
-        );
369
-        $paths   = array();
370
-        foreach ($dir_ref as $index => $dir) {
371
-            $paths[$index] = EE_LIBRARIES . $dir;
372
-        }
373
-        self::$_MSG_PATHS = apply_filters('FHEE__EED_Messages___set_messages_paths___MSG_PATHS', $paths);
374
-    }
375
-
376
-
377
-    /**
378
-     * Takes care of loading dependencies
379
-     *
380
-     * @since 4.5.0
381
-     * @return void
382
-     */
383
-    protected static function _load_controller()
384
-    {
385
-        if (! self::$_MSG_PROCESSOR instanceof EE_Messages_Processor) {
386
-            EE_Registry::instance()->load_core('Request_Handler');
387
-            self::set_autoloaders();
388
-            self::$_EEMSG                    = EE_Registry::instance()->load_lib('messages');
389
-            self::$_MSG_PROCESSOR            = EE_Registry::instance()->load_lib('Messages_Processor');
390
-            self::$_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
391
-        }
392
-    }
393
-
394
-
395
-    /**
396
-     * @param EE_Transaction $transaction
397
-     */
398
-    public static function payment_reminder(EE_Transaction $transaction)
399
-    {
400
-        self::_load_controller();
401
-        $data = array($transaction, null);
402
-        self::$_MSG_PROCESSOR->generate_for_all_active_messengers('payment_reminder', $data);
403
-    }
404
-
405
-
406
-    /**
407
-     * Any messages triggers for after successful gateway payments should go in here.
408
-     *
409
-     * @param  EE_Transaction object
410
-     * @param  EE_Payment     object
411
-     * @return void
412
-     */
413
-    public static function payment(EE_Transaction $transaction, EE_Payment $payment)
414
-    {
415
-        self::_load_controller();
416
-        $data = array($transaction, $payment);
417
-        EE_Registry::instance()->load_helper('MSG_Template');
418
-        $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID());
419
-        //if payment amount is less than 0 then switch to payment_refund message type.
420
-        $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type;
421
-        self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data);
422
-    }
423
-
424
-
425
-    /**
426
-     * @param EE_Transaction $transaction
427
-     */
428
-    public static function cancelled_registration(EE_Transaction $transaction)
429
-    {
430
-        self::_load_controller();
431
-        $data = array($transaction, null);
432
-        self::$_MSG_PROCESSOR->generate_for_all_active_messengers('cancelled_registration', $data);
433
-    }
434
-
435
-
436
-    /**
437
-     * Trigger for Registration messages
438
-     * Note that what registration message type is sent depends on what the reg status is for the registrations on the
439
-     * incoming transaction.
440
-     *
441
-     * @param EE_Registration $registration
442
-     * @param array           $extra_details
443
-     * @return void
444
-     */
445
-    public static function maybe_registration(EE_Registration $registration, $extra_details = array())
446
-    {
447
-
448
-        if (! self::_verify_registration_notification_send($registration, $extra_details)) {
449
-            //no messages please
450
-            return;
451
-        }
452
-
453
-
454
-        //get all registrations so we make sure we send messages for the right status.
455
-        $all_registrations = $registration->transaction()->registrations();
456
-
457
-        //cached array of statuses so we only trigger messages once per status.
458
-        $statuses_sent = array();
459
-        self::_load_controller();
460
-        $mtgs = array();
461
-
462
-        //loop through registrations and trigger messages once per status.
463
-        foreach ($all_registrations as $reg) {
464
-
465
-            //already triggered?
466
-            if (in_array($reg->status_ID(), $statuses_sent)) {
467
-                continue;
468
-            }
469
-
470
-            $message_type    = EEH_MSG_Template::convert_reg_status_to_message_type($reg->status_ID());
471
-            $mtgs            = array_merge(
472
-                    $mtgs,
473
-                    self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers(
474
-                            $message_type,
475
-                            array($registration->transaction(), null, $reg->status_ID())
476
-                    )
477
-            );
478
-            $statuses_sent[] = $reg->status_ID();
479
-        }
480
-
481
-        if (count($statuses_sent) > 1) {
482
-            $mtgs = array_merge(
483
-                $mtgs,
484
-                self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers(
485
-                    'registration_summary',
486
-                    array($registration->transaction(), null)
487
-                )
488
-            );
489
-        }
490
-
491
-        //batch queue and initiate request
492
-        self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($mtgs);
493
-        self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority();
494
-    }
495
-
496
-
497
-    /**
498
-     * This is a helper method used to very whether a registration notification should be sent or
499
-     * not.  Prevents duplicate notifications going out for registration context notifications.
500
-     *
501
-     * @param EE_Registration $registration  [description]
502
-     * @param array           $extra_details [description]
503
-     * @return bool          true = send away, false = nope halt the presses.
504
-     */
505
-    protected static function _verify_registration_notification_send(
506
-        EE_Registration $registration,
507
-        $extra_details = array()
508
-    ) {
509
-        //self::log(
510
-        //	__CLASS__, __FUNCTION__, __LINE__,
511
-        //	$registration->transaction(),
512
-        //	array( '$extra_details' => $extra_details )
513
-        //);
514
-        // currently only using this to send messages for the primary registrant
515
-        if (! $registration->is_primary_registrant()) {
516
-            return false;
517
-        }
518
-        // first we check if we're in admin and not doing front ajax
519
-        if (is_admin() && ! EE_FRONT_AJAX) {
520
-            //make sure appropriate admin params are set for sending messages
521
-            if (empty($_REQUEST['txn_reg_status_change']['send_notifications']) || ! absint($_REQUEST['txn_reg_status_change']['send_notifications'])) {
522
-                //no messages sent please.
523
-                return false;
524
-            }
525
-        } else {
526
-            // frontend request (either regular or via AJAX)
527
-            // TXN is NOT finalized ?
528
-            if (! isset($extra_details['finalized']) || $extra_details['finalized'] === false) {
529
-                return false;
530
-            }
531
-            // return visit but nothing changed ???
532
-            if (
533
-                isset($extra_details['revisit'], $extra_details['status_updates']) &&
534
-                $extra_details['revisit'] && ! $extra_details['status_updates']
535
-            ) {
536
-                return false;
537
-            }
538
-            // NOT sending messages && reg status is something other than "Not-Approved"
539
-            if (
540
-                ! apply_filters('FHEE__EED_Messages___maybe_registration__deliver_notifications', false) &&
541
-                $registration->status_ID() !== EEM_Registration::status_id_not_approved
542
-            ) {
543
-                return false;
544
-            }
545
-        }
546
-        // release the kraken
547
-        return true;
548
-    }
549
-
550
-
551
-    /**
552
-     * Simply returns an array indexed by Registration Status ID and the related message_type name associated with that
553
-     * status id.
554
-     *
555
-     * @deprecated 4.9.0  Use EEH_MSG_Template::reg_status_to_message_type_array()
556
-     *                    or EEH_MSG_Template::convert_reg_status_to_message_type
557
-     * @param string $reg_status
558
-     * @return array
559
-     */
560
-    protected static function _get_reg_status_array($reg_status = '')
561
-    {
562
-        EE_Registry::instance()->load_helper('MSG_Template');
563
-        return EEH_MSG_Template::convert_reg_status_to_message_type($reg_status)
564
-            ? EEH_MSG_Template::convert_reg_status_to_message_type($reg_status)
565
-            : EEH_MSG_Template::reg_status_to_message_type_array();
566
-    }
567
-
568
-
569
-    /**
570
-     * Simply returns the payment message type for the given payment status.
571
-     *
572
-     * @deprecated 4.9.0 Use EEH_MSG_Template::payment_status_to_message_type_array
573
-     *                   or EEH_MSG_Template::convert_payment_status_to_message_type
574
-     * @param string $payment_status The payment status being matched.
575
-     * @return string|bool The payment message type slug matching the status or false if no match.
576
-     */
577
-    protected static function _get_payment_message_type($payment_status)
578
-    {
579
-        EE_Registry::instance()->load_helper('MSG_Template');
580
-        return EEH_MSG_Template::convert_payment_status_to_message_type($payment_status)
581
-            ? EEH_MSG_Template::convert_payment_status_to_message_type($payment_status)
582
-            : false;
583
-    }
584
-
585
-
586
-    /**
587
-     * Message triggers for a resending already sent message(s) (via EE_Message list table)
588
-     *
589
-     * @access public
590
-     * @param array $req_data This is the $_POST & $_GET data sent from EE_Admin Pages
591
-     * @return bool          success/fail
592
-     */
593
-    public static function process_resend($req_data)
594
-    {
595
-        self::_load_controller();
596
-
597
-        //if $msgID in this request then skip to the new resend_message
598
-        if (EE_Registry::instance()->REQ->get('MSG_ID')) {
599
-            return self::resend_message();
600
-        }
601
-
602
-        //make sure any incoming request data is set on the REQ so that it gets picked up later.
603
-        $req_data = (array)$req_data;
604
-        foreach ($req_data as $request_key => $request_value) {
605
-            EE_Registry::instance()->REQ->set($request_key, $request_value);
606
-        }
607
-
608
-        if (! $messages_to_send = self::$_MSG_PROCESSOR->setup_messages_to_generate_from_registration_ids_in_request()) {
609
-            return false;
610
-        }
611
-
612
-        try {
613
-            self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($messages_to_send);
614
-            self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority();
615
-        } catch (EE_Error $e) {
616
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
617
-            return false;
618
-        }
619
-        EE_Error::add_success(
620
-            __('Messages have been successfully queued for generation and sending.', 'event_espresso')
621
-        );
622
-        return true; //everything got queued.
623
-    }
624
-
625
-
626
-    /**
627
-     * Message triggers for a resending already sent message(s) (via EE_Message list table)
628
-     *
629
-     * @return bool
630
-     */
631
-    public static function resend_message()
632
-    {
633
-        self::_load_controller();
634
-
635
-        $msgID = EE_Registry::instance()->REQ->get('MSG_ID');
636
-        if (! $msgID) {
637
-            EE_Error::add_error(__('Something went wrong because there is no "MSG_ID" value in the request',
638
-                'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
639
-            return false;
640
-        }
641
-
642
-        self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send((array)$msgID);
643
-
644
-        //setup success message.
645
-        $count_ready_for_resend = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend);
646
-        EE_Error::add_success(sprintf(
647
-            _n(
648
-                'There was %d message queued for resending.',
649
-                'There were %d messages queued for resending.',
650
-                $count_ready_for_resend,
651
-                'event_espresso'
652
-            ),
653
-            $count_ready_for_resend
654
-        ));
655
-        return true;
656
-    }
657
-
658
-
659
-    /**
660
-     * Message triggers for manual payment applied by admin
661
-     *
662
-     * @param  EE_Payment $payment EE_payment object
663
-     * @return bool              success/fail
664
-     */
665
-    public static function process_admin_payment(EE_Payment $payment)
666
-    {
667
-        EE_Registry::instance()->load_helper('MSG_Template');
668
-        //we need to get the transaction object
669
-        $transaction = $payment->transaction();
670
-        if ($transaction instanceof EE_Transaction) {
671
-            $data         = array($transaction, $payment);
672
-            $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID());
673
-
674
-            //if payment amount is less than 0 then switch to payment_refund message type.
675
-            $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type;
676
-
677
-            //if payment_refund is selected, but the status is NOT accepted.  Then change message type to false so NO message notification goes out.
678
-            $message_type = $message_type == 'payment_refund' && $payment->STS_ID() != EEM_Payment::status_id_approved ? false : $message_type;
679
-
680
-            self::_load_controller();
681
-
682
-            self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data);
683
-
684
-            //get count of queued for generation
685
-            $count_to_generate = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(array(
686
-                EEM_Message::status_incomplete,
687
-                EEM_Message::status_idle,
688
-            ));
689
-
690
-            if ($count_to_generate > 0 && self::$_MSG_PROCESSOR->get_queue()->get_message_repository()->count() !== 0) {
691
-                add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true');
692
-                return true;
693
-            } else {
694
-                $count_failed = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::instance()->stati_indicating_failed_sending());
695
-                /**
696
-                 * Verify that there are actually errors.  If not then we return a success message because the queue might have been emptied due to successful
697
-                 * IMMEDIATE generation.
698
-                 */
699
-                if ($count_failed > 0) {
700
-                    EE_Error::add_error(sprintf(
701
-                        _n(
702
-                            'The payment notification generation failed.',
703
-                            '%d payment notifications failed being sent.',
704
-                            $count_failed,
705
-                            'event_espresso'
706
-                        ),
707
-                        $count_failed
708
-                    ), __FILE__, __FUNCTION__, __LINE__);
709
-
710
-                    return false;
711
-                } else {
712
-                    add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true');
713
-                    return true;
714
-                }
715
-            }
716
-        } else {
717
-            EE_Error::add_error(
718
-                'Unable to generate the payment notification because the given value for the transaction is invalid.',
719
-                'event_espresso'
720
-            );
721
-            return false;
722
-        }
723
-    }
724
-
725
-
726
-    /**
727
-     * Callback for AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send_with_registrations trigger
728
-     *
729
-     * @since   4.3.0
730
-     * @param  EE_Registration[] $registrations an array of EE_Registration objects
731
-     * @param  int               $grp_id        a specific message template group id.
732
-     * @return void
733
-     */
734
-    public static function send_newsletter_message($registrations, $grp_id)
735
-    {
736
-        //make sure mtp is id and set it in the EE_Request Handler later messages setup.
737
-        EE_Registry::instance()->REQ->set('GRP_ID', (int)$grp_id);
738
-        self::_load_controller();
739
-        self::$_MSG_PROCESSOR->generate_for_all_active_messengers('newsletter', $registrations);
740
-    }
741
-
742
-
743
-    /**
744
-     * Callback for FHEE__EE_Registration__invoice_url__invoice_url or FHEE__EE_Registration__receipt_url__receipt_url
745
-     *
746
-     * @since   4.3.0
747
-     * @param    string          $registration_message_trigger_url
748
-     * @param    EE_Registration $registration
749
-     * @param string             $messenger
750
-     * @param string             $message_type
751
-     * @return    string
752
-     */
753
-    public static function registration_message_trigger_url(
754
-        $registration_message_trigger_url,
755
-        EE_Registration $registration,
756
-        $messenger = 'html',
757
-        $message_type = 'invoice'
758
-    ) {
759
-        // whitelist $messenger
760
-        switch ($messenger) {
761
-            case 'pdf' :
762
-                $sending_messenger    = 'pdf';
763
-                $generating_messenger = 'html';
764
-                break;
765
-            case 'html' :
766
-            default :
767
-                $sending_messenger    = 'html';
768
-                $generating_messenger = 'html';
769
-                break;
770
-        }
771
-        // whitelist $message_type
772
-        switch ($message_type) {
773
-            case 'receipt' :
774
-                $message_type = 'receipt';
775
-                break;
776
-            case 'invoice' :
777
-            default :
778
-                $message_type = 'invoice';
779
-                break;
780
-        }
781
-        // verify that both the messenger AND the message type are active
782
-        if (EEH_MSG_Template::is_messenger_active($sending_messenger) && EEH_MSG_Template::is_mt_active($message_type)) {
783
-            //need to get the correct message template group for this (i.e. is there a custom invoice for the event this registration is registered for?)
784
-            $template_query_params = array(
785
-                'MTP_is_active'    => true,
786
-                'MTP_messenger'    => $generating_messenger,
787
-                'MTP_message_type' => $message_type,
788
-                'Event.EVT_ID'     => $registration->event_ID(),
789
-            );
790
-            //get the message template group.
791
-            $msg_template_group = EEM_Message_Template_Group::instance()->get_one(array($template_query_params));
792
-            //if we don't have an EE_Message_Template_Group then return
793
-            if (! $msg_template_group instanceof EE_Message_Template_Group) {
794
-                // remove EVT_ID from query params so that global templates get picked up
795
-                unset($template_query_params['Event.EVT_ID']);
796
-                //get global template as the fallback
797
-                $msg_template_group = EEM_Message_Template_Group::instance()->get_one(array($template_query_params));
798
-            }
799
-            //if we don't have an EE_Message_Template_Group then return
800
-            if (! $msg_template_group instanceof EE_Message_Template_Group) {
801
-                return '';
802
-            }
803
-            // generate the URL
804
-            $registration_message_trigger_url = EEH_MSG_Template::generate_url_trigger(
805
-                $sending_messenger,
806
-                $generating_messenger,
807
-                'purchaser',
808
-                $message_type,
809
-                $registration,
810
-                $msg_template_group->ID(),
811
-                $registration->transaction_ID()
812
-            );
813
-
814
-        }
815
-        return $registration_message_trigger_url;
816
-    }
817
-
818
-
819
-    /**
820
-     * Use to generate and return a message preview!
821
-     *
822
-     * @param  string $type      This should correspond with a valid message type
823
-     * @param  string $context   This should correspond with a valid context for the message type
824
-     * @param  string $messenger This should correspond with a valid messenger.
825
-     * @param bool    $send      true we will do a test send using the messenger delivery, false we just do a regular
826
-     *                           preview
827
-     * @return string|bool          The body of the message or if send is requested, sends.
828
-     */
829
-    public static function preview_message($type, $context, $messenger, $send = false)
830
-    {
831
-        self::_load_controller();
832
-        $mtg                     = new EE_Message_To_Generate(
833
-            $messenger,
834
-            $type,
835
-            array(),
836
-            $context,
837
-            true
838
-        );
839
-        $generated_preview_queue = self::$_MSG_PROCESSOR->generate_for_preview($mtg, $send);
840
-        if ($generated_preview_queue instanceof EE_Messages_Queue) {
841
-            return $generated_preview_queue->get_message_repository()->current()->content();
842
-        } else {
843
-            return $generated_preview_queue;
844
-        }
845
-    }
846
-
847
-
848
-    /**
849
-     * This is a method that allows for sending a message using a messenger matching the string given and the provided
850
-     * EE_Message_Queue object.  The EE_Message_Queue object is used to create a single aggregate EE_Message via the
851
-     * content found in the EE_Message objects in the queue.
852
-     *
853
-     * @since 4.9.0
854
-     * @param string            $messenger            a string matching a valid active messenger in the system
855
-     * @param string            $message_type         Although it seems contrary to the name of the method, a message
856
-     *                                                type name is still required to send along the message type to the
857
-     *                                                messenger because this is used for determining what specific
858
-     *                                                variations might be loaded for the generated message.
859
-     * @param EE_Messages_Queue $queue
860
-     * @param string            $custom_subject       Can be used to set what the custom subject string will be on the
861
-     *                                                aggregate EE_Message object.
862
-     * @return bool          success or fail.
863
-     */
864
-    public static function send_message_with_messenger_only(
865
-        $messenger,
866
-        $message_type,
867
-        EE_Messages_Queue $queue,
868
-        $custom_subject = ''
869
-    ) {
870
-        self::_load_controller();
871
-        /** @type EE_Message_To_Generate_From_Queue $message_to_generate */
872
-        $message_to_generate = EE_Registry::instance()->load_lib(
873
-            'Message_To_Generate_From_Queue',
874
-            array(
875
-                $messenger,
876
-                $message_type,
877
-                $queue,
878
-                $custom_subject,
879
-            )
880
-        );
881
-        return self::$_MSG_PROCESSOR->queue_for_sending($message_to_generate);
882
-    }
883
-
884
-
885
-    /**
886
-     * Generates Messages immediately for EE_Message IDs (but only for the correct status for generation)
887
-     *
888
-     * @since 4.9.0
889
-     * @param array $message_ids An array of message ids
890
-     * @return bool | EE_Messages_Queue     false if nothing was generated, EE_Messages_Queue containing generated
891
-     *              messages.
892
-     */
893
-    public static function generate_now($message_ids)
894
-    {
895
-        self::_load_controller();
896
-        $messages        = EEM_Message::instance()->get_all(
897
-            array(
898
-                0 => array(
899
-                    'MSG_ID' => array('IN', $message_ids),
900
-                    'STS_ID' => EEM_Message::status_incomplete,
901
-                ),
902
-            )
903
-        );
904
-        $generated_queue = false;
905
-        if ($messages) {
906
-            $generated_queue = self::$_MSG_PROCESSOR->batch_generate_from_queue($messages);
907
-        }
908
-
909
-        if (! $generated_queue instanceof EE_Messages_Queue) {
910
-            EE_Error::add_error(
911
-                __('The messages were not generated. This could mean there is already a batch being generated on a separate request, or because the selected messages are not ready for generation. Please wait a minute or two and try again.',
912
-                    'event_espresso'),
913
-                __FILE__, __FUNCTION__, __LINE__
914
-            );
915
-        }
916
-        return $generated_queue;
917
-    }
918
-
919
-
920
-    /**
921
-     * Sends messages immediately for the incoming message_ids that have the status of EEM_Message::status_resend or,
922
-     * EEM_Message::status_idle
923
-     *
924
-     * @since 4.9.0
925
-     * @param $message_ids
926
-     * @return bool | EE_Messages_Queue  false if no messages sent.
927
-     */
928
-    public static function send_now($message_ids)
929
-    {
930
-        self::_load_controller();
931
-        $messages   = EEM_Message::instance()->get_all(
932
-            array(
933
-                0 => array(
934
-                    'MSG_ID' => array('IN', $message_ids),
935
-                    'STS_ID' => array(
936
-                        'IN',
937
-                        array(EEM_Message::status_idle, EEM_Message::status_resend, EEM_Message::status_retry),
938
-                    ),
939
-                ),
940
-            )
941
-        );
942
-        $sent_queue = false;
943
-        if ($messages) {
944
-            $sent_queue = self::$_MSG_PROCESSOR->batch_send_from_queue($messages);
945
-        }
946
-
947
-        if (! $sent_queue instanceof EE_Messages_Queue) {
948
-            EE_Error::add_error(
949
-                __('The messages were not sent. This could mean there is already a batch being sent on a separate request, or because the selected messages are not sendable. Please wait a minute or two and try again.',
950
-                    'event_espresso'),
951
-                __FILE__, __FUNCTION__, __LINE__
952
-            );
953
-        } else {
954
-            //can count how many sent by using the messages in the queue
955
-            $sent_count = $sent_queue->count_STS_in_queue(EEM_Message::instance()->stati_indicating_sent());
956
-            if ($sent_count > 0) {
957
-                EE_Error::add_success(
958
-                    sprintf(
959
-                        _n(
960
-                            'There was %d message successfully sent.',
961
-                            'There were %d messages successfully sent.',
962
-                            $sent_count,
963
-                            'event_espresso'
964
-                        ),
965
-                        $sent_count
966
-                    )
967
-                );
968
-            } else {
969
-                EE_Error::overwrite_errors();
970
-                EE_Error::add_error(
971
-                    __('No message was sent because of problems with sending. Either all the messages you selected were not a sendable message, they were ALREADY sent on a different scheduled task, or there was an error.
201
+				exit;
202
+			}
203
+		}
204
+		return;
205
+	}
206
+
207
+
208
+	/**
209
+	 *  This runs when the msg_url_trigger route has initiated.
210
+	 *
211
+	 * @since 4.5.0
212
+	 * @param WP $WP
213
+	 * @throws EE_Error
214
+	 * @return    void
215
+	 */
216
+	public function run($WP)
217
+	{
218
+		//ensure controller is loaded
219
+		self::_load_controller();
220
+		// attempt to process message
221
+		try {
222
+			/** @type EE_Message_To_Generate_From_Request $message_to_generate */
223
+			$message_to_generate = EE_Registry::instance()->load_lib('Message_To_Generate_From_Request');
224
+			self::$_MSG_PROCESSOR->generate_and_send_now($message_to_generate);
225
+		} catch (EE_Error $e) {
226
+			$error_msg = __('Please note that a system message failed to send due to a technical issue.',
227
+				'event_espresso');
228
+			// add specific message for developers if WP_DEBUG in on
229
+			$error_msg .= '||' . $e->getMessage();
230
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
231
+		}
232
+	}
233
+
234
+
235
+	/**
236
+	 * This is triggered by the 'msg_cron_trigger' route.
237
+	 *
238
+	 * @param WP $WP
239
+	 */
240
+	public function execute_batch_request($WP)
241
+	{
242
+		$this->run_cron();
243
+		header('HTTP/1.1 200 OK');
244
+		exit();
245
+	}
246
+
247
+
248
+	/**
249
+	 * This gets executed on wp_cron jobs or when a batch request is initiated on its own separate non regular wp
250
+	 * request.
251
+	 */
252
+	public function run_cron()
253
+	{
254
+		self::_load_controller();
255
+		//get required vars
256
+		$cron_type     = EE_Registry::instance()->REQ->get('type');
257
+		$transient_key = EE_Registry::instance()->REQ->get('key');
258
+
259
+		//now let's verify transient, if not valid exit immediately
260
+		if (! get_transient($transient_key)) {
261
+			/**
262
+			 * trigger error so this gets in the error logs.  This is important because it happens on a non-user request.
263
+			 */
264
+			trigger_error(esc_attr__('Invalid Request (Transient does not exist)', 'event_espresso'));
265
+		}
266
+
267
+		//if made it here, lets' delete the transient to keep the db clean
268
+		delete_transient($transient_key);
269
+
270
+		if (apply_filters('FHEE__EED_Messages__run_cron__use_wp_cron', true)) {
271
+
272
+			$method = 'batch_' . $cron_type . '_from_queue';
273
+			if (method_exists(self::$_MSG_PROCESSOR, $method)) {
274
+				self::$_MSG_PROCESSOR->$method();
275
+			} else {
276
+				//no matching task
277
+				/**
278
+				 * trigger error so this gets in the error logs.  This is important because it happens on a non user request.
279
+				 */
280
+				trigger_error(esc_attr(sprintf(__('There is no task corresponding to this route %s', 'event_espresso'),
281
+					$cron_type)));
282
+			}
283
+		}
284
+
285
+		do_action('FHEE__EED_Messages__run_cron__end');
286
+	}
287
+
288
+
289
+	/**
290
+	 * This is used to retrieve the template pack for the given name.
291
+	 * Retrieved packs are cached on the static $_TMP_PACKS array.  If there is no class matching the given name then
292
+	 * the default template pack is returned.
293
+	 *
294
+	 * @deprecated 4.9.0  @see EEH_MSG_Template::get_template_pack()
295
+	 * @param string $template_pack_name This should correspond to the dbref of the template pack (which is also used
296
+	 *                                   in generating the Pack class name).
297
+	 * @return EE_Messages_Template_Pack
298
+	 */
299
+	public static function get_template_pack($template_pack_name)
300
+	{
301
+		EE_Registry::instance()->load_helper('MSG_Template');
302
+		return EEH_MSG_Template::get_template_pack($template_pack_name);
303
+	}
304
+
305
+
306
+	/**
307
+	 * Retrieves an array of all template packs.
308
+	 * Array is in the format array( 'dbref' => EE_Messages_Template_Pack )
309
+	 *
310
+	 * @deprecated 4.9.0  @see EEH_MSG_Template_Pack::get_template_pack_collection
311
+	 * @return EE_Messages_Template_Pack[]
312
+	 */
313
+	public static function get_template_packs()
314
+	{
315
+		EE_Registry::instance()->load_helper('MSG_Template');
316
+
317
+		//for backward compat, let's make sure this returns in the same format as originally.
318
+		$template_pack_collection = EEH_MSG_Template::get_template_pack_collection();
319
+		$template_pack_collection->rewind();
320
+		$template_packs = array();
321
+		while ($template_pack_collection->valid()) {
322
+			$template_packs[$template_pack_collection->current()->dbref] = $template_pack_collection->current();
323
+			$template_pack_collection->next();
324
+		}
325
+		return $template_packs;
326
+	}
327
+
328
+
329
+	/**
330
+	 * This simply makes sure the autoloaders are registered for the EE_messages system.
331
+	 *
332
+	 * @since 4.5.0
333
+	 * @return void
334
+	 */
335
+	public static function set_autoloaders()
336
+	{
337
+		if (empty(self::$_MSG_PATHS)) {
338
+			self::_set_messages_paths();
339
+			foreach (self::$_MSG_PATHS as $path) {
340
+				EEH_Autoloader::register_autoloaders_for_each_file_in_folder($path);
341
+			}
342
+			// add aliases
343
+			EEH_Autoloader::add_alias('EE_messages', 'EE_messages');
344
+			EEH_Autoloader::add_alias('EE_messenger', 'EE_messenger');
345
+		}
346
+	}
347
+
348
+
349
+	/**
350
+	 * Take care of adding all the paths for the messages components to the $_MSG_PATHS property
351
+	 * for use by the Messages Autoloaders
352
+	 *
353
+	 * @since 4.5.0
354
+	 * @return void.
355
+	 */
356
+	protected static function _set_messages_paths()
357
+	{
358
+		$dir_ref = array(
359
+			'messages/message_type',
360
+			'messages/messenger',
361
+			'messages/defaults',
362
+			'messages/defaults/email',
363
+			'messages/data_class',
364
+			'messages/validators',
365
+			'messages/validators/email',
366
+			'messages/validators/html',
367
+			'shortcodes',
368
+		);
369
+		$paths   = array();
370
+		foreach ($dir_ref as $index => $dir) {
371
+			$paths[$index] = EE_LIBRARIES . $dir;
372
+		}
373
+		self::$_MSG_PATHS = apply_filters('FHEE__EED_Messages___set_messages_paths___MSG_PATHS', $paths);
374
+	}
375
+
376
+
377
+	/**
378
+	 * Takes care of loading dependencies
379
+	 *
380
+	 * @since 4.5.0
381
+	 * @return void
382
+	 */
383
+	protected static function _load_controller()
384
+	{
385
+		if (! self::$_MSG_PROCESSOR instanceof EE_Messages_Processor) {
386
+			EE_Registry::instance()->load_core('Request_Handler');
387
+			self::set_autoloaders();
388
+			self::$_EEMSG                    = EE_Registry::instance()->load_lib('messages');
389
+			self::$_MSG_PROCESSOR            = EE_Registry::instance()->load_lib('Messages_Processor');
390
+			self::$_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
391
+		}
392
+	}
393
+
394
+
395
+	/**
396
+	 * @param EE_Transaction $transaction
397
+	 */
398
+	public static function payment_reminder(EE_Transaction $transaction)
399
+	{
400
+		self::_load_controller();
401
+		$data = array($transaction, null);
402
+		self::$_MSG_PROCESSOR->generate_for_all_active_messengers('payment_reminder', $data);
403
+	}
404
+
405
+
406
+	/**
407
+	 * Any messages triggers for after successful gateway payments should go in here.
408
+	 *
409
+	 * @param  EE_Transaction object
410
+	 * @param  EE_Payment     object
411
+	 * @return void
412
+	 */
413
+	public static function payment(EE_Transaction $transaction, EE_Payment $payment)
414
+	{
415
+		self::_load_controller();
416
+		$data = array($transaction, $payment);
417
+		EE_Registry::instance()->load_helper('MSG_Template');
418
+		$message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID());
419
+		//if payment amount is less than 0 then switch to payment_refund message type.
420
+		$message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type;
421
+		self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data);
422
+	}
423
+
424
+
425
+	/**
426
+	 * @param EE_Transaction $transaction
427
+	 */
428
+	public static function cancelled_registration(EE_Transaction $transaction)
429
+	{
430
+		self::_load_controller();
431
+		$data = array($transaction, null);
432
+		self::$_MSG_PROCESSOR->generate_for_all_active_messengers('cancelled_registration', $data);
433
+	}
434
+
435
+
436
+	/**
437
+	 * Trigger for Registration messages
438
+	 * Note that what registration message type is sent depends on what the reg status is for the registrations on the
439
+	 * incoming transaction.
440
+	 *
441
+	 * @param EE_Registration $registration
442
+	 * @param array           $extra_details
443
+	 * @return void
444
+	 */
445
+	public static function maybe_registration(EE_Registration $registration, $extra_details = array())
446
+	{
447
+
448
+		if (! self::_verify_registration_notification_send($registration, $extra_details)) {
449
+			//no messages please
450
+			return;
451
+		}
452
+
453
+
454
+		//get all registrations so we make sure we send messages for the right status.
455
+		$all_registrations = $registration->transaction()->registrations();
456
+
457
+		//cached array of statuses so we only trigger messages once per status.
458
+		$statuses_sent = array();
459
+		self::_load_controller();
460
+		$mtgs = array();
461
+
462
+		//loop through registrations and trigger messages once per status.
463
+		foreach ($all_registrations as $reg) {
464
+
465
+			//already triggered?
466
+			if (in_array($reg->status_ID(), $statuses_sent)) {
467
+				continue;
468
+			}
469
+
470
+			$message_type    = EEH_MSG_Template::convert_reg_status_to_message_type($reg->status_ID());
471
+			$mtgs            = array_merge(
472
+					$mtgs,
473
+					self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers(
474
+							$message_type,
475
+							array($registration->transaction(), null, $reg->status_ID())
476
+					)
477
+			);
478
+			$statuses_sent[] = $reg->status_ID();
479
+		}
480
+
481
+		if (count($statuses_sent) > 1) {
482
+			$mtgs = array_merge(
483
+				$mtgs,
484
+				self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers(
485
+					'registration_summary',
486
+					array($registration->transaction(), null)
487
+				)
488
+			);
489
+		}
490
+
491
+		//batch queue and initiate request
492
+		self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($mtgs);
493
+		self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority();
494
+	}
495
+
496
+
497
+	/**
498
+	 * This is a helper method used to very whether a registration notification should be sent or
499
+	 * not.  Prevents duplicate notifications going out for registration context notifications.
500
+	 *
501
+	 * @param EE_Registration $registration  [description]
502
+	 * @param array           $extra_details [description]
503
+	 * @return bool          true = send away, false = nope halt the presses.
504
+	 */
505
+	protected static function _verify_registration_notification_send(
506
+		EE_Registration $registration,
507
+		$extra_details = array()
508
+	) {
509
+		//self::log(
510
+		//	__CLASS__, __FUNCTION__, __LINE__,
511
+		//	$registration->transaction(),
512
+		//	array( '$extra_details' => $extra_details )
513
+		//);
514
+		// currently only using this to send messages for the primary registrant
515
+		if (! $registration->is_primary_registrant()) {
516
+			return false;
517
+		}
518
+		// first we check if we're in admin and not doing front ajax
519
+		if (is_admin() && ! EE_FRONT_AJAX) {
520
+			//make sure appropriate admin params are set for sending messages
521
+			if (empty($_REQUEST['txn_reg_status_change']['send_notifications']) || ! absint($_REQUEST['txn_reg_status_change']['send_notifications'])) {
522
+				//no messages sent please.
523
+				return false;
524
+			}
525
+		} else {
526
+			// frontend request (either regular or via AJAX)
527
+			// TXN is NOT finalized ?
528
+			if (! isset($extra_details['finalized']) || $extra_details['finalized'] === false) {
529
+				return false;
530
+			}
531
+			// return visit but nothing changed ???
532
+			if (
533
+				isset($extra_details['revisit'], $extra_details['status_updates']) &&
534
+				$extra_details['revisit'] && ! $extra_details['status_updates']
535
+			) {
536
+				return false;
537
+			}
538
+			// NOT sending messages && reg status is something other than "Not-Approved"
539
+			if (
540
+				! apply_filters('FHEE__EED_Messages___maybe_registration__deliver_notifications', false) &&
541
+				$registration->status_ID() !== EEM_Registration::status_id_not_approved
542
+			) {
543
+				return false;
544
+			}
545
+		}
546
+		// release the kraken
547
+		return true;
548
+	}
549
+
550
+
551
+	/**
552
+	 * Simply returns an array indexed by Registration Status ID and the related message_type name associated with that
553
+	 * status id.
554
+	 *
555
+	 * @deprecated 4.9.0  Use EEH_MSG_Template::reg_status_to_message_type_array()
556
+	 *                    or EEH_MSG_Template::convert_reg_status_to_message_type
557
+	 * @param string $reg_status
558
+	 * @return array
559
+	 */
560
+	protected static function _get_reg_status_array($reg_status = '')
561
+	{
562
+		EE_Registry::instance()->load_helper('MSG_Template');
563
+		return EEH_MSG_Template::convert_reg_status_to_message_type($reg_status)
564
+			? EEH_MSG_Template::convert_reg_status_to_message_type($reg_status)
565
+			: EEH_MSG_Template::reg_status_to_message_type_array();
566
+	}
567
+
568
+
569
+	/**
570
+	 * Simply returns the payment message type for the given payment status.
571
+	 *
572
+	 * @deprecated 4.9.0 Use EEH_MSG_Template::payment_status_to_message_type_array
573
+	 *                   or EEH_MSG_Template::convert_payment_status_to_message_type
574
+	 * @param string $payment_status The payment status being matched.
575
+	 * @return string|bool The payment message type slug matching the status or false if no match.
576
+	 */
577
+	protected static function _get_payment_message_type($payment_status)
578
+	{
579
+		EE_Registry::instance()->load_helper('MSG_Template');
580
+		return EEH_MSG_Template::convert_payment_status_to_message_type($payment_status)
581
+			? EEH_MSG_Template::convert_payment_status_to_message_type($payment_status)
582
+			: false;
583
+	}
584
+
585
+
586
+	/**
587
+	 * Message triggers for a resending already sent message(s) (via EE_Message list table)
588
+	 *
589
+	 * @access public
590
+	 * @param array $req_data This is the $_POST & $_GET data sent from EE_Admin Pages
591
+	 * @return bool          success/fail
592
+	 */
593
+	public static function process_resend($req_data)
594
+	{
595
+		self::_load_controller();
596
+
597
+		//if $msgID in this request then skip to the new resend_message
598
+		if (EE_Registry::instance()->REQ->get('MSG_ID')) {
599
+			return self::resend_message();
600
+		}
601
+
602
+		//make sure any incoming request data is set on the REQ so that it gets picked up later.
603
+		$req_data = (array)$req_data;
604
+		foreach ($req_data as $request_key => $request_value) {
605
+			EE_Registry::instance()->REQ->set($request_key, $request_value);
606
+		}
607
+
608
+		if (! $messages_to_send = self::$_MSG_PROCESSOR->setup_messages_to_generate_from_registration_ids_in_request()) {
609
+			return false;
610
+		}
611
+
612
+		try {
613
+			self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($messages_to_send);
614
+			self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority();
615
+		} catch (EE_Error $e) {
616
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
617
+			return false;
618
+		}
619
+		EE_Error::add_success(
620
+			__('Messages have been successfully queued for generation and sending.', 'event_espresso')
621
+		);
622
+		return true; //everything got queued.
623
+	}
624
+
625
+
626
+	/**
627
+	 * Message triggers for a resending already sent message(s) (via EE_Message list table)
628
+	 *
629
+	 * @return bool
630
+	 */
631
+	public static function resend_message()
632
+	{
633
+		self::_load_controller();
634
+
635
+		$msgID = EE_Registry::instance()->REQ->get('MSG_ID');
636
+		if (! $msgID) {
637
+			EE_Error::add_error(__('Something went wrong because there is no "MSG_ID" value in the request',
638
+				'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
639
+			return false;
640
+		}
641
+
642
+		self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send((array)$msgID);
643
+
644
+		//setup success message.
645
+		$count_ready_for_resend = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend);
646
+		EE_Error::add_success(sprintf(
647
+			_n(
648
+				'There was %d message queued for resending.',
649
+				'There were %d messages queued for resending.',
650
+				$count_ready_for_resend,
651
+				'event_espresso'
652
+			),
653
+			$count_ready_for_resend
654
+		));
655
+		return true;
656
+	}
657
+
658
+
659
+	/**
660
+	 * Message triggers for manual payment applied by admin
661
+	 *
662
+	 * @param  EE_Payment $payment EE_payment object
663
+	 * @return bool              success/fail
664
+	 */
665
+	public static function process_admin_payment(EE_Payment $payment)
666
+	{
667
+		EE_Registry::instance()->load_helper('MSG_Template');
668
+		//we need to get the transaction object
669
+		$transaction = $payment->transaction();
670
+		if ($transaction instanceof EE_Transaction) {
671
+			$data         = array($transaction, $payment);
672
+			$message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID());
673
+
674
+			//if payment amount is less than 0 then switch to payment_refund message type.
675
+			$message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type;
676
+
677
+			//if payment_refund is selected, but the status is NOT accepted.  Then change message type to false so NO message notification goes out.
678
+			$message_type = $message_type == 'payment_refund' && $payment->STS_ID() != EEM_Payment::status_id_approved ? false : $message_type;
679
+
680
+			self::_load_controller();
681
+
682
+			self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data);
683
+
684
+			//get count of queued for generation
685
+			$count_to_generate = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(array(
686
+				EEM_Message::status_incomplete,
687
+				EEM_Message::status_idle,
688
+			));
689
+
690
+			if ($count_to_generate > 0 && self::$_MSG_PROCESSOR->get_queue()->get_message_repository()->count() !== 0) {
691
+				add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true');
692
+				return true;
693
+			} else {
694
+				$count_failed = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::instance()->stati_indicating_failed_sending());
695
+				/**
696
+				 * Verify that there are actually errors.  If not then we return a success message because the queue might have been emptied due to successful
697
+				 * IMMEDIATE generation.
698
+				 */
699
+				if ($count_failed > 0) {
700
+					EE_Error::add_error(sprintf(
701
+						_n(
702
+							'The payment notification generation failed.',
703
+							'%d payment notifications failed being sent.',
704
+							$count_failed,
705
+							'event_espresso'
706
+						),
707
+						$count_failed
708
+					), __FILE__, __FUNCTION__, __LINE__);
709
+
710
+					return false;
711
+				} else {
712
+					add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true');
713
+					return true;
714
+				}
715
+			}
716
+		} else {
717
+			EE_Error::add_error(
718
+				'Unable to generate the payment notification because the given value for the transaction is invalid.',
719
+				'event_espresso'
720
+			);
721
+			return false;
722
+		}
723
+	}
724
+
725
+
726
+	/**
727
+	 * Callback for AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send_with_registrations trigger
728
+	 *
729
+	 * @since   4.3.0
730
+	 * @param  EE_Registration[] $registrations an array of EE_Registration objects
731
+	 * @param  int               $grp_id        a specific message template group id.
732
+	 * @return void
733
+	 */
734
+	public static function send_newsletter_message($registrations, $grp_id)
735
+	{
736
+		//make sure mtp is id and set it in the EE_Request Handler later messages setup.
737
+		EE_Registry::instance()->REQ->set('GRP_ID', (int)$grp_id);
738
+		self::_load_controller();
739
+		self::$_MSG_PROCESSOR->generate_for_all_active_messengers('newsletter', $registrations);
740
+	}
741
+
742
+
743
+	/**
744
+	 * Callback for FHEE__EE_Registration__invoice_url__invoice_url or FHEE__EE_Registration__receipt_url__receipt_url
745
+	 *
746
+	 * @since   4.3.0
747
+	 * @param    string          $registration_message_trigger_url
748
+	 * @param    EE_Registration $registration
749
+	 * @param string             $messenger
750
+	 * @param string             $message_type
751
+	 * @return    string
752
+	 */
753
+	public static function registration_message_trigger_url(
754
+		$registration_message_trigger_url,
755
+		EE_Registration $registration,
756
+		$messenger = 'html',
757
+		$message_type = 'invoice'
758
+	) {
759
+		// whitelist $messenger
760
+		switch ($messenger) {
761
+			case 'pdf' :
762
+				$sending_messenger    = 'pdf';
763
+				$generating_messenger = 'html';
764
+				break;
765
+			case 'html' :
766
+			default :
767
+				$sending_messenger    = 'html';
768
+				$generating_messenger = 'html';
769
+				break;
770
+		}
771
+		// whitelist $message_type
772
+		switch ($message_type) {
773
+			case 'receipt' :
774
+				$message_type = 'receipt';
775
+				break;
776
+			case 'invoice' :
777
+			default :
778
+				$message_type = 'invoice';
779
+				break;
780
+		}
781
+		// verify that both the messenger AND the message type are active
782
+		if (EEH_MSG_Template::is_messenger_active($sending_messenger) && EEH_MSG_Template::is_mt_active($message_type)) {
783
+			//need to get the correct message template group for this (i.e. is there a custom invoice for the event this registration is registered for?)
784
+			$template_query_params = array(
785
+				'MTP_is_active'    => true,
786
+				'MTP_messenger'    => $generating_messenger,
787
+				'MTP_message_type' => $message_type,
788
+				'Event.EVT_ID'     => $registration->event_ID(),
789
+			);
790
+			//get the message template group.
791
+			$msg_template_group = EEM_Message_Template_Group::instance()->get_one(array($template_query_params));
792
+			//if we don't have an EE_Message_Template_Group then return
793
+			if (! $msg_template_group instanceof EE_Message_Template_Group) {
794
+				// remove EVT_ID from query params so that global templates get picked up
795
+				unset($template_query_params['Event.EVT_ID']);
796
+				//get global template as the fallback
797
+				$msg_template_group = EEM_Message_Template_Group::instance()->get_one(array($template_query_params));
798
+			}
799
+			//if we don't have an EE_Message_Template_Group then return
800
+			if (! $msg_template_group instanceof EE_Message_Template_Group) {
801
+				return '';
802
+			}
803
+			// generate the URL
804
+			$registration_message_trigger_url = EEH_MSG_Template::generate_url_trigger(
805
+				$sending_messenger,
806
+				$generating_messenger,
807
+				'purchaser',
808
+				$message_type,
809
+				$registration,
810
+				$msg_template_group->ID(),
811
+				$registration->transaction_ID()
812
+			);
813
+
814
+		}
815
+		return $registration_message_trigger_url;
816
+	}
817
+
818
+
819
+	/**
820
+	 * Use to generate and return a message preview!
821
+	 *
822
+	 * @param  string $type      This should correspond with a valid message type
823
+	 * @param  string $context   This should correspond with a valid context for the message type
824
+	 * @param  string $messenger This should correspond with a valid messenger.
825
+	 * @param bool    $send      true we will do a test send using the messenger delivery, false we just do a regular
826
+	 *                           preview
827
+	 * @return string|bool          The body of the message or if send is requested, sends.
828
+	 */
829
+	public static function preview_message($type, $context, $messenger, $send = false)
830
+	{
831
+		self::_load_controller();
832
+		$mtg                     = new EE_Message_To_Generate(
833
+			$messenger,
834
+			$type,
835
+			array(),
836
+			$context,
837
+			true
838
+		);
839
+		$generated_preview_queue = self::$_MSG_PROCESSOR->generate_for_preview($mtg, $send);
840
+		if ($generated_preview_queue instanceof EE_Messages_Queue) {
841
+			return $generated_preview_queue->get_message_repository()->current()->content();
842
+		} else {
843
+			return $generated_preview_queue;
844
+		}
845
+	}
846
+
847
+
848
+	/**
849
+	 * This is a method that allows for sending a message using a messenger matching the string given and the provided
850
+	 * EE_Message_Queue object.  The EE_Message_Queue object is used to create a single aggregate EE_Message via the
851
+	 * content found in the EE_Message objects in the queue.
852
+	 *
853
+	 * @since 4.9.0
854
+	 * @param string            $messenger            a string matching a valid active messenger in the system
855
+	 * @param string            $message_type         Although it seems contrary to the name of the method, a message
856
+	 *                                                type name is still required to send along the message type to the
857
+	 *                                                messenger because this is used for determining what specific
858
+	 *                                                variations might be loaded for the generated message.
859
+	 * @param EE_Messages_Queue $queue
860
+	 * @param string            $custom_subject       Can be used to set what the custom subject string will be on the
861
+	 *                                                aggregate EE_Message object.
862
+	 * @return bool          success or fail.
863
+	 */
864
+	public static function send_message_with_messenger_only(
865
+		$messenger,
866
+		$message_type,
867
+		EE_Messages_Queue $queue,
868
+		$custom_subject = ''
869
+	) {
870
+		self::_load_controller();
871
+		/** @type EE_Message_To_Generate_From_Queue $message_to_generate */
872
+		$message_to_generate = EE_Registry::instance()->load_lib(
873
+			'Message_To_Generate_From_Queue',
874
+			array(
875
+				$messenger,
876
+				$message_type,
877
+				$queue,
878
+				$custom_subject,
879
+			)
880
+		);
881
+		return self::$_MSG_PROCESSOR->queue_for_sending($message_to_generate);
882
+	}
883
+
884
+
885
+	/**
886
+	 * Generates Messages immediately for EE_Message IDs (but only for the correct status for generation)
887
+	 *
888
+	 * @since 4.9.0
889
+	 * @param array $message_ids An array of message ids
890
+	 * @return bool | EE_Messages_Queue     false if nothing was generated, EE_Messages_Queue containing generated
891
+	 *              messages.
892
+	 */
893
+	public static function generate_now($message_ids)
894
+	{
895
+		self::_load_controller();
896
+		$messages        = EEM_Message::instance()->get_all(
897
+			array(
898
+				0 => array(
899
+					'MSG_ID' => array('IN', $message_ids),
900
+					'STS_ID' => EEM_Message::status_incomplete,
901
+				),
902
+			)
903
+		);
904
+		$generated_queue = false;
905
+		if ($messages) {
906
+			$generated_queue = self::$_MSG_PROCESSOR->batch_generate_from_queue($messages);
907
+		}
908
+
909
+		if (! $generated_queue instanceof EE_Messages_Queue) {
910
+			EE_Error::add_error(
911
+				__('The messages were not generated. This could mean there is already a batch being generated on a separate request, or because the selected messages are not ready for generation. Please wait a minute or two and try again.',
912
+					'event_espresso'),
913
+				__FILE__, __FUNCTION__, __LINE__
914
+			);
915
+		}
916
+		return $generated_queue;
917
+	}
918
+
919
+
920
+	/**
921
+	 * Sends messages immediately for the incoming message_ids that have the status of EEM_Message::status_resend or,
922
+	 * EEM_Message::status_idle
923
+	 *
924
+	 * @since 4.9.0
925
+	 * @param $message_ids
926
+	 * @return bool | EE_Messages_Queue  false if no messages sent.
927
+	 */
928
+	public static function send_now($message_ids)
929
+	{
930
+		self::_load_controller();
931
+		$messages   = EEM_Message::instance()->get_all(
932
+			array(
933
+				0 => array(
934
+					'MSG_ID' => array('IN', $message_ids),
935
+					'STS_ID' => array(
936
+						'IN',
937
+						array(EEM_Message::status_idle, EEM_Message::status_resend, EEM_Message::status_retry),
938
+					),
939
+				),
940
+			)
941
+		);
942
+		$sent_queue = false;
943
+		if ($messages) {
944
+			$sent_queue = self::$_MSG_PROCESSOR->batch_send_from_queue($messages);
945
+		}
946
+
947
+		if (! $sent_queue instanceof EE_Messages_Queue) {
948
+			EE_Error::add_error(
949
+				__('The messages were not sent. This could mean there is already a batch being sent on a separate request, or because the selected messages are not sendable. Please wait a minute or two and try again.',
950
+					'event_espresso'),
951
+				__FILE__, __FUNCTION__, __LINE__
952
+			);
953
+		} else {
954
+			//can count how many sent by using the messages in the queue
955
+			$sent_count = $sent_queue->count_STS_in_queue(EEM_Message::instance()->stati_indicating_sent());
956
+			if ($sent_count > 0) {
957
+				EE_Error::add_success(
958
+					sprintf(
959
+						_n(
960
+							'There was %d message successfully sent.',
961
+							'There were %d messages successfully sent.',
962
+							$sent_count,
963
+							'event_espresso'
964
+						),
965
+						$sent_count
966
+					)
967
+				);
968
+			} else {
969
+				EE_Error::overwrite_errors();
970
+				EE_Error::add_error(
971
+					__('No message was sent because of problems with sending. Either all the messages you selected were not a sendable message, they were ALREADY sent on a different scheduled task, or there was an error.
972 972
 					If there was an error, you can look at the messages in the message activity list table for any error messages.',
973
-                        'event_espresso'),
974
-                    __FILE__, __FUNCTION__, __LINE__
975
-                );
976
-            }
977
-        }
978
-        return $sent_queue;
979
-    }
980
-
981
-
982
-    /**
983
-     * This will queue the incoming message ids for resending.
984
-     * Note, only message_ids corresponding to messages with the status of EEM_Message::sent will be queued.
985
-     *
986
-     * @since 4.9.0
987
-     * @param array $message_ids An array of EE_Message IDs
988
-     * @return bool  true means messages were successfully queued for resending, false means none were queued for
989
-     *               resending.
990
-     */
991
-    public static function queue_for_resending($message_ids)
992
-    {
993
-        self::_load_controller();
994
-        self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send($message_ids);
995
-
996
-        //get queue and count
997
-        $queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend);
998
-
999
-        if (
1000
-            $queue_count > 0
1001
-        ) {
1002
-            EE_Error::add_success(
1003
-                sprintf(
1004
-                    _n(
1005
-                        '%d message successfully queued for resending.',
1006
-                        '%d messages successfully queued for resending.',
1007
-                        $queue_count,
1008
-                        'event_espresso'
1009
-                    ),
1010
-                    $queue_count
1011
-                )
1012
-            );
1013
-            /**
1014
-             * @see filter usage in EE_Messages_Queue::initiate_request_by_priority
1015
-             */
1016
-        } elseif (
1017
-            apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', true)
1018
-            || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
1019
-        ) {
1020
-            $queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_sent);
1021
-            if ($queue_count > 0) {
1022
-                EE_Error::add_success(
1023
-                    sprintf(
1024
-                        _n(
1025
-                            '%d message successfully sent.',
1026
-                            '%d messages successfully sent.',
1027
-                            $queue_count,
1028
-                            'event_espresso'
1029
-                        ),
1030
-                        $queue_count
1031
-                    )
1032
-                );
1033
-            } else {
1034
-                EE_Error::add_error(
1035
-                    __('No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.',
1036
-                        'event_espresso'),
1037
-                    __FILE__, __FUNCTION__, __LINE__
1038
-                );
1039
-            }
1040
-        } else {
1041
-            EE_Error::add_error(
1042
-                __('No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.',
1043
-                    'event_espresso'),
1044
-                __FILE__, __FUNCTION__, __LINE__
1045
-            );
1046
-        }
1047
-        return (bool)$queue_count;
1048
-    }
1049
-
1050
-
1051
-    /**
1052
-     * debug
1053
-     *
1054
-     * @param string          $class
1055
-     * @param string          $func
1056
-     * @param string          $line
1057
-     * @param \EE_Transaction $transaction
1058
-     * @param array           $info
1059
-     * @param bool            $display_request
1060
-     */
1061
-    protected static function log(
1062
-        $class = '',
1063
-        $func = '',
1064
-        $line = '',
1065
-        EE_Transaction $transaction,
1066
-        $info = array(),
1067
-        $display_request = false
1068
-    ) {
1069
-        if (WP_DEBUG && false) {
1070
-            if ($transaction instanceof EE_Transaction) {
1071
-                // don't serialize objects
1072
-                $info                  = EEH_Debug_Tools::strip_objects($info);
1073
-                $info['TXN_status']    = $transaction->status_ID();
1074
-                $info['TXN_reg_steps'] = $transaction->reg_steps();
1075
-                if ($transaction->ID()) {
1076
-                    $index = 'EE_Transaction: ' . $transaction->ID();
1077
-                    EEH_Debug_Tools::log($class, $func, $line, $info, $display_request, $index);
1078
-                }
1079
-            }
1080
-        }
1081
-
1082
-    }
1083
-
1084
-
1085
-    /**
1086
-     *  Resets all the static properties in this class when called.
1087
-     */
1088
-    public static function reset()
1089
-    {
1090
-        self::$_EEMSG                    = null;
1091
-        self::$_message_resource_manager = null;
1092
-        self::$_MSG_PROCESSOR            = null;
1093
-        self::$_MSG_PATHS                = null;
1094
-        self::$_TMP_PACKS                = array();
1095
-    }
973
+						'event_espresso'),
974
+					__FILE__, __FUNCTION__, __LINE__
975
+				);
976
+			}
977
+		}
978
+		return $sent_queue;
979
+	}
980
+
981
+
982
+	/**
983
+	 * This will queue the incoming message ids for resending.
984
+	 * Note, only message_ids corresponding to messages with the status of EEM_Message::sent will be queued.
985
+	 *
986
+	 * @since 4.9.0
987
+	 * @param array $message_ids An array of EE_Message IDs
988
+	 * @return bool  true means messages were successfully queued for resending, false means none were queued for
989
+	 *               resending.
990
+	 */
991
+	public static function queue_for_resending($message_ids)
992
+	{
993
+		self::_load_controller();
994
+		self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send($message_ids);
995
+
996
+		//get queue and count
997
+		$queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend);
998
+
999
+		if (
1000
+			$queue_count > 0
1001
+		) {
1002
+			EE_Error::add_success(
1003
+				sprintf(
1004
+					_n(
1005
+						'%d message successfully queued for resending.',
1006
+						'%d messages successfully queued for resending.',
1007
+						$queue_count,
1008
+						'event_espresso'
1009
+					),
1010
+					$queue_count
1011
+				)
1012
+			);
1013
+			/**
1014
+			 * @see filter usage in EE_Messages_Queue::initiate_request_by_priority
1015
+			 */
1016
+		} elseif (
1017
+			apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', true)
1018
+			|| EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
1019
+		) {
1020
+			$queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_sent);
1021
+			if ($queue_count > 0) {
1022
+				EE_Error::add_success(
1023
+					sprintf(
1024
+						_n(
1025
+							'%d message successfully sent.',
1026
+							'%d messages successfully sent.',
1027
+							$queue_count,
1028
+							'event_espresso'
1029
+						),
1030
+						$queue_count
1031
+					)
1032
+				);
1033
+			} else {
1034
+				EE_Error::add_error(
1035
+					__('No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.',
1036
+						'event_espresso'),
1037
+					__FILE__, __FUNCTION__, __LINE__
1038
+				);
1039
+			}
1040
+		} else {
1041
+			EE_Error::add_error(
1042
+				__('No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.',
1043
+					'event_espresso'),
1044
+				__FILE__, __FUNCTION__, __LINE__
1045
+			);
1046
+		}
1047
+		return (bool)$queue_count;
1048
+	}
1049
+
1050
+
1051
+	/**
1052
+	 * debug
1053
+	 *
1054
+	 * @param string          $class
1055
+	 * @param string          $func
1056
+	 * @param string          $line
1057
+	 * @param \EE_Transaction $transaction
1058
+	 * @param array           $info
1059
+	 * @param bool            $display_request
1060
+	 */
1061
+	protected static function log(
1062
+		$class = '',
1063
+		$func = '',
1064
+		$line = '',
1065
+		EE_Transaction $transaction,
1066
+		$info = array(),
1067
+		$display_request = false
1068
+	) {
1069
+		if (WP_DEBUG && false) {
1070
+			if ($transaction instanceof EE_Transaction) {
1071
+				// don't serialize objects
1072
+				$info                  = EEH_Debug_Tools::strip_objects($info);
1073
+				$info['TXN_status']    = $transaction->status_ID();
1074
+				$info['TXN_reg_steps'] = $transaction->reg_steps();
1075
+				if ($transaction->ID()) {
1076
+					$index = 'EE_Transaction: ' . $transaction->ID();
1077
+					EEH_Debug_Tools::log($class, $func, $line, $info, $display_request, $index);
1078
+				}
1079
+			}
1080
+		}
1081
+
1082
+	}
1083
+
1084
+
1085
+	/**
1086
+	 *  Resets all the static properties in this class when called.
1087
+	 */
1088
+	public static function reset()
1089
+	{
1090
+		self::$_EEMSG                    = null;
1091
+		self::$_message_resource_manager = null;
1092
+		self::$_MSG_PROCESSOR            = null;
1093
+		self::$_MSG_PATHS                = null;
1094
+		self::$_TMP_PACKS                = array();
1095
+	}
1096 1096
 
1097 1097
 }
1098 1098
 // End of file EED_Messages.module.php
Please login to merge, or discard this patch.
core/services/database/TableManager.php 2 patches
Indentation   +245 added lines, -247 removed lines patch added patch discarded remove patch
@@ -17,254 +17,252 @@
 block discarded – undo
17 17
 class TableManager extends \EE_Base
18 18
 {
19 19
 
20
-    /**
21
-     * @var TableAnalysis $table_analysis
22
-     */
23
-    private $table_analysis;
24
-
25
-
26
-
27
-    /**
28
-     * TableManager constructor.
29
-     *
30
-     * @param TableAnalysis $TableAnalysis
31
-     */
32
-    public function __construct(TableAnalysis $TableAnalysis)
33
-    {
34
-        $this->table_analysis = $TableAnalysis;
35
-    }
36
-
37
-
38
-
39
-    /**
40
-     * Gets the injected table analyzer, or throws an exception
41
-     *
42
-     * @return TableAnalysis
43
-     * @throws \EE_Error
44
-     */
45
-    protected function getTableAnalysis()
46
-    {
47
-        if ($this->table_analysis instanceof TableAnalysis) {
48
-            return $this->table_analysis;
49
-        } else {
50
-            throw new \EE_Error(
51
-                sprintf(
52
-                    __('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
53
-                    get_class($this)
54
-                )
55
-            );
56
-        }
57
-    }
58
-
59
-
60
-
61
-    /**
62
-     * @param string $table_name which can optionally start with $wpdb->prefix or not
63
-     * @param string $column_name
64
-     * @param string $column_info
65
-     * @return bool|false|int
66
-     */
67
-    public function addColumn($table_name, $column_name, $column_info = 'INT UNSIGNED NOT NULL')
68
-    {
69
-        if (apply_filters('FHEE__EEH_Activation__add_column_if_it_doesnt_exist__short_circuit', false)) {
70
-            return false;
71
-        }
72
-        global $wpdb;
73
-        $full_table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
74
-        $columns = $this->getTableColumns($table_name);
75
-        if ( ! in_array($column_name, $columns)) {
76
-            $alter_query = "ALTER TABLE {$full_table_name} ADD {$column_name} {$column_info}";
77
-            return $wpdb->query($alter_query);
78
-        }
79
-        return true;
80
-    }
81
-
82
-
83
-
84
-    /**
85
-     * Gets the name of all columns on the  table. $table_name can
86
-     * optionally start with $wpdb->prefix or not
87
-     *
88
-     * @global \wpdb $wpdb
89
-     * @param string $table_name
90
-     * @return array
91
-     */
92
-    public function getTableColumns($table_name)
93
-    {
94
-        global $wpdb;
95
-        $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
96
-        $field_array = array();
97
-        if ( ! empty($table_name)) {
98
-            $columns = $wpdb->get_results("SHOW COLUMNS FROM {$table_name} ");
99
-            if ($columns !== false) {
100
-                foreach ($columns as $column) {
101
-                    $field_array[] = $column->Field;
102
-                }
103
-            }
104
-        }
105
-        return $field_array;
106
-    }
107
-
108
-
109
-
110
-    /**
111
-     * Drops the specified table from the database. $table_name can
112
-     * optionally start with $wpdb->prefix or not
113
-     *
114
-     * @global \wpdb $wpdb
115
-     * @param string $table_name
116
-     * @return int
117
-     */
118
-    public function dropTable($table_name)
119
-    {
120
-        global $wpdb;
121
-        if ($this->getTableAnalysis()->tableExists($table_name)) {
122
-            $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
123
-            return $wpdb->query("DROP TABLE IF EXISTS {$table_name}");
124
-        }
125
-        return 0;
126
-    }
127
-
128
-
129
-
130
-    /**
131
-     * Drops all the tables mentioned in a single MYSQL query. Double-checks
132
-     * each table name provided has a wpdb prefix attached, and that it exists.
133
-     * Returns the list actually deleted
134
-     *
135
-     * @global WPDB $wpdb
136
-     * @param array $table_names
137
-     * @return array of table names which we deleted
138
-     */
139
-    public function dropTables($table_names)
140
-    {
141
-        $tables_to_delete = array();
142
-        foreach ($table_names as $table_name) {
143
-            $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
144
-            if ($this->getTableAnalysis()->tableExists($table_name)) {
145
-                $tables_to_delete[$table_name] = $table_name;
146
-            }
147
-        }
148
-        if( ! empty( $tables_to_delete ) ) {
149
-            global $wpdb;
150
-            //make sure we only have a unique strings in the array.
151
-            $tables_to_delete = array_unique($tables_to_delete);
152
-            $wpdb->query('DROP TABLE ' . implode(', ', $tables_to_delete));
153
-        }
154
-        return $tables_to_delete;
155
-    }
156
-
157
-
158
-
159
-    /**
160
-     * Drops the specified index from the specified table. $table_name can
161
-     * optionally start with $wpdb->prefix or not
162
-
163
-     *
20
+	/**
21
+	 * @var TableAnalysis $table_analysis
22
+	 */
23
+	private $table_analysis;
24
+
25
+
26
+
27
+	/**
28
+	 * TableManager constructor.
29
+	 *
30
+	 * @param TableAnalysis $TableAnalysis
31
+	 */
32
+	public function __construct(TableAnalysis $TableAnalysis)
33
+	{
34
+		$this->table_analysis = $TableAnalysis;
35
+	}
36
+
37
+
38
+
39
+	/**
40
+	 * Gets the injected table analyzer, or throws an exception
41
+	 *
42
+	 * @return TableAnalysis
43
+	 * @throws \EE_Error
44
+	 */
45
+	protected function getTableAnalysis()
46
+	{
47
+		if ($this->table_analysis instanceof TableAnalysis) {
48
+			return $this->table_analysis;
49
+		} else {
50
+			throw new \EE_Error(
51
+				sprintf(
52
+					__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
53
+					get_class($this)
54
+				)
55
+			);
56
+		}
57
+	}
58
+
59
+
60
+
61
+	/**
62
+	 * @param string $table_name which can optionally start with $wpdb->prefix or not
63
+	 * @param string $column_name
64
+	 * @param string $column_info
65
+	 * @return bool|false|int
66
+	 */
67
+	public function addColumn($table_name, $column_name, $column_info = 'INT UNSIGNED NOT NULL')
68
+	{
69
+		if (apply_filters('FHEE__EEH_Activation__add_column_if_it_doesnt_exist__short_circuit', false)) {
70
+			return false;
71
+		}
72
+		global $wpdb;
73
+		$full_table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
74
+		$columns = $this->getTableColumns($table_name);
75
+		if ( ! in_array($column_name, $columns)) {
76
+			$alter_query = "ALTER TABLE {$full_table_name} ADD {$column_name} {$column_info}";
77
+			return $wpdb->query($alter_query);
78
+		}
79
+		return true;
80
+	}
81
+
82
+
83
+
84
+	/**
85
+	 * Gets the name of all columns on the  table. $table_name can
86
+	 * optionally start with $wpdb->prefix or not
87
+	 *
88
+	 * @global \wpdb $wpdb
89
+	 * @param string $table_name
90
+	 * @return array
91
+	 */
92
+	public function getTableColumns($table_name)
93
+	{
94
+		global $wpdb;
95
+		$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
96
+		$field_array = array();
97
+		if ( ! empty($table_name)) {
98
+			$columns = $wpdb->get_results("SHOW COLUMNS FROM {$table_name} ");
99
+			if ($columns !== false) {
100
+				foreach ($columns as $column) {
101
+					$field_array[] = $column->Field;
102
+				}
103
+			}
104
+		}
105
+		return $field_array;
106
+	}
107
+
108
+
109
+
110
+	/**
111
+	 * Drops the specified table from the database. $table_name can
112
+	 * optionally start with $wpdb->prefix or not
113
+	 *
114
+	 * @global \wpdb $wpdb
115
+	 * @param string $table_name
116
+	 * @return int
117
+	 */
118
+	public function dropTable($table_name)
119
+	{
120
+		global $wpdb;
121
+		if ($this->getTableAnalysis()->tableExists($table_name)) {
122
+			$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
123
+			return $wpdb->query("DROP TABLE IF EXISTS {$table_name}");
124
+		}
125
+		return 0;
126
+	}
127
+
128
+
129
+
130
+	/**
131
+	 * Drops all the tables mentioned in a single MYSQL query. Double-checks
132
+	 * each table name provided has a wpdb prefix attached, and that it exists.
133
+	 * Returns the list actually deleted
134
+	 *
135
+	 * @global WPDB $wpdb
136
+	 * @param array $table_names
137
+	 * @return array of table names which we deleted
138
+	 */
139
+	public function dropTables($table_names)
140
+	{
141
+		$tables_to_delete = array();
142
+		foreach ($table_names as $table_name) {
143
+			$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
144
+			if ($this->getTableAnalysis()->tableExists($table_name)) {
145
+				$tables_to_delete[$table_name] = $table_name;
146
+			}
147
+		}
148
+		if( ! empty( $tables_to_delete ) ) {
149
+			global $wpdb;
150
+			//make sure we only have a unique strings in the array.
151
+			$tables_to_delete = array_unique($tables_to_delete);
152
+			$wpdb->query('DROP TABLE ' . implode(', ', $tables_to_delete));
153
+		}
154
+		return $tables_to_delete;
155
+	}
156
+
157
+
158
+
159
+	/**
160
+	 * Drops the specified index from the specified table. $table_name can
161
+	 * optionally start with $wpdb->prefix or not
162
+	 *
164 163
 *@global \wpdb       $wpdb
165
-     * @param string $table_name
166
-     * @param string $index_name
167
-     * @return int the number of indexes dropped. False if there was a datbase error
168
-     */
169
-    public function dropIndex($table_name, $index_name)
170
-    {
171
-        if (apply_filters('FHEE__EEH_Activation__drop_index__short_circuit', false)) {
172
-            return 0;
173
-        }
174
-        global $wpdb;
175
-        $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
176
-        $index_exists_query = "SHOW INDEX FROM {$table_name} WHERE key_name = '{$index_name}'";
177
-        if (
178
-            $this->getTableAnalysis()->tableExists($table_name)
179
-            && $wpdb->get_var($index_exists_query)
180
-               === $table_name //using get_var with the $index_exists_query returns the table's name
181
-        ) {
182
-            return $wpdb->query("ALTER TABLE {$table_name} DROP INDEX {$index_name}");
183
-        }
184
-        return 0;
185
-    }
186
-
187
-
188
-
189
-    /**
190
-     * Just creates the requested table. $table_name can
191
-     * optionally start with $wpdb->prefix or not
192
-
193
-     *
164
+	 * @param string $table_name
165
+	 * @param string $index_name
166
+	 * @return int the number of indexes dropped. False if there was a datbase error
167
+	 */
168
+	public function dropIndex($table_name, $index_name)
169
+	{
170
+		if (apply_filters('FHEE__EEH_Activation__drop_index__short_circuit', false)) {
171
+			return 0;
172
+		}
173
+		global $wpdb;
174
+		$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
175
+		$index_exists_query = "SHOW INDEX FROM {$table_name} WHERE key_name = '{$index_name}'";
176
+		if (
177
+			$this->getTableAnalysis()->tableExists($table_name)
178
+			&& $wpdb->get_var($index_exists_query)
179
+			   === $table_name //using get_var with the $index_exists_query returns the table's name
180
+		) {
181
+			return $wpdb->query("ALTER TABLE {$table_name} DROP INDEX {$index_name}");
182
+		}
183
+		return 0;
184
+	}
185
+
186
+
187
+
188
+	/**
189
+	 * Just creates the requested table. $table_name can
190
+	 * optionally start with $wpdb->prefix or not
191
+	 *
194 192
 *@param string       $table_name
195
-     * @param string $create_sql defining the table's columns and indexes
196
-     * @param string $engine     (no need to specify "ENGINE=", that's implied)
197
-     * @return void
198
-     * @throws \EE_Error
199
-     */
200
-    public function createTable($table_name, $create_sql, $engine = 'MyISAM')
201
-    {
202
-        // does $sql contain valid column information? ( LPT: https://regex101.com/ is great for working out regex patterns )
203
-        if (preg_match('((((.*?))(,\s))+)', $create_sql, $valid_column_data)) {
204
-            $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
205
-            /** @var \wpdb $wpdb */
206
-            global $wpdb;
207
-            $SQL = "CREATE TABLE {$table_name} ( {$create_sql} ) ENGINE={$engine} " . $wpdb->get_charset_collate();
208
-
209
-            //get $wpdb to echo errors, but buffer them. This way at least WE know an error
210
-            //happened. And then we can choose to tell the end user
211
-            $old_show_errors_policy = $wpdb->show_errors(true);
212
-            $old_error_suppression_policy = $wpdb->suppress_errors(false);
213
-            ob_start();
214
-            dbDelta($SQL);
215
-            $output = ob_get_contents();
216
-            ob_end_clean();
217
-            $wpdb->show_errors($old_show_errors_policy);
218
-            $wpdb->suppress_errors($old_error_suppression_policy);
219
-            if ( ! empty($output)) {
220
-                throw new \EE_Error($output);
221
-            }
222
-        } else {
223
-            throw new \EE_Error(
224
-                sprintf(
225
-                    __('The following table creation SQL does not contain valid information about the table columns: %1$s %2$s',
226
-                        'event_espresso'),
227
-                    '<br />',
228
-                    $create_sql
229
-                )
230
-            );
231
-        }
232
-    }
233
-
234
-
235
-
236
-    /**
237
-     * Drops the specified index if it's size differs from $desired_index_size.
238
-     * WordPress' dbdelta method doesn't automatically change index sizes, so this
239
-     * method can be used to only drop the index if needed, and afterwards dbdelta can be used as normal.
240
-     * If the table doesn't exist, or it exists but the index does not, or returns false
241
-     *
242
-     * @param string $table_name
243
-     * @param string $index_name
244
-     * @param string $column_name if none is provided, we assume the column name matches the index (often true in EE)
245
-     * @param string|int $desired_index_size defaults to TableAnalysis::index_col_size, the max for utf8mb4.
246
-     * @return bool whether an index was dropped or not
247
-     * @throws /EE_Error if table analysis object isn't defined
248
-     */
249
-    public function dropIndexIfSizeNot($table_name, $index_name, $column_name = null, $desired_index_size = TableAnalysis::INDEX_COLUMN_SIZE)
250
-    {
251
-        if($column_name === null){
252
-            $column_name = $index_name;
253
-        }
254
-        if(!$this->getTableAnalysis()->tableExists($table_name)){
255
-            return false;
256
-        }
257
-        $index_entries = $this->getTableAnalysis()->showIndexes($table_name,$index_name);
258
-        if(empty($index_entries)){
259
-            return false;
260
-        }
261
-        foreach($index_entries as $index_entry){
262
-            if( $column_name === $index_entry->Column_name
263
-                && (string)$desired_index_size !== $index_entry->Sub_part){
264
-                return $this->dropIndex($table_name,$index_name);
265
-            }
266
-        }
267
-        return false;
268
-    }
193
+	 * @param string $create_sql defining the table's columns and indexes
194
+	 * @param string $engine     (no need to specify "ENGINE=", that's implied)
195
+	 * @return void
196
+	 * @throws \EE_Error
197
+	 */
198
+	public function createTable($table_name, $create_sql, $engine = 'MyISAM')
199
+	{
200
+		// does $sql contain valid column information? ( LPT: https://regex101.com/ is great for working out regex patterns )
201
+		if (preg_match('((((.*?))(,\s))+)', $create_sql, $valid_column_data)) {
202
+			$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
203
+			/** @var \wpdb $wpdb */
204
+			global $wpdb;
205
+			$SQL = "CREATE TABLE {$table_name} ( {$create_sql} ) ENGINE={$engine} " . $wpdb->get_charset_collate();
206
+
207
+			//get $wpdb to echo errors, but buffer them. This way at least WE know an error
208
+			//happened. And then we can choose to tell the end user
209
+			$old_show_errors_policy = $wpdb->show_errors(true);
210
+			$old_error_suppression_policy = $wpdb->suppress_errors(false);
211
+			ob_start();
212
+			dbDelta($SQL);
213
+			$output = ob_get_contents();
214
+			ob_end_clean();
215
+			$wpdb->show_errors($old_show_errors_policy);
216
+			$wpdb->suppress_errors($old_error_suppression_policy);
217
+			if ( ! empty($output)) {
218
+				throw new \EE_Error($output);
219
+			}
220
+		} else {
221
+			throw new \EE_Error(
222
+				sprintf(
223
+					__('The following table creation SQL does not contain valid information about the table columns: %1$s %2$s',
224
+						'event_espresso'),
225
+					'<br />',
226
+					$create_sql
227
+				)
228
+			);
229
+		}
230
+	}
231
+
232
+
233
+
234
+	/**
235
+	 * Drops the specified index if it's size differs from $desired_index_size.
236
+	 * WordPress' dbdelta method doesn't automatically change index sizes, so this
237
+	 * method can be used to only drop the index if needed, and afterwards dbdelta can be used as normal.
238
+	 * If the table doesn't exist, or it exists but the index does not, or returns false
239
+	 *
240
+	 * @param string $table_name
241
+	 * @param string $index_name
242
+	 * @param string $column_name if none is provided, we assume the column name matches the index (often true in EE)
243
+	 * @param string|int $desired_index_size defaults to TableAnalysis::index_col_size, the max for utf8mb4.
244
+	 * @return bool whether an index was dropped or not
245
+	 * @throws /EE_Error if table analysis object isn't defined
246
+	 */
247
+	public function dropIndexIfSizeNot($table_name, $index_name, $column_name = null, $desired_index_size = TableAnalysis::INDEX_COLUMN_SIZE)
248
+	{
249
+		if($column_name === null){
250
+			$column_name = $index_name;
251
+		}
252
+		if(!$this->getTableAnalysis()->tableExists($table_name)){
253
+			return false;
254
+		}
255
+		$index_entries = $this->getTableAnalysis()->showIndexes($table_name,$index_name);
256
+		if(empty($index_entries)){
257
+			return false;
258
+		}
259
+		foreach($index_entries as $index_entry){
260
+			if( $column_name === $index_entry->Column_name
261
+				&& (string)$desired_index_size !== $index_entry->Sub_part){
262
+				return $this->dropIndex($table_name,$index_name);
263
+			}
264
+		}
265
+		return false;
266
+	}
269 267
 
270 268
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -145,11 +145,11 @@  discard block
 block discarded – undo
145 145
                 $tables_to_delete[$table_name] = $table_name;
146 146
             }
147 147
         }
148
-        if( ! empty( $tables_to_delete ) ) {
148
+        if ( ! empty($tables_to_delete)) {
149 149
             global $wpdb;
150 150
             //make sure we only have a unique strings in the array.
151 151
             $tables_to_delete = array_unique($tables_to_delete);
152
-            $wpdb->query('DROP TABLE ' . implode(', ', $tables_to_delete));
152
+            $wpdb->query('DROP TABLE '.implode(', ', $tables_to_delete));
153 153
         }
154 154
         return $tables_to_delete;
155 155
     }
@@ -204,7 +204,7 @@  discard block
 block discarded – undo
204 204
             $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
205 205
             /** @var \wpdb $wpdb */
206 206
             global $wpdb;
207
-            $SQL = "CREATE TABLE {$table_name} ( {$create_sql} ) ENGINE={$engine} " . $wpdb->get_charset_collate();
207
+            $SQL = "CREATE TABLE {$table_name} ( {$create_sql} ) ENGINE={$engine} ".$wpdb->get_charset_collate();
208 208
 
209 209
             //get $wpdb to echo errors, but buffer them. This way at least WE know an error
210 210
             //happened. And then we can choose to tell the end user
@@ -248,20 +248,20 @@  discard block
 block discarded – undo
248 248
      */
249 249
     public function dropIndexIfSizeNot($table_name, $index_name, $column_name = null, $desired_index_size = TableAnalysis::INDEX_COLUMN_SIZE)
250 250
     {
251
-        if($column_name === null){
251
+        if ($column_name === null) {
252 252
             $column_name = $index_name;
253 253
         }
254
-        if(!$this->getTableAnalysis()->tableExists($table_name)){
254
+        if ( ! $this->getTableAnalysis()->tableExists($table_name)) {
255 255
             return false;
256 256
         }
257
-        $index_entries = $this->getTableAnalysis()->showIndexes($table_name,$index_name);
258
-        if(empty($index_entries)){
257
+        $index_entries = $this->getTableAnalysis()->showIndexes($table_name, $index_name);
258
+        if (empty($index_entries)) {
259 259
             return false;
260 260
         }
261
-        foreach($index_entries as $index_entry){
262
-            if( $column_name === $index_entry->Column_name
263
-                && (string)$desired_index_size !== $index_entry->Sub_part){
264
-                return $this->dropIndex($table_name,$index_name);
261
+        foreach ($index_entries as $index_entry) {
262
+            if ($column_name === $index_entry->Column_name
263
+                && (string) $desired_index_size !== $index_entry->Sub_part) {
264
+                return $this->dropIndex($table_name, $index_name);
265 265
             }
266 266
         }
267 267
         return false;
Please login to merge, or discard this patch.
core/helpers/EEH_Activation.helper.php 1 patch
Indentation   +1653 added lines, -1653 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 
5 5
 
@@ -14,244 +14,244 @@  discard block
 block discarded – undo
14 14
 class EEH_Activation
15 15
 {
16 16
 
17
-    /**
18
-     * constant used to indicate a cron task is no longer in use
19
-     */
20
-    const cron_task_no_longer_in_use = 'no_longer_in_use';
21
-
22
-    /**
23
-     * option name that will indicate whether or not we still
24
-     * need to create EE's folders in the uploads directory
25
-     * (because if EE was installed without file system access,
26
-     * we need to request credentials before we can create them)
27
-     */
28
-    const upload_directories_incomplete_option_name = 'ee_upload_directories_incomplete';
29
-
30
-    /**
31
-     * WP_User->ID
32
-     *
33
-     * @var int
34
-     */
35
-    private static $_default_creator_id;
36
-
37
-    /**
38
-     * indicates whether or not we've already verified core's default data during this request,
39
-     * because after migrations are done, any addons activated while in maintenance mode
40
-     * will want to setup their own default data, and they might hook into core's default data
41
-     * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
42
-     * This prevents doing that for EVERY single addon.
43
-     *
44
-     * @var boolean
45
-     */
46
-    protected static $_initialized_db_content_already_in_this_request = false;
47
-
48
-    /**
49
-     * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
50
-     */
51
-    private static $table_analysis;
52
-
53
-    /**
54
-     * @var \EventEspresso\core\services\database\TableManager $table_manager
55
-     */
56
-    private static $table_manager;
57
-
58
-
59
-    /**
60
-     * @return \EventEspresso\core\services\database\TableAnalysis
61
-     */
62
-    public static function getTableAnalysis()
63
-    {
64
-        if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
65
-            self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
66
-        }
67
-        return self::$table_analysis;
68
-    }
69
-
70
-
71
-    /**
72
-     * @return \EventEspresso\core\services\database\TableManager
73
-     */
74
-    public static function getTableManager()
75
-    {
76
-        if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
77
-            self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
78
-        }
79
-        return self::$table_manager;
80
-    }
81
-
82
-
83
-    /**
84
-     *    _ensure_table_name_has_prefix
85
-     *
86
-     * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
87
-     * @access     public
88
-     * @static
89
-     * @param $table_name
90
-     * @return string
91
-     */
92
-    public static function ensure_table_name_has_prefix($table_name)
93
-    {
94
-        return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
95
-    }
96
-
97
-
98
-    /**
99
-     *    system_initialization
100
-     *    ensures the EE configuration settings are loaded with at least default options set
101
-     *    and that all critical EE pages have been generated with the appropriate shortcodes in place
102
-     *
103
-     * @access public
104
-     * @static
105
-     * @return void
106
-     */
107
-    public static function system_initialization()
108
-    {
109
-        EEH_Activation::reset_and_update_config();
110
-        //which is fired BEFORE activation of plugin anyways
111
-        EEH_Activation::verify_default_pages_exist();
112
-    }
113
-
114
-
115
-    /**
116
-     * Sets the database schema and creates folders. This should
117
-     * be called on plugin activation and reactivation
118
-     *
119
-     * @return boolean success, whether the database and folders are setup properly
120
-     * @throws \EE_Error
121
-     */
122
-    public static function initialize_db_and_folders()
123
-    {
124
-        $good_filesystem = EEH_Activation::create_upload_directories();
125
-        $good_db         = EEH_Activation::create_database_tables();
126
-        return $good_filesystem && $good_db;
127
-    }
128
-
129
-
130
-    /**
131
-     * assuming we have an up-to-date database schema, this will populate it
132
-     * with default and initial data. This should be called
133
-     * upon activation of a new plugin, reactivation, and at the end
134
-     * of running migration scripts
135
-     *
136
-     * @throws \EE_Error
137
-     */
138
-    public static function initialize_db_content()
139
-    {
140
-        //let's avoid doing all this logic repeatedly, especially when addons are requesting it
141
-        if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
142
-            return;
143
-        }
144
-        EEH_Activation::$_initialized_db_content_already_in_this_request = true;
145
-
146
-        EEH_Activation::initialize_system_questions();
147
-        EEH_Activation::insert_default_status_codes();
148
-        EEH_Activation::generate_default_message_templates();
149
-        EEH_Activation::create_no_ticket_prices_array();
150
-        EE_Registry::instance()->CAP->init_caps();
151
-
152
-        EEH_Activation::validate_messages_system();
153
-        EEH_Activation::insert_default_payment_methods();
154
-        //in case we've
155
-        EEH_Activation::remove_cron_tasks();
156
-        EEH_Activation::create_cron_tasks();
157
-        // remove all TXN locks since that is being done via extra meta now
158
-        delete_option('ee_locked_transactions');
159
-        //also, check for CAF default db content
160
-        do_action('AHEE__EEH_Activation__initialize_db_content');
161
-        //also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
162
-        //which users really won't care about on initial activation
163
-        EE_Error::overwrite_success();
164
-    }
165
-
166
-
167
-    /**
168
-     * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
169
-     * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
170
-     * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
171
-     * (null)
172
-     *
173
-     * @param string $which_to_include can be 'current' (ones that are currently in use),
174
-     *                                 'old' (only returns ones that should no longer be used),or 'all',
175
-     * @return array
176
-     * @throws \EE_Error
177
-     */
178
-    public static function get_cron_tasks($which_to_include)
179
-    {
180
-        $cron_tasks = apply_filters(
181
-            'FHEE__EEH_Activation__get_cron_tasks',
182
-            array(
183
-                'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
17
+	/**
18
+	 * constant used to indicate a cron task is no longer in use
19
+	 */
20
+	const cron_task_no_longer_in_use = 'no_longer_in_use';
21
+
22
+	/**
23
+	 * option name that will indicate whether or not we still
24
+	 * need to create EE's folders in the uploads directory
25
+	 * (because if EE was installed without file system access,
26
+	 * we need to request credentials before we can create them)
27
+	 */
28
+	const upload_directories_incomplete_option_name = 'ee_upload_directories_incomplete';
29
+
30
+	/**
31
+	 * WP_User->ID
32
+	 *
33
+	 * @var int
34
+	 */
35
+	private static $_default_creator_id;
36
+
37
+	/**
38
+	 * indicates whether or not we've already verified core's default data during this request,
39
+	 * because after migrations are done, any addons activated while in maintenance mode
40
+	 * will want to setup their own default data, and they might hook into core's default data
41
+	 * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
42
+	 * This prevents doing that for EVERY single addon.
43
+	 *
44
+	 * @var boolean
45
+	 */
46
+	protected static $_initialized_db_content_already_in_this_request = false;
47
+
48
+	/**
49
+	 * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
50
+	 */
51
+	private static $table_analysis;
52
+
53
+	/**
54
+	 * @var \EventEspresso\core\services\database\TableManager $table_manager
55
+	 */
56
+	private static $table_manager;
57
+
58
+
59
+	/**
60
+	 * @return \EventEspresso\core\services\database\TableAnalysis
61
+	 */
62
+	public static function getTableAnalysis()
63
+	{
64
+		if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
65
+			self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
66
+		}
67
+		return self::$table_analysis;
68
+	}
69
+
70
+
71
+	/**
72
+	 * @return \EventEspresso\core\services\database\TableManager
73
+	 */
74
+	public static function getTableManager()
75
+	{
76
+		if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
77
+			self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
78
+		}
79
+		return self::$table_manager;
80
+	}
81
+
82
+
83
+	/**
84
+	 *    _ensure_table_name_has_prefix
85
+	 *
86
+	 * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
87
+	 * @access     public
88
+	 * @static
89
+	 * @param $table_name
90
+	 * @return string
91
+	 */
92
+	public static function ensure_table_name_has_prefix($table_name)
93
+	{
94
+		return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
95
+	}
96
+
97
+
98
+	/**
99
+	 *    system_initialization
100
+	 *    ensures the EE configuration settings are loaded with at least default options set
101
+	 *    and that all critical EE pages have been generated with the appropriate shortcodes in place
102
+	 *
103
+	 * @access public
104
+	 * @static
105
+	 * @return void
106
+	 */
107
+	public static function system_initialization()
108
+	{
109
+		EEH_Activation::reset_and_update_config();
110
+		//which is fired BEFORE activation of plugin anyways
111
+		EEH_Activation::verify_default_pages_exist();
112
+	}
113
+
114
+
115
+	/**
116
+	 * Sets the database schema and creates folders. This should
117
+	 * be called on plugin activation and reactivation
118
+	 *
119
+	 * @return boolean success, whether the database and folders are setup properly
120
+	 * @throws \EE_Error
121
+	 */
122
+	public static function initialize_db_and_folders()
123
+	{
124
+		$good_filesystem = EEH_Activation::create_upload_directories();
125
+		$good_db         = EEH_Activation::create_database_tables();
126
+		return $good_filesystem && $good_db;
127
+	}
128
+
129
+
130
+	/**
131
+	 * assuming we have an up-to-date database schema, this will populate it
132
+	 * with default and initial data. This should be called
133
+	 * upon activation of a new plugin, reactivation, and at the end
134
+	 * of running migration scripts
135
+	 *
136
+	 * @throws \EE_Error
137
+	 */
138
+	public static function initialize_db_content()
139
+	{
140
+		//let's avoid doing all this logic repeatedly, especially when addons are requesting it
141
+		if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
142
+			return;
143
+		}
144
+		EEH_Activation::$_initialized_db_content_already_in_this_request = true;
145
+
146
+		EEH_Activation::initialize_system_questions();
147
+		EEH_Activation::insert_default_status_codes();
148
+		EEH_Activation::generate_default_message_templates();
149
+		EEH_Activation::create_no_ticket_prices_array();
150
+		EE_Registry::instance()->CAP->init_caps();
151
+
152
+		EEH_Activation::validate_messages_system();
153
+		EEH_Activation::insert_default_payment_methods();
154
+		//in case we've
155
+		EEH_Activation::remove_cron_tasks();
156
+		EEH_Activation::create_cron_tasks();
157
+		// remove all TXN locks since that is being done via extra meta now
158
+		delete_option('ee_locked_transactions');
159
+		//also, check for CAF default db content
160
+		do_action('AHEE__EEH_Activation__initialize_db_content');
161
+		//also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
162
+		//which users really won't care about on initial activation
163
+		EE_Error::overwrite_success();
164
+	}
165
+
166
+
167
+	/**
168
+	 * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
169
+	 * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
170
+	 * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
171
+	 * (null)
172
+	 *
173
+	 * @param string $which_to_include can be 'current' (ones that are currently in use),
174
+	 *                                 'old' (only returns ones that should no longer be used),or 'all',
175
+	 * @return array
176
+	 * @throws \EE_Error
177
+	 */
178
+	public static function get_cron_tasks($which_to_include)
179
+	{
180
+		$cron_tasks = apply_filters(
181
+			'FHEE__EEH_Activation__get_cron_tasks',
182
+			array(
183
+				'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
184 184
 //				'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions' => EEH_Activation::cron_task_no_longer_in_use, actually this is still in use
185
-                'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
186
-                //there may have been a bug which prevented from these cron tasks from getting unscheduled, so we might want to remove these for a few updates
187
-                'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs'       => 'daily',
188
-            )
189
-        );
190
-        if ($which_to_include === 'old') {
191
-            $cron_tasks = array_filter(
192
-                $cron_tasks,
193
-                function ($value) {
194
-                    return $value === EEH_Activation::cron_task_no_longer_in_use;
195
-                }
196
-            );
197
-        } elseif ($which_to_include === 'current') {
198
-            $cron_tasks = array_filter($cron_tasks);
199
-        } elseif (WP_DEBUG && $which_to_include !== 'all') {
200
-            throw new EE_Error(
201
-                sprintf(
202
-                    __(
203
-                        'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
204
-                        'event_espresso'
205
-                    ),
206
-                    $which_to_include
207
-                )
208
-            );
209
-        }
210
-        return $cron_tasks;
211
-    }
212
-
213
-
214
-    /**
215
-     * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
216
-     *
217
-     * @throws \EE_Error
218
-     */
219
-    public static function create_cron_tasks()
220
-    {
221
-
222
-        foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
223
-            if (! wp_next_scheduled($hook_name)) {
224
-                /**
225
-                 * This allows client code to define the initial start timestamp for this schedule.
226
-                 */
227
-                if (is_array($frequency)
228
-                    && count($frequency) === 2
229
-                    && isset($frequency[0], $frequency[1])
230
-                ) {
231
-                    $start_timestamp = $frequency[0];
232
-                    $frequency = $frequency[1];
233
-                } else {
234
-                    $start_timestamp = time();
235
-                }
236
-                wp_schedule_event($start_timestamp, $frequency, $hook_name);
237
-            }
238
-        }
239
-
240
-    }
241
-
242
-
243
-    /**
244
-     * Remove the currently-existing and now-removed cron tasks.
245
-     *
246
-     * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
247
-     * @throws \EE_Error
248
-     */
249
-    public static function remove_cron_tasks($remove_all = true)
250
-    {
251
-        $cron_tasks_to_remove = $remove_all ? 'all' : 'old';
252
-        $crons                = _get_cron_array();
253
-        $crons                = is_array($crons) ? $crons : array();
254
-        /* reminder of what $crons look like:
185
+				'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
186
+				//there may have been a bug which prevented from these cron tasks from getting unscheduled, so we might want to remove these for a few updates
187
+				'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs'       => 'daily',
188
+			)
189
+		);
190
+		if ($which_to_include === 'old') {
191
+			$cron_tasks = array_filter(
192
+				$cron_tasks,
193
+				function ($value) {
194
+					return $value === EEH_Activation::cron_task_no_longer_in_use;
195
+				}
196
+			);
197
+		} elseif ($which_to_include === 'current') {
198
+			$cron_tasks = array_filter($cron_tasks);
199
+		} elseif (WP_DEBUG && $which_to_include !== 'all') {
200
+			throw new EE_Error(
201
+				sprintf(
202
+					__(
203
+						'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
204
+						'event_espresso'
205
+					),
206
+					$which_to_include
207
+				)
208
+			);
209
+		}
210
+		return $cron_tasks;
211
+	}
212
+
213
+
214
+	/**
215
+	 * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
216
+	 *
217
+	 * @throws \EE_Error
218
+	 */
219
+	public static function create_cron_tasks()
220
+	{
221
+
222
+		foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
223
+			if (! wp_next_scheduled($hook_name)) {
224
+				/**
225
+				 * This allows client code to define the initial start timestamp for this schedule.
226
+				 */
227
+				if (is_array($frequency)
228
+					&& count($frequency) === 2
229
+					&& isset($frequency[0], $frequency[1])
230
+				) {
231
+					$start_timestamp = $frequency[0];
232
+					$frequency = $frequency[1];
233
+				} else {
234
+					$start_timestamp = time();
235
+				}
236
+				wp_schedule_event($start_timestamp, $frequency, $hook_name);
237
+			}
238
+		}
239
+
240
+	}
241
+
242
+
243
+	/**
244
+	 * Remove the currently-existing and now-removed cron tasks.
245
+	 *
246
+	 * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
247
+	 * @throws \EE_Error
248
+	 */
249
+	public static function remove_cron_tasks($remove_all = true)
250
+	{
251
+		$cron_tasks_to_remove = $remove_all ? 'all' : 'old';
252
+		$crons                = _get_cron_array();
253
+		$crons                = is_array($crons) ? $crons : array();
254
+		/* reminder of what $crons look like:
255 255
          * Top-level keys are timestamps, and their values are arrays.
256 256
          * The 2nd level arrays have keys with each of the cron task hook names to run at that time
257 257
          * and their values are arrays.
@@ -268,912 +268,912 @@  discard block
 block discarded – undo
268 268
          *					...
269 269
          *      ...
270 270
          */
271
-        $ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
272
-        foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
273
-            if (is_array($hooks_to_fire_at_time)) {
274
-                foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
275
-                    if (isset($ee_cron_tasks_to_remove[$hook_name])
276
-                        && is_array($ee_cron_tasks_to_remove[$hook_name])
277
-                    ) {
278
-                        unset($crons[$timestamp][$hook_name]);
279
-                    }
280
-                }
281
-                //also take care of any empty cron timestamps.
282
-                if (empty($hooks_to_fire_at_time)) {
283
-                    unset($crons[$timestamp]);
284
-                }
285
-            }
286
-        }
287
-        _set_cron_array($crons);
288
-    }
289
-
290
-
291
-    /**
292
-     *    CPT_initialization
293
-     *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
294
-     *
295
-     * @access public
296
-     * @static
297
-     * @return void
298
-     */
299
-    public static function CPT_initialization()
300
-    {
301
-        // register Custom Post Types
302
-        EE_Registry::instance()->load_core('Register_CPTs');
303
-        flush_rewrite_rules();
304
-    }
305
-
306
-
307
-
308
-    /**
309
-     *    reset_and_update_config
310
-     * The following code was moved over from EE_Config so that it will no longer run on every request.
311
-     * If there is old calendar config data saved, then it will get converted on activation.
312
-     * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
313
-     *
314
-     * @access public
315
-     * @static
316
-     * @return void
317
-     */
318
-    public static function reset_and_update_config()
319
-    {
320
-        do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
321
-        add_filter(
322
-            'FHEE__EE_Config___load_core_config__config_settings',
323
-            array('EEH_Activation', 'migrate_old_config_data'),
324
-            10,
325
-            3
326
-        );
327
-        //EE_Config::reset();
328
-        if (! EE_Config::logging_enabled()) {
329
-            delete_option(EE_Config::LOG_NAME);
330
-        }
331
-    }
332
-
333
-
334
-    /**
335
-     *    load_calendar_config
336
-     *
337
-     * @access    public
338
-     * @return    void
339
-     */
340
-    public static function load_calendar_config()
341
-    {
342
-        // grab array of all plugin folders and loop thru it
343
-        $plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
344
-        if (empty($plugins)) {
345
-            return;
346
-        }
347
-        foreach ($plugins as $plugin_path) {
348
-            // grab plugin folder name from path
349
-            $plugin = basename($plugin_path);
350
-            // drill down to Espresso plugins
351
-            // then to calendar related plugins
352
-            if (
353
-                strpos($plugin, 'espresso') !== false
354
-                || strpos($plugin, 'Espresso') !== false
355
-                || strpos($plugin, 'ee4') !== false
356
-                || strpos($plugin, 'EE4') !== false
357
-                || strpos($plugin, 'calendar') !== false
358
-            ) {
359
-                // this is what we are looking for
360
-                $calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
361
-                // does it exist in this folder ?
362
-                if (is_readable($calendar_config)) {
363
-                    // YEAH! let's load it
364
-                    require_once($calendar_config);
365
-                }
366
-            }
367
-        }
368
-    }
369
-
370
-
371
-
372
-    /**
373
-     *    _migrate_old_config_data
374
-     *
375
-     * @access    public
376
-     * @param array|stdClass $settings
377
-     * @param string         $config
378
-     * @param \EE_Config     $EE_Config
379
-     * @return \stdClass
380
-     */
381
-    public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
382
-    {
383
-        $convert_from_array = array('addons');
384
-        // in case old settings were saved as an array
385
-        if (is_array($settings) && in_array($config, $convert_from_array)) {
386
-            // convert existing settings to an object
387
-            $config_array = $settings;
388
-            $settings = new stdClass();
389
-            foreach ($config_array as $key => $value) {
390
-                if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
391
-                    $EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
392
-                } else {
393
-                    $settings->{$key} = $value;
394
-                }
395
-            }
396
-            add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
397
-        }
398
-        return $settings;
399
-    }
400
-
401
-
402
-    /**
403
-     * deactivate_event_espresso
404
-     *
405
-     * @access public
406
-     * @static
407
-     * @return void
408
-     */
409
-    public static function deactivate_event_espresso()
410
-    {
411
-        // check permissions
412
-        if (current_user_can('activate_plugins')) {
413
-            deactivate_plugins(EE_PLUGIN_BASENAME, true);
414
-        }
415
-    }
416
-
417
-
418
-
419
-
420
-
421
-    /**
422
-     * verify_default_pages_exist
423
-     *
424
-     * @access public
425
-     * @static
426
-     * @return void
427
-     */
428
-    public static function verify_default_pages_exist()
429
-    {
430
-        $critical_page_problem = false;
431
-        $critical_pages = array(
432
-            array(
433
-                'id'   => 'reg_page_id',
434
-                'name' => __('Registration Checkout', 'event_espresso'),
435
-                'post' => null,
436
-                'code' => 'ESPRESSO_CHECKOUT',
437
-            ),
438
-            array(
439
-                'id'   => 'txn_page_id',
440
-                'name' => __('Transactions', 'event_espresso'),
441
-                'post' => null,
442
-                'code' => 'ESPRESSO_TXN_PAGE',
443
-            ),
444
-            array(
445
-                'id'   => 'thank_you_page_id',
446
-                'name' => __('Thank You', 'event_espresso'),
447
-                'post' => null,
448
-                'code' => 'ESPRESSO_THANK_YOU',
449
-            ),
450
-            array(
451
-                'id'   => 'cancel_page_id',
452
-                'name' => __('Registration Cancelled', 'event_espresso'),
453
-                'post' => null,
454
-                'code' => 'ESPRESSO_CANCELLED',
455
-            ),
456
-        );
457
-        $EE_Core_Config = EE_Registry::instance()->CFG->core;
458
-        foreach ($critical_pages as $critical_page) {
459
-            // is critical page ID set in config ?
460
-            if ($EE_Core_Config->{$critical_page['id']} !== false) {
461
-                // attempt to find post by ID
462
-                $critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
463
-            }
464
-            // no dice?
465
-            if ($critical_page['post'] === null) {
466
-                // attempt to find post by title
467
-                $critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
468
-                // still nothing?
469
-                if ($critical_page['post'] === null) {
470
-                    $critical_page = EEH_Activation::create_critical_page($critical_page);
471
-                    // REALLY? Still nothing ??!?!?
472
-                    if ($critical_page['post'] === null) {
473
-                        $msg = __(
474
-                            'The Event Espresso critical page configuration settings could not be updated.',
475
-                            'event_espresso'
476
-                        );
477
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
478
-                        break;
479
-                    }
480
-                }
481
-            }
482
-            // check that Post ID matches critical page ID in config
483
-            if (
484
-                isset($critical_page['post']->ID)
485
-                && $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
486
-            ) {
487
-                //update Config with post ID
488
-                $EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
489
-                if (! EE_Config::instance()->update_espresso_config(false, false)) {
490
-                    $msg = __(
491
-                        'The Event Espresso critical page configuration settings could not be updated.',
492
-                        'event_espresso'
493
-                    );
494
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
495
-                }
496
-            }
497
-            $critical_page_problem =
498
-                ! isset($critical_page['post']->post_status)
499
-                || $critical_page['post']->post_status !== 'publish'
500
-                || strpos($critical_page['post']->post_content, $critical_page['code']) === false
501
-                    ? true
502
-                    : $critical_page_problem;
503
-        }
504
-        if ($critical_page_problem) {
505
-            $msg = sprintf(
506
-                __(
507
-                    'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
508
-                    'event_espresso'
509
-                ),
510
-                '<a href="'
511
-                . admin_url('admin.php?page=espresso_general_settings&action=critical_pages')
512
-                . '">'
513
-                . __('Event Espresso Critical Pages Settings', 'event_espresso')
514
-                . '</a>'
515
-            );
516
-            EE_Error::add_persistent_admin_notice('critical_page_problem', $msg);
517
-        }
518
-        if (EE_Error::has_notices()) {
519
-            EE_Error::get_notices(false, true, true);
520
-        }
521
-    }
522
-
523
-
524
-
525
-    /**
526
-     * Returns the first post which uses the specified shortcode
527
-     *
528
-     * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
529
-     *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
530
-     *                             "[ESPRESSO_THANK_YOU"
531
-     *                             (we don't search for the closing shortcode bracket because they might have added
532
-     *                             parameter to the shortcode
533
-     * @return WP_Post or NULl
534
-     */
535
-    public static function get_page_by_ee_shortcode($ee_shortcode)
536
-    {
537
-        global $wpdb;
538
-        $shortcode_and_opening_bracket = '[' . $ee_shortcode;
539
-        $post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
540
-        if ($post_id) {
541
-            return get_post($post_id);
542
-        } else {
543
-            return null;
544
-        }
545
-    }
546
-
547
-
548
-    /**
549
-     *    This function generates a post for critical espresso pages
550
-     *
551
-     * @access public
552
-     * @static
553
-     * @param array $critical_page
554
-     * @return array
555
-     */
556
-    public static function create_critical_page($critical_page)
557
-    {
558
-
559
-        $post_args = array(
560
-            'post_title'     => $critical_page['name'],
561
-            'post_status'    => 'publish',
562
-            'post_type'      => 'page',
563
-            'comment_status' => 'closed',
564
-            'post_content'   => '[' . $critical_page['code'] . ']',
565
-        );
566
-
567
-        $post_id = wp_insert_post($post_args);
568
-        if (! $post_id) {
569
-            $msg = sprintf(
570
-                __('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
571
-                $critical_page['name']
572
-            );
573
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
574
-            return $critical_page;
575
-        }
576
-        // get newly created post's details
577
-        if (! $critical_page['post'] = get_post($post_id)) {
578
-            $msg = sprintf(
579
-                __('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
580
-                $critical_page['name']
581
-            );
582
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
583
-        }
584
-
585
-        return $critical_page;
586
-
587
-    }
588
-
589
-
590
-
591
-
592
-    /**
593
-     * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
594
-     * The role being used to check is filterable.
595
-     *
596
-     * @since  4.6.0
597
-     * @global WPDB $wpdb
598
-     * @return mixed null|int WP_user ID or NULL
599
-     */
600
-    public static function get_default_creator_id()
601
-    {
602
-        global $wpdb;
603
-        if ( ! empty(self::$_default_creator_id)) {
604
-            return self::$_default_creator_id;
605
-        }/**/
606
-        $role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
607
-        //let's allow pre_filtering for early exits by alternative methods for getting id.  We check for truthy result and if so then exit early.
608
-        $pre_filtered_id = apply_filters(
609
-            'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
610
-            false,
611
-            $role_to_check
612
-        );
613
-        if ($pre_filtered_id !== false) {
614
-            return (int)$pre_filtered_id;
615
-        }
616
-        $capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
617
-        $query = $wpdb->prepare(
618
-            "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
619
-            '%' . $role_to_check . '%'
620
-        );
621
-        $user_id = $wpdb->get_var($query);
622
-        $user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
623
-        if ($user_id && (int)$user_id) {
624
-            self::$_default_creator_id = (int)$user_id;
625
-            return self::$_default_creator_id;
626
-        } else {
627
-            return null;
628
-        }
629
-    }
630
-
631
-
632
-
633
-    /**
634
-     * used by EE and EE addons during plugin activation to create tables.
635
-     * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
636
-     * but includes extra logic regarding activations.
637
-     *
638
-     * @access public
639
-     * @static
640
-     * @param string  $table_name              without the $wpdb->prefix
641
-     * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
642
-     *                                         table query)
643
-     * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
644
-     * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
645
-     *                                         and new once this function is done (ie, you really do want to CREATE a
646
-     *                                         table, and expect it to be empty once you're done) leave as FALSE when
647
-     *                                         you just want to verify the table exists and matches this definition
648
-     *                                         (and if it HAS data in it you want to leave it be)
649
-     * @return void
650
-     * @throws EE_Error if there are database errors
651
-     */
652
-    public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
653
-    {
654
-        if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
655
-            return;
656
-        }
657
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
658
-        if ( ! function_exists('dbDelta')) {
659
-            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
660
-        }
661
-        $tableAnalysis = \EEH_Activation::getTableAnalysis();
662
-        $wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
663
-        // do we need to first delete an existing version of this table ?
664
-        if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
665
-            // ok, delete the table... but ONLY if it's empty
666
-            $deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
667
-            // table is NOT empty, are you SURE you want to delete this table ???
668
-            if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
669
-                \EEH_Activation::getTableManager()->dropTable($wp_table_name);
670
-            } else if ( ! $deleted_safely) {
671
-                // so we should be more cautious rather than just dropping tables so easily
672
-                error_log(
673
-                    sprintf(
674
-                        __(
675
-                            'It appears that database table "%1$s" exists when it shouldn\'t, and therefore may contain erroneous data. If you have previously restored your database from a backup that didn\'t remove the old tables, then we recommend: %2$s 1. create a new COMPLETE backup of your database, %2$s 2. delete ALL tables from your database, %2$s 3. restore to your previous backup. %2$s If, however, you have not restored to a backup, then somehow your "%3$s" WordPress option could not be read. You can probably ignore this message, but should investigate why that option is being removed.',
676
-                            'event_espresso'
677
-                        ),
678
-                        $wp_table_name,
679
-                        '<br/>',
680
-                        'espresso_db_update'
681
-                    )
682
-                );
683
-            }
684
-        }
685
-        $engine = str_replace('ENGINE=', '', $engine);
686
-        \EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
687
-    }
688
-
689
-
690
-
691
-    /**
692
-     *    add_column_if_it_doesn't_exist
693
-     *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
694
-     *
695
-     * @access     public
696
-     * @static
697
-     * @deprecated instead use TableManager::addColumn()
698
-     * @param string $table_name  (without "wp_", eg "esp_attendee"
699
-     * @param string $column_name
700
-     * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
701
-     *                            'VARCHAR(10)'
702
-     * @return bool|int
703
-     */
704
-    public static function add_column_if_it_doesnt_exist(
705
-        $table_name,
706
-        $column_name,
707
-        $column_info = 'INT UNSIGNED NOT NULL'
708
-    ) {
709
-        return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
710
-    }
711
-
712
-
713
-    /**
714
-     * get_fields_on_table
715
-     * Gets all the fields on the database table.
716
-     *
717
-     * @access     public
718
-     * @deprecated instead use TableManager::getTableColumns()
719
-     * @static
720
-     * @param string $table_name , without prefixed $wpdb->prefix
721
-     * @return array of database column names
722
-     */
723
-    public static function get_fields_on_table($table_name = null)
724
-    {
725
-        return \EEH_Activation::getTableManager()->getTableColumns($table_name);
726
-    }
727
-
728
-
729
-    /**
730
-     * db_table_is_empty
731
-     *
732
-     * @access     public\
733
-     * @deprecated instead use TableAnalysis::tableIsEmpty()
734
-     * @static
735
-     * @param string $table_name
736
-     * @return bool
737
-     */
738
-    public static function db_table_is_empty($table_name)
739
-    {
740
-        return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
741
-    }
742
-
743
-
744
-    /**
745
-     * delete_db_table_if_empty
746
-     *
747
-     * @access public
748
-     * @static
749
-     * @param string $table_name
750
-     * @return bool | int
751
-     */
752
-    public static function delete_db_table_if_empty($table_name)
753
-    {
754
-        if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
755
-            return \EEH_Activation::getTableManager()->dropTable($table_name);
756
-        }
757
-        return false;
758
-    }
759
-
760
-
761
-    /**
762
-     * delete_unused_db_table
763
-     *
764
-     * @access     public
765
-     * @static
766
-     * @deprecated instead use TableManager::dropTable()
767
-     * @param string $table_name
768
-     * @return bool | int
769
-     */
770
-    public static function delete_unused_db_table($table_name)
771
-    {
772
-        return \EEH_Activation::getTableManager()->dropTable($table_name);
773
-    }
774
-
775
-
776
-    /**
777
-     * drop_index
778
-     *
779
-     * @access     public
780
-     * @static
781
-     * @deprecated instead use TableManager::dropIndex()
782
-     * @param string $table_name
783
-     * @param string $index_name
784
-     * @return bool | int
785
-     */
786
-    public static function drop_index($table_name, $index_name)
787
-    {
788
-        return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
789
-    }
790
-
791
-
792
-
793
-    /**
794
-     * create_database_tables
795
-     *
796
-     * @access public
797
-     * @static
798
-     * @throws EE_Error
799
-     * @return boolean success (whether database is setup properly or not)
800
-     */
801
-    public static function create_database_tables()
802
-    {
803
-        EE_Registry::instance()->load_core('Data_Migration_Manager');
804
-        //find the migration script that sets the database to be compatible with the code
805
-        $dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
806
-        if ($dms_name) {
807
-            $current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
808
-            $current_data_migration_script->set_migrating(false);
809
-            $current_data_migration_script->schema_changes_before_migration();
810
-            $current_data_migration_script->schema_changes_after_migration();
811
-            if ($current_data_migration_script->get_errors()) {
812
-                if (WP_DEBUG) {
813
-                    foreach ($current_data_migration_script->get_errors() as $error) {
814
-                        EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
815
-                    }
816
-                } else {
817
-                    EE_Error::add_error(
818
-                        __(
819
-                            'There were errors creating the Event Espresso database tables and Event Espresso has been 
271
+		$ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
272
+		foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
273
+			if (is_array($hooks_to_fire_at_time)) {
274
+				foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
275
+					if (isset($ee_cron_tasks_to_remove[$hook_name])
276
+						&& is_array($ee_cron_tasks_to_remove[$hook_name])
277
+					) {
278
+						unset($crons[$timestamp][$hook_name]);
279
+					}
280
+				}
281
+				//also take care of any empty cron timestamps.
282
+				if (empty($hooks_to_fire_at_time)) {
283
+					unset($crons[$timestamp]);
284
+				}
285
+			}
286
+		}
287
+		_set_cron_array($crons);
288
+	}
289
+
290
+
291
+	/**
292
+	 *    CPT_initialization
293
+	 *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
294
+	 *
295
+	 * @access public
296
+	 * @static
297
+	 * @return void
298
+	 */
299
+	public static function CPT_initialization()
300
+	{
301
+		// register Custom Post Types
302
+		EE_Registry::instance()->load_core('Register_CPTs');
303
+		flush_rewrite_rules();
304
+	}
305
+
306
+
307
+
308
+	/**
309
+	 *    reset_and_update_config
310
+	 * The following code was moved over from EE_Config so that it will no longer run on every request.
311
+	 * If there is old calendar config data saved, then it will get converted on activation.
312
+	 * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
313
+	 *
314
+	 * @access public
315
+	 * @static
316
+	 * @return void
317
+	 */
318
+	public static function reset_and_update_config()
319
+	{
320
+		do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
321
+		add_filter(
322
+			'FHEE__EE_Config___load_core_config__config_settings',
323
+			array('EEH_Activation', 'migrate_old_config_data'),
324
+			10,
325
+			3
326
+		);
327
+		//EE_Config::reset();
328
+		if (! EE_Config::logging_enabled()) {
329
+			delete_option(EE_Config::LOG_NAME);
330
+		}
331
+	}
332
+
333
+
334
+	/**
335
+	 *    load_calendar_config
336
+	 *
337
+	 * @access    public
338
+	 * @return    void
339
+	 */
340
+	public static function load_calendar_config()
341
+	{
342
+		// grab array of all plugin folders and loop thru it
343
+		$plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
344
+		if (empty($plugins)) {
345
+			return;
346
+		}
347
+		foreach ($plugins as $plugin_path) {
348
+			// grab plugin folder name from path
349
+			$plugin = basename($plugin_path);
350
+			// drill down to Espresso plugins
351
+			// then to calendar related plugins
352
+			if (
353
+				strpos($plugin, 'espresso') !== false
354
+				|| strpos($plugin, 'Espresso') !== false
355
+				|| strpos($plugin, 'ee4') !== false
356
+				|| strpos($plugin, 'EE4') !== false
357
+				|| strpos($plugin, 'calendar') !== false
358
+			) {
359
+				// this is what we are looking for
360
+				$calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
361
+				// does it exist in this folder ?
362
+				if (is_readable($calendar_config)) {
363
+					// YEAH! let's load it
364
+					require_once($calendar_config);
365
+				}
366
+			}
367
+		}
368
+	}
369
+
370
+
371
+
372
+	/**
373
+	 *    _migrate_old_config_data
374
+	 *
375
+	 * @access    public
376
+	 * @param array|stdClass $settings
377
+	 * @param string         $config
378
+	 * @param \EE_Config     $EE_Config
379
+	 * @return \stdClass
380
+	 */
381
+	public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
382
+	{
383
+		$convert_from_array = array('addons');
384
+		// in case old settings were saved as an array
385
+		if (is_array($settings) && in_array($config, $convert_from_array)) {
386
+			// convert existing settings to an object
387
+			$config_array = $settings;
388
+			$settings = new stdClass();
389
+			foreach ($config_array as $key => $value) {
390
+				if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
391
+					$EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
392
+				} else {
393
+					$settings->{$key} = $value;
394
+				}
395
+			}
396
+			add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
397
+		}
398
+		return $settings;
399
+	}
400
+
401
+
402
+	/**
403
+	 * deactivate_event_espresso
404
+	 *
405
+	 * @access public
406
+	 * @static
407
+	 * @return void
408
+	 */
409
+	public static function deactivate_event_espresso()
410
+	{
411
+		// check permissions
412
+		if (current_user_can('activate_plugins')) {
413
+			deactivate_plugins(EE_PLUGIN_BASENAME, true);
414
+		}
415
+	}
416
+
417
+
418
+
419
+
420
+
421
+	/**
422
+	 * verify_default_pages_exist
423
+	 *
424
+	 * @access public
425
+	 * @static
426
+	 * @return void
427
+	 */
428
+	public static function verify_default_pages_exist()
429
+	{
430
+		$critical_page_problem = false;
431
+		$critical_pages = array(
432
+			array(
433
+				'id'   => 'reg_page_id',
434
+				'name' => __('Registration Checkout', 'event_espresso'),
435
+				'post' => null,
436
+				'code' => 'ESPRESSO_CHECKOUT',
437
+			),
438
+			array(
439
+				'id'   => 'txn_page_id',
440
+				'name' => __('Transactions', 'event_espresso'),
441
+				'post' => null,
442
+				'code' => 'ESPRESSO_TXN_PAGE',
443
+			),
444
+			array(
445
+				'id'   => 'thank_you_page_id',
446
+				'name' => __('Thank You', 'event_espresso'),
447
+				'post' => null,
448
+				'code' => 'ESPRESSO_THANK_YOU',
449
+			),
450
+			array(
451
+				'id'   => 'cancel_page_id',
452
+				'name' => __('Registration Cancelled', 'event_espresso'),
453
+				'post' => null,
454
+				'code' => 'ESPRESSO_CANCELLED',
455
+			),
456
+		);
457
+		$EE_Core_Config = EE_Registry::instance()->CFG->core;
458
+		foreach ($critical_pages as $critical_page) {
459
+			// is critical page ID set in config ?
460
+			if ($EE_Core_Config->{$critical_page['id']} !== false) {
461
+				// attempt to find post by ID
462
+				$critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
463
+			}
464
+			// no dice?
465
+			if ($critical_page['post'] === null) {
466
+				// attempt to find post by title
467
+				$critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
468
+				// still nothing?
469
+				if ($critical_page['post'] === null) {
470
+					$critical_page = EEH_Activation::create_critical_page($critical_page);
471
+					// REALLY? Still nothing ??!?!?
472
+					if ($critical_page['post'] === null) {
473
+						$msg = __(
474
+							'The Event Espresso critical page configuration settings could not be updated.',
475
+							'event_espresso'
476
+						);
477
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
478
+						break;
479
+					}
480
+				}
481
+			}
482
+			// check that Post ID matches critical page ID in config
483
+			if (
484
+				isset($critical_page['post']->ID)
485
+				&& $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
486
+			) {
487
+				//update Config with post ID
488
+				$EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
489
+				if (! EE_Config::instance()->update_espresso_config(false, false)) {
490
+					$msg = __(
491
+						'The Event Espresso critical page configuration settings could not be updated.',
492
+						'event_espresso'
493
+					);
494
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
495
+				}
496
+			}
497
+			$critical_page_problem =
498
+				! isset($critical_page['post']->post_status)
499
+				|| $critical_page['post']->post_status !== 'publish'
500
+				|| strpos($critical_page['post']->post_content, $critical_page['code']) === false
501
+					? true
502
+					: $critical_page_problem;
503
+		}
504
+		if ($critical_page_problem) {
505
+			$msg = sprintf(
506
+				__(
507
+					'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
508
+					'event_espresso'
509
+				),
510
+				'<a href="'
511
+				. admin_url('admin.php?page=espresso_general_settings&action=critical_pages')
512
+				. '">'
513
+				. __('Event Espresso Critical Pages Settings', 'event_espresso')
514
+				. '</a>'
515
+			);
516
+			EE_Error::add_persistent_admin_notice('critical_page_problem', $msg);
517
+		}
518
+		if (EE_Error::has_notices()) {
519
+			EE_Error::get_notices(false, true, true);
520
+		}
521
+	}
522
+
523
+
524
+
525
+	/**
526
+	 * Returns the first post which uses the specified shortcode
527
+	 *
528
+	 * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
529
+	 *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
530
+	 *                             "[ESPRESSO_THANK_YOU"
531
+	 *                             (we don't search for the closing shortcode bracket because they might have added
532
+	 *                             parameter to the shortcode
533
+	 * @return WP_Post or NULl
534
+	 */
535
+	public static function get_page_by_ee_shortcode($ee_shortcode)
536
+	{
537
+		global $wpdb;
538
+		$shortcode_and_opening_bracket = '[' . $ee_shortcode;
539
+		$post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
540
+		if ($post_id) {
541
+			return get_post($post_id);
542
+		} else {
543
+			return null;
544
+		}
545
+	}
546
+
547
+
548
+	/**
549
+	 *    This function generates a post for critical espresso pages
550
+	 *
551
+	 * @access public
552
+	 * @static
553
+	 * @param array $critical_page
554
+	 * @return array
555
+	 */
556
+	public static function create_critical_page($critical_page)
557
+	{
558
+
559
+		$post_args = array(
560
+			'post_title'     => $critical_page['name'],
561
+			'post_status'    => 'publish',
562
+			'post_type'      => 'page',
563
+			'comment_status' => 'closed',
564
+			'post_content'   => '[' . $critical_page['code'] . ']',
565
+		);
566
+
567
+		$post_id = wp_insert_post($post_args);
568
+		if (! $post_id) {
569
+			$msg = sprintf(
570
+				__('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
571
+				$critical_page['name']
572
+			);
573
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
574
+			return $critical_page;
575
+		}
576
+		// get newly created post's details
577
+		if (! $critical_page['post'] = get_post($post_id)) {
578
+			$msg = sprintf(
579
+				__('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
580
+				$critical_page['name']
581
+			);
582
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
583
+		}
584
+
585
+		return $critical_page;
586
+
587
+	}
588
+
589
+
590
+
591
+
592
+	/**
593
+	 * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
594
+	 * The role being used to check is filterable.
595
+	 *
596
+	 * @since  4.6.0
597
+	 * @global WPDB $wpdb
598
+	 * @return mixed null|int WP_user ID or NULL
599
+	 */
600
+	public static function get_default_creator_id()
601
+	{
602
+		global $wpdb;
603
+		if ( ! empty(self::$_default_creator_id)) {
604
+			return self::$_default_creator_id;
605
+		}/**/
606
+		$role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
607
+		//let's allow pre_filtering for early exits by alternative methods for getting id.  We check for truthy result and if so then exit early.
608
+		$pre_filtered_id = apply_filters(
609
+			'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
610
+			false,
611
+			$role_to_check
612
+		);
613
+		if ($pre_filtered_id !== false) {
614
+			return (int)$pre_filtered_id;
615
+		}
616
+		$capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
617
+		$query = $wpdb->prepare(
618
+			"SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
619
+			'%' . $role_to_check . '%'
620
+		);
621
+		$user_id = $wpdb->get_var($query);
622
+		$user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
623
+		if ($user_id && (int)$user_id) {
624
+			self::$_default_creator_id = (int)$user_id;
625
+			return self::$_default_creator_id;
626
+		} else {
627
+			return null;
628
+		}
629
+	}
630
+
631
+
632
+
633
+	/**
634
+	 * used by EE and EE addons during plugin activation to create tables.
635
+	 * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
636
+	 * but includes extra logic regarding activations.
637
+	 *
638
+	 * @access public
639
+	 * @static
640
+	 * @param string  $table_name              without the $wpdb->prefix
641
+	 * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
642
+	 *                                         table query)
643
+	 * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
644
+	 * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
645
+	 *                                         and new once this function is done (ie, you really do want to CREATE a
646
+	 *                                         table, and expect it to be empty once you're done) leave as FALSE when
647
+	 *                                         you just want to verify the table exists and matches this definition
648
+	 *                                         (and if it HAS data in it you want to leave it be)
649
+	 * @return void
650
+	 * @throws EE_Error if there are database errors
651
+	 */
652
+	public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
653
+	{
654
+		if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
655
+			return;
656
+		}
657
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
658
+		if ( ! function_exists('dbDelta')) {
659
+			require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
660
+		}
661
+		$tableAnalysis = \EEH_Activation::getTableAnalysis();
662
+		$wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
663
+		// do we need to first delete an existing version of this table ?
664
+		if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
665
+			// ok, delete the table... but ONLY if it's empty
666
+			$deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
667
+			// table is NOT empty, are you SURE you want to delete this table ???
668
+			if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
669
+				\EEH_Activation::getTableManager()->dropTable($wp_table_name);
670
+			} else if ( ! $deleted_safely) {
671
+				// so we should be more cautious rather than just dropping tables so easily
672
+				error_log(
673
+					sprintf(
674
+						__(
675
+							'It appears that database table "%1$s" exists when it shouldn\'t, and therefore may contain erroneous data. If you have previously restored your database from a backup that didn\'t remove the old tables, then we recommend: %2$s 1. create a new COMPLETE backup of your database, %2$s 2. delete ALL tables from your database, %2$s 3. restore to your previous backup. %2$s If, however, you have not restored to a backup, then somehow your "%3$s" WordPress option could not be read. You can probably ignore this message, but should investigate why that option is being removed.',
676
+							'event_espresso'
677
+						),
678
+						$wp_table_name,
679
+						'<br/>',
680
+						'espresso_db_update'
681
+					)
682
+				);
683
+			}
684
+		}
685
+		$engine = str_replace('ENGINE=', '', $engine);
686
+		\EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
687
+	}
688
+
689
+
690
+
691
+	/**
692
+	 *    add_column_if_it_doesn't_exist
693
+	 *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
694
+	 *
695
+	 * @access     public
696
+	 * @static
697
+	 * @deprecated instead use TableManager::addColumn()
698
+	 * @param string $table_name  (without "wp_", eg "esp_attendee"
699
+	 * @param string $column_name
700
+	 * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
701
+	 *                            'VARCHAR(10)'
702
+	 * @return bool|int
703
+	 */
704
+	public static function add_column_if_it_doesnt_exist(
705
+		$table_name,
706
+		$column_name,
707
+		$column_info = 'INT UNSIGNED NOT NULL'
708
+	) {
709
+		return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
710
+	}
711
+
712
+
713
+	/**
714
+	 * get_fields_on_table
715
+	 * Gets all the fields on the database table.
716
+	 *
717
+	 * @access     public
718
+	 * @deprecated instead use TableManager::getTableColumns()
719
+	 * @static
720
+	 * @param string $table_name , without prefixed $wpdb->prefix
721
+	 * @return array of database column names
722
+	 */
723
+	public static function get_fields_on_table($table_name = null)
724
+	{
725
+		return \EEH_Activation::getTableManager()->getTableColumns($table_name);
726
+	}
727
+
728
+
729
+	/**
730
+	 * db_table_is_empty
731
+	 *
732
+	 * @access     public\
733
+	 * @deprecated instead use TableAnalysis::tableIsEmpty()
734
+	 * @static
735
+	 * @param string $table_name
736
+	 * @return bool
737
+	 */
738
+	public static function db_table_is_empty($table_name)
739
+	{
740
+		return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
741
+	}
742
+
743
+
744
+	/**
745
+	 * delete_db_table_if_empty
746
+	 *
747
+	 * @access public
748
+	 * @static
749
+	 * @param string $table_name
750
+	 * @return bool | int
751
+	 */
752
+	public static function delete_db_table_if_empty($table_name)
753
+	{
754
+		if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
755
+			return \EEH_Activation::getTableManager()->dropTable($table_name);
756
+		}
757
+		return false;
758
+	}
759
+
760
+
761
+	/**
762
+	 * delete_unused_db_table
763
+	 *
764
+	 * @access     public
765
+	 * @static
766
+	 * @deprecated instead use TableManager::dropTable()
767
+	 * @param string $table_name
768
+	 * @return bool | int
769
+	 */
770
+	public static function delete_unused_db_table($table_name)
771
+	{
772
+		return \EEH_Activation::getTableManager()->dropTable($table_name);
773
+	}
774
+
775
+
776
+	/**
777
+	 * drop_index
778
+	 *
779
+	 * @access     public
780
+	 * @static
781
+	 * @deprecated instead use TableManager::dropIndex()
782
+	 * @param string $table_name
783
+	 * @param string $index_name
784
+	 * @return bool | int
785
+	 */
786
+	public static function drop_index($table_name, $index_name)
787
+	{
788
+		return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
789
+	}
790
+
791
+
792
+
793
+	/**
794
+	 * create_database_tables
795
+	 *
796
+	 * @access public
797
+	 * @static
798
+	 * @throws EE_Error
799
+	 * @return boolean success (whether database is setup properly or not)
800
+	 */
801
+	public static function create_database_tables()
802
+	{
803
+		EE_Registry::instance()->load_core('Data_Migration_Manager');
804
+		//find the migration script that sets the database to be compatible with the code
805
+		$dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
806
+		if ($dms_name) {
807
+			$current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
808
+			$current_data_migration_script->set_migrating(false);
809
+			$current_data_migration_script->schema_changes_before_migration();
810
+			$current_data_migration_script->schema_changes_after_migration();
811
+			if ($current_data_migration_script->get_errors()) {
812
+				if (WP_DEBUG) {
813
+					foreach ($current_data_migration_script->get_errors() as $error) {
814
+						EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
815
+					}
816
+				} else {
817
+					EE_Error::add_error(
818
+						__(
819
+							'There were errors creating the Event Espresso database tables and Event Espresso has been 
820 820
                             deactivated. To view the errors, please enable WP_DEBUG in your wp-config.php file.',
821
-                            'event_espresso'
822
-                        )
823
-                    );
824
-                }
825
-                return false;
826
-            }
827
-            EE_Data_Migration_Manager::instance()->update_current_database_state_to();
828
-        } else {
829
-            EE_Error::add_error(
830
-                __(
831
-                    'Could not determine most up-to-date data migration script from which to pull database schema
821
+							'event_espresso'
822
+						)
823
+					);
824
+				}
825
+				return false;
826
+			}
827
+			EE_Data_Migration_Manager::instance()->update_current_database_state_to();
828
+		} else {
829
+			EE_Error::add_error(
830
+				__(
831
+					'Could not determine most up-to-date data migration script from which to pull database schema
832 832
                      structure. So database is probably not setup properly',
833
-                    'event_espresso'
834
-                ),
835
-                __FILE__,
836
-                __FUNCTION__,
837
-                __LINE__
838
-            );
839
-            return false;
840
-        }
841
-        return true;
842
-    }
843
-
844
-
845
-
846
-    /**
847
-     * initialize_system_questions
848
-     *
849
-     * @access public
850
-     * @static
851
-     * @return void
852
-     */
853
-    public static function initialize_system_questions()
854
-    {
855
-        // QUESTION GROUPS
856
-        global $wpdb;
857
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
858
-        $SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
859
-        // what we have
860
-        $question_groups = $wpdb->get_col($SQL);
861
-        // check the response
862
-        $question_groups = is_array($question_groups) ? $question_groups : array();
863
-        // what we should have
864
-        $QSG_systems = array(1, 2);
865
-        // loop thru what we should have and compare to what we have
866
-        foreach ($QSG_systems as $QSG_system) {
867
-            // reset values array
868
-            $QSG_values = array();
869
-            // if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
870
-            if (! in_array("$QSG_system", $question_groups)) {
871
-                // add it
872
-                switch ($QSG_system) {
873
-                    case 1:
874
-                        $QSG_values = array(
875
-                            'QSG_name'            => __('Personal Information', 'event_espresso'),
876
-                            'QSG_identifier'      => 'personal-information-' . time(),
877
-                            'QSG_desc'            => '',
878
-                            'QSG_order'           => 1,
879
-                            'QSG_show_group_name' => 1,
880
-                            'QSG_show_group_desc' => 1,
881
-                            'QSG_system'          => EEM_Question_Group::system_personal,
882
-                            'QSG_deleted'         => 0,
883
-                        );
884
-                        break;
885
-                    case 2:
886
-                        $QSG_values = array(
887
-                            'QSG_name'            => __('Address Information', 'event_espresso'),
888
-                            'QSG_identifier'      => 'address-information-' . time(),
889
-                            'QSG_desc'            => '',
890
-                            'QSG_order'           => 2,
891
-                            'QSG_show_group_name' => 1,
892
-                            'QSG_show_group_desc' => 1,
893
-                            'QSG_system'          => EEM_Question_Group::system_address,
894
-                            'QSG_deleted'         => 0,
895
-                        );
896
-                        break;
897
-                }
898
-                // make sure we have some values before inserting them
899
-                if (! empty($QSG_values)) {
900
-                    // insert system question
901
-                    $wpdb->insert(
902
-                        $table_name,
903
-                        $QSG_values,
904
-                        array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
905
-                    );
906
-                    $QSG_IDs[$QSG_system] = $wpdb->insert_id;
907
-                }
908
-            }
909
-        }
910
-        // QUESTIONS
911
-        global $wpdb;
912
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
913
-        $SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
914
-        // what we have
915
-        $questions = $wpdb->get_col($SQL);
916
-        // what we should have
917
-        $QST_systems = array(
918
-            'fname',
919
-            'lname',
920
-            'email',
921
-            'address',
922
-            'address2',
923
-            'city',
924
-            'country',
925
-            'state',
926
-            'zip',
927
-            'phone',
928
-        );
929
-        $order_for_group_1 = 1;
930
-        $order_for_group_2 = 1;
931
-        // loop thru what we should have and compare to what we have
932
-        foreach ($QST_systems as $QST_system) {
933
-            // reset values array
934
-            $QST_values = array();
935
-            // if we don't have what we should have
936
-            if (! in_array($QST_system, $questions)) {
937
-                // add it
938
-                switch ($QST_system) {
939
-                    case 'fname':
940
-                        $QST_values = array(
941
-                            'QST_display_text'  => __('First Name', 'event_espresso'),
942
-                            'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
943
-                            'QST_system'        => 'fname',
944
-                            'QST_type'          => 'TEXT',
945
-                            'QST_required'      => 1,
946
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
947
-                            'QST_order'         => 1,
948
-                            'QST_admin_only'    => 0,
949
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
950
-                            'QST_wp_user'       => self::get_default_creator_id(),
951
-                            'QST_deleted'       => 0,
952
-                        );
953
-                        break;
954
-                    case 'lname':
955
-                        $QST_values = array(
956
-                            'QST_display_text'  => __('Last Name', 'event_espresso'),
957
-                            'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
958
-                            'QST_system'        => 'lname',
959
-                            'QST_type'          => 'TEXT',
960
-                            'QST_required'      => 1,
961
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
962
-                            'QST_order'         => 2,
963
-                            'QST_admin_only'    => 0,
964
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
965
-                            'QST_wp_user'       => self::get_default_creator_id(),
966
-                            'QST_deleted'       => 0,
967
-                        );
968
-                        break;
969
-                    case 'email':
970
-                        $QST_values = array(
971
-                            'QST_display_text'  => __('Email Address', 'event_espresso'),
972
-                            'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
973
-                            'QST_system'        => 'email',
974
-                            'QST_type'          => 'EMAIL',
975
-                            'QST_required'      => 1,
976
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
977
-                            'QST_order'         => 3,
978
-                            'QST_admin_only'    => 0,
979
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
980
-                            'QST_wp_user'       => self::get_default_creator_id(),
981
-                            'QST_deleted'       => 0,
982
-                        );
983
-                        break;
984
-                    case 'address':
985
-                        $QST_values = array(
986
-                            'QST_display_text'  => __('Address', 'event_espresso'),
987
-                            'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
988
-                            'QST_system'        => 'address',
989
-                            'QST_type'          => 'TEXT',
990
-                            'QST_required'      => 0,
991
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
992
-                            'QST_order'         => 4,
993
-                            'QST_admin_only'    => 0,
994
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
995
-                            'QST_wp_user'       => self::get_default_creator_id(),
996
-                            'QST_deleted'       => 0,
997
-                        );
998
-                        break;
999
-                    case 'address2':
1000
-                        $QST_values = array(
1001
-                            'QST_display_text'  => __('Address2', 'event_espresso'),
1002
-                            'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
1003
-                            'QST_system'        => 'address2',
1004
-                            'QST_type'          => 'TEXT',
1005
-                            'QST_required'      => 0,
1006
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1007
-                            'QST_order'         => 5,
1008
-                            'QST_admin_only'    => 0,
1009
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1010
-                            'QST_wp_user'       => self::get_default_creator_id(),
1011
-                            'QST_deleted'       => 0,
1012
-                        );
1013
-                        break;
1014
-                    case 'city':
1015
-                        $QST_values = array(
1016
-                            'QST_display_text'  => __('City', 'event_espresso'),
1017
-                            'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1018
-                            'QST_system'        => 'city',
1019
-                            'QST_type'          => 'TEXT',
1020
-                            'QST_required'      => 0,
1021
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1022
-                            'QST_order'         => 6,
1023
-                            'QST_admin_only'    => 0,
1024
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1025
-                            'QST_wp_user'       => self::get_default_creator_id(),
1026
-                            'QST_deleted'       => 0,
1027
-                        );
1028
-                        break;
1029
-                    case 'country':
1030
-                        $QST_values = array(
1031
-                            'QST_display_text'  => __('Country', 'event_espresso'),
1032
-                            'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1033
-                            'QST_system'        => 'country',
1034
-                            'QST_type'          => 'COUNTRY',
1035
-                            'QST_required'      => 0,
1036
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1037
-                            'QST_order'         => 7,
1038
-                            'QST_admin_only'    => 0,
1039
-                            'QST_wp_user'       => self::get_default_creator_id(),
1040
-                            'QST_deleted'       => 0,
1041
-                        );
1042
-                        break;
1043
-                    case 'state':
1044
-                        $QST_values = array(
1045
-                            'QST_display_text'  => __('State/Province', 'event_espresso'),
1046
-                            'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1047
-                            'QST_system'        => 'state',
1048
-                            'QST_type'          => 'STATE',
1049
-                            'QST_required'      => 0,
1050
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1051
-                            'QST_order'         => 8,
1052
-                            'QST_admin_only'    => 0,
1053
-                            'QST_wp_user'       => self::get_default_creator_id(),
1054
-                            'QST_deleted'       => 0,
1055
-                        );
1056
-                        break;
1057
-                    case 'zip':
1058
-                        $QST_values = array(
1059
-                            'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1060
-                            'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1061
-                            'QST_system'        => 'zip',
1062
-                            'QST_type'          => 'TEXT',
1063
-                            'QST_required'      => 0,
1064
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1065
-                            'QST_order'         => 9,
1066
-                            'QST_admin_only'    => 0,
1067
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1068
-                            'QST_wp_user'       => self::get_default_creator_id(),
1069
-                            'QST_deleted'       => 0,
1070
-                        );
1071
-                        break;
1072
-                    case 'phone':
1073
-                        $QST_values = array(
1074
-                            'QST_display_text'  => __('Phone Number', 'event_espresso'),
1075
-                            'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1076
-                            'QST_system'        => 'phone',
1077
-                            'QST_type'          => 'TEXT',
1078
-                            'QST_required'      => 0,
1079
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1080
-                            'QST_order'         => 10,
1081
-                            'QST_admin_only'    => 0,
1082
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1083
-                            'QST_wp_user'       => self::get_default_creator_id(),
1084
-                            'QST_deleted'       => 0,
1085
-                        );
1086
-                        break;
1087
-                }
1088
-                if (! empty($QST_values)) {
1089
-                    // insert system question
1090
-                    $wpdb->insert(
1091
-                        $table_name,
1092
-                        $QST_values,
1093
-                        array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1094
-                    );
1095
-                    $QST_ID = $wpdb->insert_id;
1096
-                    // QUESTION GROUP QUESTIONS
1097
-                    if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1098
-                        $system_question_we_want = EEM_Question_Group::system_personal;
1099
-                    } else {
1100
-                        $system_question_we_want = EEM_Question_Group::system_address;
1101
-                    }
1102
-                    if (isset($QSG_IDs[$system_question_we_want])) {
1103
-                        $QSG_ID = $QSG_IDs[$system_question_we_want];
1104
-                    } else {
1105
-                        $id_col = EEM_Question_Group::instance()
1106
-                                                    ->get_col(array(array('QSG_system' => $system_question_we_want)));
1107
-                        if (is_array($id_col)) {
1108
-                            $QSG_ID = reset($id_col);
1109
-                        } else {
1110
-                            //ok so we didn't find it in the db either?? that's weird because we should have inserted it at the start of this method
1111
-                            EE_Log::instance()->log(
1112
-                                __FILE__,
1113
-                                __FUNCTION__,
1114
-                                sprintf(
1115
-                                    __(
1116
-                                        'Could not associate question %1$s to a question group because no system question
833
+					'event_espresso'
834
+				),
835
+				__FILE__,
836
+				__FUNCTION__,
837
+				__LINE__
838
+			);
839
+			return false;
840
+		}
841
+		return true;
842
+	}
843
+
844
+
845
+
846
+	/**
847
+	 * initialize_system_questions
848
+	 *
849
+	 * @access public
850
+	 * @static
851
+	 * @return void
852
+	 */
853
+	public static function initialize_system_questions()
854
+	{
855
+		// QUESTION GROUPS
856
+		global $wpdb;
857
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
858
+		$SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
859
+		// what we have
860
+		$question_groups = $wpdb->get_col($SQL);
861
+		// check the response
862
+		$question_groups = is_array($question_groups) ? $question_groups : array();
863
+		// what we should have
864
+		$QSG_systems = array(1, 2);
865
+		// loop thru what we should have and compare to what we have
866
+		foreach ($QSG_systems as $QSG_system) {
867
+			// reset values array
868
+			$QSG_values = array();
869
+			// if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
870
+			if (! in_array("$QSG_system", $question_groups)) {
871
+				// add it
872
+				switch ($QSG_system) {
873
+					case 1:
874
+						$QSG_values = array(
875
+							'QSG_name'            => __('Personal Information', 'event_espresso'),
876
+							'QSG_identifier'      => 'personal-information-' . time(),
877
+							'QSG_desc'            => '',
878
+							'QSG_order'           => 1,
879
+							'QSG_show_group_name' => 1,
880
+							'QSG_show_group_desc' => 1,
881
+							'QSG_system'          => EEM_Question_Group::system_personal,
882
+							'QSG_deleted'         => 0,
883
+						);
884
+						break;
885
+					case 2:
886
+						$QSG_values = array(
887
+							'QSG_name'            => __('Address Information', 'event_espresso'),
888
+							'QSG_identifier'      => 'address-information-' . time(),
889
+							'QSG_desc'            => '',
890
+							'QSG_order'           => 2,
891
+							'QSG_show_group_name' => 1,
892
+							'QSG_show_group_desc' => 1,
893
+							'QSG_system'          => EEM_Question_Group::system_address,
894
+							'QSG_deleted'         => 0,
895
+						);
896
+						break;
897
+				}
898
+				// make sure we have some values before inserting them
899
+				if (! empty($QSG_values)) {
900
+					// insert system question
901
+					$wpdb->insert(
902
+						$table_name,
903
+						$QSG_values,
904
+						array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
905
+					);
906
+					$QSG_IDs[$QSG_system] = $wpdb->insert_id;
907
+				}
908
+			}
909
+		}
910
+		// QUESTIONS
911
+		global $wpdb;
912
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
913
+		$SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
914
+		// what we have
915
+		$questions = $wpdb->get_col($SQL);
916
+		// what we should have
917
+		$QST_systems = array(
918
+			'fname',
919
+			'lname',
920
+			'email',
921
+			'address',
922
+			'address2',
923
+			'city',
924
+			'country',
925
+			'state',
926
+			'zip',
927
+			'phone',
928
+		);
929
+		$order_for_group_1 = 1;
930
+		$order_for_group_2 = 1;
931
+		// loop thru what we should have and compare to what we have
932
+		foreach ($QST_systems as $QST_system) {
933
+			// reset values array
934
+			$QST_values = array();
935
+			// if we don't have what we should have
936
+			if (! in_array($QST_system, $questions)) {
937
+				// add it
938
+				switch ($QST_system) {
939
+					case 'fname':
940
+						$QST_values = array(
941
+							'QST_display_text'  => __('First Name', 'event_espresso'),
942
+							'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
943
+							'QST_system'        => 'fname',
944
+							'QST_type'          => 'TEXT',
945
+							'QST_required'      => 1,
946
+							'QST_required_text' => __('This field is required', 'event_espresso'),
947
+							'QST_order'         => 1,
948
+							'QST_admin_only'    => 0,
949
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
950
+							'QST_wp_user'       => self::get_default_creator_id(),
951
+							'QST_deleted'       => 0,
952
+						);
953
+						break;
954
+					case 'lname':
955
+						$QST_values = array(
956
+							'QST_display_text'  => __('Last Name', 'event_espresso'),
957
+							'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
958
+							'QST_system'        => 'lname',
959
+							'QST_type'          => 'TEXT',
960
+							'QST_required'      => 1,
961
+							'QST_required_text' => __('This field is required', 'event_espresso'),
962
+							'QST_order'         => 2,
963
+							'QST_admin_only'    => 0,
964
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
965
+							'QST_wp_user'       => self::get_default_creator_id(),
966
+							'QST_deleted'       => 0,
967
+						);
968
+						break;
969
+					case 'email':
970
+						$QST_values = array(
971
+							'QST_display_text'  => __('Email Address', 'event_espresso'),
972
+							'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
973
+							'QST_system'        => 'email',
974
+							'QST_type'          => 'EMAIL',
975
+							'QST_required'      => 1,
976
+							'QST_required_text' => __('This field is required', 'event_espresso'),
977
+							'QST_order'         => 3,
978
+							'QST_admin_only'    => 0,
979
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
980
+							'QST_wp_user'       => self::get_default_creator_id(),
981
+							'QST_deleted'       => 0,
982
+						);
983
+						break;
984
+					case 'address':
985
+						$QST_values = array(
986
+							'QST_display_text'  => __('Address', 'event_espresso'),
987
+							'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
988
+							'QST_system'        => 'address',
989
+							'QST_type'          => 'TEXT',
990
+							'QST_required'      => 0,
991
+							'QST_required_text' => __('This field is required', 'event_espresso'),
992
+							'QST_order'         => 4,
993
+							'QST_admin_only'    => 0,
994
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
995
+							'QST_wp_user'       => self::get_default_creator_id(),
996
+							'QST_deleted'       => 0,
997
+						);
998
+						break;
999
+					case 'address2':
1000
+						$QST_values = array(
1001
+							'QST_display_text'  => __('Address2', 'event_espresso'),
1002
+							'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
1003
+							'QST_system'        => 'address2',
1004
+							'QST_type'          => 'TEXT',
1005
+							'QST_required'      => 0,
1006
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1007
+							'QST_order'         => 5,
1008
+							'QST_admin_only'    => 0,
1009
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1010
+							'QST_wp_user'       => self::get_default_creator_id(),
1011
+							'QST_deleted'       => 0,
1012
+						);
1013
+						break;
1014
+					case 'city':
1015
+						$QST_values = array(
1016
+							'QST_display_text'  => __('City', 'event_espresso'),
1017
+							'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1018
+							'QST_system'        => 'city',
1019
+							'QST_type'          => 'TEXT',
1020
+							'QST_required'      => 0,
1021
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1022
+							'QST_order'         => 6,
1023
+							'QST_admin_only'    => 0,
1024
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1025
+							'QST_wp_user'       => self::get_default_creator_id(),
1026
+							'QST_deleted'       => 0,
1027
+						);
1028
+						break;
1029
+					case 'country':
1030
+						$QST_values = array(
1031
+							'QST_display_text'  => __('Country', 'event_espresso'),
1032
+							'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1033
+							'QST_system'        => 'country',
1034
+							'QST_type'          => 'COUNTRY',
1035
+							'QST_required'      => 0,
1036
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1037
+							'QST_order'         => 7,
1038
+							'QST_admin_only'    => 0,
1039
+							'QST_wp_user'       => self::get_default_creator_id(),
1040
+							'QST_deleted'       => 0,
1041
+						);
1042
+						break;
1043
+					case 'state':
1044
+						$QST_values = array(
1045
+							'QST_display_text'  => __('State/Province', 'event_espresso'),
1046
+							'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1047
+							'QST_system'        => 'state',
1048
+							'QST_type'          => 'STATE',
1049
+							'QST_required'      => 0,
1050
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1051
+							'QST_order'         => 8,
1052
+							'QST_admin_only'    => 0,
1053
+							'QST_wp_user'       => self::get_default_creator_id(),
1054
+							'QST_deleted'       => 0,
1055
+						);
1056
+						break;
1057
+					case 'zip':
1058
+						$QST_values = array(
1059
+							'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1060
+							'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1061
+							'QST_system'        => 'zip',
1062
+							'QST_type'          => 'TEXT',
1063
+							'QST_required'      => 0,
1064
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1065
+							'QST_order'         => 9,
1066
+							'QST_admin_only'    => 0,
1067
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1068
+							'QST_wp_user'       => self::get_default_creator_id(),
1069
+							'QST_deleted'       => 0,
1070
+						);
1071
+						break;
1072
+					case 'phone':
1073
+						$QST_values = array(
1074
+							'QST_display_text'  => __('Phone Number', 'event_espresso'),
1075
+							'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1076
+							'QST_system'        => 'phone',
1077
+							'QST_type'          => 'TEXT',
1078
+							'QST_required'      => 0,
1079
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1080
+							'QST_order'         => 10,
1081
+							'QST_admin_only'    => 0,
1082
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1083
+							'QST_wp_user'       => self::get_default_creator_id(),
1084
+							'QST_deleted'       => 0,
1085
+						);
1086
+						break;
1087
+				}
1088
+				if (! empty($QST_values)) {
1089
+					// insert system question
1090
+					$wpdb->insert(
1091
+						$table_name,
1092
+						$QST_values,
1093
+						array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1094
+					);
1095
+					$QST_ID = $wpdb->insert_id;
1096
+					// QUESTION GROUP QUESTIONS
1097
+					if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1098
+						$system_question_we_want = EEM_Question_Group::system_personal;
1099
+					} else {
1100
+						$system_question_we_want = EEM_Question_Group::system_address;
1101
+					}
1102
+					if (isset($QSG_IDs[$system_question_we_want])) {
1103
+						$QSG_ID = $QSG_IDs[$system_question_we_want];
1104
+					} else {
1105
+						$id_col = EEM_Question_Group::instance()
1106
+													->get_col(array(array('QSG_system' => $system_question_we_want)));
1107
+						if (is_array($id_col)) {
1108
+							$QSG_ID = reset($id_col);
1109
+						} else {
1110
+							//ok so we didn't find it in the db either?? that's weird because we should have inserted it at the start of this method
1111
+							EE_Log::instance()->log(
1112
+								__FILE__,
1113
+								__FUNCTION__,
1114
+								sprintf(
1115
+									__(
1116
+										'Could not associate question %1$s to a question group because no system question
1117 1117
                                          group existed',
1118
-                                        'event_espresso'
1119
-                                    ),
1120
-                                    $QST_ID),
1121
-                                'error');
1122
-                            continue;
1123
-                        }
1124
-                    }
1125
-                    // add system questions to groups
1126
-                    $wpdb->insert(
1127
-                        \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1128
-                        array(
1129
-                            'QSG_ID'    => $QSG_ID,
1130
-                            'QST_ID'    => $QST_ID,
1131
-                            'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1132
-                        ),
1133
-                        array('%d', '%d', '%d')
1134
-                    );
1135
-                }
1136
-            }
1137
-        }
1138
-    }
1139
-
1140
-
1141
-    /**
1142
-     * Makes sure the default payment method (Invoice) is active.
1143
-     * This used to be done automatically as part of constructing the old gateways config
1144
-     *
1145
-     * @throws \EE_Error
1146
-     */
1147
-    public static function insert_default_payment_methods()
1148
-    {
1149
-        if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1150
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
1151
-            EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1152
-        } else {
1153
-            EEM_Payment_Method::instance()->verify_button_urls();
1154
-        }
1155
-    }
1156
-
1157
-    /**
1158
-     * insert_default_status_codes
1159
-     *
1160
-     * @access public
1161
-     * @static
1162
-     * @return void
1163
-     */
1164
-    public static function insert_default_status_codes()
1165
-    {
1166
-
1167
-        global $wpdb;
1168
-
1169
-        if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1170
-
1171
-            $table_name = EEM_Status::instance()->table();
1172
-
1173
-            $SQL = "DELETE FROM $table_name WHERE STS_ID IN ( 'ACT', 'NAC', 'NOP', 'OPN', 'CLS', 'PND', 'ONG', 'SEC', 'DRF', 'DEL', 'DEN', 'EXP', 'RPP', 'RCN', 'RDC', 'RAP', 'RNA', 'RWL', 'TAB', 'TIN', 'TFL', 'TCM', 'TOP', 'PAP', 'PCN', 'PFL', 'PDC', 'EDR', 'ESN', 'PPN', 'RIC', 'MSN', 'MFL', 'MID', 'MRS', 'MIC', 'MDO', 'MEX' );";
1174
-            $wpdb->query($SQL);
1175
-
1176
-            $SQL = "INSERT INTO $table_name
1118
+										'event_espresso'
1119
+									),
1120
+									$QST_ID),
1121
+								'error');
1122
+							continue;
1123
+						}
1124
+					}
1125
+					// add system questions to groups
1126
+					$wpdb->insert(
1127
+						\EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1128
+						array(
1129
+							'QSG_ID'    => $QSG_ID,
1130
+							'QST_ID'    => $QST_ID,
1131
+							'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1132
+						),
1133
+						array('%d', '%d', '%d')
1134
+					);
1135
+				}
1136
+			}
1137
+		}
1138
+	}
1139
+
1140
+
1141
+	/**
1142
+	 * Makes sure the default payment method (Invoice) is active.
1143
+	 * This used to be done automatically as part of constructing the old gateways config
1144
+	 *
1145
+	 * @throws \EE_Error
1146
+	 */
1147
+	public static function insert_default_payment_methods()
1148
+	{
1149
+		if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1150
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
1151
+			EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1152
+		} else {
1153
+			EEM_Payment_Method::instance()->verify_button_urls();
1154
+		}
1155
+	}
1156
+
1157
+	/**
1158
+	 * insert_default_status_codes
1159
+	 *
1160
+	 * @access public
1161
+	 * @static
1162
+	 * @return void
1163
+	 */
1164
+	public static function insert_default_status_codes()
1165
+	{
1166
+
1167
+		global $wpdb;
1168
+
1169
+		if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1170
+
1171
+			$table_name = EEM_Status::instance()->table();
1172
+
1173
+			$SQL = "DELETE FROM $table_name WHERE STS_ID IN ( 'ACT', 'NAC', 'NOP', 'OPN', 'CLS', 'PND', 'ONG', 'SEC', 'DRF', 'DEL', 'DEN', 'EXP', 'RPP', 'RCN', 'RDC', 'RAP', 'RNA', 'RWL', 'TAB', 'TIN', 'TFL', 'TCM', 'TOP', 'PAP', 'PCN', 'PFL', 'PDC', 'EDR', 'ESN', 'PPN', 'RIC', 'MSN', 'MFL', 'MID', 'MRS', 'MIC', 'MDO', 'MEX' );";
1174
+			$wpdb->query($SQL);
1175
+
1176
+			$SQL = "INSERT INTO $table_name
1177 1177
 					(STS_ID, STS_code, STS_type, STS_can_edit, STS_desc, STS_open) VALUES
1178 1178
 					('ACT', 'ACTIVE', 'event', 0, NULL, 1),
1179 1179
 					('NAC', 'NOT_ACTIVE', 'event', 0, NULL, 0),
@@ -1213,521 +1213,521 @@  discard block
 block discarded – undo
1213 1213
 					('MID', 'IDLE', 'message', 0, NULL, 1),
1214 1214
 					('MRS', 'RESEND', 'message', 0, NULL, 1),
1215 1215
 					('MIC', 'INCOMPLETE', 'message', 0, NULL, 0);";
1216
-            $wpdb->query($SQL);
1217
-
1218
-        }
1219
-
1220
-    }
1221
-
1222
-
1223
-    /**
1224
-     * create_upload_directories
1225
-     * Creates folders in the uploads directory to facilitate addons and templates
1226
-     *
1227
-     * @access public
1228
-     * @static
1229
-     * @return boolean success of verifying upload directories exist
1230
-     */
1231
-    public static function create_upload_directories()
1232
-    {
1233
-        // Create the required folders
1234
-        $folders = array(
1235
-            EVENT_ESPRESSO_TEMPLATE_DIR,
1236
-            EVENT_ESPRESSO_GATEWAY_DIR,
1237
-            EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1238
-            EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1239
-            EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/',
1240
-        );
1241
-        foreach ($folders as $folder) {
1242
-            try {
1243
-                EEH_File::ensure_folder_exists_and_is_writable($folder);
1244
-                @ chmod($folder, 0755);
1245
-            } catch (EE_Error $e) {
1246
-                EE_Error::add_error(
1247
-                    sprintf(
1248
-                        __('Could not create the folder at "%1$s" because: %2$s', 'event_espresso'),
1249
-                        $folder,
1250
-                        '<br />' . $e->getMessage()
1251
-                    ),
1252
-                    __FILE__, __FUNCTION__, __LINE__
1253
-                );
1254
-                //indicate we'll need to fix this later
1255
-                update_option(EEH_Activation::upload_directories_incomplete_option_name, true);
1256
-                return false;
1257
-            }
1258
-        }
1259
-        //just add the .htaccess file to the logs directory to begin with. Even if logging
1260
-        //is disabled, there might be activation errors recorded in there
1261
-        EEH_File::add_htaccess_deny_from_all(EVENT_ESPRESSO_UPLOAD_DIR . 'logs/');
1262
-        //remember EE's folders are all good
1263
-        delete_option(EEH_Activation::upload_directories_incomplete_option_name);
1264
-        return true;
1265
-    }
1266
-
1267
-    /**
1268
-     * Whether the upload directories need to be fixed or not.
1269
-     * If EE is installed but filesystem access isn't initially available,
1270
-     * we need to get the user's filesystem credentials and THEN create them,
1271
-     * so there might be period of time when EE is installed but its
1272
-     * upload directories aren't available. This indicates such a state
1273
-     *
1274
-     * @return boolean
1275
-     */
1276
-    public static function upload_directories_incomplete()
1277
-    {
1278
-        return get_option(EEH_Activation::upload_directories_incomplete_option_name, false);
1279
-    }
1280
-
1281
-
1282
-    /**
1283
-     * generate_default_message_templates
1284
-     *
1285
-     * @static
1286
-     * @throws EE_Error
1287
-     * @return bool     true means new templates were created.
1288
-     *                  false means no templates were created.
1289
-     *                  This is NOT an error flag. To check for errors you will want
1290
-     *                  to use either EE_Error or a try catch for an EE_Error exception.
1291
-     */
1292
-    public static function generate_default_message_templates()
1293
-    {
1294
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1295
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1296
-        /*
1216
+			$wpdb->query($SQL);
1217
+
1218
+		}
1219
+
1220
+	}
1221
+
1222
+
1223
+	/**
1224
+	 * create_upload_directories
1225
+	 * Creates folders in the uploads directory to facilitate addons and templates
1226
+	 *
1227
+	 * @access public
1228
+	 * @static
1229
+	 * @return boolean success of verifying upload directories exist
1230
+	 */
1231
+	public static function create_upload_directories()
1232
+	{
1233
+		// Create the required folders
1234
+		$folders = array(
1235
+			EVENT_ESPRESSO_TEMPLATE_DIR,
1236
+			EVENT_ESPRESSO_GATEWAY_DIR,
1237
+			EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1238
+			EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1239
+			EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/',
1240
+		);
1241
+		foreach ($folders as $folder) {
1242
+			try {
1243
+				EEH_File::ensure_folder_exists_and_is_writable($folder);
1244
+				@ chmod($folder, 0755);
1245
+			} catch (EE_Error $e) {
1246
+				EE_Error::add_error(
1247
+					sprintf(
1248
+						__('Could not create the folder at "%1$s" because: %2$s', 'event_espresso'),
1249
+						$folder,
1250
+						'<br />' . $e->getMessage()
1251
+					),
1252
+					__FILE__, __FUNCTION__, __LINE__
1253
+				);
1254
+				//indicate we'll need to fix this later
1255
+				update_option(EEH_Activation::upload_directories_incomplete_option_name, true);
1256
+				return false;
1257
+			}
1258
+		}
1259
+		//just add the .htaccess file to the logs directory to begin with. Even if logging
1260
+		//is disabled, there might be activation errors recorded in there
1261
+		EEH_File::add_htaccess_deny_from_all(EVENT_ESPRESSO_UPLOAD_DIR . 'logs/');
1262
+		//remember EE's folders are all good
1263
+		delete_option(EEH_Activation::upload_directories_incomplete_option_name);
1264
+		return true;
1265
+	}
1266
+
1267
+	/**
1268
+	 * Whether the upload directories need to be fixed or not.
1269
+	 * If EE is installed but filesystem access isn't initially available,
1270
+	 * we need to get the user's filesystem credentials and THEN create them,
1271
+	 * so there might be period of time when EE is installed but its
1272
+	 * upload directories aren't available. This indicates such a state
1273
+	 *
1274
+	 * @return boolean
1275
+	 */
1276
+	public static function upload_directories_incomplete()
1277
+	{
1278
+		return get_option(EEH_Activation::upload_directories_incomplete_option_name, false);
1279
+	}
1280
+
1281
+
1282
+	/**
1283
+	 * generate_default_message_templates
1284
+	 *
1285
+	 * @static
1286
+	 * @throws EE_Error
1287
+	 * @return bool     true means new templates were created.
1288
+	 *                  false means no templates were created.
1289
+	 *                  This is NOT an error flag. To check for errors you will want
1290
+	 *                  to use either EE_Error or a try catch for an EE_Error exception.
1291
+	 */
1292
+	public static function generate_default_message_templates()
1293
+	{
1294
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1295
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1296
+		/*
1297 1297
          * This first method is taking care of ensuring any default messengers
1298 1298
          * that should be made active and have templates generated are done.
1299 1299
          */
1300
-        $new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1301
-            $message_resource_manager
1302
-        );
1303
-        /**
1304
-         * This method is verifying there are no NEW default message types
1305
-         * for ACTIVE messengers that need activated (and corresponding templates setup).
1306
-         */
1307
-        $new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1308
-            $message_resource_manager
1309
-        );
1310
-        //after all is done, let's persist these changes to the db.
1311
-        $message_resource_manager->update_has_activated_messengers_option();
1312
-        $message_resource_manager->update_active_messengers_option();
1313
-        // will return true if either of these are true.  Otherwise will return false.
1314
-        return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1315
-    }
1316
-
1317
-
1318
-
1319
-    /**
1320
-     * @param \EE_Message_Resource_Manager $message_resource_manager
1321
-     * @return array|bool
1322
-     * @throws \EE_Error
1323
-     */
1324
-    protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1325
-        EE_Message_Resource_Manager $message_resource_manager
1326
-    ) {
1327
-        /** @type EE_messenger[] $active_messengers */
1328
-        $active_messengers = $message_resource_manager->active_messengers();
1329
-        $installed_message_types = $message_resource_manager->installed_message_types();
1330
-        $templates_created = false;
1331
-        foreach ($active_messengers as $active_messenger) {
1332
-            $default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1333
-            $default_message_type_names_to_activate = array();
1334
-            // looping through each default message type reported by the messenger
1335
-            // and setup the actual message types to activate.
1336
-            foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1337
-                // if already active or has already been activated before we skip
1338
-                // (otherwise we might reactivate something user's intentionally deactivated.)
1339
-                // we also skip if the message type is not installed.
1340
-                if (
1341
-                    $message_resource_manager->has_message_type_been_activated_for_messenger(
1342
-                        $default_message_type_name_for_messenger,
1343
-                        $active_messenger->name
1344
-                    )
1345
-                    || $message_resource_manager->is_message_type_active_for_messenger(
1346
-                        $active_messenger->name,
1347
-                        $default_message_type_name_for_messenger
1348
-                    )
1349
-                    || ! isset($installed_message_types[$default_message_type_name_for_messenger])
1350
-                ) {
1351
-                    continue;
1352
-                }
1353
-                $default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1354
-            }
1355
-            //let's activate!
1356
-            $message_resource_manager->ensure_message_types_are_active(
1357
-                $default_message_type_names_to_activate,
1358
-                $active_messenger->name,
1359
-                false
1360
-            );
1361
-            //activate the templates for these message types
1362
-            if ( ! empty($default_message_type_names_to_activate)) {
1363
-                $templates_created = EEH_MSG_Template::generate_new_templates(
1364
-                    $active_messenger->name,
1365
-                    $default_message_type_names_for_messenger,
1366
-                    '',
1367
-                    true
1368
-                );
1369
-            }
1370
-        }
1371
-        return $templates_created;
1372
-    }
1373
-
1374
-
1375
-
1376
-    /**
1377
-     * This will activate and generate default messengers and default message types for those messengers.
1378
-     *
1379
-     * @param EE_message_Resource_Manager $message_resource_manager
1380
-     * @return array|bool  True means there were default messengers and message type templates generated.
1381
-     *                     False means that there were no templates generated
1382
-     *                     (which could simply mean there are no default message types for a messenger).
1383
-     * @throws EE_Error
1384
-     */
1385
-    protected static function _activate_and_generate_default_messengers_and_message_templates(
1386
-        EE_Message_Resource_Manager $message_resource_manager
1387
-    ) {
1388
-        /** @type EE_messenger[] $messengers_to_generate */
1389
-        $messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1390
-        $installed_message_types = $message_resource_manager->installed_message_types();
1391
-        $templates_generated = false;
1392
-        foreach ($messengers_to_generate as $messenger_to_generate) {
1393
-            $default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1394
-            //verify the default message types match an installed message type.
1395
-            foreach ($default_message_type_names_for_messenger as $key => $name) {
1396
-                if (
1397
-                    ! isset($installed_message_types[$name])
1398
-                    || $message_resource_manager->has_message_type_been_activated_for_messenger(
1399
-                        $name,
1400
-                        $messenger_to_generate->name
1401
-                    )
1402
-                ) {
1403
-                    unset($default_message_type_names_for_messenger[$key]);
1404
-                }
1405
-            }
1406
-            // in previous iterations, the active_messengers option in the db
1407
-            // needed updated before calling create templates. however with the changes this may not be necessary.
1408
-            // This comment is left here just in case we discover that we _do_ need to update before
1409
-            // passing off to create templates (after the refactor is done).
1410
-            // @todo remove this comment when determined not necessary.
1411
-            $message_resource_manager->activate_messenger(
1412
-                $messenger_to_generate->name,
1413
-                $default_message_type_names_for_messenger,
1414
-                false
1415
-            );
1416
-            //create any templates needing created (or will reactivate templates already generated as necessary).
1417
-            if ( ! empty($default_message_type_names_for_messenger)) {
1418
-                $templates_generated = EEH_MSG_Template::generate_new_templates(
1419
-                    $messenger_to_generate->name,
1420
-                    $default_message_type_names_for_messenger,
1421
-                    '',
1422
-                    true
1423
-                );
1424
-            }
1425
-        }
1426
-        return $templates_generated;
1427
-    }
1428
-
1429
-
1430
-    /**
1431
-     * This returns the default messengers to generate templates for on activation of EE.
1432
-     * It considers:
1433
-     * - whether a messenger is already active in the db.
1434
-     * - whether a messenger has been made active at any time in the past.
1435
-     *
1436
-     * @static
1437
-     * @param  EE_Message_Resource_Manager $message_resource_manager
1438
-     * @return EE_messenger[]
1439
-     */
1440
-    protected static function _get_default_messengers_to_generate_on_activation(
1441
-        EE_Message_Resource_Manager $message_resource_manager
1442
-    ) {
1443
-        $active_messengers    = $message_resource_manager->active_messengers();
1444
-        $installed_messengers = $message_resource_manager->installed_messengers();
1445
-        $has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1446
-
1447
-        $messengers_to_generate = array();
1448
-        foreach ($installed_messengers as $installed_messenger) {
1449
-            //if installed messenger is a messenger that should be activated on install
1450
-            //and is not already active
1451
-            //and has never been activated
1452
-            if (
1453
-                ! $installed_messenger->activate_on_install
1454
-                || isset($active_messengers[$installed_messenger->name])
1455
-                || isset($has_activated[$installed_messenger->name])
1456
-            ) {
1457
-                continue;
1458
-            }
1459
-            $messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1460
-        }
1461
-        return $messengers_to_generate;
1462
-    }
1463
-
1464
-
1465
-    /**
1466
-     * This simply validates active message types to ensure they actually match installed
1467
-     * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1468
-     * rows are set inactive.
1469
-     * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1470
-     * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1471
-     * are still handled in here.
1472
-     *
1473
-     * @since 4.3.1
1474
-     * @return void
1475
-     */
1476
-    public static function validate_messages_system()
1477
-    {
1478
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1479
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1480
-        $message_resource_manager->validate_active_message_types_are_installed();
1481
-        do_action('AHEE__EEH_Activation__validate_messages_system');
1482
-    }
1483
-
1484
-
1485
-    /**
1486
-     * create_no_ticket_prices_array
1487
-     *
1488
-     * @access public
1489
-     * @static
1490
-     * @return void
1491
-     */
1492
-    public static function create_no_ticket_prices_array()
1493
-    {
1494
-        // this creates an array for tracking events that have no active ticket prices created
1495
-        // this allows us to warn admins of the situation so that it can be corrected
1496
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1497
-        if (! $espresso_no_ticket_prices) {
1498
-            add_option('ee_no_ticket_prices', array(), '', false);
1499
-        }
1500
-    }
1501
-
1502
-
1503
-    /**
1504
-     * plugin_deactivation
1505
-     *
1506
-     * @access public
1507
-     * @static
1508
-     * @return void
1509
-     */
1510
-    public static function plugin_deactivation()
1511
-    {
1512
-    }
1513
-
1514
-
1515
-    /**
1516
-     * Finds all our EE4 custom post types, and deletes them and their associated data
1517
-     * (like post meta or term relations)
1518
-     *
1519
-     * @global wpdb $wpdb
1520
-     * @throws \EE_Error
1521
-     */
1522
-    public static function delete_all_espresso_cpt_data()
1523
-    {
1524
-        global $wpdb;
1525
-        //get all the CPT post_types
1526
-        $ee_post_types = array();
1527
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1528
-            if (method_exists($model_name, 'instance')) {
1529
-                $model_obj = call_user_func(array($model_name, 'instance'));
1530
-                if ($model_obj instanceof EEM_CPT_Base) {
1531
-                    $ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1532
-                }
1533
-            }
1534
-        }
1535
-        //get all our CPTs
1536
-        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1537
-        $cpt_ids = $wpdb->get_col($query);
1538
-        //delete each post meta and term relations too
1539
-        foreach ($cpt_ids as $post_id) {
1540
-            wp_delete_post($post_id, true);
1541
-        }
1542
-    }
1543
-
1544
-    /**
1545
-     * Deletes all EE custom tables
1546
-     *
1547
-     * @return array
1548
-     */
1549
-    public static function drop_espresso_tables()
1550
-    {
1551
-        $tables = array();
1552
-        // load registry
1553
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1554
-            if (method_exists($model_name, 'instance')) {
1555
-                $model_obj = call_user_func(array($model_name, 'instance'));
1556
-                if ($model_obj instanceof EEM_Base) {
1557
-                    foreach ($model_obj->get_tables() as $table) {
1558
-                        if (strpos($table->get_table_name(), 'esp_')
1559
-                            &&
1560
-                            (
1561
-                                is_main_site()//main site? nuke them all
1562
-                                || ! $table->is_global()//not main site,but not global either. nuke it
1563
-                            )
1564
-                        ) {
1565
-                            $tables[$table->get_table_name()] = $table->get_table_name();
1566
-                        }
1567
-                    }
1568
-                }
1569
-            }
1570
-        }
1571
-
1572
-        //there are some tables whose models were removed.
1573
-        //they should be removed when removing all EE core's data
1574
-        $tables_without_models = array(
1575
-            'esp_promotion',
1576
-            'esp_promotion_applied',
1577
-            'esp_promotion_object',
1578
-            'esp_promotion_rule',
1579
-            'esp_rule',
1580
-        );
1581
-        foreach ($tables_without_models as $table) {
1582
-            $tables[$table] = $table;
1583
-        }
1584
-        return \EEH_Activation::getTableManager()->dropTables($tables);
1585
-    }
1586
-
1587
-
1588
-
1589
-    /**
1590
-     * Drops all the tables mentioned in a single MYSQL query. Double-checks
1591
-     * each table name provided has a wpdb prefix attached, and that it exists.
1592
-     * Returns the list actually deleted
1593
-     *
1594
-     * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1595
-     * @global WPDB $wpdb
1596
-     * @param array $table_names
1597
-     * @return array of table names which we deleted
1598
-     */
1599
-    public static function drop_tables($table_names)
1600
-    {
1601
-        return \EEH_Activation::getTableManager()->dropTables($table_names);
1602
-    }
1603
-
1604
-
1605
-
1606
-    /**
1607
-     * plugin_uninstall
1608
-     *
1609
-     * @access public
1610
-     * @static
1611
-     * @param bool $remove_all
1612
-     * @return void
1613
-     */
1614
-    public static function delete_all_espresso_tables_and_data($remove_all = true)
1615
-    {
1616
-        global $wpdb;
1617
-        self::drop_espresso_tables();
1618
-        $wp_options_to_delete = array(
1619
-            'ee_no_ticket_prices'                => true,
1620
-            'ee_active_messengers'               => true,
1621
-            'ee_has_activated_messenger'         => true,
1622
-            'ee_flush_rewrite_rules'             => true,
1623
-            'ee_config'                          => false,
1624
-            'ee_data_migration_current_db_state' => true,
1625
-            'ee_data_migration_mapping_'         => false,
1626
-            'ee_data_migration_script_'          => false,
1627
-            'ee_data_migrations'                 => true,
1628
-            'ee_dms_map'                         => false,
1629
-            'ee_notices'                         => true,
1630
-            'lang_file_check_'                   => false,
1631
-            'ee_maintenance_mode'                => true,
1632
-            'ee_ueip_optin'                      => true,
1633
-            'ee_ueip_has_notified'               => true,
1634
-            'ee_plugin_activation_errors'        => true,
1635
-            'ee_id_mapping_from'                 => false,
1636
-            'espresso_persistent_admin_notices'  => true,
1637
-            'ee_encryption_key'                  => true,
1638
-            'pue_force_upgrade_'                 => false,
1639
-            'pue_json_error_'                    => false,
1640
-            'pue_install_key_'                   => false,
1641
-            'pue_verification_error_'            => false,
1642
-            'pu_dismissed_upgrade_'              => false,
1643
-            'external_updates-'                  => false,
1644
-            'ee_extra_data'                      => true,
1645
-            'ee_ssn_'                            => false,
1646
-            'ee_rss_'                            => false,
1647
-            'ee_rte_n_tx_'                       => false,
1648
-            'ee_pers_admin_notices'              => true,
1649
-            'ee_job_parameters_'                 => false,
1650
-            'ee_upload_directories_incomplete'   => true,
1651
-            'ee_verified_db_collations'          => true,
1652
-        );
1653
-        if (is_main_site()) {
1654
-            $wp_options_to_delete['ee_network_config'] = true;
1655
-        }
1656
-        $undeleted_options = array();
1657
-        foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1658
-            if ($no_wildcard) {
1659
-                if ( ! delete_option($option_name)) {
1660
-                    $undeleted_options[] = $option_name;
1661
-                }
1662
-            } else {
1663
-                $option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1664
-                foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1665
-                    if ( ! delete_option($option_name_from_wildcard)) {
1666
-                        $undeleted_options[] = $option_name_from_wildcard;
1667
-                    }
1668
-                }
1669
-            }
1670
-        }
1671
-        //also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1672
-        remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1673
-        if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1674
-            $db_update_sans_ee4 = array();
1675
-            foreach ($espresso_db_update as $version => $times_activated) {
1676
-                if ((string)$version[0] === '3') {//if its NON EE4
1677
-                    $db_update_sans_ee4[$version] = $times_activated;
1678
-                }
1679
-            }
1680
-            update_option('espresso_db_update', $db_update_sans_ee4);
1681
-        }
1682
-        $errors = '';
1683
-        if ( ! empty($undeleted_options)) {
1684
-            $errors .= sprintf(
1685
-                __('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1686
-                '<br/>',
1687
-                implode(',<br/>', $undeleted_options)
1688
-            );
1689
-        }
1690
-        if ( ! empty($errors)) {
1691
-            EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1692
-        }
1693
-    }
1694
-
1695
-    /**
1696
-     * Gets the mysql error code from the last used query by wpdb
1697
-     *
1698
-     * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1699
-     */
1700
-    public static function last_wpdb_error_code()
1701
-    {
1702
-        global $wpdb;
1703
-        if ($wpdb->use_mysqli) {
1704
-            return mysqli_errno($wpdb->dbh);
1705
-        } else {
1706
-            return mysql_errno($wpdb->dbh);
1707
-        }
1708
-    }
1709
-
1710
-    /**
1711
-     * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1712
-     *
1713
-     * @global wpdb  $wpdb
1714
-     * @deprecated instead use TableAnalysis::tableExists()
1715
-     * @param string $table_name with or without $wpdb->prefix
1716
-     * @return boolean
1717
-     */
1718
-    public static function table_exists($table_name)
1719
-    {
1720
-        return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1721
-    }
1722
-
1723
-    /**
1724
-     * Resets the cache on EEH_Activation
1725
-     */
1726
-    public static function reset()
1727
-    {
1728
-        self::$_default_creator_id                             = null;
1729
-        self::$_initialized_db_content_already_in_this_request = false;
1730
-    }
1300
+		$new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1301
+			$message_resource_manager
1302
+		);
1303
+		/**
1304
+		 * This method is verifying there are no NEW default message types
1305
+		 * for ACTIVE messengers that need activated (and corresponding templates setup).
1306
+		 */
1307
+		$new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1308
+			$message_resource_manager
1309
+		);
1310
+		//after all is done, let's persist these changes to the db.
1311
+		$message_resource_manager->update_has_activated_messengers_option();
1312
+		$message_resource_manager->update_active_messengers_option();
1313
+		// will return true if either of these are true.  Otherwise will return false.
1314
+		return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1315
+	}
1316
+
1317
+
1318
+
1319
+	/**
1320
+	 * @param \EE_Message_Resource_Manager $message_resource_manager
1321
+	 * @return array|bool
1322
+	 * @throws \EE_Error
1323
+	 */
1324
+	protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1325
+		EE_Message_Resource_Manager $message_resource_manager
1326
+	) {
1327
+		/** @type EE_messenger[] $active_messengers */
1328
+		$active_messengers = $message_resource_manager->active_messengers();
1329
+		$installed_message_types = $message_resource_manager->installed_message_types();
1330
+		$templates_created = false;
1331
+		foreach ($active_messengers as $active_messenger) {
1332
+			$default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1333
+			$default_message_type_names_to_activate = array();
1334
+			// looping through each default message type reported by the messenger
1335
+			// and setup the actual message types to activate.
1336
+			foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1337
+				// if already active or has already been activated before we skip
1338
+				// (otherwise we might reactivate something user's intentionally deactivated.)
1339
+				// we also skip if the message type is not installed.
1340
+				if (
1341
+					$message_resource_manager->has_message_type_been_activated_for_messenger(
1342
+						$default_message_type_name_for_messenger,
1343
+						$active_messenger->name
1344
+					)
1345
+					|| $message_resource_manager->is_message_type_active_for_messenger(
1346
+						$active_messenger->name,
1347
+						$default_message_type_name_for_messenger
1348
+					)
1349
+					|| ! isset($installed_message_types[$default_message_type_name_for_messenger])
1350
+				) {
1351
+					continue;
1352
+				}
1353
+				$default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1354
+			}
1355
+			//let's activate!
1356
+			$message_resource_manager->ensure_message_types_are_active(
1357
+				$default_message_type_names_to_activate,
1358
+				$active_messenger->name,
1359
+				false
1360
+			);
1361
+			//activate the templates for these message types
1362
+			if ( ! empty($default_message_type_names_to_activate)) {
1363
+				$templates_created = EEH_MSG_Template::generate_new_templates(
1364
+					$active_messenger->name,
1365
+					$default_message_type_names_for_messenger,
1366
+					'',
1367
+					true
1368
+				);
1369
+			}
1370
+		}
1371
+		return $templates_created;
1372
+	}
1373
+
1374
+
1375
+
1376
+	/**
1377
+	 * This will activate and generate default messengers and default message types for those messengers.
1378
+	 *
1379
+	 * @param EE_message_Resource_Manager $message_resource_manager
1380
+	 * @return array|bool  True means there were default messengers and message type templates generated.
1381
+	 *                     False means that there were no templates generated
1382
+	 *                     (which could simply mean there are no default message types for a messenger).
1383
+	 * @throws EE_Error
1384
+	 */
1385
+	protected static function _activate_and_generate_default_messengers_and_message_templates(
1386
+		EE_Message_Resource_Manager $message_resource_manager
1387
+	) {
1388
+		/** @type EE_messenger[] $messengers_to_generate */
1389
+		$messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1390
+		$installed_message_types = $message_resource_manager->installed_message_types();
1391
+		$templates_generated = false;
1392
+		foreach ($messengers_to_generate as $messenger_to_generate) {
1393
+			$default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1394
+			//verify the default message types match an installed message type.
1395
+			foreach ($default_message_type_names_for_messenger as $key => $name) {
1396
+				if (
1397
+					! isset($installed_message_types[$name])
1398
+					|| $message_resource_manager->has_message_type_been_activated_for_messenger(
1399
+						$name,
1400
+						$messenger_to_generate->name
1401
+					)
1402
+				) {
1403
+					unset($default_message_type_names_for_messenger[$key]);
1404
+				}
1405
+			}
1406
+			// in previous iterations, the active_messengers option in the db
1407
+			// needed updated before calling create templates. however with the changes this may not be necessary.
1408
+			// This comment is left here just in case we discover that we _do_ need to update before
1409
+			// passing off to create templates (after the refactor is done).
1410
+			// @todo remove this comment when determined not necessary.
1411
+			$message_resource_manager->activate_messenger(
1412
+				$messenger_to_generate->name,
1413
+				$default_message_type_names_for_messenger,
1414
+				false
1415
+			);
1416
+			//create any templates needing created (or will reactivate templates already generated as necessary).
1417
+			if ( ! empty($default_message_type_names_for_messenger)) {
1418
+				$templates_generated = EEH_MSG_Template::generate_new_templates(
1419
+					$messenger_to_generate->name,
1420
+					$default_message_type_names_for_messenger,
1421
+					'',
1422
+					true
1423
+				);
1424
+			}
1425
+		}
1426
+		return $templates_generated;
1427
+	}
1428
+
1429
+
1430
+	/**
1431
+	 * This returns the default messengers to generate templates for on activation of EE.
1432
+	 * It considers:
1433
+	 * - whether a messenger is already active in the db.
1434
+	 * - whether a messenger has been made active at any time in the past.
1435
+	 *
1436
+	 * @static
1437
+	 * @param  EE_Message_Resource_Manager $message_resource_manager
1438
+	 * @return EE_messenger[]
1439
+	 */
1440
+	protected static function _get_default_messengers_to_generate_on_activation(
1441
+		EE_Message_Resource_Manager $message_resource_manager
1442
+	) {
1443
+		$active_messengers    = $message_resource_manager->active_messengers();
1444
+		$installed_messengers = $message_resource_manager->installed_messengers();
1445
+		$has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1446
+
1447
+		$messengers_to_generate = array();
1448
+		foreach ($installed_messengers as $installed_messenger) {
1449
+			//if installed messenger is a messenger that should be activated on install
1450
+			//and is not already active
1451
+			//and has never been activated
1452
+			if (
1453
+				! $installed_messenger->activate_on_install
1454
+				|| isset($active_messengers[$installed_messenger->name])
1455
+				|| isset($has_activated[$installed_messenger->name])
1456
+			) {
1457
+				continue;
1458
+			}
1459
+			$messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1460
+		}
1461
+		return $messengers_to_generate;
1462
+	}
1463
+
1464
+
1465
+	/**
1466
+	 * This simply validates active message types to ensure they actually match installed
1467
+	 * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1468
+	 * rows are set inactive.
1469
+	 * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1470
+	 * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1471
+	 * are still handled in here.
1472
+	 *
1473
+	 * @since 4.3.1
1474
+	 * @return void
1475
+	 */
1476
+	public static function validate_messages_system()
1477
+	{
1478
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1479
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1480
+		$message_resource_manager->validate_active_message_types_are_installed();
1481
+		do_action('AHEE__EEH_Activation__validate_messages_system');
1482
+	}
1483
+
1484
+
1485
+	/**
1486
+	 * create_no_ticket_prices_array
1487
+	 *
1488
+	 * @access public
1489
+	 * @static
1490
+	 * @return void
1491
+	 */
1492
+	public static function create_no_ticket_prices_array()
1493
+	{
1494
+		// this creates an array for tracking events that have no active ticket prices created
1495
+		// this allows us to warn admins of the situation so that it can be corrected
1496
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1497
+		if (! $espresso_no_ticket_prices) {
1498
+			add_option('ee_no_ticket_prices', array(), '', false);
1499
+		}
1500
+	}
1501
+
1502
+
1503
+	/**
1504
+	 * plugin_deactivation
1505
+	 *
1506
+	 * @access public
1507
+	 * @static
1508
+	 * @return void
1509
+	 */
1510
+	public static function plugin_deactivation()
1511
+	{
1512
+	}
1513
+
1514
+
1515
+	/**
1516
+	 * Finds all our EE4 custom post types, and deletes them and their associated data
1517
+	 * (like post meta or term relations)
1518
+	 *
1519
+	 * @global wpdb $wpdb
1520
+	 * @throws \EE_Error
1521
+	 */
1522
+	public static function delete_all_espresso_cpt_data()
1523
+	{
1524
+		global $wpdb;
1525
+		//get all the CPT post_types
1526
+		$ee_post_types = array();
1527
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1528
+			if (method_exists($model_name, 'instance')) {
1529
+				$model_obj = call_user_func(array($model_name, 'instance'));
1530
+				if ($model_obj instanceof EEM_CPT_Base) {
1531
+					$ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1532
+				}
1533
+			}
1534
+		}
1535
+		//get all our CPTs
1536
+		$query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1537
+		$cpt_ids = $wpdb->get_col($query);
1538
+		//delete each post meta and term relations too
1539
+		foreach ($cpt_ids as $post_id) {
1540
+			wp_delete_post($post_id, true);
1541
+		}
1542
+	}
1543
+
1544
+	/**
1545
+	 * Deletes all EE custom tables
1546
+	 *
1547
+	 * @return array
1548
+	 */
1549
+	public static function drop_espresso_tables()
1550
+	{
1551
+		$tables = array();
1552
+		// load registry
1553
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1554
+			if (method_exists($model_name, 'instance')) {
1555
+				$model_obj = call_user_func(array($model_name, 'instance'));
1556
+				if ($model_obj instanceof EEM_Base) {
1557
+					foreach ($model_obj->get_tables() as $table) {
1558
+						if (strpos($table->get_table_name(), 'esp_')
1559
+							&&
1560
+							(
1561
+								is_main_site()//main site? nuke them all
1562
+								|| ! $table->is_global()//not main site,but not global either. nuke it
1563
+							)
1564
+						) {
1565
+							$tables[$table->get_table_name()] = $table->get_table_name();
1566
+						}
1567
+					}
1568
+				}
1569
+			}
1570
+		}
1571
+
1572
+		//there are some tables whose models were removed.
1573
+		//they should be removed when removing all EE core's data
1574
+		$tables_without_models = array(
1575
+			'esp_promotion',
1576
+			'esp_promotion_applied',
1577
+			'esp_promotion_object',
1578
+			'esp_promotion_rule',
1579
+			'esp_rule',
1580
+		);
1581
+		foreach ($tables_without_models as $table) {
1582
+			$tables[$table] = $table;
1583
+		}
1584
+		return \EEH_Activation::getTableManager()->dropTables($tables);
1585
+	}
1586
+
1587
+
1588
+
1589
+	/**
1590
+	 * Drops all the tables mentioned in a single MYSQL query. Double-checks
1591
+	 * each table name provided has a wpdb prefix attached, and that it exists.
1592
+	 * Returns the list actually deleted
1593
+	 *
1594
+	 * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1595
+	 * @global WPDB $wpdb
1596
+	 * @param array $table_names
1597
+	 * @return array of table names which we deleted
1598
+	 */
1599
+	public static function drop_tables($table_names)
1600
+	{
1601
+		return \EEH_Activation::getTableManager()->dropTables($table_names);
1602
+	}
1603
+
1604
+
1605
+
1606
+	/**
1607
+	 * plugin_uninstall
1608
+	 *
1609
+	 * @access public
1610
+	 * @static
1611
+	 * @param bool $remove_all
1612
+	 * @return void
1613
+	 */
1614
+	public static function delete_all_espresso_tables_and_data($remove_all = true)
1615
+	{
1616
+		global $wpdb;
1617
+		self::drop_espresso_tables();
1618
+		$wp_options_to_delete = array(
1619
+			'ee_no_ticket_prices'                => true,
1620
+			'ee_active_messengers'               => true,
1621
+			'ee_has_activated_messenger'         => true,
1622
+			'ee_flush_rewrite_rules'             => true,
1623
+			'ee_config'                          => false,
1624
+			'ee_data_migration_current_db_state' => true,
1625
+			'ee_data_migration_mapping_'         => false,
1626
+			'ee_data_migration_script_'          => false,
1627
+			'ee_data_migrations'                 => true,
1628
+			'ee_dms_map'                         => false,
1629
+			'ee_notices'                         => true,
1630
+			'lang_file_check_'                   => false,
1631
+			'ee_maintenance_mode'                => true,
1632
+			'ee_ueip_optin'                      => true,
1633
+			'ee_ueip_has_notified'               => true,
1634
+			'ee_plugin_activation_errors'        => true,
1635
+			'ee_id_mapping_from'                 => false,
1636
+			'espresso_persistent_admin_notices'  => true,
1637
+			'ee_encryption_key'                  => true,
1638
+			'pue_force_upgrade_'                 => false,
1639
+			'pue_json_error_'                    => false,
1640
+			'pue_install_key_'                   => false,
1641
+			'pue_verification_error_'            => false,
1642
+			'pu_dismissed_upgrade_'              => false,
1643
+			'external_updates-'                  => false,
1644
+			'ee_extra_data'                      => true,
1645
+			'ee_ssn_'                            => false,
1646
+			'ee_rss_'                            => false,
1647
+			'ee_rte_n_tx_'                       => false,
1648
+			'ee_pers_admin_notices'              => true,
1649
+			'ee_job_parameters_'                 => false,
1650
+			'ee_upload_directories_incomplete'   => true,
1651
+			'ee_verified_db_collations'          => true,
1652
+		);
1653
+		if (is_main_site()) {
1654
+			$wp_options_to_delete['ee_network_config'] = true;
1655
+		}
1656
+		$undeleted_options = array();
1657
+		foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1658
+			if ($no_wildcard) {
1659
+				if ( ! delete_option($option_name)) {
1660
+					$undeleted_options[] = $option_name;
1661
+				}
1662
+			} else {
1663
+				$option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1664
+				foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1665
+					if ( ! delete_option($option_name_from_wildcard)) {
1666
+						$undeleted_options[] = $option_name_from_wildcard;
1667
+					}
1668
+				}
1669
+			}
1670
+		}
1671
+		//also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1672
+		remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1673
+		if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1674
+			$db_update_sans_ee4 = array();
1675
+			foreach ($espresso_db_update as $version => $times_activated) {
1676
+				if ((string)$version[0] === '3') {//if its NON EE4
1677
+					$db_update_sans_ee4[$version] = $times_activated;
1678
+				}
1679
+			}
1680
+			update_option('espresso_db_update', $db_update_sans_ee4);
1681
+		}
1682
+		$errors = '';
1683
+		if ( ! empty($undeleted_options)) {
1684
+			$errors .= sprintf(
1685
+				__('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1686
+				'<br/>',
1687
+				implode(',<br/>', $undeleted_options)
1688
+			);
1689
+		}
1690
+		if ( ! empty($errors)) {
1691
+			EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1692
+		}
1693
+	}
1694
+
1695
+	/**
1696
+	 * Gets the mysql error code from the last used query by wpdb
1697
+	 *
1698
+	 * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1699
+	 */
1700
+	public static function last_wpdb_error_code()
1701
+	{
1702
+		global $wpdb;
1703
+		if ($wpdb->use_mysqli) {
1704
+			return mysqli_errno($wpdb->dbh);
1705
+		} else {
1706
+			return mysql_errno($wpdb->dbh);
1707
+		}
1708
+	}
1709
+
1710
+	/**
1711
+	 * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1712
+	 *
1713
+	 * @global wpdb  $wpdb
1714
+	 * @deprecated instead use TableAnalysis::tableExists()
1715
+	 * @param string $table_name with or without $wpdb->prefix
1716
+	 * @return boolean
1717
+	 */
1718
+	public static function table_exists($table_name)
1719
+	{
1720
+		return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1721
+	}
1722
+
1723
+	/**
1724
+	 * Resets the cache on EEH_Activation
1725
+	 */
1726
+	public static function reset()
1727
+	{
1728
+		self::$_default_creator_id                             = null;
1729
+		self::$_initialized_db_content_already_in_this_request = false;
1730
+	}
1731 1731
 }
1732 1732
 // End of file EEH_Activation.helper.php
1733 1733
 // Location: /helpers/EEH_Activation.core.php
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 2 patches
Indentation   +2628 added lines, -2628 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
3
-    exit('NO direct script access allowed');
3
+	exit('NO direct script access allowed');
4 4
 }
5 5
 
6 6
 
@@ -17,2634 +17,2634 @@  discard block
 block discarded – undo
17 17
 class Events_Admin_Page extends EE_Admin_Page_CPT
18 18
 {
19 19
 
20
-    /**
21
-     * This will hold the event object for event_details screen.
22
-     *
23
-     * @access protected
24
-     * @var EE_Event $_event
25
-     */
26
-    protected $_event;
27
-
28
-
29
-    /**
30
-     * This will hold the category object for category_details screen.
31
-     *
32
-     * @var stdClass $_category
33
-     */
34
-    protected $_category;
35
-
36
-
37
-    /**
38
-     * This will hold the event model instance
39
-     *
40
-     * @var EEM_Event $_event_model
41
-     */
42
-    protected $_event_model;
43
-
44
-
45
-
46
-    /**
47
-     * @var EE_Event
48
-     */
49
-    protected $_cpt_model_obj = false;
50
-
51
-
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')
69
-        );
70
-    }
71
-
72
-
73
-
74
-    protected function _ajax_hooks()
75
-    {
76
-        //todo: all hooks for events ajax goes in here.
77
-    }
78
-
79
-
80
-
81
-    protected function _define_page_props()
82
-    {
83
-        $this->_admin_page_title = EVENTS_LABEL;
84
-        $this->_labels = array(
85
-            'buttons'      => array(
86
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
87
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
88
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
89
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
90
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
91
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
92
-            ),
93
-            'editor_title' => array(
94
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
95
-            ),
96
-            'publishbox'   => array(
97
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
98
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
99
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
100
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
101
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
102
-            ),
103
-        );
104
-    }
105
-
106
-
107
-
108
-    protected function _set_page_routes()
109
-    {
110
-        //load formatter helper
111
-        //load field generator helper
112
-        //is there a evt_id in the request?
113
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
114
-            ? $this->_req_data['EVT_ID'] : 0;
115
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
116
-        $this->_page_routes = array(
117
-            'default'                       => array(
118
-                'func'       => '_events_overview_list_table',
119
-                'capability' => 'ee_read_events',
120
-            ),
121
-            'create_new'                    => array(
122
-                'func'       => '_create_new_cpt_item',
123
-                'capability' => 'ee_edit_events',
124
-            ),
125
-            'edit'                          => array(
126
-                'func'       => '_edit_cpt_item',
127
-                'capability' => 'ee_edit_event',
128
-                'obj_id'     => $evt_id,
129
-            ),
130
-            'copy_event'                    => array(
131
-                'func'       => '_copy_events',
132
-                'capability' => 'ee_edit_event',
133
-                'obj_id'     => $evt_id,
134
-                'noheader'   => true,
135
-            ),
136
-            'trash_event'                   => array(
137
-                'func'       => '_trash_or_restore_event',
138
-                'args'       => array('event_status' => 'trash'),
139
-                'capability' => 'ee_delete_event',
140
-                'obj_id'     => $evt_id,
141
-                'noheader'   => true,
142
-            ),
143
-            'trash_events'                  => array(
144
-                'func'       => '_trash_or_restore_events',
145
-                'args'       => array('event_status' => 'trash'),
146
-                'capability' => 'ee_delete_events',
147
-                'noheader'   => true,
148
-            ),
149
-            'restore_event'                 => array(
150
-                'func'       => '_trash_or_restore_event',
151
-                'args'       => array('event_status' => 'draft'),
152
-                'capability' => 'ee_delete_event',
153
-                'obj_id'     => $evt_id,
154
-                'noheader'   => true,
155
-            ),
156
-            'restore_events'                => array(
157
-                'func'       => '_trash_or_restore_events',
158
-                'args'       => array('event_status' => 'draft'),
159
-                'capability' => 'ee_delete_events',
160
-                'noheader'   => true,
161
-            ),
162
-            'delete_event'                  => array(
163
-                'func'       => '_delete_event',
164
-                'capability' => 'ee_delete_event',
165
-                'obj_id'     => $evt_id,
166
-                'noheader'   => true,
167
-            ),
168
-            'delete_events'                 => array(
169
-                'func'       => '_delete_events',
170
-                'capability' => 'ee_delete_events',
171
-                'noheader'   => true,
172
-            ),
173
-            'view_report'                   => array(
174
-                'func'      => '_view_report',
175
-                'capablity' => 'ee_edit_events',
176
-            ),
177
-            'default_event_settings'        => array(
178
-                'func'       => '_default_event_settings',
179
-                'capability' => 'manage_options',
180
-            ),
181
-            'update_default_event_settings' => array(
182
-                'func'       => '_update_default_event_settings',
183
-                'capability' => 'manage_options',
184
-                'noheader'   => true,
185
-            ),
186
-            'template_settings'             => array(
187
-                'func'       => '_template_settings',
188
-                'capability' => 'manage_options',
189
-            ),
190
-            //event category tab related
191
-            'add_category'                  => array(
192
-                'func'       => '_category_details',
193
-                'capability' => 'ee_edit_event_category',
194
-                'args'       => array('add'),
195
-            ),
196
-            'edit_category'                 => array(
197
-                'func'       => '_category_details',
198
-                'capability' => 'ee_edit_event_category',
199
-                'args'       => array('edit'),
200
-            ),
201
-            'delete_categories'             => array(
202
-                'func'       => '_delete_categories',
203
-                'capability' => 'ee_delete_event_category',
204
-                'noheader'   => true,
205
-            ),
206
-            'delete_category'               => array(
207
-                'func'       => '_delete_categories',
208
-                'capability' => 'ee_delete_event_category',
209
-                'noheader'   => true,
210
-            ),
211
-            'insert_category'               => array(
212
-                'func'       => '_insert_or_update_category',
213
-                'args'       => array('new_category' => true),
214
-                'capability' => 'ee_edit_event_category',
215
-                'noheader'   => true,
216
-            ),
217
-            'update_category'               => array(
218
-                'func'       => '_insert_or_update_category',
219
-                'args'       => array('new_category' => false),
220
-                'capability' => 'ee_edit_event_category',
221
-                'noheader'   => true,
222
-            ),
223
-            'category_list'                 => array(
224
-                'func'       => '_category_list_table',
225
-                'capability' => 'ee_manage_event_categories',
226
-            ),
227
-        );
228
-    }
229
-
230
-
231
-
232
-    protected function _set_page_config()
233
-    {
234
-        $this->_page_config = array(
235
-            'default'                => array(
236
-                'nav'           => array(
237
-                    'label' => esc_html__('Overview', 'event_espresso'),
238
-                    'order' => 10,
239
-                ),
240
-                'list_table'    => 'Events_Admin_List_Table',
241
-                'help_tabs'     => array(
242
-                    'events_overview_help_tab'                       => array(
243
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
244
-                        'filename' => 'events_overview',
245
-                    ),
246
-                    'events_overview_table_column_headings_help_tab' => array(
247
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
248
-                        'filename' => 'events_overview_table_column_headings',
249
-                    ),
250
-                    'events_overview_filters_help_tab'               => array(
251
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
252
-                        'filename' => 'events_overview_filters',
253
-                    ),
254
-                    'events_overview_view_help_tab'                  => array(
255
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
256
-                        'filename' => 'events_overview_views',
257
-                    ),
258
-                    'events_overview_other_help_tab'                 => array(
259
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
260
-                        'filename' => 'events_overview_other',
261
-                    ),
262
-                ),
263
-                'help_tour'     => array(
264
-                    'Event_Overview_Help_Tour',
265
-                    //'New_Features_Test_Help_Tour' for testing multiple help tour
266
-                ),
267
-                'qtips'         => array(
268
-                    'EE_Event_List_Table_Tips',
269
-                ),
270
-                'require_nonce' => false,
271
-            ),
272
-            'create_new'             => array(
273
-                'nav'           => array(
274
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
275
-                    'order'      => 5,
276
-                    'persistent' => false,
277
-                ),
278
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
279
-                'help_tabs'     => array(
280
-                    'event_editor_help_tab'                            => array(
281
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
282
-                        'filename' => 'event_editor',
283
-                    ),
284
-                    'event_editor_title_richtexteditor_help_tab'       => array(
285
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
286
-                        'filename' => 'event_editor_title_richtexteditor',
287
-                    ),
288
-                    'event_editor_venue_details_help_tab'              => array(
289
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
290
-                        'filename' => 'event_editor_venue_details',
291
-                    ),
292
-                    'event_editor_event_datetimes_help_tab'            => array(
293
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
294
-                        'filename' => 'event_editor_event_datetimes',
295
-                    ),
296
-                    'event_editor_event_tickets_help_tab'              => array(
297
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
298
-                        'filename' => 'event_editor_event_tickets',
299
-                    ),
300
-                    'event_editor_event_registration_options_help_tab' => array(
301
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
302
-                        'filename' => 'event_editor_event_registration_options',
303
-                    ),
304
-                    'event_editor_tags_categories_help_tab'            => array(
305
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
306
-                        'filename' => 'event_editor_tags_categories',
307
-                    ),
308
-                    'event_editor_questions_registrants_help_tab'      => array(
309
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
310
-                        'filename' => 'event_editor_questions_registrants',
311
-                    ),
312
-                    'event_editor_save_new_event_help_tab'             => array(
313
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
314
-                        'filename' => 'event_editor_save_new_event',
315
-                    ),
316
-                    'event_editor_other_help_tab'                      => array(
317
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
318
-                        'filename' => 'event_editor_other',
319
-                    ),
320
-                ),
321
-                'help_tour'     => array(
322
-                    'Event_Editor_Help_Tour',
323
-                ),
324
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
325
-                'require_nonce' => false,
326
-            ),
327
-            'edit'                   => array(
328
-                'nav'           => array(
329
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
330
-                    'order'      => 5,
331
-                    'persistent' => false,
332
-                    'url'        => isset($this->_req_data['post'])
333
-                        ? EE_Admin_Page::add_query_args_and_nonce(
334
-                            array('post' => $this->_req_data['post'], 'action' => 'edit'),
335
-                            $this->_current_page_view_url
336
-                        )
337
-                        : $this->_admin_base_url,
338
-                ),
339
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
340
-                'help_tabs'     => array(
341
-                    'event_editor_help_tab'                            => array(
342
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
343
-                        'filename' => 'event_editor',
344
-                    ),
345
-                    'event_editor_title_richtexteditor_help_tab'       => array(
346
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
347
-                        'filename' => 'event_editor_title_richtexteditor',
348
-                    ),
349
-                    'event_editor_venue_details_help_tab'              => array(
350
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
351
-                        'filename' => 'event_editor_venue_details',
352
-                    ),
353
-                    'event_editor_event_datetimes_help_tab'            => array(
354
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
355
-                        'filename' => 'event_editor_event_datetimes',
356
-                    ),
357
-                    'event_editor_event_tickets_help_tab'              => array(
358
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
359
-                        'filename' => 'event_editor_event_tickets',
360
-                    ),
361
-                    'event_editor_event_registration_options_help_tab' => array(
362
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
363
-                        'filename' => 'event_editor_event_registration_options',
364
-                    ),
365
-                    'event_editor_tags_categories_help_tab'            => array(
366
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
367
-                        'filename' => 'event_editor_tags_categories',
368
-                    ),
369
-                    'event_editor_questions_registrants_help_tab'      => array(
370
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
371
-                        'filename' => 'event_editor_questions_registrants',
372
-                    ),
373
-                    'event_editor_save_new_event_help_tab'             => array(
374
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
375
-                        'filename' => 'event_editor_save_new_event',
376
-                    ),
377
-                    'event_editor_other_help_tab'                      => array(
378
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
379
-                        'filename' => 'event_editor_other',
380
-                    ),
381
-                ),
382
-                /*'help_tour' => array(
20
+	/**
21
+	 * This will hold the event object for event_details screen.
22
+	 *
23
+	 * @access protected
24
+	 * @var EE_Event $_event
25
+	 */
26
+	protected $_event;
27
+
28
+
29
+	/**
30
+	 * This will hold the category object for category_details screen.
31
+	 *
32
+	 * @var stdClass $_category
33
+	 */
34
+	protected $_category;
35
+
36
+
37
+	/**
38
+	 * This will hold the event model instance
39
+	 *
40
+	 * @var EEM_Event $_event_model
41
+	 */
42
+	protected $_event_model;
43
+
44
+
45
+
46
+	/**
47
+	 * @var EE_Event
48
+	 */
49
+	protected $_cpt_model_obj = false;
50
+
51
+
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')
69
+		);
70
+	}
71
+
72
+
73
+
74
+	protected function _ajax_hooks()
75
+	{
76
+		//todo: all hooks for events ajax goes in here.
77
+	}
78
+
79
+
80
+
81
+	protected function _define_page_props()
82
+	{
83
+		$this->_admin_page_title = EVENTS_LABEL;
84
+		$this->_labels = array(
85
+			'buttons'      => array(
86
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
87
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
88
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
89
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
90
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
91
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
92
+			),
93
+			'editor_title' => array(
94
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
95
+			),
96
+			'publishbox'   => array(
97
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
98
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
99
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
100
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
101
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
102
+			),
103
+		);
104
+	}
105
+
106
+
107
+
108
+	protected function _set_page_routes()
109
+	{
110
+		//load formatter helper
111
+		//load field generator helper
112
+		//is there a evt_id in the request?
113
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
114
+			? $this->_req_data['EVT_ID'] : 0;
115
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
116
+		$this->_page_routes = array(
117
+			'default'                       => array(
118
+				'func'       => '_events_overview_list_table',
119
+				'capability' => 'ee_read_events',
120
+			),
121
+			'create_new'                    => array(
122
+				'func'       => '_create_new_cpt_item',
123
+				'capability' => 'ee_edit_events',
124
+			),
125
+			'edit'                          => array(
126
+				'func'       => '_edit_cpt_item',
127
+				'capability' => 'ee_edit_event',
128
+				'obj_id'     => $evt_id,
129
+			),
130
+			'copy_event'                    => array(
131
+				'func'       => '_copy_events',
132
+				'capability' => 'ee_edit_event',
133
+				'obj_id'     => $evt_id,
134
+				'noheader'   => true,
135
+			),
136
+			'trash_event'                   => array(
137
+				'func'       => '_trash_or_restore_event',
138
+				'args'       => array('event_status' => 'trash'),
139
+				'capability' => 'ee_delete_event',
140
+				'obj_id'     => $evt_id,
141
+				'noheader'   => true,
142
+			),
143
+			'trash_events'                  => array(
144
+				'func'       => '_trash_or_restore_events',
145
+				'args'       => array('event_status' => 'trash'),
146
+				'capability' => 'ee_delete_events',
147
+				'noheader'   => true,
148
+			),
149
+			'restore_event'                 => array(
150
+				'func'       => '_trash_or_restore_event',
151
+				'args'       => array('event_status' => 'draft'),
152
+				'capability' => 'ee_delete_event',
153
+				'obj_id'     => $evt_id,
154
+				'noheader'   => true,
155
+			),
156
+			'restore_events'                => array(
157
+				'func'       => '_trash_or_restore_events',
158
+				'args'       => array('event_status' => 'draft'),
159
+				'capability' => 'ee_delete_events',
160
+				'noheader'   => true,
161
+			),
162
+			'delete_event'                  => array(
163
+				'func'       => '_delete_event',
164
+				'capability' => 'ee_delete_event',
165
+				'obj_id'     => $evt_id,
166
+				'noheader'   => true,
167
+			),
168
+			'delete_events'                 => array(
169
+				'func'       => '_delete_events',
170
+				'capability' => 'ee_delete_events',
171
+				'noheader'   => true,
172
+			),
173
+			'view_report'                   => array(
174
+				'func'      => '_view_report',
175
+				'capablity' => 'ee_edit_events',
176
+			),
177
+			'default_event_settings'        => array(
178
+				'func'       => '_default_event_settings',
179
+				'capability' => 'manage_options',
180
+			),
181
+			'update_default_event_settings' => array(
182
+				'func'       => '_update_default_event_settings',
183
+				'capability' => 'manage_options',
184
+				'noheader'   => true,
185
+			),
186
+			'template_settings'             => array(
187
+				'func'       => '_template_settings',
188
+				'capability' => 'manage_options',
189
+			),
190
+			//event category tab related
191
+			'add_category'                  => array(
192
+				'func'       => '_category_details',
193
+				'capability' => 'ee_edit_event_category',
194
+				'args'       => array('add'),
195
+			),
196
+			'edit_category'                 => array(
197
+				'func'       => '_category_details',
198
+				'capability' => 'ee_edit_event_category',
199
+				'args'       => array('edit'),
200
+			),
201
+			'delete_categories'             => array(
202
+				'func'       => '_delete_categories',
203
+				'capability' => 'ee_delete_event_category',
204
+				'noheader'   => true,
205
+			),
206
+			'delete_category'               => array(
207
+				'func'       => '_delete_categories',
208
+				'capability' => 'ee_delete_event_category',
209
+				'noheader'   => true,
210
+			),
211
+			'insert_category'               => array(
212
+				'func'       => '_insert_or_update_category',
213
+				'args'       => array('new_category' => true),
214
+				'capability' => 'ee_edit_event_category',
215
+				'noheader'   => true,
216
+			),
217
+			'update_category'               => array(
218
+				'func'       => '_insert_or_update_category',
219
+				'args'       => array('new_category' => false),
220
+				'capability' => 'ee_edit_event_category',
221
+				'noheader'   => true,
222
+			),
223
+			'category_list'                 => array(
224
+				'func'       => '_category_list_table',
225
+				'capability' => 'ee_manage_event_categories',
226
+			),
227
+		);
228
+	}
229
+
230
+
231
+
232
+	protected function _set_page_config()
233
+	{
234
+		$this->_page_config = array(
235
+			'default'                => array(
236
+				'nav'           => array(
237
+					'label' => esc_html__('Overview', 'event_espresso'),
238
+					'order' => 10,
239
+				),
240
+				'list_table'    => 'Events_Admin_List_Table',
241
+				'help_tabs'     => array(
242
+					'events_overview_help_tab'                       => array(
243
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
244
+						'filename' => 'events_overview',
245
+					),
246
+					'events_overview_table_column_headings_help_tab' => array(
247
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
248
+						'filename' => 'events_overview_table_column_headings',
249
+					),
250
+					'events_overview_filters_help_tab'               => array(
251
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
252
+						'filename' => 'events_overview_filters',
253
+					),
254
+					'events_overview_view_help_tab'                  => array(
255
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
256
+						'filename' => 'events_overview_views',
257
+					),
258
+					'events_overview_other_help_tab'                 => array(
259
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
260
+						'filename' => 'events_overview_other',
261
+					),
262
+				),
263
+				'help_tour'     => array(
264
+					'Event_Overview_Help_Tour',
265
+					//'New_Features_Test_Help_Tour' for testing multiple help tour
266
+				),
267
+				'qtips'         => array(
268
+					'EE_Event_List_Table_Tips',
269
+				),
270
+				'require_nonce' => false,
271
+			),
272
+			'create_new'             => array(
273
+				'nav'           => array(
274
+					'label'      => esc_html__('Add Event', 'event_espresso'),
275
+					'order'      => 5,
276
+					'persistent' => false,
277
+				),
278
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
279
+				'help_tabs'     => array(
280
+					'event_editor_help_tab'                            => array(
281
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
282
+						'filename' => 'event_editor',
283
+					),
284
+					'event_editor_title_richtexteditor_help_tab'       => array(
285
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
286
+						'filename' => 'event_editor_title_richtexteditor',
287
+					),
288
+					'event_editor_venue_details_help_tab'              => array(
289
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
290
+						'filename' => 'event_editor_venue_details',
291
+					),
292
+					'event_editor_event_datetimes_help_tab'            => array(
293
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
294
+						'filename' => 'event_editor_event_datetimes',
295
+					),
296
+					'event_editor_event_tickets_help_tab'              => array(
297
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
298
+						'filename' => 'event_editor_event_tickets',
299
+					),
300
+					'event_editor_event_registration_options_help_tab' => array(
301
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
302
+						'filename' => 'event_editor_event_registration_options',
303
+					),
304
+					'event_editor_tags_categories_help_tab'            => array(
305
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
306
+						'filename' => 'event_editor_tags_categories',
307
+					),
308
+					'event_editor_questions_registrants_help_tab'      => array(
309
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
310
+						'filename' => 'event_editor_questions_registrants',
311
+					),
312
+					'event_editor_save_new_event_help_tab'             => array(
313
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
314
+						'filename' => 'event_editor_save_new_event',
315
+					),
316
+					'event_editor_other_help_tab'                      => array(
317
+						'title'    => esc_html__('Event Other', 'event_espresso'),
318
+						'filename' => 'event_editor_other',
319
+					),
320
+				),
321
+				'help_tour'     => array(
322
+					'Event_Editor_Help_Tour',
323
+				),
324
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
325
+				'require_nonce' => false,
326
+			),
327
+			'edit'                   => array(
328
+				'nav'           => array(
329
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
330
+					'order'      => 5,
331
+					'persistent' => false,
332
+					'url'        => isset($this->_req_data['post'])
333
+						? EE_Admin_Page::add_query_args_and_nonce(
334
+							array('post' => $this->_req_data['post'], 'action' => 'edit'),
335
+							$this->_current_page_view_url
336
+						)
337
+						: $this->_admin_base_url,
338
+				),
339
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
340
+				'help_tabs'     => array(
341
+					'event_editor_help_tab'                            => array(
342
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
343
+						'filename' => 'event_editor',
344
+					),
345
+					'event_editor_title_richtexteditor_help_tab'       => array(
346
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
347
+						'filename' => 'event_editor_title_richtexteditor',
348
+					),
349
+					'event_editor_venue_details_help_tab'              => array(
350
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
351
+						'filename' => 'event_editor_venue_details',
352
+					),
353
+					'event_editor_event_datetimes_help_tab'            => array(
354
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
355
+						'filename' => 'event_editor_event_datetimes',
356
+					),
357
+					'event_editor_event_tickets_help_tab'              => array(
358
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
359
+						'filename' => 'event_editor_event_tickets',
360
+					),
361
+					'event_editor_event_registration_options_help_tab' => array(
362
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
363
+						'filename' => 'event_editor_event_registration_options',
364
+					),
365
+					'event_editor_tags_categories_help_tab'            => array(
366
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
367
+						'filename' => 'event_editor_tags_categories',
368
+					),
369
+					'event_editor_questions_registrants_help_tab'      => array(
370
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
371
+						'filename' => 'event_editor_questions_registrants',
372
+					),
373
+					'event_editor_save_new_event_help_tab'             => array(
374
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
375
+						'filename' => 'event_editor_save_new_event',
376
+					),
377
+					'event_editor_other_help_tab'                      => array(
378
+						'title'    => esc_html__('Event Other', 'event_espresso'),
379
+						'filename' => 'event_editor_other',
380
+					),
381
+				),
382
+				/*'help_tour' => array(
383 383
 					'Event_Edit_Help_Tour'
384 384
 				),*/
385
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
386
-                'require_nonce' => false,
387
-            ),
388
-            'default_event_settings' => array(
389
-                'nav'           => array(
390
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
391
-                    'order' => 40,
392
-                ),
393
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
394
-                'labels'        => array(
395
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
396
-                ),
397
-                'help_tabs'     => array(
398
-                    'default_settings_help_tab'        => array(
399
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
400
-                        'filename' => 'events_default_settings',
401
-                    ),
402
-                    'default_settings_status_help_tab' => array(
403
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
404
-                        'filename' => 'events_default_settings_status',
405
-                    ),
406
-                    'default_maximum_tickets_help_tab' => array(
407
-                        'title' => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
408
-                        'filename' => 'events_default_settings_max_tickets',
409
-                    )
410
-                ),
411
-                'help_tour'     => array('Event_Default_Settings_Help_Tour'),
412
-                'require_nonce' => false,
413
-            ),
414
-            //template settings
415
-            'template_settings'      => array(
416
-                'nav'           => array(
417
-                    'label' => esc_html__('Templates', 'event_espresso'),
418
-                    'order' => 30,
419
-                ),
420
-                'metaboxes'     => $this->_default_espresso_metaboxes,
421
-                'help_tabs'     => array(
422
-                    'general_settings_templates_help_tab' => array(
423
-                        'title'    => esc_html__('Templates', 'event_espresso'),
424
-                        'filename' => 'general_settings_templates',
425
-                    ),
426
-                ),
427
-                'help_tour'     => array('Templates_Help_Tour'),
428
-                'require_nonce' => false,
429
-            ),
430
-            //event category stuff
431
-            'add_category'           => array(
432
-                'nav'           => array(
433
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
434
-                    'order'      => 15,
435
-                    'persistent' => false,
436
-                ),
437
-                'help_tabs'     => array(
438
-                    'add_category_help_tab' => array(
439
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
440
-                        'filename' => 'events_add_category',
441
-                    ),
442
-                ),
443
-                'help_tour'     => array('Event_Add_Category_Help_Tour'),
444
-                'metaboxes'     => array('_publish_post_box'),
445
-                'require_nonce' => false,
446
-            ),
447
-            'edit_category'          => array(
448
-                'nav'           => array(
449
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
450
-                    'order'      => 15,
451
-                    'persistent' => false,
452
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
453
-                        ? add_query_arg(
454
-                            array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
455
-                            $this->_current_page_view_url
456
-                        )
457
-                        : $this->_admin_base_url,
458
-                ),
459
-                'help_tabs'     => array(
460
-                    'edit_category_help_tab' => array(
461
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
462
-                        'filename' => 'events_edit_category',
463
-                    ),
464
-                ),
465
-                /*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
466
-                'metaboxes'     => array('_publish_post_box'),
467
-                'require_nonce' => false,
468
-            ),
469
-            'category_list'          => array(
470
-                'nav'           => array(
471
-                    'label' => esc_html__('Categories', 'event_espresso'),
472
-                    'order' => 20,
473
-                ),
474
-                'list_table'    => 'Event_Categories_Admin_List_Table',
475
-                'help_tabs'     => array(
476
-                    'events_categories_help_tab'                       => array(
477
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
478
-                        'filename' => 'events_categories',
479
-                    ),
480
-                    'events_categories_table_column_headings_help_tab' => array(
481
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
482
-                        'filename' => 'events_categories_table_column_headings',
483
-                    ),
484
-                    'events_categories_view_help_tab'                  => array(
485
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
486
-                        'filename' => 'events_categories_views',
487
-                    ),
488
-                    'events_categories_other_help_tab'                 => array(
489
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
490
-                        'filename' => 'events_categories_other',
491
-                    ),
492
-                ),
493
-                'help_tour'     => array(
494
-                    'Event_Categories_Help_Tour',
495
-                ),
496
-                'metaboxes'     => $this->_default_espresso_metaboxes,
497
-                'require_nonce' => false,
498
-            ),
499
-        );
500
-    }
501
-
502
-
503
-
504
-    protected function _add_screen_options()
505
-    {
506
-        //todo
507
-    }
508
-
509
-
510
-
511
-    protected function _add_screen_options_default()
512
-    {
513
-        $this->_per_page_screen_option();
514
-    }
515
-
516
-
517
-
518
-    protected function _add_screen_options_category_list()
519
-    {
520
-        $page_title = $this->_admin_page_title;
521
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
522
-        $this->_per_page_screen_option();
523
-        $this->_admin_page_title = $page_title;
524
-    }
525
-
526
-
527
-
528
-    protected function _add_feature_pointers()
529
-    {
530
-        //todo
531
-    }
532
-
533
-
534
-
535
-    public function load_scripts_styles()
536
-    {
537
-        wp_register_style(
538
-            'events-admin-css',
539
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
540
-            array(),
541
-            EVENT_ESPRESSO_VERSION
542
-        );
543
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
544
-        wp_enqueue_style('events-admin-css');
545
-        wp_enqueue_style('ee-cat-admin');
546
-        //todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
547
-        //registers for all views
548
-        //scripts
549
-        wp_register_script(
550
-            'event_editor_js',
551
-            EVENTS_ASSETS_URL . 'event_editor.js',
552
-            array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
553
-            EVENT_ESPRESSO_VERSION,
554
-            true
555
-        );
556
-    }
557
-
558
-
559
-
560
-    /**
561
-     * enqueuing scripts and styles specific to this view
562
-     *
563
-     * @return void
564
-     */
565
-    public function load_scripts_styles_create_new()
566
-    {
567
-        $this->load_scripts_styles_edit();
568
-    }
569
-
570
-
571
-
572
-    /**
573
-     * enqueuing scripts and styles specific to this view
574
-     *
575
-     * @return void
576
-     */
577
-    public function load_scripts_styles_edit()
578
-    {
579
-        //styles
580
-        wp_enqueue_style('espresso-ui-theme');
581
-        wp_register_style(
582
-            'event-editor-css',
583
-            EVENTS_ASSETS_URL . 'event-editor.css',
584
-            array('ee-admin-css'),
585
-            EVENT_ESPRESSO_VERSION
586
-        );
587
-        wp_enqueue_style('event-editor-css');
588
-        //scripts
589
-        wp_register_script(
590
-            'event-datetime-metabox',
591
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
592
-            array('event_editor_js', 'ee-datepicker'),
593
-            EVENT_ESPRESSO_VERSION
594
-        );
595
-        wp_enqueue_script('event-datetime-metabox');
596
-    }
597
-
598
-
599
-
600
-    public function load_scripts_styles_add_category()
601
-    {
602
-        $this->load_scripts_styles_edit_category();
603
-    }
604
-
605
-
606
-
607
-    public function load_scripts_styles_edit_category()
608
-    {
609
-    }
610
-
611
-
612
-
613
-    protected function _set_list_table_views_category_list()
614
-    {
615
-        $this->_views = array(
616
-            'all' => array(
617
-                'slug'        => 'all',
618
-                'label'       => esc_html__('All', 'event_espresso'),
619
-                'count'       => 0,
620
-                'bulk_action' => array(
621
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
622
-                ),
623
-            ),
624
-        );
625
-    }
626
-
627
-
628
-
629
-    public function admin_init()
630
-    {
631
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
632
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
633
-            'event_espresso'
634
-        );
635
-    }
636
-
637
-
638
-
639
-    //nothing needed for events with these methods.
640
-    public function admin_notices()
641
-    {
642
-    }
643
-
644
-
645
-
646
-    public function admin_footer_scripts()
647
-    {
648
-    }
649
-
650
-
651
-
652
-    /**
653
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
654
-     * warning (via EE_Error::add_error());
655
-     *
656
-     * @param  EE_Event $event Event object
657
-     * @access public
658
-     * @return void
659
-     */
660
-    public function verify_event_edit($event = null)
661
-    {
662
-        // no event?
663
-        if (empty($event)) {
664
-            // set event
665
-            $event = $this->_cpt_model_obj;
666
-        }
667
-        // STILL no event?
668
-        if (! $event instanceof EE_Event) {
669
-            return;
670
-        }
671
-        $orig_status = $event->status();
672
-        // first check if event is active.
673
-        if (
674
-            $orig_status === EEM_Event::cancelled
675
-            || $orig_status === EEM_Event::postponed
676
-            || $event->is_expired()
677
-            || $event->is_inactive()
678
-        ) {
679
-            return;
680
-        }
681
-        //made it here so it IS active... next check that any of the tickets are sold.
682
-        if ($event->is_sold_out(true)) {
683
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
684
-                EE_Error::add_attention(
685
-                    sprintf(
686
-                        esc_html__(
687
-                            '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.',
688
-                            'event_espresso'
689
-                        ),
690
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
691
-                    )
692
-                );
693
-            }
694
-            return;
695
-        } else if ($orig_status === EEM_Event::sold_out) {
696
-            EE_Error::add_attention(
697
-                sprintf(
698
-                    esc_html__(
699
-                        '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.',
700
-                        'event_espresso'
701
-                    ),
702
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
703
-                )
704
-            );
705
-        }
706
-        //now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
707
-        if ( ! $event->tickets_on_sale()) {
708
-            return;
709
-        }
710
-        //made it here so show warning
711
-        $this->_edit_event_warning();
712
-    }
713
-
714
-
715
-
716
-    /**
717
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
718
-     * When needed, hook this into a EE_Error::add_error() notice.
719
-     *
720
-     * @access protected
721
-     * @return void
722
-     */
723
-    protected function _edit_event_warning()
724
-    {
725
-        // we don't want to add warnings during these requests
726
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
727
-            return;
728
-        }
729
-        EE_Error::add_attention(
730
-            esc_html__(
731
-                '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.',
732
-                'event_espresso'
733
-            )
734
-        );
735
-    }
736
-
737
-
738
-
739
-    /**
740
-     * When a user is creating a new event, notify them if they haven't set their timezone.
741
-     * Otherwise, do the normal logic
742
-     *
743
-     * @return string
744
-     * @throws \EE_Error
745
-     */
746
-    protected function _create_new_cpt_item()
747
-    {
748
-        $gmt_offset = get_option('gmt_offset');
749
-        //only nag them about setting their timezone if it's their first event, and they haven't already done it
750
-        if ($gmt_offset === '0' && ! EEM_Event::instance()->exists(array())) {
751
-            EE_Error::add_attention(
752
-                sprintf(
753
-                    __(
754
-                        'Your website\'s timezone is currently set to UTC + 0. We recommend updating your timezone to a city or region near you before you create an event. Your timezone can be updated through the %1$sGeneral Settings%2$s page.',
755
-                        'event_espresso'
756
-                    ),
757
-                    '<a href="' . admin_url('options-general.php') . '">',
758
-                    '</a>'
759
-                ),
760
-                __FILE__,
761
-                __FUNCTION__,
762
-                __LINE__
763
-            );
764
-        }
765
-        return parent::_create_new_cpt_item();
766
-    }
767
-
768
-
769
-
770
-    protected function _set_list_table_views_default()
771
-    {
772
-        $this->_views = array(
773
-            'all'   => array(
774
-                'slug'        => 'all',
775
-                'label'       => esc_html__('View All Events', 'event_espresso'),
776
-                'count'       => 0,
777
-                'bulk_action' => array(
778
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
779
-                ),
780
-            ),
781
-            'draft' => array(
782
-                'slug'        => 'draft',
783
-                'label'       => esc_html__('Draft', 'event_espresso'),
784
-                'count'       => 0,
785
-                'bulk_action' => array(
786
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
787
-                ),
788
-            ),
789
-        );
790
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
791
-            $this->_views['trash'] = array(
792
-                'slug'        => 'trash',
793
-                'label'       => esc_html__('Trash', 'event_espresso'),
794
-                'count'       => 0,
795
-                'bulk_action' => array(
796
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
797
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
798
-                ),
799
-            );
800
-        }
801
-    }
802
-
803
-
804
-
805
-    /**
806
-     * @return array
807
-     */
808
-    protected function _event_legend_items()
809
-    {
810
-        $items = array(
811
-            'view_details'   => array(
812
-                'class' => 'dashicons dashicons-search',
813
-                'desc'  => esc_html__('View Event', 'event_espresso'),
814
-            ),
815
-            'edit_event'     => array(
816
-                'class' => 'ee-icon ee-icon-calendar-edit',
817
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
818
-            ),
819
-            'view_attendees' => array(
820
-                'class' => 'dashicons dashicons-groups',
821
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
822
-            ),
823
-        );
824
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
825
-        $statuses = array(
826
-            'sold_out_status'  => array(
827
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
828
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
829
-            ),
830
-            'active_status'    => array(
831
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
832
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
833
-            ),
834
-            'upcoming_status'  => array(
835
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
836
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
837
-            ),
838
-            'postponed_status' => array(
839
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
840
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
841
-            ),
842
-            'cancelled_status' => array(
843
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
844
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
845
-            ),
846
-            'expired_status'   => array(
847
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
848
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
849
-            ),
850
-            'inactive_status'  => array(
851
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
852
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
853
-            ),
854
-        );
855
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
856
-        return array_merge($items, $statuses);
857
-    }
858
-
859
-
860
-
861
-    /**
862
-     * _event_model
863
-     *
864
-     * @return EEM_Event
865
-     */
866
-    private function _event_model()
867
-    {
868
-        if ( ! $this->_event_model instanceof EEM_Event) {
869
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
870
-        }
871
-        return $this->_event_model;
872
-    }
873
-
874
-
875
-
876
-    /**
877
-     * Adds extra buttons to the WP CPT permalink field row.
878
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
879
-     *
880
-     * @param  string $return    the current html
881
-     * @param  int    $id        the post id for the page
882
-     * @param  string $new_title What the title is
883
-     * @param  string $new_slug  what the slug is
884
-     * @return string            The new html string for the permalink area
885
-     */
886
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
887
-    {
888
-        //make sure this is only when editing
889
-        if ( ! empty($id)) {
890
-            $post = get_post($id);
891
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
892
-                       . esc_html__('Shortcode', 'event_espresso')
893
-                       . '</a> ';
894
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
895
-                       . $post->ID
896
-                       . ']">';
897
-        }
898
-        return $return;
899
-    }
900
-
901
-
902
-
903
-    /**
904
-     * _events_overview_list_table
905
-     * This contains the logic for showing the events_overview list
906
-     *
907
-     * @access protected
908
-     * @return void
909
-     * @throws \EE_Error
910
-     */
911
-    protected function _events_overview_list_table()
912
-    {
913
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
914
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
915
-            ? (array)$this->_template_args['after_list_table']
916
-            : array();
917
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
918
-                                                                              . EEH_Template::get_button_or_link(
919
-                get_post_type_archive_link('espresso_events'),
920
-                esc_html__("View Event Archive Page", "event_espresso"),
921
-                'button'
922
-            );
923
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
924
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
925
-                'create_new',
926
-                'add',
927
-                array(),
928
-                'add-new-h2'
929
-            );
930
-        $this->display_admin_list_table_page_with_no_sidebar();
931
-    }
932
-
933
-
934
-
935
-    /**
936
-     * this allows for extra misc actions in the default WP publish box
937
-     *
938
-     * @return void
939
-     */
940
-    public function extra_misc_actions_publish_box()
941
-    {
942
-        $this->_generate_publish_box_extra_content();
943
-    }
944
-
945
-
946
-
947
-    /**
948
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
949
-     * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
950
-     * data.
951
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
952
-     * ALSO very important.  When a post transitions from scheduled to published, the save_post action is fired but you
953
-     * will NOT have any _POST data containing any extra info you may have from other meta saves.  So MAKE sure that
954
-     * you handle this accordingly.
955
-     *
956
-     * @access protected
957
-     * @abstract
958
-     * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
959
-     * @param  object $post    The post object of the cpt that was saved.
960
-     * @return void
961
-     */
962
-    protected function _insert_update_cpt_item($post_id, $post)
963
-    {
964
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
965
-            //get out we're not processing an event save.
966
-            return;
967
-        }
968
-        $event_values = array(
969
-            'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
970
-            'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
971
-            'EVT_additional_limit'            => min(
972
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
973
-                ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
974
-            ),
975
-            'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
976
-                ? $this->_req_data['EVT_default_registration_status']
977
-                : EE_Registry::instance()->CFG->registration->default_STS_ID,
978
-            'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
979
-            'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
980
-            'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
981
-                ? $this->_req_data['timezone_string'] : null,
982
-            'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
983
-                ? $this->_req_data['externalURL'] : null,
984
-            'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
985
-                ? $this->_req_data['event_phone'] : null,
986
-        );
987
-        //update event
988
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
989
-        //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!
990
-        $get_one_where = array($this->_event_model()->primary_key_name() => $post_id, 'status' => $post->post_status);
991
-        $event = $this->_event_model()->get_one(array($get_one_where));
992
-        //the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
993
-        $event_update_callbacks = apply_filters(
994
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
995
-            array(array($this, '_default_venue_update'), array($this, '_default_tickets_update'))
996
-        );
997
-        $att_success = true;
998
-        foreach ($event_update_callbacks as $e_callback) {
999
-            $_succ = call_user_func_array($e_callback, array($event, $this->_req_data));
1000
-            $att_success = ! $att_success ? $att_success
1001
-                : $_succ; //if ANY of these updates fail then we want the appropriate global error message
1002
-        }
1003
-        //any errors?
1004
-        if ($success && false === $att_success) {
1005
-            EE_Error::add_error(
1006
-                esc_html__(
1007
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1008
-                    'event_espresso'
1009
-                ),
1010
-                __FILE__,
1011
-                __FUNCTION__,
1012
-                __LINE__
1013
-            );
1014
-        } else if ($success === false) {
1015
-            EE_Error::add_error(
1016
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1017
-                __FILE__,
1018
-                __FUNCTION__,
1019
-                __LINE__
1020
-            );
1021
-        }
1022
-    }
1023
-
1024
-
1025
-
1026
-    /**
1027
-     * @see parent::restore_item()
1028
-     * @param int $post_id
1029
-     * @param int $revision_id
1030
-     */
1031
-    protected function _restore_cpt_item($post_id, $revision_id)
1032
-    {
1033
-        //copy existing event meta to new post
1034
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1035
-        if ($post_evt instanceof EE_Event) {
1036
-            //meta revision restore
1037
-            $post_evt->restore_revision($revision_id);
1038
-            //related objs restore
1039
-            $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1040
-        }
1041
-    }
1042
-
1043
-
1044
-
1045
-    /**
1046
-     * Attach the venue to the Event
1047
-     *
1048
-     * @param  \EE_Event $evtobj Event Object to add the venue to
1049
-     * @param  array     $data   The request data from the form
1050
-     * @return bool           Success or fail.
1051
-     */
1052
-    protected function _default_venue_update(\EE_Event $evtobj, $data)
1053
-    {
1054
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1055
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1056
-        $rows_affected = null;
1057
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1058
-        // very important.  If we don't have a venue name...
1059
-        // then we'll get out because not necessary to create empty venue
1060
-        if (empty($data['venue_title'])) {
1061
-            return false;
1062
-        }
1063
-        $venue_array = array(
1064
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1065
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1066
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1067
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1068
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1069
-                : null,
1070
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1071
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1072
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1073
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1074
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1075
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1076
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1077
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1078
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1079
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1080
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1081
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1082
-            'status'              => 'publish',
1083
-        );
1084
-        //if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1085
-        if ( ! empty($venue_id)) {
1086
-            $update_where = array($venue_model->primary_key_name() => $venue_id);
1087
-            $rows_affected = $venue_model->update($venue_array, array($update_where));
1088
-            //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.
1089
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1090
-            return $rows_affected > 0 ? true : false;
1091
-        } else {
1092
-            //we insert the venue
1093
-            $venue_id = $venue_model->insert($venue_array);
1094
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1095
-            return ! empty($venue_id) ? true : false;
1096
-        }
1097
-        //when we have the ancestor come in it's already been handled by the revision save.
1098
-    }
1099
-
1100
-
1101
-
1102
-    /**
1103
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1104
-     *
1105
-     * @param  EE_Event $evtobj The Event object we're attaching data to
1106
-     * @param  array    $data   The request data from the form
1107
-     * @return array
1108
-     */
1109
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1110
-    {
1111
-        $success = true;
1112
-        $saved_dtt = null;
1113
-        $saved_tickets = array();
1114
-        $incoming_date_formats = array('Y-m-d', 'h:i a');
1115
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1116
-            //trim all values to ensure any excess whitespace is removed.
1117
-            $dtt = array_map('trim', $dtt);
1118
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1119
-                : $dtt['DTT_EVT_start'];
1120
-            $datetime_values = array(
1121
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1122
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1123
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1124
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1125
-                'DTT_order'     => $row,
1126
-            );
1127
-            //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.
1128
-            if ( ! empty($dtt['DTT_ID'])) {
1129
-                $DTM = EE_Registry::instance()
1130
-                                  ->load_model('Datetime', array($evtobj->get_timezone()))
1131
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1132
-                $DTM->set_date_format($incoming_date_formats[0]);
1133
-                $DTM->set_time_format($incoming_date_formats[1]);
1134
-                foreach ($datetime_values as $field => $value) {
1135
-                    $DTM->set($field, $value);
1136
-                }
1137
-                //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.
1138
-                $saved_dtts[$DTM->ID()] = $DTM;
1139
-            } else {
1140
-                $DTM = EE_Registry::instance()->load_class(
1141
-                    'Datetime',
1142
-                    array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1143
-                    false,
1144
-                    false
1145
-                );
1146
-                foreach ($datetime_values as $field => $value) {
1147
-                    $DTM->set($field, $value);
1148
-                }
1149
-            }
1150
-            $DTM->save();
1151
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1152
-            //load DTT helper
1153
-            //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.
1154
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1155
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1156
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1157
-                $DTT->save();
1158
-            }
1159
-            //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.
1160
-            $saved_dtt = $DTT;
1161
-            $success = ! $success ? $success : $DTT;
1162
-            //if ANY of these updates fail then we want the appropriate global error message.
1163
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1164
-        }
1165
-        //no dtts get deleted so we don't do any of that logic here.
1166
-        //update tickets next
1167
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1168
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1169
-            $incoming_date_formats = array('Y-m-d', 'h:i a');
1170
-            $update_prices = false;
1171
-            $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1172
-                ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1173
-            // trim inputs to ensure any excess whitespace is removed.
1174
-            $tkt = array_map('trim', $tkt);
1175
-            if (empty($tkt['TKT_start_date'])) {
1176
-                //let's use now in the set timezone.
1177
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1178
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1179
-            }
1180
-            if (empty($tkt['TKT_end_date'])) {
1181
-                //use the start date of the first datetime
1182
-                $dtt = $evtobj->first_datetime();
1183
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1184
-                    $incoming_date_formats[0],
1185
-                    $incoming_date_formats[1]
1186
-                );
1187
-            }
1188
-            $TKT_values = array(
1189
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1190
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1191
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1192
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1193
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1194
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1195
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1196
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1197
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1198
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1199
-                'TKT_row'         => $row,
1200
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1201
-                'TKT_price'       => $ticket_price,
1202
-            );
1203
-            //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.
1204
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1205
-                $TKT_values['TKT_ID'] = 0;
1206
-                $TKT_values['TKT_is_default'] = 0;
1207
-                $TKT_values['TKT_price'] = $ticket_price;
1208
-                $update_prices = true;
1209
-            }
1210
-            //if we have a TKT_ID then we need to get that existing TKT_obj and update it
1211
-            //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.
1212
-            //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.
1213
-            if ( ! empty($tkt['TKT_ID'])) {
1214
-                $TKT = EE_Registry::instance()
1215
-                                  ->load_model('Ticket', array($evtobj->get_timezone()))
1216
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1217
-                if ($TKT instanceof EE_Ticket) {
1218
-                    $ticket_sold = $TKT->count_related(
1219
-                        'Registration',
1220
-                        array(
1221
-                            array(
1222
-                                'STS_ID' => array(
1223
-                                    'NOT IN',
1224
-                                    array(EEM_Registration::status_id_incomplete),
1225
-                                ),
1226
-                            ),
1227
-                        )
1228
-                    ) > 0 ? true : false;
1229
-                    //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.
1230
-                    $create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1231
-                                      && ! $TKT->get(
1232
-                        'TKT_deleted'
1233
-                    ) ? true : false;
1234
-                    $TKT->set_date_format($incoming_date_formats[0]);
1235
-                    $TKT->set_time_format($incoming_date_formats[1]);
1236
-                    //set new values
1237
-                    foreach ($TKT_values as $field => $value) {
1238
-                        if ($field == 'TKT_qty') {
1239
-                            $TKT->set_qty($value);
1240
-                        } else {
1241
-                            $TKT->set($field, $value);
1242
-                        }
1243
-                    }
1244
-                    //if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1245
-                    if ($create_new_TKT) {
1246
-                        //archive the old ticket first
1247
-                        $TKT->set('TKT_deleted', 1);
1248
-                        $TKT->save();
1249
-                        //make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1250
-                        $saved_tickets[$TKT->ID()] = $TKT;
1251
-                        //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.
1252
-                        $TKT = clone $TKT;
1253
-                        $TKT->set('TKT_ID', 0);
1254
-                        $TKT->set('TKT_deleted', 0);
1255
-                        $TKT->set('TKT_price', $ticket_price);
1256
-                        $TKT->set('TKT_sold', 0);
1257
-                        //now we need to make sure that $new prices are created as well and attached to new ticket.
1258
-                        $update_prices = true;
1259
-                    }
1260
-                    //make sure price is set if it hasn't been already
1261
-                    $TKT->set('TKT_price', $ticket_price);
1262
-                }
1263
-            } else {
1264
-                //no TKT_id so a new TKT
1265
-                $TKT_values['TKT_price'] = $ticket_price;
1266
-                $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1267
-                if ($TKT instanceof EE_Ticket) {
1268
-                    //need to reset values to properly account for the date formats
1269
-                    $TKT->set_date_format($incoming_date_formats[0]);
1270
-                    $TKT->set_time_format($incoming_date_formats[1]);
1271
-                    $TKT->set_timezone($evtobj->get_timezone());
1272
-                    //set new values
1273
-                    foreach ($TKT_values as $field => $value) {
1274
-                        if ($field == 'TKT_qty') {
1275
-                            $TKT->set_qty($value);
1276
-                        } else {
1277
-                            $TKT->set($field, $value);
1278
-                        }
1279
-                    }
1280
-                    $update_prices = true;
1281
-                }
1282
-            }
1283
-            // cap ticket qty by datetime reg limits
1284
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1285
-            //update ticket.
1286
-            $TKT->save();
1287
-            //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.
1288
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1289
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1290
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1291
-                $TKT->save();
1292
-            }
1293
-            //initially let's add the ticket to the dtt
1294
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1295
-            $saved_tickets[$TKT->ID()] = $TKT;
1296
-            //add prices to ticket
1297
-            $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1298
-        }
1299
-        //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.
1300
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1301
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1302
-        foreach ($tickets_removed as $id) {
1303
-            $id = absint($id);
1304
-            //get the ticket for this id
1305
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1306
-            //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)
1307
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1308
-            foreach ($dtts as $dtt) {
1309
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1310
-            }
1311
-            //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))
1312
-            $tkt_to_remove->delete_related_permanently('Price');
1313
-            //finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1314
-            $tkt_to_remove->delete_permanently();
1315
-        }
1316
-        return array($saved_dtt, $saved_tickets);
1317
-    }
1318
-
1319
-
1320
-
1321
-    /**
1322
-     * This attaches a list of given prices to a ticket.
1323
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1324
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1325
-     * price info and prices are automatically "archived" via the ticket.
1326
-     *
1327
-     * @access  private
1328
-     * @param array     $prices     Array of prices from the form.
1329
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1330
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1331
-     * @return  void
1332
-     */
1333
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1334
-    {
1335
-        foreach ($prices as $row => $prc) {
1336
-            $PRC_values = array(
1337
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1338
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1339
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1340
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1341
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1342
-                'PRC_is_default' => 0, //make sure prices are NOT set as default from this context
1343
-                'PRC_order'      => $row,
1344
-            );
1345
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1346
-                $PRC_values['PRC_ID'] = 0;
1347
-                $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1348
-            } else {
1349
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1350
-                //update this price with new values
1351
-                foreach ($PRC_values as $field => $newprc) {
1352
-                    $PRC->set($field, $newprc);
1353
-                }
1354
-                $PRC->save();
1355
-            }
1356
-            $ticket->_add_relation_to($PRC, 'Price');
1357
-        }
1358
-    }
1359
-
1360
-
1361
-
1362
-    /**
1363
-     * Add in our autosave ajax handlers
1364
-     *
1365
-     * @return void
1366
-     */
1367
-    protected function _ee_autosave_create_new()
1368
-    {
1369
-        // $this->_ee_autosave_edit();
1370
-    }
1371
-
1372
-
1373
-
1374
-    protected function _ee_autosave_edit()
1375
-    {
1376
-        return; //TEMPORARILY EXITING CAUSE THIS IS A TODO
1377
-    }
1378
-
1379
-
1380
-
1381
-    /**
1382
-     *    _generate_publish_box_extra_content
1383
-     *
1384
-     * @access private
1385
-     * @return void
1386
-     */
1387
-    private function _generate_publish_box_extra_content()
1388
-    {
1389
-        //load formatter helper
1390
-        //args for getting related registrations
1391
-        $approved_query_args = array(
1392
-            array(
1393
-                'REG_deleted' => 0,
1394
-                'STS_ID'      => EEM_Registration::status_id_approved,
1395
-            ),
1396
-        );
1397
-        $not_approved_query_args = array(
1398
-            array(
1399
-                'REG_deleted' => 0,
1400
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1401
-            ),
1402
-        );
1403
-        $pending_payment_query_args = array(
1404
-            array(
1405
-                'REG_deleted' => 0,
1406
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1407
-            ),
1408
-        );
1409
-        // publish box
1410
-        $publish_box_extra_args = array(
1411
-            'view_approved_reg_url'        => add_query_arg(
1412
-                array(
1413
-                    'action'      => 'default',
1414
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1415
-                    '_reg_status' => EEM_Registration::status_id_approved,
1416
-                ),
1417
-                REG_ADMIN_URL
1418
-            ),
1419
-            'view_not_approved_reg_url'    => add_query_arg(
1420
-                array(
1421
-                    'action'      => 'default',
1422
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1423
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1424
-                ),
1425
-                REG_ADMIN_URL
1426
-            ),
1427
-            'view_pending_payment_reg_url' => add_query_arg(
1428
-                array(
1429
-                    'action'      => 'default',
1430
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1431
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1432
-                ),
1433
-                REG_ADMIN_URL
1434
-            ),
1435
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1436
-                'Registration',
1437
-                $approved_query_args
1438
-            ),
1439
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1440
-                'Registration',
1441
-                $not_approved_query_args
1442
-            ),
1443
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1444
-                'Registration',
1445
-                $pending_payment_query_args
1446
-            ),
1447
-            'misc_pub_section_class'       => apply_filters(
1448
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1449
-                'misc-pub-section'
1450
-            ),
1451
-            //'email_attendees_url' => add_query_arg(
1452
-            //	array(
1453
-            //		'event_admin_reports' => 'event_newsletter',
1454
-            //		'event_id' => $this->_cpt_model_obj->id
1455
-            //	),
1456
-            //	'admin.php?page=espresso_registrations'
1457
-            //),
1458
-        );
1459
-        ob_start();
1460
-        do_action(
1461
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1462
-            $this->_cpt_model_obj
1463
-        );
1464
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1465
-        // load template
1466
-        EEH_Template::display_template(
1467
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1468
-            $publish_box_extra_args
1469
-        );
1470
-    }
1471
-
1472
-
1473
-
1474
-    /**
1475
-     * This just returns whatever is set as the _event object property
1476
-     * //todo this will become obsolete once the models are in place
1477
-     *
1478
-     * @return object
1479
-     */
1480
-    public function get_event_object()
1481
-    {
1482
-        return $this->_cpt_model_obj;
1483
-    }
1484
-
1485
-
1486
-
1487
-
1488
-    /** METABOXES * */
1489
-    /**
1490
-     * _register_event_editor_meta_boxes
1491
-     * add all metaboxes related to the event_editor
1492
-     *
1493
-     * @return void
1494
-     */
1495
-    protected function _register_event_editor_meta_boxes()
1496
-    {
1497
-        $this->verify_cpt_object();
1498
-        add_meta_box(
1499
-            'espresso_event_editor_tickets',
1500
-            esc_html__('Event Datetime & Ticket', 'event_espresso'),
1501
-            array($this, 'ticket_metabox'),
1502
-            $this->page_slug,
1503
-            'normal',
1504
-            'high'
1505
-        );
1506
-        add_meta_box(
1507
-            'espresso_event_editor_event_options',
1508
-            esc_html__('Event Registration Options', 'event_espresso'),
1509
-            array($this, 'registration_options_meta_box'),
1510
-            $this->page_slug,
1511
-            'side',
1512
-            'default'
1513
-        );
1514
-        // NOTE: if you're looking for other metaboxes in here,
1515
-        // where a metabox has a related management page in the admin
1516
-        // you will find it setup in the related management page's "_Hooks" file.
1517
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1518
-    }
1519
-
1520
-
1521
-
1522
-    public function ticket_metabox()
1523
-    {
1524
-        $existing_datetime_ids = $existing_ticket_ids = array();
1525
-        //defaults for template args
1526
-        $template_args = array(
1527
-            'existing_datetime_ids'    => '',
1528
-            'event_datetime_help_link' => '',
1529
-            'ticket_options_help_link' => '',
1530
-            'time'                     => null,
1531
-            'ticket_rows'              => '',
1532
-            'existing_ticket_ids'      => '',
1533
-            'total_ticket_rows'        => 1,
1534
-            'ticket_js_structure'      => '',
1535
-            'trash_icon'               => 'ee-lock-icon',
1536
-            'disabled'                 => '',
1537
-        );
1538
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1539
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1540
-        /**
1541
-         * 1. Start with retrieving Datetimes
1542
-         * 2. Fore each datetime get related tickets
1543
-         * 3. For each ticket get related prices
1544
-         */
1545
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1546
-        /** @type EE_Datetime $first_datetime */
1547
-        $first_datetime = reset($times);
1548
-        //do we get related tickets?
1549
-        if ($first_datetime instanceof EE_Datetime
1550
-            && $first_datetime->ID() !== 0
1551
-        ) {
1552
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1553
-            $template_args['time'] = $first_datetime;
1554
-            $related_tickets = $first_datetime->tickets(
1555
-                array(
1556
-                    array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1557
-                    'default_where_conditions' => 'none',
1558
-                )
1559
-            );
1560
-            if ( ! empty($related_tickets)) {
1561
-                $template_args['total_ticket_rows'] = count($related_tickets);
1562
-                $row = 0;
1563
-                foreach ($related_tickets as $ticket) {
1564
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1565
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1566
-                    $row++;
1567
-                }
1568
-            } else {
1569
-                $template_args['total_ticket_rows'] = 1;
1570
-                /** @type EE_Ticket $ticket */
1571
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1572
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1573
-            }
1574
-        } else {
1575
-            $template_args['time'] = $times[0];
1576
-            /** @type EE_Ticket $ticket */
1577
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1578
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1579
-            // NOTE: we're just sending the first default row
1580
-            // (decaf can't manage default tickets so this should be sufficient);
1581
-        }
1582
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1583
-            'event_editor_event_datetimes_help_tab'
1584
-        );
1585
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1586
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1587
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1588
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1589
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1590
-            true
1591
-        );
1592
-        $template = apply_filters(
1593
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1594
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1595
-        );
1596
-        EEH_Template::display_template($template, $template_args);
1597
-    }
1598
-
1599
-
1600
-
1601
-    /**
1602
-     * Setup an individual ticket form for the decaf event editor page
1603
-     *
1604
-     * @access private
1605
-     * @param  EE_Ticket $ticket   the ticket object
1606
-     * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1607
-     * @param int        $row
1608
-     * @return string generated html for the ticket row.
1609
-     */
1610
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1611
-    {
1612
-        $template_args = array(
1613
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1614
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1615
-                : '',
1616
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1617
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1618
-            'TKT_name'            => $ticket->get('TKT_name'),
1619
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1620
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1621
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1622
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1623
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1624
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1625
-            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1626
-                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1627
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1628
-            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1629
-                : ' disabled=disabled',
1630
-        );
1631
-        $price = $ticket->ID() !== 0
1632
-            ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1633
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1634
-        $price_args = array(
1635
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1636
-            'PRC_amount'            => $price->get('PRC_amount'),
1637
-            'PRT_ID'                => $price->get('PRT_ID'),
1638
-            'PRC_ID'                => $price->get('PRC_ID'),
1639
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1640
-        );
1641
-        //make sure we have default start and end dates if skeleton
1642
-        //handle rows that should NOT be empty
1643
-        if (empty($template_args['TKT_start_date'])) {
1644
-            //if empty then the start date will be now.
1645
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1646
-        }
1647
-        if (empty($template_args['TKT_end_date'])) {
1648
-            //get the earliest datetime (if present);
1649
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1650
-                ? $this->_cpt_model_obj->get_first_related(
1651
-                    'Datetime',
1652
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1653
-                )
1654
-                : null;
1655
-            if ( ! empty($earliest_dtt)) {
1656
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1657
-            } else {
1658
-                $template_args['TKT_end_date'] = date(
1659
-                    'Y-m-d h:i a',
1660
-                    mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1661
-                );
1662
-            }
1663
-        }
1664
-        $template_args = array_merge($template_args, $price_args);
1665
-        $template = apply_filters(
1666
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1667
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1668
-            $ticket
1669
-        );
1670
-        return EEH_Template::display_template($template, $template_args, true);
1671
-    }
1672
-
1673
-
1674
-
1675
-    public function registration_options_meta_box()
1676
-    {
1677
-        $yes_no_values = array(
1678
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1679
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1680
-        );
1681
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1682
-            array(
1683
-                EEM_Registration::status_id_cancelled,
1684
-                EEM_Registration::status_id_declined,
1685
-                EEM_Registration::status_id_incomplete,
1686
-            ),
1687
-            true
1688
-        );
1689
-        //$template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1690
-        $template_args['_event'] = $this->_cpt_model_obj;
1691
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1692
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1693
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1694
-            'default_reg_status',
1695
-            $default_reg_status_values,
1696
-            $this->_cpt_model_obj->default_registration_status()
1697
-        );
1698
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1699
-            'display_desc',
1700
-            $yes_no_values,
1701
-            $this->_cpt_model_obj->display_description()
1702
-        );
1703
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1704
-            'display_ticket_selector',
1705
-            $yes_no_values,
1706
-            $this->_cpt_model_obj->display_ticket_selector(),
1707
-            '',
1708
-            '',
1709
-            false
1710
-        );
1711
-        $template_args['additional_registration_options'] = apply_filters(
1712
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1713
-            '',
1714
-            $template_args,
1715
-            $yes_no_values,
1716
-            $default_reg_status_values
1717
-        );
1718
-        EEH_Template::display_template(
1719
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1720
-            $template_args
1721
-        );
1722
-    }
1723
-
1724
-
1725
-
1726
-    /**
1727
-     * _get_events()
1728
-     * This method simply returns all the events (for the given _view and paging)
1729
-     *
1730
-     * @access public
1731
-     * @param int  $per_page     count of items per page (20 default);
1732
-     * @param int  $current_page what is the current page being viewed.
1733
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1734
-     *                           If FALSE then we return an array of event objects
1735
-     *                           that match the given _view and paging parameters.
1736
-     * @return array an array of event objects.
1737
-     */
1738
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1739
-    {
1740
-        $EEME = $this->_event_model();
1741
-        $offset = ($current_page - 1) * $per_page;
1742
-        $limit = $count ? null : $offset . ',' . $per_page;
1743
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1744
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1745
-        if (isset($this->_req_data['month_range'])) {
1746
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1747
-            //simulate the FIRST day of the month, that fixes issues for months like February
1748
-            //where PHP doesn't know what to assume for date.
1749
-            //@see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1750
-            $month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1751
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1752
-        }
1753
-        $where = array();
1754
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1755
-        //determine what post_status our condition will have for the query.
1756
-        switch ($status) {
1757
-            case 'month' :
1758
-            case 'today' :
1759
-            case null :
1760
-            case 'all' :
1761
-                break;
1762
-            case 'draft' :
1763
-                $where['status'] = array('IN', array('draft', 'auto-draft'));
1764
-                break;
1765
-            default :
1766
-                $where['status'] = $status;
1767
-        }
1768
-        //categories?
1769
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1770
-            ? $this->_req_data['EVT_CAT'] : null;
1771
-        if ( ! empty ($category)) {
1772
-            $where['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1773
-            $where['Term_Taxonomy.term_id'] = $category;
1774
-        }
1775
-        //date where conditions
1776
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1777
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1778
-            $DateTime = new DateTime(
1779
-                $year_r . '-' . $month_r . '-01 00:00:00',
1780
-                new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1781
-            );
1782
-            $start = $DateTime->format(implode(' ', $start_formats));
1783
-            $end = $DateTime->setDate($year_r, $month_r, $DateTime
1784
-                ->format('t'))->setTime(23, 59, 59)
1785
-                            ->format(implode(' ', $start_formats));
1786
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1787
-        } else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1788
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1789
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1790
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1791
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1792
-        } else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1793
-            $now = date('Y-m-01');
1794
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1795
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1796
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1797
-                            ->setTime(23, 59, 59)
1798
-                            ->format(implode(' ', $start_formats));
1799
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1800
-        }
1801
-        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1802
-            $where['EVT_wp_user'] = get_current_user_id();
1803
-        } else {
1804
-            if ( ! isset($where['status'])) {
1805
-                if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1806
-                    $where['OR'] = array(
1807
-                        'status*restrict_private' => array('!=', 'private'),
1808
-                        'AND'                     => array(
1809
-                            'status*inclusive' => array('=', 'private'),
1810
-                            'EVT_wp_user'      => get_current_user_id(),
1811
-                        ),
1812
-                    );
1813
-                }
1814
-            }
1815
-        }
1816
-        if (isset($this->_req_data['EVT_wp_user'])) {
1817
-            if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1818
-                && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1819
-            ) {
1820
-                $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1821
-            }
1822
-        }
1823
-        //search query handling
1824
-        if (isset($this->_req_data['s'])) {
1825
-            $search_string = '%' . $this->_req_data['s'] . '%';
1826
-            $where['OR'] = array(
1827
-                'EVT_name'       => array('LIKE', $search_string),
1828
-                'EVT_desc'       => array('LIKE', $search_string),
1829
-                'EVT_short_desc' => array('LIKE', $search_string),
1830
-            );
1831
-        }
1832
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1833
-        $query_params = apply_filters(
1834
-            'FHEE__Events_Admin_Page__get_events__query_params',
1835
-            array(
1836
-                $where,
1837
-                'limit'    => $limit,
1838
-                'order_by' => $orderby,
1839
-                'order'    => $order,
1840
-                'group_by' => 'EVT_ID',
1841
-            ),
1842
-            $this->_req_data
1843
-        );
1844
-        //let's first check if we have special requests coming in.
1845
-        if (isset($this->_req_data['active_status'])) {
1846
-            switch ($this->_req_data['active_status']) {
1847
-                case 'upcoming' :
1848
-                    return $EEME->get_upcoming_events($query_params, $count);
1849
-                    break;
1850
-                case 'expired' :
1851
-                    return $EEME->get_expired_events($query_params, $count);
1852
-                    break;
1853
-                case 'active' :
1854
-                    return $EEME->get_active_events($query_params, $count);
1855
-                    break;
1856
-                case 'inactive' :
1857
-                    return $EEME->get_inactive_events($query_params, $count);
1858
-                    break;
1859
-            }
1860
-        }
1861
-        $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1862
-        return $events;
1863
-    }
1864
-
1865
-
1866
-
1867
-    /**
1868
-     * handling for WordPress CPT actions (trash, restore, delete)
1869
-     *
1870
-     * @param string $post_id
1871
-     */
1872
-    public function trash_cpt_item($post_id)
1873
-    {
1874
-        $this->_req_data['EVT_ID'] = $post_id;
1875
-        $this->_trash_or_restore_event('trash', false);
1876
-    }
1877
-
1878
-
1879
-
1880
-    /**
1881
-     * @param string $post_id
1882
-     */
1883
-    public function restore_cpt_item($post_id)
1884
-    {
1885
-        $this->_req_data['EVT_ID'] = $post_id;
1886
-        $this->_trash_or_restore_event('draft', false);
1887
-    }
1888
-
1889
-
1890
-
1891
-    /**
1892
-     * @param string $post_id
1893
-     */
1894
-    public function delete_cpt_item($post_id)
1895
-    {
1896
-        $this->_req_data['EVT_ID'] = $post_id;
1897
-        $this->_delete_event(false);
1898
-    }
1899
-
1900
-
1901
-
1902
-    /**
1903
-     * _trash_or_restore_event
1904
-     *
1905
-     * @access protected
1906
-     * @param  string $event_status
1907
-     * @param bool    $redirect_after
1908
-     */
1909
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1910
-    {
1911
-        //determine the event id and set to array.
1912
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1913
-        // loop thru events
1914
-        if ($EVT_ID) {
1915
-            // clean status
1916
-            $event_status = sanitize_key($event_status);
1917
-            // grab status
1918
-            if ( ! empty($event_status)) {
1919
-                $success = $this->_change_event_status($EVT_ID, $event_status);
1920
-            } else {
1921
-                $success = false;
1922
-                $msg = esc_html__(
1923
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1924
-                    'event_espresso'
1925
-                );
1926
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1927
-            }
1928
-        } else {
1929
-            $success = false;
1930
-            $msg = esc_html__(
1931
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1932
-                'event_espresso'
1933
-            );
1934
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1935
-        }
1936
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1937
-        if ($redirect_after) {
1938
-            $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1939
-        }
1940
-    }
1941
-
1942
-
1943
-
1944
-    /**
1945
-     * _trash_or_restore_events
1946
-     *
1947
-     * @access protected
1948
-     * @param  string $event_status
1949
-     * @return void
1950
-     */
1951
-    protected function _trash_or_restore_events($event_status = 'trash')
1952
-    {
1953
-        // clean status
1954
-        $event_status = sanitize_key($event_status);
1955
-        // grab status
1956
-        if ( ! empty($event_status)) {
1957
-            $success = true;
1958
-            //determine the event id and set to array.
1959
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
1960
-            // loop thru events
1961
-            foreach ($EVT_IDs as $EVT_ID) {
1962
-                if ($EVT_ID = absint($EVT_ID)) {
1963
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
1964
-                    $success = $results !== false ? $success : false;
1965
-                } else {
1966
-                    $msg = sprintf(
1967
-                        esc_html__(
1968
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
1969
-                            'event_espresso'
1970
-                        ),
1971
-                        $EVT_ID
1972
-                    );
1973
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1974
-                    $success = false;
1975
-                }
1976
-            }
1977
-        } else {
1978
-            $success = false;
1979
-            $msg = esc_html__(
1980
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1981
-                'event_espresso'
1982
-            );
1983
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1984
-        }
1985
-        // in order to force a pluralized result message we need to send back a success status greater than 1
1986
-        $success = $success ? 2 : false;
1987
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1988
-        $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
1989
-    }
1990
-
1991
-
1992
-
1993
-    /**
1994
-     * _trash_or_restore_events
1995
-     *
1996
-     * @access  private
1997
-     * @param  int    $EVT_ID
1998
-     * @param  string $event_status
1999
-     * @return bool
2000
-     */
2001
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2002
-    {
2003
-        // grab event id
2004
-        if ( ! $EVT_ID) {
2005
-            $msg = esc_html__(
2006
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2007
-                'event_espresso'
2008
-            );
2009
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2010
-            return false;
2011
-        }
2012
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2013
-        // clean status
2014
-        $event_status = sanitize_key($event_status);
2015
-        // grab status
2016
-        if (empty($event_status)) {
2017
-            $msg = esc_html__(
2018
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2019
-                'event_espresso'
2020
-            );
2021
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2022
-            return false;
2023
-        }
2024
-        // was event trashed or restored ?
2025
-        switch ($event_status) {
2026
-            case 'draft' :
2027
-                $action = 'restored from the trash';
2028
-                $hook = 'AHEE_event_restored_from_trash';
2029
-                break;
2030
-            case 'trash' :
2031
-                $action = 'moved to the trash';
2032
-                $hook = 'AHEE_event_moved_to_trash';
2033
-                break;
2034
-            default :
2035
-                $action = 'updated';
2036
-                $hook = false;
2037
-        }
2038
-        //use class to change status
2039
-        $this->_cpt_model_obj->set_status($event_status);
2040
-        $success = $this->_cpt_model_obj->save();
2041
-        if ($success === false) {
2042
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2043
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2044
-            return false;
2045
-        }
2046
-        if ($hook) {
2047
-            do_action($hook);
2048
-        }
2049
-        return true;
2050
-    }
2051
-
2052
-
2053
-
2054
-    /**
2055
-     * _delete_event
2056
-     *
2057
-     * @access protected
2058
-     * @param bool $redirect_after
2059
-     */
2060
-    protected function _delete_event($redirect_after = true)
2061
-    {
2062
-        //determine the event id and set to array.
2063
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2064
-        $EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2065
-        // loop thru events
2066
-        if ($EVT_ID) {
2067
-            $success = $this->_permanently_delete_event($EVT_ID);
2068
-            // get list of events with no prices
2069
-            $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2070
-            // remove this event from the list of events with no prices
2071
-            if (isset($espresso_no_ticket_prices[$EVT_ID])) {
2072
-                unset($espresso_no_ticket_prices[$EVT_ID]);
2073
-            }
2074
-            update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2075
-        } else {
2076
-            $success = false;
2077
-            $msg = esc_html__(
2078
-                'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2079
-                'event_espresso'
2080
-            );
2081
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2082
-        }
2083
-        if ($redirect_after) {
2084
-            $this->_redirect_after_action(
2085
-                $success,
2086
-                'Event',
2087
-                'deleted',
2088
-                array('action' => 'default', 'status' => 'trash')
2089
-            );
2090
-        }
2091
-    }
2092
-
2093
-
2094
-
2095
-    /**
2096
-     * _delete_events
2097
-     *
2098
-     * @access protected
2099
-     * @return void
2100
-     */
2101
-    protected function _delete_events()
2102
-    {
2103
-        $success = true;
2104
-        // get list of events with no prices
2105
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2106
-        //determine the event id and set to array.
2107
-        $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
2108
-        // loop thru events
2109
-        foreach ($EVT_IDs as $EVT_ID) {
2110
-            $EVT_ID = absint($EVT_ID);
2111
-            if ($EVT_ID) {
2112
-                $results = $this->_permanently_delete_event($EVT_ID);
2113
-                $success = $results !== false ? $success : false;
2114
-                // remove this event from the list of events with no prices
2115
-                unset($espresso_no_ticket_prices[$EVT_ID]);
2116
-            } else {
2117
-                $success = false;
2118
-                $msg = esc_html__(
2119
-                    'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2120
-                    'event_espresso'
2121
-                );
2122
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2123
-            }
2124
-        }
2125
-        update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2126
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2127
-        $success = $success ? 2 : false;
2128
-        $this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2129
-    }
2130
-
2131
-
2132
-
2133
-    /**
2134
-     * _permanently_delete_event
2135
-     *
2136
-     * @access  private
2137
-     * @param  int $EVT_ID
2138
-     * @return bool
2139
-     */
2140
-    private function _permanently_delete_event($EVT_ID = 0)
2141
-    {
2142
-        // grab event id
2143
-        if ( ! $EVT_ID) {
2144
-            $msg = esc_html__(
2145
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2146
-                'event_espresso'
2147
-            );
2148
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2149
-            return false;
2150
-        }
2151
-        if (
2152
-            ! $this->_cpt_model_obj instanceof EE_Event
2153
-            || $this->_cpt_model_obj->ID() !== $EVT_ID
2154
-        ) {
2155
-            $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2156
-        }
2157
-        if ( ! $this->_cpt_model_obj instanceof EE_Event) {
2158
-            return false;
2159
-        }
2160
-        //need to delete related tickets and prices first.
2161
-        $datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2162
-        foreach ($datetimes as $datetime) {
2163
-            $this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2164
-            $tickets = $datetime->get_many_related('Ticket');
2165
-            foreach ($tickets as $ticket) {
2166
-                $ticket->_remove_relation_to($datetime, 'Datetime');
2167
-                $ticket->delete_related_permanently('Price');
2168
-                $ticket->delete_permanently();
2169
-            }
2170
-            $datetime->delete();
2171
-        }
2172
-        //what about related venues or terms?
2173
-        $venues = $this->_cpt_model_obj->get_many_related('Venue');
2174
-        foreach ($venues as $venue) {
2175
-            $this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2176
-        }
2177
-        //any attached question groups?
2178
-        $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2179
-        if ( ! empty($question_groups)) {
2180
-            foreach ($question_groups as $question_group) {
2181
-                $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2182
-            }
2183
-        }
2184
-        //Message Template Groups
2185
-        $this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2186
-        /** @type EE_Term_Taxonomy[] $term_taxonomies */
2187
-        $term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2188
-        foreach ($term_taxonomies as $term_taxonomy) {
2189
-            $this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2190
-        }
2191
-        $success = $this->_cpt_model_obj->delete_permanently();
2192
-        // did it all go as planned ?
2193
-        if ($success) {
2194
-            $msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2195
-            EE_Error::add_success($msg);
2196
-        } else {
2197
-            $msg = sprintf(
2198
-                esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2199
-                $EVT_ID
2200
-            );
2201
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2202
-            return false;
2203
-        }
2204
-        do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2205
-        return true;
2206
-    }
2207
-
2208
-
2209
-
2210
-    /**
2211
-     * get total number of events
2212
-     *
2213
-     * @access public
2214
-     * @return int
2215
-     */
2216
-    public function total_events()
2217
-    {
2218
-        $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2219
-        return $count;
2220
-    }
2221
-
2222
-
2223
-
2224
-    /**
2225
-     * get total number of draft events
2226
-     *
2227
-     * @access public
2228
-     * @return int
2229
-     */
2230
-    public function total_events_draft()
2231
-    {
2232
-        $where = array(
2233
-            'status' => array('IN', array('draft', 'auto-draft')),
2234
-        );
2235
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2236
-        return $count;
2237
-    }
2238
-
2239
-
2240
-
2241
-    /**
2242
-     * get total number of trashed events
2243
-     *
2244
-     * @access public
2245
-     * @return int
2246
-     */
2247
-    public function total_trashed_events()
2248
-    {
2249
-        $where = array(
2250
-            'status' => 'trash',
2251
-        );
2252
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2253
-        return $count;
2254
-    }
2255
-
2256
-
2257
-    /**
2258
-     *    _default_event_settings
2259
-     *    This generates the Default Settings Tab
2260
-     *
2261
-     * @return void
2262
-     * @throws \EE_Error
2263
-     */
2264
-    protected function _default_event_settings()
2265
-    {
2266
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2267
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2268
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2269
-        $this->display_admin_page_with_sidebar();
2270
-    }
2271
-
2272
-
2273
-    /**
2274
-     * Return the form for event settings.
2275
-     * @return \EE_Form_Section_Proper
2276
-     */
2277
-    protected function _default_event_settings_form()
2278
-    {
2279
-        $registration_config = EE_Registry::instance()->CFG->registration;
2280
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2281
-        //exclude
2282
-            array(
2283
-                EEM_Registration::status_id_cancelled,
2284
-                EEM_Registration::status_id_declined,
2285
-                EEM_Registration::status_id_incomplete,
2286
-                EEM_Registration::status_id_wait_list,
2287
-            ),
2288
-            true
2289
-        );
2290
-        return new EE_Form_Section_Proper(
2291
-            array(
2292
-                'name' => 'update_default_event_settings',
2293
-                'html_id' => 'update_default_event_settings',
2294
-                'html_class' => 'form-table',
2295
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2296
-                'subsections' => apply_filters(
2297
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2298
-                    array(
2299
-                        'default_reg_status' => new EE_Select_Input(
2300
-                            $registration_stati_for_selection,
2301
-                            array(
2302
-                                'default' => isset($registration_config->default_STS_ID)
2303
-                                             && array_key_exists(
2304
-                                                $registration_config->default_STS_ID,
2305
-                                                $registration_stati_for_selection
2306
-                                             )
2307
-                                            ? sanitize_text_field($registration_config->default_STS_ID)
2308
-                                            : EEM_Registration::status_id_pending_payment,
2309
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2310
-                                                    . EEH_Template::get_help_tab_link(
2311
-                                                        'default_settings_status_help_tab'
2312
-                                                    ),
2313
-                                'html_help_text' => esc_html__(
2314
-                                    '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.',
2315
-                                    'event_espresso'
2316
-                                )
2317
-                            )
2318
-                        ),
2319
-                        'default_max_tickets' => new EE_Integer_Input(
2320
-                            array(
2321
-                                'default' => isset($registration_config->default_maximum_number_of_tickets)
2322
-                                    ? $registration_config->default_maximum_number_of_tickets
2323
-                                    : EEM_Event::get_default_additional_limit(),
2324
-                                'html_label_text' => esc_html__(
2325
-                                    'Default Maximum Tickets Allowed Per Order:',
2326
-                                    'event_espresso'
2327
-                                ) . EEH_Template::get_help_tab_link(
2328
-                                    'default_maximum_tickets_help_tab"'
2329
-                                    ),
2330
-                                'html_help_text' => esc_html__(
2331
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2332
-                                    'event_espresso'
2333
-                                )
2334
-                            )
2335
-                        )
2336
-                    )
2337
-                )
2338
-            )
2339
-        );
2340
-    }
2341
-
2342
-
2343
-    /**
2344
-     * _update_default_event_settings
2345
-     *
2346
-     * @access protected
2347
-     * @return void
2348
-     * @throws \EE_Error
2349
-     */
2350
-    protected function _update_default_event_settings()
2351
-    {
2352
-        $registration_config = EE_Registry::instance()->CFG->registration;
2353
-        $form = $this->_default_event_settings_form();
2354
-        if ($form->was_submitted()) {
2355
-            $form->receive_form_submission();
2356
-            if ($form->is_valid()) {
2357
-                $valid_data = $form->valid_data();
2358
-                if (isset($valid_data['default_reg_status'])) {
2359
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2360
-                }
2361
-                if (isset($valid_data['default_max_tickets'])) {
2362
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2363
-                }
2364
-                //update because data was valid!
2365
-                EE_Registry::instance()->CFG->update_espresso_config();
2366
-                EE_Error::overwrite_success();
2367
-                EE_Error::add_success(
2368
-                    __('Default Event Settings were updated', 'event_espresso')
2369
-                );
2370
-            }
2371
-        }
2372
-        $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2373
-    }
2374
-
2375
-
2376
-
2377
-    /*************        Templates        *************/
2378
-    protected function _template_settings()
2379
-    {
2380
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2381
-        $this->_template_args['preview_img'] = '<img src="'
2382
-                                               . EVENTS_ASSETS_URL
2383
-                                               . DS
2384
-                                               . 'images'
2385
-                                               . DS
2386
-                                               . 'caffeinated_template_features.jpg" alt="'
2387
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2388
-                                               . '" />';
2389
-        $this->_template_args['preview_text'] = '<strong>' . esc_html__(
2390
-                '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.',
2391
-                'event_espresso'
2392
-            ) . '</strong>';
2393
-        $this->display_admin_caf_preview_page('template_settings_tab');
2394
-    }
2395
-
2396
-
2397
-    /** Event Category Stuff **/
2398
-    /**
2399
-     * set the _category property with the category object for the loaded page.
2400
-     *
2401
-     * @access private
2402
-     * @return void
2403
-     */
2404
-    private function _set_category_object()
2405
-    {
2406
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2407
-            return;
2408
-        } //already have the category object so get out.
2409
-        //set default category object
2410
-        $this->_set_empty_category_object();
2411
-        //only set if we've got an id
2412
-        if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2413
-            return;
2414
-        }
2415
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2416
-        $term = get_term($category_id, 'espresso_event_categories');
2417
-        if ( ! empty($term)) {
2418
-            $this->_category->category_name = $term->name;
2419
-            $this->_category->category_identifier = $term->slug;
2420
-            $this->_category->category_desc = $term->description;
2421
-            $this->_category->id = $term->term_id;
2422
-            $this->_category->parent = $term->parent;
2423
-        }
2424
-    }
2425
-
2426
-
2427
-
2428
-    private function _set_empty_category_object()
2429
-    {
2430
-        $this->_category = new stdClass();
2431
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2432
-        $this->_category->id = $this->_category->parent = 0;
2433
-    }
2434
-
2435
-
2436
-
2437
-    protected function _category_list_table()
2438
-    {
2439
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2440
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2441
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2442
-                'add_category',
2443
-                'add_category',
2444
-                array(),
2445
-                'add-new-h2'
2446
-            );
2447
-        $this->display_admin_list_table_page_with_sidebar();
2448
-    }
2449
-
2450
-
2451
-
2452
-    /**
2453
-     * @param $view
2454
-     */
2455
-    protected function _category_details($view)
2456
-    {
2457
-        //load formatter helper
2458
-        //load field generator helper
2459
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
2460
-        $this->_set_add_edit_form_tags($route);
2461
-        $this->_set_category_object();
2462
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2463
-        $delete_action = 'delete_category';
2464
-        //custom redirect
2465
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2466
-            array('action' => 'category_list'),
2467
-            $this->_admin_base_url
2468
-        );
2469
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2470
-        //take care of contents
2471
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2472
-        $this->display_admin_page_with_sidebar();
2473
-    }
2474
-
2475
-
2476
-
2477
-    /**
2478
-     * @return mixed
2479
-     */
2480
-    protected function _category_details_content()
2481
-    {
2482
-        $editor_args['category_desc'] = array(
2483
-            'type'          => 'wp_editor',
2484
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2485
-            'class'         => 'my_editor_custom',
2486
-            'wpeditor_args' => array('media_buttons' => false),
2487
-        );
2488
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2489
-        $all_terms = get_terms(
2490
-            array('espresso_event_categories'),
2491
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2492
-        );
2493
-        //setup category select for term parents.
2494
-        $category_select_values[] = array(
2495
-            'text' => esc_html__('No Parent', 'event_espresso'),
2496
-            'id'   => 0,
2497
-        );
2498
-        foreach ($all_terms as $term) {
2499
-            $category_select_values[] = array(
2500
-                'text' => $term->name,
2501
-                'id'   => $term->term_id,
2502
-            );
2503
-        }
2504
-        $category_select = EEH_Form_Fields::select_input(
2505
-            'category_parent',
2506
-            $category_select_values,
2507
-            $this->_category->parent
2508
-        );
2509
-        $template_args = array(
2510
-            'category'                 => $this->_category,
2511
-            'category_select'          => $category_select,
2512
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2513
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2514
-            'disable'                  => '',
2515
-            'disabled_message'         => false,
2516
-        );
2517
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2518
-        return EEH_Template::display_template($template, $template_args, true);
2519
-    }
2520
-
2521
-
2522
-
2523
-    protected function _delete_categories()
2524
-    {
2525
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array)$this->_req_data['EVT_CAT_ID']
2526
-            : (array)$this->_req_data['category_id'];
2527
-        foreach ($cat_ids as $cat_id) {
2528
-            $this->_delete_category($cat_id);
2529
-        }
2530
-        //doesn't matter what page we're coming from... we're going to the same place after delete.
2531
-        $query_args = array(
2532
-            'action' => 'category_list',
2533
-        );
2534
-        $this->_redirect_after_action(0, '', '', $query_args);
2535
-    }
2536
-
2537
-
2538
-
2539
-    /**
2540
-     * @param $cat_id
2541
-     */
2542
-    protected function _delete_category($cat_id)
2543
-    {
2544
-        $cat_id = absint($cat_id);
2545
-        wp_delete_term($cat_id, 'espresso_event_categories');
2546
-    }
2547
-
2548
-
2549
-
2550
-    /**
2551
-     * @param $new_category
2552
-     */
2553
-    protected function _insert_or_update_category($new_category)
2554
-    {
2555
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2556
-        $success = 0; //we already have a success message so lets not send another.
2557
-        if ($cat_id) {
2558
-            $query_args = array(
2559
-                'action'     => 'edit_category',
2560
-                'EVT_CAT_ID' => $cat_id,
2561
-            );
2562
-        } else {
2563
-            $query_args = array('action' => 'add_category');
2564
-        }
2565
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2566
-    }
2567
-
2568
-
2569
-
2570
-    /**
2571
-     * @param bool $update
2572
-     * @return bool|mixed|string
2573
-     */
2574
-    private function _insert_category($update = false)
2575
-    {
2576
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2577
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2578
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2579
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2580
-        if (empty($category_name)) {
2581
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2582
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2583
-            return false;
2584
-        }
2585
-        $term_args = array(
2586
-            'name'        => $category_name,
2587
-            'description' => $category_desc,
2588
-            'parent'      => $category_parent,
2589
-        );
2590
-        //was the category_identifier input disabled?
2591
-        if (isset($this->_req_data['category_identifier'])) {
2592
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2593
-        }
2594
-        $insert_ids = $update
2595
-            ? wp_update_term($cat_id, 'espresso_event_categories', $term_args)
2596
-            : wp_insert_term($category_name, 'espresso_event_categories', $term_args);
2597
-        if ( ! is_array($insert_ids)) {
2598
-            $msg = esc_html__(
2599
-                'An error occurred and the category has not been saved to the database.',
2600
-                'event_espresso'
2601
-            );
2602
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2603
-        } else {
2604
-            $cat_id = $insert_ids['term_id'];
2605
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2606
-            EE_Error::add_success($msg);
2607
-        }
2608
-        return $cat_id;
2609
-    }
2610
-
2611
-
2612
-
2613
-    /**
2614
-     * @param int  $per_page
2615
-     * @param int  $current_page
2616
-     * @param bool $count
2617
-     * @return \EE_Base_Class[]|int
2618
-     */
2619
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2620
-    {
2621
-        //testing term stuff
2622
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2623
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2624
-        $limit = ($current_page - 1) * $per_page;
2625
-        $where = array('taxonomy' => 'espresso_event_categories');
2626
-        if (isset($this->_req_data['s'])) {
2627
-            $sstr = '%' . $this->_req_data['s'] . '%';
2628
-            $where['OR'] = array(
2629
-                'Term.name'   => array('LIKE', $sstr),
2630
-                'description' => array('LIKE', $sstr),
2631
-            );
2632
-        }
2633
-        $query_params = array(
2634
-            $where,
2635
-            'order_by'   => array($orderby => $order),
2636
-            'limit'      => $limit . ',' . $per_page,
2637
-            'force_join' => array('Term'),
2638
-        );
2639
-        $categories = $count
2640
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2641
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2642
-        return $categories;
2643
-    }
2644
-
2645
-
2646
-
2647
-    /* end category stuff */
2648
-    /**************/
385
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
386
+				'require_nonce' => false,
387
+			),
388
+			'default_event_settings' => array(
389
+				'nav'           => array(
390
+					'label' => esc_html__('Default Settings', 'event_espresso'),
391
+					'order' => 40,
392
+				),
393
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
394
+				'labels'        => array(
395
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
396
+				),
397
+				'help_tabs'     => array(
398
+					'default_settings_help_tab'        => array(
399
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
400
+						'filename' => 'events_default_settings',
401
+					),
402
+					'default_settings_status_help_tab' => array(
403
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
404
+						'filename' => 'events_default_settings_status',
405
+					),
406
+					'default_maximum_tickets_help_tab' => array(
407
+						'title' => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
408
+						'filename' => 'events_default_settings_max_tickets',
409
+					)
410
+				),
411
+				'help_tour'     => array('Event_Default_Settings_Help_Tour'),
412
+				'require_nonce' => false,
413
+			),
414
+			//template settings
415
+			'template_settings'      => array(
416
+				'nav'           => array(
417
+					'label' => esc_html__('Templates', 'event_espresso'),
418
+					'order' => 30,
419
+				),
420
+				'metaboxes'     => $this->_default_espresso_metaboxes,
421
+				'help_tabs'     => array(
422
+					'general_settings_templates_help_tab' => array(
423
+						'title'    => esc_html__('Templates', 'event_espresso'),
424
+						'filename' => 'general_settings_templates',
425
+					),
426
+				),
427
+				'help_tour'     => array('Templates_Help_Tour'),
428
+				'require_nonce' => false,
429
+			),
430
+			//event category stuff
431
+			'add_category'           => array(
432
+				'nav'           => array(
433
+					'label'      => esc_html__('Add Category', 'event_espresso'),
434
+					'order'      => 15,
435
+					'persistent' => false,
436
+				),
437
+				'help_tabs'     => array(
438
+					'add_category_help_tab' => array(
439
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
440
+						'filename' => 'events_add_category',
441
+					),
442
+				),
443
+				'help_tour'     => array('Event_Add_Category_Help_Tour'),
444
+				'metaboxes'     => array('_publish_post_box'),
445
+				'require_nonce' => false,
446
+			),
447
+			'edit_category'          => array(
448
+				'nav'           => array(
449
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
450
+					'order'      => 15,
451
+					'persistent' => false,
452
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
453
+						? add_query_arg(
454
+							array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
455
+							$this->_current_page_view_url
456
+						)
457
+						: $this->_admin_base_url,
458
+				),
459
+				'help_tabs'     => array(
460
+					'edit_category_help_tab' => array(
461
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
462
+						'filename' => 'events_edit_category',
463
+					),
464
+				),
465
+				/*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
466
+				'metaboxes'     => array('_publish_post_box'),
467
+				'require_nonce' => false,
468
+			),
469
+			'category_list'          => array(
470
+				'nav'           => array(
471
+					'label' => esc_html__('Categories', 'event_espresso'),
472
+					'order' => 20,
473
+				),
474
+				'list_table'    => 'Event_Categories_Admin_List_Table',
475
+				'help_tabs'     => array(
476
+					'events_categories_help_tab'                       => array(
477
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
478
+						'filename' => 'events_categories',
479
+					),
480
+					'events_categories_table_column_headings_help_tab' => array(
481
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
482
+						'filename' => 'events_categories_table_column_headings',
483
+					),
484
+					'events_categories_view_help_tab'                  => array(
485
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
486
+						'filename' => 'events_categories_views',
487
+					),
488
+					'events_categories_other_help_tab'                 => array(
489
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
490
+						'filename' => 'events_categories_other',
491
+					),
492
+				),
493
+				'help_tour'     => array(
494
+					'Event_Categories_Help_Tour',
495
+				),
496
+				'metaboxes'     => $this->_default_espresso_metaboxes,
497
+				'require_nonce' => false,
498
+			),
499
+		);
500
+	}
501
+
502
+
503
+
504
+	protected function _add_screen_options()
505
+	{
506
+		//todo
507
+	}
508
+
509
+
510
+
511
+	protected function _add_screen_options_default()
512
+	{
513
+		$this->_per_page_screen_option();
514
+	}
515
+
516
+
517
+
518
+	protected function _add_screen_options_category_list()
519
+	{
520
+		$page_title = $this->_admin_page_title;
521
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
522
+		$this->_per_page_screen_option();
523
+		$this->_admin_page_title = $page_title;
524
+	}
525
+
526
+
527
+
528
+	protected function _add_feature_pointers()
529
+	{
530
+		//todo
531
+	}
532
+
533
+
534
+
535
+	public function load_scripts_styles()
536
+	{
537
+		wp_register_style(
538
+			'events-admin-css',
539
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
540
+			array(),
541
+			EVENT_ESPRESSO_VERSION
542
+		);
543
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
544
+		wp_enqueue_style('events-admin-css');
545
+		wp_enqueue_style('ee-cat-admin');
546
+		//todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
547
+		//registers for all views
548
+		//scripts
549
+		wp_register_script(
550
+			'event_editor_js',
551
+			EVENTS_ASSETS_URL . 'event_editor.js',
552
+			array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
553
+			EVENT_ESPRESSO_VERSION,
554
+			true
555
+		);
556
+	}
557
+
558
+
559
+
560
+	/**
561
+	 * enqueuing scripts and styles specific to this view
562
+	 *
563
+	 * @return void
564
+	 */
565
+	public function load_scripts_styles_create_new()
566
+	{
567
+		$this->load_scripts_styles_edit();
568
+	}
569
+
570
+
571
+
572
+	/**
573
+	 * enqueuing scripts and styles specific to this view
574
+	 *
575
+	 * @return void
576
+	 */
577
+	public function load_scripts_styles_edit()
578
+	{
579
+		//styles
580
+		wp_enqueue_style('espresso-ui-theme');
581
+		wp_register_style(
582
+			'event-editor-css',
583
+			EVENTS_ASSETS_URL . 'event-editor.css',
584
+			array('ee-admin-css'),
585
+			EVENT_ESPRESSO_VERSION
586
+		);
587
+		wp_enqueue_style('event-editor-css');
588
+		//scripts
589
+		wp_register_script(
590
+			'event-datetime-metabox',
591
+			EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
592
+			array('event_editor_js', 'ee-datepicker'),
593
+			EVENT_ESPRESSO_VERSION
594
+		);
595
+		wp_enqueue_script('event-datetime-metabox');
596
+	}
597
+
598
+
599
+
600
+	public function load_scripts_styles_add_category()
601
+	{
602
+		$this->load_scripts_styles_edit_category();
603
+	}
604
+
605
+
606
+
607
+	public function load_scripts_styles_edit_category()
608
+	{
609
+	}
610
+
611
+
612
+
613
+	protected function _set_list_table_views_category_list()
614
+	{
615
+		$this->_views = array(
616
+			'all' => array(
617
+				'slug'        => 'all',
618
+				'label'       => esc_html__('All', 'event_espresso'),
619
+				'count'       => 0,
620
+				'bulk_action' => array(
621
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
622
+				),
623
+			),
624
+		);
625
+	}
626
+
627
+
628
+
629
+	public function admin_init()
630
+	{
631
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
632
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
633
+			'event_espresso'
634
+		);
635
+	}
636
+
637
+
638
+
639
+	//nothing needed for events with these methods.
640
+	public function admin_notices()
641
+	{
642
+	}
643
+
644
+
645
+
646
+	public function admin_footer_scripts()
647
+	{
648
+	}
649
+
650
+
651
+
652
+	/**
653
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
654
+	 * warning (via EE_Error::add_error());
655
+	 *
656
+	 * @param  EE_Event $event Event object
657
+	 * @access public
658
+	 * @return void
659
+	 */
660
+	public function verify_event_edit($event = null)
661
+	{
662
+		// no event?
663
+		if (empty($event)) {
664
+			// set event
665
+			$event = $this->_cpt_model_obj;
666
+		}
667
+		// STILL no event?
668
+		if (! $event instanceof EE_Event) {
669
+			return;
670
+		}
671
+		$orig_status = $event->status();
672
+		// first check if event is active.
673
+		if (
674
+			$orig_status === EEM_Event::cancelled
675
+			|| $orig_status === EEM_Event::postponed
676
+			|| $event->is_expired()
677
+			|| $event->is_inactive()
678
+		) {
679
+			return;
680
+		}
681
+		//made it here so it IS active... next check that any of the tickets are sold.
682
+		if ($event->is_sold_out(true)) {
683
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
684
+				EE_Error::add_attention(
685
+					sprintf(
686
+						esc_html__(
687
+							'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.',
688
+							'event_espresso'
689
+						),
690
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
691
+					)
692
+				);
693
+			}
694
+			return;
695
+		} else if ($orig_status === EEM_Event::sold_out) {
696
+			EE_Error::add_attention(
697
+				sprintf(
698
+					esc_html__(
699
+						'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.',
700
+						'event_espresso'
701
+					),
702
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
703
+				)
704
+			);
705
+		}
706
+		//now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
707
+		if ( ! $event->tickets_on_sale()) {
708
+			return;
709
+		}
710
+		//made it here so show warning
711
+		$this->_edit_event_warning();
712
+	}
713
+
714
+
715
+
716
+	/**
717
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
718
+	 * When needed, hook this into a EE_Error::add_error() notice.
719
+	 *
720
+	 * @access protected
721
+	 * @return void
722
+	 */
723
+	protected function _edit_event_warning()
724
+	{
725
+		// we don't want to add warnings during these requests
726
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
727
+			return;
728
+		}
729
+		EE_Error::add_attention(
730
+			esc_html__(
731
+				'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.',
732
+				'event_espresso'
733
+			)
734
+		);
735
+	}
736
+
737
+
738
+
739
+	/**
740
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
741
+	 * Otherwise, do the normal logic
742
+	 *
743
+	 * @return string
744
+	 * @throws \EE_Error
745
+	 */
746
+	protected function _create_new_cpt_item()
747
+	{
748
+		$gmt_offset = get_option('gmt_offset');
749
+		//only nag them about setting their timezone if it's their first event, and they haven't already done it
750
+		if ($gmt_offset === '0' && ! EEM_Event::instance()->exists(array())) {
751
+			EE_Error::add_attention(
752
+				sprintf(
753
+					__(
754
+						'Your website\'s timezone is currently set to UTC + 0. We recommend updating your timezone to a city or region near you before you create an event. Your timezone can be updated through the %1$sGeneral Settings%2$s page.',
755
+						'event_espresso'
756
+					),
757
+					'<a href="' . admin_url('options-general.php') . '">',
758
+					'</a>'
759
+				),
760
+				__FILE__,
761
+				__FUNCTION__,
762
+				__LINE__
763
+			);
764
+		}
765
+		return parent::_create_new_cpt_item();
766
+	}
767
+
768
+
769
+
770
+	protected function _set_list_table_views_default()
771
+	{
772
+		$this->_views = array(
773
+			'all'   => array(
774
+				'slug'        => 'all',
775
+				'label'       => esc_html__('View All Events', 'event_espresso'),
776
+				'count'       => 0,
777
+				'bulk_action' => array(
778
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
779
+				),
780
+			),
781
+			'draft' => array(
782
+				'slug'        => 'draft',
783
+				'label'       => esc_html__('Draft', 'event_espresso'),
784
+				'count'       => 0,
785
+				'bulk_action' => array(
786
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
787
+				),
788
+			),
789
+		);
790
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
791
+			$this->_views['trash'] = array(
792
+				'slug'        => 'trash',
793
+				'label'       => esc_html__('Trash', 'event_espresso'),
794
+				'count'       => 0,
795
+				'bulk_action' => array(
796
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
797
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
798
+				),
799
+			);
800
+		}
801
+	}
802
+
803
+
804
+
805
+	/**
806
+	 * @return array
807
+	 */
808
+	protected function _event_legend_items()
809
+	{
810
+		$items = array(
811
+			'view_details'   => array(
812
+				'class' => 'dashicons dashicons-search',
813
+				'desc'  => esc_html__('View Event', 'event_espresso'),
814
+			),
815
+			'edit_event'     => array(
816
+				'class' => 'ee-icon ee-icon-calendar-edit',
817
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
818
+			),
819
+			'view_attendees' => array(
820
+				'class' => 'dashicons dashicons-groups',
821
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
822
+			),
823
+		);
824
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
825
+		$statuses = array(
826
+			'sold_out_status'  => array(
827
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
828
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
829
+			),
830
+			'active_status'    => array(
831
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
832
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
833
+			),
834
+			'upcoming_status'  => array(
835
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
836
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
837
+			),
838
+			'postponed_status' => array(
839
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
840
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
841
+			),
842
+			'cancelled_status' => array(
843
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
844
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
845
+			),
846
+			'expired_status'   => array(
847
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
848
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
849
+			),
850
+			'inactive_status'  => array(
851
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
852
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
853
+			),
854
+		);
855
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
856
+		return array_merge($items, $statuses);
857
+	}
858
+
859
+
860
+
861
+	/**
862
+	 * _event_model
863
+	 *
864
+	 * @return EEM_Event
865
+	 */
866
+	private function _event_model()
867
+	{
868
+		if ( ! $this->_event_model instanceof EEM_Event) {
869
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
870
+		}
871
+		return $this->_event_model;
872
+	}
873
+
874
+
875
+
876
+	/**
877
+	 * Adds extra buttons to the WP CPT permalink field row.
878
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
879
+	 *
880
+	 * @param  string $return    the current html
881
+	 * @param  int    $id        the post id for the page
882
+	 * @param  string $new_title What the title is
883
+	 * @param  string $new_slug  what the slug is
884
+	 * @return string            The new html string for the permalink area
885
+	 */
886
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
887
+	{
888
+		//make sure this is only when editing
889
+		if ( ! empty($id)) {
890
+			$post = get_post($id);
891
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
892
+					   . esc_html__('Shortcode', 'event_espresso')
893
+					   . '</a> ';
894
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
895
+					   . $post->ID
896
+					   . ']">';
897
+		}
898
+		return $return;
899
+	}
900
+
901
+
902
+
903
+	/**
904
+	 * _events_overview_list_table
905
+	 * This contains the logic for showing the events_overview list
906
+	 *
907
+	 * @access protected
908
+	 * @return void
909
+	 * @throws \EE_Error
910
+	 */
911
+	protected function _events_overview_list_table()
912
+	{
913
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
914
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
915
+			? (array)$this->_template_args['after_list_table']
916
+			: array();
917
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
918
+																			  . EEH_Template::get_button_or_link(
919
+				get_post_type_archive_link('espresso_events'),
920
+				esc_html__("View Event Archive Page", "event_espresso"),
921
+				'button'
922
+			);
923
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
924
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
925
+				'create_new',
926
+				'add',
927
+				array(),
928
+				'add-new-h2'
929
+			);
930
+		$this->display_admin_list_table_page_with_no_sidebar();
931
+	}
932
+
933
+
934
+
935
+	/**
936
+	 * this allows for extra misc actions in the default WP publish box
937
+	 *
938
+	 * @return void
939
+	 */
940
+	public function extra_misc_actions_publish_box()
941
+	{
942
+		$this->_generate_publish_box_extra_content();
943
+	}
944
+
945
+
946
+
947
+	/**
948
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
949
+	 * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
950
+	 * data.
951
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
952
+	 * ALSO very important.  When a post transitions from scheduled to published, the save_post action is fired but you
953
+	 * will NOT have any _POST data containing any extra info you may have from other meta saves.  So MAKE sure that
954
+	 * you handle this accordingly.
955
+	 *
956
+	 * @access protected
957
+	 * @abstract
958
+	 * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
959
+	 * @param  object $post    The post object of the cpt that was saved.
960
+	 * @return void
961
+	 */
962
+	protected function _insert_update_cpt_item($post_id, $post)
963
+	{
964
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
965
+			//get out we're not processing an event save.
966
+			return;
967
+		}
968
+		$event_values = array(
969
+			'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
970
+			'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
971
+			'EVT_additional_limit'            => min(
972
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
973
+				! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
974
+			),
975
+			'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
976
+				? $this->_req_data['EVT_default_registration_status']
977
+				: EE_Registry::instance()->CFG->registration->default_STS_ID,
978
+			'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
979
+			'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
980
+			'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
981
+				? $this->_req_data['timezone_string'] : null,
982
+			'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
983
+				? $this->_req_data['externalURL'] : null,
984
+			'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
985
+				? $this->_req_data['event_phone'] : null,
986
+		);
987
+		//update event
988
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
989
+		//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!
990
+		$get_one_where = array($this->_event_model()->primary_key_name() => $post_id, 'status' => $post->post_status);
991
+		$event = $this->_event_model()->get_one(array($get_one_where));
992
+		//the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
993
+		$event_update_callbacks = apply_filters(
994
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
995
+			array(array($this, '_default_venue_update'), array($this, '_default_tickets_update'))
996
+		);
997
+		$att_success = true;
998
+		foreach ($event_update_callbacks as $e_callback) {
999
+			$_succ = call_user_func_array($e_callback, array($event, $this->_req_data));
1000
+			$att_success = ! $att_success ? $att_success
1001
+				: $_succ; //if ANY of these updates fail then we want the appropriate global error message
1002
+		}
1003
+		//any errors?
1004
+		if ($success && false === $att_success) {
1005
+			EE_Error::add_error(
1006
+				esc_html__(
1007
+					'Event Details saved successfully but something went wrong with saving attachments.',
1008
+					'event_espresso'
1009
+				),
1010
+				__FILE__,
1011
+				__FUNCTION__,
1012
+				__LINE__
1013
+			);
1014
+		} else if ($success === false) {
1015
+			EE_Error::add_error(
1016
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1017
+				__FILE__,
1018
+				__FUNCTION__,
1019
+				__LINE__
1020
+			);
1021
+		}
1022
+	}
1023
+
1024
+
1025
+
1026
+	/**
1027
+	 * @see parent::restore_item()
1028
+	 * @param int $post_id
1029
+	 * @param int $revision_id
1030
+	 */
1031
+	protected function _restore_cpt_item($post_id, $revision_id)
1032
+	{
1033
+		//copy existing event meta to new post
1034
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1035
+		if ($post_evt instanceof EE_Event) {
1036
+			//meta revision restore
1037
+			$post_evt->restore_revision($revision_id);
1038
+			//related objs restore
1039
+			$post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1040
+		}
1041
+	}
1042
+
1043
+
1044
+
1045
+	/**
1046
+	 * Attach the venue to the Event
1047
+	 *
1048
+	 * @param  \EE_Event $evtobj Event Object to add the venue to
1049
+	 * @param  array     $data   The request data from the form
1050
+	 * @return bool           Success or fail.
1051
+	 */
1052
+	protected function _default_venue_update(\EE_Event $evtobj, $data)
1053
+	{
1054
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1055
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1056
+		$rows_affected = null;
1057
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1058
+		// very important.  If we don't have a venue name...
1059
+		// then we'll get out because not necessary to create empty venue
1060
+		if (empty($data['venue_title'])) {
1061
+			return false;
1062
+		}
1063
+		$venue_array = array(
1064
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1065
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1066
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1067
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1068
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1069
+				: null,
1070
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1071
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1072
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1073
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1074
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1075
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1076
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1077
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1078
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1079
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1080
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1081
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1082
+			'status'              => 'publish',
1083
+		);
1084
+		//if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1085
+		if ( ! empty($venue_id)) {
1086
+			$update_where = array($venue_model->primary_key_name() => $venue_id);
1087
+			$rows_affected = $venue_model->update($venue_array, array($update_where));
1088
+			//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.
1089
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1090
+			return $rows_affected > 0 ? true : false;
1091
+		} else {
1092
+			//we insert the venue
1093
+			$venue_id = $venue_model->insert($venue_array);
1094
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1095
+			return ! empty($venue_id) ? true : false;
1096
+		}
1097
+		//when we have the ancestor come in it's already been handled by the revision save.
1098
+	}
1099
+
1100
+
1101
+
1102
+	/**
1103
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1104
+	 *
1105
+	 * @param  EE_Event $evtobj The Event object we're attaching data to
1106
+	 * @param  array    $data   The request data from the form
1107
+	 * @return array
1108
+	 */
1109
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1110
+	{
1111
+		$success = true;
1112
+		$saved_dtt = null;
1113
+		$saved_tickets = array();
1114
+		$incoming_date_formats = array('Y-m-d', 'h:i a');
1115
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1116
+			//trim all values to ensure any excess whitespace is removed.
1117
+			$dtt = array_map('trim', $dtt);
1118
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1119
+				: $dtt['DTT_EVT_start'];
1120
+			$datetime_values = array(
1121
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1122
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1123
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1124
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1125
+				'DTT_order'     => $row,
1126
+			);
1127
+			//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.
1128
+			if ( ! empty($dtt['DTT_ID'])) {
1129
+				$DTM = EE_Registry::instance()
1130
+								  ->load_model('Datetime', array($evtobj->get_timezone()))
1131
+								  ->get_one_by_ID($dtt['DTT_ID']);
1132
+				$DTM->set_date_format($incoming_date_formats[0]);
1133
+				$DTM->set_time_format($incoming_date_formats[1]);
1134
+				foreach ($datetime_values as $field => $value) {
1135
+					$DTM->set($field, $value);
1136
+				}
1137
+				//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.
1138
+				$saved_dtts[$DTM->ID()] = $DTM;
1139
+			} else {
1140
+				$DTM = EE_Registry::instance()->load_class(
1141
+					'Datetime',
1142
+					array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1143
+					false,
1144
+					false
1145
+				);
1146
+				foreach ($datetime_values as $field => $value) {
1147
+					$DTM->set($field, $value);
1148
+				}
1149
+			}
1150
+			$DTM->save();
1151
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1152
+			//load DTT helper
1153
+			//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.
1154
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1155
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1156
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1157
+				$DTT->save();
1158
+			}
1159
+			//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.
1160
+			$saved_dtt = $DTT;
1161
+			$success = ! $success ? $success : $DTT;
1162
+			//if ANY of these updates fail then we want the appropriate global error message.
1163
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1164
+		}
1165
+		//no dtts get deleted so we don't do any of that logic here.
1166
+		//update tickets next
1167
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1168
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1169
+			$incoming_date_formats = array('Y-m-d', 'h:i a');
1170
+			$update_prices = false;
1171
+			$ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1172
+				? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1173
+			// trim inputs to ensure any excess whitespace is removed.
1174
+			$tkt = array_map('trim', $tkt);
1175
+			if (empty($tkt['TKT_start_date'])) {
1176
+				//let's use now in the set timezone.
1177
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1178
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1179
+			}
1180
+			if (empty($tkt['TKT_end_date'])) {
1181
+				//use the start date of the first datetime
1182
+				$dtt = $evtobj->first_datetime();
1183
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1184
+					$incoming_date_formats[0],
1185
+					$incoming_date_formats[1]
1186
+				);
1187
+			}
1188
+			$TKT_values = array(
1189
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1190
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1191
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1192
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1193
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1194
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1195
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1196
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1197
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1198
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1199
+				'TKT_row'         => $row,
1200
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1201
+				'TKT_price'       => $ticket_price,
1202
+			);
1203
+			//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.
1204
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1205
+				$TKT_values['TKT_ID'] = 0;
1206
+				$TKT_values['TKT_is_default'] = 0;
1207
+				$TKT_values['TKT_price'] = $ticket_price;
1208
+				$update_prices = true;
1209
+			}
1210
+			//if we have a TKT_ID then we need to get that existing TKT_obj and update it
1211
+			//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.
1212
+			//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.
1213
+			if ( ! empty($tkt['TKT_ID'])) {
1214
+				$TKT = EE_Registry::instance()
1215
+								  ->load_model('Ticket', array($evtobj->get_timezone()))
1216
+								  ->get_one_by_ID($tkt['TKT_ID']);
1217
+				if ($TKT instanceof EE_Ticket) {
1218
+					$ticket_sold = $TKT->count_related(
1219
+						'Registration',
1220
+						array(
1221
+							array(
1222
+								'STS_ID' => array(
1223
+									'NOT IN',
1224
+									array(EEM_Registration::status_id_incomplete),
1225
+								),
1226
+							),
1227
+						)
1228
+					) > 0 ? true : false;
1229
+					//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.
1230
+					$create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1231
+									  && ! $TKT->get(
1232
+						'TKT_deleted'
1233
+					) ? true : false;
1234
+					$TKT->set_date_format($incoming_date_formats[0]);
1235
+					$TKT->set_time_format($incoming_date_formats[1]);
1236
+					//set new values
1237
+					foreach ($TKT_values as $field => $value) {
1238
+						if ($field == 'TKT_qty') {
1239
+							$TKT->set_qty($value);
1240
+						} else {
1241
+							$TKT->set($field, $value);
1242
+						}
1243
+					}
1244
+					//if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1245
+					if ($create_new_TKT) {
1246
+						//archive the old ticket first
1247
+						$TKT->set('TKT_deleted', 1);
1248
+						$TKT->save();
1249
+						//make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1250
+						$saved_tickets[$TKT->ID()] = $TKT;
1251
+						//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.
1252
+						$TKT = clone $TKT;
1253
+						$TKT->set('TKT_ID', 0);
1254
+						$TKT->set('TKT_deleted', 0);
1255
+						$TKT->set('TKT_price', $ticket_price);
1256
+						$TKT->set('TKT_sold', 0);
1257
+						//now we need to make sure that $new prices are created as well and attached to new ticket.
1258
+						$update_prices = true;
1259
+					}
1260
+					//make sure price is set if it hasn't been already
1261
+					$TKT->set('TKT_price', $ticket_price);
1262
+				}
1263
+			} else {
1264
+				//no TKT_id so a new TKT
1265
+				$TKT_values['TKT_price'] = $ticket_price;
1266
+				$TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1267
+				if ($TKT instanceof EE_Ticket) {
1268
+					//need to reset values to properly account for the date formats
1269
+					$TKT->set_date_format($incoming_date_formats[0]);
1270
+					$TKT->set_time_format($incoming_date_formats[1]);
1271
+					$TKT->set_timezone($evtobj->get_timezone());
1272
+					//set new values
1273
+					foreach ($TKT_values as $field => $value) {
1274
+						if ($field == 'TKT_qty') {
1275
+							$TKT->set_qty($value);
1276
+						} else {
1277
+							$TKT->set($field, $value);
1278
+						}
1279
+					}
1280
+					$update_prices = true;
1281
+				}
1282
+			}
1283
+			// cap ticket qty by datetime reg limits
1284
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1285
+			//update ticket.
1286
+			$TKT->save();
1287
+			//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.
1288
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1289
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1290
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1291
+				$TKT->save();
1292
+			}
1293
+			//initially let's add the ticket to the dtt
1294
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1295
+			$saved_tickets[$TKT->ID()] = $TKT;
1296
+			//add prices to ticket
1297
+			$this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1298
+		}
1299
+		//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.
1300
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1301
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1302
+		foreach ($tickets_removed as $id) {
1303
+			$id = absint($id);
1304
+			//get the ticket for this id
1305
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1306
+			//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)
1307
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1308
+			foreach ($dtts as $dtt) {
1309
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1310
+			}
1311
+			//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))
1312
+			$tkt_to_remove->delete_related_permanently('Price');
1313
+			//finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1314
+			$tkt_to_remove->delete_permanently();
1315
+		}
1316
+		return array($saved_dtt, $saved_tickets);
1317
+	}
1318
+
1319
+
1320
+
1321
+	/**
1322
+	 * This attaches a list of given prices to a ticket.
1323
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1324
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1325
+	 * price info and prices are automatically "archived" via the ticket.
1326
+	 *
1327
+	 * @access  private
1328
+	 * @param array     $prices     Array of prices from the form.
1329
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1330
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1331
+	 * @return  void
1332
+	 */
1333
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1334
+	{
1335
+		foreach ($prices as $row => $prc) {
1336
+			$PRC_values = array(
1337
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1338
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1339
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1340
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1341
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1342
+				'PRC_is_default' => 0, //make sure prices are NOT set as default from this context
1343
+				'PRC_order'      => $row,
1344
+			);
1345
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1346
+				$PRC_values['PRC_ID'] = 0;
1347
+				$PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1348
+			} else {
1349
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1350
+				//update this price with new values
1351
+				foreach ($PRC_values as $field => $newprc) {
1352
+					$PRC->set($field, $newprc);
1353
+				}
1354
+				$PRC->save();
1355
+			}
1356
+			$ticket->_add_relation_to($PRC, 'Price');
1357
+		}
1358
+	}
1359
+
1360
+
1361
+
1362
+	/**
1363
+	 * Add in our autosave ajax handlers
1364
+	 *
1365
+	 * @return void
1366
+	 */
1367
+	protected function _ee_autosave_create_new()
1368
+	{
1369
+		// $this->_ee_autosave_edit();
1370
+	}
1371
+
1372
+
1373
+
1374
+	protected function _ee_autosave_edit()
1375
+	{
1376
+		return; //TEMPORARILY EXITING CAUSE THIS IS A TODO
1377
+	}
1378
+
1379
+
1380
+
1381
+	/**
1382
+	 *    _generate_publish_box_extra_content
1383
+	 *
1384
+	 * @access private
1385
+	 * @return void
1386
+	 */
1387
+	private function _generate_publish_box_extra_content()
1388
+	{
1389
+		//load formatter helper
1390
+		//args for getting related registrations
1391
+		$approved_query_args = array(
1392
+			array(
1393
+				'REG_deleted' => 0,
1394
+				'STS_ID'      => EEM_Registration::status_id_approved,
1395
+			),
1396
+		);
1397
+		$not_approved_query_args = array(
1398
+			array(
1399
+				'REG_deleted' => 0,
1400
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1401
+			),
1402
+		);
1403
+		$pending_payment_query_args = array(
1404
+			array(
1405
+				'REG_deleted' => 0,
1406
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1407
+			),
1408
+		);
1409
+		// publish box
1410
+		$publish_box_extra_args = array(
1411
+			'view_approved_reg_url'        => add_query_arg(
1412
+				array(
1413
+					'action'      => 'default',
1414
+					'event_id'    => $this->_cpt_model_obj->ID(),
1415
+					'_reg_status' => EEM_Registration::status_id_approved,
1416
+				),
1417
+				REG_ADMIN_URL
1418
+			),
1419
+			'view_not_approved_reg_url'    => add_query_arg(
1420
+				array(
1421
+					'action'      => 'default',
1422
+					'event_id'    => $this->_cpt_model_obj->ID(),
1423
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1424
+				),
1425
+				REG_ADMIN_URL
1426
+			),
1427
+			'view_pending_payment_reg_url' => add_query_arg(
1428
+				array(
1429
+					'action'      => 'default',
1430
+					'event_id'    => $this->_cpt_model_obj->ID(),
1431
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1432
+				),
1433
+				REG_ADMIN_URL
1434
+			),
1435
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1436
+				'Registration',
1437
+				$approved_query_args
1438
+			),
1439
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1440
+				'Registration',
1441
+				$not_approved_query_args
1442
+			),
1443
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1444
+				'Registration',
1445
+				$pending_payment_query_args
1446
+			),
1447
+			'misc_pub_section_class'       => apply_filters(
1448
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1449
+				'misc-pub-section'
1450
+			),
1451
+			//'email_attendees_url' => add_query_arg(
1452
+			//	array(
1453
+			//		'event_admin_reports' => 'event_newsletter',
1454
+			//		'event_id' => $this->_cpt_model_obj->id
1455
+			//	),
1456
+			//	'admin.php?page=espresso_registrations'
1457
+			//),
1458
+		);
1459
+		ob_start();
1460
+		do_action(
1461
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1462
+			$this->_cpt_model_obj
1463
+		);
1464
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1465
+		// load template
1466
+		EEH_Template::display_template(
1467
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1468
+			$publish_box_extra_args
1469
+		);
1470
+	}
1471
+
1472
+
1473
+
1474
+	/**
1475
+	 * This just returns whatever is set as the _event object property
1476
+	 * //todo this will become obsolete once the models are in place
1477
+	 *
1478
+	 * @return object
1479
+	 */
1480
+	public function get_event_object()
1481
+	{
1482
+		return $this->_cpt_model_obj;
1483
+	}
1484
+
1485
+
1486
+
1487
+
1488
+	/** METABOXES * */
1489
+	/**
1490
+	 * _register_event_editor_meta_boxes
1491
+	 * add all metaboxes related to the event_editor
1492
+	 *
1493
+	 * @return void
1494
+	 */
1495
+	protected function _register_event_editor_meta_boxes()
1496
+	{
1497
+		$this->verify_cpt_object();
1498
+		add_meta_box(
1499
+			'espresso_event_editor_tickets',
1500
+			esc_html__('Event Datetime & Ticket', 'event_espresso'),
1501
+			array($this, 'ticket_metabox'),
1502
+			$this->page_slug,
1503
+			'normal',
1504
+			'high'
1505
+		);
1506
+		add_meta_box(
1507
+			'espresso_event_editor_event_options',
1508
+			esc_html__('Event Registration Options', 'event_espresso'),
1509
+			array($this, 'registration_options_meta_box'),
1510
+			$this->page_slug,
1511
+			'side',
1512
+			'default'
1513
+		);
1514
+		// NOTE: if you're looking for other metaboxes in here,
1515
+		// where a metabox has a related management page in the admin
1516
+		// you will find it setup in the related management page's "_Hooks" file.
1517
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1518
+	}
1519
+
1520
+
1521
+
1522
+	public function ticket_metabox()
1523
+	{
1524
+		$existing_datetime_ids = $existing_ticket_ids = array();
1525
+		//defaults for template args
1526
+		$template_args = array(
1527
+			'existing_datetime_ids'    => '',
1528
+			'event_datetime_help_link' => '',
1529
+			'ticket_options_help_link' => '',
1530
+			'time'                     => null,
1531
+			'ticket_rows'              => '',
1532
+			'existing_ticket_ids'      => '',
1533
+			'total_ticket_rows'        => 1,
1534
+			'ticket_js_structure'      => '',
1535
+			'trash_icon'               => 'ee-lock-icon',
1536
+			'disabled'                 => '',
1537
+		);
1538
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1539
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1540
+		/**
1541
+		 * 1. Start with retrieving Datetimes
1542
+		 * 2. Fore each datetime get related tickets
1543
+		 * 3. For each ticket get related prices
1544
+		 */
1545
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1546
+		/** @type EE_Datetime $first_datetime */
1547
+		$first_datetime = reset($times);
1548
+		//do we get related tickets?
1549
+		if ($first_datetime instanceof EE_Datetime
1550
+			&& $first_datetime->ID() !== 0
1551
+		) {
1552
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1553
+			$template_args['time'] = $first_datetime;
1554
+			$related_tickets = $first_datetime->tickets(
1555
+				array(
1556
+					array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1557
+					'default_where_conditions' => 'none',
1558
+				)
1559
+			);
1560
+			if ( ! empty($related_tickets)) {
1561
+				$template_args['total_ticket_rows'] = count($related_tickets);
1562
+				$row = 0;
1563
+				foreach ($related_tickets as $ticket) {
1564
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1565
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1566
+					$row++;
1567
+				}
1568
+			} else {
1569
+				$template_args['total_ticket_rows'] = 1;
1570
+				/** @type EE_Ticket $ticket */
1571
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1572
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1573
+			}
1574
+		} else {
1575
+			$template_args['time'] = $times[0];
1576
+			/** @type EE_Ticket $ticket */
1577
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1578
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1579
+			// NOTE: we're just sending the first default row
1580
+			// (decaf can't manage default tickets so this should be sufficient);
1581
+		}
1582
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1583
+			'event_editor_event_datetimes_help_tab'
1584
+		);
1585
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1586
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1587
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1588
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1589
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1590
+			true
1591
+		);
1592
+		$template = apply_filters(
1593
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1594
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1595
+		);
1596
+		EEH_Template::display_template($template, $template_args);
1597
+	}
1598
+
1599
+
1600
+
1601
+	/**
1602
+	 * Setup an individual ticket form for the decaf event editor page
1603
+	 *
1604
+	 * @access private
1605
+	 * @param  EE_Ticket $ticket   the ticket object
1606
+	 * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1607
+	 * @param int        $row
1608
+	 * @return string generated html for the ticket row.
1609
+	 */
1610
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1611
+	{
1612
+		$template_args = array(
1613
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1614
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1615
+				: '',
1616
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1617
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1618
+			'TKT_name'            => $ticket->get('TKT_name'),
1619
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1620
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1621
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1622
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1623
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1624
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1625
+			'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1626
+									 && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1627
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1628
+			'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1629
+				: ' disabled=disabled',
1630
+		);
1631
+		$price = $ticket->ID() !== 0
1632
+			? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1633
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1634
+		$price_args = array(
1635
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1636
+			'PRC_amount'            => $price->get('PRC_amount'),
1637
+			'PRT_ID'                => $price->get('PRT_ID'),
1638
+			'PRC_ID'                => $price->get('PRC_ID'),
1639
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1640
+		);
1641
+		//make sure we have default start and end dates if skeleton
1642
+		//handle rows that should NOT be empty
1643
+		if (empty($template_args['TKT_start_date'])) {
1644
+			//if empty then the start date will be now.
1645
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1646
+		}
1647
+		if (empty($template_args['TKT_end_date'])) {
1648
+			//get the earliest datetime (if present);
1649
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1650
+				? $this->_cpt_model_obj->get_first_related(
1651
+					'Datetime',
1652
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1653
+				)
1654
+				: null;
1655
+			if ( ! empty($earliest_dtt)) {
1656
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1657
+			} else {
1658
+				$template_args['TKT_end_date'] = date(
1659
+					'Y-m-d h:i a',
1660
+					mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1661
+				);
1662
+			}
1663
+		}
1664
+		$template_args = array_merge($template_args, $price_args);
1665
+		$template = apply_filters(
1666
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1667
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1668
+			$ticket
1669
+		);
1670
+		return EEH_Template::display_template($template, $template_args, true);
1671
+	}
1672
+
1673
+
1674
+
1675
+	public function registration_options_meta_box()
1676
+	{
1677
+		$yes_no_values = array(
1678
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1679
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1680
+		);
1681
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1682
+			array(
1683
+				EEM_Registration::status_id_cancelled,
1684
+				EEM_Registration::status_id_declined,
1685
+				EEM_Registration::status_id_incomplete,
1686
+			),
1687
+			true
1688
+		);
1689
+		//$template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1690
+		$template_args['_event'] = $this->_cpt_model_obj;
1691
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1692
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1693
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1694
+			'default_reg_status',
1695
+			$default_reg_status_values,
1696
+			$this->_cpt_model_obj->default_registration_status()
1697
+		);
1698
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1699
+			'display_desc',
1700
+			$yes_no_values,
1701
+			$this->_cpt_model_obj->display_description()
1702
+		);
1703
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1704
+			'display_ticket_selector',
1705
+			$yes_no_values,
1706
+			$this->_cpt_model_obj->display_ticket_selector(),
1707
+			'',
1708
+			'',
1709
+			false
1710
+		);
1711
+		$template_args['additional_registration_options'] = apply_filters(
1712
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1713
+			'',
1714
+			$template_args,
1715
+			$yes_no_values,
1716
+			$default_reg_status_values
1717
+		);
1718
+		EEH_Template::display_template(
1719
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1720
+			$template_args
1721
+		);
1722
+	}
1723
+
1724
+
1725
+
1726
+	/**
1727
+	 * _get_events()
1728
+	 * This method simply returns all the events (for the given _view and paging)
1729
+	 *
1730
+	 * @access public
1731
+	 * @param int  $per_page     count of items per page (20 default);
1732
+	 * @param int  $current_page what is the current page being viewed.
1733
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1734
+	 *                           If FALSE then we return an array of event objects
1735
+	 *                           that match the given _view and paging parameters.
1736
+	 * @return array an array of event objects.
1737
+	 */
1738
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1739
+	{
1740
+		$EEME = $this->_event_model();
1741
+		$offset = ($current_page - 1) * $per_page;
1742
+		$limit = $count ? null : $offset . ',' . $per_page;
1743
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1744
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1745
+		if (isset($this->_req_data['month_range'])) {
1746
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1747
+			//simulate the FIRST day of the month, that fixes issues for months like February
1748
+			//where PHP doesn't know what to assume for date.
1749
+			//@see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1750
+			$month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1751
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1752
+		}
1753
+		$where = array();
1754
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1755
+		//determine what post_status our condition will have for the query.
1756
+		switch ($status) {
1757
+			case 'month' :
1758
+			case 'today' :
1759
+			case null :
1760
+			case 'all' :
1761
+				break;
1762
+			case 'draft' :
1763
+				$where['status'] = array('IN', array('draft', 'auto-draft'));
1764
+				break;
1765
+			default :
1766
+				$where['status'] = $status;
1767
+		}
1768
+		//categories?
1769
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1770
+			? $this->_req_data['EVT_CAT'] : null;
1771
+		if ( ! empty ($category)) {
1772
+			$where['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1773
+			$where['Term_Taxonomy.term_id'] = $category;
1774
+		}
1775
+		//date where conditions
1776
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1777
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1778
+			$DateTime = new DateTime(
1779
+				$year_r . '-' . $month_r . '-01 00:00:00',
1780
+				new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1781
+			);
1782
+			$start = $DateTime->format(implode(' ', $start_formats));
1783
+			$end = $DateTime->setDate($year_r, $month_r, $DateTime
1784
+				->format('t'))->setTime(23, 59, 59)
1785
+							->format(implode(' ', $start_formats));
1786
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1787
+		} else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1788
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1789
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1790
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1791
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1792
+		} else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1793
+			$now = date('Y-m-01');
1794
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1795
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1796
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1797
+							->setTime(23, 59, 59)
1798
+							->format(implode(' ', $start_formats));
1799
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1800
+		}
1801
+		if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1802
+			$where['EVT_wp_user'] = get_current_user_id();
1803
+		} else {
1804
+			if ( ! isset($where['status'])) {
1805
+				if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1806
+					$where['OR'] = array(
1807
+						'status*restrict_private' => array('!=', 'private'),
1808
+						'AND'                     => array(
1809
+							'status*inclusive' => array('=', 'private'),
1810
+							'EVT_wp_user'      => get_current_user_id(),
1811
+						),
1812
+					);
1813
+				}
1814
+			}
1815
+		}
1816
+		if (isset($this->_req_data['EVT_wp_user'])) {
1817
+			if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1818
+				&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1819
+			) {
1820
+				$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1821
+			}
1822
+		}
1823
+		//search query handling
1824
+		if (isset($this->_req_data['s'])) {
1825
+			$search_string = '%' . $this->_req_data['s'] . '%';
1826
+			$where['OR'] = array(
1827
+				'EVT_name'       => array('LIKE', $search_string),
1828
+				'EVT_desc'       => array('LIKE', $search_string),
1829
+				'EVT_short_desc' => array('LIKE', $search_string),
1830
+			);
1831
+		}
1832
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1833
+		$query_params = apply_filters(
1834
+			'FHEE__Events_Admin_Page__get_events__query_params',
1835
+			array(
1836
+				$where,
1837
+				'limit'    => $limit,
1838
+				'order_by' => $orderby,
1839
+				'order'    => $order,
1840
+				'group_by' => 'EVT_ID',
1841
+			),
1842
+			$this->_req_data
1843
+		);
1844
+		//let's first check if we have special requests coming in.
1845
+		if (isset($this->_req_data['active_status'])) {
1846
+			switch ($this->_req_data['active_status']) {
1847
+				case 'upcoming' :
1848
+					return $EEME->get_upcoming_events($query_params, $count);
1849
+					break;
1850
+				case 'expired' :
1851
+					return $EEME->get_expired_events($query_params, $count);
1852
+					break;
1853
+				case 'active' :
1854
+					return $EEME->get_active_events($query_params, $count);
1855
+					break;
1856
+				case 'inactive' :
1857
+					return $EEME->get_inactive_events($query_params, $count);
1858
+					break;
1859
+			}
1860
+		}
1861
+		$events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1862
+		return $events;
1863
+	}
1864
+
1865
+
1866
+
1867
+	/**
1868
+	 * handling for WordPress CPT actions (trash, restore, delete)
1869
+	 *
1870
+	 * @param string $post_id
1871
+	 */
1872
+	public function trash_cpt_item($post_id)
1873
+	{
1874
+		$this->_req_data['EVT_ID'] = $post_id;
1875
+		$this->_trash_or_restore_event('trash', false);
1876
+	}
1877
+
1878
+
1879
+
1880
+	/**
1881
+	 * @param string $post_id
1882
+	 */
1883
+	public function restore_cpt_item($post_id)
1884
+	{
1885
+		$this->_req_data['EVT_ID'] = $post_id;
1886
+		$this->_trash_or_restore_event('draft', false);
1887
+	}
1888
+
1889
+
1890
+
1891
+	/**
1892
+	 * @param string $post_id
1893
+	 */
1894
+	public function delete_cpt_item($post_id)
1895
+	{
1896
+		$this->_req_data['EVT_ID'] = $post_id;
1897
+		$this->_delete_event(false);
1898
+	}
1899
+
1900
+
1901
+
1902
+	/**
1903
+	 * _trash_or_restore_event
1904
+	 *
1905
+	 * @access protected
1906
+	 * @param  string $event_status
1907
+	 * @param bool    $redirect_after
1908
+	 */
1909
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1910
+	{
1911
+		//determine the event id and set to array.
1912
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1913
+		// loop thru events
1914
+		if ($EVT_ID) {
1915
+			// clean status
1916
+			$event_status = sanitize_key($event_status);
1917
+			// grab status
1918
+			if ( ! empty($event_status)) {
1919
+				$success = $this->_change_event_status($EVT_ID, $event_status);
1920
+			} else {
1921
+				$success = false;
1922
+				$msg = esc_html__(
1923
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1924
+					'event_espresso'
1925
+				);
1926
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1927
+			}
1928
+		} else {
1929
+			$success = false;
1930
+			$msg = esc_html__(
1931
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1932
+				'event_espresso'
1933
+			);
1934
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1935
+		}
1936
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1937
+		if ($redirect_after) {
1938
+			$this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1939
+		}
1940
+	}
1941
+
1942
+
1943
+
1944
+	/**
1945
+	 * _trash_or_restore_events
1946
+	 *
1947
+	 * @access protected
1948
+	 * @param  string $event_status
1949
+	 * @return void
1950
+	 */
1951
+	protected function _trash_or_restore_events($event_status = 'trash')
1952
+	{
1953
+		// clean status
1954
+		$event_status = sanitize_key($event_status);
1955
+		// grab status
1956
+		if ( ! empty($event_status)) {
1957
+			$success = true;
1958
+			//determine the event id and set to array.
1959
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
1960
+			// loop thru events
1961
+			foreach ($EVT_IDs as $EVT_ID) {
1962
+				if ($EVT_ID = absint($EVT_ID)) {
1963
+					$results = $this->_change_event_status($EVT_ID, $event_status);
1964
+					$success = $results !== false ? $success : false;
1965
+				} else {
1966
+					$msg = sprintf(
1967
+						esc_html__(
1968
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
1969
+							'event_espresso'
1970
+						),
1971
+						$EVT_ID
1972
+					);
1973
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1974
+					$success = false;
1975
+				}
1976
+			}
1977
+		} else {
1978
+			$success = false;
1979
+			$msg = esc_html__(
1980
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1981
+				'event_espresso'
1982
+			);
1983
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1984
+		}
1985
+		// in order to force a pluralized result message we need to send back a success status greater than 1
1986
+		$success = $success ? 2 : false;
1987
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1988
+		$this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
1989
+	}
1990
+
1991
+
1992
+
1993
+	/**
1994
+	 * _trash_or_restore_events
1995
+	 *
1996
+	 * @access  private
1997
+	 * @param  int    $EVT_ID
1998
+	 * @param  string $event_status
1999
+	 * @return bool
2000
+	 */
2001
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2002
+	{
2003
+		// grab event id
2004
+		if ( ! $EVT_ID) {
2005
+			$msg = esc_html__(
2006
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2007
+				'event_espresso'
2008
+			);
2009
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2010
+			return false;
2011
+		}
2012
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2013
+		// clean status
2014
+		$event_status = sanitize_key($event_status);
2015
+		// grab status
2016
+		if (empty($event_status)) {
2017
+			$msg = esc_html__(
2018
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2019
+				'event_espresso'
2020
+			);
2021
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2022
+			return false;
2023
+		}
2024
+		// was event trashed or restored ?
2025
+		switch ($event_status) {
2026
+			case 'draft' :
2027
+				$action = 'restored from the trash';
2028
+				$hook = 'AHEE_event_restored_from_trash';
2029
+				break;
2030
+			case 'trash' :
2031
+				$action = 'moved to the trash';
2032
+				$hook = 'AHEE_event_moved_to_trash';
2033
+				break;
2034
+			default :
2035
+				$action = 'updated';
2036
+				$hook = false;
2037
+		}
2038
+		//use class to change status
2039
+		$this->_cpt_model_obj->set_status($event_status);
2040
+		$success = $this->_cpt_model_obj->save();
2041
+		if ($success === false) {
2042
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2043
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2044
+			return false;
2045
+		}
2046
+		if ($hook) {
2047
+			do_action($hook);
2048
+		}
2049
+		return true;
2050
+	}
2051
+
2052
+
2053
+
2054
+	/**
2055
+	 * _delete_event
2056
+	 *
2057
+	 * @access protected
2058
+	 * @param bool $redirect_after
2059
+	 */
2060
+	protected function _delete_event($redirect_after = true)
2061
+	{
2062
+		//determine the event id and set to array.
2063
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2064
+		$EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2065
+		// loop thru events
2066
+		if ($EVT_ID) {
2067
+			$success = $this->_permanently_delete_event($EVT_ID);
2068
+			// get list of events with no prices
2069
+			$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2070
+			// remove this event from the list of events with no prices
2071
+			if (isset($espresso_no_ticket_prices[$EVT_ID])) {
2072
+				unset($espresso_no_ticket_prices[$EVT_ID]);
2073
+			}
2074
+			update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2075
+		} else {
2076
+			$success = false;
2077
+			$msg = esc_html__(
2078
+				'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2079
+				'event_espresso'
2080
+			);
2081
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2082
+		}
2083
+		if ($redirect_after) {
2084
+			$this->_redirect_after_action(
2085
+				$success,
2086
+				'Event',
2087
+				'deleted',
2088
+				array('action' => 'default', 'status' => 'trash')
2089
+			);
2090
+		}
2091
+	}
2092
+
2093
+
2094
+
2095
+	/**
2096
+	 * _delete_events
2097
+	 *
2098
+	 * @access protected
2099
+	 * @return void
2100
+	 */
2101
+	protected function _delete_events()
2102
+	{
2103
+		$success = true;
2104
+		// get list of events with no prices
2105
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2106
+		//determine the event id and set to array.
2107
+		$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
2108
+		// loop thru events
2109
+		foreach ($EVT_IDs as $EVT_ID) {
2110
+			$EVT_ID = absint($EVT_ID);
2111
+			if ($EVT_ID) {
2112
+				$results = $this->_permanently_delete_event($EVT_ID);
2113
+				$success = $results !== false ? $success : false;
2114
+				// remove this event from the list of events with no prices
2115
+				unset($espresso_no_ticket_prices[$EVT_ID]);
2116
+			} else {
2117
+				$success = false;
2118
+				$msg = esc_html__(
2119
+					'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2120
+					'event_espresso'
2121
+				);
2122
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2123
+			}
2124
+		}
2125
+		update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2126
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2127
+		$success = $success ? 2 : false;
2128
+		$this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2129
+	}
2130
+
2131
+
2132
+
2133
+	/**
2134
+	 * _permanently_delete_event
2135
+	 *
2136
+	 * @access  private
2137
+	 * @param  int $EVT_ID
2138
+	 * @return bool
2139
+	 */
2140
+	private function _permanently_delete_event($EVT_ID = 0)
2141
+	{
2142
+		// grab event id
2143
+		if ( ! $EVT_ID) {
2144
+			$msg = esc_html__(
2145
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2146
+				'event_espresso'
2147
+			);
2148
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2149
+			return false;
2150
+		}
2151
+		if (
2152
+			! $this->_cpt_model_obj instanceof EE_Event
2153
+			|| $this->_cpt_model_obj->ID() !== $EVT_ID
2154
+		) {
2155
+			$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2156
+		}
2157
+		if ( ! $this->_cpt_model_obj instanceof EE_Event) {
2158
+			return false;
2159
+		}
2160
+		//need to delete related tickets and prices first.
2161
+		$datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2162
+		foreach ($datetimes as $datetime) {
2163
+			$this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2164
+			$tickets = $datetime->get_many_related('Ticket');
2165
+			foreach ($tickets as $ticket) {
2166
+				$ticket->_remove_relation_to($datetime, 'Datetime');
2167
+				$ticket->delete_related_permanently('Price');
2168
+				$ticket->delete_permanently();
2169
+			}
2170
+			$datetime->delete();
2171
+		}
2172
+		//what about related venues or terms?
2173
+		$venues = $this->_cpt_model_obj->get_many_related('Venue');
2174
+		foreach ($venues as $venue) {
2175
+			$this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2176
+		}
2177
+		//any attached question groups?
2178
+		$question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2179
+		if ( ! empty($question_groups)) {
2180
+			foreach ($question_groups as $question_group) {
2181
+				$this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2182
+			}
2183
+		}
2184
+		//Message Template Groups
2185
+		$this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2186
+		/** @type EE_Term_Taxonomy[] $term_taxonomies */
2187
+		$term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2188
+		foreach ($term_taxonomies as $term_taxonomy) {
2189
+			$this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2190
+		}
2191
+		$success = $this->_cpt_model_obj->delete_permanently();
2192
+		// did it all go as planned ?
2193
+		if ($success) {
2194
+			$msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2195
+			EE_Error::add_success($msg);
2196
+		} else {
2197
+			$msg = sprintf(
2198
+				esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2199
+				$EVT_ID
2200
+			);
2201
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2202
+			return false;
2203
+		}
2204
+		do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2205
+		return true;
2206
+	}
2207
+
2208
+
2209
+
2210
+	/**
2211
+	 * get total number of events
2212
+	 *
2213
+	 * @access public
2214
+	 * @return int
2215
+	 */
2216
+	public function total_events()
2217
+	{
2218
+		$count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2219
+		return $count;
2220
+	}
2221
+
2222
+
2223
+
2224
+	/**
2225
+	 * get total number of draft events
2226
+	 *
2227
+	 * @access public
2228
+	 * @return int
2229
+	 */
2230
+	public function total_events_draft()
2231
+	{
2232
+		$where = array(
2233
+			'status' => array('IN', array('draft', 'auto-draft')),
2234
+		);
2235
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2236
+		return $count;
2237
+	}
2238
+
2239
+
2240
+
2241
+	/**
2242
+	 * get total number of trashed events
2243
+	 *
2244
+	 * @access public
2245
+	 * @return int
2246
+	 */
2247
+	public function total_trashed_events()
2248
+	{
2249
+		$where = array(
2250
+			'status' => 'trash',
2251
+		);
2252
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2253
+		return $count;
2254
+	}
2255
+
2256
+
2257
+	/**
2258
+	 *    _default_event_settings
2259
+	 *    This generates the Default Settings Tab
2260
+	 *
2261
+	 * @return void
2262
+	 * @throws \EE_Error
2263
+	 */
2264
+	protected function _default_event_settings()
2265
+	{
2266
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2267
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2268
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2269
+		$this->display_admin_page_with_sidebar();
2270
+	}
2271
+
2272
+
2273
+	/**
2274
+	 * Return the form for event settings.
2275
+	 * @return \EE_Form_Section_Proper
2276
+	 */
2277
+	protected function _default_event_settings_form()
2278
+	{
2279
+		$registration_config = EE_Registry::instance()->CFG->registration;
2280
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2281
+		//exclude
2282
+			array(
2283
+				EEM_Registration::status_id_cancelled,
2284
+				EEM_Registration::status_id_declined,
2285
+				EEM_Registration::status_id_incomplete,
2286
+				EEM_Registration::status_id_wait_list,
2287
+			),
2288
+			true
2289
+		);
2290
+		return new EE_Form_Section_Proper(
2291
+			array(
2292
+				'name' => 'update_default_event_settings',
2293
+				'html_id' => 'update_default_event_settings',
2294
+				'html_class' => 'form-table',
2295
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2296
+				'subsections' => apply_filters(
2297
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2298
+					array(
2299
+						'default_reg_status' => new EE_Select_Input(
2300
+							$registration_stati_for_selection,
2301
+							array(
2302
+								'default' => isset($registration_config->default_STS_ID)
2303
+											 && array_key_exists(
2304
+												$registration_config->default_STS_ID,
2305
+												$registration_stati_for_selection
2306
+											 )
2307
+											? sanitize_text_field($registration_config->default_STS_ID)
2308
+											: EEM_Registration::status_id_pending_payment,
2309
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2310
+													. EEH_Template::get_help_tab_link(
2311
+														'default_settings_status_help_tab'
2312
+													),
2313
+								'html_help_text' => esc_html__(
2314
+									'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.',
2315
+									'event_espresso'
2316
+								)
2317
+							)
2318
+						),
2319
+						'default_max_tickets' => new EE_Integer_Input(
2320
+							array(
2321
+								'default' => isset($registration_config->default_maximum_number_of_tickets)
2322
+									? $registration_config->default_maximum_number_of_tickets
2323
+									: EEM_Event::get_default_additional_limit(),
2324
+								'html_label_text' => esc_html__(
2325
+									'Default Maximum Tickets Allowed Per Order:',
2326
+									'event_espresso'
2327
+								) . EEH_Template::get_help_tab_link(
2328
+									'default_maximum_tickets_help_tab"'
2329
+									),
2330
+								'html_help_text' => esc_html__(
2331
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2332
+									'event_espresso'
2333
+								)
2334
+							)
2335
+						)
2336
+					)
2337
+				)
2338
+			)
2339
+		);
2340
+	}
2341
+
2342
+
2343
+	/**
2344
+	 * _update_default_event_settings
2345
+	 *
2346
+	 * @access protected
2347
+	 * @return void
2348
+	 * @throws \EE_Error
2349
+	 */
2350
+	protected function _update_default_event_settings()
2351
+	{
2352
+		$registration_config = EE_Registry::instance()->CFG->registration;
2353
+		$form = $this->_default_event_settings_form();
2354
+		if ($form->was_submitted()) {
2355
+			$form->receive_form_submission();
2356
+			if ($form->is_valid()) {
2357
+				$valid_data = $form->valid_data();
2358
+				if (isset($valid_data['default_reg_status'])) {
2359
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2360
+				}
2361
+				if (isset($valid_data['default_max_tickets'])) {
2362
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2363
+				}
2364
+				//update because data was valid!
2365
+				EE_Registry::instance()->CFG->update_espresso_config();
2366
+				EE_Error::overwrite_success();
2367
+				EE_Error::add_success(
2368
+					__('Default Event Settings were updated', 'event_espresso')
2369
+				);
2370
+			}
2371
+		}
2372
+		$this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2373
+	}
2374
+
2375
+
2376
+
2377
+	/*************        Templates        *************/
2378
+	protected function _template_settings()
2379
+	{
2380
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2381
+		$this->_template_args['preview_img'] = '<img src="'
2382
+											   . EVENTS_ASSETS_URL
2383
+											   . DS
2384
+											   . 'images'
2385
+											   . DS
2386
+											   . 'caffeinated_template_features.jpg" alt="'
2387
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2388
+											   . '" />';
2389
+		$this->_template_args['preview_text'] = '<strong>' . esc_html__(
2390
+				'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.',
2391
+				'event_espresso'
2392
+			) . '</strong>';
2393
+		$this->display_admin_caf_preview_page('template_settings_tab');
2394
+	}
2395
+
2396
+
2397
+	/** Event Category Stuff **/
2398
+	/**
2399
+	 * set the _category property with the category object for the loaded page.
2400
+	 *
2401
+	 * @access private
2402
+	 * @return void
2403
+	 */
2404
+	private function _set_category_object()
2405
+	{
2406
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2407
+			return;
2408
+		} //already have the category object so get out.
2409
+		//set default category object
2410
+		$this->_set_empty_category_object();
2411
+		//only set if we've got an id
2412
+		if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2413
+			return;
2414
+		}
2415
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2416
+		$term = get_term($category_id, 'espresso_event_categories');
2417
+		if ( ! empty($term)) {
2418
+			$this->_category->category_name = $term->name;
2419
+			$this->_category->category_identifier = $term->slug;
2420
+			$this->_category->category_desc = $term->description;
2421
+			$this->_category->id = $term->term_id;
2422
+			$this->_category->parent = $term->parent;
2423
+		}
2424
+	}
2425
+
2426
+
2427
+
2428
+	private function _set_empty_category_object()
2429
+	{
2430
+		$this->_category = new stdClass();
2431
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2432
+		$this->_category->id = $this->_category->parent = 0;
2433
+	}
2434
+
2435
+
2436
+
2437
+	protected function _category_list_table()
2438
+	{
2439
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2440
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2441
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2442
+				'add_category',
2443
+				'add_category',
2444
+				array(),
2445
+				'add-new-h2'
2446
+			);
2447
+		$this->display_admin_list_table_page_with_sidebar();
2448
+	}
2449
+
2450
+
2451
+
2452
+	/**
2453
+	 * @param $view
2454
+	 */
2455
+	protected function _category_details($view)
2456
+	{
2457
+		//load formatter helper
2458
+		//load field generator helper
2459
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
2460
+		$this->_set_add_edit_form_tags($route);
2461
+		$this->_set_category_object();
2462
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2463
+		$delete_action = 'delete_category';
2464
+		//custom redirect
2465
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2466
+			array('action' => 'category_list'),
2467
+			$this->_admin_base_url
2468
+		);
2469
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2470
+		//take care of contents
2471
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2472
+		$this->display_admin_page_with_sidebar();
2473
+	}
2474
+
2475
+
2476
+
2477
+	/**
2478
+	 * @return mixed
2479
+	 */
2480
+	protected function _category_details_content()
2481
+	{
2482
+		$editor_args['category_desc'] = array(
2483
+			'type'          => 'wp_editor',
2484
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2485
+			'class'         => 'my_editor_custom',
2486
+			'wpeditor_args' => array('media_buttons' => false),
2487
+		);
2488
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2489
+		$all_terms = get_terms(
2490
+			array('espresso_event_categories'),
2491
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2492
+		);
2493
+		//setup category select for term parents.
2494
+		$category_select_values[] = array(
2495
+			'text' => esc_html__('No Parent', 'event_espresso'),
2496
+			'id'   => 0,
2497
+		);
2498
+		foreach ($all_terms as $term) {
2499
+			$category_select_values[] = array(
2500
+				'text' => $term->name,
2501
+				'id'   => $term->term_id,
2502
+			);
2503
+		}
2504
+		$category_select = EEH_Form_Fields::select_input(
2505
+			'category_parent',
2506
+			$category_select_values,
2507
+			$this->_category->parent
2508
+		);
2509
+		$template_args = array(
2510
+			'category'                 => $this->_category,
2511
+			'category_select'          => $category_select,
2512
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2513
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2514
+			'disable'                  => '',
2515
+			'disabled_message'         => false,
2516
+		);
2517
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2518
+		return EEH_Template::display_template($template, $template_args, true);
2519
+	}
2520
+
2521
+
2522
+
2523
+	protected function _delete_categories()
2524
+	{
2525
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array)$this->_req_data['EVT_CAT_ID']
2526
+			: (array)$this->_req_data['category_id'];
2527
+		foreach ($cat_ids as $cat_id) {
2528
+			$this->_delete_category($cat_id);
2529
+		}
2530
+		//doesn't matter what page we're coming from... we're going to the same place after delete.
2531
+		$query_args = array(
2532
+			'action' => 'category_list',
2533
+		);
2534
+		$this->_redirect_after_action(0, '', '', $query_args);
2535
+	}
2536
+
2537
+
2538
+
2539
+	/**
2540
+	 * @param $cat_id
2541
+	 */
2542
+	protected function _delete_category($cat_id)
2543
+	{
2544
+		$cat_id = absint($cat_id);
2545
+		wp_delete_term($cat_id, 'espresso_event_categories');
2546
+	}
2547
+
2548
+
2549
+
2550
+	/**
2551
+	 * @param $new_category
2552
+	 */
2553
+	protected function _insert_or_update_category($new_category)
2554
+	{
2555
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2556
+		$success = 0; //we already have a success message so lets not send another.
2557
+		if ($cat_id) {
2558
+			$query_args = array(
2559
+				'action'     => 'edit_category',
2560
+				'EVT_CAT_ID' => $cat_id,
2561
+			);
2562
+		} else {
2563
+			$query_args = array('action' => 'add_category');
2564
+		}
2565
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2566
+	}
2567
+
2568
+
2569
+
2570
+	/**
2571
+	 * @param bool $update
2572
+	 * @return bool|mixed|string
2573
+	 */
2574
+	private function _insert_category($update = false)
2575
+	{
2576
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2577
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2578
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2579
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2580
+		if (empty($category_name)) {
2581
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2582
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2583
+			return false;
2584
+		}
2585
+		$term_args = array(
2586
+			'name'        => $category_name,
2587
+			'description' => $category_desc,
2588
+			'parent'      => $category_parent,
2589
+		);
2590
+		//was the category_identifier input disabled?
2591
+		if (isset($this->_req_data['category_identifier'])) {
2592
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2593
+		}
2594
+		$insert_ids = $update
2595
+			? wp_update_term($cat_id, 'espresso_event_categories', $term_args)
2596
+			: wp_insert_term($category_name, 'espresso_event_categories', $term_args);
2597
+		if ( ! is_array($insert_ids)) {
2598
+			$msg = esc_html__(
2599
+				'An error occurred and the category has not been saved to the database.',
2600
+				'event_espresso'
2601
+			);
2602
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2603
+		} else {
2604
+			$cat_id = $insert_ids['term_id'];
2605
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2606
+			EE_Error::add_success($msg);
2607
+		}
2608
+		return $cat_id;
2609
+	}
2610
+
2611
+
2612
+
2613
+	/**
2614
+	 * @param int  $per_page
2615
+	 * @param int  $current_page
2616
+	 * @param bool $count
2617
+	 * @return \EE_Base_Class[]|int
2618
+	 */
2619
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2620
+	{
2621
+		//testing term stuff
2622
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2623
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2624
+		$limit = ($current_page - 1) * $per_page;
2625
+		$where = array('taxonomy' => 'espresso_event_categories');
2626
+		if (isset($this->_req_data['s'])) {
2627
+			$sstr = '%' . $this->_req_data['s'] . '%';
2628
+			$where['OR'] = array(
2629
+				'Term.name'   => array('LIKE', $sstr),
2630
+				'description' => array('LIKE', $sstr),
2631
+			);
2632
+		}
2633
+		$query_params = array(
2634
+			$where,
2635
+			'order_by'   => array($orderby => $order),
2636
+			'limit'      => $limit . ',' . $per_page,
2637
+			'force_join' => array('Term'),
2638
+		);
2639
+		$categories = $count
2640
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2641
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2642
+		return $categories;
2643
+	}
2644
+
2645
+
2646
+
2647
+	/* end category stuff */
2648
+	/**************/
2649 2649
 }
2650 2650
 //end class Events_Admin_Page
Please login to merge, or discard this patch.
Spacing   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -536,11 +536,11 @@  discard block
 block discarded – undo
536 536
     {
537 537
         wp_register_style(
538 538
             'events-admin-css',
539
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
539
+            EVENTS_ASSETS_URL.'events-admin-page.css',
540 540
             array(),
541 541
             EVENT_ESPRESSO_VERSION
542 542
         );
543
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
543
+        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL.'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
544 544
         wp_enqueue_style('events-admin-css');
545 545
         wp_enqueue_style('ee-cat-admin');
546 546
         //todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
@@ -548,7 +548,7 @@  discard block
 block discarded – undo
548 548
         //scripts
549 549
         wp_register_script(
550 550
             'event_editor_js',
551
-            EVENTS_ASSETS_URL . 'event_editor.js',
551
+            EVENTS_ASSETS_URL.'event_editor.js',
552 552
             array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
553 553
             EVENT_ESPRESSO_VERSION,
554 554
             true
@@ -580,7 +580,7 @@  discard block
 block discarded – undo
580 580
         wp_enqueue_style('espresso-ui-theme');
581 581
         wp_register_style(
582 582
             'event-editor-css',
583
-            EVENTS_ASSETS_URL . 'event-editor.css',
583
+            EVENTS_ASSETS_URL.'event-editor.css',
584 584
             array('ee-admin-css'),
585 585
             EVENT_ESPRESSO_VERSION
586 586
         );
@@ -588,7 +588,7 @@  discard block
 block discarded – undo
588 588
         //scripts
589 589
         wp_register_script(
590 590
             'event-datetime-metabox',
591
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
591
+            EVENTS_ASSETS_URL.'event-datetime-metabox.js',
592 592
             array('event_editor_js', 'ee-datepicker'),
593 593
             EVENT_ESPRESSO_VERSION
594 594
         );
@@ -665,7 +665,7 @@  discard block
 block discarded – undo
665 665
             $event = $this->_cpt_model_obj;
666 666
         }
667 667
         // STILL no event?
668
-        if (! $event instanceof EE_Event) {
668
+        if ( ! $event instanceof EE_Event) {
669 669
             return;
670 670
         }
671 671
         $orig_status = $event->status();
@@ -754,7 +754,7 @@  discard block
 block discarded – undo
754 754
                         'Your website\'s timezone is currently set to UTC + 0. We recommend updating your timezone to a city or region near you before you create an event. Your timezone can be updated through the %1$sGeneral Settings%2$s page.',
755 755
                         'event_espresso'
756 756
                     ),
757
-                    '<a href="' . admin_url('options-general.php') . '">',
757
+                    '<a href="'.admin_url('options-general.php').'">',
758 758
                     '</a>'
759 759
                 ),
760 760
                 __FILE__,
@@ -824,31 +824,31 @@  discard block
 block discarded – undo
824 824
         $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
825 825
         $statuses = array(
826 826
             'sold_out_status'  => array(
827
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
827
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::sold_out,
828 828
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
829 829
             ),
830 830
             'active_status'    => array(
831
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
831
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::active,
832 832
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
833 833
             ),
834 834
             'upcoming_status'  => array(
835
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
835
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::upcoming,
836 836
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
837 837
             ),
838 838
             'postponed_status' => array(
839
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
839
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::postponed,
840 840
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
841 841
             ),
842 842
             'cancelled_status' => array(
843
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
843
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::cancelled,
844 844
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
845 845
             ),
846 846
             'expired_status'   => array(
847
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
847
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::expired,
848 848
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
849 849
             ),
850 850
             'inactive_status'  => array(
851
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
851
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::inactive,
852 852
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
853 853
             ),
854 854
         );
@@ -912,7 +912,7 @@  discard block
 block discarded – undo
912 912
     {
913 913
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
914 914
         $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
915
-            ? (array)$this->_template_args['after_list_table']
915
+            ? (array) $this->_template_args['after_list_table']
916 916
             : array();
917 917
         $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
918 918
                                                                               . EEH_Template::get_button_or_link(
@@ -921,7 +921,7 @@  discard block
 block discarded – undo
921 921
                 'button'
922 922
             );
923 923
         $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
924
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
924
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
925 925
                 'create_new',
926 926
                 'add',
927 927
                 array(),
@@ -1051,7 +1051,7 @@  discard block
 block discarded – undo
1051 1051
      */
1052 1052
     protected function _default_venue_update(\EE_Event $evtobj, $data)
1053 1053
     {
1054
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1054
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1055 1055
         $venue_model = EE_Registry::instance()->load_model('Venue');
1056 1056
         $rows_affected = null;
1057 1057
         $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
@@ -1175,7 +1175,7 @@  discard block
 block discarded – undo
1175 1175
             if (empty($tkt['TKT_start_date'])) {
1176 1176
                 //let's use now in the set timezone.
1177 1177
                 $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1178
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1178
+                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0].' '.$incoming_date_formats[1]);
1179 1179
             }
1180 1180
             if (empty($tkt['TKT_end_date'])) {
1181 1181
                 //use the start date of the first datetime
@@ -1464,7 +1464,7 @@  discard block
 block discarded – undo
1464 1464
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1465 1465
         // load template
1466 1466
         EEH_Template::display_template(
1467
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1467
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1468 1468
             $publish_box_extra_args
1469 1469
         );
1470 1470
     }
@@ -1591,7 +1591,7 @@  discard block
 block discarded – undo
1591 1591
         );
1592 1592
         $template = apply_filters(
1593 1593
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1594
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1594
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1595 1595
         );
1596 1596
         EEH_Template::display_template($template, $template_args);
1597 1597
     }
@@ -1610,7 +1610,7 @@  discard block
 block discarded – undo
1610 1610
     private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1611 1611
     {
1612 1612
         $template_args = array(
1613
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1613
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1614 1614
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1615 1615
                 : '',
1616 1616
             'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
@@ -1664,7 +1664,7 @@  discard block
 block discarded – undo
1664 1664
         $template_args = array_merge($template_args, $price_args);
1665 1665
         $template = apply_filters(
1666 1666
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1667
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1667
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1668 1668
             $ticket
1669 1669
         );
1670 1670
         return EEH_Template::display_template($template, $template_args, true);
@@ -1716,7 +1716,7 @@  discard block
 block discarded – undo
1716 1716
             $default_reg_status_values
1717 1717
         );
1718 1718
         EEH_Template::display_template(
1719
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1719
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1720 1720
             $template_args
1721 1721
         );
1722 1722
     }
@@ -1739,7 +1739,7 @@  discard block
 block discarded – undo
1739 1739
     {
1740 1740
         $EEME = $this->_event_model();
1741 1741
         $offset = ($current_page - 1) * $per_page;
1742
-        $limit = $count ? null : $offset . ',' . $per_page;
1742
+        $limit = $count ? null : $offset.','.$per_page;
1743 1743
         $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1744 1744
         $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1745 1745
         if (isset($this->_req_data['month_range'])) {
@@ -1776,7 +1776,7 @@  discard block
 block discarded – undo
1776 1776
         $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1777 1777
         if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1778 1778
             $DateTime = new DateTime(
1779
-                $year_r . '-' . $month_r . '-01 00:00:00',
1779
+                $year_r.'-'.$month_r.'-01 00:00:00',
1780 1780
                 new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1781 1781
             );
1782 1782
             $start = $DateTime->format(implode(' ', $start_formats));
@@ -1822,7 +1822,7 @@  discard block
 block discarded – undo
1822 1822
         }
1823 1823
         //search query handling
1824 1824
         if (isset($this->_req_data['s'])) {
1825
-            $search_string = '%' . $this->_req_data['s'] . '%';
1825
+            $search_string = '%'.$this->_req_data['s'].'%';
1826 1826
             $where['OR'] = array(
1827 1827
                 'EVT_name'       => array('LIKE', $search_string),
1828 1828
                 'EVT_desc'       => array('LIKE', $search_string),
@@ -1956,7 +1956,7 @@  discard block
 block discarded – undo
1956 1956
         if ( ! empty($event_status)) {
1957 1957
             $success = true;
1958 1958
             //determine the event id and set to array.
1959
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
1959
+            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
1960 1960
             // loop thru events
1961 1961
             foreach ($EVT_IDs as $EVT_ID) {
1962 1962
                 if ($EVT_ID = absint($EVT_ID)) {
@@ -2104,7 +2104,7 @@  discard block
 block discarded – undo
2104 2104
         // get list of events with no prices
2105 2105
         $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2106 2106
         //determine the event id and set to array.
2107
-        $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
2107
+        $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2108 2108
         // loop thru events
2109 2109
         foreach ($EVT_IDs as $EVT_ID) {
2110 2110
             $EVT_ID = absint($EVT_ID);
@@ -2324,7 +2324,7 @@  discard block
 block discarded – undo
2324 2324
                                 'html_label_text' => esc_html__(
2325 2325
                                     'Default Maximum Tickets Allowed Per Order:',
2326 2326
                                     'event_espresso'
2327
-                                ) . EEH_Template::get_help_tab_link(
2327
+                                ).EEH_Template::get_help_tab_link(
2328 2328
                                     'default_maximum_tickets_help_tab"'
2329 2329
                                     ),
2330 2330
                                 'html_help_text' => esc_html__(
@@ -2386,10 +2386,10 @@  discard block
 block discarded – undo
2386 2386
                                                . 'caffeinated_template_features.jpg" alt="'
2387 2387
                                                . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2388 2388
                                                . '" />';
2389
-        $this->_template_args['preview_text'] = '<strong>' . esc_html__(
2389
+        $this->_template_args['preview_text'] = '<strong>'.esc_html__(
2390 2390
                 '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.',
2391 2391
                 'event_espresso'
2392
-            ) . '</strong>';
2392
+            ).'</strong>';
2393 2393
         $this->display_admin_caf_preview_page('template_settings_tab');
2394 2394
     }
2395 2395
 
@@ -2438,7 +2438,7 @@  discard block
 block discarded – undo
2438 2438
     {
2439 2439
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2440 2440
         $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2441
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2441
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
2442 2442
                 'add_category',
2443 2443
                 'add_category',
2444 2444
                 array(),
@@ -2514,7 +2514,7 @@  discard block
 block discarded – undo
2514 2514
             'disable'                  => '',
2515 2515
             'disabled_message'         => false,
2516 2516
         );
2517
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2517
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2518 2518
         return EEH_Template::display_template($template, $template_args, true);
2519 2519
     }
2520 2520
 
@@ -2522,8 +2522,8 @@  discard block
 block discarded – undo
2522 2522
 
2523 2523
     protected function _delete_categories()
2524 2524
     {
2525
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array)$this->_req_data['EVT_CAT_ID']
2526
-            : (array)$this->_req_data['category_id'];
2525
+        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2526
+            : (array) $this->_req_data['category_id'];
2527 2527
         foreach ($cat_ids as $cat_id) {
2528 2528
             $this->_delete_category($cat_id);
2529 2529
         }
@@ -2624,7 +2624,7 @@  discard block
 block discarded – undo
2624 2624
         $limit = ($current_page - 1) * $per_page;
2625 2625
         $where = array('taxonomy' => 'espresso_event_categories');
2626 2626
         if (isset($this->_req_data['s'])) {
2627
-            $sstr = '%' . $this->_req_data['s'] . '%';
2627
+            $sstr = '%'.$this->_req_data['s'].'%';
2628 2628
             $where['OR'] = array(
2629 2629
                 'Term.name'   => array('LIKE', $sstr),
2630 2630
                 'description' => array('LIKE', $sstr),
@@ -2633,7 +2633,7 @@  discard block
 block discarded – undo
2633 2633
         $query_params = array(
2634 2634
             $where,
2635 2635
             'order_by'   => array($orderby => $order),
2636
-            'limit'      => $limit . ',' . $per_page,
2636
+            'limit'      => $limit.','.$per_page,
2637 2637
             'force_join' => array('Term'),
2638 2638
         );
2639 2639
         $categories = $count
Please login to merge, or discard this patch.