GravityView  2.17
The best, easiest way to display Gravity Forms entries on your website.
AdminMenu.php
Go to the documentation of this file.
1 <?php
2 /**
3  * @license GPL-2.0-or-later
4  *
5  * Modified by gravityview on 13-January-2023 using Strauss.
6  * @see https://github.com/BrianHenryIE/strauss
7  */
8 
10 
11 /**
12  * This class is responsible for adding a GravityKit menu and submenu items to the WP admin panel.
13  */
14 class AdminMenu {
15  const WP_ADMIN_MENU_SLUG = '_gk_admin_menu';
16 
17  /**
18  * @since 1.0.0
19  *
20  * @var AdminMenu Class instance.
21  */
22  private static $_instance;
23 
24  /**
25  * @since 1.0.0
26  *
27  * @var array Submenus of the top menu.
28  */
29  private static $_submenus = [
30  'top' => [],
31  'center' => [],
32  'bottom' => [],
33  ];
34 
35  /**
36  * Returns class instance.
37  *
38  * @since 1.0.0
39  *
40  * @return AdminMenu
41  */
42  public static function get_instance() {
43  if ( is_null( self::$_instance ) ) {
44  self::$_instance = new self();
45  }
46 
47  return self::$_instance;
48  }
49 
50  /**
51  * Initializes the class.
52  *
53  * @since 1.0.0
54  *
55  * @return void
56  */
57  public function init() {
58  static $initialized;
59 
60  if ( $initialized ) {
61  return;
62  }
63 
64  add_action( 'admin_menu', [ $this, 'add_admin_menu' ] );
65  add_action( 'network_admin_menu', [ $this, 'add_admin_menu' ] );
66 
67  $initialized = true;
68  }
69 
70  /**
71  * Configures GravityKit top-level menu and submenu items in WP admin.
72  *
73  * @since 1.0.0
74  *
75  * @global array $menu
76  * @global array $submenu
77  *
78  * @retun void
79  */
80  public function add_admin_menu() {
81  global $menu, $submenu;
82 
83  // Make sure we're not adding a duplicate top-level menu.
84  if ( strpos( json_encode( $menu ?: [] ), self::WP_ADMIN_MENU_SLUG ) !== false ) {
85  return;
86  }
87 
88  $_get_divider = function () {
89  // Divider is added to the menu title; because WP wraps it in <a>, we need to first close the tag, then add the divider.
90  return '</a> <hr style="margin: 10px 12px; border: none; height: 1px; background-color: hsla( 0, 0%, 100%, .2 );" tabindex="-1" />';
91  };
92 
93  $total_badge_count = 0;
94  $submenus = self::get_submenus();
95  $filtered_submenus = [];
96 
97  // Filter submenus by removing those for which the user doesn't have the required capability.
98  foreach ( $submenus as $submenu_data ) {
99  if ( empty( $submenu_data ) ) {
100  continue;
101  }
102 
103  foreach ( array_values( $submenu_data ) as $index => $submenu_item ) {
104  if ( ! current_user_can( $submenu_item['capability'] ) ) {
105  return;
106  }
107 
108  /**
109  * @filter `gk/foundation/admin-menu/submenu/{$submenu_id}/counter` Displays counter next to the submenu title.
110  *
111  * @since 1.0.0
112  *
113  * @param int $badge_count
114  */
115  $badge_count = (int) apply_filters( "gk/foundation/admin-menu/submenu/{$submenu_item['id']}/counter", 0 );
116 
117  if ( $badge_count > 0 ) {
118  $total_badge_count += $badge_count;
119  }
120 
121  $filtered_submenu = [
122  'slug' => self::WP_ADMIN_MENU_SLUG,
123  'page_title' => $submenu_item['page_title'],
124  'menu_title' => $submenu_item['menu_title'] . $this->get_badge_counter_markup( $submenu_item['id'], $badge_count ),
125  'capability' => $submenu_item['capability'],
126  'id' => $submenu_item['id'],
127  'callback' => $submenu_item['callback']
128  ];
129 
130  if ( $index === count( $submenu_data ) - 1 ) {
131  $filtered_submenu['divider'] = $_get_divider();
132  }
133 
134  $filtered_submenus[] = $filtered_submenu;
135  }
136  }
137 
138  if ( empty( $filtered_submenus ) ) {
139  return;
140  }
141 
142  // Add top-level menu.
143  $page_title = esc_html__( 'GravityKit', 'gk-gravityview' );
144  $menu_title = esc_html__( 'GravityKit', 'gk-gravityview' );
145 
146  /**
147  * Controls the position of the top-level GravityKit admin menu.
148  *
149  * @filter gk/foundation/admin-menu/position
150  *
151  * @since 1.0.0
152  *
153  * @param float $menu_position Default: value of `gform_menu_position` filter + 0.001.
154  */
155  $menu_position = apply_filters( 'gk/foundation/admin-menu/position', (float) apply_filters( 'gform_menu_position', '16.9' ) + .0001 );
156 
157  add_menu_page(
158  $page_title,
159  $menu_title,
160  $filtered_submenus[0]['capability'], // Use the capability of the first submenu (all submenus have a capability that the user has).
161  self::WP_ADMIN_MENU_SLUG,
162  null,
163  'data:image/svg+xml;base64,' . base64_encode( '<svg id="Artwork" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path fill="#a7aaad" class="st0" d="M128 0C57.3 0 0 57.3 0 128s57.3 128 128 128 128-57.3 128-128S198.7 0 128 0zm0 243.2c-63.6 0-115.2-51.6-115.2-115.2S64.4 12.8 128 12.8 243.2 64.4 243.2 128 191.6 243.2 128 243.2zm7.9-172.5c-.8.1-1.4-.5-1.5-1.3V57.7c-.1-.9.4-1.8 1.3-2.1 7.8-4.2 10.6-13.9 6.4-21.7-4.2-7.8-13.9-10.6-21.7-6.4-7.8 4.2-10.6 13.9-6.4 21.7 1.5 2.7 3.7 4.9 6.4 6.4.8.3 1.4 1.2 1.3 2.1v11.4c.1.8-.4 1.5-1.2 1.6h-.3c-41 3-68.9 29.6-68.9 66.9 0 39.6 31.5 67.2 76.8 67.2s76.8-27.6 76.8-67.2c-.1-37.3-28-63.9-69-66.9zM128 182.4c-35.9 0-60.8-18.4-60.8-44.8S92.1 92.8 128 92.8s60.8 18.4 60.8 44.8-24.9 44.8-60.8 44.8zm53.8-44.8c0 22.3-22.1 37.8-53.8 37.8-5.1 0-10.2-.4-15.2-1.3-6.8-1.2-9.4-3.2-12-9.6-3.1-7.5-4.8-16.6-4.8-26.9s1.7-19.4 4.8-26.9c2.7-6.4 5.2-8.4 12-9.6 5-.9 10.1-1.3 15.2-1.3 31.7 0 53.8 15.5 53.8 37.8z"/></svg>' ),
164  $menu_position
165  );
166 
167  add_filter( 'gk/foundation/inline-styles', function ( $styles ) {
168  $styles[] = [
169  'style' => '#toplevel_page_' . self::WP_ADMIN_MENU_SLUG . ' div.wp-menu-image.svg { background-size: 1.5em auto; }',
170  ];
171 
172  return $styles;
173  } );
174 
175  /**
176  * @filter `gk/foundation/admin-menu/counter` Displays counter next to the top-menu title.
177  *
178  * @since 1.0.0
179  *
180  * @param int $total_badge_count
181  */
182  $total_badge_count = (int) apply_filters( 'gk/foundation/admin-menu/counter', $total_badge_count );
183 
184  if ( $total_badge_count ) {
185  foreach ( $menu as &$menu_item ) {
186  if ( $menu_item[2] === self::WP_ADMIN_MENU_SLUG ) {
187  $menu_item[0] .= $this->get_badge_counter_markup( self::WP_ADMIN_MENU_SLUG, $total_badge_count );
188  }
189  }
190  }
191 
192  // Add submenus.
193  foreach ( $filtered_submenus as $index => $filtered_submenu ) {
194  add_submenu_page(
195  $filtered_submenu['slug'],
196  $filtered_submenu['page_title'],
197  $filtered_submenu['menu_title'],
198  $filtered_submenu['capability'],
199  $filtered_submenu['id'],
200  $filtered_submenu['callback']
201  );
202 
203  // Add divider unless it's the last submenu item that we've added.
204  if ( ! isset( $filtered_submenu['divider'] ) || $index === count( $filtered_submenus ) - 1 ) {
205  continue;
206  }
207 
208  $added_submenu_to_update = array_pop( $submenu[ self::WP_ADMIN_MENU_SLUG ] );
209  $added_submenu_to_update[0] .= $filtered_submenu['divider'];
210 
211  $submenu[ self::WP_ADMIN_MENU_SLUG ][] = $added_submenu_to_update;
212  }
213 
214  // On a multisite the first submenu item equals the top-level menu.
215  // Let's indiscriminately remove all submenu items that have the top-level menu's slug.
216  foreach ( $submenu[ self::WP_ADMIN_MENU_SLUG ] as $key => $submenu_item ) {
217  if ( $submenu_item[2] === self::WP_ADMIN_MENU_SLUG ) {
218  unset( $submenu[ self::WP_ADMIN_MENU_SLUG ][ $key ] );
219  }
220  }
221  }
222 
223  /**
224  * Adds a submenu to the GravityKit top-level menu in WP admin.
225  *
226  * @since 1.0.0
227  *
228  * @param array $submenu The submenu data.
229  * @param string $position The position of the submenu. Default: 'top'.
230  *
231  * @retun void
232  */
233  static function add_submenu_item( $submenu, $position = 'top' ) {
234  if ( ! isset( $submenu['id'] ) && ! isset( $_submenus[ $position ] ) ) {
235  return;
236  }
237 
238  $submenus = self::get_submenus();
239 
240  if ( ! isset( $submenu['order'] ) ) {
241  $order = array_column( $submenus[ $position ], 'order' );
242 
243  if ( empty( $order ) ) {
244  $submenu['order'] = 1;
245  } else {
246  $submenu['order'] = max( $order ) + 100;
247  }
248  }
249 
250  $submenus[ $position ][ $submenu['id'] ] = $submenu;
251 
252  $order = array_column( $submenus[ $position ], 'order' );
253 
254  array_multisort( $submenus[ $position ], SORT_NUMERIC, $order );
255 
256  self::$_submenus = $submenus;
257  }
258 
259  /**
260  * Returns submenus optionally modified by a filter.
261  *
262  * @since 1.0.0
263  *
264  * @return array
265  */
266  static function get_submenus() {
267  /**
268  * @filter `gk/foundation/admin-menu/submenus` Modifies the submenus object.
269  *
270  * @since 1.0.0
271  *
272  * @param array $submenus Submenus.
273  */
274  return apply_filters( 'gk/foundation/admin-menu/submenus', self::$_submenus );
275  }
276 
277  /**
278  * Removes a submenu from the GravityKit top-level menu in WP admin and if the top-level menu is empty, removes it as well.
279  *
280  * @since 1.0.0
281  *
282  * @global array $submenu
283  *
284  * @retun void
285  */
286  static function remove_submenu_item( $id ) {
287  global $submenu;
288 
289  if ( ! isset( $submenu[ self::WP_ADMIN_MENU_SLUG ] ) ) {
290  return;
291  }
292 
293  foreach ( $submenu[ self::WP_ADMIN_MENU_SLUG ] as $index => $submenu_item ) {
294  if ( $submenu_item[2] === $id ) {
295  unset( $submenu[ self::WP_ADMIN_MENU_SLUG ][ $index ] );
296  }
297  }
298 
299  if ( ! empty( $submenu[ self::WP_ADMIN_MENU_SLUG ] ) ) {
300  return;
301  }
302 
303  self::remove_admin_menu();
304  }
305 
306  /**
307  * Removes the GravityKit top-level menu from WP admin.
308  *
309  * @since 1.0.0
310  *
311  * @global array $menu
312  *
313  * @retun void
314  */
315  static function remove_admin_menu() {
316  global $menu;
317 
318  foreach ( $menu as $index => $menu_item ) {
319  if ( $menu_item[2] === self::WP_ADMIN_MENU_SLUG ) {
320  unset( $menu[ $index ] );
321  }
322  }
323  }
324 
325  /**
326  * Returns the markup for the badge counter.
327  *
328  * @since 1.0.0
329  *
330  * @param string $menu_id
331  * @param int|string $badge_count
332  *
333  * @return string
334  */
335  public function get_badge_counter_markup( $menu_id, $badge_count ) {
336  $badge_count = (int) $badge_count;
337 
338  return '<span id="' . $menu_id . '-badge" style="margin-left: 5px;" class="update-plugins count-' . $badge_count . '"><span class="plugin-count">' . number_format_i18n( $badge_count ) . '</span></span>';
339  }
340 }
get_badge_counter_markup( $menu_id, $badge_count)
Returns the markup for the badge counter.
Definition: AdminMenu.php:335
static remove_submenu_item( $id)
Removes a submenu from the GravityKit top-level menu in WP admin and if the top-level menu is empty...
Definition: AdminMenu.php:286
static add_submenu_item( $submenu, $position='top')
Adds a submenu to the GravityKit top-level menu in WP admin.
Definition: AdminMenu.php:233
This class is responsible for adding a GravityKit menu and submenu items to the WP admin panel...
Definition: AdminMenu.php:14
add_admin_menu()
Configures GravityKit top-level menu and submenu items in WP admin.
Definition: AdminMenu.php:80
static static get_instance()
Returns class instance.
Definition: AdminMenu.php:42
static get_submenus()
Returns submenus optionally modified by a filter.
Definition: AdminMenu.php:266
static remove_admin_menu()
Removes the GravityKit top-level menu from WP admin.
Definition: AdminMenu.php:315