Completed
Branch BUG-10202-persistent-admin-not... (260a81)
by
unknown
12:43 queued 14s
created

displayPersistentAdminNotice()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 15
nc 1
nop 1
dl 0
loc 22
rs 9.2
c 1
b 0
f 0
1
<?php
2
namespace EventEspresso\core\services\notifications;
3
4
use DomainException;
5
use EE_Error;
6
use EE_Request;
7
use EventEspresso\core\domain\entities\notifications\PersistentAdminNotice;
8
use EventEspresso\core\domain\services\capabilities\CapabilitiesChecker;
9
use EventEspresso\core\exceptions\InsufficientPermissionsException;
10
use EventEspresso\core\exceptions\InvalidClassException;
11
use EventEspresso\core\exceptions\InvalidDataTypeException;
12
use EventEspresso\core\exceptions\InvalidInterfaceException;
13
use EventEspresso\core\services\collections\Collection;
14
15
defined('EVENT_ESPRESSO_VERSION') || exit;
16
17
18
19
/**
20
 * Class PersistentAdminNoticeManager
21
 * class for managing the loading, display, and storage of PersistentAdminNotice objects
22
 *
23
 * @package Event Espresso
24
 * @author  Brent Christensen
25
 * @since   4.9.27
26
 */
27
class PersistentAdminNoticeManager
28
{
29
30
    const WP_OPTION_KEY = 'ee_pers_admin_notices';
31
32
    /**
33
     * @var Collection|PersistentAdminNotice[] $notice_collection
34
     */
35
    private $notice_collection;
36
37
    /**
38
     * @type string $return_url
39
     */
40
    private $return_url;
41
42
    /**
43
     * @type CapabilitiesChecker $capabilities_checker
44
     */
45
    private $capabilities_checker;
46
47
    /**
48
     * @type EE_Request $request
49
     */
50
    private $request;
51
52
53
54
    /**
55
     * CapChecker constructor
56
     *
57
     * @param string $return_url
58
     * @param CapabilitiesChecker $capabilities_checker
59
     * @param EE_Request          $request
60
     * @throws InvalidDataTypeException
61
     */
62
    public function __construct($return_url = '', CapabilitiesChecker $capabilities_checker, EE_Request $request)
63
    {
64
        $this->setReturnUrl($return_url);
65
        $this->capabilities_checker = $capabilities_checker;
66
        $this->request = $request;
67
        //ok so we want to enable the entire admin
68
        add_action('admin_notices', array($this, 'displayNotices'), 9);
69
        add_action('network_admin_notices', array($this, 'displayNotices'), 9);
70
        add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismissNotice'));
71
        add_action('shutdown', array($this, 'saveNotices'));
72
    }
73
74
75
76
    /**
77
     * @param string $return_url
78
     * @throws InvalidDataTypeException
79
     */
80
    private function setReturnUrl($return_url)
81
    {
82
        if ( ! is_string($return_url)) {
83
            throw new InvalidDataTypeException('$return_url', $return_url, 'string');
84
        }
85
        $this->return_url = $return_url;
86
    }
87
88
89
90
    /**
91
     * @return Collection
92
     * @throws InvalidInterfaceException
93
     * @throws InvalidDataTypeException
94
     * @throws DomainException
95
     */
96
    protected function getPersistentAdminNoticeCollection()
97
    {
98
        if ( ! $this->notice_collection instanceof Collection) {
99
            $this->notice_collection = new Collection(
100
                '\EventEspresso\core\domain\entities\notifications\PersistentAdminNotice'
101
            );
102
            $this->retrieveStoredNotices();
103
            $this->registerNotices();
104
        }
105
        return $this->notice_collection;
106
    }
107
108
109
110
    /**
111
     * generates PersistentAdminNotice objects for all non-dismissed notices saved to the db
112
     *
113
     * @return void
114
     * @throws DomainException
115
     * @throws InvalidDataTypeException
116
     */
117
    public function retrieveStoredNotices()
118
    {
119
        $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array());
120
        // \EEH_Debug_Tools::printr($persistent_admin_notices, '$persistent_admin_notices', __FILE__, __LINE__);
121
        if ( ! empty($persistent_admin_notices)) {
122
            foreach ($persistent_admin_notices as $name => $details) {
123
                if (is_array($details)){
124
                    if (
125
                        ! isset(
126
                            $details['message'],
127
                            $details['capability'],
128
                            $details['cap_context'],
129
                            $details['dismissed']
130
                        )
131
                    ) {
132
                        throw new DomainException(
133
                            sprintf(
134
                                esc_html__(
135
                                    'The "%1$s" PersistentAdminNotice could not be retrieved from the database.',
136
                                    'event_espresso'
137
                                ),
138
                                $name
139
                            )
140
                        );
141
                    }
142
                    // new format for nag notices
143
                    new PersistentAdminNotice(
144
                        $name,
145
                        $details['message'],
146
                        false,
147
                        $details['capability'],
148
                        $details['cap_context'],
149
                        $details['dismissed']
150
                    );
151
                } else {
152
                    try {
153
                        // old nag notices, that we want to convert to the new format
154
                        new PersistentAdminNotice(
155
                            $name,
156
                            (string)$details,
157
                            false,
158
                            '',
159
                            '',
160
                            empty($details)
161
                        );
162
                    } catch (\Exception $e) {
163
                        EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
164
                    }
165
                }
166
                // each notice will self register when the action hook in registerNotices is triggered
167
            }
168
        }
169
    }
170
171
172
173
    /**
174
     * exposes the Persistent Admin Notice Collection via an action
175
     * so that PersistentAdminNotice objects can be added and/or removed
176
     * without compromising the actual collection like a filter would
177
     */
178
    public function registerNotices()
179
    {
180
        do_action(
181
            'AHEE__EventEspresso_core_services_notifications_PersistentAdminNoticeManager__registerNotices',
182
            $this->notice_collection
183
        );
184
    }
185
186
187
188
    /**
189
     * @throws DomainException
190
     * @throws InvalidClassException
191
     * @throws InvalidDataTypeException
192
     * @throws InvalidInterfaceException
193
     */
194
    public function displayNotices()
195
    {
196
        $this->notice_collection = $this->getPersistentAdminNoticeCollection();
197
        if ($this->notice_collection->hasObjects()) {
198
            // and display notices
199
            foreach ($this->notice_collection as $persistent_admin_notice) {
200
                /** @var PersistentAdminNotice $persistent_admin_notice */
201
                // don't display notices that have already been dismissed
202
                if ($persistent_admin_notice->getDismissed()) {
203
                    continue;
204
                }
205
                try {
206
                    $this->capabilities_checker->processCapCheck(
207
                        $persistent_admin_notice->getCapCheck()
208
                    );
209
                } catch (InsufficientPermissionsException $e) {
210
                    // user does not have required cap, so skip to next notice
211
                    // and just eat the exception - nom nom nom nom
212
                    continue;
213
                }
214
                $this->displayPersistentAdminNotice($persistent_admin_notice);
215
            }
216
        }
217
    }
218
219
220
221
    /**
222
     * does what it's named
223
     *
224
     * @return bool
225
     */
226
    public function enqueueAssets()
227
    {
228
        static $print_scripts = true;
229
        if (! $print_scripts) {
230
            return $print_scripts;
231
        }
232
        wp_register_script(
233
            'espresso_core',
234
            EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
235
            array('jquery'),
236
            EVENT_ESPRESSO_VERSION,
237
            true
238
        );
239
        wp_register_script(
240
            'ee_error_js',
241
            EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
242
            array('espresso_core'),
243
            EVENT_ESPRESSO_VERSION,
244
            true
245
        );
246
        wp_enqueue_script('ee_error_js');
247
        $print_scripts = true;
248
        return $print_scripts;
249
    }
250
251
252
253
254
    /**
255
     * displayPersistentAdminNoticeHtml
256
     *
257
     * @param  PersistentAdminNotice $persistent_admin_notice
258
     */
259
    public function displayPersistentAdminNotice(PersistentAdminNotice $persistent_admin_notice)
260
    {
261
        // used in template for printing css
262
        $print_styles = $this->enqueueAssets();
263
        wp_localize_script(
264
            'espresso_core',
265
            'ee_dismiss',
266
            array(
267
                'nag_notice'    => $persistent_admin_notice->getName(),
268
                'return_url'    => urlencode($this->return_url),
269
                'ajax_url'      => WP_AJAX_URL,
270
                'unknown_error' => esc_html__(
271
                    'An unknown error has occurred on the server while attempting to dismiss this notice.',
272
                    'event_espresso'
273
                )
274
            )
275
        );
276
        // used in template
277
        $persistent_admin_notice_name = $persistent_admin_notice->getName();
278
        $persistent_admin_notice_message = $persistent_admin_notice->getMessage();
279
        require EE_TEMPLATES . DS . 'notifications' . DS . 'persistent_admin_notice.template.php';
280
    }
281
282
283
284
    /**
285
     * dismissNotice
286
     *
287
     * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed
288
     * @param bool   $purge    if true, then delete it from the db
289
     * @param bool   $return   forget all of this AJAX or redirect nonsense, and just return
290
     * @return void
291
     * @throws InvalidInterfaceException
292
     * @throws InvalidDataTypeException
293
     * @throws DomainException
294
     */
295
    public function dismissNotice($pan_name = '', $purge = false, $return = false)
296
    {
297
        $pan_name = $this->request->get('ee_nag_notice', $pan_name);
298
        $this->notice_collection = $this->getPersistentAdminNoticeCollection();
299
        if ( ! empty($pan_name) && $this->notice_collection->has($pan_name)){
300
            /** @var PersistentAdminNotice $persistent_admin_notice */
301
            $persistent_admin_notice = $this->notice_collection->get($pan_name);
302
            $persistent_admin_notice->setDismissed(true);
303
            $persistent_admin_notice->setPurge($purge);
304
            $this->saveNotices();
305
        }
306
        if ($return) {
307
            return;
308
        } else if ($this->request->ajax) {
309
            // grab any notices and concatenate into string
310
            echo wp_json_encode(
311
                array(
312
                    'errors' => implode('<br />', EE_Error::get_notices(false))
313
                )
314
            );
315
            exit();
316
        } else {
317
            // save errors to a transient to be displayed on next request (after redirect)
318
            EE_Error::get_notices(false, true);
319
            wp_safe_redirect(
320
                urldecode(
321
                    $this->request->get('return_url', '')
322
                )
323
            );
324
        }
325
    }
326
327
328
329
    /**
330
     * saveNotices
331
     *
332
     * @throws DomainException
333
     * @throws InvalidDataTypeException
334
     * @throws InvalidInterfaceException
335
     */
336
    public function saveNotices()
337
    {
338
        $this->notice_collection = $this->getPersistentAdminNoticeCollection();
339
        if ($this->notice_collection->hasObjects()) {
340
            $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array());
341
            //maybe initialize persistent_admin_notices
342
            if (empty($persistent_admin_notices)) {
343
                add_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array(), '', 'no');
344
            }
345
            foreach ($this->notice_collection as $persistent_admin_notice) {
346
                // are we deleting this notice ?
347
                if ($persistent_admin_notice->getPurge()) {
348
                    unset($persistent_admin_notices[$persistent_admin_notice->getName()]);
349
                } else {
350
                    /** @var PersistentAdminNotice $persistent_admin_notice */
351
                    $persistent_admin_notices[$persistent_admin_notice->getName()] = array(
352
                        'message'     => $persistent_admin_notice->getMessage(),
353
                        'capability'  => $persistent_admin_notice->getCapability(),
354
                        'cap_context' => $persistent_admin_notice->getCapContext(),
355
                        'dismissed'   => $persistent_admin_notice->getDismissed(),
356
                    );
357
                }
358
            }
359
            update_option(PersistentAdminNoticeManager::WP_OPTION_KEY, $persistent_admin_notices);
360
        }
361
    }
362
363
364
365
}
366
// End of file PersistentAdminNoticeManager.php
367
// Location: EventEspresso\core\services\notifications/PersistentAdminNoticeManager.php