~canonical-sysadmins/wordpress/5.1

« back to all changes in this revision

Viewing changes to wp-includes/class-wp-customize-nav-menus.php

  • Committer: Nick Moffitt
  • Date: 2016-04-14 10:43:32 UTC
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: nick.moffitt@canonical.com-20160414104332-61kvsia27qpmjquk
new upstream release 4.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
                $this->previewed_menus = array();
49
49
                $this->manager         = $manager;
50
50
 
 
51
                // Skip useless hooks when the user can't manage nav menus anyway.
 
52
                if ( ! current_user_can( 'edit_theme_options' ) ) {
 
53
                        return;
 
54
                }
 
55
 
 
56
                add_filter( 'customize_refresh_nonces', array( $this, 'filter_nonces' ) );
51
57
                add_action( 'wp_ajax_load-available-menu-items-customizer', array( $this, 'ajax_load_available_items' ) );
52
58
                add_action( 'wp_ajax_search-available-menu-items-customizer', array( $this, 'ajax_search_available_items' ) );
53
59
                add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
60
66
                add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_templates' ) );
61
67
                add_action( 'customize_controls_print_footer_scripts', array( $this, 'available_items_template' ) );
62
68
                add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) );
 
69
 
 
70
                // Selective Refresh partials.
 
71
                add_filter( 'customize_dynamic_partial_args', array( $this, 'customize_dynamic_partial_args' ), 10, 2 );
 
72
        }
 
73
 
 
74
        /**
 
75
         * Adds a nonce for customizing menus.
 
76
         *
 
77
         * @since 4.5.0
 
78
         * @access public
 
79
         *
 
80
         * @param array $nonces Array of nonces.
 
81
         * @return array $nonces Modified array of nonces.
 
82
         */
 
83
        public function filter_nonces( $nonces ) {
 
84
                $nonces['customize-menus'] = wp_create_nonce( 'customize-menus' );
 
85
                return $nonces;
63
86
        }
64
87
 
65
88
        /**
311
334
                        }
312
335
                }
313
336
 
 
337
                /**
 
338
                 * Filter the available menu items during a search request.
 
339
                 *
 
340
                 * @since 4.5.0
 
341
                 *
 
342
                 * @param array $items The array of menu items.
 
343
                 * @param array $args  Includes 'pagenum' and 's' (search) arguments.
 
344
                 */
 
345
                $items = apply_filters( 'customize_nav_menu_searched_items', $items, $args );
 
346
 
314
347
                return $items;
315
348
        }
316
349
 
329
362
 
330
363
                // Pass data to JS.
331
364
                $settings = array(
332
 
                        'nonce'                => wp_create_nonce( 'customize-menus' ),
333
365
                        'allMenus'             => wp_get_nav_menus(),
334
366
                        'itemTypes'            => $this->available_item_types(),
335
367
                        'l10n'                 => array(
336
368
                                'untitled'          => _x( '(no label)', 'missing menu item navigation label' ),
337
369
                                'unnamed'           => _x( '(unnamed)', 'Missing menu name.' ),
338
370
                                'custom_label'      => __( 'Custom Link' ),
339
 
                                /* translators: %s: menu location slug */
 
371
                                /* translators: %s: menu location */
340
372
                                'menuLocation'      => _x( '(Currently set to: %s)', 'menu' ),
341
373
                                'menuNameLabel'     => __( 'Menu Name' ),
342
374
                                'itemAdded'         => __( 'Menu item added' ),
361
393
                                'reorderLabelOn'    => esc_attr__( 'Reorder menu items' ),
362
394
                                'reorderLabelOff'   => esc_attr__( 'Close reorder mode' ),
363
395
                        ),
364
 
                        'menuItemTransport'    => 'postMessage',
 
396
                        'settingTransport'     => 'postMessage',
365
397
                        'phpIntMax'            => PHP_INT_MAX,
366
398
                        'defaultSettingValues' => array(
367
399
                                'nav_menu'      => $temp_nav_menu_setting->default,
368
400
                                'nav_menu_item' => $temp_nav_menu_item_setting->default,
369
401
                        ),
 
402
                        'locationSlugMappedToName' => get_registered_nav_menus(),
370
403
                );
371
404
 
372
405
                $data = sprintf( 'var _wpCustomizeNavMenusSettings = %s;', wp_json_encode( $settings ) );
411
444
        public function filter_dynamic_setting_args( $setting_args, $setting_id ) {
412
445
                if ( preg_match( WP_Customize_Nav_Menu_Setting::ID_PATTERN, $setting_id ) ) {
413
446
                        $setting_args = array(
414
 
                                'type' => WP_Customize_Nav_Menu_Setting::TYPE,
 
447
                                'type'      => WP_Customize_Nav_Menu_Setting::TYPE,
 
448
                                'transport' => 'postMessage',
415
449
                        );
416
450
                } elseif ( preg_match( WP_Customize_Nav_Menu_Item_Setting::ID_PATTERN, $setting_id ) ) {
417
451
                        $setting_args = array(
418
 
                                'type' => WP_Customize_Nav_Menu_Item_Setting::TYPE,
 
452
                                'type'      => WP_Customize_Nav_Menu_Item_Setting::TYPE,
 
453
                                'transport' => 'postMessage',
419
454
                        );
420
455
                }
421
456
                return $setting_args;
534
569
                        ) ) );
535
570
 
536
571
                        $nav_menu_setting_id = 'nav_menu[' . $menu_id . ']';
537
 
                        $this->manager->add_setting( new WP_Customize_Nav_Menu_Setting( $this->manager, $nav_menu_setting_id ) );
 
572
                        $this->manager->add_setting( new WP_Customize_Nav_Menu_Setting( $this->manager, $nav_menu_setting_id, array(
 
573
                                'transport' => 'postMessage',
 
574
                        ) ) );
538
575
 
539
576
                        // Add the menu contents.
540
577
                        $menu_items = (array) wp_get_nav_menu_items( $menu_id );
547
584
                                $value = (array) $item;
548
585
                                $value['nav_menu_term_id'] = $menu_id;
549
586
                                $this->manager->add_setting( new WP_Customize_Nav_Menu_Item_Setting( $this->manager, $menu_item_setting_id, array(
550
 
                                        'value' => $value,
 
587
                                        'value'     => $value,
 
588
                                        'transport' => 'postMessage',
551
589
                                ) ) );
552
590
 
553
591
                                // Create a control for each menu item.
568
606
                        'priority' => 999,
569
607
                ) ) );
570
608
 
571
 
                $this->manager->add_setting( 'new_menu_name', array(
572
 
                        'type'      => 'new_menu',
573
 
                        'default'   => '',
574
 
                        'transport' => 'postMessage',
575
 
                ) );
576
 
 
577
609
                $this->manager->add_control( 'new_menu_name', array(
578
610
                        'label'       => '',
579
611
                        'section'     => 'add_menu',
580
612
                        'type'        => 'text',
 
613
                        'settings'    => array(),
581
614
                        'input_attrs' => array(
582
615
                                'class'       => 'menu-name-field',
583
616
                                'placeholder' => __( 'New menu name' ),
584
617
                        ),
585
618
                ) );
586
619
 
587
 
                $this->manager->add_setting( 'create_new_menu', array(
588
 
                        'type' => 'new_menu',
589
 
                ) );
590
 
 
591
620
                $this->manager->add_control( new WP_Customize_New_Menu_Control( $this->manager, 'create_new_menu', array(
592
 
                        'section' => 'add_menu',
 
621
                        'section'  => 'add_menu',
 
622
                        'settings' => array(),
593
623
                ) ) );
594
624
        }
595
625
 
743
773
                                                <span class="toggle-indicator" aria-hidden="true"></span>
744
774
                                        </button>
745
775
                                </h4>
746
 
                                <div class="accordion-section-content">
 
776
                                <div class="accordion-section-content customlinkdiv">
747
777
                                        <input type="hidden" value="custom" id="custom-menu-item-type" name="menu-item[-1][menu-item-type]" />
748
 
                                        <p id="menu-item-url-wrap">
749
 
                                                <label class="howto" for="custom-menu-item-url">
750
 
                                                        <span><?php _e( 'URL' ); ?></span>
751
 
                                                        <input id="custom-menu-item-url" name="menu-item[-1][menu-item-url]" type="text" class="code menu-item-textbox" value="http://">
752
 
                                                </label>
 
778
                                        <p id="menu-item-url-wrap" class="wp-clearfix">
 
779
                                                <label class="howto" for="custom-menu-item-url"><?php _e( 'URL' ); ?></label>
 
780
                                                <input id="custom-menu-item-url" name="menu-item[-1][menu-item-url]" type="text" class="code menu-item-textbox" value="http://">
753
781
                                        </p>
754
 
                                        <p id="menu-item-name-wrap">
755
 
                                                <label class="howto" for="custom-menu-item-name">
756
 
                                                        <span><?php _e( 'Link Text' ); ?></span>
757
 
                                                        <input id="custom-menu-item-name" name="menu-item[-1][menu-item-title]" type="text" class="regular-text menu-item-textbox">
758
 
                                                </label>
 
782
                                        <p id="menu-item-name-wrap" class="wp-clearfix">
 
783
                                                <label class="howto" for="custom-menu-item-name"><?php _e( 'Link Text' ); ?></label>
 
784
                                                <input id="custom-menu-item-name" name="menu-item[-1][menu-item-title]" type="text" class="regular-text menu-item-textbox">
759
785
                                        </p>
760
786
                                        <p class="button-controls">
761
787
                                                <span class="add-to-menu">
791
817
        <?php
792
818
        }
793
819
 
 
820
        //
794
821
        // Start functionality specific to partial-refresh of menu changes in Customizer preview.
795
 
        const RENDER_AJAX_ACTION = 'customize_render_menu_partial';
796
 
        const RENDER_NONCE_POST_KEY = 'render-menu-nonce';
797
 
        const RENDER_QUERY_VAR = 'wp_customize_menu_render';
798
 
 
799
 
        /**
800
 
         * The number of wp_nav_menu() calls which have happened in the preview.
801
 
         *
802
 
         * @since 4.3.0
803
 
         * @access public
804
 
         * @var int
805
 
         */
806
 
        public $preview_nav_menu_instance_number = 0;
807
 
 
808
 
        /**
809
 
         * Nav menu args used for each instance.
 
822
        //
 
823
 
 
824
        /**
 
825
         * Nav menu args used for each instance, keyed by the args HMAC.
810
826
         *
811
827
         * @since 4.3.0
812
828
         * @access public
815
831
        public $preview_nav_menu_instance_args = array();
816
832
 
817
833
        /**
 
834
         * Filter arguments for dynamic nav_menu selective refresh partials.
 
835
         *
 
836
         * @since 4.5.0
 
837
         * @access public
 
838
         *
 
839
         * @param array|false $partial_args Partial args.
 
840
         * @param string      $partial_id   Partial ID.
 
841
         * @return array Partial args.
 
842
         */
 
843
        public function customize_dynamic_partial_args( $partial_args, $partial_id ) {
 
844
 
 
845
                if ( preg_match( '/^nav_menu_instance\[[0-9a-f]{32}\]$/', $partial_id ) ) {
 
846
                        if ( false === $partial_args ) {
 
847
                                $partial_args = array();
 
848
                        }
 
849
                        $partial_args = array_merge(
 
850
                                $partial_args,
 
851
                                array(
 
852
                                        'type'                => 'nav_menu_instance',
 
853
                                        'render_callback'     => array( $this, 'render_nav_menu_partial' ),
 
854
                                        'container_inclusive' => true,
 
855
                                        'settings'            => array(), // Empty because the nav menu instance may relate to a menu or a location.
 
856
                                        'capability'          => 'edit_theme_options',
 
857
                                )
 
858
                        );
 
859
                }
 
860
 
 
861
                return $partial_args;
 
862
        }
 
863
 
 
864
        /**
818
865
         * Add hooks for the Customizer preview.
819
866
         *
820
867
         * @since 4.3.0
821
868
         * @access public
822
869
         */
823
870
        public function customize_preview_init() {
824
 
                add_action( 'template_redirect', array( $this, 'render_menu' ) );
825
871
                add_action( 'wp_enqueue_scripts', array( $this, 'customize_preview_enqueue_deps' ) );
826
 
 
827
 
                if ( ! isset( $_REQUEST[ self::RENDER_QUERY_VAR ] ) ) {
828
 
                        add_filter( 'wp_nav_menu_args', array( $this, 'filter_wp_nav_menu_args' ), 1000 );
829
 
                        add_filter( 'wp_nav_menu', array( $this, 'filter_wp_nav_menu' ), 10, 2 );
830
 
                }
 
872
                add_filter( 'wp_nav_menu_args', array( $this, 'filter_wp_nav_menu_args' ), 1000 );
 
873
                add_filter( 'wp_nav_menu', array( $this, 'filter_wp_nav_menu' ), 10, 2 );
 
874
                add_filter( 'wp_footer', array( $this, 'export_preview_data' ), 1 );
 
875
                add_filter( 'customize_render_partials_response', array( $this, 'export_partial_rendered_nav_menu_instances' ) );
831
876
        }
832
877
 
833
878
        /**
835
880
         *
836
881
         * @since 4.3.0
837
882
         * @access public
838
 
         *
839
883
         * @see wp_nav_menu()
 
884
         * @see WP_Customize_Widgets_Partial_Refresh::filter_dynamic_sidebar_params()
840
885
         *
841
886
         * @param array $args An array containing wp_nav_menu() arguments.
842
887
         * @return array Arguments.
843
888
         */
844
889
        public function filter_wp_nav_menu_args( $args ) {
845
 
                $this->preview_nav_menu_instance_number += 1;
846
 
                $args['instance_number'] = $this->preview_nav_menu_instance_number;
847
 
 
 
890
                /*
 
891
                 * The following conditions determine whether or not this instance of
 
892
                 * wp_nav_menu() can use selective refreshed. A wp_nav_menu() can be
 
893
                 * selective refreshed if...
 
894
                 */
848
895
                $can_partial_refresh = (
 
896
                        // ...if wp_nav_menu() is directly echoing out the menu (and thus isn't manipulating the string after generated),
849
897
                        ! empty( $args['echo'] )
850
898
                        &&
 
899
                        // ...and if the fallback_cb can be serialized to JSON, since it will be included in the placement context data,
851
900
                        ( empty( $args['fallback_cb'] ) || is_string( $args['fallback_cb'] ) )
852
901
                        &&
 
902
                        // ...and if the walker can also be serialized to JSON, since it will be included in the placement context data as well,
853
903
                        ( empty( $args['walker'] ) || is_string( $args['walker'] ) )
854
 
                        &&
855
 
                        (
 
904
                        // ...and if it has a theme location assigned or an assigned menu to display,
 
905
                        && (
856
906
                                ! empty( $args['theme_location'] )
857
907
                                ||
858
908
                                ( ! empty( $args['menu'] ) && ( is_numeric( $args['menu'] ) || is_object( $args['menu'] ) ) )
859
909
                        )
 
910
                        &&
 
911
                        // ...and if the nav menu would be rendered with a wrapper container element (upon which to attach data-* attributes).
 
912
                        (
 
913
                                ! empty( $args['container'] )
 
914
                                ||
 
915
                                ( isset( $args['items_wrap'] ) && '<' === substr( $args['items_wrap'], 0, 1 ) )
 
916
                        )
860
917
                );
861
918
                $args['can_partial_refresh'] = $can_partial_refresh;
862
919
 
863
 
                $hashed_args = $args;
 
920
                $exported_args = $args;
864
921
 
 
922
                // Empty out args which may not be JSON-serializable.
865
923
                if ( ! $can_partial_refresh ) {
866
 
                        $hashed_args['fallback_cb'] = '';
867
 
                        $hashed_args['walker'] = '';
868
 
                }
869
 
 
870
 
                // Replace object menu arg with a term_id menu arg, as this exports better to JS and is easier to compare hashes.
871
 
                if ( ! empty( $hashed_args['menu'] ) && is_object( $hashed_args['menu'] ) ) {
872
 
                        $hashed_args['menu'] = $hashed_args['menu']->term_id;
873
 
                }
874
 
 
875
 
                ksort( $hashed_args );
876
 
                $hashed_args['args_hash'] = $this->hash_nav_menu_args( $hashed_args );
877
 
 
878
 
                $this->preview_nav_menu_instance_args[ $this->preview_nav_menu_instance_number ] = $hashed_args;
 
924
                        $exported_args['fallback_cb'] = '';
 
925
                        $exported_args['walker'] = '';
 
926
                }
 
927
 
 
928
                /*
 
929
                 * Replace object menu arg with a term_id menu arg, as this exports better
 
930
                 * to JS and is easier to compare hashes.
 
931
                 */
 
932
                if ( ! empty( $exported_args['menu'] ) && is_object( $exported_args['menu'] ) ) {
 
933
                        $exported_args['menu'] = $exported_args['menu']->term_id;
 
934
                }
 
935
 
 
936
                ksort( $exported_args );
 
937
                $exported_args['args_hmac'] = $this->hash_nav_menu_args( $exported_args );
 
938
 
 
939
                $args['customize_preview_nav_menus_args'] = $exported_args;
 
940
                $this->preview_nav_menu_instance_args[ $exported_args['args_hmac'] ] = $exported_args;
879
941
                return $args;
880
942
        }
881
943
 
882
944
        /**
883
 
         * Prepare wp_nav_menu() calls for partial refresh. Wraps output in container for refreshing.
 
945
         * Prepares wp_nav_menu() calls for partial refresh.
 
946
         *
 
947
         * Injects attributes into container element.
884
948
         *
885
949
         * @since 4.3.0
886
950
         * @access public
892
956
         * @return null
893
957
         */
894
958
        public function filter_wp_nav_menu( $nav_menu_content, $args ) {
895
 
                if ( ! empty( $args->can_partial_refresh ) && ! empty( $args->instance_number ) ) {
896
 
                        $nav_menu_content = preg_replace(
897
 
                                '/(?<=class=")/',
898
 
                                sprintf( 'partial-refreshable-nav-menu partial-refreshable-nav-menu-%1$d ', $args->instance_number ),
899
 
                                $nav_menu_content,
900
 
                                1 // Only update the class on the first element found, the menu container.
901
 
                        );
 
959
                if ( isset( $args->customize_preview_nav_menus_args['can_partial_refresh'] ) && $args->customize_preview_nav_menus_args['can_partial_refresh'] ) {
 
960
                        $attributes = sprintf( ' data-customize-partial-id="%s"', esc_attr( 'nav_menu_instance[' . $args->customize_preview_nav_menus_args['args_hmac'] . ']' ) );
 
961
                        $attributes .= ' data-customize-partial-type="nav_menu_instance"';
 
962
                        $attributes .= sprintf( ' data-customize-partial-placement-context="%s"', esc_attr( wp_json_encode( $args->customize_preview_nav_menus_args ) ) );
 
963
                        $nav_menu_content = preg_replace( '#^(<\w+)#', '$1 ' . $attributes, $nav_menu_content, 1 );
902
964
                }
903
965
                return $nav_menu_content;
904
966
        }
905
967
 
906
968
        /**
907
 
         * Hash (hmac) the arguments with the nonce and secret auth key to ensure they
908
 
         * are not tampered with when submitted in the Ajax request.
 
969
         * Hashes (hmac) the nav menu arguments to ensure they are not tampered with when
 
970
         * submitted in the Ajax request.
 
971
         *
 
972
         * Note that the array is expected to be pre-sorted.
909
973
         *
910
974
         * @since 4.3.0
911
975
         * @access public
912
976
         *
913
977
         * @param array $args The arguments to hash.
914
 
         * @return string
 
978
         * @return string Hashed nav menu arguments.
915
979
         */
916
980
        public function hash_nav_menu_args( $args ) {
917
 
                return wp_hash( wp_create_nonce( self::RENDER_AJAX_ACTION ) . serialize( $args ) );
 
981
                return wp_hash( serialize( $args ) );
918
982
        }
919
983
 
920
984
        /**
924
988
         * @access public
925
989
         */
926
990
        public function customize_preview_enqueue_deps() {
927
 
                wp_enqueue_script( 'customize-preview-nav-menus' );
 
991
                wp_enqueue_script( 'customize-preview-nav-menus' ); // Note that we have overridden this.
928
992
                wp_enqueue_style( 'customize-preview' );
929
 
 
930
 
                add_action( 'wp_print_footer_scripts', array( $this, 'export_preview_data' ) );
931
993
        }
932
994
 
933
995
        /**
934
 
         * Export data from PHP to JS.
 
996
         * Exports data from PHP to JS.
935
997
         *
936
998
         * @since 4.3.0
937
999
         * @access public
940
1002
 
941
1003
                // Why not wp_localize_script? Because we're not localizing, and it forces values into strings.
942
1004
                $exports = array(
943
 
                        'renderQueryVar'        => self::RENDER_QUERY_VAR,
944
 
                        'renderNonceValue'      => wp_create_nonce( self::RENDER_AJAX_ACTION ),
945
 
                        'renderNoncePostKey'    => self::RENDER_NONCE_POST_KEY,
946
 
                        'requestUri'            => empty( $_SERVER['REQUEST_URI'] ) ? home_url( '/' ) : esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ),
947
 
                        'theme'                 => array(
948
 
                                'stylesheet' => $this->manager->get_stylesheet(),
949
 
                                'active'     => $this->manager->is_theme_active(),
950
 
                        ),
951
 
                        'previewCustomizeNonce' => wp_create_nonce( 'preview-customize_' . $this->manager->get_stylesheet() ),
952
 
                        'navMenuInstanceArgs'   => $this->preview_nav_menu_instance_args,
 
1005
                        'navMenuInstanceArgs' => $this->preview_nav_menu_instance_args,
953
1006
                );
954
 
 
955
1007
                printf( '<script>var _wpCustomizePreviewNavMenusExports = %s;</script>', wp_json_encode( $exports ) );
956
1008
        }
957
1009
 
958
1010
        /**
 
1011
         * Export any wp_nav_menu() calls during the rendering of any partials.
 
1012
         *
 
1013
         * @since 4.5.0
 
1014
         * @access public
 
1015
         *
 
1016
         * @param array $response Response.
 
1017
         * @return array Response.
 
1018
         */
 
1019
        public function export_partial_rendered_nav_menu_instances( $response ) {
 
1020
                $response['nav_menu_instance_args'] = $this->preview_nav_menu_instance_args;
 
1021
                return $response;
 
1022
        }
 
1023
 
 
1024
        /**
959
1025
         * Render a specific menu via wp_nav_menu() using the supplied arguments.
960
1026
         *
961
1027
         * @since 4.3.0
962
1028
         * @access public
963
1029
         *
964
1030
         * @see wp_nav_menu()
 
1031
         *
 
1032
         * @param WP_Customize_Partial $partial       Partial.
 
1033
         * @param array                $nav_menu_args Nav menu args supplied as container context.
 
1034
         * @return string|false
965
1035
         */
966
 
        public function render_menu() {
967
 
                if ( empty( $_POST[ self::RENDER_QUERY_VAR ] ) ) {
968
 
                        return;
969
 
                }
970
 
 
971
 
                $this->manager->remove_preview_signature();
972
 
 
973
 
                if ( empty( $_POST[ self::RENDER_NONCE_POST_KEY ] ) ) {
974
 
                        wp_send_json_error( 'missing_nonce_param' );
975
 
                }
976
 
 
977
 
                if ( ! is_customize_preview() ) {
978
 
                        wp_send_json_error( 'expected_customize_preview' );
979
 
                }
980
 
 
981
 
                if ( ! check_ajax_referer( self::RENDER_AJAX_ACTION, self::RENDER_NONCE_POST_KEY, false ) ) {
982
 
                        wp_send_json_error( 'nonce_check_fail' );
983
 
                }
984
 
 
985
 
                if ( ! current_user_can( 'edit_theme_options' ) ) {
986
 
                        wp_send_json_error( 'unauthorized' );
987
 
                }
988
 
 
989
 
                if ( ! isset( $_POST['wp_nav_menu_args'] ) ) {
990
 
                        wp_send_json_error( 'missing_param' );
991
 
                }
992
 
 
993
 
                if ( ! isset( $_POST['wp_nav_menu_args_hash'] ) ) {
994
 
                        wp_send_json_error( 'missing_param' );
995
 
                }
996
 
 
997
 
                $wp_nav_menu_args = json_decode( wp_unslash( $_POST['wp_nav_menu_args'] ), true );
998
 
                if ( ! is_array( $wp_nav_menu_args ) ) {
999
 
                        wp_send_json_error( 'wp_nav_menu_args_not_array' );
1000
 
                }
1001
 
 
1002
 
                $wp_nav_menu_args_hash = sanitize_text_field( wp_unslash( $_POST['wp_nav_menu_args_hash'] ) );
1003
 
                if ( ! hash_equals( $this->hash_nav_menu_args( $wp_nav_menu_args ), $wp_nav_menu_args_hash ) ) {
1004
 
                        wp_send_json_error( 'wp_nav_menu_args_hash_mismatch' );
1005
 
                }
1006
 
 
1007
 
                $wp_nav_menu_args['echo'] = false;
1008
 
                wp_send_json_success( wp_nav_menu( $wp_nav_menu_args ) );
 
1036
        public function render_nav_menu_partial( $partial, $nav_menu_args ) {
 
1037
                unset( $partial );
 
1038
 
 
1039
                if ( ! isset( $nav_menu_args['args_hmac'] ) ) {
 
1040
                        // Error: missing_args_hmac.
 
1041
                        return false;
 
1042
                }
 
1043
 
 
1044
                $nav_menu_args_hmac = $nav_menu_args['args_hmac'];
 
1045
                unset( $nav_menu_args['args_hmac'] );
 
1046
 
 
1047
                ksort( $nav_menu_args );
 
1048
                if ( ! hash_equals( $this->hash_nav_menu_args( $nav_menu_args ), $nav_menu_args_hmac ) ) {
 
1049
                        // Error: args_hmac_mismatch.
 
1050
                        return false;
 
1051
                }
 
1052
 
 
1053
                ob_start();
 
1054
                wp_nav_menu( $nav_menu_args );
 
1055
                $content = ob_get_clean();
 
1056
 
 
1057
                return $content;
1009
1058
        }
1010
1059
}