How to add a link from a featured image to any URL

I want to provide a link to the source of a featured image, that I use to draw attention to a post of mine, to help catalog that as a “fair use”.

Unfortunately, the standard Twentyseventeen theme of WordPress doesn’t offer any way of doing such a simple thing out of the box.

But with the help of my Custom Stuff plugin

<?php
/*
Plugin Name: Custom Stuff
Plugin URI: http://andowebsit.es/
Description: Custom stuff for my blog.
Author: Andrea Ercolino
Author URI: http://andowebsit.es/about
Version: 1.1
*/

function custom_stuff_header() {
    require 'header.php';
}
add_action( 'wp_head',  'custom_stuff_header', 10, 0 );


function custom_stuff_footer() {
    require 'footer.php';
}
add_action( 'wp_footer',  'custom_stuff_footer', 10, 0 );

require 'no-richedit.php';

(file wordpress/wp-content/plugins/custom-stuff/custom-stuff.php)

that’s only a few lines away

<?php

function custom_stuff_featured_image_link($html, $post_id, $post_thumbnail_id) {
    $post_thumbnail = get_post( $post_thumbnail_id );
    if ( ! $post_thumbnail ) {
        return $html;
    }
    $href = $post_thumbnail->post_title;
    if ( ! $href ) {
        return $html;
    }
    return "<a href='$href' target='_blank'>$html</a>";
}

add_filter( 'post_thumbnail_html', 'custom_stuff_featured_image_link', 10, 3 );

(file wordpress/wp-content/plugins/custom-stuff/featured-image-link.php)

<?php
/*
Plugin Name: Custom Stuff
Plugin URI: http://andowebsit.es/
Description: Custom stuff for my blog.
Author: Andrea Ercolino
Author URI: http://andowebsit.es/about
Version: 1.2
*/

function custom_stuff_header() {
    require 'header.php';
}
add_action( 'wp_head',  'custom_stuff_header', 10, 0 );


function custom_stuff_footer() {
    require 'footer.php';
}
add_action( 'wp_footer',  'custom_stuff_footer', 10, 0 );

require 'no-richedit.php';

require 'featured-image-link.php';

(file wordpress/wp-content/plugins/custom-stuff/custom-stuff.php)

How to use Markdown in WordPress and preserve spaces in code blocks

It’s easy to add Markdown support to WordPress. However, it does have a nefarious quirk. In fact, even if you can input Markdown text from the Text panel, and it gets rendered just fine in the blog, the harsh truth is that, as soon as you inadvertently switch to the Visual panel, all the white space in your code blocks gets wiped out, losing all the indentation you had put in.

This looks like a typical reason for writing a plugin to fix that.

Use a shell plugin

Given that I often need small WordPress adjustments like this one, in the past I developed one ring to rule them all: Custom Stuff.

<?php
/*
Plugin Name: Custom Stuff
Plugin URI: http://andowebsit.es/
Description: Custom stuff for my blog.
Author: Andrea Ercolino
Author URI: http://andowebsit.es/about
Version: 1.0
*/

function custom_stuff_header() {
    require 'header.php';
}
add_action( 'wp_head',  'custom_stuff_header', 10, 0 );


function custom_stuff_footer() {
    require 'footer.php';
}
add_action( 'wp_footer',  'custom_stuff_footer', 10, 0 );

 (file wordpress/wp-content/plugins/custom-stuff/custom-stuff.php)

which is just a simple PHP script that basically declares itself as a WordPress plugin and all it does is to require other PHP scripts where the real action takes place.

Design a usable solution

What we need is a way to make WordPress aware that a post is written in Markdown thus no Visual editor will ever be allowed for it.

My solution is based on the user_can_richedit hook and the Shortcode API. It works like this:

  1. At the start of a Markdown text, you add the shortcode.
  2. In editing mode, the hook handler determines whether or not a post begins with that shortcode. If it does, a false is returned, thus effectively forbidding the Vsual editor.
  3. In reading mode, that shortcode is just replaced by an empty string.

Code

<?php

function custom_stuff_no_richedit_if_content_asks( $default ) {
    global $post;
    $content = $post ? $post->post_content : '';
    $start = '';
    if ( substr($content, 0, strlen($start)) === $start ) {
        return false;
    }
    return $default;
}
add_filter( 'user_can_richedit', 'custom_stuff_no_richedit_if_content_asks', 10, 1 );

function custom_stuff_nothing() {
    return '';
}
add_shortcode( 'no_richedit', 'custom_stuff_nothing', 10, 0 );

 (file wordpress/wp-content/plugins/custom-stuff/no-richedit.php)

<?php
/*
Plugin Name: Custom Stuff
Plugin URI: http://andowebsit.es/
Description: Custom stuff for my blog.
Author: Andrea Ercolino
Author URI: http://andowebsit.es/about
Version: 1.1
*/

function custom_stuff_header() {
    require 'header.php';
}
add_action( 'wp_head',  'custom_stuff_header', 10, 0 );


function custom_stuff_footer() {
    require 'footer.php';
}
add_action( 'wp_footer',  'custom_stuff_footer', 10, 0 );

require 'no-richedit.php';

 (file wordpress/wp-content/plugins/custom-stuff/custom-stuff.php)

Example

This is how WordPress looks like when the shortcode is used. Notice that there is no Visual editor panel

This is how WordPress looks like when the shortcode is not used.

Only one thing to remember

There is only one thing to remember then. When adding a post, before introducing any relevant Markdown, switch to the Text panel, add the [no-richedit] shortcode and save a draft. Then the Visual editor won’t appear anymore for that post. (until you remove the shortcode and save again)

How to use Rake::PackageTask to create a zip file

I found out that the easiest way to build a WordPress plugin is using a rake task. In fact, you can use Rake::PackageTask to create a zip file. However, there is very little documentation about how to do it in practice. Here is my solution.

  1. (destroy and) create a folder to hold just the needed files
  2. copy the (possibly transformed) needed files to that folder
  3. compress the folder

Here is my Rakefile:

require 'rake/packagetask'

namespace :nzymes do
    desc 'Build plugin'
    task build: %w(destroy create package)

    desc 'Destroy dist folder and its contents'
    task :destroy do
      rm_rf 'dist'
    end

    desc 'Create dist folder and its contents'
    task :create do
      mkdir_p 'dist/nzymes/vendor'
      cp_r 'vendor/Ando', 'dist/nzymes/vendor'
      cp_r 'src', 'dist/nzymes'
      cp_r Dir.glob('*.php'), 'dist/nzymes'
      cp_r Dir.glob('*.md'), 'dist/nzymes'
      cp_r 'readme.txt', 'dist/nzymes'
    end

    Rake::PackageTask.new('nzymes', :noversion) do |p|
      p.need_zip = true
      p.package_dir = 'dist'
    end
end

Here are the tasks it creates:

andrea at Lock-and-Stock in ~/dev/wordpress/plugins/nzymes on master [!?$]
$ rake --tasks
rake nzymes:build            # Build plugin
rake nzymes:clobber_package  # Remove package products
rake nzymes:create           # Create dist folder and its contents
rake nzymes:destroy          # Destroy dist folder and its contents
rake nzymes:package          # Build all the packages
rake nzymes:repackage        # Force a rebuild of the package files

Here is how you can use it:

andrea at Lock-and-Stock in ~/dev/wordpress/plugins/nzymes on master [!?$]
$ rake nzymes:build
rm -rf dist
mkdir -p dist/nzymes/vendor
cp -r vendor/Ando dist/nzymes/vendor
cp -r src dist/nzymes
cp -r nzymes.php dist/nzymes
cp -r nzymes-manual.md README.md dist/nzymes
cp -r readme.txt dist/nzymes
cd dist
zip -r nzymes.zip nzymes
  adding: nzymes/ (stored 0%)
  adding: nzymes/nzymes-manual.md (deflated 70%)
  adding: nzymes/nzymes.php (deflated 46%)
  adding: nzymes/README.md (deflated 48%)
  adding: nzymes/readme.txt (deflated 53%)
  adding: nzymes/src/ (stored 0%)
  adding: nzymes/src/Nzymes/ (stored 0%)
  adding: nzymes/src/Nzymes/Capabilities.php (deflated 84%)
  adding: nzymes/src/Nzymes/Engine.php (deflated 80%)
  adding: nzymes/src/Nzymes/Options.php (deflated 73%)
  adding: nzymes/src/Nzymes/Plugin.php (deflated 74%)
  adding: nzymes/src/Nzymes/Stack.php (deflated 70%)
  adding: nzymes/src/Nzymes/Unused.php (deflated 69%)
  adding: nzymes/vendor/ (stored 0%)
  adding: nzymes/vendor/Ando/ (stored 0%)
  adding: nzymes/vendor/Ando/ErrorFactory.php (deflated 79%)
  adding: nzymes/vendor/Ando/Exception.php (deflated 29%)
  adding: nzymes/vendor/Ando/Regex.php (deflated 78%)
  adding: nzymes/vendor/Ando/StarFunc.php (deflated 73%)
cd -

Here is what you get:

andrea at Lock-and-Stock in ~/dev/wordpress/plugins/nzymes on master [$]
$ ls -la dist
total 104
drwxr-xr-x   4 andrea  staff    136 May 25 13:03 .
drwxr-xr-x@ 20 andrea  staff    680 May 25 13:03 ..
drwxr-xr-x   8 andrea  staff    272 May 25 13:03 nzymes
-rw-r--r--   1 andrea  staff  50814 May 25 13:03 nzymes.zip