PluginProbe
Themify Builder / trunk
Themify Builder vtrunk
7.8.1 7.8.0 7.7.9 7.7.8 7.7.7 7.7.6 7.7.5 7.7.4 7.7.3 7.7.2 trunk 7.6.0 7.6.1 7.6.2 7.6.3 7.6.4 7.6.5 7.6.6 7.6.7 7.6.8 7.6.9 7.7.0 7.7.1
themify-builder / themify / megamenu / class-mega-menu.php

class-mega-menu.php in Themify Builder trunk, at themify/megamenu/class-mega-menu.php

764 lines 31.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class that generates custom markup for mega menu that shows posts by categories
4 * @package themify
5 * @subpackage megamenu
6 * @since 1.0.0
7 */
8
9 defined( 'ABSPATH' ) || exit;
10
11 if( ! class_exists( 'Themify_Mega_Menu_Walker', false ) ) {
12 /**
13 * Class Themify_Mega_Menu_Walker generates menu with posts by category
14 * @since 1.0.0
15 */
16 class Themify_Mega_Menu_Walker extends Walker_Nav_Menu {
17 static $mega_open = false;
18 private static $hasLayout=false;
19 private static $open=false;
20 static $disableAssetsLoading=false;
21
22 /**
23 * render a widget menu item
24 *
25 * $depth level
26 * $class_names additional CSS classes to add to the menu wrapper
27 * @return string
28 */
29
30 function render_widget_menu( $item, int $depth, $args, string $class_names = '' ):string {
31 $output = '';
32 if ( $depth === 0 ) {
33 $title = apply_filters( 'the_title', $item->title, $item->ID );
34 $title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
35 $output = "<li class='{$class_names}'><a role='button' tabindex='0'>" . $title . '<span class="child-arrow"></span></a><ul class="sub-menu tf_box">';
36 }
37
38 $menu_widget = Themify_Widgets_Menu::get_instance()->get_widget_menu_class( $item );
39 $output .= '<li class="themify-widget-menu">';
40 $output .= sprintf( '<!--themify_widget_menu %s %s -->', $menu_widget, $item->ID );
41
42 if( $depth === 0 ) {
43 $output .= '</ul>';
44 }
45
46 return $output;
47 }
48
49 /**
50 * Render a Layout Part inside menu
51 *
52 * $depth level
53 * $class_names additional CSS classes to add to the menu wrapper
54 * @return string
55 */
56 function render_layout_part( $item,int $depth, $args, string $class_names = ''):string {
57 $output = '';
58 if( $depth === 0 ) {
59 $title = apply_filters( 'the_title', $item->title, $item->ID );
60 $title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
61 $output = "<li class='{$class_names}'><a role='button' tabindex='0'>" . $title . '<span class="child-arrow"></span></a><ul class="sub-menu tf_box">';
62 }
63
64 $output .= '<li class="themify-widget-menu">' . do_shortcode( sprintf( '[themify_layout_part id="%s"]', $item->object_id ) );
65
66 if( $depth === 0 ) {
67 $output .= '</ul>';
68 }
69
70 return $output;
71 }
72
73 function start_el( &$output, $item, $depth = 0, $args = array(), $current_object_id = 0 ) {
74
75 $classes = empty ( $item->classes ) ? array () : (array) $item->classes;
76 if( $item->type === 'taxonomy' ){
77 $classes[]='mega-link';
78 }
79 $classes[]='menu-item-'.$item->ID;
80
81 /** This filter is documented in wp-includes/class-walker-nav-menu.php */
82 $args = apply_filters( 'nav_menu_item_args', $args, $item, $depth );
83
84 $classes = implode(' ', apply_filters('nav_menu_css_class', array_keys(array_flip(array_filter($classes) )), $item, $args, $depth ));
85
86 /** This filter is documented in wp-includes/class-walker-nav-menu.php */
87 $id = apply_filters( 'nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args, $depth );
88
89 /* handle the display of widget menu items */
90 if( Themify_Widgets_Menu::get_instance()->is_menu_widget( $item ) ) {
91 $item_output= $this->render_widget_menu( $item, $depth, $args, $classes, $args );
92 } else if ( $item->type === 'post_type' && $item->object === 'tbuilder_layout_part' ) {
93 $item_output = $this->render_layout_part( $item, $depth, $args, $classes );
94 } else {
95 $li_attributes = [
96 'id' => ! empty( $id ) ? $id : '',
97 'class' => ! empty( $classes ) ? $classes : ''
98 ];
99 /* required for "mega" menu type which displays posts from a taxonomy term */
100 if ( $item->type === 'taxonomy' ) {
101 $li_attributes['data-termid']= $item->object_id;
102 $li_attributes['data-tax']= $item->object;
103 }
104 if ( $args->walker->has_children > 0 ) {
105 $li_attributes['aria-haspopup'] = "true";
106 }
107
108 /** This filter is documented in wp-includes/class-walker-nav-menu.php */
109 $li_attributes = apply_filters( 'nav_menu_item_attributes', $li_attributes, $item, $args, $depth );
110 $output .= '<li ' . $this->build_atts( $li_attributes ) . '>';
111
112 $atts = array();
113 $atts['title'] = ! empty( $item->attr_title ) ? $item->attr_title : '';
114 $atts['target'] = ! empty( $item->target ) ? $item->target : '';
115 if ( '_blank' === $item->target && empty( $item->xfn ) ) {
116 $atts['rel'] = 'noopener';
117 } else {
118 $atts['rel'] = $item->xfn;
119 }
120
121 if ( ! empty( $item->url ) ) {
122 if ( get_privacy_policy_url() === $item->url ) {
123 $atts['rel'] = empty( $atts['rel'] ) ? 'privacy-policy' : $atts['rel'] . ' privacy-policy';
124 }
125
126 $atts['href'] = $item->url;
127 } else {
128 $atts['href'] = '';
129 }
130
131 $atts['aria-current'] = $item->current ? 'page' : '';
132
133 /** This filter is documented in wp-includes/class-walker-nav-menu.php */
134 $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );
135
136 /** This filter is documented in wp-includes/post-template.php */
137 $title = apply_filters( 'the_title', $item->title, $item->ID );
138
139 /** This filter is documented in wp-includes/class-walker-nav-menu.php */
140 $title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
141
142 $item_output = $args->before. '<a ' . $this->build_atts( $atts ) . '>' . $args->link_before . $title;
143
144 if(isset($args->post_count) && $args->post_count===true && $item->type==='taxonomy'){
145 $term = get_term( $item->object_id, $item->object );
146 $item_output.='<span class="tf_post_count">'.$term->count.'</span>';
147 }
148 if($args->walker->has_children>0){
149 $item_output.='<span class="child-arrow"></span>';
150 }
151 if ( ! empty( $item->post_content ) && themify_check( 'menu_description', true ) ) {
152 $item_output .= '<small>' . esc_html( $item->post_content ) . '</small>';
153 }
154 $item_output.='</a> ' . $args->link_after . $args->after;
155 }
156
157 $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
158 }
159
160 /**
161 * Start sub level markup
162 * @param string $output
163 * @param int $depth
164 * @param array $args
165 */
166 function start_lvl( &$output, $depth = 0, $args = array() ) {
167 $cl='sub-menu';
168 if(self::$hasLayout==='layout'){
169 $cl.=' tf_scrollbar';
170 }
171 elseif(self::$hasLayout==='ajax'){
172 $cl='tf_mega_taxes tf_left tf_box';
173 $output.='<div class="mega-sub-menu sub-menu tf_scrollbar">';
174 self::$open=true;
175 }
176 $output .= '<ul class="'.$cl.'">';
177 }
178
179 /**
180 * End sub level markup
181 * @param string $output
182 * @param int $depth
183 * @param array $args
184 */
185 function end_lvl( &$output, $depth = 0, $args = array() ) {
186 $output .= '</ul>';
187 if(self::$open===true){
188 self::$open=false;
189 $output.='</div>';
190 }
191 }
192
193 /**
194 * Modify item rendering
195 * @param object $item
196 * @param array $children_elements
197 * @param int $max_depth
198 * @param int $depth
199 * @param array $args
200 * @param string $output
201 * @return null|void
202 * @since 1.0.0
203 */
204 function display_element( $item, &$children_elements, $max_depth, $depth, $args, &$output ) {
205 $id_field = $this->db_fields['id'];
206 static $is=null;
207 self::$hasLayout=false;
208 if ( themify_is_menu_highlighted_link($item->ID) ) {
209 $item->classes[] = 'highlight-link';
210 }
211 $cl=false;
212 if ( in_array( 'mega', $item->classes,true ) || themify_is_mega_menu_type( $item->ID, 'mega' )){ // backward compatibility
213 if($is===null){
214 $is=true;
215 self::preloadCssJs();
216 }
217 $item->classes[] = 'mega';
218 $item->classes[] = 'has-mega-sub-menu';
219 $item->classes[] = 'has-mega';
220 self::$hasLayout='ajax';
221 $cl='mega-sub-item';
222 }
223 elseif(in_array( 'columns', $item->classes,true ) || themify_is_mega_menu_type( $item->$id_field, 'column' )){// backwards compatibility
224 if($is===null){
225 $is=true;
226 self::preloadCssJs();
227 }
228 $item->classes[] = 'has-mega-column';
229 $item->classes[] = 'has-mega';
230 if( $column_layout = get_post_meta( $item->ID, '_themify_mega_menu_columns_layout', true ) ) {
231 $item->classes[] = 'layout-' . $column_layout;
232 } else {
233 $item->classes[] = 'layout-auto';
234 }
235 self::$hasLayout='layout';
236 $cl='columns-sub-item';
237 }
238 elseif(($dropdown_columns = get_post_meta( $item->$id_field, '_themify_dropdown_columns', true ))){
239 if($dropdown_columns>1){
240 $item->classes[] = 'has-mega-dropdown dropdown-columns-' . $dropdown_columns;
241 if($is===null){
242 $is=true;
243 self::preloadCssJs();
244 }
245 }
246 }
247 elseif(in_array( 'columns-sub-item', $item->classes,true ) ) {
248 $cl='columns-sub-item';
249 }
250 if ( ! empty( $children_elements[ $item->$id_field ] ) ) {
251 $item->classes[] = 'has-sub-menu';
252
253 if ($cl!==false ) {
254 foreach( $children_elements[ $item->$id_field ] as $child ) {
255 $child->classes[] =$cl;
256 }
257 }
258 }
259
260 Walker_Nav_Menu::display_element( $item, $children_elements, $max_depth, $depth, $args, $output );
261 }
262
263 public static function preloadCssJs(){
264 if(self::$disableAssetsLoading===false){
265 if ( themify_is_themify_theme() ) {
266 themify_enque_style('tf_megamenu',THEMIFY_URI . '/megamenu/css/style.css',null,THEMIFY_VERSION,'screen and (min-width:' . (Themify_Enqueue_Assets::$mobileMenuActive + 1) . 'px)');
267 }
268 Themify_Enqueue_Assets::addLocalization('done','tf_megamenu',true);
269 }
270 }
271
272 /**
273 * copy of Walker_Nav_Menu::build_atts, for compatibility with WP < 6.3.0
274 * documented in wp-includes/class-walker-nav-menu.php
275 */
276 protected function build_atts( $atts = array() ) {
277 $attribute_string = '';
278 foreach ( $atts as $attr => $value ) {
279 if ( false !== $value && '' !== $value && is_scalar( $value ) ) {
280 $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
281 $attribute_string .= ' ' . $attr . '="' . $value . '"';
282 }
283 }
284 return $attribute_string;
285 }
286 }
287
288 }
289
290 if( ! function_exists('themify_theme_mega_get_posts') ) {
291 /**
292 * Returns posts from a taxonomy by a given term
293 * @param $term_id
294 * @param $taxonomy
295 * @return string
296 */
297 function themify_theme_mega_get_posts( $term_id, $taxonomy ):string {
298 $taxObject = get_taxonomy( $taxonomy );
299 if ( is_wp_error( $taxObject ) || empty( $taxObject ) ) {
300 return '';
301 }
302
303 $postPerPage = themify_get( 'setting-mega_menu_posts', 5, true );
304 $term_query_args = apply_filters( 'themify_mega_menu_query',
305 array(
306 'post_type' => $taxObject->object_type,
307 'tax_query' => array(
308 array(
309 'taxonomy' => $taxonomy,
310 'field' => 'id',
311 'terms' => $term_id
312 )
313 ),
314 'orderby' => themify_get( 'setting-mega_menu_orderby', 'date', true ),
315 'order' => themify_get( 'setting-mega_menu_order', 'desc', true ),
316 'suppress_filters' => false,
317 'posts_per_page' => $postPerPage
318 )
319 );
320
321 $posts = get_posts( $term_query_args );
322
323 if ( !empty($posts) ) {
324 global $post;
325 if ( isset( $post ) ){
326 $saved_post = clone $post;
327 }
328 $template = locate_template( array(
329 'includes/loop-megamenu-'.get_post_type().'.php',
330 'includes/loop-megamenu.php',
331 ) );
332 if ( ! $template ) {
333 $template = THEMIFY_DIR . '/megamenu/templates/loop-megamenu.php';
334 }
335
336 ob_start();
337 foreach( $posts as $p ) {
338 $post=$p;
339 setup_postdata( $p );
340 include $template;
341 }
342 $mega_posts = ob_get_clean();
343 unset($posts);
344 if ( isset( $saved_post )) {
345 $post = $saved_post;
346 setup_postdata( $saved_post );
347 unset($saved_post);
348 }
349 } else {
350 $mega_posts = '<article itemscope itemtype="https://schema.org/Article" class="post"><p class="post-title">'.__('Error loading posts.', 'themify').'</p></article>';
351 }
352
353 return apply_filters( 'themify_mega_posts_output', $mega_posts, $term_id, $taxonomy );
354 }
355 }
356
357 if( ! function_exists( 'themify_theme_mega_posts' ) ) {
358 /**
359 * Called with AJAX to return posts
360 * @since 1.0.0
361 */
362 function themify_theme_mega_posts() {
363 $termid = isset( $_POST['termid'] ) ? absint( $_POST['termid'] ) : 0;
364 $taxonomy = isset( $_POST['tax'] ) ? sanitize_key( $_POST['tax'] ) : 'category';
365 die(themify_theme_mega_get_posts( $termid, $taxonomy ));
366 }
367 }
368 add_action('wp_ajax_themify_theme_mega_posts', 'themify_theme_mega_posts');
369 add_action('wp_ajax_nopriv_themify_theme_mega_posts', 'themify_theme_mega_posts');
370
371
372 /***************************************************
373 * Themify Theme Access Point
374 ***************************************************/
375
376 if ( ! function_exists( 'themify_theme_main_menu' ) ) {
377 /**
378 * Sets custom menu selected in page custom panel as navigation, otherwise sets the default.
379 *
380 * @since 1.0.0
381 */
382 function themify_theme_main_menu( $args = array() ) {
383
384 $args['echo'] = false;
385 $menu_type = 'main';
386
387 if( 'no' !== themify_get( 'setting-mega_menu',false,true ) ) {
388 $args['walker'] = new Themify_Mega_Menu_Walker;
389 $menu_type = 'mega';
390 }
391
392 echo apply_filters( 'themify_' . $menu_type . '_menu_html', themify_menu_nav( $args ), $args );
393 }
394 }
395
396 /**
397 * Check if mega menu is enabled for a menu item
398 *
399 * @param int $item_id
400 * @param string $type
401 *
402 * @return bool
403 * @since 1.0.0
404 */
405 function themify_is_mega_menu_type( $item_id, $type = 'mega' ) {
406 if($type==='mega' || $type==='column' || $type==='dual'){
407 $key=$type==='mega'?'item':$type;
408 return get_post_meta( $item_id, '_themify_mega_menu_'.$key, true ) == '1';
409 }
410 }
411
412 function themify_is_menu_highlighted_link( $item_id ) {
413 return get_post_meta( $item_id, '_themify_highlight_link', true );
414 }
415
416 /**
417 * Add the option to enable mega menu to taxonomy menu types
418 *
419 * @since 1.0.0
420 */
421 function themify_menu_mega_option( $item_id, $item, $depth, $args ) {
422 $dropdown_columns = (int) get_post_meta( $item_id, '_themify_dropdown_columns', true );
423 $is_mega = themify_is_mega_menu_type( $item_id, 'mega' );
424 $is_column = !$is_mega && themify_is_mega_menu_type( $item_id, 'column' );
425 $is_dropdown_column = !$is_column && ! empty( $dropdown_columns );
426 $column_layout = get_post_meta( $item_id, '_themify_mega_menu_columns_layout', true );
427 ?>
428 <div class="field-tf-mega description description-thin">
429 <label for="edit-menu-item-tf-mega-<?php echo $item_id; ?>">
430 <?php _e( 'Mega Menu', 'themify' ) ?>
431 <a href="https://themify.me/docs/builder#mega-menu" target="_blank"><i class="ti-help"></i></a>
432 <br />
433 <select name="menu-item-tf-mega[<?php echo $item_id; ?>]" id="edit-menu-item-tf-mega-<?php echo $item_id?>" class="edit-menu-item-tf-mega themify_field_tf-mega widefat">
434 <option value=""></option>
435 <option value="mega" <?php if( $is_mega ) echo 'selected';?>><?php _e( 'Mega Posts', 'themify' ); ?></option>
436 <option value="columns" <?php if( $is_column ) echo 'selected';?>><?php _e( 'Fullwidth Columns', 'themify' ); ?></option>
437 <option value="drop" <?php if( $is_dropdown_column===true ) echo 'selected';?>><?php _e( 'Dropdown Columns', 'themify' ); ?></option>
438 </select>
439 </label>
440 <div class="tf-mega-columns-layout">
441 <?php
442 echo '<input type="hidden" name="menu-item-tf-mega-columns-layout[' . $item_id . ']" value="'.$column_layout.'" class="val">';
443 foreach ( array(
444 '' => __( 'Auto', 'themify' ),
445 '4-8' => __( '1/3 - 2/3', 'themify' ),
446 '8-4' => __( '2/3 - 1/3', 'themify' ),
447 '6-3-3' => __( '2/4 - 1/4 - 1/4', 'themify' ),
448 '3-3-6' => __( '1/4 - 1/4 - 2/4', 'themify' ),
449 '3-6-3' => __( '1/4 - 2/4 - 1/4', 'themify' ),
450 '3-9' => __( '1/4 - 3/4', 'themify' ),
451 '9-3' => __( '3/4 - 1/4', 'themify' ),
452 ) as $key => $label ) {
453 $selected = $column_layout === $key ? 'class="selected"' : '';
454 echo '<a href="#" ' . $selected . ' data-value="'. $key . '" title="' . $label . '"></a>';
455 }
456 ?>
457 </div>
458 </div>
459
460 <p class="tf-dropdown-columns-field description description-thin">
461 <label for="edit-menu-item-tf-dropdown-columns-<?php echo $item_id; ?>">
462 <?php _e( 'Dropdown Columns', 'themify' ) ?><br />
463 <select name="menu-item-tf-dropdown_columns[<?php echo $item_id; ?>]" id="edit-menu-item-tf-dropdown_columns-<?php echo $item_id?>" class="edit-menu-item-tf-dropdown_columns">
464 <option value=""></option>
465 <option value="2" <?php selected( 2, $dropdown_columns ) ?>>2</option>
466 <option value="3" <?php selected( 3, $dropdown_columns ) ?>>3</option>
467 <option value="4" <?php selected( 4, $dropdown_columns ) ?>>4</option>
468 </select>
469 </label>
470 </p>
471
472 <?php
473 $allow_hightlight = apply_filters( 'themify_menu_highlight_link', false);
474 if ($allow_hightlight) :
475 $highlight = get_post_meta( $item_id, '_themify_highlight_link', true );
476 ?>
477 <div class="field-tf-highlight description description-thin"><br>
478 <label for="edit-menu-item-tf-highlight-<?php echo $item_id; ?>">
479 <input type="checkbox" name="menu-item-tf-highlight[<?php echo $item_id; ?>]" value="1" <?php echo ($highlight ? 'checked="checked"' : ''); ?> id="edit-menu-item-tf-highlight-<?php echo $item_id?>" class="edit-menu-item-tf-highlight themify_field_tf-highlight widefat">
480 <?php _e( 'Highlight this link', 'themify' ) ?><br />
481 </label>
482 </div>
483 <?php endif;
484 }
485 add_action( 'wp_nav_menu_item_custom_fields', 'themify_menu_mega_option', 12, 4 );
486
487 /**
488 * Save the mega menu option for menu items
489 *
490 * @since 1.0.0
491 */
492 function themify_update_mega_menu_option( $menu_id, $menu_item_db_id, $args ) {
493 $meta_keys = array(
494 '_themify_mega_menu_item_tax' => 'menu-item-tf-mega_tax',
495 '_themify_mega_menu_columns_layout' => 'menu-item-tf-mega-columns-layout',
496 '_themify_highlight_link' => 'menu-item-tf-highlight',
497 );
498
499 /**
500 * save Mega Menu <select> option
501 * the Mega Menu option saves as two different custom fields, for backwards compatibility
502 */
503 if ( isset( $_POST['menu-item-tf-mega'][$menu_item_db_id] ) ) {
504 /* delete both keys first to ensure they are not both activated on a menu item at the same time */
505 delete_post_meta( $menu_item_db_id, '_themify_mega_menu_item' );
506 delete_post_meta( $menu_item_db_id, '_themify_mega_menu_column' );
507 delete_post_meta( $menu_item_db_id, '_themify_dropdown_columns' );
508 if( $_POST['menu-item-tf-mega'][ $menu_item_db_id ] != '' ) {
509 if ( $_POST['menu-item-tf-mega'][ $menu_item_db_id ] === 'mega' ) {
510 update_post_meta( $menu_item_db_id, '_themify_mega_menu_item', 1 );
511 } elseif( $_POST['menu-item-tf-mega'][ $menu_item_db_id ] === 'columns' ) {
512 update_post_meta( $menu_item_db_id, '_themify_mega_menu_column', 1 );
513 } elseif ( $_POST['menu-item-tf-mega'][ $menu_item_db_id ] === 'drop' && isset( $_POST['menu-item-tf-dropdown_columns'][ $menu_item_db_id ] ) ) {
514 update_post_meta( $menu_item_db_id, '_themify_dropdown_columns', $_POST['menu-item-tf-dropdown_columns'][ $menu_item_db_id ] );
515 }
516 }
517 }
518
519 foreach ( $meta_keys as $meta_key => $param_key ) {
520 $new_meta_value = isset( $_POST[$param_key] , $_POST[$param_key][$menu_item_db_id] ) ? $_POST[$param_key][$menu_item_db_id] : false;
521 if ( $new_meta_value ) {
522 update_post_meta( $menu_item_db_id, $meta_key, $new_meta_value );
523 } else {
524 delete_post_meta( $menu_item_db_id, $meta_key );
525 }
526 }
527 }
528 add_action( 'wp_update_nav_menu_item', 'themify_update_mega_menu_option', 10, 3 );
529
530 class Themify_Widgets_Menu {
531
532 private static $instance = null;
533 public $meta_key = '_themify_menu_widget';
534
535 /**
536 * Creates or returns an instance of this class.
537 *
538 * @return A single instance of this class.
539 */
540 public static function get_instance() {
541 return null == self::$instance ? self::$instance = new self : self::$instance;
542 }
543
544 private function __construct() {
545 if( is_admin() ) {
546 require_once( ABSPATH . 'wp-admin/includes/widgets.php' );
547 add_action( 'admin_init', array( $this, 'add_menu_meta_box' ) );
548 add_action( 'admin_enqueue_scripts', array( $this, 'nav_menu_script' ), 12 );
549 add_action( 'admin_footer-nav-menus.php', array( $this, 'admin_footer' ) );
550 add_action( 'wp_nav_menu_item_custom_fields', array( $this, 'wp_nav_menu_item_custom_fields' ), 99, 4 );
551 add_action( 'wp_update_nav_menu_item', array( $this, 'wp_update_nav_menu_item' ), 10, 3 );
552 }
553 }
554
555 function add_menu_meta_box() {
556 add_meta_box(
557 'themify-menu-widgets-meta',
558 __( 'Widgets', 'themify' ),
559 array( $this, 'widgets_menu_meta_box' ),
560 'nav-menus',
561 'side',
562 'high'
563 );
564 }
565
566 function widgets_menu_meta_box() {
567 global $wp_widget_factory;
568
569 ?>
570 <div id="themify-widget-section" class="posttypediv">
571 <label for="themify-menu-widgets"><?php _e( 'Widgets', 'themify' ); ?>:</label>
572 <select id="themify-menu-widgets" class="widefat">
573 <?php foreach( $wp_widget_factory->widgets as $widget ) : ?>
574 <option value="<?php echo get_class( $widget ); ?>"><?php echo $widget->name; ?> </option>
575 <?php endforeach; ?>
576 </select>
577
578 <p class="button-controls">
579 <span class="add-to-menu">
580 <input type="submit" class="button-secondary submit-add-to-menu right" value="<?php _e( 'Add to Menu', 'themify' ); ?>" name="add-post-type-menu-item" id="themify-widget-menu-submit">
581 </span>
582 </p>
583 </div>
584 <?php
585 }
586
587 function wp_nav_menu_item_custom_fields( $item_id, $item, $depth, $args ) {
588 if( $this->is_menu_widget( $item ) ) :
589 global $wp_widget_factory;
590 $class = $this->get_widget_menu_class( $item );
591
592 /* Check widget availability */
593 if ( ! isset( $wp_widget_factory->widgets[ $class ] ) )
594 return;
595 ?>
596 <input type="hidden" class="themify-widget-menu-type" value="widget" />
597 <div class="themify-widget-options" style="clear: both;">
598 <div class="widget-inside">
599 <div class="form">
600 <div class="widget-content">
601 <?php echo $this->get_widget_form( $class, $item_id, $item ); ?>
602 </div>
603 <input type="hidden" class="id_base" name="id_base" value="<?php echo esc_attr( $wp_widget_factory->widgets[$class]->id_base ) ?>" />
604 <input type="hidden" class="widget-id" name="widget-id" value="<?php echo time() ?>" />
605 </div>
606 </div>
607 </div>
608 <?php endif;
609 }
610
611 function wp_update_nav_menu_item( $menu_id, $menu_item_db_id, $args ) {
612 if ( isset( $_POST['menu-item-widget-options'],$_POST['menu-item-widget-options'][ $menu_item_db_id ] ) ) {
613 global $wp_widget_factory;
614 $new_instance = $_POST['menu-item-widget-options'][ $menu_item_db_id ];
615 /* the widget class is stored in the menu item URL field */
616 $widget_class = ltrim( $_POST['menu-item-url'][ $menu_item_db_id ], '#' );
617 if ( isset( $wp_widget_factory->widgets[ $widget_class ] ) ) {
618
619 $old_instance = get_post_meta( $menu_item_db_id, $this->meta_key, true );
620 if ( ! is_array( $old_instance ) )
621 $old_instance = array();
622 $instance = $wp_widget_factory->widgets[ $widget_class ]->update( $new_instance, $old_instance );
623 $instance = apply_filters( 'widget_update_callback', $instance, $new_instance, $old_instance, $wp_widget_factory->widgets[ $widget_class ] );
624 $this->save_meta( $this->meta_key, $instance, $menu_item_db_id );
625 }
626 }
627 }
628
629 function nav_menu_script() {
630 $screen = get_current_screen();
631 if( 'nav-menus' !== $screen->base )
632 return;
633
634 themify_enque_script( 'themify-widgets-menu-admin',THEMIFY_URI . '/megamenu/js/admin.js',THEMIFY_VERSION, array( 'jquery' ));
635 themify_enque_style( 'themify-widgets-menu-admin', THEMIFY_URI . '/megamenu/css/admin.css',null,THEMIFY_VERSION );
636
637 do_action( 'themify_widgets_menu_enqueue_admin_scripts' );
638 remove_action( 'admin_enqueue_scripts', array( $this, 'nav_menu_script' ), 12 );
639
640 /**
641 * Fire enqueue events for Wigets Manager in Menus screen.
642 * Disabled if using "Google Listings and Ads" plugin, since it throws a fatal error if its script is registered multiple times.
643 */
644 if ( defined( 'WC_GLA_VERSION' ) ) {
645 return;
646 }
647 do_action( 'sidebar_admin_setup' );
648 do_action( 'admin_enqueue_scripts', 'widgets.php' );
649 do_action( 'admin_print_styles-widgets.php' );
650 do_action( 'admin_print_scripts-widgets.php' );
651 }
652
653 function admin_footer() {
654 do_action( 'admin_footer-widgets.php' );
655 }
656
657 /**
658 * Returns an array of all registered widget classes
659 *
660 * @return array
661 */
662 function get_widget_types() {
663 global $wp_widget_factory;
664
665 return array_keys( (array) $wp_widget_factory->widgets );
666 }
667
668 /**
669 * Checks if the menu item is of "widget" type and returns the widget's base class name
670 *
671 * @return mixed string name of the base widget class, false otherwise
672 */
673 function get_widget_menu_class( $item ) {
674 $type = ltrim( $item->url, '#' );
675 return in_array( $type, $this->get_widget_types(),true )?$type:false;
676 }
677
678 function is_menu_widget( $item ) {
679 return $this->get_widget_menu_class( $item )?true:false;
680 }
681
682 /**
683 * Generates the widget form required for widget menu types
684 *
685 * @since 1.0
686 * @return string
687 */
688 function get_widget_form( $widget, $item_id, $item ) {
689 global $wp_widget_factory;
690
691 $options = $this->get_widget_options( $item_id );
692
693 ob_start();
694 $wp_widget_factory->widgets[$widget]->form( $options );
695 do_action_ref_array( 'in_widget_form', array( $wp_widget_factory->widgets[$widget], null, $options ) );
696 $form = ob_get_clean();
697 $base_name = 'widget-' . $wp_widget_factory->widgets[$widget]->id_base . '\[' . $wp_widget_factory->widgets[$widget]->number . '\]';
698 return preg_replace( "/{$base_name}/", 'menu-item-widget-options['. $item_id .']', $form );
699 }
700
701 /**
702 * Returns saved options for a widget menu type
703 *
704 * @since 1.0
705 * @return array
706 */
707 function get_widget_options( $item_id ) {
708 $options = get_post_meta( $item_id, $this->meta_key, true );
709 if( ! is_array( $options ) ) {
710 $options = array();
711 }
712
713 return $options;
714 }
715
716 /**
717 * Helper method that performs proper action on a metadata based on user input
718 *
719 * @since 1.0
720 */
721 public function save_meta( $meta_key, $new_meta_value, $post_id = null ) {
722 global $post;
723
724 if( ! $post_id )
725 $post_id = $post->ID;
726 $meta_value = get_post_meta( $post_id, $meta_key, true );
727 if ( $new_meta_value && '' == $meta_value )
728 add_post_meta( $post_id, $meta_key, $new_meta_value, true );
729 elseif ( $new_meta_value && $new_meta_value != $meta_value )
730 update_post_meta( $post_id, $meta_key, $new_meta_value );
731 elseif ( '' == $new_meta_value && $meta_value )
732 delete_post_meta( $post_id, $meta_key, $meta_value );
733 }
734
735 /**
736 * Renders a widget using the provided options
737 *
738 * @since 1.0
739 * @return string
740 */
741 function render_widget( $widget, $instance, $args = array() ) {
742 ob_start();
743 the_widget( $widget, $instance, apply_filters( 'themify_widget_menu_args', $args ) );
744 return ob_get_clean();
745 }
746 }
747 Themify_Widgets_Menu::get_instance();
748
749
750 /**
751 * Allow Layout Part post type in navigation menus
752 *
753 * @return array
754 * @since 3.3.5
755 */
756 function themify_allow_layout_parts_in_nav_menus( $args, $name ) {
757 if ( 'tbuilder_layout_part' === $name ) {
758 $args['show_in_nav_menus'] = true;
759 }
760
761 return $args;
762 }
763 // add_filter( 'register_post_type_args', 'themify_allow_layout_parts_in_nav_menus', 10, 2 );
764