How to extend the Kapost Plugin

The purpose of this document is to outline the various techniques that can be employed in order to extend and build upon the base functionality provided by the Kapost plugin.

Extending the plugin requires custom code that can live within your own theme's functions.php or as a separate dedicated plugin.

Before you consider embarking on this journey, please ensure that the functionality you are looking for isn't provided by the Kapost plugin as-is.

To confirm this, please contact Kapost.

WARNING: Kapost cannot debug any potential issues that can arise in your custom code, which can prevent Kapost from being able to successfully push content to your Wordpress instance.

Kapost provides a sample reference implementation. The provided code is NOT production ready, therefore please do not use it as such. Keep this in mind when implementing any of what is suggested below.

In addition, everything outlined below assumes that you are familiar with basic Wordpress concepts like filters.

IMPORTANT: For any of this to work you need to have version 1.9.6 or newer of the Kapost plugin.

Easy

This approach is the most convient and the easiest to use, when all you want to do is to peform some custom logic based on the value of some custom field.

$args = array(
    'post'          => array('title' => 'my post title', 'post_type' => 'post'), // this will be persisted
    'custom_fields' => array('key' => 'value'), // custom fields parsed from the raw request data
    'data'          => array(), // raw request data
    'blog_id'       => current_blog->id // current blog id
);

function kapost_byline_extension_before_on_insert_post_data($args)
{
  // args is mutable, so you can unset custom fields, and
  // set any $args['post'] fields you want
  // this is fired before kapost does his own "on_insert_post_data"
  // therefore it is possible to unset certain things you do not
  // want Kapost to handle on his own

  return $args;
}

function kapost_byline_extension_after_on_insert_post_data($args)
{
  // this is fired after kapost does his own "on_insert_post_data"
  // and therefore it is ideal to build on the top of any changes
  // kapost did to args

  return $args;
}

add_filter('kapost_byline_before_on_insert_post_data', 'kapost_byline_extension_before_on_insert_post_data');
add_filter('kapost_byline_after_on_insert_post_data', 'kapost_byline_extension_after_on_insert_post_data');

The following two filters are ideal to perform actions after the post has been saved (persisted) into the database. This comes in handy when you want to add any metadata (custom fields) or perform any other "post-save" actions that require an actual post_id.

$args = array(
    'post_id' => $post_id, // post id
    'custom_fields' => array('key' => 'value'), // custom fields parsed from the raw request data
    'data' => array() // raw request data
);

function kapost_byline_extension_before_on_insert_post($args)
{
  // this is fired before kapost fires his own "on_insert_post"
  // therefore it is possible to unset certain custom fields
  // to prevent Kapost from performing its default behavior

  return $args;
}

function kapost_byline_extension_after_on_insert_post($args)
{
  // this is fired after kapost fires his own "on_insert_post"
  // therefore this is ideal to build upon the changes Kapost
  // did to the post

  return $args; 
}

add_filter('kapost_byline_before_on_insert_post', 'kapost_byline_extension_before_on_insert_post');
add_filter('kapost_byline_after_on_insert_post', 'kapost_byline_extension_after_on_insert_post');

The $args['custom fields'] array contains all user defined custom fields and built-in metadata sent by Kapost.

Kapost metadata are prefixed with _kapost_ or kapost_, (kapost_post_id, kapost_author_email, etc.) which is to avoid any naming collisions with user defined custom fields.

The custom_fields is an unordered hash:

$args['custom_fields'] = array(
    'kapost_post_id' => '58c6fa420da2e77c62000000', 
    'kapost_author_email' => 'john@doe.org'
);

Each key and value has been sanitized via sanitize_text_field, so they do not need any further sanitization.

If for some reason it is desired to access the raw custom fields data, without any prior sanitization, then one can do so by using the data argument.

$args['data']['custom_fields'] = array(
    array('key' => 'kapost_post_id', 'value' => '58c6fa420da2e77c62000000'),
    array('key' => 'kapost_author_email', 'value' => 'john@doe.org')
);

It is worth noting that in this particular case, custom_fields is an array of arrays and it's not "ordered" so you should not rely on numeric indices to locate the desired key => value pair.

Advanced

If what you read in the Easy section above, wasn't enough for your particular usecase, it is possible to go a little bit further down the pipeline.

function kapost_byline_extension_xmlrpc_new_post_args($args)
{
  // manipulate args in any way, do validations, etc
  // you can return an IXR_Error with a specific error
  // message which will show up in Kapost

  if(!isset($args['title']))
    $args['title'] = 'Hello World';

  return $args;
}

function kapost_byline_extension_xmlrpc_new_post($post_id, $args)
{
  // if post_id is a string then post has been persisted 
  // at this point, so you can do a get_post() to retrieve it
  // or add metadata (custom fields), etc

  if(is_string($post_id))
    add_post_meta($post_id, 'hello_world', 'kapost');

  return $post_id;
}

add_filter('kapost_byline_xmlrpc_new_post_args', 'kapost_byline_extension_xmlrpc_new_post_args');
add_filter('kapost_byline_xmlrpc_new_post', 'kapost_byline_extension_xmlrpc_new_post', 999, 2);

Expert

If you find yourself reading this section, it means that you want full control over the flow from beginning to end.

Kapost exposes its own xmlrpc methods, and it is possible to override them with your own.

The $args argument that this function receives contains the raw request data converted into arrays (and hashes) by the XML-RPC server.

function kapost_byline_extension_xmlrpc_new_post($args)
{
  // manipulate args in any way, do validations, etc
  // you can return an IXR_Error with a specific error
  // message which will show up in Kapost

  $post_id = kapost_byline_xmlrpc_new_post($args);

  if($post_id instanceof IXR_Error)
    return $post_id;

  // do something with the post_id, add metadata (custom fields), etc

  return $post_id;
}

function kapost_byline_extension_xmlrpc_methods($methods)
{
  $methods['kapost.newPost'] = 'kapost_byline_extension_xmlrpc_new_post';
  return $methods;
}

add_filter('kapost_byline_xmlrpc_methods', 'kapost_byline_extension_xmlrpc_methods');

Reference

Here is a list of all possible filters as exposed by the Kapost Byline Plugin.

  • kapost_byline_new_post_args (one argument: $args)
  • kapost_byline_new_post (two arguments: $post_id, $args)
  • kapost_byline_edit_post_args (two arguments: $args, $post_id)
  • kapost_byline_edit_post (three arguments: $result (boolean), $post_id, $args)
  • kapost_byline_get_post (one argument: $post)
  • kapost_byline_new_media_object_args (one argument: $args)
  • kapost_byline_new_media_object (two arguments: $image, $args)
  • kapost_byline_get_permalink (two arguments: $permalink, $post_id)
  • kapost_byline_get_preview_permalink (two arguments: $preview_permalink, $post_id)
  • kapost_byline_get_preview_args (two arguments: $args, $post_id)
  • kapost_byline_get_preview (one argument: $permalink)
  • kapost_byline_before_on_insert_post_data (one argument: $args)
  • kapost_byline_after_on_insert_post_data (one argument: $args)
  • kapost_byline_before_on_insert_post (one argument: $args)
  • kapost_byline_after_on_insert_post (one argument: $args)
  • kapost_byline_get_attachment_by_url (one argument: $args)

If a filter has more than one argument then the actual number has to be passed to the add_filter function as such. The third argument specifies the count.

In addition to this, make sure to always 'return' the first argument of the filter.

This is the only mutable argument.

function kapost_byline_extension_xmlrpc_edit_post($result, $post_id, $args)
{
  if($result === true)
  {
    // do stuff
  }

  return $result;
}

add_filter('kapost_byline_edit_post', 'kapost_byline_extension_xmlrpc_edit_post', 999, 3);

Reference Implementation

<?php
/*
    Plugin Name: Kapost Extension
    Plugin URI: http://www.kapost.com/
    Description: Kapost Extension
    Version: 1.0.0
    Author: Kapost
    Author URI: http://www.kapost.com
    License: Public Domain. No warranties expressed or implied. Use at your own risk.
*/
define('KAPOST_EXTENSION_VERSION', '1.0.0');

function kapost_extension_after_on_insert_post($args)
{
    $post_id = $args['post_id'];
    $custom_fields = $args['custom_fields'];

    if(isset($custom_fields['_kapost_personas']))
        update_post_meta($post_id, 'personas', $custom_fields['_kapost_personas']);

    return $args; 
}

add_filter('kapost_byline_after_on_insert_post', 'kapost_extension_after_on_insert_post');
?>