Skip to content

Instantly share code, notes, and snippets.

@lightningspirit
Last active August 8, 2024 15:26
Show Gist options
  • Save lightningspirit/7a4e5abd77b5b63b3409086f1ac6aa55 to your computer and use it in GitHub Desktop.
Save lightningspirit/7a4e5abd77b5b63b3409086f1ac6aa55 to your computer and use it in GitHub Desktop.
Intercepts WordPress posts and terms changes and pings an external service
<?php
/**
* Plugin Name: Ping Updates
* Plugin URI: https://gist.github.com/lightningspirit/7a4e5abd77b5b63b3409086f1ac6aa55
* Description: Intercepts posts and terms changes and pings an external service
* Author: Move Your Digital, Inc.
* Author URI: https://moveyourdigital.com
* Version: 0.2.0
* License: GPLv2
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Update URI: https://gist.githubusercontent.com/lightningspirit/7a4e5abd77b5b63b3409086f1ac6aa55/raw/wp-update-info.json
* Text Domain: email-logs
* Domain Path: /languages
*
* @package Post_Updates
*/
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Load plugin translations and post type
*
* @since 0.1.0
*/
add_action(
'plugins_loaded',
function () {
include __DIR__ . '/updater.php';
}
);
/**
* Filters this plugin data
*
* @since 0.3.2
*/
add_filter(
'plugin_basename_file_' . plugin_basename( __DIR__ ),
function () {
return plugin_basename( __FILE__ );
}
);
/**
* @var $name
* @var $body
*/
function api_send_event(string $name, array $body = [])
{
$url = defined('PING_UPDATES_URL') ? constant('PING_UPDATES_URL') : get_option('ping_updates_url', home_url());
$token = get_option('ping_updates_authz_token');
$result = wp_remote_post($url, [
'method' => 'POST',
'timeout' => 30,
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => $token,
],
'data_format' => 'body',
'body' => wp_json_encode(array_merge([
'name' => $name,
], $body)),
]);
if (is_wp_error($result)) {
error_log($result->get_error_message(), 0);
}
return $result;
}
/**
* Sends event of post update
*/
add_action("post_updated", function (int $post_id, \WP_Post $post) {
api_send_event("post_updated", [
"ID" => $post_id,
"uri" => wp_make_link_relative(get_permalink($post_id)),
"type" => $post->post_type,
]);
}, 10, 3);
/**
* Sends event of post delete
*/
add_action("delete_post", function (int $post_id, \WP_Post $post) {
api_send_event("post_deleted", [
"ID" => $post_id,
"uri" => wp_make_link_relative(get_permalink($post_id)),
"type" => $post->post_type,
]);
}, 10, 2);
/**
* Sends event of term saved
*/
add_action("saved_term", function (int $term_id, int $taxonomy_id, string $taxonomy) {
$term_url = get_term_link($term_id, $taxonomy);
api_send_event("term_updated", [
"ID" => $term_id,
"uri" => wp_make_link_relative($term_url),
"type" => $taxonomy,
]);
}, 10, 3);
/**
* Sends event of term deleted
* Also, optionally ping for all associated posts
*/
add_action("delete_term", function (int $term_id, int $tax_id, string $taxonomy, WP_Term $term, array $object_ids) {
$term_url = get_term_link($term, $taxonomy);
api_send_event("term_deleted", [
"ID" => $term_id,
"uri" => wp_make_link_relative($term_url),
"type" => $taxonomy,
]);
$ping_associated_posts = defined('ENABLE_PING_UPDATES_ON_TERMS_POSTS')
? !!constant('ENABLE_PING_UPDATES_ON_TERMS_POSTS')
: false;
if ($ping_associated_posts) {
$posts = get_posts([
'post__in' => $object_ids
]);
foreach ($posts as $post) {
api_send_event("post_updated", [
"ID" => $post->ID,
"uri" => wp_make_link_relative(get_permalink($post->ID)),
"type" => $post->post_type,
]);
}
}
}, 10, 5);
<?php
/**
* Hook plugin updater from git repository
*
* @package email-logs
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Gets and updates plugin Update URI
*
* @since 0.3.5
*/
add_filter(
'plugin_update_uri_' . plugin_basename( __DIR__ ),
function ( $delete = false ) {
if ( true === $delete ) {
delete_option( 'plugin_update_uri_' . plugin_basename( __DIR__ ) );
}
$update_uri = get_option( 'plugin_update_uri_' . plugin_basename( __DIR__ ) );
if ( ! $update_uri ) {
if ( ! function_exists( 'get_plugin_data' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$basename_file = apply_filters( 'plugin_basename_file_' . plugin_basename( __DIR__ ), '' );
$plugin_data = get_plugin_data( trailingslashit( WP_PLUGIN_DIR ) . $basename_file );
$update_uri = $plugin_data['UpdateURI'];
update_option( 'plugin_update_uri_' . plugin_basename( __DIR__ ), $update_uri );
}
return $update_uri;
}
);
/**
* Fetch and return plugin data from declared remote
*
* @since 0.3.2
*
* @param false|object|array $default_result default data to return if fetch fails
*/
add_filter(
'plugin_update_remote_data_' . plugin_basename( __DIR__ ),
function ( $default_result = '' ) {
$remote_data = wp_remote_get(
apply_filters( 'plugin_update_uri_' . plugin_basename( __DIR__ ), null ),
array(
'timeout' => 10,
'headers' => array(
'Accept' => 'application/json',
),
)
);
if ( is_wp_error( $remote_data )
|| 200 !== wp_remote_retrieve_response_code( $remote_data )
|| empty( wp_remote_retrieve_body( $remote_data ) ) ) {
return $default_result;
}
return json_decode( wp_remote_retrieve_body( $remote_data ) );
}
);
/**
* Filters the response for the current WordPress.org Plugin Installation API request.
*
* Returning a non-false value will effectively short-circuit the WordPress.org API request.
*
* If `$action` is 'query_plugins' or 'plugin_information', an object MUST be passed.
* If `$action` is 'hot_tags' or 'hot_categories', an array should be passed.
*
* @since 2.7.0
*
* @param false|object|array $result The result object or array. Default false.
* @param string $action The type of information being requested from the Plugin Installation API.
* @param object $args Plugin API arguments.
*/
add_filter(
'plugins_api',
function ( $result, $action, $args ) {
if ( 'plugin_information' !== $action ) {
return $result;
}
if ( plugin_basename( __DIR__ ) !== $args->slug ) {
return $result;
}
$result = apply_filters( 'plugin_update_remote_data_' . plugin_basename( __DIR__ ), $result );
$result->slug = plugin_basename( __DIR__ );
$result->trunk = $result->download_url;
$result->sections = array(
'description' => $result->sections->description,
'installation' => $result->sections->installation,
);
$result->banners = array(
'low' => $result->banners->low,
'high' => $result->banners->high,
);
return $result;
},
20,
3
);
/**
* Fires once activated plugins have loaded.
*
* Pluggable functions are also available at this point in the loading order.
*
* @since 1.5.0
*/
add_action(
'init',
function () {
$update_uri = apply_filters( 'plugin_update_uri_' . plugin_basename( __DIR__ ), null );
$hostname = wp_parse_url( sanitize_url( $update_uri ), PHP_URL_HOST );
add_filter(
'update_plugins_' . $hostname,
function ( $update, $plugin_data, $plugin_file ) {
$basename_file = apply_filters( 'plugin_basename_file_' . plugin_basename( __DIR__ ), '' );
if ( $plugin_file !== $basename_file ) {
return $update;
}
if ( ! empty( $update ) ) {
return $update;
}
$remote_data = apply_filters( 'plugin_update_remote_data_' . plugin_basename( __DIR__ ), $update );
if ( ! $remote_data ) {
return $update;
}
if ( version_compare( $remote_data->version, $plugin_data['Version'], '<=' ) ) {
return $update;
}
if ( version_compare( get_bloginfo( 'version' ), $remote_data->requires, '<' ) ) {
return $update;
}
if ( version_compare( PHP_VERSION, $remote_data->requires_php, '<' ) ) {
return $update;
}
return array(
'slug' => plugin_basename( __DIR__ ),
'version' => $remote_data->version,
'url' => $plugin_data['PluginURI'],
'package' => $remote_data->download_url,
);
},
10,
4
);
}
);
/**
* Fires when the upgrader process is complete.
*
* See also {@see 'upgrader_package_options'}.
*
* @since 3.6.0
* @since 3.7.0 Added to WP_Upgrader::run().
* @since 4.6.0 `$translations` was added as a possible argument to `$hook_extra`.
*
* @param WP_Upgrader $upgrader WP_Upgrader instance. In other contexts this might be a
* Theme_Upgrader, Plugin_Upgrader, Core_Upgrade, or Language_Pack_Upgrader instance.
* @param array $hook_extra {
* Array of bulk item update data.
*
* @type string $action Type of action. Default 'update'.
* @type string $type Type of update process. Accepts 'plugin', 'theme', 'translation', or 'core'.
* @type bool $bulk Whether the update process is a bulk update. Default true.
* @type array $plugins Array of the basename paths of the plugins' main files.
* @type array $themes The theme slugs.
* @type array $translations {
* Array of translations update data.
*
* @type string $language The locale the translation is for.
* @type string $type Type of translation. Accepts 'plugin', 'theme', or 'core'.
* @type string $slug Text domain the translation is for. The slug of a theme/plugin or
* 'default' for core translations.
* @type string $version The version of a theme, plugin, or core.
* }
* }
*/
add_action(
'upgrader_process_complete',
function ( $upgrader_object, $options ) {
$basename_file = apply_filters( 'plugin_basename_file_' . plugin_basename( __DIR__ ), '' );
if ( 'update' === $options['action'] && 'plugin' === $options['type'] ) {
foreach ( $options['plugins'] as $each_plugin ) {
if ( $each_plugin === $basename_file ) {
apply_filters( 'plugin_update_uri_' . plugin_basename( __DIR__ ), true );
}
}
}
},
10,
2
);

WordPress Ping Updates

This plugin intercepts WordPress posts and terms changes and pings an external service.

Usage

  1. Download this ZIP
  2. Add define('PING_UPDATES_URL', 'https://my-service.com/api'); to wp-config.php or ping_updates_url option in wp_options
  3. Optionally, add define('ENABLE_PING_UPDATES_ON_TERMS_POSTS', true); if you want to ping each associated post when a term is changed
  4. Add an option ping_updates_authz_token in wp_options where the value is the token to include in the Authorization header
  5. Upload to plugins of your WordPress
{
"name": "Ping Updates",
"slug": "ping-updates",
"author": "<a href='https://github.com/moveyourdigital'>Move Your Digital</a>",
"author_profile": "https://github.com/moveyourdigital",
"version": "0.2.0",
"download_url": "https://gist.github.com/lightningspirit/7a4e5abd77b5b63b3409086f1ac6aa55/archive/71ab57f4d59d23de63d156168ec6210709cbb3e6.zip",
"requires": "5.8",
"tested": "6.5.2",
"requires_php": "7.4",
"last_updated": "2024-04-21 09:35:00",
"sections": {
"description": "Intercepts posts and terms changes and pings an external service.",
"installation": "Click the <i>activate</i> button. No further configuration."
},
"banners": {
"low": "https://eu-west-1-serve-cdn.ofloop.com/wp-ping-updates-plugin/banner-772x250.jpg",
"high": "https://eu-west-1-serve-cdn.ofloop.com/wp-ping-updates-plugin/banner-1544x500.jpg"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment