Créer des raccourcis vers des pages « importantes » dans le menu d’administration de WordPress

Ce besoin est venu d’une ancienne chef de projet qui en avait marre de chercher certaines pages « importantes » dans la liste des pages 😄 Ça peut se comprendre. Entre nous, avec l’extension Simple Page Ordering, elle aurait pu remonter les pages concernées tout en haut mais pas question (pour tout le monde) de voir la liste des pages dans le plan du site (via wp_list_pages) être impactée par ce choix/besoin côté back-office.

Alors d’un commun accord, nous avons décidé d’ajouter des raccourcis dans le menu « Pages » du back-office de WordPress. Juste entre l’entrée « Toutes les pages » et « Ajouter » pour que ça soit plus « pratique » et « logique » 😅 Je savais que ça risquerait d’être chiant mais j’étais d’accord avec elle 👍 De toutes façons, quand je réfléchis avec les CdP, j’évite de penser à la technique car ça bloque/tend souvent les discussions.

Donc voilà comment j’ai répondu à notre besoin :

La première chose à faire est de pouvoir récupérer et modifier une liste des pages qui vont faire l’objet d’un raccourci en tant que sous-menu. 
Par défaut, nous avons décidé d’ajouter la page d’accueil ainsi que la page « Politique de confidentialité ».

/**
 * Retrieves the list of pages which will have a shortcut into the "Page"
 * admin menu.
 *
 * @param void
 * @return array An associate array (`post_id => label`) of pages.
 */
function thistle_get_admin_submenu_page_shortcuts() {
    $shortcuts =  apply_filters( 'thistle_admin_submenu_page_shortcuts', array(
		get_option( 'page_on_front' )              => __( 'Front Page' ),
		get_option( 'wp_page_for_privacy_policy' ) => __( 'Privacy Policy' )
    ) );

    // Be sure that the page ID asked for is not zero ;)
    $shortcuts = array_filter( $shortcuts, function( $sk ) { return !! intval( $sk ); }, ARRAY_FILTER_USE_KEY );

    return is_array( $shortcuts ) ? $shortcuts : array();
}

La façon la plus « propre » et responsable d’ajouter ces pages serait d’utiliser la fonction add_pages_page. Mais malheureusement pour nous, cette fonction ne nous permet pas de choisir la position de nos éléments… La faute à add_submenu_page qui ne gère pas de priorité/position contrairement à sa grande soeur add_menu_page 😩 On garde les doigts croisés (ça ne fait qu’un an et demi) pour que le ticket 39776 fasse parti de WordPress 5.0 mais en attendant il va falloir bricoler… 
J’ai donc décidé de me mettre sur l’action admin_menu et d’attaquer directement la variable globale $submenu sur l’index edit.php?post_type=page 😬 Sauf que même si ça parait plutot simple, il y a un hic 😉 
Voici comment est organisé le tableau pour construire le sous-menu :

Array
(
    [5] => Array
        (
            [0] => All pages
            [1] => edit_pages
            [2] => edit.php?post_type=page
        )

    [10] => Array
        (
            [0] => Add new
            [1] => edit_pages
            [2] => post-new.php?post_type=page
        )

)

Même si cela ne me choque pas vraiment (cf. : Menu Structure), il va falloir tenir compte de ce détail pour que notre cinquième raccourci n’écrase/efface pas l’entrée « Ajouter ». 
Donc à la place d’insérer nos raccourcis sur un pas de 1, nous les ajouterons sur un pas de 0.1 😜 Sachez le, la fonction add_menu_page accepte déjà ce genre de valeurs (cf. : add_menu_page supports decimal positions) et c’est super pratique.

/**
 * Adds page shortcuts into the "Page" admin menu between "All Pages" and "Add new".
 *
 * @param void
 * @return void
 */
function thistle_add_admin_submenu_page_shortcuts() {
    global $submenu, $wp_post_types;

    $page_shortcuts = thistle_get_admin_submenu_page_shortcuts();
    $page_shortcuts_count = count( $page_shortcuts );

    // Exit early if no shortcut is needed.
    if ( empty( $page_shortcuts ) ) {
        return;
    }

    // Start to add shortcuts just after "all Pages" submenu.
    $index = (int) array_search( $wp_post_types['page']->labels->all_items, array_combine( array_keys( $submenu['edit.php?post_type=page'] ), array_column( $submenu['edit.php?post_type=page'], 0 ) ) );

    foreach ( $page_shortcuts as $id => $label ) {
        $index += .1;

        $submenu['edit.php?post_type=page'][(string) $index] = array(
            $label,
            'edit_pages',
            'post.php?post=' . $id . '&action=edit'
        );

      //add_pages_page( $label, $label, 'edit_pages', 'post.php?post=' . $id . '&action=edit', (string) $index );
    }

    ksort( $submenu['edit.php?post_type=page'] );
}
add_action( 'admin_menu', 'thistle_add_admin_submenu_page_shortcuts', 5 );

Il ne reste plus qu’à sélectionner/illuminer le bon sous-menu car par défaut lors de l’édition d’un contenu, WordPress sélectionne/illumine l’entrée « générale » (dans notre cas « Toutes les pages »). 
Pour faire cela, il y a plusieurs écoles : via admin_head, via parent_file ou celle ci-dessous 😙

/**
 * Highlights the shortcut submenu into the "Page" admin menu instead of "All pages".
 *
 * @param string $submenu_file The submenu file.
 * @param string $parent_file  The submenu item's parent file.
 * @return string
 */
function thistle_highlight_admin_submenu_page_shortcut( $submenu_file, $parent_file ) {
    global $post_type;

    $page_shortcuts = thistle_get_admin_submenu_page_shortcuts();

    if ( $post_type == 'page' && isset( $_GET['post'], $_GET['action'] ) && array_key_exists( $_GET['post'], $page_shortcuts ) && $_GET['action'] == 'edit' ) {
        return 'post.php?post=' . $_GET['post'] . '&action=edit';
    }

    return $submenu_file;
}
add_filter( 'submenu_file', 'thistle_highlight_admin_submenu_page_shortcut', 10, 2 );

Cela n’était pas notre besoin lors du développement mais l’ensemble de ce code pourrait tout à fait être fonctionnel pour l’ensemble des types de contenu avec quelques ajustements.

Voila, c’est fini 😁