Dev web

#3 ACF Free : créer une page d'options sur WordPress

@thomasclaireau

17 septembre 2021
coucou

Salut les devs Wordpress 👋

Cette semaine, je suis en pleine configuration du backend WordPress de mon application. J'en parlerais plus en détail dans l'hebdomadev de la semaine prochaine mais j'ai choisis de développer un WordPress headless pour avoir le choix de la vue derrière (React.JS en l'occurence).

Wordpress est génial niveau écriture d'articles avec Gutemberg (oui, oui j'apprécie Gutemberg !) mais il manque des fonctionnalités quand il s'agit d'étendre la contribution des pages ou des posts. C'est pourquoi j'utilise le plugin Advanced Custom Fields (ACF) qui me permet d'ajouter des champs de contribution dans la meta de WordPress.

Le problème d'aujourd'hui, c'est que ce plugin est en freemium et ne propose pas, dans sa version gratuite, de page d'options. Cette feature est bien pratique pour configurer les éléments globaux d'une application : header, footer, code analytics etc...

Je vous montre donc comment ajouter une page dont on viendra ensuite apporter des modifications.

Création de la page sur WordPress

Créez une page sur WordPress avec comme nom Site settings et comme slug site-settings. Ne rentrez pas de contenu dans l'éditeur, ce n'est pas utile : on utilisera les champs ACF pour contribuer cette page un peu spéciale.

A cette étape, la page est visible dans la liste :

Liste des pages sur WordPress

Cacher la page de la liste et l'ajouter au menu

Il va nous falloir cacher la page de la liste des pages classiques. On aura ensuite besoin de l'ajouter au menu WordPress pour y accéder. C'est le comportement par défaut de la véritable page d'options ACF.

Pour faire ces actions, rendez-vous dans le fichier functions.php et greffez-vous sur le hook d'action pre_get_posts

Ce code viendra s'interférer avant l'appel des posts sur la liste des pages. Si la page avec le slug site-settings existe, on ajoute un paramètre à la requête post__not_in permettant de cacher la page des résultats.

add_action( 'pre_get_posts', 'hide_settings_page' );

/**
 * Hide settings page from the list
 *
 * @param mixed $query - Query.
 *
 * @return null
 */
function hide_settings_page( $query ) {
	if ( ! is_admin() && ! $query->is_main_query() ) {
		return;
	}
	global $typenow;
	if ( 'page' === $typenow ) {
		$settings_page = get_page_by_path( 'site-settings', null, 'page' )->ID;
		$query->set( 'post__not_in', array( $settings_page ) );
	}

	return null;
}

Puis on l'ajoute ensuite au menu :

add_action( 'admin_menu', 'add_site_settings_to_menu' );

/**
 * Add the page to admin menu
 *
 * @return mixed
 */
function add_site_settings_to_menu() {
	$settings_page = get_page_by_path( 'site-settings', null, 'page' );

	add_menu_page(
		'Site Settings',
		'Site Setttings',
		'manage_options',
		'post.php?post=' . $settings_page->ID . '&action=edit',
		'',
		'dashicons-admin-tools',
		20
	);
}

Cette fois-ci, on se greffe sur le hook admin_menu pour charger du code au moment du chargement du menu. Ce code permet notamment d'ajouter la page avec un label de menu Site Settings puis on reconstruit l'url.

Il nous reste à configurer le lien actif dans le menu. Pour l'instant, quand je suis sur la page site-settings, le lien actif est toujours Page, et oui, WordPress la considère encore comme une page classique :

Pour changer ça, il faudra se greffer sur le hook parent_file permettant de modifier le comportement des liens actifs dans le menu :

add_filter( 'parent_file', 'higlight_custom_settings_page' );

/**
 * Change the active menu item
 *
 * @param mixed $file - File.
 *
 * @return mixed
 */
function higlight_custom_settings_page( $file ) {
	global $pagenow;

	$settings_page = get_page_by_path( 'site-settings', null, 'page' )->ID;

	$post = (int) filter_input( INPUT_GET, 'post' );
	if ( 'post.php' === $pagenow && $post === $settings_page ) {
		$file = "post.php?post=$settings_page&action=edit";
	}
	return $file;
}

Désactiver Gutemberg (sans extension)

Le dernier point de configuration consiste à désactiver Gutemberg sur la page d'options. En effet, nous n'en avons pas besoin, puisqu'on contribut cette page à l'aide des champs ACF :

add_filter( 'use_block_editor_for_post', 'disable_gutemberg_on_specific_pages', 5, 2 );

/**
 * Disable Gutemberg on specific page
 *
 * @param mixed $can - Can.
 * @param mixed $post - Post.
 *
 * @return mixed
 */
function disable_gutemberg_on_specific_pages( $can, $post ) {
	$exclude_pages = array(
		'site-settings',
		'accueil',
		'blog',
	);

	if ( $post ) {
		if ( in_array( $post->post_name, $exclude_pages, true ) ) {
			return false;
		}
	}
	return $can;
}

Cette fois, nous n'utilisons pas un hook d'action mais un filter WordPress nous permettant de désactiver Gutemberg sous certaines conditions. Vous voyez notamment que je l'ai désactivé également sur la page d'accueil et sur la page listant mes articles.

Et voici le résultat dans le back-office :

Bonus : comment récupérer les données de cette page ?

Habituellement, quand on utilise la page d'option d'ACF, on rédupère en front (ou dans l'api dans mon cas) les champs de la manière suivante :

get_field('header_title', 'option');

La fonction get_field est utilisé sur ACF pour récupérer des champs spécifiques, comme ici, le titre du header.

Dans notre configuration, cet appel n'est pas possible et nous devrions faire de cette manière :

// 20 est l'id de la page settings
get_field('header_title', 20);

Dans mon cas, je ne passe pas par l'id de la page pour récupérer les champs mais par son slug comme ceci :

get_field('header_title', op('site-settings'));

Et cet appel est possible grâce à la fonction suivante :

/**
 * Get field from slug
 *
 * @param mixed $slug - Slug of the page settings.
 *
 * @return int
 */
function op( $slug ) {
	$page_url_id = get_page_by_path( $slug );

	return $page_url_id ? $page_url_id->ID : null;
}

Si cette configuration vous intéresse, vous trouverez le code complet sur mon GitHub

Bonne fin de semaine 👋

Dev life, Hebdomadev

#4 - Hebdomadev - mission freelance, premiers retours sur le blog et avancement de mon site

@thomasclaireau

17 septembre 2021
Dev life, Hebdomadev

#2 Hebdomadev : lancement du blog, mission et refonte de site

@thomasclaireau

17 septembre 2021