WP Plugin API (Hooks)

- Samt real world examples

Patrick Hesselberg

- WP Udvikler hos Peytz & Co

- Uddannet Web/Multimedie integrator

- Interesse i data, integration og automatisering

 

Peytz:    peytz.dk/medarbejdere/phh

Twitter: @computephh

Github: phh

Spørgsmål

Hooks

Actions

Filters

Hook into WordPress

do_action($tag, $arguments...)

 

apply_filters($tag, $value, $arguments...)

do_action($tag, $arguments...)

 

add_action($tag, $callback, $priority, $accepted_args)

 

remove_action($tag, $callback, $priority)

 

remove_all_actions($tag, $priority)

Actions

do_action('post_updated', $post_ID);

 

add_action('post_updated', 'phh_update_post_author_notification');

<?php

function phh_update_post_author_notification( $post_id ) {
	$post = get_post( $post_id );

	// Author is not the current user
	if ( $post->post_author != get_current_user_id() ) {
		$author = get_userdata( $post->post_author );
		$subject = sprintf( 'Your post "%s" has been updated!', $post->post_title );
		$body = sprintf( 'Check the changes to your post here: %s', get_permalink( $post_id ) );

		wp_mail( $author->user_email, $subject, $body );
	}
}
add_action( 'post_updated', 'phh_update_post_author_notification' );

do_action('post_updated', $post_ID, $post_after, $post_before);

 

add_action('post_updated', 'phh_update_post_author_notification', 10, 3);

<?php

function phh_update_post_author_notification( $post_id, $post_after, $post_before ) {
	$post = get_post( $post_id );

	// Author is not the current user
	if ( $post->post_author != get_current_user_id() ) {
		$author = get_userdata( $post->post_author );
		$subject = sprintf( 'Your post "%s" has been updated!', $post->post_title );
		$body = 'Here is a diff of the changes:';
		$body .= sprintf( 'Title: %s', wp_text_diff( $post_before->post_title, $post_after->post_title ) );
		$body .= sprintf( 'Content: %s', wp_text_diff( $post_before->post_content, $post_after->post_content ) );
		$body .= sprintf( 'Check the changes to your post here: %s', get_permalink( $post_id ) );

		wp_mail( $author->user_email, $subject, $body );
	}
}
add_action( 'post_updated', 'phh_update_post_author_notification', 10, 3 );

do_action('post_updated', $post_ID, $post_after, $post_before);

 

remove_action('after_update_post', 'phh_update_post_author_notification');

<?php

if ( get_option( 'phh_remove_update_post_author_notification' ) {
    remove_action( 'post_updated', 'phh_update_post_author_notification' );
}

apply_filters($tag, $value, $arguments...)

 

add_filter($tag, $callback, $priority, $accepted_args)

 

remove_filter($tag, $callback, $priority)

 

remove_all_filters($tag, $priority)

Filters

apply_filters('the_title', $title);

 

add_filter('the_title', 'phh_bad_to_good_title');

<?php

/**
 * Filter the post title and replace 'bad' by 'good'.
 * Turns 'Have a bad day' into 'Have a good day!'
 *
 * @param string $title The post title.
 */
function phh_bad_to_good_title( $title ) {
    $title = str_replace( 'bad', 'good', $title );

    return $title;
}
add_filter( 'the_title', 'phh_bad_to_good_title' );
<?php

/**
 * Filter the post title and replace 'bad' by 'good'.
 * Turns 'Have a bad day' into 'Have a good day!'
 *
 * @param string $title The post title.
 */
function phh_bad_to_good_title( $title ) {
    $search = apply_filters( 'phh_bad_to_good_title_words', [
        'bad',
        'terrible',
        'meh',
    ] );
    $title = str_replace( $search, 'good', $title );

    return $title;
}
add_filter( 'the_title', 'phh_bad_to_good_title' );

/**
 * Adds 'unhappy' and 'miserable' to the search filter list.
 *
 * @param array $search List of words to replace to 'good'.
 */
function phh_bad_to_good_title_words( $search ) {
    $search[] = 'unhappy';
    $search[] = 'miserable';

    return $search;
}
add_filter( 'phh_bad_to_good_title_words', 'phh_bad_to_good_title_words' );
<?php

function print_current_hook() {
    echo '<p>' . current_filter() . '</p>';
}
add_action( 'all', 'print_current_hook' );

Good to know hooks

*_init (widgets_init, admin_init ...)

wp/admin_enqueue_script

Template tags return filter (the_title, the_content)
pre_get_posts (every WP_Query)

template_include (current template path)

Plugins

Create a plugin

wp-content/plugins/<folder>/<file>.php

wp-content/plugins/phh-plugin/phh-plugin.php

<?php
/*
Plugin Name: Phh-plugin
Plugin URI: https://github.com/phh/phh-plugin
Description: A custom phh plugin!
Version: 1.0.0
Author: Patrick Hesselberg
Author URI: peytz.dk/medarbejdere/phh
Text Domain: phh-plugin
Domain Path: /languages
*/

Plugin file headers

Activation hooks

register_activation_hook($file, $callback)

register_deactivation_hook($file, $callback)

register_uninstall_hook($file, $callback)

 

$file (__FILE__)

WordPress.org plugin

Plugin vs. themes

Plugin tools

Plugin boilerplates:

  • http://wppb.io/
  • http://wppb.me/
  • Kig i andre plugins

Dev Plugins:

  • query-monitor
  • debug-bar
  • debug-objects

Real world example

- Kode fra rigtige projekter!

// Taxonomy flere cpt
$post_types = apply_filters( 'discipline_ct_post_types', [] );

register_taxonomy( self::TAXONOMY, $post_types );

-----

class...
    add_filter( 'discipline_ct_post_types', [ $this, 'add_type' ] );
...

public function add_type( $object_types ) {
    $object_types[] = self::POST_TYPE;
	
    return $object_types;
}

Filter post types to taxonomy

// Specific sidebar
if ( ! $sidebar = apply_filters( 'hooked_sidebar', false ) ) {
	if ( is_singular( 'post' ) ) {
		$sidebar = 'sidebar-post';
	} elseif ( is_page() ) {
		$sidebar = 'sidebar-page';
	} else {
		$sidebar = 'sidebar';
	}
}

Add a hooked_sidebar

<?php

// Title on the course single page.
public function single_course_the_title( $title, $id ) {
	if ( is_singular( Course::POST_TYPE ) && get_the_ID() == $id && get_post_type( $id ) == Course::POST_TYPE ) {
		$sub_titles = apply_filters( 'course_single_the_title', [], $id );

		if ( ! empty( $sub_titles ) ) {
			$title .= sprintf( '<span>%s</span>', implode( ' | ', $sub_titles ) );
		}

	}

	return $title;
}

Subtitles to title

<?php

// Get queries to search
function get_queries( $image_url, $image_id, $image_relative ) {
	$default_queries = [
		'post_types_content' => [
			'description' => __( 'Search image inside the post content area.', Plugin::TEXT_DOMAIN ),
			'query' => [
				'post_type' => apply_filters( 'unattached_images_queries_post_types_content', $post_types ),
				's' => $image_relative,
			],
		],
		'post_meta_image_id' => [
			'description' => __( 'Search image post thumbnail featured image.', Plugin::TEXT_DOMAIN ),
			'query' => [
				'post_type' => apply_filters( 'unattached_images_queries_post_meta_image_id', $post_types ),
				'meta_query' => [
					[
						'key' => '_thumbnail_id',
						'value' => $image_id,
					],
				],
			],
		],
	];
	
	// Add/modify/delete any existing queries
	return apply_filters( 'unattached_images_queries', $default_queries, $image_id, $image_relative, $image_url );
}

Duplicate functionality

<?php

class...
    add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 10, 2 );
...
    // Local attachment_url
    function wp_get_attachment_url( $url, $post_id ) {
	    return get_the_guid( $post_id );
    }
}

Use guid for image url

<?php

class...
    add_filter( 'login_headerurl', array( $this, 'login_url' ) );
    add_filter( 'login_headertitle', array( $this, 'login_headertitle' ) );
...
    // Login header
    function login_url() {
    	return home_url();
    }
    
    function login_headertitle() {
    	return get_bloginfo( 'name' );
    }
}

Replace wordpress.org references

<?php

class...
    add_action( 'pre_get_posts', [ $this, 'dictionary_words_query' ] );
...
    // Order by title asc
    public function dictionary_words_query( $query ) {
    	if ( $query->is_main_query() && $query->is_post_type_archive( Dictionary::POST_TYPE ) ) {
    		$query->set( 'orderby', 'title' );
    		$query->set( 'order', 'ASC' );
    	}
    }
}

Order archive main query

<?php

class...
    add_action( 'pre_get_posts', [ $this, 'events_archive_query_order' ] );
...
    // Order by start date
    public function events_archive_query_order( $query ) {
    	if ( ! $query->is_main_query() || ! $query->is_post_type_archive( Event::POST_TYPE ) ) {
    	    return;
    	}
    
    	$query->set( 'meta_query', [
    	    'date_start' => [
       	        'key'     => 'date_start',
                'value'   => strtotime( 'today' ),
                'compare' => '>=',
                'type' => 'NUMERIC',
            ],
    	] );
    
    	$query->set( 'orderby', 'date_start' );
    	$query->set( 'order', 'ASC' );
    }
}

Order events by start date

// Add something after singluar
do_action( 'before_header' );
do_action( 'after_singular' );
do_action( 'singular_meta' );

Hook up your templates

// Add something by priority
add_action( 'course_definitions_list', [ $this, 'definitions_list_notes' ] );
add_action( 'course_definitions_list', [ $this, 'definitions_list_downloads' ], 11 );
add_action( 'course_definitions_list', [ $this, 'definitions_list_extra' ], 12 );

Hook up your template (priority)

// Hook into hook
do_action( 'courses_loaded' );

add_action( 'courses_loaded', [ $this, 'courses_loaded' ] );

public function courses_loaded() {
	add_filter( 'single_course_the_title', [ $this, 'single_course_the_title' ] );
	add_action( 'course_definitions_list', [ $this, 'definitions_list_extra' ], 12 );
}

Hook your hook

Tak fordi i lyttede!

Spørgsmål?

WP Plugin API (Hooks) samt real world examples

By Patrick Holberg Hesselberg

WP Plugin API (Hooks) samt real world examples

  • 3,541