' . "\n";
echo '' . "\n";
echo ' ' . "\n";
echo ' bbPress' . "\n";
echo ' http://bbpress.org/' . "\n";
echo ' ' . bb_get_uri() . '' . "\n";
echo ' ' . "\n";
echo ' ' . "\n";
echo ' ' . "\n";
echo ' ' . "\n";
echo '' . "\n";
exit;
}
// Load the XML-RPC server/client classes
if ( ! class_exists( 'IXR_Value' ) ) {
require_once( BACKPRESS_PATH . '/class.ixr.php' );
}
/**
* XML-RPC server class to allow for remote publishing
*
* @since 1.0
* @package bbPress
* @subpackage Publishing
* @uses class IXR_Server
*/
class BB_XMLRPC_Server extends IXR_Server
{
/**
* Stores the last error generated by the class
*
* @since 1.0
* @var object|boolean An instance of the IXR_Error class or false if no error exists
*/
var $error = false;
/**
* Site options which can be manipulated using XML-RPC
*
* @since 1.0
* @var array
*/
var $site_options = array();
/**
* Whether read-only methods require authentication
*
* @since 1.0
* @var boolean
**/
var $auth_readonly = false;
/**
* Whether user switching is allowed
*
* @since 1.0
* @var boolean
**/
var $allow_user_switching = false;
/**
* Initialises the XML-RPC server
*
* @since 1.0
* @return void
*/
function __construct()
{
// bbPress publishing API
if ( bb_get_option( 'enable_xmlrpc' ) ) {
$this->methods = array(
// - Demo
'demo.sayHello' => 'this:sayHello',
'demo.addTwoNumbers' => 'this:addTwoNumbers',
// - Forums
'bb.getForumCount' => 'this:bb_getForumCount',
'bb.getForums' => 'this:bb_getForums',
'bb.getForum' => 'this:bb_getForum',
'bb.newForum' => 'this:bb_newForum',
'bb.editForum' => 'this:bb_editForum',
'bb.deleteForum' => 'this:bb_deleteForum',
// - Topics
'bb.getTopicCount' => 'this:bb_getTopicCount',
'bb.getTopics' => 'this:bb_getTopics',
'bb.getTopic' => 'this:bb_getTopic',
'bb.newTopic' => 'this:bb_newTopic',
'bb.editTopic' => 'this:bb_editTopic',
'bb.deleteTopic' => 'this:bb_deleteTopic', // Also undeletes
'bb.moveTopic' => 'this:bb_moveTopic',
'bb.stickTopic' => 'this:bb_stickTopic', // Also unsticks
'bb.closeTopic' => 'this:bb_closeTopic', // Also opens
'bb.getTopicStatusList' => 'this:bb_getTopicStatusList',
// - Posts (replies)
'bb.getPostCount' => 'this:bb_getPostCount',
'bb.getPosts' => 'this:bb_getPosts',
'bb.getPost' => 'this:bb_getPost',
'bb.newPost' => 'this:bb_newPost',
'bb.editPost' => 'this:bb_editPost',
'bb.deletePost' => 'this:bb_deletePost', // Also undeletes
'bb.getPostStatusList' => 'this:bb_getPostStatusList',
// - Topic Tags
'bb.getHotTopicTags' => 'this:bb_getHotTopicTags',
'bb.getTopicTagCount' => 'this:bb_getTopicTagCount',
'bb.getTopicTags' => 'this:bb_getTopicTags',
'bb.getTopicTag' => 'this:bb_getTopicTag',
'bb.addTopicTags' => 'this:bb_addTopicTags',
'bb.removeTopicTags' => 'this:bb_removeTopicTags',
'bb.renameTopicTag' => 'this:bb_renameTopicTag',
'bb.mergeTopicTags' => 'this:bb_mergeTopicTags',
'bb.destroyTopicTag' => 'this:bb_destroyTopicTag',
// - Options
'bb.getOptions' => 'this:bb_getOptions',
'bb.setOptions' => 'this:bb_setOptions'
);
}
// Pingback
if ( bb_get_option( 'enable_pingback' ) ) {
$this->methods = array_merge( (array)$this->methods, array(
'pingback.ping' => 'this:pingback_ping',
'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks'
) );
}
// Tells read-only methods whether they require authentication or not
$this->auth_readonly = apply_filters( 'bb_xmlrpc_auth_readonly', $this->auth_readonly );
// Whether or not to allow user switching
$this->allow_user_switching = bb_get_option( 'bb_xmlrpc_allow_user_switching' );
$this->initialise_site_option_info();
$this->methods = apply_filters( 'bb_xmlrpc_methods', $this->methods );
$this->IXR_Server( $this->methods );
}
function BB_XMLRPC_Server()
{
$this->__construct();
}
/**
* Utility methods
*/
/**
* Checks the user credentials supplied in the request to make sure they are valid
*
* @since 1.0
* @return integer|boolean The user id if the user is valid, otherwise false
* @param string $user_login The users login
* @param string $user_pass The users password in plain text
* @param string $capability The capability to check (optional)
* @param string $message The message to pass back in the error if the capability check fails (optional)
*/
function authenticate( $user_login, $user_pass, $capability = 'read', $message = false )
{
if ( is_array( $user_login ) ) {
$auth_user_login = (string) $user_login[0];
$switch_user_login = (string) $user_login[1];
} else {
$auth_user_login = (string) $user_login;
$switch_user_login = false;
}
// Check the login
$user = bb_check_login( $auth_user_login, $user_pass );
if ( !$user || is_wp_error( $user ) ) {
$this->error = new IXR_Error( 403, __( 'Authentication failed.' ) );
return false;
}
// Set the current user
$user = bb_set_current_user( $user->ID );
// Make sure they are allowed to do this
if ( !bb_current_user_can( $capability ) ) {
if ( !$message ) {
$message = __( 'You do not have permission to read this.' );
}
$this->error = new IXR_Error( 403, $message );
return false;
}
// Switch the user if requested and allowed
if ( $switch_user_login && $this->allow_user_switching && bb_current_user_can( 'edit_users' ) ) {
$user = $this->switch_user( $switch_user_login, $capability, $message );
}
return $user;
}
/**
* Switches the currently active user for incognito actions
*
* @since 1.0
* @return integer|boolean The user id if the user is valid, otherwise false
* @param string $user_login The users login
* @param string $capability The capability to check (optional)
* @param string $message The message to pass back in the error if the capability check fails (optional)
*/
function switch_user( $user_login, $capability = 'read', $message = false )
{
// Just get the user, authentication has already been established by the
$user = bb_get_user( $user_login, array( 'by' => 'login' ) );
if ( !$user || is_wp_error( $user ) ) {
$this->error = new IXR_Error( 400, __( 'User switching failed, the requested user does not exist.' ) );
return false;
}
// Set the current user
$user = bb_set_current_user( $user->ID );
// Make sure they are allowed to do this
if ( !bb_current_user_can( $capability ) ) {
if ( !$message ) {
$message = __( 'You do not have permission to read this.' );
}
$this->error = new IXR_Error( 403, $message );
return false;
}
return $user;
}
/**
* Sanitises data from XML-RPC request parameters
*
* @since 1.0
* @return mixed The sanitised variable, should come back with the same type
* @param $array mixed The variable to be sanitised
* @uses $bbdb BackPress database class instance
*/
function escape( &$array )
{
global $bbdb;
if ( !is_array( $array ) ) {
// Escape it
$array = $bbdb->escape( $array );
} elseif ( count( $array ) ) {
foreach ( (array) $array as $k => $v ) {
if ( is_array( $v ) ) {
// Recursively sanitize arrays
$this->escape( $array[$k] );
} elseif ( is_object( $v ) ) {
// Don't sanitise objects - shouldn't happen anyway
} else {
// Escape it
$array[$k] = $bbdb->escape( $v );
}
}
}
return $array;
}
/**
* Prepares forum data for return in an XML-RPC object
*
* @since 1.0
* @return array The prepared forum data
* @param array|object The unprepared forum data
**/
function prepare_forum( $forum )
{
// Cast to an array
$_forum = (array) $forum;
// Set the URI
$_forum['forum_uri'] = get_forum_link( $_forum['forum_id'] );
// Give this a definite value
if ( !isset( $_forum['forum_is_category'] ) ) {
$_forum['forum_is_category'] = 0;
}
// Allow plugins to modify the data
return apply_filters( 'bb_xmlrpc_prepare_forum', $_forum, (array) $forum );
}
/**
* Prepares topic data for return in an XML-RPC object
*
* @since 1.0
* @return array The prepared topic data
* @param array|object The unprepared topic data
**/
function prepare_topic( $topic )
{
// Cast to an array
$_topic = (array) $topic;
// Set the URI
$_topic['topic_uri'] = get_topic_link( $_topic['topic_id'] );
// Set readable times
$_topic['topic_start_time_since'] = bb_since( $_topic['topic_start_time'] );
$_topic['topic_time_since'] = bb_since( $_topic['topic_time'] );
// Set the display names
$_topic['topic_poster_display_name'] = get_user_display_name( $_topic['topic_poster'] );
$_topic['topic_last_poster_display_name'] = get_user_display_name( $_topic['topic_last_poster'] );
// Remove some sensitive user ids
unset(
$_topic['topic_poster'],
$_topic['topic_last_poster']
);
// Allow plugins to modify the data
return apply_filters( 'bb_xmlrpc_prepare_topic', $_topic, (array) $topic );
}
/**
* Prepares post data for return in an XML-RPC object
*
* @since 1.0
* @return array The prepared post data
* @param array|object The unprepared post data
**/
function prepare_post( $post )
{
// Cast to an array
$_post = (array) $post;
// Set the URI
$_post['post_uri'] = get_post_link( $_post['post_id'] );
// Set readable times
$_post['post_time_since'] = bb_since( $_post['post_time'] );
// Set the display names
$_post['poster_display_name'] = get_user_display_name( $_post['poster_id'] );
// Remove some sensitive data
unset(
$_post['poster_id'],
$_post['poster_ip'],
$_post['pingback_queued']
);
// Allow plugins to modify the data
return apply_filters( 'bb_xmlrpc_prepare_post', $_post, (array) $post );
}
/**
* Prepares topic tag data for return in an XML-RPC object
*
* @since 1.0
* @return array The prepared topic tag data
* @param array|object The unprepared topic tag data
**/
function prepare_topic_tag( $tag )
{
// Cast to an array
$_tag = (array) $tag;
// Set the URI
$_tag['topic_tag_uri'] = bb_get_tag_link( $tag );
// Consistent nomenclature
$_tag['topic_tag_name'] = (string) $_tag['name'];
$_tag['topic_tag_slug'] = (string) $_tag['slug'];
$_tag['topic_tag_count'] = (int) $_tag['count'];
// Remove some sensitive data
unset(
$_tag['object_id'],
$_tag['name'],
$_tag['slug'],
$_tag['count'],
$_tag['term_id'],
$_tag['term_group'],
$_tag['term_taxonomy_id'],
$_tag['taxonomy'],
$_tag['description'],
$_tag['parent'],
$_tag['count'],
$_tag['user_id'],
$_tag['tag_id'],
$_tag['tag'],
$_tag['raw_tag'],
$_tag['tag_count']
);
// Allow plugins to modify the data
return apply_filters( 'bb_xmlrpc_prepare_topic_tag', $_tag, (array) $tag );
}
/**
* bbPress publishing API - Demo XML-RPC methods
*/
/**
* Hello world demo function for XML-RPC
*
* @since 1.0
* @return string The phrase 'Hello!'
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
*
* XML-RPC request to get a greeting
*
* demo.sayHello
*
* joeblow
* 123password
*
*
*/
function sayHello( $args )
{
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly && !$this->authenticate( $username, $password ) ) {
return $this->error;
}
return 'Hello!';
}
/**
* Adds two numbers together as a demo of XML-RPC
*
* @since 1.0
* @return integer The sum of the two supplied numbers
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer $args[2] The first number to be added
* @param integer $args[3] The second number to be added
*
* XML-RPC request to get the sum of two numbers
*
* demo.addTwoNumbers
*
* joeblow
* 123password
* 5
* 102
*
*
*/
function addTwoNumbers( $args )
{
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly && !$this->authenticate( $username, $password ) ) {
return $this->error;
}
$number1 = (int) $args[2];
$number2 = (int) $args[3];
return ( $number1 + $number2 );
}
/**
* bbPress publishing API - Forum XML-RPC methods
*/
/**
* Returns a numerical count of forums
*
* @since 1.0
* @return integer|object The number of forums when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The parent forum's id or slug (optional)
* @param integer $args[3] The depth of child forums to retrieve (optional)
*
* XML-RPC request to get a count of all forums in the bbPress instance
*
* bb.getForumCount
*
* joeblow
* 123password
*
*
*
* XML-RPC request to get a count of all child forums in the forum with id number 34
*
* bb.getForumCount
*
* joeblow
* 123password
* 34
*
*
*
* XML-RPC request to get a count of all child forums in the forum with slug "first-forum"
*
* bb.getForumCount
*
* joeblow
* 123password
* first-forum
*
*
*
* XML-RPC request to get a count of all child forums in the forum with id number 34 no more than 2 forums deep in the hierarchy
*
* bb.getForumCount
*
* joeblow
* 123password
* 34
* 2
*
*
*/
function bb_getForumCount( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getForumCount' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getForumCount' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Setup an array to store arguments to pass to bb_get_forums() function
$get_forums_args = array(
'child_of' => 0,
'hierarchical' => 0,
'depth' => 0
);
// Can be numeric id or slug
$forum_id = isset( $args[2] ) ? $args[2] : false;
if ( $forum_id ) {
// Check for bad data
if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) );
return $this->error;
}
// Check the requested forum exists
if ( !$forum = bb_get_forum( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'The forum does not exist.' ) );
return $this->error;
}
// Add the specific forum to the arguments
$get_forums_args['child_of'] = (int) $forum->forum_id;
}
// Can only be an integer
$depth = (int) $args[3];
if ( $depth > 0 ) {
// Add the depth to traverse to the arguments
$get_forums_args['depth'] = $depth;
// Only make it hierarchical if the depth > 1
if ( $depth > 1 ) {
$get_forums_args['hierarchical'] = 1;
}
}
// Get the forums. Return 0 when no forums exist
if ( !$forums = bb_get_forums( $get_forums_args ) ) {
$count = 0;
} else {
$count = count( $forums );
}
do_action( 'bb_xmlrpc_call_return', 'bb.getForumCount' );
// Return a count of the forums
return $count;
}
/**
* Returns details of multiple forums
*
* @since 1.0
* @return array|object An array containing details of all returned forums when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The parent forum's id or slug (optional)
* @param integer $args[3] The depth of child forums to retrieve (optional)
*
* XML-RPC request to get all forums in the bbPress instance
*
* bb.getForums
*
* joeblow
* 123password
*
*
*
* XML-RPC request to get all child forums in the forum with id number 34
*
* bb.getForums
*
* joeblow
* 123password
* 34
*
*
*
* XML-RPC request to get all child forums in the forum with slug "first-forum"
*
* bb.getForums
*
* joeblow
* 123password
* first-forum
*
*
*
* XML-RPC request to get all child forums in the forum with id number 34 no more than 2 forums deep in the hierarchy
*
* bb.getForums
*
* joeblow
* 123password
* 34
* 2
*
*
*/
function bb_getForums( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getForums' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getForums' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Setup an array to store arguments to pass to bb_get_forums() function
$get_forums_args = array(
'child_of' => 0,
'hierarchical' => 0,
'depth' => 0
);
// Can be numeric id or slug
$forum_id = isset( $args[2] ) ? $args[2] : false;
if ( $forum_id ) {
// Check for bad data
if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) );
return $this->error;
}
// First check the requested forum exists
if ( !$forum = bb_get_forum( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'The forum does not exist.' ) );
return $this->error;
}
// Add the specific forum to the arguments
$get_forums_args['child_of'] = (int) $forum->forum_id;
}
// Can only be an integer
$depth = (int) $args[3];
if ( $depth > 0 ) {
// Add the depth to traverse to to the arguments
$get_forums_args['depth'] = $depth;
// Only make it hierarchical if the depth > 1
if ( $depth > 1 ) {
$get_forums_args['hierarchical'] = 1;
}
}
// Get the forums. Return an error when no forums exist
if ( !$forums = bb_get_forums( $get_forums_args ) ) {
$this->error = new IXR_Error( 404, __( 'No forums found.' ) );
return $this->error;
}
// Only include "safe" data in the array
$_forums = array();
foreach ( $forums as $forum ) {
$_forums[] = $this->prepare_forum( $forum );
}
do_action( 'bb_xmlrpc_call_return', 'bb.getForums' );
// Return the forums
return $_forums;
}
/**
* Returns details of a forum
*
* @since 1.0
* @return array|object An array containing details of the returned forum when successfully executed or an IXR_Error object on failure
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The forum's id or slug
*
* XML-RPC request to get the forum with id number 34
*
* bb.getForum
*
* joeblow
* 123password
* 34
*
*
*
* XML-RPC request to get the forum with slug "first-forum"
*
* bb.getForum
*
* joeblow
* 123password
* first-forum
*
*
*/
function bb_getForum( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getForum' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getForum' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$forum_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) );
return $this->error;
}
// Check the requested forum exists
if ( !$forum = bb_get_forum( $forum_id ) ) {
$this->error = new IXR_Error( 404, __( 'No forum found.' ) );
return $this->error;
}
// Only include "safe" data in the array
$forum = $this->prepare_forum( $forum );
do_action( 'bb_xmlrpc_call_return', 'bb.getForum' );
// Return the forums
return $forum;
}
/**
* Creates a new forum
*
* @since 1.0
* @return array|object The forum data when successfully created or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param array $args[2] The values for the various settings in the new forum
* @param string $args[2]['name'] The name of the forum
* @param string $args[2]['description'] The description of the forum (optional)
* @param integer|string $args[2]['parent_id'] The unique id of the parent forum for this forum (optional)
* @param integer $args[2]['order'] The position of the forum in the forum list (optional)
* @param integer $args[2]['is_category'] Whether the forum is simply a container category (optional)
*
* XML-RPC request to create a new sub-forum called "A new forum" inside the parent forum with id 2
*
* bb.newForum
*
* joeblow
* 123password
*
*
* name
* A new forum
*
*
* parent_id
* 2
*
*
*
*
*/
function bb_newForum( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.newForum' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'manage_forums', __( 'You do not have permission to manage forums.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.newForum' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Make sure there is something for us to do
if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) {
$this->error = new IXR_Error( 400, __( 'The forum data is invalid.' ) );
return $this->error;
}
$structure = (array) $args[2];
// Minimum requirement is a name for the new forum
if ( !isset( $structure['name'] ) || !$structure['name'] ) {
$this->error = new IXR_Error( 400, __( 'The forum name is invalid.' ) );
return $this->error;
}
// Inject structure into an array suitable for bb_new_forum()
$bb_new_forum_args = array(
'forum_name' => (string) $structure['name'],
'forum_desc' => (string) $structure['description'],
'forum_parent' => (int) $structure['parent_id'],
'forum_order' => (int) $structure['order'],
'forum_is_category' => (int) $structure['is_category']
);
// Remove empty settings so that changes to the defaults in bb_new_forum() are honoured
$bb_new_forum_args = array_filter( $bb_new_forum_args );
// Leave the require until the very end
require_once( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' );
// Create the forum
if ( !$forum_id = (int) bb_new_forum( $bb_new_forum_args ) ) {
$this->error = new IXR_Error( 500, __( 'The forum could not be created.' ) );
return $this->error;
}
// Only include "safe" data in the array
$forum = $this->prepare_forum( bb_get_forum( $forum_id ) );
do_action( 'bb_xmlrpc_call_return', 'bb.newForum' );
return $forum;
}
/**
* Edits an existing forum
*
* @since 1.0
* @return array|object The forum data when successfully edited or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param array $args[2] The values for the various settings in the new forum, at least one must be specified
* @param integer|string $args[2]['forum_id'] The unique id of the forum to be edited
* @param string $args[2]['name'] The name of the forum (optional)
* @param string $args[2]['slug'] The slug for the forum (optional)
* @param string $args[2]['description'] The description of the forum (optional)
* @param integer $args[2]['parent_id'] The unique id of the parent forum for this forum (optional)
* @param integer $args[2]['order'] The position of the forum in the forum list (optional)
* @param integer $args[2]['is_category'] Whether the forum is simply a container category (optional)
*
* XML-RPC request to edit a forum with id 11, changing the description
*
* bb.editForum
*
* joeblow
* 123password
*
*
* forum_id
* 11
*
*
* description
* This is a great forum for all sorts of reasons.
*
*
*
*
*/
function bb_editForum( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.editForum' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'manage_forums', __( 'You do not have permission to manage forums.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.editForum' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Make sure there is something for us to do
if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) {
$this->error = new IXR_Error( 400, __( 'The forum data is invalid.' ) );
return $this->error;
}
$structure = (array) $args[2];
// Can be numeric id or slug
$forum_id = isset( $structure['forum_id'] ) ? $structure['forum_id'] : false;
// Check for bad data
if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) );
return $this->error;
}
// Check the requested forum exists
if ( !$forum = bb_get_forum( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'No forum found.' ) );
return $this->error;
}
// Cast the forum object as an array
$forum = (array) $forum;
// The forum id may have been a slug, so make sure it's an integer here
$forum_id = (int) $forum['forum_id'];
// Remove some unneeded indexes
unset( $forum['topics'] );
unset( $forum['posts'] );
// Add one if it isn't there
if ( !isset( $forum['forum_is_category'] ) ) {
$forum['forum_is_category'] = 0;
}
// Validate the name for the forum
if ( isset( $structure['name'] ) && !$structure['name'] ) {
$this->error = new IXR_Error( 400, __( 'The forum name is invalid.' ) );
return $this->error;
}
// Inject structure into an array suitable for bb_update_forum()
$bb_update_forum_args = array(
'forum_name' => $structure['name']
);
// Slug cannot be blank
if ( isset( $structure['slug'] ) && $structure['slug'] !== '' ) {
$bb_update_forum_args['forum_slug'] = $structure['slug'];
}
// Description can be nothing
if ( isset( $structure['description'] ) ) {
$bb_update_forum_args['forum_desc'] = $structure['description'];
}
// Parent forum ID must be an integer and it can be 0
if ( isset( $structure['parent_id'] ) && is_integer( $structure['parent_id'] ) ) {
$bb_update_forum_args['forum_parent'] = $structure['parent_id'];
}
// Order must be an integer and it can be 0
if ( isset( $structure['order'] ) && is_integer( $structure['order'] ) ) {
$bb_update_forum_args['forum_order'] = $structure['order'];
}
// Category flag must be an integer and it can be 0
if ( isset( $structure['is_category'] ) && is_integer( $structure['is_category'] ) ) {
$bb_update_forum_args['forum_is_category'] = $structure['is_category'];
}
// Merge the changes into the existing data for the forum
$bb_update_forum_args = wp_parse_args( $bb_update_forum_args, $forum );
// Leave the require until the very end
require_once( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' );
// Update the forum
if ( !bb_update_forum( $bb_update_forum_args ) ) {
$this->error = new IXR_Error( 500, __( 'The forum could not be edited.' ) );
return $this->error;
}
// Only include "safe" data in the array
$forum = $this->prepare_forum( bb_get_forum( $forum_id ) );
do_action( 'bb_xmlrpc_call_return', 'bb.editForum' );
return $forum;
}
/**
* Deletes a forum
*
* @since 1.0
* @return integer|object 1 when successfully deleted or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The unique id of the forum to be deleted
*
* XML-RPC request to delete a forum with the slug "naughty-forum"
*
* bb.deleteForum
*
* joeblow
* 123password
* naughty-forum
*
*
*/
function bb_deleteForum( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.deleteForum' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'delete_forums', __( 'You do not have permission to delete forums.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.deleteForum' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$forum_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) );
return $this->error;
}
// Check the requested forum exists
if ( !$forum = bb_get_forum( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'No forum found.' ) );
return $this->error;
}
// Cast the forum object as an array
$forum = (array) $forum;
// The forum id may have been a slug, so make sure it's an integer here
$forum_id = (int) $forum['forum_id'];
// Make sure they are allowed to delete this forum specifically
if ( !bb_current_user_can( 'delete_forum', $forum_id ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to delete this forum.' ) );
return $this->error;
}
// Leave the require until the very end
require_once( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' );
// Delete the forum
if ( !bb_delete_forum( $forum_id ) ) {
$this->error = new IXR_Error( 500, __( 'The forum could not be deleted.' ) );
return $this->error;
}
$result = 1;
do_action( 'bb_xmlrpc_call_return', 'bb.deleteForum' );
return $result;
}
/**
* bbPress publishing API - Topic XML-RPC methods
*/
/**
* Returns a numerical count of topics
*
* @since 1.0
* @return integer|object The number of topics when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The forum id or slug (optional)
*
* XML-RPC request to get a count of all topics in the bbPress instance
*
* bb.getTopicCount
*
* joeblow
* 123password
*
*
*
* XML-RPC request to get a count of all topics in the forum with id number 34
*
* bb.getTopicCount
*
* joeblow
* 123password
* 34
*
*
*
* XML-RPC request to get a count of all topics in the forum with slug "first-forum"
*
* bb.getTopicCount
*
* joeblow
* 123password
* first-forum
*
*
*/
function bb_getTopicCount( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getTopicCount' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopicCount' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
if ( isset( $args[2] ) && $forum_id = $args[2] ) {
// Check for bad data
if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) );
return $this->error;
}
// Check the requested forum exists
if ( !$forum = bb_get_forum( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'The forum does not exist.' ) );
return $this->error;
}
// OK, let's trust the count in the forum table
$count = (int) $forum->topics;
} else {
// Get all forums
$forums = bb_get_forums();
// Return an error when no forums exist
if ( !$forums ) {
$this->error = new IXR_Error( 400, __( 'No forums found.' ) );
return $this->error;
}
// Count the topics
$count = 0;
foreach ( $forums as $forum ) {
$count += (int) $forum->topics;
}
}
do_action( 'bb_xmlrpc_call_return', 'bb.getTopicCount' );
// Return the count of topics
return $count;
}
/**
* Returns details of the latest topics
*
* @since 1.0
* @return array|object The topics when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The forum id or slug (optional)
* @param integer $args[3] The number of topics to return (optional)
* @param integer $args[4] The number of the page to return (optional)
*
* XML-RPC request to get all topics in the bbPress instance
*
* bb.getTopics
*
* joeblow
* 123password
*
*
*
* XML-RPC request to get all topics in the forum with id number 34
*
* bb.getTopics
*
* joeblow
* 123password
* 34
*
*
*
* XML-RPC request to get topics 6 to 10 in the forum with slug "first-forum"
*
* bb.getTopics
*
* joeblow
* 123password
* first-forum
* 5
* 2
*
*
*/
function bb_getTopics( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getTopics' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopics' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Setup an array to store arguments to pass to get_topics() function
$get_topics_args = array(
'forum' => false,
'number' => false,
'page' => false
);
// Can be numeric id or slug
if ( isset( $args[2] ) && $forum_id = $args[2] ) {
// Check for bad data
if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) );
return $this->error;
}
// Check the requested forum exists
if ( !$forum = bb_get_forum( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'The forum does not exist.' ) );
return $this->error;
}
// The forum id may have been a slug, so make sure it's an integer here
$get_topics_args['forum'] = (int) $forum->forum_id;
}
// Can only be an integer
if ( isset( $args[3] ) && $number = (int) $args[3] ) {
$get_topics_args['number'] = $number;
}
// Can only be an integer
if ( isset( $args[4] ) && $page = (int) $args[4] ) {
$get_topics_args['page'] = $page;
}
// Get the topics
if ( !$topics = get_latest_topics( $get_topics_args ) ) {
$this->error = new IXR_Error( 400, __( 'No topics found.' ) );
return $this->error;
}
// Only include "safe" data in the array
$_topics = array();
foreach ( $topics as $topic ) {
$_topics[] = $this->prepare_topic( $topic );
}
do_action( 'bb_xmlrpc_call_return', 'bb.getTopics' );
// Return the topics
return $_topics;
}
/**
* Returns details of a topic
*
* @since 1.0
* @return array|object An array containing details of the returned topic when successfully executed or an IXR_Error object on failure
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The topic's id or slug
*
* XML-RPC request to get the topic with id number 105
*
* bb.getTopic
*
* joeblow
* 123password
* 105
*
*
*
* XML-RPC request to get the topic with slug "cheesy-biscuits"
*
* bb.getTopic
*
* joeblow
* 123password
* cheesy-biscuits
*
*
*/
function bb_getTopic( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getTopic' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopic' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$topic_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// Only include "safe" data in the array
$topic = $this->prepare_topic( $topic );
do_action( 'bb_xmlrpc_call_return', 'bb.getTopic' );
// Return the topic
return $topic;
}
/**
* Creates a new topic
*
* @since 1.0
* @return array|object The topic data when successfully created or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param array $args[2] The values for the various parameters in the new topic
* @param string $args[2]['title'] The title of the topic
* @param string $args[2]['text'] The text of the topic
* @param integer|string $args[2]['forum_id'] The unique id of the forum which will contain this topic, slugs are OK to use too
* @param string|array $args[2]['tags'] A comma delimited string or an array of tags to add to the topic (optional)
*
* XML-RPC request to create a new topic called "Insane monkeys" inside the forum with id 2
*
* bb.newTopic
*
* joeblow
* 123password
*
*
* title
* Insane monkeys
*
*
* text
* I just saw some insane monkeys eating bananas, did anyone else see that?
*
*
* forum_id
* 2
*
*
* tags
* monkeys, bananas
*
*
*
*
*/
function bb_newTopic( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.newTopic' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'write_topics', __( 'You do not have permission to write topics.' ) );
// Additionally they need to be able to write posts
if ( !$this->error && !bb_current_user_can( 'write_posts' ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to write posts.' ) );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.newTopic' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Make sure there is something for us to do
if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) {
$this->error = new IXR_Error( 400, __( 'The topic data is invalid.' ) );
return $this->error;
}
$structure = (array) $args[2];
// Can be numeric id or slug
$forum_id = isset( $structure['forum_id'] ) ? $structure['forum_id'] : false;
// Check for bad data
if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) );
return $this->error;
}
// Check the requested forum exists
if ( !$forum = bb_get_forum( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'No forum found.' ) );
return $this->error;
}
// The forum id may have been a slug, so make sure it's an integer here
$forum_id = (int) $forum->forum_id;
// Make sure they are allowed to write topics to this forum
if ( !bb_current_user_can( 'write_topic', $forum_id ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to write topics to this forum.' ) );
return $this->error;
}
// The topic requires a title
if ( !isset( $structure['title'] ) || !$structure['title'] ) {
$this->error = new IXR_Error( 400, __( 'The topic title is invalid.' ) );
return $this->error;
}
// The topic requires text
if ( !isset( $structure['text'] ) || !$structure['text'] ) {
$this->error = new IXR_Error( 400, __( 'The topic text is invalid.' ) );
return $this->error;
}
// Inject structure into an array suitable for bb_insert_topic()
$bb_insert_topic_args = array(
'topic_title' => (string) $structure['title'],
'forum_id' => $forum_id,
'tags' => (string) trim( $structure['tags'] )
);
// Remove empty settings so that changes to the defaults in bb_insert_topic() are honoured
$bb_insert_topic_args = array_filter( $bb_insert_topic_args );
// Create the topic
if ( !$topic_id = bb_insert_topic( $bb_insert_topic_args ) ) {
$this->error = new IXR_Error( 500, __( 'The topic could not be created.' ) );
return $this->error;
}
// Inject structure into an array suitable for bb_insert_post()
$bb_insert_post_args = array(
'topic_id' => (int) $topic_id,
'post_text' => (string) $structure['text']
);
// Create the post
if ( !$post_id = bb_insert_post( $bb_insert_post_args ) ) {
$this->error = new IXR_Error( 500, __( 'The post could not be created.' ) );
return $this->error;
}
// Only include "safe" data in the array
$topic = $this->prepare_topic( get_topic( $topic_id ) );
do_action( 'bb_xmlrpc_call_return', 'bb.newTopic' );
return $topic;
}
/**
* Edits an existing topic
*
* @since 1.0
* @return array|object The topic data when successfully edited or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param array $args[2] The values for the various parameters in the edited topic
* @param integer|string $args[2]['topic_id'] The topic's id or slug
* @param string $args[2]['title'] The title of the topic
* @param string $args[2]['text'] The text of the topic
*
* XML-RPC request to edit the title of a topic with the slug "insane-monkeys"
*
* bb.editTopic
*
* joeblow
* 123password
*
*
* topic_id
* insane-monkeys
*
*
* title
* Very insane monkeys
*
*
*
*
*/
function bb_editTopic( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.editTopic' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'edit_topics', __( 'You do not have permission to edit topics.' ) );
// Additionally they need to be able to edit posts
if ( !$this->error && !bb_current_user_can( 'edit_posts' ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to edit posts.' ) );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.editTopic' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Make sure there is something for us to do
if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) {
$this->error = new IXR_Error( 400, __( 'The topic data is invalid.' ) );
return $this->error;
}
$structure = (array) $args[2];
// Can be numeric id or slug
$topic_id = isset( $structure['topic_id'] ) ? $structure['topic_id'] : false;
// Check for bad data
if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// The topic id may have been a slug, so make sure it's an integer here
$topic_id = (int) $topic->topic_id;
// Make sure they are allowed to edit this topic
if ( !bb_current_user_can( 'edit_topic', $topic_id ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to edit this topic.' ) );
return $this->error;
}
// Get the first post in the topic (that's where the content is)
if ( !$post = bb_get_first_post( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No posts found.' ) );
return $this->error;
}
$post_id = (int) $post->post_id;
// Make sure they are allowed to edit this post
if ( !bb_current_user_can( 'edit_post', $post_id ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to edit this post.' ) );
return $this->error;
}
// The topic requires a title
if ( isset( $structure['title'] ) && !$structure['title'] ) {
$this->error = new IXR_Error( 400, __( 'The topic title is invalid.' ) );
return $this->error;
}
// The topic requires text
if ( isset( $structure['text'] ) && !$structure['text'] ) {
$this->error = new IXR_Error( 400, __( 'The topic text is invalid.' ) );
return $this->error;
}
if ( $structure['title'] ) {
if ( !bb_insert_topic( array( 'topic_title' => (string) $structure['title'], 'topic_id' => $topic_id ) ) ) {
$this->error = new IXR_Error( 500, __( 'The topic could not be edited.' ) );
return $this->error;
}
}
if ( $structure['text'] ) {
if ( !bb_insert_post( array( 'post_text' => (string) $structure['text'], 'post_id' => $post_id, 'topic_id'=> $topic_id ) ) ) {
$this->error = new IXR_Error( 500, __( 'The post could not be edited.' ) );
return $this->error;
}
}
// Only include "safe" data in the array
$topic = $this->prepare_topic( get_topic( $topic_id ) );
do_action( 'bb_xmlrpc_call_return', 'bb.editTopic' );
return $topic;
}
/**
* Deletes a topic
*
* @since 1.0
* @return integer|object 0 if already changed, 1 when successfully changed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The unique id of the topic to be deleted
* @param integer $args[3] 1 deletes the topic, 0 undeletes the topic
*
* XML-RPC request to delete a topic with id of 34
*
* bb.deleteTopic
*
* joeblow
* 123password
* 34
*
*
*/
function bb_deleteTopic( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.deleteTopic' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'delete_topics', __( 'You do not have permission to delete topics.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.deleteTopic' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$topic_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// The topic id may have been a slug, so make sure it's an integer here
$topic_id = (int) $topic->topic_id;
$delete = isset( $args[3] ) ? (int) $args[3] : 1;
// Don't do anything if already set that way
if ( $delete === (int) $topic->topic_status ) {
return 0;
}
// Make sure they are allowed to delete this topic
if ( !bb_current_user_can( 'delete_topic', $topic_id ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to delete this topic.' ) );
return $this->error;
}
// Delete the topic
if ( !bb_delete_topic( $topic_id, $delete ) ) {
$this->error = new IXR_Error( 500, __( 'The topic could not be deleted.' ) );
return $this->error;
}
$result = 1;
do_action( 'bb_xmlrpc_call_return', 'bb.deleteTopic' );
return $result;
}
/**
* Moves a topic to a different forum
*
* @since 1.0
* @return integer|object the forum id where the topic lives after the method is called or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The unique id of the topic to be moved
* @param integer|string $args[3] The unique id of the forum to be moved to
*
* XML-RPC request to move the topic with id of 34 to forum with slug of "better-forum"
*
* bb.moveTopic
*
* joeblow
* 123password
* 34
* better-forum
*
*
*/
function bb_moveTopic( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.moveTopic' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'move_topics', __( 'You do not have permission to move topics.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.moveTopic' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$topic_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// The topic id may have been a slug, so make sure it's an integer here
$topic_id = (int) $topic->topic_id;
// Can be numeric id or slug
$forum_id = isset( $args[3] ) ? $args[3] : false;
// Check for bad data
if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$forum = bb_get_forum( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'No forum found.' ) );
return $this->error;
}
// The forum id may have been a slug, so make sure it's an integer here
$forum_id = (int) $forum->forum_id;
// Only move it if it isn't already there
if ( $forum_id !== (int) $topic->forum_id ) {
// Make sure they are allowed to move this topic specifically to this forum
if ( !bb_current_user_can( 'move_topic', $topic_id, $forum_id ) ) {
$this->error = new IXR_Error( 403, __( 'You are not allowed to move this topic to this forum.' ) );
return $this->error;
}
// Move the topic
if ( !bb_move_topic( $topic_id, $forum_id ) ) {
$this->error = new IXR_Error( 500, __( 'The topic could not be moved.' ) );
return $this->error;
}
}
do_action( 'bb_xmlrpc_call_return', 'bb.moveTopic' );
return $forum_id;
}
/**
* Sticks a topic to the top of a forum or the front page
*
* @since 1.0
* @return integer|object 0 if it is already stuck to the desired location, 1 when successfully stuck or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The unique id of the topic to be stuck
* @param integer $args[3] 0 unsticks, 1 sticks, 2 sticks to front (optional)
*
* XML-RPC request to stick the topic with id of 34 to the front page
*
* bb.stickTopic
*
* joeblow
* 123password
* 34
* 1
*
*
*/
function bb_stickTopic( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.stickTopic' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'stick_topics', __( 'You do not have permission to stick topics.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.stickTopic' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$topic_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// The topic id may have been a slug, so make sure it's an integer here
$topic_id = (int) $topic->topic_id;
// Make sure they are allowed to stick this topic
if ( !bb_current_user_can( 'stick_topic', $topic_id ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to stick this topic.' ) );
return $this->error;
}
// Stick to where?
$where = isset( $args[3] ) ? (int) $args[3] : 1;
// Forget it if it's already there
if ( $where === (int) $topic->topic_sticky ) {
return 0;
}
// Stick the topic
if ( !bb_stick_topic( $topic_id, $where ) ) {
$this->error = new IXR_Error( 500, __( 'The topic could not be stuck.' ) );
return $this->error;
}
$result = 1;
do_action( 'bb_xmlrpc_call_return', 'bb.stickTopic' );
return $result;
}
/**
* Closes a topic
*
* @since 1.0
* @return integer|object 0 when already changed, 1 when successfully changed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The unique id of the topic to be closed
* @param integer $args[2] 0 closes, 1 opens (optional)
*
* XML-RPC request to close the topic with slug of "really-old-topic"
*
* bb.closeTopic
*
* joeblow
* 123password
* really-old-topic
*
*
*
* XML-RPC request to open the topic with slug of "really-old-topic"
*
* bb.closeTopic
*
* joeblow
* 123password
* really-old-topic
* 1
*
*
*/
function bb_closeTopic( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.closeTopic' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'close_topics', __( 'You do not have permission to close topics.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.closeTopic' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$topic_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// The topic id may have been a slug, so make sure it's an integer here
$topic_id = (int) $topic->topic_id;
// Make sure they are allowed to close this topic
if ( !bb_current_user_can( 'close_topic', $topic_id ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to close this topic.' ) );
return $this->error;
}
// Open or close?
$close = isset( $args[3] ) ? (int) $args[3] : 0;
// Forget it if it's already matching
if ( $close === (int) $topic->topic_open ) {
return 0;
}
// Close the topic
if ( !$close && !bb_close_topic( $topic_id ) ) {
$this->error = new IXR_Error( 500, __( 'The topic could not be closed.' ) );
return $this->error;
}
// Open the topic
if ( $close && !bb_open_topic( $topic_id ) ) {
$this->error = new IXR_Error( 500, __( 'The topic could not be opened.' ) );
return $this->error;
}
$result = 1;
do_action( 'bb_xmlrpc_call_return', 'bb.closeTopic' );
return $result;
}
/**
* bbPress publishing API - Post XML-RPC methods
*/
/**
* Returns a numerical count of posts
*
* @since 1.0
* @return integer|object The number of topics when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The topic id or slug
*
* XML-RPC request to get a count of all posts in the topic with slug "countable-topic"
*
* bb.getPostCount
*
* joeblow
* 123password
* countable-topic
*
*
*/
function bb_getPostCount( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getPostCount' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getPostCount' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$topic_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// OK, let's trust the count in the topic table
$count = $topic->topic_posts;
do_action( 'bb_xmlrpc_call_return', 'bb.getPostCount' );
// Return the count of posts
return $count;
}
/**
* Returns details of the posts in a given topic
*
* @since 1.0
* @return array|object The posts when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The topic id or slug
* @param integer $args[3] The number of posts to return (optional)
* @param integer $args[4] The number of the page to return (optional)
*
* XML-RPC request to get all posts in the topic with id number 53
*
* bb.getPosts
*
* joeblow
* 123password
* 53
*
*
*
* XML-RPC request to get the latest 5 posts in the topic with id number 341
*
* bb.getPosts
*
* joeblow
* 123password
* 341
* 5
*
*
*
* XML-RPC request to get posts 11 to 20 in the topic with slug "long-topic"
*
* bb.getPosts
*
* joeblow
* 123password
* long-topic
* 10
* 2
*
*
*/
function bb_getPosts( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getPosts' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getPosts' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$topic_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// The topic id may have been a slug, so make sure it's an integer here
$topic_id = (int) $topic->topic_id;
// Setup an array to store arguments to pass to get_thread() function
$get_thread_args = array();
// Can only be an integer
if ( isset( $args[3] ) && $per_page = (int) $args[3] ) {
$get_thread_args['per_page'] = $per_page;
}
// Can only be an integer
if ( isset( $args[4] ) && $page = (int) $args[4] ) {
$get_thread_args['page'] = $page;
}
// Get the posts
if ( !$posts = get_thread( $topic_id, $get_thread_args ) ) {
$this->error = new IXR_Error( 500, __( 'No posts found.' ) );
return $this->error;
}
// Only include "safe" data in the array
$_posts = array();
foreach ( $posts as $post ) {
$_posts[] = $this->prepare_post( $post );
}
do_action( 'bb_xmlrpc_call_return', 'bb.getPosts' );
// Return the posts
return $_posts;
}
/**
* Returns details of a post
*
* @since 1.0
* @return array|object An array containing details of the returned post when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer $args[2] The post's id
*
* XML-RPC request to get the post with id number 32
*
* bb.getPost
*
* joeblow
* 123password
* 32
*
*
*/
function bb_getPost( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getPost' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getPost' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$post_id = isset( $args[2] ) ? (int) $args[2] : false;
// Check for bad data
if ( !$post_id ) {
$this->error = new IXR_Error( 400, __( 'The post id is invalid.' ) );
return $this->error;
}
// Check the requested post exists
if ( !$post = bb_get_post( $post_id ) ) {
$this->error = new IXR_Error( 400, __( 'No post found.' ) );
return $this->error;
}
// Only include "safe" data in the array
$_post = $this->prepare_post( $post );
do_action( 'bb_xmlrpc_call_return', 'bb.getPost' );
// Return the post
return $_post;
}
/**
* Creates a new post in a given topic
*
* @since 1.0
* @return array|object The post data when successfully created or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param array $args[2] The values for the various parameters in the new topic
* @param string $args[2]['text'] The text of the topic
* @param integer|string $args[2]['topic_id'] The unique id of the topic which will contain this topic, slugs are OK to use too
*
* XML-RPC request to create a new post in the topic with slug "totally-worth-it"
*
* bb.newPost
*
* joeblow
* 123password
*
*
* text
* I agree, it is totally worth it.
*
*
* topic_id
* totally-worth-it
*
*
*
*
*/
function bb_newPost( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.newPost' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'write_posts', __( 'You do not have permission to write posts.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.newPost' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Make sure there is something for us to do
if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) {
$this->error = new IXR_Error( 400, __( 'The post data is invalid.' ) );
return $this->error;
}
$structure = (array) $args[2];
// Can be numeric id or slug
$topic_id = isset( $structure['topic_id'] ) ? $structure['topic_id'] : false;
// Check for bad data
if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// The topic id may have been a slug, so make sure it's an integer here
$topic_id = (int) $topic->topic_id;
// Make sure they are allowed to write posts to this topic
if ( !bb_current_user_can( 'write_post', $topic_id ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to write posts to this topic.' ) );
return $this->error;
}
// The post requires text
if ( !isset( $structure['text'] ) || !$structure['text'] ) {
$this->error = new IXR_Error( 400, __( 'The post text is invalid.' ) );
return $this->error;
}
// Inject structure into an array suitable for bb_insert_post()
$bb_insert_post_args = array(
'topic_id' => $topic_id,
'post_text' => (string) $structure['text']
);
// Create the post
if ( !$post_id = bb_insert_post( $bb_insert_post_args ) ) {
$this->error = new IXR_Error( 500, __( 'The post could not be created.' ) );
return $this->error;
}
// Only include "safe" data in the array
$post = $this->prepare_forum( bb_get_post( $post_id ) );
do_action( 'bb_xmlrpc_call_return', 'bb.newPost' );
return $post;
}
/**
* Edits an existing post
*
* @since 1.0
* @return array|object The post data when successfully edited or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param array $args[2] The values for the various parameters in the new topic
* @param integer $args[2]['post_id'] The unique id of the post
* @param string $args[2]['text'] The text of the topic
*
* XML-RPC request to edit the text of the post with an id of 452
*
* bb.editPost
*
* joeblow
* 123password
*
*
* post_id
* 452
*
*
* text
* For now I will withhold my opinion.
*
*
*
*
*/
function bb_editPost( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.editPost' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'edit_posts', __( 'You do not have permission to edit posts.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.editPost' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Make sure there is something for us to do
if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) {
$this->error = new IXR_Error( 400, __( 'The post data is invalid.' ) );
return $this->error;
}
$structure = (array) $args[2];
// Can be numeric id or slug
$post_id = isset( $structure['post_id'] ) ? (int) $structure['post_id'] : false;
// Check for bad data
if ( !$post_id ) {
$this->error = new IXR_Error( 400, __( 'The post id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$post = bb_get_post( $post_id ) ) {
$this->error = new IXR_Error( 400, __( 'No post found.' ) );
return $this->error;
}
// Re-assign the post id
$post_id = (int) $post->post_id;
// Make sure they are allowed to edit this post
if ( !bb_current_user_can( 'edit_post', $post_id ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to edit this post.' ) );
return $this->error;
}
// The post requires text
if ( !isset( $structure['text'] ) || !$structure['text'] ) {
$this->error = new IXR_Error( 400, __( 'The post text is invalid.' ) );
return $this->error;
}
// Inject structure into an array suitable for bb_insert_post()
$bb_insert_post_args = array(
'post_id' => $post_id,
'post_text' => (string) $structure['text']
);
// Create the post
if ( !$post_id = bb_insert_post( $bb_insert_post_args ) ) {
$this->error = new IXR_Error( 500, __( 'The post could not be edited.' ) );
return $this->error;
}
// Only include "safe" data in the array
$post = $this->prepare_forum( bb_get_post( $post_id ) );
do_action( 'bb_xmlrpc_call_return', 'bb.editPost' );
return $post;
}
/**
* Deletes an existing post
*
* @since 1.0
* @return integer|object 1 when successfully deleted, 0 when already deleted or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param array $args[2] The unique id of the post
* @param array $args[3] 1 deletes the post, 0 undeletes the post (optional)
*
* XML-RPC request to delete the post with an id of 4301
*
* bb.editPost
*
* joeblow
* 123password
* 4301
*
*
*/
function bb_deletePost( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.deletePost' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'delete_posts', __( 'You do not have permission to delete posts.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.deletePost' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$post_id = isset( $args[2] ) ? (int) $args[2] : false;
// Check for bad data
if ( !$post_id ) {
$this->error = new IXR_Error( 400, __( 'The post id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$post = bb_get_post( $post_id ) ) {
$this->error = new IXR_Error( 400, __( 'No post found.' ) );
return $this->error;
}
// Re-assign the post id
$post_id = (int) $post->post_id;
// Make sure they are allowed to delete this post
if ( !bb_current_user_can( 'delete_post', $post_id ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to delete this post.' ) );
return $this->error;
}
$status = isset( $args[3] ) ? (int) $args[3] : 1;
if ( $status === (int) $post->post_status ) {
return 0;
}
// Delete the post
if ( !$post_id = bb_delete_post( $post_id, $status ) ) {
$this->error = new IXR_Error( 500, __( 'The post could not be edited.' ) );
return $this->error;
}
$result = 1;
do_action( 'bb_xmlrpc_call_return', 'bb.deletePost' );
return $result;
}
/**
* bbPress publishing API - Topic Tag XML-RPC methods
*/
/**
* Returns the hot tags in order of hotness in a given forum or all hot tags
*
* @since 1.0
* @return integer|object The tag data when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer $args[2] The number of tags to return (optional)
* @param integer|string $args[3] The forum id or slug (optional)
*
* XML-RPC request to get the 20 hottest tags in the forum with slug "hawtness"
*
* bb.getTopicTags
*
* joeblow
* 123password
* 20
* hawtness
*
*
*/
function bb_getHotTopicTags( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getHotTopicTags' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getHotTopicTags' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Must be a number
$per_page = isset( $args[2] ) ? (integer) $args[2] : false;
// Can be numeric id or slug
$forum_id = isset( $args[3] ) ? $args[3] : false;
if ( $forum_id ) {
// Check for bad data
if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) {
$this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) );
return $this->error;
}
// Check the requested forum exists
if ( !$forum = bb_get_forum( $forum_id ) ) {
$this->error = new IXR_Error( 404, __( 'No forum found.' ) );
return $this->error;
}
global $bbdb;
$topic_ids = $bbdb->get_col( $bbdb->prepare( "SELECT topic_id FROM `" . $bbdb->topics . "` WHERE `topic_status` = 0 AND `topic_open` = 1 AND `tag_count` > 0 AND `forum_id` = %s;", $forum_id ) );
if ( !count( $topic_ids ) ) {
$this->error = new IXR_Error( 400, __( 'No topics found.' ) );
return $this->error;
}
global $wp_taxonomy_object;
$tags = $wp_taxonomy_object->get_object_terms( $topic_ids, 'bb_topic_tag', array( 'fields' => 'all_with_object_id', 'orderby' => 'count', 'order' => 'DESC' ) );
if ( !$tags || is_wp_error( $tags ) ) {
$this->error = new IXR_Error( 500, __( 'Could not retrieve hot topic tags.' ) );
return $this->error;
}
if ( !count( $tags ) ) {
$this->error = new IXR_Error( 500, __( 'No hot topic tags found.' ) );
return $this->error;
}
global $bb_log;
$bb_log->debug($tags);
for ( $i = 0; isset( $tags[$i] ); $i++ ) {
_bb_make_tag_compat( $tags[$i] );
}
$bb_log->debug($tags);
// Only include "safe" data in the array
$_tags = array();
foreach ( $tags as $tag ) {
$_tag = $this->prepare_topic_tag( $tag );
if ( !in_array( $_tag, $_tags ) ) {
$_tags[] = $_tag;
}
}
if ( $per_page ) {
$_tags = array_slice( $_tags, 0, $per_page );
}
} else {
if ( !$tags = bb_get_top_tags( array( 'get' => 'all', 'number' => $per_page ) ) ) {
$this->error = new IXR_Error( 500, __( 'No hot topic tags found.' ) );
return $this->error;
}
// Only include "safe" data in the array
$_tags = array();
foreach ( $tags as $tag ) {
$_tags[] = $this->prepare_topic_tag( $tag );
}
}
do_action( 'bb_xmlrpc_call', 'bb.getHotTopicTags' );
return $_tags;
}
/**
* Returns a numerical count of tags in a given topic or all tags
*
* @since 1.0
* @return integer|object The number of topics when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The topic id or slug (optional)
*
* XML-RPC request to get a count of all tags in the topic with slug "woot-frist-topic"
*
* bb.getTopicTagCount
*
* joeblow
* 123password
* woot-frist-topic
*
*
*/
function bb_getTopicTagCount( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getTopicTagCount' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopicTagCount' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$topic_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( $topic_id ) {
if ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// The topic id may have been a slug, so make sure it's an integer here
$topic_id = (int) $topic->topic_id;
// Now get the tags
if ( !$tags = bb_get_topic_tags( $topic_id ) ) {
$tags = array();
}
// Count the tags
$count = count( $tags );
} else {
global $wp_taxonomy_object;
$count = $wp_taxonomy_object->count_terms( 'bb_topic_tag' );
if ( is_wp_error( $count ) ) {
$this->error = new IXR_Error( 500, __( 'Could not get a count of all topic tags.' ) );
return $this->error;
}
}
do_action( 'bb_xmlrpc_call_return', 'bb.getTopicTagCount' );
// Return the count of tags
return $count;
}
/**
* Returns the tags in a given topic or all tags
*
* @since 1.0
* @return integer|object The tag data when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param integer|string $args[2] The topic id or slug (optional)
*
* XML-RPC request to get all tags in the topic with slug "woot-frist-topic"
*
* bb.getTopicTags
*
* joeblow
* 123password
* woot-frist-topic
*
*
*/
function bb_getTopicTags( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getTopicTags' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopicTags' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$topic_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( $topic_id ) {
if ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// The topic id may have been a slug, so make sure it's an integer here
$topic_id = (int) $topic->topic_id;
// Now get the tags
if ( !$tags = bb_get_topic_tags( $topic_id ) ) {
$this->error = new IXR_Error( 500, __( 'No topic tags found.' ) );
return $this->error;
}
} else {
global $wp_taxonomy_object;
$tags = $wp_taxonomy_object->get_terms( 'bb_topic_tag', array( 'get' => 'all' ) );
if ( is_wp_error( $tags ) ) {
$this->error = new IXR_Error( 500, __( 'Could not retrieve all topic tags.' ) );
return $this->error;
}
for ( $i = 0; isset( $tags[$i] ); $i++ ) {
_bb_make_tag_compat( $tags[$i] );
}
}
// Only include "safe" data in the array
$_tags = array();
foreach ( $tags as $tag ) {
$_tags[] = $this->prepare_topic_tag( $tag );
}
do_action( 'bb_xmlrpc_call_return', 'bb.getTopicTags' );
// Return the tags
return $_tags;
}
/**
* Returns the topics which are tagged with the given tag
*
* @since 1.0
* @return integer|object The topic data when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param string $args[2] The tag name or slug
* @param integer $args[3] The number of topics to return (optional)
* @param integer $args[4] The number of the page to return (optional)
*
* XML-RPC request to get the latest 10 topics tagged with the tag "apples"
*
* bb.getTopicTag
*
* joeblow
* 123password
* apples
* 10
*
*
*/
function bb_getTopicTag( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getTopicTag' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopicTag' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can only be a string
$tag_id = isset( $args[2] ) ? (string) $args[2] : false;
// Check for bad data
if ( !$tag_id ) {
$this->error = new IXR_Error( 400, __( 'The tag id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$tag = bb_get_tag( $tag_id ) ) {
$this->error = new IXR_Error( 400, __( 'No tag found.' ) );
return $this->error;
}
// Get the numeric tag id
$tag_id = (int) $tag->tag_id;
// Setup an array to store arguments to pass to get_tagged_topics() function
$get_topics_args = array(
'tag_id' => false,
'number' => false,
'page' => false
);
// Can only be an integer
if ( isset( $args[3] ) && $number = (int) $args[3] ) {
$get_topics_args['number'] = $number;
}
// Can only be an integer
if ( isset( $args[4] ) && $page = (int) $args[4] ) {
$get_topics_args['page'] = $page;
}
// Now get the topics
if ( !$topics = get_tagged_topics( $tag_id ) ) {
$this->error = new IXR_Error( 500, __( 'No topics found.' ) );
return $this->error;
}
// Only include "safe" data in the array
$_topics = array();
foreach ( $topics as $topic ) {
$_topics[] = $this->prepare_topic( $topic );
}
do_action( 'bb_xmlrpc_call_return', 'bb.getTopicTag' );
// Return the topics
return $_topics;
}
/**
* Adds the specified tags to the specified topic
*
* @since 1.0
* @return array|object The tags which were added when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param string|integer $args[2] The topic id or slug
* @param string|array $args[3] The tags to add to the topic
*
* XML-RPC request to add the tag "banana" to the topic with id 219
*
* bb.addTopicTags
*
* joeblow
* 123password
* 219
* banana
*
*
*
* XML-RPC request to add the tags "banana" and "man" to the topic with id 219
*
* bb.addTopicTags
*
* joeblow
* 123password
* 219
* banana, man
*
*
*
* XML-RPC request to add the tags "banana" and "man" to the topic with id 219 using an array
*
* bb.addTopicTags
*
* joeblow
* 123password
* 219
*
* banana
* man
*
*
*
*/
function bb_addTopicTags( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.addTopicTags' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'edit_tags', __( 'You do not have permission to edit tags.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.addTopicTags' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$topic_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// The topic id may have been a slug, so make sure it's an integer here
$topic_id = (int) $topic->topic_id;
// Make sure they are allowed to add tags to this topic
if ( !bb_current_user_can( 'add_tag_to', $topic_id ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to add tags to this topic.' ) );
return $this->error;
}
$tags = isset( $args[3] ) ? $args[3] : false;
// Check for bad data
if ( !$tags || ( !is_string( $tags ) && !is_array( $tags ) ) ) {
$this->error = new IXR_Error( 400, __( 'The tag data is invalid.' ) );
return $this->error;
}
// Add the tags
if ( !$tag_ids = bb_add_topic_tags( $topic_id, $tags ) ) {
$this->error = new IXR_Error( 500, __( 'The tags could not be added.' ) );
return $this->error;
}
// Only include "safe" data in the array
$_tags = array();
foreach ( $tag_ids as $tag_id ) {
$_tags[] = $this->prepare_topic_tag( bb_get_tag( $tag_id ) );
}
do_action( 'bb_xmlrpc_call_return', 'bb.addTopicTags' );
// Return the tags which were added as an array
return $_tags;
}
/**
* Removes the specified tags from the specified topic
*
* @since 1.0
* @return integer|object 1 when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param string|integer $args[2] The topic id or slug
* @param string|array $args[3] The tags to remove from the topic
*
* XML-RPC request to remove the tag "banana" to the topic with id 219
*
* bb.removeTopicTags
*
* joeblow
* 123password
* 219
* banana
*
*
*
* XML-RPC request to remove the tags "banana" and "man" to the topic with id 219
*
* bb.removeTopicTags
*
* joeblow
* 123password
* 219
* banana, man
*
*
*
* XML-RPC request to remove the tags "banana" and "man" to the topic with id 219 using an array
*
* bb.removeTopicTags
*
* joeblow
* 123password
* 219
*
* banana
* man
*
*
*
*/
function bb_removeTopicTags( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.removeTopicTags' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'edit_tags', __( 'You do not have permission to edit tags.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.removeTopicTags' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can be numeric id or slug
$topic_id = isset( $args[2] ) ? $args[2] : false;
// Check for bad data
if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) {
$this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) );
return $this->error;
}
// Check the requested topic exists
if ( !$topic = get_topic( $topic_id ) ) {
$this->error = new IXR_Error( 400, __( 'No topic found.' ) );
return $this->error;
}
// The topic id may have been a slug, so make sure it's an integer here
$topic_id = (int) $topic->topic_id;
// Make sure they are allowed to add tags to this topic
if ( !bb_current_user_can( 'add_tag_to', $topic_id ) ) {
$this->error = new IXR_Error( 403, __( 'You do not have permission to remove tags from this topic.' ) );
return $this->error;
}
$tags = isset( $args[3] ) ? $args[3] : false;
// Check for bad data
if ( !$tags || ( !is_string( $tags ) && !is_array( $tags ) ) ) {
$this->error = new IXR_Error( 400, __( 'The tag data is invalid.' ) );
return $this->error;
}
// Add the tags
if ( !bb_remove_topic_tags( $topic_id, $tags ) ) {
$this->error = new IXR_Error( 500, __( 'The tags could not be removed.' ) );
return $this->error;
}
$result = 1;
do_action( 'bb_xmlrpc_call_return', 'bb.removeTopicTags' );
// Return the result
return $result;
}
/**
* Renames the specified tag to a new tag name
*
* @since 1.0
* @return array|object The tag data when successfully renamed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param string $args[2] The tag name or slug
* @param string $args[3] The new tag name (slug is auto-generated)
*
* XML-RPC request to rename the tag "banana" to "bananas"
*
* bb.renameTopicTag
*
* joeblow
* 123password
* banana
* bananas
*
*
*/
function bb_renameTopicTag( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.renameTopicTag' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'manage_tags', __( 'You do not have permission to manage tags.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.renameTopicTag' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can only be a string
$tag_id = isset( $args[2] ) ? (string) $args[2] : false;
// Check for bad data
if ( !$tag_id ) {
$this->error = new IXR_Error( 400, __( 'The tag id is invalid.' ) );
return $this->error;
}
// Check the requested tag exists
if ( !$tag = bb_get_tag( $tag_id ) ) {
$this->error = new IXR_Error( 400, __( 'No tag found.' ) );
return $this->error;
}
// Get the numeric tag id
$tag_id = (int) $tag->tag_id;
// Can only be a string
$tag_name = isset( $args[3] ) ? (string) $args[3] : false;
// Check for bad data
if ( !$tag_name || $tag_name == $tag->tag_name ) {
$this->error = new IXR_Error( 400, __( 'The tag name is invalid.' ) );
return $this->error;
}
// Rename the tag
if ( !$new_tag = bb_rename_tag( $tag_id, $tag_name ) ) {
$this->error = new IXR_Error( 500, __( 'The tag could not be renamed.' ) );
return $this->error;
}
// Only include "safe" data in the array
$new_tag = $this->prepare_topic_tag( $new_tag );
do_action( 'bb_xmlrpc_call_return', 'bb.renameTopicTag' );
// Return the tag
return $new_tag;
}
/**
* Merges the specified tags
*
* @since 1.0
* @return array|object The tag data when successfully merged or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param string $args[2] The old tag name or slug to be destroyed
* @param string $args[3] The new tag name or slug where the old tag will be merged to
*
* XML-RPC request to merge the tag "banana" into the tag "apple"
*
* bb.mergeTopicTags
*
* joeblow
* 123password
* banana
* apple
*
*
*/
function bb_mergeTopicTags( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.mergeTopicTags' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'manage_tags', __( 'You do not have permission to manage tags.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.mergeTopicTags' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can only be strings
$old_tag_id = isset( $args[2] ) ? (string) $args[2] : false;
$new_tag_id = isset( $args[3] ) ? (string) $args[3] : false;
// Check for bad data
if ( !$old_tag_id ) {
$this->error = new IXR_Error( 400, __( 'The old tag id is invalid.' ) );
return $this->error;
}
if ( !$new_tag_id ) {
$this->error = new IXR_Error( 400, __( 'The new tag id is invalid.' ) );
return $this->error;
}
// Check the requested tags exist
if ( !$old_tag = bb_get_tag( $old_tag_id ) ) {
$this->error = new IXR_Error( 400, __( 'No old tag found.' ) );
return $this->error;
}
if ( !$new_tag = bb_get_tag( $new_tag_id ) ) {
$this->error = new IXR_Error( 400, __( 'No new tag found.' ) );
return $this->error;
}
// Get the numeric tag ids
$old_tag_id = (int) $old_tag->tag_id;
$new_tag_id = (int) $new_tag->tag_id;
// Rename the tag
if ( !$result = bb_rename_tag( $old_tag_id, $new_tag_id ) ) {
$this->error = new IXR_Error( 500, __( 'The tags could not be merged.' ) );
return $this->error;
}
// Get the merged tag
$new_tag = bb_get_tag( $new_tag_id );
// Only include "safe" data in the array
$new_tag = $this->prepare_topic_tag( $new_tag );
do_action( 'bb_xmlrpc_call_return', 'bb.mergeTopicTags' );
// Return the tag
return $new_tag;
}
/**
* Destroys the specified tag
*
* @since 1.0
* @return integer|object 1 when successfully deleted or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param string $args[2] The tag name or slug to be destroyed
*
* XML-RPC request to destroy the tag "banana"
*
* bb.destroyTopicTag
*
* joeblow
* 123password
* banana
*
*
*/
function bb_destroyTopicTag( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.destroyTopicTag' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'manage_tags', __( 'You do not have permission to manage tags.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.destroyTopicTag' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Can only be a string
$tag_id = isset( $args[2] ) ? (string) $args[2] : false;
// Check for bad data
if ( !$tag_id ) {
$this->error = new IXR_Error( 400, __( 'The tag id is invalid.' ) );
return $this->error;
}
// Check the requested tag exists
if ( !$tag = bb_get_tag( $tag_id ) ) {
$this->error = new IXR_Error( 400, __( 'No tag found.' ) );
return $this->error;
}
// Get the numeric tag id
$tag_id = (int) $tag->tag_id;
// Destroy the tag
if ( !$result = bb_destroy_tag( $tag_id ) ) {
$this->error = new IXR_Error( 500, __( 'The tag could not be destroyed.' ) );
return $this->error;
}
$result = 1;
do_action( 'bb_xmlrpc_call_return', 'bb.destroyTopicTag' );
// Return the tag
return $result;
}
/**
* bbPress publishing API - Options XML-RPC methods
*/
/**
* Initialises site options which can be manipulated using XML-RPC
*
* @since 1.0
* @return void
*/
function initialise_site_option_info()
{
$this->site_options = array(
// Read only options
'software_name' => array(
'desc' => __( 'Software Name' ),
'readonly' => true,
'value' => 'bbPress'
),
'software_version' => array(
'desc' => __( 'Software Version' ),
'readonly' => true,
'option' => 'version'
),
'site_url' => array(
'desc' => __( 'Site URL' ),
'readonly' => true,
'option' => 'uri'
),
// Updatable options
'site_name' => array(
'desc' => __( 'Site Name' ),
'readonly' => false,
'option' => 'name'
),
'site_description' => array(
'desc' => __( 'Site Description' ),
'readonly' => false,
'option' => 'description'
),
'time_zone' => array(
'desc' => __( 'Time Zone' ),
'readonly' => false,
'option' => 'gmt_offset'
),
'datetime_format' => array(
'desc' => __( 'Date/Time Format' ),
'readonly' => false,
'option' => 'datetime_format'
),
'date_format' => array(
'desc' => __( 'Date Format' ),
'readonly' => false,
'option' => 'date_format'
)
);
$this->site_options = apply_filters( 'xmlrpc_site_options', $this->site_options );
}
/**
* Compiles site options into an array suitable to be passed back through the XML-RPC server
*
* @since 1.0
* @return array The site options in an array
* @param array $options An array of options to fetch and return
*/
function _getOptions( $options )
{
$data = array();
foreach ( $options as $option ) {
if ( array_key_exists( $option, $this->site_options ) ) {
$data[$option] = $this->site_options[$option];
// Is the value static or dynamic?
if ( isset( $data[$option]['option'] ) ) {
$data[$option]['value'] = bb_get_option( $data[$option]['option'] );
unset( $data[$option]['option'] );
}
}
}
return $data;
}
/**
* Gets the specified site options
*
* @since 1.0
* @return array|object An array containing the specified options when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param array $args[2] The options to be retrieved, when omitted the method returns all options (optional)
*
* XML-RPC request to get all site options
*
* bb.getOptions
*
* joeblow
* 123password
*
*
*
* XML-RPC request to get the site name and site description
*
* bb.getOptions
*
* joeblow
* 123password
*
* site_name
* site_description
*
*
*
*/
function bb_getOptions( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.getOptions' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
if ( $this->auth_readonly ) {
$user = $this->authenticate( $username, $password );
}
do_action( 'bb_xmlrpc_call_authenticated', 'bb.getOptions' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// If there are parameters supplied then make sure they are in an array
$options = isset( $args[2] ) ? (array) $args[2] : false;
// If no specific options where asked for, return all of them
if ( !$options || !count( $options ) ) {
$options = array_keys( $this->site_options );
}
do_action( 'bb_xmlrpc_call_return', 'bb.getOptions' );
return $this->_getOptions( $options );
}
/**
* Sets the specified site options to the specified values
*
* @since 1.0
* @return array|object An array containing the specified options when successfully executed or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The username for authentication
* @param string $args[1] The password for authentication
* @param array $args[2] The options to be updated along with the new value of the option
*
* XML-RPC request to set the site name and site description
*
* bb.setOptions
*
* joeblow
* 123password
*
*
* site_name
* Awesome forums
*
*
* site_description
* My totally awesome forums will kick your butt
*
*
*
*
*/
function bb_setOptions( $args )
{
do_action( 'bb_xmlrpc_call', 'bb.setOptions' );
// Escape args
$this->escape( $args );
// Get the login credentials
$username = $args[0];
$password = (string) $args[1];
// Check the user is valid
$user = $this->authenticate( $username, $password, 'manage_options', __( 'You are not allowed to manage options.' ) );
do_action( 'bb_xmlrpc_call_authenticated', 'bb.setOptions' );
// If an error was raised by authentication or by an action then return it
if ( $this->error ) {
return $this->error;
}
// Make sure there is something for us to do
if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) {
$this->error = new IXR_Error( 400, __( 'The options data is invalid.' ) );
return $this->error;
}
$options = (array) $args[2];
// Update the requested options
foreach( $options as $o_name => $o_value ) {
$option_names[] = $o_name;
// If there is no value set skip it
if ( empty( $o_value ) ) {
continue;
}
// If the option doesn't exist skip it
if ( !array_key_exists( $o_name, $this->site_options ) ) {
continue;
}
// If the option is readonly skip it
if ( $this->site_options[$o_name]['readonly'] == true ) {
continue;
}
// Everything is good, update the option
bb_update_option( $this->site_options[$o_name]['option'], $o_value );
}
$_options = $this->_getOptions( $option_names );
do_action( 'bb_xmlrpc_call_return', 'bb.setOptions' );
// Now return the updated values
return $_options;
}
/**
* Pingback XML-RPC methods
*/
/**
* Processes pingback requests
*
* @since 1.0
* @link http://www.hixie.ch/specs/pingback/pingback
* @return string|object A message of success or an IXR_Error object on failure
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The full URI of the post where the pingback is being sent from
* @param string $args[1] The full URI of the post where the pingback is being sent to
*
* XML-RPC request to register a pingback
*
* pingback.ping
*
* http://example.org/2008/09/post-containing-a-link/
* http://example.com/2008/08/post-being-linked-to/
*
*
*/
function pingback_ping( $args )
{
do_action( 'bb_xmlrpc_call', 'pingback.ping' );
$this->escape( $args );
// No particular need to sanitise
$link_from = (string) $args[0];
$link_to = (string) $args[1];
// Tidy up ampersands in the URLs
$link_from = str_replace( '&', '&', $link_from );
$link_to = str_replace( '&', '&', $link_to );
$link_to = str_replace( '&', '&', $link_to );
// Check if the topic linked to is in our site - a little more strict than WordPress, doesn't pull out the www if added
if ( !bb_match_domains( $link_to, bb_get_uri() ) ) {
// These are not the droids you are looking for
$this->error = new IXR_Error( 0, __( 'This is not the site you are trying to pingback.' ) );
return $this->error;
}
// Get the topic
if ( $topic_to = bb_get_topic_from_uri( $link_to ) ) {
// Topics shouldn't ping themselves
if ( $topic_from = bb_get_topic_from_uri( $link_from ) ) {
if ( $topic_from->topic_id === $topic_to->topic_id ) {
$this->error = new IXR_Error( 0, __( 'The source URL and the target URL cannot both point to the same resource.' ) );
return $this->error;
}
}
} else {
$this->error = new IXR_Error ( 33, __( 'The specified target URL cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.' ) );
return $this->error;
}
// Let's check that the remote site didn't already pingback this entry
$query = new BB_Query( 'post', array( 'topic_id' => $topic_to->topic_id, 'append_meta' => true ), 'get_thread' );
$posts_to = $query->results;
unset( $query );
// Make sure we have some posts in the topic, this error should never happen really
if ( !$posts_to || !is_array( $posts_to ) || !count( $posts_to ) ) {
$this->error = new IXR_Error( 0, __( 'The specified target topic does not contain any posts.' ) );
return $this->error;
}
// Check if we already have a pingback from this URL
foreach ( $posts_to as $post ) {
if ( isset( $post->pingback_uri ) && trim( $post->pingback_uri ) === trim( $link_from ) ) {
$this->error = new IXR_Error( 48, __( 'The pingback has already been registered.' ) );
return $this->error;
}
}
unset( $posts_to, $post );
// Give time for the server sending the pingback to finish publishing it's post
sleep(1);
// Let's check the remote site for valid URL and content
$link_from_source = wp_remote_fopen( $link_from );
if ( !$link_from_source ) {
$this->error = new IXR_Error( 16, __( 'The source URL does not exist.' ) );
return $this->error;
}
// Allow plugins to filter here
$link_from_source = apply_filters( 'bb_pre_remote_source', $link_from_source, $link_to );
// Work around bug in strip_tags()
$link_from_source = str_replace( ']*>/", "\n\n", $link_from_source );
// Find the title of the page
preg_match( '|
([^<]*?)|is', $link_from_source, $link_from_title );
$link_from_title = $link_from_title[1];
if ( empty( $link_from_title ) ) {
$this->error = new IXR_Error( 32, __( 'We cannot find a title on that page.' ) );
return $this->error;
}
// Strip out all tags except anchors
$link_from_source = strip_tags( $link_from_source, '' ); // just keep the tag we need
// Split the source into paragraphs
$link_from_paragraphs = explode( "\n\n", $link_from_source );
// Prepare the link to search for in preg_match() once here
$preg_target = preg_quote( $link_to );
// Loop through the paragraphs looking for the context for the url
foreach ( $link_from_paragraphs as $link_from_paragraph ) {
// The url exists
if ( strpos( $link_from_paragraph, $link_to ) !== false ) {
// But is it in an anchor tag
preg_match(
"|]+?" . $preg_target . "[^>]*>([^>]+?)|",
$link_from_paragraph,
$context
);
// If the URL isn't in an anchor tag, keep looking
if ( empty( $context ) ) {
continue;
}
// We're going to use this fake tag to mark the context in a bit
// the marker is needed in case the link text appears more than once in the paragraph
$excerpt = preg_replace( '|\?wpcontext\>|', '', $link_from_paragraph );
// Prevent really long link text
if ( strlen( $context[1] ) > 100 ) {
$context[1] = substr( $context[1], 0, 100 ) . '...';
}
// Set up the marker around the context
$marker = '' . $context[1] . '';
// Swap out the link for our marker
$excerpt = str_replace( $context[0], $marker, $excerpt );
// Strip all tags except for our context marker
$excerpt = trim( strip_tags( $excerpt, '' ) );
// Make the marker safe for use in regexp
$preg_marker = preg_quote( $marker );
// Reduce the excerpt to only include 100 characters on either side of the link
$excerpt = preg_replace( "|.*?\s(.{0,100}" . $preg_marker . "{0,100})\s.*|s", '$1', $excerpt );
// Strip tags again, to remove the marker wrapper
$excerpt = strip_tags( $excerpt );
break;
}
}
// Make sure the link to the target was found in the excerpt
if ( empty( $context ) ) {
$this->error = new IXR_Error( 17, __( 'The source URL does not contain a link to the target URL, and so cannot be used as a source.' ) );
return $this->error;
}
// Add whacky prefix and suffix to the excerpt and sanitize
$excerpt = '[...] ' . esc_html( $excerpt ) . ' [...]';
$this->escape( $excerpt );
// Build an array of post data to insert then insert a new post
$postdata = array(
'topic_id' => $topic_to->topic_id,
'post_text' => $excerpt,
'poster_id' => 0,
);
if ( !$post_ID = bb_insert_post( $postdata ) ) {
$this->error = new IXR_Error( 0, __( 'The pingback could not be added.' ) );
return $this->error;
}
// Add meta to let us know where the pingback came from
$link_from = str_replace( '&', '&', $link_from );
$this->escape( $link_from );
bb_update_postmeta( $post_ID, 'pingback_uri', $link_from );
// Add the title to meta
$this->escape( $link_from_title );
bb_update_postmeta( $post_ID, 'pingback_title', $link_from_title );
// Action for plugins and what not
do_action( 'bb_pingback_post', $post_ID );
// Return success message, complete with emoticon
return sprintf( __( 'Pingback from %1$s to %2$s registered. Keep the web talking! :-)' ), $link_from, $link_to );
}
/**
* Returns an array of URLs that pingbacked the given URL
*
* @since 1.0
* @link http://www.aquarionics.com/misc/archives/blogite/0198.html
* @return array The array of URLs that pingbacked the given topic
* @param array $args Arguments passed by the XML-RPC call
* @param string $args[0] The full URI of the post where the pingback is being sent from
* @param string $args[1] The full URI of the post where the pingback is being sent to
*
* XML-RPC request to get all pingbacks on a topic
*
* pingback.ping
*
* http://example.com/2008/08/post-tobe-queried/
*
*
*/
function pingback_extensions_getPingbacks( $args )
{
do_action( 'bb_xmlrpc_call', 'pingback.extensions.getPingbacks' );
$this->escape( $args );
// Don't accept arrays of arguments
if ( is_array( $args ) ) {
$this->error = new IXR_Error( 404, __( 'The requested method only accepts one parameter.' ) );
return $this->error;
} else {
$url = (string) $args;
}
// Tidy up ampersands in the URI
$url = str_replace( '&', '&', $url );
$url = str_replace( '&', '&', $url );
// Check if the URI is in our site
if ( !bb_match_domains( $url, bb_get_uri() ) ) {
// These are not the droids you are looking for
$this->error = new IXR_Error( 0, __( 'The specified target URL is not on this domain.' ) );
return $this->error;
}
// Make sure the specified URI is in fact associated with a topic
if ( !$topic = bb_get_topic_from_uri( $url ) ) {
$this->error = new IXR_Error( 33, __( 'The specified target URL cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.' ) );
return $this->error;
}
// Grab the posts from the topic
$query = new BB_Query( 'post', array( 'topic_id' => $topic_to->topic_id, 'append_meta' => true ), 'get_thread' );
$posts_to = $query->results;
unset( $query );
// Check for pingbacks in the post meta data
$pingbacks = array();
foreach ( $posts_to as $post ) {
if ( isset( $post->pingback_uri ) ) {
$pingbacks[] = $post->pingback_uri;
}
}
unset( $post );
// This will return an empty array on failure
return $pingbacks;
}
}
/**
* Initialises the XML-RPC server
*
* @since 1.0
* @var object The instance of the XML-RPC server class
*/
$bb_xmlrpc_server = new BB_XMLRPC_Server();