PluginProbe ʕ •ᴥ•ʔ
Menu Icons by Themeisle – Add Icons to Navigation Menus / 0.12.12
Menu Icons by Themeisle – Add Icons to Navigation Menus v0.12.12
0.13.24 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 4 years ago front.php 4 years ago media-template.php 4 years ago meta.php 4 years ago picker.php 4 years ago settings.php 4 years ago type-fonts.php 10 years ago type.php 10 years ago
front.php
514 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' ), 7 );
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 $wp_styles->add( 'menu-icon-' . $registered->handle, $registered->src, $registered->deps, $registered->ver, $registered->args );
151 }
152 }
153
154 foreach ( self::$icon_types as $type ) {
155 $stylesheet_id = $type->stylesheet_id;
156 if ( 'font-awesome' === $stylesheet_id ) {
157 $stylesheet_id = 'menu-icon-' . $stylesheet_id;
158 }
159 if ( wp_style_is( $stylesheet_id, 'registered' ) ) {
160 wp_enqueue_style( $stylesheet_id );
161 }
162 }
163
164 /**
165 * Allow plugins/themes to override the extra stylesheet location
166 *
167 * @since 0.9.0
168 * @param string $extra_stylesheet_uri Extra stylesheet URI.
169 */
170 $extra_stylesheet_uri = apply_filters(
171 'menu_icons_extra_stylesheet_uri',
172 sprintf( '%scss/extra%s.css', Menu_Icons::get( 'url' ), kucrut_get_script_suffix() )
173 );
174
175 wp_enqueue_style(
176 'menu-icons-extra',
177 $extra_stylesheet_uri,
178 false,
179 Menu_Icons::VERSION
180 );
181 }
182
183
184 /**
185 * Add filter to 'the_title' hook
186 *
187 * We need to filter the menu item title but **not** regular post titles.
188 * Thus, we're adding the filter when `wp_nav_menu()` is called.
189 *
190 * @since 0.1.0
191 * @wp_hook filter wp_nav_menu_args
192 * @param array $args Not used.
193 *
194 * @return array
195 */
196 public static function _add_menu_item_title_filter( $args ) {
197 add_filter( 'the_title', array( __CLASS__, '_add_icon' ), 999, 2 );
198 add_filter( 'megamenu_the_title', array( __CLASS__, '_add_icon' ), 999, 2 );
199 add_filter( 'megamenu_nav_menu_css_class', array( __CLASS__, '_add_menu_item_class' ), 10, 3 );
200
201 return $args;
202 }
203
204
205 /**
206 * Remove filter from 'the_title' hook
207 *
208 * Because we don't want to filter post titles, we need to remove our
209 * filter when `wp_nav_menu()` exits.
210 *
211 * @since 0.1.0
212 * @wp_hook filter wp_nav_menu
213 * @param array $nav_menu Not used.
214 * @return array
215 */
216 public static function _remove_menu_item_title_filter( $nav_menu ) {
217 remove_filter( 'the_title', array( __CLASS__, '_add_icon' ), 999, 2 );
218 remove_filter( 'megamenu_the_title', array( __CLASS__, '_add_icon' ), 999, 2 );
219 remove_filter( 'megamenu_nav_menu_css_class', array( __CLASS__, '_add_menu_item_class' ), 10, 3 );
220 return $nav_menu;
221 }
222
223
224 /**
225 * Add icon to menu item title
226 *
227 * @since 0.1.0
228 * @since 0.9.0 Renamed the method to `add_icon()`.
229 * @wp_hook filter the_title
230 * @param string $title Menu item title.
231 * @param int $id Menu item ID.
232 *
233 * @return string
234 */
235 public static function _add_icon( $title, $id ) {
236 $meta = Menu_Icons_Meta::get( $id );
237 $icon = self::get_icon( $meta );
238
239 if ( empty( $icon ) ) {
240 return $title;
241 }
242
243 $title_class = ! empty( $meta['hide_label'] ) ? self::$hidden_label_class : '';
244 $title_wrapped = sprintf(
245 '<span%s>%s</span>',
246 ( ! empty( $title_class ) ) ? sprintf( ' class="%s"', esc_attr( $title_class ) ) : '',
247 $title
248 );
249
250 if ( 'after' === $meta['position'] ) {
251 $title_with_icon = "{$title_wrapped}{$icon}";
252 } else {
253 $title_with_icon = "{$icon}{$title_wrapped}";
254 }
255
256 /**
257 * Allow plugins/themes to override menu item markup
258 *
259 * @since 0.8.0
260 *
261 * @param string $title_with_icon Menu item markup after the icon is added.
262 * @param integer $id Menu item ID.
263 * @param array $meta Menu item metadata values.
264 * @param string $title Original menu item title.
265 *
266 * @return string
267 */
268 $title_with_icon = apply_filters( 'menu_icons_item_title', $title_with_icon, $id, $meta, $title );
269
270 return $title_with_icon;
271 }
272
273
274 /**
275 * Get icon
276 *
277 * @since 0.9.0
278 * @param array $meta Menu item meta value.
279 * @return string
280 */
281 public static function get_icon( $meta ) {
282 $icon = '';
283
284 // Icon type is not set.
285 if ( empty( $meta['type'] ) ) {
286 return $icon;
287 }
288
289 // Icon is not set.
290 if ( empty( $meta['icon'] ) ) {
291 return $icon;
292 }
293
294 // Icon type is not registered/enabled.
295 if ( ! isset( self::$icon_types[ $meta['type'] ] ) ) {
296 return $icon;
297 }
298
299 $type = self::$icon_types[ $meta['type'] ];
300
301 $callbacks = array(
302 array( $type, 'get_icon' ),
303 array( __CLASS__, "get_{$type->id}_icon" ),
304 array( __CLASS__, "get_{$type->template_id}_icon" ),
305 );
306
307 foreach ( $callbacks as $callback ) {
308 if ( is_callable( $callback ) ) {
309 $icon = call_user_func( $callback, $meta );
310 break;
311 }
312 }
313
314 return $icon;
315 }
316
317
318 /**
319 * Get icon style
320 *
321 * @since 0.9.0
322 * @param array $meta Menu item meta value.
323 * @param array $keys Style properties.
324 * @param bool $as_attribute Optional. Whether to output the style as HTML attribute or value only.
325 * Defaults to TRUE.
326 * @return string
327 */
328 public static function get_icon_style( $meta, $keys, $as_attribute = true ) {
329 $style_a = array();
330 $style_s = '';
331
332 foreach ( $keys as $key ) {
333 if ( ! isset( self::$default_style[ $key ] ) ) {
334 continue;
335 }
336
337 $rule = self::$default_style[ $key ];
338
339 if ( ! isset( $meta[ $key ] ) || $meta[ $key ] === $rule['value'] ) {
340 continue;
341 }
342
343 $value = $meta[ $key ];
344 if ( ! empty( $rule['unit'] ) ) {
345 $value .= $rule['unit'];
346 }
347
348 $style_a[ $rule['property'] ] = $value;
349 }
350
351 if ( empty( $style_a ) ) {
352 return $style_s;
353 }
354
355 foreach ( $style_a as $key => $value ) {
356 $style_s .= "{$key}:{$value};";
357 }
358
359 $style_s = esc_attr( $style_s );
360
361 if ( $as_attribute ) {
362 $style_s = sprintf( ' style="%s"', $style_s );
363 }
364
365 return $style_s;
366 }
367
368
369 /**
370 * Get icon classes
371 *
372 * @since 0.9.0
373 * @param array $meta Menu item meta value.
374 * @param string $output Whether to output the classes as string or array. Defaults to string.
375 * @return string|array
376 */
377 public static function get_icon_classes( $meta, $output = 'string' ) {
378 $classes = array( '_mi' );
379
380 if ( empty( $meta['hide_label'] ) ) {
381 $classes[] = "_{$meta['position']}";
382 }
383
384 if ( 'string' === $output ) {
385 $classes = implode( ' ', $classes );
386 }
387
388 return $classes;
389 }
390
391
392 /**
393 * Get font icon
394 *
395 * @since 0.9.0
396 * @param array $meta Menu item meta value.
397 * @return string
398 */
399 public static function get_font_icon( $meta ) {
400 $type = $meta['type'];
401 $icon = $meta['icon'];
402
403 $font_awesome5 = font_awesome5_backward_compatible();
404 if ( ! empty( $type ) && 'fa' === $type ) {
405 $icon = explode( ' ', $icon );
406 $type = reset( $icon );
407 $icon = end( $icon );
408 $fa_icon = sprintf( '%s-%s', $type, $icon );
409 if ( array_key_exists( $fa_icon, $font_awesome5 ) ) {
410 $fa5_icon = $font_awesome5[ $fa_icon ];
411 $fa5_class = explode( ' ', $fa5_icon );
412 $type = reset( $fa5_class );
413 $icon = end( $fa5_class );
414 }
415 }
416 $classes = sprintf( '%s %s %s', self::get_icon_classes( $meta ), $type, $icon );
417 $style = self::get_icon_style( $meta, array( 'font_size', 'vertical_align' ) );
418 return sprintf( '<i class="%s" aria-hidden="true"%s></i>', esc_attr( $classes ), $style );
419 }
420
421
422 /**
423 * Get image icon
424 *
425 * @since 0.9.0
426 * @param array $meta Menu item meta value.
427 * @return string
428 */
429 public static function get_image_icon( $meta ) {
430 $args = array(
431 'class' => sprintf( '%s _image', self::get_icon_classes( $meta ) ),
432 'aria-hidden' => 'true',
433 );
434
435 $style = self::get_icon_style( $meta, array( 'vertical_align' ), false );
436 if ( ! empty( $style ) ) {
437 $args['style'] = $style;
438 }
439
440 return wp_get_attachment_image( $meta['icon'], $meta['image_size'], false, $args );
441 }
442
443
444 /**
445 * Get SVG icon
446 *
447 * @since 0.9.0
448 * @param array $meta Menu item meta value.
449 * @return string
450 */
451 public static function get_svg_icon( $meta ) {
452 $classes = sprintf( '%s _svg', self::get_icon_classes( $meta ) );
453 $style = self::get_icon_style( $meta, array( 'svg_width', 'vertical_align' ) );
454
455 $svg_icon = esc_url( wp_get_attachment_url( $meta['icon'] ) );
456 $width = '';
457 $height = '';
458 if ( 'image/svg+xml' === get_post_mime_type( $meta['icon'] ) ) {
459
460 // Check `WP_Filesystem` function exists OR not.
461 require_once ABSPATH . '/wp-admin/includes/file.php';
462 \WP_Filesystem();
463 global $wp_filesystem;
464
465 $svg_icon = get_attached_file( $meta['icon'] );
466 $svg_icon_content = $wp_filesystem->get_contents( $svg_icon );
467 if ( $svg_icon_content ) {
468 $xmlget = simplexml_load_string( $svg_icon_content );
469 $xmlattributes = $xmlget->attributes();
470 $width = (string) $xmlattributes->width;
471 $width = (int) filter_var( $xmlattributes->width, FILTER_SANITIZE_NUMBER_INT );
472 $height = (string) $xmlattributes->height;
473 $height = (int) filter_var( $xmlattributes->height, FILTER_SANITIZE_NUMBER_INT );
474 }
475 } else {
476 $attachment_meta = wp_get_attachment_metadata( $meta['icon'] );
477 if ( $attachment_meta ) {
478 $width = isset( $attachment_meta['width'] ) ? $attachment_meta['width'] : $width;
479 $height = isset( $attachment_meta['height'] ) ? $attachment_meta['height'] : $height;
480 }
481 }
482 if ( ! empty( $width ) ) {
483 $width = sprintf( ' width="%dpx"', $width );
484 }
485 if ( ! empty( $height ) ) {
486 $height = sprintf( ' height="%dpx"', $height );
487 }
488 $image_alt = get_post_meta( $meta['icon'], '_wp_attachment_image_alt', true );
489 $image_alt = $image_alt ? wp_strip_all_tags( $image_alt ) : '';
490 return sprintf(
491 '<img src="%s" class="%s" aria-hidden="true" alt="%s"%s%s%s/>',
492 esc_url( wp_get_attachment_url( $meta['icon'] ) ),
493 esc_attr( $classes ),
494 $image_alt,
495 $width,
496 $height,
497 $style
498 );
499 }
500
501 /**
502 * Add menu item class in `Max Mega Menu` item.
503 *
504 * @param array $classes Item classes.
505 * @param array $item WP menu item.
506 * @param object $args Menu object.
507 * @return array
508 */
509 public static function _add_menu_item_class( $classes, $item, $args ) { // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore
510 $classes[] = 'menu-item';
511 return $classes;
512 }
513 }
514