@@ -30,392 +30,392 @@ |
||
30 | 30 | */ |
31 | 31 | class PersistentAdminNoticeManager |
32 | 32 | { |
33 | - const WP_OPTION_KEY = 'ee_pers_admin_notices'; |
|
34 | - |
|
35 | - /** |
|
36 | - * @var Collection|PersistentAdminNotice[] $notice_collection |
|
37 | - */ |
|
38 | - private $notice_collection; |
|
39 | - |
|
40 | - /** |
|
41 | - * if AJAX is not enabled, then the return URL will be used for redirecting back to the admin page where the |
|
42 | - * persistent admin notice was displayed, and ultimately dismissed from. |
|
43 | - * |
|
44 | - * @var string $return_url |
|
45 | - */ |
|
46 | - private $return_url; |
|
47 | - |
|
48 | - /** |
|
49 | - * @var CapabilitiesChecker $capabilities_checker |
|
50 | - */ |
|
51 | - private $capabilities_checker; |
|
52 | - |
|
53 | - /** |
|
54 | - * @var RequestInterface $request |
|
55 | - */ |
|
56 | - private $request; |
|
57 | - |
|
58 | - |
|
59 | - /** |
|
60 | - * PersistentAdminNoticeManager constructor |
|
61 | - * |
|
62 | - * @param CapabilitiesChecker $capabilities_checker |
|
63 | - * @param RequestInterface $request |
|
64 | - * @param string $return_url where to redirect to after dismissing notices |
|
65 | - * @throws InvalidDataTypeException |
|
66 | - */ |
|
67 | - public function __construct( |
|
68 | - CapabilitiesChecker $capabilities_checker, |
|
69 | - RequestInterface $request, |
|
70 | - string $return_url = '' |
|
71 | - ) { |
|
72 | - $this->setReturnUrl($return_url); |
|
73 | - $this->capabilities_checker = $capabilities_checker; |
|
74 | - $this->request = $request; |
|
75 | - // setup up notices at priority 9 because `EE_Admin::display_admin_notices()` runs at priority 10, |
|
76 | - // and we want to retrieve and generate any nag notices at the last possible moment |
|
77 | - add_action('admin_notices', array($this, 'displayNotices'), 9); |
|
78 | - add_action('network_admin_notices', array($this, 'displayNotices'), 9); |
|
79 | - add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismissNotice')); |
|
80 | - add_action('shutdown', array($this, 'registerAndSaveNotices'), 998); |
|
81 | - } |
|
82 | - |
|
83 | - |
|
84 | - /** |
|
85 | - * @param string $return_url |
|
86 | - * @throws InvalidDataTypeException |
|
87 | - */ |
|
88 | - public function setReturnUrl($return_url) |
|
89 | - { |
|
90 | - if (! is_string($return_url)) { |
|
91 | - throw new InvalidDataTypeException('$return_url', $return_url, 'string'); |
|
92 | - } |
|
93 | - $this->return_url = $return_url; |
|
94 | - } |
|
95 | - |
|
96 | - |
|
97 | - /** |
|
98 | - * @return Collection |
|
99 | - * @throws InvalidEntityException |
|
100 | - * @throws InvalidInterfaceException |
|
101 | - * @throws InvalidDataTypeException |
|
102 | - * @throws DomainException |
|
103 | - * @throws DuplicateCollectionIdentifierException |
|
104 | - */ |
|
105 | - protected function getPersistentAdminNoticeCollection() |
|
106 | - { |
|
107 | - if (! $this->notice_collection instanceof Collection) { |
|
108 | - $this->notice_collection = new Collection( |
|
109 | - 'EventEspresso\core\domain\entities\notifications\PersistentAdminNotice' |
|
110 | - ); |
|
111 | - $this->retrieveStoredNotices(); |
|
112 | - $this->registerNotices(); |
|
113 | - } |
|
114 | - return $this->notice_collection; |
|
115 | - } |
|
116 | - |
|
117 | - |
|
118 | - /** |
|
119 | - * generates PersistentAdminNotice objects for all non-dismissed notices saved to the db |
|
120 | - * |
|
121 | - * @return void |
|
122 | - * @throws InvalidEntityException |
|
123 | - * @throws DomainException |
|
124 | - * @throws InvalidDataTypeException |
|
125 | - * @throws DuplicateCollectionIdentifierException |
|
126 | - */ |
|
127 | - protected function retrieveStoredNotices() |
|
128 | - { |
|
129 | - $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array()); |
|
130 | - if (! empty($persistent_admin_notices)) { |
|
131 | - foreach ($persistent_admin_notices as $name => $details) { |
|
132 | - if (is_array($details)) { |
|
133 | - if ( |
|
134 | - ! isset( |
|
135 | - $details['message'], |
|
136 | - $details['capability'], |
|
137 | - $details['cap_context'], |
|
138 | - $details['dismissed'] |
|
139 | - ) |
|
140 | - ) { |
|
141 | - throw new DomainException( |
|
142 | - sprintf( |
|
143 | - esc_html__( |
|
144 | - 'The "%1$s" PersistentAdminNotice could not be retrieved from the database.', |
|
145 | - 'event_espresso' |
|
146 | - ), |
|
147 | - $name |
|
148 | - ) |
|
149 | - ); |
|
150 | - } |
|
151 | - // new format for nag notices |
|
152 | - $this->notice_collection->add( |
|
153 | - new PersistentAdminNotice( |
|
154 | - $name, |
|
155 | - $details['message'], |
|
156 | - false, |
|
157 | - $details['capability'], |
|
158 | - $details['cap_context'], |
|
159 | - $details['dismissed'] |
|
160 | - ), |
|
161 | - sanitize_key($name) |
|
162 | - ); |
|
163 | - } else { |
|
164 | - try { |
|
165 | - // old nag notices, that we want to convert to the new format |
|
166 | - $this->notice_collection->add( |
|
167 | - new PersistentAdminNotice( |
|
168 | - $name, |
|
169 | - (string) $details, |
|
170 | - false, |
|
171 | - '', |
|
172 | - '', |
|
173 | - empty($details) |
|
174 | - ), |
|
175 | - sanitize_key($name) |
|
176 | - ); |
|
177 | - } catch (Exception $e) { |
|
178 | - EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
179 | - } |
|
180 | - } |
|
181 | - // each notice will self register when the action hook in registerNotices is triggered |
|
182 | - } |
|
183 | - } |
|
184 | - } |
|
185 | - |
|
186 | - |
|
187 | - /** |
|
188 | - * exposes the Persistent Admin Notice Collection via an action |
|
189 | - * so that PersistentAdminNotice objects can be added and/or removed |
|
190 | - * without compromising the actual collection like a filter would |
|
191 | - */ |
|
192 | - protected function registerNotices() |
|
193 | - { |
|
194 | - do_action( |
|
195 | - 'AHEE__EventEspresso_core_services_notifications_PersistentAdminNoticeManager__registerNotices', |
|
196 | - $this->notice_collection |
|
197 | - ); |
|
198 | - } |
|
199 | - |
|
200 | - |
|
201 | - /** |
|
202 | - * @throws DomainException |
|
203 | - * @throws InvalidClassException |
|
204 | - * @throws InvalidDataTypeException |
|
205 | - * @throws InvalidInterfaceException |
|
206 | - * @throws InvalidEntityException |
|
207 | - * @throws DuplicateCollectionIdentifierException |
|
208 | - */ |
|
209 | - public function displayNotices() |
|
210 | - { |
|
211 | - $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
|
212 | - if ($this->notice_collection->hasObjects()) { |
|
213 | - $enqueue_assets = false; |
|
214 | - // and display notices |
|
215 | - foreach ($this->notice_collection as $persistent_admin_notice) { |
|
216 | - /** @var PersistentAdminNotice $persistent_admin_notice */ |
|
217 | - // don't display notices that have already been dismissed |
|
218 | - if ($persistent_admin_notice->getDismissed()) { |
|
219 | - continue; |
|
220 | - } |
|
221 | - try { |
|
222 | - $this->capabilities_checker->processCapCheck( |
|
223 | - $persistent_admin_notice->getCapCheck() |
|
224 | - ); |
|
225 | - } catch (InsufficientPermissionsException $e) { |
|
226 | - // user does not have required cap, so skip to next notice |
|
227 | - // and just eat the exception - nom nom nom nom |
|
228 | - continue; |
|
229 | - } |
|
230 | - if ($persistent_admin_notice->getMessage() === '') { |
|
231 | - continue; |
|
232 | - } |
|
233 | - $this->displayPersistentAdminNotice($persistent_admin_notice); |
|
234 | - $enqueue_assets = true; |
|
235 | - } |
|
236 | - if ($enqueue_assets) { |
|
237 | - $this->enqueueAssets(); |
|
238 | - } |
|
239 | - } |
|
240 | - } |
|
241 | - |
|
242 | - |
|
243 | - /** |
|
244 | - * does what it's named |
|
245 | - * |
|
246 | - * @return void |
|
247 | - */ |
|
248 | - public function enqueueAssets() |
|
249 | - { |
|
250 | - wp_register_script( |
|
251 | - 'espresso_core', |
|
252 | - EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js', |
|
253 | - array('jquery'), |
|
254 | - EVENT_ESPRESSO_VERSION, |
|
255 | - true |
|
256 | - ); |
|
257 | - wp_register_script( |
|
258 | - 'ee_error_js', |
|
259 | - EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js', |
|
260 | - array('espresso_core'), |
|
261 | - EVENT_ESPRESSO_VERSION, |
|
262 | - true |
|
263 | - ); |
|
264 | - wp_localize_script( |
|
265 | - 'ee_error_js', |
|
266 | - 'ee_dismiss', |
|
267 | - array( |
|
268 | - 'return_url' => urlencode($this->return_url), |
|
269 | - 'ajax_url' => WP_AJAX_URL, |
|
270 | - 'unknown_error' => wp_strip_all_tags( |
|
271 | - __( |
|
272 | - 'An unknown error has occurred on the server while attempting to dismiss this notice.', |
|
273 | - 'event_espresso' |
|
274 | - ) |
|
275 | - ), |
|
276 | - ) |
|
277 | - ); |
|
278 | - wp_enqueue_script('ee_error_js'); |
|
279 | - } |
|
280 | - |
|
281 | - |
|
282 | - /** |
|
283 | - * displayPersistentAdminNoticeHtml |
|
284 | - * |
|
285 | - * @param PersistentAdminNotice $persistent_admin_notice |
|
286 | - */ |
|
287 | - protected function displayPersistentAdminNotice(PersistentAdminNotice $persistent_admin_notice) |
|
288 | - { |
|
289 | - // used in template |
|
290 | - $persistent_admin_notice_name = $persistent_admin_notice->getName(); |
|
291 | - $persistent_admin_notice_message = $persistent_admin_notice->getMessage(); |
|
292 | - require EE_TEMPLATES . '/notifications/persistent_admin_notice.template.php'; |
|
293 | - } |
|
294 | - |
|
295 | - |
|
296 | - /** |
|
297 | - * dismissNotice |
|
298 | - * |
|
299 | - * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed |
|
300 | - * @param bool $purge if true, then delete it from the db |
|
301 | - * @param bool $return forget all of this AJAX or redirect nonsense, and just return |
|
302 | - * @return void |
|
303 | - * @throws InvalidEntityException |
|
304 | - * @throws InvalidInterfaceException |
|
305 | - * @throws InvalidDataTypeException |
|
306 | - * @throws DomainException |
|
307 | - * @throws InvalidArgumentException |
|
308 | - * @throws InvalidArgumentException |
|
309 | - * @throws InvalidArgumentException |
|
310 | - * @throws InvalidArgumentException |
|
311 | - * @throws DuplicateCollectionIdentifierException |
|
312 | - */ |
|
313 | - public function dismissNotice($pan_name = '', $purge = false, $return = false) |
|
314 | - { |
|
315 | - $pan_name = $this->request->getRequestParam('ee_nag_notice', $pan_name); |
|
316 | - $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
|
317 | - if (! empty($pan_name) && $this->notice_collection->has($pan_name)) { |
|
318 | - /** @var PersistentAdminNotice $persistent_admin_notice */ |
|
319 | - $persistent_admin_notice = $this->notice_collection->get($pan_name); |
|
320 | - $persistent_admin_notice->setDismissed(true); |
|
321 | - $persistent_admin_notice->setPurge($purge); |
|
322 | - $this->saveNotices(); |
|
323 | - } |
|
324 | - if ($return) { |
|
325 | - return; |
|
326 | - } |
|
327 | - if ($this->request->isAjax()) { |
|
328 | - // grab any notices and concatenate into string |
|
329 | - echo wp_json_encode( |
|
330 | - array( |
|
331 | - 'errors' => implode('<br />', EE_Error::get_notices(false)), |
|
332 | - ) |
|
333 | - ); |
|
334 | - exit(); |
|
335 | - } |
|
336 | - // save errors to a transient to be displayed on next request (after redirect) |
|
337 | - EE_Error::get_notices(false, true); |
|
338 | - wp_safe_redirect( |
|
339 | - urldecode( |
|
340 | - $this->request->getRequestParam('return_url', '') |
|
341 | - ) |
|
342 | - ); |
|
343 | - } |
|
344 | - |
|
345 | - |
|
346 | - /** |
|
347 | - * saveNotices |
|
348 | - * |
|
349 | - * @throws DomainException |
|
350 | - * @throws InvalidDataTypeException |
|
351 | - * @throws InvalidInterfaceException |
|
352 | - * @throws InvalidEntityException |
|
353 | - * @throws DuplicateCollectionIdentifierException |
|
354 | - */ |
|
355 | - public function saveNotices() |
|
356 | - { |
|
357 | - $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
|
358 | - if ($this->notice_collection->hasObjects()) { |
|
359 | - $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array()); |
|
360 | - // maybe initialize persistent_admin_notices |
|
361 | - if (empty($persistent_admin_notices)) { |
|
362 | - add_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array(), '', 'no'); |
|
363 | - } |
|
364 | - foreach ($this->notice_collection as $persistent_admin_notice) { |
|
365 | - // are we deleting this notice ? |
|
366 | - if ($persistent_admin_notice->getPurge()) { |
|
367 | - unset($persistent_admin_notices[ $persistent_admin_notice->getName() ]); |
|
368 | - } else { |
|
369 | - /** @var PersistentAdminNotice $persistent_admin_notice */ |
|
370 | - $persistent_admin_notices[ $persistent_admin_notice->getName() ] = array( |
|
371 | - 'message' => $persistent_admin_notice->getMessage(), |
|
372 | - 'capability' => $persistent_admin_notice->getCapability(), |
|
373 | - 'cap_context' => $persistent_admin_notice->getCapContext(), |
|
374 | - 'dismissed' => $persistent_admin_notice->getDismissed(), |
|
375 | - ); |
|
376 | - } |
|
377 | - } |
|
378 | - update_option(PersistentAdminNoticeManager::WP_OPTION_KEY, $persistent_admin_notices); |
|
379 | - } |
|
380 | - } |
|
381 | - |
|
382 | - |
|
383 | - /** |
|
384 | - * @throws DomainException |
|
385 | - * @throws InvalidDataTypeException |
|
386 | - * @throws InvalidEntityException |
|
387 | - * @throws InvalidInterfaceException |
|
388 | - * @throws DuplicateCollectionIdentifierException |
|
389 | - */ |
|
390 | - public function registerAndSaveNotices() |
|
391 | - { |
|
392 | - $this->getPersistentAdminNoticeCollection(); |
|
393 | - $this->registerNotices(); |
|
394 | - $this->saveNotices(); |
|
395 | - add_filter( |
|
396 | - 'PersistentAdminNoticeManager__registerAndSaveNotices__complete', |
|
397 | - '__return_true' |
|
398 | - ); |
|
399 | - } |
|
400 | - |
|
401 | - |
|
402 | - /** |
|
403 | - * @throws DomainException |
|
404 | - * @throws InvalidDataTypeException |
|
405 | - * @throws InvalidEntityException |
|
406 | - * @throws InvalidInterfaceException |
|
407 | - * @throws InvalidArgumentException |
|
408 | - * @throws DuplicateCollectionIdentifierException |
|
409 | - */ |
|
410 | - public static function loadRegisterAndSaveNotices() |
|
411 | - { |
|
412 | - /** @var PersistentAdminNoticeManager $persistent_admin_notice_manager */ |
|
413 | - $persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared( |
|
414 | - 'EventEspresso\core\services\notifications\PersistentAdminNoticeManager' |
|
415 | - ); |
|
416 | - // if shutdown has already run, then call registerAndSaveNotices() manually |
|
417 | - if (did_action('shutdown')) { |
|
418 | - $persistent_admin_notice_manager->registerAndSaveNotices(); |
|
419 | - } |
|
420 | - } |
|
33 | + const WP_OPTION_KEY = 'ee_pers_admin_notices'; |
|
34 | + |
|
35 | + /** |
|
36 | + * @var Collection|PersistentAdminNotice[] $notice_collection |
|
37 | + */ |
|
38 | + private $notice_collection; |
|
39 | + |
|
40 | + /** |
|
41 | + * if AJAX is not enabled, then the return URL will be used for redirecting back to the admin page where the |
|
42 | + * persistent admin notice was displayed, and ultimately dismissed from. |
|
43 | + * |
|
44 | + * @var string $return_url |
|
45 | + */ |
|
46 | + private $return_url; |
|
47 | + |
|
48 | + /** |
|
49 | + * @var CapabilitiesChecker $capabilities_checker |
|
50 | + */ |
|
51 | + private $capabilities_checker; |
|
52 | + |
|
53 | + /** |
|
54 | + * @var RequestInterface $request |
|
55 | + */ |
|
56 | + private $request; |
|
57 | + |
|
58 | + |
|
59 | + /** |
|
60 | + * PersistentAdminNoticeManager constructor |
|
61 | + * |
|
62 | + * @param CapabilitiesChecker $capabilities_checker |
|
63 | + * @param RequestInterface $request |
|
64 | + * @param string $return_url where to redirect to after dismissing notices |
|
65 | + * @throws InvalidDataTypeException |
|
66 | + */ |
|
67 | + public function __construct( |
|
68 | + CapabilitiesChecker $capabilities_checker, |
|
69 | + RequestInterface $request, |
|
70 | + string $return_url = '' |
|
71 | + ) { |
|
72 | + $this->setReturnUrl($return_url); |
|
73 | + $this->capabilities_checker = $capabilities_checker; |
|
74 | + $this->request = $request; |
|
75 | + // setup up notices at priority 9 because `EE_Admin::display_admin_notices()` runs at priority 10, |
|
76 | + // and we want to retrieve and generate any nag notices at the last possible moment |
|
77 | + add_action('admin_notices', array($this, 'displayNotices'), 9); |
|
78 | + add_action('network_admin_notices', array($this, 'displayNotices'), 9); |
|
79 | + add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismissNotice')); |
|
80 | + add_action('shutdown', array($this, 'registerAndSaveNotices'), 998); |
|
81 | + } |
|
82 | + |
|
83 | + |
|
84 | + /** |
|
85 | + * @param string $return_url |
|
86 | + * @throws InvalidDataTypeException |
|
87 | + */ |
|
88 | + public function setReturnUrl($return_url) |
|
89 | + { |
|
90 | + if (! is_string($return_url)) { |
|
91 | + throw new InvalidDataTypeException('$return_url', $return_url, 'string'); |
|
92 | + } |
|
93 | + $this->return_url = $return_url; |
|
94 | + } |
|
95 | + |
|
96 | + |
|
97 | + /** |
|
98 | + * @return Collection |
|
99 | + * @throws InvalidEntityException |
|
100 | + * @throws InvalidInterfaceException |
|
101 | + * @throws InvalidDataTypeException |
|
102 | + * @throws DomainException |
|
103 | + * @throws DuplicateCollectionIdentifierException |
|
104 | + */ |
|
105 | + protected function getPersistentAdminNoticeCollection() |
|
106 | + { |
|
107 | + if (! $this->notice_collection instanceof Collection) { |
|
108 | + $this->notice_collection = new Collection( |
|
109 | + 'EventEspresso\core\domain\entities\notifications\PersistentAdminNotice' |
|
110 | + ); |
|
111 | + $this->retrieveStoredNotices(); |
|
112 | + $this->registerNotices(); |
|
113 | + } |
|
114 | + return $this->notice_collection; |
|
115 | + } |
|
116 | + |
|
117 | + |
|
118 | + /** |
|
119 | + * generates PersistentAdminNotice objects for all non-dismissed notices saved to the db |
|
120 | + * |
|
121 | + * @return void |
|
122 | + * @throws InvalidEntityException |
|
123 | + * @throws DomainException |
|
124 | + * @throws InvalidDataTypeException |
|
125 | + * @throws DuplicateCollectionIdentifierException |
|
126 | + */ |
|
127 | + protected function retrieveStoredNotices() |
|
128 | + { |
|
129 | + $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array()); |
|
130 | + if (! empty($persistent_admin_notices)) { |
|
131 | + foreach ($persistent_admin_notices as $name => $details) { |
|
132 | + if (is_array($details)) { |
|
133 | + if ( |
|
134 | + ! isset( |
|
135 | + $details['message'], |
|
136 | + $details['capability'], |
|
137 | + $details['cap_context'], |
|
138 | + $details['dismissed'] |
|
139 | + ) |
|
140 | + ) { |
|
141 | + throw new DomainException( |
|
142 | + sprintf( |
|
143 | + esc_html__( |
|
144 | + 'The "%1$s" PersistentAdminNotice could not be retrieved from the database.', |
|
145 | + 'event_espresso' |
|
146 | + ), |
|
147 | + $name |
|
148 | + ) |
|
149 | + ); |
|
150 | + } |
|
151 | + // new format for nag notices |
|
152 | + $this->notice_collection->add( |
|
153 | + new PersistentAdminNotice( |
|
154 | + $name, |
|
155 | + $details['message'], |
|
156 | + false, |
|
157 | + $details['capability'], |
|
158 | + $details['cap_context'], |
|
159 | + $details['dismissed'] |
|
160 | + ), |
|
161 | + sanitize_key($name) |
|
162 | + ); |
|
163 | + } else { |
|
164 | + try { |
|
165 | + // old nag notices, that we want to convert to the new format |
|
166 | + $this->notice_collection->add( |
|
167 | + new PersistentAdminNotice( |
|
168 | + $name, |
|
169 | + (string) $details, |
|
170 | + false, |
|
171 | + '', |
|
172 | + '', |
|
173 | + empty($details) |
|
174 | + ), |
|
175 | + sanitize_key($name) |
|
176 | + ); |
|
177 | + } catch (Exception $e) { |
|
178 | + EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
179 | + } |
|
180 | + } |
|
181 | + // each notice will self register when the action hook in registerNotices is triggered |
|
182 | + } |
|
183 | + } |
|
184 | + } |
|
185 | + |
|
186 | + |
|
187 | + /** |
|
188 | + * exposes the Persistent Admin Notice Collection via an action |
|
189 | + * so that PersistentAdminNotice objects can be added and/or removed |
|
190 | + * without compromising the actual collection like a filter would |
|
191 | + */ |
|
192 | + protected function registerNotices() |
|
193 | + { |
|
194 | + do_action( |
|
195 | + 'AHEE__EventEspresso_core_services_notifications_PersistentAdminNoticeManager__registerNotices', |
|
196 | + $this->notice_collection |
|
197 | + ); |
|
198 | + } |
|
199 | + |
|
200 | + |
|
201 | + /** |
|
202 | + * @throws DomainException |
|
203 | + * @throws InvalidClassException |
|
204 | + * @throws InvalidDataTypeException |
|
205 | + * @throws InvalidInterfaceException |
|
206 | + * @throws InvalidEntityException |
|
207 | + * @throws DuplicateCollectionIdentifierException |
|
208 | + */ |
|
209 | + public function displayNotices() |
|
210 | + { |
|
211 | + $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
|
212 | + if ($this->notice_collection->hasObjects()) { |
|
213 | + $enqueue_assets = false; |
|
214 | + // and display notices |
|
215 | + foreach ($this->notice_collection as $persistent_admin_notice) { |
|
216 | + /** @var PersistentAdminNotice $persistent_admin_notice */ |
|
217 | + // don't display notices that have already been dismissed |
|
218 | + if ($persistent_admin_notice->getDismissed()) { |
|
219 | + continue; |
|
220 | + } |
|
221 | + try { |
|
222 | + $this->capabilities_checker->processCapCheck( |
|
223 | + $persistent_admin_notice->getCapCheck() |
|
224 | + ); |
|
225 | + } catch (InsufficientPermissionsException $e) { |
|
226 | + // user does not have required cap, so skip to next notice |
|
227 | + // and just eat the exception - nom nom nom nom |
|
228 | + continue; |
|
229 | + } |
|
230 | + if ($persistent_admin_notice->getMessage() === '') { |
|
231 | + continue; |
|
232 | + } |
|
233 | + $this->displayPersistentAdminNotice($persistent_admin_notice); |
|
234 | + $enqueue_assets = true; |
|
235 | + } |
|
236 | + if ($enqueue_assets) { |
|
237 | + $this->enqueueAssets(); |
|
238 | + } |
|
239 | + } |
|
240 | + } |
|
241 | + |
|
242 | + |
|
243 | + /** |
|
244 | + * does what it's named |
|
245 | + * |
|
246 | + * @return void |
|
247 | + */ |
|
248 | + public function enqueueAssets() |
|
249 | + { |
|
250 | + wp_register_script( |
|
251 | + 'espresso_core', |
|
252 | + EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js', |
|
253 | + array('jquery'), |
|
254 | + EVENT_ESPRESSO_VERSION, |
|
255 | + true |
|
256 | + ); |
|
257 | + wp_register_script( |
|
258 | + 'ee_error_js', |
|
259 | + EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js', |
|
260 | + array('espresso_core'), |
|
261 | + EVENT_ESPRESSO_VERSION, |
|
262 | + true |
|
263 | + ); |
|
264 | + wp_localize_script( |
|
265 | + 'ee_error_js', |
|
266 | + 'ee_dismiss', |
|
267 | + array( |
|
268 | + 'return_url' => urlencode($this->return_url), |
|
269 | + 'ajax_url' => WP_AJAX_URL, |
|
270 | + 'unknown_error' => wp_strip_all_tags( |
|
271 | + __( |
|
272 | + 'An unknown error has occurred on the server while attempting to dismiss this notice.', |
|
273 | + 'event_espresso' |
|
274 | + ) |
|
275 | + ), |
|
276 | + ) |
|
277 | + ); |
|
278 | + wp_enqueue_script('ee_error_js'); |
|
279 | + } |
|
280 | + |
|
281 | + |
|
282 | + /** |
|
283 | + * displayPersistentAdminNoticeHtml |
|
284 | + * |
|
285 | + * @param PersistentAdminNotice $persistent_admin_notice |
|
286 | + */ |
|
287 | + protected function displayPersistentAdminNotice(PersistentAdminNotice $persistent_admin_notice) |
|
288 | + { |
|
289 | + // used in template |
|
290 | + $persistent_admin_notice_name = $persistent_admin_notice->getName(); |
|
291 | + $persistent_admin_notice_message = $persistent_admin_notice->getMessage(); |
|
292 | + require EE_TEMPLATES . '/notifications/persistent_admin_notice.template.php'; |
|
293 | + } |
|
294 | + |
|
295 | + |
|
296 | + /** |
|
297 | + * dismissNotice |
|
298 | + * |
|
299 | + * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed |
|
300 | + * @param bool $purge if true, then delete it from the db |
|
301 | + * @param bool $return forget all of this AJAX or redirect nonsense, and just return |
|
302 | + * @return void |
|
303 | + * @throws InvalidEntityException |
|
304 | + * @throws InvalidInterfaceException |
|
305 | + * @throws InvalidDataTypeException |
|
306 | + * @throws DomainException |
|
307 | + * @throws InvalidArgumentException |
|
308 | + * @throws InvalidArgumentException |
|
309 | + * @throws InvalidArgumentException |
|
310 | + * @throws InvalidArgumentException |
|
311 | + * @throws DuplicateCollectionIdentifierException |
|
312 | + */ |
|
313 | + public function dismissNotice($pan_name = '', $purge = false, $return = false) |
|
314 | + { |
|
315 | + $pan_name = $this->request->getRequestParam('ee_nag_notice', $pan_name); |
|
316 | + $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
|
317 | + if (! empty($pan_name) && $this->notice_collection->has($pan_name)) { |
|
318 | + /** @var PersistentAdminNotice $persistent_admin_notice */ |
|
319 | + $persistent_admin_notice = $this->notice_collection->get($pan_name); |
|
320 | + $persistent_admin_notice->setDismissed(true); |
|
321 | + $persistent_admin_notice->setPurge($purge); |
|
322 | + $this->saveNotices(); |
|
323 | + } |
|
324 | + if ($return) { |
|
325 | + return; |
|
326 | + } |
|
327 | + if ($this->request->isAjax()) { |
|
328 | + // grab any notices and concatenate into string |
|
329 | + echo wp_json_encode( |
|
330 | + array( |
|
331 | + 'errors' => implode('<br />', EE_Error::get_notices(false)), |
|
332 | + ) |
|
333 | + ); |
|
334 | + exit(); |
|
335 | + } |
|
336 | + // save errors to a transient to be displayed on next request (after redirect) |
|
337 | + EE_Error::get_notices(false, true); |
|
338 | + wp_safe_redirect( |
|
339 | + urldecode( |
|
340 | + $this->request->getRequestParam('return_url', '') |
|
341 | + ) |
|
342 | + ); |
|
343 | + } |
|
344 | + |
|
345 | + |
|
346 | + /** |
|
347 | + * saveNotices |
|
348 | + * |
|
349 | + * @throws DomainException |
|
350 | + * @throws InvalidDataTypeException |
|
351 | + * @throws InvalidInterfaceException |
|
352 | + * @throws InvalidEntityException |
|
353 | + * @throws DuplicateCollectionIdentifierException |
|
354 | + */ |
|
355 | + public function saveNotices() |
|
356 | + { |
|
357 | + $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
|
358 | + if ($this->notice_collection->hasObjects()) { |
|
359 | + $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array()); |
|
360 | + // maybe initialize persistent_admin_notices |
|
361 | + if (empty($persistent_admin_notices)) { |
|
362 | + add_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array(), '', 'no'); |
|
363 | + } |
|
364 | + foreach ($this->notice_collection as $persistent_admin_notice) { |
|
365 | + // are we deleting this notice ? |
|
366 | + if ($persistent_admin_notice->getPurge()) { |
|
367 | + unset($persistent_admin_notices[ $persistent_admin_notice->getName() ]); |
|
368 | + } else { |
|
369 | + /** @var PersistentAdminNotice $persistent_admin_notice */ |
|
370 | + $persistent_admin_notices[ $persistent_admin_notice->getName() ] = array( |
|
371 | + 'message' => $persistent_admin_notice->getMessage(), |
|
372 | + 'capability' => $persistent_admin_notice->getCapability(), |
|
373 | + 'cap_context' => $persistent_admin_notice->getCapContext(), |
|
374 | + 'dismissed' => $persistent_admin_notice->getDismissed(), |
|
375 | + ); |
|
376 | + } |
|
377 | + } |
|
378 | + update_option(PersistentAdminNoticeManager::WP_OPTION_KEY, $persistent_admin_notices); |
|
379 | + } |
|
380 | + } |
|
381 | + |
|
382 | + |
|
383 | + /** |
|
384 | + * @throws DomainException |
|
385 | + * @throws InvalidDataTypeException |
|
386 | + * @throws InvalidEntityException |
|
387 | + * @throws InvalidInterfaceException |
|
388 | + * @throws DuplicateCollectionIdentifierException |
|
389 | + */ |
|
390 | + public function registerAndSaveNotices() |
|
391 | + { |
|
392 | + $this->getPersistentAdminNoticeCollection(); |
|
393 | + $this->registerNotices(); |
|
394 | + $this->saveNotices(); |
|
395 | + add_filter( |
|
396 | + 'PersistentAdminNoticeManager__registerAndSaveNotices__complete', |
|
397 | + '__return_true' |
|
398 | + ); |
|
399 | + } |
|
400 | + |
|
401 | + |
|
402 | + /** |
|
403 | + * @throws DomainException |
|
404 | + * @throws InvalidDataTypeException |
|
405 | + * @throws InvalidEntityException |
|
406 | + * @throws InvalidInterfaceException |
|
407 | + * @throws InvalidArgumentException |
|
408 | + * @throws DuplicateCollectionIdentifierException |
|
409 | + */ |
|
410 | + public static function loadRegisterAndSaveNotices() |
|
411 | + { |
|
412 | + /** @var PersistentAdminNoticeManager $persistent_admin_notice_manager */ |
|
413 | + $persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared( |
|
414 | + 'EventEspresso\core\services\notifications\PersistentAdminNoticeManager' |
|
415 | + ); |
|
416 | + // if shutdown has already run, then call registerAndSaveNotices() manually |
|
417 | + if (did_action('shutdown')) { |
|
418 | + $persistent_admin_notice_manager->registerAndSaveNotices(); |
|
419 | + } |
|
420 | + } |
|
421 | 421 | } |
@@ -12,106 +12,106 @@ |
||
12 | 12 | */ |
13 | 13 | class EE_Load_Textdomain extends EE_Base |
14 | 14 | { |
15 | - private const REPO_BASE_URL = 'https://raw.githubusercontent.com/eventespresso/languages-ee4/master/event_espresso'; |
|
15 | + private const REPO_BASE_URL = 'https://raw.githubusercontent.com/eventespresso/languages-ee4/master/event_espresso'; |
|
16 | 16 | |
17 | 17 | |
18 | - /** |
|
19 | - * holds the current lang in WP |
|
20 | - * |
|
21 | - * @var string |
|
22 | - */ |
|
23 | - private static $locale; |
|
18 | + /** |
|
19 | + * holds the current lang in WP |
|
20 | + * |
|
21 | + * @var string |
|
22 | + */ |
|
23 | + private static $locale; |
|
24 | 24 | |
25 | 25 | |
26 | - /** |
|
27 | - * this takes care of retrieving a matching textdomain for event espresso for the current WPLANG from EE GitHub |
|
28 | - * repo (if necessary) and then loading it for translations. should only be called in wp plugins_loaded callback |
|
29 | - * |
|
30 | - * @return void |
|
31 | - * @throws EE_Error |
|
32 | - * @throws InvalidArgumentException |
|
33 | - * @throws ReflectionException |
|
34 | - * @throws InvalidDataTypeException |
|
35 | - * @throws InvalidInterfaceException |
|
36 | - */ |
|
37 | - public static function load_textdomain() |
|
38 | - { |
|
39 | - EE_Load_Textdomain::loadTranslationsForLocale(); |
|
40 | - // now load the textdomain |
|
41 | - if (!empty(EE_Load_Textdomain::$locale)) { |
|
42 | - $github_mo_path = EE_LANGUAGES_SAFE_DIR . 'event_espresso-' . EE_Load_Textdomain::$locale . '.mo'; |
|
43 | - if (is_readable($github_mo_path)) { |
|
44 | - load_plugin_textdomain('event_espresso', false, EE_LANGUAGES_SAFE_LOC); |
|
45 | - return; |
|
46 | - } |
|
47 | - $glotpress_mo_path = EE_LANGUAGES_SAFE_DIR . 'event-espresso-4-' . EE_Load_Textdomain::$locale . '.mo'; |
|
48 | - if (is_readable($glotpress_mo_path)) { |
|
49 | - load_textdomain('event_espresso', $glotpress_mo_path); |
|
50 | - return; |
|
51 | - } |
|
52 | - } |
|
53 | - load_plugin_textdomain('event_espresso', false, dirname(EE_PLUGIN_BASENAME) . '/languages/'); |
|
54 | - } |
|
26 | + /** |
|
27 | + * this takes care of retrieving a matching textdomain for event espresso for the current WPLANG from EE GitHub |
|
28 | + * repo (if necessary) and then loading it for translations. should only be called in wp plugins_loaded callback |
|
29 | + * |
|
30 | + * @return void |
|
31 | + * @throws EE_Error |
|
32 | + * @throws InvalidArgumentException |
|
33 | + * @throws ReflectionException |
|
34 | + * @throws InvalidDataTypeException |
|
35 | + * @throws InvalidInterfaceException |
|
36 | + */ |
|
37 | + public static function load_textdomain() |
|
38 | + { |
|
39 | + EE_Load_Textdomain::loadTranslationsForLocale(); |
|
40 | + // now load the textdomain |
|
41 | + if (!empty(EE_Load_Textdomain::$locale)) { |
|
42 | + $github_mo_path = EE_LANGUAGES_SAFE_DIR . 'event_espresso-' . EE_Load_Textdomain::$locale . '.mo'; |
|
43 | + if (is_readable($github_mo_path)) { |
|
44 | + load_plugin_textdomain('event_espresso', false, EE_LANGUAGES_SAFE_LOC); |
|
45 | + return; |
|
46 | + } |
|
47 | + $glotpress_mo_path = EE_LANGUAGES_SAFE_DIR . 'event-espresso-4-' . EE_Load_Textdomain::$locale . '.mo'; |
|
48 | + if (is_readable($glotpress_mo_path)) { |
|
49 | + load_textdomain('event_espresso', $glotpress_mo_path); |
|
50 | + return; |
|
51 | + } |
|
52 | + } |
|
53 | + load_plugin_textdomain('event_espresso', false, dirname(EE_PLUGIN_BASENAME) . '/languages/'); |
|
54 | + } |
|
55 | 55 | |
56 | 56 | |
57 | - /** |
|
58 | - * The purpose of this method is to sideload all of the lang files for EE, this includes the POT file and also the PO/MO files for the given WPLANG locale (if necessary). |
|
59 | - * |
|
60 | - * @access private |
|
61 | - * @static |
|
62 | - * @return void |
|
63 | - * @throws EE_Error |
|
64 | - * @throws InvalidArgumentException |
|
65 | - * @throws ReflectionException |
|
66 | - * @throws InvalidDataTypeException |
|
67 | - * @throws InvalidInterfaceException |
|
68 | - */ |
|
69 | - private static function loadTranslationsForLocale() |
|
70 | - { |
|
71 | - EE_Load_Textdomain::$locale = get_locale(); |
|
72 | - // can't download a language file if a language isn't set <taps temple> |
|
73 | - if (empty(EE_Load_Textdomain::$locale)) { |
|
74 | - return; |
|
75 | - } |
|
76 | - $language_check_option_name = 'ee_lang_check_' . EE_Load_Textdomain::$locale . '_' . EVENT_ESPRESSO_VERSION; |
|
77 | - // check if language files has already been sideloaded |
|
78 | - if (get_option($language_check_option_name)) { |
|
79 | - return; |
|
80 | - } |
|
57 | + /** |
|
58 | + * The purpose of this method is to sideload all of the lang files for EE, this includes the POT file and also the PO/MO files for the given WPLANG locale (if necessary). |
|
59 | + * |
|
60 | + * @access private |
|
61 | + * @static |
|
62 | + * @return void |
|
63 | + * @throws EE_Error |
|
64 | + * @throws InvalidArgumentException |
|
65 | + * @throws ReflectionException |
|
66 | + * @throws InvalidDataTypeException |
|
67 | + * @throws InvalidInterfaceException |
|
68 | + */ |
|
69 | + private static function loadTranslationsForLocale() |
|
70 | + { |
|
71 | + EE_Load_Textdomain::$locale = get_locale(); |
|
72 | + // can't download a language file if a language isn't set <taps temple> |
|
73 | + if (empty(EE_Load_Textdomain::$locale)) { |
|
74 | + return; |
|
75 | + } |
|
76 | + $language_check_option_name = 'ee_lang_check_' . EE_Load_Textdomain::$locale . '_' . EVENT_ESPRESSO_VERSION; |
|
77 | + // check if language files has already been sideloaded |
|
78 | + if (get_option($language_check_option_name)) { |
|
79 | + return; |
|
80 | + } |
|
81 | 81 | |
82 | - // load sideloader and sideload the .POT file as this should always be included. |
|
83 | - $sideloader_args = array( |
|
84 | - '_upload_to' => EE_PLUGIN_DIR_PATH . 'languages/', |
|
85 | - '_download_from' => EE_Load_Textdomain::REPO_BASE_URL . '.pot', |
|
86 | - '_new_file_name' => 'event_espresso.pot', |
|
87 | - ); |
|
88 | - /** @var EEH_Sideloader $sideloader */ |
|
89 | - $sideloader = EE_Registry::instance()->load_helper('Sideloader', $sideloader_args, false); |
|
90 | - // sideload the .POT file only for main site of the network, or if not running Multisite. |
|
91 | - if (is_main_site()) { |
|
92 | - $sideloader->sideload(); |
|
93 | - } |
|
82 | + // load sideloader and sideload the .POT file as this should always be included. |
|
83 | + $sideloader_args = array( |
|
84 | + '_upload_to' => EE_PLUGIN_DIR_PATH . 'languages/', |
|
85 | + '_download_from' => EE_Load_Textdomain::REPO_BASE_URL . '.pot', |
|
86 | + '_new_file_name' => 'event_espresso.pot', |
|
87 | + ); |
|
88 | + /** @var EEH_Sideloader $sideloader */ |
|
89 | + $sideloader = EE_Registry::instance()->load_helper('Sideloader', $sideloader_args, false); |
|
90 | + // sideload the .POT file only for main site of the network, or if not running Multisite. |
|
91 | + if (is_main_site()) { |
|
92 | + $sideloader->sideload(); |
|
93 | + } |
|
94 | 94 | |
95 | - // if locale is "en_US" then lets just get out, since Event Espresso core is already "en_US" |
|
96 | - if (EE_Load_Textdomain::$locale === 'en_US') { |
|
97 | - // but set option first else we'll forever be downloading the pot file |
|
98 | - update_option($language_check_option_name, 1); |
|
99 | - return; |
|
100 | - } |
|
101 | - $repo_locale_URL = EE_Load_Textdomain::REPO_BASE_URL . '-' . EE_Load_Textdomain::$locale; |
|
102 | - $file_name_base = 'event_espresso-' . EE_Load_Textdomain::$locale; |
|
95 | + // if locale is "en_US" then lets just get out, since Event Espresso core is already "en_US" |
|
96 | + if (EE_Load_Textdomain::$locale === 'en_US') { |
|
97 | + // but set option first else we'll forever be downloading the pot file |
|
98 | + update_option($language_check_option_name, 1); |
|
99 | + return; |
|
100 | + } |
|
101 | + $repo_locale_URL = EE_Load_Textdomain::REPO_BASE_URL . '-' . EE_Load_Textdomain::$locale; |
|
102 | + $file_name_base = 'event_espresso-' . EE_Load_Textdomain::$locale; |
|
103 | 103 | |
104 | - // made it here so let's get the language files from the github repo, first the .mo file |
|
105 | - $sideloader->set_download_from("{$repo_locale_URL}.mo"); |
|
106 | - $sideloader->set_new_file_name("{$file_name_base}.mo"); |
|
107 | - $sideloader->sideload(); |
|
104 | + // made it here so let's get the language files from the github repo, first the .mo file |
|
105 | + $sideloader->set_download_from("{$repo_locale_URL}.mo"); |
|
106 | + $sideloader->set_new_file_name("{$file_name_base}.mo"); |
|
107 | + $sideloader->sideload(); |
|
108 | 108 | |
109 | - // now the .po file: |
|
110 | - $sideloader->set_download_from("{$repo_locale_URL}.po"); |
|
111 | - $sideloader->set_new_file_name("{$file_name_base}.po"); |
|
112 | - $sideloader->sideload(); |
|
109 | + // now the .po file: |
|
110 | + $sideloader->set_download_from("{$repo_locale_URL}.po"); |
|
111 | + $sideloader->set_new_file_name("{$file_name_base}.po"); |
|
112 | + $sideloader->sideload(); |
|
113 | 113 | |
114 | - // set option so the above only runs when EE updates. |
|
115 | - update_option($language_check_option_name, 1); |
|
116 | - } |
|
114 | + // set option so the above only runs when EE updates. |
|
115 | + update_option($language_check_option_name, 1); |
|
116 | + } |
|
117 | 117 | } |
@@ -38,19 +38,19 @@ discard block |
||
38 | 38 | { |
39 | 39 | EE_Load_Textdomain::loadTranslationsForLocale(); |
40 | 40 | // now load the textdomain |
41 | - if (!empty(EE_Load_Textdomain::$locale)) { |
|
42 | - $github_mo_path = EE_LANGUAGES_SAFE_DIR . 'event_espresso-' . EE_Load_Textdomain::$locale . '.mo'; |
|
41 | + if ( ! empty(EE_Load_Textdomain::$locale)) { |
|
42 | + $github_mo_path = EE_LANGUAGES_SAFE_DIR.'event_espresso-'.EE_Load_Textdomain::$locale.'.mo'; |
|
43 | 43 | if (is_readable($github_mo_path)) { |
44 | 44 | load_plugin_textdomain('event_espresso', false, EE_LANGUAGES_SAFE_LOC); |
45 | 45 | return; |
46 | 46 | } |
47 | - $glotpress_mo_path = EE_LANGUAGES_SAFE_DIR . 'event-espresso-4-' . EE_Load_Textdomain::$locale . '.mo'; |
|
47 | + $glotpress_mo_path = EE_LANGUAGES_SAFE_DIR.'event-espresso-4-'.EE_Load_Textdomain::$locale.'.mo'; |
|
48 | 48 | if (is_readable($glotpress_mo_path)) { |
49 | 49 | load_textdomain('event_espresso', $glotpress_mo_path); |
50 | 50 | return; |
51 | 51 | } |
52 | 52 | } |
53 | - load_plugin_textdomain('event_espresso', false, dirname(EE_PLUGIN_BASENAME) . '/languages/'); |
|
53 | + load_plugin_textdomain('event_espresso', false, dirname(EE_PLUGIN_BASENAME).'/languages/'); |
|
54 | 54 | } |
55 | 55 | |
56 | 56 | |
@@ -73,7 +73,7 @@ discard block |
||
73 | 73 | if (empty(EE_Load_Textdomain::$locale)) { |
74 | 74 | return; |
75 | 75 | } |
76 | - $language_check_option_name = 'ee_lang_check_' . EE_Load_Textdomain::$locale . '_' . EVENT_ESPRESSO_VERSION; |
|
76 | + $language_check_option_name = 'ee_lang_check_'.EE_Load_Textdomain::$locale.'_'.EVENT_ESPRESSO_VERSION; |
|
77 | 77 | // check if language files has already been sideloaded |
78 | 78 | if (get_option($language_check_option_name)) { |
79 | 79 | return; |
@@ -81,8 +81,8 @@ discard block |
||
81 | 81 | |
82 | 82 | // load sideloader and sideload the .POT file as this should always be included. |
83 | 83 | $sideloader_args = array( |
84 | - '_upload_to' => EE_PLUGIN_DIR_PATH . 'languages/', |
|
85 | - '_download_from' => EE_Load_Textdomain::REPO_BASE_URL . '.pot', |
|
84 | + '_upload_to' => EE_PLUGIN_DIR_PATH.'languages/', |
|
85 | + '_download_from' => EE_Load_Textdomain::REPO_BASE_URL.'.pot', |
|
86 | 86 | '_new_file_name' => 'event_espresso.pot', |
87 | 87 | ); |
88 | 88 | /** @var EEH_Sideloader $sideloader */ |
@@ -98,8 +98,8 @@ discard block |
||
98 | 98 | update_option($language_check_option_name, 1); |
99 | 99 | return; |
100 | 100 | } |
101 | - $repo_locale_URL = EE_Load_Textdomain::REPO_BASE_URL . '-' . EE_Load_Textdomain::$locale; |
|
102 | - $file_name_base = 'event_espresso-' . EE_Load_Textdomain::$locale; |
|
101 | + $repo_locale_URL = EE_Load_Textdomain::REPO_BASE_URL.'-'.EE_Load_Textdomain::$locale; |
|
102 | + $file_name_base = 'event_espresso-'.EE_Load_Textdomain::$locale; |
|
103 | 103 | |
104 | 104 | // made it here so let's get the language files from the github repo, first the .mo file |
105 | 105 | $sideloader->set_download_from("{$repo_locale_URL}.mo"); |
@@ -15,181 +15,181 @@ |
||
15 | 15 | */ |
16 | 16 | class RegisterCustomTaxonomyTerms |
17 | 17 | { |
18 | - /** |
|
19 | - * @var array[] $custom_taxonomy_terms |
|
20 | - */ |
|
21 | - public $custom_taxonomy_terms = array(); |
|
18 | + /** |
|
19 | + * @var array[] $custom_taxonomy_terms |
|
20 | + */ |
|
21 | + public $custom_taxonomy_terms = array(); |
|
22 | 22 | |
23 | 23 | |
24 | - /** |
|
25 | - * RegisterCustomTaxonomyTerms constructor. |
|
26 | - */ |
|
27 | - public function __construct() |
|
28 | - { |
|
29 | - // hook into save_post so that we can make sure that the default terms get saved on publish of registered cpts |
|
30 | - // IF they don't have a term for that taxonomy set. |
|
31 | - add_action('save_post', array($this, 'saveDefaultTerm'), 100, 2); |
|
32 | - do_action( |
|
33 | - 'AHEE__EventEspresso_core_domain_services_custom_post_types_RegisterCustomTaxonomyTerms__construct_end', |
|
34 | - $this |
|
35 | - ); |
|
36 | - } |
|
24 | + /** |
|
25 | + * RegisterCustomTaxonomyTerms constructor. |
|
26 | + */ |
|
27 | + public function __construct() |
|
28 | + { |
|
29 | + // hook into save_post so that we can make sure that the default terms get saved on publish of registered cpts |
|
30 | + // IF they don't have a term for that taxonomy set. |
|
31 | + add_action('save_post', array($this, 'saveDefaultTerm'), 100, 2); |
|
32 | + do_action( |
|
33 | + 'AHEE__EventEspresso_core_domain_services_custom_post_types_RegisterCustomTaxonomyTerms__construct_end', |
|
34 | + $this |
|
35 | + ); |
|
36 | + } |
|
37 | 37 | |
38 | 38 | |
39 | - public function registerCustomTaxonomyTerms() |
|
40 | - { |
|
41 | - // setup default terms in any of our taxonomies (but only if we're in admin). |
|
42 | - // Why not added via register_activation_hook? |
|
43 | - // Because it's possible that in future iterations of EE we may add new defaults for specialized taxonomies |
|
44 | - // (think event_types) and register_activation_hook only reliably runs when a user manually activates the plugin. |
|
45 | - // Keep in mind that this will READ these terms if they are deleted by the user. Hence MUST use terms. |
|
46 | - // if ( is_admin() ) { |
|
47 | - // $this->set_must_use_event_types(); |
|
48 | - // } |
|
49 | - // set default terms |
|
50 | - $this->registerCustomTaxonomyTerm( |
|
51 | - 'espresso_event_type', |
|
52 | - 'single-event', |
|
53 | - array('espresso_events') |
|
54 | - ); |
|
55 | - } |
|
39 | + public function registerCustomTaxonomyTerms() |
|
40 | + { |
|
41 | + // setup default terms in any of our taxonomies (but only if we're in admin). |
|
42 | + // Why not added via register_activation_hook? |
|
43 | + // Because it's possible that in future iterations of EE we may add new defaults for specialized taxonomies |
|
44 | + // (think event_types) and register_activation_hook only reliably runs when a user manually activates the plugin. |
|
45 | + // Keep in mind that this will READ these terms if they are deleted by the user. Hence MUST use terms. |
|
46 | + // if ( is_admin() ) { |
|
47 | + // $this->set_must_use_event_types(); |
|
48 | + // } |
|
49 | + // set default terms |
|
50 | + $this->registerCustomTaxonomyTerm( |
|
51 | + 'espresso_event_type', |
|
52 | + 'single-event', |
|
53 | + array('espresso_events') |
|
54 | + ); |
|
55 | + } |
|
56 | 56 | |
57 | 57 | |
58 | - /** |
|
59 | - * Allows us to set what the default will be for terms when a cpt is PUBLISHED. |
|
60 | - * |
|
61 | - * @param string $taxonomy The taxonomy we're using for the default term |
|
62 | - * @param string $term_slug The slug of the term that will be the default. |
|
63 | - * @param array $cpt_slugs An array of custom post types we want the default assigned to |
|
64 | - */ |
|
65 | - public function registerCustomTaxonomyTerm($taxonomy, $term_slug, array $cpt_slugs = array()) |
|
66 | - { |
|
67 | - $this->custom_taxonomy_terms[][ $term_slug ] = new CustomTaxonomyTerm( |
|
68 | - $taxonomy, |
|
69 | - $term_slug, |
|
70 | - $cpt_slugs |
|
71 | - ); |
|
72 | - } |
|
58 | + /** |
|
59 | + * Allows us to set what the default will be for terms when a cpt is PUBLISHED. |
|
60 | + * |
|
61 | + * @param string $taxonomy The taxonomy we're using for the default term |
|
62 | + * @param string $term_slug The slug of the term that will be the default. |
|
63 | + * @param array $cpt_slugs An array of custom post types we want the default assigned to |
|
64 | + */ |
|
65 | + public function registerCustomTaxonomyTerm($taxonomy, $term_slug, array $cpt_slugs = array()) |
|
66 | + { |
|
67 | + $this->custom_taxonomy_terms[][ $term_slug ] = new CustomTaxonomyTerm( |
|
68 | + $taxonomy, |
|
69 | + $term_slug, |
|
70 | + $cpt_slugs |
|
71 | + ); |
|
72 | + } |
|
73 | 73 | |
74 | 74 | |
75 | - /** |
|
76 | - * hooked into the wp 'save_post' action hook for setting our default terms found in the $_default_terms property |
|
77 | - * |
|
78 | - * @param int $post_id ID of CPT being saved |
|
79 | - * @param WP_Post|null $post Post object |
|
80 | - * @return void |
|
81 | - */ |
|
82 | - public function saveDefaultTerm(int $post_id, ?WP_Post $post) |
|
83 | - { |
|
84 | - if (! $post || empty($this->custom_taxonomy_terms)) { |
|
85 | - return; |
|
86 | - } |
|
87 | - // no default terms set so lets just exit. |
|
88 | - foreach ($this->custom_taxonomy_terms as $custom_taxonomy_terms) { |
|
89 | - foreach ($custom_taxonomy_terms as $custom_taxonomy_term) { |
|
90 | - if ( |
|
91 | - $post->post_status === 'publish' |
|
92 | - && $custom_taxonomy_term instanceof CustomTaxonomyTerm |
|
93 | - && in_array($post->post_type, $custom_taxonomy_term->customPostTypeSlugs(), true) |
|
94 | - ) { |
|
95 | - // note some error proofing going on here to save unnecessary db queries |
|
96 | - $taxonomies = get_object_taxonomies($post->post_type); |
|
97 | - foreach ($taxonomies as $taxonomy) { |
|
98 | - $terms = wp_get_post_terms($post_id, $taxonomy); |
|
99 | - if (empty($terms) && $taxonomy === $custom_taxonomy_term->taxonomySlug()) { |
|
100 | - wp_set_object_terms( |
|
101 | - $post_id, |
|
102 | - array($custom_taxonomy_term->termSlug()), |
|
103 | - $taxonomy |
|
104 | - ); |
|
105 | - } |
|
106 | - } |
|
107 | - } |
|
108 | - } |
|
109 | - } |
|
110 | - } |
|
75 | + /** |
|
76 | + * hooked into the wp 'save_post' action hook for setting our default terms found in the $_default_terms property |
|
77 | + * |
|
78 | + * @param int $post_id ID of CPT being saved |
|
79 | + * @param WP_Post|null $post Post object |
|
80 | + * @return void |
|
81 | + */ |
|
82 | + public function saveDefaultTerm(int $post_id, ?WP_Post $post) |
|
83 | + { |
|
84 | + if (! $post || empty($this->custom_taxonomy_terms)) { |
|
85 | + return; |
|
86 | + } |
|
87 | + // no default terms set so lets just exit. |
|
88 | + foreach ($this->custom_taxonomy_terms as $custom_taxonomy_terms) { |
|
89 | + foreach ($custom_taxonomy_terms as $custom_taxonomy_term) { |
|
90 | + if ( |
|
91 | + $post->post_status === 'publish' |
|
92 | + && $custom_taxonomy_term instanceof CustomTaxonomyTerm |
|
93 | + && in_array($post->post_type, $custom_taxonomy_term->customPostTypeSlugs(), true) |
|
94 | + ) { |
|
95 | + // note some error proofing going on here to save unnecessary db queries |
|
96 | + $taxonomies = get_object_taxonomies($post->post_type); |
|
97 | + foreach ($taxonomies as $taxonomy) { |
|
98 | + $terms = wp_get_post_terms($post_id, $taxonomy); |
|
99 | + if (empty($terms) && $taxonomy === $custom_taxonomy_term->taxonomySlug()) { |
|
100 | + wp_set_object_terms( |
|
101 | + $post_id, |
|
102 | + array($custom_taxonomy_term->termSlug()), |
|
103 | + $taxonomy |
|
104 | + ); |
|
105 | + } |
|
106 | + } |
|
107 | + } |
|
108 | + } |
|
109 | + } |
|
110 | + } |
|
111 | 111 | |
112 | 112 | |
113 | - /** |
|
114 | - * @return void |
|
115 | - */ |
|
116 | - public function setMustUseEventTypes() |
|
117 | - { |
|
118 | - $term_details = array( |
|
119 | - // Attendee's register for the first date-time only |
|
120 | - 'single-event' => array( |
|
121 | - 'term' => esc_html__('Single Event', 'event_espresso'), |
|
122 | - 'desc' => esc_html__( |
|
123 | - 'A single event that spans one or more consecutive days.', |
|
124 | - 'event_espresso' |
|
125 | - ), |
|
126 | - ), |
|
127 | - // example: a party or two-day long workshop |
|
128 | - // Attendee's can register for any of the date-times |
|
129 | - 'multi-event' => array( |
|
130 | - 'term' => esc_html__('Multi Event', 'event_espresso'), |
|
131 | - 'desc' => esc_html__( |
|
132 | - 'Multiple, separate, but related events that occur on consecutive days.', |
|
133 | - 'event_espresso' |
|
134 | - ), |
|
135 | - ), |
|
136 | - // example: a three day music festival or week long conference |
|
137 | - // Attendee's register for the first date-time only |
|
138 | - 'event-series' => array( |
|
139 | - 'term' => esc_html__('Event Series', 'event_espresso'), |
|
140 | - 'desc' => esc_html__( |
|
141 | - ' Multiple events that occur over multiple non-consecutive days.', |
|
142 | - 'event_espresso' |
|
143 | - ), |
|
144 | - ), |
|
145 | - // example: an 8 week introduction to basket weaving course |
|
146 | - // Attendee's can register for any of the date-times. |
|
147 | - 'recurring-event' => array( |
|
148 | - 'term' => esc_html__('Recurring Event', 'event_espresso'), |
|
149 | - 'desc' => esc_html__( |
|
150 | - 'Multiple events that occur over multiple non-consecutive days.', |
|
151 | - 'event_espresso' |
|
152 | - ), |
|
153 | - ), |
|
154 | - // example: a yoga class |
|
155 | - 'ongoing' => array( |
|
156 | - 'term' => esc_html__('Ongoing Event', 'event_espresso'), |
|
157 | - 'desc' => esc_html__( |
|
158 | - 'An "event" that people can purchase tickets to gain access for anytime for this event regardless of date times on the event', |
|
159 | - 'event_espresso' |
|
160 | - ), |
|
161 | - ) |
|
162 | - // example: access to a museum |
|
163 | - // 'walk-in' => array( esc_html__('Walk In', 'event_espresso'), esc_html__('Single datetime and single entry recurring events. Attendees register for one or multiple datetimes individually.', 'event_espresso') ), |
|
164 | - // 'reservation' => array( esc_html__('Reservation', 'event_espresso'), esc_html__('Reservations are created by specifying available datetimes and quantities. Attendees choose from the available datetimes and specify the quantity available (if the maximum is greater than 1)') ), //@TODO to avoid confusion we'll implement this in a later iteration > EE4.1 |
|
165 | - // 'multiple-session' => array( esc_html__('Multiple Session', 'event_espresso'), esc_html__('Multiple event, multiple datetime, hierarchically organized, custom entry events. Attendees may be required to register for a parent event before being allowed to register for child events. Attendees can register for any combination of child events as long as the datetimes do not conflict. Parent and child events may have additional fees or registration questions.') ), //@TODO to avoid confusion we'll implement this in a later iteration > EE4.1 |
|
166 | - // 'appointment' => array( esc_html__('Appointments', 'event_espresso'), esc_html__('Time slotted events where datetimes are generally in hours or minutes. For example, attendees can register for a single 15 minute or 1 hour time slot and this type of availability frequently reoccurs.', 'event_espresso') ) |
|
167 | - ); |
|
168 | - $this->setMustUseTerms('espresso_event_type', $term_details); |
|
169 | - } |
|
113 | + /** |
|
114 | + * @return void |
|
115 | + */ |
|
116 | + public function setMustUseEventTypes() |
|
117 | + { |
|
118 | + $term_details = array( |
|
119 | + // Attendee's register for the first date-time only |
|
120 | + 'single-event' => array( |
|
121 | + 'term' => esc_html__('Single Event', 'event_espresso'), |
|
122 | + 'desc' => esc_html__( |
|
123 | + 'A single event that spans one or more consecutive days.', |
|
124 | + 'event_espresso' |
|
125 | + ), |
|
126 | + ), |
|
127 | + // example: a party or two-day long workshop |
|
128 | + // Attendee's can register for any of the date-times |
|
129 | + 'multi-event' => array( |
|
130 | + 'term' => esc_html__('Multi Event', 'event_espresso'), |
|
131 | + 'desc' => esc_html__( |
|
132 | + 'Multiple, separate, but related events that occur on consecutive days.', |
|
133 | + 'event_espresso' |
|
134 | + ), |
|
135 | + ), |
|
136 | + // example: a three day music festival or week long conference |
|
137 | + // Attendee's register for the first date-time only |
|
138 | + 'event-series' => array( |
|
139 | + 'term' => esc_html__('Event Series', 'event_espresso'), |
|
140 | + 'desc' => esc_html__( |
|
141 | + ' Multiple events that occur over multiple non-consecutive days.', |
|
142 | + 'event_espresso' |
|
143 | + ), |
|
144 | + ), |
|
145 | + // example: an 8 week introduction to basket weaving course |
|
146 | + // Attendee's can register for any of the date-times. |
|
147 | + 'recurring-event' => array( |
|
148 | + 'term' => esc_html__('Recurring Event', 'event_espresso'), |
|
149 | + 'desc' => esc_html__( |
|
150 | + 'Multiple events that occur over multiple non-consecutive days.', |
|
151 | + 'event_espresso' |
|
152 | + ), |
|
153 | + ), |
|
154 | + // example: a yoga class |
|
155 | + 'ongoing' => array( |
|
156 | + 'term' => esc_html__('Ongoing Event', 'event_espresso'), |
|
157 | + 'desc' => esc_html__( |
|
158 | + 'An "event" that people can purchase tickets to gain access for anytime for this event regardless of date times on the event', |
|
159 | + 'event_espresso' |
|
160 | + ), |
|
161 | + ) |
|
162 | + // example: access to a museum |
|
163 | + // 'walk-in' => array( esc_html__('Walk In', 'event_espresso'), esc_html__('Single datetime and single entry recurring events. Attendees register for one or multiple datetimes individually.', 'event_espresso') ), |
|
164 | + // 'reservation' => array( esc_html__('Reservation', 'event_espresso'), esc_html__('Reservations are created by specifying available datetimes and quantities. Attendees choose from the available datetimes and specify the quantity available (if the maximum is greater than 1)') ), //@TODO to avoid confusion we'll implement this in a later iteration > EE4.1 |
|
165 | + // 'multiple-session' => array( esc_html__('Multiple Session', 'event_espresso'), esc_html__('Multiple event, multiple datetime, hierarchically organized, custom entry events. Attendees may be required to register for a parent event before being allowed to register for child events. Attendees can register for any combination of child events as long as the datetimes do not conflict. Parent and child events may have additional fees or registration questions.') ), //@TODO to avoid confusion we'll implement this in a later iteration > EE4.1 |
|
166 | + // 'appointment' => array( esc_html__('Appointments', 'event_espresso'), esc_html__('Time slotted events where datetimes are generally in hours or minutes. For example, attendees can register for a single 15 minute or 1 hour time slot and this type of availability frequently reoccurs.', 'event_espresso') ) |
|
167 | + ); |
|
168 | + $this->setMustUseTerms('espresso_event_type', $term_details); |
|
169 | + } |
|
170 | 170 | |
171 | 171 | |
172 | - /** |
|
173 | - * wrapper method for handling the setting up of initial terms in the db (if they don't already exist). |
|
174 | - * Note this should ONLY be used for terms that always must be present. Be aware that if an initial term is |
|
175 | - * deleted then it WILL be recreated. |
|
176 | - * |
|
177 | - * @param string $taxonomy The name of the taxonomy |
|
178 | - * @param array $term_details An array of term details indexed by slug and containing Name of term, and |
|
179 | - * description as the elements in the array |
|
180 | - * @return void |
|
181 | - */ |
|
182 | - public function setMustUseTerms($taxonomy, $term_details) |
|
183 | - { |
|
184 | - $term_details = (array) $term_details; |
|
185 | - foreach ($term_details as $slug => $details) { |
|
186 | - if (isset($details['term'], $details['desc']) && ! term_exists($slug, $taxonomy)) { |
|
187 | - $insert_arr = array( |
|
188 | - 'slug' => $slug, |
|
189 | - 'description' => $details['desc'], |
|
190 | - ); |
|
191 | - wp_insert_term($details['term'], $taxonomy, $insert_arr); |
|
192 | - } |
|
193 | - } |
|
194 | - } |
|
172 | + /** |
|
173 | + * wrapper method for handling the setting up of initial terms in the db (if they don't already exist). |
|
174 | + * Note this should ONLY be used for terms that always must be present. Be aware that if an initial term is |
|
175 | + * deleted then it WILL be recreated. |
|
176 | + * |
|
177 | + * @param string $taxonomy The name of the taxonomy |
|
178 | + * @param array $term_details An array of term details indexed by slug and containing Name of term, and |
|
179 | + * description as the elements in the array |
|
180 | + * @return void |
|
181 | + */ |
|
182 | + public function setMustUseTerms($taxonomy, $term_details) |
|
183 | + { |
|
184 | + $term_details = (array) $term_details; |
|
185 | + foreach ($term_details as $slug => $details) { |
|
186 | + if (isset($details['term'], $details['desc']) && ! term_exists($slug, $taxonomy)) { |
|
187 | + $insert_arr = array( |
|
188 | + 'slug' => $slug, |
|
189 | + 'description' => $details['desc'], |
|
190 | + ); |
|
191 | + wp_insert_term($details['term'], $taxonomy, $insert_arr); |
|
192 | + } |
|
193 | + } |
|
194 | + } |
|
195 | 195 | } |
@@ -64,7 +64,7 @@ discard block |
||
64 | 64 | */ |
65 | 65 | public function registerCustomTaxonomyTerm($taxonomy, $term_slug, array $cpt_slugs = array()) |
66 | 66 | { |
67 | - $this->custom_taxonomy_terms[][ $term_slug ] = new CustomTaxonomyTerm( |
|
67 | + $this->custom_taxonomy_terms[][$term_slug] = new CustomTaxonomyTerm( |
|
68 | 68 | $taxonomy, |
69 | 69 | $term_slug, |
70 | 70 | $cpt_slugs |
@@ -81,7 +81,7 @@ discard block |
||
81 | 81 | */ |
82 | 82 | public function saveDefaultTerm(int $post_id, ?WP_Post $post) |
83 | 83 | { |
84 | - if (! $post || empty($this->custom_taxonomy_terms)) { |
|
84 | + if ( ! $post || empty($this->custom_taxonomy_terms)) { |
|
85 | 85 | return; |
86 | 86 | } |
87 | 87 | // no default terms set so lets just exit. |
@@ -15,407 +15,407 @@ |
||
15 | 15 | |
16 | 16 | class AdminMenuManager |
17 | 17 | { |
18 | - /** |
|
19 | - * Default: null - defaults to below Comments |
|
20 | - * |
|
21 | - * 5 - below Posts |
|
22 | - * 10 - below Media |
|
23 | - * 15 - below Links |
|
24 | - * 20 - below Pages |
|
25 | - * 25 - below comments |
|
26 | - * 60 - below first separator |
|
27 | - * 65 - below Plugins |
|
28 | - * 70 - below Users |
|
29 | - * 75 - below Tools |
|
30 | - * 80 - below Settings |
|
31 | - * 100 - below second separator |
|
32 | - */ |
|
33 | - const MENU_POSITION = 100; |
|
34 | - |
|
35 | - |
|
36 | - /** |
|
37 | - * @var AdminMenuItem[] |
|
38 | - */ |
|
39 | - private $menu_items = []; |
|
40 | - |
|
41 | - /** |
|
42 | - * objects for page_init objects detected and loaded |
|
43 | - * |
|
44 | - * @var EE_Admin_Page_Init[] |
|
45 | - */ |
|
46 | - private $installed_pages = []; |
|
47 | - |
|
48 | - /** |
|
49 | - * set to TRUE if site is currently in maintenance mode level 2 |
|
50 | - * |
|
51 | - * @var bool |
|
52 | - */ |
|
53 | - protected $maintenance_mode = false; |
|
54 | - |
|
55 | - /** |
|
56 | - * @var AdminMenuItem |
|
57 | - */ |
|
58 | - private $top_level_menu_item; |
|
59 | - |
|
60 | - |
|
61 | - public function __construct() |
|
62 | - { |
|
63 | - } |
|
64 | - |
|
65 | - |
|
66 | - public function initialize() |
|
67 | - { |
|
68 | - $this->maintenance_mode = EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance; |
|
69 | - $this->addTopLevelMenuItem(); |
|
70 | - $this->initializeMenuGroups(); |
|
71 | - add_action('admin_menu', [$this, 'generateAdminMenu']); |
|
72 | - add_action('network_admin_menu', [$this, 'generateNetworkAdminMenu']); |
|
73 | - add_filter('custom_menu_order', '__return_true'); |
|
74 | - add_filter('menu_order', [$this, 'reorderAdminMenu']); |
|
75 | - } |
|
76 | - |
|
77 | - |
|
78 | - /** |
|
79 | - * adds the top level menu item that everything else descends from. |
|
80 | - * changes depending on whether site is in full maintenance mode or not |
|
81 | - * |
|
82 | - * @return void |
|
83 | - */ |
|
84 | - private function addTopLevelMenuItem() |
|
85 | - { |
|
86 | - $this->top_level_menu_item = $this->maintenance_mode |
|
87 | - ? $this->instantiateAdminMenu( |
|
88 | - [ |
|
89 | - 'menu_slug' => 'espresso_maintenance_settings', |
|
90 | - 'menu_label' => esc_html__('Event Espresso', 'event_espresso'), |
|
91 | - 'capability' => 'manage_options', |
|
92 | - 'menu_group' => 'main', |
|
93 | - 'menu_order' => 10, |
|
94 | - 'menu_type' => AdminMenuItem::TYPE_MENU_TOP, |
|
95 | - 'parent_slug' => 'espresso_maintenance_settings', |
|
96 | - 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
97 | - ] |
|
98 | - ) |
|
99 | - : $this->instantiateAdminMenu( |
|
100 | - [ |
|
101 | - 'menu_slug' => 'espresso_events', |
|
102 | - 'menu_label' => esc_html__('Event Espresso', 'event_espresso'), |
|
103 | - 'capability' => 'ee_read_events', |
|
104 | - 'menu_group' => 'main', |
|
105 | - 'menu_order' => 10, |
|
106 | - 'menu_type' => AdminMenuItem::TYPE_MENU_TOP, |
|
107 | - 'parent_slug' => 'espresso_events', |
|
108 | - 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
109 | - ] |
|
110 | - ); |
|
111 | - } |
|
112 | - |
|
113 | - |
|
114 | - /** |
|
115 | - * sets the filterable _admin_menu_groups property (list of various "groupings" within the EE admin menu array) |
|
116 | - * |
|
117 | - * @return void |
|
118 | - */ |
|
119 | - private function initializeMenuGroups() |
|
120 | - { |
|
121 | - $this->menu_items = apply_filters( |
|
122 | - 'FHEE__EE_Admin_Page_Loader___set_menu_groups__admin_menu_groups', |
|
123 | - [ |
|
124 | - 'main' => $this->instantiateAdminMenu( |
|
125 | - [ |
|
126 | - 'menu_slug' => 'main', |
|
127 | - 'menu_label' => esc_html__('Main', 'event_espresso'), |
|
128 | - 'capability' => $this->maintenance_mode ? 'manage_options' : 'ee_read_ee', |
|
129 | - 'maintenance_mode_parent' => 'espresso_maintenance_settings', |
|
130 | - 'menu_order' => 0, |
|
131 | - 'parent_slug' => 'espresso_events', |
|
132 | - 'show_on_menu' => AdminMenuItem::DISPLAY_NONE, |
|
133 | - ] |
|
134 | - ), |
|
135 | - 'management' => $this->instantiateAdminMenu( |
|
136 | - [ |
|
137 | - 'menu_slug' => 'management', |
|
138 | - 'menu_label' => esc_html__('Management', 'event_espresso'), |
|
139 | - 'capability' => 'ee_read_ee', |
|
140 | - 'menu_order' => 10, |
|
141 | - 'parent_slug' => 'espresso_events', |
|
142 | - 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
143 | - ] |
|
144 | - ), |
|
145 | - 'addons' => $this->instantiateAdminMenu( |
|
146 | - [ |
|
147 | - 'menu_slug' => 'addons', |
|
148 | - 'menu_label' => esc_html__('Add-ons', 'event_espresso'), |
|
149 | - 'capability' => 'ee_read_ee', |
|
150 | - 'menu_order' => 20, |
|
151 | - 'parent_slug' => 'espresso_events', |
|
152 | - 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_AND_NETWORK, |
|
153 | - ] |
|
154 | - ), |
|
155 | - 'settings' => $this->instantiateAdminMenu( |
|
156 | - [ |
|
157 | - 'menu_slug' => 'settings', |
|
158 | - 'menu_label' => esc_html__('Settings', 'event_espresso'), |
|
159 | - 'capability' => 'ee_read_ee', |
|
160 | - 'menu_order' => 30, |
|
161 | - 'parent_slug' => 'espresso_events', |
|
162 | - 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
163 | - ] |
|
164 | - ), |
|
165 | - 'templates' => $this->instantiateAdminMenu( |
|
166 | - [ |
|
167 | - 'menu_slug' => 'templates', |
|
168 | - 'menu_label' => esc_html__('Templates', 'event_espresso'), |
|
169 | - 'capability' => 'ee_read_ee', |
|
170 | - 'menu_order' => 40, |
|
171 | - 'parent_slug' => 'espresso_events', |
|
172 | - 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
173 | - ] |
|
174 | - ), |
|
175 | - 'extras' => $this->instantiateAdminMenu( |
|
176 | - [ |
|
177 | - 'menu_slug' => 'extras', |
|
178 | - 'menu_label' => esc_html__('Extras', 'event_espresso'), |
|
179 | - 'capability' => 'ee_read_ee', |
|
180 | - 'maintenance_mode_parent' => 'espresso_maintenance_settings', |
|
181 | - 'menu_order' => 50, |
|
182 | - 'parent_slug' => 'espresso_events', |
|
183 | - 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_AND_NETWORK, |
|
184 | - ] |
|
185 | - ), |
|
186 | - 'tools' => $this->instantiateAdminMenu( |
|
187 | - [ |
|
188 | - 'menu_slug' => 'tools', |
|
189 | - 'menu_label' => esc_html__('Tools', 'event_espresso'), |
|
190 | - 'capability' => 'ee_read_ee', |
|
191 | - 'menu_order' => 60, |
|
192 | - 'parent_slug' => 'espresso_events', |
|
193 | - 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
194 | - ] |
|
195 | - ), |
|
196 | - ] |
|
197 | - ); |
|
198 | - } |
|
199 | - |
|
200 | - |
|
201 | - /** |
|
202 | - * instantiates and returns the appropriate AdminMenuItem for the provided EE_Admin_Page_Init |
|
203 | - * |
|
204 | - * @param EE_Admin_Page_Init $admin_page_init |
|
205 | - * @return AdminMenuItem |
|
206 | - */ |
|
207 | - public function getAdminMenu(EE_Admin_Page_Init $admin_page_init): AdminMenuItem |
|
208 | - { |
|
209 | - // see if admin page init is using new classes |
|
210 | - $menu_properties = $admin_page_init->getMenuProperties(); |
|
211 | - if (empty($menu_properties)) { |
|
212 | - // no? ok setup the admin menu item the old way |
|
213 | - $admin_page_init->setupLegacyAdminMenuItem(); |
|
214 | - } else { |
|
215 | - // adding the admin page init callback here means the menu doesn't have to cart that object around |
|
216 | - $menu_properties['menu_callback'] = [$admin_page_init, 'initialize_admin_page']; |
|
217 | - $admin_page_init->setAdminMenu($this->instantiateAdminMenu($menu_properties)); |
|
218 | - } |
|
219 | - $admin_menu = $admin_page_init->adminMenu(); |
|
220 | - if (! $admin_menu instanceof AdminMenuItem) { |
|
221 | - throw new DomainException(esc_html__('Invalid AdminMenuItem', 'event_espresso')); |
|
222 | - } |
|
223 | - if (! is_callable($admin_menu->menuCallback())) { |
|
224 | - $admin_menu->setMenuCallback([$admin_page_init, 'initialize_admin_page']); |
|
225 | - } |
|
226 | - // get the menu group that this menu item belongs to and then add it |
|
227 | - $admin_group = $this->getMenuGroup($admin_menu); |
|
228 | - $admin_group->addMenuItem($admin_menu); |
|
229 | - return $admin_menu; |
|
230 | - } |
|
231 | - |
|
232 | - |
|
233 | - /** |
|
234 | - * @param array $menu_properties |
|
235 | - * @return AdminMenuItem|null |
|
236 | - */ |
|
237 | - private function instantiateAdminMenu(array $menu_properties): ?AdminMenuItem |
|
238 | - { |
|
239 | - $type = $menu_properties['menu_type'] ?? AdminMenuItem::TYPE_MENU_GROUP; |
|
240 | - unset($menu_properties['menu_type']); |
|
241 | - switch ($type) { |
|
242 | - case AdminMenuItem::TYPE_MENU_GROUP: |
|
243 | - unset($menu_properties['menu_callback']); |
|
244 | - return new AdminMenuGroup($menu_properties); |
|
245 | - case AdminMenuItem::TYPE_MENU_TOP: |
|
246 | - return new AdminMenuTopLevel($menu_properties); |
|
247 | - case AdminMenuItem::TYPE_MENU_SUB_ITEM: |
|
248 | - return new AdminMenuSubItem($menu_properties); |
|
249 | - } |
|
250 | - return null; |
|
251 | - } |
|
252 | - |
|
253 | - |
|
254 | - /** |
|
255 | - * @param AdminMenuItem $admin_menu |
|
256 | - * @return AdminMenuGroup |
|
257 | - * @throws DomainException |
|
258 | - * @throws OutOfRangeException |
|
259 | - */ |
|
260 | - private function getMenuGroup(AdminMenuItem $admin_menu): AdminMenuGroup |
|
261 | - { |
|
262 | - if (! isset($this->menu_items[ $admin_menu->menuGroup() ])) { |
|
263 | - throw new OutOfRangeException(esc_html__('AdminMenuGroup does not exist', 'event_espresso')); |
|
264 | - } |
|
265 | - $admin_group = $this->menu_items[ $admin_menu->menuGroup() ]; |
|
266 | - if (! $admin_group instanceof AdminMenuGroup) { |
|
267 | - throw new DomainException(esc_html__('Invalid AdminMenuGroup found', 'event_espresso')); |
|
268 | - } |
|
269 | - return $admin_group; |
|
270 | - } |
|
271 | - |
|
272 | - |
|
273 | - /** |
|
274 | - * set_network_menus |
|
275 | - * This method sets up the menus for network EE Admin Pages. |
|
276 | - * Almost identical to EE_Admin_Page_Loader::set_menus() except pages |
|
277 | - * are only added to the menu map if they are intended for the admin menu |
|
278 | - * |
|
279 | - * @return void |
|
280 | - * @throws DomainException |
|
281 | - */ |
|
282 | - public function generateNetworkAdminMenu() |
|
283 | - { |
|
284 | - $this->generateAdminMenu(true); |
|
285 | - } |
|
286 | - |
|
287 | - |
|
288 | - /** |
|
289 | - * This method sets up the menus for EE Admin Pages |
|
290 | - * |
|
291 | - * @return void |
|
292 | - * @throws DomainException |
|
293 | - */ |
|
294 | - public function generateAdminMenu(bool $network_admin = false) |
|
295 | - { |
|
296 | - $admin_menu = $this->sortMenu($this->menu_items); |
|
297 | - $this->top_level_menu_item->registerAdminMenuItem($network_admin); |
|
298 | - $this->registerAdminMenu($admin_menu, $network_admin); |
|
299 | - } |
|
300 | - |
|
301 | - |
|
302 | - /** |
|
303 | - * @param array $admin_menu |
|
304 | - * @param bool $network_admin |
|
305 | - */ |
|
306 | - private function registerAdminMenu(array $admin_menu, bool $network_admin) |
|
307 | - { |
|
308 | - foreach ($admin_menu as $menu_item) { |
|
309 | - if ($this->skipMenuItem($menu_item)) { |
|
310 | - continue; |
|
311 | - } |
|
312 | - try { |
|
313 | - $wp_page_slug = $menu_item->registerAdminMenuItem($network_admin); |
|
314 | - $admin_init_page = $this->installed_pages[ $menu_item->menuSlug() ] ?? null; |
|
315 | - if ($wp_page_slug && $admin_init_page instanceof EE_Admin_Page_Init) { |
|
316 | - $admin_init_page->setWpPageSlug($wp_page_slug); |
|
317 | - $admin_init_page->set_page_dependencies($wp_page_slug); |
|
318 | - } |
|
319 | - if ($menu_item instanceof AdminMenuGroup) { |
|
320 | - $this->registerAdminMenu($menu_item->getMenuItems(), $network_admin); |
|
321 | - } |
|
322 | - } catch (Exception $e) { |
|
323 | - EE_Error::add_error($e->getMessage(), $e->getFile(), __FUNCTION__, $e->getLine()); |
|
324 | - } |
|
325 | - } |
|
326 | - } |
|
327 | - |
|
328 | - |
|
329 | - /** |
|
330 | - * returns TRUE if any of the following conditions is met: |
|
331 | - * - menu item is NOT an instanceof AdminMenuItem |
|
332 | - * - menu item has already been registered |
|
333 | - * - menu item should not be shown when site is in full maintenance mode |
|
334 | - * - current user does not have the required access permission |
|
335 | - * - menu item is a group but has no sub items |
|
336 | - * |
|
337 | - * @param AdminMenuItem|null $menu_item |
|
338 | - * @return bool |
|
339 | - */ |
|
340 | - private function skipMenuItem(?AdminMenuItem $menu_item): bool |
|
341 | - { |
|
342 | - return ! $menu_item instanceof AdminMenuItem |
|
343 | - || $menu_item->isRegistered() |
|
344 | - || ! $menu_item->showOnMaintenanceModeMenu() |
|
345 | - || ! $menu_item->currentUserHasAccess() |
|
346 | - || ( |
|
347 | - $menu_item instanceof AdminMenuGroup |
|
348 | - && $menu_item->hasNoMenuItems() |
|
349 | - ); |
|
350 | - } |
|
351 | - |
|
352 | - |
|
353 | - /** |
|
354 | - * @param EE_Admin_Page_Init[] $installed_pages |
|
355 | - */ |
|
356 | - public function setInstalledPages(array $installed_pages): void |
|
357 | - { |
|
358 | - $this->installed_pages = $installed_pages; |
|
359 | - } |
|
360 | - |
|
361 | - |
|
362 | - /** |
|
363 | - * Recursively sort menu groups and their sub items |
|
364 | - * |
|
365 | - * @return AdminMenuItem[] |
|
366 | - * @throws DomainException |
|
367 | - */ |
|
368 | - public function sortMenu(array $admin_menu): array |
|
369 | - { |
|
370 | - foreach ($admin_menu as $menu_group) { |
|
371 | - if (! $menu_group instanceof AdminMenuItem) { |
|
372 | - throw new DomainException(esc_html__('Invalid AdminMenuItem', 'event_espresso')); |
|
373 | - } |
|
374 | - if ($menu_group instanceof AdminMenuGroup) { |
|
375 | - // sort sub items |
|
376 | - $menu_items = $this->sortMenu($menu_group->getMenuItems()); |
|
377 | - $menu_group->setMenuItems($menu_items); |
|
378 | - } |
|
379 | - } |
|
380 | - // sort incoming array AFTER it's been looped through and elements have been validated |
|
381 | - usort($admin_menu, [$this, 'sortMenuItems']); |
|
382 | - return $admin_menu; |
|
383 | - } |
|
384 | - |
|
385 | - |
|
386 | - /** |
|
387 | - * sort sub menu items |
|
388 | - * |
|
389 | - * @param AdminMenuItem $a menu_item |
|
390 | - * @param AdminMenuItem $b being compared to |
|
391 | - * @return int sort order |
|
392 | - */ |
|
393 | - private function sortMenuItems(AdminMenuItem $a, AdminMenuItem $b): int |
|
394 | - { |
|
395 | - if ($a->menuOrder() === $b->menuOrder()) { |
|
396 | - return 0; |
|
397 | - } |
|
398 | - return $a->menuOrder() < $b->menuOrder() ? -1 : 1; |
|
399 | - } |
|
400 | - |
|
401 | - |
|
402 | - /** |
|
403 | - * Moves the Event Espresso admin menu to the position set by the AdminMenuManager::MENU_POSITION constant |
|
404 | - * |
|
405 | - * @param array $menu_order |
|
406 | - * @return array |
|
407 | - */ |
|
408 | - public function reorderAdminMenu(array $menu_order): array |
|
409 | - { |
|
410 | - $menu_slug = $this->maintenance_mode ? 'espresso_maintenance_settings' : 'espresso_events'; |
|
411 | - $current_index = array_search($menu_slug, $menu_order); |
|
412 | - if ($current_index === false) { |
|
413 | - return $menu_order; |
|
414 | - } |
|
415 | - // chop out the espresso admin menu if found |
|
416 | - $espresso_menu = array_splice($menu_order, $current_index, 1); |
|
417 | - // reinsert at position set by AdminMenuManager::MENU_POSITION constant |
|
418 | - array_splice($menu_order, AdminMenuManager::MENU_POSITION, 0, $espresso_menu); |
|
419 | - return $menu_order; |
|
420 | - } |
|
18 | + /** |
|
19 | + * Default: null - defaults to below Comments |
|
20 | + * |
|
21 | + * 5 - below Posts |
|
22 | + * 10 - below Media |
|
23 | + * 15 - below Links |
|
24 | + * 20 - below Pages |
|
25 | + * 25 - below comments |
|
26 | + * 60 - below first separator |
|
27 | + * 65 - below Plugins |
|
28 | + * 70 - below Users |
|
29 | + * 75 - below Tools |
|
30 | + * 80 - below Settings |
|
31 | + * 100 - below second separator |
|
32 | + */ |
|
33 | + const MENU_POSITION = 100; |
|
34 | + |
|
35 | + |
|
36 | + /** |
|
37 | + * @var AdminMenuItem[] |
|
38 | + */ |
|
39 | + private $menu_items = []; |
|
40 | + |
|
41 | + /** |
|
42 | + * objects for page_init objects detected and loaded |
|
43 | + * |
|
44 | + * @var EE_Admin_Page_Init[] |
|
45 | + */ |
|
46 | + private $installed_pages = []; |
|
47 | + |
|
48 | + /** |
|
49 | + * set to TRUE if site is currently in maintenance mode level 2 |
|
50 | + * |
|
51 | + * @var bool |
|
52 | + */ |
|
53 | + protected $maintenance_mode = false; |
|
54 | + |
|
55 | + /** |
|
56 | + * @var AdminMenuItem |
|
57 | + */ |
|
58 | + private $top_level_menu_item; |
|
59 | + |
|
60 | + |
|
61 | + public function __construct() |
|
62 | + { |
|
63 | + } |
|
64 | + |
|
65 | + |
|
66 | + public function initialize() |
|
67 | + { |
|
68 | + $this->maintenance_mode = EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance; |
|
69 | + $this->addTopLevelMenuItem(); |
|
70 | + $this->initializeMenuGroups(); |
|
71 | + add_action('admin_menu', [$this, 'generateAdminMenu']); |
|
72 | + add_action('network_admin_menu', [$this, 'generateNetworkAdminMenu']); |
|
73 | + add_filter('custom_menu_order', '__return_true'); |
|
74 | + add_filter('menu_order', [$this, 'reorderAdminMenu']); |
|
75 | + } |
|
76 | + |
|
77 | + |
|
78 | + /** |
|
79 | + * adds the top level menu item that everything else descends from. |
|
80 | + * changes depending on whether site is in full maintenance mode or not |
|
81 | + * |
|
82 | + * @return void |
|
83 | + */ |
|
84 | + private function addTopLevelMenuItem() |
|
85 | + { |
|
86 | + $this->top_level_menu_item = $this->maintenance_mode |
|
87 | + ? $this->instantiateAdminMenu( |
|
88 | + [ |
|
89 | + 'menu_slug' => 'espresso_maintenance_settings', |
|
90 | + 'menu_label' => esc_html__('Event Espresso', 'event_espresso'), |
|
91 | + 'capability' => 'manage_options', |
|
92 | + 'menu_group' => 'main', |
|
93 | + 'menu_order' => 10, |
|
94 | + 'menu_type' => AdminMenuItem::TYPE_MENU_TOP, |
|
95 | + 'parent_slug' => 'espresso_maintenance_settings', |
|
96 | + 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
97 | + ] |
|
98 | + ) |
|
99 | + : $this->instantiateAdminMenu( |
|
100 | + [ |
|
101 | + 'menu_slug' => 'espresso_events', |
|
102 | + 'menu_label' => esc_html__('Event Espresso', 'event_espresso'), |
|
103 | + 'capability' => 'ee_read_events', |
|
104 | + 'menu_group' => 'main', |
|
105 | + 'menu_order' => 10, |
|
106 | + 'menu_type' => AdminMenuItem::TYPE_MENU_TOP, |
|
107 | + 'parent_slug' => 'espresso_events', |
|
108 | + 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
109 | + ] |
|
110 | + ); |
|
111 | + } |
|
112 | + |
|
113 | + |
|
114 | + /** |
|
115 | + * sets the filterable _admin_menu_groups property (list of various "groupings" within the EE admin menu array) |
|
116 | + * |
|
117 | + * @return void |
|
118 | + */ |
|
119 | + private function initializeMenuGroups() |
|
120 | + { |
|
121 | + $this->menu_items = apply_filters( |
|
122 | + 'FHEE__EE_Admin_Page_Loader___set_menu_groups__admin_menu_groups', |
|
123 | + [ |
|
124 | + 'main' => $this->instantiateAdminMenu( |
|
125 | + [ |
|
126 | + 'menu_slug' => 'main', |
|
127 | + 'menu_label' => esc_html__('Main', 'event_espresso'), |
|
128 | + 'capability' => $this->maintenance_mode ? 'manage_options' : 'ee_read_ee', |
|
129 | + 'maintenance_mode_parent' => 'espresso_maintenance_settings', |
|
130 | + 'menu_order' => 0, |
|
131 | + 'parent_slug' => 'espresso_events', |
|
132 | + 'show_on_menu' => AdminMenuItem::DISPLAY_NONE, |
|
133 | + ] |
|
134 | + ), |
|
135 | + 'management' => $this->instantiateAdminMenu( |
|
136 | + [ |
|
137 | + 'menu_slug' => 'management', |
|
138 | + 'menu_label' => esc_html__('Management', 'event_espresso'), |
|
139 | + 'capability' => 'ee_read_ee', |
|
140 | + 'menu_order' => 10, |
|
141 | + 'parent_slug' => 'espresso_events', |
|
142 | + 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
143 | + ] |
|
144 | + ), |
|
145 | + 'addons' => $this->instantiateAdminMenu( |
|
146 | + [ |
|
147 | + 'menu_slug' => 'addons', |
|
148 | + 'menu_label' => esc_html__('Add-ons', 'event_espresso'), |
|
149 | + 'capability' => 'ee_read_ee', |
|
150 | + 'menu_order' => 20, |
|
151 | + 'parent_slug' => 'espresso_events', |
|
152 | + 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_AND_NETWORK, |
|
153 | + ] |
|
154 | + ), |
|
155 | + 'settings' => $this->instantiateAdminMenu( |
|
156 | + [ |
|
157 | + 'menu_slug' => 'settings', |
|
158 | + 'menu_label' => esc_html__('Settings', 'event_espresso'), |
|
159 | + 'capability' => 'ee_read_ee', |
|
160 | + 'menu_order' => 30, |
|
161 | + 'parent_slug' => 'espresso_events', |
|
162 | + 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
163 | + ] |
|
164 | + ), |
|
165 | + 'templates' => $this->instantiateAdminMenu( |
|
166 | + [ |
|
167 | + 'menu_slug' => 'templates', |
|
168 | + 'menu_label' => esc_html__('Templates', 'event_espresso'), |
|
169 | + 'capability' => 'ee_read_ee', |
|
170 | + 'menu_order' => 40, |
|
171 | + 'parent_slug' => 'espresso_events', |
|
172 | + 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
173 | + ] |
|
174 | + ), |
|
175 | + 'extras' => $this->instantiateAdminMenu( |
|
176 | + [ |
|
177 | + 'menu_slug' => 'extras', |
|
178 | + 'menu_label' => esc_html__('Extras', 'event_espresso'), |
|
179 | + 'capability' => 'ee_read_ee', |
|
180 | + 'maintenance_mode_parent' => 'espresso_maintenance_settings', |
|
181 | + 'menu_order' => 50, |
|
182 | + 'parent_slug' => 'espresso_events', |
|
183 | + 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_AND_NETWORK, |
|
184 | + ] |
|
185 | + ), |
|
186 | + 'tools' => $this->instantiateAdminMenu( |
|
187 | + [ |
|
188 | + 'menu_slug' => 'tools', |
|
189 | + 'menu_label' => esc_html__('Tools', 'event_espresso'), |
|
190 | + 'capability' => 'ee_read_ee', |
|
191 | + 'menu_order' => 60, |
|
192 | + 'parent_slug' => 'espresso_events', |
|
193 | + 'show_on_menu' => AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
194 | + ] |
|
195 | + ), |
|
196 | + ] |
|
197 | + ); |
|
198 | + } |
|
199 | + |
|
200 | + |
|
201 | + /** |
|
202 | + * instantiates and returns the appropriate AdminMenuItem for the provided EE_Admin_Page_Init |
|
203 | + * |
|
204 | + * @param EE_Admin_Page_Init $admin_page_init |
|
205 | + * @return AdminMenuItem |
|
206 | + */ |
|
207 | + public function getAdminMenu(EE_Admin_Page_Init $admin_page_init): AdminMenuItem |
|
208 | + { |
|
209 | + // see if admin page init is using new classes |
|
210 | + $menu_properties = $admin_page_init->getMenuProperties(); |
|
211 | + if (empty($menu_properties)) { |
|
212 | + // no? ok setup the admin menu item the old way |
|
213 | + $admin_page_init->setupLegacyAdminMenuItem(); |
|
214 | + } else { |
|
215 | + // adding the admin page init callback here means the menu doesn't have to cart that object around |
|
216 | + $menu_properties['menu_callback'] = [$admin_page_init, 'initialize_admin_page']; |
|
217 | + $admin_page_init->setAdminMenu($this->instantiateAdminMenu($menu_properties)); |
|
218 | + } |
|
219 | + $admin_menu = $admin_page_init->adminMenu(); |
|
220 | + if (! $admin_menu instanceof AdminMenuItem) { |
|
221 | + throw new DomainException(esc_html__('Invalid AdminMenuItem', 'event_espresso')); |
|
222 | + } |
|
223 | + if (! is_callable($admin_menu->menuCallback())) { |
|
224 | + $admin_menu->setMenuCallback([$admin_page_init, 'initialize_admin_page']); |
|
225 | + } |
|
226 | + // get the menu group that this menu item belongs to and then add it |
|
227 | + $admin_group = $this->getMenuGroup($admin_menu); |
|
228 | + $admin_group->addMenuItem($admin_menu); |
|
229 | + return $admin_menu; |
|
230 | + } |
|
231 | + |
|
232 | + |
|
233 | + /** |
|
234 | + * @param array $menu_properties |
|
235 | + * @return AdminMenuItem|null |
|
236 | + */ |
|
237 | + private function instantiateAdminMenu(array $menu_properties): ?AdminMenuItem |
|
238 | + { |
|
239 | + $type = $menu_properties['menu_type'] ?? AdminMenuItem::TYPE_MENU_GROUP; |
|
240 | + unset($menu_properties['menu_type']); |
|
241 | + switch ($type) { |
|
242 | + case AdminMenuItem::TYPE_MENU_GROUP: |
|
243 | + unset($menu_properties['menu_callback']); |
|
244 | + return new AdminMenuGroup($menu_properties); |
|
245 | + case AdminMenuItem::TYPE_MENU_TOP: |
|
246 | + return new AdminMenuTopLevel($menu_properties); |
|
247 | + case AdminMenuItem::TYPE_MENU_SUB_ITEM: |
|
248 | + return new AdminMenuSubItem($menu_properties); |
|
249 | + } |
|
250 | + return null; |
|
251 | + } |
|
252 | + |
|
253 | + |
|
254 | + /** |
|
255 | + * @param AdminMenuItem $admin_menu |
|
256 | + * @return AdminMenuGroup |
|
257 | + * @throws DomainException |
|
258 | + * @throws OutOfRangeException |
|
259 | + */ |
|
260 | + private function getMenuGroup(AdminMenuItem $admin_menu): AdminMenuGroup |
|
261 | + { |
|
262 | + if (! isset($this->menu_items[ $admin_menu->menuGroup() ])) { |
|
263 | + throw new OutOfRangeException(esc_html__('AdminMenuGroup does not exist', 'event_espresso')); |
|
264 | + } |
|
265 | + $admin_group = $this->menu_items[ $admin_menu->menuGroup() ]; |
|
266 | + if (! $admin_group instanceof AdminMenuGroup) { |
|
267 | + throw new DomainException(esc_html__('Invalid AdminMenuGroup found', 'event_espresso')); |
|
268 | + } |
|
269 | + return $admin_group; |
|
270 | + } |
|
271 | + |
|
272 | + |
|
273 | + /** |
|
274 | + * set_network_menus |
|
275 | + * This method sets up the menus for network EE Admin Pages. |
|
276 | + * Almost identical to EE_Admin_Page_Loader::set_menus() except pages |
|
277 | + * are only added to the menu map if they are intended for the admin menu |
|
278 | + * |
|
279 | + * @return void |
|
280 | + * @throws DomainException |
|
281 | + */ |
|
282 | + public function generateNetworkAdminMenu() |
|
283 | + { |
|
284 | + $this->generateAdminMenu(true); |
|
285 | + } |
|
286 | + |
|
287 | + |
|
288 | + /** |
|
289 | + * This method sets up the menus for EE Admin Pages |
|
290 | + * |
|
291 | + * @return void |
|
292 | + * @throws DomainException |
|
293 | + */ |
|
294 | + public function generateAdminMenu(bool $network_admin = false) |
|
295 | + { |
|
296 | + $admin_menu = $this->sortMenu($this->menu_items); |
|
297 | + $this->top_level_menu_item->registerAdminMenuItem($network_admin); |
|
298 | + $this->registerAdminMenu($admin_menu, $network_admin); |
|
299 | + } |
|
300 | + |
|
301 | + |
|
302 | + /** |
|
303 | + * @param array $admin_menu |
|
304 | + * @param bool $network_admin |
|
305 | + */ |
|
306 | + private function registerAdminMenu(array $admin_menu, bool $network_admin) |
|
307 | + { |
|
308 | + foreach ($admin_menu as $menu_item) { |
|
309 | + if ($this->skipMenuItem($menu_item)) { |
|
310 | + continue; |
|
311 | + } |
|
312 | + try { |
|
313 | + $wp_page_slug = $menu_item->registerAdminMenuItem($network_admin); |
|
314 | + $admin_init_page = $this->installed_pages[ $menu_item->menuSlug() ] ?? null; |
|
315 | + if ($wp_page_slug && $admin_init_page instanceof EE_Admin_Page_Init) { |
|
316 | + $admin_init_page->setWpPageSlug($wp_page_slug); |
|
317 | + $admin_init_page->set_page_dependencies($wp_page_slug); |
|
318 | + } |
|
319 | + if ($menu_item instanceof AdminMenuGroup) { |
|
320 | + $this->registerAdminMenu($menu_item->getMenuItems(), $network_admin); |
|
321 | + } |
|
322 | + } catch (Exception $e) { |
|
323 | + EE_Error::add_error($e->getMessage(), $e->getFile(), __FUNCTION__, $e->getLine()); |
|
324 | + } |
|
325 | + } |
|
326 | + } |
|
327 | + |
|
328 | + |
|
329 | + /** |
|
330 | + * returns TRUE if any of the following conditions is met: |
|
331 | + * - menu item is NOT an instanceof AdminMenuItem |
|
332 | + * - menu item has already been registered |
|
333 | + * - menu item should not be shown when site is in full maintenance mode |
|
334 | + * - current user does not have the required access permission |
|
335 | + * - menu item is a group but has no sub items |
|
336 | + * |
|
337 | + * @param AdminMenuItem|null $menu_item |
|
338 | + * @return bool |
|
339 | + */ |
|
340 | + private function skipMenuItem(?AdminMenuItem $menu_item): bool |
|
341 | + { |
|
342 | + return ! $menu_item instanceof AdminMenuItem |
|
343 | + || $menu_item->isRegistered() |
|
344 | + || ! $menu_item->showOnMaintenanceModeMenu() |
|
345 | + || ! $menu_item->currentUserHasAccess() |
|
346 | + || ( |
|
347 | + $menu_item instanceof AdminMenuGroup |
|
348 | + && $menu_item->hasNoMenuItems() |
|
349 | + ); |
|
350 | + } |
|
351 | + |
|
352 | + |
|
353 | + /** |
|
354 | + * @param EE_Admin_Page_Init[] $installed_pages |
|
355 | + */ |
|
356 | + public function setInstalledPages(array $installed_pages): void |
|
357 | + { |
|
358 | + $this->installed_pages = $installed_pages; |
|
359 | + } |
|
360 | + |
|
361 | + |
|
362 | + /** |
|
363 | + * Recursively sort menu groups and their sub items |
|
364 | + * |
|
365 | + * @return AdminMenuItem[] |
|
366 | + * @throws DomainException |
|
367 | + */ |
|
368 | + public function sortMenu(array $admin_menu): array |
|
369 | + { |
|
370 | + foreach ($admin_menu as $menu_group) { |
|
371 | + if (! $menu_group instanceof AdminMenuItem) { |
|
372 | + throw new DomainException(esc_html__('Invalid AdminMenuItem', 'event_espresso')); |
|
373 | + } |
|
374 | + if ($menu_group instanceof AdminMenuGroup) { |
|
375 | + // sort sub items |
|
376 | + $menu_items = $this->sortMenu($menu_group->getMenuItems()); |
|
377 | + $menu_group->setMenuItems($menu_items); |
|
378 | + } |
|
379 | + } |
|
380 | + // sort incoming array AFTER it's been looped through and elements have been validated |
|
381 | + usort($admin_menu, [$this, 'sortMenuItems']); |
|
382 | + return $admin_menu; |
|
383 | + } |
|
384 | + |
|
385 | + |
|
386 | + /** |
|
387 | + * sort sub menu items |
|
388 | + * |
|
389 | + * @param AdminMenuItem $a menu_item |
|
390 | + * @param AdminMenuItem $b being compared to |
|
391 | + * @return int sort order |
|
392 | + */ |
|
393 | + private function sortMenuItems(AdminMenuItem $a, AdminMenuItem $b): int |
|
394 | + { |
|
395 | + if ($a->menuOrder() === $b->menuOrder()) { |
|
396 | + return 0; |
|
397 | + } |
|
398 | + return $a->menuOrder() < $b->menuOrder() ? -1 : 1; |
|
399 | + } |
|
400 | + |
|
401 | + |
|
402 | + /** |
|
403 | + * Moves the Event Espresso admin menu to the position set by the AdminMenuManager::MENU_POSITION constant |
|
404 | + * |
|
405 | + * @param array $menu_order |
|
406 | + * @return array |
|
407 | + */ |
|
408 | + public function reorderAdminMenu(array $menu_order): array |
|
409 | + { |
|
410 | + $menu_slug = $this->maintenance_mode ? 'espresso_maintenance_settings' : 'espresso_events'; |
|
411 | + $current_index = array_search($menu_slug, $menu_order); |
|
412 | + if ($current_index === false) { |
|
413 | + return $menu_order; |
|
414 | + } |
|
415 | + // chop out the espresso admin menu if found |
|
416 | + $espresso_menu = array_splice($menu_order, $current_index, 1); |
|
417 | + // reinsert at position set by AdminMenuManager::MENU_POSITION constant |
|
418 | + array_splice($menu_order, AdminMenuManager::MENU_POSITION, 0, $espresso_menu); |
|
419 | + return $menu_order; |
|
420 | + } |
|
421 | 421 | } |
@@ -217,10 +217,10 @@ discard block |
||
217 | 217 | $admin_page_init->setAdminMenu($this->instantiateAdminMenu($menu_properties)); |
218 | 218 | } |
219 | 219 | $admin_menu = $admin_page_init->adminMenu(); |
220 | - if (! $admin_menu instanceof AdminMenuItem) { |
|
220 | + if ( ! $admin_menu instanceof AdminMenuItem) { |
|
221 | 221 | throw new DomainException(esc_html__('Invalid AdminMenuItem', 'event_espresso')); |
222 | 222 | } |
223 | - if (! is_callable($admin_menu->menuCallback())) { |
|
223 | + if ( ! is_callable($admin_menu->menuCallback())) { |
|
224 | 224 | $admin_menu->setMenuCallback([$admin_page_init, 'initialize_admin_page']); |
225 | 225 | } |
226 | 226 | // get the menu group that this menu item belongs to and then add it |
@@ -259,11 +259,11 @@ discard block |
||
259 | 259 | */ |
260 | 260 | private function getMenuGroup(AdminMenuItem $admin_menu): AdminMenuGroup |
261 | 261 | { |
262 | - if (! isset($this->menu_items[ $admin_menu->menuGroup() ])) { |
|
262 | + if ( ! isset($this->menu_items[$admin_menu->menuGroup()])) { |
|
263 | 263 | throw new OutOfRangeException(esc_html__('AdminMenuGroup does not exist', 'event_espresso')); |
264 | 264 | } |
265 | - $admin_group = $this->menu_items[ $admin_menu->menuGroup() ]; |
|
266 | - if (! $admin_group instanceof AdminMenuGroup) { |
|
265 | + $admin_group = $this->menu_items[$admin_menu->menuGroup()]; |
|
266 | + if ( ! $admin_group instanceof AdminMenuGroup) { |
|
267 | 267 | throw new DomainException(esc_html__('Invalid AdminMenuGroup found', 'event_espresso')); |
268 | 268 | } |
269 | 269 | return $admin_group; |
@@ -311,7 +311,7 @@ discard block |
||
311 | 311 | } |
312 | 312 | try { |
313 | 313 | $wp_page_slug = $menu_item->registerAdminMenuItem($network_admin); |
314 | - $admin_init_page = $this->installed_pages[ $menu_item->menuSlug() ] ?? null; |
|
314 | + $admin_init_page = $this->installed_pages[$menu_item->menuSlug()] ?? null; |
|
315 | 315 | if ($wp_page_slug && $admin_init_page instanceof EE_Admin_Page_Init) { |
316 | 316 | $admin_init_page->setWpPageSlug($wp_page_slug); |
317 | 317 | $admin_init_page->set_page_dependencies($wp_page_slug); |
@@ -368,7 +368,7 @@ discard block |
||
368 | 368 | public function sortMenu(array $admin_menu): array |
369 | 369 | { |
370 | 370 | foreach ($admin_menu as $menu_group) { |
371 | - if (! $menu_group instanceof AdminMenuItem) { |
|
371 | + if ( ! $menu_group instanceof AdminMenuItem) { |
|
372 | 372 | throw new DomainException(esc_html__('Invalid AdminMenuItem', 'event_espresso')); |
373 | 373 | } |
374 | 374 | if ($menu_group instanceof AdminMenuGroup) { |
@@ -4,15 +4,15 @@ |
||
4 | 4 | |
5 | 5 | class AdminMenuSubItem extends AdminMenuTopLevel |
6 | 6 | { |
7 | - protected function registerMenuItem(): string |
|
8 | - { |
|
9 | - return add_submenu_page( |
|
10 | - $this->parentSlug(), |
|
11 | - $this->title(), |
|
12 | - $this->menuLabel(), |
|
13 | - $this->capability(), |
|
14 | - $this->menuSlug(), |
|
15 | - $this->menuCallback() |
|
16 | - ); |
|
17 | - } |
|
7 | + protected function registerMenuItem(): string |
|
8 | + { |
|
9 | + return add_submenu_page( |
|
10 | + $this->parentSlug(), |
|
11 | + $this->title(), |
|
12 | + $this->menuLabel(), |
|
13 | + $this->capability(), |
|
14 | + $this->menuSlug(), |
|
15 | + $this->menuCallback() |
|
16 | + ); |
|
17 | + } |
|
18 | 18 | } |
@@ -11,517 +11,517 @@ |
||
11 | 11 | |
12 | 12 | abstract class AdminMenuItem |
13 | 13 | { |
14 | - public const DISPLAY_NONE = 0; |
|
15 | - |
|
16 | - public const DISPLAY_BLOG_ONLY = 1; |
|
17 | - |
|
18 | - public const DISPLAY_BLOG_AND_NETWORK = 2; |
|
19 | - |
|
20 | - public const DISPLAY_NETWORK_ONLY = 3; |
|
21 | - |
|
22 | - public const TYPE_MENU_TOP = 'top'; |
|
23 | - |
|
24 | - public const TYPE_MENU_GROUP = 'group'; |
|
25 | - |
|
26 | - public const TYPE_MENU_SUB_ITEM = 'sub-item'; |
|
27 | - |
|
28 | - |
|
29 | - /** |
|
30 | - * What capability is required to access this page. |
|
31 | - * |
|
32 | - * @since 4.4.0 |
|
33 | - * @var string |
|
34 | - */ |
|
35 | - protected $capability = 'administrator'; |
|
36 | - |
|
37 | - /** |
|
38 | - * set to TRUE if site is currently in maintenance mode level 2 |
|
39 | - * |
|
40 | - * @var bool |
|
41 | - */ |
|
42 | - protected $maintenance_mode = false; |
|
43 | - |
|
44 | - /** |
|
45 | - * Menu maps can define a parent slug that gets used instead of the main parent slug for the menu when |
|
46 | - * EE_Maintenance_Mode::level_2_complete_maintenance is active. |
|
47 | - * |
|
48 | - * @var string |
|
49 | - */ |
|
50 | - public $maintenance_mode_parent = ''; |
|
51 | - |
|
52 | - /** |
|
53 | - * The callback for displaying the page that the menu references. |
|
54 | - * |
|
55 | - * @since 4.4.0 |
|
56 | - * @var string |
|
57 | - */ |
|
58 | - protected $menu_callback; |
|
59 | - |
|
60 | - /** |
|
61 | - * The EE specific group this menu item belongs in (group slug). |
|
62 | - * |
|
63 | - * @since 4.4.0 |
|
64 | - * @var string |
|
65 | - */ |
|
66 | - protected $menu_group; |
|
67 | - |
|
68 | - /** |
|
69 | - * The label for the menu item. (What shows up in the actual menu). |
|
70 | - * |
|
71 | - * @since 4.4.0 |
|
72 | - * @var string |
|
73 | - */ |
|
74 | - protected $menu_label; |
|
75 | - |
|
76 | - /** |
|
77 | - * What order this item should be in the menu. |
|
78 | - * |
|
79 | - * @since 4.4.0 |
|
80 | - * @var int |
|
81 | - */ |
|
82 | - protected $menu_order; |
|
83 | - |
|
84 | - /** |
|
85 | - * What slug should be used to reference this menu item. |
|
86 | - * |
|
87 | - * @since 4.4.0 |
|
88 | - * @var string |
|
89 | - */ |
|
90 | - protected $menu_slug; |
|
91 | - |
|
92 | - /** |
|
93 | - * What menu item is the parent of this menu item. |
|
94 | - * |
|
95 | - * @since 4.4.0 |
|
96 | - * @var string |
|
97 | - */ |
|
98 | - protected $parent_slug; |
|
99 | - |
|
100 | - /** |
|
101 | - * set to TRUE once menu item has been added to generated menu |
|
102 | - * |
|
103 | - * @var bool |
|
104 | - */ |
|
105 | - protected $registered = false; |
|
106 | - |
|
107 | - /** |
|
108 | - * Whether this item is displayed in the menu or not. |
|
109 | - * Sometimes an EE Admin Page needs to register itself but is not accessible via the WordPress |
|
110 | - * admin menu. |
|
111 | - * |
|
112 | - * @since 4.4.0 |
|
113 | - * @var int |
|
114 | - */ |
|
115 | - protected $show_on_menu = self::DISPLAY_BLOG_ONLY; |
|
116 | - |
|
117 | - /** |
|
118 | - * The title for the menu page. (the page the menu links to) |
|
119 | - * |
|
120 | - * @since 4.4.0 |
|
121 | - * @var string |
|
122 | - */ |
|
123 | - protected $title; |
|
124 | - |
|
125 | - |
|
126 | - /** |
|
127 | - * @param array $menu_args An array of arguments used to setup the menu properties on construct. |
|
128 | - * @param array $required An array of keys that should be in the $menu_args, |
|
129 | - * this is used to validate that the items that should be defined are present. |
|
130 | - * @return void |
|
131 | - * @throws DomainException |
|
132 | - * @throws InvalidArgumentException |
|
133 | - * @throws OutOfBoundsException |
|
134 | - */ |
|
135 | - public function __construct(array $menu_args, array $required) |
|
136 | - { |
|
137 | - // we don't want this coupling anymore >:( |
|
138 | - unset($menu_args['admin_init_page'], $required['admin_init_page']); |
|
139 | - $this->maintenance_mode = EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance; |
|
140 | - |
|
141 | - // filter all args before processing so plugins can manipulate various settings for menus. |
|
142 | - $menu_args = apply_filters( |
|
143 | - 'FHEE__EE_Admin_Page_Menu_Map__construct__menu_args', |
|
144 | - $menu_args, |
|
145 | - $required, |
|
146 | - get_class($this) |
|
147 | - ); |
|
148 | - |
|
149 | - $this->verifyRequired($menu_args, $required); |
|
150 | - $this->setProperties($menu_args); |
|
151 | - } |
|
152 | - |
|
153 | - |
|
154 | - /** |
|
155 | - * This method should define how the menu page gets added for this particular item |
|
156 | - * and go ahead and define it. Note that child classes MUST also return the result of |
|
157 | - * the function used to register the WordPress admin page (the wp_page_slug string) |
|
158 | - * |
|
159 | - * @return string wp_page_slug. |
|
160 | - * @since 4.4.0 |
|
161 | - */ |
|
162 | - abstract protected function registerMenuItem(): string; |
|
163 | - |
|
164 | - |
|
165 | - /** |
|
166 | - * Called by client code to use this menu map for registering a WordPress admin page |
|
167 | - * |
|
168 | - * @param boolean $network_admin whether this is being added to the network admin page or not |
|
169 | - * @since 4.4.0 |
|
170 | - */ |
|
171 | - public function registerAdminMenuItem(bool $network_admin = false): string |
|
172 | - { |
|
173 | - $this->registered = true; |
|
174 | - return $this->displayOnBlogAndNetworkAdmin() |
|
175 | - || $this->displayOnBlogAdmin($network_admin) |
|
176 | - || $this->displayOnNetworkAdmin($network_admin) |
|
177 | - ? $this->registerMenuItem() |
|
178 | - : ''; |
|
179 | - } |
|
180 | - |
|
181 | - |
|
182 | - /** |
|
183 | - * @param array $menu_args |
|
184 | - * @param array $required |
|
185 | - * @throws DomainException |
|
186 | - */ |
|
187 | - private function verifyRequired(array $menu_args, array $required) |
|
188 | - { |
|
189 | - // verify that required keys are present in the incoming array. |
|
190 | - $missing = array_diff($required, array_keys($menu_args)); |
|
191 | - |
|
192 | - if (! empty($missing)) { |
|
193 | - throw new DomainException( |
|
194 | - sprintf( |
|
195 | - esc_html__( |
|
196 | - '%1$s is missing some expected keys in the argument array. The following keys are missing: %2$s', |
|
197 | - 'event_espresso' |
|
198 | - ), |
|
199 | - get_class($this), |
|
200 | - implode(', ', $missing) |
|
201 | - ) |
|
202 | - ); |
|
203 | - } |
|
204 | - |
|
205 | - if ( |
|
206 | - in_array('admin_init_page', $required, true) |
|
207 | - && ! (isset($menu_args['admin_init_page']) && $menu_args['admin_init_page'] instanceof EE_Admin_Page_Init) |
|
208 | - ) { |
|
209 | - throw new InvalidArgumentException( |
|
210 | - sprintf( |
|
211 | - esc_html__( |
|
212 | - 'The value for the "admin_init_page" argument must be an instance of an EE_Admin_Page_Init object. Instead %s was given as the value.', |
|
213 | - 'event_espresso' |
|
214 | - ), |
|
215 | - print_r($menu_args['admin_init_page'] ?? null, true) |
|
216 | - ) |
|
217 | - ); |
|
218 | - } |
|
219 | - } |
|
220 | - |
|
221 | - |
|
222 | - /** |
|
223 | - * @param array $menu_args |
|
224 | - * @throws InvalidArgumentException |
|
225 | - * @throws OutOfBoundsException |
|
226 | - */ |
|
227 | - private function setProperties(array $menu_args) |
|
228 | - { |
|
229 | - $menu_args += [ |
|
230 | - 'capability' => 'ee_read_ee', |
|
231 | - 'maintenance_mode_parent' => '', |
|
232 | - 'menu_callback' => null, |
|
233 | - 'menu_group' => '', |
|
234 | - 'menu_label' => '', |
|
235 | - 'menu_order' => 100, |
|
236 | - 'menu_slug' => '', |
|
237 | - 'parent_slug' => 'espresso_events', |
|
238 | - 'show_on_menu' => AdminMenuItem::DISPLAY_NONE, |
|
239 | - 'title' => '', |
|
240 | - ]; |
|
241 | - |
|
242 | - $this->setMenuSlug($menu_args['menu_slug']); |
|
243 | - $this->setCapability($menu_args['capability']); |
|
244 | - $this->setMaintenanceModeParent($menu_args['maintenance_mode_parent']); |
|
245 | - $this->setMenuCallback($menu_args['menu_callback']); |
|
246 | - $this->setMenuGroup($menu_args['menu_group']); |
|
247 | - $this->setMenuLabel($menu_args['menu_label']); |
|
248 | - $this->setMenuOrder($menu_args['menu_order']); |
|
249 | - $this->setParentSlug($menu_args['parent_slug']); |
|
250 | - $this->setShowOnMenu($menu_args['show_on_menu']); |
|
251 | - $this->setTitle($menu_args['title']); |
|
252 | - } |
|
253 | - |
|
254 | - |
|
255 | - /** |
|
256 | - * The capability required for this menu to be displayed to the user. |
|
257 | - * |
|
258 | - * @return string |
|
259 | - */ |
|
260 | - public function capability(): string |
|
261 | - { |
|
262 | - return $this->capability; |
|
263 | - } |
|
264 | - |
|
265 | - |
|
266 | - /** |
|
267 | - * @param string $capability |
|
268 | - */ |
|
269 | - public function setCapability(string $capability): void |
|
270 | - { |
|
271 | - $this->capability = $capability; |
|
272 | - // filter capabilities (both static and dynamic) |
|
273 | - $this->capability = apply_filters('FHEE_management_capability', $this->capability, null); |
|
274 | - $this->capability = apply_filters('FHEE_' . $this->menu_slug . '_capability', $this->capability, null); |
|
275 | - } |
|
276 | - |
|
277 | - |
|
278 | - public function currentUserHasAccess(): bool |
|
279 | - { |
|
280 | - return EE_Capabilities::instance()->current_user_can($this->capability(), $this->menuSlug()); |
|
281 | - } |
|
282 | - |
|
283 | - |
|
284 | - /** |
|
285 | - * @param bool $network_admin |
|
286 | - * @return bool |
|
287 | - */ |
|
288 | - public function displayOnBlogAdmin(bool $network_admin): bool |
|
289 | - { |
|
290 | - return ! $network_admin && $this->show_on_menu === AdminMenuItem::DISPLAY_BLOG_ONLY; |
|
291 | - } |
|
292 | - |
|
293 | - |
|
294 | - /** |
|
295 | - * @return bool |
|
296 | - */ |
|
297 | - public function displayOnBlogAndNetworkAdmin(): bool |
|
298 | - { |
|
299 | - return $this->show_on_menu === AdminMenuItem::DISPLAY_BLOG_AND_NETWORK; |
|
300 | - } |
|
301 | - |
|
302 | - |
|
303 | - /** |
|
304 | - * @param bool $network_admin |
|
305 | - * @return bool |
|
306 | - */ |
|
307 | - public function displayOnNetworkAdmin(bool $network_admin): bool |
|
308 | - { |
|
309 | - return $network_admin && $this->show_on_menu === AdminMenuItem::DISPLAY_NETWORK_ONLY; |
|
310 | - } |
|
311 | - |
|
312 | - |
|
313 | - /** |
|
314 | - * parent slug to use when site is in full maintenance mode |
|
315 | - * |
|
316 | - * @return string |
|
317 | - */ |
|
318 | - public function maintenanceModeParent(): string |
|
319 | - { |
|
320 | - return $this->maintenance_mode_parent; |
|
321 | - } |
|
322 | - |
|
323 | - |
|
324 | - /** |
|
325 | - * @param string $maintenance_mode_parent |
|
326 | - */ |
|
327 | - public function setMaintenanceModeParent(string $maintenance_mode_parent): void |
|
328 | - { |
|
329 | - $this->maintenance_mode_parent = $maintenance_mode_parent; |
|
330 | - } |
|
331 | - |
|
332 | - |
|
333 | - /** |
|
334 | - * Optional. The function to be called to output the content for this page. |
|
335 | - * |
|
336 | - * @return callable|null |
|
337 | - */ |
|
338 | - public function menuCallback(): ?callable |
|
339 | - { |
|
340 | - return $this->menu_callback; |
|
341 | - } |
|
342 | - |
|
343 | - |
|
344 | - /** |
|
345 | - * @param callable|null $menu_callback |
|
346 | - */ |
|
347 | - public function setMenuCallback(?callable $menu_callback): void |
|
348 | - { |
|
349 | - $this->menu_callback = $menu_callback; |
|
350 | - } |
|
351 | - |
|
352 | - |
|
353 | - /** |
|
354 | - * Slug for menu group that this menu item will appear under |
|
355 | - * |
|
356 | - * @return string |
|
357 | - */ |
|
358 | - public function menuGroup(): string |
|
359 | - { |
|
360 | - return $this->menu_group; |
|
361 | - } |
|
362 | - |
|
363 | - |
|
364 | - /** |
|
365 | - * @param string $menu_group |
|
366 | - */ |
|
367 | - public function setMenuGroup(string $menu_group): void |
|
368 | - { |
|
369 | - $this->menu_group = $menu_group; |
|
370 | - } |
|
371 | - |
|
372 | - |
|
373 | - /** |
|
374 | - * The text to be used for the menu. |
|
375 | - * |
|
376 | - * @return string |
|
377 | - */ |
|
378 | - public function menuLabel(): string |
|
379 | - { |
|
380 | - return $this->menu_label; |
|
381 | - } |
|
382 | - |
|
383 | - |
|
384 | - /** |
|
385 | - * @param string $menu_label |
|
386 | - */ |
|
387 | - public function setMenuLabel(string $menu_label): void |
|
388 | - { |
|
389 | - $this->menu_label = $menu_label; |
|
390 | - } |
|
391 | - |
|
392 | - |
|
393 | - /** |
|
394 | - * Optional. The position in the menu order this item should appear. |
|
395 | - * |
|
396 | - * @return int |
|
397 | - */ |
|
398 | - public function menuOrder(): int |
|
399 | - { |
|
400 | - return $this->menu_order; |
|
401 | - } |
|
402 | - |
|
403 | - |
|
404 | - /** |
|
405 | - * @param int $menu_order |
|
406 | - */ |
|
407 | - public function setMenuOrder(int $menu_order): void |
|
408 | - { |
|
409 | - $this->menu_order = absint($menu_order); |
|
410 | - } |
|
411 | - |
|
412 | - |
|
413 | - /** |
|
414 | - * The slug name to refer to this menu by. Should be unique for this menu |
|
415 | - * |
|
416 | - * @return string |
|
417 | - */ |
|
418 | - public function menuSlug(): string |
|
419 | - { |
|
420 | - return $this->menu_slug; |
|
421 | - } |
|
422 | - |
|
423 | - |
|
424 | - /** |
|
425 | - * @param string $menu_slug |
|
426 | - */ |
|
427 | - public function setMenuSlug(string $menu_slug): void |
|
428 | - { |
|
429 | - $this->menu_slug = sanitize_key($menu_slug); |
|
430 | - } |
|
431 | - |
|
432 | - |
|
433 | - /** |
|
434 | - * The slug name for the parent menu (or the file name of a standard WordPress admin page). |
|
435 | - * |
|
436 | - * @return string |
|
437 | - */ |
|
438 | - public function parentSlug(): string |
|
439 | - { |
|
440 | - return $this->parent_slug; |
|
441 | - } |
|
442 | - |
|
443 | - |
|
444 | - /** |
|
445 | - * if site is in full maintenance mode, |
|
446 | - * then parent slug will be swapped with the maintenance_mode_parent if that property has been set |
|
447 | - * |
|
448 | - * @param string $parent_slug |
|
449 | - */ |
|
450 | - public function setParentSlug(string $parent_slug): void |
|
451 | - { |
|
452 | - $this->parent_slug = $this->maintenance_mode && $this->maintenance_mode_parent |
|
453 | - ? $this->maintenance_mode_parent |
|
454 | - : $parent_slug; |
|
455 | - } |
|
456 | - |
|
457 | - |
|
458 | - /** |
|
459 | - * returns true if menu item has already been registered with WP core |
|
460 | - * |
|
461 | - * @return bool |
|
462 | - */ |
|
463 | - public function isRegistered(): bool |
|
464 | - { |
|
465 | - return $this->registered; |
|
466 | - } |
|
467 | - |
|
468 | - |
|
469 | - /** |
|
470 | - * returns TRUE if: |
|
471 | - * - site is currently NOT in full site maintenance mode |
|
472 | - * - site IS in full site maintenance mode and menu item has a valid maintenance mode parent |
|
473 | - * |
|
474 | - * @return int |
|
475 | - */ |
|
476 | - public function showOnMaintenanceModeMenu(): int |
|
477 | - { |
|
478 | - return ! $this->maintenance_mode || $this->maintenanceModeParent() !== ''; |
|
479 | - } |
|
480 | - |
|
481 | - |
|
482 | - /** |
|
483 | - * @param int $show_on_menu |
|
484 | - * @throws DomainException |
|
485 | - */ |
|
486 | - public function setShowOnMenu(int $show_on_menu): void |
|
487 | - { |
|
488 | - $valid_menu_options = [ |
|
489 | - AdminMenuItem::DISPLAY_NONE, |
|
490 | - AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
491 | - AdminMenuItem::DISPLAY_BLOG_AND_NETWORK, |
|
492 | - AdminMenuItem::DISPLAY_NETWORK_ONLY, |
|
493 | - ]; |
|
494 | - if (! in_array($show_on_menu, $valid_menu_options, true)) { |
|
495 | - throw new DomainException( |
|
496 | - sprintf( |
|
497 | - esc_html__( |
|
498 | - 'Invalid "ShowOnMenu" option of "%1$s" supplied. You must use one of the AdminMenuItem::DISPLAY_* constants.', |
|
499 | - 'event_espresso' |
|
500 | - ), |
|
501 | - $show_on_menu |
|
502 | - ) |
|
503 | - ); |
|
504 | - } |
|
505 | - $this->show_on_menu = $show_on_menu; |
|
506 | - } |
|
507 | - |
|
508 | - |
|
509 | - /** |
|
510 | - * The text to be displayed in the title tags of the page when the menu is selected |
|
511 | - * |
|
512 | - * @return string |
|
513 | - */ |
|
514 | - public function title(): string |
|
515 | - { |
|
516 | - return $this->title; |
|
517 | - } |
|
518 | - |
|
519 | - |
|
520 | - /** |
|
521 | - * @param string $title |
|
522 | - */ |
|
523 | - public function setTitle(string $title): void |
|
524 | - { |
|
525 | - $this->title = $title; |
|
526 | - } |
|
14 | + public const DISPLAY_NONE = 0; |
|
15 | + |
|
16 | + public const DISPLAY_BLOG_ONLY = 1; |
|
17 | + |
|
18 | + public const DISPLAY_BLOG_AND_NETWORK = 2; |
|
19 | + |
|
20 | + public const DISPLAY_NETWORK_ONLY = 3; |
|
21 | + |
|
22 | + public const TYPE_MENU_TOP = 'top'; |
|
23 | + |
|
24 | + public const TYPE_MENU_GROUP = 'group'; |
|
25 | + |
|
26 | + public const TYPE_MENU_SUB_ITEM = 'sub-item'; |
|
27 | + |
|
28 | + |
|
29 | + /** |
|
30 | + * What capability is required to access this page. |
|
31 | + * |
|
32 | + * @since 4.4.0 |
|
33 | + * @var string |
|
34 | + */ |
|
35 | + protected $capability = 'administrator'; |
|
36 | + |
|
37 | + /** |
|
38 | + * set to TRUE if site is currently in maintenance mode level 2 |
|
39 | + * |
|
40 | + * @var bool |
|
41 | + */ |
|
42 | + protected $maintenance_mode = false; |
|
43 | + |
|
44 | + /** |
|
45 | + * Menu maps can define a parent slug that gets used instead of the main parent slug for the menu when |
|
46 | + * EE_Maintenance_Mode::level_2_complete_maintenance is active. |
|
47 | + * |
|
48 | + * @var string |
|
49 | + */ |
|
50 | + public $maintenance_mode_parent = ''; |
|
51 | + |
|
52 | + /** |
|
53 | + * The callback for displaying the page that the menu references. |
|
54 | + * |
|
55 | + * @since 4.4.0 |
|
56 | + * @var string |
|
57 | + */ |
|
58 | + protected $menu_callback; |
|
59 | + |
|
60 | + /** |
|
61 | + * The EE specific group this menu item belongs in (group slug). |
|
62 | + * |
|
63 | + * @since 4.4.0 |
|
64 | + * @var string |
|
65 | + */ |
|
66 | + protected $menu_group; |
|
67 | + |
|
68 | + /** |
|
69 | + * The label for the menu item. (What shows up in the actual menu). |
|
70 | + * |
|
71 | + * @since 4.4.0 |
|
72 | + * @var string |
|
73 | + */ |
|
74 | + protected $menu_label; |
|
75 | + |
|
76 | + /** |
|
77 | + * What order this item should be in the menu. |
|
78 | + * |
|
79 | + * @since 4.4.0 |
|
80 | + * @var int |
|
81 | + */ |
|
82 | + protected $menu_order; |
|
83 | + |
|
84 | + /** |
|
85 | + * What slug should be used to reference this menu item. |
|
86 | + * |
|
87 | + * @since 4.4.0 |
|
88 | + * @var string |
|
89 | + */ |
|
90 | + protected $menu_slug; |
|
91 | + |
|
92 | + /** |
|
93 | + * What menu item is the parent of this menu item. |
|
94 | + * |
|
95 | + * @since 4.4.0 |
|
96 | + * @var string |
|
97 | + */ |
|
98 | + protected $parent_slug; |
|
99 | + |
|
100 | + /** |
|
101 | + * set to TRUE once menu item has been added to generated menu |
|
102 | + * |
|
103 | + * @var bool |
|
104 | + */ |
|
105 | + protected $registered = false; |
|
106 | + |
|
107 | + /** |
|
108 | + * Whether this item is displayed in the menu or not. |
|
109 | + * Sometimes an EE Admin Page needs to register itself but is not accessible via the WordPress |
|
110 | + * admin menu. |
|
111 | + * |
|
112 | + * @since 4.4.0 |
|
113 | + * @var int |
|
114 | + */ |
|
115 | + protected $show_on_menu = self::DISPLAY_BLOG_ONLY; |
|
116 | + |
|
117 | + /** |
|
118 | + * The title for the menu page. (the page the menu links to) |
|
119 | + * |
|
120 | + * @since 4.4.0 |
|
121 | + * @var string |
|
122 | + */ |
|
123 | + protected $title; |
|
124 | + |
|
125 | + |
|
126 | + /** |
|
127 | + * @param array $menu_args An array of arguments used to setup the menu properties on construct. |
|
128 | + * @param array $required An array of keys that should be in the $menu_args, |
|
129 | + * this is used to validate that the items that should be defined are present. |
|
130 | + * @return void |
|
131 | + * @throws DomainException |
|
132 | + * @throws InvalidArgumentException |
|
133 | + * @throws OutOfBoundsException |
|
134 | + */ |
|
135 | + public function __construct(array $menu_args, array $required) |
|
136 | + { |
|
137 | + // we don't want this coupling anymore >:( |
|
138 | + unset($menu_args['admin_init_page'], $required['admin_init_page']); |
|
139 | + $this->maintenance_mode = EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance; |
|
140 | + |
|
141 | + // filter all args before processing so plugins can manipulate various settings for menus. |
|
142 | + $menu_args = apply_filters( |
|
143 | + 'FHEE__EE_Admin_Page_Menu_Map__construct__menu_args', |
|
144 | + $menu_args, |
|
145 | + $required, |
|
146 | + get_class($this) |
|
147 | + ); |
|
148 | + |
|
149 | + $this->verifyRequired($menu_args, $required); |
|
150 | + $this->setProperties($menu_args); |
|
151 | + } |
|
152 | + |
|
153 | + |
|
154 | + /** |
|
155 | + * This method should define how the menu page gets added for this particular item |
|
156 | + * and go ahead and define it. Note that child classes MUST also return the result of |
|
157 | + * the function used to register the WordPress admin page (the wp_page_slug string) |
|
158 | + * |
|
159 | + * @return string wp_page_slug. |
|
160 | + * @since 4.4.0 |
|
161 | + */ |
|
162 | + abstract protected function registerMenuItem(): string; |
|
163 | + |
|
164 | + |
|
165 | + /** |
|
166 | + * Called by client code to use this menu map for registering a WordPress admin page |
|
167 | + * |
|
168 | + * @param boolean $network_admin whether this is being added to the network admin page or not |
|
169 | + * @since 4.4.0 |
|
170 | + */ |
|
171 | + public function registerAdminMenuItem(bool $network_admin = false): string |
|
172 | + { |
|
173 | + $this->registered = true; |
|
174 | + return $this->displayOnBlogAndNetworkAdmin() |
|
175 | + || $this->displayOnBlogAdmin($network_admin) |
|
176 | + || $this->displayOnNetworkAdmin($network_admin) |
|
177 | + ? $this->registerMenuItem() |
|
178 | + : ''; |
|
179 | + } |
|
180 | + |
|
181 | + |
|
182 | + /** |
|
183 | + * @param array $menu_args |
|
184 | + * @param array $required |
|
185 | + * @throws DomainException |
|
186 | + */ |
|
187 | + private function verifyRequired(array $menu_args, array $required) |
|
188 | + { |
|
189 | + // verify that required keys are present in the incoming array. |
|
190 | + $missing = array_diff($required, array_keys($menu_args)); |
|
191 | + |
|
192 | + if (! empty($missing)) { |
|
193 | + throw new DomainException( |
|
194 | + sprintf( |
|
195 | + esc_html__( |
|
196 | + '%1$s is missing some expected keys in the argument array. The following keys are missing: %2$s', |
|
197 | + 'event_espresso' |
|
198 | + ), |
|
199 | + get_class($this), |
|
200 | + implode(', ', $missing) |
|
201 | + ) |
|
202 | + ); |
|
203 | + } |
|
204 | + |
|
205 | + if ( |
|
206 | + in_array('admin_init_page', $required, true) |
|
207 | + && ! (isset($menu_args['admin_init_page']) && $menu_args['admin_init_page'] instanceof EE_Admin_Page_Init) |
|
208 | + ) { |
|
209 | + throw new InvalidArgumentException( |
|
210 | + sprintf( |
|
211 | + esc_html__( |
|
212 | + 'The value for the "admin_init_page" argument must be an instance of an EE_Admin_Page_Init object. Instead %s was given as the value.', |
|
213 | + 'event_espresso' |
|
214 | + ), |
|
215 | + print_r($menu_args['admin_init_page'] ?? null, true) |
|
216 | + ) |
|
217 | + ); |
|
218 | + } |
|
219 | + } |
|
220 | + |
|
221 | + |
|
222 | + /** |
|
223 | + * @param array $menu_args |
|
224 | + * @throws InvalidArgumentException |
|
225 | + * @throws OutOfBoundsException |
|
226 | + */ |
|
227 | + private function setProperties(array $menu_args) |
|
228 | + { |
|
229 | + $menu_args += [ |
|
230 | + 'capability' => 'ee_read_ee', |
|
231 | + 'maintenance_mode_parent' => '', |
|
232 | + 'menu_callback' => null, |
|
233 | + 'menu_group' => '', |
|
234 | + 'menu_label' => '', |
|
235 | + 'menu_order' => 100, |
|
236 | + 'menu_slug' => '', |
|
237 | + 'parent_slug' => 'espresso_events', |
|
238 | + 'show_on_menu' => AdminMenuItem::DISPLAY_NONE, |
|
239 | + 'title' => '', |
|
240 | + ]; |
|
241 | + |
|
242 | + $this->setMenuSlug($menu_args['menu_slug']); |
|
243 | + $this->setCapability($menu_args['capability']); |
|
244 | + $this->setMaintenanceModeParent($menu_args['maintenance_mode_parent']); |
|
245 | + $this->setMenuCallback($menu_args['menu_callback']); |
|
246 | + $this->setMenuGroup($menu_args['menu_group']); |
|
247 | + $this->setMenuLabel($menu_args['menu_label']); |
|
248 | + $this->setMenuOrder($menu_args['menu_order']); |
|
249 | + $this->setParentSlug($menu_args['parent_slug']); |
|
250 | + $this->setShowOnMenu($menu_args['show_on_menu']); |
|
251 | + $this->setTitle($menu_args['title']); |
|
252 | + } |
|
253 | + |
|
254 | + |
|
255 | + /** |
|
256 | + * The capability required for this menu to be displayed to the user. |
|
257 | + * |
|
258 | + * @return string |
|
259 | + */ |
|
260 | + public function capability(): string |
|
261 | + { |
|
262 | + return $this->capability; |
|
263 | + } |
|
264 | + |
|
265 | + |
|
266 | + /** |
|
267 | + * @param string $capability |
|
268 | + */ |
|
269 | + public function setCapability(string $capability): void |
|
270 | + { |
|
271 | + $this->capability = $capability; |
|
272 | + // filter capabilities (both static and dynamic) |
|
273 | + $this->capability = apply_filters('FHEE_management_capability', $this->capability, null); |
|
274 | + $this->capability = apply_filters('FHEE_' . $this->menu_slug . '_capability', $this->capability, null); |
|
275 | + } |
|
276 | + |
|
277 | + |
|
278 | + public function currentUserHasAccess(): bool |
|
279 | + { |
|
280 | + return EE_Capabilities::instance()->current_user_can($this->capability(), $this->menuSlug()); |
|
281 | + } |
|
282 | + |
|
283 | + |
|
284 | + /** |
|
285 | + * @param bool $network_admin |
|
286 | + * @return bool |
|
287 | + */ |
|
288 | + public function displayOnBlogAdmin(bool $network_admin): bool |
|
289 | + { |
|
290 | + return ! $network_admin && $this->show_on_menu === AdminMenuItem::DISPLAY_BLOG_ONLY; |
|
291 | + } |
|
292 | + |
|
293 | + |
|
294 | + /** |
|
295 | + * @return bool |
|
296 | + */ |
|
297 | + public function displayOnBlogAndNetworkAdmin(): bool |
|
298 | + { |
|
299 | + return $this->show_on_menu === AdminMenuItem::DISPLAY_BLOG_AND_NETWORK; |
|
300 | + } |
|
301 | + |
|
302 | + |
|
303 | + /** |
|
304 | + * @param bool $network_admin |
|
305 | + * @return bool |
|
306 | + */ |
|
307 | + public function displayOnNetworkAdmin(bool $network_admin): bool |
|
308 | + { |
|
309 | + return $network_admin && $this->show_on_menu === AdminMenuItem::DISPLAY_NETWORK_ONLY; |
|
310 | + } |
|
311 | + |
|
312 | + |
|
313 | + /** |
|
314 | + * parent slug to use when site is in full maintenance mode |
|
315 | + * |
|
316 | + * @return string |
|
317 | + */ |
|
318 | + public function maintenanceModeParent(): string |
|
319 | + { |
|
320 | + return $this->maintenance_mode_parent; |
|
321 | + } |
|
322 | + |
|
323 | + |
|
324 | + /** |
|
325 | + * @param string $maintenance_mode_parent |
|
326 | + */ |
|
327 | + public function setMaintenanceModeParent(string $maintenance_mode_parent): void |
|
328 | + { |
|
329 | + $this->maintenance_mode_parent = $maintenance_mode_parent; |
|
330 | + } |
|
331 | + |
|
332 | + |
|
333 | + /** |
|
334 | + * Optional. The function to be called to output the content for this page. |
|
335 | + * |
|
336 | + * @return callable|null |
|
337 | + */ |
|
338 | + public function menuCallback(): ?callable |
|
339 | + { |
|
340 | + return $this->menu_callback; |
|
341 | + } |
|
342 | + |
|
343 | + |
|
344 | + /** |
|
345 | + * @param callable|null $menu_callback |
|
346 | + */ |
|
347 | + public function setMenuCallback(?callable $menu_callback): void |
|
348 | + { |
|
349 | + $this->menu_callback = $menu_callback; |
|
350 | + } |
|
351 | + |
|
352 | + |
|
353 | + /** |
|
354 | + * Slug for menu group that this menu item will appear under |
|
355 | + * |
|
356 | + * @return string |
|
357 | + */ |
|
358 | + public function menuGroup(): string |
|
359 | + { |
|
360 | + return $this->menu_group; |
|
361 | + } |
|
362 | + |
|
363 | + |
|
364 | + /** |
|
365 | + * @param string $menu_group |
|
366 | + */ |
|
367 | + public function setMenuGroup(string $menu_group): void |
|
368 | + { |
|
369 | + $this->menu_group = $menu_group; |
|
370 | + } |
|
371 | + |
|
372 | + |
|
373 | + /** |
|
374 | + * The text to be used for the menu. |
|
375 | + * |
|
376 | + * @return string |
|
377 | + */ |
|
378 | + public function menuLabel(): string |
|
379 | + { |
|
380 | + return $this->menu_label; |
|
381 | + } |
|
382 | + |
|
383 | + |
|
384 | + /** |
|
385 | + * @param string $menu_label |
|
386 | + */ |
|
387 | + public function setMenuLabel(string $menu_label): void |
|
388 | + { |
|
389 | + $this->menu_label = $menu_label; |
|
390 | + } |
|
391 | + |
|
392 | + |
|
393 | + /** |
|
394 | + * Optional. The position in the menu order this item should appear. |
|
395 | + * |
|
396 | + * @return int |
|
397 | + */ |
|
398 | + public function menuOrder(): int |
|
399 | + { |
|
400 | + return $this->menu_order; |
|
401 | + } |
|
402 | + |
|
403 | + |
|
404 | + /** |
|
405 | + * @param int $menu_order |
|
406 | + */ |
|
407 | + public function setMenuOrder(int $menu_order): void |
|
408 | + { |
|
409 | + $this->menu_order = absint($menu_order); |
|
410 | + } |
|
411 | + |
|
412 | + |
|
413 | + /** |
|
414 | + * The slug name to refer to this menu by. Should be unique for this menu |
|
415 | + * |
|
416 | + * @return string |
|
417 | + */ |
|
418 | + public function menuSlug(): string |
|
419 | + { |
|
420 | + return $this->menu_slug; |
|
421 | + } |
|
422 | + |
|
423 | + |
|
424 | + /** |
|
425 | + * @param string $menu_slug |
|
426 | + */ |
|
427 | + public function setMenuSlug(string $menu_slug): void |
|
428 | + { |
|
429 | + $this->menu_slug = sanitize_key($menu_slug); |
|
430 | + } |
|
431 | + |
|
432 | + |
|
433 | + /** |
|
434 | + * The slug name for the parent menu (or the file name of a standard WordPress admin page). |
|
435 | + * |
|
436 | + * @return string |
|
437 | + */ |
|
438 | + public function parentSlug(): string |
|
439 | + { |
|
440 | + return $this->parent_slug; |
|
441 | + } |
|
442 | + |
|
443 | + |
|
444 | + /** |
|
445 | + * if site is in full maintenance mode, |
|
446 | + * then parent slug will be swapped with the maintenance_mode_parent if that property has been set |
|
447 | + * |
|
448 | + * @param string $parent_slug |
|
449 | + */ |
|
450 | + public function setParentSlug(string $parent_slug): void |
|
451 | + { |
|
452 | + $this->parent_slug = $this->maintenance_mode && $this->maintenance_mode_parent |
|
453 | + ? $this->maintenance_mode_parent |
|
454 | + : $parent_slug; |
|
455 | + } |
|
456 | + |
|
457 | + |
|
458 | + /** |
|
459 | + * returns true if menu item has already been registered with WP core |
|
460 | + * |
|
461 | + * @return bool |
|
462 | + */ |
|
463 | + public function isRegistered(): bool |
|
464 | + { |
|
465 | + return $this->registered; |
|
466 | + } |
|
467 | + |
|
468 | + |
|
469 | + /** |
|
470 | + * returns TRUE if: |
|
471 | + * - site is currently NOT in full site maintenance mode |
|
472 | + * - site IS in full site maintenance mode and menu item has a valid maintenance mode parent |
|
473 | + * |
|
474 | + * @return int |
|
475 | + */ |
|
476 | + public function showOnMaintenanceModeMenu(): int |
|
477 | + { |
|
478 | + return ! $this->maintenance_mode || $this->maintenanceModeParent() !== ''; |
|
479 | + } |
|
480 | + |
|
481 | + |
|
482 | + /** |
|
483 | + * @param int $show_on_menu |
|
484 | + * @throws DomainException |
|
485 | + */ |
|
486 | + public function setShowOnMenu(int $show_on_menu): void |
|
487 | + { |
|
488 | + $valid_menu_options = [ |
|
489 | + AdminMenuItem::DISPLAY_NONE, |
|
490 | + AdminMenuItem::DISPLAY_BLOG_ONLY, |
|
491 | + AdminMenuItem::DISPLAY_BLOG_AND_NETWORK, |
|
492 | + AdminMenuItem::DISPLAY_NETWORK_ONLY, |
|
493 | + ]; |
|
494 | + if (! in_array($show_on_menu, $valid_menu_options, true)) { |
|
495 | + throw new DomainException( |
|
496 | + sprintf( |
|
497 | + esc_html__( |
|
498 | + 'Invalid "ShowOnMenu" option of "%1$s" supplied. You must use one of the AdminMenuItem::DISPLAY_* constants.', |
|
499 | + 'event_espresso' |
|
500 | + ), |
|
501 | + $show_on_menu |
|
502 | + ) |
|
503 | + ); |
|
504 | + } |
|
505 | + $this->show_on_menu = $show_on_menu; |
|
506 | + } |
|
507 | + |
|
508 | + |
|
509 | + /** |
|
510 | + * The text to be displayed in the title tags of the page when the menu is selected |
|
511 | + * |
|
512 | + * @return string |
|
513 | + */ |
|
514 | + public function title(): string |
|
515 | + { |
|
516 | + return $this->title; |
|
517 | + } |
|
518 | + |
|
519 | + |
|
520 | + /** |
|
521 | + * @param string $title |
|
522 | + */ |
|
523 | + public function setTitle(string $title): void |
|
524 | + { |
|
525 | + $this->title = $title; |
|
526 | + } |
|
527 | 527 | } |
@@ -19,7 +19,7 @@ discard block |
||
19 | 19 | |
20 | 20 | public const DISPLAY_NETWORK_ONLY = 3; |
21 | 21 | |
22 | - public const TYPE_MENU_TOP = 'top'; |
|
22 | + public const TYPE_MENU_TOP = 'top'; |
|
23 | 23 | |
24 | 24 | public const TYPE_MENU_GROUP = 'group'; |
25 | 25 | |
@@ -189,7 +189,7 @@ discard block |
||
189 | 189 | // verify that required keys are present in the incoming array. |
190 | 190 | $missing = array_diff($required, array_keys($menu_args)); |
191 | 191 | |
192 | - if (! empty($missing)) { |
|
192 | + if ( ! empty($missing)) { |
|
193 | 193 | throw new DomainException( |
194 | 194 | sprintf( |
195 | 195 | esc_html__( |
@@ -271,7 +271,7 @@ discard block |
||
271 | 271 | $this->capability = $capability; |
272 | 272 | // filter capabilities (both static and dynamic) |
273 | 273 | $this->capability = apply_filters('FHEE_management_capability', $this->capability, null); |
274 | - $this->capability = apply_filters('FHEE_' . $this->menu_slug . '_capability', $this->capability, null); |
|
274 | + $this->capability = apply_filters('FHEE_'.$this->menu_slug.'_capability', $this->capability, null); |
|
275 | 275 | } |
276 | 276 | |
277 | 277 | |
@@ -491,7 +491,7 @@ discard block |
||
491 | 491 | AdminMenuItem::DISPLAY_BLOG_AND_NETWORK, |
492 | 492 | AdminMenuItem::DISPLAY_NETWORK_ONLY, |
493 | 493 | ]; |
494 | - if (! in_array($show_on_menu, $valid_menu_options, true)) { |
|
494 | + if ( ! in_array($show_on_menu, $valid_menu_options, true)) { |
|
495 | 495 | throw new DomainException( |
496 | 496 | sprintf( |
497 | 497 | esc_html__( |
@@ -4,123 +4,123 @@ |
||
4 | 4 | |
5 | 5 | class AdminMenuTopLevel extends AdminMenuItem |
6 | 6 | { |
7 | - /** |
|
8 | - * The page to a icon used for this menu. |
|
9 | - * |
|
10 | - * @since 4.4.0 |
|
11 | - * @see http://codex.wordpress.org/Function_Reference/add_menu_page#Parameters |
|
12 | - * for what can be set for this property. |
|
13 | - * @var string |
|
14 | - */ |
|
15 | - protected $icon_url = ''; |
|
16 | - |
|
17 | - /** |
|
18 | - * What position in the main menu order for the WP admin menu this menu item |
|
19 | - * should show. |
|
20 | - * |
|
21 | - * @since 4.4.0 |
|
22 | - * @see http://codex.wordpress.org/Function_Reference/add_menu_page#Parameters |
|
23 | - * for what can be set for this property. |
|
24 | - * @var integer |
|
25 | - */ |
|
26 | - protected $position = 0; |
|
27 | - |
|
28 | - /** |
|
29 | - * If included int incoming params, then this class will also register a Sub Menu Admin page with a different |
|
30 | - * subtitle than the main menu item. |
|
31 | - * |
|
32 | - * @since 4.4.0 |
|
33 | - * @var string |
|
34 | - */ |
|
35 | - protected $subtitle = ''; |
|
36 | - |
|
37 | - |
|
38 | - public function __construct(array $menu_args) |
|
39 | - { |
|
40 | - $this->setIconUrl($menu_args['icon_url'] ?? ''); |
|
41 | - $this->setPosition($menu_args['position'] ?? 0); |
|
42 | - $this->setSubtitle($menu_args['subtitle'] ?? ''); |
|
43 | - unset($menu_args['icon_url'], $menu_args['position'], $menu_args['subtitle']); |
|
44 | - parent::__construct( |
|
45 | - $menu_args, |
|
46 | - // required args |
|
47 | - [ |
|
48 | - 'menu_label', |
|
49 | - 'menu_slug', |
|
50 | - 'menu_group', |
|
51 | - 'menu_order', |
|
52 | - ] |
|
53 | - ); |
|
54 | - } |
|
55 | - |
|
56 | - |
|
57 | - /** |
|
58 | - * Uses the proper WP utility for registering a menu page for the main WP pages. |
|
59 | - */ |
|
60 | - protected function registerMenuItem(): string |
|
61 | - { |
|
62 | - return add_menu_page( |
|
63 | - $this->title(), |
|
64 | - $this->menuLabel(), |
|
65 | - $this->capability(), |
|
66 | - $this->parentSlug(), |
|
67 | - $this->menuCallback(), |
|
68 | - $this->iconUrl(), |
|
69 | - $this->position() |
|
70 | - ); |
|
71 | - } |
|
72 | - |
|
73 | - |
|
74 | - /** |
|
75 | - * @return string |
|
76 | - */ |
|
77 | - public function iconUrl(): string |
|
78 | - { |
|
79 | - return $this->icon_url; |
|
80 | - } |
|
81 | - |
|
82 | - |
|
83 | - /** |
|
84 | - * @param string $icon_url |
|
85 | - */ |
|
86 | - public function setIconUrl(string $icon_url): void |
|
87 | - { |
|
88 | - $this->icon_url = $icon_url; |
|
89 | - } |
|
90 | - |
|
91 | - |
|
92 | - /** |
|
93 | - * @return int |
|
94 | - */ |
|
95 | - public function position(): int |
|
96 | - { |
|
97 | - return $this->position; |
|
98 | - } |
|
99 | - |
|
100 | - |
|
101 | - /** |
|
102 | - * @param int $position |
|
103 | - */ |
|
104 | - public function setPosition(int $position): void |
|
105 | - { |
|
106 | - $this->position = absint($position); |
|
107 | - } |
|
108 | - |
|
109 | - |
|
110 | - /** |
|
111 | - * @return string |
|
112 | - */ |
|
113 | - public function subtitle(): string |
|
114 | - { |
|
115 | - return $this->subtitle; |
|
116 | - } |
|
117 | - |
|
118 | - |
|
119 | - /** |
|
120 | - * @param string $subtitle |
|
121 | - */ |
|
122 | - public function setSubtitle(string $subtitle): void |
|
123 | - { |
|
124 | - $this->subtitle = $subtitle; |
|
125 | - } |
|
7 | + /** |
|
8 | + * The page to a icon used for this menu. |
|
9 | + * |
|
10 | + * @since 4.4.0 |
|
11 | + * @see http://codex.wordpress.org/Function_Reference/add_menu_page#Parameters |
|
12 | + * for what can be set for this property. |
|
13 | + * @var string |
|
14 | + */ |
|
15 | + protected $icon_url = ''; |
|
16 | + |
|
17 | + /** |
|
18 | + * What position in the main menu order for the WP admin menu this menu item |
|
19 | + * should show. |
|
20 | + * |
|
21 | + * @since 4.4.0 |
|
22 | + * @see http://codex.wordpress.org/Function_Reference/add_menu_page#Parameters |
|
23 | + * for what can be set for this property. |
|
24 | + * @var integer |
|
25 | + */ |
|
26 | + protected $position = 0; |
|
27 | + |
|
28 | + /** |
|
29 | + * If included int incoming params, then this class will also register a Sub Menu Admin page with a different |
|
30 | + * subtitle than the main menu item. |
|
31 | + * |
|
32 | + * @since 4.4.0 |
|
33 | + * @var string |
|
34 | + */ |
|
35 | + protected $subtitle = ''; |
|
36 | + |
|
37 | + |
|
38 | + public function __construct(array $menu_args) |
|
39 | + { |
|
40 | + $this->setIconUrl($menu_args['icon_url'] ?? ''); |
|
41 | + $this->setPosition($menu_args['position'] ?? 0); |
|
42 | + $this->setSubtitle($menu_args['subtitle'] ?? ''); |
|
43 | + unset($menu_args['icon_url'], $menu_args['position'], $menu_args['subtitle']); |
|
44 | + parent::__construct( |
|
45 | + $menu_args, |
|
46 | + // required args |
|
47 | + [ |
|
48 | + 'menu_label', |
|
49 | + 'menu_slug', |
|
50 | + 'menu_group', |
|
51 | + 'menu_order', |
|
52 | + ] |
|
53 | + ); |
|
54 | + } |
|
55 | + |
|
56 | + |
|
57 | + /** |
|
58 | + * Uses the proper WP utility for registering a menu page for the main WP pages. |
|
59 | + */ |
|
60 | + protected function registerMenuItem(): string |
|
61 | + { |
|
62 | + return add_menu_page( |
|
63 | + $this->title(), |
|
64 | + $this->menuLabel(), |
|
65 | + $this->capability(), |
|
66 | + $this->parentSlug(), |
|
67 | + $this->menuCallback(), |
|
68 | + $this->iconUrl(), |
|
69 | + $this->position() |
|
70 | + ); |
|
71 | + } |
|
72 | + |
|
73 | + |
|
74 | + /** |
|
75 | + * @return string |
|
76 | + */ |
|
77 | + public function iconUrl(): string |
|
78 | + { |
|
79 | + return $this->icon_url; |
|
80 | + } |
|
81 | + |
|
82 | + |
|
83 | + /** |
|
84 | + * @param string $icon_url |
|
85 | + */ |
|
86 | + public function setIconUrl(string $icon_url): void |
|
87 | + { |
|
88 | + $this->icon_url = $icon_url; |
|
89 | + } |
|
90 | + |
|
91 | + |
|
92 | + /** |
|
93 | + * @return int |
|
94 | + */ |
|
95 | + public function position(): int |
|
96 | + { |
|
97 | + return $this->position; |
|
98 | + } |
|
99 | + |
|
100 | + |
|
101 | + /** |
|
102 | + * @param int $position |
|
103 | + */ |
|
104 | + public function setPosition(int $position): void |
|
105 | + { |
|
106 | + $this->position = absint($position); |
|
107 | + } |
|
108 | + |
|
109 | + |
|
110 | + /** |
|
111 | + * @return string |
|
112 | + */ |
|
113 | + public function subtitle(): string |
|
114 | + { |
|
115 | + return $this->subtitle; |
|
116 | + } |
|
117 | + |
|
118 | + |
|
119 | + /** |
|
120 | + * @param string $subtitle |
|
121 | + */ |
|
122 | + public function setSubtitle(string $subtitle): void |
|
123 | + { |
|
124 | + $this->subtitle = $subtitle; |
|
125 | + } |
|
126 | 126 | } |
@@ -16,64 +16,64 @@ |
||
16 | 16 | */ |
17 | 17 | class AdminMenuGroup extends AdminMenuItem |
18 | 18 | { |
19 | - /** |
|
20 | - * @var AdminMenuItem[] |
|
21 | - */ |
|
22 | - private $menu_items = []; |
|
19 | + /** |
|
20 | + * @var AdminMenuItem[] |
|
21 | + */ |
|
22 | + private $menu_items = []; |
|
23 | 23 | |
24 | 24 | |
25 | 25 | |
26 | - public function __construct(array $menu_args) |
|
27 | - { |
|
28 | - parent::__construct( |
|
29 | - $menu_args, |
|
30 | - // required args |
|
31 | - [ |
|
32 | - 'menu_label', |
|
33 | - 'menu_slug', |
|
34 | - 'menu_order', |
|
35 | - 'parent_slug' |
|
36 | - ] |
|
37 | - ); |
|
38 | - } |
|
26 | + public function __construct(array $menu_args) |
|
27 | + { |
|
28 | + parent::__construct( |
|
29 | + $menu_args, |
|
30 | + // required args |
|
31 | + [ |
|
32 | + 'menu_label', |
|
33 | + 'menu_slug', |
|
34 | + 'menu_order', |
|
35 | + 'parent_slug' |
|
36 | + ] |
|
37 | + ); |
|
38 | + } |
|
39 | 39 | |
40 | 40 | |
41 | - public function addMenuItem(AdminMenuItem $menu_item): void |
|
42 | - { |
|
43 | - $this->menu_items[ $menu_item->menuSlug() ] = $menu_item; |
|
44 | - } |
|
41 | + public function addMenuItem(AdminMenuItem $menu_item): void |
|
42 | + { |
|
43 | + $this->menu_items[ $menu_item->menuSlug() ] = $menu_item; |
|
44 | + } |
|
45 | 45 | |
46 | - public function getMenuItems(): array |
|
47 | - { |
|
48 | - return $this->menu_items; |
|
49 | - } |
|
46 | + public function getMenuItems(): array |
|
47 | + { |
|
48 | + return $this->menu_items; |
|
49 | + } |
|
50 | 50 | |
51 | - public function hasNoMenuItems(): bool |
|
52 | - { |
|
53 | - return empty($this->menu_items); |
|
54 | - } |
|
51 | + public function hasNoMenuItems(): bool |
|
52 | + { |
|
53 | + return empty($this->menu_items); |
|
54 | + } |
|
55 | 55 | |
56 | - public function setMenuItems(array $menu_items): void |
|
57 | - { |
|
58 | - $this->menu_items = $menu_items; |
|
59 | - } |
|
56 | + public function setMenuItems(array $menu_items): void |
|
57 | + { |
|
58 | + $this->menu_items = $menu_items; |
|
59 | + } |
|
60 | 60 | |
61 | 61 | |
62 | - protected function registerMenuItem(): string |
|
63 | - { |
|
64 | - return add_submenu_page( |
|
65 | - $this->parentSlug(), |
|
66 | - $this->menuLabel(), |
|
67 | - $this->groupLink(), |
|
68 | - $this->capability(), |
|
69 | - $this->menuSlug(), |
|
70 | - '__return_false' |
|
71 | - ); |
|
72 | - } |
|
62 | + protected function registerMenuItem(): string |
|
63 | + { |
|
64 | + return add_submenu_page( |
|
65 | + $this->parentSlug(), |
|
66 | + $this->menuLabel(), |
|
67 | + $this->groupLink(), |
|
68 | + $this->capability(), |
|
69 | + $this->menuSlug(), |
|
70 | + '__return_false' |
|
71 | + ); |
|
72 | + } |
|
73 | 73 | |
74 | 74 | |
75 | - protected function groupLink(): string |
|
76 | - { |
|
77 | - return '<span class="ee_menu_group" onclick="return false;">' . $this->menuLabel() . '</span>'; |
|
78 | - } |
|
75 | + protected function groupLink(): string |
|
76 | + { |
|
77 | + return '<span class="ee_menu_group" onclick="return false;">' . $this->menuLabel() . '</span>'; |
|
78 | + } |
|
79 | 79 | } |
@@ -40,7 +40,7 @@ discard block |
||
40 | 40 | |
41 | 41 | public function addMenuItem(AdminMenuItem $menu_item): void |
42 | 42 | { |
43 | - $this->menu_items[ $menu_item->menuSlug() ] = $menu_item; |
|
43 | + $this->menu_items[$menu_item->menuSlug()] = $menu_item; |
|
44 | 44 | } |
45 | 45 | |
46 | 46 | public function getMenuItems(): array |
@@ -74,6 +74,6 @@ discard block |
||
74 | 74 | |
75 | 75 | protected function groupLink(): string |
76 | 76 | { |
77 | - return '<span class="ee_menu_group" onclick="return false;">' . $this->menuLabel() . '</span>'; |
|
77 | + return '<span class="ee_menu_group" onclick="return false;">'.$this->menuLabel().'</span>'; |
|
78 | 78 | } |
79 | 79 | } |
@@ -17,48 +17,48 @@ |
||
17 | 17 | */ |
18 | 18 | class ActivationRequests extends PrimaryRoute |
19 | 19 | { |
20 | - /** |
|
21 | - * returns true if the current request matches this route |
|
22 | - * |
|
23 | - * @return bool |
|
24 | - * @since $VID:$ |
|
25 | - */ |
|
26 | - public function matchesCurrentRequest(): bool |
|
27 | - { |
|
28 | - return $this->request->isActivation(); |
|
29 | - } |
|
20 | + /** |
|
21 | + * returns true if the current request matches this route |
|
22 | + * |
|
23 | + * @return bool |
|
24 | + * @since $VID:$ |
|
25 | + */ |
|
26 | + public function matchesCurrentRequest(): bool |
|
27 | + { |
|
28 | + return $this->request->isActivation(); |
|
29 | + } |
|
30 | 30 | |
31 | 31 | |
32 | - /** |
|
33 | - * @since $VID:$ |
|
34 | - */ |
|
35 | - protected function registerDependencies() |
|
36 | - { |
|
37 | - $admin_dependencies = ['EE_Admin_Config' => EE_Dependency_Map::load_from_cache] + Route::$default_dependencies; |
|
38 | - $this->dependency_map->registerDependencies( |
|
39 | - 'EventEspresso\core\domain\entities\routing\handlers\admin\AdminRoute', |
|
40 | - $admin_dependencies |
|
41 | - ); |
|
42 | - $this->dependency_map->registerDependencies( |
|
43 | - 'EventEspresso\core\domain\entities\routing\handlers\admin\PueRequests', |
|
44 | - Route::$default_dependencies |
|
45 | - ); |
|
46 | - $this->dependency_map->registerDependencies( |
|
47 | - 'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressPluginsPage', |
|
48 | - $admin_dependencies |
|
49 | - ); |
|
50 | - } |
|
32 | + /** |
|
33 | + * @since $VID:$ |
|
34 | + */ |
|
35 | + protected function registerDependencies() |
|
36 | + { |
|
37 | + $admin_dependencies = ['EE_Admin_Config' => EE_Dependency_Map::load_from_cache] + Route::$default_dependencies; |
|
38 | + $this->dependency_map->registerDependencies( |
|
39 | + 'EventEspresso\core\domain\entities\routing\handlers\admin\AdminRoute', |
|
40 | + $admin_dependencies |
|
41 | + ); |
|
42 | + $this->dependency_map->registerDependencies( |
|
43 | + 'EventEspresso\core\domain\entities\routing\handlers\admin\PueRequests', |
|
44 | + Route::$default_dependencies |
|
45 | + ); |
|
46 | + $this->dependency_map->registerDependencies( |
|
47 | + 'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressPluginsPage', |
|
48 | + $admin_dependencies |
|
49 | + ); |
|
50 | + } |
|
51 | 51 | |
52 | 52 | |
53 | - /** |
|
54 | - * implements logic required to run during request |
|
55 | - * |
|
56 | - * @return bool |
|
57 | - * @since $VID:$ |
|
58 | - */ |
|
59 | - protected function requestHandler(): bool |
|
60 | - { |
|
61 | - $this->setRouteRequestType(PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION); |
|
62 | - return true; |
|
63 | - } |
|
53 | + /** |
|
54 | + * implements logic required to run during request |
|
55 | + * |
|
56 | + * @return bool |
|
57 | + * @since $VID:$ |
|
58 | + */ |
|
59 | + protected function requestHandler(): bool |
|
60 | + { |
|
61 | + $this->setRouteRequestType(PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION); |
|
62 | + return true; |
|
63 | + } |
|
64 | 64 | } |