Skip to content

Instantly share code, notes, and snippets.

@JeroenSormani
Created August 18, 2015 06:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JeroenSormani/2a1b6de6e27f6a2c905e to your computer and use it in GitHub Desktop.
Save JeroenSormani/2a1b6de6e27f6a2c905e to your computer and use it in GitHub Desktop.
Automatically link post titles
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
/**
* Get post titles.
*
* Get a list of the post titles and related post IDs.
*
* @since 1.0.0
*
* @return array List of post titles/ post IDs.
*/
function wpal_get_post_titles() {
$post_titles = array();
if ( false === $post_titles = get_transient( 'wpal_post_titles' ) ) :
global $wpdb;
$post_titles = $wpdb->get_results( ( "SELECT ID, post_title from $wpdb->posts WHERE post_type='post' AND post_status = 'publish' AND CHAR_LENGTH(post_title) > 5" ) );
set_transient( 'wpal_post_titles', $post_titles, WEEK_IN_SECONDS );
endif;
return $post_titles;
}
/**
* Replace content.
*
* Search the content for the post titles and replace them when found.
*
* @since 1.0.0
*
* @param string $content Existing post content.
* @return string Modified post content.
*/
function wpal_replace_the_content( $content ) {
// Prepare pot titles
$post_titles = wpal_get_post_titles();
$titles = wp_list_pluck( $post_titles, 'post_title', 'ID' );
$preg_quote_titles = array();
// Escape post titles
foreach ( $titles as $key => $title ) :
$preg_quote_titles[ $key ] = preg_quote( $title, '/' );
endforeach;
// Search for any post titles
$content = preg_replace_callback( '/(' . implode( '|', $preg_quote_titles ) . ')/i', function( $matches ) use ( $preg_quote_titles ) {
global $post;
// Get post ID
$post_id = array_search( strtolower( $matches[0] ), array_map( 'strtolower', $preg_quote_titles ) );
// Don't link to the current page
if ( isset( $preg_quote_titles[ $post_id ] ) && $post->ID !== $post_id ) :
// Use the post title from the DB to its casing is the same
return '<a href="' . get_permalink( $post_id ) . '" class="post-link">' . $preg_quote_titles[ $post_id ] . '</a>';
endif;
return $matches[0];
}, $content );
return $content;
}
add_filter( 'the_content', 'wpal_replace_the_content' );
/**
* Remove transient on save.
*
* Remove the transient holding the post_titles every time a
* post is saved to ensure no unwanted links occur.
*
* ALSO re-index the post titles.
*
* @since 1.0.0
*/
function wpal_remove_transient() {
// Delete old post title transient
delete_transient( 'wpal_post_titles' );
// Re-index post titles
wpal_get_post_titles();
}
add_action( 'save_post', 'wpal_remove_transient' );
@jakedeg
Copy link

jakedeg commented Aug 12, 2017

How do I actually implement this on a wordpress site? Do I have to copy it to functions.php? Do I have to somehow tell the site to load this file?

@AntoineR951
Copy link

AntoineR951 commented May 18, 2020

Hi, thanks for the function. For me it works with some changes :

Line 59 :

$post_id = array_search( strtolower( $matches[0] ), array_map( 'strtolower', $preg_quote_titles ) );

Become :

$post_id = array_search( strtolower( preg_quote ($matches[0] ) ), array_map( 'strtolower', $preg_quote_titles ) );

Line 65 :

return '<a href="' . get_permalink( $post_id ) . '" class="post-link">' . $preg_quote_titles[ $post_id ] . '</a>';

become :

return '<a href="' . get_permalink( $post_id ) . '" class="post-link">' . addslashes($preg_quote_titles[ $post_id ]) . '</a>';

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment