Si vous gérez un site WordPress, vous pouvez désactiver l’éditeur de blocs pour un ou deux types de contenu (post types) pendant que tous les autres types le gardent. Les types de contenu sont les sortes de contenu que WordPress enregistre, comme les articles, les pages ou les produits. La solution la plus propre est l’interrupteur par type de WordPress : une extension obligatoire d’une dizaine de lignes (un fichier que WordPress charge toujours) qui renvoie false au filtre use_block_editor_for_post_type pour les types choisis. Vous confirmez ensuite le résultat avec WP-CLI et directement dans les écrans d’édition.
Les équipes le demandent surtout quand un type personnalisé est bâti autour de métaboxes, ces panneaux de champs supplémentaires de l’écran d’édition. L’extension Classic Editor est la réponse habituelle, mais son réglage principal vaut pour tout le site, et son option par utilisateur disperse le choix entre tous les auteurs.
Ce que vous allez accomplir
- Trouver le nom interne exact de chaque type de contenu à modifier.
- Voir ce que WordPress décide aujourd’hui pour chaque type, et pourquoi.
- Envoyer les types choisis vers l’écran d’édition classique avec une extension obligatoire que personne ne peut désactiver depuis l’administration.
- Au besoin, ajouter une règle par contenu, par exemple pour les pages bâties sur un ancien modèle.
- Prouver le changement depuis le terminal et dans le navigateur, et confirmer que l’API REST sert toujours ces types.
Prérequis
- WordPress 6.1 ou plus récent pour les vérifications WP-CLI telles qu’écrites. Cette version a sorti
use_block_editor_for_post_type()etuse_block_editor_for_post()dewp-admin, ce qui permet àwp evalde les appeler directement. Les filtres eux-mêmes existent depuis la 5.0. Sur un site plus ancien, commencez chaquewp evalparrequire_once ABSPATH . "wp-admin/includes/post.php";(avec des guillemets doubles, puisque toute la commande est entre apostrophes). - WP-CLI, qui pilote WordPress depuis le terminal, utilisé par SSH avec l’utilisateur du site. Lancez les commandes depuis la racine de WordPress, le dossier qui contient
wp-config.php. - Un accès en écriture à
wp-content/mu-plugins/. Une extension obligatoire (must-use plugin) est un fichier PHP placé dans ce dossier, que WordPress charge toujours et que personne ne peut désactiver depuis l’écran des extensions. - Un compte administrateur qui peut modifier les types concernés, pour la vérification dans le navigateur.
- Une copie de préproduction si vous en avez une. Le changement s’annule facilement (on supprime un fichier), mais les rédacteurs remarquent tout de suite un écran différent.
Comment ça fonctionne
Quand quelqu’un ouvre post.php (modifier un contenu) ou post-new.php (en ajouter un), WordPress appelle use_block_editor_for_post(). Cette fonction demande d’abord à use_block_editor_for_post_type() la réponse pour le type, qui passe par quatre vérifications dans l’ordre :
- Le type de contenu doit exister.
- Il doit prendre en charge
editor, le champ de contenu principal déclaré dans la listesupportsderegister_post_type(). - Il doit avoir
show_in_restàtrue, parce que l’éditeur de blocs lit et enregistre par l’API REST. - Le filtre
use_block_editor_for_post_types’exécute, en partant detrue.
Si l’une des trois premières échoue, la réponse est false et le filtre ne s’exécute jamais. De retour dans use_block_editor_for_post(), la réponse du type passe par un dernier filtre, use_block_editor_for_post, qui reçoit le contenu lui-même. Ce que renvoie ce dernier filtre décide de l’écran : true charge l’éditeur de blocs, false charge le formulaire classique avec sa zone de contenu et ses métaboxes.
La figure montre pourquoi le filtre par type est le bon endroit pour votre règle. Il ne s’exécute que pour les types qui pourraient utiliser l’éditeur de blocs, il ne voit que le nom du type, et il ne touche à rien d’autre.
Deux autres acteurs peuvent changer le résultat :
- L’extension Classic Editor. Prenons le cas où l’éditeur par défaut pour tous les utilisateurs (Default editor for all users) est Classic, sans changement permis aux utilisateurs. Elle ajoute alors
__return_falseàuse_block_editor_for_post_typeavec la priorité 100. Tous les types reçoivent alors l’écran classique, peu importe ce que dit votre extension à la priorité 10. Quand le changement par les utilisateurs est permis, elle filtre plutôtuse_block_editor_for_postà la priorité 100 et suit le choix de chaque auteur. Même dans ce cas, elle n’offre jamais l’éditeur de blocs pour un type dont la réponse par type estfalse; votre règle tient donc. - Les thèmes et les autres extensions qui se branchent sur les mêmes filtres. L’étape 7 montre comment lister chaque fonction de rappel.
Pourquoi show_in_rest => false n’est pas le bon levier
Mettre show_in_rest à false désactive bien l’éditeur de blocs pour un type, puisque la vérification 3 échoue. Mais cela retire aussi le type de l’API REST. Ses routes /wp-json/wp/v2/... disparaissent et renvoient une erreur 404 avec le code rest_no_route. La recherche de liens de l’éditeur ne trouve plus ces contenus, puisque le point de terminaison de recherche ne couvre que les types publics présents dans l’API REST. Un site découplé (headless), un script d’importation ou un outil de rapports qui lit le type par REST cessent aussi de fonctionner. Le filtre, lui, change l’écran d’édition et rien d’autre.
Étapes
- Trouvez le nom interne du type de contenu. Les menus affichent des libellés comme « Books », mais le filtre a besoin du nom donné à l’enregistrement du type. Listez les types qui ont un écran d’administration :
wp post-type list --show_ui=1 --fields=name,label,public
Exemple de sortie :
+---------------+-------------------+--------+
| name | label | public |
+---------------+-------------------+--------+
| post | Posts | 1 |
| page | Pages | 1 |
| attachment | Media | 1 |
| wp_block | Patterns | |
| wp_navigation | Navigation Menus | |
| book | Books | 1 |
| listing | Property Listings | 1 |
+---------------+-------------------+--------+
Utilisez la colonne name. Ici, le type affiché « Property Listings » s’appelle listing. Autre façon de le lire : ouvrez la liste du type dans l’administration et regardez la barre d’adresse, où edit.php?post_type=listing donne le nom. Si votre type n’apparaît pas, l’extension ou le thème qui l’enregistre est inactif.
- Vérifiez ce que WordPress décide aujourd’hui. Cette commande affiche chaque vérification de l’échelle pour les types qui vous intéressent. Mettez vos propres noms dans le tableau :
wp eval 'foreach ( array( "post", "page", "book", "listing" ) as $t ) { if ( ! post_type_exists( $t ) ) { echo "$t: not registered\n"; continue; } printf( "%-8s editor=%-3s rest=%-3s block=%s\n", $t, post_type_supports( $t, "editor" ) ? "yes" : "no", get_post_type_object( $t )->show_in_rest ? "yes" : "no", use_block_editor_for_post_type( $t ) ? "yes" : "no" ); }'
Exemple de sortie :
post editor=yes rest=yes block=yes
page editor=yes rest=yes block=yes
book editor=yes rest=yes block=yes
listing editor=yes rest=yes block=yes
block=yes signifie que le type s’ouvre aujourd’hui dans l’éditeur de blocs. Un type qui affiche editor=no ou rest=no reçoit déjà l’écran classique et n’a pas besoin du filtre; voyez le Dépannage si cela vous étonne. Si toutes les lignes affichent block=no, quelque chose filtre déjà tous les types, le plus souvent l’extension Classic Editor; l’étape 7 le trouve.
- Créez l’extension obligatoire. Créez le dossier s’il n’existe pas, puis enregistrez ce fichier sous
wp-content/mu-plugins/classic-editor-for-types.php, avec vos propres noms de types dans la liste :
<?php
/**
* Plugin Name: Classic edit screen for chosen post types
* Description: Loads the classic edit screen for the post types listed below. Every other type keeps the block editor.
*/
// Post type names (not labels) that should open in the classic edit screen.
function sh_classic_post_types() {
return array( 'book', 'listing' );
}
function sh_classic_for_post_types( $use_block_editor, $post_type ) {
if ( in_array( $post_type, sh_classic_post_types(), true ) ) {
return false;
}
return $use_block_editor;
}
add_filter( 'use_block_editor_for_post_type', 'sh_classic_for_post_types', 10, 2 );
La fonction renvoie la valeur reçue pour tous les autres types; elle n’impose donc l’éditeur de blocs nulle part. Des fonctions nommées, plutôt qu’anonymes, rendent la fonction de rappel facile à repérer à l’étape 7. Le fichier doit être directement dans mu-plugins/, car WordPress ne charge pas les fichiers des sous-dossiers à cet endroit. Le functions.php d’un thème fonctionnerait aussi, mais un changement de thème l’annulerait sans avertissement.
Confirmez que WordPress voit le fichier :
wp plugin list --status=must-use --fields=name,status
Exemple de sortie :
+--------------------------+----------+
| name | status |
+--------------------------+----------+
| classic-editor-for-types | must-use |
+--------------------------+----------+
Si la ligne manque, vérifiez le dossier et le nom du fichier. Une erreur de syntaxe PHP apparaît sous forme de ligne PHP Parse error qui nomme le fichier, à la prochaine commande wp.
- Au besoin, ajoutez une règle par contenu. Certaines équipes veulent l’édition classique pour une partie d’un seul type, par exemple les pages bâties sur un ancien modèle de page d’atterrissage. Ajoutez ceci au même fichier, avec le chemin de votre modèle :
// Pages built on the old landing template also open in the classic screen.
function sh_classic_for_legacy_template( $use_block_editor, $post ) {
if ( 'page' === $post->post_type && 'templates/legacy-landing.php' === get_page_template_slug( $post ) ) {
return false;
}
return $use_block_editor;
}
add_filter( 'use_block_editor_for_post', 'sh_classic_for_legacy_template', 10, 2 );
La règle a besoin de la valeur que WordPress enregistre pour le modèle. Listez les modèles de page du thème actif :
wp eval 'print_r( wp_get_theme()->get_page_templates() );'
Exemple de sortie :
Array
(
[templates/legacy-landing.php] => Legacy landing
[templates/full-width.php] => Full width
)
La clé à gauche est la valeur à utiliser. Avec un thème de blocs, la valeur enregistrée est le slug du modèle, comme legacy-landing, sans dossier ni .php. Listez ensuite les pages qui l’utilisent :
wp post list --post_type=page --meta_key=_wp_page_template --meta_value=templates/legacy-landing.php --fields=ID,post_title
Exemple de sortie :
+-----+-------------------+
| ID | post_title |
+-----+-------------------+
| 812 | Spring open house |
| 640 | Downtown condos |
+-----+-------------------+
Aucune ligne veut dire qu’aucune page n’utilise encore cette valeur. Réservez les règles par contenu aux cas comme celui-ci. Une nouvelle page commence comme un brouillon vide, sans modèle; le bouton Ajouter ouvre donc encore l’éditeur de blocs. La règle prend effet une fois la page enregistrée avec le modèle, puis rouverte.
- Refaites la vérification de l’étape 2. Relancez la même commande
wp eval. Exemple de sortie :
post editor=yes rest=yes block=yes
page editor=yes rest=yes block=yes
book editor=yes rest=yes block=no
listing editor=yes rest=yes block=no
Seuls les types de votre liste doivent passer à block=no, et rest=yes doit rester. Pour une règle par contenu, vérifiez un contenu visé et un autre qui ne doit pas l’être :
wp eval 'var_dump( use_block_editor_for_post( 812 ), use_block_editor_for_post( 2 ) );'
Exemple de sortie :
bool(false)
bool(true)
Utilisez un ID de l’étape 4 et l’ID d’une page ordinaire. Un bool(true) pour le premier veut dire que le chemin du modèle dans la règle ne correspond pas à la valeur enregistrée.
- Ouvrez les écrans d’édition. Connectez-vous et chargez l’écran d’ajout de chaque type modifié, par exemple
/wp-admin/post-new.php?post_type=book, puis ouvrez un contenu existant à partir de sa liste. L’écran classique montre le champ du titre, la zone de contenu avec sa barre d’outils de mise en forme, et les métaboxes dans la colonne de droite. Ouvrez ensuite un article pour confirmer qu’il charge toujours le canevas plein écran de l’éditeur de blocs. Pour une réponse précise, ouvrez la console de développement du navigateur sur chaque écran et lancez :
document.body.classList.contains( 'block-editor-page' )
WordPress ajoute cette classe à la page seulement quand l’éditeur de blocs se charge. Attendez-vous à false sur vos types et à true sur un article. Videz d’abord le cache de pages si votre hébergeur met wp-admin en cache (la plupart ne le font pas).
Valider le résultat
- Listez toutes les fonctions de rappel des deux filtres. Cette commande montre votre extension et tout ce qui se branche sur les mêmes filtres, avec les priorités :
wp eval 'global $wp_filter; foreach ( array( "use_block_editor_for_post_type", "use_block_editor_for_post" ) as $h ) { echo "== $h\n"; if ( empty( $wp_filter[ $h ] ) ) { continue; } foreach ( $wp_filter[ $h ]->callbacks as $prio => $cbs ) { foreach ( $cbs as $id => $cb ) { echo "$prio $id\n"; } } }'
Exemple de sortie :
== use_block_editor_for_post_type
10 sh_classic_for_post_types
== use_block_editor_for_post
10 sh_classic_for_legacy_template
Les fonctions s’exécutent de la priorité la plus basse à la plus haute, et la dernière a le dernier mot. Vos fonctions devraient être les seules ici, ou les autres ne devraient pas renvoyer true pour vos types. Une ligne comme 100 __return_false sous le filtre par type veut dire que l’extension Classic Editor impose l’écran classique partout. Un long identifiant hexadécimal est une fonction anonyme d’un thème ou d’une extension; cherchez-la avec grep -rn "use_block_editor_for_post" wp-content/themes wp-content/plugins wp-content/mu-plugins.
- Confirmez que l’API REST sert toujours le type. Demandez à WordPress la route du type, puis interrogez-la :
wp eval 'echo rest_get_route_for_post_type_items( "book" ), PHP_EOL;'
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/wp-json/wp/v2/book
Exemple de sortie :
/wp/v2/book
200
Utilisez votre domaine et la route affichée par la première commande. Une première ligne vide, ou un 404 de curl, veut dire que le type n’est pas dans l’API REST. C’était déjà le cas avant votre changement, puisque votre extension n’y touche pas.
Dépannage
Un type de la liste s’ouvre encore dans l’éditeur de blocs. Comparez d’abord le nom dans votre liste avec l’étape 1; un libellé ou une faute de frappe échoue sans aucune erreur. Lancez ensuite l’étape 7. Si une autre fonction à une priorité plus haute renvoie true, montez votre priorité au-dessus de la sienne, par exemple de 10 à 110, dans la ligne add_filter(). Si l’étape 7 ne montre pas du tout votre fonction, le fichier ne se charge pas; revoyez l’étape 3.
Tous les types ouvrent maintenant l’écran classique, y compris les articles. L’extension Classic Editor est réglée sur Classic pour tous les utilisateurs, sans changement possible, et l’étape 7 montre 100 __return_false. Désactivez-la, puisque votre extension fait maintenant la partie par type, ou remettez son éditeur par défaut sur l’éditeur de blocs :
wp option update classic-editor-replace block
La commande affiche Success: Updated 'classic-editor-replace' option. Les articles reviennent à l’éditeur de blocs et vos types restent en mode classique. Sur un réseau multisite, l’extension peut plutôt suivre le réglage du réseau, sous Réglages dans l’administration du réseau.
L’écran classique n’a pas de zone de contenu. Le type ne prend pas en charge editor, et l’étape 2 affiche editor=no. L’éditeur de blocs ne se charge jamais pour un tel type, et vous n’avez pas besoin du filtre pour lui. Si les rédacteurs doivent y écrire du texte, ajoutez add_post_type_support( 'listing', 'editor' ); au même fichier obligatoire, dans une fonction branchée sur init à la priorité 20, pour qu’elle s’exécute après l’enregistrement du type.
WP-CLI indique block=no, mais le navigateur montre encore l’éditeur de blocs. Trois causes reviennent souvent. Certaines extensions n’ajoutent leurs filtres que quand is_admin() est vrai, ce qui n’est jamais le cas sous WP-CLI; le navigateur voit alors une fonction que wp eval ne voit pas. Un filtre par contenu peut aussi renvoyer true pour ce contenu précis; vérifiez-le avec use_block_editor_for_post() comme à l’étape 5. Enfin, si l’OPcache de PHP a opcache.validate_timestamps désactivé, il continue de servir l’ancienne copie d’un fichier modifié jusqu’au rechargement de PHP-FPM. Demandez ce rechargement à votre hébergeur, ou vérifiez avec php -i | grep validate_timestamps, en sachant que la valeur en ligne de commande peut différer de celle du serveur Web.
Les auteurs peuvent encore choisir l’éditeur de blocs pour les articles. Cela vient du réglage de l’extension Classic Editor qui permet aux utilisateurs de changer d’éditeur (Allow users to switch editors). Il ajoute des liens « Edit (block editor) » et « Edit (classic editor) » dans les listes d’articles, mais les omet sur vos types, où un seul éditeur est offert. Si vous ne voulez de choix nulle part, mettez ce réglage à Non, ou désactivez l’extension.
Quand ce n’est pas la bonne approche
Si toute l’équipe veut l’éditeur classique pour tous les types, l’extension Classic Editor est l’outil le plus simple. Quand garder l’éditeur classique couvre cette décision et ses réglages.
Si un type n’a aucun texte principal, retirer la prise en charge d’editor le décrit peut-être mieux qu’un filtre. Les rédacteurs ont alors un titre, des métaboxes, et pas de zone de contenu vide.
Si le reproche porte sur des métaboxes qui détonnent, sachez que l’éditeur de blocs affiche lui aussi les métaboxes classiques, dans des panneaux sous le contenu ou dans la barre latérale. Déplacer les champs vers register_post_meta() avec show_in_rest vous permet de les refaire plus tard en panneaux latéraux. Ces choix d’enregistrement sont traités dans les bonnes pratiques des types de contenu personnalisés.
Sur un réseau multisite, un fichier dans mu-plugins/ se charge sur chaque site. Si un seul site a besoin de la règle, ajoutez une vérification get_current_blog_id() dans la fonction, ou utilisez une extension ordinaire activée sur ce site.
Un WordPress qui rapporte vraiment mérite un opérateur — Stack Harbor opère cette pile sous WordPress Entreprise ; réservez une consultation d’infrastructure.