Reihenfolge der Wordpress-API-Menüs / Untermenüs

11

Ich entwickle ein untergeordnetes Thema mit Wordpress 3.4.2 und der Entwicklungsversion des Options Framework von David Price . Dies ist mein erstes Thema, und ich bin relativ neu in diesem Bereich. Daher habe ich mir den Wordpress-Codex angesehen und die Registrierung von Elementen in der API überprüft.

Ohne externe Dateien außerhalb meines Themas zu manipulieren, habe ich mich gefragt, ob es eine Möglichkeit gibt, neu zu ordnen, wo sich die Seite " Themenoptionen" in der Hierarchie des Menüs " Darstellung" befindet. Wenn also mein Thema aktiviert ist, entspricht die Position nicht der Position das erste Bild aber wie das zweite.

altNeu

Ich weiß, dass Sie entweder ein Menü (wie die Registerkarte Darstellung , Plugins , Benutzer usw.) oder ein Untermenü ( Themen , Widgets , Menüs usw.) erstellen können , aber wie würde ich vorgehen, um beispielsweise ein Untermenü festzulegen? von oben?

Soweit ich weiß, wird irgendwo eine Bestellung aufgerufen und danach werden weitere zusätzliche Seiten in der functions.phpDatei platziert?

In meiner Datei 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';
}

Vielen Dank.

user1752759
quelle
Haben Sie die aktualisierte Funktion ausprobiert?
Adam
Vielen Dank, dass Sie sich bei mir gemeldet haben @userabuser. Ich habe Ihr aktualisiertes Skript kopiert und es scheint die Elemente in der Liste nach oben und unten zu verschieben, ohne andere zu überschreiben. Mit dem neuen Update erhalte ich jedoch immer noch einige Fehler im Widgets- Menü. Warning: Invalid argument supplied for foreach() in /wp-content/themes/mythemename/functions.php on line 1444 Zeile 1444: foreach ($submenu[$menus] as $index => $value){ und Warning: ksort() expects parameter 1 to be array, null given in /wp-content/themes/mythemename/functions.php on line 1468 Zeile 1468: ksort($submenu[$menus]);
user1752759
Wenn Sie sich das bitte ansehen könnten, wäre das großartig.
user1752759

Antworten:

3

Hier ist ein Beispiel;

Um zunächst die Reihenfolge der Untermenüelemente anhand des Array-Schlüssels zu ermitteln, können Sie eine Anweisung für die var_dumpglobale Variable $ submenu ausführen, die Folgendes ausgibt:

(Ich verwende das Menü Beiträge und das Untermenü als Beispiel)

  //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"
    }
  }

Wir können sehen, dass mein Untermenüelement mit einem Schlüssel von 17 nach den Standardelementen zum Array hinzugefügt wird.

Wenn ich zum Beispiel meinen Untermenüpunkt hinzufügen möchte, muss ich dies direkt nach dem Untermenüpunkt Alle Beiträge tun, indem ich meinen Array-Schlüssel auf 6, 7, 8 oder 9 setze (alles nach 5 bzw. vor 10).

Das ist wie man es macht...

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']);

}

Ergebnis,

  ["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"
    }
  }

... probieren Sie es aus und lassen Sie uns wissen, wie es Ihnen geht!

Update 1:

Fügen Sie dies Ihrer Datei functions.php hinzu.

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]);

}

Mein Update enthält eine etwas einfachere Möglichkeit, die Einstellung Ihrer Menüposition vorzunehmen. Sie müssen nur den Namen Ihrer Untermenüseite und die gewünschte Position innerhalb des Menüs angeben. Wenn Sie jedoch eine Untermenüseite auswählen $location, die der eines vorhandenen Schlüssels entspricht, wird dieser Schlüssel mit Ihrem überschrieben, sodass der Menüpunkt mit Ihrem Menüpunkt an seiner Stelle verschwindet. Erhöhen oder verringern Sie die Anzahl, um Ihr Menü korrekt zu ordnen, wenn dies der Fall ist. Wenn jemand ein Plugin installiert, das denselben Menübereich betrifft und für das dasselbe $locationwie Ihr Untermenüelement verwendet wird, tritt dasselbe Problem auf. Um dies zu umgehen, bietet Kaisers Beispiel einige grundlegende Überprüfungen dafür.

Update 2:

Ich habe einen zusätzlichen Codeblock hinzugefügt, der alle vorhandenen Schlüssel im Array mit dem gewünschten Code vergleicht. $locationWenn eine Übereinstimmung gefunden wird, erhöhen wir unseren $locationWert um, 1um zu vermeiden, dass sich Menüelemente gegenseitig überschreiben. Dies ist der Code, der dafür verantwortlich ist.

   //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;

Update 3: (Skript überarbeitet, um das Sortieren mehrerer Untermenüelemente zu ermöglichen)

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;

}

Im obigen Beispiel können Sie mehrere Untermenüs und mehrere Elemente pro Untermenü als Ziel festlegen, indem Sie die Parameter innerhalb der $target_menuVariablen, die ein mehrdimensionales Array von Werten enthält, entsprechend einstellen .

$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....
);

Diese Überarbeitung verhindert, dass sich Untermenüelemente gegenseitig überschreiben, wenn sie dieselbe Taste (Position) haben, da sie durchlaufen, bis eine verfügbare Taste (Position) gefunden wird, die nicht vorhanden ist.

Adam
quelle
Vielen Dank für die schnelle Antwort des Benutzers, aber ich bin ziemlich neu in all dem. Bitte nehmen Sie einfach Kontakt mit mir auf. Ich bin mir nicht ganz sicher, wie ich Ihr Skript / Ihren Code oben implementieren soll und in welche Datei es eingefügt werden muss, da es so präzise geschrieben wurde - bitte erläutern Sie es. Wenn dieses Beispiel jedoch funktioniert und die erforderliche Anzahl ausgegeben wird ... Wenn der Benutzer später ein Plugin installieren sollte, das ein zusätzliches Menü der obersten Ebene mit einigen Unterebenen (z. B. eine E-Commerce-Lösung) erstellt, wird dies der Fall sein den Array-Schlüssel betätigen und bremsen, was er tun soll?
user1752759
1
@Rob Eine geringfügige Anpassung vorgenommen, um Situationen zu vermeiden, in denen sich Menüelemente gegenseitig überschreiben.
Adam
@ user1752759 Was hat das mit dem oben genannten zu tun? Was ist der vollständige Pfad zur Datei functions.php, die Sie in Ihrem obigen Kommentar angegeben haben? Was ist der Code in dieser Datei? Beim letzten Gespräch hat das bei Ihnen funktioniert. Es funktioniert auch bei mir. Ich vermute also, dass etwas anderes hier ein Fehler in Ihrem Code sein könnte, wenn ich mich richtig erinnere, dass Sie das letzte Mal zwei Codeausschnitte dupliziert haben und nicht die richtigen Klammern um Ihre Funktion hatten.
Adam
Vielen Dank, dass Sie sich bei mir gemeldet haben @userabuser. Ich habe Ihr aktualisiertes Skript kopiert und es scheint die Elemente in der Liste nach oben und unten zu verschieben, ohne andere zu überschreiben. Mit dem neuen Update erhalte ich jedoch immer noch einige Fehler im Widgets-Menü. Warning: Invalid argument supplied for foreach() in /wp-content/themes/mythemename/functions.php on line 1444 Linie 1444: foreach ($submenu[$menus] as $index => $value){ und Warning: ksort() expects parameter 1 to be array, null given in /wp-content/themes/mythemename/functions.php on line 1468 Linie 1468: ksort($submenu[$menus]);
Benutzer 1752759
Wenn Sie sich das bitte ansehen könnten, wäre das großartig.
user1752759
2

Das Admin-Menü (und seine Probleme)

Da im Admin-Menü keine Hooks und keine öffentliche API vorhanden sind (mit der die Elemente verschoben werden können), müssen Sie einige Problemumgehungen verwenden. Die folgende Antwort zeigt Ihnen, was Sie in Zukunft erwartet und wie Sie umgehen können, solange wir den aktuellen Kernstatus haben.

Zuerst muss ich beachten, dass scribu an einem Admin-Menü-Patch arbeitet , der die Handhabung erheblich vereinfachen soll. Die aktuelle Struktur ist ziemlich durcheinander und ich habe einen Artikel darüber geschrieben , der bald veraltet sein wird. Erwarten Sie, dass WP 3.6 die Dinge vollständig ändert.

Dann gibt es auch den Punkt, dass Sie Optionsseiten nicht mehr für Themen verwenden sollten. Dafür gibt es heutzutage den »Theme Customizer« .

Das Plugin

Ich habe ein Plugin geschrieben, das dies mit der Standardseite "Themenoptionen" für die Seite "TwentyEleven / Ten-Optionen" testet. Wie Sie sehen können, gibt es keine echte API, die eine Position zulässt. Also müssen wir das Globale abfangen.

Kurz gesagt: Folgen Sie einfach den Kommentaren und sehen Sie sich die Admin-Hinweise an, die ich hinzugefügt habe, um Ihnen eine Debug-Ausgabe zu geben.

<?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

Viel Glück und hab Spaß.

Kaiser
quelle
2

Benutzerdefinierte Filter

Es gibt eine andere Möglichkeit, dies zu erreichen. Fragen Sie mich nicht, warum ich vorher nicht darüber nachgedacht habe. Auf jeden Fall gibt es einen Filter für eine benutzerdefinierte Menüreihenfolge. Stellen Sie es einfach auf ein true, um eine benutzerdefinierte Bestellung zuzulassen. Dann haben Sie einen zweiten Haken, um die Hauptmenüpunkte zu bestellen. Dort fangen wir einfach die ab global $submenuund wechseln unsere Untermenüpunkte.

Geben Sie hier die Bildbeschreibung ein

In diesem Beispiel wird das Menüelement über das Widgets-Element verschoben , um seine Funktionalität zu demonstrieren. Sie können es nach Ihren Wünschen anpassen.

<?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;
}
Kaiser
quelle
Ich bin nicht sehr sicher, wenn es um die Verwendung von PHP @kaiser geht, aber würden Sie möglicherweise eine Möglichkeit kennen, das obige Skript so zu implementieren, dass mehrere Elemente in demselben enthalten sind function wpse70916_custom_submenu_order( $menu ), um nicht nur das Menü , sondern auch das Thema neu zu ordnen Optionen , Widgets , Editor usw. machen es ziemlich flexibel und auch damit sich die Elemente nicht gegenseitig überschreiben? Vielen Dank.
user1752759
@ user1752759 Das Plugin hat diese Flexibilität bereits. Konfliktsicherheit (Überschreiben vermeiden) ist ein weiteres Problem. Dies ist in einem 100% -Szenario nicht möglich, da Sie Ihre Aktion nicht zuletzt zuweisen können. Es gibt immer etwas, das später ausgeführt werden kann. Wie auch immer: Bitte öffnen Sie eine neue Frage und verlinken Sie auf diese.
Kaiser
danke und werde kaiser machen. Wenn es nicht zu viel verlangt, können Sie bitte das obige Skript aktualisieren, um zu zeigen, wie mehrere Elemente ausgeführt werden (z. B. das Menü und die Widgets ), die ich als Leitfaden verwenden sollte, um dasselbe mit anderen Elementen zu tun? Ich bin ziemlich neu in PHP und glaube nicht, dass ich es richtig mache, vielleicht wegen der Zahlen. prost
user1752759
Bitte stellen Sie einfach eine neue Frage und verlinken Sie auf diese. Vielen Dank.
Kaiser