WordPress propose un éditeur WYSIWYG plutôt riche et bien fichu. La possibilité d’insérer un contenu riche (lien, image, etc.) est à portée de tout le monde. Nous allons nous concentrer sur les chemins des liens et des images pour voir comment travaille cet éditeur.
Contenu inséré par l’éditeur
WordPress dispose de deux boutons pour insérer médias et liens. Le bouton des médias situé au dessus du cadre de l’éditeur permet l’insertion d’une image, par exemple.
Si l’on regarde l’attribut src
du code généré, voici ce qui ressort (code simplifié) :
<img src="http://yourawesomewebsite.us/wp-content/uploads/2012/02/image.png" alt="" />
Pour les liens, le bouton situé sur la première ligne des outils de l’éditeur permet leur insertion.
En utilisant le nouvel outil de liens internes, il est possible de faire des liens vers d’autres ressources de son propre site web (page et article).
Ces liens ont un attribut href
absolu, eux aussi.
<a href="http://yourawesomewebsite.us/a-propos">la page à propos</a>
Inconvénient
Si jamais il vous prenait l’envie de déménager votre blog sur un nouveau domaine ou sous-domaine, vous seriez bien embêtés !
En effet, il vous faudrait créer une petite moulinette (requête SQL par exemple) pour intervenir sur les bases de données de WordPress, ou vous retaper les articles à la main.
Solution ?
Cela n’a rien d’absolu, mais mes premiers essais sont plutôt concluants :
Dans functions.php
glisser ce code :
if (!function_exists('juiz_absolute_2_relative')) {
function juiz_absolute_2_relative($post_ID, $post) {
// ScreenFeed - suggestion (http://screenfeed.fr)
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return $post->ID;
$nonce_action = 'update-' . $post->post_type . '_' . $post->ID;
if ( !isset($_POST[ '_wpnonce' ]) || !wp_verify_nonce( $_POST[ '_wpnonce' ], $nonce_action ) )
return $post->ID;
$post_type = get_post_type_object( $post->post_type );
if ( !current_user_can( $post_type->cap->edit_post, $post->ID ) )
return $post->ID;
// CreativeJuiz - replace absolute by relative link
$siteurl = get_bloginfo('url');
// if we are in sub folder installation (/!\) be carefull (/!\)
$after_domain = preg_replace('#http(s)?://(.+)/(.+)#', '$3', $siteurl);
// absolute links to relative links
$new_content = preg_replace('#href="'.$siteurl.'#', 'href="/'.$after_domain, $post->post_content);
//absolute src to relative src
$new_content = preg_replace('#src="'.$siteurl.'#', 'src="/'.$after_domain, $new_content);
// save the post
global $wpdb;
$wpdb->update( $wpdb->posts, array( 'post_content' => $new_content ), array( 'ID' => $post->ID ) );
}
add_action( 'save_post', 'juiz_absolute_2_relative', 10, 2 );
}
Une fois ce code enregistré dans functions.php
, lors d’un enregistrement d’un post, le script vérifiera s’il croise une valeur absolue des attributs src
ou href
et les passera en relative (à condition qu’il reconnaisse la base de l’URL de votre site WordPress).
Le code détecte la valeur de bloginfo('url')
et prend en compte une installation dans un dossier (avec la nuance précédemment citée) ou en sous-domaine, ainsi qu’une installation plus classique bien évidemment.
Une alternative ?
Il existe un plugin qui vous permet d’effectuer un changement d’URL de base pour votre blog.
Ce plugin une fois activé vous offre deux champs texte à renseigner avec : l’ancienne URL, la nouvelle URL.
Il se charge de remplacer dans la base de données toutes les occurences de l’ancienne par la nouvelle URL.
Ce plugin ne vous permet pas d’avoir des liens relatifs !
WordPress.org
Plugin
Velvet blues update
Bref…
N’hésitez pas à me faire vos retours si jamais vous rencontrez un bogue, difficile d’avoir toutes les exceptions en tête 😉
Bonjour,
je l’ai testé pour un site et je n’ai jamais eu de problème, le plugin est assez pratique comme tu l’expliques et il y a pas mal de support en cas de problème.
Excellent tuyau, merci !
Hello
Je te propose de supprimer la requête supplémentaire en utilisant un hook plus tôt « wp_insert_post_data », voici ta fonction modifiée :
function juiz_absolute_2_relative( $post_data ) {
global $post;
// ScreenFeed – suggestion (http://screenfeed.fr)
if ( defined( ‘DOING_AUTOSAVE’ ) && DOING_AUTOSAVE )
return $post->ID;
$nonce_action = ‘update-‘ . $post->post_type . ‘_’ . $post->ID;
if ( !isset($_POST[ ‘_wpnonce’ ]) || !wp_verify_nonce( $_POST[ ‘_wpnonce’ ], $nonce_action ) )
return $post->ID;
$post_type = get_post_type_object( $post->post_type );
if ( !current_user_can( $post_type->cap->edit_post, $post->ID ) )
return $post->ID;
// CreativeJuiz – replace absolute by relative link
$siteurl = get_bloginfo(‘url’);
// if we are in sub folder installation (/!\) be carefull (/!\)
$after_domain = preg_replace(‘#http(s)?://(.+)/(.+)#’, ‘$3’, $siteurl);
// absolute links to relative links
// var_dump($siteurl);
// var_dump($after_domain);
$new_content = preg_replace(‘#href= »‘.$siteurl.’#’, ‘href= »/’.$after_domain, $post->post_content);
//absolute src to relative src
$new_content = preg_replace(‘#src= »‘.$siteurl.’#’, ‘src= »/’.$after_domain, $new_content);
// replace the post content
$post_data[‘post_content’] = $new_content;
return $post_data;
}
add_action( ‘wp_insert_post_data’, ‘juiz_absolute_2_relative’ );
Merci de tester avant de modifier ton article si ça te plait.
Bye !
Hello,
L’idée me plait bien mais elle provoque pas mal d’erreurs.
La doc me parle d’un filter sur ce hook, ainsi que de deux paramètres.
Même en modifiant ta retouche de fonction les clefs du tableau que je lui retourne ne semble pas lui convenir.
Il estime ne pas recevoir de tableau dans le fichier wp-includes/wp-db.php ligne 1204, et donc forcément il a du mal ligne 1206 et suivantes.
J’essaye de voir ça demain si j’ai le temps, là je suis trop crevé 🙂
Merci pour ta proposition !
add_filter = add_action 😉
On les différencie pour la maintenance du code, j’avoue mettre souvent add_actionlors de mes tests…
Pour ce qui est de 2 paramètres, oui, le filtre en attends 2, mais par défaut un add_filter c’est « 10 » pour la prio et « 1 » pour les arguments, et comme je ne lui en donne qu’un, ça ne pose pas de problème.
Pour l’erreur euh, je ne l’ai pas chez moi :s
Tu peux ressayer avec ma function et me donner ici l’erreur ? Merci à demain
Je t’ai envoyé un mail, plus simple pour l’affichage des erreurs.
Merci pour ton implication.
Bizarre, j’ai débuggé « $post_data » et c’est bien un array, ensuite je modifie le contenu d’un item de cet array, puis je return cet array.
Et dans ton erreur il dait que c’est une string o_O
#louche
Je confirme que j’ai toujours la même erreur.
Le problème ne se pose pas sur un article existant, mais sur un nouvel article.
C’est toujours problématique ces strings dans l’array…
Mmm…
Vu la configuration qu’il faut déployer dans le functions.php, autant passer directement par PHPMyAdmin et taper l’incantation suivante :
UPDATE xp_posts SET post_content = REPLACE(post_content, ‘anciensite.com’, ‘nouveausite.com’);
Et comme ça on garde les url absolues, toujours pratiques : quand les ‘fermes de contenus’ copient notre site à la volée, elles copient aussi nos liens. C’est toujours ça de gagné.
Hello.
Je pense que tu n’as pas compris la teneur de mon propos.
Le but c’est de conserver tout le temps des URL relatives même au moment de la rédaction de ses articles.
Je ne parle pas ici de changements radicaux dans la base de données, mais de changement dans les habitudes de WordPress.
Après concrètement, le hotlinking c’est pas mon truc, je préfère faire appliquer mes droits 😉
Dans ta solutions SQL tu oublies des choses aussi, avec seulement cette requête tu vas te bloquer.
Bonne soirée et merci.
Erratum : c’était :
UPDATE wp_posts…