wp_xmlrpc_server::mw_newPost( array $args ): int|IXR_Error

Creates a new post.

Description

The ‘content_struct’ argument must contain:

  • title
  • description
  • mt_excerpt
  • mt_text_more
  • mt_keywords
  • mt_tb_ping_urls
  • categories

Also, it can optionally contain:

  • wp_slug
  • wp_password
  • wp_page_parent_id
  • wp_page_order
  • wp_author_id
  • post_status | page_status – can be ‘draft’, ‘private’, ‘publish’, or ‘pending’
  • mt_allow_comments – can be ‘open’ or ‘closed’
  • mt_allow_pings – can be ‘open’ or ‘closed’
  • date_created_gmt
  • dateCreated
  • wp_post_thumbnail

Parameters

$argsarrayrequired
Method arguments. Note: arguments must be ordered as documented.
  • 0 int
    Blog ID (unused).
  • 1 string
    Username.
  • 2 string
    Password.
  • 3 array
    Content structure.
  • 4 int
    Optional. Publish flag. 0 for draft, 1 for publish. Default 0.

Return

int|IXR_Error

Source

public function mw_newPost( $args ) {
	$this->escape( $args );

	$username       = $args[1];
	$password       = $args[2];
	$content_struct = $args[3];
	$publish        = isset( $args[4] ) ? $args[4] : 0;

	$user = $this->login( $username, $password );
	if ( ! $user ) {
		return $this->error;
	}

	/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
	do_action( 'xmlrpc_call', 'metaWeblog.newPost', $args, $this );

	$page_template = '';
	if ( ! empty( $content_struct['post_type'] ) ) {
		if ( 'page' === $content_struct['post_type'] ) {
			if ( $publish ) {
				$cap = 'publish_pages';
			} elseif ( isset( $content_struct['page_status'] ) && 'publish' === $content_struct['page_status'] ) {
				$cap = 'publish_pages';
			} else {
				$cap = 'edit_pages';
			}
			$error_message = __( 'Sorry, you are not allowed to publish pages on this site.' );
			$post_type     = 'page';
			if ( ! empty( $content_struct['wp_page_template'] ) ) {
				$page_template = $content_struct['wp_page_template'];
			}
		} elseif ( 'post' === $content_struct['post_type'] ) {
			if ( $publish ) {
				$cap = 'publish_posts';
			} elseif ( isset( $content_struct['post_status'] ) && 'publish' === $content_struct['post_status'] ) {
				$cap = 'publish_posts';
			} else {
				$cap = 'edit_posts';
			}
			$error_message = __( 'Sorry, you are not allowed to publish posts on this site.' );
			$post_type     = 'post';
		} else {
			// No other 'post_type' values are allowed here.
			return new IXR_Error( 401, __( 'Invalid post type.' ) );
		}
	} else {
		if ( $publish ) {
			$cap = 'publish_posts';
		} elseif ( isset( $content_struct['post_status'] ) && 'publish' === $content_struct['post_status'] ) {
			$cap = 'publish_posts';
		} else {
			$cap = 'edit_posts';
		}
		$error_message = __( 'Sorry, you are not allowed to publish posts on this site.' );
		$post_type     = 'post';
	}

	if ( ! current_user_can( get_post_type_object( $post_type )->cap->create_posts ) ) {
		return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish posts on this site.' ) );
	}
	if ( ! current_user_can( $cap ) ) {
		return new IXR_Error( 401, $error_message );
	}

	// Check for a valid post format if one was given.
	if ( isset( $content_struct['wp_post_format'] ) ) {
		$content_struct['wp_post_format'] = sanitize_key( $content_struct['wp_post_format'] );
		if ( ! array_key_exists( $content_struct['wp_post_format'], get_post_format_strings() ) ) {
			return new IXR_Error( 404, __( 'Invalid post format.' ) );
		}
	}

	// Let WordPress generate the 'post_name' (slug) unless
	// one has been provided.
	$post_name = null;
	if ( isset( $content_struct['wp_slug'] ) ) {
		$post_name = $content_struct['wp_slug'];
	}

	// Only use a password if one was given.
	$post_password = '';
	if ( isset( $content_struct['wp_password'] ) ) {
		$post_password = $content_struct['wp_password'];
	}

	// Only set a post parent if one was given.
	$post_parent = 0;
	if ( isset( $content_struct['wp_page_parent_id'] ) ) {
		$post_parent = $content_struct['wp_page_parent_id'];
	}

	// Only set the 'menu_order' if it was given.
	$menu_order = 0;
	if ( isset( $content_struct['wp_page_order'] ) ) {
		$menu_order = $content_struct['wp_page_order'];
	}

	$post_author = $user->ID;

	// If an author id was provided then use it instead.
	if ( isset( $content_struct['wp_author_id'] ) && ( $user->ID != $content_struct['wp_author_id'] ) ) {
		switch ( $post_type ) {
			case 'post':
				if ( ! current_user_can( 'edit_others_posts' ) ) {
					return new IXR_Error( 401, __( 'Sorry, you are not allowed to create posts as this user.' ) );
				}
				break;
			case 'page':
				if ( ! current_user_can( 'edit_others_pages' ) ) {
					return new IXR_Error( 401, __( 'Sorry, you are not allowed to create pages as this user.' ) );
				}
				break;
			default:
				return new IXR_Error( 401, __( 'Invalid post type.' ) );
		}
		$author = get_userdata( $content_struct['wp_author_id'] );
		if ( ! $author ) {
			return new IXR_Error( 404, __( 'Invalid author ID.' ) );
		}
		$post_author = $content_struct['wp_author_id'];
	}

	$post_title   = isset( $content_struct['title'] ) ? $content_struct['title'] : '';
	$post_content = isset( $content_struct['description'] ) ? $content_struct['description'] : '';

	$post_status = $publish ? 'publish' : 'draft';

	if ( isset( $content_struct[ "{$post_type}_status" ] ) ) {
		switch ( $content_struct[ "{$post_type}_status" ] ) {
			case 'draft':
			case 'pending':
			case 'private':
			case 'publish':
				$post_status = $content_struct[ "{$post_type}_status" ];
				break;
			default:
				// Deliberably left empty.
				break;
		}
	}

	$post_excerpt = isset( $content_struct['mt_excerpt'] ) ? $content_struct['mt_excerpt'] : '';
	$post_more    = isset( $content_struct['mt_text_more'] ) ? $content_struct['mt_text_more'] : '';

	$tags_input = isset( $content_struct['mt_keywords'] ) ? $content_struct['mt_keywords'] : array();

	if ( isset( $content_struct['mt_allow_comments'] ) ) {
		if ( ! is_numeric( $content_struct['mt_allow_comments'] ) ) {
			switch ( $content_struct['mt_allow_comments'] ) {
				case 'closed':
					$comment_status = 'closed';
					break;
				case 'open':
					$comment_status = 'open';
					break;
				default:
					$comment_status = get_default_comment_status( $post_type );
					break;
			}
		} else {
			switch ( (int) $content_struct['mt_allow_comments'] ) {
				case 0:
				case 2:
					$comment_status = 'closed';
					break;
				case 1:
					$comment_status = 'open';
					break;
				default:
					$comment_status = get_default_comment_status( $post_type );
					break;
			}
		}
	} else {
		$comment_status = get_default_comment_status( $post_type );
	}

	if ( isset( $content_struct['mt_allow_pings'] ) ) {
		if ( ! is_numeric( $content_struct['mt_allow_pings'] ) ) {
			switch ( $content_struct['mt_allow_pings'] ) {
				case 'closed':
					$ping_status = 'closed';
					break;
				case 'open':
					$ping_status = 'open';
					break;
				default:
					$ping_status = get_default_comment_status( $post_type, 'pingback' );
					break;
			}
		} else {
			switch ( (int) $content_struct['mt_allow_pings'] ) {
				case 0:
					$ping_status = 'closed';
					break;
				case 1:
					$ping_status = 'open';
					break;
				default:
					$ping_status = get_default_comment_status( $post_type, 'pingback' );
					break;
			}
		}
	} else {
		$ping_status = get_default_comment_status( $post_type, 'pingback' );
	}

	if ( $post_more ) {
		$post_content .= '<!--more-->' . $post_more;
	}

	$to_ping = '';
	if ( isset( $content_struct['mt_tb_ping_urls'] ) ) {
		$to_ping = $content_struct['mt_tb_ping_urls'];
		if ( is_array( $to_ping ) ) {
			$to_ping = implode( ' ', $to_ping );
		}
	}

	// Do some timestamp voodoo.
	if ( ! empty( $content_struct['date_created_gmt'] ) ) {
		// We know this is supposed to be GMT, so we're going to slap that Z on there by force.
		$dateCreated = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
	} elseif ( ! empty( $content_struct['dateCreated'] ) ) {
		$dateCreated = $content_struct['dateCreated']->getIso();
	}

	$post_date     = '';
	$post_date_gmt = '';
	if ( ! empty( $dateCreated ) ) {
		$post_date     = iso8601_to_datetime( $dateCreated );
		$post_date_gmt = iso8601_to_datetime( $dateCreated, 'gmt' );
	}

	$post_category = array();
	if ( isset( $content_struct['categories'] ) ) {
		$catnames = $content_struct['categories'];

		if ( is_array( $catnames ) ) {
			foreach ( $catnames as $cat ) {
				$post_category[] = get_cat_ID( $cat );
			}
		}
	}

	$postdata = compact( 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'to_ping', 'post_type', 'post_name', 'post_password', 'post_parent', 'menu_order', 'tags_input', 'page_template' );

	$post_id        = get_default_post_to_edit( $post_type, true )->ID;
	$postdata['ID'] = $post_id;

	// Only posts can be sticky.
	if ( 'post' === $post_type && isset( $content_struct['sticky'] ) ) {
		$data           = $postdata;
		$data['sticky'] = $content_struct['sticky'];
		$error          = $this->_toggle_sticky( $data );
		if ( $error ) {
			return $error;
		}
	}

	if ( isset( $content_struct['custom_fields'] ) ) {
		$this->set_custom_fields( $post_id, $content_struct['custom_fields'] );
	}

	if ( isset( $content_struct['wp_post_thumbnail'] ) ) {
		if ( set_post_thumbnail( $post_id, $content_struct['wp_post_thumbnail'] ) === false ) {
			return new IXR_Error( 404, __( 'Invalid attachment ID.' ) );
		}

		unset( $content_struct['wp_post_thumbnail'] );
	}

	// Handle enclosures.
	$thisEnclosure = isset( $content_struct['enclosure'] ) ? $content_struct['enclosure'] : null;
	$this->add_enclosure_if_new( $post_id, $thisEnclosure );

	$this->attach_uploads( $post_id, $post_content );

	/*
	 * Handle post formats if assigned, value is validated earlier
	 * in this function.
	 */
	if ( isset( $content_struct['wp_post_format'] ) ) {
		set_post_format( $post_id, $content_struct['wp_post_format'] );
	}

	$post_id = wp_insert_post( $postdata, true );
	if ( is_wp_error( $post_id ) ) {
		return new IXR_Error( 500, $post_id->get_error_message() );
	}

	if ( ! $post_id ) {
		return new IXR_Error( 500, __( 'Sorry, the post could not be created.' ) );
	}

	/**
	 * Fires after a new post has been successfully created via the XML-RPC MovableType API.
	 *
	 * @since 3.4.0
	 *
	 * @param int   $post_id ID of the new post.
	 * @param array $args    An array of arguments to create the new post.
	 */
	do_action( 'xmlrpc_call_success_mw_newPost', $post_id, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase

	return (string) $post_id;
}

Hooks

do_action( ‘xmlrpc_call’, string $name, array|string $args, wp_xmlrpc_server $server )

Fires after the XML-RPC user has been authenticated but before the rest of the method logic begins.

do_action( ‘xmlrpc_call_success_mw_newPost’, int $post_id, array $args )

Fires after a new post has been successfully created via the XML-RPC MovableType API.

Changelog

VersionDescription
1.5.0Introduced.

User Contributed Notes

You must log in before being able to contribute a note or feedback.