Completed
Branch FET-10416-autoload-b4-bootstra... (e94275)
by
unknown
88:30 queued 75:54
created
core/EE_Capabilities.core.php 1 patch
Indentation   +1388 added lines, -1388 removed lines patch added patch discarded remove patch
@@ -18,1000 +18,1000 @@  discard block
 block discarded – undo
18 18
 final class EE_Capabilities extends EE_Base
19 19
 {
20 20
 
21
-    /**
22
-     * the name of the wp option used to store caps previously initialized
23
-     */
24
-    const option_name = 'ee_caps_initialized';
25
-
26
-    /**
27
-     * instance of EE_Capabilities object
28
-     *
29
-     * @var EE_Capabilities
30
-     */
31
-    private static $_instance;
32
-
33
-
34
-    /**
35
-     * This is a map of caps that correspond to a default WP_Role.
36
-     * Array is indexed by Role and values are ee capabilities.
37
-     *
38
-     * @since 4.5.0
39
-     *
40
-     * @var array
41
-     */
42
-    private $capabilities_map = array();
43
-
44
-    /**
45
-     * This used to hold an array of EE_Meta_Capability_Map objects
46
-     * that define the granular capabilities mapped to for a user depending on context.
47
-     *
48
-     * @var EE_Meta_Capability_Map[]
49
-     */
50
-    private $_meta_caps = array();
51
-
52
-    /**
53
-     * The internal $capabilities_map needs to be initialized before it can be used.
54
-     * This flag tracks whether that has happened or not.
55
-     * But for this to work, we need three states to indicate:
56
-     *      initialization has not occurred at all
57
-     *      initialization has started but is not complete
58
-     *      initialization is complete
59
-     * The reason this is needed is because the addCaps() method
60
-     * normally requires the $capabilities_map to be initialized,
61
-     * but is also used during the initialization process.
62
-     * So:
63
-     *      If initialized === null, init_caps() will be called before any other methods will run.
64
-     *      If initialized === false, then init_caps() is in the process of running it's logic.
65
-     *      If initialized === true, then init_caps() has completed the initialization process.
66
-     *
67
-     * @var boolean|null $initialized
68
-     */
69
-    private $initialized;
70
-
71
-    /**
72
-     * @var boolean $reset
73
-     */
74
-    private $reset = false;
75
-
76
-
77
-
78
-    /**
79
-     * singleton method used to instantiate class object
80
-     *
81
-     * @since 4.5.0
82
-     *
83
-     * @return EE_Capabilities
84
-     */
85
-    public static function instance()
86
-    {
87
-        //check if instantiated, and if not do so.
88
-        if (! self::$_instance instanceof EE_Capabilities) {
89
-            self::$_instance = new self();
90
-        }
91
-        return self::$_instance;
92
-    }
93
-
94
-
95
-
96
-    /**
97
-     * private constructor
98
-     *
99
-     * @since 4.5.0
100
-     */
101
-    private function __construct()
102
-    {
103
-    }
104
-
105
-
106
-
107
-    /**
108
-     * This delays the initialization of the capabilities class until EE_System core is loaded and ready.
109
-     *
110
-     * @param bool $reset allows for resetting the default capabilities saved on roles.  Note that this doesn't
111
-     *                    actually REMOVE any capabilities from existing roles, it just resaves defaults roles and
112
-     *                    ensures that they are up to date.
113
-     *
114
-     * @since 4.5.0
115
-     * @return bool
116
-     * @throws EE_Error
117
-     */
118
-    public function init_caps($reset = false)
119
-    {
120
-        if(! EE_Maintenance_Mode::instance()->models_can_query()){
121
-            return false;
122
-        }
123
-        $this->reset = filter_var($reset, FILTER_VALIDATE_BOOLEAN);
124
-        // if reset, then completely delete the cache option and clear the $capabilities_map property.
125
-        if ($this->reset) {
126
-            $this->initialized = null;
127
-            $this->capabilities_map = array();
128
-            delete_option(self::option_name);
129
-        }
130
-        if ($this->initialized === null) {
131
-            $this->initialized = false;
132
-            do_action(
133
-                'AHEE__EE_Capabilities__init_caps__before_initialization',
134
-                $this->reset
135
-            );
136
-            $this->addCaps($this->_init_caps_map());
137
-            $this->_set_meta_caps();
138
-            do_action(
139
-                'AHEE__EE_Capabilities__init_caps__after_initialization',
140
-                $this->capabilities_map
141
-            );
142
-            $this->initialized = true;
143
-        }
144
-        // reset $this->reset so that it's not stuck on true if init_caps() gets called again
145
-        $this->reset = false;
146
-        return true;
147
-    }
148
-
149
-
150
-
151
-
152
-    /**
153
-     * This sets the meta caps property.
154
-     *
155
-     * @since 4.5.0
156
-     * @return void
157
-     * @throws EE_Error
158
-     */
159
-    private function _set_meta_caps()
160
-    {
161
-        // get default meta caps and filter the returned array
162
-        $this->_meta_caps = apply_filters(
163
-            'FHEE__EE_Capabilities___set_meta_caps__meta_caps',
164
-            $this->_get_default_meta_caps_array()
165
-        );
166
-        //add filter for map_meta_caps but only if models can query.
167
-        if (! has_filter('map_meta_cap', array($this, 'map_meta_caps'))) {
168
-            add_filter('map_meta_cap', array($this, 'map_meta_caps'), 10, 4);
169
-        }
170
-    }
171
-
172
-
173
-
174
-    /**
175
-     * This builds and returns the default meta_caps array only once.
176
-     *
177
-     * @since  4.8.28.rc.012
178
-     * @return array
179
-     * @throws EE_Error
180
-     */
181
-    private function _get_default_meta_caps_array()
182
-    {
183
-        static $default_meta_caps = array();
184
-        // make sure we're only ever initializing the default _meta_caps array once if it's empty.
185
-        if (empty($default_meta_caps)) {
186
-            $default_meta_caps = array(
187
-                //edits
188
-                new EE_Meta_Capability_Map_Edit(
189
-                    'ee_edit_event',
190
-                    array('Event', 'ee_edit_published_events', 'ee_edit_others_events', 'ee_edit_private_events')
191
-                ),
192
-                new EE_Meta_Capability_Map_Edit(
193
-                    'ee_edit_venue',
194
-                    array('Venue', 'ee_edit_published_venues', 'ee_edit_others_venues', 'ee_edit_private_venues')
195
-                ),
196
-                new EE_Meta_Capability_Map_Edit(
197
-                    'ee_edit_registration',
198
-                    array('Registration', '', 'ee_edit_others_registrations', '')
199
-                ),
200
-                new EE_Meta_Capability_Map_Edit(
201
-                    'ee_edit_checkin',
202
-                    array('Registration', '', 'ee_edit_others_checkins', '')
203
-                ),
204
-                new EE_Meta_Capability_Map_Messages_Cap(
205
-                    'ee_edit_message',
206
-                    array('Message_Template_Group', '', 'ee_edit_others_messages', 'ee_edit_global_messages')
207
-                ),
208
-                new EE_Meta_Capability_Map_Edit(
209
-                    'ee_edit_default_ticket',
210
-                    array('Ticket', '', 'ee_edit_others_default_tickets', '')
211
-                ),
212
-                new EE_Meta_Capability_Map_Registration_Form_Cap(
213
-                    'ee_edit_question',
214
-                    array('Question', '', '', 'ee_edit_system_questions')
215
-                ),
216
-                new EE_Meta_Capability_Map_Registration_Form_Cap(
217
-                    'ee_edit_question_group',
218
-                    array('Question_Group', '', '', 'ee_edit_system_question_groups')
219
-                ),
220
-                new EE_Meta_Capability_Map_Edit(
221
-                    'ee_edit_payment_method',
222
-                    array('Payment_Method', '', 'ee_edit_others_payment_methods', '')
223
-                ),
224
-                //reads
225
-                new EE_Meta_Capability_Map_Read(
226
-                    'ee_read_event',
227
-                    array('Event', '', 'ee_read_others_events', 'ee_read_private_events')
228
-                ),
229
-                new EE_Meta_Capability_Map_Read(
230
-                    'ee_read_venue',
231
-                    array('Venue', '', 'ee_read_others_venues', 'ee_read_private_venues')
232
-                ),
233
-                new EE_Meta_Capability_Map_Read(
234
-                    'ee_read_registration',
235
-                    array('Registration', '', 'ee_read_others_registrations', '')
236
-                ),
237
-                new EE_Meta_Capability_Map_Read(
238
-                    'ee_read_checkin',
239
-                    array('Registration', '', 'ee_read_others_checkins', '')
240
-                ),
241
-                new EE_Meta_Capability_Map_Messages_Cap(
242
-                    'ee_read_message',
243
-                    array('Message_Template_Group', '', 'ee_read_others_messages', 'ee_read_global_messages')
244
-                ),
245
-                new EE_Meta_Capability_Map_Read(
246
-                    'ee_read_default_ticket',
247
-                    array('Ticket', '', 'ee_read_others_default_tickets', '')
248
-                ),
249
-                new EE_Meta_Capability_Map_Read(
250
-                    'ee_read_payment_method',
251
-                    array('Payment_Method', '', 'ee_read_others_payment_methods', '')
252
-                ),
253
-                //deletes
254
-                new EE_Meta_Capability_Map_Delete(
255
-                    'ee_delete_event',
256
-                    array(
257
-                        'Event',
258
-                        'ee_delete_published_events',
259
-                        'ee_delete_others_events',
260
-                        'ee_delete_private_events',
261
-                    )
262
-                ),
263
-                new EE_Meta_Capability_Map_Delete(
264
-                    'ee_delete_venue',
265
-                    array(
266
-                        'Venue',
267
-                        'ee_delete_published_venues',
268
-                        'ee_delete_others_venues',
269
-                        'ee_delete_private_venues',
270
-                    )
271
-                ),
272
-                new EE_Meta_Capability_Map_Delete(
273
-                    'ee_delete_registration',
274
-                    array('Registration', '', 'ee_delete_others_registrations', '')
275
-                ),
276
-                new EE_Meta_Capability_Map_Delete(
277
-                    'ee_delete_checkin',
278
-                    array('Registration', '', 'ee_delete_others_checkins', '')
279
-                ),
280
-                new EE_Meta_Capability_Map_Messages_Cap(
281
-                    'ee_delete_message',
282
-                    array('Message_Template_Group', '', 'ee_delete_others_messages', 'ee_delete_global_messages')
283
-                ),
284
-                new EE_Meta_Capability_Map_Delete(
285
-                    'ee_delete_default_ticket',
286
-                    array('Ticket', '', 'ee_delete_others_default_tickets', '')
287
-                ),
288
-                new EE_Meta_Capability_Map_Registration_Form_Cap(
289
-                    'ee_delete_question',
290
-                    array('Question', '', '', 'delete_system_questions')
291
-                ),
292
-                new EE_Meta_Capability_Map_Registration_Form_Cap(
293
-                    'ee_delete_question_group',
294
-                    array('Question_Group', '', '', 'delete_system_question_groups')
295
-                ),
296
-                new EE_Meta_Capability_Map_Delete(
297
-                    'ee_delete_payment_method',
298
-                    array('Payment_Method', '', 'ee_delete_others_payment_methods', '')
299
-                ),
300
-            );
301
-        }
302
-        return $default_meta_caps;
303
-    }
304
-
305
-
306
-
307
-    /**
308
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
309
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
310
-     *
311
-     * The actual logic is carried out by implementer classes in their definition of _map_meta_caps.
312
-     *
313
-     * @since 4.5.0
314
-     * @see   wp-includes/capabilities.php
315
-     *
316
-     * @param array  $caps    actual users capabilities
317
-     * @param string $cap     initial capability name that is being checked (the "map" key)
318
-     * @param int    $user_id The user id
319
-     * @param array  $args    Adds context to the cap. Typically the object ID.
320
-     * @return array actual users capabilities
321
-     * @throws EE_Error
322
-     */
323
-    public function map_meta_caps($caps, $cap, $user_id, $args)
324
-    {
325
-        if (did_action('AHEE__EE_System__load_espresso_addons__complete')) {
326
-            //loop through our _meta_caps array
327
-            foreach ($this->_meta_caps as $meta_map) {
328
-                if (! $meta_map instanceof EE_Meta_Capability_Map) {
329
-                    continue;
330
-                }
331
-                // don't load models if there is no object ID in the args
332
-                if (! empty($args[0])) {
333
-                    $meta_map->ensure_is_model();
334
-                }
335
-                $caps = $meta_map->map_meta_caps($caps, $cap, $user_id, $args);
336
-            }
337
-        }
338
-        return $caps;
339
-    }
340
-
341
-
342
-
343
-    /**
344
-     * This sets up and returns the initial capabilities map for Event Espresso
345
-     * Note this array is filtered.
346
-     * It is assumed that all available EE capabilities are assigned to the administrator role.
347
-     *
348
-     * @since 4.5.0
349
-     *
350
-     * @return array
351
-     */
352
-    private function _init_caps_map()
353
-    {
354
-        return apply_filters(
355
-            'FHEE__EE_Capabilities__init_caps_map__caps',
356
-            array(
357
-                'administrator'           => array(
358
-                    //basic access
359
-                    'ee_read_ee',
360
-                    //gateways
361
-                    /**
362
-                     * note that with payment method capabilities, although we've implemented
363
-                     * capability mapping which will be used for accessing payment methods owned by
364
-                     * other users.  This is not fully implemented yet in the payment method ui.
365
-                     * Currently only the "plural" caps are in active use.
366
-                     * (Specific payment method caps are in use as well).
367
-                     **/
368
-                    'ee_manage_gateways',
369
-                    'ee_read_payment_methods',
370
-                    'ee_read_others_payment_methods',
371
-                    'ee_edit_payment_methods',
372
-                    'ee_edit_others_payment_methods',
373
-                    'ee_delete_payment_methods',
374
-                    //events
375
-                    'ee_publish_events',
376
-                    'ee_read_private_events',
377
-                    'ee_read_others_events',
378
-                    'ee_read_events',
379
-                    'ee_edit_events',
380
-                    'ee_edit_published_events',
381
-                    'ee_edit_others_events',
382
-                    'ee_edit_private_events',
383
-                    'ee_delete_published_events',
384
-                    'ee_delete_private_events',
385
-                    'ee_delete_events',
386
-                    'ee_delete_others_events',
387
-                    //event categories
388
-                    'ee_manage_event_categories',
389
-                    'ee_edit_event_category',
390
-                    'ee_delete_event_category',
391
-                    'ee_assign_event_category',
392
-                    //venues
393
-                    'ee_publish_venues',
394
-                    'ee_read_venues',
395
-                    'ee_read_others_venues',
396
-                    'ee_read_private_venues',
397
-                    'ee_edit_venues',
398
-                    'ee_edit_others_venues',
399
-                    'ee_edit_published_venues',
400
-                    'ee_edit_private_venues',
401
-                    'ee_delete_venues',
402
-                    'ee_delete_others_venues',
403
-                    'ee_delete_private_venues',
404
-                    'ee_delete_published_venues',
405
-                    //venue categories
406
-                    'ee_manage_venue_categories',
407
-                    'ee_edit_venue_category',
408
-                    'ee_delete_venue_category',
409
-                    'ee_assign_venue_category',
410
-                    //contacts
411
-                    'ee_read_contacts',
412
-                    'ee_edit_contacts',
413
-                    'ee_delete_contacts',
414
-                    //registrations
415
-                    'ee_read_registrations',
416
-                    'ee_read_others_registrations',
417
-                    'ee_edit_registrations',
418
-                    'ee_edit_others_registrations',
419
-                    'ee_delete_registrations',
420
-                    //checkins
421
-                    'ee_read_others_checkins',
422
-                    'ee_read_checkins',
423
-                    'ee_edit_checkins',
424
-                    'ee_edit_others_checkins',
425
-                    'ee_delete_checkins',
426
-                    'ee_delete_others_checkins',
427
-                    //transactions && payments
428
-                    'ee_read_transaction',
429
-                    'ee_read_transactions',
430
-                    'ee_edit_payments',
431
-                    'ee_delete_payments',
432
-                    //messages
433
-                    'ee_read_messages',
434
-                    'ee_read_others_messages',
435
-                    'ee_read_global_messages',
436
-                    'ee_edit_global_messages',
437
-                    'ee_edit_messages',
438
-                    'ee_edit_others_messages',
439
-                    'ee_delete_messages',
440
-                    'ee_delete_others_messages',
441
-                    'ee_delete_global_messages',
442
-                    'ee_send_message',
443
-                    //tickets
444
-                    'ee_read_default_tickets',
445
-                    'ee_read_others_default_tickets',
446
-                    'ee_edit_default_tickets',
447
-                    'ee_edit_others_default_tickets',
448
-                    'ee_delete_default_tickets',
449
-                    'ee_delete_others_default_tickets',
450
-                    //prices
451
-                    'ee_edit_default_price',
452
-                    'ee_edit_default_prices',
453
-                    'ee_delete_default_price',
454
-                    'ee_delete_default_prices',
455
-                    'ee_edit_default_price_type',
456
-                    'ee_edit_default_price_types',
457
-                    'ee_delete_default_price_type',
458
-                    'ee_delete_default_price_types',
459
-                    'ee_read_default_prices',
460
-                    'ee_read_default_price_types',
461
-                    //registration form
462
-                    'ee_edit_questions',
463
-                    'ee_edit_system_questions',
464
-                    'ee_read_questions',
465
-                    'ee_delete_questions',
466
-                    'ee_edit_question_groups',
467
-                    'ee_read_question_groups',
468
-                    'ee_edit_system_question_groups',
469
-                    'ee_delete_question_groups',
470
-                    //event_type taxonomy
471
-                    'ee_assign_event_type',
472
-                    'ee_manage_event_types',
473
-                    'ee_edit_event_type',
474
-                    'ee_delete_event_type',
475
-                ),
476
-                'ee_events_administrator' => array(
477
-                    //core wp caps
478
-                    'read',
479
-                    'read_private_pages',
480
-                    'read_private_posts',
481
-                    'edit_users',
482
-                    'edit_posts',
483
-                    'edit_pages',
484
-                    'edit_published_posts',
485
-                    'edit_published_pages',
486
-                    'edit_private_pages',
487
-                    'edit_private_posts',
488
-                    'edit_others_posts',
489
-                    'edit_others_pages',
490
-                    'publish_posts',
491
-                    'publish_pages',
492
-                    'delete_posts',
493
-                    'delete_pages',
494
-                    'delete_private_pages',
495
-                    'delete_private_posts',
496
-                    'delete_published_pages',
497
-                    'delete_published_posts',
498
-                    'delete_others_posts',
499
-                    'delete_others_pages',
500
-                    'manage_categories',
501
-                    'manage_links',
502
-                    'moderate_comments',
503
-                    'unfiltered_html',
504
-                    'upload_files',
505
-                    'export',
506
-                    'import',
507
-                    'list_users',
508
-                    'level_1', //required if user with this role shows up in author dropdowns
509
-                    //basic ee access
510
-                    'ee_read_ee',
511
-                    //events
512
-                    'ee_publish_events',
513
-                    'ee_read_private_events',
514
-                    'ee_read_others_events',
515
-                    'ee_read_event',
516
-                    'ee_read_events',
517
-                    'ee_edit_event',
518
-                    'ee_edit_events',
519
-                    'ee_edit_published_events',
520
-                    'ee_edit_others_events',
521
-                    'ee_edit_private_events',
522
-                    'ee_delete_published_events',
523
-                    'ee_delete_private_events',
524
-                    'ee_delete_event',
525
-                    'ee_delete_events',
526
-                    'ee_delete_others_events',
527
-                    //event categories
528
-                    'ee_manage_event_categories',
529
-                    'ee_edit_event_category',
530
-                    'ee_delete_event_category',
531
-                    'ee_assign_event_category',
532
-                    //venues
533
-                    'ee_publish_venues',
534
-                    'ee_read_venue',
535
-                    'ee_read_venues',
536
-                    'ee_read_others_venues',
537
-                    'ee_read_private_venues',
538
-                    'ee_edit_venue',
539
-                    'ee_edit_venues',
540
-                    'ee_edit_others_venues',
541
-                    'ee_edit_published_venues',
542
-                    'ee_edit_private_venues',
543
-                    'ee_delete_venue',
544
-                    'ee_delete_venues',
545
-                    'ee_delete_others_venues',
546
-                    'ee_delete_private_venues',
547
-                    'ee_delete_published_venues',
548
-                    //venue categories
549
-                    'ee_manage_venue_categories',
550
-                    'ee_edit_venue_category',
551
-                    'ee_delete_venue_category',
552
-                    'ee_assign_venue_category',
553
-                    //contacts
554
-                    'ee_read_contacts',
555
-                    'ee_edit_contacts',
556
-                    'ee_delete_contacts',
557
-                    //registrations
558
-                    'ee_read_registrations',
559
-                    'ee_read_others_registrations',
560
-                    'ee_edit_registration',
561
-                    'ee_edit_registrations',
562
-                    'ee_edit_others_registrations',
563
-                    'ee_delete_registration',
564
-                    'ee_delete_registrations',
565
-                    //checkins
566
-                    'ee_read_others_checkins',
567
-                    'ee_read_checkins',
568
-                    'ee_edit_checkins',
569
-                    'ee_edit_others_checkins',
570
-                    'ee_delete_checkins',
571
-                    'ee_delete_others_checkins',
572
-                    //transactions && payments
573
-                    'ee_read_transaction',
574
-                    'ee_read_transactions',
575
-                    'ee_edit_payments',
576
-                    'ee_delete_payments',
577
-                    //messages
578
-                    'ee_read_messages',
579
-                    'ee_read_others_messages',
580
-                    'ee_read_global_messages',
581
-                    'ee_edit_global_messages',
582
-                    'ee_edit_messages',
583
-                    'ee_edit_others_messages',
584
-                    'ee_delete_messages',
585
-                    'ee_delete_others_messages',
586
-                    'ee_delete_global_messages',
587
-                    'ee_send_message',
588
-                    //tickets
589
-                    'ee_read_default_tickets',
590
-                    'ee_read_others_default_tickets',
591
-                    'ee_edit_default_tickets',
592
-                    'ee_edit_others_default_tickets',
593
-                    'ee_delete_default_tickets',
594
-                    'ee_delete_others_default_tickets',
595
-                    //prices
596
-                    'ee_edit_default_price',
597
-                    'ee_edit_default_prices',
598
-                    'ee_delete_default_price',
599
-                    'ee_delete_default_prices',
600
-                    'ee_edit_default_price_type',
601
-                    'ee_edit_default_price_types',
602
-                    'ee_delete_default_price_type',
603
-                    'ee_delete_default_price_types',
604
-                    'ee_read_default_prices',
605
-                    'ee_read_default_price_types',
606
-                    //registration form
607
-                    'ee_edit_questions',
608
-                    'ee_edit_system_questions',
609
-                    'ee_read_questions',
610
-                    'ee_delete_questions',
611
-                    'ee_edit_question_groups',
612
-                    'ee_read_question_groups',
613
-                    'ee_edit_system_question_groups',
614
-                    'ee_delete_question_groups',
615
-                    //event_type taxonomy
616
-                    'ee_assign_event_type',
617
-                    'ee_manage_event_types',
618
-                    'ee_edit_event_type',
619
-                    'ee_delete_event_type',
620
-                )
621
-            )
622
-        );
623
-    }
624
-
625
-
626
-
627
-    /**
628
-     * @return bool
629
-     * @throws EE_Error
630
-     */
631
-    private function setupCapabilitiesMap()
632
-    {
633
-        // if the initialization process hasn't even started, then we need to call init_caps()
634
-        if($this->initialized === null) {
635
-            return $this->init_caps();
636
-        }
637
-        // unless resetting, get caps from db if we haven't already
638
-        $this->capabilities_map = $this->reset || ! empty($this->capabilities_map)
639
-            ? $this->capabilities_map
640
-            : get_option(self::option_name, array());
641
-        return true;
642
-    }
643
-
644
-
645
-
646
-    /**
647
-     * @param bool $update
648
-     * @return bool
649
-     */
650
-    private function updateCapabilitiesMap($update = true)
651
-    {
652
-        return $update ? update_option(self::option_name, $this->capabilities_map) : false;
653
-    }
654
-
655
-
656
-
657
-    /**
658
-     * Adds capabilities to roles.
659
-     *
660
-     * @since 4.9.42
661
-     * @param array $capabilities_to_add array of capabilities to add, indexed by roles.
662
-     *                                   Note that this should ONLY be called on activation hook
663
-     *                                   otherwise the caps will be added on every request.
664
-     * @return bool
665
-     * @throws \EE_Error
666
-     */
667
-    public function addCaps(array $capabilities_to_add)
668
-    {
669
-        // don't do anything if the capabilities map can not be initialized
670
-        if (! $this->setupCapabilitiesMap()) {
671
-            return false;
672
-        }
673
-        // and filter the array so others can get in on the fun during resets
674
-        $capabilities_to_add = apply_filters(
675
-            'FHEE__EE_Capabilities__addCaps__capabilities_to_add',
676
-            $capabilities_to_add,
677
-            $this->reset,
678
-            $this->capabilities_map
679
-        );
680
-        $update_capabilities_map = false;
681
-        // if not reset, see what caps are new for each role. if they're new, add them.
682
-        foreach ($capabilities_to_add as $role => $caps_for_role) {
683
-            if (is_array($caps_for_role)) {
684
-                foreach ($caps_for_role as $cap) {
685
-                    if (
686
-                        ! $this->capHasBeenAddedToRole($role, $cap)
687
-                        && $this->add_cap_to_role($role, $cap, true, false)
688
-                    ) {
689
-                        $update_capabilities_map = true;
690
-                    }
691
-                }
692
-            }
693
-        }
694
-        // now let's just save the cap that has been set but only if there's been a change.
695
-        $updated = $this->updateCapabilitiesMap($update_capabilities_map);
696
-        $this->flushWpUser($updated);
697
-        do_action('AHEE__EE_Capabilities__addCaps__complete', $this->capabilities_map, $updated);
698
-        return $updated;
699
-    }
700
-
701
-
702
-
703
-    /**
704
-     * Loops through the capabilities map and removes the role caps specified by the incoming array
705
-     *
706
-     * @param array $caps_map map of capabilities to be removed (indexed by roles)
707
-     * @return bool
708
-     * @throws \EE_Error
709
-     */
710
-    public function removeCaps($caps_map)
711
-    {
712
-        // don't do anything if the capabilities map can not be initialized
713
-        if (! $this->setupCapabilitiesMap()) {
714
-            return false;
715
-        }
716
-        $update_capabilities_map = false;
717
-        foreach ($caps_map as $role => $caps_for_role) {
718
-            if (is_array($caps_for_role)) {
719
-                foreach ($caps_for_role as $cap) {
720
-                    if ($this->capHasBeenAddedToRole($role, $cap)
721
-                        && $this->remove_cap_from_role($role, $cap, false)
722
-                    ) {
723
-                        $update_capabilities_map = true;
724
-                    }
725
-                }
726
-            }
727
-        }
728
-        // maybe resave the caps
729
-        $updated = $this->updateCapabilitiesMap($update_capabilities_map);
730
-        $this->flushWpUser($updated);
731
-        return $updated;
732
-    }
733
-
734
-
735
-    /**
736
-     * This ensures that the WP User object cached on the $current_user global in WP has the latest capabilities from
737
-     * the roles on that user.
738
-     *
739
-     * @param bool $flush  Default is to flush the WP_User object.  If false, then this method effectively does nothing.
740
-     */
741
-    private function flushWpUser($flush = true)
742
-    {
743
-        if ($flush) {
744
-            $user = wp_get_current_user();
745
-            if ($user instanceof WP_User) {
746
-                $user->get_role_caps();
747
-            }
748
-        }
749
-    }
750
-
751
-
752
-
753
-    /**
754
-     * This method sets a capability on a role.  Note this should only be done on activation, or if you have something
755
-     * specific to prevent the cap from being added on every page load (adding caps are persistent to the db). Note.
756
-     * this is a wrapper for $wp_role->add_cap()
757
-     *
758
-     * @see   wp-includes/capabilities.php
759
-     * @since 4.5.0
760
-     * @param string|WP_Role $role  A WordPress role the capability is being added to
761
-     * @param string         $cap   The capability being added to the role
762
-     * @param bool           $grant Whether to grant access to this cap on this role.
763
-     * @param bool           $update_capabilities_map
764
-     * @return bool
765
-     * @throws \EE_Error
766
-     */
767
-    public function add_cap_to_role($role, $cap, $grant = true, $update_capabilities_map = true)
768
-    {
769
-        // capture incoming value for $role because we may need it to create a new WP_Role
770
-        $orig_role = $role;
771
-        $role = $role instanceof WP_Role ? $role : get_role($role);
772
-        //if the role isn't available then we create it.
773
-        if (! $role instanceof WP_Role) {
774
-            // if a plugin wants to create a specific role name then they should create the role before
775
-            // EE_Capabilities does.  Otherwise this function will create the role name from the slug:
776
-            // - removes any `ee_` namespacing from the start of the slug.
777
-            // - replaces `_` with ` ` (empty space).
778
-            // - sentence case on the resulting string.
779
-            $role_label = ucwords(str_replace(array('ee_', '_'), array('', ' '), $orig_role));
780
-            $role = add_role($orig_role, $role_label);
781
-        }
782
-        if ($role instanceof WP_Role) {
783
-            // don't do anything if the capabilities map can not be initialized
784
-            if (! $this->setupCapabilitiesMap()) {
785
-                return false;
786
-            }
787
-            if (! $this->capHasBeenAddedToRole($role->name, $cap)) {
788
-                $role->add_cap($cap, $grant);
789
-                $this->capabilities_map[ $role->name ][] = $cap;
790
-                $this->updateCapabilitiesMap($update_capabilities_map);
791
-                return true;
792
-            }
793
-        }
794
-        return false;
795
-    }
796
-
797
-
798
-
799
-    /**
800
-     * Functions similarly to add_cap_to_role except removes cap from given role.
801
-     * Wrapper for $wp_role->remove_cap()
802
-     *
803
-     * @see   wp-includes/capabilities.php
804
-     * @since 4.5.0
805
-     * @param string|WP_Role $role A WordPress role the capability is being removed from.
806
-     * @param string         $cap  The capability being removed
807
-     * @param bool           $update_capabilities_map
808
-     * @return bool
809
-     * @throws \EE_Error
810
-     */
811
-    public function remove_cap_from_role($role, $cap, $update_capabilities_map = true)
812
-    {
813
-        // don't do anything if the capabilities map can not be initialized
814
-        if (! $this->setupCapabilitiesMap()) {
815
-            return false;
816
-        }
817
-        $role = $role instanceof WP_Role ? $role :get_role($role);
818
-        if ($index = $this->capHasBeenAddedToRole($role->name, $cap, true)) {
819
-            $role->remove_cap($cap);
820
-            unset($this->capabilities_map[ $role->name ][ $index ]);
821
-            $this->updateCapabilitiesMap($update_capabilities_map);
822
-            return true;
823
-        }
824
-        return false;
825
-    }
826
-
827
-
828
-
829
-    /**
830
-     * @param string $role_name
831
-     * @param string $cap
832
-     * @param bool   $get_index
833
-     * @return bool|mixed
834
-     */
835
-    private function capHasBeenAddedToRole($role_name='', $cap='', $get_index = false)
836
-    {
837
-        if (
838
-            isset($this->capabilities_map[$role_name])
839
-            && ($index = array_search($cap, $this->capabilities_map[$role_name], true)) !== false
840
-        ) {
841
-            return $get_index ? $index : true;
842
-        }
843
-        return false;
844
-    }
845
-
846
-
847
-
848
-    /**
849
-     * Wrapper for the native WP current_user_can() method.
850
-     * This is provided as a handy method for a couple things:
851
-     * 1. Using the context string it allows for targeted filtering by addons for a specific check (without having to
852
-     * write those filters wherever current_user_can is called).
853
-     * 2. Explicit passing of $id from a given context ( useful in the cases of map_meta_cap filters )
854
-     *
855
-     * @since 4.5.0
856
-     *
857
-     * @param string $cap     The cap being checked.
858
-     * @param string $context The context where the current_user_can is being called from.
859
-     * @param int    $id      Optional. Id for item where current_user_can is being called from (used in map_meta_cap()
860
-     *                        filters.
861
-     *
862
-     * @return bool  Whether user can or not.
863
-     */
864
-    public function current_user_can($cap, $context, $id = 0)
865
-    {
866
-        //apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
867
-        $filtered_cap = apply_filters('FHEE__EE_Capabilities__current_user_can__cap__' . $context, $cap, $id);
868
-        $filtered_cap = apply_filters(
869
-            'FHEE__EE_Capabilities__current_user_can__cap',
870
-            $filtered_cap,
871
-            $context,
872
-            $cap,
873
-            $id
874
-        );
875
-        return ! empty($id)
876
-            ? current_user_can($filtered_cap, $id)
877
-            : current_user_can($filtered_cap);
878
-    }
879
-
880
-
881
-
882
-    /**
883
-     * This is a wrapper for the WP user_can() function and follows the same style as the other wrappers in this class.
884
-     *
885
-     * @param int|WP_User $user    Either the user_id or a WP_User object
886
-     * @param string      $cap     The capability string being checked
887
-     * @param string      $context The context where the user_can is being called from (used in filters).
888
-     * @param int         $id      Optional. Id for item where user_can is being called from ( used in map_meta_cap()
889
-     *                             filters)
890
-     *
891
-     * @return bool Whether user can or not.
892
-     */
893
-    public function user_can($user, $cap, $context, $id = 0)
894
-    {
895
-        //apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
896
-        $filtered_cap = apply_filters('FHEE__EE_Capabilities__user_can__cap__' . $context, $cap, $user, $id);
897
-        $filtered_cap = apply_filters(
898
-            'FHEE__EE_Capabilities__user_can__cap',
899
-            $filtered_cap,
900
-            $context,
901
-            $cap,
902
-            $user,
903
-            $id
904
-        );
905
-        return ! empty($id)
906
-            ? user_can($user, $filtered_cap, $id)
907
-            : user_can($user, $filtered_cap);
908
-    }
909
-
910
-
911
-
912
-    /**
913
-     * Wrapper for the native WP current_user_can_for_blog() method.
914
-     * This is provided as a handy method for a couple things:
915
-     * 1. Using the context string it allows for targeted filtering by addons for a specific check (without having to
916
-     * write those filters wherever current_user_can is called).
917
-     * 2. Explicit passing of $id from a given context ( useful in the cases of map_meta_cap filters )
918
-     *
919
-     * @since 4.5.0
920
-     *
921
-     * @param int    $blog_id The blog id that is being checked for.
922
-     * @param string $cap     The cap being checked.
923
-     * @param string $context The context where the current_user_can is being called from.
924
-     * @param int    $id      Optional. Id for item where current_user_can is being called from (used in map_meta_cap()
925
-     *                        filters.
926
-     *
927
-     * @return bool  Whether user can or not.
928
-     */
929
-    public function current_user_can_for_blog($blog_id, $cap, $context, $id = 0)
930
-    {
931
-        $user_can = ! empty($id)
932
-            ? current_user_can_for_blog($blog_id, $cap, $id)
933
-            : current_user_can($blog_id, $cap);
934
-        //apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
935
-        $user_can = apply_filters(
936
-            'FHEE__EE_Capabilities__current_user_can_for_blog__user_can__' . $context,
937
-            $user_can,
938
-            $blog_id,
939
-            $cap,
940
-            $id
941
-        );
942
-        $user_can = apply_filters(
943
-            'FHEE__EE_Capabilities__current_user_can_for_blog__user_can',
944
-            $user_can,
945
-            $context,
946
-            $blog_id,
947
-            $cap,
948
-            $id
949
-        );
950
-        return $user_can;
951
-    }
952
-
953
-
954
-
955
-    /**
956
-     * This helper method just returns an array of registered EE capabilities.
957
-     *
958
-     * @since 4.5.0
959
-     * @param string $role If empty then the entire role/capability map is returned.
960
-     *                     Otherwise just the capabilities for the given role are returned.
961
-     * @return array
962
-     * @throws EE_Error
963
-     */
964
-    public function get_ee_capabilities($role = 'administrator')
965
-    {
966
-        if (! $this->initialized) {
967
-            $this->init_caps();
968
-        }
969
-        if (empty($role)) {
970
-            return $this->capabilities_map;
971
-        }
972
-        return isset($this->capabilities_map[ $role ])
973
-            ? $this->capabilities_map[ $role ]
974
-            : array();
975
-    }
976
-
977
-
978
-
979
-    /**
980
-     * @deprecated 4.9.42
981
-     * @param bool  $reset      If you need to reset Event Espresso's capabilities,
982
-     *                          then please use the init_caps() method with the "$reset" parameter set to "true"
983
-     * @param array $caps_map   Optional.
984
-     *                          Can be used to send a custom map of roles and capabilities for setting them up.
985
-     *                          Note that this should ONLY be called on activation hook or some other one-time
986
-     *                          task otherwise the caps will be added on every request.
987
-     * @return void
988
-     * @throws EE_Error
989
-     */
990
-    public function init_role_caps($reset = false, $caps_map = array())
991
-    {
992
-        // If this method is called directly and reset is set as 'true',
993
-        // then display a doing it wrong notice, because we want resets to go through init_caps()
994
-        // to guarantee that everything is set up correctly.
995
-        // This prevents the capabilities map getting reset incorrectly by direct calls to this method.
996
-        if ($reset) {
997
-            EE_Error::doing_it_wrong(
998
-                __METHOD__,
999
-                sprintf(
1000
-                    esc_html__(
1001
-                        'The "%1$s" parameter for the "%2$s" method is deprecated. If you need to reset Event Espresso\'s capabilities, then please use the "%3$s" method with the "%1$s" parameter set to "%4$s".',
1002
-                        'event_espresso'
1003
-                    ),
1004
-                    '$reset',
1005
-                    __METHOD__ . '()',
1006
-                    'EE_Capabilities::init_caps()',
1007
-                    'true'
1008
-                ),
1009
-                '4.9.42',
1010
-                '5.0.0'
1011
-            );
1012
-        }
1013
-        $this->addCaps($caps_map);
1014
-    }
21
+	/**
22
+	 * the name of the wp option used to store caps previously initialized
23
+	 */
24
+	const option_name = 'ee_caps_initialized';
25
+
26
+	/**
27
+	 * instance of EE_Capabilities object
28
+	 *
29
+	 * @var EE_Capabilities
30
+	 */
31
+	private static $_instance;
32
+
33
+
34
+	/**
35
+	 * This is a map of caps that correspond to a default WP_Role.
36
+	 * Array is indexed by Role and values are ee capabilities.
37
+	 *
38
+	 * @since 4.5.0
39
+	 *
40
+	 * @var array
41
+	 */
42
+	private $capabilities_map = array();
43
+
44
+	/**
45
+	 * This used to hold an array of EE_Meta_Capability_Map objects
46
+	 * that define the granular capabilities mapped to for a user depending on context.
47
+	 *
48
+	 * @var EE_Meta_Capability_Map[]
49
+	 */
50
+	private $_meta_caps = array();
51
+
52
+	/**
53
+	 * The internal $capabilities_map needs to be initialized before it can be used.
54
+	 * This flag tracks whether that has happened or not.
55
+	 * But for this to work, we need three states to indicate:
56
+	 *      initialization has not occurred at all
57
+	 *      initialization has started but is not complete
58
+	 *      initialization is complete
59
+	 * The reason this is needed is because the addCaps() method
60
+	 * normally requires the $capabilities_map to be initialized,
61
+	 * but is also used during the initialization process.
62
+	 * So:
63
+	 *      If initialized === null, init_caps() will be called before any other methods will run.
64
+	 *      If initialized === false, then init_caps() is in the process of running it's logic.
65
+	 *      If initialized === true, then init_caps() has completed the initialization process.
66
+	 *
67
+	 * @var boolean|null $initialized
68
+	 */
69
+	private $initialized;
70
+
71
+	/**
72
+	 * @var boolean $reset
73
+	 */
74
+	private $reset = false;
75
+
76
+
77
+
78
+	/**
79
+	 * singleton method used to instantiate class object
80
+	 *
81
+	 * @since 4.5.0
82
+	 *
83
+	 * @return EE_Capabilities
84
+	 */
85
+	public static function instance()
86
+	{
87
+		//check if instantiated, and if not do so.
88
+		if (! self::$_instance instanceof EE_Capabilities) {
89
+			self::$_instance = new self();
90
+		}
91
+		return self::$_instance;
92
+	}
93
+
94
+
95
+
96
+	/**
97
+	 * private constructor
98
+	 *
99
+	 * @since 4.5.0
100
+	 */
101
+	private function __construct()
102
+	{
103
+	}
104
+
105
+
106
+
107
+	/**
108
+	 * This delays the initialization of the capabilities class until EE_System core is loaded and ready.
109
+	 *
110
+	 * @param bool $reset allows for resetting the default capabilities saved on roles.  Note that this doesn't
111
+	 *                    actually REMOVE any capabilities from existing roles, it just resaves defaults roles and
112
+	 *                    ensures that they are up to date.
113
+	 *
114
+	 * @since 4.5.0
115
+	 * @return bool
116
+	 * @throws EE_Error
117
+	 */
118
+	public function init_caps($reset = false)
119
+	{
120
+		if(! EE_Maintenance_Mode::instance()->models_can_query()){
121
+			return false;
122
+		}
123
+		$this->reset = filter_var($reset, FILTER_VALIDATE_BOOLEAN);
124
+		// if reset, then completely delete the cache option and clear the $capabilities_map property.
125
+		if ($this->reset) {
126
+			$this->initialized = null;
127
+			$this->capabilities_map = array();
128
+			delete_option(self::option_name);
129
+		}
130
+		if ($this->initialized === null) {
131
+			$this->initialized = false;
132
+			do_action(
133
+				'AHEE__EE_Capabilities__init_caps__before_initialization',
134
+				$this->reset
135
+			);
136
+			$this->addCaps($this->_init_caps_map());
137
+			$this->_set_meta_caps();
138
+			do_action(
139
+				'AHEE__EE_Capabilities__init_caps__after_initialization',
140
+				$this->capabilities_map
141
+			);
142
+			$this->initialized = true;
143
+		}
144
+		// reset $this->reset so that it's not stuck on true if init_caps() gets called again
145
+		$this->reset = false;
146
+		return true;
147
+	}
148
+
149
+
150
+
151
+
152
+	/**
153
+	 * This sets the meta caps property.
154
+	 *
155
+	 * @since 4.5.0
156
+	 * @return void
157
+	 * @throws EE_Error
158
+	 */
159
+	private function _set_meta_caps()
160
+	{
161
+		// get default meta caps and filter the returned array
162
+		$this->_meta_caps = apply_filters(
163
+			'FHEE__EE_Capabilities___set_meta_caps__meta_caps',
164
+			$this->_get_default_meta_caps_array()
165
+		);
166
+		//add filter for map_meta_caps but only if models can query.
167
+		if (! has_filter('map_meta_cap', array($this, 'map_meta_caps'))) {
168
+			add_filter('map_meta_cap', array($this, 'map_meta_caps'), 10, 4);
169
+		}
170
+	}
171
+
172
+
173
+
174
+	/**
175
+	 * This builds and returns the default meta_caps array only once.
176
+	 *
177
+	 * @since  4.8.28.rc.012
178
+	 * @return array
179
+	 * @throws EE_Error
180
+	 */
181
+	private function _get_default_meta_caps_array()
182
+	{
183
+		static $default_meta_caps = array();
184
+		// make sure we're only ever initializing the default _meta_caps array once if it's empty.
185
+		if (empty($default_meta_caps)) {
186
+			$default_meta_caps = array(
187
+				//edits
188
+				new EE_Meta_Capability_Map_Edit(
189
+					'ee_edit_event',
190
+					array('Event', 'ee_edit_published_events', 'ee_edit_others_events', 'ee_edit_private_events')
191
+				),
192
+				new EE_Meta_Capability_Map_Edit(
193
+					'ee_edit_venue',
194
+					array('Venue', 'ee_edit_published_venues', 'ee_edit_others_venues', 'ee_edit_private_venues')
195
+				),
196
+				new EE_Meta_Capability_Map_Edit(
197
+					'ee_edit_registration',
198
+					array('Registration', '', 'ee_edit_others_registrations', '')
199
+				),
200
+				new EE_Meta_Capability_Map_Edit(
201
+					'ee_edit_checkin',
202
+					array('Registration', '', 'ee_edit_others_checkins', '')
203
+				),
204
+				new EE_Meta_Capability_Map_Messages_Cap(
205
+					'ee_edit_message',
206
+					array('Message_Template_Group', '', 'ee_edit_others_messages', 'ee_edit_global_messages')
207
+				),
208
+				new EE_Meta_Capability_Map_Edit(
209
+					'ee_edit_default_ticket',
210
+					array('Ticket', '', 'ee_edit_others_default_tickets', '')
211
+				),
212
+				new EE_Meta_Capability_Map_Registration_Form_Cap(
213
+					'ee_edit_question',
214
+					array('Question', '', '', 'ee_edit_system_questions')
215
+				),
216
+				new EE_Meta_Capability_Map_Registration_Form_Cap(
217
+					'ee_edit_question_group',
218
+					array('Question_Group', '', '', 'ee_edit_system_question_groups')
219
+				),
220
+				new EE_Meta_Capability_Map_Edit(
221
+					'ee_edit_payment_method',
222
+					array('Payment_Method', '', 'ee_edit_others_payment_methods', '')
223
+				),
224
+				//reads
225
+				new EE_Meta_Capability_Map_Read(
226
+					'ee_read_event',
227
+					array('Event', '', 'ee_read_others_events', 'ee_read_private_events')
228
+				),
229
+				new EE_Meta_Capability_Map_Read(
230
+					'ee_read_venue',
231
+					array('Venue', '', 'ee_read_others_venues', 'ee_read_private_venues')
232
+				),
233
+				new EE_Meta_Capability_Map_Read(
234
+					'ee_read_registration',
235
+					array('Registration', '', 'ee_read_others_registrations', '')
236
+				),
237
+				new EE_Meta_Capability_Map_Read(
238
+					'ee_read_checkin',
239
+					array('Registration', '', 'ee_read_others_checkins', '')
240
+				),
241
+				new EE_Meta_Capability_Map_Messages_Cap(
242
+					'ee_read_message',
243
+					array('Message_Template_Group', '', 'ee_read_others_messages', 'ee_read_global_messages')
244
+				),
245
+				new EE_Meta_Capability_Map_Read(
246
+					'ee_read_default_ticket',
247
+					array('Ticket', '', 'ee_read_others_default_tickets', '')
248
+				),
249
+				new EE_Meta_Capability_Map_Read(
250
+					'ee_read_payment_method',
251
+					array('Payment_Method', '', 'ee_read_others_payment_methods', '')
252
+				),
253
+				//deletes
254
+				new EE_Meta_Capability_Map_Delete(
255
+					'ee_delete_event',
256
+					array(
257
+						'Event',
258
+						'ee_delete_published_events',
259
+						'ee_delete_others_events',
260
+						'ee_delete_private_events',
261
+					)
262
+				),
263
+				new EE_Meta_Capability_Map_Delete(
264
+					'ee_delete_venue',
265
+					array(
266
+						'Venue',
267
+						'ee_delete_published_venues',
268
+						'ee_delete_others_venues',
269
+						'ee_delete_private_venues',
270
+					)
271
+				),
272
+				new EE_Meta_Capability_Map_Delete(
273
+					'ee_delete_registration',
274
+					array('Registration', '', 'ee_delete_others_registrations', '')
275
+				),
276
+				new EE_Meta_Capability_Map_Delete(
277
+					'ee_delete_checkin',
278
+					array('Registration', '', 'ee_delete_others_checkins', '')
279
+				),
280
+				new EE_Meta_Capability_Map_Messages_Cap(
281
+					'ee_delete_message',
282
+					array('Message_Template_Group', '', 'ee_delete_others_messages', 'ee_delete_global_messages')
283
+				),
284
+				new EE_Meta_Capability_Map_Delete(
285
+					'ee_delete_default_ticket',
286
+					array('Ticket', '', 'ee_delete_others_default_tickets', '')
287
+				),
288
+				new EE_Meta_Capability_Map_Registration_Form_Cap(
289
+					'ee_delete_question',
290
+					array('Question', '', '', 'delete_system_questions')
291
+				),
292
+				new EE_Meta_Capability_Map_Registration_Form_Cap(
293
+					'ee_delete_question_group',
294
+					array('Question_Group', '', '', 'delete_system_question_groups')
295
+				),
296
+				new EE_Meta_Capability_Map_Delete(
297
+					'ee_delete_payment_method',
298
+					array('Payment_Method', '', 'ee_delete_others_payment_methods', '')
299
+				),
300
+			);
301
+		}
302
+		return $default_meta_caps;
303
+	}
304
+
305
+
306
+
307
+	/**
308
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
309
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
310
+	 *
311
+	 * The actual logic is carried out by implementer classes in their definition of _map_meta_caps.
312
+	 *
313
+	 * @since 4.5.0
314
+	 * @see   wp-includes/capabilities.php
315
+	 *
316
+	 * @param array  $caps    actual users capabilities
317
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
318
+	 * @param int    $user_id The user id
319
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
320
+	 * @return array actual users capabilities
321
+	 * @throws EE_Error
322
+	 */
323
+	public function map_meta_caps($caps, $cap, $user_id, $args)
324
+	{
325
+		if (did_action('AHEE__EE_System__load_espresso_addons__complete')) {
326
+			//loop through our _meta_caps array
327
+			foreach ($this->_meta_caps as $meta_map) {
328
+				if (! $meta_map instanceof EE_Meta_Capability_Map) {
329
+					continue;
330
+				}
331
+				// don't load models if there is no object ID in the args
332
+				if (! empty($args[0])) {
333
+					$meta_map->ensure_is_model();
334
+				}
335
+				$caps = $meta_map->map_meta_caps($caps, $cap, $user_id, $args);
336
+			}
337
+		}
338
+		return $caps;
339
+	}
340
+
341
+
342
+
343
+	/**
344
+	 * This sets up and returns the initial capabilities map for Event Espresso
345
+	 * Note this array is filtered.
346
+	 * It is assumed that all available EE capabilities are assigned to the administrator role.
347
+	 *
348
+	 * @since 4.5.0
349
+	 *
350
+	 * @return array
351
+	 */
352
+	private function _init_caps_map()
353
+	{
354
+		return apply_filters(
355
+			'FHEE__EE_Capabilities__init_caps_map__caps',
356
+			array(
357
+				'administrator'           => array(
358
+					//basic access
359
+					'ee_read_ee',
360
+					//gateways
361
+					/**
362
+					 * note that with payment method capabilities, although we've implemented
363
+					 * capability mapping which will be used for accessing payment methods owned by
364
+					 * other users.  This is not fully implemented yet in the payment method ui.
365
+					 * Currently only the "plural" caps are in active use.
366
+					 * (Specific payment method caps are in use as well).
367
+					 **/
368
+					'ee_manage_gateways',
369
+					'ee_read_payment_methods',
370
+					'ee_read_others_payment_methods',
371
+					'ee_edit_payment_methods',
372
+					'ee_edit_others_payment_methods',
373
+					'ee_delete_payment_methods',
374
+					//events
375
+					'ee_publish_events',
376
+					'ee_read_private_events',
377
+					'ee_read_others_events',
378
+					'ee_read_events',
379
+					'ee_edit_events',
380
+					'ee_edit_published_events',
381
+					'ee_edit_others_events',
382
+					'ee_edit_private_events',
383
+					'ee_delete_published_events',
384
+					'ee_delete_private_events',
385
+					'ee_delete_events',
386
+					'ee_delete_others_events',
387
+					//event categories
388
+					'ee_manage_event_categories',
389
+					'ee_edit_event_category',
390
+					'ee_delete_event_category',
391
+					'ee_assign_event_category',
392
+					//venues
393
+					'ee_publish_venues',
394
+					'ee_read_venues',
395
+					'ee_read_others_venues',
396
+					'ee_read_private_venues',
397
+					'ee_edit_venues',
398
+					'ee_edit_others_venues',
399
+					'ee_edit_published_venues',
400
+					'ee_edit_private_venues',
401
+					'ee_delete_venues',
402
+					'ee_delete_others_venues',
403
+					'ee_delete_private_venues',
404
+					'ee_delete_published_venues',
405
+					//venue categories
406
+					'ee_manage_venue_categories',
407
+					'ee_edit_venue_category',
408
+					'ee_delete_venue_category',
409
+					'ee_assign_venue_category',
410
+					//contacts
411
+					'ee_read_contacts',
412
+					'ee_edit_contacts',
413
+					'ee_delete_contacts',
414
+					//registrations
415
+					'ee_read_registrations',
416
+					'ee_read_others_registrations',
417
+					'ee_edit_registrations',
418
+					'ee_edit_others_registrations',
419
+					'ee_delete_registrations',
420
+					//checkins
421
+					'ee_read_others_checkins',
422
+					'ee_read_checkins',
423
+					'ee_edit_checkins',
424
+					'ee_edit_others_checkins',
425
+					'ee_delete_checkins',
426
+					'ee_delete_others_checkins',
427
+					//transactions && payments
428
+					'ee_read_transaction',
429
+					'ee_read_transactions',
430
+					'ee_edit_payments',
431
+					'ee_delete_payments',
432
+					//messages
433
+					'ee_read_messages',
434
+					'ee_read_others_messages',
435
+					'ee_read_global_messages',
436
+					'ee_edit_global_messages',
437
+					'ee_edit_messages',
438
+					'ee_edit_others_messages',
439
+					'ee_delete_messages',
440
+					'ee_delete_others_messages',
441
+					'ee_delete_global_messages',
442
+					'ee_send_message',
443
+					//tickets
444
+					'ee_read_default_tickets',
445
+					'ee_read_others_default_tickets',
446
+					'ee_edit_default_tickets',
447
+					'ee_edit_others_default_tickets',
448
+					'ee_delete_default_tickets',
449
+					'ee_delete_others_default_tickets',
450
+					//prices
451
+					'ee_edit_default_price',
452
+					'ee_edit_default_prices',
453
+					'ee_delete_default_price',
454
+					'ee_delete_default_prices',
455
+					'ee_edit_default_price_type',
456
+					'ee_edit_default_price_types',
457
+					'ee_delete_default_price_type',
458
+					'ee_delete_default_price_types',
459
+					'ee_read_default_prices',
460
+					'ee_read_default_price_types',
461
+					//registration form
462
+					'ee_edit_questions',
463
+					'ee_edit_system_questions',
464
+					'ee_read_questions',
465
+					'ee_delete_questions',
466
+					'ee_edit_question_groups',
467
+					'ee_read_question_groups',
468
+					'ee_edit_system_question_groups',
469
+					'ee_delete_question_groups',
470
+					//event_type taxonomy
471
+					'ee_assign_event_type',
472
+					'ee_manage_event_types',
473
+					'ee_edit_event_type',
474
+					'ee_delete_event_type',
475
+				),
476
+				'ee_events_administrator' => array(
477
+					//core wp caps
478
+					'read',
479
+					'read_private_pages',
480
+					'read_private_posts',
481
+					'edit_users',
482
+					'edit_posts',
483
+					'edit_pages',
484
+					'edit_published_posts',
485
+					'edit_published_pages',
486
+					'edit_private_pages',
487
+					'edit_private_posts',
488
+					'edit_others_posts',
489
+					'edit_others_pages',
490
+					'publish_posts',
491
+					'publish_pages',
492
+					'delete_posts',
493
+					'delete_pages',
494
+					'delete_private_pages',
495
+					'delete_private_posts',
496
+					'delete_published_pages',
497
+					'delete_published_posts',
498
+					'delete_others_posts',
499
+					'delete_others_pages',
500
+					'manage_categories',
501
+					'manage_links',
502
+					'moderate_comments',
503
+					'unfiltered_html',
504
+					'upload_files',
505
+					'export',
506
+					'import',
507
+					'list_users',
508
+					'level_1', //required if user with this role shows up in author dropdowns
509
+					//basic ee access
510
+					'ee_read_ee',
511
+					//events
512
+					'ee_publish_events',
513
+					'ee_read_private_events',
514
+					'ee_read_others_events',
515
+					'ee_read_event',
516
+					'ee_read_events',
517
+					'ee_edit_event',
518
+					'ee_edit_events',
519
+					'ee_edit_published_events',
520
+					'ee_edit_others_events',
521
+					'ee_edit_private_events',
522
+					'ee_delete_published_events',
523
+					'ee_delete_private_events',
524
+					'ee_delete_event',
525
+					'ee_delete_events',
526
+					'ee_delete_others_events',
527
+					//event categories
528
+					'ee_manage_event_categories',
529
+					'ee_edit_event_category',
530
+					'ee_delete_event_category',
531
+					'ee_assign_event_category',
532
+					//venues
533
+					'ee_publish_venues',
534
+					'ee_read_venue',
535
+					'ee_read_venues',
536
+					'ee_read_others_venues',
537
+					'ee_read_private_venues',
538
+					'ee_edit_venue',
539
+					'ee_edit_venues',
540
+					'ee_edit_others_venues',
541
+					'ee_edit_published_venues',
542
+					'ee_edit_private_venues',
543
+					'ee_delete_venue',
544
+					'ee_delete_venues',
545
+					'ee_delete_others_venues',
546
+					'ee_delete_private_venues',
547
+					'ee_delete_published_venues',
548
+					//venue categories
549
+					'ee_manage_venue_categories',
550
+					'ee_edit_venue_category',
551
+					'ee_delete_venue_category',
552
+					'ee_assign_venue_category',
553
+					//contacts
554
+					'ee_read_contacts',
555
+					'ee_edit_contacts',
556
+					'ee_delete_contacts',
557
+					//registrations
558
+					'ee_read_registrations',
559
+					'ee_read_others_registrations',
560
+					'ee_edit_registration',
561
+					'ee_edit_registrations',
562
+					'ee_edit_others_registrations',
563
+					'ee_delete_registration',
564
+					'ee_delete_registrations',
565
+					//checkins
566
+					'ee_read_others_checkins',
567
+					'ee_read_checkins',
568
+					'ee_edit_checkins',
569
+					'ee_edit_others_checkins',
570
+					'ee_delete_checkins',
571
+					'ee_delete_others_checkins',
572
+					//transactions && payments
573
+					'ee_read_transaction',
574
+					'ee_read_transactions',
575
+					'ee_edit_payments',
576
+					'ee_delete_payments',
577
+					//messages
578
+					'ee_read_messages',
579
+					'ee_read_others_messages',
580
+					'ee_read_global_messages',
581
+					'ee_edit_global_messages',
582
+					'ee_edit_messages',
583
+					'ee_edit_others_messages',
584
+					'ee_delete_messages',
585
+					'ee_delete_others_messages',
586
+					'ee_delete_global_messages',
587
+					'ee_send_message',
588
+					//tickets
589
+					'ee_read_default_tickets',
590
+					'ee_read_others_default_tickets',
591
+					'ee_edit_default_tickets',
592
+					'ee_edit_others_default_tickets',
593
+					'ee_delete_default_tickets',
594
+					'ee_delete_others_default_tickets',
595
+					//prices
596
+					'ee_edit_default_price',
597
+					'ee_edit_default_prices',
598
+					'ee_delete_default_price',
599
+					'ee_delete_default_prices',
600
+					'ee_edit_default_price_type',
601
+					'ee_edit_default_price_types',
602
+					'ee_delete_default_price_type',
603
+					'ee_delete_default_price_types',
604
+					'ee_read_default_prices',
605
+					'ee_read_default_price_types',
606
+					//registration form
607
+					'ee_edit_questions',
608
+					'ee_edit_system_questions',
609
+					'ee_read_questions',
610
+					'ee_delete_questions',
611
+					'ee_edit_question_groups',
612
+					'ee_read_question_groups',
613
+					'ee_edit_system_question_groups',
614
+					'ee_delete_question_groups',
615
+					//event_type taxonomy
616
+					'ee_assign_event_type',
617
+					'ee_manage_event_types',
618
+					'ee_edit_event_type',
619
+					'ee_delete_event_type',
620
+				)
621
+			)
622
+		);
623
+	}
624
+
625
+
626
+
627
+	/**
628
+	 * @return bool
629
+	 * @throws EE_Error
630
+	 */
631
+	private function setupCapabilitiesMap()
632
+	{
633
+		// if the initialization process hasn't even started, then we need to call init_caps()
634
+		if($this->initialized === null) {
635
+			return $this->init_caps();
636
+		}
637
+		// unless resetting, get caps from db if we haven't already
638
+		$this->capabilities_map = $this->reset || ! empty($this->capabilities_map)
639
+			? $this->capabilities_map
640
+			: get_option(self::option_name, array());
641
+		return true;
642
+	}
643
+
644
+
645
+
646
+	/**
647
+	 * @param bool $update
648
+	 * @return bool
649
+	 */
650
+	private function updateCapabilitiesMap($update = true)
651
+	{
652
+		return $update ? update_option(self::option_name, $this->capabilities_map) : false;
653
+	}
654
+
655
+
656
+
657
+	/**
658
+	 * Adds capabilities to roles.
659
+	 *
660
+	 * @since 4.9.42
661
+	 * @param array $capabilities_to_add array of capabilities to add, indexed by roles.
662
+	 *                                   Note that this should ONLY be called on activation hook
663
+	 *                                   otherwise the caps will be added on every request.
664
+	 * @return bool
665
+	 * @throws \EE_Error
666
+	 */
667
+	public function addCaps(array $capabilities_to_add)
668
+	{
669
+		// don't do anything if the capabilities map can not be initialized
670
+		if (! $this->setupCapabilitiesMap()) {
671
+			return false;
672
+		}
673
+		// and filter the array so others can get in on the fun during resets
674
+		$capabilities_to_add = apply_filters(
675
+			'FHEE__EE_Capabilities__addCaps__capabilities_to_add',
676
+			$capabilities_to_add,
677
+			$this->reset,
678
+			$this->capabilities_map
679
+		);
680
+		$update_capabilities_map = false;
681
+		// if not reset, see what caps are new for each role. if they're new, add them.
682
+		foreach ($capabilities_to_add as $role => $caps_for_role) {
683
+			if (is_array($caps_for_role)) {
684
+				foreach ($caps_for_role as $cap) {
685
+					if (
686
+						! $this->capHasBeenAddedToRole($role, $cap)
687
+						&& $this->add_cap_to_role($role, $cap, true, false)
688
+					) {
689
+						$update_capabilities_map = true;
690
+					}
691
+				}
692
+			}
693
+		}
694
+		// now let's just save the cap that has been set but only if there's been a change.
695
+		$updated = $this->updateCapabilitiesMap($update_capabilities_map);
696
+		$this->flushWpUser($updated);
697
+		do_action('AHEE__EE_Capabilities__addCaps__complete', $this->capabilities_map, $updated);
698
+		return $updated;
699
+	}
700
+
701
+
702
+
703
+	/**
704
+	 * Loops through the capabilities map and removes the role caps specified by the incoming array
705
+	 *
706
+	 * @param array $caps_map map of capabilities to be removed (indexed by roles)
707
+	 * @return bool
708
+	 * @throws \EE_Error
709
+	 */
710
+	public function removeCaps($caps_map)
711
+	{
712
+		// don't do anything if the capabilities map can not be initialized
713
+		if (! $this->setupCapabilitiesMap()) {
714
+			return false;
715
+		}
716
+		$update_capabilities_map = false;
717
+		foreach ($caps_map as $role => $caps_for_role) {
718
+			if (is_array($caps_for_role)) {
719
+				foreach ($caps_for_role as $cap) {
720
+					if ($this->capHasBeenAddedToRole($role, $cap)
721
+						&& $this->remove_cap_from_role($role, $cap, false)
722
+					) {
723
+						$update_capabilities_map = true;
724
+					}
725
+				}
726
+			}
727
+		}
728
+		// maybe resave the caps
729
+		$updated = $this->updateCapabilitiesMap($update_capabilities_map);
730
+		$this->flushWpUser($updated);
731
+		return $updated;
732
+	}
733
+
734
+
735
+	/**
736
+	 * This ensures that the WP User object cached on the $current_user global in WP has the latest capabilities from
737
+	 * the roles on that user.
738
+	 *
739
+	 * @param bool $flush  Default is to flush the WP_User object.  If false, then this method effectively does nothing.
740
+	 */
741
+	private function flushWpUser($flush = true)
742
+	{
743
+		if ($flush) {
744
+			$user = wp_get_current_user();
745
+			if ($user instanceof WP_User) {
746
+				$user->get_role_caps();
747
+			}
748
+		}
749
+	}
750
+
751
+
752
+
753
+	/**
754
+	 * This method sets a capability on a role.  Note this should only be done on activation, or if you have something
755
+	 * specific to prevent the cap from being added on every page load (adding caps are persistent to the db). Note.
756
+	 * this is a wrapper for $wp_role->add_cap()
757
+	 *
758
+	 * @see   wp-includes/capabilities.php
759
+	 * @since 4.5.0
760
+	 * @param string|WP_Role $role  A WordPress role the capability is being added to
761
+	 * @param string         $cap   The capability being added to the role
762
+	 * @param bool           $grant Whether to grant access to this cap on this role.
763
+	 * @param bool           $update_capabilities_map
764
+	 * @return bool
765
+	 * @throws \EE_Error
766
+	 */
767
+	public function add_cap_to_role($role, $cap, $grant = true, $update_capabilities_map = true)
768
+	{
769
+		// capture incoming value for $role because we may need it to create a new WP_Role
770
+		$orig_role = $role;
771
+		$role = $role instanceof WP_Role ? $role : get_role($role);
772
+		//if the role isn't available then we create it.
773
+		if (! $role instanceof WP_Role) {
774
+			// if a plugin wants to create a specific role name then they should create the role before
775
+			// EE_Capabilities does.  Otherwise this function will create the role name from the slug:
776
+			// - removes any `ee_` namespacing from the start of the slug.
777
+			// - replaces `_` with ` ` (empty space).
778
+			// - sentence case on the resulting string.
779
+			$role_label = ucwords(str_replace(array('ee_', '_'), array('', ' '), $orig_role));
780
+			$role = add_role($orig_role, $role_label);
781
+		}
782
+		if ($role instanceof WP_Role) {
783
+			// don't do anything if the capabilities map can not be initialized
784
+			if (! $this->setupCapabilitiesMap()) {
785
+				return false;
786
+			}
787
+			if (! $this->capHasBeenAddedToRole($role->name, $cap)) {
788
+				$role->add_cap($cap, $grant);
789
+				$this->capabilities_map[ $role->name ][] = $cap;
790
+				$this->updateCapabilitiesMap($update_capabilities_map);
791
+				return true;
792
+			}
793
+		}
794
+		return false;
795
+	}
796
+
797
+
798
+
799
+	/**
800
+	 * Functions similarly to add_cap_to_role except removes cap from given role.
801
+	 * Wrapper for $wp_role->remove_cap()
802
+	 *
803
+	 * @see   wp-includes/capabilities.php
804
+	 * @since 4.5.0
805
+	 * @param string|WP_Role $role A WordPress role the capability is being removed from.
806
+	 * @param string         $cap  The capability being removed
807
+	 * @param bool           $update_capabilities_map
808
+	 * @return bool
809
+	 * @throws \EE_Error
810
+	 */
811
+	public function remove_cap_from_role($role, $cap, $update_capabilities_map = true)
812
+	{
813
+		// don't do anything if the capabilities map can not be initialized
814
+		if (! $this->setupCapabilitiesMap()) {
815
+			return false;
816
+		}
817
+		$role = $role instanceof WP_Role ? $role :get_role($role);
818
+		if ($index = $this->capHasBeenAddedToRole($role->name, $cap, true)) {
819
+			$role->remove_cap($cap);
820
+			unset($this->capabilities_map[ $role->name ][ $index ]);
821
+			$this->updateCapabilitiesMap($update_capabilities_map);
822
+			return true;
823
+		}
824
+		return false;
825
+	}
826
+
827
+
828
+
829
+	/**
830
+	 * @param string $role_name
831
+	 * @param string $cap
832
+	 * @param bool   $get_index
833
+	 * @return bool|mixed
834
+	 */
835
+	private function capHasBeenAddedToRole($role_name='', $cap='', $get_index = false)
836
+	{
837
+		if (
838
+			isset($this->capabilities_map[$role_name])
839
+			&& ($index = array_search($cap, $this->capabilities_map[$role_name], true)) !== false
840
+		) {
841
+			return $get_index ? $index : true;
842
+		}
843
+		return false;
844
+	}
845
+
846
+
847
+
848
+	/**
849
+	 * Wrapper for the native WP current_user_can() method.
850
+	 * This is provided as a handy method for a couple things:
851
+	 * 1. Using the context string it allows for targeted filtering by addons for a specific check (without having to
852
+	 * write those filters wherever current_user_can is called).
853
+	 * 2. Explicit passing of $id from a given context ( useful in the cases of map_meta_cap filters )
854
+	 *
855
+	 * @since 4.5.0
856
+	 *
857
+	 * @param string $cap     The cap being checked.
858
+	 * @param string $context The context where the current_user_can is being called from.
859
+	 * @param int    $id      Optional. Id for item where current_user_can is being called from (used in map_meta_cap()
860
+	 *                        filters.
861
+	 *
862
+	 * @return bool  Whether user can or not.
863
+	 */
864
+	public function current_user_can($cap, $context, $id = 0)
865
+	{
866
+		//apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
867
+		$filtered_cap = apply_filters('FHEE__EE_Capabilities__current_user_can__cap__' . $context, $cap, $id);
868
+		$filtered_cap = apply_filters(
869
+			'FHEE__EE_Capabilities__current_user_can__cap',
870
+			$filtered_cap,
871
+			$context,
872
+			$cap,
873
+			$id
874
+		);
875
+		return ! empty($id)
876
+			? current_user_can($filtered_cap, $id)
877
+			: current_user_can($filtered_cap);
878
+	}
879
+
880
+
881
+
882
+	/**
883
+	 * This is a wrapper for the WP user_can() function and follows the same style as the other wrappers in this class.
884
+	 *
885
+	 * @param int|WP_User $user    Either the user_id or a WP_User object
886
+	 * @param string      $cap     The capability string being checked
887
+	 * @param string      $context The context where the user_can is being called from (used in filters).
888
+	 * @param int         $id      Optional. Id for item where user_can is being called from ( used in map_meta_cap()
889
+	 *                             filters)
890
+	 *
891
+	 * @return bool Whether user can or not.
892
+	 */
893
+	public function user_can($user, $cap, $context, $id = 0)
894
+	{
895
+		//apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
896
+		$filtered_cap = apply_filters('FHEE__EE_Capabilities__user_can__cap__' . $context, $cap, $user, $id);
897
+		$filtered_cap = apply_filters(
898
+			'FHEE__EE_Capabilities__user_can__cap',
899
+			$filtered_cap,
900
+			$context,
901
+			$cap,
902
+			$user,
903
+			$id
904
+		);
905
+		return ! empty($id)
906
+			? user_can($user, $filtered_cap, $id)
907
+			: user_can($user, $filtered_cap);
908
+	}
909
+
910
+
911
+
912
+	/**
913
+	 * Wrapper for the native WP current_user_can_for_blog() method.
914
+	 * This is provided as a handy method for a couple things:
915
+	 * 1. Using the context string it allows for targeted filtering by addons for a specific check (without having to
916
+	 * write those filters wherever current_user_can is called).
917
+	 * 2. Explicit passing of $id from a given context ( useful in the cases of map_meta_cap filters )
918
+	 *
919
+	 * @since 4.5.0
920
+	 *
921
+	 * @param int    $blog_id The blog id that is being checked for.
922
+	 * @param string $cap     The cap being checked.
923
+	 * @param string $context The context where the current_user_can is being called from.
924
+	 * @param int    $id      Optional. Id for item where current_user_can is being called from (used in map_meta_cap()
925
+	 *                        filters.
926
+	 *
927
+	 * @return bool  Whether user can or not.
928
+	 */
929
+	public function current_user_can_for_blog($blog_id, $cap, $context, $id = 0)
930
+	{
931
+		$user_can = ! empty($id)
932
+			? current_user_can_for_blog($blog_id, $cap, $id)
933
+			: current_user_can($blog_id, $cap);
934
+		//apply filters (both a global on just the cap, and context specific.  Global overrides context specific)
935
+		$user_can = apply_filters(
936
+			'FHEE__EE_Capabilities__current_user_can_for_blog__user_can__' . $context,
937
+			$user_can,
938
+			$blog_id,
939
+			$cap,
940
+			$id
941
+		);
942
+		$user_can = apply_filters(
943
+			'FHEE__EE_Capabilities__current_user_can_for_blog__user_can',
944
+			$user_can,
945
+			$context,
946
+			$blog_id,
947
+			$cap,
948
+			$id
949
+		);
950
+		return $user_can;
951
+	}
952
+
953
+
954
+
955
+	/**
956
+	 * This helper method just returns an array of registered EE capabilities.
957
+	 *
958
+	 * @since 4.5.0
959
+	 * @param string $role If empty then the entire role/capability map is returned.
960
+	 *                     Otherwise just the capabilities for the given role are returned.
961
+	 * @return array
962
+	 * @throws EE_Error
963
+	 */
964
+	public function get_ee_capabilities($role = 'administrator')
965
+	{
966
+		if (! $this->initialized) {
967
+			$this->init_caps();
968
+		}
969
+		if (empty($role)) {
970
+			return $this->capabilities_map;
971
+		}
972
+		return isset($this->capabilities_map[ $role ])
973
+			? $this->capabilities_map[ $role ]
974
+			: array();
975
+	}
976
+
977
+
978
+
979
+	/**
980
+	 * @deprecated 4.9.42
981
+	 * @param bool  $reset      If you need to reset Event Espresso's capabilities,
982
+	 *                          then please use the init_caps() method with the "$reset" parameter set to "true"
983
+	 * @param array $caps_map   Optional.
984
+	 *                          Can be used to send a custom map of roles and capabilities for setting them up.
985
+	 *                          Note that this should ONLY be called on activation hook or some other one-time
986
+	 *                          task otherwise the caps will be added on every request.
987
+	 * @return void
988
+	 * @throws EE_Error
989
+	 */
990
+	public function init_role_caps($reset = false, $caps_map = array())
991
+	{
992
+		// If this method is called directly and reset is set as 'true',
993
+		// then display a doing it wrong notice, because we want resets to go through init_caps()
994
+		// to guarantee that everything is set up correctly.
995
+		// This prevents the capabilities map getting reset incorrectly by direct calls to this method.
996
+		if ($reset) {
997
+			EE_Error::doing_it_wrong(
998
+				__METHOD__,
999
+				sprintf(
1000
+					esc_html__(
1001
+						'The "%1$s" parameter for the "%2$s" method is deprecated. If you need to reset Event Espresso\'s capabilities, then please use the "%3$s" method with the "%1$s" parameter set to "%4$s".',
1002
+						'event_espresso'
1003
+					),
1004
+					'$reset',
1005
+					__METHOD__ . '()',
1006
+					'EE_Capabilities::init_caps()',
1007
+					'true'
1008
+				),
1009
+				'4.9.42',
1010
+				'5.0.0'
1011
+			);
1012
+		}
1013
+		$this->addCaps($caps_map);
1014
+	}
1015 1015
 
1016 1016
 
1017 1017
 
@@ -1032,142 +1032,142 @@  discard block
 block discarded – undo
1032 1032
 abstract class EE_Meta_Capability_Map
1033 1033
 {
1034 1034
 
1035
-    public $meta_cap;
1036
-
1037
-    /**
1038
-     * @var EEM_Base
1039
-     */
1040
-    protected $_model;
1041
-
1042
-    protected $_model_name;
1043
-
1044
-    public $published_cap = '';
1045
-
1046
-    public $others_cap = '';
1047
-
1048
-    public $private_cap = '';
1049
-
1050
-
1051
-    /**
1052
-     * constructor.
1053
-     * Receives the setup arguments for the map.
1054
-     *
1055
-     * @since                        4.5.0
1056
-     *
1057
-     * @param string $meta_cap   What meta capability is this mapping.
1058
-     * @param array  $map_values array {
1059
-     *                           //array of values that MUST match a count of 4.  It's okay to send an empty string for
1060
-     *                           capabilities that don't get mapped to.
1061
-     *
1062
-     * @type         $map_values [0] string A string representing the model name. Required.  String's
1063
-     *                               should always be used when Menu Maps are registered via the
1064
-     *                               plugin API as models are not allowed to be instantiated when
1065
-     *                               in maintenance mode 2 (migrations).
1066
-     * @type         $map_values [1] string represents the capability used for published. Optional.
1067
-     * @type         $map_values [2] string represents the capability used for "others". Optional.
1068
-     * @type         $map_values [3] string represents the capability used for private. Optional.
1069
-     *                               }
1070
-     * @throws EE_Error
1071
-     */
1072
-    public function __construct($meta_cap, $map_values)
1073
-    {
1074
-        $this->meta_cap = $meta_cap;
1075
-        //verify there are four args in the $map_values array;
1076
-        if (count($map_values) !== 4) {
1077
-            throw new EE_Error(
1078
-                sprintf(
1079
-                    __(
1080
-                        'Incoming $map_values array should have a count of four values in it.  This is what was given: %s',
1081
-                        'event_espresso'
1082
-                    ),
1083
-                    '<br>' . print_r($map_values, true)
1084
-                )
1085
-            );
1086
-        }
1087
-        //set properties
1088
-        $this->_model = null;
1089
-        $this->_model_name = $map_values[0];
1090
-        $this->published_cap = (string)$map_values[1];
1091
-        $this->others_cap = (string)$map_values[2];
1092
-        $this->private_cap = (string)$map_values[3];
1093
-    }
1094
-
1095
-    /**
1096
-     * Makes it so this object stops filtering caps
1097
-     */
1098
-    public function remove_filters()
1099
-    {
1100
-        remove_filter('map_meta_cap', array($this, 'map_meta_caps'), 10);
1101
-    }
1102
-
1103
-
1104
-    /**
1105
-     * This method ensures that the $model property is converted from the model name string to a proper EEM_Base class
1106
-     *
1107
-     * @since 4.5.0
1108
-     * @throws EE_Error
1109
-     *
1110
-     * @return void
1111
-     */
1112
-    public function ensure_is_model()
1113
-    {
1114
-        //is it already instantiated?
1115
-        if ($this->_model instanceof EEM_Base) {
1116
-            return;
1117
-        }
1118
-        //ensure model name is string
1119
-        $this->_model_name = (string)$this->_model_name;
1120
-        //error proof if the name has EEM in it
1121
-        $this->_model_name = str_replace('EEM', '', $this->_model_name);
1122
-        $this->_model = EE_Registry::instance()->load_model($this->_model_name);
1123
-        if (! $this->_model instanceof EEM_Base) {
1124
-            throw new EE_Error(
1125
-                sprintf(
1126
-                    __(
1127
-                        'This string passed in to %s to represent a EEM_Base model class was not able to be used to instantiate the class.   Please ensure that the string is a match for the EEM_Base model name (not including the EEM_ part). This was given: %s',
1128
-                        'event_espresso'
1129
-                    ),
1130
-                    get_class($this),
1131
-                    $this->_model
1132
-                )
1133
-            );
1134
-        }
1135
-    }
1136
-
1137
-
1138
-    /**
1139
-     *
1140
-     * @see   EE_Meta_Capability_Map::_map_meta_caps() for docs on params.
1141
-     * @since 4.6.x
1142
-     *
1143
-     * @param $caps
1144
-     * @param $cap
1145
-     * @param $user_id
1146
-     * @param $args
1147
-     *
1148
-     * @return array
1149
-     */
1150
-    public function map_meta_caps($caps, $cap, $user_id, $args)
1151
-    {
1152
-        return $this->_map_meta_caps($caps, $cap, $user_id, $args);
1153
-    }
1154
-
1155
-
1156
-    /**
1157
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1158
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1159
-     *
1160
-     * @since 4.5.0
1161
-     * @see   wp-includes/capabilities.php
1162
-     *
1163
-     * @param array  $caps    actual users capabilities
1164
-     * @param string $cap     initial capability name that is being checked (the "map" key)
1165
-     * @param int    $user_id The user id
1166
-     * @param array  $args    Adds context to the cap. Typically the object ID.
1167
-     *
1168
-     * @return array   actual users capabilities
1169
-     */
1170
-    abstract protected function _map_meta_caps($caps, $cap, $user_id, $args);
1035
+	public $meta_cap;
1036
+
1037
+	/**
1038
+	 * @var EEM_Base
1039
+	 */
1040
+	protected $_model;
1041
+
1042
+	protected $_model_name;
1043
+
1044
+	public $published_cap = '';
1045
+
1046
+	public $others_cap = '';
1047
+
1048
+	public $private_cap = '';
1049
+
1050
+
1051
+	/**
1052
+	 * constructor.
1053
+	 * Receives the setup arguments for the map.
1054
+	 *
1055
+	 * @since                        4.5.0
1056
+	 *
1057
+	 * @param string $meta_cap   What meta capability is this mapping.
1058
+	 * @param array  $map_values array {
1059
+	 *                           //array of values that MUST match a count of 4.  It's okay to send an empty string for
1060
+	 *                           capabilities that don't get mapped to.
1061
+	 *
1062
+	 * @type         $map_values [0] string A string representing the model name. Required.  String's
1063
+	 *                               should always be used when Menu Maps are registered via the
1064
+	 *                               plugin API as models are not allowed to be instantiated when
1065
+	 *                               in maintenance mode 2 (migrations).
1066
+	 * @type         $map_values [1] string represents the capability used for published. Optional.
1067
+	 * @type         $map_values [2] string represents the capability used for "others". Optional.
1068
+	 * @type         $map_values [3] string represents the capability used for private. Optional.
1069
+	 *                               }
1070
+	 * @throws EE_Error
1071
+	 */
1072
+	public function __construct($meta_cap, $map_values)
1073
+	{
1074
+		$this->meta_cap = $meta_cap;
1075
+		//verify there are four args in the $map_values array;
1076
+		if (count($map_values) !== 4) {
1077
+			throw new EE_Error(
1078
+				sprintf(
1079
+					__(
1080
+						'Incoming $map_values array should have a count of four values in it.  This is what was given: %s',
1081
+						'event_espresso'
1082
+					),
1083
+					'<br>' . print_r($map_values, true)
1084
+				)
1085
+			);
1086
+		}
1087
+		//set properties
1088
+		$this->_model = null;
1089
+		$this->_model_name = $map_values[0];
1090
+		$this->published_cap = (string)$map_values[1];
1091
+		$this->others_cap = (string)$map_values[2];
1092
+		$this->private_cap = (string)$map_values[3];
1093
+	}
1094
+
1095
+	/**
1096
+	 * Makes it so this object stops filtering caps
1097
+	 */
1098
+	public function remove_filters()
1099
+	{
1100
+		remove_filter('map_meta_cap', array($this, 'map_meta_caps'), 10);
1101
+	}
1102
+
1103
+
1104
+	/**
1105
+	 * This method ensures that the $model property is converted from the model name string to a proper EEM_Base class
1106
+	 *
1107
+	 * @since 4.5.0
1108
+	 * @throws EE_Error
1109
+	 *
1110
+	 * @return void
1111
+	 */
1112
+	public function ensure_is_model()
1113
+	{
1114
+		//is it already instantiated?
1115
+		if ($this->_model instanceof EEM_Base) {
1116
+			return;
1117
+		}
1118
+		//ensure model name is string
1119
+		$this->_model_name = (string)$this->_model_name;
1120
+		//error proof if the name has EEM in it
1121
+		$this->_model_name = str_replace('EEM', '', $this->_model_name);
1122
+		$this->_model = EE_Registry::instance()->load_model($this->_model_name);
1123
+		if (! $this->_model instanceof EEM_Base) {
1124
+			throw new EE_Error(
1125
+				sprintf(
1126
+					__(
1127
+						'This string passed in to %s to represent a EEM_Base model class was not able to be used to instantiate the class.   Please ensure that the string is a match for the EEM_Base model name (not including the EEM_ part). This was given: %s',
1128
+						'event_espresso'
1129
+					),
1130
+					get_class($this),
1131
+					$this->_model
1132
+				)
1133
+			);
1134
+		}
1135
+	}
1136
+
1137
+
1138
+	/**
1139
+	 *
1140
+	 * @see   EE_Meta_Capability_Map::_map_meta_caps() for docs on params.
1141
+	 * @since 4.6.x
1142
+	 *
1143
+	 * @param $caps
1144
+	 * @param $cap
1145
+	 * @param $user_id
1146
+	 * @param $args
1147
+	 *
1148
+	 * @return array
1149
+	 */
1150
+	public function map_meta_caps($caps, $cap, $user_id, $args)
1151
+	{
1152
+		return $this->_map_meta_caps($caps, $cap, $user_id, $args);
1153
+	}
1154
+
1155
+
1156
+	/**
1157
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1158
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1159
+	 *
1160
+	 * @since 4.5.0
1161
+	 * @see   wp-includes/capabilities.php
1162
+	 *
1163
+	 * @param array  $caps    actual users capabilities
1164
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
1165
+	 * @param int    $user_id The user id
1166
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
1167
+	 *
1168
+	 * @return array   actual users capabilities
1169
+	 */
1170
+	abstract protected function _map_meta_caps($caps, $cap, $user_id, $args);
1171 1171
 }
1172 1172
 
1173 1173
 
@@ -1183,81 +1183,81 @@  discard block
 block discarded – undo
1183 1183
 class EE_Meta_Capability_Map_Edit extends EE_Meta_Capability_Map
1184 1184
 {
1185 1185
 
1186
-    /**
1187
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1188
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1189
-     *
1190
-     * @since 4.5.0
1191
-     * @see   wp-includes/capabilities.php
1192
-     *
1193
-     * @param array  $caps    actual users capabilities
1194
-     * @param string $cap     initial capability name that is being checked (the "map" key)
1195
-     * @param int    $user_id The user id
1196
-     * @param array  $args    Adds context to the cap. Typically the object ID.
1197
-     *
1198
-     * @return array   actual users capabilities
1199
-     */
1200
-    protected function _map_meta_caps($caps, $cap, $user_id, $args)
1201
-    {
1202
-        //only process if we're checking our mapped_cap
1203
-        if ($cap !== $this->meta_cap) {
1204
-            return $caps;
1205
-        }
1206
-
1207
-        //okay it is a meta cap so let's first remove that cap from the $caps array.
1208
-        if (($key = array_search($cap, $caps)) !== false) {
1209
-            unset($caps[$key]);
1210
-        }
1211
-
1212
-        //cast $user_id to int for later explicit comparisons
1213
-        $user_id = (int) $user_id;
1214
-
1215
-        /** @var EE_Base_Class $obj */
1216
-        $obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1217
-        //if no obj then let's just do cap
1218
-        if (! $obj instanceof EE_Base_Class) {
1219
-            $caps[] = 'do_not_allow';
1220
-            return $caps;
1221
-        }
1222
-        $caps[] = $cap . 's';
1223
-        if ($obj instanceof EE_CPT_Base) {
1224
-            //if the item author is set and the user is the author...
1225
-            if ($obj->wp_user() && $user_id === $obj->wp_user()) {
1226
-                //if obj is published...
1227
-                if ($obj->status() === 'publish') {
1228
-                    $caps[] = $this->published_cap;
1229
-                }
1230
-            } else {
1231
-                //the user is trying to edit someone else's obj
1232
-                if (! empty($this->others_cap)) {
1233
-                    $caps[] = $this->others_cap;
1234
-                }
1235
-                if (! empty($this->published_cap) && $obj->status() === 'publish') {
1236
-                    $caps[] = $this->published_cap;
1237
-                } elseif (! empty($this->private_cap) && $obj->status() === 'private') {
1238
-                    $caps[] = $this->private_cap;
1239
-                }
1240
-            }
1241
-        } else {
1242
-            //not a cpt object so handled differently
1243
-            $has_cap = false;
1244
-            try {
1245
-                $has_cap = method_exists($obj, 'wp_user')
1246
-                    && $obj->wp_user()
1247
-                    && $obj->wp_user() === $user_id;
1248
-            } catch (Exception $e) {
1249
-                if (WP_DEBUG) {
1250
-                    EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1251
-                }
1252
-            }
1253
-            if (! $has_cap) {
1254
-                if (! empty($this->others_cap)) {
1255
-                    $caps[] = $this->others_cap;
1256
-                }
1257
-            }
1258
-        }
1259
-        return $caps;
1260
-    }
1186
+	/**
1187
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1188
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1189
+	 *
1190
+	 * @since 4.5.0
1191
+	 * @see   wp-includes/capabilities.php
1192
+	 *
1193
+	 * @param array  $caps    actual users capabilities
1194
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
1195
+	 * @param int    $user_id The user id
1196
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
1197
+	 *
1198
+	 * @return array   actual users capabilities
1199
+	 */
1200
+	protected function _map_meta_caps($caps, $cap, $user_id, $args)
1201
+	{
1202
+		//only process if we're checking our mapped_cap
1203
+		if ($cap !== $this->meta_cap) {
1204
+			return $caps;
1205
+		}
1206
+
1207
+		//okay it is a meta cap so let's first remove that cap from the $caps array.
1208
+		if (($key = array_search($cap, $caps)) !== false) {
1209
+			unset($caps[$key]);
1210
+		}
1211
+
1212
+		//cast $user_id to int for later explicit comparisons
1213
+		$user_id = (int) $user_id;
1214
+
1215
+		/** @var EE_Base_Class $obj */
1216
+		$obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1217
+		//if no obj then let's just do cap
1218
+		if (! $obj instanceof EE_Base_Class) {
1219
+			$caps[] = 'do_not_allow';
1220
+			return $caps;
1221
+		}
1222
+		$caps[] = $cap . 's';
1223
+		if ($obj instanceof EE_CPT_Base) {
1224
+			//if the item author is set and the user is the author...
1225
+			if ($obj->wp_user() && $user_id === $obj->wp_user()) {
1226
+				//if obj is published...
1227
+				if ($obj->status() === 'publish') {
1228
+					$caps[] = $this->published_cap;
1229
+				}
1230
+			} else {
1231
+				//the user is trying to edit someone else's obj
1232
+				if (! empty($this->others_cap)) {
1233
+					$caps[] = $this->others_cap;
1234
+				}
1235
+				if (! empty($this->published_cap) && $obj->status() === 'publish') {
1236
+					$caps[] = $this->published_cap;
1237
+				} elseif (! empty($this->private_cap) && $obj->status() === 'private') {
1238
+					$caps[] = $this->private_cap;
1239
+				}
1240
+			}
1241
+		} else {
1242
+			//not a cpt object so handled differently
1243
+			$has_cap = false;
1244
+			try {
1245
+				$has_cap = method_exists($obj, 'wp_user')
1246
+					&& $obj->wp_user()
1247
+					&& $obj->wp_user() === $user_id;
1248
+			} catch (Exception $e) {
1249
+				if (WP_DEBUG) {
1250
+					EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1251
+				}
1252
+			}
1253
+			if (! $has_cap) {
1254
+				if (! empty($this->others_cap)) {
1255
+					$caps[] = $this->others_cap;
1256
+				}
1257
+			}
1258
+		}
1259
+		return $caps;
1260
+	}
1261 1261
 }
1262 1262
 
1263 1263
 
@@ -1274,24 +1274,24 @@  discard block
 block discarded – undo
1274 1274
 class EE_Meta_Capability_Map_Delete extends EE_Meta_Capability_Map_Edit
1275 1275
 {
1276 1276
 
1277
-    /**
1278
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1279
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1280
-     *
1281
-     * @since 4.5.0
1282
-     * @see   wp-includes/capabilities.php
1283
-     *
1284
-     * @param array  $caps    actual users capabilities
1285
-     * @param string $cap     initial capability name that is being checked (the "map" key)
1286
-     * @param int    $user_id The user id
1287
-     * @param array  $args    Adds context to the cap. Typically the object ID.
1288
-     *
1289
-     * @return array   actual users capabilities
1290
-     */
1291
-    protected function _map_meta_caps($caps, $cap, $user_id, $args)
1292
-    {
1293
-        return parent::_map_meta_caps($caps, $cap, $user_id, $args);
1294
-    }
1277
+	/**
1278
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1279
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1280
+	 *
1281
+	 * @since 4.5.0
1282
+	 * @see   wp-includes/capabilities.php
1283
+	 *
1284
+	 * @param array  $caps    actual users capabilities
1285
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
1286
+	 * @param int    $user_id The user id
1287
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
1288
+	 *
1289
+	 * @return array   actual users capabilities
1290
+	 */
1291
+	protected function _map_meta_caps($caps, $cap, $user_id, $args)
1292
+	{
1293
+		return parent::_map_meta_caps($caps, $cap, $user_id, $args);
1294
+	}
1295 1295
 }
1296 1296
 
1297 1297
 
@@ -1307,85 +1307,85 @@  discard block
 block discarded – undo
1307 1307
 class EE_Meta_Capability_Map_Read extends EE_Meta_Capability_Map
1308 1308
 {
1309 1309
 
1310
-    /**
1311
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1312
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1313
-     *
1314
-     * @since 4.5.0
1315
-     * @see   wp-includes/capabilities.php
1316
-     *
1317
-     * @param array  $caps    actual users capabilities
1318
-     * @param string $cap     initial capability name that is being checked (the "map" key)
1319
-     * @param int    $user_id The user id
1320
-     * @param array  $args    Adds context to the cap. Typically the object ID.
1321
-     *
1322
-     * @return array   actual users capabilities
1323
-     */
1324
-    protected function _map_meta_caps($caps, $cap, $user_id, $args)
1325
-    {
1326
-        //only process if we're checking our mapped cap;
1327
-        if ($cap !== $this->meta_cap) {
1328
-            return $caps;
1329
-        }
1330
-
1331
-        //okay it is a meta cap so let's first remove that cap from the $caps array.
1332
-        if (($key = array_search($cap, $caps)) !== false) {
1333
-            unset($caps[$key]);
1334
-        }
1335
-
1336
-        //cast $user_id to int for later explicit comparisons
1337
-        $user_id = (int) $user_id;
1338
-
1339
-        $obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1340
-        //if no obj then let's just do cap
1341
-        if (! $obj instanceof EE_Base_Class) {
1342
-            $caps[] = 'do_not_allow';
1343
-            return $caps;
1344
-        }
1345
-
1346
-        $caps[] = $cap . 's';
1347
-        if ($obj instanceof EE_CPT_Base) {
1348
-            $status_obj = get_post_status_object($obj->status());
1349
-            if ($status_obj->public) {
1350
-                return $caps;
1351
-            }
1352
-            //if the item author is set and the user is not the author...
1353
-            if ($obj->wp_user() && $obj->wp_user() !== $user_id) {
1354
-                if (! empty($this->others_cap)) {
1355
-                    $caps[] = $this->others_cap;
1356
-                }
1357
-            }
1358
-            //yes this means that if users created the private post, they are able to see it regardless of private cap.
1359
-            if ($status_obj->private
1360
-                && ! empty($this->private_cap)
1361
-                && $obj->wp_user() !== $user_id
1362
-            ) {
1363
-                //the user is trying to view a private object for an object they don't own.
1364
-                $caps[] = $this->private_cap;
1365
-            }
1366
-        } else {
1367
-            //not a cpt object so handled differently
1368
-            $has_cap = false;
1369
-            try {
1370
-                $has_cap = method_exists($obj, 'wp_user')
1371
-                           && $obj->wp_user()
1372
-                           && $obj->wp_user() === $user_id;
1373
-            } catch (Exception $e) {
1374
-                if (WP_DEBUG) {
1375
-                    EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1376
-                }
1377
-            }
1378
-            if (! $has_cap) {
1379
-                if (! empty($this->private_cap)) {
1380
-                    $caps[] = $this->private_cap;
1381
-                }
1382
-                if (! empty($this->others_cap)) {
1383
-                    $caps[] = $this->others_cap;
1384
-                }
1385
-            }
1386
-        }
1387
-        return $caps;
1388
-    }
1310
+	/**
1311
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1312
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1313
+	 *
1314
+	 * @since 4.5.0
1315
+	 * @see   wp-includes/capabilities.php
1316
+	 *
1317
+	 * @param array  $caps    actual users capabilities
1318
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
1319
+	 * @param int    $user_id The user id
1320
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
1321
+	 *
1322
+	 * @return array   actual users capabilities
1323
+	 */
1324
+	protected function _map_meta_caps($caps, $cap, $user_id, $args)
1325
+	{
1326
+		//only process if we're checking our mapped cap;
1327
+		if ($cap !== $this->meta_cap) {
1328
+			return $caps;
1329
+		}
1330
+
1331
+		//okay it is a meta cap so let's first remove that cap from the $caps array.
1332
+		if (($key = array_search($cap, $caps)) !== false) {
1333
+			unset($caps[$key]);
1334
+		}
1335
+
1336
+		//cast $user_id to int for later explicit comparisons
1337
+		$user_id = (int) $user_id;
1338
+
1339
+		$obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1340
+		//if no obj then let's just do cap
1341
+		if (! $obj instanceof EE_Base_Class) {
1342
+			$caps[] = 'do_not_allow';
1343
+			return $caps;
1344
+		}
1345
+
1346
+		$caps[] = $cap . 's';
1347
+		if ($obj instanceof EE_CPT_Base) {
1348
+			$status_obj = get_post_status_object($obj->status());
1349
+			if ($status_obj->public) {
1350
+				return $caps;
1351
+			}
1352
+			//if the item author is set and the user is not the author...
1353
+			if ($obj->wp_user() && $obj->wp_user() !== $user_id) {
1354
+				if (! empty($this->others_cap)) {
1355
+					$caps[] = $this->others_cap;
1356
+				}
1357
+			}
1358
+			//yes this means that if users created the private post, they are able to see it regardless of private cap.
1359
+			if ($status_obj->private
1360
+				&& ! empty($this->private_cap)
1361
+				&& $obj->wp_user() !== $user_id
1362
+			) {
1363
+				//the user is trying to view a private object for an object they don't own.
1364
+				$caps[] = $this->private_cap;
1365
+			}
1366
+		} else {
1367
+			//not a cpt object so handled differently
1368
+			$has_cap = false;
1369
+			try {
1370
+				$has_cap = method_exists($obj, 'wp_user')
1371
+						   && $obj->wp_user()
1372
+						   && $obj->wp_user() === $user_id;
1373
+			} catch (Exception $e) {
1374
+				if (WP_DEBUG) {
1375
+					EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1376
+				}
1377
+			}
1378
+			if (! $has_cap) {
1379
+				if (! empty($this->private_cap)) {
1380
+					$caps[] = $this->private_cap;
1381
+				}
1382
+				if (! empty($this->others_cap)) {
1383
+					$caps[] = $this->others_cap;
1384
+				}
1385
+			}
1386
+		}
1387
+		return $caps;
1388
+	}
1389 1389
 }
1390 1390
 
1391 1391
 
@@ -1402,56 +1402,56 @@  discard block
 block discarded – undo
1402 1402
 class EE_Meta_Capability_Map_Messages_Cap extends EE_Meta_Capability_Map
1403 1403
 {
1404 1404
 
1405
-    /**
1406
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1407
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1408
-     *
1409
-     * @since 4.5.0
1410
-     * @see   wp-includes/capabilities.php
1411
-     *
1412
-     * @param array  $caps    actual users capabilities
1413
-     * @param string $cap     initial capability name that is being checked (the "map" key)
1414
-     * @param int    $user_id The user id
1415
-     * @param array  $args    Adds context to the cap. Typically the object ID.
1416
-     *
1417
-     * @return array   actual users capabilities
1418
-     */
1419
-    protected function _map_meta_caps($caps, $cap, $user_id, $args)
1420
-    {
1421
-        //only process if we're checking our mapped_cap
1422
-        if ($cap !== $this->meta_cap) {
1423
-            return $caps;
1424
-        }
1425
-
1426
-        //okay it is a meta cap so let's first remove that cap from the $caps array.
1427
-        if (($key = array_search($cap, $caps)) !== false) {
1428
-            unset($caps[$key]);
1429
-        }
1430
-
1431
-        //cast $user_id to int for later explicit comparisons
1432
-        $user_id = (int) $user_id;
1433
-
1434
-        $obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1435
-        //if no obj then let's just do cap
1436
-        if (! $obj instanceof EE_Message_Template_Group) {
1437
-            $caps[] = 'do_not_allow';
1438
-            return $caps;
1439
-        }
1440
-        $caps[] = $cap . 's';
1441
-        $is_global = $obj->is_global();
1442
-        if ($obj->wp_user() && $obj->wp_user() === $user_id) {
1443
-            if ($is_global) {
1444
-                $caps[] = $this->private_cap;
1445
-            }
1446
-        } else {
1447
-            if ($is_global) {
1448
-                $caps[] = $this->private_cap;
1449
-            } else {
1450
-                $caps[] = $this->others_cap;
1451
-            }
1452
-        }
1453
-        return $caps;
1454
-    }
1405
+	/**
1406
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1407
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1408
+	 *
1409
+	 * @since 4.5.0
1410
+	 * @see   wp-includes/capabilities.php
1411
+	 *
1412
+	 * @param array  $caps    actual users capabilities
1413
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
1414
+	 * @param int    $user_id The user id
1415
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
1416
+	 *
1417
+	 * @return array   actual users capabilities
1418
+	 */
1419
+	protected function _map_meta_caps($caps, $cap, $user_id, $args)
1420
+	{
1421
+		//only process if we're checking our mapped_cap
1422
+		if ($cap !== $this->meta_cap) {
1423
+			return $caps;
1424
+		}
1425
+
1426
+		//okay it is a meta cap so let's first remove that cap from the $caps array.
1427
+		if (($key = array_search($cap, $caps)) !== false) {
1428
+			unset($caps[$key]);
1429
+		}
1430
+
1431
+		//cast $user_id to int for later explicit comparisons
1432
+		$user_id = (int) $user_id;
1433
+
1434
+		$obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1435
+		//if no obj then let's just do cap
1436
+		if (! $obj instanceof EE_Message_Template_Group) {
1437
+			$caps[] = 'do_not_allow';
1438
+			return $caps;
1439
+		}
1440
+		$caps[] = $cap . 's';
1441
+		$is_global = $obj->is_global();
1442
+		if ($obj->wp_user() && $obj->wp_user() === $user_id) {
1443
+			if ($is_global) {
1444
+				$caps[] = $this->private_cap;
1445
+			}
1446
+		} else {
1447
+			if ($is_global) {
1448
+				$caps[] = $this->private_cap;
1449
+			} else {
1450
+				$caps[] = $this->others_cap;
1451
+			}
1452
+		}
1453
+		return $caps;
1454
+	}
1455 1455
 }
1456 1456
 
1457 1457
 
@@ -1468,40 +1468,40 @@  discard block
 block discarded – undo
1468 1468
 class EE_Meta_Capability_Map_Registration_Form_Cap extends EE_Meta_Capability_Map
1469 1469
 {
1470 1470
 
1471
-    /**
1472
-     * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1473
-     * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1474
-     *
1475
-     * @since 4.5.0
1476
-     * @see   wp-includes/capabilities.php
1477
-     * @param array  $caps    actual users capabilities
1478
-     * @param string $cap     initial capability name that is being checked (the "map" key)
1479
-     * @param int    $user_id The user id
1480
-     * @param array  $args    Adds context to the cap. Typically the object ID.
1481
-     * @return array   actual users capabilities
1482
-     */
1483
-    protected function _map_meta_caps($caps, $cap, $user_id, $args)
1484
-    {
1485
-        //only process if we're checking our mapped_cap
1486
-        if ($cap !== $this->meta_cap) {
1487
-            return $caps;
1488
-        }
1489
-        //okay it is a meta cap so let's first remove that cap from the $caps array.
1490
-        if (($key = array_search($cap, $caps)) !== false) {
1491
-            unset($caps[$key]);
1492
-        }
1493
-        $obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1494
-        //if no obj then let's just do cap
1495
-        if (! $obj instanceof EE_Base_Class) {
1496
-            $caps[] = 'do_not_allow';
1497
-            return $caps;
1498
-        }
1499
-        $caps[]    = $cap . 's';
1500
-        $is_system = $obj instanceof EE_Question_Group ? $obj->system_group() : false;
1501
-        $is_system = $obj instanceof EE_Question ? $obj->is_system_question() : $is_system;
1502
-        if ($is_system) {
1503
-            $caps[] = $this->private_cap;
1504
-        }
1505
-        return $caps;
1506
-    }
1471
+	/**
1472
+	 * This is the callback for the wp map_meta_caps() function which allows for ensuring certain caps that act as a
1473
+	 * "meta" for other caps ( i.e. ee_edit_event is a meta for ee_edit_others_events ) work as expected.
1474
+	 *
1475
+	 * @since 4.5.0
1476
+	 * @see   wp-includes/capabilities.php
1477
+	 * @param array  $caps    actual users capabilities
1478
+	 * @param string $cap     initial capability name that is being checked (the "map" key)
1479
+	 * @param int    $user_id The user id
1480
+	 * @param array  $args    Adds context to the cap. Typically the object ID.
1481
+	 * @return array   actual users capabilities
1482
+	 */
1483
+	protected function _map_meta_caps($caps, $cap, $user_id, $args)
1484
+	{
1485
+		//only process if we're checking our mapped_cap
1486
+		if ($cap !== $this->meta_cap) {
1487
+			return $caps;
1488
+		}
1489
+		//okay it is a meta cap so let's first remove that cap from the $caps array.
1490
+		if (($key = array_search($cap, $caps)) !== false) {
1491
+			unset($caps[$key]);
1492
+		}
1493
+		$obj = ! empty($args[0]) ? $this->_model->get_one_by_ID($args[0]) : null;
1494
+		//if no obj then let's just do cap
1495
+		if (! $obj instanceof EE_Base_Class) {
1496
+			$caps[] = 'do_not_allow';
1497
+			return $caps;
1498
+		}
1499
+		$caps[]    = $cap . 's';
1500
+		$is_system = $obj instanceof EE_Question_Group ? $obj->system_group() : false;
1501
+		$is_system = $obj instanceof EE_Question ? $obj->is_system_question() : $is_system;
1502
+		if ($is_system) {
1503
+			$caps[] = $this->private_cap;
1504
+		}
1505
+		return $caps;
1506
+	}
1507 1507
 }
Please login to merge, or discard this patch.
core/libraries/messages/messenger/EE_Email_messenger.class.php 2 patches
Indentation   +642 added lines, -642 removed lines patch added patch discarded remove patch
@@ -8,646 +8,646 @@
 block discarded – undo
8 8
 class EE_Email_messenger extends EE_messenger
9 9
 {
10 10
 
11
-    /**
12
-     * To field for email
13
-     * @var string
14
-     */
15
-    protected $_to = '';
16
-
17
-
18
-    /**
19
-     * CC field for email.
20
-     * @var string
21
-     */
22
-    protected $_cc = '';
23
-
24
-    /**
25
-     * From field for email
26
-     * @var string
27
-     */
28
-    protected $_from = '';
29
-
30
-
31
-    /**
32
-     * Subject field for email
33
-     * @var string
34
-     */
35
-    protected $_subject = '';
36
-
37
-
38
-    /**
39
-     * Content field for email
40
-     * @var string
41
-     */
42
-    protected $_content = '';
43
-
44
-
45
-    /**
46
-     * constructor
47
-     *
48
-     * @access public
49
-     */
50
-    public function __construct()
51
-    {
52
-        //set name and description properties
53
-        $this->name                = 'email';
54
-        $this->description         = sprintf(
55
-            esc_html__(
56
-                'This messenger delivers messages via email using the built-in %s function included with WordPress',
57
-                'event_espresso'
58
-            ),
59
-            '<code>wp_mail</code>'
60
-        );
61
-        $this->label               = array(
62
-            'singular' => esc_html__('email', 'event_espresso'),
63
-            'plural'   => esc_html__('emails', 'event_espresso'),
64
-        );
65
-        $this->activate_on_install = true;
66
-
67
-        //we're using defaults so let's call parent constructor that will take care of setting up all the other
68
-        // properties
69
-        parent::__construct();
70
-    }
71
-
72
-
73
-    /**
74
-     * see abstract declaration in parent class for details.
75
-     */
76
-    protected function _set_admin_pages()
77
-    {
78
-        $this->admin_registered_pages = array(
79
-            'events_edit' => true,
80
-        );
81
-    }
82
-
83
-
84
-    /**
85
-     * see abstract declaration in parent class for details
86
-     */
87
-    protected function _set_valid_shortcodes()
88
-    {
89
-        //remember by leaving the other fields not set, those fields will inherit the valid shortcodes from the
90
-        // message type.
91
-        $this->_valid_shortcodes = array(
92
-            'to'   => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
93
-            'cc' => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
94
-            'from' => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
95
-        );
96
-    }
97
-
98
-
99
-    /**
100
-     * see abstract declaration in parent class for details
101
-     *
102
-     * @access protected
103
-     * @return void
104
-     */
105
-    protected function _set_validator_config()
106
-    {
107
-        $valid_shortcodes = $this->get_valid_shortcodes();
108
-
109
-        $this->_validator_config = array(
110
-            'to'            => array(
111
-                'shortcodes' => $valid_shortcodes['to'],
112
-                'type'       => 'email',
113
-            ),
114
-            'cc' => array(
115
-                'shortcodes' => $valid_shortcodes['to'],
116
-                'type' => 'email',
117
-            ),
118
-            'from'          => array(
119
-                'shortcodes' => $valid_shortcodes['from'],
120
-                'type'       => 'email',
121
-            ),
122
-            'subject'       => array(
123
-                'shortcodes' => array(
124
-                    'organization',
125
-                    'primary_registration_details',
126
-                    'event_author',
127
-                    'primary_registration_details',
128
-                    'recipient_details',
129
-                ),
130
-            ),
131
-            'content'       => array(
132
-                'shortcodes' => array(
133
-                    'event_list',
134
-                    'attendee_list',
135
-                    'ticket_list',
136
-                    'organization',
137
-                    'primary_registration_details',
138
-                    'primary_registration_list',
139
-                    'event_author',
140
-                    'recipient_details',
141
-                    'recipient_list',
142
-                    'transaction',
143
-                    'messenger',
144
-                ),
145
-            ),
146
-            'attendee_list' => array(
147
-                'shortcodes' => array('attendee', 'event_list', 'ticket_list'),
148
-                'required'   => array('[ATTENDEE_LIST]'),
149
-            ),
150
-            'event_list'    => array(
151
-                'shortcodes' => array(
152
-                    'event',
153
-                    'attendee_list',
154
-                    'ticket_list',
155
-                    'venue',
156
-                    'datetime_list',
157
-                    'attendee',
158
-                    'primary_registration_details',
159
-                    'primary_registration_list',
160
-                    'event_author',
161
-                    'recipient_details',
162
-                    'recipient_list',
163
-                ),
164
-                'required'   => array('[EVENT_LIST]'),
165
-            ),
166
-            'ticket_list'   => array(
167
-                'shortcodes' => array(
168
-                    'event_list',
169
-                    'attendee_list',
170
-                    'ticket',
171
-                    'datetime_list',
172
-                    'primary_registration_details',
173
-                    'recipient_details',
174
-                ),
175
-                'required'   => array('[TICKET_LIST]'),
176
-            ),
177
-            'datetime_list' => array(
178
-                'shortcodes' => array('datetime'),
179
-                'required'   => array('[DATETIME_LIST]'),
180
-            ),
181
-        );
182
-    }
183
-
184
-
185
-    /**
186
-     * @see   parent EE_messenger class for docs
187
-     * @since 4.5.0
188
-     */
189
-    public function do_secondary_messenger_hooks($sending_messenger_name)
190
-    {
191
-        if ($sending_messenger_name = 'html') {
192
-            add_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10, 8);
193
-        }
194
-    }
195
-
196
-
197
-    public function add_email_css(
198
-        $variation_path,
199
-        $messenger,
200
-        $message_type,
201
-        $type,
202
-        $variation,
203
-        $file_extension,
204
-        $url,
205
-        EE_Messages_Template_Pack $template_pack
206
-    ) {
207
-        //prevent recursion on this callback.
208
-        remove_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10);
209
-        $variation = $this->get_variation($template_pack, $message_type, $url, 'main', $variation, false);
210
-
211
-        add_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10, 8);
212
-        return $variation;
213
-    }
214
-
215
-
216
-    /**
217
-     * See parent for details
218
-     *
219
-     * @access protected
220
-     * @return void
221
-     */
222
-    protected function _set_test_settings_fields()
223
-    {
224
-        $this->_test_settings_fields = array(
225
-            'to'      => array(
226
-                'input'      => 'text',
227
-                'label'      => esc_html__('Send a test email to', 'event_espresso'),
228
-                'type'       => 'email',
229
-                'required'   => true,
230
-                'validation' => true,
231
-                'css_class'  => 'large-text',
232
-                'format'     => '%s',
233
-                'default'    => get_bloginfo('admin_email'),
234
-            ),
235
-            'subject' => array(
236
-                'input'      => 'hidden',
237
-                'label'      => '',
238
-                'type'       => 'string',
239
-                'required'   => false,
240
-                'validation' => false,
241
-                'format'     => '%s',
242
-                'value'      => sprintf(__('Test email sent from %s', 'event_espresso'), get_bloginfo('name')),
243
-                'default'    => '',
244
-                'css_class'  => '',
245
-            ),
246
-        );
247
-    }
248
-
249
-
250
-    /**
251
-     * _set_template_fields
252
-     * This sets up the fields that a messenger requires for the message to go out.
253
-     *
254
-     * @access  protected
255
-     * @return void
256
-     */
257
-    protected function _set_template_fields()
258
-    {
259
-        // any extra template fields that are NOT used by the messenger but will get used by a messenger field for
260
-        // shortcode replacement get added to the 'extra' key in an associated array indexed by the messenger field
261
-        // they relate to.  This is important for the Messages_admin to know what fields to display to the user.
262
-        //  Also, notice that the "values" are equal to the field type that messages admin will use to know what
263
-        // kind of field to display. The values ALSO have one index labeled "shortcode".  the values in that array
264
-        // indicate which ACTUAL SHORTCODE (i.e. [SHORTCODE]) is required in order for this extra field to be
265
-        // displayed.  If the required shortcode isn't part of the shortcodes array then the field is not needed and
266
-        // will not be displayed/parsed.
267
-        $this->_template_fields = array(
268
-            'to'      => array(
269
-                'input'      => 'text',
270
-                'label'      => esc_html_x(
271
-                    'To',
272
-                    'Label for the "To" field for email addresses',
273
-                    'event_espresso'
274
-                ),
275
-                'type'       => 'string',
276
-                'required'   => true,
277
-                'validation' => true,
278
-                'css_class'  => 'large-text',
279
-                'format'     => '%s',
280
-            ),
281
-            'cc'      => array(
282
-                'input'      => 'text',
283
-                'label'      => esc_html_x(
284
-                    'CC',
285
-                    'Label for the "Carbon Copy" field used for additional email addresses',
286
-                    'event_espresso'
287
-                ),
288
-                'type'       => 'string',
289
-                'required'   => false,
290
-                'validation' => true,
291
-                'css_class'  => 'large-text',
292
-                'format'     => '%s',
293
-            ),
294
-            'from'    => array(
295
-                'input'      => 'text',
296
-                'label'      => esc_html_x(
297
-                    'From',
298
-                    'Label for the "From" field for email addresses.',
299
-                    'event_espresso'
300
-                ),
301
-                'type'       => 'string',
302
-                'required'   => true,
303
-                'validation' => true,
304
-                'css_class'  => 'large-text',
305
-                'format'     => '%s',
306
-            ),
307
-            'subject' => array(
308
-                'input'      => 'text',
309
-                'label'      => esc_html_x(
310
-                    'Subject',
311
-                    'Label for the "Subject" field (short description of contents) for emails.',
312
-                    'event_espresso'
313
-                ),
314
-                'type'       => 'string',
315
-                'required'   => true,
316
-                'validation' => true,
317
-                'css_class'  => 'large-text',
318
-                'format'     => '%s',
319
-            ),
320
-            'content' => '',
321
-            //left empty b/c it is in the "extra array" but messenger still needs needs to know this is a field.
322
-            'extra'   => array(
323
-                'content' => array(
324
-                    'main'          => array(
325
-                        'input'      => 'wp_editor',
326
-                        'label'      => esc_html__('Main Content', 'event_espresso'),
327
-                        'type'       => 'string',
328
-                        'required'   => true,
329
-                        'validation' => true,
330
-                        'format'     => '%s',
331
-                        'rows'       => '15',
332
-                    ),
333
-                    'event_list'    => array(
334
-                        'input'               => 'wp_editor',
335
-                        'label'               => '[EVENT_LIST]',
336
-                        'type'                => 'string',
337
-                        'required'            => true,
338
-                        'validation'          => true,
339
-                        'format'              => '%s',
340
-                        'rows'                => '15',
341
-                        'shortcodes_required' => array('[EVENT_LIST]'),
342
-                    ),
343
-                    'attendee_list' => array(
344
-                        'input'               => 'textarea',
345
-                        'label'               => '[ATTENDEE_LIST]',
346
-                        'type'                => 'string',
347
-                        'required'            => true,
348
-                        'validation'          => true,
349
-                        'format'              => '%s',
350
-                        'css_class'           => 'large-text',
351
-                        'rows'                => '5',
352
-                        'shortcodes_required' => array('[ATTENDEE_LIST]'),
353
-                    ),
354
-                    'ticket_list'   => array(
355
-                        'input'               => 'textarea',
356
-                        'label'               => '[TICKET_LIST]',
357
-                        'type'                => 'string',
358
-                        'required'            => true,
359
-                        'validation'          => true,
360
-                        'format'              => '%s',
361
-                        'css_class'           => 'large-text',
362
-                        'rows'                => '10',
363
-                        'shortcodes_required' => array('[TICKET_LIST]'),
364
-                    ),
365
-                    'datetime_list' => array(
366
-                        'input'               => 'textarea',
367
-                        'label'               => '[DATETIME_LIST]',
368
-                        'type'                => 'string',
369
-                        'required'            => true,
370
-                        'validation'          => true,
371
-                        'format'              => '%s',
372
-                        'css_class'           => 'large-text',
373
-                        'rows'                => '10',
374
-                        'shortcodes_required' => array('[DATETIME_LIST]'),
375
-                    ),
376
-                ),
377
-            ),
378
-        );
379
-    }
380
-
381
-
382
-    /**
383
-     * See definition of this class in parent
384
-     */
385
-    protected function _set_default_message_types()
386
-    {
387
-        $this->_default_message_types = array(
388
-            'payment',
389
-            'payment_refund',
390
-            'registration',
391
-            'not_approved_registration',
392
-            'pending_approval',
393
-        );
394
-    }
395
-
396
-
397
-    /**
398
-     * @see   definition of this class in parent
399
-     * @since 4.5.0
400
-     */
401
-    protected function _set_valid_message_types()
402
-    {
403
-        $this->_valid_message_types = array(
404
-            'payment',
405
-            'registration',
406
-            'not_approved_registration',
407
-            'declined_registration',
408
-            'cancelled_registration',
409
-            'pending_approval',
410
-            'registration_summary',
411
-            'payment_reminder',
412
-            'payment_declined',
413
-            'payment_refund',
414
-        );
415
-    }
416
-
417
-
418
-    /**
419
-     * setting up admin_settings_fields for messenger.
420
-     */
421
-    protected function _set_admin_settings_fields()
422
-    {
423
-    }
424
-
425
-    /**
426
-     * We just deliver the messages don't kill us!!
427
-     *
428
-     * @return bool|WP_Error true if message delivered, false if it didn't deliver OR bubble up any error object if
429
-     *              present.
430
-     * @throws EE_Error
431
-     * @throws \TijsVerkoyen\CssToInlineStyles\Exception
432
-     */
433
-    protected function _send_message()
434
-    {
435
-        $success = wp_mail(
436
-            html_entity_decode($this->_to, ENT_QUOTES, "UTF-8"),
437
-            stripslashes(html_entity_decode($this->_subject, ENT_QUOTES, "UTF-8")),
438
-            $this->_body(),
439
-            $this->_headers()
440
-        );
441
-        if (! $success) {
442
-            EE_Error::add_error(
443
-                sprintf(
444
-                    esc_html__(
445
-                        'The email did not send successfully.%3$sThe WordPress wp_mail function is used for sending mails but does not give any useful information when an email fails to send.%3$sIt is possible the "to" address (%1$s) or "from" address (%2$s) is invalid.%3$s',
446
-                        'event_espresso'
447
-                    ),
448
-                    $this->_to,
449
-                    $this->_from,
450
-                    '<br />'
451
-                ),
452
-                __FILE__,
453
-                __FUNCTION__,
454
-                __LINE__
455
-            );
456
-        }
457
-        return $success;
458
-    }
459
-
460
-
461
-    /**
462
-     * see parent for definition
463
-     *
464
-     * @return string html body of the message content and the related css.
465
-     * @throws EE_Error
466
-     * @throws \TijsVerkoyen\CssToInlineStyles\Exception
467
-     */
468
-    protected function _preview()
469
-    {
470
-        return $this->_body(true);
471
-    }
472
-
473
-
474
-    /**
475
-     * Setup headers for email
476
-     *
477
-     * @access protected
478
-     * @return string formatted header for email
479
-     */
480
-    protected function _headers()
481
-    {
482
-        $this->_ensure_has_from_email_address();
483
-        $from    = stripslashes_deep(html_entity_decode($this->_from, ENT_QUOTES, "UTF-8"));
484
-        $headers = array(
485
-            'MIME-Version: 1.0',
486
-            'From:' . $from,
487
-            'Reply-To:' . $from,
488
-            'Content-Type:text/html; charset=utf-8',
489
-        );
490
-
491
-        if (! empty($this->_cc)) {
492
-            $headers[] = 'cc: ' . $this->_cc;
493
-        }
494
-
495
-        //but wait!  Header's for the from is NOT reliable because some plugins don't respect From: as set in the
496
-        // header.
497
-        add_filter('wp_mail_from', array($this, 'set_from_address'), 100);
498
-        add_filter('wp_mail_from_name', array($this, 'set_from_name'), 100);
499
-        return apply_filters('FHEE__EE_Email_messenger___headers', $headers, $this->_incoming_message_type, $this);
500
-    }
501
-
502
-
503
-    /**
504
-     * This simply ensures that the from address is not empty.  If it is, then we use whatever is set as the site email
505
-     * address for the from address to avoid problems with sending emails.
506
-     */
507
-    protected function _ensure_has_from_email_address()
508
-    {
509
-        if (empty($this->_from)) {
510
-            $this->_from = get_bloginfo('admin_email');
511
-        }
512
-    }
513
-
514
-
515
-    /**
516
-     * This simply parses whatever is set as the $_from address and determines if it is in the format {name} <{email}>
517
-     * or just {email} and returns an array with the "from_name" and "from_email" as the values. Note from_name *MAY*
518
-     * be empty
519
-     *
520
-     * @since 4.3.1
521
-     * @return array
522
-     */
523
-    private function _parse_from()
524
-    {
525
-        if (strpos($this->_from, '<') !== false) {
526
-            $from_name = substr($this->_from, 0, strpos($this->_from, '<') - 1);
527
-            $from_name = str_replace('"', '', $from_name);
528
-            $from_name = trim($from_name);
529
-
530
-            $from_email = substr($this->_from, strpos($this->_from, '<') + 1);
531
-            $from_email = str_replace('>', '', $from_email);
532
-            $from_email = trim($from_email);
533
-        } elseif (trim($this->_from) !== '') {
534
-            $from_name  = '';
535
-            $from_email = trim($this->_from);
536
-        } else {
537
-            $from_name = $from_email = '';
538
-        }
539
-        return array($from_name, $from_email);
540
-    }
541
-
542
-
543
-    /**
544
-     * Callback for the wp_mail_from filter.
545
-     *
546
-     * @since 4.3.1
547
-     * @param string $from_email What the original from_email is.
548
-     * @return string
549
-     */
550
-    public function set_from_address($from_email)
551
-    {
552
-        $parsed_from = $this->_parse_from();
553
-        //includes fallback if the parsing failed.
554
-        $from_email = is_array($parsed_from) && ! empty($parsed_from[1])
555
-            ? $parsed_from[1]
556
-            : get_bloginfo('admin_email');
557
-        return $from_email;
558
-    }
559
-
560
-
561
-    /**
562
-     * Callback fro the wp_mail_from_name filter.
563
-     *
564
-     * @since 4.3.1
565
-     * @param string $from_name The original from_name.
566
-     * @return string
567
-     */
568
-    public function set_from_name($from_name)
569
-    {
570
-        $parsed_from = $this->_parse_from();
571
-        if (is_array($parsed_from) && ! empty($parsed_from[0])) {
572
-            $from_name = $parsed_from[0];
573
-        }
574
-
575
-        //if from name is "WordPress" let's sub in the site name instead (more friendly!)
576
-        $from_name = $from_name == 'WordPress' ? get_bloginfo() : $from_name;
577
-
578
-        return stripslashes_deep(html_entity_decode($from_name, ENT_QUOTES, "UTF-8"));
579
-    }
580
-
581
-
582
-    /**
583
-     * setup body for email
584
-     *
585
-     * @param bool $preview will determine whether this is preview template or not.
586
-     * @return string formatted body for email.
587
-     * @throws EE_Error
588
-     * @throws \TijsVerkoyen\CssToInlineStyles\Exception
589
-     */
590
-    protected function _body($preview = false)
591
-    {
592
-        //setup template args!
593
-        $this->_template_args = array(
594
-            'subject'   => $this->_subject,
595
-            'from'      => $this->_from,
596
-            'main_body' => wpautop(
597
-                stripslashes_deep(
598
-                    html_entity_decode($this->_content, ENT_QUOTES, "UTF-8")
599
-                )
600
-            ),
601
-        );
602
-        $body                 = $this->_get_main_template($preview);
603
-
604
-        /**
605
-         * This filter allows one to bypass the CSSToInlineStyles tool and leave the body untouched.
606
-         *
607
-         * @type    bool $preview Indicates whether a preview is being generated or not.
608
-         * @return  bool    true  indicates to use the inliner, false bypasses it.
609
-         */
610
-        if (apply_filters('FHEE__EE_Email_messenger__apply_CSSInliner ', true, $preview)) {
611
-            //require CssToInlineStyles library and its dependencies via composer autoloader
612
-            require_once EE_THIRD_PARTY . 'cssinliner/vendor/autoload.php';
613
-
614
-            //now if this isn't a preview, let's setup the body so it has inline styles
615
-            if (! $preview || ($preview && defined('DOING_AJAX'))) {
616
-                $style = file_get_contents(
617
-                    $this->get_variation(
618
-                        $this->_tmp_pack,
619
-                        $this->_incoming_message_type->name,
620
-                        false,
621
-                        'main',
622
-                        $this->_variation
623
-                    ),
624
-                    true
625
-                );
626
-                $CSS   = new TijsVerkoyen\CssToInlineStyles\CssToInlineStyles($body, $style);
627
-                //for some reason the library has a bracket and new line at the beginning.  This takes care of that.
628
-                $body  = ltrim($CSS->convert(true), ">\n");
629
-                //see https://events.codebasehq.com/projects/event-espresso/tickets/8609
630
-                $body  = ltrim($body, "<?");
631
-            }
632
-
633
-        }
634
-        return $body;
635
-    }
636
-
637
-
638
-    /**
639
-     * This just returns any existing test settings that might be saved in the database
640
-     *
641
-     * @access public
642
-     * @return array
643
-     */
644
-    public function get_existing_test_settings()
645
-    {
646
-        $settings = parent::get_existing_test_settings();
647
-        //override subject if present because we always want it to be fresh.
648
-        if (is_array($settings) && ! empty($settings['subject'])) {
649
-            $settings['subject'] = sprintf(__('Test email sent from %s', 'event_espresso'), get_bloginfo('name'));
650
-        }
651
-        return $settings;
652
-    }
11
+	/**
12
+	 * To field for email
13
+	 * @var string
14
+	 */
15
+	protected $_to = '';
16
+
17
+
18
+	/**
19
+	 * CC field for email.
20
+	 * @var string
21
+	 */
22
+	protected $_cc = '';
23
+
24
+	/**
25
+	 * From field for email
26
+	 * @var string
27
+	 */
28
+	protected $_from = '';
29
+
30
+
31
+	/**
32
+	 * Subject field for email
33
+	 * @var string
34
+	 */
35
+	protected $_subject = '';
36
+
37
+
38
+	/**
39
+	 * Content field for email
40
+	 * @var string
41
+	 */
42
+	protected $_content = '';
43
+
44
+
45
+	/**
46
+	 * constructor
47
+	 *
48
+	 * @access public
49
+	 */
50
+	public function __construct()
51
+	{
52
+		//set name and description properties
53
+		$this->name                = 'email';
54
+		$this->description         = sprintf(
55
+			esc_html__(
56
+				'This messenger delivers messages via email using the built-in %s function included with WordPress',
57
+				'event_espresso'
58
+			),
59
+			'<code>wp_mail</code>'
60
+		);
61
+		$this->label               = array(
62
+			'singular' => esc_html__('email', 'event_espresso'),
63
+			'plural'   => esc_html__('emails', 'event_espresso'),
64
+		);
65
+		$this->activate_on_install = true;
66
+
67
+		//we're using defaults so let's call parent constructor that will take care of setting up all the other
68
+		// properties
69
+		parent::__construct();
70
+	}
71
+
72
+
73
+	/**
74
+	 * see abstract declaration in parent class for details.
75
+	 */
76
+	protected function _set_admin_pages()
77
+	{
78
+		$this->admin_registered_pages = array(
79
+			'events_edit' => true,
80
+		);
81
+	}
82
+
83
+
84
+	/**
85
+	 * see abstract declaration in parent class for details
86
+	 */
87
+	protected function _set_valid_shortcodes()
88
+	{
89
+		//remember by leaving the other fields not set, those fields will inherit the valid shortcodes from the
90
+		// message type.
91
+		$this->_valid_shortcodes = array(
92
+			'to'   => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
93
+			'cc' => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
94
+			'from' => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
95
+		);
96
+	}
97
+
98
+
99
+	/**
100
+	 * see abstract declaration in parent class for details
101
+	 *
102
+	 * @access protected
103
+	 * @return void
104
+	 */
105
+	protected function _set_validator_config()
106
+	{
107
+		$valid_shortcodes = $this->get_valid_shortcodes();
108
+
109
+		$this->_validator_config = array(
110
+			'to'            => array(
111
+				'shortcodes' => $valid_shortcodes['to'],
112
+				'type'       => 'email',
113
+			),
114
+			'cc' => array(
115
+				'shortcodes' => $valid_shortcodes['to'],
116
+				'type' => 'email',
117
+			),
118
+			'from'          => array(
119
+				'shortcodes' => $valid_shortcodes['from'],
120
+				'type'       => 'email',
121
+			),
122
+			'subject'       => array(
123
+				'shortcodes' => array(
124
+					'organization',
125
+					'primary_registration_details',
126
+					'event_author',
127
+					'primary_registration_details',
128
+					'recipient_details',
129
+				),
130
+			),
131
+			'content'       => array(
132
+				'shortcodes' => array(
133
+					'event_list',
134
+					'attendee_list',
135
+					'ticket_list',
136
+					'organization',
137
+					'primary_registration_details',
138
+					'primary_registration_list',
139
+					'event_author',
140
+					'recipient_details',
141
+					'recipient_list',
142
+					'transaction',
143
+					'messenger',
144
+				),
145
+			),
146
+			'attendee_list' => array(
147
+				'shortcodes' => array('attendee', 'event_list', 'ticket_list'),
148
+				'required'   => array('[ATTENDEE_LIST]'),
149
+			),
150
+			'event_list'    => array(
151
+				'shortcodes' => array(
152
+					'event',
153
+					'attendee_list',
154
+					'ticket_list',
155
+					'venue',
156
+					'datetime_list',
157
+					'attendee',
158
+					'primary_registration_details',
159
+					'primary_registration_list',
160
+					'event_author',
161
+					'recipient_details',
162
+					'recipient_list',
163
+				),
164
+				'required'   => array('[EVENT_LIST]'),
165
+			),
166
+			'ticket_list'   => array(
167
+				'shortcodes' => array(
168
+					'event_list',
169
+					'attendee_list',
170
+					'ticket',
171
+					'datetime_list',
172
+					'primary_registration_details',
173
+					'recipient_details',
174
+				),
175
+				'required'   => array('[TICKET_LIST]'),
176
+			),
177
+			'datetime_list' => array(
178
+				'shortcodes' => array('datetime'),
179
+				'required'   => array('[DATETIME_LIST]'),
180
+			),
181
+		);
182
+	}
183
+
184
+
185
+	/**
186
+	 * @see   parent EE_messenger class for docs
187
+	 * @since 4.5.0
188
+	 */
189
+	public function do_secondary_messenger_hooks($sending_messenger_name)
190
+	{
191
+		if ($sending_messenger_name = 'html') {
192
+			add_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10, 8);
193
+		}
194
+	}
195
+
196
+
197
+	public function add_email_css(
198
+		$variation_path,
199
+		$messenger,
200
+		$message_type,
201
+		$type,
202
+		$variation,
203
+		$file_extension,
204
+		$url,
205
+		EE_Messages_Template_Pack $template_pack
206
+	) {
207
+		//prevent recursion on this callback.
208
+		remove_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10);
209
+		$variation = $this->get_variation($template_pack, $message_type, $url, 'main', $variation, false);
210
+
211
+		add_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10, 8);
212
+		return $variation;
213
+	}
214
+
215
+
216
+	/**
217
+	 * See parent for details
218
+	 *
219
+	 * @access protected
220
+	 * @return void
221
+	 */
222
+	protected function _set_test_settings_fields()
223
+	{
224
+		$this->_test_settings_fields = array(
225
+			'to'      => array(
226
+				'input'      => 'text',
227
+				'label'      => esc_html__('Send a test email to', 'event_espresso'),
228
+				'type'       => 'email',
229
+				'required'   => true,
230
+				'validation' => true,
231
+				'css_class'  => 'large-text',
232
+				'format'     => '%s',
233
+				'default'    => get_bloginfo('admin_email'),
234
+			),
235
+			'subject' => array(
236
+				'input'      => 'hidden',
237
+				'label'      => '',
238
+				'type'       => 'string',
239
+				'required'   => false,
240
+				'validation' => false,
241
+				'format'     => '%s',
242
+				'value'      => sprintf(__('Test email sent from %s', 'event_espresso'), get_bloginfo('name')),
243
+				'default'    => '',
244
+				'css_class'  => '',
245
+			),
246
+		);
247
+	}
248
+
249
+
250
+	/**
251
+	 * _set_template_fields
252
+	 * This sets up the fields that a messenger requires for the message to go out.
253
+	 *
254
+	 * @access  protected
255
+	 * @return void
256
+	 */
257
+	protected function _set_template_fields()
258
+	{
259
+		// any extra template fields that are NOT used by the messenger but will get used by a messenger field for
260
+		// shortcode replacement get added to the 'extra' key in an associated array indexed by the messenger field
261
+		// they relate to.  This is important for the Messages_admin to know what fields to display to the user.
262
+		//  Also, notice that the "values" are equal to the field type that messages admin will use to know what
263
+		// kind of field to display. The values ALSO have one index labeled "shortcode".  the values in that array
264
+		// indicate which ACTUAL SHORTCODE (i.e. [SHORTCODE]) is required in order for this extra field to be
265
+		// displayed.  If the required shortcode isn't part of the shortcodes array then the field is not needed and
266
+		// will not be displayed/parsed.
267
+		$this->_template_fields = array(
268
+			'to'      => array(
269
+				'input'      => 'text',
270
+				'label'      => esc_html_x(
271
+					'To',
272
+					'Label for the "To" field for email addresses',
273
+					'event_espresso'
274
+				),
275
+				'type'       => 'string',
276
+				'required'   => true,
277
+				'validation' => true,
278
+				'css_class'  => 'large-text',
279
+				'format'     => '%s',
280
+			),
281
+			'cc'      => array(
282
+				'input'      => 'text',
283
+				'label'      => esc_html_x(
284
+					'CC',
285
+					'Label for the "Carbon Copy" field used for additional email addresses',
286
+					'event_espresso'
287
+				),
288
+				'type'       => 'string',
289
+				'required'   => false,
290
+				'validation' => true,
291
+				'css_class'  => 'large-text',
292
+				'format'     => '%s',
293
+			),
294
+			'from'    => array(
295
+				'input'      => 'text',
296
+				'label'      => esc_html_x(
297
+					'From',
298
+					'Label for the "From" field for email addresses.',
299
+					'event_espresso'
300
+				),
301
+				'type'       => 'string',
302
+				'required'   => true,
303
+				'validation' => true,
304
+				'css_class'  => 'large-text',
305
+				'format'     => '%s',
306
+			),
307
+			'subject' => array(
308
+				'input'      => 'text',
309
+				'label'      => esc_html_x(
310
+					'Subject',
311
+					'Label for the "Subject" field (short description of contents) for emails.',
312
+					'event_espresso'
313
+				),
314
+				'type'       => 'string',
315
+				'required'   => true,
316
+				'validation' => true,
317
+				'css_class'  => 'large-text',
318
+				'format'     => '%s',
319
+			),
320
+			'content' => '',
321
+			//left empty b/c it is in the "extra array" but messenger still needs needs to know this is a field.
322
+			'extra'   => array(
323
+				'content' => array(
324
+					'main'          => array(
325
+						'input'      => 'wp_editor',
326
+						'label'      => esc_html__('Main Content', 'event_espresso'),
327
+						'type'       => 'string',
328
+						'required'   => true,
329
+						'validation' => true,
330
+						'format'     => '%s',
331
+						'rows'       => '15',
332
+					),
333
+					'event_list'    => array(
334
+						'input'               => 'wp_editor',
335
+						'label'               => '[EVENT_LIST]',
336
+						'type'                => 'string',
337
+						'required'            => true,
338
+						'validation'          => true,
339
+						'format'              => '%s',
340
+						'rows'                => '15',
341
+						'shortcodes_required' => array('[EVENT_LIST]'),
342
+					),
343
+					'attendee_list' => array(
344
+						'input'               => 'textarea',
345
+						'label'               => '[ATTENDEE_LIST]',
346
+						'type'                => 'string',
347
+						'required'            => true,
348
+						'validation'          => true,
349
+						'format'              => '%s',
350
+						'css_class'           => 'large-text',
351
+						'rows'                => '5',
352
+						'shortcodes_required' => array('[ATTENDEE_LIST]'),
353
+					),
354
+					'ticket_list'   => array(
355
+						'input'               => 'textarea',
356
+						'label'               => '[TICKET_LIST]',
357
+						'type'                => 'string',
358
+						'required'            => true,
359
+						'validation'          => true,
360
+						'format'              => '%s',
361
+						'css_class'           => 'large-text',
362
+						'rows'                => '10',
363
+						'shortcodes_required' => array('[TICKET_LIST]'),
364
+					),
365
+					'datetime_list' => array(
366
+						'input'               => 'textarea',
367
+						'label'               => '[DATETIME_LIST]',
368
+						'type'                => 'string',
369
+						'required'            => true,
370
+						'validation'          => true,
371
+						'format'              => '%s',
372
+						'css_class'           => 'large-text',
373
+						'rows'                => '10',
374
+						'shortcodes_required' => array('[DATETIME_LIST]'),
375
+					),
376
+				),
377
+			),
378
+		);
379
+	}
380
+
381
+
382
+	/**
383
+	 * See definition of this class in parent
384
+	 */
385
+	protected function _set_default_message_types()
386
+	{
387
+		$this->_default_message_types = array(
388
+			'payment',
389
+			'payment_refund',
390
+			'registration',
391
+			'not_approved_registration',
392
+			'pending_approval',
393
+		);
394
+	}
395
+
396
+
397
+	/**
398
+	 * @see   definition of this class in parent
399
+	 * @since 4.5.0
400
+	 */
401
+	protected function _set_valid_message_types()
402
+	{
403
+		$this->_valid_message_types = array(
404
+			'payment',
405
+			'registration',
406
+			'not_approved_registration',
407
+			'declined_registration',
408
+			'cancelled_registration',
409
+			'pending_approval',
410
+			'registration_summary',
411
+			'payment_reminder',
412
+			'payment_declined',
413
+			'payment_refund',
414
+		);
415
+	}
416
+
417
+
418
+	/**
419
+	 * setting up admin_settings_fields for messenger.
420
+	 */
421
+	protected function _set_admin_settings_fields()
422
+	{
423
+	}
424
+
425
+	/**
426
+	 * We just deliver the messages don't kill us!!
427
+	 *
428
+	 * @return bool|WP_Error true if message delivered, false if it didn't deliver OR bubble up any error object if
429
+	 *              present.
430
+	 * @throws EE_Error
431
+	 * @throws \TijsVerkoyen\CssToInlineStyles\Exception
432
+	 */
433
+	protected function _send_message()
434
+	{
435
+		$success = wp_mail(
436
+			html_entity_decode($this->_to, ENT_QUOTES, "UTF-8"),
437
+			stripslashes(html_entity_decode($this->_subject, ENT_QUOTES, "UTF-8")),
438
+			$this->_body(),
439
+			$this->_headers()
440
+		);
441
+		if (! $success) {
442
+			EE_Error::add_error(
443
+				sprintf(
444
+					esc_html__(
445
+						'The email did not send successfully.%3$sThe WordPress wp_mail function is used for sending mails but does not give any useful information when an email fails to send.%3$sIt is possible the "to" address (%1$s) or "from" address (%2$s) is invalid.%3$s',
446
+						'event_espresso'
447
+					),
448
+					$this->_to,
449
+					$this->_from,
450
+					'<br />'
451
+				),
452
+				__FILE__,
453
+				__FUNCTION__,
454
+				__LINE__
455
+			);
456
+		}
457
+		return $success;
458
+	}
459
+
460
+
461
+	/**
462
+	 * see parent for definition
463
+	 *
464
+	 * @return string html body of the message content and the related css.
465
+	 * @throws EE_Error
466
+	 * @throws \TijsVerkoyen\CssToInlineStyles\Exception
467
+	 */
468
+	protected function _preview()
469
+	{
470
+		return $this->_body(true);
471
+	}
472
+
473
+
474
+	/**
475
+	 * Setup headers for email
476
+	 *
477
+	 * @access protected
478
+	 * @return string formatted header for email
479
+	 */
480
+	protected function _headers()
481
+	{
482
+		$this->_ensure_has_from_email_address();
483
+		$from    = stripslashes_deep(html_entity_decode($this->_from, ENT_QUOTES, "UTF-8"));
484
+		$headers = array(
485
+			'MIME-Version: 1.0',
486
+			'From:' . $from,
487
+			'Reply-To:' . $from,
488
+			'Content-Type:text/html; charset=utf-8',
489
+		);
490
+
491
+		if (! empty($this->_cc)) {
492
+			$headers[] = 'cc: ' . $this->_cc;
493
+		}
494
+
495
+		//but wait!  Header's for the from is NOT reliable because some plugins don't respect From: as set in the
496
+		// header.
497
+		add_filter('wp_mail_from', array($this, 'set_from_address'), 100);
498
+		add_filter('wp_mail_from_name', array($this, 'set_from_name'), 100);
499
+		return apply_filters('FHEE__EE_Email_messenger___headers', $headers, $this->_incoming_message_type, $this);
500
+	}
501
+
502
+
503
+	/**
504
+	 * This simply ensures that the from address is not empty.  If it is, then we use whatever is set as the site email
505
+	 * address for the from address to avoid problems with sending emails.
506
+	 */
507
+	protected function _ensure_has_from_email_address()
508
+	{
509
+		if (empty($this->_from)) {
510
+			$this->_from = get_bloginfo('admin_email');
511
+		}
512
+	}
513
+
514
+
515
+	/**
516
+	 * This simply parses whatever is set as the $_from address and determines if it is in the format {name} <{email}>
517
+	 * or just {email} and returns an array with the "from_name" and "from_email" as the values. Note from_name *MAY*
518
+	 * be empty
519
+	 *
520
+	 * @since 4.3.1
521
+	 * @return array
522
+	 */
523
+	private function _parse_from()
524
+	{
525
+		if (strpos($this->_from, '<') !== false) {
526
+			$from_name = substr($this->_from, 0, strpos($this->_from, '<') - 1);
527
+			$from_name = str_replace('"', '', $from_name);
528
+			$from_name = trim($from_name);
529
+
530
+			$from_email = substr($this->_from, strpos($this->_from, '<') + 1);
531
+			$from_email = str_replace('>', '', $from_email);
532
+			$from_email = trim($from_email);
533
+		} elseif (trim($this->_from) !== '') {
534
+			$from_name  = '';
535
+			$from_email = trim($this->_from);
536
+		} else {
537
+			$from_name = $from_email = '';
538
+		}
539
+		return array($from_name, $from_email);
540
+	}
541
+
542
+
543
+	/**
544
+	 * Callback for the wp_mail_from filter.
545
+	 *
546
+	 * @since 4.3.1
547
+	 * @param string $from_email What the original from_email is.
548
+	 * @return string
549
+	 */
550
+	public function set_from_address($from_email)
551
+	{
552
+		$parsed_from = $this->_parse_from();
553
+		//includes fallback if the parsing failed.
554
+		$from_email = is_array($parsed_from) && ! empty($parsed_from[1])
555
+			? $parsed_from[1]
556
+			: get_bloginfo('admin_email');
557
+		return $from_email;
558
+	}
559
+
560
+
561
+	/**
562
+	 * Callback fro the wp_mail_from_name filter.
563
+	 *
564
+	 * @since 4.3.1
565
+	 * @param string $from_name The original from_name.
566
+	 * @return string
567
+	 */
568
+	public function set_from_name($from_name)
569
+	{
570
+		$parsed_from = $this->_parse_from();
571
+		if (is_array($parsed_from) && ! empty($parsed_from[0])) {
572
+			$from_name = $parsed_from[0];
573
+		}
574
+
575
+		//if from name is "WordPress" let's sub in the site name instead (more friendly!)
576
+		$from_name = $from_name == 'WordPress' ? get_bloginfo() : $from_name;
577
+
578
+		return stripslashes_deep(html_entity_decode($from_name, ENT_QUOTES, "UTF-8"));
579
+	}
580
+
581
+
582
+	/**
583
+	 * setup body for email
584
+	 *
585
+	 * @param bool $preview will determine whether this is preview template or not.
586
+	 * @return string formatted body for email.
587
+	 * @throws EE_Error
588
+	 * @throws \TijsVerkoyen\CssToInlineStyles\Exception
589
+	 */
590
+	protected function _body($preview = false)
591
+	{
592
+		//setup template args!
593
+		$this->_template_args = array(
594
+			'subject'   => $this->_subject,
595
+			'from'      => $this->_from,
596
+			'main_body' => wpautop(
597
+				stripslashes_deep(
598
+					html_entity_decode($this->_content, ENT_QUOTES, "UTF-8")
599
+				)
600
+			),
601
+		);
602
+		$body                 = $this->_get_main_template($preview);
603
+
604
+		/**
605
+		 * This filter allows one to bypass the CSSToInlineStyles tool and leave the body untouched.
606
+		 *
607
+		 * @type    bool $preview Indicates whether a preview is being generated or not.
608
+		 * @return  bool    true  indicates to use the inliner, false bypasses it.
609
+		 */
610
+		if (apply_filters('FHEE__EE_Email_messenger__apply_CSSInliner ', true, $preview)) {
611
+			//require CssToInlineStyles library and its dependencies via composer autoloader
612
+			require_once EE_THIRD_PARTY . 'cssinliner/vendor/autoload.php';
613
+
614
+			//now if this isn't a preview, let's setup the body so it has inline styles
615
+			if (! $preview || ($preview && defined('DOING_AJAX'))) {
616
+				$style = file_get_contents(
617
+					$this->get_variation(
618
+						$this->_tmp_pack,
619
+						$this->_incoming_message_type->name,
620
+						false,
621
+						'main',
622
+						$this->_variation
623
+					),
624
+					true
625
+				);
626
+				$CSS   = new TijsVerkoyen\CssToInlineStyles\CssToInlineStyles($body, $style);
627
+				//for some reason the library has a bracket and new line at the beginning.  This takes care of that.
628
+				$body  = ltrim($CSS->convert(true), ">\n");
629
+				//see https://events.codebasehq.com/projects/event-espresso/tickets/8609
630
+				$body  = ltrim($body, "<?");
631
+			}
632
+
633
+		}
634
+		return $body;
635
+	}
636
+
637
+
638
+	/**
639
+	 * This just returns any existing test settings that might be saved in the database
640
+	 *
641
+	 * @access public
642
+	 * @return array
643
+	 */
644
+	public function get_existing_test_settings()
645
+	{
646
+		$settings = parent::get_existing_test_settings();
647
+		//override subject if present because we always want it to be fresh.
648
+		if (is_array($settings) && ! empty($settings['subject'])) {
649
+			$settings['subject'] = sprintf(__('Test email sent from %s', 'event_espresso'), get_bloginfo('name'));
650
+		}
651
+		return $settings;
652
+	}
653 653
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -58,7 +58,7 @@  discard block
 block discarded – undo
58 58
             ),
59 59
             '<code>wp_mail</code>'
60 60
         );
61
-        $this->label               = array(
61
+        $this->label = array(
62 62
             'singular' => esc_html__('email', 'event_espresso'),
63 63
             'plural'   => esc_html__('emails', 'event_espresso'),
64 64
         );
@@ -438,7 +438,7 @@  discard block
 block discarded – undo
438 438
             $this->_body(),
439 439
             $this->_headers()
440 440
         );
441
-        if (! $success) {
441
+        if ( ! $success) {
442 442
             EE_Error::add_error(
443 443
                 sprintf(
444 444
                     esc_html__(
@@ -483,13 +483,13 @@  discard block
 block discarded – undo
483 483
         $from    = stripslashes_deep(html_entity_decode($this->_from, ENT_QUOTES, "UTF-8"));
484 484
         $headers = array(
485 485
             'MIME-Version: 1.0',
486
-            'From:' . $from,
487
-            'Reply-To:' . $from,
486
+            'From:'.$from,
487
+            'Reply-To:'.$from,
488 488
             'Content-Type:text/html; charset=utf-8',
489 489
         );
490 490
 
491
-        if (! empty($this->_cc)) {
492
-            $headers[] = 'cc: ' . $this->_cc;
491
+        if ( ! empty($this->_cc)) {
492
+            $headers[] = 'cc: '.$this->_cc;
493 493
         }
494 494
 
495 495
         //but wait!  Header's for the from is NOT reliable because some plugins don't respect From: as set in the
@@ -599,7 +599,7 @@  discard block
 block discarded – undo
599 599
                 )
600 600
             ),
601 601
         );
602
-        $body                 = $this->_get_main_template($preview);
602
+        $body = $this->_get_main_template($preview);
603 603
 
604 604
         /**
605 605
          * This filter allows one to bypass the CSSToInlineStyles tool and leave the body untouched.
@@ -609,10 +609,10 @@  discard block
 block discarded – undo
609 609
          */
610 610
         if (apply_filters('FHEE__EE_Email_messenger__apply_CSSInliner ', true, $preview)) {
611 611
             //require CssToInlineStyles library and its dependencies via composer autoloader
612
-            require_once EE_THIRD_PARTY . 'cssinliner/vendor/autoload.php';
612
+            require_once EE_THIRD_PARTY.'cssinliner/vendor/autoload.php';
613 613
 
614 614
             //now if this isn't a preview, let's setup the body so it has inline styles
615
-            if (! $preview || ($preview && defined('DOING_AJAX'))) {
615
+            if ( ! $preview || ($preview && defined('DOING_AJAX'))) {
616 616
                 $style = file_get_contents(
617 617
                     $this->get_variation(
618 618
                         $this->_tmp_pack,
Please login to merge, or discard this patch.
admin/extend/registrations/Extend_Registrations_Admin_Page.core.php 1 patch
Indentation   +1173 added lines, -1173 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,1177 +17,1177 @@  discard block
 block discarded – undo
17 17
 {
18 18
 
19 19
 
20
-    /**
21
-     * This is used to hold the reports template data which is setup early in the request.
22
-     *
23
-     * @type array
24
-     */
25
-    protected $_reports_template_data = array();
26
-
27
-
28
-
29
-    /**
30
-     * Extend_Registrations_Admin_Page constructor.
31
-     *
32
-     * @param bool $routing
33
-     */
34
-    public function __construct($routing = true)
35
-    {
36
-        parent::__construct($routing);
37
-        if ( ! defined('REG_CAF_TEMPLATE_PATH')) {
38
-            define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
39
-            define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
40
-            define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
41
-        }
42
-    }
43
-
44
-
45
-
46
-    protected function _extend_page_config()
47
-    {
48
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
49
-        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
50
-            ? $this->_req_data['_REG_ID']
51
-            : 0;
52
-        // $att_id = ! empty( $this->_req_data['ATT_ID'] ) ? ! is_array( $this->_req_data['ATT_ID'] ) : 0;
53
-        // $att_id = ! empty( $this->_req_data['post'] ) && ! is_array( $this->_req_data['post'] )
54
-        // 	? $this->_req_data['post'] : $att_id;
55
-        $new_page_routes = array(
56
-            'reports'                  => array(
57
-                'func'       => '_registration_reports',
58
-                'capability' => 'ee_read_registrations',
59
-            ),
60
-            'registration_checkins'    => array(
61
-                'func'       => '_registration_checkin_list_table',
62
-                'capability' => 'ee_read_checkins',
63
-            ),
64
-            'newsletter_selected_send' => array(
65
-                'func'       => '_newsletter_selected_send',
66
-                'noheader'   => true,
67
-                'capability' => 'ee_send_message',
68
-            ),
69
-            'delete_checkin_rows'      => array(
70
-                'func'       => '_delete_checkin_rows',
71
-                'noheader'   => true,
72
-                'capability' => 'ee_delete_checkins',
73
-            ),
74
-            'delete_checkin_row'       => array(
75
-                'func'       => '_delete_checkin_row',
76
-                'noheader'   => true,
77
-                'capability' => 'ee_delete_checkin',
78
-                'obj_id'     => $reg_id,
79
-            ),
80
-            'toggle_checkin_status'    => array(
81
-                'func'       => '_toggle_checkin_status',
82
-                'noheader'   => true,
83
-                'capability' => 'ee_edit_checkin',
84
-                'obj_id'     => $reg_id,
85
-            ),
86
-            'toggle_checkin_status_bulk' => array(
87
-                'func' => '_toggle_checkin_status',
88
-                'noheader' => true,
89
-                'capability' => 'ee_edit_checkins'
90
-            ),
91
-            'event_registrations'      => array(
92
-                'func'       => '_event_registrations_list_table',
93
-                'capability' => 'ee_read_checkins',
94
-            ),
95
-            'registrations_checkin_report' => array(
96
-                'func'       => '_registrations_checkin_report',
97
-                'noheader'   => true,
98
-                'capability' => 'ee_read_registrations',
99
-            ),
100
-        );
101
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
102
-        $new_page_config = array(
103
-            'reports'               => array(
104
-                'nav'           => array(
105
-                    'label' => __('Reports', 'event_espresso'),
106
-                    'order' => 30,
107
-                ),
108
-                'help_tabs'     => array(
109
-                    'registrations_reports_help_tab' => array(
110
-                        'title'    => __('Registration Reports', 'event_espresso'),
111
-                        'filename' => 'registrations_reports',
112
-                    ),
113
-                ),
114
-                /*'help_tour' => array( 'Registration_Reports_Help_Tour' ),*/
115
-                'require_nonce' => false,
116
-            ),
117
-            'event_registrations'   => array(
118
-                'nav'           => array(
119
-                    'label'      => __('Event Check-In', 'event_espresso'),
120
-                    'order'      => 10,
121
-                    'persistent' => true,
122
-                ),
123
-                'help_tabs'     => array(
124
-                    'registrations_event_checkin_help_tab'                       => array(
125
-                        'title'    => __('Registrations Event Check-In', 'event_espresso'),
126
-                        'filename' => 'registrations_event_checkin',
127
-                    ),
128
-                    'registrations_event_checkin_table_column_headings_help_tab' => array(
129
-                        'title'    => __('Event Check-In Table Column Headings', 'event_espresso'),
130
-                        'filename' => 'registrations_event_checkin_table_column_headings',
131
-                    ),
132
-                    'registrations_event_checkin_filters_help_tab'               => array(
133
-                        'title'    => __('Event Check-In Filters', 'event_espresso'),
134
-                        'filename' => 'registrations_event_checkin_filters',
135
-                    ),
136
-                    'registrations_event_checkin_views_help_tab'                 => array(
137
-                        'title'    => __('Event Check-In Views', 'event_espresso'),
138
-                        'filename' => 'registrations_event_checkin_views',
139
-                    ),
140
-                    'registrations_event_checkin_other_help_tab'                 => array(
141
-                        'title'    => __('Event Check-In Other', 'event_espresso'),
142
-                        'filename' => 'registrations_event_checkin_other',
143
-                    ),
144
-                ),
145
-                'help_tour'     => array('Event_Checkin_Help_Tour'),
146
-                'qtips'         => array('Registration_List_Table_Tips'),
147
-                'list_table'    => 'EE_Event_Registrations_List_Table',
148
-                'metaboxes'     => array(),
149
-                'require_nonce' => false,
150
-            ),
151
-            'registration_checkins' => array(
152
-                'nav'           => array(
153
-                    'label'      => __('Check-In Records', 'event_espresso'),
154
-                    'order'      => 15,
155
-                    'persistent' => false,
156
-                ),
157
-                'list_table'    => 'EE_Registration_CheckIn_List_Table',
158
-                //'help_tour' => array( 'Checkin_Toggle_View_Help_Tour' ),
159
-                'metaboxes'     => array(),
160
-                'require_nonce' => false,
161
-            ),
162
-        );
163
-        $this->_page_config = array_merge($this->_page_config, $new_page_config);
164
-        $this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table';
165
-        $this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table';
166
-    }
167
-
168
-
169
-
170
-    protected function _ajax_hooks()
171
-    {
172
-        parent::_ajax_hooks();
173
-        add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content'));
174
-    }
175
-
176
-
177
-
178
-    public function load_scripts_styles()
179
-    {
180
-        parent::load_scripts_styles();
181
-        //if newsletter message type is active then let's add filter and load js for it.
182
-        if (EEH_MSG_Template::is_mt_active('newsletter')) {
183
-            //enqueue newsletter js
184
-            wp_enqueue_script(
185
-                'ee-newsletter-trigger',
186
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
187
-                array('ee-dialog'),
188
-                EVENT_ESPRESSO_VERSION,
189
-                true
190
-            );
191
-            wp_enqueue_style(
192
-                'ee-newsletter-trigger-css',
193
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
194
-                array(),
195
-                EVENT_ESPRESSO_VERSION
196
-            );
197
-            //hook in buttons for newsletter message type trigger.
198
-            add_action(
199
-                'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
200
-                array($this, 'add_newsletter_action_buttons'),
201
-                10
202
-            );
203
-        }
204
-    }
205
-
206
-
207
-
208
-    public function load_scripts_styles_reports()
209
-    {
210
-        wp_register_script(
211
-            'ee-reg-reports-js',
212
-            REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
213
-            array('google-charts'),
214
-            EVENT_ESPRESSO_VERSION,
215
-            true
216
-        );
217
-        wp_enqueue_script('ee-reg-reports-js');
218
-        $this->_registration_reports_js_setup();
219
-    }
220
-
221
-
222
-
223
-    protected function _add_screen_options_event_registrations()
224
-    {
225
-        $this->_per_page_screen_option();
226
-    }
227
-
228
-
229
-
230
-    protected function _add_screen_options_registration_checkins()
231
-    {
232
-        $page_title = $this->_admin_page_title;
233
-        $this->_admin_page_title = __('Check-In Records', 'event_espresso');
234
-        $this->_per_page_screen_option();
235
-        $this->_admin_page_title = $page_title;
236
-    }
237
-
238
-
239
-
240
-    protected function _set_list_table_views_event_registrations()
241
-    {
242
-        $this->_views = array(
243
-            'all' => array(
244
-                'slug'        => 'all',
245
-                'label'       => __('All', 'event_espresso'),
246
-                'count'       => 0,
247
-                'bulk_action' => ! isset($this->_req_data['event_id'])
248
-                    ? array()
249
-                    : array(
250
-                        'toggle_checkin_status_bulk' => __('Toggle Check-In', 'event_espresso'),
251
-                    ),
252
-            ),
253
-        );
254
-    }
255
-
256
-
257
-
258
-    protected function _set_list_table_views_registration_checkins()
259
-    {
260
-        $this->_views = array(
261
-            'all' => array(
262
-                'slug'        => 'all',
263
-                'label'       => __('All', 'event_espresso'),
264
-                'count'       => 0,
265
-                'bulk_action' => array('delete_checkin_rows' => __('Delete Check-In Rows', 'event_espresso')),
266
-            ),
267
-        );
268
-    }
269
-
270
-
271
-
272
-    /**
273
-     * callback for ajax action.
274
-     *
275
-     * @since 4.3.0
276
-     * @return void (JSON)
277
-     * @throws \EE_Error
278
-     */
279
-    public function get_newsletter_form_content()
280
-    {
281
-        //do a nonce check cause we're not coming in from an normal route here.
282
-        $nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field(
283
-            $this->_req_data['get_newsletter_form_content_nonce']
284
-        ) : '';
285
-        $nonce_ref = 'get_newsletter_form_content_nonce';
286
-        $this->_verify_nonce($nonce, $nonce_ref);
287
-        //let's get the mtp for the incoming MTP_ ID
288
-        if ( ! isset($this->_req_data['GRP_ID'])) {
289
-            EE_Error::add_error(
290
-                __(
291
-                    'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).',
292
-                    'event_espresso'
293
-                ),
294
-                __FILE__,
295
-                __FUNCTION__,
296
-                __LINE__
297
-            );
298
-            $this->_template_args['success'] = false;
299
-            $this->_template_args['error'] = true;
300
-            $this->_return_json();
301
-        }
302
-        $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
303
-        if ( ! $MTPG instanceof EE_Message_Template_Group) {
304
-            EE_Error::add_error(
305
-                sprintf(
306
-                    __(
307
-                        'The GRP_ID given (%d) does not appear to have a corresponding row in the database.',
308
-                        'event_espresso'
309
-                    ),
310
-                    $this->_req_data['GRP_ID']
311
-                ),
312
-                __FILE__,
313
-                __FUNCTION__,
314
-                __LINE__
315
-            );
316
-            $this->_template_args['success'] = false;
317
-            $this->_template_args['error'] = true;
318
-            $this->_return_json();
319
-        }
320
-        $MTPs = $MTPG->context_templates();
321
-        $MTPs = $MTPs['attendee'];
322
-        $template_fields = array();
323
-        /** @var EE_Message_Template $MTP */
324
-        foreach ($MTPs as $MTP) {
325
-            $field = $MTP->get('MTP_template_field');
326
-            if ($field === 'content') {
327
-                $content = $MTP->get('MTP_content');
328
-                if ( ! empty($content['newsletter_content'])) {
329
-                    $template_fields['newsletter_content'] = $content['newsletter_content'];
330
-                }
331
-                continue;
332
-            }
333
-            $template_fields[$MTP->get('MTP_template_field')] = $MTP->get('MTP_content');
334
-        }
335
-        $this->_template_args['success'] = true;
336
-        $this->_template_args['error'] = false;
337
-        $this->_template_args['data'] = array(
338
-            'batch_message_from'    => isset($template_fields['from'])
339
-                ? $template_fields['from']
340
-                : '',
341
-            'batch_message_subject' => isset($template_fields['subject'])
342
-                ? $template_fields['subject']
343
-                : '',
344
-            'batch_message_content' => isset($template_fields['newsletter_content'])
345
-                ? $template_fields['newsletter_content']
346
-                : '',
347
-        );
348
-        $this->_return_json();
349
-    }
350
-
351
-
352
-
353
-    /**
354
-     * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action
355
-     *
356
-     * @since 4.3.0
357
-     * @param EE_Admin_List_Table $list_table
358
-     * @return void
359
-     */
360
-    public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
361
-    {
362
-        if ( ! EE_Registry::instance()->CAP->current_user_can(
363
-            'ee_send_message',
364
-            'espresso_registrations_newsletter_selected_send'
365
-        )
366
-        ) {
367
-            return;
368
-        }
369
-        $routes_to_add_to = array(
370
-            'contact_list',
371
-            'event_registrations',
372
-            'default',
373
-        );
374
-        if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) {
375
-            if (($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id']))
376
-                || (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash')
377
-            ) {
378
-                echo '';
379
-            } else {
380
-                $button_text = sprintf(
381
-                    __('Send Batch Message (%s selected)', 'event_espresso'),
382
-                    '<span class="send-selected-newsletter-count">0</span>'
383
-                );
384
-                echo '<button id="selected-batch-send-trigger" class="button secondary-button"><span class="dashicons dashicons-email "></span>'
385
-                     . $button_text
386
-                     . '</button>';
387
-                add_action('admin_footer', array($this, 'newsletter_send_form_skeleton'));
388
-            }
389
-        }
390
-    }
391
-
392
-
393
-
394
-    public function newsletter_send_form_skeleton()
395
-    {
396
-        $list_table = $this->_list_table_object;
397
-        $codes = array();
398
-        //need to templates for the newsletter message type for the template selector.
399
-        $values[] = array('text' => __('Select Template to Use', 'event_espresso'), 'id' => 0);
400
-        $mtps = EEM_Message_Template_Group::instance()->get_all(
401
-            array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email'))
402
-        );
403
-        foreach ($mtps as $mtp) {
404
-            $name = $mtp->name();
405
-            $values[] = array(
406
-                'text' => empty($name) ? __('Global', 'event_espresso') : $name,
407
-                'id'   => $mtp->ID(),
408
-            );
409
-        }
410
-        //need to get a list of shortcodes that are available for the newsletter message type.
411
-        $shortcodes = EEH_MSG_Template::get_shortcodes('newsletter', 'email', array(), 'attendee', false);
412
-        foreach ($shortcodes as $field => $shortcode_array) {
413
-            $codes[$field] = implode(', ', array_keys($shortcode_array));
414
-        }
415
-        $shortcodes = $codes;
416
-        $form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
417
-        $form_template_args = array(
418
-            'form_action'       => admin_url('admin.php?page=espresso_registrations'),
419
-            'form_route'        => 'newsletter_selected_send',
420
-            'form_nonce_name'   => 'newsletter_selected_send_nonce',
421
-            'form_nonce'        => wp_create_nonce('newsletter_selected_send_nonce'),
422
-            'redirect_back_to'  => $this->_req_action,
423
-            'ajax_nonce'        => wp_create_nonce('get_newsletter_form_content_nonce'),
424
-            'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values),
425
-            'shortcodes'        => $shortcodes,
426
-            'id_type'           => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration',
427
-        );
428
-        EEH_Template::display_template($form_template, $form_template_args);
429
-    }
430
-
431
-
432
-
433
-    /**
434
-     * Handles sending selected registrations/contacts a newsletter.
435
-     *
436
-     * @since  4.3.0
437
-     * @return void
438
-     * @throws \EE_Error
439
-     */
440
-    protected function _newsletter_selected_send()
441
-    {
442
-        $success = true;
443
-        //first we need to make sure we have a GRP_ID so we know what template we're sending and updating!
444
-        if (empty($this->_req_data['newsletter_mtp_selected'])) {
445
-            EE_Error::add_error(
446
-                __(
447
-                    'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.',
448
-                    'event_espresso'
449
-                ),
450
-                __FILE__,
451
-                __FUNCTION__,
452
-                __LINE__
453
-            );
454
-            $success = false;
455
-        }
456
-        if ($success) {
457
-            //update Message template in case there are any changes
458
-            $Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID(
459
-                $this->_req_data['newsletter_mtp_selected']
460
-            );
461
-            $Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group
462
-                ? $Message_Template_Group->context_templates()
463
-                : array();
464
-            if (empty($Message_Templates)) {
465
-                EE_Error::add_error(
466
-                    __(
467
-                        'Unable to retrieve message template fields from the db. Messages not sent.',
468
-                        'event_espresso'
469
-                    ),
470
-                    __FILE__,
471
-                    __FUNCTION__,
472
-                    __LINE__
473
-                );
474
-            }
475
-            //let's just update the specific fields
476
-            foreach ($Message_Templates['attendee'] as $Message_Template) {
477
-                if ($Message_Template instanceof EE_Message_Template) {
478
-                    $field = $Message_Template->get('MTP_template_field');
479
-                    $content = $Message_Template->get('MTP_content');
480
-                    $new_content = $content;
481
-                    switch ($field) {
482
-                        case 'from' :
483
-                            $new_content = ! empty($this->_req_data['batch_message']['from'])
484
-                                ? $this->_req_data['batch_message']['from']
485
-                                : $content;
486
-                            break;
487
-                        case 'subject' :
488
-                            $new_content = ! empty($this->_req_data['batch_message']['subject'])
489
-                                ? $this->_req_data['batch_message']['subject']
490
-                                : $content;
491
-                            break;
492
-                        case 'content' :
493
-                            $new_content = $content;
494
-                            $new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content'])
495
-                                ? $this->_req_data['batch_message']['content']
496
-                                : $content['newsletter_content'];
497
-                            break;
498
-                        default :
499
-                            //continue the foreach loop, we don't want to set $new_content nor save.
500
-                            continue 2;
501
-                    }
502
-                    $Message_Template->set('MTP_content', $new_content);
503
-                    $Message_Template->save();
504
-                }
505
-            }
506
-            //great fields are updated!  now let's make sure we just have contact objects (EE_Attendee).
507
-            $id_type = ! empty($this->_req_data['batch_message']['id_type'])
508
-                ? $this->_req_data['batch_message']['id_type']
509
-                : 'registration';
510
-            //id_type will affect how we assemble the ids.
511
-            $ids = ! empty($this->_req_data['batch_message']['ids'])
512
-                ? json_decode(stripslashes($this->_req_data['batch_message']['ids']))
513
-                : array();
514
-            $registrations_used_for_contact_data = array();
515
-            //using switch because eventually we'll have other contexts that will be used for generating messages.
516
-            switch ($id_type) {
517
-                case 'registration' :
518
-                    $registrations_used_for_contact_data = EEM_Registration::instance()->get_all(
519
-                        array(
520
-                            array(
521
-                                'REG_ID' => array('IN', $ids),
522
-                            ),
523
-                        )
524
-                    );
525
-                    break;
526
-                case 'contact' :
527
-                    $registrations_used_for_contact_data = EEM_Registration::instance()
528
-                                                                           ->get_latest_registration_for_each_of_given_contacts($ids);
529
-                    break;
530
-            }
531
-            do_action(
532
-                'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
533
-                $registrations_used_for_contact_data,
534
-                $Message_Template_Group->ID()
535
-            );
536
-            //kept for backward compat, internally we no longer use this action.
537
-            //@deprecated 4.8.36.rc.002
538
-            $contacts = $id_type === 'registration'
539
-                ? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids)
540
-                : EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids))));
541
-            do_action(
542
-                'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send',
543
-                $contacts,
544
-                $Message_Template_Group->ID()
545
-            );
546
-        }
547
-        $query_args = array(
548
-            'action' => ! empty($this->_req_data['redirect_back_to'])
549
-                ? $this->_req_data['redirect_back_to']
550
-                : 'default',
551
-        );
552
-        $this->_redirect_after_action(false, '', '', $query_args, true);
553
-    }
554
-
555
-
556
-
557
-    /**
558
-     * This is called when javascript is being enqueued to setup the various data needed for the reports js.
559
-     * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method.
560
-     */
561
-    protected function _registration_reports_js_setup()
562
-    {
563
-        $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report();
564
-        $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report();
565
-    }
566
-
567
-
568
-
569
-    /**
570
-     *        generates Business Reports regarding Registrations
571
-     *
572
-     * @access protected
573
-     * @return void
574
-     */
575
-    protected function _registration_reports()
576
-    {
577
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
578
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
579
-            $template_path,
580
-            $this->_reports_template_data,
581
-            true
582
-        );
583
-        // the final template wrapper
584
-        $this->display_admin_page_with_no_sidebar();
585
-    }
586
-
587
-
588
-
589
-    /**
590
-     * Generates Business Report showing total registrations per day.
591
-     *
592
-     * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
593
-     * @return string
594
-     */
595
-    private function _registrations_per_day_report($period = '-1 month')
596
-    {
597
-        $report_ID = 'reg-admin-registrations-per-day-report-dv';
598
-        $results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period);
599
-        $results = (array)$results;
600
-        $regs = array();
601
-        $subtitle = '';
602
-        if ($results) {
603
-            $column_titles = array();
604
-            $tracker = 0;
605
-            foreach ($results as $result) {
606
-                $report_column_values = array();
607
-                foreach ($result as $property_name => $property_value) {
608
-                    $property_value = $property_name === 'Registration_REG_date' ? $property_value
609
-                        : (int)$property_value;
610
-                    $report_column_values[] = $property_value;
611
-                    if ($tracker === 0) {
612
-                        if ($property_name === 'Registration_REG_date') {
613
-                            $column_titles[] = __('Date (only days with registrations are shown)', 'event_espresso');
614
-                        } else {
615
-                            $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
616
-                        }
617
-                    }
618
-                }
619
-                $tracker++;
620
-                $regs[] = $report_column_values;
621
-            }
622
-            //make sure the column_titles is pushed to the beginning of the array
623
-            array_unshift($regs, $column_titles);
624
-            //setup the date range.
625
-            $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
626
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
627
-            $ending_date = new DateTime("now", $DateTimeZone);
628
-            $subtitle = sprintf(
629
-                _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
630
-                $beginning_date->format('Y-m-d'),
631
-                $ending_date->format('Y-m-d')
632
-            );
633
-        }
634
-        $report_title = __('Total Registrations per Day', 'event_espresso');
635
-        $report_params = array(
636
-            'title'     => $report_title,
637
-            'subtitle'  => $subtitle,
638
-            'id'        => $report_ID,
639
-            'regs'      => $regs,
640
-            'noResults' => empty($regs),
641
-            'noRegsMsg' => sprintf(
642
-                __(
643
-                    '%sThere are currently no registration records in the last month for this report.%s',
644
-                    'event_espresso'
645
-                ),
646
-                '<h2>' . $report_title . '</h2><p>',
647
-                '</p>'
648
-            ),
649
-        );
650
-        wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params);
651
-        return $report_ID;
652
-    }
653
-
654
-
655
-
656
-    /**
657
-     * Generates Business Report showing total registrations per event.
658
-     *
659
-     * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
660
-     * @return string
661
-     */
662
-    private function _registrations_per_event_report($period = '-1 month')
663
-    {
664
-        $report_ID = 'reg-admin-registrations-per-event-report-dv';
665
-        $results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period);
666
-        $results = (array)$results;
667
-        $regs = array();
668
-        $subtitle = '';
669
-        if ($results) {
670
-            $column_titles = array();
671
-            $tracker = 0;
672
-            foreach ($results as $result) {
673
-                $report_column_values = array();
674
-                foreach ($result as $property_name => $property_value) {
675
-                    $property_value = $property_name === 'Registration_Event' ? wp_trim_words(
676
-                        $property_value,
677
-                        4,
678
-                        '...'
679
-                    ) : (int)$property_value;
680
-                    $report_column_values[] = $property_value;
681
-                    if ($tracker === 0) {
682
-                        if ($property_name === 'Registration_Event') {
683
-                            $column_titles[] = __('Event', 'event_espresso');
684
-                        } else {
685
-                            $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
686
-                        }
687
-                    }
688
-                }
689
-                $tracker++;
690
-                $regs[] = $report_column_values;
691
-            }
692
-            //make sure the column_titles is pushed to the beginning of the array
693
-            array_unshift($regs, $column_titles);
694
-            //setup the date range.
695
-            $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
696
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
697
-            $ending_date = new DateTime("now", $DateTimeZone);
698
-            $subtitle = sprintf(
699
-                _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
700
-                $beginning_date->format('Y-m-d'),
701
-                $ending_date->format('Y-m-d')
702
-            );
703
-        }
704
-        $report_title = __('Total Registrations per Event', 'event_espresso');
705
-        $report_params = array(
706
-            'title'     => $report_title,
707
-            'subtitle'  => $subtitle,
708
-            'id'        => $report_ID,
709
-            'regs'      => $regs,
710
-            'noResults' => empty($regs),
711
-            'noRegsMsg' => sprintf(
712
-                __(
713
-                    '%sThere are currently no registration records in the last month for this report.%s',
714
-                    'event_espresso'
715
-                ),
716
-                '<h2>' . $report_title . '</h2><p>',
717
-                '</p>'
718
-            ),
719
-        );
720
-        wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params);
721
-        return $report_ID;
722
-    }
723
-
724
-
725
-
726
-    /**
727
-     * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
728
-     *
729
-     * @access protected
730
-     * @return void
731
-     * @throws \EE_Error
732
-     */
733
-    protected function _registration_checkin_list_table()
734
-    {
735
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
736
-        $reg_id = isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : null;
737
-        /** @var EE_Registration $registration */
738
-        $registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
739
-        $attendee = $registration->attendee();
740
-        $this->_admin_page_title .= $this->get_action_link_or_button(
741
-            'new_registration',
742
-            'add-registrant',
743
-            array('event_id' => $registration->event_ID()),
744
-            'add-new-h2'
745
-        );
746
-        $legend_items = array(
747
-            'checkin'  => array(
748
-                'class' => 'ee-icon ee-icon-check-in',
749
-                'desc'  => __('This indicates the attendee has been checked in', 'event_espresso'),
750
-            ),
751
-            'checkout' => array(
752
-                'class' => 'ee-icon ee-icon-check-out',
753
-                'desc'  => __('This indicates the attendee has been checked out', 'event_espresso'),
754
-            ),
755
-        );
756
-        $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
757
-        $dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
758
-        /** @var EE_Datetime $datetime */
759
-        $datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id);
760
-        $datetime_label = '';
761
-        if ($datetime instanceof EE_Datetime) {
762
-            $datetime_label = $datetime->get_dtt_display_name(true);
763
-            $datetime_label .= ! empty($datetime_label)
764
-                ? ' (' . $datetime->get_dtt_display_name() . ')'
765
-                : $datetime->get_dtt_display_name();
766
-        }
767
-        $datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
768
-            ? EE_Admin_Page::add_query_args_and_nonce(
769
-                array(
770
-                    'action'   => 'event_registrations',
771
-                    'event_id' => $registration->event_ID(),
772
-                    'DTT_ID'   => $dtt_id,
773
-                ),
774
-                $this->_admin_base_url
775
-            )
776
-            : '';
777
-        $datetime_link = ! empty($datetime_link)
778
-            ? '<a href="' . $datetime_link . '">'
779
-              . '<span id="checkin-dtt">'
780
-              . $datetime_label
781
-              . '</span></a>'
782
-            : $datetime_label;
783
-        $attendee_name = $attendee instanceof EE_Attendee
784
-            ? $attendee->full_name()
785
-            : '';
786
-        $attendee_link = $attendee instanceof EE_Attendee
787
-            ? $attendee->get_admin_details_link()
788
-            : '';
789
-        $attendee_link = ! empty($attendee_link)
790
-            ? '<a href="' . $attendee->get_admin_details_link() . '"'
791
-              . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
792
-              . '<span id="checkin-attendee-name">'
793
-              . $attendee_name
794
-              . '</span></a>'
795
-            : '';
796
-        $event_link = $registration->event() instanceof EE_Event
797
-            ? $registration->event()->get_admin_details_link()
798
-            : '';
799
-        $event_link = ! empty($event_link)
800
-            ? '<a href="' . $event_link . '"'
801
-              . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
802
-              . '<span id="checkin-event-name">'
803
-              . $registration->event_name()
804
-              . '</span>'
805
-              . '</a>'
806
-            : '';
807
-        $this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
808
-            ? '<h2>' . sprintf(
809
-                esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
810
-                $attendee_link,
811
-                $datetime_link,
812
-                $event_link
813
-            ) . '</h2>'
814
-            : '';
815
-        $this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
816
-            ? '<input type="hidden" name="_REGID" value="' . $reg_id . '">' : '';
817
-        $this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
818
-            ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
819
-        $this->display_admin_list_table_page_with_no_sidebar();
820
-    }
821
-
822
-
823
-
824
-    /**
825
-     * toggle the Check-in status for the given registration (coming from ajax)
826
-     *
827
-     * @return void (JSON)
828
-     */
829
-    public function toggle_checkin_status()
830
-    {
831
-        //first make sure we have the necessary data
832
-        if ( ! isset($this->_req_data['_regid'])) {
833
-            EE_Error::add_error(
834
-                __(
835
-                    'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax',
836
-                    'event_espresso'
837
-                ),
838
-                __FILE__,
839
-                __FUNCTION__,
840
-                __LINE__
841
-            );
842
-            $this->_template_args['success'] = false;
843
-            $this->_template_args['error'] = true;
844
-            $this->_return_json();
845
-        };
846
-        //do a nonce check cause we're not coming in from an normal route here.
847
-        $nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce'])
848
-            : '';
849
-        $nonce_ref = 'checkin_nonce';
850
-        $this->_verify_nonce($nonce, $nonce_ref);
851
-        //beautiful! Made it this far so let's get the status.
852
-        $new_status = $this->_toggle_checkin_status();
853
-        //setup new class to return via ajax
854
-        $this->_template_args['admin_page_content'] = 'clickable trigger-checkin checkin-icons checkedin-status-'
855
-                                                      . $new_status;
856
-        $this->_template_args['success'] = true;
857
-        $this->_return_json();
858
-    }
859
-
860
-
861
-
862
-    /**
863
-     * handles toggling the checkin status for the registration,
864
-     *
865
-     * @access protected
866
-     * @return int|void
867
-     */
868
-    protected function _toggle_checkin_status()
869
-    {
870
-        //first let's get the query args out of the way for the redirect
871
-        $query_args = array(
872
-            'action'   => 'event_registrations',
873
-            'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
874
-            'DTT_ID'   => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null,
875
-        );
876
-        $new_status = false;
877
-        // bulk action check in toggle
878
-        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
879
-            // cycle thru checkboxes
880
-            while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) {
881
-                $DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
882
-                $new_status = $this->_toggle_checkin($REG_ID, $DTT_ID);
883
-            }
884
-        } elseif (isset($this->_req_data['_regid'])) {
885
-            //coming from ajax request
886
-            $DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null;
887
-            $query_args['DTT_ID'] = $DTT_ID;
888
-            $new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID);
889
-        } else {
890
-            EE_Error::add_error(
891
-                __('Missing some required data to toggle the Check-in', 'event_espresso'),
892
-                __FILE__,
893
-                __FUNCTION__,
894
-                __LINE__
895
-            );
896
-        }
897
-        if (defined('DOING_AJAX')) {
898
-            return $new_status;
899
-        }
900
-        $this->_redirect_after_action(false, '', '', $query_args, true);
901
-    }
902
-
903
-
904
-
905
-    /**
906
-     * This is toggles a single Check-in for the given registration and datetime.
907
-     *
908
-     * @param  int $REG_ID The registration we're toggling
909
-     * @param  int $DTT_ID The datetime we're toggling
910
-     * @return int            The new status toggled to.
911
-     * @throws \EE_Error
912
-     */
913
-    private function _toggle_checkin($REG_ID, $DTT_ID)
914
-    {
915
-        /** @var EE_Registration $REG */
916
-        $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
917
-        $new_status = $REG->toggle_checkin_status($DTT_ID);
918
-        if ($new_status !== false) {
919
-            EE_Error::add_success($REG->get_checkin_msg($DTT_ID));
920
-        } else {
921
-            EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__);
922
-            $new_status = false;
923
-        }
924
-        return $new_status;
925
-    }
926
-
927
-
928
-
929
-    /**
930
-     * Takes care of deleting multiple EE_Checkin table rows
931
-     *
932
-     * @access protected
933
-     * @return void
934
-     * @throws \EE_Error
935
-     */
936
-    protected function _delete_checkin_rows()
937
-    {
938
-        $query_args = array(
939
-            'action' => 'registration_checkins',
940
-            'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
941
-            '_REGID' => isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : 0,
942
-        );
943
-        $errors = 0;
944
-        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
945
-            while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) {
946
-                if ( ! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
947
-                    $errors++;
948
-                }
949
-            }
950
-        } else {
951
-            EE_Error::add_error(
952
-                __(
953
-                    'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!',
954
-                    'event_espresso'
955
-                ),
956
-                __FILE__,
957
-                __FUNCTION__,
958
-                __LINE__
959
-            );
960
-            $this->_redirect_after_action(false, '', '', $query_args, true);
961
-        }
962
-        if ($errors > 0) {
963
-            EE_Error::add_error(
964
-                sprintf(__('There were %d records that did not delete successfully', 'event_espresso'), $errors),
965
-                __FILE__,
966
-                __FUNCTION__,
967
-                __LINE__
968
-            );
969
-        } else {
970
-            EE_Error::add_success(__('Records were successfully deleted', 'event_espresso'));
971
-        }
972
-        $this->_redirect_after_action(false, '', '', $query_args, true);
973
-    }
974
-
975
-
976
-
977
-    /**
978
-     * Deletes a single EE_Checkin row
979
-     *
980
-     * @return void
981
-     * @throws \EE_Error
982
-     */
983
-    protected function _delete_checkin_row()
984
-    {
985
-        $query_args = array(
986
-            'action' => 'registration_checkins',
987
-            'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
988
-            '_REGID' => isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : 0,
989
-        );
990
-        if ( ! empty($this->_req_data['CHK_ID'])) {
991
-            if ( ! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
992
-                EE_Error::add_error(
993
-                    __('Something went wrong and this check-in record was not deleted', 'event_espresso'),
994
-                    __FILE__,
995
-                    __FUNCTION__,
996
-                    __LINE__
997
-                );
998
-            } else {
999
-                EE_Error::add_success(__('Check-In record successfully deleted', 'event_espresso'));
1000
-            }
1001
-        } else {
1002
-            EE_Error::add_error(
1003
-                __(
1004
-                    'In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code',
1005
-                    'event_espresso'
1006
-                ),
1007
-                __FILE__,
1008
-                __FUNCTION__,
1009
-                __LINE__
1010
-            );
1011
-        }
1012
-        $this->_redirect_after_action(false, '', '', $query_args, true);
1013
-    }
1014
-
1015
-
1016
-
1017
-    /**
1018
-     *        generates HTML for the Event Registrations List Table
1019
-     *
1020
-     * @access protected
1021
-     * @return void
1022
-     * @throws \EE_Error
1023
-     */
1024
-    protected function _event_registrations_list_table()
1025
-    {
1026
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1027
-        $this->_admin_page_title .= isset($this->_req_data['event_id'])
1028
-            ? $this->get_action_link_or_button(
1029
-                'new_registration',
1030
-                'add-registrant',
1031
-                array('event_id' => $this->_req_data['event_id']),
1032
-                'add-new-h2',
1033
-                '',
1034
-                false
1035
-            )
1036
-            : '';
1037
-        $legend_items = array(
1038
-            'star-icon'        => array(
1039
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1040
-                'desc'  => __('This Registrant is the Primary Registrant', 'event_espresso'),
1041
-            ),
1042
-            'checkin'          => array(
1043
-                'class' => 'ee-icon ee-icon-check-in',
1044
-                'desc'  => __('This Registrant has been Checked In', 'event_espresso'),
1045
-            ),
1046
-            'checkout'         => array(
1047
-                'class' => 'ee-icon ee-icon-check-out',
1048
-                'desc'  => __('This Registrant has been Checked Out', 'event_espresso'),
1049
-            ),
1050
-            'nocheckinrecord'  => array(
1051
-                'class' => 'dashicons dashicons-no',
1052
-                'desc'  => __('No Check-in Record has been Created for this Registrant', 'event_espresso'),
1053
-            ),
1054
-            'view_details'     => array(
1055
-                'class' => 'dashicons dashicons-search',
1056
-                'desc'  => __('View All Check-in Records for this Registrant', 'event_espresso'),
1057
-            ),
1058
-            'approved_status'  => array(
1059
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1060
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1061
-            ),
1062
-            'cancelled_status' => array(
1063
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1064
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1065
-            ),
1066
-            'declined_status'  => array(
1067
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1068
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1069
-            ),
1070
-            'not_approved'     => array(
1071
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1072
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1073
-            ),
1074
-            'pending_status'   => array(
1075
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1076
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1077
-            ),
1078
-            'wait_list'        => array(
1079
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1080
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1081
-            ),
1082
-        );
1083
-        $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
1084
-        $event_id = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null;
1085
-        $this->_template_args['before_list_table'] = ! empty($event_id)
1086
-            ? '<h2>' . sprintf(
1087
-                __('Viewing Registrations for Event: %s', 'event_espresso'),
1088
-                EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1089
-            ) . '</h2>'
1090
-            : '';
1091
-        //need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on the event.
1092
-        /** @var EE_Event $event */
1093
-        $event = EEM_Event::instance()->get_one_by_ID($event_id);
1094
-        $DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0;
1095
-        $datetime = null;
1096
-        if ($event instanceof EE_Event) {
1097
-            $datetimes_on_event = $event->datetimes();
1098
-            if (count($datetimes_on_event) === 1) {
1099
-                $datetime = reset($datetimes_on_event);
1100
-            }
1101
-        }
1102
-        $datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1103
-        if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') {
1104
-            $this->_template_args['before_list_table'] = substr($this->_template_args['before_list_table'], 0, -5);
1105
-            $this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1106
-            $this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1107
-            $this->_template_args['before_list_table'] .= $datetime->name();
1108
-            $this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1109
-            $this->_template_args['before_list_table'] .= '</span></h2>';
1110
-        }
1111
-        //if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status column
1112
-        //represents
1113
-        if ( ! $datetime instanceof EE_Datetime) {
1114
-            $this->_template_args['before_list_table'] .= '<br><p class="description">'
1115
-                                                          . __('In this view, the check-in status represents the latest check-in record for the registration in that row.',
1116
-                    'event_espresso')
1117
-                                                          . '</p>';
1118
-        }
1119
-        $this->display_admin_list_table_page_with_no_sidebar();
1120
-    }
1121
-
1122
-    /**
1123
-     * Download the registrations check-in report (same as the normal registration report, but with different where
1124
-     * conditions)
1125
-     *
1126
-     * @return void ends the request by a redirect or download
1127
-     */
1128
-    public function _registrations_checkin_report()
1129
-    {
1130
-        $this->_registrations_report_base('_get_checkin_query_params_from_request');
1131
-    }
1132
-
1133
-    /**
1134
-     * Gets the query params from the request, plus adds a where condition for the registration status,
1135
-     * because on the checkin page we only ever want to see approved and pending-approval registrations
1136
-     *
1137
-     * @param array     $request
1138
-     * @param int  $per_page
1139
-     * @param bool $count
1140
-     * @return array
1141
-     */
1142
-    protected function _get_checkin_query_params_from_request(
1143
-        $request,
1144
-        $per_page = 10,
1145
-        $count = false
1146
-    ) {
1147
-        $query_params = $this->_get_registration_query_parameters($request, $per_page, $count);
1148
-        //unlike the regular registrations list table,
1149
-        $status_ids_array = apply_filters(
1150
-            'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
1151
-            array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved)
1152
-        );
1153
-        $query_params[0]['STS_ID'] = array('IN', $status_ids_array);
1154
-        return $query_params;
1155
-    }
1156
-
1157
-
1158
-
1159
-
1160
-    /**
1161
-     * Gets registrations for an event
1162
-     *
1163
-     * @param int    $per_page
1164
-     * @param bool   $count whether to return count or data.
1165
-     * @param bool   $trash
1166
-     * @param string $orderby
1167
-     * @return EE_Registration[]|int
1168
-     * @throws \EE_Error
1169
-     */
1170
-    public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname')
1171
-    {
1172
-        //normalize some request params that get setup by the parent `get_registrations` method.
1173
-        $request = $this->_req_data;
1174
-        $request['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : $orderby;
1175
-        $request['order'] =  ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'ASC';
1176
-        if($trash){
1177
-            $request['status'] = 'trash';
1178
-        }
1179
-        $query_params = $this->_get_checkin_query_params_from_request( $request, $per_page, $count );
1180
-        /**
1181
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1182
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1183
-         * @see EEM_Base::get_all()
1184
-         */
1185
-        $query_params['group_by'] = '';
1186
-
1187
-        return $count
1188
-            ? EEM_Registration::instance()->count($query_params)
1189
-            /** @type EE_Registration[] */
1190
-            : EEM_Registration::instance()->get_all($query_params);
1191
-    }
20
+	/**
21
+	 * This is used to hold the reports template data which is setup early in the request.
22
+	 *
23
+	 * @type array
24
+	 */
25
+	protected $_reports_template_data = array();
26
+
27
+
28
+
29
+	/**
30
+	 * Extend_Registrations_Admin_Page constructor.
31
+	 *
32
+	 * @param bool $routing
33
+	 */
34
+	public function __construct($routing = true)
35
+	{
36
+		parent::__construct($routing);
37
+		if ( ! defined('REG_CAF_TEMPLATE_PATH')) {
38
+			define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
39
+			define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
40
+			define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
41
+		}
42
+	}
43
+
44
+
45
+
46
+	protected function _extend_page_config()
47
+	{
48
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
49
+		$reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
50
+			? $this->_req_data['_REG_ID']
51
+			: 0;
52
+		// $att_id = ! empty( $this->_req_data['ATT_ID'] ) ? ! is_array( $this->_req_data['ATT_ID'] ) : 0;
53
+		// $att_id = ! empty( $this->_req_data['post'] ) && ! is_array( $this->_req_data['post'] )
54
+		// 	? $this->_req_data['post'] : $att_id;
55
+		$new_page_routes = array(
56
+			'reports'                  => array(
57
+				'func'       => '_registration_reports',
58
+				'capability' => 'ee_read_registrations',
59
+			),
60
+			'registration_checkins'    => array(
61
+				'func'       => '_registration_checkin_list_table',
62
+				'capability' => 'ee_read_checkins',
63
+			),
64
+			'newsletter_selected_send' => array(
65
+				'func'       => '_newsletter_selected_send',
66
+				'noheader'   => true,
67
+				'capability' => 'ee_send_message',
68
+			),
69
+			'delete_checkin_rows'      => array(
70
+				'func'       => '_delete_checkin_rows',
71
+				'noheader'   => true,
72
+				'capability' => 'ee_delete_checkins',
73
+			),
74
+			'delete_checkin_row'       => array(
75
+				'func'       => '_delete_checkin_row',
76
+				'noheader'   => true,
77
+				'capability' => 'ee_delete_checkin',
78
+				'obj_id'     => $reg_id,
79
+			),
80
+			'toggle_checkin_status'    => array(
81
+				'func'       => '_toggle_checkin_status',
82
+				'noheader'   => true,
83
+				'capability' => 'ee_edit_checkin',
84
+				'obj_id'     => $reg_id,
85
+			),
86
+			'toggle_checkin_status_bulk' => array(
87
+				'func' => '_toggle_checkin_status',
88
+				'noheader' => true,
89
+				'capability' => 'ee_edit_checkins'
90
+			),
91
+			'event_registrations'      => array(
92
+				'func'       => '_event_registrations_list_table',
93
+				'capability' => 'ee_read_checkins',
94
+			),
95
+			'registrations_checkin_report' => array(
96
+				'func'       => '_registrations_checkin_report',
97
+				'noheader'   => true,
98
+				'capability' => 'ee_read_registrations',
99
+			),
100
+		);
101
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
102
+		$new_page_config = array(
103
+			'reports'               => array(
104
+				'nav'           => array(
105
+					'label' => __('Reports', 'event_espresso'),
106
+					'order' => 30,
107
+				),
108
+				'help_tabs'     => array(
109
+					'registrations_reports_help_tab' => array(
110
+						'title'    => __('Registration Reports', 'event_espresso'),
111
+						'filename' => 'registrations_reports',
112
+					),
113
+				),
114
+				/*'help_tour' => array( 'Registration_Reports_Help_Tour' ),*/
115
+				'require_nonce' => false,
116
+			),
117
+			'event_registrations'   => array(
118
+				'nav'           => array(
119
+					'label'      => __('Event Check-In', 'event_espresso'),
120
+					'order'      => 10,
121
+					'persistent' => true,
122
+				),
123
+				'help_tabs'     => array(
124
+					'registrations_event_checkin_help_tab'                       => array(
125
+						'title'    => __('Registrations Event Check-In', 'event_espresso'),
126
+						'filename' => 'registrations_event_checkin',
127
+					),
128
+					'registrations_event_checkin_table_column_headings_help_tab' => array(
129
+						'title'    => __('Event Check-In Table Column Headings', 'event_espresso'),
130
+						'filename' => 'registrations_event_checkin_table_column_headings',
131
+					),
132
+					'registrations_event_checkin_filters_help_tab'               => array(
133
+						'title'    => __('Event Check-In Filters', 'event_espresso'),
134
+						'filename' => 'registrations_event_checkin_filters',
135
+					),
136
+					'registrations_event_checkin_views_help_tab'                 => array(
137
+						'title'    => __('Event Check-In Views', 'event_espresso'),
138
+						'filename' => 'registrations_event_checkin_views',
139
+					),
140
+					'registrations_event_checkin_other_help_tab'                 => array(
141
+						'title'    => __('Event Check-In Other', 'event_espresso'),
142
+						'filename' => 'registrations_event_checkin_other',
143
+					),
144
+				),
145
+				'help_tour'     => array('Event_Checkin_Help_Tour'),
146
+				'qtips'         => array('Registration_List_Table_Tips'),
147
+				'list_table'    => 'EE_Event_Registrations_List_Table',
148
+				'metaboxes'     => array(),
149
+				'require_nonce' => false,
150
+			),
151
+			'registration_checkins' => array(
152
+				'nav'           => array(
153
+					'label'      => __('Check-In Records', 'event_espresso'),
154
+					'order'      => 15,
155
+					'persistent' => false,
156
+				),
157
+				'list_table'    => 'EE_Registration_CheckIn_List_Table',
158
+				//'help_tour' => array( 'Checkin_Toggle_View_Help_Tour' ),
159
+				'metaboxes'     => array(),
160
+				'require_nonce' => false,
161
+			),
162
+		);
163
+		$this->_page_config = array_merge($this->_page_config, $new_page_config);
164
+		$this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table';
165
+		$this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table';
166
+	}
167
+
168
+
169
+
170
+	protected function _ajax_hooks()
171
+	{
172
+		parent::_ajax_hooks();
173
+		add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content'));
174
+	}
175
+
176
+
177
+
178
+	public function load_scripts_styles()
179
+	{
180
+		parent::load_scripts_styles();
181
+		//if newsletter message type is active then let's add filter and load js for it.
182
+		if (EEH_MSG_Template::is_mt_active('newsletter')) {
183
+			//enqueue newsletter js
184
+			wp_enqueue_script(
185
+				'ee-newsletter-trigger',
186
+				REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
187
+				array('ee-dialog'),
188
+				EVENT_ESPRESSO_VERSION,
189
+				true
190
+			);
191
+			wp_enqueue_style(
192
+				'ee-newsletter-trigger-css',
193
+				REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
194
+				array(),
195
+				EVENT_ESPRESSO_VERSION
196
+			);
197
+			//hook in buttons for newsletter message type trigger.
198
+			add_action(
199
+				'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
200
+				array($this, 'add_newsletter_action_buttons'),
201
+				10
202
+			);
203
+		}
204
+	}
205
+
206
+
207
+
208
+	public function load_scripts_styles_reports()
209
+	{
210
+		wp_register_script(
211
+			'ee-reg-reports-js',
212
+			REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
213
+			array('google-charts'),
214
+			EVENT_ESPRESSO_VERSION,
215
+			true
216
+		);
217
+		wp_enqueue_script('ee-reg-reports-js');
218
+		$this->_registration_reports_js_setup();
219
+	}
220
+
221
+
222
+
223
+	protected function _add_screen_options_event_registrations()
224
+	{
225
+		$this->_per_page_screen_option();
226
+	}
227
+
228
+
229
+
230
+	protected function _add_screen_options_registration_checkins()
231
+	{
232
+		$page_title = $this->_admin_page_title;
233
+		$this->_admin_page_title = __('Check-In Records', 'event_espresso');
234
+		$this->_per_page_screen_option();
235
+		$this->_admin_page_title = $page_title;
236
+	}
237
+
238
+
239
+
240
+	protected function _set_list_table_views_event_registrations()
241
+	{
242
+		$this->_views = array(
243
+			'all' => array(
244
+				'slug'        => 'all',
245
+				'label'       => __('All', 'event_espresso'),
246
+				'count'       => 0,
247
+				'bulk_action' => ! isset($this->_req_data['event_id'])
248
+					? array()
249
+					: array(
250
+						'toggle_checkin_status_bulk' => __('Toggle Check-In', 'event_espresso'),
251
+					),
252
+			),
253
+		);
254
+	}
255
+
256
+
257
+
258
+	protected function _set_list_table_views_registration_checkins()
259
+	{
260
+		$this->_views = array(
261
+			'all' => array(
262
+				'slug'        => 'all',
263
+				'label'       => __('All', 'event_espresso'),
264
+				'count'       => 0,
265
+				'bulk_action' => array('delete_checkin_rows' => __('Delete Check-In Rows', 'event_espresso')),
266
+			),
267
+		);
268
+	}
269
+
270
+
271
+
272
+	/**
273
+	 * callback for ajax action.
274
+	 *
275
+	 * @since 4.3.0
276
+	 * @return void (JSON)
277
+	 * @throws \EE_Error
278
+	 */
279
+	public function get_newsletter_form_content()
280
+	{
281
+		//do a nonce check cause we're not coming in from an normal route here.
282
+		$nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field(
283
+			$this->_req_data['get_newsletter_form_content_nonce']
284
+		) : '';
285
+		$nonce_ref = 'get_newsletter_form_content_nonce';
286
+		$this->_verify_nonce($nonce, $nonce_ref);
287
+		//let's get the mtp for the incoming MTP_ ID
288
+		if ( ! isset($this->_req_data['GRP_ID'])) {
289
+			EE_Error::add_error(
290
+				__(
291
+					'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).',
292
+					'event_espresso'
293
+				),
294
+				__FILE__,
295
+				__FUNCTION__,
296
+				__LINE__
297
+			);
298
+			$this->_template_args['success'] = false;
299
+			$this->_template_args['error'] = true;
300
+			$this->_return_json();
301
+		}
302
+		$MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
303
+		if ( ! $MTPG instanceof EE_Message_Template_Group) {
304
+			EE_Error::add_error(
305
+				sprintf(
306
+					__(
307
+						'The GRP_ID given (%d) does not appear to have a corresponding row in the database.',
308
+						'event_espresso'
309
+					),
310
+					$this->_req_data['GRP_ID']
311
+				),
312
+				__FILE__,
313
+				__FUNCTION__,
314
+				__LINE__
315
+			);
316
+			$this->_template_args['success'] = false;
317
+			$this->_template_args['error'] = true;
318
+			$this->_return_json();
319
+		}
320
+		$MTPs = $MTPG->context_templates();
321
+		$MTPs = $MTPs['attendee'];
322
+		$template_fields = array();
323
+		/** @var EE_Message_Template $MTP */
324
+		foreach ($MTPs as $MTP) {
325
+			$field = $MTP->get('MTP_template_field');
326
+			if ($field === 'content') {
327
+				$content = $MTP->get('MTP_content');
328
+				if ( ! empty($content['newsletter_content'])) {
329
+					$template_fields['newsletter_content'] = $content['newsletter_content'];
330
+				}
331
+				continue;
332
+			}
333
+			$template_fields[$MTP->get('MTP_template_field')] = $MTP->get('MTP_content');
334
+		}
335
+		$this->_template_args['success'] = true;
336
+		$this->_template_args['error'] = false;
337
+		$this->_template_args['data'] = array(
338
+			'batch_message_from'    => isset($template_fields['from'])
339
+				? $template_fields['from']
340
+				: '',
341
+			'batch_message_subject' => isset($template_fields['subject'])
342
+				? $template_fields['subject']
343
+				: '',
344
+			'batch_message_content' => isset($template_fields['newsletter_content'])
345
+				? $template_fields['newsletter_content']
346
+				: '',
347
+		);
348
+		$this->_return_json();
349
+	}
350
+
351
+
352
+
353
+	/**
354
+	 * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action
355
+	 *
356
+	 * @since 4.3.0
357
+	 * @param EE_Admin_List_Table $list_table
358
+	 * @return void
359
+	 */
360
+	public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
361
+	{
362
+		if ( ! EE_Registry::instance()->CAP->current_user_can(
363
+			'ee_send_message',
364
+			'espresso_registrations_newsletter_selected_send'
365
+		)
366
+		) {
367
+			return;
368
+		}
369
+		$routes_to_add_to = array(
370
+			'contact_list',
371
+			'event_registrations',
372
+			'default',
373
+		);
374
+		if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) {
375
+			if (($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id']))
376
+				|| (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash')
377
+			) {
378
+				echo '';
379
+			} else {
380
+				$button_text = sprintf(
381
+					__('Send Batch Message (%s selected)', 'event_espresso'),
382
+					'<span class="send-selected-newsletter-count">0</span>'
383
+				);
384
+				echo '<button id="selected-batch-send-trigger" class="button secondary-button"><span class="dashicons dashicons-email "></span>'
385
+					 . $button_text
386
+					 . '</button>';
387
+				add_action('admin_footer', array($this, 'newsletter_send_form_skeleton'));
388
+			}
389
+		}
390
+	}
391
+
392
+
393
+
394
+	public function newsletter_send_form_skeleton()
395
+	{
396
+		$list_table = $this->_list_table_object;
397
+		$codes = array();
398
+		//need to templates for the newsletter message type for the template selector.
399
+		$values[] = array('text' => __('Select Template to Use', 'event_espresso'), 'id' => 0);
400
+		$mtps = EEM_Message_Template_Group::instance()->get_all(
401
+			array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email'))
402
+		);
403
+		foreach ($mtps as $mtp) {
404
+			$name = $mtp->name();
405
+			$values[] = array(
406
+				'text' => empty($name) ? __('Global', 'event_espresso') : $name,
407
+				'id'   => $mtp->ID(),
408
+			);
409
+		}
410
+		//need to get a list of shortcodes that are available for the newsletter message type.
411
+		$shortcodes = EEH_MSG_Template::get_shortcodes('newsletter', 'email', array(), 'attendee', false);
412
+		foreach ($shortcodes as $field => $shortcode_array) {
413
+			$codes[$field] = implode(', ', array_keys($shortcode_array));
414
+		}
415
+		$shortcodes = $codes;
416
+		$form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
417
+		$form_template_args = array(
418
+			'form_action'       => admin_url('admin.php?page=espresso_registrations'),
419
+			'form_route'        => 'newsletter_selected_send',
420
+			'form_nonce_name'   => 'newsletter_selected_send_nonce',
421
+			'form_nonce'        => wp_create_nonce('newsletter_selected_send_nonce'),
422
+			'redirect_back_to'  => $this->_req_action,
423
+			'ajax_nonce'        => wp_create_nonce('get_newsletter_form_content_nonce'),
424
+			'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values),
425
+			'shortcodes'        => $shortcodes,
426
+			'id_type'           => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration',
427
+		);
428
+		EEH_Template::display_template($form_template, $form_template_args);
429
+	}
430
+
431
+
432
+
433
+	/**
434
+	 * Handles sending selected registrations/contacts a newsletter.
435
+	 *
436
+	 * @since  4.3.0
437
+	 * @return void
438
+	 * @throws \EE_Error
439
+	 */
440
+	protected function _newsletter_selected_send()
441
+	{
442
+		$success = true;
443
+		//first we need to make sure we have a GRP_ID so we know what template we're sending and updating!
444
+		if (empty($this->_req_data['newsletter_mtp_selected'])) {
445
+			EE_Error::add_error(
446
+				__(
447
+					'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.',
448
+					'event_espresso'
449
+				),
450
+				__FILE__,
451
+				__FUNCTION__,
452
+				__LINE__
453
+			);
454
+			$success = false;
455
+		}
456
+		if ($success) {
457
+			//update Message template in case there are any changes
458
+			$Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID(
459
+				$this->_req_data['newsletter_mtp_selected']
460
+			);
461
+			$Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group
462
+				? $Message_Template_Group->context_templates()
463
+				: array();
464
+			if (empty($Message_Templates)) {
465
+				EE_Error::add_error(
466
+					__(
467
+						'Unable to retrieve message template fields from the db. Messages not sent.',
468
+						'event_espresso'
469
+					),
470
+					__FILE__,
471
+					__FUNCTION__,
472
+					__LINE__
473
+				);
474
+			}
475
+			//let's just update the specific fields
476
+			foreach ($Message_Templates['attendee'] as $Message_Template) {
477
+				if ($Message_Template instanceof EE_Message_Template) {
478
+					$field = $Message_Template->get('MTP_template_field');
479
+					$content = $Message_Template->get('MTP_content');
480
+					$new_content = $content;
481
+					switch ($field) {
482
+						case 'from' :
483
+							$new_content = ! empty($this->_req_data['batch_message']['from'])
484
+								? $this->_req_data['batch_message']['from']
485
+								: $content;
486
+							break;
487
+						case 'subject' :
488
+							$new_content = ! empty($this->_req_data['batch_message']['subject'])
489
+								? $this->_req_data['batch_message']['subject']
490
+								: $content;
491
+							break;
492
+						case 'content' :
493
+							$new_content = $content;
494
+							$new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content'])
495
+								? $this->_req_data['batch_message']['content']
496
+								: $content['newsletter_content'];
497
+							break;
498
+						default :
499
+							//continue the foreach loop, we don't want to set $new_content nor save.
500
+							continue 2;
501
+					}
502
+					$Message_Template->set('MTP_content', $new_content);
503
+					$Message_Template->save();
504
+				}
505
+			}
506
+			//great fields are updated!  now let's make sure we just have contact objects (EE_Attendee).
507
+			$id_type = ! empty($this->_req_data['batch_message']['id_type'])
508
+				? $this->_req_data['batch_message']['id_type']
509
+				: 'registration';
510
+			//id_type will affect how we assemble the ids.
511
+			$ids = ! empty($this->_req_data['batch_message']['ids'])
512
+				? json_decode(stripslashes($this->_req_data['batch_message']['ids']))
513
+				: array();
514
+			$registrations_used_for_contact_data = array();
515
+			//using switch because eventually we'll have other contexts that will be used for generating messages.
516
+			switch ($id_type) {
517
+				case 'registration' :
518
+					$registrations_used_for_contact_data = EEM_Registration::instance()->get_all(
519
+						array(
520
+							array(
521
+								'REG_ID' => array('IN', $ids),
522
+							),
523
+						)
524
+					);
525
+					break;
526
+				case 'contact' :
527
+					$registrations_used_for_contact_data = EEM_Registration::instance()
528
+																		   ->get_latest_registration_for_each_of_given_contacts($ids);
529
+					break;
530
+			}
531
+			do_action(
532
+				'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
533
+				$registrations_used_for_contact_data,
534
+				$Message_Template_Group->ID()
535
+			);
536
+			//kept for backward compat, internally we no longer use this action.
537
+			//@deprecated 4.8.36.rc.002
538
+			$contacts = $id_type === 'registration'
539
+				? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids)
540
+				: EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids))));
541
+			do_action(
542
+				'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send',
543
+				$contacts,
544
+				$Message_Template_Group->ID()
545
+			);
546
+		}
547
+		$query_args = array(
548
+			'action' => ! empty($this->_req_data['redirect_back_to'])
549
+				? $this->_req_data['redirect_back_to']
550
+				: 'default',
551
+		);
552
+		$this->_redirect_after_action(false, '', '', $query_args, true);
553
+	}
554
+
555
+
556
+
557
+	/**
558
+	 * This is called when javascript is being enqueued to setup the various data needed for the reports js.
559
+	 * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method.
560
+	 */
561
+	protected function _registration_reports_js_setup()
562
+	{
563
+		$this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report();
564
+		$this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report();
565
+	}
566
+
567
+
568
+
569
+	/**
570
+	 *        generates Business Reports regarding Registrations
571
+	 *
572
+	 * @access protected
573
+	 * @return void
574
+	 */
575
+	protected function _registration_reports()
576
+	{
577
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
578
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
579
+			$template_path,
580
+			$this->_reports_template_data,
581
+			true
582
+		);
583
+		// the final template wrapper
584
+		$this->display_admin_page_with_no_sidebar();
585
+	}
586
+
587
+
588
+
589
+	/**
590
+	 * Generates Business Report showing total registrations per day.
591
+	 *
592
+	 * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
593
+	 * @return string
594
+	 */
595
+	private function _registrations_per_day_report($period = '-1 month')
596
+	{
597
+		$report_ID = 'reg-admin-registrations-per-day-report-dv';
598
+		$results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period);
599
+		$results = (array)$results;
600
+		$regs = array();
601
+		$subtitle = '';
602
+		if ($results) {
603
+			$column_titles = array();
604
+			$tracker = 0;
605
+			foreach ($results as $result) {
606
+				$report_column_values = array();
607
+				foreach ($result as $property_name => $property_value) {
608
+					$property_value = $property_name === 'Registration_REG_date' ? $property_value
609
+						: (int)$property_value;
610
+					$report_column_values[] = $property_value;
611
+					if ($tracker === 0) {
612
+						if ($property_name === 'Registration_REG_date') {
613
+							$column_titles[] = __('Date (only days with registrations are shown)', 'event_espresso');
614
+						} else {
615
+							$column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
616
+						}
617
+					}
618
+				}
619
+				$tracker++;
620
+				$regs[] = $report_column_values;
621
+			}
622
+			//make sure the column_titles is pushed to the beginning of the array
623
+			array_unshift($regs, $column_titles);
624
+			//setup the date range.
625
+			$DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
626
+			$beginning_date = new DateTime("now " . $period, $DateTimeZone);
627
+			$ending_date = new DateTime("now", $DateTimeZone);
628
+			$subtitle = sprintf(
629
+				_x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
630
+				$beginning_date->format('Y-m-d'),
631
+				$ending_date->format('Y-m-d')
632
+			);
633
+		}
634
+		$report_title = __('Total Registrations per Day', 'event_espresso');
635
+		$report_params = array(
636
+			'title'     => $report_title,
637
+			'subtitle'  => $subtitle,
638
+			'id'        => $report_ID,
639
+			'regs'      => $regs,
640
+			'noResults' => empty($regs),
641
+			'noRegsMsg' => sprintf(
642
+				__(
643
+					'%sThere are currently no registration records in the last month for this report.%s',
644
+					'event_espresso'
645
+				),
646
+				'<h2>' . $report_title . '</h2><p>',
647
+				'</p>'
648
+			),
649
+		);
650
+		wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params);
651
+		return $report_ID;
652
+	}
653
+
654
+
655
+
656
+	/**
657
+	 * Generates Business Report showing total registrations per event.
658
+	 *
659
+	 * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
660
+	 * @return string
661
+	 */
662
+	private function _registrations_per_event_report($period = '-1 month')
663
+	{
664
+		$report_ID = 'reg-admin-registrations-per-event-report-dv';
665
+		$results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period);
666
+		$results = (array)$results;
667
+		$regs = array();
668
+		$subtitle = '';
669
+		if ($results) {
670
+			$column_titles = array();
671
+			$tracker = 0;
672
+			foreach ($results as $result) {
673
+				$report_column_values = array();
674
+				foreach ($result as $property_name => $property_value) {
675
+					$property_value = $property_name === 'Registration_Event' ? wp_trim_words(
676
+						$property_value,
677
+						4,
678
+						'...'
679
+					) : (int)$property_value;
680
+					$report_column_values[] = $property_value;
681
+					if ($tracker === 0) {
682
+						if ($property_name === 'Registration_Event') {
683
+							$column_titles[] = __('Event', 'event_espresso');
684
+						} else {
685
+							$column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
686
+						}
687
+					}
688
+				}
689
+				$tracker++;
690
+				$regs[] = $report_column_values;
691
+			}
692
+			//make sure the column_titles is pushed to the beginning of the array
693
+			array_unshift($regs, $column_titles);
694
+			//setup the date range.
695
+			$DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
696
+			$beginning_date = new DateTime("now " . $period, $DateTimeZone);
697
+			$ending_date = new DateTime("now", $DateTimeZone);
698
+			$subtitle = sprintf(
699
+				_x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
700
+				$beginning_date->format('Y-m-d'),
701
+				$ending_date->format('Y-m-d')
702
+			);
703
+		}
704
+		$report_title = __('Total Registrations per Event', 'event_espresso');
705
+		$report_params = array(
706
+			'title'     => $report_title,
707
+			'subtitle'  => $subtitle,
708
+			'id'        => $report_ID,
709
+			'regs'      => $regs,
710
+			'noResults' => empty($regs),
711
+			'noRegsMsg' => sprintf(
712
+				__(
713
+					'%sThere are currently no registration records in the last month for this report.%s',
714
+					'event_espresso'
715
+				),
716
+				'<h2>' . $report_title . '</h2><p>',
717
+				'</p>'
718
+			),
719
+		);
720
+		wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params);
721
+		return $report_ID;
722
+	}
723
+
724
+
725
+
726
+	/**
727
+	 * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
728
+	 *
729
+	 * @access protected
730
+	 * @return void
731
+	 * @throws \EE_Error
732
+	 */
733
+	protected function _registration_checkin_list_table()
734
+	{
735
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
736
+		$reg_id = isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : null;
737
+		/** @var EE_Registration $registration */
738
+		$registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
739
+		$attendee = $registration->attendee();
740
+		$this->_admin_page_title .= $this->get_action_link_or_button(
741
+			'new_registration',
742
+			'add-registrant',
743
+			array('event_id' => $registration->event_ID()),
744
+			'add-new-h2'
745
+		);
746
+		$legend_items = array(
747
+			'checkin'  => array(
748
+				'class' => 'ee-icon ee-icon-check-in',
749
+				'desc'  => __('This indicates the attendee has been checked in', 'event_espresso'),
750
+			),
751
+			'checkout' => array(
752
+				'class' => 'ee-icon ee-icon-check-out',
753
+				'desc'  => __('This indicates the attendee has been checked out', 'event_espresso'),
754
+			),
755
+		);
756
+		$this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
757
+		$dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
758
+		/** @var EE_Datetime $datetime */
759
+		$datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id);
760
+		$datetime_label = '';
761
+		if ($datetime instanceof EE_Datetime) {
762
+			$datetime_label = $datetime->get_dtt_display_name(true);
763
+			$datetime_label .= ! empty($datetime_label)
764
+				? ' (' . $datetime->get_dtt_display_name() . ')'
765
+				: $datetime->get_dtt_display_name();
766
+		}
767
+		$datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
768
+			? EE_Admin_Page::add_query_args_and_nonce(
769
+				array(
770
+					'action'   => 'event_registrations',
771
+					'event_id' => $registration->event_ID(),
772
+					'DTT_ID'   => $dtt_id,
773
+				),
774
+				$this->_admin_base_url
775
+			)
776
+			: '';
777
+		$datetime_link = ! empty($datetime_link)
778
+			? '<a href="' . $datetime_link . '">'
779
+			  . '<span id="checkin-dtt">'
780
+			  . $datetime_label
781
+			  . '</span></a>'
782
+			: $datetime_label;
783
+		$attendee_name = $attendee instanceof EE_Attendee
784
+			? $attendee->full_name()
785
+			: '';
786
+		$attendee_link = $attendee instanceof EE_Attendee
787
+			? $attendee->get_admin_details_link()
788
+			: '';
789
+		$attendee_link = ! empty($attendee_link)
790
+			? '<a href="' . $attendee->get_admin_details_link() . '"'
791
+			  . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
792
+			  . '<span id="checkin-attendee-name">'
793
+			  . $attendee_name
794
+			  . '</span></a>'
795
+			: '';
796
+		$event_link = $registration->event() instanceof EE_Event
797
+			? $registration->event()->get_admin_details_link()
798
+			: '';
799
+		$event_link = ! empty($event_link)
800
+			? '<a href="' . $event_link . '"'
801
+			  . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
802
+			  . '<span id="checkin-event-name">'
803
+			  . $registration->event_name()
804
+			  . '</span>'
805
+			  . '</a>'
806
+			: '';
807
+		$this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
808
+			? '<h2>' . sprintf(
809
+				esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
810
+				$attendee_link,
811
+				$datetime_link,
812
+				$event_link
813
+			) . '</h2>'
814
+			: '';
815
+		$this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
816
+			? '<input type="hidden" name="_REGID" value="' . $reg_id . '">' : '';
817
+		$this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
818
+			? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
819
+		$this->display_admin_list_table_page_with_no_sidebar();
820
+	}
821
+
822
+
823
+
824
+	/**
825
+	 * toggle the Check-in status for the given registration (coming from ajax)
826
+	 *
827
+	 * @return void (JSON)
828
+	 */
829
+	public function toggle_checkin_status()
830
+	{
831
+		//first make sure we have the necessary data
832
+		if ( ! isset($this->_req_data['_regid'])) {
833
+			EE_Error::add_error(
834
+				__(
835
+					'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax',
836
+					'event_espresso'
837
+				),
838
+				__FILE__,
839
+				__FUNCTION__,
840
+				__LINE__
841
+			);
842
+			$this->_template_args['success'] = false;
843
+			$this->_template_args['error'] = true;
844
+			$this->_return_json();
845
+		};
846
+		//do a nonce check cause we're not coming in from an normal route here.
847
+		$nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce'])
848
+			: '';
849
+		$nonce_ref = 'checkin_nonce';
850
+		$this->_verify_nonce($nonce, $nonce_ref);
851
+		//beautiful! Made it this far so let's get the status.
852
+		$new_status = $this->_toggle_checkin_status();
853
+		//setup new class to return via ajax
854
+		$this->_template_args['admin_page_content'] = 'clickable trigger-checkin checkin-icons checkedin-status-'
855
+													  . $new_status;
856
+		$this->_template_args['success'] = true;
857
+		$this->_return_json();
858
+	}
859
+
860
+
861
+
862
+	/**
863
+	 * handles toggling the checkin status for the registration,
864
+	 *
865
+	 * @access protected
866
+	 * @return int|void
867
+	 */
868
+	protected function _toggle_checkin_status()
869
+	{
870
+		//first let's get the query args out of the way for the redirect
871
+		$query_args = array(
872
+			'action'   => 'event_registrations',
873
+			'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
874
+			'DTT_ID'   => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null,
875
+		);
876
+		$new_status = false;
877
+		// bulk action check in toggle
878
+		if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
879
+			// cycle thru checkboxes
880
+			while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) {
881
+				$DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
882
+				$new_status = $this->_toggle_checkin($REG_ID, $DTT_ID);
883
+			}
884
+		} elseif (isset($this->_req_data['_regid'])) {
885
+			//coming from ajax request
886
+			$DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null;
887
+			$query_args['DTT_ID'] = $DTT_ID;
888
+			$new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID);
889
+		} else {
890
+			EE_Error::add_error(
891
+				__('Missing some required data to toggle the Check-in', 'event_espresso'),
892
+				__FILE__,
893
+				__FUNCTION__,
894
+				__LINE__
895
+			);
896
+		}
897
+		if (defined('DOING_AJAX')) {
898
+			return $new_status;
899
+		}
900
+		$this->_redirect_after_action(false, '', '', $query_args, true);
901
+	}
902
+
903
+
904
+
905
+	/**
906
+	 * This is toggles a single Check-in for the given registration and datetime.
907
+	 *
908
+	 * @param  int $REG_ID The registration we're toggling
909
+	 * @param  int $DTT_ID The datetime we're toggling
910
+	 * @return int            The new status toggled to.
911
+	 * @throws \EE_Error
912
+	 */
913
+	private function _toggle_checkin($REG_ID, $DTT_ID)
914
+	{
915
+		/** @var EE_Registration $REG */
916
+		$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
917
+		$new_status = $REG->toggle_checkin_status($DTT_ID);
918
+		if ($new_status !== false) {
919
+			EE_Error::add_success($REG->get_checkin_msg($DTT_ID));
920
+		} else {
921
+			EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__);
922
+			$new_status = false;
923
+		}
924
+		return $new_status;
925
+	}
926
+
927
+
928
+
929
+	/**
930
+	 * Takes care of deleting multiple EE_Checkin table rows
931
+	 *
932
+	 * @access protected
933
+	 * @return void
934
+	 * @throws \EE_Error
935
+	 */
936
+	protected function _delete_checkin_rows()
937
+	{
938
+		$query_args = array(
939
+			'action' => 'registration_checkins',
940
+			'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
941
+			'_REGID' => isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : 0,
942
+		);
943
+		$errors = 0;
944
+		if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
945
+			while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) {
946
+				if ( ! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
947
+					$errors++;
948
+				}
949
+			}
950
+		} else {
951
+			EE_Error::add_error(
952
+				__(
953
+					'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!',
954
+					'event_espresso'
955
+				),
956
+				__FILE__,
957
+				__FUNCTION__,
958
+				__LINE__
959
+			);
960
+			$this->_redirect_after_action(false, '', '', $query_args, true);
961
+		}
962
+		if ($errors > 0) {
963
+			EE_Error::add_error(
964
+				sprintf(__('There were %d records that did not delete successfully', 'event_espresso'), $errors),
965
+				__FILE__,
966
+				__FUNCTION__,
967
+				__LINE__
968
+			);
969
+		} else {
970
+			EE_Error::add_success(__('Records were successfully deleted', 'event_espresso'));
971
+		}
972
+		$this->_redirect_after_action(false, '', '', $query_args, true);
973
+	}
974
+
975
+
976
+
977
+	/**
978
+	 * Deletes a single EE_Checkin row
979
+	 *
980
+	 * @return void
981
+	 * @throws \EE_Error
982
+	 */
983
+	protected function _delete_checkin_row()
984
+	{
985
+		$query_args = array(
986
+			'action' => 'registration_checkins',
987
+			'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
988
+			'_REGID' => isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : 0,
989
+		);
990
+		if ( ! empty($this->_req_data['CHK_ID'])) {
991
+			if ( ! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
992
+				EE_Error::add_error(
993
+					__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
994
+					__FILE__,
995
+					__FUNCTION__,
996
+					__LINE__
997
+				);
998
+			} else {
999
+				EE_Error::add_success(__('Check-In record successfully deleted', 'event_espresso'));
1000
+			}
1001
+		} else {
1002
+			EE_Error::add_error(
1003
+				__(
1004
+					'In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code',
1005
+					'event_espresso'
1006
+				),
1007
+				__FILE__,
1008
+				__FUNCTION__,
1009
+				__LINE__
1010
+			);
1011
+		}
1012
+		$this->_redirect_after_action(false, '', '', $query_args, true);
1013
+	}
1014
+
1015
+
1016
+
1017
+	/**
1018
+	 *        generates HTML for the Event Registrations List Table
1019
+	 *
1020
+	 * @access protected
1021
+	 * @return void
1022
+	 * @throws \EE_Error
1023
+	 */
1024
+	protected function _event_registrations_list_table()
1025
+	{
1026
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1027
+		$this->_admin_page_title .= isset($this->_req_data['event_id'])
1028
+			? $this->get_action_link_or_button(
1029
+				'new_registration',
1030
+				'add-registrant',
1031
+				array('event_id' => $this->_req_data['event_id']),
1032
+				'add-new-h2',
1033
+				'',
1034
+				false
1035
+			)
1036
+			: '';
1037
+		$legend_items = array(
1038
+			'star-icon'        => array(
1039
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1040
+				'desc'  => __('This Registrant is the Primary Registrant', 'event_espresso'),
1041
+			),
1042
+			'checkin'          => array(
1043
+				'class' => 'ee-icon ee-icon-check-in',
1044
+				'desc'  => __('This Registrant has been Checked In', 'event_espresso'),
1045
+			),
1046
+			'checkout'         => array(
1047
+				'class' => 'ee-icon ee-icon-check-out',
1048
+				'desc'  => __('This Registrant has been Checked Out', 'event_espresso'),
1049
+			),
1050
+			'nocheckinrecord'  => array(
1051
+				'class' => 'dashicons dashicons-no',
1052
+				'desc'  => __('No Check-in Record has been Created for this Registrant', 'event_espresso'),
1053
+			),
1054
+			'view_details'     => array(
1055
+				'class' => 'dashicons dashicons-search',
1056
+				'desc'  => __('View All Check-in Records for this Registrant', 'event_espresso'),
1057
+			),
1058
+			'approved_status'  => array(
1059
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1060
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1061
+			),
1062
+			'cancelled_status' => array(
1063
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1064
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1065
+			),
1066
+			'declined_status'  => array(
1067
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1068
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1069
+			),
1070
+			'not_approved'     => array(
1071
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1072
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1073
+			),
1074
+			'pending_status'   => array(
1075
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1076
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1077
+			),
1078
+			'wait_list'        => array(
1079
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1080
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1081
+			),
1082
+		);
1083
+		$this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
1084
+		$event_id = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null;
1085
+		$this->_template_args['before_list_table'] = ! empty($event_id)
1086
+			? '<h2>' . sprintf(
1087
+				__('Viewing Registrations for Event: %s', 'event_espresso'),
1088
+				EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1089
+			) . '</h2>'
1090
+			: '';
1091
+		//need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on the event.
1092
+		/** @var EE_Event $event */
1093
+		$event = EEM_Event::instance()->get_one_by_ID($event_id);
1094
+		$DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0;
1095
+		$datetime = null;
1096
+		if ($event instanceof EE_Event) {
1097
+			$datetimes_on_event = $event->datetimes();
1098
+			if (count($datetimes_on_event) === 1) {
1099
+				$datetime = reset($datetimes_on_event);
1100
+			}
1101
+		}
1102
+		$datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1103
+		if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') {
1104
+			$this->_template_args['before_list_table'] = substr($this->_template_args['before_list_table'], 0, -5);
1105
+			$this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1106
+			$this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1107
+			$this->_template_args['before_list_table'] .= $datetime->name();
1108
+			$this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1109
+			$this->_template_args['before_list_table'] .= '</span></h2>';
1110
+		}
1111
+		//if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status column
1112
+		//represents
1113
+		if ( ! $datetime instanceof EE_Datetime) {
1114
+			$this->_template_args['before_list_table'] .= '<br><p class="description">'
1115
+														  . __('In this view, the check-in status represents the latest check-in record for the registration in that row.',
1116
+					'event_espresso')
1117
+														  . '</p>';
1118
+		}
1119
+		$this->display_admin_list_table_page_with_no_sidebar();
1120
+	}
1121
+
1122
+	/**
1123
+	 * Download the registrations check-in report (same as the normal registration report, but with different where
1124
+	 * conditions)
1125
+	 *
1126
+	 * @return void ends the request by a redirect or download
1127
+	 */
1128
+	public function _registrations_checkin_report()
1129
+	{
1130
+		$this->_registrations_report_base('_get_checkin_query_params_from_request');
1131
+	}
1132
+
1133
+	/**
1134
+	 * Gets the query params from the request, plus adds a where condition for the registration status,
1135
+	 * because on the checkin page we only ever want to see approved and pending-approval registrations
1136
+	 *
1137
+	 * @param array     $request
1138
+	 * @param int  $per_page
1139
+	 * @param bool $count
1140
+	 * @return array
1141
+	 */
1142
+	protected function _get_checkin_query_params_from_request(
1143
+		$request,
1144
+		$per_page = 10,
1145
+		$count = false
1146
+	) {
1147
+		$query_params = $this->_get_registration_query_parameters($request, $per_page, $count);
1148
+		//unlike the regular registrations list table,
1149
+		$status_ids_array = apply_filters(
1150
+			'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
1151
+			array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved)
1152
+		);
1153
+		$query_params[0]['STS_ID'] = array('IN', $status_ids_array);
1154
+		return $query_params;
1155
+	}
1156
+
1157
+
1158
+
1159
+
1160
+	/**
1161
+	 * Gets registrations for an event
1162
+	 *
1163
+	 * @param int    $per_page
1164
+	 * @param bool   $count whether to return count or data.
1165
+	 * @param bool   $trash
1166
+	 * @param string $orderby
1167
+	 * @return EE_Registration[]|int
1168
+	 * @throws \EE_Error
1169
+	 */
1170
+	public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname')
1171
+	{
1172
+		//normalize some request params that get setup by the parent `get_registrations` method.
1173
+		$request = $this->_req_data;
1174
+		$request['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : $orderby;
1175
+		$request['order'] =  ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'ASC';
1176
+		if($trash){
1177
+			$request['status'] = 'trash';
1178
+		}
1179
+		$query_params = $this->_get_checkin_query_params_from_request( $request, $per_page, $count );
1180
+		/**
1181
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1182
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1183
+		 * @see EEM_Base::get_all()
1184
+		 */
1185
+		$query_params['group_by'] = '';
1186
+
1187
+		return $count
1188
+			? EEM_Registration::instance()->count($query_params)
1189
+			/** @type EE_Registration[] */
1190
+			: EEM_Registration::instance()->get_all($query_params);
1191
+	}
1192 1192
 
1193 1193
 } //end class Registrations Admin Page
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +192 added lines, -192 removed lines patch added patch discarded remove patch
@@ -38,217 +38,217 @@
 block discarded – undo
38 38
  * @since       4.0
39 39
  */
40 40
 if (function_exists('espresso_version')) {
41
-    if (! function_exists('espresso_duplicate_plugin_error')) {
42
-        /**
43
-         *    espresso_duplicate_plugin_error
44
-         *    displays if more than one version of EE is activated at the same time
45
-         */
46
-        function espresso_duplicate_plugin_error()
47
-        {
48
-            ?>
41
+	if (! function_exists('espresso_duplicate_plugin_error')) {
42
+		/**
43
+		 *    espresso_duplicate_plugin_error
44
+		 *    displays if more than one version of EE is activated at the same time
45
+		 */
46
+		function espresso_duplicate_plugin_error()
47
+		{
48
+			?>
49 49
             <div class="error">
50 50
                 <p>
51 51
                     <?php
52
-                    echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                    ); ?>
52
+					echo esc_html__(
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+					); ?>
56 56
                 </p>
57 57
             </div>
58 58
             <?php
59
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-        }
61
-    }
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
59
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+		}
61
+	}
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 
64 64
 } else {
65
-    define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
66
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
67
-        /**
68
-         * espresso_minimum_php_version_error
69
-         *
70
-         * @return void
71
-         */
72
-        function espresso_minimum_php_version_error()
73
-        {
74
-            ?>
65
+	define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
66
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
67
+		/**
68
+		 * espresso_minimum_php_version_error
69
+		 *
70
+		 * @return void
71
+		 */
72
+		function espresso_minimum_php_version_error()
73
+		{
74
+			?>
75 75
             <div class="error">
76 76
                 <p>
77 77
                     <?php
78
-                    printf(
79
-                        esc_html__(
80
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
81
-                            'event_espresso'
82
-                        ),
83
-                        EE_MIN_PHP_VER_REQUIRED,
84
-                        PHP_VERSION,
85
-                        '<br/>',
86
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
87
-                    );
88
-                    ?>
78
+					printf(
79
+						esc_html__(
80
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
81
+							'event_espresso'
82
+						),
83
+						EE_MIN_PHP_VER_REQUIRED,
84
+						PHP_VERSION,
85
+						'<br/>',
86
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
87
+					);
88
+					?>
89 89
                 </p>
90 90
             </div>
91 91
             <?php
92
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
93
-        }
92
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
93
+		}
94 94
 
95
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
96
-    } else {
97
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
98
-        /**
99
-         * espresso_version
100
-         * Returns the plugin version
101
-         *
102
-         * @return string
103
-         */
104
-        function espresso_version()
105
-        {
106
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.46.rc.051');
107
-        }
95
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
96
+	} else {
97
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
98
+		/**
99
+		 * espresso_version
100
+		 * Returns the plugin version
101
+		 *
102
+		 * @return string
103
+		 */
104
+		function espresso_version()
105
+		{
106
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.46.rc.051');
107
+		}
108 108
 
109
-        /**
110
-         * espresso_plugin_activation
111
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
112
-         */
113
-        function espresso_plugin_activation()
114
-        {
115
-            update_option('ee_espresso_activation', true);
116
-        }
109
+		/**
110
+		 * espresso_plugin_activation
111
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
112
+		 */
113
+		function espresso_plugin_activation()
114
+		{
115
+			update_option('ee_espresso_activation', true);
116
+		}
117 117
 
118
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
119
-        /**
120
-         *    espresso_load_error_handling
121
-         *    this function loads EE's class for handling exceptions and errors
122
-         */
123
-        function espresso_load_error_handling()
124
-        {
125
-            static $error_handling_loaded = false;
126
-            if ($error_handling_loaded) {
127
-                return;
128
-            }
129
-            // load debugging tools
130
-            if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
131
-                require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
132
-                \EEH_Debug_Tools::instance();
133
-            }
134
-            // load error handling
135
-            if (is_readable(EE_CORE . 'EE_Error.core.php')) {
136
-                require_once(EE_CORE . 'EE_Error.core.php');
137
-            } else {
138
-                wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
139
-            }
140
-            $error_handling_loaded = true;
141
-        }
118
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
119
+		/**
120
+		 *    espresso_load_error_handling
121
+		 *    this function loads EE's class for handling exceptions and errors
122
+		 */
123
+		function espresso_load_error_handling()
124
+		{
125
+			static $error_handling_loaded = false;
126
+			if ($error_handling_loaded) {
127
+				return;
128
+			}
129
+			// load debugging tools
130
+			if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
131
+				require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
132
+				\EEH_Debug_Tools::instance();
133
+			}
134
+			// load error handling
135
+			if (is_readable(EE_CORE . 'EE_Error.core.php')) {
136
+				require_once(EE_CORE . 'EE_Error.core.php');
137
+			} else {
138
+				wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
139
+			}
140
+			$error_handling_loaded = true;
141
+		}
142 142
 
143
-        /**
144
-         *    espresso_load_required
145
-         *    given a class name and path, this function will load that file or throw an exception
146
-         *
147
-         * @param    string $classname
148
-         * @param    string $full_path_to_file
149
-         * @throws    EE_Error
150
-         */
151
-        function espresso_load_required($classname, $full_path_to_file)
152
-        {
153
-            if (is_readable($full_path_to_file)) {
154
-                require_once($full_path_to_file);
155
-            } else {
156
-                throw new \EE_Error (
157
-                    sprintf(
158
-                        esc_html__(
159
-                            'The %s class file could not be located or is not readable due to file permissions.',
160
-                            'event_espresso'
161
-                        ),
162
-                        $classname
163
-                    )
164
-                );
165
-            }
166
-        }
143
+		/**
144
+		 *    espresso_load_required
145
+		 *    given a class name and path, this function will load that file or throw an exception
146
+		 *
147
+		 * @param    string $classname
148
+		 * @param    string $full_path_to_file
149
+		 * @throws    EE_Error
150
+		 */
151
+		function espresso_load_required($classname, $full_path_to_file)
152
+		{
153
+			if (is_readable($full_path_to_file)) {
154
+				require_once($full_path_to_file);
155
+			} else {
156
+				throw new \EE_Error (
157
+					sprintf(
158
+						esc_html__(
159
+							'The %s class file could not be located or is not readable due to file permissions.',
160
+							'event_espresso'
161
+						),
162
+						$classname
163
+					)
164
+				);
165
+			}
166
+		}
167 167
 
168
-        /**
169
-         * @since 4.9.27
170
-         * @throws \EE_Error
171
-         * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
172
-         * @throws \EventEspresso\core\exceptions\InvalidEntityException
173
-         * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
174
-         * @throws \EventEspresso\core\exceptions\InvalidClassException
175
-         * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
176
-         * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException
177
-         * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException
178
-         * @throws \OutOfBoundsException
179
-         */
180
-        function bootstrap_espresso()
181
-        {
182
-            require_once(plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE) . 'core/espresso_definitions.php');
183
-            try {
184
-                espresso_load_error_handling();
185
-                espresso_load_required(
186
-                    'EEH_Base',
187
-                    EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php'
188
-                );
189
-                espresso_load_required(
190
-                    'EEH_File',
191
-                    EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php'
192
-                );
193
-                espresso_load_required(
194
-                    'EEH_File',
195
-                    EE_CORE . 'helpers' . DS . 'EEH_File.helper.php'
196
-                );
197
-                espresso_load_required(
198
-                    'EEH_Array',
199
-                    EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php'
200
-                );
201
-                // instantiate and configure PSR4 autoloader
202
-                espresso_load_required(
203
-                    'Psr4Autoloader',
204
-                    EE_CORE . 'Psr4Autoloader.php'
205
-                );
206
-                espresso_load_required(
207
-                    'EE_Psr4AutoloaderInit',
208
-                    EE_CORE . 'EE_Psr4AutoloaderInit.core.php'
209
-                );
210
-                $AutoloaderInit = new EE_Psr4AutoloaderInit();
211
-                $AutoloaderInit->initializeAutoloader();
212
-                espresso_load_required(
213
-                    'EE_Request',
214
-                    EE_CORE . 'request_stack' . DS . 'EE_Request.core.php'
215
-                );
216
-                espresso_load_required(
217
-                    'EE_Response',
218
-                    EE_CORE . 'request_stack' . DS . 'EE_Response.core.php'
219
-                );
220
-                espresso_load_required(
221
-                    'EE_Bootstrap',
222
-                    EE_CORE . 'EE_Bootstrap.core.php'
223
-                );
224
-                // bootstrap EE and the request stack
225
-                new EE_Bootstrap(
226
-                    new EE_Request($_GET, $_POST, $_COOKIE),
227
-                    new EE_Response()
228
-                );
229
-            } catch (Exception $e) {
230
-                require_once EE_CORE . 'exceptions.' . DS . 'ExceptionStackTraceDisplay.php';
231
-                new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e);
232
-            }
233
-        }
234
-        bootstrap_espresso();
235
-    }
168
+		/**
169
+		 * @since 4.9.27
170
+		 * @throws \EE_Error
171
+		 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
172
+		 * @throws \EventEspresso\core\exceptions\InvalidEntityException
173
+		 * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
174
+		 * @throws \EventEspresso\core\exceptions\InvalidClassException
175
+		 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
176
+		 * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException
177
+		 * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException
178
+		 * @throws \OutOfBoundsException
179
+		 */
180
+		function bootstrap_espresso()
181
+		{
182
+			require_once(plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE) . 'core/espresso_definitions.php');
183
+			try {
184
+				espresso_load_error_handling();
185
+				espresso_load_required(
186
+					'EEH_Base',
187
+					EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php'
188
+				);
189
+				espresso_load_required(
190
+					'EEH_File',
191
+					EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php'
192
+				);
193
+				espresso_load_required(
194
+					'EEH_File',
195
+					EE_CORE . 'helpers' . DS . 'EEH_File.helper.php'
196
+				);
197
+				espresso_load_required(
198
+					'EEH_Array',
199
+					EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php'
200
+				);
201
+				// instantiate and configure PSR4 autoloader
202
+				espresso_load_required(
203
+					'Psr4Autoloader',
204
+					EE_CORE . 'Psr4Autoloader.php'
205
+				);
206
+				espresso_load_required(
207
+					'EE_Psr4AutoloaderInit',
208
+					EE_CORE . 'EE_Psr4AutoloaderInit.core.php'
209
+				);
210
+				$AutoloaderInit = new EE_Psr4AutoloaderInit();
211
+				$AutoloaderInit->initializeAutoloader();
212
+				espresso_load_required(
213
+					'EE_Request',
214
+					EE_CORE . 'request_stack' . DS . 'EE_Request.core.php'
215
+				);
216
+				espresso_load_required(
217
+					'EE_Response',
218
+					EE_CORE . 'request_stack' . DS . 'EE_Response.core.php'
219
+				);
220
+				espresso_load_required(
221
+					'EE_Bootstrap',
222
+					EE_CORE . 'EE_Bootstrap.core.php'
223
+				);
224
+				// bootstrap EE and the request stack
225
+				new EE_Bootstrap(
226
+					new EE_Request($_GET, $_POST, $_COOKIE),
227
+					new EE_Response()
228
+				);
229
+			} catch (Exception $e) {
230
+				require_once EE_CORE . 'exceptions.' . DS . 'ExceptionStackTraceDisplay.php';
231
+				new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e);
232
+			}
233
+		}
234
+		bootstrap_espresso();
235
+	}
236 236
 }
237 237
 if (! function_exists('espresso_deactivate_plugin')) {
238
-    /**
239
-     *    deactivate_plugin
240
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
241
-     *
242
-     * @access public
243
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
244
-     * @return    void
245
-     */
246
-    function espresso_deactivate_plugin($plugin_basename = '')
247
-    {
248
-        if (! function_exists('deactivate_plugins')) {
249
-            require_once(ABSPATH . 'wp-admin/includes/plugin.php');
250
-        }
251
-        unset($_GET['activate'], $_REQUEST['activate']);
252
-        deactivate_plugins($plugin_basename);
253
-    }
238
+	/**
239
+	 *    deactivate_plugin
240
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
241
+	 *
242
+	 * @access public
243
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
244
+	 * @return    void
245
+	 */
246
+	function espresso_deactivate_plugin($plugin_basename = '')
247
+	{
248
+		if (! function_exists('deactivate_plugins')) {
249
+			require_once(ABSPATH . 'wp-admin/includes/plugin.php');
250
+		}
251
+		unset($_GET['activate'], $_REQUEST['activate']);
252
+		deactivate_plugins($plugin_basename);
253
+	}
254 254
 }
Please login to merge, or discard this patch.