: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Method arguments. Note: arguments must be ordered as documented.
* @type int $0 Blog ID (unused).
* @type string $1 Username.
* @type string $2 Password.
* @type int $3 Optional. Number of pages. Default 10.
* @return array|IXR_Error
public function wp_getPages( $args ) {
$num_pages = isset( $args[3] ) ? (int) $args[3] : 10;
$user = $this->login( $username, $password );
if ( ! current_user_can( 'edit_pages' ) ) {
return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit pages.' ) );
/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
do_action( 'xmlrpc_call', 'wp.getPages', $args, $this );
'numberposts' => $num_pages,
$num_pages = count( $pages );
// If we have pages, put together their info.
foreach ( $pages as $page ) {
if ( current_user_can( 'edit_page', $page->ID ) ) {
$pages_struct[] = $this->_prepare_page( $page );
* @see wp_xmlrpc_server::mw_newPost()
* Method arguments. Note: arguments must be ordered as documented.
* @type int $0 Blog ID (unused).
* @type string $1 Username.
* @type string $2 Password.
* @type array $3 Content struct.
public function wp_newPage( $args ) {
// Items not escaped here will be escaped in wp_newPost().
$username = $this->escape( $args[1] );
$password = $this->escape( $args[2] );
$user = $this->login( $username, $password );
/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
do_action( 'xmlrpc_call', 'wp.newPage', $args, $this );
// Mark this as content for a page.
$args[3]['post_type'] = 'page';
// Let mw_newPost() do all of the heavy lifting.
return $this->mw_newPost( $args );
* Method arguments. Note: arguments must be ordered as documented.
* @type int $0 Blog ID (unused).
* @type string $1 Username.
* @type string $2 Password.
* @return true|IXR_Error True, if success.
public function wp_deletePage( $args ) {
$page_id = (int) $args[3];
$user = $this->login( $username, $password );
/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
do_action( 'xmlrpc_call', 'wp.deletePage', $args, $this );
* Get the current page based on the 'page_id' and
* make sure it is a page and not a post.
$actual_page = get_post( $page_id, ARRAY_A );
if ( ! $actual_page || ( 'page' !== $actual_page['post_type'] ) ) {
return new IXR_Error( 404, __( 'Sorry, no such page.' ) );
// Make sure the user can delete pages.
if ( ! current_user_can( 'delete_page', $page_id ) ) {
return new IXR_Error( 401, __( 'Sorry, you are not allowed to delete this page.' ) );
// Attempt to delete the page.
$result = wp_delete_post( $page_id );
return new IXR_Error( 500, __( 'Failed to delete the page.' ) );
* Fires after a page has been successfully deleted via XML-RPC.
* @param int $page_id ID of the deleted page.
* @param array $args An array of arguments to delete the page.
do_action( 'xmlrpc_call_success_wp_deletePage', $page_id, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
* Method arguments. Note: arguments must be ordered as documented.
* @type int $0 Blog ID (unused).
* @type string $2 Username.
* @type string $3 Password.
* @type string $4 Content.
* @type int $5 Publish flag. 0 for draft, 1 for publish.
* @return array|IXR_Error
public function wp_editPage( $args ) {
// Items will be escaped in mw_editPost().
$page_id = (int) $args[1];
$escaped_username = $this->escape( $username );
$escaped_password = $this->escape( $password );
$user = $this->login( $escaped_username, $escaped_password );
/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
do_action( 'xmlrpc_call', 'wp.editPage', $args, $this );
// Get the page data and make sure it is a page.
$actual_page = get_post( $page_id, ARRAY_A );
if ( ! $actual_page || ( 'page' !== $actual_page['post_type'] ) ) {
return new IXR_Error( 404, __( 'Sorry, no such page.' ) );
// Make sure the user is allowed to edit pages.
if ( ! current_user_can( 'edit_page', $page_id ) ) {
return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this page.' ) );
// Mark this as content for a page.
$content['post_type'] = 'page';
// Arrange args in the way mw_editPost() understands.
// Let mw_editPost() do all of the heavy lifting.
return $this->mw_editPost( $args );
* @global wpdb $wpdb WordPress database abstraction object.
* Method arguments. Note: arguments must be ordered as documented.
* @type int $0 Blog ID (unused).
* @type string $1 Username.
* @type string $2 Password.
* @return array|IXR_Error
public function wp_getPageList( $args ) {
$user = $this->login( $username, $password );
if ( ! current_user_can( 'edit_pages' ) ) {
return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit pages.' ) );
/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
do_action( 'xmlrpc_call', 'wp.getPageList', $args, $this );
// Get list of page IDs and titles.
$page_list = $wpdb->get_results(
post_parent page_parent_id,
// The date needs to be formatted properly.
$num_pages = count( $page_list );
for ( $i = 0; $i < $num_pages; $i++ ) {
$page_list[ $i ]->dateCreated = $this->_convert_date( $page_list[ $i ]->post_date );
$page_list[ $i ]->date_created_gmt = $this->_convert_date_gmt( $page_list[ $i ]->post_date_gmt, $page_list[ $i ]->post_date );
unset( $page_list[ $i ]->post_date_gmt );
unset( $page_list[ $i ]->post_date );
unset( $page_list[ $i ]->post_status );
* Retrieves authors list.
* Method arguments. Note: arguments must be ordered as documented.
* @type int $0 Blog ID (unused).
* @type string $1 Username.
* @type string $2 Password.
* @return array|IXR_Error
public function wp_getAuthors( $args ) {
$user = $this->login( $username, $password );
if ( ! current_user_can( 'edit_posts' ) ) {
return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit posts.' ) );
/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
do_action( 'xmlrpc_call', 'wp.getAuthors', $args, $this );
foreach ( get_users( array( 'fields' => array( 'ID', 'user_login', 'display_name' ) ) ) as $user ) {
'user_login' => $user->user_login,
'display_name' => $user->display_name,
* Gets the list of all tags.
* Method arguments. Note: arguments must be ordered as documented.
* @type int $0 Blog ID (unused).
* @type string $1 Username.
* @type string $2 Password.
* @return array|IXR_Error
public function wp_getTags( $args ) {
$user = $this->login( $username, $password );
if ( ! current_user_can( 'edit_posts' ) ) {
return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this site in order to view tags.' ) );
/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
do_action( 'xmlrpc_call', 'wp.getKeywords', $args, $this );
foreach ( (array) $all_tags as $tag ) {
$struct['tag_id'] = $tag->term_id;
$struct['name'] = $tag->name;
$struct['count'] = $tag->count;
$struct['slug'] = $tag->slug;
$struct['html_url'] = esc_html( get_tag_link( $tag->term_id ) );
$struct['rss_url'] = esc_html( get_tag_feed_link( $tag->term_id ) );
* Creates a new category.
* Method arguments. Note: arguments must be ordered as documented.
* @type int $0 Blog ID (unused).
* @type string $1 Username.
* @type string $2 Password.
* @type array $3 Category.
* @return int|IXR_Error Category ID.
public function wp_newCategory( $args ) {
$user = $this->login( $username, $password );
/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
do_action( 'xmlrpc_call', 'wp.newCategory', $args, $this );
// Make sure the user is allowed to add a category.
if ( ! current_user_can( 'manage_categories' ) ) {
return new IXR_Error( 401, __( 'Sorry, you are not allowed to add a category.' ) );
* If no slug was provided, make it empty
* so that WordPress will generate one.
if ( empty( $category['slug'] ) ) {
* If no parent_id was provided, make it empty
* so that it will be a top-level page (no parent).
if ( ! isset( $category['parent_id'] ) ) {
$category['parent_id'] = '';
// If no description was provided, make it empty.
if ( empty( $category['description'] ) ) {
$category['description'] = '';
'cat_name' => $category['name'],
'category_nicename' => $category['slug'],
'category_parent' => $category['parent_id'],
'category_description' => $category['description'],
$cat_id = wp_insert_category( $new_category, true );
if ( is_wp_error( $cat_id ) ) {
if ( 'term_exists' === $cat_id->get_error_code() ) {
return (int) $cat_id->get_error_data();
return new IXR_Error( 500, __( 'Sorry, the category could not be created.' ) );
return new IXR_Error( 500, __( 'Sorry, the category could not be created.' ) );
* Fires after a new category has been successfully created via XML-RPC.
* @param int $cat_id ID of the new category.
* @param array $args An array of new category arguments.
do_action( 'xmlrpc_call_success_wp_newCategory', $cat_id, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
* Method arguments. Note: arguments must be ordered as documented.
* @type int $0 Blog ID (unused).
* @type string $1 Username.
* @type string $2 Password.
* @type int $3 Category ID.
* @return bool|IXR_Error See wp_delete_term() for return info.
public function wp_deleteCategory( $args ) {
$category_id = (int) $args[3];
$user = $this->login( $username, $password );
/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
do_action( 'xmlrpc_call', 'wp.deleteCategory', $args, $this );