Menú de Wordpress API / Submenú Orden

11

Estoy desarrollando un tema infantil usando Wordpress 3.4.2 y la versión de desarrollo del Marco de opciones de David Price . Este es mi primer tema y soy relativamente nuevo en esto, así que eché un vistazo al Wordpress Codex y comprobé el registro de elementos en la API.

Sin alterar ningún archivo externo fuera de mi tema, me preguntaba si había alguna forma de reorganizar la ubicación de la página Opciones de tema dentro de la jerarquía de Apariencia menu - así que cuando mi tema está activado, la posición no es como la primera imagen sino como la segunda.

Sé que puede crear un menú (como la pestaña Apariencia , Complementos , Usuarios , etc.) o un submenú ( Temas , Widgets , Menús , etc.), pero, ¿cómo hago para configurar un submenú por ejemplo, segundo desde la parte superior?

De lo que he recopilado, ¿en algún lugar hay una orden que se llama y otras páginas adicionales dentro del archivo functions.php se colocan después de esas?

En mi archivo 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';
}

Gracias.

    
pregunta user1752759 30.10.2012 - 07:18

3 respuestas

3

Aquí hay un ejemplo;

Primero, para averiguar el orden de los elementos del submenú según su clave de matriz, puede hacer un var_dump en la variable global $ submenu que dará como resultado lo siguiente:

(Estoy usando el menú de Entradas y el submenú como ejemplo)

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

Podemos ver que mi elemento de submenú se agrega a la matriz con una clave de 17 después de los elementos predeterminados.

Si, por ejemplo, quiero agregar el elemento de mi submenú, inmediatamente después del elemento del submenú Todas las publicaciones , debo hacerlo configurando la clave de mi matriz en 6, 7, 8 o 9 ( cualquier cosa después de 5 y antes de 10 respectivamente.

Así es como lo haces ...

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

}

Resultado,

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

... pruébalo y dinos cómo te va.

Actualización 1:

Agregue esto a su archivo 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]);

}

Mi actualización incluye una forma un poco más fácil de manejar la configuración de la posición del menú, solo tiene que estipular el nombre de la página del submenú y la posición que desea dentro del menú. Sin embargo, si selecciona una página de submenú $location igual a la de una tecla existente, anulará esa tecla con la suya, por lo que el elemento de menú desaparecerá con su elemento de menú en su lugar. Incremente o disminuya el número para ordenar correctamente su menú si ese es el caso. De manera similar, si alguien instala un complemento que afecte esa misma área de menú, y para el cual tenga el mismo $location que su elemento de submenú, se producirá el mismo problema. Para evitarlo, el ejemplo de Kaiser proporciona algunos ejemplos. Comprobación básica para eso.

Actualización 2:

Agregué un bloque de código adicional que verifica todas las claves existentes en el arreglo contra nuestro $location deseado y si se encuentra una coincidencia, incrementaremos nuestro valor $location en 1 para evitar elementos del menú anulando unos a otros. Este es el código responsable de eso,

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

Actualización 3: (secuencia de comandos revisada para permitir la clasificación de varios elementos del submenú)

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;

}

En el ejemplo anterior, puede apuntar a varios submenús y múltiples elementos por submenú configurando los parámetros correspondientes dentro de la variable $target_menu que contiene una matriz de valores multidimensional.

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

Esta revisión evitará que los elementos del submenú se sobrescriban entre sí si tienen la misma clave (posición), ya que se desplazará hasta que encuentre una clave (posición) disponible que no existe.

    
respondido por el userabuser 30.10.2012 - 13:07
2

El menú de administración (y sus problemas)

Como el menú de administración carece seriamente de enlaces y de una API pública (que permite mover los elementos), tiene que usar algunas soluciones. La siguiente respuesta le muestra lo que le espera en el futuro y cómo puede solucionarlo mientras tengamos el estado actual del núcleo.

Primero debo señalar que scribu está trabajando en un parche del menú de administración que debería hacer mucho más manejo más fácil. La estructura actual está bastante desordenada y He escrito un artículo al respecto que pronto estará desactualizado . Espere que WP 3.6 cambie las cosas por completo.

Luego también está el punto, que ya no debes usar las páginas de Opciones para los temas. Hay - hoy en día - el »Personalizador de tema« para eso.

El complemento

Escribí un complemento que prueba esto con la página predeterminada de "Opciones de tema" para la página de opciones de TwentyEleven / Ten. Como puede ver, no hay una API real que permita ninguna posición. Así que tenemos que interceptar lo global.

En resumen: solo siga los comentarios y eche un vistazo a los avisos de administración, que agregué para darle un poco de salida de depuración.

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

Buena suerte y diviértete.

    
respondido por el kaiser 30.10.2012 - 14:16
2

Filtros personalizados

Hay otra posibilidad para lograrlo. No me preguntes por qué no lo he pensado antes. De todos modos, hay un filtro dedicado a un orden de menú personalizado. Simplemente configúrelo en true para permitir un pedido personalizado. Luego tienes un segundo gancho para ordenar los elementos del menú principal. Allí simplemente interceptamos el global $submenu y cambiamos alrededor de los elementos de nuestro submenú.

  

Este ejemplo mueve el elemento de menús arriba el elemento de widgets para demostrar su funcionalidad. Puedes ajustarlo a lo que quieras.

<?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;
}
    
respondido por el kaiser 02.02.2013 - 15:51

Lea otras preguntas en las etiquetas