PluginProbe ʕ •ᴥ•ʔ
Image Widget / 4.2
Image Widget v4.2
trunk 1.0 2.0 2.1 2.2 2.2.1 2.2.2 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.2 3.2.1 3.2.10 3.2.11 3.2.2 3.2.3 3.2.4 3.2.5 3.2.7 3.2.8 3.2.9 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 4.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.0.9 4.1 4.1.1 4.1.2 4.2 4.2.1 4.2.2 4.3 4.3.1 4.4 4.4.1 4.4.11 4.4.12 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9
image-widget / freemius / includes / managers / class-fs-admin-menu-manager.php
image-widget / freemius / includes / managers Last commit date
class-fs-admin-menu-manager.php 10 years ago class-fs-admin-notice-manager.php 10 years ago class-fs-key-value-storage.php 10 years ago class-fs-license-manager.php 10 years ago class-fs-option-manager.php 10 years ago class-fs-plan-manager.php 10 years ago class-fs-plugin-manager.php 10 years ago
class-fs-admin-menu-manager.php
531 lines
1 <?php
2 /**
3 * @package Freemius
4 * @copyright Copyright (c) 2015, Freemius, Inc.
5 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
6 * @since 1.1.3
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 class FS_Admin_Menu_Manager {
14
15 #region Properties
16
17 /**
18 * @var string
19 */
20 protected $_plugin_slug;
21
22 /**
23 * @since 1.0.6
24 *
25 * @var string
26 */
27 private $_menu_slug;
28 /**
29 * @since 1.1.3
30 *
31 * @var string
32 */
33 private $_parent_slug;
34 /**
35 * @since 1.1.3
36 *
37 * @var string
38 */
39 private $_parent_type;
40 /**
41 * @since 1.1.3
42 *
43 * @var string
44 */
45 private $_type;
46 /**
47 * @since 1.1.3
48 *
49 * @var bool
50 */
51 private $_is_top_level;
52 /**
53 * @since 1.1.3
54 *
55 * @var bool
56 */
57 private $_is_override_exact;
58 /**
59 * @since 1.1.3
60 *
61 * @var string[]bool
62 */
63 private $_default_submenu_items;
64 /**
65 * @since 1.1.3
66 *
67 * @var string
68 */
69 private $_first_time_path;
70
71 #endregion Properties
72
73 /**
74 * @var FS_Logger
75 */
76 protected $_logger;
77
78 #region Singleton
79
80 /**
81 * @var FS_Admin_Menu_Manager[]
82 */
83 private static $_instances = array();
84
85 /**
86 * @param string $plugin_slug
87 *
88 * @return FS_Admin_Notice_Manager
89 */
90 static function instance( $plugin_slug ) {
91 if ( ! isset( self::$_instances[ $plugin_slug ] ) ) {
92 self::$_instances[ $plugin_slug ] = new FS_Admin_Menu_Manager( $plugin_slug );
93 }
94
95 return self::$_instances[ $plugin_slug ];
96 }
97
98 protected function __construct( $plugin_slug ) {
99 $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $plugin_slug . '_admin_menu', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
100
101 $this->_plugin_slug = $plugin_slug;
102 }
103
104 #endregion Singleton
105
106 #region Helpers
107
108 private function get_option( &$options, $key, $default = false ) {
109 return ! empty( $options[ $key ] ) ? $options[ $key ] : $default;
110 }
111
112 private function get_bool_option( &$options, $key, $default = false ) {
113 return isset( $options[ $key ] ) && is_bool( $options[ $key ] ) ? $options[ $key ] : $default;
114 }
115
116 #endregion Helpers
117
118 /**
119 * @param array $menu
120 * @param bool $is_addon
121 */
122 function init( $menu, $is_addon = false ) {
123 $this->_menu_slug = $menu['slug'];
124
125 $this->_default_submenu_items = array();
126 // @deprecated
127 $this->_type = 'page';
128 $this->_is_top_level = true;
129 $this->_is_override_exact = false;
130 $this->_parent_slug = false;
131 // @deprecated
132 $this->_parent_type = 'page';
133
134 if ( ! $is_addon && isset( $menu ) ) {
135 $this->_default_submenu_items = array(
136 'contact' => $this->get_bool_option( $menu, 'contact', true ),
137 'support' => $this->get_bool_option( $menu, 'support', true ),
138 'account' => $this->get_bool_option( $menu, 'account', true ),
139 'pricing' => $this->get_bool_option( $menu, 'pricing', true ),
140 'addons' => $this->get_bool_option( $menu, 'addons', true ),
141 );
142
143 // @deprecated
144 $this->_type = $this->get_option( $menu, 'type', 'page' );
145 $this->_is_override_exact = $this->get_bool_option( $menu, 'override_exact' );
146
147 if ( isset( $menu['parent'] ) ) {
148 $this->_parent_slug = $this->get_option( $menu['parent'], 'slug' );
149 // @deprecated
150 $this->_parent_type = $this->get_option( $menu['parent'], 'type', 'page' );
151
152 // If parent's slug is different, then it's NOT a top level menu item.
153 $this->_is_top_level = ( $this->_parent_slug === $this->_menu_slug );
154 } else {
155 /**
156 * If no parent then top level if:
157 * - Has custom admin menu ('page')
158 * - CPT menu type ('cpt')
159 */
160 // $this->_is_top_level = in_array( $this->_type, array(
161 // 'cpt',
162 // 'page'
163 // ) );
164 }
165
166 $this->_first_time_path = $this->get_option( $menu, 'first-path', false );
167 if ( ! empty( $this->_first_time_path ) && is_string( $this->_first_time_path ) ) {
168 $this->_first_time_path = admin_url( $this->_first_time_path, 'admin' );
169 }
170 }
171 }
172
173 /**
174 * Check if top level menu.
175 *
176 * @author Vova Feldman (@svovaf)
177 * @since 1.1.3
178 *
179 * @return bool False if submenu item.
180 */
181 function is_top_level() {
182 return $this->_is_top_level;
183 }
184
185 /**
186 * Check if the page should be override on exact URL match.
187 *
188 * @author Vova Feldman (@svovaf)
189 * @since 1.1.3
190 *
191 * @return bool False if submenu item.
192 */
193 function is_override_exact() {
194 return $this->_is_override_exact;
195 }
196
197
198 /**
199 * Get the path of the page the user should be forwarded to after first activation.
200 *
201 * @author Vova Feldman (@svovaf)
202 * @since 1.1.3
203 *
204 * @return string
205 */
206 function get_first_time_path() {
207 return $this->_first_time_path;
208 }
209
210 /**
211 * Check if plugin's menu item is part of a custom top level menu.
212 *
213 * @author Vova Feldman (@svovaf)
214 * @since 1.1.3
215 *
216 * @return bool
217 */
218 function has_custom_parent() {
219 return ! $this->_is_top_level && is_string( $this->_parent_slug );
220 }
221
222 /**
223 * @author Vova Feldman (@svovaf)
224 * @since 1.1.3
225 *
226 * @return string
227 */
228 // function slug(){
229 // return $this->_menu_slug;
230 // }
231
232 /**
233 * @author Vova Feldman (@svovaf)
234 * @since 1.1.3
235 *
236 * @param string $id
237 * @param bool $default
238 *
239 * @return bool
240 */
241 function is_submenu_item_visible( $id, $default = true ) {
242 return $this->get_bool_option( $this->_default_submenu_items, $id, $default );
243 }
244
245 /**
246 * Calculates admin settings menu slug.
247 * If plugin's menu slug is a file (e.g. CPT), uses plugin's slug as the menu slug.
248 *
249 * @author Vova Feldman (@svovaf)
250 * @since 1.1.3
251 *
252 * @param string $page
253 *
254 * @return string
255 */
256 function get_slug( $page = '' ) {
257 return ( ( false === strpos( $this->_menu_slug, '.php?' ) ) ?
258 $this->_menu_slug :
259 $this->_plugin_slug ) . ( empty( $page ) ? '' : ( '-' . $page ) );
260 }
261
262 /**
263 * @author Vova Feldman (@svovaf)
264 * @since 1.1.3
265 *
266 * @return string
267 */
268 function get_parent_slug() {
269 return $this->_parent_slug;
270 }
271
272 /**
273 * @author Vova Feldman (@svovaf)
274 * @since 1.1.3
275 *
276 * @return string
277 */
278 function get_type() {
279 return $this->_type;
280 }
281
282 /**
283 * @author Vova Feldman (@svovaf)
284 * @since 1.1.3
285 *
286 * @return bool
287 */
288 function is_cpt() {
289 return ( 0 === strpos( $this->_menu_slug, 'edit.php?post_type=' ) ||
290 // Back compatibility.
291 'cpt' === $this->_type
292 );
293 }
294
295 /**
296 * @author Vova Feldman (@svovaf)
297 * @since 1.1.3
298 *
299 * @return string
300 */
301 function get_parent_type() {
302 return $this->_parent_type;
303 }
304
305 /**
306 * @author Vova Feldman (@svovaf)
307 * @since 1.1.3
308 *
309 * @return string
310 */
311 function get_raw_slug() {
312 return $this->_menu_slug;
313 }
314
315 /**
316 * Get plugin's original menu slug.
317 *
318 * @author Vova Feldman (@svovaf)
319 * @since 1.1.3
320 *
321 * @return string
322 */
323 function get_original_menu_slug() {
324 if ( 'cpt' === $this->_type ) {
325 return add_query_arg( array(
326 'post_type' => $this->_menu_slug
327 ), 'edit.php' );
328 }
329
330 if ( false === strpos( $this->_menu_slug, '.php?' ) ) {
331 return $this->_menu_slug;
332 } else {
333 return $this->_plugin_slug;
334 }
335 }
336
337 /**
338 * @author Vova Feldman (@svovaf)
339 * @since 1.1.3
340 *
341 * @return string
342 */
343 function get_top_level_menu_slug() {
344 return $this->has_custom_parent() ?
345 $this->get_parent_slug() :
346 $this->get_raw_slug();
347 }
348
349 /**
350 * Is user on plugin's admin activation page.
351 *
352 * @author Vova Feldman (@svovaf)
353 * @since 1.0.8
354 *
355 * @return bool
356 */
357 function is_activation_page() {
358 return isset( $_GET['page'] ) &&
359 ( ( strtolower( $this->_menu_slug ) === strtolower( $_GET['page'] ) ) ||
360 ( strtolower( $this->_plugin_slug ) === strtolower( $_GET['page'] ) ) );
361 }
362
363 #region Submenu Override
364
365 /**
366 * Override submenu's action.
367 *
368 * @author Vova Feldman (@svovaf)
369 * @since 1.1.0
370 *
371 * @param string $parent_slug
372 * @param string $menu_slug
373 * @param callable $function
374 *
375 * @return false|string If submenu exist, will return the hook name.
376 */
377 function override_submenu_action( $parent_slug, $menu_slug, $function ) {
378 global $submenu;
379
380 $menu_slug = plugin_basename( $menu_slug );
381 $parent_slug = plugin_basename( $parent_slug );
382
383 if ( ! isset( $submenu[ $parent_slug ] ) ) {
384 // Parent menu not exist.
385 return false;
386 }
387
388 $found_submenu_item = false;
389 foreach ( $submenu[ $parent_slug ] as $submenu_item ) {
390 if ( $menu_slug === $submenu_item[2] ) {
391 $found_submenu_item = $submenu_item;
392 break;
393 }
394 }
395
396 if ( false === $found_submenu_item ) {
397 // Submenu item not found.
398 return false;
399 }
400
401 // Remove current function.
402 $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug );
403 remove_all_actions( $hookname );
404
405 // Attach new action.
406 add_action( $hookname, $function );
407
408 return $hookname;
409 }
410
411 #endregion Submenu Override
412
413 #region Top level menu Override
414
415 /**
416 * Find plugin's admin dashboard main menu item.
417 *
418 * @author Vova Feldman (@svovaf)
419 * @since 1.0.2
420 *
421 * @return string[]|false
422 */
423 private function find_top_level_menu() {
424 global $menu;
425
426 $position = - 1;
427 $found_menu = false;
428
429 $menu_slug = $this->get_raw_slug();
430
431 $hook_name = get_plugin_page_hookname( $menu_slug, '' );
432 foreach ( $menu as $pos => $m ) {
433 if ( $menu_slug === $m[2] ) {
434 $position = $pos;
435 $found_menu = $m;
436 break;
437 }
438 }
439
440 if ( false === $found_menu ) {
441 return false;
442 }
443
444 return array(
445 'menu' => $found_menu,
446 'position' => $position,
447 'hook_name' => $hook_name
448 );
449 }
450
451 /**
452 * Remove all sub-menu items.
453 *
454 * @author Vova Feldman (@svovaf)
455 * @since 1.0.7
456 *
457 * @return bool If submenu with plugin's menu slug was found.
458 */
459 private function remove_all_submenu_items() {
460 global $submenu;
461
462 $menu_slug = $this->get_raw_slug();
463
464 if ( ! isset( $submenu[ $menu_slug ] ) ) {
465 return false;
466 }
467
468 $submenu[ $menu_slug ] = array();
469
470 return true;
471 }
472
473 /**
474 *
475 * @author Vova Feldman (@svovaf)
476 * @since 1.0.9
477 *
478 * @return array[string]mixed
479 */
480 function remove_menu_item() {
481 $this->_logger->entrance();
482
483 // Find main menu item.
484 $menu = $this->find_top_level_menu();
485
486 if ( false === $menu ) {
487 return false;
488 }
489
490 // Remove it with its actions.
491 remove_all_actions( $menu['hook_name'] );
492
493 // Remove all submenu items.
494 $this->remove_all_submenu_items();
495
496 return $menu;
497 }
498
499 /**
500 *
501 * @author Vova Feldman (@svovaf)
502 * @since 1.1.4
503 *
504 * @param callable $function
505 *
506 * @return array[string]mixed
507 */
508 function override_menu_item( $function ) {
509 $menu = $this->remove_menu_item();
510
511 if ( false === $menu ) {
512 return false;
513 }
514
515 // Override menu action.
516 $hook = add_menu_page(
517 $menu['menu'][3],
518 $menu['menu'][0],
519 'manage_options',
520 $this->get_slug(),
521 $function,
522 $menu['menu'][6],
523 $menu['position']
524 );
525
526
527 return $hook;
528 }
529
530 #endregion Top level menu Override
531 }