Rinominare uno Shortcode via Codice

Rinominare uno Shortcode via Codice

Capita cambiare idea. Ma quando per qualche ragione cambiamo idea sul nome di uno shortcode diventato quasi onnipresente tra i nostri Articoli, Pagine e Post Personalizzati, l'unico modo ragionevole di rinominarne tutte le occorrenze è programmaticamente — sviluppare script a cui delegare tutto il lavoro ripetitivo è un'abitudine che, credimi, ripaga a lungo termine.

Il frammento di codice che segue è una generalizzazione di uno script più semplice che ho sviluppato per la migrazione dei dati da SiteTree a The Permalinks Cascade, sostanzialmente è un'implementazione dell'operazione 'ricerca e sostituisci' iterata su tutti i post che presentano una traccia dello shortcode da rinominare. Il più della magia è condensata nelle espressioni regolari, usate per individuare le occorrenze dello shortcode che non includano una sequenza di escape, ovvero doppie parentesi quadre. Per fare ciò, le due regex usano un lookaround negativo, un'asserzione di larghezza zero di cui puoi apprendere tutto sul sito Regular-Expressions.info.

1$old_shortcode_name = 'my-shortcode';
2$new_shortcode_name = 'my-new-shortcode';
3
4// We do a preliminary sorting of the posts by using
5// the search feature built into the WP_Query class, 
6// so as to retrieve from the database only the posts  
7// that might contain the shortcode to rename.
8$arguments = array(
9  'posts_per_page' => -1,
10  'post_type'      => 'any',
11  's'              => "[{$old_shortcode_name}"
12);
13
14$query = new WP_Query( $arguments );
15
16// The negative look-behind and the negative look-ahead in 
17// the regular expressions ensure that shortcodes escaped 
18// with double square brackets are not matched.
19// Also, the capturing group in the first regex is 
20// used to capture the list of attributes that 
21// the shortcode might include. 
22$patterns = array(
23  "#(?<!\[)\[{$old_shortcode_name}( [^\]]+)?\]#",
24  "#\[/{$old_shortcode_name}\](?!\])#"
25);
26
27// The match variable '$1' will be replaced either with 
28// an empty string or a list of shortcode attributes.
29$replacements = array(
30  "[{$new_shortcode_name}\$1]",
31  "[/{$new_shortcode_name}]"
32);
33
34while ( $query->have_posts() ) {
35  $query->the_post();
36
37  $the_content = get_the_content();
38
39  // If $the_content doesn't contain non-escaped 
40  // occurrences of the shortcode we want to rename, 
41  // we just go on to analyse the next post.
42  if (! preg_match( $patterns[0], $the_content ) ) {
43    continue;
44  }
45  
46  // We retrieve the current post 
47  // as an associative array.
48  $the_post = get_post( null, ARRAY_A );
49
50  if (! $the_post ) {
51    continue;
52  }
53
54  $the_post['post_content'] = preg_replace( $patterns,
55                                            $replacements,
56                                            $the_content );
57
58  // We let WordPress automatically update 
59  // the post's modification date.
60  unset( $the_post['post_modified'], $the_post['post_modified_gmt'] );
61
62  // The last parameter hinders WordPress 
63  // from triggering the after-insert hooks.
64  wp_update_post( $the_post, false, false );
65}
66
67// Mandatory when we create 
68// a secondary loop through WP_Query. 
69wp_reset_postdata();

Il Caso Limite

La presenza di shortcode nidificati in uno o più dei tuoi post non è certamente un'improbabilità tale da doverla etichettare come caso limite, ma uno shortcode con sequenza di escape che racchiuda proprio un'occorrenza dello shortcode da rinominare è senza dubbio un caso limite. Quindi, se da qualche parte nel tuo sito hai scritto qualcosa del genere...

1[[my-outer-shortcode]
2  [my-shortcode arg="value"]
3[/my-outer-shortcode]]

...sarebbe meglio escludere preventivamente dalla query i post contenenti pseudo-codice di questo tipo. Devi giusto passare al costruttore di WP_Query una lista di ID quale valore dell'argomento post__not_in.

Eseguire il Codice: Dove e Quando

Considerato un contesto generico, puoi semplicemente mettere il codice nel file functions.php del tema attivo, e cancellarlo una volta che lo shortcode sia stato rinominato. Come precauzione però, ti suggerisco di lasciare che WordPress lo esegua in corrispondenza dell'hook init, in questo modo:

1function rename_my_shortcode() {
2  // The snippet goes here.
3}
4add_action( 'init', 'rename_my_shortcode' );

Eseguire il Codice: Una Nota Finale

Eseguire lo snippet una sola volta è più che sufficiente, però, nell'eventualità in cui lasci lo snippet in esecuzione più volte, non devi preoccuparti, perché le istruzioni condizionali di cui è provvisto agiranno da deterrente a risultati inattesi.

TOP