PluginProbe
Responsive Menu – Mobile Menu & Hamburger Menu Builder / 4.7.4
Responsive Menu – Mobile Menu & Hamburger Menu Builder v4.7.4
4.7.4 4.7.3 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.10 4.1.11 4.1.12 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 All 91 releases
responsive-menu / v4.0.0 / inc / classes / class-rmp-menu.php

class-rmp-menu.php in Responsive Menu – Mobile Menu & Hamburger Menu Builder 4.7.4, at v4.0.0/inc/classes/class-rmp-menu.php

557 lines 17.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * This is core class file for responsive menu pro.
5 *
6 * @package responsive_menu_pro
7 * @since 4.0.0
8 */
9
10 namespace RMP\Features\Inc;
11
12 use RMP\Features\Inc\Option_Manager;
13 use RMP\Features\Inc\Walker;
14
15 /** Disbale the direct access to this class */
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit;
18 }
19
20 if ( ! class_exists( 'RMP_Menu' ) ) :
21
22 /**
23 * Class RMP_Menu prepare the menu as per loction and menu id.
24 *
25 * @package responsive_menu_pro
26 *
27 * @author Expresstech System
28 */
29 class RMP_Menu {
30
31
32 /**
33 * Hold the menu id.
34 *
35 * @since 4.0.0
36 * @access protected
37 * @var string $menu_id
38 */
39 protected $menu_id;
40
41 /**
42 * Hold the menu id.
43 *
44 * @since 4.0.0
45 * @access protected
46 * @var array $options
47 */
48 public $options;
49
50 /**
51 * This is menu class constructor function.
52 *
53 * @access public
54 */
55 public function __construct( $menu_id ) {
56 $option_manager = Option_Manager::get_instance();
57 $this->options = $option_manager->get_options( $menu_id );
58
59 $this->menu_id = $menu_id;
60 }
61
62 /**
63 * Prepare mobile menu markup.
64 *
65 * @version 4.0.0
66 *
67 * @return HTML|string
68 */
69 public function mobile_menu() {
70 $menu_items = '';
71 if ( ! empty( $this->options['items_order'] ) ) {
72 $menu_items = $this->options['items_order'];
73 }
74
75 if ( empty( $menu_items ) ) {
76 return;
77 }
78
79 $side_animation = 'rmp-' . $this->options['animation_type'] . '-' . $this->options['menu_appear_from'];
80 $menu_container_classes = apply_filters( 'rmp_menu_container_classes', array( 'rmp-container', $side_animation ), $this->menu_id );
81 $menu_container_classes = implode( ' ', $menu_container_classes );
82
83 $this->menu_trigger()
84 ?>
85 <div id="rmp-container-<?php echo esc_attr( $this->menu_id ); ?>" class="rmp-container <?php echo esc_attr( $menu_container_classes ); ?>" tabindex="-1">
86 <?php
87 foreach ( $menu_items as $key => $value ) {
88 if ( ! empty( $value ) && 'on' === $value ) {
89 if ( 'menu' === $key ) {
90 $this->menu();
91 } elseif ( 'title' === $key ) {
92 $this->menu_title();
93 } elseif ( 'search' === $key ) {
94 $this->menu_search_box();
95 } elseif ( 'social-icons' === $key ) {
96 $this->menu_social_icons();
97 } else {
98 $this->menu_additional_content();
99 }
100 }
101 }
102 ?>
103 </div>
104 <?php
105 }
106
107 /**
108 * Function to print the menu markups in webpage.
109 */
110 public function build_menu() {
111 $this->mobile_menu();
112
113 /**
114 * Filters the menu marksup.
115 *
116 * @since 4.1.0
117 *
118 * @param HTML|string $html
119 * @param int menu_id
120 */
121 echo apply_filters( 'rmp_menu_html', '', $this->menu_id );
122 }
123
124 /**
125 * Function to return the prepared menu items.
126 *
127 * @since 4.0.0
128 *
129 * @return HTML|string
130 */
131 public function menu() {
132 $param = $this->rmp_nav_menu_args();
133
134 if ( empty( $param ) ) {
135 return;
136 }
137
138 $param['echo'] = false;
139
140 echo wp_nav_menu( $param );
141
142 /**
143 * Filters the nav menu markups.
144 *
145 * @since 4.1.2
146 *
147 * @param HTML $menu_markups
148 * @param int $this->menu_id
149 * @param array $param
150 */
151 echo apply_filters( 'rmp_menu_markups', '', $this->menu_id, $param );
152 }
153
154 public function menu_trigger() {
155 $trigger_click_animation = '';
156 if ( ! empty( $this->options['button_click_animation'] ) ) {
157 $trigger_click_animation = 'rmp-menu-trigger-' . $this->options['button_click_animation'];
158 }
159
160 $toggle_theme_class = '';
161 if ( ! empty( $this->options['menu_theme'] ) ) {
162 $toggle_theme_class = 'rmp-' . str_replace( ' ', '-', strtolower( $this->options['menu_theme'] ) ) . '-trigger';
163 }
164
165 $toggle_theme_class = apply_filters( 'rmp_menu_toggle_classes', array( 'rmp_menu_trigger', $trigger_click_animation ), $this->menu_id );
166 $toggle_theme_class = implode( ' ', $toggle_theme_class );
167 if ( wp_is_mobile() ) {
168 $toggle_theme_class .= ' rmp-mobile-device-menu';
169 }
170 $menu_trigger_destination = '';
171 if ( ! empty( $this->options['hamburger_position_selector'] ) ) {
172 $menu_trigger_destination = 'data-destination=' . $this->options['hamburger_position_selector'];
173 }
174
175 $trigger_text_position = '';
176
177 if ( ! empty( $this->options['button_title_position'] ) ) {
178 $trigger_text_position = $this->options['button_title_position'];
179 }
180
181 /*
182 * Only label the button when it has no visible text of its own. An aria-label
183 * overrides the visible label, and a mismatch between the two fails WCAG 2.5.3
184 * (Label in Name) and breaks voice control.
185 */
186 $trigger_has_visible_label = ! empty( $this->options['button_title'] )
187 && in_array( $trigger_text_position, array( 'left', 'right', 'top', 'bottom' ), true );
188
189 $trigger_aria_label = $trigger_has_visible_label ? '' : __( 'Menu', 'responsive-menu' );
190
191 /**
192 * Filters the accessible name of the menu trigger button.
193 *
194 * @since 4.7.4
195 *
196 * @param string $trigger_aria_label Accessible name, or '' to let the visible text name the button.
197 * @param int $menu_id Menu id.
198 */
199 $trigger_aria_label = apply_filters( 'rmp_menu_trigger_aria_label', $trigger_aria_label, $this->menu_id );
200 ?>
201 <button type="button" aria-controls="rmp-container-<?php echo esc_attr( $this->menu_id ); ?>" aria-expanded="false" <?php if ( ! empty( $trigger_aria_label ) ) : ?>aria-label="<?php echo esc_attr( $trigger_aria_label ); ?>" <?php endif; ?>id="rmp_menu_trigger-<?php echo esc_attr( $this->menu_id ); ?>" <?php echo esc_attr( $menu_trigger_destination ); ?> class="<?php echo esc_attr( $toggle_theme_class ); ?>">
202 <?php
203 if ( ( 'left' === $trigger_text_position || 'top' === $trigger_text_position ) && ! empty( $this->options['button_title'] ) ) {
204 // Menu trigger text.
205 ?>
206 <div class="rmp-trigger-label rmp-trigger-label-<?php echo esc_attr( $trigger_text_position ); ?>">
207 <span class="rmp-trigger-text"><?php echo esc_html( $this->options['button_title'] ); ?></span>
208 <?php
209 if ( ! empty( $this->options['button_title_open'] ) ) {
210 ?>
211 <span class="rmp-trigger-text-open"><?php echo esc_html( $this->options['button_title_open'] ); ?></span>
212 <?php } ?>
213 </div>
214 <?php } ?>
215 <span class="rmp-trigger-box">
216 <?php
217
218 // Normal state menu trigger type.
219 if ( ! empty( $this->options['button_font_icon'] ) ) {
220 ?>
221 <span class="rmp-trigger-icon rmp-trigger-icon-inactive"><?php echo wp_kses_post( $this->options['button_font_icon'] ); ?></span>
222 <?php
223 } elseif ( ! empty( $this->options['button_image'] ) ) {
224 ?>
225 <img src="<?php echo esc_url( $this->options['button_image'] ); ?>" alt="<?php echo esc_attr( rmp_image_alt_by_url( $this->options['button_image'] ) ); ?>" class="rmp-trigger-icon rmp-trigger-icon-inactive" width="100" height="100">
226 <?php
227 } else {
228 ?>
229 <span class="responsive-menu-pro-inner"></span>
230 <?php
231 }
232
233 // Active state menu trigger type.
234 if ( ! empty( $this->options['button_font_icon_when_clicked'] ) ) {
235 ?>
236 <span class="rmp-trigger-icon rmp-trigger-icon-active"><?php echo wp_kses_post( $this->options['button_font_icon_when_clicked'] ); ?></span>
237 <?php
238 } elseif ( ! empty( $this->options['button_image_when_clicked'] ) ) {
239 ?>
240 <img src="<?php echo esc_url( $this->options['button_image_when_clicked'] ); ?>" alt="<?php echo esc_attr( rmp_image_alt_by_url( $this->options['button_image_when_clicked'] ) ); ?>" class="rmp-trigger-icon rmp-trigger-icon-active" width="100" height="100">
241 <?php
242 }
243 ?>
244 </span>
245 <?php
246
247 if ( ( 'bottom' === $trigger_text_position || 'right' === $trigger_text_position ) && ! empty( $this->options['button_title'] ) ) {
248 // Menu trigger text.
249 ?>
250 <div class="rmp-trigger-label rmp-trigger-label-<?php echo esc_attr( $trigger_text_position ); ?>">
251 <span class="rmp-trigger-text"><?php echo esc_html( $this->options['button_title'] ); ?></span>
252 <?php
253 if ( ! empty( $this->options['button_title_open'] ) ) {
254 ?>
255 <span class="rmp-trigger-text-open"><?php echo esc_html( $this->options['button_title_open'] ); ?></span>
256 <?php } ?>
257 </div>
258 <?php } ?>
259 </button>
260 <?php
261 }
262
263 /**
264 * Returns menu title.
265 *
266 * @return HTML|string
267 */
268 public function menu_title() {
269 $menu_title_wrap = null;
270 $menu_title = '';
271 if ( ! empty( $this->options['menu_title'] ) ) {
272 $menu_title = $this->options['menu_title'];
273 }
274
275 $menu_image = '';
276 if ( ! empty( $this->options['menu_title_image'] ) ) {
277 $image_alt = rmp_image_alt_by_url( $this->options['menu_title_image'] );
278 $menu_image = sprintf(
279 '<img class="rmp-menu-title-image" src="%1$s" alt="%2$s" title="%2$s" width="100" height="100"/>',
280 esc_url( $this->options['menu_title_image'] ),
281 esc_attr( $image_alt )
282 );
283 }
284
285 if ( ! empty( $this->options['menu_title_font_icon'] ) ) {
286 $menu_image = sprintf( '%s', $this->options['menu_title_font_icon'] );
287 }
288
289 $link_target = '_self';
290 if ( ! empty( $this->options['menu_title_link_location'] ) ) {
291 $link_target = $this->options['menu_title_link_location'];
292 }
293 ?>
294 <div id="rmp-menu-title-<?php echo esc_attr( $this->menu_id ); ?>" class="rmp-menu-title">
295 <?php if ( ! empty( $this->options['menu_title_link'] ) ) { ?>
296 <a href="<?php echo esc_url( $this->options['menu_title_link'] ); ?>" target="<?php echo esc_attr( $link_target ); ?>" class="rmp-menu-title-link" id="rmp-menu-title-link">
297 <?php }else { ?>
298 <span class="rmp-menu-title-link">
299 <?php } ?>
300 <?php $title_html = $menu_image;
301 $title_html .= "<span>" . $menu_title . "</span>";
302 echo rm_sanitize_html_tags( $title_html );
303 if ( ! empty( $this->options['menu_title_link'] ) ) { ?>
304 </a>
305 <?php }else { ?>
306 </span>
307 <?php } ?>
308 </div>
309 <?php
310 }
311
312 /**
313 * Return menu search box.
314 *
315 * @return HTML|string
316 */
317 public function menu_search_box() {
318 ?>
319 <div id="rmp-search-box-<?php echo esc_attr( $this->menu_id ); ?>" class="rmp-search-box">
320 <form action="<?php echo esc_url( home_url( '/' ) ); ?>" class="rmp-search-form" role="search">
321 <input type="search" name="s" title="Search" placeholder="<?php esc_attr_e( 'Search', 'responsive-menu' ); ?>" class="rmp-search-box">
322 </form>
323 </div>
324 <?php
325 }
326
327 /**
328 * Function to prepare the the menu additional content section.
329 *
330 * @since 4.0.0
331 *
332 * @return HTML|string $content
333 */
334 public function menu_additional_content() {
335 $content = '';
336
337 if ( ! empty( $this->options['menu_additional_content'] ) ) {
338
339 // Sanitize HTML content using wp_kses with a strict allowlist.
340 // This replaces the previous script-tag-only regex strip, which was
341 // bypassable via event-handler attributes (e.g. onerror, onload).
342 $content = rm_sanitize_html_tags( $this->options['menu_additional_content'] );
343 }
344 ?>
345 <div id="rmp-menu-additional-content-<?php echo esc_attr( $this->menu_id ); ?>" class="rmp-menu-additional-content">
346 <?php echo do_shortcode( $content ); ?>
347 </div>
348 <?php
349
350 /**
351 * Filters the menu additional contents markups.
352 *
353 * @since 4.1.0
354 *
355 * @param string $content
356 * @param int $menu_id
357 */
358 echo apply_filters( 'menu_additional_content_html', '', $this->menu_id );
359 }
360
361 /**
362 * Function to prepare the menu social icons section.
363 *
364 * @since 4.6.0
365 *
366 * @return void
367 */
368 public function menu_social_icons() {
369 $social_icons = array();
370
371 if ( ! empty( $this->options['menu_social_icons'] ) && is_array( $this->options['menu_social_icons'] ) ) {
372 $social_icons = $this->options['menu_social_icons'];
373 }
374
375 if ( empty( $social_icons ) ) {
376 return;
377 }
378
379 $layout = ! empty( $this->options['menu_social_icons_layout'] ) ? $this->options['menu_social_icons_layout'] : 'horizontal';
380 $layout = in_array( $layout, array( 'horizontal', 'vertical' ), true ) ? $layout : 'horizontal';
381
382 $alignment = ! empty( $this->options['menu_social_icons_alignment'] ) ? $this->options['menu_social_icons_alignment'] : 'left';
383 $alignment = in_array( $alignment, array( 'left', 'center', 'right' ), true ) ? $alignment : 'left';
384
385 $wrapper_classes = array(
386 'rmp-menu-social-icons',
387 'rmp-social-icons-layout-' . $layout,
388 'rmp-social-icons-align-' . $alignment,
389 );
390 ?>
391 <div id="rmp-menu-social-icons-<?php echo esc_attr( $this->menu_id ); ?>" class="<?php echo esc_attr( implode( ' ', $wrapper_classes ) ); ?>">
392 <ul class="rmp-social-icons-list">
393 <?php
394 foreach ( $social_icons as $index => $icon ) {
395 $icon_value = ! empty( $icon['icon'] ) ? wp_specialchars_decode( (string) $icon['icon'], ENT_QUOTES ) : '';
396 $icon_value = trim( $icon_value );
397
398 if ( '' === $icon_value ) {
399 continue;
400 }
401
402 $icon_link = ! empty( $icon['link'] ) ? esc_url( $icon['link'] ) : '';
403
404 if ( false !== strpos( $icon_value, '<' ) ) {
405 $icon_markup = rm_sanitize_html_tags( $icon_value );
406 } else {
407 $icon_markup = sprintf( '<span class="rmp-font-icon %s"></span>', esc_attr( $icon_value ) );
408 }
409 ?>
410 <li class="rmp-social-icon-item rmp-social-icon-item--<?php echo esc_attr( $index ); ?>">
411 <?php if ( ! empty( $icon_link ) ) { ?>
412 <a href="<?php echo $icon_link; ?>" target="_blank" rel="noopener noreferrer" class="rmp-social-icon-link">
413 <span class="rmp-social-icon"><?php echo $icon_markup; ?></span>
414 </a>
415 <?php } else { ?>
416 <span class="rmp-social-icon-link rmp-social-icon-link--no-link">
417 <span class="rmp-social-icon"><?php echo $icon_markup; ?></span>
418 </span>
419 <?php } ?>
420 </li>
421 <?php
422 }
423 ?>
424 </ul>
425 </div>
426 <?php
427
428 /**
429 * Filters the menu social icons markups.
430 *
431 * @since 4.6.0
432 *
433 * @param string $html
434 * @param int $menu_id
435 */
436 echo apply_filters( 'rmp_menu_social_icons_html', '', $this->menu_id );
437 }
438
439 public function rmp_nav_menu_args( $args = null ) {
440 $menu = $this->get_wp_menu_to_use();
441 $menu_location = $this->get_wp_menu_location();
442 $wp_menu_obj = wp_get_nav_menu_object( $menu );
443
444 // Check menu object is not empty.
445 if ( empty( $wp_menu_obj ) ) {
446 return $args;
447 }
448
449 $menu_depth = 0;
450 if ( ! empty( $this->options['menu_depth'] ) ) {
451 $menu_depth = $this->options['menu_depth'];
452 }
453
454 $menu_label = ! empty( $this->options['menu_name'] ) ? $this->options['menu_name'] : 'Default';
455
456 if ( empty( $menu_label ) ) {
457 $menu_label = $menu;
458 }
459
460 /*
461 * No role="menubar" here: that is the ARIA application-menu pattern, which
462 * implies arrow-key roving-tabindex semantics this menu does not implement and
463 * which degrades screen-reader output for ordinary site navigation. The list
464 * stays a plain list; the <nav> container below carries the landmark label.
465 */
466 $item_wrap_attrs = array(
467 'id' => '%1$s',
468 'class' => '%2$s',
469 );
470
471 $wrap_attributes = apply_filters( 'rmp_wrap_attributes', $item_wrap_attrs, $this->menu_id, $menu_location );
472
473 $attributes = '';
474 foreach ( $wrap_attributes as $attribute => $value ) {
475 if ( ! empty( $value ) ) {
476 $attributes .= sprintf( ' %s="%s"', $attribute, esc_attr( $value ) );
477 }
478 }
479
480 $walker = new Walker( $this->options );
481 if ( ! empty( $this->options['custom_walker'] ) ) {
482 $walker = new $this->options['custom_walker']( $this->options );
483 }
484
485 $param = array(
486 'container' => 'nav',
487 'container_id' => 'rmp-menu-wrap-' . $this->menu_id,
488 'container_class' => 'rmp-menu-wrap',
489 'container_aria_label' => $menu_label,
490 'menu_id' => 'rmp-menu-' . $this->menu_id,
491 'menu_class' => 'rmp-menu',
492 'menu' => $wp_menu_obj,
493 'depth' => $menu_depth,
494 'fallback_cb' => 'wp_page_menu',
495 'before' => '',
496 'after' => '',
497 'link_before' => '',
498 'link_after' => '',
499 'theme_location' => '',
500 'walker' => $walker,
501 'items_wrap' => '<ul' . $attributes . '>%3$s</ul>',
502 );
503
504 $param = apply_filters( 'rmp_nav_menu_args', $param, $wp_menu_obj->term_id, $menu_location );
505 return $param;
506 }
507
508
509 /**
510 * Function to return the correct wp menu name.
511 *
512 * @version 4.0.0
513 *
514 * @return string Name of wp menu.
515 */
516 public function get_wp_menu_to_use() {
517 $menu = '';
518
519 // Set menu as per settings priority.
520 if ( ! empty( $this->options['different_menu_for_mobile'] ) && 'on' === $this->options['different_menu_for_mobile'] && wp_is_mobile() ) {
521 $menu = $this->options['menu_to_use_in_mobile'];
522 } elseif ( ! empty( $this->options['theme_location_menu'] ) && has_nav_menu( $this->options['theme_location_menu'] ) ) {
523 $menu = get_term( get_nav_menu_locations()[ $this->options['theme_location_menu'] ], 'nav_menu' )->slug;
524 } elseif ( ! empty( $this->options['menu_to_use'] ) ) {
525 $menu = $this->options['menu_to_use'];
526 } elseif ( ! empty( get_terms( 'nav_menu' )[0]->slug ) ) {
527 $menu = get_terms( 'nav_menu' )[0]->slug;
528 }
529
530 return $menu;
531 }
532
533 /**
534 * Function to get the location of menu.
535 *
536 * @return string Returns the menu location.
537 */
538 public function get_wp_menu_location() {
539 $menu = $this->get_wp_menu_to_use();
540 if ( empty( $menu ) ) {
541 return;
542 }
543
544 $theme_location = null;
545 $menu_object = wp_get_nav_menu_object( $menu );
546 $theme_locations = get_nav_menu_locations();
547 foreach ( $theme_locations as $location => $value ) {
548 if ( $value === $menu_object->term_id ) {
549 $theme_location = $location;
550 break;
551 }
552 }
553 return $theme_location;
554 }
555 }
556 endif;
557