Plugin Directory

Changeset 3441285


Ignore:
Timestamp:
01/16/2026 09:52:08 PM (7 weeks ago)
Author:
linux4me2
Message:

Tagging version 1.4.0

Location:
menu-in-post
Files:
6 added
2 deleted
8 edited
1 copied

Legend:

Unmodified
Added
Removed
  • menu-in-post/tags/1.4.0/admin/admin.php

    r2994821 r3441285  
    11<?php
    22/**
     3 * Admin functions for Menu In Post
     4 *
     5 * @package menu-in-post
     6 * @since 1.0.0
     7 */
     8
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
     13
     14/**
    315 * Menu In Post options and settings.
    416 *
    5  * @return Nothing
    6  */
    7 function initMenuInPostOptions()
    8 {
    9     // Register option array.
    10     register_setting(
    11         'menu-in-post',
    12         'mip_options'
    13     );
    14    
    15     add_settings_section(
    16         'mip_options_section_js',
    17         __('Javascript Options', 'menu-in-post'),
    18         'callbackMIPJSOptions',
    19         'menu-in-post-options'
    20     );
    21    
    22     /*
    23         Register a new field in the "mip_options_section_js" section, on the
    24         menu-in-post-options page.
    25        
    26         Note: As of WP 4.6, the settings ID is only used internally.
    27        
    28         Use the $args "label_for" to populate the ID inside the callback.
    29        
    30         Note: If you ever add or change settings, make sure you change the
    31         defaults you have set for the get_options() function calls both in
    32         admin.php and in menu-in-post.php.
    33     */
    34     add_settings_field(
    35         'miploadjs',
    36         __('Load JavaScript:', 'menu-in-post'),
    37         'callbackMenuInPostFieldLoadJS',
    38         'menu-in-post-options',
    39         'mip_options_section_js',
    40         array(
    41             'label_for' => 'miploadjs',
    42             'class' => 'mip-option-row'
    43         )
    44     );
    45     add_settings_field(
    46         'miponlypages',
    47         __('Only on Posts/Pages:'),
    48         'callbackMenuInPostFieldOnlyPages',
    49         'menu-in-post-options',
    50         'mip_options_section_js',
    51         array(
    52             'label_for' => 'miponlypages',
    53             'class' => 'mip-options-row mip-only-pages-row'
    54         )
    55     );
    56     add_settings_field(
    57         'mipminimizejs',
    58         __('Minimize JavaScript:'),
    59         'callbackMenuInPostMinimizeJS',
    60         'menu-in-post-options',
    61         'mip_options_section_js',
    62         array(
    63             'label_for' => 'mipminimizejs',
    64             'class' => 'mip-option-row'
    65         )
    66     );
    67    
    68     if (wp_is_block_theme()) {
    69         add_settings_section(
    70             'mip_options_section_appearance_menus',
    71             __('Show Appearance > Menus Submenu Item', 'menu-in-post'),
    72             'callbackMIPAppearanceMenus',
    73             'menu-in-post-options'
    74         );
    75        
    76         add_settings_field(
    77             'mipaddappearancemenu',
    78             __('Show Appearance > Menus:'),
    79             'callbackMIPShowAppearanceMenus',
    80             'menu-in-post-options',
    81             'mip_options_section_appearance_menus',
    82             array(
    83                 'label_for' => 'mipshowappearancemenus',
    84                 'class' => 'mip-option-row'
    85             )
    86         );
    87     }
    88 }
    89 
    90 /**
    91  * Register initMenuInPostOptions to the admin_init action hook.
    92  */
    93 add_action('admin_init', 'initMenuInPostOptions');
     17 * @return void
     18 */
     19function init_menu_in_post_options() {
     20    // Register option array.
     21    register_setting(
     22        'menu-in-post',
     23        'mip_options'
     24    );
     25
     26    add_settings_section(
     27        'mip_options_section_js',
     28        __( 'Javascript Options', 'menu-in-post' ),
     29        'callback_mipjs_options',
     30        'menu-in-post-options'
     31    );
     32
     33    /*
     34        Register a new field in the "mip_options_section_js" section, on the
     35        menu-in-post-options page.
     36
     37        Note: As of WP 4.6, the settings ID is only used internally.
     38
     39        Use the $args "label_for" to populate the ID inside the callback.
     40
     41        Note: If you ever add or change settings, make sure you change the
     42        defaults you have set for the get_options() function calls both in
     43        admin.php and in menu-in-post.php.
     44    */
     45    add_settings_field(
     46        'miploadjs',
     47        __( 'Load JavaScript:', 'menu-in-post' ),
     48        'callback_mip_field_load_js',
     49        'menu-in-post-options',
     50        'mip_options_section_js',
     51        array(
     52            'label_for' => 'miploadjs',
     53            'class'     => 'mip-option-row',
     54        )
     55    );
     56    add_settings_field(
     57        'miponlypages',
     58        __( 'Only on Posts/Pages:' ),
     59        'callback_mip_field_only_pages',
     60        'menu-in-post-options',
     61        'mip_options_section_js',
     62        array(
     63            'label_for' => 'miponlypages',
     64            'class'     => 'mip-options-row mip-only-pages-row',
     65        )
     66    );
     67    add_settings_field(
     68        'mipminimizejs',
     69        __( 'Minimize JavaScript:' ),
     70        'callback_mip_minimize_js',
     71        'menu-in-post-options',
     72        'mip_options_section_js',
     73        array(
     74            'label_for' => 'mipminimizejs',
     75            'class'     => 'mip-option-row',
     76        )
     77    );
     78
     79    if ( wp_is_block_theme() ) {
     80        add_settings_section(
     81            'mip_options_section_appearance_menus',
     82            __( 'Show Appearance > Menus Submenu Item', 'menu-in-post' ),
     83            'callback_mip_appearance_menus',
     84            'menu-in-post-options'
     85        );
     86
     87        add_settings_field(
     88            'mipaddappearancemenu',
     89            __( 'Show Appearance > Menus:' ),
     90            'callback_mip_show_appearance_menus',
     91            'menu-in-post-options',
     92            'mip_options_section_appearance_menus',
     93            array(
     94                'label_for' => 'mipshowappearancemenus',
     95                'class'     => 'mip-option-row',
     96            )
     97        );
     98    }
     99}
     100
     101/**
     102 * Register init_menu_in_post_options to the admin_init action hook.
     103 */
     104add_action( 'admin_init', 'init_menu_in_post_options' );
    94105
    95106/**
     
    98109 * @param array $args Arguments passed to the callback function.
    99110 *
    100  * @return Returns the HTML for the intro.
    101  */
    102 function callbackMIPJSOptions($args)
    103 {
    104     $str = esc_html_e(
    105         'Use the following settings to control how Menu In Post&#39;s JavaScript ' .
    106             'is handled. Click the Help Tab for more information.',
    107         'menu-in-post'
    108     );
    109     ?>
    110     <p id="<?php echo esc_attr($args['id']); ?>">
    111        <?php echo $str; ?>
    112     </p>
    113     <?php
     111 * @return void
     112 */
     113function callback_mipjs_options( $args ) {
     114    // Returns the HTML for the intro.
     115    $str = esc_html__(
     116        "Use the following settings to control how Menu In Post's JavaScript is handled. Click the Help Tab for more information.",
     117        'menu-in-post'
     118    );
     119    ?>
     120    <p id="<?php echo esc_attr( $args['id'] ); ?>">
     121        <?php echo esc_html( $str ); // $str is already escaped, but still generates a warning, so escape it again ?>
     122    </p>
     123    <?php
    114124}
    115125
     
    119129 * @param array $args Arguments passed to the callback function.
    120130 *
    121  * @return Returns the HTML for the intro.
    122  */
    123 function callbackMIPAppearanceMenus($args)
    124 {
    125     $str = esc_html_e(
    126         'Since WordPress version 5.9, the Appearance > Menus menu item is hidden ' .
    127             'for block-enabled themes. Set &quot;Show Appearance > Menus&quot; ' .
    128             'to &quot;yes&quot; to display the menu.',
    129         'menu-in-post'
    130     );
    131     ?>
    132     <p id="<?php echo esc_attr($args['id']); ?>">
    133        <?php echo $str; ?>
    134     </p>
    135     <?php
     131 * @return void
     132 */
     133function callback_mip_appearance_menus( $args ) {
     134    // Returns the HTML for the intro.
     135    $str = esc_html__(
     136        'Since WordPress version 5.9, the Appearance > Menus menu item is hidden for block-enabled themes. Set "Show Appearance > Menus" to "yes" to display the menu.',
     137        'menu-in-post'
     138    );
     139    ?>
     140    <p id="<?php echo esc_attr( $args['id'] ); ?>">
     141        <?php echo esc_html( $str ); // $str is already escaped above, but still generates a warning, so escape it again. ?>
     142    </p>
     143    <?php
    136144}
    137145
     
    141149 * @param array $args Arguments passed to the callback function.
    142150 *
    143  * @return Returns the HTML.
    144  */
    145 function callbackMenuInPostFieldLoadJS($args)
    146 {
    147     $options = get_option('mip_options');
    148     ?>
    149     <select
    150         id="<?php echo esc_attr($args['label_for']); ?>"
    151         name="mip_options[<?php echo esc_attr($args['label_for']); ?>]"
    152     >
    153         <?php
    154         $vals = array(
    155             'always' => 'always (default)',
    156             'never' => 'never',
    157             'onlypages' => 'only on posts/pages'
    158         );
    159         foreach ($vals as $val => $desc) {
    160             $selected = '';
    161             if (isset($options[$args['label_for']])
    162                 && $options[$args['label_for']] == $val
    163             ) {
    164                 $selected = ' selected';
    165             }
    166             ?>
    167             <option
    168                 value="<?php echo $val; ?>"
    169                 <?php echo $selected; ?>
    170             >
    171                 <?php echo $desc; ?>
    172             </option>
    173             <?php
    174         }
    175         ?>
    176     </select>
    177     <?php
     151 * @return void
     152 */
     153function callback_mip_field_load_js( $args ) {
     154    // Returns the HTML.
     155    $options = get_option( 'mip_options' );
     156    ?>
     157    <select
     158        id="<?php echo esc_attr( $args['label_for'] ); ?>"
     159        name="mip_options[<?php echo esc_attr( $args['label_for'] ); ?>]"
     160    >
     161        <?php
     162        $vals = array(
     163            'always'    => 'always (default)',
     164            'never'     => 'never',
     165            'onlypages' => 'only on posts/pages',
     166        );
     167        foreach ( $vals as $val => $desc ) {
     168            $selected = '';
     169            if ( isset( $options[ $args['label_for'] ] )
     170                && $options[ $args['label_for'] ] === $val
     171            ) {
     172                $selected = ' selected';
     173            }
     174            ?>
     175            <option
     176                value="<?php echo esc_html( $val ); ?>"
     177                <?php echo esc_html( $selected ); ?>
     178            >
     179                <?php echo esc_html( $desc ); ?>
     180            </option>
     181            <?php
     182        }
     183        ?>
     184    </select>
     185    <?php
    178186}
    179187
     
    183191 * @param array $args Arguments passed to the callback function.
    184192 *
    185  * @return Returns the HTML.
    186  */
    187 function callbackMenuInPostFieldOnlyPages($args)
    188 {
    189     $options = get_option('mip_options');
    190     if (isset($options[$args['label_for']])) {
    191         $val = $options[$args['label_for']];
    192     } else {
    193         $val = '';
    194     }
    195     ?>
    196     <input
    197         id="<?php echo esc_attr($args['label_for']); ?>"
    198         name="mip_options[<?php echo esc_attr($args['label_for']); ?>]"
    199         type="text"
    200         placeholder="comma-separated post/page IDs"
    201         value="<?php echo $val; ?>"
    202     >
    203     <?php
     193 * @return void
     194 */
     195function callback_mip_field_only_pages( $args ) {
     196    // Returns the HTML.
     197    $options = get_option( 'mip_options' );
     198    if ( isset( $options[ $args['label_for'] ] ) ) {
     199        $val = $options[ $args['label_for'] ];
     200    } else {
     201        $val = '';
     202    }
     203    ?>
     204    <input
     205        id="<?php echo esc_attr( $args['label_for'] ); ?>"
     206        name="mip_options[<?php echo esc_attr( $args['label_for'] ); ?>]"
     207        type="text"
     208        placeholder="comma-separated post/page IDs"
     209        value="<?php echo esc_html( $val ); ?>"
     210    >
     211    <?php
    204212}
    205213
     
    209217 * @param array $args Arguments passed to the callback function.
    210218 *
    211  * @return Returns the HTML.
    212  */
    213 function callbackMenuInPostMinimizeJS($args)
    214 {
    215     $options = get_option('mip_options');
    216     if (isset($options[$args['label_for']])) {
    217         $selected = ' selected';
    218     } else {
    219         $selected = '';
    220     }
    221     ?>
    222     <select
    223         id="<?php echo esc_attr($args['label_for']); ?>"
    224         name="mip_options[<?php echo esc_attr($args['label_for']); ?>]"
    225     >
    226         <?php
    227         $vals = array(
    228             'yes' => 'yes (default)',
    229             'no' => 'no'
    230         );
    231         foreach ($vals as $val => $desc) {
    232             $selected = '';
    233             if (isset($options[$args['label_for']])
    234                 && $options[$args['label_for']] == $val
    235             ) {
    236                 $selected = ' selected';
    237             }
    238             ?>
    239             <option
    240                 value="<?php echo $val; ?>"
    241                 <?php echo $selected; ?>
    242             >
    243                 <?php echo $desc; ?>
    244             </option>
    245             <?php
    246         }
    247         ?>
    248     </select>
    249     <?php
     219 * @return void
     220 */
     221function callback_mip_minimize_js( $args ) {
     222    // Returns the HTML.
     223    $options = get_option( 'mip_options' );
     224    if ( isset( $options[ $args['label_for'] ] ) ) {
     225        $selected = ' selected';
     226    } else {
     227        $selected = '';
     228    }
     229    ?>
     230    <select
     231        id="<?php echo esc_attr( $args['label_for'] ); ?>"
     232        name="mip_options[<?php echo esc_attr( $args['label_for'] ); ?>]"
     233    >
     234        <?php
     235        $vals = array(
     236            'yes' => 'yes (default)',
     237            'no'  => 'no',
     238        );
     239        foreach ( $vals as $val => $desc ) {
     240            $selected = '';
     241            if ( isset( $options[ $args['label_for'] ] )
     242                && $options[ $args['label_for'] ] === $val
     243            ) {
     244                $selected = ' selected';
     245            }
     246            ?>
     247            <option
     248                value="<?php echo esc_html( $val ); ?>"
     249                <?php echo esc_html( $selected ); ?>
     250            >
     251                <?php echo esc_html( $desc ); ?>
     252            </option>
     253            <?php
     254        }
     255        ?>
     256    </select>
     257    <?php
    250258}
    251259
     
    255263 * @param array $args Arguments passed to the callback function.
    256264 *
    257  * @return Returns the HTML.
    258  */
    259 function callbackMIPShowAppearanceMenus($args)
    260 {
    261     $options = get_option('mip_options');
    262     if (isset($options[$args['label_for']])) {
    263         $selected = ' selected';
    264     } else {
    265         $selected = '';
    266     }
    267     ?>
    268     <select
    269         id="<?php echo esc_attr($args['label_for']); ?>"
    270         name="mip_options[<?php echo esc_attr($args['label_for']); ?>]"
    271     >
    272         <?php
    273         $vals = array(
    274             'no' => 'no (default)',
    275             'yes' => 'yes'
    276         );
    277         foreach ($vals as $val => $desc) {
    278             $selected = '';
    279             if (isset($options[$args['label_for']])
    280                 && $options[$args['label_for']] == $val
    281             ) {
    282                 $selected = ' selected';
    283             }
    284             ?>
    285             <option
    286                 value="<?php echo $val; ?>"
    287                 <?php echo $selected; ?>
    288             >
    289                 <?php echo $desc; ?>
    290             </option>
    291             <?php
    292         }
    293         ?>
    294     </select>
    295     <?php
     265 * @return void
     266 */
     267function callback_mip_show_appearance_menus( $args ) {
     268    // Returns the HTML.
     269    $options = get_option( 'mip_options' );
     270    if ( isset( $options[ $args['label_for'] ] ) ) {
     271        $selected = ' selected';
     272    } else {
     273        $selected = '';
     274    }
     275    ?>
     276    <select
     277        id="<?php echo esc_attr( $args['label_for'] ); ?>"
     278        name="mip_options[<?php echo esc_attr( $args['label_for'] ); ?>]"
     279    >
     280        <?php
     281        $vals = array(
     282            'no'  => 'no (default)',
     283            'yes' => 'yes',
     284        );
     285        foreach ( $vals as $val => $desc ) {
     286            $selected = '';
     287            if ( isset( $options[ $args['label_for'] ] )
     288                && $options[ $args['label_for'] ] === $val
     289            ) {
     290                $selected = ' selected';
     291            }
     292            ?>
     293            <option
     294                value="<?php echo esc_html( $val ); ?>"
     295                <?php echo esc_html( $selected ); ?>
     296            >
     297                <?php echo esc_html( $desc ); ?>
     298            </option>
     299            <?php
     300        }
     301        ?>
     302    </select>
     303    <?php
    296304}
    297305
     
    299307 * Create the Menu In Post menus for WordPress Admin.
    300308 *
    301  * @return Returns the options for the Menu In Post menus.
    302  */
    303 function addMenuInPostAdminMenus()
    304 {
    305     $tools = add_submenu_page(
    306         'tools.php',
    307         __('Menu In Post Tools', 'menu-in-post'),
    308         __('Menu In Post Tools', 'menu-in-post'),
    309         'manage_options',
    310         'menu-in-post',
    311         'outputMenuInPostToolsPageHTML'
    312     );
    313     add_action('load-' . $tools, 'loadMenuInPostToolsPage');
    314    
    315     $options = add_submenu_page(
    316         'options-general.php',
    317         __('Menu In Post', 'menu-in-post'),
    318         __('Menu In Post', 'menu-in-post'),
    319         'manage_options',
    320         'menu-in-post-options',
    321         'outputMenuInPostOptionsHTML'
    322     );
    323     add_action('load-' . $options, 'loadMenuInPostOptionsPage');
    324 }
    325 add_action('admin_menu', 'addMenuInPostAdminMenus');
     309 * @return void
     310 */
     311function add_mip_admin_menus() {
     312    // Returns the options for the Menu In Post menus.
     313    $tools = add_submenu_page(
     314        'tools.php',
     315        __( 'Menu In Post Tools', 'menu-in-post' ),
     316        __( 'Menu In Post Tools', 'menu-in-post' ),
     317        'manage_options',
     318        'menu-in-post',
     319        'output_mip_tools_page_html'
     320    );
     321    add_action( 'load-' . $tools, 'load_mip_tools_page' );
     322
     323    $options = add_submenu_page(
     324        'options-general.php',
     325        __( 'Menu In Post', 'menu-in-post' ),
     326        __( 'Menu In Post', 'menu-in-post' ),
     327        'manage_options',
     328        'menu-in-post-options',
     329        'output_mip_post_options_html'
     330    );
     331    add_action( 'load-' . $options, 'load_mip_options_page' );
     332}
     333add_action( 'admin_menu', 'add_mip_admin_menus' );
    326334
    327335/**
    328336 * Load the Menu In Post Tools Admin page and Help Tabs.
    329337 *
    330  * @return Nothing
    331  */
    332 function loadMenuInPostToolsPage()
    333 {
    334     $help_tabs = new MENUINPOST_Help_Tabs(get_current_screen());
    335     $help_tabs->mipSetHelpTabs('tools');
     338 * @return void
     339 */
     340function load_mip_tools_page() {
     341    $help_tabs = new \MenuInPost\MIPHelpTabs( get_current_screen() );
     342    $help_tabs->mip_set_help_tabs( 'tools' );
    336343}
    337344
     
    339346 * Load the Menu In Post Admin Settings page and Help Tabs.
    340347 *
    341  * @return Nothing
    342  */
    343 function loadMenuInPostOptionsPage()
    344 {
    345     $help_tabs = new MENUINPOST_Help_Tabs(get_current_screen());
    346     $help_tabs->mipSetHelpTabs('options');
     348 * @return void
     349 */
     350function load_mip_options_page() {
     351    $help_tabs = new \MenuInPost\MIPHelpTabs( get_current_screen() );
     352    $help_tabs->mip_set_help_tabs( 'options' );
    347353}
    348354
     
    350356 * Output the HTML for the Menu In Post Settings page.
    351357 *
    352  * @return Returns the HTML.
    353  */
    354 function outputMenuInPostOptionsHTML()
    355 {
    356     if (!current_user_can('manage_options')) {
    357         return;
    358     }
    359     /*
    360         Check to see if the user submitted the settings.
    361        
    362         WP adds the "settings-updated" $_GET parameter to the url.
    363     */
    364     if (isset($_GET['settings-updated'])) {
    365         // Add settings saved message with the class of "updated".
    366         add_settings_error(
    367             'mip_messages',
    368             'mip_message',
    369             __('Settings Saved', 'menu-in-post'),
    370             'updated'
    371         );
    372     }
    373 
    374     ?>
    375     <div class="wrap">
    376         <h1><?php echo esc_html(get_admin_page_title()); ?></h1>
    377         <form
    378             name="menu-in-post-options-form"
    379             method="post"
    380             action="options.php"
    381         >
    382             <?php
    383             settings_fields('menu-in-post');
    384             do_settings_sections('menu-in-post-options');
    385             submit_button('Save Settings');
    386             ?>
    387         </form>
    388     </div>
    389     <?php
     358 * @return void
     359 */
     360function output_mip_post_options_html() {
     361    // Returns the HTML.
     362    if ( ! current_user_can( 'manage_options' ) ) {
     363        return;
     364    }
     365    // Check to see if the user submitted the settings.
     366    // WP adds the "settings-updated" $_GET parameter to the url.
     367    if ( isset( $_GET['settings-updated'] ) ) {
     368        /* Verify the nonce that settings_fields() printed. */
     369        if ( isset( $_POST['option_page'] ) && isset( $_POST['_wpnonce'] ) ) {
     370
     371            // Unsanitize the raw POST values.
     372            $option_page = sanitize_key( wp_unslash( $_POST['option_page'] ) );
     373            $nonce       = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) );
     374
     375            // The second argument is the name of the nonce field (default is '_wpnonce').
     376            check_admin_referer( $option_page, '_wpnonce' );
     377        }
     378
     379        // Add settings saved message with the class of "updated".
     380        add_settings_error(
     381            'mip_messages',
     382            'mip_message',
     383            __( 'Settings Saved', 'menu-in-post' ),
     384            'updated'
     385        );
     386    }
     387
     388    ?>
     389    <div class="wrap">
     390        <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
     391        <form
     392            name="menu-in-post-options-form"
     393            method="post"
     394            action="options.php"
     395        >
     396            <?php
     397            settings_fields( 'menu-in-post' );
     398            do_settings_sections( 'menu-in-post-options' );
     399            submit_button( 'Save Settings' );
     400            ?>
     401        </form>
     402    </div>
     403    <?php
    390404}
    391405
     
    393407 * Output the HTML for the Menu In Post Tools page.
    394408 *
    395  * @return Returns the HTML.
    396  */
    397 function outputMenuInPostToolsPageHTML()
    398 {
    399     if (!current_user_can('manage_options')) {
    400         return;
    401     }
    402     $options = get_option(
    403         'mip_options',
    404         array(
    405             'miploadjs' => 'always',
    406             'miponlypages' => '',
    407             'mipminimizejs' => 'yes'
    408         )
    409     );
    410     $shortcode = '';
    411     /*
    412         Fallback for no JavaScript. Normally, the form is submitted via JavaScript,
    413         and everything is done client-side.
    414     */
    415     if (isset($_POST['mip_menu'])) {
    416         $atts = array(
    417         'menu'=>'mip_menu',
    418         'menu_class'=>'mip_menu_class',
    419         'menu_id'=>'mip_menu_id', 
    420         'container'=>'mip_container',
    421         'container_class'=>'mip_container_class',
    422         'container_id'=>'mip_container_id',
    423         'depth'=>'mip_depth',
    424         'style'=>'mip_style',
    425         'placeholder_text'=>'mip_placeholder_text',
    426         'append_to_url'=>'mip_append_to_url'
    427         );
    428         foreach ($atts as $att=>$field) {
    429             switch($att) {
    430             case 'menu':
    431             case 'depth':
    432             case 'container':
    433                 $$att = absint($_POST[$field]);
    434                 break;
    435             break;
    436             // These should only be strings.
    437             default:
    438                 $$att = trim(sanitize_text_field($_POST[$field]));
    439             }
    440         }
    441         // Build the shortcode.
    442         $shortcode = '[menu_in_post_menu';
    443         foreach ($atts as $att=>$field) {
    444             switch($att) {
    445             case 'menu':
    446                 $shortcode .= ' ' . $att . '=' . $$att;
    447                 break;
    448             case 'depth':
    449                 if ($depth > 0) {
    450                     $shortcode .= ' depth=' . $depth;
    451                 }
    452                 break;
    453             case 'style':
    454                 if ($style != 'list') {
    455                     $shortcode .= ' style=' . $style;
    456                 }
    457                 break;
    458             case 'container':
    459                 if ($container == 0) {
    460                     $shortcode .= ' container=&#34;false&#34;';
    461                 }
    462                 break;
    463             default:
    464                 if ($$att != '') {
    465                     $shortcode .= ' ' . $att . '=&#34;' . $$att . '&#34;';
    466                 }
    467             }
    468         }
    469         $shortcode .= ']';
    470     }
    471     /* ************************* End of JavaScript fallback. ********************* */
    472     ?>
    473     <div class="wrap">
    474         <h1><?php echo esc_html(__('Menu In Post Tools', 'menu-in-post')); ?></h1>
    475         <?php
    476         $str = '';
    477         $title = esc_html(__('Note:', 'menu-in-post'));
    478         switch($options['miploadjs']) {
    479         case 'never':
    480             $str = esc_html(
    481                 __(
    482                     'Dropdown-style menus will not work with your current ' .
    483                     'setting of &quot;never&quot; in Settings > Menu In Post, ' .
    484                     'Load JavaScript.', 'menu-in-post'
    485                 )
    486             );
    487             break;
    488         case 'onlypages':
    489             $str = esc_html(
    490                 __(
    491                     'Dropdown-style menus will not work with your current ' .
    492                     'setting of &quot;only on posts/pages&quot; in Settings > ' .
    493                     'Menu In Post > Menu In Post Options, Load JavaScript ' .
    494                     'unless you have set the correct page ID(s) in &quot;Only on ' .
    495                     'Posts/Pages&quot;.',
    496                     'menu-in-post'
    497                 )
    498             );
    499             break;
    500         }
    501         if ($str !== '') {
    502             /*
    503                 Use the wp_admin_notice() function, added in WP 6.4, if possible.
    504                
    505                 Fall back to HTML output if < WP 6.4.
    506                
    507                 You can remove the conditional for WP version once there has
    508                 been time for everyone to upgrade to >= WP 6.4.
    509             */
    510             if (is_wp_version_compatible('6.4')) {
    511                 wp_admin_notice(
    512                     __('<strong>' . $title . '</strong> ' . $str, 'menu-in-post'),
    513                     array(
    514                         'type' => 'warning',
    515                         'dismissible' => false
    516                     )
    517                 );
    518             } else {
    519                 ?>
    520                 <div class="notice notice-warning">
    521                     <p>
    522                         <strong><?php echo $title; ?></strong> <?php echo $str; ?>
    523                     </p>
    524                 </div>
    525                 <?php
    526             }
    527         }
    528         ?>
    529         <p>
    530             <?php
    531                 echo esc_html(
    532                     __(
    533                         'Use the form below to create shortcodes to display ' .
    534                             'menus in posts and pages. Paste the shortcodes ' .
    535                             'you create in a Shortcode Block to display them.',
    536                         'menu-in-post'
    537                     )
    538                 );
    539             ?>
    540         </p>
    541         <h2><?php echo esc_html(__('Shortcode Builder', 'menu-in-post')); ?></h2>
    542     <?php
    543         $menus = wp_get_nav_menus();
    544     if (is_array($menus) && count($menus) > 0) {
    545         ?>
    546         <form
    547             name="mip_shortcode_builder_form"
    548             id="mip_shortcode_builder_form"
    549             method="post"
    550         >
    551             <div class="inputgroup">
    552                 <div class="inputrow">
    553                     <label for="mip_menu">
    554                     <?php
    555                         echo esc_html(__('Select Menu', 'menu-in-post'));
    556                     ?>:
    557                     </label>
    558                     <select name="mip_menu" id="mip_menu">
    559                     <?php
    560                     foreach ($menus as $menu) {
    561                         echo '<option value="' . $menu->term_id . '">' .
    562                             $menu->name . '</option>';
    563                     }
    564                     ?>
    565                     </select>
    566                 </div>
    567                 <div class="inputrow">
    568                     <label for="mip_container">
    569                     <?php
    570                         echo esc_html(
    571                             __('Include Container', 'menu-in-post')
    572                         );
    573                     ?>:
    574                     </label>
    575                     <select name="mip_container" id="mip_container">
    576                         <option value="1">
    577                         <?php echo esc_html(__('Yes', 'menu-in-post')); ?>
    578                         </option>
    579                         <option value="0">
    580                         <?php echo esc_html(__('No', 'menu-in-post')); ?>
    581                         </option>
    582                     </select>
    583                 </div>
    584                 <div class="inputrow">
    585                     <label for="mip_container_id">
    586                         <?php
    587                         echo esc_html(__('Container ID', 'menu-in-post'));
    588                         ?>:
    589                     </label>
    590                     <input
    591                         type="text"
    592                         name="mip_container_id"
    593                         id="mip_container_id"
    594                     >
    595                 </div>
    596                 <div class="inputrow">
    597                     <label for="mip_container_class">
    598                         <?php
    599                         echo esc_html(
    600                             __('Container Class(es)', 'menu-in-post')
    601                         );
    602                         ?>:
    603                     </label>
    604                     <input
    605                         type="text"
    606                         name="mip_container_class"
    607                         id="mip_container_class"
    608                     >
    609                 </div>
    610                 <div class="inputrow">
    611                     <label for="mip_menu_id">
    612                         <?php echo esc_html(__('Menu ID', 'menu-in-post')); ?>:
    613                     </label>
    614                     <input type="text" name="mip_menu_id" id="mip_menu_id">
    615                 </div>
    616                 <div class="inputrow">
    617                     <label for="mip_menu_class">
    618                         <?php
    619                             echo esc_html(__('Menu Class(es)', 'menu-in-post'));
    620                         ?>:
    621                     </label>
    622                     <input type="text" name="mip_menu_class" id="mip_menu_class">
    623                 </div>
    624                 <div class="inputrow">
    625                     <label for="mip_depth">
    626                         <?php echo esc_html(__('Depth', 'menu-in-post')); ?>:
    627                     </label>
    628                     <select name="mip_depth" id="mip_depth">
    629                         <?php
    630                         $depth_options = array(
    631                             0=>esc_html(__('All Levels', 'menu-in-post')),
    632                             1=>esc_html(__('1 Level', 'menu-in-post')),
    633                             2=>esc_html(__('2 Levels', 'menu-in-post')),
    634                             3=>esc_html(__('3 Levels', 'menu-in-post')),
    635                             4=>esc_html(__('4 Levels', 'menu-in-post')),
    636                             5=>esc_html(__('5 Levels', 'menu-in-post'))
    637                         );
    638                         foreach ($depth_options as $value=>$text) {
    639                             if ($value == 0) {
    640                                 echo '<option value="' . $value .
    641                                     '" selected="selected">' . $text .
    642                                     '</option>';
    643                             } else {
    644                                 echo '<option value="' . $value . '">' .
    645                                     $text . '</option>';
    646                             }
    647                         }
    648                         ?>
    649                     </select>
    650                 </div>
    651                 <div class="inputrow">
    652                     <label for="mip_style">
    653                         <?php echo esc_html(__('Style', 'menu-in-post')); ?>:
    654                     </label>
    655                     <select name="mip_style" id="mip_style">
    656                         <?php
    657                         $style_options = array(
    658                             'list'=>esc_html(
    659                                 __('List of Links', 'menu-in-post')
    660                             ),
    661                             'dropdown'=>esc_html(__('Dropdown', 'menu-in-post'))
    662                         );
    663                         foreach ($style_options as $value=>$text) {
    664                             if ($value == 'list') {
    665                                 echo '<option value="' . $value .
    666                                     '" selected="selected">' . $text .
    667                                     '</option>';
    668                             } else {
    669                                 echo '<option value="' . $value . '">' .
    670                                     $text . '</option>';
    671                             }
    672                         }
    673                         ?>
    674                     </select>
    675                 </div>
    676                 <div class="inputrow">
    677                     <label for="mip_placeholder_text">
    678                         <?php
    679                             echo esc_html(
    680                                 __('Placeholder Text', 'menu-in-post')
    681                             );
    682                         ?>:
    683                     </label>
    684                     <input
    685                         type="text"
    686                         name="mip_placeholder_text"
    687                         id="mip_placeholder_text"
    688                     >
    689                 </div>
    690                 <div class="inputrow">
    691                     <label for="mip_append_to_url">
    692                         <?php
    693                             echo esc_html(__('Append to URL', 'menu-in-post'));
    694                         ?>:
    695                     </label>
    696                     <input
    697                         type="text"
    698                         name="mip_append_to_url"
    699                         id="mip_append_to_url"
    700                     >
    701                 </div>
    702             </div><br>
    703             <input
    704                 type="submit"
    705                 name="mip_build"
    706                 value="<?php
    707                     echo esc_attr(__('Build the Shortcode', 'menu-in-post'));
    708                 ?>"
    709             >
    710         </form>
    711         <div>
    712             <label for="mip_shortcode_builder_output">
    713                 <?php echo esc_html(__('Shortcode', 'menu-in-post')); ?>:
    714             </label>
    715             <div class="mip_shortcode_output_hightlight">
    716                 <input
    717                     type="text"
    718                     name="mip_shortcode_builder_output"
    719                     id="mip_shortcode_builder_output"
    720                     value="<?php echo $shortcode; ?>"
    721                     readonly
    722                 >
    723             </div>
    724             <div>
    725                 <button
    726                     type="button"
    727                     id="mip_shortcode_output_copy_button"
    728                 >
    729                 <?php echo esc_html(__('Copy Shortcode', 'menu-in-post')); ?>
    730                 </button>&nbsp;
    731                 <span id="mip_shortcode_copy_success">
    732                     <?php echo esc_html(__('Copied...', 'menu-in-post')); ?>
    733                 </span>
    734             </div>
    735       </div>
    736     </div>
    737         <?php
    738     } else {
    739         $str = esc_html(
    740             __(
    741                 'You must create one or more menus (Appearance > Menus) ' .
    742                     'prior to using Menu In Post&#39;s Shortcode Builder.',
    743                 'menu-in-post'
    744             )
    745         );
    746         /*
    747             Use the wp_admin_notice() function, added in WP 6.4, if possible.
    748            
    749             Fall back to HTML output if < WP 6.4.
    750            
    751             You can remove the conditional for WP version once there has
    752             been time for everyone to upgrade to >= WP 6.4.
    753         */
    754         if (is_wp_version_compatible('6.4')) {
    755             wp_admin_notice(
    756                 __($str, 'menu-in-post'),
    757                 array(
    758                     'type' => 'warning',
    759                     'dismissible' => true
    760                 )
    761             );
    762         } else {
    763             ?>
    764             <div class="notice notice-warning is-dismissible">
    765                 <p><?php echo $str; ?></p>
    766             </div>
    767             <?php
    768         }
    769     }
     409 * @return void
     410 */
     411function output_mip_tools_page_html() {
     412    // Returns the HTML.
     413    // In the Tools page callback (runs on every load).
     414    if ( isset( $_GET['_wpnonce'] ) ) {
     415        // Uns­lash and sanitise the value – PHPCS‑friendly.
     416        $nonce = sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) );
     417
     418        // Verify it against the current screen’s action.
     419        // The first argument is the *action* you want to protect;
     420        // the second argument is the name of the GET variable (default is '_wpnonce').
     421        check_admin_referer( 'menu-in-post', '_wpnonce' );
     422    }
     423
     424    // Capability check.
     425    if ( ! current_user_can( 'manage_options' ) ) {
     426        wp_die( esc_html__( 'You do not have permission for this task.', 'menu-in-post' ), 403 );
     427    }
     428
     429    $options   = get_option(
     430        'mip_options',
     431        array(
     432            'miploadjs'     => 'always',
     433            'miponlypages'  => '',
     434            'mipminimizejs' => 'yes',
     435        )
     436    );
     437    $shortcode = '';
     438    // Fallback for no JavaScript. Normally, the form is submitted via JavaScript,
     439    // and everything is done client-side.
     440    if ( isset( $_POST['mip_menu'] ) ) {
     441        $atts = array(
     442            'menu'             => 'mip_menu',
     443            'menu_class'       => 'mip_menu_class',
     444            'menu_id'          => 'mip_menu_id',
     445            'container'        => 'mip_container',
     446            'container_class'  => 'mip_container_class',
     447            'container_id'     => 'mip_container_id',
     448            'depth'            => 'mip_depth',
     449            'style'            => 'mip_style',
     450            'placeholder_text' => 'mip_placeholder_text',
     451            'append_to_url'    => 'mip_append_to_url',
     452        );
     453        foreach ( $atts as $att => $field ) {
     454            if ( isset( $_POST[ $field ] ) ) {
     455                switch ( $att ) {
     456                    case 'menu':
     457                    case 'depth':
     458                    case 'container':
     459                        $$att = absint( $_POST[ $field ] );
     460                        break;
     461                    // These should only be strings.
     462                    default:
     463                        $$att = trim( sanitize_text_field( wp_unslash( $_POST[ $field ] ) ) );
     464                }
     465            }
     466        }
     467        // Build the shortcode.
     468        $shortcode = '[menu_in_post_menu';
     469        foreach ( $atts as $att => $field ) {
     470            switch ( $att ) {
     471                case 'menu':
     472                    $shortcode .= ' ' . $att . '=' . $$att;
     473                    break;
     474                case 'depth':
     475                    if ( $depth > 0 ) {
     476                        $shortcode .= ' depth=' . $depth;
     477                    }
     478                    break;
     479                case 'style':
     480                    if ( 'list' !== $style ) {
     481                        $shortcode .= ' style=' . $style;
     482                    }
     483                    break;
     484                case 'container':
     485                    if ( 0 === $container ) {
     486                        $shortcode .= ' container=&#34;false&#34;';
     487                    }
     488                    break;
     489                default:
     490                    if ( '' !== $$att ) {
     491                        $shortcode .= ' ' . $att . '=&#34;' . $$att . '&#34;';
     492                    }
     493            }
     494        }
     495        $shortcode .= ']';
     496    }
     497    /* ************************* End of JavaScript fallback. ********************* */
     498    ?>
     499    <div class="wrap">
     500        <h1><?php echo esc_html( __( 'Menu In Post Tools', 'menu-in-post' ) ); ?></h1>
     501        <?php
     502        $str   = '';
     503        $title = esc_html( __( 'Note:', 'menu-in-post' ) );
     504        switch ( $options['miploadjs'] ) {
     505            case 'never':
     506                $str = esc_html(
     507                    __(
     508                        'Dropdown-style menus will not work with your current setting of "never" in Settings > Menu In Post, Load JavaScript.',
     509                        'menu-in-post'
     510                    )
     511                );
     512                break;
     513            case 'onlypages':
     514                $str = esc_html(
     515                    __(
     516                        'Dropdown-style menus will not work with your current setting of "only on posts/pages" in Settings > Menu In Post > Menu In Post Options, Load JavaScript unless you have set the correct page ID(s) in "Only on Posts/Pages".',
     517                        'menu-in-post'
     518                    )
     519                );
     520                break;
     521        }
     522        if ( '' !== $str ) {
     523            /*
     524                Use the wp_admin_notice() function, added in WP 6.4, if possible.
     525
     526                Fall back to HTML output if < WP 6.4.
     527
     528                You can remove the conditional for WP version once there has
     529                been time for everyone to upgrade to >= WP 6.4.
     530            */
     531            if ( is_wp_version_compatible( '6.4' ) ) {
     532                wp_admin_notice(
     533                    sprintf(
     534                        /* translators: %1$s = already‑translated title, %2$s = already‑translated description */
     535                        __( '<strong>%1$s</strong> %2$s', 'menu-in-post' ),
     536                        $title,
     537                        $str
     538                    ),
     539                    array(
     540                        'type'        => 'warning',
     541                        'dismissible' => false,
     542                    )
     543                );
     544            } else {
     545                ?>
     546                <div class="notice notice-warning">
     547                    <p>
     548                        <strong><?php echo esc_html( $title ); ?></strong> <?php echo esc_html( $str ); ?>
     549                    </p>
     550                </div>
     551                <?php
     552            }
     553        }
     554        ?>
     555        <p>
     556            <?php
     557                echo esc_html(
     558                    __(
     559                        'Use the form below to create shortcodes to display menus in posts and pages. Paste the shortcodes you create in a Shortcode Block to display them.',
     560                        'menu-in-post'
     561                    )
     562                );
     563            ?>
     564        </p>
     565        <h2><?php echo esc_html( __( 'Shortcode Builder', 'menu-in-post' ) ); ?></h2>
     566    <?php
     567        $menus = wp_get_nav_menus();
     568    if ( is_array( $menus ) && count( $menus ) > 0 ) {
     569        ?>
     570        <form
     571            name="mip_shortcode_builder_form"
     572            id="mip_shortcode_builder_form"
     573            method="post"
     574        >
     575            <div class="inputgroup">
     576                <div class="inputrow">
     577                    <label for="mip_menu">
     578                    <?php
     579                        echo esc_html( __( 'Select Menu', 'menu-in-post' ) );
     580                    ?>
     581                    :
     582                    </label>
     583                    <select name="mip_menu" id="mip_menu">
     584                    <?php
     585                    foreach ( $menus as $menu ) {
     586                        echo '<option value="' . esc_html( $menu->term_id ) . '">' .
     587                            esc_html( $menu->name ) . '</option>';
     588                    }
     589                    ?>
     590                    </select>
     591                </div>
     592                <div class="inputrow">
     593                    <label for="mip_container">
     594                    <?php
     595                        echo esc_html(
     596                            __( 'Include Container', 'menu-in-post' )
     597                        );
     598                    ?>
     599                    :
     600                    </label>
     601                    <select name="mip_container" id="mip_container">
     602                        <option value="1">
     603                        <?php echo esc_html( __( 'Yes', 'menu-in-post' ) ); ?>
     604                        </option>
     605                        <option value="0">
     606                        <?php echo esc_html( __( 'No', 'menu-in-post' ) ); ?>
     607                        </option>
     608                    </select>
     609                </div>
     610                <div class="inputrow">
     611                    <label for="mip_container_id">
     612                        <?php
     613                        echo esc_html( __( 'Container ID', 'menu-in-post' ) );
     614                        ?>
     615                        :
     616                    </label>
     617                    <input
     618                        type="text"
     619                        name="mip_container_id"
     620                        id="mip_container_id"
     621                    >
     622                </div>
     623                <div class="inputrow">
     624                    <label for="mip_container_class">
     625                        <?php
     626                        echo esc_html(
     627                            __( 'Container Class(es)', 'menu-in-post' )
     628                        );
     629                        ?>
     630                        :
     631                    </label>
     632                    <input
     633                        type="text"
     634                        name="mip_container_class"
     635                        id="mip_container_class"
     636                    >
     637                </div>
     638                <div class="inputrow">
     639                    <label for="mip_menu_id">
     640                        <?php echo esc_html( __( 'Menu ID', 'menu-in-post' ) ); ?>:
     641                    </label>
     642                    <input type="text" name="mip_menu_id" id="mip_menu_id">
     643                </div>
     644                <div class="inputrow">
     645                    <label for="mip_menu_class">
     646                        <?php
     647                            echo esc_html( __( 'Menu Class(es)', 'menu-in-post' ) );
     648                        ?>
     649                        :
     650                    </label>
     651                    <input type="text" name="mip_menu_class" id="mip_menu_class">
     652                </div>
     653                <div class="inputrow">
     654                    <label for="mip_depth">
     655                        <?php echo esc_html( __( 'Depth', 'menu-in-post' ) ); ?>:
     656                    </label>
     657                    <select name="mip_depth" id="mip_depth">
     658                        <?php
     659                        $depth_options = array(
     660                            0 => esc_html( __( 'All Levels', 'menu-in-post' ) ),
     661                            1 => esc_html( __( '1 Level', 'menu-in-post' ) ),
     662                            2 => esc_html( __( '2 Levels', 'menu-in-post' ) ),
     663                            3 => esc_html( __( '3 Levels', 'menu-in-post' ) ),
     664                            4 => esc_html( __( '4 Levels', 'menu-in-post' ) ),
     665                            5 => esc_html( __( '5 Levels', 'menu-in-post' ) ),
     666                        );
     667                        foreach ( $depth_options as $value => $text ) {
     668                            if ( 0 === $value ) {
     669                                echo '<option value="' . esc_html( $value ) .
     670                                    '" selected="selected">' . esc_html( $text ) .
     671                                    '</option>';
     672                            } else {
     673                                echo '<option value="' . esc_html( $value ) . '">' .
     674                                    esc_html( $text ) . '</option>';
     675                            }
     676                        }
     677                        ?>
     678                    </select>
     679                </div>
     680                <div class="inputrow">
     681                    <label for="mip_style">
     682                        <?php echo esc_html( __( 'Style', 'menu-in-post' ) ); ?>:
     683                    </label>
     684                    <select name="mip_style" id="mip_style">
     685                        <?php
     686                        $style_options = array(
     687                            'list'     => esc_html(
     688                                __( 'List of Links', 'menu-in-post' )
     689                            ),
     690                            'dropdown' => esc_html( __( 'Dropdown', 'menu-in-post' ) ),
     691                        );
     692                        foreach ( $style_options as $value => $text ) {
     693                            if ( 'list' === $value ) {
     694                                echo '<option value="' . esc_html( $value ) .
     695                                    '" selected="selected">' . esc_html( $text ) .
     696                                    '</option>';
     697                            } else {
     698                                echo '<option value="' . esc_html( $value ) . '">' .
     699                                    esc_html( $text ) . '</option>';
     700                            }
     701                        }
     702                        ?>
     703                    </select>
     704                </div>
     705                <div class="inputrow">
     706                    <label for="mip_placeholder_text">
     707                        <?php
     708                            echo esc_html(
     709                                __( 'Placeholder Text', 'menu-in-post' )
     710                            );
     711                        ?>
     712                        :
     713                    </label>
     714                    <input
     715                        type="text"
     716                        name="mip_placeholder_text"
     717                        id="mip_placeholder_text"
     718                    >
     719                </div>
     720                <div class="inputrow">
     721                    <label for="mip_append_to_url">
     722                        <?php
     723                            echo esc_html( __( 'Append to URL', 'menu-in-post' ) );
     724                        ?>
     725                        :
     726                    </label>
     727                    <input
     728                        type="text"
     729                        name="mip_append_to_url"
     730                        id="mip_append_to_url"
     731                    >
     732                </div>
     733            </div><br>
     734            <input
     735                type="submit"
     736                name="mip_build"
     737                value="<?php echo esc_attr( __( 'Build the Shortcode', 'menu-in-post' ) ); ?>"
     738            >
     739        </form>
     740        <div>
     741            <label for="mip_shortcode_builder_output">
     742                <?php echo esc_html( __( 'Shortcode', 'menu-in-post' ) ); ?>:
     743            </label>
     744            <div class="mip_shortcode_output_hightlight">
     745                <input
     746                    type="text"
     747                    name="mip_shortcode_builder_output"
     748                    id="mip_shortcode_builder_output"
     749                    value="<?php echo esc_html( $shortcode ); ?>"
     750                    readonly
     751                >
     752            </div>
     753            <div>
     754                <button
     755                    type="button"
     756                    id="mip_shortcode_output_copy_button"
     757                >
     758                <?php echo esc_html( __( 'Copy Shortcode', 'menu-in-post' ) ); ?>
     759                </button>&nbsp;
     760                <span id="mip_shortcode_copy_success">
     761                    <?php echo esc_html( __( 'Copied...', 'menu-in-post' ) ); ?>
     762                </span>
     763            </div>
     764        </div>
     765    </div>
     766        <?php
     767    } elseif ( is_wp_version_compatible( '6.4' ) ) {
     768        /*
     769            Use the wp_admin_notice() function, added in WP 6.4, if possible.
     770
     771            Fall back to HTML output if < WP 6.4.
     772
     773            You can remove the conditional for WP version once there has
     774            been time for everyone to upgrade to >= WP 6.4.
     775        */
     776        wp_admin_notice(
     777            esc_html__(
     778                "You must create one or more menus (Appearance > Menus) prior to using Menu In Post's Shortcode Builder.",
     779                'menu-in-post'
     780            ),
     781            array(
     782                'type'        => 'warning',
     783                'dismissible' => true,
     784            )
     785        );
     786    } else {
     787        ?>
     788        <div class="notice notice-warning is-dismissible">
     789            <p><?php echo esc_html( $str ); ?></p>
     790        </div>
     791        <?php
     792    }
    770793}
    771794
    772795/**
    773796 * Enqueue the scripts and stylesheet(s) required for Menu In Post Admin pages.
    774  * Option: $live can be set to false during development in order to load 
     797 * Option: $live can be set to false during development in order to load
    775798 * unminified versions of CSS and JS in Admin.
    776799 *
    777800 * @param string $hook Hook associated with the Tools page.
    778801 *
    779  * @return Nothing.
    780  */
    781 function enqueueMenuInPostAdminScripts($hook)
    782 {
    783     if ($hook != 'tools_page_menu-in-post'
    784         && $hook != 'settings_page_menu-in-post-options'
    785     ) {
    786         return;
    787     }
    788     $options = get_option(
    789         'mip_options',
    790         array(
    791             'miploadjs' => 'always',
    792             'miponlypages' => '',
    793             'mipminimizejs' => 'yes'
    794         )
    795     );
    796     if ($options['mipminimizejs'] == 'yes') {
    797         $min = '-min';
    798     } else {
    799         $min = '';
    800     }
    801     wp_enqueue_style(
    802         'menu_in_post_admin_style',
    803         plugins_url('css/style' . $min . '.css', __FILE__)
    804     );
    805     wp_enqueue_script(
    806         'menu_in_post_admin_script',
    807         plugins_url('js/main' . $min . '.js', __FILE__),
    808         array('jquery')
    809     );
    810 }
    811 add_action('admin_enqueue_scripts', 'enqueueMenuInPostAdminScripts');
    812 
    813 /**
    814  * Optionally, add back the Appearance > Menus menu subitem so that users
    815  * of block themes can add/edit classic menus for use in Menu In Post by
    816  * registering the existing Menus menu that was removed in WP 5.9+ for
     802 * @return void
     803 */
     804function enqueue_mip_admin_scripts( $hook ) {
     805    if ( 'tools_page_menu-in-post' !== $hook
     806        && 'settings_page_menu-in-post-options' !== $hook
     807    ) {
     808        return;
     809    }
     810    $options = get_option(
     811        'mip_options',
     812        array(
     813            'miploadjs'     => 'always',
     814            'miponlypages'  => '',
     815            'mipminimizejs' => 'yes',
     816        )
     817    );
     818    if ( 'yes' === $options['mipminimizejs'] ) {
     819        $min = '-min';
     820    } else {
     821        $min = '';
     822    }
     823    wp_enqueue_style(
     824        'menu_in_post_admin_style',
     825        plugins_url( 'css/style' . $min . '.css', __FILE__ ),
     826        array(),
     827        MENU_IN_POST_VERSION,
     828        'all'
     829    );
     830    wp_enqueue_script(
     831        'menu_in_post_admin_script',
     832        plugins_url( 'js/main' . $min . '.js', __FILE__ ),
     833        array( 'jquery' ),
     834        MENU_IN_POST_VERSION,
     835        false
     836    );
     837}
     838add_action( 'admin_enqueue_scripts', 'enqueue_mip_admin_scripts' );
     839
     840/**
     841 * Optionally, add back the Appearance > Menus menu subitem so that users
     842 * of block themes can add/edit classic menus for use in Menu In Post by
     843 * registering the existing Menus menu that was removed in WP 5.9+ for
    817844 * block-enabled themes.
    818845 *
    819  * @return Nothing.
    820  */
    821 function getBackAppearanceMenus()
    822 {
    823     $options = get_option(
    824         'mip_options',
    825         array('mipshowappearancemenus' => 'no')
    826     );
    827     if (array_key_exists('mipshowappearancemenus', $options)) {
    828         if ($options['mipshowappearancemenus'] == 'yes' && wp_is_block_theme()) {
    829             register_nav_menus(
    830                 array(
    831                     'primary' => esc_html__('Primary Menu',
    832                     'raft'
    833                     )
    834                 )
    835             );
    836         }
    837     }
    838 }
    839 add_action('init', 'getBackAppearanceMenus');
     846 * @return void
     847 */
     848function get_back_appearance_menus() {
     849    $options = get_option(
     850        'mip_options',
     851        array( 'mipshowappearancemenus' => 'no' )
     852    );
     853    if ( array_key_exists( 'mipshowappearancemenus', $options ) ) {
     854        if ( 'yes' === $options['mipshowappearancemenus'] && wp_is_block_theme() ) {
     855            register_nav_menus(
     856                array(
     857                    'primary' => esc_html__(
     858                        'Primary Menu',
     859                        'raft'
     860                    ),
     861                )
     862            );
     863        }
     864    }
     865}
     866add_action( 'init', 'get_back_appearance_menus' );
    840867?>
  • menu-in-post/tags/1.4.0/menu-in-post.php

    r3079625 r3441285  
    66 * Author URI: https://profiles.wordpress.org/linux4me2
    77 * Text Domain: menu-in-post
    8  * Version: 1.3
     8 * Version: 1.4
    99 * License: GPL3
    1010 * License URI: https://www.gnu.org/licenses/gpl-3.0-standalone.html
    11  */
    12 
    13 defined('ABSPATH') or die('No direct access.');
    14 
    15 define('MENUINPOST_PLUGIN', __FILE__);
    16 define('MENUINPOST_PLUGIN_DIR', untrailingslashit(dirname(MENUINPOST_PLUGIN)));
    17 
    18 if (is_admin()) {
    19     include_once MENUINPOST_PLUGIN_DIR . '/admin/help-tabs.php';
    20     include_once MENUINPOST_PLUGIN_DIR . '/admin/admin.php';
    21 }
    22 
    23 add_shortcode('menu_in_post_menu', 'outputMenuInPostMenu');
     11 *
     12 * @package menu-in-post
     13 */
     14
     15use MenuInPost\MIPHelpTabs;
     16use MenuInPost\MIPWalkerNavMenuDropdownBuilder;
     17use MenuInPost\MIPWalkerNavMenuListBuilder;
     18
     19// Prevent direct access.
     20if ( ! defined( 'ABSPATH' ) ) {
     21    exit;
     22}
     23
     24define( 'MENUINPOST_PLUGIN', __FILE__ );
     25define( 'MENUINPOST_PLUGIN_DIR', untrailingslashit( dirname( MENUINPOST_PLUGIN ) ) );
     26
     27if ( ! defined( 'MENU_IN_POST_VERSION' ) ) {
     28    define( 'MENU_IN_POST_VERSION', '1.4' ); // keep in sync with the plugin header.
     29}
     30
     31// Register a simple autoloader that looks in the plugin’s root directory.
     32spl_autoload_register(
     33    function ( $theclass ) {
     34       
     35       
     36       
     37        $prefix = 'MenuInPost\\';
     38        $base   = __DIR__ . '/';
     39
     40        // Only handle our own namespace.
     41        $len = strlen( $prefix );
     42        if ( strncmp( $prefix, $theclass, $len ) !== 0 ) {
     43                return;
     44        }
     45
     46        // Strip the namespace prefix.
     47        $relative = substr( $theclass, $len );
     48
     49        // Convert namespace separators to directory separators.
     50        $relative = str_replace( '\\', '/', $relative );
     51
     52        // Build the full path to the file.
     53        $file = $base . 'class-' . strtolower($relative) . '.php';
     54       
     55        // ******************** Debugging code. ********************
     56        //error_log( "[MenuInPost] Autoloader invoked for class: $theclass" );
     57        //error_log( "[MenuInPost] class filename = $file" );
     58        // ******************** End debugging code. ****************
     59       
     60        if ( file_exists( $file ) ) {
     61            require_once $file;
     62        }
     63    }
     64);
     65
     66if ( is_admin() ) {
     67    include_once MENUINPOST_PLUGIN_DIR . '/admin/admin.php';
     68}
     69
     70add_shortcode( 'menu_in_post_menu', 'output_mip_menu' );
     71
    2472
    2573/**
     
    3078 * @return Returns the menu via wp_nav_menu()
    3179 */
    32 function outputMenuInPostMenu($atts = array())
    33 {
    34     if (isset($atts['menu'])) {
    35         $menu = absint($atts['menu']);
    36     } else {
    37         $menu = 0;
    38     }
    39     if ($menu == 0) {
    40         return fallbackMenuInPost();
    41     } else {
    42         $args = array(
    43             'menu'=>$menu,
    44             'fallback_cb'=>'fallbackMenuInPost',
    45             'echo'=>false
    46         );
    47     }
    48     /*
    49         If menu_id is empty, don't pass a value, and the menu slug with an
    50         incremented value added will be used.
    51          
    52         If container_class is empty, don't pass a value and
    53         'menu-{menu slug}-container' will be used.
    54     */
    55     $defaults = array(
    56         'menu_class'=>'menu',
    57         'menu_id'=>'',   
    58         'container'=>'div',
    59         'container_class'=>'',
    60         'container_id'=>'',
    61         'style'=>'list',
    62         'placeholder_text'=>esc_html(__('Select...', 'menu-in-post')),
    63         'append_to_url'=>'',
    64         'depth'=>0
    65     );
    66     foreach ($defaults as $att=>$default) {
    67         switch($att) {
    68         case 'depth':
    69             if (isset($atts[$att])) {
    70                  $passed_depth = absint($atts[$att]);
    71                 if ($passed_depth > 0) {
    72                     $args['depth'] = $passed_depth;
    73                 }
    74             } else {
    75                 $atts['depth'] = $default;
    76             }
    77             break;
    78         // These should be only strings.
    79         default:
    80             if (isset($atts[$att])) {
    81                 $passed_att = sanitize_text_field($atts[$att]);
    82                 if ($passed_att != '') {
    83                     $args[$att] = $passed_att;
    84                 }
    85             } else {
    86                 $atts[$att] = $default;
    87             }
    88         }   
    89     }
    90     if ($atts['style'] == 'dropdown') {
    91         $select = '<select class="mip-drop-nav"';
    92         if ($atts['menu_id'] != '') {
    93             $select .= ' id="' . $args['menu_id'] . '"';
    94         }
    95         $select .= '>';
    96         $args['items_wrap'] = $select . '<option value="#">' .
    97             $atts['placeholder_text'] . '</option>%3$s</select>';
    98         $args['walker'] = new MIPWalkerNavMenuDropdownBuilder();
    99     } else {
    100         if ($atts['append_to_url'] != '') {
    101             $args['walker'] = new MIPWalkerNavMenuListBuilder();
    102         }
    103     }
    104     if ($atts['append_to_url'] != '') {
    105         $args['append_to_url'] = $atts['append_to_url'];
    106     }
    107     return wp_nav_menu($args);
     80function output_mip_menu( $atts = array() ) {
     81    if ( isset( $atts['menu'] ) ) {
     82        $menu = absint( $atts['menu'] );
     83    } else {
     84        $menu = 0;
     85    }
     86    if ( 0 === $menu ) {
     87        return fallback_mip();
     88    } else {
     89        $args = array(
     90            'menu'        => $menu,
     91            'fallback_cb' => 'fallback_mip',
     92            'echo'        => false,
     93        );
     94    }
     95
     96    /*
     97        If menu_id is empty, don't pass a value, and the menu slug with an
     98        incremented value added will be used.
     99
     100        If container_class is empty, don't pass a value and
     101        'menu-{menu slug}-container' will be used.
     102    */
     103    $defaults = array(
     104        'menu_class'       => 'menu',
     105        'menu_id'          => '',
     106        'container'        => 'div',
     107        'container_class'  => '',
     108        'container_id'     => '',
     109        'style'            => 'list',
     110        'placeholder_text' => esc_html( __( 'Select...', 'menu-in-post' ) ),
     111        'append_to_url'    => '',
     112        'depth'            => 0,
     113    );
     114    foreach ( $defaults as $att => $default ) {
     115        switch ( $att ) {
     116            case 'depth':
     117                if ( isset( $atts[ $att ] ) ) {
     118                    $passed_depth = absint( $atts[ $att ] );
     119                    if ( $passed_depth > 0 ) {
     120                        $args['depth'] = $passed_depth;
     121                    }
     122                } else {
     123                    $atts['depth'] = $default;
     124                }
     125                break;
     126            // These should be only strings.
     127            default:
     128                if ( isset( $atts[ $att ] ) ) {
     129                    $passed_att = sanitize_text_field( $atts[ $att ] );
     130                    if ( '' !== $passed_att ) {
     131                        $args[ $att ] = $passed_att;
     132                    }
     133                } else {
     134                    $atts[ $att ] = $default;
     135                }
     136        }
     137    }
     138    if ( 'dropdown' === $atts['style'] ) {
     139        $select = '<select class="mip-drop-nav"';
     140        if ( '' !== $atts['menu_id'] ) {
     141            $select .= ' id="' . $args['menu_id'] . '"';
     142        }
     143        $select            .= '>';
     144        $args['items_wrap'] = $select . '<option value="#">' .
     145            $atts['placeholder_text'] . '</option>%3$s</select>';
     146        $args['walker']     = new MIPWalkerNavMenuDropdownBuilder();
     147    } elseif ( '' !== $atts['append_to_url'] ) {
     148            $args['walker'] = new MIPWalkerNavMenuListBuilder();
     149    }
     150    if ( '' !== $atts['append_to_url'] ) {
     151        $args['append_to_url'] = $atts['append_to_url'];
     152    }
     153    return wp_nav_menu( $args );
    108154}
    109155
     
    111157 * Menu In Post fallback function.
    112158 *
    113  * @return Nothing
    114  */
    115 function fallbackMenuInPost()
    116 {
    117     return;   
    118 }
    119 
    120 add_action('wp_enqueue_scripts', 'enqueueMenuInPostFrontEndJS');
     159 * @return void
     160 */
     161function fallback_mip() {}
     162
     163add_action( 'wp_enqueue_scripts', 'enqueue_mip_front_end_js' );
    121164
    122165/**
    123166 * Selectively enqueues the JavaScript for Menu In Post
    124167 *
    125  * @return Nothing, but it runs wp_enqueue_script().
    126  */
    127 function enqueueMenuInPostFrontEndJS()
    128 {
    129     $options = get_option(
    130         'mip_options',
    131         array(
    132             'miploadjs' => 'always',
    133             'miponlypages' => '',
    134             'mipminimizejs' => 'yes'
    135         )
    136     );
    137    
    138     $load = false;
    139     $loadjs = $options['miploadjs'];
    140     if ($options['mipminimizejs'] === 'yes') {
    141         $file = 'main-min.js';
    142     } else {
    143         $file = 'main.js';
    144     }
    145    
    146     switch($loadjs) {
    147     case 'always':
    148         $load = true;
    149         break;
    150     case 'onlypages':
    151         $pagestr = trim(str_replace(' ', '', $options['miponlypages']));
    152         if ($pagestr !== '') {
    153             $pages = explode(',', $pagestr);
    154             if (is_array($pages)) {
    155                 $pageid = get_queried_object_id();
    156                 if (in_array($pageid, $pages)) {
    157                     $load = true;
    158                 }
    159             }
    160         }
    161         break;
    162     }
    163    
    164     if ($load === true) {
    165         wp_enqueue_script(
    166             'menu_in_post_frontend_script',
    167             plugins_url('js/' . $file, __FILE__),
    168             array('jquery')
    169         );
    170     }
    171 }
    172 
    173 class MIPWalkerNavMenuDropdownBuilder extends Walker_Nav_Menu
    174 {
    175     /**
    176      * Starts the list before the elements are added.
    177      *
    178      * @param string   $output Used to append additional content (passed by ref).
    179      * @param int      $depth  Depth of menu item. Used for padding.
    180      * @param stdClass $args   An object of wp_nav_menu() arguments.
    181      *
    182      * @return Nothing here.
    183      */
    184     function start_lvl(&$output, $depth = 0, $args = null)
    185     {
    186     }
    187    
    188     /**
    189      * Ends the list of after the elements are added.
    190      *
    191      * @param string   $output Used to append additional content (passed by ref).
    192      * @param int      $depth  Depth of menu item. Used for padding.
    193      * @param stdClass $args   An object of wp_nav_menu() arguments.
    194      *
    195      * @return Nothing here.
    196      */
    197     function end_lvl(&$output, $depth = 0, $args = null)
    198     {
    199     }
    200    
    201     /**
    202      * Starts the element output.
    203      *
    204      * @param string   $output Appends additional content (passed by reference).
    205      * @param WP_Post  $item   Menu item data object.
    206      * @param int      $depth  Depth of menu item. Used for padding.
    207      * @param stdClass $args   An object of wp_nav_menu() arguments.
    208      * @param int      $id     The current menu item. Default 0.
    209      *
    210      * @return Returns the HTML output for the element.
    211      */
    212     function start_el(&$output, $item, $depth = 0, $args = null, $id = 0)
    213     {
    214         // Create each option.
    215         $item_output = '';
    216 
    217         // Add spacing to the title based on the depth.
    218         $item->title = str_repeat(' - ', $depth * 1) . $item->title;
    219 
    220         // Get the link.
    221         if (!empty($args->append_to_url)) {
    222             $attributes = !empty($item->url) ? ' value="' . esc_attr($item->url) .
    223                 $args->append_to_url .'"' : '';
    224         } else {
    225             $attributes = !empty($item->url) ? ' value="' . esc_attr($item->url) .
    226                 '"' : '';
    227         }
    228        
    229         // Get the target, if any.
    230         if (!empty($item->target)) {
    231             $attributes .= ' data-target="' . esc_attr($item->target) . '"';
    232         }
    233        
    234         // Add selected attribute if menu item is the current page.
    235         if ($item->current) {
    236             $attributes .= ' selected="selected"';
    237         }
    238        
    239         // Add the HTML.
    240         $item_output .= '<option'. $attributes .'>';
    241         $item_output .= apply_filters('the_title_attribute', $item->title);
    242 
    243         // Add the new item to the output string.
    244         $output .= $item_output;
    245     }
    246    
    247     /**
    248      * Ends the element output, if needed.
    249      *
    250      * @param string   $output Used to append additional content (passed by ref).
    251      * @param WP_Post  $item   Menu item data object. Not used.
    252      * @param int      $depth  Depth of page. Not Used.
    253      * @param stdClass $args   An object of wp_nav_menu() arguments.
    254      *
    255      * @return Returns the closing tag, if needed.
    256      */
    257     function end_el(&$output, $item, $depth = 0, $args = null)
    258     {
    259         // Close the item.
    260         $output .= "</option>\n";
    261 
    262     }
    263 
    264 }
    265 
    266 class MIPWalkerNavMenuListBuilder extends Walker_Nav_Menu
    267 {
    268     /**
    269      * Starts the element output.
    270      *
    271      * @param string   $output Appends additional content (passed by reference).
    272      * @param WP_Post  $item   Menu item data object.
    273      * @param int      $depth  Depth of menu item. Used for padding.
    274      * @param stdClass $args   An object of wp_nav_menu() arguments.
    275      * @param int      $id     The current menu item. Default 0.
    276      *
    277      * @return Returns the HTML output for the element.
    278      */
    279     function start_el(&$output, $item, $depth = 0, $args = null, $id = 0)
    280     {
    281         if (isset($args->item_spacing) && 'discard' === $args->item_spacing) {
    282             $t = '';
    283             $n = '';
    284         } else {
    285             $t = "\t";
    286             $n = "\n";
    287         }
    288         $indent = ( $depth ) ? str_repeat($t, $depth) : '';
    289  
    290         $classes   = empty($item->classes) ? array() : (array) $item->classes;
    291         $classes[] = 'menu-item-' . $item->ID;
    292  
    293         $args = apply_filters('nav_menu_item_args', $args, $item, $depth);
    294  
    295         $class_names = implode(
    296             ' ',
    297             apply_filters(
    298                 'nav_menu_css_class',
    299                 array_filter($classes),
    300                 $item,
    301                 $args,
    302                 $depth
    303             )
    304         );
    305         $class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';
    306  
    307         $id = apply_filters(
    308             'nav_menu_item_id',
    309             'menu-item-' . $item->ID,
    310             $item,
    311             $args,
    312             $depth
    313         );
    314         $id = $id ? ' id="' . esc_attr($id) . '"' : '';
    315  
    316         $output .= $indent . '<li' . $id . $class_names . '>';
    317  
    318         $atts           = array();
    319         $atts['title']  = !empty($item->attr_title) ? $item->attr_title : '';
    320         $atts['target'] = !empty($item->target) ? $item->target : '';
    321         if ('_blank' === $item->target && empty($item->xfn) ) {
    322             $atts['rel'] = 'noopener';
    323         } else {
    324             $atts['rel'] = $item->xfn;
    325         }
    326         if (!empty($args->append_to_url)) {
    327             $atts['href'] = !empty($item->url) ? $item->url .
    328                 $args->append_to_url : '';
    329         } else {
    330             $atts['href'] = !empty($item->url) ? $item->url : '';
    331         }
    332         $atts['aria-current'] = $item->current ? 'page' : '';
    333  
    334         $atts = apply_filters(
    335             'nav_menu_link_attributes',
    336             $atts,
    337             $item,
    338             $args,
    339             $depth
    340         );
    341  
    342         $attributes = '';
    343         foreach ( $atts as $attr => $value ) {
    344             if (is_scalar($value) && '' !== $value && false !== $value ) {
    345                 $value = ( 'href' === $attr ) ? esc_url($value) : esc_attr($value);
    346                 $attributes .= ' ' . $attr . '="' . $value . '"';
    347             }
    348         }
    349  
    350         $title = apply_filters('the_title', $item->title, $item->ID);
    351  
    352         $title = apply_filters('nav_menu_item_title', $title, $item, $args, $depth);
    353  
    354         $item_output  = $args->before;
    355         $item_output .= '<a' . $attributes . '>';
    356         $item_output .= $args->link_before . $title . $args->link_after;
    357         $item_output .= '</a>';
    358         $item_output .= $args->after;
    359  
    360         $output .= apply_filters(
    361             'walker_nav_menu_start_el',
    362             $item_output,
    363             $item,
    364             $depth,
    365             $args
    366         );
    367     }
    368 }
    369 ?>
     168 * @return void
     169 */
     170function enqueue_mip_front_end_js() {
     171    $options = get_option(
     172        'mip_options',
     173        array(
     174            'miploadjs'     => 'always',
     175            'miponlypages'  => '',
     176            'mipminimizejs' => 'yes',
     177        )
     178    );
     179
     180    $load   = false;
     181    $loadjs = $options['miploadjs'];
     182    if ( 'yes' === $options['mipminimizejs'] ) {
     183        $file = 'main-min.js';
     184    } else {
     185        $file = 'main.js';
     186    }
     187
     188    switch ( $loadjs ) {
     189        case 'always':
     190            $load = true;
     191            break;
     192        case 'onlypages':
     193            $pagestr = trim( str_replace( ' ', '', $options['miponlypages'] ) );
     194            if ( '' !== $pagestr ) {
     195                $pages = explode( ',', $pagestr );
     196                if ( is_array( $pages ) ) {
     197                    $pageid = get_queried_object_id();
     198                    if ( in_array( $pageid, $pages, true ) ) {
     199                        $load = true;
     200                    }
     201                }
     202            }
     203            break;
     204    }
     205
     206    if ( true === $load ) {
     207        wp_enqueue_script(
     208            'menu_in_post_frontend_script',
     209            plugins_url( 'js/' . $file, __FILE__ ),
     210            array( 'jquery' ),
     211            MENU_IN_POST_VERSION,
     212            true
     213        );
     214    }
     215}
  • menu-in-post/tags/1.4.0/readme.txt

    r3411215 r3441285  
    55Tested up to: 6.9
    66Requires PHP: 7.4
    7 Stable tag: 1.3
     7Stable tag: 1.4
    88License: GPLv3
    99License URI: https://www.gnu.org/licenses/gpl-3.0-standalone.html
     
    6262
    6363== Changelog ==
     64
     65= 1.4 =
     66
     67* Fixed cross-site scripting vulnerability for users >= contributor, updated code and structure to current WP best-practices.
    6468
    6569= 1.3 =
  • menu-in-post/tags/1.4.0/uninstall.php

    r2912059 r3441285  
    11<?php
    2 if (!defined('WP_UNINSTALL_PLUGIN')) {
    3     die;
     2/**
     3 * Uninstall functions for Menu In Post
     4 *
     5 * @package menu-in-post
     6 * @since 1.0.0
     7 */
     8
     9if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
     10    die;
    411}
    512
    613$option_name = 'mip_options';
    714
    8 delete_option($option_name);
    9 ?>
     15delete_option( $option_name );
  • menu-in-post/trunk/admin/admin.php

    r2994821 r3441285  
    11<?php
    22/**
     3 * Admin functions for Menu In Post
     4 *
     5 * @package menu-in-post
     6 * @since 1.0.0
     7 */
     8
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
     13
     14/**
    315 * Menu In Post options and settings.
    416 *
    5  * @return Nothing
    6  */
    7 function initMenuInPostOptions()
    8 {
    9     // Register option array.
    10     register_setting(
    11         'menu-in-post',
    12         'mip_options'
    13     );
    14    
    15     add_settings_section(
    16         'mip_options_section_js',
    17         __('Javascript Options', 'menu-in-post'),
    18         'callbackMIPJSOptions',
    19         'menu-in-post-options'
    20     );
    21    
    22     /*
    23         Register a new field in the "mip_options_section_js" section, on the
    24         menu-in-post-options page.
    25        
    26         Note: As of WP 4.6, the settings ID is only used internally.
    27        
    28         Use the $args "label_for" to populate the ID inside the callback.
    29        
    30         Note: If you ever add or change settings, make sure you change the
    31         defaults you have set for the get_options() function calls both in
    32         admin.php and in menu-in-post.php.
    33     */
    34     add_settings_field(
    35         'miploadjs',
    36         __('Load JavaScript:', 'menu-in-post'),
    37         'callbackMenuInPostFieldLoadJS',
    38         'menu-in-post-options',
    39         'mip_options_section_js',
    40         array(
    41             'label_for' => 'miploadjs',
    42             'class' => 'mip-option-row'
    43         )
    44     );
    45     add_settings_field(
    46         'miponlypages',
    47         __('Only on Posts/Pages:'),
    48         'callbackMenuInPostFieldOnlyPages',
    49         'menu-in-post-options',
    50         'mip_options_section_js',
    51         array(
    52             'label_for' => 'miponlypages',
    53             'class' => 'mip-options-row mip-only-pages-row'
    54         )
    55     );
    56     add_settings_field(
    57         'mipminimizejs',
    58         __('Minimize JavaScript:'),
    59         'callbackMenuInPostMinimizeJS',
    60         'menu-in-post-options',
    61         'mip_options_section_js',
    62         array(
    63             'label_for' => 'mipminimizejs',
    64             'class' => 'mip-option-row'
    65         )
    66     );
    67    
    68     if (wp_is_block_theme()) {
    69         add_settings_section(
    70             'mip_options_section_appearance_menus',
    71             __('Show Appearance > Menus Submenu Item', 'menu-in-post'),
    72             'callbackMIPAppearanceMenus',
    73             'menu-in-post-options'
    74         );
    75        
    76         add_settings_field(
    77             'mipaddappearancemenu',
    78             __('Show Appearance > Menus:'),
    79             'callbackMIPShowAppearanceMenus',
    80             'menu-in-post-options',
    81             'mip_options_section_appearance_menus',
    82             array(
    83                 'label_for' => 'mipshowappearancemenus',
    84                 'class' => 'mip-option-row'
    85             )
    86         );
    87     }
    88 }
    89 
    90 /**
    91  * Register initMenuInPostOptions to the admin_init action hook.
    92  */
    93 add_action('admin_init', 'initMenuInPostOptions');
     17 * @return void
     18 */
     19function init_menu_in_post_options() {
     20    // Register option array.
     21    register_setting(
     22        'menu-in-post',
     23        'mip_options'
     24    );
     25
     26    add_settings_section(
     27        'mip_options_section_js',
     28        __( 'Javascript Options', 'menu-in-post' ),
     29        'callback_mipjs_options',
     30        'menu-in-post-options'
     31    );
     32
     33    /*
     34        Register a new field in the "mip_options_section_js" section, on the
     35        menu-in-post-options page.
     36
     37        Note: As of WP 4.6, the settings ID is only used internally.
     38
     39        Use the $args "label_for" to populate the ID inside the callback.
     40
     41        Note: If you ever add or change settings, make sure you change the
     42        defaults you have set for the get_options() function calls both in
     43        admin.php and in menu-in-post.php.
     44    */
     45    add_settings_field(
     46        'miploadjs',
     47        __( 'Load JavaScript:', 'menu-in-post' ),
     48        'callback_mip_field_load_js',
     49        'menu-in-post-options',
     50        'mip_options_section_js',
     51        array(
     52            'label_for' => 'miploadjs',
     53            'class'     => 'mip-option-row',
     54        )
     55    );
     56    add_settings_field(
     57        'miponlypages',
     58        __( 'Only on Posts/Pages:' ),
     59        'callback_mip_field_only_pages',
     60        'menu-in-post-options',
     61        'mip_options_section_js',
     62        array(
     63            'label_for' => 'miponlypages',
     64            'class'     => 'mip-options-row mip-only-pages-row',
     65        )
     66    );
     67    add_settings_field(
     68        'mipminimizejs',
     69        __( 'Minimize JavaScript:' ),
     70        'callback_mip_minimize_js',
     71        'menu-in-post-options',
     72        'mip_options_section_js',
     73        array(
     74            'label_for' => 'mipminimizejs',
     75            'class'     => 'mip-option-row',
     76        )
     77    );
     78
     79    if ( wp_is_block_theme() ) {
     80        add_settings_section(
     81            'mip_options_section_appearance_menus',
     82            __( 'Show Appearance > Menus Submenu Item', 'menu-in-post' ),
     83            'callback_mip_appearance_menus',
     84            'menu-in-post-options'
     85        );
     86
     87        add_settings_field(
     88            'mipaddappearancemenu',
     89            __( 'Show Appearance > Menus:' ),
     90            'callback_mip_show_appearance_menus',
     91            'menu-in-post-options',
     92            'mip_options_section_appearance_menus',
     93            array(
     94                'label_for' => 'mipshowappearancemenus',
     95                'class'     => 'mip-option-row',
     96            )
     97        );
     98    }
     99}
     100
     101/**
     102 * Register init_menu_in_post_options to the admin_init action hook.
     103 */
     104add_action( 'admin_init', 'init_menu_in_post_options' );
    94105
    95106/**
     
    98109 * @param array $args Arguments passed to the callback function.
    99110 *
    100  * @return Returns the HTML for the intro.
    101  */
    102 function callbackMIPJSOptions($args)
    103 {
    104     $str = esc_html_e(
    105         'Use the following settings to control how Menu In Post&#39;s JavaScript ' .
    106             'is handled. Click the Help Tab for more information.',
    107         'menu-in-post'
    108     );
    109     ?>
    110     <p id="<?php echo esc_attr($args['id']); ?>">
    111        <?php echo $str; ?>
    112     </p>
    113     <?php
     111 * @return void
     112 */
     113function callback_mipjs_options( $args ) {
     114    // Returns the HTML for the intro.
     115    $str = esc_html__(
     116        "Use the following settings to control how Menu In Post's JavaScript is handled. Click the Help Tab for more information.",
     117        'menu-in-post'
     118    );
     119    ?>
     120    <p id="<?php echo esc_attr( $args['id'] ); ?>">
     121        <?php echo esc_html( $str ); // $str is already escaped, but still generates a warning, so escape it again ?>
     122    </p>
     123    <?php
    114124}
    115125
     
    119129 * @param array $args Arguments passed to the callback function.
    120130 *
    121  * @return Returns the HTML for the intro.
    122  */
    123 function callbackMIPAppearanceMenus($args)
    124 {
    125     $str = esc_html_e(
    126         'Since WordPress version 5.9, the Appearance > Menus menu item is hidden ' .
    127             'for block-enabled themes. Set &quot;Show Appearance > Menus&quot; ' .
    128             'to &quot;yes&quot; to display the menu.',
    129         'menu-in-post'
    130     );
    131     ?>
    132     <p id="<?php echo esc_attr($args['id']); ?>">
    133        <?php echo $str; ?>
    134     </p>
    135     <?php
     131 * @return void
     132 */
     133function callback_mip_appearance_menus( $args ) {
     134    // Returns the HTML for the intro.
     135    $str = esc_html__(
     136        'Since WordPress version 5.9, the Appearance > Menus menu item is hidden for block-enabled themes. Set "Show Appearance > Menus" to "yes" to display the menu.',
     137        'menu-in-post'
     138    );
     139    ?>
     140    <p id="<?php echo esc_attr( $args['id'] ); ?>">
     141        <?php echo esc_html( $str ); // $str is already escaped above, but still generates a warning, so escape it again. ?>
     142    </p>
     143    <?php
    136144}
    137145
     
    141149 * @param array $args Arguments passed to the callback function.
    142150 *
    143  * @return Returns the HTML.
    144  */
    145 function callbackMenuInPostFieldLoadJS($args)
    146 {
    147     $options = get_option('mip_options');
    148     ?>
    149     <select
    150         id="<?php echo esc_attr($args['label_for']); ?>"
    151         name="mip_options[<?php echo esc_attr($args['label_for']); ?>]"
    152     >
    153         <?php
    154         $vals = array(
    155             'always' => 'always (default)',
    156             'never' => 'never',
    157             'onlypages' => 'only on posts/pages'
    158         );
    159         foreach ($vals as $val => $desc) {
    160             $selected = '';
    161             if (isset($options[$args['label_for']])
    162                 && $options[$args['label_for']] == $val
    163             ) {
    164                 $selected = ' selected';
    165             }
    166             ?>
    167             <option
    168                 value="<?php echo $val; ?>"
    169                 <?php echo $selected; ?>
    170             >
    171                 <?php echo $desc; ?>
    172             </option>
    173             <?php
    174         }
    175         ?>
    176     </select>
    177     <?php
     151 * @return void
     152 */
     153function callback_mip_field_load_js( $args ) {
     154    // Returns the HTML.
     155    $options = get_option( 'mip_options' );
     156    ?>
     157    <select
     158        id="<?php echo esc_attr( $args['label_for'] ); ?>"
     159        name="mip_options[<?php echo esc_attr( $args['label_for'] ); ?>]"
     160    >
     161        <?php
     162        $vals = array(
     163            'always'    => 'always (default)',
     164            'never'     => 'never',
     165            'onlypages' => 'only on posts/pages',
     166        );
     167        foreach ( $vals as $val => $desc ) {
     168            $selected = '';
     169            if ( isset( $options[ $args['label_for'] ] )
     170                && $options[ $args['label_for'] ] === $val
     171            ) {
     172                $selected = ' selected';
     173            }
     174            ?>
     175            <option
     176                value="<?php echo esc_html( $val ); ?>"
     177                <?php echo esc_html( $selected ); ?>
     178            >
     179                <?php echo esc_html( $desc ); ?>
     180            </option>
     181            <?php
     182        }
     183        ?>
     184    </select>
     185    <?php
    178186}
    179187
     
    183191 * @param array $args Arguments passed to the callback function.
    184192 *
    185  * @return Returns the HTML.
    186  */
    187 function callbackMenuInPostFieldOnlyPages($args)
    188 {
    189     $options = get_option('mip_options');
    190     if (isset($options[$args['label_for']])) {
    191         $val = $options[$args['label_for']];
    192     } else {
    193         $val = '';
    194     }
    195     ?>
    196     <input
    197         id="<?php echo esc_attr($args['label_for']); ?>"
    198         name="mip_options[<?php echo esc_attr($args['label_for']); ?>]"
    199         type="text"
    200         placeholder="comma-separated post/page IDs"
    201         value="<?php echo $val; ?>"
    202     >
    203     <?php
     193 * @return void
     194 */
     195function callback_mip_field_only_pages( $args ) {
     196    // Returns the HTML.
     197    $options = get_option( 'mip_options' );
     198    if ( isset( $options[ $args['label_for'] ] ) ) {
     199        $val = $options[ $args['label_for'] ];
     200    } else {
     201        $val = '';
     202    }
     203    ?>
     204    <input
     205        id="<?php echo esc_attr( $args['label_for'] ); ?>"
     206        name="mip_options[<?php echo esc_attr( $args['label_for'] ); ?>]"
     207        type="text"
     208        placeholder="comma-separated post/page IDs"
     209        value="<?php echo esc_html( $val ); ?>"
     210    >
     211    <?php
    204212}
    205213
     
    209217 * @param array $args Arguments passed to the callback function.
    210218 *
    211  * @return Returns the HTML.
    212  */
    213 function callbackMenuInPostMinimizeJS($args)
    214 {
    215     $options = get_option('mip_options');
    216     if (isset($options[$args['label_for']])) {
    217         $selected = ' selected';
    218     } else {
    219         $selected = '';
    220     }
    221     ?>
    222     <select
    223         id="<?php echo esc_attr($args['label_for']); ?>"
    224         name="mip_options[<?php echo esc_attr($args['label_for']); ?>]"
    225     >
    226         <?php
    227         $vals = array(
    228             'yes' => 'yes (default)',
    229             'no' => 'no'
    230         );
    231         foreach ($vals as $val => $desc) {
    232             $selected = '';
    233             if (isset($options[$args['label_for']])
    234                 && $options[$args['label_for']] == $val
    235             ) {
    236                 $selected = ' selected';
    237             }
    238             ?>
    239             <option
    240                 value="<?php echo $val; ?>"
    241                 <?php echo $selected; ?>
    242             >
    243                 <?php echo $desc; ?>
    244             </option>
    245             <?php
    246         }
    247         ?>
    248     </select>
    249     <?php
     219 * @return void
     220 */
     221function callback_mip_minimize_js( $args ) {
     222    // Returns the HTML.
     223    $options = get_option( 'mip_options' );
     224    if ( isset( $options[ $args['label_for'] ] ) ) {
     225        $selected = ' selected';
     226    } else {
     227        $selected = '';
     228    }
     229    ?>
     230    <select
     231        id="<?php echo esc_attr( $args['label_for'] ); ?>"
     232        name="mip_options[<?php echo esc_attr( $args['label_for'] ); ?>]"
     233    >
     234        <?php
     235        $vals = array(
     236            'yes' => 'yes (default)',
     237            'no'  => 'no',
     238        );
     239        foreach ( $vals as $val => $desc ) {
     240            $selected = '';
     241            if ( isset( $options[ $args['label_for'] ] )
     242                && $options[ $args['label_for'] ] === $val
     243            ) {
     244                $selected = ' selected';
     245            }
     246            ?>
     247            <option
     248                value="<?php echo esc_html( $val ); ?>"
     249                <?php echo esc_html( $selected ); ?>
     250            >
     251                <?php echo esc_html( $desc ); ?>
     252            </option>
     253            <?php
     254        }
     255        ?>
     256    </select>
     257    <?php
    250258}
    251259
     
    255263 * @param array $args Arguments passed to the callback function.
    256264 *
    257  * @return Returns the HTML.
    258  */
    259 function callbackMIPShowAppearanceMenus($args)
    260 {
    261     $options = get_option('mip_options');
    262     if (isset($options[$args['label_for']])) {
    263         $selected = ' selected';
    264     } else {
    265         $selected = '';
    266     }
    267     ?>
    268     <select
    269         id="<?php echo esc_attr($args['label_for']); ?>"
    270         name="mip_options[<?php echo esc_attr($args['label_for']); ?>]"
    271     >
    272         <?php
    273         $vals = array(
    274             'no' => 'no (default)',
    275             'yes' => 'yes'
    276         );
    277         foreach ($vals as $val => $desc) {
    278             $selected = '';
    279             if (isset($options[$args['label_for']])
    280                 && $options[$args['label_for']] == $val
    281             ) {
    282                 $selected = ' selected';
    283             }
    284             ?>
    285             <option
    286                 value="<?php echo $val; ?>"
    287                 <?php echo $selected; ?>
    288             >
    289                 <?php echo $desc; ?>
    290             </option>
    291             <?php
    292         }
    293         ?>
    294     </select>
    295     <?php
     265 * @return void
     266 */
     267function callback_mip_show_appearance_menus( $args ) {
     268    // Returns the HTML.
     269    $options = get_option( 'mip_options' );
     270    if ( isset( $options[ $args['label_for'] ] ) ) {
     271        $selected = ' selected';
     272    } else {
     273        $selected = '';
     274    }
     275    ?>
     276    <select
     277        id="<?php echo esc_attr( $args['label_for'] ); ?>"
     278        name="mip_options[<?php echo esc_attr( $args['label_for'] ); ?>]"
     279    >
     280        <?php
     281        $vals = array(
     282            'no'  => 'no (default)',
     283            'yes' => 'yes',
     284        );
     285        foreach ( $vals as $val => $desc ) {
     286            $selected = '';
     287            if ( isset( $options[ $args['label_for'] ] )
     288                && $options[ $args['label_for'] ] === $val
     289            ) {
     290                $selected = ' selected';
     291            }
     292            ?>
     293            <option
     294                value="<?php echo esc_html( $val ); ?>"
     295                <?php echo esc_html( $selected ); ?>
     296            >
     297                <?php echo esc_html( $desc ); ?>
     298            </option>
     299            <?php
     300        }
     301        ?>
     302    </select>
     303    <?php
    296304}
    297305
     
    299307 * Create the Menu In Post menus for WordPress Admin.
    300308 *
    301  * @return Returns the options for the Menu In Post menus.
    302  */
    303 function addMenuInPostAdminMenus()
    304 {
    305     $tools = add_submenu_page(
    306         'tools.php',
    307         __('Menu In Post Tools', 'menu-in-post'),
    308         __('Menu In Post Tools', 'menu-in-post'),
    309         'manage_options',
    310         'menu-in-post',
    311         'outputMenuInPostToolsPageHTML'
    312     );
    313     add_action('load-' . $tools, 'loadMenuInPostToolsPage');
    314    
    315     $options = add_submenu_page(
    316         'options-general.php',
    317         __('Menu In Post', 'menu-in-post'),
    318         __('Menu In Post', 'menu-in-post'),
    319         'manage_options',
    320         'menu-in-post-options',
    321         'outputMenuInPostOptionsHTML'
    322     );
    323     add_action('load-' . $options, 'loadMenuInPostOptionsPage');
    324 }
    325 add_action('admin_menu', 'addMenuInPostAdminMenus');
     309 * @return void
     310 */
     311function add_mip_admin_menus() {
     312    // Returns the options for the Menu In Post menus.
     313    $tools = add_submenu_page(
     314        'tools.php',
     315        __( 'Menu In Post Tools', 'menu-in-post' ),
     316        __( 'Menu In Post Tools', 'menu-in-post' ),
     317        'manage_options',
     318        'menu-in-post',
     319        'output_mip_tools_page_html'
     320    );
     321    add_action( 'load-' . $tools, 'load_mip_tools_page' );
     322
     323    $options = add_submenu_page(
     324        'options-general.php',
     325        __( 'Menu In Post', 'menu-in-post' ),
     326        __( 'Menu In Post', 'menu-in-post' ),
     327        'manage_options',
     328        'menu-in-post-options',
     329        'output_mip_post_options_html'
     330    );
     331    add_action( 'load-' . $options, 'load_mip_options_page' );
     332}
     333add_action( 'admin_menu', 'add_mip_admin_menus' );
    326334
    327335/**
    328336 * Load the Menu In Post Tools Admin page and Help Tabs.
    329337 *
    330  * @return Nothing
    331  */
    332 function loadMenuInPostToolsPage()
    333 {
    334     $help_tabs = new MENUINPOST_Help_Tabs(get_current_screen());
    335     $help_tabs->mipSetHelpTabs('tools');
     338 * @return void
     339 */
     340function load_mip_tools_page() {
     341    $help_tabs = new \MenuInPost\MIPHelpTabs( get_current_screen() );
     342    $help_tabs->mip_set_help_tabs( 'tools' );
    336343}
    337344
     
    339346 * Load the Menu In Post Admin Settings page and Help Tabs.
    340347 *
    341  * @return Nothing
    342  */
    343 function loadMenuInPostOptionsPage()
    344 {
    345     $help_tabs = new MENUINPOST_Help_Tabs(get_current_screen());
    346     $help_tabs->mipSetHelpTabs('options');
     348 * @return void
     349 */
     350function load_mip_options_page() {
     351    $help_tabs = new \MenuInPost\MIPHelpTabs( get_current_screen() );
     352    $help_tabs->mip_set_help_tabs( 'options' );
    347353}
    348354
     
    350356 * Output the HTML for the Menu In Post Settings page.
    351357 *
    352  * @return Returns the HTML.
    353  */
    354 function outputMenuInPostOptionsHTML()
    355 {
    356     if (!current_user_can('manage_options')) {
    357         return;
    358     }
    359     /*
    360         Check to see if the user submitted the settings.
    361        
    362         WP adds the "settings-updated" $_GET parameter to the url.
    363     */
    364     if (isset($_GET['settings-updated'])) {
    365         // Add settings saved message with the class of "updated".
    366         add_settings_error(
    367             'mip_messages',
    368             'mip_message',
    369             __('Settings Saved', 'menu-in-post'),
    370             'updated'
    371         );
    372     }
    373 
    374     ?>
    375     <div class="wrap">
    376         <h1><?php echo esc_html(get_admin_page_title()); ?></h1>
    377         <form
    378             name="menu-in-post-options-form"
    379             method="post"
    380             action="options.php"
    381         >
    382             <?php
    383             settings_fields('menu-in-post');
    384             do_settings_sections('menu-in-post-options');
    385             submit_button('Save Settings');
    386             ?>
    387         </form>
    388     </div>
    389     <?php
     358 * @return void
     359 */
     360function output_mip_post_options_html() {
     361    // Returns the HTML.
     362    if ( ! current_user_can( 'manage_options' ) ) {
     363        return;
     364    }
     365    // Check to see if the user submitted the settings.
     366    // WP adds the "settings-updated" $_GET parameter to the url.
     367    if ( isset( $_GET['settings-updated'] ) ) {
     368        /* Verify the nonce that settings_fields() printed. */
     369        if ( isset( $_POST['option_page'] ) && isset( $_POST['_wpnonce'] ) ) {
     370
     371            // Unsanitize the raw POST values.
     372            $option_page = sanitize_key( wp_unslash( $_POST['option_page'] ) );
     373            $nonce       = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) );
     374
     375            // The second argument is the name of the nonce field (default is '_wpnonce').
     376            check_admin_referer( $option_page, '_wpnonce' );
     377        }
     378
     379        // Add settings saved message with the class of "updated".
     380        add_settings_error(
     381            'mip_messages',
     382            'mip_message',
     383            __( 'Settings Saved', 'menu-in-post' ),
     384            'updated'
     385        );
     386    }
     387
     388    ?>
     389    <div class="wrap">
     390        <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
     391        <form
     392            name="menu-in-post-options-form"
     393            method="post"
     394            action="options.php"
     395        >
     396            <?php
     397            settings_fields( 'menu-in-post' );
     398            do_settings_sections( 'menu-in-post-options' );
     399            submit_button( 'Save Settings' );
     400            ?>
     401        </form>
     402    </div>
     403    <?php
    390404}
    391405
     
    393407 * Output the HTML for the Menu In Post Tools page.
    394408 *
    395  * @return Returns the HTML.
    396  */
    397 function outputMenuInPostToolsPageHTML()
    398 {
    399     if (!current_user_can('manage_options')) {
    400         return;
    401     }
    402     $options = get_option(
    403         'mip_options',
    404         array(
    405             'miploadjs' => 'always',
    406             'miponlypages' => '',
    407             'mipminimizejs' => 'yes'
    408         )
    409     );
    410     $shortcode = '';
    411     /*
    412         Fallback for no JavaScript. Normally, the form is submitted via JavaScript,
    413         and everything is done client-side.
    414     */
    415     if (isset($_POST['mip_menu'])) {
    416         $atts = array(
    417         'menu'=>'mip_menu',
    418         'menu_class'=>'mip_menu_class',
    419         'menu_id'=>'mip_menu_id', 
    420         'container'=>'mip_container',
    421         'container_class'=>'mip_container_class',
    422         'container_id'=>'mip_container_id',
    423         'depth'=>'mip_depth',
    424         'style'=>'mip_style',
    425         'placeholder_text'=>'mip_placeholder_text',
    426         'append_to_url'=>'mip_append_to_url'
    427         );
    428         foreach ($atts as $att=>$field) {
    429             switch($att) {
    430             case 'menu':
    431             case 'depth':
    432             case 'container':
    433                 $$att = absint($_POST[$field]);
    434                 break;
    435             break;
    436             // These should only be strings.
    437             default:
    438                 $$att = trim(sanitize_text_field($_POST[$field]));
    439             }
    440         }
    441         // Build the shortcode.
    442         $shortcode = '[menu_in_post_menu';
    443         foreach ($atts as $att=>$field) {
    444             switch($att) {
    445             case 'menu':
    446                 $shortcode .= ' ' . $att . '=' . $$att;
    447                 break;
    448             case 'depth':
    449                 if ($depth > 0) {
    450                     $shortcode .= ' depth=' . $depth;
    451                 }
    452                 break;
    453             case 'style':
    454                 if ($style != 'list') {
    455                     $shortcode .= ' style=' . $style;
    456                 }
    457                 break;
    458             case 'container':
    459                 if ($container == 0) {
    460                     $shortcode .= ' container=&#34;false&#34;';
    461                 }
    462                 break;
    463             default:
    464                 if ($$att != '') {
    465                     $shortcode .= ' ' . $att . '=&#34;' . $$att . '&#34;';
    466                 }
    467             }
    468         }
    469         $shortcode .= ']';
    470     }
    471     /* ************************* End of JavaScript fallback. ********************* */
    472     ?>
    473     <div class="wrap">
    474         <h1><?php echo esc_html(__('Menu In Post Tools', 'menu-in-post')); ?></h1>
    475         <?php
    476         $str = '';
    477         $title = esc_html(__('Note:', 'menu-in-post'));
    478         switch($options['miploadjs']) {
    479         case 'never':
    480             $str = esc_html(
    481                 __(
    482                     'Dropdown-style menus will not work with your current ' .
    483                     'setting of &quot;never&quot; in Settings > Menu In Post, ' .
    484                     'Load JavaScript.', 'menu-in-post'
    485                 )
    486             );
    487             break;
    488         case 'onlypages':
    489             $str = esc_html(
    490                 __(
    491                     'Dropdown-style menus will not work with your current ' .
    492                     'setting of &quot;only on posts/pages&quot; in Settings > ' .
    493                     'Menu In Post > Menu In Post Options, Load JavaScript ' .
    494                     'unless you have set the correct page ID(s) in &quot;Only on ' .
    495                     'Posts/Pages&quot;.',
    496                     'menu-in-post'
    497                 )
    498             );
    499             break;
    500         }
    501         if ($str !== '') {
    502             /*
    503                 Use the wp_admin_notice() function, added in WP 6.4, if possible.
    504                
    505                 Fall back to HTML output if < WP 6.4.
    506                
    507                 You can remove the conditional for WP version once there has
    508                 been time for everyone to upgrade to >= WP 6.4.
    509             */
    510             if (is_wp_version_compatible('6.4')) {
    511                 wp_admin_notice(
    512                     __('<strong>' . $title . '</strong> ' . $str, 'menu-in-post'),
    513                     array(
    514                         'type' => 'warning',
    515                         'dismissible' => false
    516                     )
    517                 );
    518             } else {
    519                 ?>
    520                 <div class="notice notice-warning">
    521                     <p>
    522                         <strong><?php echo $title; ?></strong> <?php echo $str; ?>
    523                     </p>
    524                 </div>
    525                 <?php
    526             }
    527         }
    528         ?>
    529         <p>
    530             <?php
    531                 echo esc_html(
    532                     __(
    533                         'Use the form below to create shortcodes to display ' .
    534                             'menus in posts and pages. Paste the shortcodes ' .
    535                             'you create in a Shortcode Block to display them.',
    536                         'menu-in-post'
    537                     )
    538                 );
    539             ?>
    540         </p>
    541         <h2><?php echo esc_html(__('Shortcode Builder', 'menu-in-post')); ?></h2>
    542     <?php
    543         $menus = wp_get_nav_menus();
    544     if (is_array($menus) && count($menus) > 0) {
    545         ?>
    546         <form
    547             name="mip_shortcode_builder_form"
    548             id="mip_shortcode_builder_form"
    549             method="post"
    550         >
    551             <div class="inputgroup">
    552                 <div class="inputrow">
    553                     <label for="mip_menu">
    554                     <?php
    555                         echo esc_html(__('Select Menu', 'menu-in-post'));
    556                     ?>:
    557                     </label>
    558                     <select name="mip_menu" id="mip_menu">
    559                     <?php
    560                     foreach ($menus as $menu) {
    561                         echo '<option value="' . $menu->term_id . '">' .
    562                             $menu->name . '</option>';
    563                     }
    564                     ?>
    565                     </select>
    566                 </div>
    567                 <div class="inputrow">
    568                     <label for="mip_container">
    569                     <?php
    570                         echo esc_html(
    571                             __('Include Container', 'menu-in-post')
    572                         );
    573                     ?>:
    574                     </label>
    575                     <select name="mip_container" id="mip_container">
    576                         <option value="1">
    577                         <?php echo esc_html(__('Yes', 'menu-in-post')); ?>
    578                         </option>
    579                         <option value="0">
    580                         <?php echo esc_html(__('No', 'menu-in-post')); ?>
    581                         </option>
    582                     </select>
    583                 </div>
    584                 <div class="inputrow">
    585                     <label for="mip_container_id">
    586                         <?php
    587                         echo esc_html(__('Container ID', 'menu-in-post'));
    588                         ?>:
    589                     </label>
    590                     <input
    591                         type="text"
    592                         name="mip_container_id"
    593                         id="mip_container_id"
    594                     >
    595                 </div>
    596                 <div class="inputrow">
    597                     <label for="mip_container_class">
    598                         <?php
    599                         echo esc_html(
    600                             __('Container Class(es)', 'menu-in-post')
    601                         );
    602                         ?>:
    603                     </label>
    604                     <input
    605                         type="text"
    606                         name="mip_container_class"
    607                         id="mip_container_class"
    608                     >
    609                 </div>
    610                 <div class="inputrow">
    611                     <label for="mip_menu_id">
    612                         <?php echo esc_html(__('Menu ID', 'menu-in-post')); ?>:
    613                     </label>
    614                     <input type="text" name="mip_menu_id" id="mip_menu_id">
    615                 </div>
    616                 <div class="inputrow">
    617                     <label for="mip_menu_class">
    618                         <?php
    619                             echo esc_html(__('Menu Class(es)', 'menu-in-post'));
    620                         ?>:
    621                     </label>
    622                     <input type="text" name="mip_menu_class" id="mip_menu_class">
    623                 </div>
    624                 <div class="inputrow">
    625                     <label for="mip_depth">
    626                         <?php echo esc_html(__('Depth', 'menu-in-post')); ?>:
    627                     </label>
    628                     <select name="mip_depth" id="mip_depth">
    629                         <?php
    630                         $depth_options = array(
    631                             0=>esc_html(__('All Levels', 'menu-in-post')),
    632                             1=>esc_html(__('1 Level', 'menu-in-post')),
    633                             2=>esc_html(__('2 Levels', 'menu-in-post')),
    634                             3=>esc_html(__('3 Levels', 'menu-in-post')),
    635                             4=>esc_html(__('4 Levels', 'menu-in-post')),
    636                             5=>esc_html(__('5 Levels', 'menu-in-post'))
    637                         );
    638                         foreach ($depth_options as $value=>$text) {
    639                             if ($value == 0) {
    640                                 echo '<option value="' . $value .
    641                                     '" selected="selected">' . $text .
    642                                     '</option>';
    643                             } else {
    644                                 echo '<option value="' . $value . '">' .
    645                                     $text . '</option>';
    646                             }
    647                         }
    648                         ?>
    649                     </select>
    650                 </div>
    651                 <div class="inputrow">
    652                     <label for="mip_style">
    653                         <?php echo esc_html(__('Style', 'menu-in-post')); ?>:
    654                     </label>
    655                     <select name="mip_style" id="mip_style">
    656                         <?php
    657                         $style_options = array(
    658                             'list'=>esc_html(
    659                                 __('List of Links', 'menu-in-post')
    660                             ),
    661                             'dropdown'=>esc_html(__('Dropdown', 'menu-in-post'))
    662                         );
    663                         foreach ($style_options as $value=>$text) {
    664                             if ($value == 'list') {
    665                                 echo '<option value="' . $value .
    666                                     '" selected="selected">' . $text .
    667                                     '</option>';
    668                             } else {
    669                                 echo '<option value="' . $value . '">' .
    670                                     $text . '</option>';
    671                             }
    672                         }
    673                         ?>
    674                     </select>
    675                 </div>
    676                 <div class="inputrow">
    677                     <label for="mip_placeholder_text">
    678                         <?php
    679                             echo esc_html(
    680                                 __('Placeholder Text', 'menu-in-post')
    681                             );
    682                         ?>:
    683                     </label>
    684                     <input
    685                         type="text"
    686                         name="mip_placeholder_text"
    687                         id="mip_placeholder_text"
    688                     >
    689                 </div>
    690                 <div class="inputrow">
    691                     <label for="mip_append_to_url">
    692                         <?php
    693                             echo esc_html(__('Append to URL', 'menu-in-post'));
    694                         ?>:
    695                     </label>
    696                     <input
    697                         type="text"
    698                         name="mip_append_to_url"
    699                         id="mip_append_to_url"
    700                     >
    701                 </div>
    702             </div><br>
    703             <input
    704                 type="submit"
    705                 name="mip_build"
    706                 value="<?php
    707                     echo esc_attr(__('Build the Shortcode', 'menu-in-post'));
    708                 ?>"
    709             >
    710         </form>
    711         <div>
    712             <label for="mip_shortcode_builder_output">
    713                 <?php echo esc_html(__('Shortcode', 'menu-in-post')); ?>:
    714             </label>
    715             <div class="mip_shortcode_output_hightlight">
    716                 <input
    717                     type="text"
    718                     name="mip_shortcode_builder_output"
    719                     id="mip_shortcode_builder_output"
    720                     value="<?php echo $shortcode; ?>"
    721                     readonly
    722                 >
    723             </div>
    724             <div>
    725                 <button
    726                     type="button"
    727                     id="mip_shortcode_output_copy_button"
    728                 >
    729                 <?php echo esc_html(__('Copy Shortcode', 'menu-in-post')); ?>
    730                 </button>&nbsp;
    731                 <span id="mip_shortcode_copy_success">
    732                     <?php echo esc_html(__('Copied...', 'menu-in-post')); ?>
    733                 </span>
    734             </div>
    735       </div>
    736     </div>
    737         <?php
    738     } else {
    739         $str = esc_html(
    740             __(
    741                 'You must create one or more menus (Appearance > Menus) ' .
    742                     'prior to using Menu In Post&#39;s Shortcode Builder.',
    743                 'menu-in-post'
    744             )
    745         );
    746         /*
    747             Use the wp_admin_notice() function, added in WP 6.4, if possible.
    748            
    749             Fall back to HTML output if < WP 6.4.
    750            
    751             You can remove the conditional for WP version once there has
    752             been time for everyone to upgrade to >= WP 6.4.
    753         */
    754         if (is_wp_version_compatible('6.4')) {
    755             wp_admin_notice(
    756                 __($str, 'menu-in-post'),
    757                 array(
    758                     'type' => 'warning',
    759                     'dismissible' => true
    760                 )
    761             );
    762         } else {
    763             ?>
    764             <div class="notice notice-warning is-dismissible">
    765                 <p><?php echo $str; ?></p>
    766             </div>
    767             <?php
    768         }
    769     }
     409 * @return void
     410 */
     411function output_mip_tools_page_html() {
     412    // Returns the HTML.
     413    // In the Tools page callback (runs on every load).
     414    if ( isset( $_GET['_wpnonce'] ) ) {
     415        // Uns­lash and sanitise the value – PHPCS‑friendly.
     416        $nonce = sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) );
     417
     418        // Verify it against the current screen’s action.
     419        // The first argument is the *action* you want to protect;
     420        // the second argument is the name of the GET variable (default is '_wpnonce').
     421        check_admin_referer( 'menu-in-post', '_wpnonce' );
     422    }
     423
     424    // Capability check.
     425    if ( ! current_user_can( 'manage_options' ) ) {
     426        wp_die( esc_html__( 'You do not have permission for this task.', 'menu-in-post' ), 403 );
     427    }
     428
     429    $options   = get_option(
     430        'mip_options',
     431        array(
     432            'miploadjs'     => 'always',
     433            'miponlypages'  => '',
     434            'mipminimizejs' => 'yes',
     435        )
     436    );
     437    $shortcode = '';
     438    // Fallback for no JavaScript. Normally, the form is submitted via JavaScript,
     439    // and everything is done client-side.
     440    if ( isset( $_POST['mip_menu'] ) ) {
     441        $atts = array(
     442            'menu'             => 'mip_menu',
     443            'menu_class'       => 'mip_menu_class',
     444            'menu_id'          => 'mip_menu_id',
     445            'container'        => 'mip_container',
     446            'container_class'  => 'mip_container_class',
     447            'container_id'     => 'mip_container_id',
     448            'depth'            => 'mip_depth',
     449            'style'            => 'mip_style',
     450            'placeholder_text' => 'mip_placeholder_text',
     451            'append_to_url'    => 'mip_append_to_url',
     452        );
     453        foreach ( $atts as $att => $field ) {
     454            if ( isset( $_POST[ $field ] ) ) {
     455                switch ( $att ) {
     456                    case 'menu':
     457                    case 'depth':
     458                    case 'container':
     459                        $$att = absint( $_POST[ $field ] );
     460                        break;
     461                    // These should only be strings.
     462                    default:
     463                        $$att = trim( sanitize_text_field( wp_unslash( $_POST[ $field ] ) ) );
     464                }
     465            }
     466        }
     467        // Build the shortcode.
     468        $shortcode = '[menu_in_post_menu';
     469        foreach ( $atts as $att => $field ) {
     470            switch ( $att ) {
     471                case 'menu':
     472                    $shortcode .= ' ' . $att . '=' . $$att;
     473                    break;
     474                case 'depth':
     475                    if ( $depth > 0 ) {
     476                        $shortcode .= ' depth=' . $depth;
     477                    }
     478                    break;
     479                case 'style':
     480                    if ( 'list' !== $style ) {
     481                        $shortcode .= ' style=' . $style;
     482                    }
     483                    break;
     484                case 'container':
     485                    if ( 0 === $container ) {
     486                        $shortcode .= ' container=&#34;false&#34;';
     487                    }
     488                    break;
     489                default:
     490                    if ( '' !== $$att ) {
     491                        $shortcode .= ' ' . $att . '=&#34;' . $$att . '&#34;';
     492                    }
     493            }
     494        }
     495        $shortcode .= ']';
     496    }
     497    /* ************************* End of JavaScript fallback. ********************* */
     498    ?>
     499    <div class="wrap">
     500        <h1><?php echo esc_html( __( 'Menu In Post Tools', 'menu-in-post' ) ); ?></h1>
     501        <?php
     502        $str   = '';
     503        $title = esc_html( __( 'Note:', 'menu-in-post' ) );
     504        switch ( $options['miploadjs'] ) {
     505            case 'never':
     506                $str = esc_html(
     507                    __(
     508                        'Dropdown-style menus will not work with your current setting of "never" in Settings > Menu In Post, Load JavaScript.',
     509                        'menu-in-post'
     510                    )
     511                );
     512                break;
     513            case 'onlypages':
     514                $str = esc_html(
     515                    __(
     516                        'Dropdown-style menus will not work with your current setting of "only on posts/pages" in Settings > Menu In Post > Menu In Post Options, Load JavaScript unless you have set the correct page ID(s) in "Only on Posts/Pages".',
     517                        'menu-in-post'
     518                    )
     519                );
     520                break;
     521        }
     522        if ( '' !== $str ) {
     523            /*
     524                Use the wp_admin_notice() function, added in WP 6.4, if possible.
     525
     526                Fall back to HTML output if < WP 6.4.
     527
     528                You can remove the conditional for WP version once there has
     529                been time for everyone to upgrade to >= WP 6.4.
     530            */
     531            if ( is_wp_version_compatible( '6.4' ) ) {
     532                wp_admin_notice(
     533                    sprintf(
     534                        /* translators: %1$s = already‑translated title, %2$s = already‑translated description */
     535                        __( '<strong>%1$s</strong> %2$s', 'menu-in-post' ),
     536                        $title,
     537                        $str
     538                    ),
     539                    array(
     540                        'type'        => 'warning',
     541                        'dismissible' => false,
     542                    )
     543                );
     544            } else {
     545                ?>
     546                <div class="notice notice-warning">
     547                    <p>
     548                        <strong><?php echo esc_html( $title ); ?></strong> <?php echo esc_html( $str ); ?>
     549                    </p>
     550                </div>
     551                <?php
     552            }
     553        }
     554        ?>
     555        <p>
     556            <?php
     557                echo esc_html(
     558                    __(
     559                        'Use the form below to create shortcodes to display menus in posts and pages. Paste the shortcodes you create in a Shortcode Block to display them.',
     560                        'menu-in-post'
     561                    )
     562                );
     563            ?>
     564        </p>
     565        <h2><?php echo esc_html( __( 'Shortcode Builder', 'menu-in-post' ) ); ?></h2>
     566    <?php
     567        $menus = wp_get_nav_menus();
     568    if ( is_array( $menus ) && count( $menus ) > 0 ) {
     569        ?>
     570        <form
     571            name="mip_shortcode_builder_form"
     572            id="mip_shortcode_builder_form"
     573            method="post"
     574        >
     575            <div class="inputgroup">
     576                <div class="inputrow">
     577                    <label for="mip_menu">
     578                    <?php
     579                        echo esc_html( __( 'Select Menu', 'menu-in-post' ) );
     580                    ?>
     581                    :
     582                    </label>
     583                    <select name="mip_menu" id="mip_menu">
     584                    <?php
     585                    foreach ( $menus as $menu ) {
     586                        echo '<option value="' . esc_html( $menu->term_id ) . '">' .
     587                            esc_html( $menu->name ) . '</option>';
     588                    }
     589                    ?>
     590                    </select>
     591                </div>
     592                <div class="inputrow">
     593                    <label for="mip_container">
     594                    <?php
     595                        echo esc_html(
     596                            __( 'Include Container', 'menu-in-post' )
     597                        );
     598                    ?>
     599                    :
     600                    </label>
     601                    <select name="mip_container" id="mip_container">
     602                        <option value="1">
     603                        <?php echo esc_html( __( 'Yes', 'menu-in-post' ) ); ?>
     604                        </option>
     605                        <option value="0">
     606                        <?php echo esc_html( __( 'No', 'menu-in-post' ) ); ?>
     607                        </option>
     608                    </select>
     609                </div>
     610                <div class="inputrow">
     611                    <label for="mip_container_id">
     612                        <?php
     613                        echo esc_html( __( 'Container ID', 'menu-in-post' ) );
     614                        ?>
     615                        :
     616                    </label>
     617                    <input
     618                        type="text"
     619                        name="mip_container_id"
     620                        id="mip_container_id"
     621                    >
     622                </div>
     623                <div class="inputrow">
     624                    <label for="mip_container_class">
     625                        <?php
     626                        echo esc_html(
     627                            __( 'Container Class(es)', 'menu-in-post' )
     628                        );
     629                        ?>
     630                        :
     631                    </label>
     632                    <input
     633                        type="text"
     634                        name="mip_container_class"
     635                        id="mip_container_class"
     636                    >
     637                </div>
     638                <div class="inputrow">
     639                    <label for="mip_menu_id">
     640                        <?php echo esc_html( __( 'Menu ID', 'menu-in-post' ) ); ?>:
     641                    </label>
     642                    <input type="text" name="mip_menu_id" id="mip_menu_id">
     643                </div>
     644                <div class="inputrow">
     645                    <label for="mip_menu_class">
     646                        <?php
     647                            echo esc_html( __( 'Menu Class(es)', 'menu-in-post' ) );
     648                        ?>
     649                        :
     650                    </label>
     651                    <input type="text" name="mip_menu_class" id="mip_menu_class">
     652                </div>
     653                <div class="inputrow">
     654                    <label for="mip_depth">
     655                        <?php echo esc_html( __( 'Depth', 'menu-in-post' ) ); ?>:
     656                    </label>
     657                    <select name="mip_depth" id="mip_depth">
     658                        <?php
     659                        $depth_options = array(
     660                            0 => esc_html( __( 'All Levels', 'menu-in-post' ) ),
     661                            1 => esc_html( __( '1 Level', 'menu-in-post' ) ),
     662                            2 => esc_html( __( '2 Levels', 'menu-in-post' ) ),
     663                            3 => esc_html( __( '3 Levels', 'menu-in-post' ) ),
     664                            4 => esc_html( __( '4 Levels', 'menu-in-post' ) ),
     665                            5 => esc_html( __( '5 Levels', 'menu-in-post' ) ),
     666                        );
     667                        foreach ( $depth_options as $value => $text ) {
     668                            if ( 0 === $value ) {
     669                                echo '<option value="' . esc_html( $value ) .
     670                                    '" selected="selected">' . esc_html( $text ) .
     671                                    '</option>';
     672                            } else {
     673                                echo '<option value="' . esc_html( $value ) . '">' .
     674                                    esc_html( $text ) . '</option>';
     675                            }
     676                        }
     677                        ?>
     678                    </select>
     679                </div>
     680                <div class="inputrow">
     681                    <label for="mip_style">
     682                        <?php echo esc_html( __( 'Style', 'menu-in-post' ) ); ?>:
     683                    </label>
     684                    <select name="mip_style" id="mip_style">
     685                        <?php
     686                        $style_options = array(
     687                            'list'     => esc_html(
     688                                __( 'List of Links', 'menu-in-post' )
     689                            ),
     690                            'dropdown' => esc_html( __( 'Dropdown', 'menu-in-post' ) ),
     691                        );
     692                        foreach ( $style_options as $value => $text ) {
     693                            if ( 'list' === $value ) {
     694                                echo '<option value="' . esc_html( $value ) .
     695                                    '" selected="selected">' . esc_html( $text ) .
     696                                    '</option>';
     697                            } else {
     698                                echo '<option value="' . esc_html( $value ) . '">' .
     699                                    esc_html( $text ) . '</option>';
     700                            }
     701                        }
     702                        ?>
     703                    </select>
     704                </div>
     705                <div class="inputrow">
     706                    <label for="mip_placeholder_text">
     707                        <?php
     708                            echo esc_html(
     709                                __( 'Placeholder Text', 'menu-in-post' )
     710                            );
     711                        ?>
     712                        :
     713                    </label>
     714                    <input
     715                        type="text"
     716                        name="mip_placeholder_text"
     717                        id="mip_placeholder_text"
     718                    >
     719                </div>
     720                <div class="inputrow">
     721                    <label for="mip_append_to_url">
     722                        <?php
     723                            echo esc_html( __( 'Append to URL', 'menu-in-post' ) );
     724                        ?>
     725                        :
     726                    </label>
     727                    <input
     728                        type="text"
     729                        name="mip_append_to_url"
     730                        id="mip_append_to_url"
     731                    >
     732                </div>
     733            </div><br>
     734            <input
     735                type="submit"
     736                name="mip_build"
     737                value="<?php echo esc_attr( __( 'Build the Shortcode', 'menu-in-post' ) ); ?>"
     738            >
     739        </form>
     740        <div>
     741            <label for="mip_shortcode_builder_output">
     742                <?php echo esc_html( __( 'Shortcode', 'menu-in-post' ) ); ?>:
     743            </label>
     744            <div class="mip_shortcode_output_hightlight">
     745                <input
     746                    type="text"
     747                    name="mip_shortcode_builder_output"
     748                    id="mip_shortcode_builder_output"
     749                    value="<?php echo esc_html( $shortcode ); ?>"
     750                    readonly
     751                >
     752            </div>
     753            <div>
     754                <button
     755                    type="button"
     756                    id="mip_shortcode_output_copy_button"
     757                >
     758                <?php echo esc_html( __( 'Copy Shortcode', 'menu-in-post' ) ); ?>
     759                </button>&nbsp;
     760                <span id="mip_shortcode_copy_success">
     761                    <?php echo esc_html( __( 'Copied...', 'menu-in-post' ) ); ?>
     762                </span>
     763            </div>
     764        </div>
     765    </div>
     766        <?php
     767    } elseif ( is_wp_version_compatible( '6.4' ) ) {
     768        /*
     769            Use the wp_admin_notice() function, added in WP 6.4, if possible.
     770
     771            Fall back to HTML output if < WP 6.4.
     772
     773            You can remove the conditional for WP version once there has
     774            been time for everyone to upgrade to >= WP 6.4.
     775        */
     776        wp_admin_notice(
     777            esc_html__(
     778                "You must create one or more menus (Appearance > Menus) prior to using Menu In Post's Shortcode Builder.",
     779                'menu-in-post'
     780            ),
     781            array(
     782                'type'        => 'warning',
     783                'dismissible' => true,
     784            )
     785        );
     786    } else {
     787        ?>
     788        <div class="notice notice-warning is-dismissible">
     789            <p><?php echo esc_html( $str ); ?></p>
     790        </div>
     791        <?php
     792    }
    770793}
    771794
    772795/**
    773796 * Enqueue the scripts and stylesheet(s) required for Menu In Post Admin pages.
    774  * Option: $live can be set to false during development in order to load 
     797 * Option: $live can be set to false during development in order to load
    775798 * unminified versions of CSS and JS in Admin.
    776799 *
    777800 * @param string $hook Hook associated with the Tools page.
    778801 *
    779  * @return Nothing.
    780  */
    781 function enqueueMenuInPostAdminScripts($hook)
    782 {
    783     if ($hook != 'tools_page_menu-in-post'
    784         && $hook != 'settings_page_menu-in-post-options'
    785     ) {
    786         return;
    787     }
    788     $options = get_option(
    789         'mip_options',
    790         array(
    791             'miploadjs' => 'always',
    792             'miponlypages' => '',
    793             'mipminimizejs' => 'yes'
    794         )
    795     );
    796     if ($options['mipminimizejs'] == 'yes') {
    797         $min = '-min';
    798     } else {
    799         $min = '';
    800     }
    801     wp_enqueue_style(
    802         'menu_in_post_admin_style',
    803         plugins_url('css/style' . $min . '.css', __FILE__)
    804     );
    805     wp_enqueue_script(
    806         'menu_in_post_admin_script',
    807         plugins_url('js/main' . $min . '.js', __FILE__),
    808         array('jquery')
    809     );
    810 }
    811 add_action('admin_enqueue_scripts', 'enqueueMenuInPostAdminScripts');
    812 
    813 /**
    814  * Optionally, add back the Appearance > Menus menu subitem so that users
    815  * of block themes can add/edit classic menus for use in Menu In Post by
    816  * registering the existing Menus menu that was removed in WP 5.9+ for
     802 * @return void
     803 */
     804function enqueue_mip_admin_scripts( $hook ) {
     805    if ( 'tools_page_menu-in-post' !== $hook
     806        && 'settings_page_menu-in-post-options' !== $hook
     807    ) {
     808        return;
     809    }
     810    $options = get_option(
     811        'mip_options',
     812        array(
     813            'miploadjs'     => 'always',
     814            'miponlypages'  => '',
     815            'mipminimizejs' => 'yes',
     816        )
     817    );
     818    if ( 'yes' === $options['mipminimizejs'] ) {
     819        $min = '-min';
     820    } else {
     821        $min = '';
     822    }
     823    wp_enqueue_style(
     824        'menu_in_post_admin_style',
     825        plugins_url( 'css/style' . $min . '.css', __FILE__ ),
     826        array(),
     827        MENU_IN_POST_VERSION,
     828        'all'
     829    );
     830    wp_enqueue_script(
     831        'menu_in_post_admin_script',
     832        plugins_url( 'js/main' . $min . '.js', __FILE__ ),
     833        array( 'jquery' ),
     834        MENU_IN_POST_VERSION,
     835        false
     836    );
     837}
     838add_action( 'admin_enqueue_scripts', 'enqueue_mip_admin_scripts' );
     839
     840/**
     841 * Optionally, add back the Appearance > Menus menu subitem so that users
     842 * of block themes can add/edit classic menus for use in Menu In Post by
     843 * registering the existing Menus menu that was removed in WP 5.9+ for
    817844 * block-enabled themes.
    818845 *
    819  * @return Nothing.
    820  */
    821 function getBackAppearanceMenus()
    822 {
    823     $options = get_option(
    824         'mip_options',
    825         array('mipshowappearancemenus' => 'no')
    826     );
    827     if (array_key_exists('mipshowappearancemenus', $options)) {
    828         if ($options['mipshowappearancemenus'] == 'yes' && wp_is_block_theme()) {
    829             register_nav_menus(
    830                 array(
    831                     'primary' => esc_html__('Primary Menu',
    832                     'raft'
    833                     )
    834                 )
    835             );
    836         }
    837     }
    838 }
    839 add_action('init', 'getBackAppearanceMenus');
     846 * @return void
     847 */
     848function get_back_appearance_menus() {
     849    $options = get_option(
     850        'mip_options',
     851        array( 'mipshowappearancemenus' => 'no' )
     852    );
     853    if ( array_key_exists( 'mipshowappearancemenus', $options ) ) {
     854        if ( 'yes' === $options['mipshowappearancemenus'] && wp_is_block_theme() ) {
     855            register_nav_menus(
     856                array(
     857                    'primary' => esc_html__(
     858                        'Primary Menu',
     859                        'raft'
     860                    ),
     861                )
     862            );
     863        }
     864    }
     865}
     866add_action( 'init', 'get_back_appearance_menus' );
    840867?>
  • menu-in-post/trunk/menu-in-post.php

    r3079625 r3441285  
    66 * Author URI: https://profiles.wordpress.org/linux4me2
    77 * Text Domain: menu-in-post
    8  * Version: 1.3
     8 * Version: 1.4
    99 * License: GPL3
    1010 * License URI: https://www.gnu.org/licenses/gpl-3.0-standalone.html
    11  */
    12 
    13 defined('ABSPATH') or die('No direct access.');
    14 
    15 define('MENUINPOST_PLUGIN', __FILE__);
    16 define('MENUINPOST_PLUGIN_DIR', untrailingslashit(dirname(MENUINPOST_PLUGIN)));
    17 
    18 if (is_admin()) {
    19     include_once MENUINPOST_PLUGIN_DIR . '/admin/help-tabs.php';
    20     include_once MENUINPOST_PLUGIN_DIR . '/admin/admin.php';
    21 }
    22 
    23 add_shortcode('menu_in_post_menu', 'outputMenuInPostMenu');
     11 *
     12 * @package menu-in-post
     13 */
     14
     15use MenuInPost\MIPHelpTabs;
     16use MenuInPost\MIPWalkerNavMenuDropdownBuilder;
     17use MenuInPost\MIPWalkerNavMenuListBuilder;
     18
     19// Prevent direct access.
     20if ( ! defined( 'ABSPATH' ) ) {
     21    exit;
     22}
     23
     24define( 'MENUINPOST_PLUGIN', __FILE__ );
     25define( 'MENUINPOST_PLUGIN_DIR', untrailingslashit( dirname( MENUINPOST_PLUGIN ) ) );
     26
     27if ( ! defined( 'MENU_IN_POST_VERSION' ) ) {
     28    define( 'MENU_IN_POST_VERSION', '1.4' ); // keep in sync with the plugin header.
     29}
     30
     31// Register a simple autoloader that looks in the plugin’s root directory.
     32spl_autoload_register(
     33    function ( $theclass ) {
     34       
     35       
     36       
     37        $prefix = 'MenuInPost\\';
     38        $base   = __DIR__ . '/';
     39
     40        // Only handle our own namespace.
     41        $len = strlen( $prefix );
     42        if ( strncmp( $prefix, $theclass, $len ) !== 0 ) {
     43                return;
     44        }
     45
     46        // Strip the namespace prefix.
     47        $relative = substr( $theclass, $len );
     48
     49        // Convert namespace separators to directory separators.
     50        $relative = str_replace( '\\', '/', $relative );
     51
     52        // Build the full path to the file.
     53        $file = $base . 'class-' . strtolower($relative) . '.php';
     54       
     55        // ******************** Debugging code. ********************
     56        //error_log( "[MenuInPost] Autoloader invoked for class: $theclass" );
     57        //error_log( "[MenuInPost] class filename = $file" );
     58        // ******************** End debugging code. ****************
     59       
     60        if ( file_exists( $file ) ) {
     61            require_once $file;
     62        }
     63    }
     64);
     65
     66if ( is_admin() ) {
     67    include_once MENUINPOST_PLUGIN_DIR . '/admin/admin.php';
     68}
     69
     70add_shortcode( 'menu_in_post_menu', 'output_mip_menu' );
     71
    2472
    2573/**
     
    3078 * @return Returns the menu via wp_nav_menu()
    3179 */
    32 function outputMenuInPostMenu($atts = array())
    33 {
    34     if (isset($atts['menu'])) {
    35         $menu = absint($atts['menu']);
    36     } else {
    37         $menu = 0;
    38     }
    39     if ($menu == 0) {
    40         return fallbackMenuInPost();
    41     } else {
    42         $args = array(
    43             'menu'=>$menu,
    44             'fallback_cb'=>'fallbackMenuInPost',
    45             'echo'=>false
    46         );
    47     }
    48     /*
    49         If menu_id is empty, don't pass a value, and the menu slug with an
    50         incremented value added will be used.
    51          
    52         If container_class is empty, don't pass a value and
    53         'menu-{menu slug}-container' will be used.
    54     */
    55     $defaults = array(
    56         'menu_class'=>'menu',
    57         'menu_id'=>'',   
    58         'container'=>'div',
    59         'container_class'=>'',
    60         'container_id'=>'',
    61         'style'=>'list',
    62         'placeholder_text'=>esc_html(__('Select...', 'menu-in-post')),
    63         'append_to_url'=>'',
    64         'depth'=>0
    65     );
    66     foreach ($defaults as $att=>$default) {
    67         switch($att) {
    68         case 'depth':
    69             if (isset($atts[$att])) {
    70                  $passed_depth = absint($atts[$att]);
    71                 if ($passed_depth > 0) {
    72                     $args['depth'] = $passed_depth;
    73                 }
    74             } else {
    75                 $atts['depth'] = $default;
    76             }
    77             break;
    78         // These should be only strings.
    79         default:
    80             if (isset($atts[$att])) {
    81                 $passed_att = sanitize_text_field($atts[$att]);
    82                 if ($passed_att != '') {
    83                     $args[$att] = $passed_att;
    84                 }
    85             } else {
    86                 $atts[$att] = $default;
    87             }
    88         }   
    89     }
    90     if ($atts['style'] == 'dropdown') {
    91         $select = '<select class="mip-drop-nav"';
    92         if ($atts['menu_id'] != '') {
    93             $select .= ' id="' . $args['menu_id'] . '"';
    94         }
    95         $select .= '>';
    96         $args['items_wrap'] = $select . '<option value="#">' .
    97             $atts['placeholder_text'] . '</option>%3$s</select>';
    98         $args['walker'] = new MIPWalkerNavMenuDropdownBuilder();
    99     } else {
    100         if ($atts['append_to_url'] != '') {
    101             $args['walker'] = new MIPWalkerNavMenuListBuilder();
    102         }
    103     }
    104     if ($atts['append_to_url'] != '') {
    105         $args['append_to_url'] = $atts['append_to_url'];
    106     }
    107     return wp_nav_menu($args);
     80function output_mip_menu( $atts = array() ) {
     81    if ( isset( $atts['menu'] ) ) {
     82        $menu = absint( $atts['menu'] );
     83    } else {
     84        $menu = 0;
     85    }
     86    if ( 0 === $menu ) {
     87        return fallback_mip();
     88    } else {
     89        $args = array(
     90            'menu'        => $menu,
     91            'fallback_cb' => 'fallback_mip',
     92            'echo'        => false,
     93        );
     94    }
     95
     96    /*
     97        If menu_id is empty, don't pass a value, and the menu slug with an
     98        incremented value added will be used.
     99
     100        If container_class is empty, don't pass a value and
     101        'menu-{menu slug}-container' will be used.
     102    */
     103    $defaults = array(
     104        'menu_class'       => 'menu',
     105        'menu_id'          => '',
     106        'container'        => 'div',
     107        'container_class'  => '',
     108        'container_id'     => '',
     109        'style'            => 'list',
     110        'placeholder_text' => esc_html( __( 'Select...', 'menu-in-post' ) ),
     111        'append_to_url'    => '',
     112        'depth'            => 0,
     113    );
     114    foreach ( $defaults as $att => $default ) {
     115        switch ( $att ) {
     116            case 'depth':
     117                if ( isset( $atts[ $att ] ) ) {
     118                    $passed_depth = absint( $atts[ $att ] );
     119                    if ( $passed_depth > 0 ) {
     120                        $args['depth'] = $passed_depth;
     121                    }
     122                } else {
     123                    $atts['depth'] = $default;
     124                }
     125                break;
     126            // These should be only strings.
     127            default:
     128                if ( isset( $atts[ $att ] ) ) {
     129                    $passed_att = sanitize_text_field( $atts[ $att ] );
     130                    if ( '' !== $passed_att ) {
     131                        $args[ $att ] = $passed_att;
     132                    }
     133                } else {
     134                    $atts[ $att ] = $default;
     135                }
     136        }
     137    }
     138    if ( 'dropdown' === $atts['style'] ) {
     139        $select = '<select class="mip-drop-nav"';
     140        if ( '' !== $atts['menu_id'] ) {
     141            $select .= ' id="' . $args['menu_id'] . '"';
     142        }
     143        $select            .= '>';
     144        $args['items_wrap'] = $select . '<option value="#">' .
     145            $atts['placeholder_text'] . '</option>%3$s</select>';
     146        $args['walker']     = new MIPWalkerNavMenuDropdownBuilder();
     147    } elseif ( '' !== $atts['append_to_url'] ) {
     148            $args['walker'] = new MIPWalkerNavMenuListBuilder();
     149    }
     150    if ( '' !== $atts['append_to_url'] ) {
     151        $args['append_to_url'] = $atts['append_to_url'];
     152    }
     153    return wp_nav_menu( $args );
    108154}
    109155
     
    111157 * Menu In Post fallback function.
    112158 *
    113  * @return Nothing
    114  */
    115 function fallbackMenuInPost()
    116 {
    117     return;   
    118 }
    119 
    120 add_action('wp_enqueue_scripts', 'enqueueMenuInPostFrontEndJS');
     159 * @return void
     160 */
     161function fallback_mip() {}
     162
     163add_action( 'wp_enqueue_scripts', 'enqueue_mip_front_end_js' );
    121164
    122165/**
    123166 * Selectively enqueues the JavaScript for Menu In Post
    124167 *
    125  * @return Nothing, but it runs wp_enqueue_script().
    126  */
    127 function enqueueMenuInPostFrontEndJS()
    128 {
    129     $options = get_option(
    130         'mip_options',
    131         array(
    132             'miploadjs' => 'always',
    133             'miponlypages' => '',
    134             'mipminimizejs' => 'yes'
    135         )
    136     );
    137    
    138     $load = false;
    139     $loadjs = $options['miploadjs'];
    140     if ($options['mipminimizejs'] === 'yes') {
    141         $file = 'main-min.js';
    142     } else {
    143         $file = 'main.js';
    144     }
    145    
    146     switch($loadjs) {
    147     case 'always':
    148         $load = true;
    149         break;
    150     case 'onlypages':
    151         $pagestr = trim(str_replace(' ', '', $options['miponlypages']));
    152         if ($pagestr !== '') {
    153             $pages = explode(',', $pagestr);
    154             if (is_array($pages)) {
    155                 $pageid = get_queried_object_id();
    156                 if (in_array($pageid, $pages)) {
    157                     $load = true;
    158                 }
    159             }
    160         }
    161         break;
    162     }
    163    
    164     if ($load === true) {
    165         wp_enqueue_script(
    166             'menu_in_post_frontend_script',
    167             plugins_url('js/' . $file, __FILE__),
    168             array('jquery')
    169         );
    170     }
    171 }
    172 
    173 class MIPWalkerNavMenuDropdownBuilder extends Walker_Nav_Menu
    174 {
    175     /**
    176      * Starts the list before the elements are added.
    177      *
    178      * @param string   $output Used to append additional content (passed by ref).
    179      * @param int      $depth  Depth of menu item. Used for padding.
    180      * @param stdClass $args   An object of wp_nav_menu() arguments.
    181      *
    182      * @return Nothing here.
    183      */
    184     function start_lvl(&$output, $depth = 0, $args = null)
    185     {
    186     }
    187    
    188     /**
    189      * Ends the list of after the elements are added.
    190      *
    191      * @param string   $output Used to append additional content (passed by ref).
    192      * @param int      $depth  Depth of menu item. Used for padding.
    193      * @param stdClass $args   An object of wp_nav_menu() arguments.
    194      *
    195      * @return Nothing here.
    196      */
    197     function end_lvl(&$output, $depth = 0, $args = null)
    198     {
    199     }
    200    
    201     /**
    202      * Starts the element output.
    203      *
    204      * @param string   $output Appends additional content (passed by reference).
    205      * @param WP_Post  $item   Menu item data object.
    206      * @param int      $depth  Depth of menu item. Used for padding.
    207      * @param stdClass $args   An object of wp_nav_menu() arguments.
    208      * @param int      $id     The current menu item. Default 0.
    209      *
    210      * @return Returns the HTML output for the element.
    211      */
    212     function start_el(&$output, $item, $depth = 0, $args = null, $id = 0)
    213     {
    214         // Create each option.
    215         $item_output = '';
    216 
    217         // Add spacing to the title based on the depth.
    218         $item->title = str_repeat(' - ', $depth * 1) . $item->title;
    219 
    220         // Get the link.
    221         if (!empty($args->append_to_url)) {
    222             $attributes = !empty($item->url) ? ' value="' . esc_attr($item->url) .
    223                 $args->append_to_url .'"' : '';
    224         } else {
    225             $attributes = !empty($item->url) ? ' value="' . esc_attr($item->url) .
    226                 '"' : '';
    227         }
    228        
    229         // Get the target, if any.
    230         if (!empty($item->target)) {
    231             $attributes .= ' data-target="' . esc_attr($item->target) . '"';
    232         }
    233        
    234         // Add selected attribute if menu item is the current page.
    235         if ($item->current) {
    236             $attributes .= ' selected="selected"';
    237         }
    238        
    239         // Add the HTML.
    240         $item_output .= '<option'. $attributes .'>';
    241         $item_output .= apply_filters('the_title_attribute', $item->title);
    242 
    243         // Add the new item to the output string.
    244         $output .= $item_output;
    245     }
    246    
    247     /**
    248      * Ends the element output, if needed.
    249      *
    250      * @param string   $output Used to append additional content (passed by ref).
    251      * @param WP_Post  $item   Menu item data object. Not used.
    252      * @param int      $depth  Depth of page. Not Used.
    253      * @param stdClass $args   An object of wp_nav_menu() arguments.
    254      *
    255      * @return Returns the closing tag, if needed.
    256      */
    257     function end_el(&$output, $item, $depth = 0, $args = null)
    258     {
    259         // Close the item.
    260         $output .= "</option>\n";
    261 
    262     }
    263 
    264 }
    265 
    266 class MIPWalkerNavMenuListBuilder extends Walker_Nav_Menu
    267 {
    268     /**
    269      * Starts the element output.
    270      *
    271      * @param string   $output Appends additional content (passed by reference).
    272      * @param WP_Post  $item   Menu item data object.
    273      * @param int      $depth  Depth of menu item. Used for padding.
    274      * @param stdClass $args   An object of wp_nav_menu() arguments.
    275      * @param int      $id     The current menu item. Default 0.
    276      *
    277      * @return Returns the HTML output for the element.
    278      */
    279     function start_el(&$output, $item, $depth = 0, $args = null, $id = 0)
    280     {
    281         if (isset($args->item_spacing) && 'discard' === $args->item_spacing) {
    282             $t = '';
    283             $n = '';
    284         } else {
    285             $t = "\t";
    286             $n = "\n";
    287         }
    288         $indent = ( $depth ) ? str_repeat($t, $depth) : '';
    289  
    290         $classes   = empty($item->classes) ? array() : (array) $item->classes;
    291         $classes[] = 'menu-item-' . $item->ID;
    292  
    293         $args = apply_filters('nav_menu_item_args', $args, $item, $depth);
    294  
    295         $class_names = implode(
    296             ' ',
    297             apply_filters(
    298                 'nav_menu_css_class',
    299                 array_filter($classes),
    300                 $item,
    301                 $args,
    302                 $depth
    303             )
    304         );
    305         $class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';
    306  
    307         $id = apply_filters(
    308             'nav_menu_item_id',
    309             'menu-item-' . $item->ID,
    310             $item,
    311             $args,
    312             $depth
    313         );
    314         $id = $id ? ' id="' . esc_attr($id) . '"' : '';
    315  
    316         $output .= $indent . '<li' . $id . $class_names . '>';
    317  
    318         $atts           = array();
    319         $atts['title']  = !empty($item->attr_title) ? $item->attr_title : '';
    320         $atts['target'] = !empty($item->target) ? $item->target : '';
    321         if ('_blank' === $item->target && empty($item->xfn) ) {
    322             $atts['rel'] = 'noopener';
    323         } else {
    324             $atts['rel'] = $item->xfn;
    325         }
    326         if (!empty($args->append_to_url)) {
    327             $atts['href'] = !empty($item->url) ? $item->url .
    328                 $args->append_to_url : '';
    329         } else {
    330             $atts['href'] = !empty($item->url) ? $item->url : '';
    331         }
    332         $atts['aria-current'] = $item->current ? 'page' : '';
    333  
    334         $atts = apply_filters(
    335             'nav_menu_link_attributes',
    336             $atts,
    337             $item,
    338             $args,
    339             $depth
    340         );
    341  
    342         $attributes = '';
    343         foreach ( $atts as $attr => $value ) {
    344             if (is_scalar($value) && '' !== $value && false !== $value ) {
    345                 $value = ( 'href' === $attr ) ? esc_url($value) : esc_attr($value);
    346                 $attributes .= ' ' . $attr . '="' . $value . '"';
    347             }
    348         }
    349  
    350         $title = apply_filters('the_title', $item->title, $item->ID);
    351  
    352         $title = apply_filters('nav_menu_item_title', $title, $item, $args, $depth);
    353  
    354         $item_output  = $args->before;
    355         $item_output .= '<a' . $attributes . '>';
    356         $item_output .= $args->link_before . $title . $args->link_after;
    357         $item_output .= '</a>';
    358         $item_output .= $args->after;
    359  
    360         $output .= apply_filters(
    361             'walker_nav_menu_start_el',
    362             $item_output,
    363             $item,
    364             $depth,
    365             $args
    366         );
    367     }
    368 }
    369 ?>
     168 * @return void
     169 */
     170function enqueue_mip_front_end_js() {
     171    $options = get_option(
     172        'mip_options',
     173        array(
     174            'miploadjs'     => 'always',
     175            'miponlypages'  => '',
     176            'mipminimizejs' => 'yes',
     177        )
     178    );
     179
     180    $load   = false;
     181    $loadjs = $options['miploadjs'];
     182    if ( 'yes' === $options['mipminimizejs'] ) {
     183        $file = 'main-min.js';
     184    } else {
     185        $file = 'main.js';
     186    }
     187
     188    switch ( $loadjs ) {
     189        case 'always':
     190            $load = true;
     191            break;
     192        case 'onlypages':
     193            $pagestr = trim( str_replace( ' ', '', $options['miponlypages'] ) );
     194            if ( '' !== $pagestr ) {
     195                $pages = explode( ',', $pagestr );
     196                if ( is_array( $pages ) ) {
     197                    $pageid = get_queried_object_id();
     198                    if ( in_array( $pageid, $pages, true ) ) {
     199                        $load = true;
     200                    }
     201                }
     202            }
     203            break;
     204    }
     205
     206    if ( true === $load ) {
     207        wp_enqueue_script(
     208            'menu_in_post_frontend_script',
     209            plugins_url( 'js/' . $file, __FILE__ ),
     210            array( 'jquery' ),
     211            MENU_IN_POST_VERSION,
     212            true
     213        );
     214    }
     215}
  • menu-in-post/trunk/readme.txt

    r3411215 r3441285  
    55Tested up to: 6.9
    66Requires PHP: 7.4
    7 Stable tag: 1.3
     7Stable tag: 1.4
    88License: GPLv3
    99License URI: https://www.gnu.org/licenses/gpl-3.0-standalone.html
     
    6262
    6363== Changelog ==
     64
     65= 1.4 =
     66
     67* Fixed cross-site scripting vulnerability for users >= contributor, updated code and structure to current WP best-practices.
    6468
    6569= 1.3 =
  • menu-in-post/trunk/uninstall.php

    r2912059 r3441285  
    11<?php
    2 if (!defined('WP_UNINSTALL_PLUGIN')) {
    3     die;
     2/**
     3 * Uninstall functions for Menu In Post
     4 *
     5 * @package menu-in-post
     6 * @since 1.0.0
     7 */
     8
     9if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
     10    die;
    411}
    512
    613$option_name = 'mip_options';
    714
    8 delete_option($option_name);
    9 ?>
     15delete_option( $option_name );
Note: See TracChangeset for help on using the changeset viewer.