web-dev-qa-db-fra.com

Wordpress API Menu/Sous-menu Ordre

Je développe un thème enfant en utilisant Wordpress 3.4.2 et la version de développement de Options Framework par David Price. C’est mon premier thème et je suis relativement nouveau dans ce domaine. J’ai donc jeté un œil au Codex Wordpress et j’ai vérifié comment enregistrer des éléments dans l’API.

Sans toucher à aucun fichier externe en dehors de mon thème, je me demandais s’il existait un moyen de réorganiser l’emplacement de la page Theme Options dans la hiérarchie du menu Appearance. est activé, la position n’est pas celle de la première image mais celle de la seconde.

oldnew

Je sais que vous pouvez créer un menu (tel que l'onglet Appearance, Plugins, Users etc.) ou un sous-menu (Themes, Widgets , Menus etc.), mais comment puis-je configurer un sous-menu, deuxième à partir du haut?

D'après ce que je comprends, une commande est appelée quelque part et toutes les autres pages supplémentaires du fichier functions.php sont placées après celles-ci?

Dans mon fichier functions.php:

// Add our "Theme Options" page to the Wordpress API admin menu.
if ( !function_exists( 'optionsframework_init' ) ) {
    define( 'OPTIONS_FRAMEWORK_DIRECTORY', get_template_directory_uri() . '/inc/' );
    require_once dirname( __FILE__ ) . '/inc/options-framework.php';
}

Merci.

11
user1752759

Voici un exemple.

Tout d’abord, pour déterminer l’ordre des éléments de sous-menu en fonction de la clé de tableau, vous pouvez créer un var_dump dans la variable globale $ du sous-menu, ce qui donnera le résultat suivant:

(J'utilise le menu Messages et le sous-menu comme exemple)

  //shortened for brevity....

  ["edit.php"]=>
  array(6) {
    [5]=>
    array(3) {
      [0]=> string(9) "All Posts"
      [1]=> string(10) "edit_posts"
      [2]=> string(8) "edit.php"
    }
    [10]=>
    array(3) {
      [0]=> string(7) "Add New"
      [1]=> string(10) "edit_posts"
      [2]=> string(12) "post-new.php"
    }
    [15]=>
    array(3) {
      [0]=> string(10) "Categories"
      [1]=> string(17) "manage_categories"
      [2]=> string(31) "edit-tags.php?taxonomy=category"
    }
    [17]=>
    array(3) {
      [0]=> string(14) "Sub Menu Title"
      [1]=> string(10) "edit_posts"
      [2]=> string(17) "sub_menu_page.php"
    }
  }

Nous pouvons voir que mon élément de sous-menu est ajouté au tableau avec une clé de 17 après les éléments par défaut.

Si, par exemple, je veux ajouter mon élément de menu, directement après l’option Tous les articles , je dois le faire en définissant ma clé de tableau sur 6, 7, 8 ou 9 (tout élément situé entre 5 et avant 10). respectivement.

Voici comment tu le fais ...

function change_submenu_order() {

    global $menu;
    global $submenu;

     //set our new key
    $new_key['edit.php'][6] = $submenu['edit.php'][17];

    //unset the old key
    unset($submenu['edit.php'][17]);

    //get our new key back into the array
    $submenu['edit.php'][6] = $new_key['edit.php'][6];


    //sort the array - important! If you don't the key will be appended
    //to the end of $submenu['edit.php'] array. We don't want that, we
    //our keys to be in descending order
    ksort($submenu['edit.php']);

}

Résultat,

  ["edit.php"]=>
  array(6) {
    [5]=>
    array(3) {
      [0]=> string(9) "All Posts"
      [1]=> string(10) "edit_posts"
      [2]=> string(8) "edit.php"
    }
    [6]=>
    array(3) {
      [0]=> string(14) "Sub Menu Title"
      [1]=> string(10) "edit_posts"
      [2]=> string(17) "sub_menu_page.php"
    }
    [10]=>
    array(3) {
      [0]=> string(7) "Add New"
      [1]=> string(10) "edit_posts"
      [2]=> string(12) "post-new.php"
    }
    [15]=>
    array(3) {
      [0]=> string(10) "Categories"
      [1]=> string(17) "manage_categories"
      [2]=> string(31) "edit-tags.php?taxonomy=category"
    }
  }

... essayez et laissez-nous savoir comment vous allez!

Mise à jour 1:

Ajoutez ceci à votre fichier functions.php;

function change_post_menu_label() {

    global $menu;
    global $submenu;

    $my_menu  = 'example_page'; //set submenu page via its ID
    $location = 1; //set the position (1 = first item etc)
    $target_menu = 'edit.php'; //the menu we are adding our item to

    /* ----- do not edit below this line ----- */


    //check if our desired location is already used by another submenu item
    //if TRUE add 1 to our value so menu items don't clash and override each other
    $existing_key = array_keys( $submenu[$target_menu] );
    if ($existing_key = $location)
    $location = $location + 1;

    $key = false;
    foreach ( $submenu[$target_menu] as $index => $values ){

        $key = array_search( $my_menu, $values );

        if ( false !== $key ){
            $key = $index;
            break;
        }
    }

     $new['edit.php'][$location] = $submenu[$target_menu][$key];
     unset($submenu[$target_menu][$key]);
     $submenu[$target_menu][$location] = $new[$target_menu][$location];

    ksort($submenu[$target_menu]);

}

Ma mise à jour inclut un moyen légèrement plus facile de gérer le paramétrage de la position de votre menu. Il vous suffit de préciser le nom de la page de votre sous-menu et la position souhaitée dans le menu. Toutefois, si vous sélectionnez une page de sous-menu $location égale à celle d'une touche existante, cette touche sera remplacée par la votre, ainsi l'élément de menu disparaîtra avec votre élément de menu à la place. Incrémentez ou décrémentez le nombre afin d’organiser correctement votre menu si tel est le cas. De même, si quelqu'un installe un plug-in qui affecte le même domaine de menu et qui a le même $location que votre élément de sous-menu, le même problème se produira. Pour contourner cela, l'exemple de Kaiser fournit quelques vérifications de base à ce sujet.

Mise à jour 2:

J'ai ajouté un bloc de code supplémentaire qui vérifie toutes les clés existantes du tableau par rapport à notre $location souhaité et si une correspondance est trouvée, nous incrémenterons notre valeur $location de 1 afin d'éviter que les éléments de menu ne se superposent. C'est le code responsable de cela,

   //excerpted snippet only for example purposes (found in original code above)
   $existing_key = array_keys( $submenu[$target_menu] );
   if ($existing_key = $location)
   $location = $location + 1;

Mise à jour 3: (script révisé pour permettre le tri de plusieurs éléments de sous-menu)

add_action('admin_init', 'move_theme_options_label', 999);

function move_theme_options_label() {
    global $menu;
    global $submenu;

$target_menu = array(
    'themes.php' => array(
        array('id' => 'optionsframework', 'pos' => 2),
        array('id' => 'bp-tpack-options', 'pos' => 4),
        array('id' => 'multiple_sidebars', 'pos' => 3),
        )
);

$key = false;

foreach ( $target_menu as $menus => $atts ){

    foreach ($atts as $att){

        foreach ($submenu[$menus] as $index => $value){

        $current = $index;  

        if(array_search( $att['id'], $value)){ 
        $key = $current;
        }

            while (array_key_exists($att['pos'], $submenu[$menus]))
                $att['pos'] = $att['pos'] + 1;

            if ( false !== $key ){

                if (array_key_exists($key, $submenu[$menus])){
                    $new[$menus][$key] = $submenu[$menus][$key];
                    unset($submenu[$menus][$key]);
                    $submenu[$menus][$att['pos']] = $new[$menus][$key];

                } 
            }
        }
    }
}

ksort($submenu[$menus]);
return $submenu;

}

Dans l'exemple ci-dessus, vous pouvez cibler plusieurs sous-menus et plusieurs éléments par sous-menu en définissant les paramètres en conséquence dans la variable $target_menu qui contient un tableau multidimensionnel de valeurs.

$target_menu = array(
//menu to target (e.g. appearance menu)
'themes.php' => array(
    //id of menu item you want to target followed by the position you want in sub menu
    array('id' => 'optionsframework', 'pos' => 2),
    //id of menu item you want to target followed by the position you want in sub menu
    array('id' => 'bp-tpack-options', 'pos' => 3),
    //id of menu item you want to target followed by the position you want in sub menu
    array('id' => 'multiple_sidebars', 'pos' => 4),
    )
 //etc....
);

Cette révision empêchera les éléments de sous-menu de s’écraser s’ils ont la même clé (position), car ils seront parcourus jusqu’à trouver une clé disponible (position) qui n’existe pas.

3
userabuser

Le menu d'administration (et ses problèmes)

Comme le menu d'administration manque sérieusement de points d'ancrage et d'une API publique (qui permet de déplacer les éléments), vous devez utiliser certaines solutions de contournement. La réponse suivante vous montre ce qui vous attend dans l’avenir et comment vous pouvez le contourner tant que vous avez l’état actuel du cœur.

Je dois d’abord noter que scribu fonctionne sur un correctif de menu d’administrateur qui devrait en faciliter la gestion. La structure actuelle est assez désordonnée et j'ai écrit un article à ce sujet qui sera bientôt dépassée. Attendez-vous que WP 3.6 change complètement les choses.

Il y a aussi le fait que vous ne devriez plus utiliser les pages Options pour les thèmes. Il y a - de nos jours - le "Thème Customizer" pour ça.

Le plugin

J'ai écrit un plugin qui teste cela avec la page "Options du thème" par défaut de la page d'options TwentyEleven/Ten. Comme vous pouvez le constater, aucune API ne permet de positionner. Nous devons donc intercepter le global.

En bref: il suffit de suivre les commentaires et de jeter un coup d'œil aux avis de l'administrateur, que j'ai ajoutés pour vous donner un résultat de débogage.

<?php
/** Plugin Name: (#70916) Move Submenu item */

add_action( 'plugins_loaded', array( 'wpse70916_admin_submenu_items', 'init' ) );

class wpse70916_admin_submenu_items
{
    protected static $instance;

    public $msg;

    public static function init()
    {
        is_null( self :: $instance ) AND self :: $instance = new self;
        return self :: $instance;
    }

    public function __construct()
    {
        add_action( 'admin_notices', array( $this, 'add_msg' ) );

        add_filter( 'parent_file', array( $this, 'move_submenu_items' ) );
    }

    public function move_submenu_items( $parent_file )
    {
        global $submenu;
        $parent = $submenu['themes.php'];

        $search_for = 'theme_options';

        // Find current position
        $found = false;
        foreach ( $parent as $pos => $item )
        {
            $found = array_search( $search_for, $item );
            if ( false !== $found )
            {
                $found = $pos;
                break;
            }
        }
        // DEBUG: Tell if we didn't find it.
        if ( empty( $found ) )
            return $this->msg = 'That search did not work out...';

        // Now we need to determine the first and second item position
        $temp = array_keys( $parent );
        $first_item  = array_shift( $temp );
        $second_item = array_shift( $temp );

        // DEBUG: Check if it the item fits between the first two items:
        $distance = ( $second_item - $first_item );
        if ( 1 >= $distance )
            return $this->msg = 'We do not have enough space for your item';

        // Temporary container for our item data
        $target_data = $parent[ $found ];

        // Now we can savely remove the current options page
        if ( false === remove_submenu_page( 'themes.php', $search_for ) )
            return $this->msg = 'Failed to remove the item';

        // Shuffle items (insert options page)
        $submenu['themes.php'][ $first_item + 1 ] = $target_data;
        // Need to resort the items by their index/key
        ksort( $submenu['themes.php'] );
    }

    // DEBUG Messages
    public function add_msg()
    {
        return print sprintf(
             '<div class="update-nag">%s</div>'
            ,$this->msg
        );
    }
} // END Class wpse70916_admin_submenu_items

Bonne chance et amusez-vous bien.

2
kaiser

Filtres personnalisés

Il existe une autre possibilité pour y parvenir. Ne me demandez pas pourquoi je n'y ai pas pensé plus tôt. Quoi qu'il en soit, il existe un filtre dédié à un ordre de menu personnalisé. Réglez-le simplement sur true pour autoriser une commande personnalisée. Ensuite, vous avez un deuxième crochet pour commander les éléments du menu principal. Ici, nous interceptons simplement le global $submenu et basculons autour de nos éléments de sous-menu.

enter image description here

Cet exemple déplace l'élément Menus ci-dessus l'élément Widgets pour illustrer ses fonctionnalités. Vous pouvez l'ajuster à votre guise.

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: (#70916) Custom Menu Order
 * Description: Changes the menu order of a submenu item.
 */

// Allow a custom order
add_filter( 'custom_menu_order', '__return_true' );
add_filter( 'menu_order', 'wpse70916_custom_submenu_order' );
function wpse70916_custom_submenu_order( $menu )
{
    // Get the original position/index
    $old_index = 10;
    // Define a new position/index
    $new_index = 6;

    // We directly interact with the global
    $submenu = &$GLOBALS['submenu'];
    // Assign our item at the new position/index
    $submenu['themes.php'][ $new_index ] = $submenu['themes.php'][ $old_index ];
    // Get rid of the old item
    unset( $submenu['themes.php'][ $old_index ] );
    // Restore the order
    ksort( $submenu['themes.php'] );

    return $menu;
}
2
kaiser