PluginProbe ʕ •ᴥ•ʔ
Menu Icons by Themeisle – Add Icons to Navigation Menus / 0.13.3
Menu Icons by Themeisle – Add Icons to Navigation Menus v0.13.3
trunk 0.1.0 0.1.1 0.1.2 0.1.3 0.1.4 0.1.5 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.11.2 0.11.3 0.11.4 0.11.5 0.12.0 0.12.1 0.12.10 0.12.11 0.12.12 0.12.2 0.12.3 0.12.4 0.12.5 0.12.6 0.12.7 0.12.8 0.12.9 0.13.0 0.13.1 0.13.10 0.13.11 0.13.12 0.13.13 0.13.14 0.13.15 0.13.16 0.13.17 0.13.18 0.13.19 0.13.2 0.13.20 0.13.21 0.13.22 0.13.23 0.13.3 0.13.4 0.13.5 0.13.6 0.13.7 0.13.8 0.13.9 0.2.0 0.2.1 0.2.2 0.2.3 0.3.0 0.3.1 0.3.2 0.4.0 0.5.0 0.5.1 0.6.0 0.7.0 0.8.0 0.8.1 0.9.0 0.9.2
menu-icons / includes / front.php
menu-icons / includes Last commit date
library 3 years ago front.php 3 years ago media-template.php 4 years ago meta.php 3 years ago picker.php 3 years ago settings.php 3 years ago type-fonts.php 10 years ago type.php 10 years ago
front.php
515 lines
1 <?php
2
3 /**
4 * Front end functionalities
5 *
6 * @package Menu_Icons
7 * @author Dzikri Aziz <kvcrvt@gmail.com>
8 */
9 final class Menu_Icons_Front_End {
10
11 /**
12 * Icon types
13 *
14 * @since 0.9.0
15 * @access protected
16 * @var array
17 */
18 protected static $icon_types = array();
19
20 /**
21 * Default icon style
22 *
23 * @since 0.9.0
24 * @access protected
25 * @var array
26 */
27 protected static $default_style = array(
28 'font_size' => array(
29 'property' => 'font-size',
30 'value' => '1.2',
31 'unit' => 'em',
32 ),
33 'vertical_align' => array(
34 'property' => 'vertical-align',
35 'value' => 'middle',
36 'unit' => null,
37 ),
38 'svg_width' => array(
39 'property' => 'width',
40 'value' => '1',
41 'unit' => 'em',
42 ),
43 );
44
45 /**
46 * Hidden label class
47 *
48 * @since 0.9.0
49 * @access protected
50 * @var string
51 */
52 protected static $hidden_label_class = 'visuallyhidden';
53
54
55 /**
56 * Add hooks for front-end functionalities
57 *
58 * @since 0.9.0
59 */
60 public static function init() {
61 $active_types = Menu_Icons_Settings::get( 'global', 'icon_types' );
62
63 if ( empty( $active_types ) ) {
64 return;
65 }
66
67 foreach ( Menu_Icons::get( 'types' ) as $type ) {
68 if ( in_array( $type->id, $active_types, true ) ) {
69 self::$icon_types[ $type->id ] = $type;
70 }
71 }
72
73 /**
74 * Allow themes/plugins to override the hidden label class
75 *
76 * @since 0.8.0
77 * @param string $hidden_label_class Hidden label class.
78 * @return string
79 */
80 self::$hidden_label_class = apply_filters( 'menu_icons_hidden_label_class', self::$hidden_label_class );
81
82 /**
83 * Allow themes/plugins to override default inline style
84 *
85 * @since 0.9.0
86 * @param array $default_style Default inline style.
87 * @return array
88 */
89 self::$default_style = apply_filters( 'menu_icons_default_style', self::$default_style );
90
91 add_action( 'wp_enqueue_scripts', array( __CLASS__, '_enqueue_styles' ), 4 );
92 add_filter( 'wp_nav_menu_args', array( __CLASS__, '_add_menu_item_title_filter' ) );
93 add_filter( 'wp_nav_menu', array( __CLASS__, '_remove_menu_item_title_filter' ) );
94 }
95
96
97 /**
98 * Get nav menu ID based on arguments passed to wp_nav_menu()
99 *
100 * @since 0.3.0
101 * @param array $args wp_nav_menu() Arguments
102 * @return mixed Nav menu ID or FALSE on failure
103 */
104 public static function get_nav_menu_id( $args ) {
105 $args = (object) $args;
106 $menu = wp_get_nav_menu_object( $args->menu );
107
108 // Get the nav menu based on the theme_location
109 if ( ! $menu
110 && $args->theme_location
111 && ( $locations = get_nav_menu_locations() )
112 && isset( $locations[ $args->theme_location ] )
113 ) {
114 $menu = wp_get_nav_menu_object( $locations[ $args->theme_location ] );
115 }
116
117 // get the first menu that has items if we still can't find a menu
118 if ( ! $menu && ! $args->theme_location ) {
119 $menus = wp_get_nav_menus();
120 foreach ( $menus as $menu_maybe ) {
121 if ( $menu_items = wp_get_nav_menu_items( $menu_maybe->term_id, array( 'update_post_term_cache' => false ) ) ) {
122 $menu = $menu_maybe;
123 break;
124 }
125 }
126 }
127
128 if ( is_object( $menu ) && ! is_wp_error( $menu ) ) {
129 return $menu->term_id;
130 } else {
131 return false;
132 }
133 }
134
135
136 /**
137 * Enqueue stylesheets
138 *
139 * @since 0.1.0
140 * @wp_hook action wp_enqueue_scripts
141 * @link http://codex.wordpress.org/Plugin_API/Action_Reference/wp_enqueue_scripts
142 */
143 public static function _enqueue_styles() {
144 // Deregister icon picker plugin font-awesome style and re-register with the new handler to avoid other plugin/theme style handler conflict.
145 $wp_styles = wp_styles();
146 if ( $wp_styles && isset( $wp_styles->registered['font-awesome'] ) ) {
147 $registered = $wp_styles->registered['font-awesome'];
148 if ( strpos( $registered->src, Menu_Icons::get( 'url' ) ) !== false ) {
149 $wp_styles->remove( 'font-awesome' );
150 $registered->ver = Menu_Icons_Font_Awesome::$version;
151 $wp_styles->add( 'menu-icon-' . $registered->handle, $registered->src, $registered->deps, $registered->ver, $registered->args );
152 }
153 }
154
155 foreach ( self::$icon_types as $type ) {
156 $stylesheet_id = $type->stylesheet_id;
157 if ( 'font-awesome' === $stylesheet_id ) {
158 $stylesheet_id = 'menu-icon-' . $stylesheet_id;
159 }
160 if ( wp_style_is( $stylesheet_id, 'registered' ) ) {
161 wp_enqueue_style( $stylesheet_id );
162 }
163 }
164
165 /**
166 * Allow plugins/themes to override the extra stylesheet location
167 *
168 * @since 0.9.0
169 * @param string $extra_stylesheet_uri Extra stylesheet URI.
170 */
171 $extra_stylesheet_uri = apply_filters(
172 'menu_icons_extra_stylesheet_uri',
173 sprintf( '%scss/extra%s.css', Menu_Icons::get( 'url' ), kucrut_get_script_suffix() )
174 );
175
176 wp_enqueue_style(
177 'menu-icons-extra',
178 $extra_stylesheet_uri,
179 false,
180 Menu_Icons::VERSION
181 );
182 }
183
184
185 /**
186 * Add filter to 'the_title' hook
187 *
188 * We need to filter the menu item title but **not** regular post titles.
189 * Thus, we're adding the filter when `wp_nav_menu()` is called.
190 *
191 * @since 0.1.0
192 * @wp_hook filter wp_nav_menu_args
193 * @param array $args Not used.
194 *
195 * @return array
196 */
197 public static function _add_menu_item_title_filter( $args ) {
198 add_filter( 'the_title', array( __CLASS__, '_add_icon' ), 999, 2 );
199 add_filter( 'megamenu_the_title', array( __CLASS__, '_add_icon' ), 999, 2 );
200 add_filter( 'megamenu_nav_menu_css_class', array( __CLASS__, '_add_menu_item_class' ), 10, 3 );
201
202 return $args;
203 }
204
205
206 /**
207 * Remove filter from 'the_title' hook
208 *
209 * Because we don't want to filter post titles, we need to remove our
210 * filter when `wp_nav_menu()` exits.
211 *
212 * @since 0.1.0
213 * @wp_hook filter wp_nav_menu
214 * @param array $nav_menu Not used.
215 * @return array
216 */
217 public static function _remove_menu_item_title_filter( $nav_menu ) {
218 remove_filter( 'the_title', array( __CLASS__, '_add_icon' ), 999, 2 );
219 remove_filter( 'megamenu_the_title', array( __CLASS__, '_add_icon' ), 999, 2 );
220 remove_filter( 'megamenu_nav_menu_css_class', array( __CLASS__, '_add_menu_item_class' ), 10, 3 );
221 return $nav_menu;
222 }
223
224
225 /**
226 * Add icon to menu item title
227 *
228 * @since 0.1.0
229 * @since 0.9.0 Renamed the method to `add_icon()`.
230 * @wp_hook filter the_title
231 * @param string $title Menu item title.
232 * @param int $id Menu item ID.
233 *
234 * @return string
235 */
236 public static function _add_icon( $title, $id ) {
237 $meta = Menu_Icons_Meta::get( $id );
238 $icon = self::get_icon( $meta );
239
240 if ( empty( $icon ) ) {
241 return $title;
242 }
243
244 $title_class = ! empty( $meta['hide_label'] ) ? self::$hidden_label_class : '';
245 $title_wrapped = sprintf(
246 '<span%s>%s</span>',
247 ( ! empty( $title_class ) ) ? sprintf( ' class="%s"', esc_attr( $title_class ) ) : '',
248 $title
249 );
250
251 if ( 'after' === $meta['position'] ) {
252 $title_with_icon = "{$title_wrapped}{$icon}";
253 } else {
254 $title_with_icon = "{$icon}{$title_wrapped}";
255 }
256
257 /**
258 * Allow plugins/themes to override menu item markup
259 *
260 * @since 0.8.0
261 *
262 * @param string $title_with_icon Menu item markup after the icon is added.
263 * @param integer $id Menu item ID.
264 * @param array $meta Menu item metadata values.
265 * @param string $title Original menu item title.
266 *
267 * @return string
268 */
269 $title_with_icon = apply_filters( 'menu_icons_item_title', $title_with_icon, $id, $meta, $title );
270
271 return $title_with_icon;
272 }
273
274
275 /**
276 * Get icon
277 *
278 * @since 0.9.0
279 * @param array $meta Menu item meta value.
280 * @return string
281 */
282 public static function get_icon( $meta ) {
283 $icon = '';
284
285 // Icon type is not set.
286 if ( empty( $meta['type'] ) ) {
287 return $icon;
288 }
289
290 // Icon is not set.
291 if ( empty( $meta['icon'] ) ) {
292 return $icon;
293 }
294
295 // Icon type is not registered/enabled.
296 if ( ! isset( self::$icon_types[ $meta['type'] ] ) ) {
297 return $icon;
298 }
299
300 $type = self::$icon_types[ $meta['type'] ];
301
302 $callbacks = array(
303 array( $type, 'get_icon' ),
304 array( __CLASS__, "get_{$type->id}_icon" ),
305 array( __CLASS__, "get_{$type->template_id}_icon" ),
306 );
307
308 foreach ( $callbacks as $callback ) {
309 if ( is_callable( $callback ) ) {
310 $icon = call_user_func( $callback, $meta );
311 break;
312 }
313 }
314
315 return $icon;
316 }
317
318
319 /**
320 * Get icon style
321 *
322 * @since 0.9.0
323 * @param array $meta Menu item meta value.
324 * @param array $keys Style properties.
325 * @param bool $as_attribute Optional. Whether to output the style as HTML attribute or value only.
326 * Defaults to TRUE.
327 * @return string
328 */
329 public static function get_icon_style( $meta, $keys, $as_attribute = true ) {
330 $style_a = array();
331 $style_s = '';
332
333 foreach ( $keys as $key ) {
334 if ( ! isset( self::$default_style[ $key ] ) ) {
335 continue;
336 }
337
338 $rule = self::$default_style[ $key ];
339
340 if ( ! isset( $meta[ $key ] ) || $meta[ $key ] === $rule['value'] ) {
341 continue;
342 }
343
344 $value = $meta[ $key ];
345 if ( ! empty( $rule['unit'] ) ) {
346 $value .= $rule['unit'];
347 }
348
349 $style_a[ $rule['property'] ] = $value;
350 }
351
352 if ( empty( $style_a ) ) {
353 return $style_s;
354 }
355
356 foreach ( $style_a as $key => $value ) {
357 $style_s .= "{$key}:{$value};";
358 }
359
360 $style_s = esc_attr( $style_s );
361
362 if ( $as_attribute ) {
363 $style_s = sprintf( ' style="%s"', $style_s );
364 }
365
366 return $style_s;
367 }
368
369
370 /**
371 * Get icon classes
372 *
373 * @since 0.9.0
374 * @param array $meta Menu item meta value.
375 * @param string $output Whether to output the classes as string or array. Defaults to string.
376 * @return string|array
377 */
378 public static function get_icon_classes( $meta, $output = 'string' ) {
379 $classes = array( '_mi' );
380
381 if ( empty( $meta['hide_label'] ) ) {
382 $classes[] = "_{$meta['position']}";
383 }
384
385 if ( 'string' === $output ) {
386 $classes = implode( ' ', $classes );
387 }
388
389 return $classes;
390 }
391
392
393 /**
394 * Get font icon
395 *
396 * @since 0.9.0
397 * @param array $meta Menu item meta value.
398 * @return string
399 */
400 public static function get_font_icon( $meta ) {
401 $type = $meta['type'];
402 $icon = $meta['icon'];
403
404 $font_awesome5 = font_awesome_backward_compatible();
405 if ( ! empty( $type ) && 'fa' === $type ) {
406 $icon = explode( ' ', $icon );
407 $type = reset( $icon );
408 $icon = end( $icon );
409 $fa_icon = sprintf( '%s-%s', $type, $icon );
410 if ( array_key_exists( $fa_icon, $font_awesome5 ) ) {
411 $fa5_icon = $font_awesome5[ $fa_icon ];
412 $fa5_class = explode( ' ', $fa5_icon );
413 $type = reset( $fa5_class );
414 $icon = end( $fa5_class );
415 }
416 }
417 $classes = sprintf( '%s %s %s', self::get_icon_classes( $meta ), $type, $icon );
418 $style = self::get_icon_style( $meta, array( 'font_size', 'vertical_align' ) );
419 return sprintf( '<i class="%s" aria-hidden="true"%s></i>', esc_attr( $classes ), $style );
420 }
421
422
423 /**
424 * Get image icon
425 *
426 * @since 0.9.0
427 * @param array $meta Menu item meta value.
428 * @return string
429 */
430 public static function get_image_icon( $meta ) {
431 $args = array(
432 'class' => sprintf( '%s _image', self::get_icon_classes( $meta ) ),
433 'aria-hidden' => 'true',
434 );
435
436 $style = self::get_icon_style( $meta, array( 'vertical_align' ), false );
437 if ( ! empty( $style ) ) {
438 $args['style'] = $style;
439 }
440
441 return wp_get_attachment_image( $meta['icon'], $meta['image_size'], false, $args );
442 }
443
444
445 /**
446 * Get SVG icon
447 *
448 * @since 0.9.0
449 * @param array $meta Menu item meta value.
450 * @return string
451 */
452 public static function get_svg_icon( $meta ) {
453 $classes = sprintf( '%s _svg', self::get_icon_classes( $meta ) );
454 $style = self::get_icon_style( $meta, array( 'svg_width', 'vertical_align' ) );
455
456 $svg_icon = esc_url( wp_get_attachment_url( $meta['icon'] ) );
457 $width = '';
458 $height = '';
459 if ( 'image/svg+xml' === get_post_mime_type( $meta['icon'] ) ) {
460
461 // Check `WP_Filesystem` function exists OR not.
462 require_once ABSPATH . '/wp-admin/includes/file.php';
463 \WP_Filesystem();
464 global $wp_filesystem;
465
466 $svg_icon = get_attached_file( $meta['icon'] );
467 $svg_icon_content = $wp_filesystem->get_contents( $svg_icon );
468 if ( $svg_icon_content ) {
469 $xmlget = simplexml_load_string( $svg_icon_content );
470 $xmlattributes = $xmlget->attributes();
471 $width = (string) $xmlattributes->width;
472 $width = (int) filter_var( $xmlattributes->width, FILTER_SANITIZE_NUMBER_INT );
473 $height = (string) $xmlattributes->height;
474 $height = (int) filter_var( $xmlattributes->height, FILTER_SANITIZE_NUMBER_INT );
475 }
476 } else {
477 $attachment_meta = wp_get_attachment_metadata( $meta['icon'] );
478 if ( $attachment_meta ) {
479 $width = isset( $attachment_meta['width'] ) ? $attachment_meta['width'] : $width;
480 $height = isset( $attachment_meta['height'] ) ? $attachment_meta['height'] : $height;
481 }
482 }
483 if ( ! empty( $width ) ) {
484 $width = sprintf( ' width="%d"', $width );
485 }
486 if ( ! empty( $height ) ) {
487 $height = sprintf( ' height="%d"', $height );
488 }
489 $image_alt = get_post_meta( $meta['icon'], '_wp_attachment_image_alt', true );
490 $image_alt = $image_alt ? wp_strip_all_tags( $image_alt ) : '';
491 return sprintf(
492 '<img src="%s" class="%s" aria-hidden="true" alt="%s"%s%s%s/>',
493 esc_url( wp_get_attachment_url( $meta['icon'] ) ),
494 esc_attr( $classes ),
495 $image_alt,
496 $width,
497 $height,
498 $style
499 );
500 }
501
502 /**
503 * Add menu item class in `Max Mega Menu` item.
504 *
505 * @param array $classes Item classes.
506 * @param array $item WP menu item.
507 * @param object $args Menu object.
508 * @return array
509 */
510 public static function _add_menu_item_class( $classes, $item, $args ) { // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore
511 $classes[] = 'menu-item';
512 return $classes;
513 }
514 }
515