wp/wp-includes/class-wp-xmlrpc-server.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
     1 <?php
     1 <?php
     2 /**
     2 /**
     3  * XML-RPC protocol support for WordPress
     3  * XML-RPC protocol support for WordPress.
     4  *
     4  *
     5  * @package WordPress
     5  * @package WordPress
     6  * @subpackage Publishing
     6  * @subpackage Publishing
     7  */
     7  */
     8 
     8 
    18  *
    18  *
    19  * @since 1.5.0
    19  * @since 1.5.0
    20  *
    20  *
    21  * @see IXR_Server
    21  * @see IXR_Server
    22  */
    22  */
       
    23 #[AllowDynamicProperties]
    23 class wp_xmlrpc_server extends IXR_Server {
    24 class wp_xmlrpc_server extends IXR_Server {
    24 	/**
    25 	/**
    25 	 * Methods.
    26 	 * Methods.
    26 	 *
    27 	 *
    27 	 * @var array
    28 	 * @var array
    57 	private $is_enabled;
    58 	private $is_enabled;
    58 
    59 
    59 	/**
    60 	/**
    60 	 * Registers all of the XMLRPC methods that XMLRPC server understands.
    61 	 * Registers all of the XMLRPC methods that XMLRPC server understands.
    61 	 *
    62 	 *
    62 	 * Sets up server and method property. Passes XMLRPC
    63 	 * Sets up server and method property. Passes XMLRPC methods through the
    63 	 * methods through the {@see 'xmlrpc_methods'} filter to allow plugins to extend
    64 	 * {@see 'xmlrpc_methods'} filter to allow plugins to extend or replace
    64 	 * or replace XML-RPC methods.
    65 	 * XML-RPC methods.
    65 	 *
    66 	 *
    66 	 * @since 1.5.0
    67 	 * @since 1.5.0
    67 	 */
    68 	 */
    68 	public function __construct() {
    69 	public function __construct() {
    69 		$this->methods = array(
    70 		$this->methods = array(
   134 			'metaWeblog.getPost'               => 'this:mw_getPost',
   135 			'metaWeblog.getPost'               => 'this:mw_getPost',
   135 			'metaWeblog.getRecentPosts'        => 'this:mw_getRecentPosts',
   136 			'metaWeblog.getRecentPosts'        => 'this:mw_getRecentPosts',
   136 			'metaWeblog.getCategories'         => 'this:mw_getCategories',
   137 			'metaWeblog.getCategories'         => 'this:mw_getCategories',
   137 			'metaWeblog.newMediaObject'        => 'this:mw_newMediaObject',
   138 			'metaWeblog.newMediaObject'        => 'this:mw_newMediaObject',
   138 
   139 
   139 			// MetaWeblog API aliases for Blogger API.
   140 			/*
   140 			// See http://www.xmlrpc.com/stories/storyReader$2460
   141 			 * MetaWeblog API aliases for Blogger API.
       
   142 			 * See http://www.xmlrpc.com/stories/storyReader$2460
       
   143 			 */
   141 			'metaWeblog.deletePost'            => 'this:blogger_deletePost',
   144 			'metaWeblog.deletePost'            => 'this:blogger_deletePost',
   142 			'metaWeblog.getUsersBlogs'         => 'this:blogger_getUsersBlogs',
   145 			'metaWeblog.getUsersBlogs'         => 'this:blogger_getUsersBlogs',
   143 
   146 
   144 			// MovableType API.
   147 			// MovableType API.
   145 			'mt.getCategoryList'               => 'this:mt_getCategoryList',
   148 			'mt.getCategoryList'               => 'this:mt_getCategoryList',
   174 
   177 
   175 		$this->set_is_enabled();
   178 		$this->set_is_enabled();
   176 	}
   179 	}
   177 
   180 
   178 	/**
   181 	/**
   179 	 * Set wp_xmlrpc_server::$is_enabled property.
   182 	 * Sets wp_xmlrpc_server::$is_enabled property.
   180 	 *
   183 	 *
   181 	 * Determine whether the xmlrpc server is enabled on this WordPress install
   184 	 * Determines whether the xmlrpc server is enabled on this WordPress install
   182 	 * and set the is_enabled property accordingly.
   185 	 * and set the is_enabled property accordingly.
   183 	 *
   186 	 *
   184 	 * @since 5.7.3
   187 	 * @since 5.7.3
   185 	 */
   188 	 */
   186 	private function set_is_enabled() {
   189 	private function set_is_enabled() {
   195 
   198 
   196 		/**
   199 		/**
   197 		 * Filters whether XML-RPC methods requiring authentication are enabled.
   200 		 * Filters whether XML-RPC methods requiring authentication are enabled.
   198 		 *
   201 		 *
   199 		 * Contrary to the way it's named, this filter does not control whether XML-RPC is *fully*
   202 		 * Contrary to the way it's named, this filter does not control whether XML-RPC is *fully*
   200 		 * enabled, rather, it only controls whether XML-RPC methods requiring authentication - such
   203 		 * enabled, rather, it only controls whether XML-RPC methods requiring authentication -
   201 		 * as for publishing purposes - are enabled.
   204 		 * such as for publishing purposes - are enabled.
   202 		 *
   205 		 *
   203 		 * Further, the filter does not control whether pingbacks or other custom endpoints that don't
   206 		 * Further, the filter does not control whether pingbacks or other custom endpoints that don't
   204 		 * require authentication are enabled. This behavior is expected, and due to how parity was matched
   207 		 * require authentication are enabled. This behavior is expected, and due to how parity was matched
   205 		 * with the `enable_xmlrpc` UI option the filter replaced when it was introduced in 3.5.
   208 		 * with the `enable_xmlrpc` UI option the filter replaced when it was introduced in 3.5.
   206 		 *
   209 		 *
   217 		 */
   220 		 */
   218 		$this->is_enabled = apply_filters( 'xmlrpc_enabled', $is_enabled );
   221 		$this->is_enabled = apply_filters( 'xmlrpc_enabled', $is_enabled );
   219 	}
   222 	}
   220 
   223 
   221 	/**
   224 	/**
   222 	 * Make private/protected methods readable for backward compatibility.
   225 	 * Makes private/protected methods readable for backward compatibility.
   223 	 *
   226 	 *
   224 	 * @since 4.0.0
   227 	 * @since 4.0.0
   225 	 *
   228 	 *
   226 	 * @param string $name      Method to call.
   229 	 * @param string $name      Method to call.
   227 	 * @param array  $arguments Arguments to pass when calling.
   230 	 * @param array  $arguments Arguments to pass when calling.
   242 	public function serve_request() {
   245 	public function serve_request() {
   243 		$this->IXR_Server( $this->methods );
   246 		$this->IXR_Server( $this->methods );
   244 	}
   247 	}
   245 
   248 
   246 	/**
   249 	/**
   247 	 * Test XMLRPC API by saying, "Hello!" to client.
   250 	 * Tests XMLRPC API by saying, "Hello!" to client.
   248 	 *
   251 	 *
   249 	 * @since 1.5.0
   252 	 * @since 1.5.0
   250 	 *
   253 	 *
   251 	 * @return string Hello string response.
   254 	 * @return string Hello string response.
   252 	 */
   255 	 */
   253 	public function sayHello() {
   256 	public function sayHello() {
   254 		return 'Hello!';
   257 		return 'Hello!';
   255 	}
   258 	}
   256 
   259 
   257 	/**
   260 	/**
   258 	 * Test XMLRPC API by adding two numbers for client.
   261 	 * Tests XMLRPC API by adding two numbers for client.
   259 	 *
   262 	 *
   260 	 * @since 1.5.0
   263 	 * @since 1.5.0
   261 	 *
   264 	 *
   262 	 * @param array $args {
   265 	 * @param array $args {
   263 	 *     Method arguments. Note: arguments must be ordered as documented.
   266 	 *     Method arguments. Note: arguments must be ordered as documented.
   264 	 *
   267 	 *
   265 	 *     @type int $number1 A number to add.
   268 	 *     @type int $0 A number to add.
   266 	 *     @type int $number2 A second number to add.
   269 	 *     @type int $1 A second number to add.
   267 	 * }
   270 	 * }
   268 	 * @return int Sum of the two given numbers.
   271 	 * @return int Sum of the two given numbers.
   269 	 */
   272 	 */
   270 	public function addTwoNumbers( $args ) {
   273 	public function addTwoNumbers( $args ) {
   271 		$number1 = $args[0];
   274 		$number1 = $args[0];
   272 		$number2 = $args[1];
   275 		$number2 = $args[1];
   273 		return $number1 + $number2;
   276 		return $number1 + $number2;
   274 	}
   277 	}
   275 
   278 
   276 	/**
   279 	/**
   277 	 * Log user in.
   280 	 * Logs user in.
   278 	 *
   281 	 *
   279 	 * @since 2.8.0
   282 	 * @since 2.8.0
   280 	 *
   283 	 *
   281 	 * @param string $username User's username.
   284 	 * @param string $username User's username.
   282 	 * @param string $password User's password.
   285 	 * @param string $password User's password.
   283 	 * @return WP_User|false WP_User object if authentication passed, false otherwise
   286 	 * @return WP_User|false WP_User object if authentication passed, false otherwise.
   284 	 */
   287 	 */
   285 	public function login( $username, $password ) {
   288 	public function login( $username, $password ) {
   286 		if ( ! $this->is_enabled ) {
   289 		if ( ! $this->is_enabled ) {
   287 			$this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site.' ) ) );
   290 			$this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site.' ) ) );
   288 			return false;
   291 			return false;
   315 		wp_set_current_user( $user->ID );
   318 		wp_set_current_user( $user->ID );
   316 		return $user;
   319 		return $user;
   317 	}
   320 	}
   318 
   321 
   319 	/**
   322 	/**
   320 	 * Check user's credentials. Deprecated.
   323 	 * Checks user's credentials. Deprecated.
   321 	 *
   324 	 *
   322 	 * @since 1.5.0
   325 	 * @since 1.5.0
   323 	 * @deprecated 2.8.0 Use wp_xmlrpc_server::login()
   326 	 * @deprecated 2.8.0 Use wp_xmlrpc_server::login()
   324 	 * @see wp_xmlrpc_server::login()
   327 	 * @see wp_xmlrpc_server::login()
   325 	 *
   328 	 *
   330 	public function login_pass_ok( $username, $password ) {
   333 	public function login_pass_ok( $username, $password ) {
   331 		return (bool) $this->login( $username, $password );
   334 		return (bool) $this->login( $username, $password );
   332 	}
   335 	}
   333 
   336 
   334 	/**
   337 	/**
   335 	 * Escape string or array of strings for database.
   338 	 * Escapes string or array of strings for database.
   336 	 *
   339 	 *
   337 	 * @since 1.5.2
   340 	 * @since 1.5.2
   338 	 *
   341 	 *
   339 	 * @param string|array $data Escape single string or array of strings.
   342 	 * @param string|array $data Escape single string or array of strings.
   340 	 * @return string|void Returns with string is passed, alters by-reference
   343 	 * @return string|void Returns with string is passed, alters by-reference
   353 			}
   356 			}
   354 		}
   357 		}
   355 	}
   358 	}
   356 
   359 
   357 	/**
   360 	/**
   358 	 * Send error response to client.
   361 	 * Sends error response to client.
   359 	 *
   362 	 *
   360 	 * Send an XML error response to the client. If the endpoint is enabled
   363 	 * Sends an XML error response to the client. If the endpoint is enabled
   361 	 * an HTTP 200 response is always sent per the XML-RPC specification.
   364 	 * an HTTP 200 response is always sent per the XML-RPC specification.
   362 	 *
   365 	 *
   363 	 * @since 5.7.3
   366 	 * @since 5.7.3
   364 	 *
   367 	 *
   365 	 * @param IXR_Error|string $error   Error code or an error object.
   368 	 * @param IXR_Error|string $error   Error code or an error object.
   377 
   380 
   378 		$this->output( $error->getXml() );
   381 		$this->output( $error->getXml() );
   379 	}
   382 	}
   380 
   383 
   381 	/**
   384 	/**
   382 	 * Retrieve custom fields for post.
   385 	 * Retrieves custom fields for post.
   383 	 *
   386 	 *
   384 	 * @since 2.5.0
   387 	 * @since 2.5.0
   385 	 *
   388 	 *
   386 	 * @param int $post_id Post ID.
   389 	 * @param int $post_id Post ID.
   387 	 * @return array Custom fields, if exist.
   390 	 * @return array Custom fields, if exist.
   406 
   409 
   407 		return $custom_fields;
   410 		return $custom_fields;
   408 	}
   411 	}
   409 
   412 
   410 	/**
   413 	/**
   411 	 * Set custom fields for post.
   414 	 * Sets custom fields for post.
   412 	 *
   415 	 *
   413 	 * @since 2.5.0
   416 	 * @since 2.5.0
   414 	 *
   417 	 *
   415 	 * @param int   $post_id Post ID.
   418 	 * @param int   $post_id Post ID.
   416 	 * @param array $fields  Custom fields.
   419 	 * @param array $fields  Custom fields.
   444 			}
   447 			}
   445 		}
   448 		}
   446 	}
   449 	}
   447 
   450 
   448 	/**
   451 	/**
   449 	 * Retrieve custom fields for a term.
   452 	 * Retrieves custom fields for a term.
   450 	 *
   453 	 *
   451 	 * @since 4.9.0
   454 	 * @since 4.9.0
   452 	 *
   455 	 *
   453 	 * @param int $term_id Term ID.
   456 	 * @param int $term_id Term ID.
   454 	 * @return array Array of custom fields, if they exist.
   457 	 * @return array Array of custom fields, if they exist.
   473 
   476 
   474 		return $custom_fields;
   477 		return $custom_fields;
   475 	}
   478 	}
   476 
   479 
   477 	/**
   480 	/**
   478 	 * Set custom fields for a term.
   481 	 * Sets custom fields for a term.
   479 	 *
   482 	 *
   480 	 * @since 4.9.0
   483 	 * @since 4.9.0
   481 	 *
   484 	 *
   482 	 * @param int   $term_id Term ID.
   485 	 * @param int   $term_id Term ID.
   483 	 * @param array $fields  Custom fields.
   486 	 * @param array $fields  Custom fields.
   506 			}
   509 			}
   507 		}
   510 		}
   508 	}
   511 	}
   509 
   512 
   510 	/**
   513 	/**
   511 	 * Set up blog options property.
   514 	 * Sets up blog options property.
   512 	 *
   515 	 *
   513 	 * Passes property through {@see 'xmlrpc_blog_options'} filter.
   516 	 * Passes property through {@see 'xmlrpc_blog_options'} filter.
   514 	 *
   517 	 *
   515 	 * @since 2.6.0
   518 	 * @since 2.6.0
   516 	 */
   519 	 */
   675 		 */
   678 		 */
   676 		$this->blog_options = apply_filters( 'xmlrpc_blog_options', $this->blog_options );
   679 		$this->blog_options = apply_filters( 'xmlrpc_blog_options', $this->blog_options );
   677 	}
   680 	}
   678 
   681 
   679 	/**
   682 	/**
   680 	 * Retrieve the blogs of the user.
   683 	 * Retrieves the blogs of the user.
   681 	 *
   684 	 *
   682 	 * @since 2.6.0
   685 	 * @since 2.6.0
   683 	 *
   686 	 *
   684 	 * @param array $args {
   687 	 * @param array $args {
   685 	 *     Method arguments. Note: arguments must be ordered as documented.
   688 	 *     Method arguments. Note: arguments must be ordered as documented.
   686 	 *
   689 	 *
   687 	 *     @type string $username Username.
   690 	 *     @type string $0 Username.
   688 	 *     @type string $password Password.
   691 	 *     @type string $1 Password.
   689 	 * }
   692 	 * }
   690 	 * @return array|IXR_Error Array contains:
   693 	 * @return array|IXR_Error Array contains:
   691 	 *  - 'isAdmin'
   694 	 *  - 'isAdmin'
   692 	 *  - 'isPrimary' - whether the blog is the user's primary blog
   695 	 *  - 'isPrimary' - whether the blog is the user's primary blog
   693 	 *  - 'url'
   696 	 *  - 'url'
   865 		 */
   868 		 */
   866 		return apply_filters( 'xmlrpc_prepare_term', $_term, $term );
   869 		return apply_filters( 'xmlrpc_prepare_term', $_term, $term );
   867 	}
   870 	}
   868 
   871 
   869 	/**
   872 	/**
   870 	 * Convert a WordPress date string to an IXR_Date object.
   873 	 * Converts a WordPress date string to an IXR_Date object.
   871 	 *
   874 	 *
   872 	 * @param string $date Date string to convert.
   875 	 * @param string $date Date string to convert.
   873 	 * @return IXR_Date IXR_Date object.
   876 	 * @return IXR_Date IXR_Date object.
   874 	 */
   877 	 */
   875 	protected function _convert_date( $date ) {
   878 	protected function _convert_date( $date ) {
   878 		}
   881 		}
   879 		return new IXR_Date( mysql2date( 'Ymd\TH:i:s', $date, false ) );
   882 		return new IXR_Date( mysql2date( 'Ymd\TH:i:s', $date, false ) );
   880 	}
   883 	}
   881 
   884 
   882 	/**
   885 	/**
   883 	 * Convert a WordPress GMT date string to an IXR_Date object.
   886 	 * Converts a WordPress GMT date string to an IXR_Date object.
   884 	 *
   887 	 *
   885 	 * @param string $date_gmt WordPress GMT date string.
   888 	 * @param string $date_gmt WordPress GMT date string.
   886 	 * @param string $date     Date string.
   889 	 * @param string $date     Date string.
   887 	 * @return IXR_Date IXR_Date object.
   890 	 * @return IXR_Date IXR_Date object.
   888 	 */
   891 	 */
  1062 			'title'            => $media_item->post_title,
  1065 			'title'            => $media_item->post_title,
  1063 			'caption'          => $media_item->post_excerpt,
  1066 			'caption'          => $media_item->post_excerpt,
  1064 			'description'      => $media_item->post_content,
  1067 			'description'      => $media_item->post_content,
  1065 			'metadata'         => wp_get_attachment_metadata( $media_item->ID ),
  1068 			'metadata'         => wp_get_attachment_metadata( $media_item->ID ),
  1066 			'type'             => $media_item->post_mime_type,
  1069 			'type'             => $media_item->post_mime_type,
       
  1070 			'alt'              => get_post_meta( $media_item->ID, '_wp_attachment_image_alt', true ),
  1067 		);
  1071 		);
  1068 
  1072 
  1069 		$thumbnail_src = image_downsize( $media_item->ID, $thumbnail_size );
  1073 		$thumbnail_src = image_downsize( $media_item->ID, $thumbnail_size );
  1070 		if ( $thumbnail_src ) {
  1074 		if ( $thumbnail_src ) {
  1071 			$_media_item['thumbnail'] = $thumbnail_src[0];
  1075 			$_media_item['thumbnail'] = $thumbnail_src[0];
  1258 		 */
  1262 		 */
  1259 		return apply_filters( 'xmlrpc_prepare_user', $_user, $user, $fields );
  1263 		return apply_filters( 'xmlrpc_prepare_user', $_user, $user, $fields );
  1260 	}
  1264 	}
  1261 
  1265 
  1262 	/**
  1266 	/**
  1263 	 * Create a new post for any registered post type.
  1267 	 * Creates a new post for any registered post type.
  1264 	 *
  1268 	 *
  1265 	 * @since 3.4.0
  1269 	 * @since 3.4.0
  1266 	 *
  1270 	 *
  1267 	 * @link https://en.wikipedia.org/wiki/RSS_enclosure for information on RSS enclosures.
  1271 	 * @link https://en.wikipedia.org/wiki/RSS_enclosure for information on RSS enclosures.
  1268 	 *
  1272 	 *
  1269 	 * @param array $args {
  1273 	 * @param array $args {
  1270 	 *     Method arguments. Note: top-level arguments must be ordered as documented.
  1274 	 *     Method arguments. Note: top-level arguments must be ordered as documented.
  1271 	 *
  1275 	 *
  1272 	 *     @type int    $blog_id        Blog ID (unused).
  1276 	 *     @type int    $0 Blog ID (unused).
  1273 	 *     @type string $username       Username.
  1277 	 *     @type string $1 Username.
  1274 	 *     @type string $password       Password.
  1278 	 *     @type string $2 Password.
  1275 	 *     @type array  $content_struct {
  1279 	 *     @type array  $3 {
  1276 	 *         Content struct for adding a new post. See wp_insert_post() for information on
  1280 	 *         Content struct for adding a new post. See wp_insert_post() for information on
  1277 	 *         additional post fields
  1281 	 *         additional post fields
  1278 	 *
  1282 	 *
  1279 	 *         @type string $post_type      Post type. Default 'post'.
  1283 	 *         @type string $post_type      Post type. Default 'post'.
  1280 	 *         @type string $post_status    Post status. Default 'draft'
  1284 	 *         @type string $post_status    Post status. Default 'draft'
  1358 	private function _is_greater_than_one( $count ) {
  1362 	private function _is_greater_than_one( $count ) {
  1359 		return $count > 1;
  1363 		return $count > 1;
  1360 	}
  1364 	}
  1361 
  1365 
  1362 	/**
  1366 	/**
  1363 	 * Encapsulate the logic for sticking a post
  1367 	 * Encapsulates the logic for sticking a post and determining if
  1364 	 * and determining if the user has permission to do so
  1368 	 * the user has permission to do so.
  1365 	 *
  1369 	 *
  1366 	 * @since 4.3.0
  1370 	 * @since 4.3.0
  1367 	 *
  1371 	 *
  1368 	 * @param array $post_data
  1372 	 * @param array $post_data
  1369 	 * @param bool  $update
  1373 	 * @param bool  $update
  1409 	 */
  1413 	 */
  1410 	protected function _insert_post( $user, $content_struct ) {
  1414 	protected function _insert_post( $user, $content_struct ) {
  1411 		$defaults = array(
  1415 		$defaults = array(
  1412 			'post_status'    => 'draft',
  1416 			'post_status'    => 'draft',
  1413 			'post_type'      => 'post',
  1417 			'post_type'      => 'post',
  1414 			'post_author'    => null,
  1418 			'post_author'    => 0,
  1415 			'post_password'  => null,
  1419 			'post_password'  => '',
  1416 			'post_excerpt'   => null,
  1420 			'post_excerpt'   => '',
  1417 			'post_content'   => null,
  1421 			'post_content'   => '',
  1418 			'post_title'     => null,
  1422 			'post_title'     => '',
  1419 			'post_date'      => null,
  1423 			'post_date'      => '',
  1420 			'post_date_gmt'  => null,
  1424 			'post_date_gmt'  => '',
  1421 			'post_format'    => null,
  1425 			'post_format'    => null,
  1422 			'post_name'      => null,
  1426 			'post_name'      => null,
  1423 			'post_thumbnail' => null,
  1427 			'post_thumbnail' => null,
  1424 			'post_parent'    => null,
  1428 			'post_parent'    => 0,
  1425 			'ping_status'    => null,
  1429 			'ping_status'    => '',
  1426 			'comment_status' => null,
  1430 			'comment_status' => '',
  1427 			'custom_fields'  => null,
  1431 			'custom_fields'  => null,
  1428 			'terms_names'    => null,
  1432 			'terms_names'    => null,
  1429 			'terms'          => null,
  1433 			'terms'          => null,
  1430 			'sticky'         => null,
  1434 			'sticky'         => null,
  1431 			'enclosure'      => null,
  1435 			'enclosure'      => null,
  1496 			}
  1500 			}
  1497 		} else {
  1501 		} else {
  1498 			$post_data['post_author'] = $user->ID;
  1502 			$post_data['post_author'] = $user->ID;
  1499 		}
  1503 		}
  1500 
  1504 
  1501 		if ( isset( $post_data['comment_status'] ) && 'open' !== $post_data['comment_status'] && 'closed' !== $post_data['comment_status'] ) {
  1505 		if ( 'open' !== $post_data['comment_status'] && 'closed' !== $post_data['comment_status'] ) {
  1502 			unset( $post_data['comment_status'] );
  1506 			unset( $post_data['comment_status'] );
  1503 		}
  1507 		}
  1504 
  1508 
  1505 		if ( isset( $post_data['ping_status'] ) && 'open' !== $post_data['ping_status'] && 'closed' !== $post_data['ping_status'] ) {
  1509 		if ( 'open' !== $post_data['ping_status'] && 'closed' !== $post_data['ping_status'] ) {
  1506 			unset( $post_data['ping_status'] );
  1510 			unset( $post_data['ping_status'] );
  1507 		}
  1511 		}
  1508 
  1512 
  1509 		// Do some timestamp voodoo.
  1513 		// Do some timestamp voodoo.
  1510 		if ( ! empty( $post_data['post_date_gmt'] ) ) {
  1514 		if ( ! empty( $post_data['post_date_gmt'] ) ) {
  1526 		}
  1530 		}
  1527 
  1531 
  1528 		if ( ! isset( $post_data['ID'] ) ) {
  1532 		if ( ! isset( $post_data['ID'] ) ) {
  1529 			$post_data['ID'] = get_default_post_to_edit( $post_data['post_type'], true )->ID;
  1533 			$post_data['ID'] = get_default_post_to_edit( $post_data['post_type'], true )->ID;
  1530 		}
  1534 		}
  1531 		$post_ID = $post_data['ID'];
  1535 		$post_id = $post_data['ID'];
  1532 
  1536 
  1533 		if ( 'post' === $post_data['post_type'] ) {
  1537 		if ( 'post' === $post_data['post_type'] ) {
  1534 			$error = $this->_toggle_sticky( $post_data, $update );
  1538 			$error = $this->_toggle_sticky( $post_data, $update );
  1535 			if ( $error ) {
  1539 			if ( $error ) {
  1536 				return $error;
  1540 				return $error;
  1538 		}
  1542 		}
  1539 
  1543 
  1540 		if ( isset( $post_data['post_thumbnail'] ) ) {
  1544 		if ( isset( $post_data['post_thumbnail'] ) ) {
  1541 			// Empty value deletes, non-empty value adds/updates.
  1545 			// Empty value deletes, non-empty value adds/updates.
  1542 			if ( ! $post_data['post_thumbnail'] ) {
  1546 			if ( ! $post_data['post_thumbnail'] ) {
  1543 				delete_post_thumbnail( $post_ID );
  1547 				delete_post_thumbnail( $post_id );
  1544 			} elseif ( ! get_post( absint( $post_data['post_thumbnail'] ) ) ) {
  1548 			} elseif ( ! get_post( absint( $post_data['post_thumbnail'] ) ) ) {
  1545 				return new IXR_Error( 404, __( 'Invalid attachment ID.' ) );
  1549 				return new IXR_Error( 404, __( 'Invalid attachment ID.' ) );
  1546 			}
  1550 			}
  1547 			set_post_thumbnail( $post_ID, $post_data['post_thumbnail'] );
  1551 			set_post_thumbnail( $post_id, $post_data['post_thumbnail'] );
  1548 			unset( $content_struct['post_thumbnail'] );
  1552 			unset( $content_struct['post_thumbnail'] );
  1549 		}
  1553 		}
  1550 
  1554 
  1551 		if ( isset( $post_data['custom_fields'] ) ) {
  1555 		if ( isset( $post_data['custom_fields'] ) ) {
  1552 			$this->set_custom_fields( $post_ID, $post_data['custom_fields'] );
  1556 			$this->set_custom_fields( $post_id, $post_data['custom_fields'] );
  1553 		}
  1557 		}
  1554 
  1558 
  1555 		if ( isset( $post_data['terms'] ) || isset( $post_data['terms_names'] ) ) {
  1559 		if ( isset( $post_data['terms'] ) || isset( $post_data['terms_names'] ) ) {
  1556 			$post_type_taxonomies = get_object_taxonomies( $post_data['post_type'], 'objects' );
  1560 			$post_type_taxonomies = get_object_taxonomies( $post_data['post_type'], 'objects' );
  1557 
  1561 
  1653 			$post_data['tax_input'] = $terms;
  1657 			$post_data['tax_input'] = $terms;
  1654 			unset( $post_data['terms'], $post_data['terms_names'] );
  1658 			unset( $post_data['terms'], $post_data['terms_names'] );
  1655 		}
  1659 		}
  1656 
  1660 
  1657 		if ( isset( $post_data['post_format'] ) ) {
  1661 		if ( isset( $post_data['post_format'] ) ) {
  1658 			$format = set_post_format( $post_ID, $post_data['post_format'] );
  1662 			$format = set_post_format( $post_id, $post_data['post_format'] );
  1659 
  1663 
  1660 			if ( is_wp_error( $format ) ) {
  1664 			if ( is_wp_error( $format ) ) {
  1661 				return new IXR_Error( 500, $format->get_error_message() );
  1665 				return new IXR_Error( 500, $format->get_error_message() );
  1662 			}
  1666 			}
  1663 
  1667 
  1664 			unset( $post_data['post_format'] );
  1668 			unset( $post_data['post_format'] );
  1665 		}
  1669 		}
  1666 
  1670 
  1667 		// Handle enclosures.
  1671 		// Handle enclosures.
  1668 		$enclosure = isset( $post_data['enclosure'] ) ? $post_data['enclosure'] : null;
  1672 		$enclosure = isset( $post_data['enclosure'] ) ? $post_data['enclosure'] : null;
  1669 		$this->add_enclosure_if_new( $post_ID, $enclosure );
  1673 		$this->add_enclosure_if_new( $post_id, $enclosure );
  1670 
  1674 
  1671 		$this->attach_uploads( $post_ID, $post_data['post_content'] );
  1675 		$this->attach_uploads( $post_id, $post_data['post_content'] );
  1672 
  1676 
  1673 		/**
  1677 		/**
  1674 		 * Filters post data array to be inserted via XML-RPC.
  1678 		 * Filters post data array to be inserted via XML-RPC.
  1675 		 *
  1679 		 *
  1676 		 * @since 3.4.0
  1680 		 * @since 3.4.0
  1678 		 * @param array $post_data      Parsed array of post data.
  1682 		 * @param array $post_data      Parsed array of post data.
  1679 		 * @param array $content_struct Post data array.
  1683 		 * @param array $content_struct Post data array.
  1680 		 */
  1684 		 */
  1681 		$post_data = apply_filters( 'xmlrpc_wp_insert_post_data', $post_data, $content_struct );
  1685 		$post_data = apply_filters( 'xmlrpc_wp_insert_post_data', $post_data, $content_struct );
  1682 
  1686 
  1683 		$post_ID = $update ? wp_update_post( $post_data, true ) : wp_insert_post( $post_data, true );
  1687 		// Remove all null values to allow for using the insert/update post default values for those keys instead.
  1684 		if ( is_wp_error( $post_ID ) ) {
  1688 		$post_data = array_filter(
  1685 			return new IXR_Error( 500, $post_ID->get_error_message() );
  1689 			$post_data,
  1686 		}
  1690 			static function ( $value ) {
  1687 
  1691 				return null !== $value;
  1688 		if ( ! $post_ID ) {
  1692 			}
       
  1693 		);
       
  1694 
       
  1695 		$post_id = $update ? wp_update_post( $post_data, true ) : wp_insert_post( $post_data, true );
       
  1696 		if ( is_wp_error( $post_id ) ) {
       
  1697 			return new IXR_Error( 500, $post_id->get_error_message() );
       
  1698 		}
       
  1699 
       
  1700 		if ( ! $post_id ) {
  1689 			if ( $update ) {
  1701 			if ( $update ) {
  1690 				return new IXR_Error( 401, __( 'Sorry, the post could not be updated.' ) );
  1702 				return new IXR_Error( 401, __( 'Sorry, the post could not be updated.' ) );
  1691 			} else {
  1703 			} else {
  1692 				return new IXR_Error( 401, __( 'Sorry, the post could not be created.' ) );
  1704 				return new IXR_Error( 401, __( 'Sorry, the post could not be created.' ) );
  1693 			}
  1705 			}
  1694 		}
  1706 		}
  1695 
  1707 
  1696 		return (string) $post_ID;
  1708 		return (string) $post_id;
  1697 	}
  1709 	}
  1698 
  1710 
  1699 	/**
  1711 	/**
  1700 	 * Edit a post for any registered post type.
  1712 	 * Edits a post for any registered post type.
  1701 	 *
  1713 	 *
  1702 	 * The $content_struct parameter only needs to contain fields that
  1714 	 * The $content_struct parameter only needs to contain fields that
  1703 	 * should be changed. All other fields will retain their existing values.
  1715 	 * should be changed. All other fields will retain their existing values.
  1704 	 *
  1716 	 *
  1705 	 * @since 3.4.0
  1717 	 * @since 3.4.0
  1706 	 *
  1718 	 *
  1707 	 * @param array $args {
  1719 	 * @param array $args {
  1708 	 *     Method arguments. Note: arguments must be ordered as documented.
  1720 	 *     Method arguments. Note: arguments must be ordered as documented.
  1709 	 *
  1721 	 *
  1710 	 *     @type int    $blog_id        Blog ID (unused).
  1722 	 *     @type int    $0 Blog ID (unused).
  1711 	 *     @type string $username       Username.
  1723 	 *     @type string $1 Username.
  1712 	 *     @type string $password       Password.
  1724 	 *     @type string $2 Password.
  1713 	 *     @type int    $post_id        Post ID.
  1725 	 *     @type int    $3 Post ID.
  1714 	 *     @type array  $content_struct Extra content arguments.
  1726 	 *     @type array  $4 Extra content arguments.
  1715 	 * }
  1727 	 * }
  1716 	 * @return true|IXR_Error True on success, IXR_Error on failure.
  1728 	 * @return true|IXR_Error True on success, IXR_Error on failure.
  1717 	 */
  1729 	 */
  1718 	public function wp_editPost( $args ) {
  1730 	public function wp_editPost( $args ) {
  1719 		if ( ! $this->minimum_args( $args, 5 ) ) {
  1731 		if ( ! $this->minimum_args( $args, 5 ) ) {
  1781 
  1793 
  1782 		return true;
  1794 		return true;
  1783 	}
  1795 	}
  1784 
  1796 
  1785 	/**
  1797 	/**
  1786 	 * Delete a post for any registered post type.
  1798 	 * Deletes a post for any registered post type.
  1787 	 *
  1799 	 *
  1788 	 * @since 3.4.0
  1800 	 * @since 3.4.0
  1789 	 *
  1801 	 *
  1790 	 * @see wp_delete_post()
  1802 	 * @see wp_delete_post()
  1791 	 *
  1803 	 *
  1792 	 * @param array $args {
  1804 	 * @param array $args {
  1793 	 *     Method arguments. Note: arguments must be ordered as documented.
  1805 	 *     Method arguments. Note: arguments must be ordered as documented.
  1794 	 *
  1806 	 *
  1795 	 *     @type int    $blog_id  Blog ID (unused).
  1807 	 *     @type int    $0 Blog ID (unused).
  1796 	 *     @type string $username Username.
  1808 	 *     @type string $1 Username.
  1797 	 *     @type string $password Password.
  1809 	 *     @type string $2 Password.
  1798 	 *     @type int    $post_id  Post ID.
  1810 	 *     @type int    $3 Post ID.
  1799 	 * }
  1811 	 * }
  1800 	 * @return true|IXR_Error True on success, IXR_Error instance on failure.
  1812 	 * @return true|IXR_Error True on success, IXR_Error instance on failure.
  1801 	 */
  1813 	 */
  1802 	public function wp_deletePost( $args ) {
  1814 	public function wp_deletePost( $args ) {
  1803 		if ( ! $this->minimum_args( $args, 4 ) ) {
  1815 		if ( ! $this->minimum_args( $args, 4 ) ) {
  1835 
  1847 
  1836 		return true;
  1848 		return true;
  1837 	}
  1849 	}
  1838 
  1850 
  1839 	/**
  1851 	/**
  1840 	 * Retrieve a post.
  1852 	 * Retrieves a post.
  1841 	 *
  1853 	 *
  1842 	 * @since 3.4.0
  1854 	 * @since 3.4.0
  1843 	 *
  1855 	 *
  1844 	 * The optional $fields parameter specifies what fields will be included
  1856 	 * The optional $fields parameter specifies what fields will be included
  1845 	 * in the response array. This should be a list of field names. 'post_id' will
  1857 	 * in the response array. This should be a list of field names. 'post_id' will
  1853 	 * @see get_post()
  1865 	 * @see get_post()
  1854 	 *
  1866 	 *
  1855 	 * @param array $args {
  1867 	 * @param array $args {
  1856 	 *     Method arguments. Note: arguments must be ordered as documented.
  1868 	 *     Method arguments. Note: arguments must be ordered as documented.
  1857 	 *
  1869 	 *
  1858 	 *     @type int    $blog_id  Blog ID (unused).
  1870 	 *     @type int    $0 Blog ID (unused).
  1859 	 *     @type string $username Username.
  1871 	 *     @type string $1 Username.
  1860 	 *     @type string $password Password.
  1872 	 *     @type string $2 Password.
  1861 	 *     @type int    $post_id  Post ID.
  1873 	 *     @type int    $3 Post ID.
  1862 	 *     @type array  $fields   The subset of post type fields to return.
  1874 	 *     @type array  $4 Optional. The subset of post type fields to return.
  1863 	 * }
  1875 	 * }
  1864 	 * @return array|IXR_Error Array contains (based on $fields parameter):
  1876 	 * @return array|IXR_Error Array contains (based on $fields parameter):
  1865 	 *  - 'post_id'
  1877 	 *  - 'post_id'
  1866 	 *  - 'post_title'
  1878 	 *  - 'post_title'
  1867 	 *  - 'post_date'
  1879 	 *  - 'post_date'
  1898 
  1910 
  1899 		if ( isset( $args[4] ) ) {
  1911 		if ( isset( $args[4] ) ) {
  1900 			$fields = $args[4];
  1912 			$fields = $args[4];
  1901 		} else {
  1913 		} else {
  1902 			/**
  1914 			/**
  1903 			 * Filters the list of post query fields used by the given XML-RPC method.
  1915 			 * Filters the default post query fields used by the given XML-RPC method.
  1904 			 *
  1916 			 *
  1905 			 * @since 3.4.0
  1917 			 * @since 3.4.0
  1906 			 *
  1918 			 *
  1907 			 * @param array  $fields Array of post fields. Default array contains 'post', 'terms', and 'custom_fields'.
  1919 			 * @param array  $fields An array of post fields to retrieve. By default,
       
  1920 			 *                       contains 'post', 'terms', and 'custom_fields'.
  1908 			 * @param string $method Method name.
  1921 			 * @param string $method Method name.
  1909 			 */
  1922 			 */
  1910 			$fields = apply_filters( 'xmlrpc_default_post_fields', array( 'post', 'terms', 'custom_fields' ), 'wp.getPost' );
  1923 			$fields = apply_filters( 'xmlrpc_default_post_fields', array( 'post', 'terms', 'custom_fields' ), 'wp.getPost' );
  1911 		}
  1924 		}
  1912 
  1925 
  1930 
  1943 
  1931 		return $this->_prepare_post( $post, $fields );
  1944 		return $this->_prepare_post( $post, $fields );
  1932 	}
  1945 	}
  1933 
  1946 
  1934 	/**
  1947 	/**
  1935 	 * Retrieve posts.
  1948 	 * Retrieves posts.
  1936 	 *
  1949 	 *
  1937 	 * @since 3.4.0
  1950 	 * @since 3.4.0
  1938 	 *
  1951 	 *
  1939 	 * @see wp_get_recent_posts()
  1952 	 * @see wp_get_recent_posts()
  1940 	 * @see wp_getPost() for more on `$fields`
  1953 	 * @see wp_getPost() for more on `$fields`
  1941 	 * @see get_posts() for more on `$filter` values
  1954 	 * @see get_posts() for more on `$filter` values
  1942 	 *
  1955 	 *
  1943 	 * @param array $args {
  1956 	 * @param array $args {
  1944 	 *     Method arguments. Note: arguments must be ordered as documented.
  1957 	 *     Method arguments. Note: arguments must be ordered as documented.
  1945 	 *
  1958 	 *
  1946 	 *     @type int    $blog_id  Blog ID (unused).
  1959 	 *     @type int    $0 Blog ID (unused).
  1947 	 *     @type string $username Username.
  1960 	 *     @type string $1 Username.
  1948 	 *     @type string $password Password.
  1961 	 *     @type string $2 Password.
  1949 	 *     @type array  $filter   Optional. Modifies the query used to retrieve posts. Accepts 'post_type',
  1962 	 *     @type array  $3 Optional. Modifies the query used to retrieve posts. Accepts 'post_type',
  1950 	 *                            'post_status', 'number', 'offset', 'orderby', 's', and 'order'.
  1963 	 *                     'post_status', 'number', 'offset', 'orderby', 's', and 'order'.
  1951 	 *                            Default empty array.
  1964 	 *                     Default empty array.
  1952 	 *     @type array  $fields   Optional. The subset of post type fields to return in the response array.
  1965 	 *     @type array  $4 Optional. The subset of post type fields to return in the response array.
  1953 	 * }
  1966 	 * }
  1954 	 * @return array|IXR_Error Array contains a collection of posts.
  1967 	 * @return array|IXR_Error Array containing a collection of posts.
  1955 	 */
  1968 	 */
  1956 	public function wp_getPosts( $args ) {
  1969 	public function wp_getPosts( $args ) {
  1957 		if ( ! $this->minimum_args( $args, 3 ) ) {
  1970 		if ( ! $this->minimum_args( $args, 3 ) ) {
  1958 			return $this->error;
  1971 			return $this->error;
  1959 		}
  1972 		}
  2039 
  2052 
  2040 		return $struct;
  2053 		return $struct;
  2041 	}
  2054 	}
  2042 
  2055 
  2043 	/**
  2056 	/**
  2044 	 * Create a new term.
  2057 	 * Creates a new term.
  2045 	 *
  2058 	 *
  2046 	 * @since 3.4.0
  2059 	 * @since 3.4.0
  2047 	 *
  2060 	 *
  2048 	 * @see wp_insert_term()
  2061 	 * @see wp_insert_term()
  2049 	 *
  2062 	 *
  2050 	 * @param array $args {
  2063 	 * @param array $args {
  2051 	 *     Method arguments. Note: arguments must be ordered as documented.
  2064 	 *     Method arguments. Note: arguments must be ordered as documented.
  2052 	 *
  2065 	 *
  2053 	 *     @type int    $blog_id        Blog ID (unused).
  2066 	 *     @type int    $0 Blog ID (unused).
  2054 	 *     @type string $username       Username.
  2067 	 *     @type string $1 Username.
  2055 	 *     @type string $password       Password.
  2068 	 *     @type string $2 Password.
  2056 	 *     @type array  $content_struct Content struct for adding a new term. The struct must contain
  2069 	 *     @type array  $3 Content struct for adding a new term. The struct must contain
  2057 	 *                                  the term 'name' and 'taxonomy'. Optional accepted values include
  2070 	 *                     the term 'name' and 'taxonomy'. Optional accepted values include
  2058 	 *                                  'parent', 'description', and 'slug'.
  2071 	 *                     'parent', 'description', and 'slug'.
  2059 	 * }
  2072 	 * }
  2060 	 * @return int|IXR_Error The term ID on success, or an IXR_Error object on failure.
  2073 	 * @return int|IXR_Error The term ID on success, or an IXR_Error object on failure.
  2061 	 */
  2074 	 */
  2062 	public function wp_newTerm( $args ) {
  2075 	public function wp_newTerm( $args ) {
  2063 		if ( ! $this->minimum_args( $args, 4 ) ) {
  2076 		if ( ! $this->minimum_args( $args, 4 ) ) {
  2142 
  2155 
  2143 		return (string) $term['term_id'];
  2156 		return (string) $term['term_id'];
  2144 	}
  2157 	}
  2145 
  2158 
  2146 	/**
  2159 	/**
  2147 	 * Edit a term.
  2160 	 * Edits a term.
  2148 	 *
  2161 	 *
  2149 	 * @since 3.4.0
  2162 	 * @since 3.4.0
  2150 	 *
  2163 	 *
  2151 	 * @see wp_update_term()
  2164 	 * @see wp_update_term()
  2152 	 *
  2165 	 *
  2153 	 * @param array $args {
  2166 	 * @param array $args {
  2154 	 *     Method arguments. Note: arguments must be ordered as documented.
  2167 	 *     Method arguments. Note: arguments must be ordered as documented.
  2155 	 *
  2168 	 *
  2156 	 *     @type int    $blog_id        Blog ID (unused).
  2169 	 *     @type int    $0 Blog ID (unused).
  2157 	 *     @type string $username       Username.
  2170 	 *     @type string $1 Username.
  2158 	 *     @type string $password       Password.
  2171 	 *     @type string $2 Password.
  2159 	 *     @type int    $term_id        Term ID.
  2172 	 *     @type int    $3 Term ID.
  2160 	 *     @type array  $content_struct Content struct for editing a term. The struct must contain the
  2173 	 *     @type array  $4 Content struct for editing a term. The struct must contain the
  2161 	 *                                  term ''taxonomy'. Optional accepted values include 'name', 'parent',
  2174 	 *                     term 'taxonomy'. Optional accepted values include 'name', 'parent',
  2162 	 *                                  'description', and 'slug'.
  2175 	 *                     'description', and 'slug'.
  2163 	 * }
  2176 	 * }
  2164 	 * @return true|IXR_Error True on success, IXR_Error instance on failure.
  2177 	 * @return true|IXR_Error True on success, IXR_Error instance on failure.
  2165 	 */
  2178 	 */
  2166 	public function wp_editTerm( $args ) {
  2179 	public function wp_editTerm( $args ) {
  2167 		if ( ! $this->minimum_args( $args, 5 ) ) {
  2180 		if ( ! $this->minimum_args( $args, 5 ) ) {
  2260 
  2273 
  2261 		return true;
  2274 		return true;
  2262 	}
  2275 	}
  2263 
  2276 
  2264 	/**
  2277 	/**
  2265 	 * Delete a term.
  2278 	 * Deletes a term.
  2266 	 *
  2279 	 *
  2267 	 * @since 3.4.0
  2280 	 * @since 3.4.0
  2268 	 *
  2281 	 *
  2269 	 * @see wp_delete_term()
  2282 	 * @see wp_delete_term()
  2270 	 *
  2283 	 *
  2271 	 * @param array $args {
  2284 	 * @param array $args {
  2272 	 *     Method arguments. Note: arguments must be ordered as documented.
  2285 	 *     Method arguments. Note: arguments must be ordered as documented.
  2273 	 *
  2286 	 *
  2274 	 *     @type int    $blog_id       Blog ID (unused).
  2287 	 *     @type int    $0 Blog ID (unused).
  2275 	 *     @type string $username      Username.
  2288 	 *     @type string $1 Username.
  2276 	 *     @type string $password      Password.
  2289 	 *     @type string $2 Password.
  2277 	 *     @type string $taxonomy_name Taxonomy name.
  2290 	 *     @type string $3 Taxonomy name.
  2278 	 *     @type int    $term_id       Term ID.
  2291 	 *     @type int    $4 Term ID.
  2279 	 * }
  2292 	 * }
  2280 	 * @return true|IXR_Error True on success, IXR_Error instance on failure.
  2293 	 * @return true|IXR_Error True on success, IXR_Error instance on failure.
  2281 	 */
  2294 	 */
  2282 	public function wp_deleteTerm( $args ) {
  2295 	public function wp_deleteTerm( $args ) {
  2283 		if ( ! $this->minimum_args( $args, 5 ) ) {
  2296 		if ( ! $this->minimum_args( $args, 5 ) ) {
  2330 
  2343 
  2331 		return $result;
  2344 		return $result;
  2332 	}
  2345 	}
  2333 
  2346 
  2334 	/**
  2347 	/**
  2335 	 * Retrieve a term.
  2348 	 * Retrieves a term.
  2336 	 *
  2349 	 *
  2337 	 * @since 3.4.0
  2350 	 * @since 3.4.0
  2338 	 *
  2351 	 *
  2339 	 * @see get_term()
  2352 	 * @see get_term()
  2340 	 *
  2353 	 *
  2341 	 * @param array $args {
  2354 	 * @param array $args {
  2342 	 *     Method arguments. Note: arguments must be ordered as documented.
  2355 	 *     Method arguments. Note: arguments must be ordered as documented.
  2343 	 *
  2356 	 *
  2344 	 *     @type int    $blog_id  Blog ID (unused).
  2357 	 *     @type int    $0 Blog ID (unused).
  2345 	 *     @type string $username Username.
  2358 	 *     @type string $1 Username.
  2346 	 *     @type string $password Password.
  2359 	 *     @type string $2 Password.
  2347 	 *     @type string $taxonomy Taxonomy name.
  2360 	 *     @type string $3 Taxonomy name.
  2348 	 *     @type string $term_id  Term ID.
  2361 	 *     @type int    $4 Term ID.
  2349 	 * }
  2362 	 * }
  2350 	 * @return array|IXR_Error IXR_Error on failure, array on success, containing:
  2363 	 * @return array|IXR_Error IXR_Error on failure, array on success, containing:
  2351 	 *  - 'term_id'
  2364 	 *  - 'term_id'
  2352 	 *  - 'name'
  2365 	 *  - 'name'
  2353 	 *  - 'slug'
  2366 	 *  - 'slug'
  2400 
  2413 
  2401 		return $this->_prepare_term( $term );
  2414 		return $this->_prepare_term( $term );
  2402 	}
  2415 	}
  2403 
  2416 
  2404 	/**
  2417 	/**
  2405 	 * Retrieve all terms for a taxonomy.
  2418 	 * Retrieves all terms for a taxonomy.
  2406 	 *
  2419 	 *
  2407 	 * @since 3.4.0
  2420 	 * @since 3.4.0
  2408 	 *
  2421 	 *
  2409 	 * The optional $filter parameter modifies the query used to retrieve terms.
  2422 	 * The optional $filter parameter modifies the query used to retrieve terms.
  2410 	 * Accepted keys are 'number', 'offset', 'orderby', 'order', 'hide_empty', and 'search'.
  2423 	 * Accepted keys are 'number', 'offset', 'orderby', 'order', 'hide_empty', and 'search'.
  2412 	 * @see get_terms()
  2425 	 * @see get_terms()
  2413 	 *
  2426 	 *
  2414 	 * @param array $args {
  2427 	 * @param array $args {
  2415 	 *     Method arguments. Note: arguments must be ordered as documented.
  2428 	 *     Method arguments. Note: arguments must be ordered as documented.
  2416 	 *
  2429 	 *
  2417 	 *     @type int    $blog_id  Blog ID (unused).
  2430 	 *     @type int    $0 Blog ID (unused).
  2418 	 *     @type string $username Username.
  2431 	 *     @type string $1 Username.
  2419 	 *     @type string $password Password.
  2432 	 *     @type string $2 Password.
  2420 	 *     @type string $taxonomy Taxonomy name.
  2433 	 *     @type string $3 Taxonomy name.
  2421 	 *     @type array  $filter   Optional. Modifies the query used to retrieve posts. Accepts 'number',
  2434 	 *     @type array  $4 Optional. Modifies the query used to retrieve posts. Accepts 'number',
  2422 	 *                            'offset', 'orderby', 'order', 'hide_empty', and 'search'. Default empty array.
  2435 	 *                     'offset', 'orderby', 'order', 'hide_empty', and 'search'. Default empty array.
  2423 	 * }
  2436 	 * }
  2424 	 * @return array|IXR_Error An associative array of terms data on success, IXR_Error instance otherwise.
  2437 	 * @return array|IXR_Error An associative array of terms data on success, IXR_Error instance otherwise.
  2425 	 */
  2438 	 */
  2426 	public function wp_getTerms( $args ) {
  2439 	public function wp_getTerms( $args ) {
  2427 		if ( ! $this->minimum_args( $args, 4 ) ) {
  2440 		if ( ! $this->minimum_args( $args, 4 ) ) {
  2495 
  2508 
  2496 		return $struct;
  2509 		return $struct;
  2497 	}
  2510 	}
  2498 
  2511 
  2499 	/**
  2512 	/**
  2500 	 * Retrieve a taxonomy.
  2513 	 * Retrieves a taxonomy.
  2501 	 *
  2514 	 *
  2502 	 * @since 3.4.0
  2515 	 * @since 3.4.0
  2503 	 *
  2516 	 *
  2504 	 * @see get_taxonomy()
  2517 	 * @see get_taxonomy()
  2505 	 *
  2518 	 *
  2506 	 * @param array $args {
  2519 	 * @param array $args {
  2507 	 *     Method arguments. Note: arguments must be ordered as documented.
  2520 	 *     Method arguments. Note: arguments must be ordered as documented.
  2508 	 *
  2521 	 *
  2509 	 *     @type int    $blog_id  Blog ID (unused).
  2522 	 *     @type int    $0 Blog ID (unused).
  2510 	 *     @type string $username Username.
  2523 	 *     @type string $1 Username.
  2511 	 *     @type string $password Password.
  2524 	 *     @type string $2 Password.
  2512 	 *     @type string $taxonomy Taxonomy name.
  2525 	 *     @type string $3 Taxonomy name.
  2513 	 *     @type array  $fields   Optional. Array of taxonomy fields to limit to in the return.
  2526 	 *     @type array  $4 Optional. Array of taxonomy fields to limit to in the return.
  2514 	 *                            Accepts 'labels', 'cap', 'menu', and 'object_type'.
  2527 	 *                     Accepts 'labels', 'cap', 'menu', and 'object_type'.
  2515 	 *                            Default empty array.
  2528 	 *                     Default empty array.
  2516 	 * }
  2529 	 * }
  2517 	 * @return array|IXR_Error An array of taxonomy data on success, IXR_Error instance otherwise.
  2530 	 * @return array|IXR_Error An array of taxonomy data on success, IXR_Error instance otherwise.
  2518 	 */
  2531 	 */
  2519 	public function wp_getTaxonomy( $args ) {
  2532 	public function wp_getTaxonomy( $args ) {
  2520 		if ( ! $this->minimum_args( $args, 4 ) ) {
  2533 		if ( ! $this->minimum_args( $args, 4 ) ) {
  2529 
  2542 
  2530 		if ( isset( $args[4] ) ) {
  2543 		if ( isset( $args[4] ) ) {
  2531 			$fields = $args[4];
  2544 			$fields = $args[4];
  2532 		} else {
  2545 		} else {
  2533 			/**
  2546 			/**
  2534 			 * Filters the taxonomy query fields used by the given XML-RPC method.
  2547 			 * Filters the default taxonomy query fields used by the given XML-RPC method.
  2535 			 *
  2548 			 *
  2536 			 * @since 3.4.0
  2549 			 * @since 3.4.0
  2537 			 *
  2550 			 *
  2538 			 * @param array  $fields An array of taxonomy fields to retrieve.
  2551 			 * @param array  $fields An array of taxonomy fields to retrieve. By default,
       
  2552 			 *                       contains 'labels', 'cap', and 'object_type'.
  2539 			 * @param string $method The method name.
  2553 			 * @param string $method The method name.
  2540 			 */
  2554 			 */
  2541 			$fields = apply_filters( 'xmlrpc_default_taxonomy_fields', array( 'labels', 'cap', 'object_type' ), 'wp.getTaxonomy' );
  2555 			$fields = apply_filters( 'xmlrpc_default_taxonomy_fields', array( 'labels', 'cap', 'object_type' ), 'wp.getTaxonomy' );
  2542 		}
  2556 		}
  2543 
  2557 
  2561 
  2575 
  2562 		return $this->_prepare_taxonomy( $taxonomy, $fields );
  2576 		return $this->_prepare_taxonomy( $taxonomy, $fields );
  2563 	}
  2577 	}
  2564 
  2578 
  2565 	/**
  2579 	/**
  2566 	 * Retrieve all taxonomies.
  2580 	 * Retrieves all taxonomies.
  2567 	 *
  2581 	 *
  2568 	 * @since 3.4.0
  2582 	 * @since 3.4.0
  2569 	 *
  2583 	 *
  2570 	 * @see get_taxonomies()
  2584 	 * @see get_taxonomies()
  2571 	 *
  2585 	 *
  2572 	 * @param array $args {
  2586 	 * @param array $args {
  2573 	 *     Method arguments. Note: arguments must be ordered as documented.
  2587 	 *     Method arguments. Note: arguments must be ordered as documented.
  2574 	 *
  2588 	 *
  2575 	 *     @type int    $blog_id  Blog ID (unused).
  2589 	 *     @type int    $0 Blog ID (unused).
  2576 	 *     @type string $username Username.
  2590 	 *     @type string $1 Username.
  2577 	 *     @type string $password Password.
  2591 	 *     @type string $2 Password.
  2578 	 *     @type array  $filter   Optional. An array of arguments for retrieving taxonomies.
  2592 	 *     @type array  $3 Optional. An array of arguments for retrieving taxonomies.
  2579 	 *     @type array  $fields   Optional. The subset of taxonomy fields to return.
  2593 	 *     @type array  $4 Optional. The subset of taxonomy fields to return.
  2580 	 * }
  2594 	 * }
  2581 	 * @return array|IXR_Error An associative array of taxonomy data with returned fields determined
  2595 	 * @return array|IXR_Error An associative array of taxonomy data with returned fields determined
  2582 	 *                         by `$fields`, or an IXR_Error instance on failure.
  2596 	 *                         by `$fields`, or an IXR_Error instance on failure.
  2583 	 */
  2597 	 */
  2584 	public function wp_getTaxonomies( $args ) {
  2598 	public function wp_getTaxonomies( $args ) {
  2623 
  2637 
  2624 		return $struct;
  2638 		return $struct;
  2625 	}
  2639 	}
  2626 
  2640 
  2627 	/**
  2641 	/**
  2628 	 * Retrieve a user.
  2642 	 * Retrieves a user.
  2629 	 *
  2643 	 *
  2630 	 * The optional $fields parameter specifies what fields will be included
  2644 	 * The optional $fields parameter specifies what fields will be included
  2631 	 * in the response array. This should be a list of field names. 'user_id' will
  2645 	 * in the response array. This should be a list of field names. 'user_id' will
  2632 	 * always be included in the response regardless of the value of $fields.
  2646 	 * always be included in the response regardless of the value of $fields.
  2633 	 *
  2647 	 *
  2638 	 * @uses get_userdata()
  2652 	 * @uses get_userdata()
  2639 	 *
  2653 	 *
  2640 	 * @param array $args {
  2654 	 * @param array $args {
  2641 	 *     Method arguments. Note: arguments must be ordered as documented.
  2655 	 *     Method arguments. Note: arguments must be ordered as documented.
  2642 	 *
  2656 	 *
  2643 	 *     @type int    $blog_id (unused)
  2657 	 *     @type int    $0 Blog ID (unused).
  2644 	 *     @type string $username
  2658 	 *     @type string $1 Username.
  2645 	 *     @type string $password
  2659 	 *     @type string $2 Password.
  2646 	 *     @type int    $user_id
  2660 	 *     @type int    $3 User ID.
  2647 	 *     @type array  $fields (optional)
  2661 	 *     @type array  $4 Optional. Array of fields to return.
  2648 	 * }
  2662 	 * }
  2649 	 * @return array|IXR_Error Array contains (based on $fields parameter):
  2663 	 * @return array|IXR_Error Array contains (based on $fields parameter):
  2650 	 *  - 'user_id'
  2664 	 *  - 'user_id'
  2651 	 *  - 'username'
  2665 	 *  - 'username'
  2652 	 *  - 'first_name'
  2666 	 *  - 'first_name'
  2677 			/**
  2691 			/**
  2678 			 * Filters the default user query fields used by the given XML-RPC method.
  2692 			 * Filters the default user query fields used by the given XML-RPC method.
  2679 			 *
  2693 			 *
  2680 			 * @since 3.5.0
  2694 			 * @since 3.5.0
  2681 			 *
  2695 			 *
  2682 			 * @param array  $fields User query fields for given method. Default 'all'.
  2696 			 * @param array  $fields An array of user fields to retrieve. By default, contains 'all'.
  2683 			 * @param string $method The method name.
  2697 			 * @param string $method The method name.
  2684 			 */
  2698 			 */
  2685 			$fields = apply_filters( 'xmlrpc_default_user_fields', array( 'all' ), 'wp.getUser' );
  2699 			$fields = apply_filters( 'xmlrpc_default_user_fields', array( 'all' ), 'wp.getUser' );
  2686 		}
  2700 		}
  2687 
  2701 
  2705 
  2719 
  2706 		return $this->_prepare_user( $user_data, $fields );
  2720 		return $this->_prepare_user( $user_data, $fields );
  2707 	}
  2721 	}
  2708 
  2722 
  2709 	/**
  2723 	/**
  2710 	 * Retrieve users.
  2724 	 * Retrieves users.
  2711 	 *
  2725 	 *
  2712 	 * The optional $filter parameter modifies the query used to retrieve users.
  2726 	 * The optional $filter parameter modifies the query used to retrieve users.
  2713 	 * Accepted keys are 'number' (default: 50), 'offset' (default: 0), 'role',
  2727 	 * Accepted keys are 'number' (default: 50), 'offset' (default: 0), 'role',
  2714 	 * 'who', 'orderby', and 'order'.
  2728 	 * 'who', 'orderby', and 'order'.
  2715 	 *
  2729 	 *
  2720 	 * @see wp_getUser() for more on $fields and return values
  2734 	 * @see wp_getUser() for more on $fields and return values
  2721 	 *
  2735 	 *
  2722 	 * @param array $args {
  2736 	 * @param array $args {
  2723 	 *     Method arguments. Note: arguments must be ordered as documented.
  2737 	 *     Method arguments. Note: arguments must be ordered as documented.
  2724 	 *
  2738 	 *
  2725 	 *     @type int    $blog_id (unused)
  2739 	 *     @type int    $0 Blog ID (unused).
  2726 	 *     @type string $username
  2740 	 *     @type string $1 Username.
  2727 	 *     @type string $password
  2741 	 *     @type string $2 Password.
  2728 	 *     @type array  $filter (optional)
  2742 	 *     @type array  $3 Optional. Arguments for the user query.
  2729 	 *     @type array  $fields (optional)
  2743 	 *     @type array  $4 Optional. Fields to return.
  2730 	 * }
  2744 	 * }
  2731 	 * @return array|IXR_Error users data
  2745 	 * @return array|IXR_Error users data
  2732 	 */
  2746 	 */
  2733 	public function wp_getUsers( $args ) {
  2747 	public function wp_getUsers( $args ) {
  2734 		if ( ! $this->minimum_args( $args, 3 ) ) {
  2748 		if ( ! $this->minimum_args( $args, 3 ) ) {
  2795 		}
  2809 		}
  2796 		return $_users;
  2810 		return $_users;
  2797 	}
  2811 	}
  2798 
  2812 
  2799 	/**
  2813 	/**
  2800 	 * Retrieve information about the requesting user.
  2814 	 * Retrieves information about the requesting user.
  2801 	 *
  2815 	 *
  2802 	 * @uses get_userdata()
  2816 	 * @uses get_userdata()
  2803 	 *
  2817 	 *
  2804 	 * @param array $args {
  2818 	 * @param array $args {
  2805 	 *     Method arguments. Note: arguments must be ordered as documented.
  2819 	 *     Method arguments. Note: arguments must be ordered as documented.
  2806 	 *
  2820 	 *
  2807 	 *     @type int    $blog_id (unused)
  2821 	 *     @type int    $0 Blog ID (unused).
  2808 	 *     @type string $username
  2822 	 *     @type string $1 Username
  2809 	 *     @type string $password
  2823 	 *     @type string $2 Password
  2810 	 *     @type array  $fields (optional)
  2824 	 *     @type array  $3 Optional. Fields to return.
  2811 	 * }
  2825 	 * }
  2812 	 * @return array|IXR_Error (@see wp_getUser)
  2826 	 * @return array|IXR_Error (@see wp_getUser)
  2813 	 */
  2827 	 */
  2814 	public function wp_getProfile( $args ) {
  2828 	public function wp_getProfile( $args ) {
  2815 		if ( ! $this->minimum_args( $args, 3 ) ) {
  2829 		if ( ! $this->minimum_args( $args, 3 ) ) {
  2844 
  2858 
  2845 		return $this->_prepare_user( $user_data, $fields );
  2859 		return $this->_prepare_user( $user_data, $fields );
  2846 	}
  2860 	}
  2847 
  2861 
  2848 	/**
  2862 	/**
  2849 	 * Edit user's profile.
  2863 	 * Edits user's profile.
  2850 	 *
  2864 	 *
  2851 	 * @uses wp_update_user()
  2865 	 * @uses wp_update_user()
  2852 	 *
  2866 	 *
  2853 	 * @param array $args {
  2867 	 * @param array $args {
  2854 	 *     Method arguments. Note: arguments must be ordered as documented.
  2868 	 *     Method arguments. Note: arguments must be ordered as documented.
  2855 	 *
  2869 	 *
  2856 	 *     @type int    $blog_id (unused)
  2870 	 *     @type int    $0 Blog ID (unused).
  2857 	 *     @type string $username
  2871 	 *     @type string $1 Username.
  2858 	 *     @type string $password
  2872 	 *     @type string $2 Password.
  2859 	 *     @type array  $content_struct It can optionally contain:
  2873 	 *     @type array  $3 Content struct. It can optionally contain:
  2860 	 *      - 'first_name'
  2874 	 *      - 'first_name'
  2861 	 *      - 'last_name'
  2875 	 *      - 'last_name'
  2862 	 *      - 'website'
  2876 	 *      - 'website'
  2863 	 *      - 'display_name'
  2877 	 *      - 'display_name'
  2864 	 *      - 'nickname'
  2878 	 *      - 'nickname'
  2935 
  2949 
  2936 		return true;
  2950 		return true;
  2937 	}
  2951 	}
  2938 
  2952 
  2939 	/**
  2953 	/**
  2940 	 * Retrieve page.
  2954 	 * Retrieves a page.
  2941 	 *
  2955 	 *
  2942 	 * @since 2.2.0
  2956 	 * @since 2.2.0
  2943 	 *
  2957 	 *
  2944 	 * @param array $args {
  2958 	 * @param array $args {
  2945 	 *     Method arguments. Note: arguments must be ordered as documented.
  2959 	 *     Method arguments. Note: arguments must be ordered as documented.
  2946 	 *
  2960 	 *
  2947 	 *     @type int    $blog_id (unused)
  2961 	 *     @type int    $0 Blog ID (unused).
  2948 	 *     @type int    $page_id
  2962 	 *     @type int    $1 Page ID.
  2949 	 *     @type string $username
  2963 	 *     @type string $2 Username.
  2950 	 *     @type string $password
  2964 	 *     @type string $3 Password.
  2951 	 * }
  2965 	 * }
  2952 	 * @return array|IXR_Error
  2966 	 * @return array|IXR_Error
  2953 	 */
  2967 	 */
  2954 	public function wp_getPage( $args ) {
  2968 	public function wp_getPage( $args ) {
  2955 		$this->escape( $args );
  2969 		$this->escape( $args );
  2983 			return new IXR_Error( 404, __( 'Sorry, no such page.' ) );
  2997 			return new IXR_Error( 404, __( 'Sorry, no such page.' ) );
  2984 		}
  2998 		}
  2985 	}
  2999 	}
  2986 
  3000 
  2987 	/**
  3001 	/**
  2988 	 * Retrieve Pages.
  3002 	 * Retrieves Pages.
  2989 	 *
  3003 	 *
  2990 	 * @since 2.2.0
  3004 	 * @since 2.2.0
  2991 	 *
  3005 	 *
  2992 	 * @param array $args {
  3006 	 * @param array $args {
  2993 	 *     Method arguments. Note: arguments must be ordered as documented.
  3007 	 *     Method arguments. Note: arguments must be ordered as documented.
  2994 	 *
  3008 	 *
  2995 	 *     @type int    $blog_id (unused)
  3009 	 *     @type int    $0 Blog ID (unused).
  2996 	 *     @type string $username
  3010 	 *     @type string $1 Username.
  2997 	 *     @type string $password
  3011 	 *     @type string $2 Password.
  2998 	 *     @type int    $num_pages
  3012 	 *     @type int    $3 Optional. Number of pages. Default 10.
  2999 	 * }
  3013 	 * }
  3000 	 * @return array|IXR_Error
  3014 	 * @return array|IXR_Error
  3001 	 */
  3015 	 */
  3002 	public function wp_getPages( $args ) {
  3016 	public function wp_getPages( $args ) {
  3003 		$this->escape( $args );
  3017 		$this->escape( $args );
  3042 
  3056 
  3043 		return array();
  3057 		return array();
  3044 	}
  3058 	}
  3045 
  3059 
  3046 	/**
  3060 	/**
  3047 	 * Create new page.
  3061 	 * Creates a new page.
  3048 	 *
  3062 	 *
  3049 	 * @since 2.2.0
  3063 	 * @since 2.2.0
  3050 	 *
  3064 	 *
  3051 	 * @see wp_xmlrpc_server::mw_newPost()
  3065 	 * @see wp_xmlrpc_server::mw_newPost()
  3052 	 *
  3066 	 *
  3053 	 * @param array $args {
  3067 	 * @param array $args {
  3054 	 *     Method arguments. Note: arguments must be ordered as documented.
  3068 	 *     Method arguments. Note: arguments must be ordered as documented.
  3055 	 *
  3069 	 *
  3056 	 *     @type int    $blog_id (unused)
  3070 	 *     @type int    $0 Blog ID (unused).
  3057 	 *     @type string $username
  3071 	 *     @type string $1 Username.
  3058 	 *     @type string $password
  3072 	 *     @type string $2 Password.
  3059 	 *     @type array  $content_struct
  3073 	 *     @type array  $3 Content struct.
  3060 	 * }
  3074 	 * }
  3061 	 * @return int|IXR_Error
  3075 	 * @return int|IXR_Error
  3062 	 */
  3076 	 */
  3063 	public function wp_newPage( $args ) {
  3077 	public function wp_newPage( $args ) {
  3064 		// Items not escaped here will be escaped in wp_newPost().
  3078 		// Items not escaped here will be escaped in wp_newPost().
  3079 		// Let mw_newPost() do all of the heavy lifting.
  3093 		// Let mw_newPost() do all of the heavy lifting.
  3080 		return $this->mw_newPost( $args );
  3094 		return $this->mw_newPost( $args );
  3081 	}
  3095 	}
  3082 
  3096 
  3083 	/**
  3097 	/**
  3084 	 * Delete page.
  3098 	 * Deletes a page.
  3085 	 *
  3099 	 *
  3086 	 * @since 2.2.0
  3100 	 * @since 2.2.0
  3087 	 *
  3101 	 *
  3088 	 * @param array $args {
  3102 	 * @param array $args {
  3089 	 *     Method arguments. Note: arguments must be ordered as documented.
  3103 	 *     Method arguments. Note: arguments must be ordered as documented.
  3090 	 *
  3104 	 *
  3091 	 *     @type int    $blog_id (unused)
  3105 	 *     @type int    $0 Blog ID (unused).
  3092 	 *     @type string $username
  3106 	 *     @type string $1 Username.
  3093 	 *     @type string $password
  3107 	 *     @type string $2 Password.
  3094 	 *     @type int    $page_id
  3108 	 *     @type int    $3 Page ID.
  3095 	 * }
  3109 	 * }
  3096 	 * @return true|IXR_Error True, if success.
  3110 	 * @return true|IXR_Error True, if success.
  3097 	 */
  3111 	 */
  3098 	public function wp_deletePage( $args ) {
  3112 	public function wp_deletePage( $args ) {
  3099 		$this->escape( $args );
  3113 		$this->escape( $args );
  3108 		}
  3122 		}
  3109 
  3123 
  3110 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3124 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3111 		do_action( 'xmlrpc_call', 'wp.deletePage', $args, $this );
  3125 		do_action( 'xmlrpc_call', 'wp.deletePage', $args, $this );
  3112 
  3126 
  3113 		// Get the current page based on the 'page_id' and
  3127 		/*
  3114 		// make sure it is a page and not a post.
  3128 		 * Get the current page based on the 'page_id' and
       
  3129 		 * make sure it is a page and not a post.
       
  3130 		 */
  3115 		$actual_page = get_post( $page_id, ARRAY_A );
  3131 		$actual_page = get_post( $page_id, ARRAY_A );
  3116 		if ( ! $actual_page || ( 'page' !== $actual_page['post_type'] ) ) {
  3132 		if ( ! $actual_page || ( 'page' !== $actual_page['post_type'] ) ) {
  3117 			return new IXR_Error( 404, __( 'Sorry, no such page.' ) );
  3133 			return new IXR_Error( 404, __( 'Sorry, no such page.' ) );
  3118 		}
  3134 		}
  3119 
  3135 
  3140 
  3156 
  3141 		return true;
  3157 		return true;
  3142 	}
  3158 	}
  3143 
  3159 
  3144 	/**
  3160 	/**
  3145 	 * Edit page.
  3161 	 * Edits a page.
  3146 	 *
  3162 	 *
  3147 	 * @since 2.2.0
  3163 	 * @since 2.2.0
  3148 	 *
  3164 	 *
  3149 	 * @param array $args {
  3165 	 * @param array $args {
  3150 	 *     Method arguments. Note: arguments must be ordered as documented.
  3166 	 *     Method arguments. Note: arguments must be ordered as documented.
  3151 	 *
  3167 	 *
  3152 	 *     @type int    $blog_id (unused)
  3168 	 *     @type int    $0 Blog ID (unused).
  3153 	 *     @type int    $page_id
  3169 	 *     @type int    $1 Page ID.
  3154 	 *     @type string $username
  3170 	 *     @type string $2 Username.
  3155 	 *     @type string $password
  3171 	 *     @type string $3 Password.
  3156 	 *     @type string $content
  3172 	 *     @type string $4 Content.
  3157 	 *     @type string $publish
  3173 	 *     @type int    $5 Publish flag. 0 for draft, 1 for publish.
  3158 	 * }
  3174 	 * }
  3159 	 * @return array|IXR_Error
  3175 	 * @return array|IXR_Error
  3160 	 */
  3176 	 */
  3161 	public function wp_editPage( $args ) {
  3177 	public function wp_editPage( $args ) {
  3162 		// Items will be escaped in mw_editPost().
  3178 		// Items will be escaped in mw_editPost().
  3203 		// Let mw_editPost() do all of the heavy lifting.
  3219 		// Let mw_editPost() do all of the heavy lifting.
  3204 		return $this->mw_editPost( $args );
  3220 		return $this->mw_editPost( $args );
  3205 	}
  3221 	}
  3206 
  3222 
  3207 	/**
  3223 	/**
  3208 	 * Retrieve page list.
  3224 	 * Retrieves page list.
  3209 	 *
  3225 	 *
  3210 	 * @since 2.2.0
  3226 	 * @since 2.2.0
  3211 	 *
  3227 	 *
  3212 	 * @global wpdb $wpdb WordPress database abstraction object.
  3228 	 * @global wpdb $wpdb WordPress database abstraction object.
  3213 	 *
  3229 	 *
  3214 	 * @param array $args {
  3230 	 * @param array $args {
  3215 	 *     Method arguments. Note: arguments must be ordered as documented.
  3231 	 *     Method arguments. Note: arguments must be ordered as documented.
  3216 	 *
  3232 	 *
  3217 	 *     @type int    $blog_id (unused)
  3233 	 *     @type int    $0 Blog ID (unused).
  3218 	 *     @type string $username
  3234 	 *     @type string $1 Username.
  3219 	 *     @type string $password
  3235 	 *     @type string $2 Password.
  3220 	 * }
  3236 	 * }
  3221 	 * @return array|IXR_Error
  3237 	 * @return array|IXR_Error
  3222 	 */
  3238 	 */
  3223 	public function wp_getPageList( $args ) {
  3239 	public function wp_getPageList( $args ) {
  3224 		global $wpdb;
  3240 		global $wpdb;
  3268 
  3284 
  3269 		return $page_list;
  3285 		return $page_list;
  3270 	}
  3286 	}
  3271 
  3287 
  3272 	/**
  3288 	/**
  3273 	 * Retrieve authors list.
  3289 	 * Retrieves authors list.
  3274 	 *
  3290 	 *
  3275 	 * @since 2.2.0
  3291 	 * @since 2.2.0
  3276 	 *
  3292 	 *
  3277 	 * @param array $args {
  3293 	 * @param array $args {
  3278 	 *     Method arguments. Note: arguments must be ordered as documented.
  3294 	 *     Method arguments. Note: arguments must be ordered as documented.
  3279 	 *
  3295 	 *
  3280 	 *     @type int    $blog_id (unused)
  3296 	 *     @type int    $0 Blog ID (unused).
  3281 	 *     @type string $username
  3297 	 *     @type string $1 Username.
  3282 	 *     @type string $password
  3298 	 *     @type string $2 Password.
  3283 	 * }
  3299 	 * }
  3284 	 * @return array|IXR_Error
  3300 	 * @return array|IXR_Error
  3285 	 */
  3301 	 */
  3286 	public function wp_getAuthors( $args ) {
  3302 	public function wp_getAuthors( $args ) {
  3287 		$this->escape( $args );
  3303 		$this->escape( $args );
  3312 
  3328 
  3313 		return $authors;
  3329 		return $authors;
  3314 	}
  3330 	}
  3315 
  3331 
  3316 	/**
  3332 	/**
  3317 	 * Get list of all tags
  3333 	 * Gets the list of all tags.
  3318 	 *
  3334 	 *
  3319 	 * @since 2.7.0
  3335 	 * @since 2.7.0
  3320 	 *
  3336 	 *
  3321 	 * @param array $args {
  3337 	 * @param array $args {
  3322 	 *     Method arguments. Note: arguments must be ordered as documented.
  3338 	 *     Method arguments. Note: arguments must be ordered as documented.
  3323 	 *
  3339 	 *
  3324 	 *     @type int    $blog_id (unused)
  3340 	 *     @type int    $0 Blog ID (unused).
  3325 	 *     @type string $username
  3341 	 *     @type string $1 Username.
  3326 	 *     @type string $password
  3342 	 *     @type string $2 Password.
  3327 	 * }
  3343 	 * }
  3328 	 * @return array|IXR_Error
  3344 	 * @return array|IXR_Error
  3329 	 */
  3345 	 */
  3330 	public function wp_getTags( $args ) {
  3346 	public function wp_getTags( $args ) {
  3331 		$this->escape( $args );
  3347 		$this->escape( $args );
  3364 
  3380 
  3365 		return $tags;
  3381 		return $tags;
  3366 	}
  3382 	}
  3367 
  3383 
  3368 	/**
  3384 	/**
  3369 	 * Create new category.
  3385 	 * Creates a new category.
  3370 	 *
  3386 	 *
  3371 	 * @since 2.2.0
  3387 	 * @since 2.2.0
  3372 	 *
  3388 	 *
  3373 	 * @param array $args {
  3389 	 * @param array $args {
  3374 	 *     Method arguments. Note: arguments must be ordered as documented.
  3390 	 *     Method arguments. Note: arguments must be ordered as documented.
  3375 	 *
  3391 	 *
  3376 	 *     @type int    $blog_id (unused)
  3392 	 *     @type int    $0 Blog ID (unused).
  3377 	 *     @type string $username
  3393 	 *     @type string $1 Username.
  3378 	 *     @type string $password
  3394 	 *     @type string $2 Password.
  3379 	 *     @type array  $category
  3395 	 *     @type array  $3 Category.
  3380 	 * }
  3396 	 * }
  3381 	 * @return int|IXR_Error Category ID.
  3397 	 * @return int|IXR_Error Category ID.
  3382 	 */
  3398 	 */
  3383 	public function wp_newCategory( $args ) {
  3399 	public function wp_newCategory( $args ) {
  3384 		$this->escape( $args );
  3400 		$this->escape( $args );
  3398 		// Make sure the user is allowed to add a category.
  3414 		// Make sure the user is allowed to add a category.
  3399 		if ( ! current_user_can( 'manage_categories' ) ) {
  3415 		if ( ! current_user_can( 'manage_categories' ) ) {
  3400 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to add a category.' ) );
  3416 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to add a category.' ) );
  3401 		}
  3417 		}
  3402 
  3418 
  3403 		// If no slug was provided, make it empty
  3419 		/*
  3404 		// so that WordPress will generate one.
  3420 		 * If no slug was provided, make it empty
       
  3421 		 * so that WordPress will generate one.
       
  3422 		 */
  3405 		if ( empty( $category['slug'] ) ) {
  3423 		if ( empty( $category['slug'] ) ) {
  3406 			$category['slug'] = '';
  3424 			$category['slug'] = '';
  3407 		}
  3425 		}
  3408 
  3426 
  3409 		// If no parent_id was provided, make it empty
  3427 		/*
  3410 		// so that it will be a top-level page (no parent).
  3428 		 * If no parent_id was provided, make it empty
       
  3429 		 * so that it will be a top-level page (no parent).
       
  3430 		 */
  3411 		if ( ! isset( $category['parent_id'] ) ) {
  3431 		if ( ! isset( $category['parent_id'] ) ) {
  3412 			$category['parent_id'] = '';
  3432 			$category['parent_id'] = '';
  3413 		}
  3433 		}
  3414 
  3434 
  3415 		// If no description was provided, make it empty.
  3435 		// If no description was provided, make it empty.
  3447 
  3467 
  3448 		return $cat_id;
  3468 		return $cat_id;
  3449 	}
  3469 	}
  3450 
  3470 
  3451 	/**
  3471 	/**
  3452 	 * Remove category.
  3472 	 * Deletes a category.
  3453 	 *
  3473 	 *
  3454 	 * @since 2.5.0
  3474 	 * @since 2.5.0
  3455 	 *
  3475 	 *
  3456 	 * @param array $args {
  3476 	 * @param array $args {
  3457 	 *     Method arguments. Note: arguments must be ordered as documented.
  3477 	 *     Method arguments. Note: arguments must be ordered as documented.
  3458 	 *
  3478 	 *
  3459 	 *     @type int    $blog_id (unused)
  3479 	 *     @type int    $0 Blog ID (unused).
  3460 	 *     @type string $username
  3480 	 *     @type string $1 Username.
  3461 	 *     @type string $password
  3481 	 *     @type string $2 Password.
  3462 	 *     @type int    $category_id
  3482 	 *     @type int    $3 Category ID.
  3463 	 * }
  3483 	 * }
  3464 	 * @return bool|IXR_Error See wp_delete_term() for return info.
  3484 	 * @return bool|IXR_Error See wp_delete_term() for return info.
  3465 	 */
  3485 	 */
  3466 	public function wp_deleteCategory( $args ) {
  3486 	public function wp_deleteCategory( $args ) {
  3467 		$this->escape( $args );
  3487 		$this->escape( $args );
  3498 
  3518 
  3499 		return $status;
  3519 		return $status;
  3500 	}
  3520 	}
  3501 
  3521 
  3502 	/**
  3522 	/**
  3503 	 * Retrieve category list.
  3523 	 * Retrieves category list.
  3504 	 *
  3524 	 *
  3505 	 * @since 2.2.0
  3525 	 * @since 2.2.0
  3506 	 *
  3526 	 *
  3507 	 * @param array $args {
  3527 	 * @param array $args {
  3508 	 *     Method arguments. Note: arguments must be ordered as documented.
  3528 	 *     Method arguments. Note: arguments must be ordered as documented.
  3509 	 *
  3529 	 *
  3510 	 *     @type int    $blog_id (unused)
  3530 	 *     @type int    $0 Blog ID (unused).
  3511 	 *     @type string $username
  3531 	 *     @type string $1 Username.
  3512 	 *     @type string $password
  3532 	 *     @type string $2 Password.
  3513 	 *     @type array  $category
  3533 	 *     @type array  $3 Category
  3514 	 *     @type int    $max_results
  3534 	 *     @type int    $4 Max number of results.
  3515 	 * }
  3535 	 * }
  3516 	 * @return array|IXR_Error
  3536 	 * @return array|IXR_Error
  3517 	 */
  3537 	 */
  3518 	public function wp_suggestCategories( $args ) {
  3538 	public function wp_suggestCategories( $args ) {
  3519 		$this->escape( $args );
  3539 		$this->escape( $args );
  3550 
  3570 
  3551 		return $category_suggestions;
  3571 		return $category_suggestions;
  3552 	}
  3572 	}
  3553 
  3573 
  3554 	/**
  3574 	/**
  3555 	 * Retrieve comment.
  3575 	 * Retrieves a comment.
  3556 	 *
  3576 	 *
  3557 	 * @since 2.7.0
  3577 	 * @since 2.7.0
  3558 	 *
  3578 	 *
  3559 	 * @param array $args {
  3579 	 * @param array $args {
  3560 	 *     Method arguments. Note: arguments must be ordered as documented.
  3580 	 *     Method arguments. Note: arguments must be ordered as documented.
  3561 	 *
  3581 	 *
  3562 	 *     @type int    $blog_id (unused)
  3582 	 *     @type int    $0 Blog ID (unused).
  3563 	 *     @type string $username
  3583 	 *     @type string $1 Username.
  3564 	 *     @type string $password
  3584 	 *     @type string $2 Password.
  3565 	 *     @type int    $comment_id
  3585 	 *     @type int    $3 Comment ID.
  3566 	 * }
  3586 	 * }
  3567 	 * @return array|IXR_Error
  3587 	 * @return array|IXR_Error
  3568 	 */
  3588 	 */
  3569 	public function wp_getComment( $args ) {
  3589 	public function wp_getComment( $args ) {
  3570 		$this->escape( $args );
  3590 		$this->escape( $args );
  3592 
  3612 
  3593 		return $this->_prepare_comment( $comment );
  3613 		return $this->_prepare_comment( $comment );
  3594 	}
  3614 	}
  3595 
  3615 
  3596 	/**
  3616 	/**
  3597 	 * Retrieve comments.
  3617 	 * Retrieves comments.
  3598 	 *
  3618 	 *
  3599 	 * Besides the common blog_id (unused), username, and password arguments, it takes a filter
  3619 	 * Besides the common blog_id (unused), username, and password arguments,
  3600 	 * array as last argument.
  3620 	 * it takes a filter array as the last argument.
  3601 	 *
  3621 	 *
  3602 	 * Accepted 'filter' keys are 'status', 'post_id', 'offset', and 'number'.
  3622 	 * Accepted 'filter' keys are 'status', 'post_id', 'offset', and 'number'.
  3603 	 *
  3623 	 *
  3604 	 * The defaults are as follows:
  3624 	 * The defaults are as follows:
  3605 	 * - 'status' - Default is ''. Filter by status (e.g., 'approve', 'hold')
  3625 	 * - 'status'  - Default is ''. Filter by status (e.g., 'approve', 'hold')
  3606 	 * - 'post_id' - Default is ''. The post where the comment is posted. Empty string shows all comments.
  3626 	 * - 'post_id' - Default is ''. The post where the comment is posted.
  3607 	 * - 'number' - Default is 10. Total number of media items to retrieve.
  3627 	 *               Empty string shows all comments.
  3608 	 * - 'offset' - Default is 0. See WP_Query::query() for more.
  3628 	 * - 'number'  - Default is 10. Total number of media items to retrieve.
       
  3629 	 * - 'offset'  - Default is 0. See WP_Query::query() for more.
  3609 	 *
  3630 	 *
  3610 	 * @since 2.7.0
  3631 	 * @since 2.7.0
  3611 	 *
  3632 	 *
  3612 	 * @param array $args {
  3633 	 * @param array $args {
  3613 	 *     Method arguments. Note: arguments must be ordered as documented.
  3634 	 *     Method arguments. Note: arguments must be ordered as documented.
  3614 	 *
  3635 	 *
  3615 	 *     @type int    $blog_id (unused)
  3636 	 *     @type int    $0 Blog ID (unused).
  3616 	 *     @type string $username
  3637 	 *     @type string $1 Username.
  3617 	 *     @type string $password
  3638 	 *     @type string $2 Password.
  3618 	 *     @type array  $struct
  3639 	 *     @type array  $3 Optional. Query arguments.
  3619 	 * }
  3640 	 * }
  3620 	 * @return array|IXR_Error Contains a collection of comments. See wp_xmlrpc_server::wp_getComment() for a description of each item contents
  3641 	 * @return array|IXR_Error Array containing a collection of comments.
       
  3642 	 *                         See wp_xmlrpc_server::wp_getComment() for a description
       
  3643 	 *                         of each item contents.
  3621 	 */
  3644 	 */
  3622 	public function wp_getComments( $args ) {
  3645 	public function wp_getComments( $args ) {
  3623 		$this->escape( $args );
  3646 		$this->escape( $args );
  3624 
  3647 
  3625 		$username = $args[1];
  3648 		$username = $args[1];
  3687 
  3710 
  3688 		return $comments_struct;
  3711 		return $comments_struct;
  3689 	}
  3712 	}
  3690 
  3713 
  3691 	/**
  3714 	/**
  3692 	 * Delete a comment.
  3715 	 * Deletes a comment.
  3693 	 *
  3716 	 *
  3694 	 * By default, the comment will be moved to the Trash instead of deleted.
  3717 	 * By default, the comment will be moved to the Trash instead of deleted.
  3695 	 * See wp_delete_comment() for more information on this behavior.
  3718 	 * See wp_delete_comment() for more information on this behavior.
  3696 	 *
  3719 	 *
  3697 	 * @since 2.7.0
  3720 	 * @since 2.7.0
  3698 	 *
  3721 	 *
  3699 	 * @param array $args {
  3722 	 * @param array $args {
  3700 	 *     Method arguments. Note: arguments must be ordered as documented.
  3723 	 *     Method arguments. Note: arguments must be ordered as documented.
  3701 	 *
  3724 	 *
  3702 	 *     @type int    $blog_id (unused)
  3725 	 *     @type int    $0 Blog ID (unused).
  3703 	 *     @type string $username
  3726 	 *     @type string $1 Username.
  3704 	 *     @type string $password
  3727 	 *     @type string $2 Password.
  3705 	 *     @type int    $comment_ID
  3728 	 *     @type int    $3 Comment ID.
  3706 	 * }
  3729 	 * }
  3707 	 * @return bool|IXR_Error See wp_delete_comment().
  3730 	 * @return bool|IXR_Error See wp_delete_comment().
  3708 	 */
  3731 	 */
  3709 	public function wp_deleteComment( $args ) {
  3732 	public function wp_deleteComment( $args ) {
  3710 		$this->escape( $args );
  3733 		$this->escape( $args );
  3711 
  3734 
  3712 		$username   = $args[1];
  3735 		$username   = $args[1];
  3713 		$password   = $args[2];
  3736 		$password   = $args[2];
  3714 		$comment_ID = (int) $args[3];
  3737 		$comment_id = (int) $args[3];
  3715 
  3738 
  3716 		$user = $this->login( $username, $password );
  3739 		$user = $this->login( $username, $password );
  3717 		if ( ! $user ) {
  3740 		if ( ! $user ) {
  3718 			return $this->error;
  3741 			return $this->error;
  3719 		}
  3742 		}
  3720 
  3743 
  3721 		if ( ! get_comment( $comment_ID ) ) {
  3744 		if ( ! get_comment( $comment_id ) ) {
  3722 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
  3745 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
  3723 		}
  3746 		}
  3724 
  3747 
  3725 		if ( ! current_user_can( 'edit_comment', $comment_ID ) ) {
  3748 		if ( ! current_user_can( 'edit_comment', $comment_id ) ) {
  3726 			return new IXR_Error( 403, __( 'Sorry, you are not allowed to delete this comment.' ) );
  3749 			return new IXR_Error( 403, __( 'Sorry, you are not allowed to delete this comment.' ) );
  3727 		}
  3750 		}
  3728 
  3751 
  3729 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3752 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3730 		do_action( 'xmlrpc_call', 'wp.deleteComment', $args, $this );
  3753 		do_action( 'xmlrpc_call', 'wp.deleteComment', $args, $this );
  3731 
  3754 
  3732 		$status = wp_delete_comment( $comment_ID );
  3755 		$status = wp_delete_comment( $comment_id );
  3733 
  3756 
  3734 		if ( $status ) {
  3757 		if ( $status ) {
  3735 			/**
  3758 			/**
  3736 			 * Fires after a comment has been successfully deleted via XML-RPC.
  3759 			 * Fires after a comment has been successfully deleted via XML-RPC.
  3737 			 *
  3760 			 *
  3738 			 * @since 3.4.0
  3761 			 * @since 3.4.0
  3739 			 *
  3762 			 *
  3740 			 * @param int   $comment_ID ID of the deleted comment.
  3763 			 * @param int   $comment_id ID of the deleted comment.
  3741 			 * @param array $args       An array of arguments to delete the comment.
  3764 			 * @param array $args       An array of arguments to delete the comment.
  3742 			 */
  3765 			 */
  3743 			do_action( 'xmlrpc_call_success_wp_deleteComment', $comment_ID, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  3766 			do_action( 'xmlrpc_call_success_wp_deleteComment', $comment_id, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  3744 		}
  3767 		}
  3745 
  3768 
  3746 		return $status;
  3769 		return $status;
  3747 	}
  3770 	}
  3748 
  3771 
  3749 	/**
  3772 	/**
  3750 	 * Edit comment.
  3773 	 * Edits a comment.
  3751 	 *
  3774 	 *
  3752 	 * Besides the common blog_id (unused), username, and password arguments, it takes a
  3775 	 * Besides the common blog_id (unused), username, and password arguments,
  3753 	 * comment_id integer and a content_struct array as last argument.
  3776 	 * it takes a comment_id integer and a content_struct array as the last argument.
  3754 	 *
  3777 	 *
  3755 	 * The allowed keys in the content_struct array are:
  3778 	 * The allowed keys in the content_struct array are:
  3756 	 *  - 'author'
  3779 	 *  - 'author'
  3757 	 *  - 'author_url'
  3780 	 *  - 'author_url'
  3758 	 *  - 'author_email'
  3781 	 *  - 'author_email'
  3759 	 *  - 'content'
  3782 	 *  - 'content'
  3760 	 *  - 'date_created_gmt'
  3783 	 *  - 'date_created_gmt'
  3761 	 *  - 'status'. Common statuses are 'approve', 'hold', 'spam'. See get_comment_statuses() for more details
  3784 	 *  - 'status'. Common statuses are 'approve', 'hold', 'spam'. See get_comment_statuses() for more details.
  3762 	 *
  3785 	 *
  3763 	 * @since 2.7.0
  3786 	 * @since 2.7.0
  3764 	 *
  3787 	 *
  3765 	 * @param array $args {
  3788 	 * @param array $args {
  3766 	 *     Method arguments. Note: arguments must be ordered as documented.
  3789 	 *     Method arguments. Note: arguments must be ordered as documented.
  3767 	 *
  3790 	 *
  3768 	 *     @type int    $blog_id (unused)
  3791 	 *     @type int    $0 Blog ID (unused).
  3769 	 *     @type string $username
  3792 	 *     @type string $1 Username.
  3770 	 *     @type string $password
  3793 	 *     @type string $2 Password.
  3771 	 *     @type int    $comment_ID
  3794 	 *     @type int    $3 Comment ID.
  3772 	 *     @type array  $content_struct
  3795 	 *     @type array  $4 Content structure.
  3773 	 * }
  3796 	 * }
  3774 	 * @return true|IXR_Error True, on success.
  3797 	 * @return true|IXR_Error True, on success.
  3775 	 */
  3798 	 */
  3776 	public function wp_editComment( $args ) {
  3799 	public function wp_editComment( $args ) {
  3777 		$this->escape( $args );
  3800 		$this->escape( $args );
  3778 
  3801 
  3779 		$username       = $args[1];
  3802 		$username       = $args[1];
  3780 		$password       = $args[2];
  3803 		$password       = $args[2];
  3781 		$comment_ID     = (int) $args[3];
  3804 		$comment_id     = (int) $args[3];
  3782 		$content_struct = $args[4];
  3805 		$content_struct = $args[4];
  3783 
  3806 
  3784 		$user = $this->login( $username, $password );
  3807 		$user = $this->login( $username, $password );
  3785 		if ( ! $user ) {
  3808 		if ( ! $user ) {
  3786 			return $this->error;
  3809 			return $this->error;
  3787 		}
  3810 		}
  3788 
  3811 
  3789 		if ( ! get_comment( $comment_ID ) ) {
  3812 		if ( ! get_comment( $comment_id ) ) {
  3790 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
  3813 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
  3791 		}
  3814 		}
  3792 
  3815 
  3793 		if ( ! current_user_can( 'edit_comment', $comment_ID ) ) {
  3816 		if ( ! current_user_can( 'edit_comment', $comment_id ) ) {
  3794 			return new IXR_Error( 403, __( 'Sorry, you are not allowed to moderate or edit this comment.' ) );
  3817 			return new IXR_Error( 403, __( 'Sorry, you are not allowed to moderate or edit this comment.' ) );
  3795 		}
  3818 		}
  3796 
  3819 
  3797 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3820 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3798 		do_action( 'xmlrpc_call', 'wp.editComment', $args, $this );
  3821 		do_action( 'xmlrpc_call', 'wp.editComment', $args, $this );
  3799 		$comment = array(
  3822 		$comment = array(
  3800 			'comment_ID' => $comment_ID,
  3823 			'comment_ID' => $comment_id,
  3801 		);
  3824 		);
  3802 
  3825 
  3803 		if ( isset( $content_struct['status'] ) ) {
  3826 		if ( isset( $content_struct['status'] ) ) {
  3804 			$statuses = get_comment_statuses();
  3827 			$statuses = get_comment_statuses();
  3805 			$statuses = array_keys( $statuses );
  3828 			$statuses = array_keys( $statuses );
  3847 		/**
  3870 		/**
  3848 		 * Fires after a comment has been successfully updated via XML-RPC.
  3871 		 * Fires after a comment has been successfully updated via XML-RPC.
  3849 		 *
  3872 		 *
  3850 		 * @since 3.4.0
  3873 		 * @since 3.4.0
  3851 		 *
  3874 		 *
  3852 		 * @param int   $comment_ID ID of the updated comment.
  3875 		 * @param int   $comment_id ID of the updated comment.
  3853 		 * @param array $args       An array of arguments to update the comment.
  3876 		 * @param array $args       An array of arguments to update the comment.
  3854 		 */
  3877 		 */
  3855 		do_action( 'xmlrpc_call_success_wp_editComment', $comment_ID, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  3878 		do_action( 'xmlrpc_call_success_wp_editComment', $comment_id, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  3856 
  3879 
  3857 		return true;
  3880 		return true;
  3858 	}
  3881 	}
  3859 
  3882 
  3860 	/**
  3883 	/**
  3861 	 * Create new comment.
  3884 	 * Creates a new comment.
  3862 	 *
  3885 	 *
  3863 	 * @since 2.7.0
  3886 	 * @since 2.7.0
  3864 	 *
  3887 	 *
  3865 	 * @param array $args {
  3888 	 * @param array $args {
  3866 	 *     Method arguments. Note: arguments must be ordered as documented.
  3889 	 *     Method arguments. Note: arguments must be ordered as documented.
  3867 	 *
  3890 	 *
  3868 	 *     @type int        $blog_id (unused)
  3891 	 *     @type int        $0 Blog ID (unused).
  3869 	 *     @type string     $username
  3892 	 *     @type string     $1 Username.
  3870 	 *     @type string     $password
  3893 	 *     @type string     $2 Password.
  3871 	 *     @type string|int $post
  3894 	 *     @type string|int $3 Post ID or URL.
  3872 	 *     @type array      $content_struct
  3895 	 *     @type array      $4 Content structure.
  3873 	 * }
  3896 	 * }
  3874 	 * @return int|IXR_Error See wp_new_comment().
  3897 	 * @return int|IXR_Error See wp_new_comment().
  3875 	 */
  3898 	 */
  3876 	public function wp_newComment( $args ) {
  3899 	public function wp_newComment( $args ) {
  3877 		$this->escape( $args );
  3900 		$this->escape( $args );
  3948 			$user_url     = $user->user_url;
  3971 			$user_url     = $user->user_url;
  3949 
  3972 
  3950 			$comment['comment_author']       = $this->escape( $display_name );
  3973 			$comment['comment_author']       = $this->escape( $display_name );
  3951 			$comment['comment_author_email'] = $this->escape( $user_email );
  3974 			$comment['comment_author_email'] = $this->escape( $user_email );
  3952 			$comment['comment_author_url']   = $this->escape( $user_url );
  3975 			$comment['comment_author_url']   = $this->escape( $user_url );
  3953 			$comment['user_ID']              = $user->ID;
  3976 			$comment['user_id']              = $user->ID;
  3954 		} else {
  3977 		} else {
  3955 			$comment['comment_author'] = '';
  3978 			$comment['comment_author'] = '';
  3956 			if ( isset( $content_struct['author'] ) ) {
  3979 			if ( isset( $content_struct['author'] ) ) {
  3957 				$comment['comment_author'] = $content_struct['author'];
  3980 				$comment['comment_author'] = $content_struct['author'];
  3958 			}
  3981 			}
  3965 			$comment['comment_author_url'] = '';
  3988 			$comment['comment_author_url'] = '';
  3966 			if ( isset( $content_struct['author_url'] ) ) {
  3989 			if ( isset( $content_struct['author_url'] ) ) {
  3967 				$comment['comment_author_url'] = $content_struct['author_url'];
  3990 				$comment['comment_author_url'] = $content_struct['author_url'];
  3968 			}
  3991 			}
  3969 
  3992 
  3970 			$comment['user_ID'] = 0;
  3993 			$comment['user_id'] = 0;
  3971 
  3994 
  3972 			if ( get_option( 'require_name_email' ) ) {
  3995 			if ( get_option( 'require_name_email' ) ) {
  3973 				if ( strlen( $comment['comment_author_email'] ) < 6 || '' === $comment['comment_author'] ) {
  3996 				if ( strlen( $comment['comment_author_email'] ) < 6 || '' === $comment['comment_author'] ) {
  3974 					return new IXR_Error( 403, __( 'Comment author name and email are required.' ) );
  3997 					return new IXR_Error( 403, __( 'Comment author name and email are required.' ) );
  3975 				} elseif ( ! is_email( $comment['comment_author_email'] ) ) {
  3998 				} elseif ( ! is_email( $comment['comment_author_email'] ) ) {
  3988 		}
  4011 		}
  3989 
  4012 
  3990 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4013 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3991 		do_action( 'xmlrpc_call', 'wp.newComment', $args, $this );
  4014 		do_action( 'xmlrpc_call', 'wp.newComment', $args, $this );
  3992 
  4015 
  3993 		$comment_ID = wp_new_comment( $comment, true );
  4016 		$comment_id = wp_new_comment( $comment, true );
  3994 		if ( is_wp_error( $comment_ID ) ) {
  4017 		if ( is_wp_error( $comment_id ) ) {
  3995 			return new IXR_Error( 403, $comment_ID->get_error_message() );
  4018 			return new IXR_Error( 403, $comment_id->get_error_message() );
  3996 		}
  4019 		}
  3997 
  4020 
  3998 		if ( ! $comment_ID ) {
  4021 		if ( ! $comment_id ) {
  3999 			return new IXR_Error( 403, __( 'Something went wrong.' ) );
  4022 			return new IXR_Error( 403, __( 'Something went wrong.' ) );
  4000 		}
  4023 		}
  4001 
  4024 
  4002 		/**
  4025 		/**
  4003 		 * Fires after a new comment has been successfully created via XML-RPC.
  4026 		 * Fires after a new comment has been successfully created via XML-RPC.
  4004 		 *
  4027 		 *
  4005 		 * @since 3.4.0
  4028 		 * @since 3.4.0
  4006 		 *
  4029 		 *
  4007 		 * @param int   $comment_ID ID of the new comment.
  4030 		 * @param int   $comment_id ID of the new comment.
  4008 		 * @param array $args       An array of new comment arguments.
  4031 		 * @param array $args       An array of new comment arguments.
  4009 		 */
  4032 		 */
  4010 		do_action( 'xmlrpc_call_success_wp_newComment', $comment_ID, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  4033 		do_action( 'xmlrpc_call_success_wp_newComment', $comment_id, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  4011 
  4034 
  4012 		return $comment_ID;
  4035 		return $comment_id;
  4013 	}
  4036 	}
  4014 
  4037 
  4015 	/**
  4038 	/**
  4016 	 * Retrieve all of the comment status.
  4039 	 * Retrieves all of the comment status.
  4017 	 *
  4040 	 *
  4018 	 * @since 2.7.0
  4041 	 * @since 2.7.0
  4019 	 *
  4042 	 *
  4020 	 * @param array $args {
  4043 	 * @param array $args {
  4021 	 *     Method arguments. Note: arguments must be ordered as documented.
  4044 	 *     Method arguments. Note: arguments must be ordered as documented.
  4022 	 *
  4045 	 *
  4023 	 *     @type int    $blog_id (unused)
  4046 	 *     @type int    $0 Blog ID (unused).
  4024 	 *     @type string $username
  4047 	 *     @type string $1 Username.
  4025 	 *     @type string $password
  4048 	 *     @type string $2 Password.
  4026 	 * }
  4049 	 * }
  4027 	 * @return array|IXR_Error
  4050 	 * @return array|IXR_Error
  4028 	 */
  4051 	 */
  4029 	public function wp_getCommentStatusList( $args ) {
  4052 	public function wp_getCommentStatusList( $args ) {
  4030 		$this->escape( $args );
  4053 		$this->escape( $args );
  4046 
  4069 
  4047 		return get_comment_statuses();
  4070 		return get_comment_statuses();
  4048 	}
  4071 	}
  4049 
  4072 
  4050 	/**
  4073 	/**
  4051 	 * Retrieve comment count.
  4074 	 * Retrieves comment counts.
  4052 	 *
  4075 	 *
  4053 	 * @since 2.5.0
  4076 	 * @since 2.5.0
  4054 	 *
  4077 	 *
  4055 	 * @param array $args {
  4078 	 * @param array $args {
  4056 	 *     Method arguments. Note: arguments must be ordered as documented.
  4079 	 *     Method arguments. Note: arguments must be ordered as documented.
  4057 	 *
  4080 	 *
  4058 	 *     @type int    $blog_id (unused)
  4081 	 *     @type int    $0 Blog ID (unused).
  4059 	 *     @type string $username
  4082 	 *     @type string $1 Username.
  4060 	 *     @type string $password
  4083 	 *     @type string $2 Password.
  4061 	 *     @type int    $post_id
  4084 	 *     @type int    $3 Post ID.
  4062 	 * }
  4085 	 * }
  4063 	 * @return array|IXR_Error
  4086 	 * @return array|IXR_Error
  4064 	 */
  4087 	 */
  4065 	public function wp_getCommentCount( $args ) {
  4088 	public function wp_getCommentCount( $args ) {
  4066 		$this->escape( $args );
  4089 		$this->escape( $args );
  4095 			'total_comments'      => $count->total_comments,
  4118 			'total_comments'      => $count->total_comments,
  4096 		);
  4119 		);
  4097 	}
  4120 	}
  4098 
  4121 
  4099 	/**
  4122 	/**
  4100 	 * Retrieve post statuses.
  4123 	 * Retrieves post statuses.
  4101 	 *
  4124 	 *
  4102 	 * @since 2.5.0
  4125 	 * @since 2.5.0
  4103 	 *
  4126 	 *
  4104 	 * @param array $args {
  4127 	 * @param array $args {
  4105 	 *     Method arguments. Note: arguments must be ordered as documented.
  4128 	 *     Method arguments. Note: arguments must be ordered as documented.
  4106 	 *
  4129 	 *
  4107 	 *     @type int    $blog_id (unused)
  4130 	 *     @type int    $0 Blog ID (unused).
  4108 	 *     @type string $username
  4131 	 *     @type string $1 Username.
  4109 	 *     @type string $password
  4132 	 *     @type string $2 Password.
  4110 	 * }
  4133 	 * }
  4111 	 * @return array|IXR_Error
  4134 	 * @return array|IXR_Error
  4112 	 */
  4135 	 */
  4113 	public function wp_getPostStatusList( $args ) {
  4136 	public function wp_getPostStatusList( $args ) {
  4114 		$this->escape( $args );
  4137 		$this->escape( $args );
  4130 
  4153 
  4131 		return get_post_statuses();
  4154 		return get_post_statuses();
  4132 	}
  4155 	}
  4133 
  4156 
  4134 	/**
  4157 	/**
  4135 	 * Retrieve page statuses.
  4158 	 * Retrieves page statuses.
  4136 	 *
  4159 	 *
  4137 	 * @since 2.5.0
  4160 	 * @since 2.5.0
  4138 	 *
  4161 	 *
  4139 	 * @param array $args {
  4162 	 * @param array $args {
  4140 	 *     Method arguments. Note: arguments must be ordered as documented.
  4163 	 *     Method arguments. Note: arguments must be ordered as documented.
  4141 	 *
  4164 	 *
  4142 	 *     @type int    $blog_id (unused)
  4165 	 *     @type int    $0 Blog ID (unused).
  4143 	 *     @type string $username
  4166 	 *     @type string $1 Username.
  4144 	 *     @type string $password
  4167 	 *     @type string $2 Password.
  4145 	 * }
  4168 	 * }
  4146 	 * @return array|IXR_Error
  4169 	 * @return array|IXR_Error
  4147 	 */
  4170 	 */
  4148 	public function wp_getPageStatusList( $args ) {
  4171 	public function wp_getPageStatusList( $args ) {
  4149 		$this->escape( $args );
  4172 		$this->escape( $args );
  4165 
  4188 
  4166 		return get_page_statuses();
  4189 		return get_page_statuses();
  4167 	}
  4190 	}
  4168 
  4191 
  4169 	/**
  4192 	/**
  4170 	 * Retrieve page templates.
  4193 	 * Retrieves page templates.
  4171 	 *
  4194 	 *
  4172 	 * @since 2.6.0
  4195 	 * @since 2.6.0
  4173 	 *
  4196 	 *
  4174 	 * @param array $args {
  4197 	 * @param array $args {
  4175 	 *     Method arguments. Note: arguments must be ordered as documented.
  4198 	 *     Method arguments. Note: arguments must be ordered as documented.
  4176 	 *
  4199 	 *
  4177 	 *     @type int    $blog_id (unused)
  4200 	 *     @type int    $0 Blog ID (unused).
  4178 	 *     @type string $username
  4201 	 *     @type string $1 Username.
  4179 	 *     @type string $password
  4202 	 *     @type string $2 Password.
  4180 	 * }
  4203 	 * }
  4181 	 * @return array|IXR_Error
  4204 	 * @return array|IXR_Error
  4182 	 */
  4205 	 */
  4183 	public function wp_getPageTemplates( $args ) {
  4206 	public function wp_getPageTemplates( $args ) {
  4184 		$this->escape( $args );
  4207 		$this->escape( $args );
  4200 
  4223 
  4201 		return $templates;
  4224 		return $templates;
  4202 	}
  4225 	}
  4203 
  4226 
  4204 	/**
  4227 	/**
  4205 	 * Retrieve blog options.
  4228 	 * Retrieves blog options.
  4206 	 *
  4229 	 *
  4207 	 * @since 2.6.0
  4230 	 * @since 2.6.0
  4208 	 *
  4231 	 *
  4209 	 * @param array $args {
  4232 	 * @param array $args {
  4210 	 *     Method arguments. Note: arguments must be ordered as documented.
  4233 	 *     Method arguments. Note: arguments must be ordered as documented.
  4211 	 *
  4234 	 *
  4212 	 *     @type int    $blog_id (unused)
  4235 	 *     @type int    $0 Blog ID (unused).
  4213 	 *     @type string $username
  4236 	 *     @type string $1 Username.
  4214 	 *     @type string $password
  4237 	 *     @type string $2 Password.
  4215 	 *     @type array  $options
  4238 	 *     @type array  $3 Optional. Options.
  4216 	 * }
  4239 	 * }
  4217 	 * @return array|IXR_Error
  4240 	 * @return array|IXR_Error
  4218 	 */
  4241 	 */
  4219 	public function wp_getOptions( $args ) {
  4242 	public function wp_getOptions( $args ) {
  4220 		$this->escape( $args );
  4243 		$this->escape( $args );
  4227 		if ( ! $user ) {
  4250 		if ( ! $user ) {
  4228 			return $this->error;
  4251 			return $this->error;
  4229 		}
  4252 		}
  4230 
  4253 
  4231 		// If no specific options where asked for, return all of them.
  4254 		// If no specific options where asked for, return all of them.
  4232 		if ( count( $options ) == 0 ) {
  4255 		if ( count( $options ) === 0 ) {
  4233 			$options = array_keys( $this->blog_options );
  4256 			$options = array_keys( $this->blog_options );
  4234 		}
  4257 		}
  4235 
  4258 
  4236 		return $this->_getOptions( $options );
  4259 		return $this->_getOptions( $options );
  4237 	}
  4260 	}
  4238 
  4261 
  4239 	/**
  4262 	/**
  4240 	 * Retrieve blog options value from list.
  4263 	 * Retrieves blog options value from list.
  4241 	 *
  4264 	 *
  4242 	 * @since 2.6.0
  4265 	 * @since 2.6.0
  4243 	 *
  4266 	 *
  4244 	 * @param array $options Options to retrieve.
  4267 	 * @param array $options Options to retrieve.
  4245 	 * @return array
  4268 	 * @return array
  4264 
  4287 
  4265 		return $data;
  4288 		return $data;
  4266 	}
  4289 	}
  4267 
  4290 
  4268 	/**
  4291 	/**
  4269 	 * Update blog options.
  4292 	 * Updates blog options.
  4270 	 *
  4293 	 *
  4271 	 * @since 2.6.0
  4294 	 * @since 2.6.0
  4272 	 *
  4295 	 *
  4273 	 * @param array $args {
  4296 	 * @param array $args {
  4274 	 *     Method arguments. Note: arguments must be ordered as documented.
  4297 	 *     Method arguments. Note: arguments must be ordered as documented.
  4275 	 *
  4298 	 *
  4276 	 *     @type int    $blog_id (unused)
  4299 	 *     @type int    $0 Blog ID (unused).
  4277 	 *     @type string $username
  4300 	 *     @type string $1 Username.
  4278 	 *     @type string $password
  4301 	 *     @type string $2 Password.
  4279 	 *     @type array  $options
  4302 	 *     @type array  $3 Options.
  4280 	 * }
  4303 	 * }
  4281 	 * @return array|IXR_Error
  4304 	 * @return array|IXR_Error
  4282 	 */
  4305 	 */
  4283 	public function wp_setOptions( $args ) {
  4306 	public function wp_setOptions( $args ) {
  4284 		$this->escape( $args );
  4307 		$this->escape( $args );
  4313 		// Now return the updated values.
  4336 		// Now return the updated values.
  4314 		return $this->_getOptions( $option_names );
  4337 		return $this->_getOptions( $option_names );
  4315 	}
  4338 	}
  4316 
  4339 
  4317 	/**
  4340 	/**
  4318 	 * Retrieve a media item by ID
  4341 	 * Retrieves a media item by ID.
  4319 	 *
  4342 	 *
  4320 	 * @since 3.1.0
  4343 	 * @since 3.1.0
  4321 	 *
  4344 	 *
  4322 	 * @param array $args {
  4345 	 * @param array $args {
  4323 	 *     Method arguments. Note: arguments must be ordered as documented.
  4346 	 *     Method arguments. Note: arguments must be ordered as documented.
  4324 	 *
  4347 	 *
  4325 	 *     @type int    $blog_id (unused)
  4348 	 *     @type int    $0 Blog ID (unused).
  4326 	 *     @type string $username
  4349 	 *     @type string $1 Username.
  4327 	 *     @type string $password
  4350 	 *     @type string $2 Password.
  4328 	 *     @type int    $attachment_id
  4351 	 *     @type int    $3 Attachment ID.
  4329 	 * }
  4352 	 * }
  4330 	 * @return array|IXR_Error Associative array contains:
  4353 	 * @return array|IXR_Error Associative array contains:
  4331 	 *  - 'date_created_gmt'
  4354 	 *  - 'date_created_gmt'
  4332 	 *  - 'parent'
  4355 	 *  - 'parent'
  4333 	 *  - 'link'
  4356 	 *  - 'link'
  4363 
  4386 
  4364 		return $this->_prepare_media_item( $attachment );
  4387 		return $this->_prepare_media_item( $attachment );
  4365 	}
  4388 	}
  4366 
  4389 
  4367 	/**
  4390 	/**
  4368 	 * Retrieves a collection of media library items (or attachments)
  4391 	 * Retrieves a collection of media library items (or attachments).
  4369 	 *
  4392 	 *
  4370 	 * Besides the common blog_id (unused), username, and password arguments, it takes a filter
  4393 	 * Besides the common blog_id (unused), username, and password arguments,
  4371 	 * array as last argument.
  4394 	 * it takes a filter array as the last argument.
  4372 	 *
  4395 	 *
  4373 	 * Accepted 'filter' keys are 'parent_id', 'mime_type', 'offset', and 'number'.
  4396 	 * Accepted 'filter' keys are 'parent_id', 'mime_type', 'offset', and 'number'.
  4374 	 *
  4397 	 *
  4375 	 * The defaults are as follows:
  4398 	 * The defaults are as follows:
  4376 	 * - 'number' - Default is 5. Total number of media items to retrieve.
  4399 	 * - 'number'    - Default is 5. Total number of media items to retrieve.
  4377 	 * - 'offset' - Default is 0. See WP_Query::query() for more.
  4400 	 * - 'offset'    - Default is 0. See WP_Query::query() for more.
  4378 	 * - 'parent_id' - Default is ''. The post where the media item is attached. Empty string shows all media items. 0 shows unattached media items.
  4401 	 * - 'parent_id' - Default is ''. The post where the media item is attached.
       
  4402 	 *                 Empty string shows all media items. 0 shows unattached media items.
  4379 	 * - 'mime_type' - Default is ''. Filter by mime type (e.g., 'image/jpeg', 'application/pdf')
  4403 	 * - 'mime_type' - Default is ''. Filter by mime type (e.g., 'image/jpeg', 'application/pdf')
  4380 	 *
  4404 	 *
  4381 	 * @since 3.1.0
  4405 	 * @since 3.1.0
  4382 	 *
  4406 	 *
  4383 	 * @param array $args {
  4407 	 * @param array $args {
  4384 	 *     Method arguments. Note: arguments must be ordered as documented.
  4408 	 *     Method arguments. Note: arguments must be ordered as documented.
  4385 	 *
  4409 	 *
  4386 	 *     @type int    $blog_id (unused)
  4410 	 *     @type int    $0 Blog ID (unused).
  4387 	 *     @type string $username
  4411 	 *     @type string $1 Username.
  4388 	 *     @type string $password
  4412 	 *     @type string $2 Password.
  4389 	 *     @type array  $struct
  4413 	 *     @type array  $3 Optional. Query arguments.
  4390 	 * }
  4414 	 * }
  4391 	 * @return array|IXR_Error Contains a collection of media items. See wp_xmlrpc_server::wp_getMediaItem() for a description of each item contents
  4415 	 * @return array|IXR_Error Array containing a collection of media items.
       
  4416 	 *                         See wp_xmlrpc_server::wp_getMediaItem() for a description
       
  4417 	 *                         of each item contents.
  4392 	 */
  4418 	 */
  4393 	public function wp_getMediaLibrary( $args ) {
  4419 	public function wp_getMediaLibrary( $args ) {
  4394 		$this->escape( $args );
  4420 		$this->escape( $args );
  4395 
  4421 
  4396 		$username = $args[1];
  4422 		$username = $args[1];
  4439 	 * @since 3.1.0
  4465 	 * @since 3.1.0
  4440 	 *
  4466 	 *
  4441 	 * @param array $args {
  4467 	 * @param array $args {
  4442 	 *     Method arguments. Note: arguments must be ordered as documented.
  4468 	 *     Method arguments. Note: arguments must be ordered as documented.
  4443 	 *
  4469 	 *
  4444 	 *     @type int    $blog_id (unused)
  4470 	 *     @type int    $0 Blog ID (unused).
  4445 	 *     @type string $username
  4471 	 *     @type string $1 Username.
  4446 	 *     @type string $password
  4472 	 *     @type string $2 Password.
  4447 	 * }
  4473 	 * }
  4448 	 * @return array|IXR_Error List of post formats, otherwise IXR_Error object.
  4474 	 * @return array|IXR_Error List of post formats, otherwise IXR_Error object.
  4449 	 */
  4475 	 */
  4450 	public function wp_getPostFormats( $args ) {
  4476 	public function wp_getPostFormats( $args ) {
  4451 		$this->escape( $args );
  4477 		$this->escape( $args );
  4484 
  4510 
  4485 		return $formats;
  4511 		return $formats;
  4486 	}
  4512 	}
  4487 
  4513 
  4488 	/**
  4514 	/**
  4489 	 * Retrieves a post type
  4515 	 * Retrieves a post type.
  4490 	 *
  4516 	 *
  4491 	 * @since 3.4.0
  4517 	 * @since 3.4.0
  4492 	 *
  4518 	 *
  4493 	 * @see get_post_type_object()
  4519 	 * @see get_post_type_object()
  4494 	 *
  4520 	 *
  4495 	 * @param array $args {
  4521 	 * @param array $args {
  4496 	 *     Method arguments. Note: arguments must be ordered as documented.
  4522 	 *     Method arguments. Note: arguments must be ordered as documented.
  4497 	 *
  4523 	 *
  4498 	 *     @type int    $blog_id (unused)
  4524 	 *     @type int    $0 Blog ID (unused).
  4499 	 *     @type string $username
  4525 	 *     @type string $1 Username.
  4500 	 *     @type string $password
  4526 	 *     @type string $2 Password.
  4501 	 *     @type string $post_type_name
  4527 	 *     @type string $3 Post type name.
  4502 	 *     @type array  $fields (optional)
  4528 	 *     @type array  $4 Optional. Fields to fetch.
  4503 	 * }
  4529 	 * }
  4504 	 * @return array|IXR_Error Array contains:
  4530 	 * @return array|IXR_Error Array contains:
  4505 	 *  - 'labels'
  4531 	 *  - 'labels'
  4506 	 *  - 'description'
  4532 	 *  - 'description'
  4507 	 *  - 'capability_type'
  4533 	 *  - 'capability_type'
  4525 
  4551 
  4526 		if ( isset( $args[4] ) ) {
  4552 		if ( isset( $args[4] ) ) {
  4527 			$fields = $args[4];
  4553 			$fields = $args[4];
  4528 		} else {
  4554 		} else {
  4529 			/**
  4555 			/**
  4530 			 * Filters the default query fields used by the given XML-RPC method.
  4556 			 * Filters the default post type query fields used by the given XML-RPC method.
  4531 			 *
  4557 			 *
  4532 			 * @since 3.4.0
  4558 			 * @since 3.4.0
  4533 			 *
  4559 			 *
  4534 			 * @param array  $fields An array of post type query fields for the given method.
  4560 			 * @param array  $fields An array of post type fields to retrieve. By default,
       
  4561 			 *                       contains 'labels', 'cap', and 'taxonomies'.
  4535 			 * @param string $method The method name.
  4562 			 * @param string $method The method name.
  4536 			 */
  4563 			 */
  4537 			$fields = apply_filters( 'xmlrpc_default_posttype_fields', array( 'labels', 'cap', 'taxonomies' ), 'wp.getPostType' );
  4564 			$fields = apply_filters( 'xmlrpc_default_posttype_fields', array( 'labels', 'cap', 'taxonomies' ), 'wp.getPostType' );
  4538 		}
  4565 		}
  4539 
  4566 
  4557 
  4584 
  4558 		return $this->_prepare_post_type( $post_type, $fields );
  4585 		return $this->_prepare_post_type( $post_type, $fields );
  4559 	}
  4586 	}
  4560 
  4587 
  4561 	/**
  4588 	/**
  4562 	 * Retrieves a post types
  4589 	 * Retrieves post types.
  4563 	 *
  4590 	 *
  4564 	 * @since 3.4.0
  4591 	 * @since 3.4.0
  4565 	 *
  4592 	 *
  4566 	 * @see get_post_types()
  4593 	 * @see get_post_types()
  4567 	 *
  4594 	 *
  4568 	 * @param array $args {
  4595 	 * @param array $args {
  4569 	 *     Method arguments. Note: arguments must be ordered as documented.
  4596 	 *     Method arguments. Note: arguments must be ordered as documented.
  4570 	 *
  4597 	 *
  4571 	 *     @type int    $blog_id (unused)
  4598 	 *     @type int    $0 Blog ID (unused).
  4572 	 *     @type string $username
  4599 	 *     @type string $1 Username.
  4573 	 *     @type string $password
  4600 	 *     @type string $2 Password.
  4574 	 *     @type array  $filter (optional)
  4601 	 *     @type array  $3 Optional. Query arguments.
  4575 	 *     @type array  $fields (optional)
  4602 	 *     @type array  $4 Optional. Fields to fetch.
  4576 	 * }
  4603 	 * }
  4577 	 * @return array|IXR_Error
  4604 	 * @return array|IXR_Error
  4578 	 */
  4605 	 */
  4579 	public function wp_getPostTypes( $args ) {
  4606 	public function wp_getPostTypes( $args ) {
  4580 		if ( ! $this->minimum_args( $args, 3 ) ) {
  4607 		if ( ! $this->minimum_args( $args, 3 ) ) {
  4616 
  4643 
  4617 		return $struct;
  4644 		return $struct;
  4618 	}
  4645 	}
  4619 
  4646 
  4620 	/**
  4647 	/**
  4621 	 * Retrieve revisions for a specific post.
  4648 	 * Retrieves revisions for a specific post.
  4622 	 *
  4649 	 *
  4623 	 * @since 3.5.0
  4650 	 * @since 3.5.0
  4624 	 *
  4651 	 *
  4625 	 * The optional $fields parameter specifies what fields will be included
  4652 	 * The optional $fields parameter specifies what fields will be included
  4626 	 * in the response array.
  4653 	 * in the response array.
  4629 	 * @see wp_getPost() for more on $fields
  4656 	 * @see wp_getPost() for more on $fields
  4630 	 *
  4657 	 *
  4631 	 * @param array $args {
  4658 	 * @param array $args {
  4632 	 *     Method arguments. Note: arguments must be ordered as documented.
  4659 	 *     Method arguments. Note: arguments must be ordered as documented.
  4633 	 *
  4660 	 *
  4634 	 *     @type int    $blog_id (unused)
  4661 	 *     @type int    $0 Blog ID (unused).
  4635 	 *     @type string $username
  4662 	 *     @type string $1 Username.
  4636 	 *     @type string $password
  4663 	 *     @type string $2 Password.
  4637 	 *     @type int    $post_id
  4664 	 *     @type int    $3 Post ID.
  4638 	 *     @type array  $fields (optional)
  4665 	 *     @type array  $4 Optional. Fields to fetch.
  4639 	 * }
  4666 	 * }
  4640 	 * @return array|IXR_Error contains a collection of posts.
  4667 	 * @return array|IXR_Error Array containing a collection of posts.
  4641 	 */
  4668 	 */
  4642 	public function wp_getRevisions( $args ) {
  4669 	public function wp_getRevisions( $args ) {
  4643 		if ( ! $this->minimum_args( $args, 4 ) ) {
  4670 		if ( ! $this->minimum_args( $args, 4 ) ) {
  4644 			return $this->error;
  4671 			return $this->error;
  4645 		}
  4672 		}
  4656 			/**
  4683 			/**
  4657 			 * Filters the default revision query fields used by the given XML-RPC method.
  4684 			 * Filters the default revision query fields used by the given XML-RPC method.
  4658 			 *
  4685 			 *
  4659 			 * @since 3.5.0
  4686 			 * @since 3.5.0
  4660 			 *
  4687 			 *
  4661 			 * @param array  $field  An array of revision query fields.
  4688 			 * @param array  $field  An array of revision fields to retrieve. By default,
       
  4689 			 *                       contains 'post_date' and 'post_date_gmt'.
  4662 			 * @param string $method The method name.
  4690 			 * @param string $method The method name.
  4663 			 */
  4691 			 */
  4664 			$fields = apply_filters( 'xmlrpc_default_revision_fields', array( 'post_date', 'post_date_gmt' ), 'wp.getRevisions' );
  4692 			$fields = apply_filters( 'xmlrpc_default_revision_fields', array( 'post_date', 'post_date_gmt' ), 'wp.getRevisions' );
  4665 		}
  4693 		}
  4666 
  4694 
  4709 
  4737 
  4710 		return $struct;
  4738 		return $struct;
  4711 	}
  4739 	}
  4712 
  4740 
  4713 	/**
  4741 	/**
  4714 	 * Restore a post revision
  4742 	 * Restores a post revision.
  4715 	 *
  4743 	 *
  4716 	 * @since 3.5.0
  4744 	 * @since 3.5.0
  4717 	 *
  4745 	 *
  4718 	 * @uses wp_restore_post_revision()
  4746 	 * @uses wp_restore_post_revision()
  4719 	 *
  4747 	 *
  4720 	 * @param array $args {
  4748 	 * @param array $args {
  4721 	 *     Method arguments. Note: arguments must be ordered as documented.
  4749 	 *     Method arguments. Note: arguments must be ordered as documented.
  4722 	 *
  4750 	 *
  4723 	 *     @type int    $blog_id (unused)
  4751 	 *     @type int    $0 Blog ID (unused).
  4724 	 *     @type string $username
  4752 	 *     @type string $1 Username.
  4725 	 *     @type string $password
  4753 	 *     @type string $2 Password.
  4726 	 *     @type int    $revision_id
  4754 	 *     @type int    $3 Revision ID.
  4727 	 * }
  4755 	 * }
  4728 	 * @return bool|IXR_Error false if there was an error restoring, true if success.
  4756 	 * @return bool|IXR_Error false if there was an error restoring, true if success.
  4729 	 */
  4757 	 */
  4730 	public function wp_restoreRevision( $args ) {
  4758 	public function wp_restoreRevision( $args ) {
  4731 		if ( ! $this->minimum_args( $args, 3 ) ) {
  4759 		if ( ! $this->minimum_args( $args, 3 ) ) {
  4778 	 * Blogger API functions.
  4806 	 * Blogger API functions.
  4779 	 * Specs on http://plant.blogger.com/api and https://groups.yahoo.com/group/bloggerDev/
  4807 	 * Specs on http://plant.blogger.com/api and https://groups.yahoo.com/group/bloggerDev/
  4780 	 */
  4808 	 */
  4781 
  4809 
  4782 	/**
  4810 	/**
  4783 	 * Retrieve blogs that user owns.
  4811 	 * Retrieves blogs that user owns.
  4784 	 *
  4812 	 *
  4785 	 * Will make more sense once we support multiple blogs.
  4813 	 * Will make more sense once we support multiple blogs.
  4786 	 *
  4814 	 *
  4787 	 * @since 1.5.0
  4815 	 * @since 1.5.0
  4788 	 *
  4816 	 *
  4789 	 * @param array $args {
  4817 	 * @param array $args {
  4790 	 *     Method arguments. Note: arguments must be ordered as documented.
  4818 	 *     Method arguments. Note: arguments must be ordered as documented.
  4791 	 *
  4819 	 *
  4792 	 *     @type int    $blog_id (unused)
  4820 	 *     @type int    $0 Blog ID (unused).
  4793 	 *     @type string $username
  4821 	 *     @type string $1 Username.
  4794 	 *     @type string $password
  4822 	 *     @type string $2 Password.
  4795 	 * }
  4823 	 * }
  4796 	 * @return array|IXR_Error
  4824 	 * @return array|IXR_Error
  4797 	 */
  4825 	 */
  4798 	public function blogger_getUsersBlogs( $args ) {
  4826 	public function blogger_getUsersBlogs( $args ) {
  4799 		if ( ! $this->minimum_args( $args, 3 ) ) {
  4827 		if ( ! $this->minimum_args( $args, 3 ) ) {
  4829 
  4857 
  4830 		return array( $struct );
  4858 		return array( $struct );
  4831 	}
  4859 	}
  4832 
  4860 
  4833 	/**
  4861 	/**
  4834 	 * Private function for retrieving a users blogs for multisite setups
  4862 	 * Private function for retrieving a users blogs for multisite setups.
  4835 	 *
  4863 	 *
  4836 	 * @since 3.0.0
  4864 	 * @since 3.0.0
  4837 	 *
  4865 	 *
  4838 	 * @param array $args {
  4866 	 * @param array $args {
  4839 	 *     Method arguments. Note: arguments must be ordered as documented.
  4867 	 *     Method arguments. Note: arguments must be ordered as documented.
  4840 	 *
  4868 	 *
  4841 	 *     @type string $username Username.
  4869 	 *     @type int    $0 Blog ID (unused).
  4842 	 *     @type string $password Password.
  4870 	 *     @type string $1 Username.
       
  4871 	 *     @type string $2 Password.
  4843 	 * }
  4872 	 * }
  4844 	 * @return array|IXR_Error
  4873 	 * @return array|IXR_Error
  4845 	 */
  4874 	 */
  4846 	protected function _multisite_getUsersBlogs( $args ) {
  4875 	protected function _multisite_getUsersBlogs( $args ) {
  4847 		$current_blog = get_site();
  4876 		$current_blog = get_site();
  4848 
  4877 
  4849 		$domain = $current_blog->domain;
  4878 		$domain = $current_blog->domain;
  4850 		$path   = $current_blog->path . 'xmlrpc.php';
  4879 		$path   = $current_blog->path . 'xmlrpc.php';
  4851 
  4880 
  4852 		$rpc = new IXR_Client( set_url_scheme( "http://{$domain}{$path}" ) );
  4881 		$blogs = $this->wp_getUsersBlogs( $args );
  4853 		$rpc->query( 'wp.getUsersBlogs', $args[1], $args[2] );
  4882 		if ( $blogs instanceof IXR_Error ) {
  4854 		$blogs = $rpc->getResponse();
  4883 			return $blogs;
  4855 
       
  4856 		if ( isset( $blogs['faultCode'] ) ) {
       
  4857 			return new IXR_Error( $blogs['faultCode'], $blogs['faultString'] );
       
  4858 		}
  4884 		}
  4859 
  4885 
  4860 		if ( $_SERVER['HTTP_HOST'] == $domain && $_SERVER['REQUEST_URI'] == $path ) {
  4886 		if ( $_SERVER['HTTP_HOST'] == $domain && $_SERVER['REQUEST_URI'] == $path ) {
  4861 			return $blogs;
  4887 			return $blogs;
  4862 		} else {
  4888 		} else {
  4863 			foreach ( (array) $blogs as $blog ) {
  4889 			foreach ( (array) $blogs as $blog ) {
  4864 				if ( strpos( $blog['url'], $_SERVER['HTTP_HOST'] ) ) {
  4890 				if ( str_contains( $blog['url'], $_SERVER['HTTP_HOST'] ) ) {
  4865 					return array( $blog );
  4891 					return array( $blog );
  4866 				}
  4892 				}
  4867 			}
  4893 			}
  4868 			return array();
  4894 			return array();
  4869 		}
  4895 		}
  4870 	}
  4896 	}
  4871 
  4897 
  4872 	/**
  4898 	/**
  4873 	 * Retrieve user's data.
  4899 	 * Retrieves user's data.
  4874 	 *
  4900 	 *
  4875 	 * Gives your client some info about you, so you don't have to.
  4901 	 * Gives your client some info about you, so you don't have to.
  4876 	 *
  4902 	 *
  4877 	 * @since 1.5.0
  4903 	 * @since 1.5.0
  4878 	 *
  4904 	 *
  4879 	 * @param array $args {
  4905 	 * @param array $args {
  4880 	 *     Method arguments. Note: arguments must be ordered as documented.
  4906 	 *     Method arguments. Note: arguments must be ordered as documented.
  4881 	 *
  4907 	 *
  4882 	 *     @type int    $blog_id (unused)
  4908 	 *     @type int    $0 Blog ID (unused).
  4883 	 *     @type string $username
  4909 	 *     @type string $1 Username.
  4884 	 *     @type string $password
  4910 	 *     @type string $2 Password.
  4885 	 * }
  4911 	 * }
  4886 	 * @return array|IXR_Error
  4912 	 * @return array|IXR_Error
  4887 	 */
  4913 	 */
  4888 	public function blogger_getUserInfo( $args ) {
  4914 	public function blogger_getUserInfo( $args ) {
  4889 		$this->escape( $args );
  4915 		$this->escape( $args );
  4913 
  4939 
  4914 		return $struct;
  4940 		return $struct;
  4915 	}
  4941 	}
  4916 
  4942 
  4917 	/**
  4943 	/**
  4918 	 * Retrieve post.
  4944 	 * Retrieves a post.
  4919 	 *
  4945 	 *
  4920 	 * @since 1.5.0
  4946 	 * @since 1.5.0
  4921 	 *
  4947 	 *
  4922 	 * @param array $args {
  4948 	 * @param array $args {
  4923 	 *     Method arguments. Note: arguments must be ordered as documented.
  4949 	 *     Method arguments. Note: arguments must be ordered as documented.
  4924 	 *
  4950 	 *
  4925 	 *     @type int    $blog_id (unused)
  4951 	 *     @type int    $0 Blog ID (unused).
  4926 	 *     @type int    $post_ID
  4952 	 *     @type int    $1 Post ID.
  4927 	 *     @type string $username
  4953 	 *     @type string $2 Username.
  4928 	 *     @type string $password
  4954 	 *     @type string $3 Password.
  4929 	 * }
  4955 	 * }
  4930 	 * @return array|IXR_Error
  4956 	 * @return array|IXR_Error
  4931 	 */
  4957 	 */
  4932 	public function blogger_getPost( $args ) {
  4958 	public function blogger_getPost( $args ) {
  4933 		$this->escape( $args );
  4959 		$this->escape( $args );
  4934 
  4960 
  4935 		$post_ID  = (int) $args[1];
  4961 		$post_id  = (int) $args[1];
  4936 		$username = $args[2];
  4962 		$username = $args[2];
  4937 		$password = $args[3];
  4963 		$password = $args[3];
  4938 
  4964 
  4939 		$user = $this->login( $username, $password );
  4965 		$user = $this->login( $username, $password );
  4940 		if ( ! $user ) {
  4966 		if ( ! $user ) {
  4941 			return $this->error;
  4967 			return $this->error;
  4942 		}
  4968 		}
  4943 
  4969 
  4944 		$post_data = get_post( $post_ID, ARRAY_A );
  4970 		$post_data = get_post( $post_id, ARRAY_A );
  4945 		if ( ! $post_data ) {
  4971 		if ( ! $post_data ) {
  4946 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  4972 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  4947 		}
  4973 		}
  4948 
  4974 
  4949 		if ( ! current_user_can( 'edit_post', $post_ID ) ) {
  4975 		if ( ! current_user_can( 'edit_post', $post_id ) ) {
  4950 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  4976 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  4951 		}
  4977 		}
  4952 
  4978 
  4953 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4979 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4954 		do_action( 'xmlrpc_call', 'blogger.getPost', $args, $this );
  4980 		do_action( 'xmlrpc_call', 'blogger.getPost', $args, $this );
  4955 
  4981 
  4956 		$categories = implode( ',', wp_get_post_categories( $post_ID ) );
  4982 		$categories = implode( ',', wp_get_post_categories( $post_id ) );
  4957 
  4983 
  4958 		$content  = '<title>' . wp_unslash( $post_data['post_title'] ) . '</title>';
  4984 		$content  = '<title>' . wp_unslash( $post_data['post_title'] ) . '</title>';
  4959 		$content .= '<category>' . $categories . '</category>';
  4985 		$content .= '<category>' . $categories . '</category>';
  4960 		$content .= wp_unslash( $post_data['post_content'] );
  4986 		$content .= wp_unslash( $post_data['post_content'] );
  4961 
  4987 
  4968 
  4994 
  4969 		return $struct;
  4995 		return $struct;
  4970 	}
  4996 	}
  4971 
  4997 
  4972 	/**
  4998 	/**
  4973 	 * Retrieve list of recent posts.
  4999 	 * Retrieves the list of recent posts.
  4974 	 *
  5000 	 *
  4975 	 * @since 1.5.0
  5001 	 * @since 1.5.0
  4976 	 *
  5002 	 *
  4977 	 * @param array $args {
  5003 	 * @param array $args {
  4978 	 *     Method arguments. Note: arguments must be ordered as documented.
  5004 	 *     Method arguments. Note: arguments must be ordered as documented.
  4979 	 *
  5005 	 *
  4980 	 *     @type string $appkey (unused)
  5006 	 *     @type string $0 App key (unused).
  4981 	 *     @type int    $blog_id (unused)
  5007 	 *     @type int    $1 Blog ID (unused).
  4982 	 *     @type string $username
  5008 	 *     @type string $2 Username.
  4983 	 *     @type string $password
  5009 	 *     @type string $3 Password.
  4984 	 *     @type int    $numberposts (optional)
  5010 	 *     @type int    $4 Optional. Number of posts.
  4985 	 * }
  5011 	 * }
  4986 	 * @return array|IXR_Error
  5012 	 * @return array|IXR_Error
  4987 	 */
  5013 	 */
  4988 	public function blogger_getRecentPosts( $args ) {
  5014 	public function blogger_getRecentPosts( $args ) {
  4989 
  5015 
  5066 	public function blogger_setTemplate( $args ) {
  5092 	public function blogger_setTemplate( $args ) {
  5067 		return new IXR_Error( 403, __( 'Sorry, this method is not supported.' ) );
  5093 		return new IXR_Error( 403, __( 'Sorry, this method is not supported.' ) );
  5068 	}
  5094 	}
  5069 
  5095 
  5070 	/**
  5096 	/**
  5071 	 * Creates new post.
  5097 	 * Creates a new post.
  5072 	 *
  5098 	 *
  5073 	 * @since 1.5.0
  5099 	 * @since 1.5.0
  5074 	 *
  5100 	 *
  5075 	 * @param array $args {
  5101 	 * @param array $args {
  5076 	 *     Method arguments. Note: arguments must be ordered as documented.
  5102 	 *     Method arguments. Note: arguments must be ordered as documented.
  5077 	 *
  5103 	 *
  5078 	 *     @type string $appkey (unused)
  5104 	 *     @type string $0 App key (unused).
  5079 	 *     @type int    $blog_id (unused)
  5105 	 *     @type int    $1 Blog ID (unused).
  5080 	 *     @type string $username
  5106 	 *     @type string $2 Username.
  5081 	 *     @type string $password
  5107 	 *     @type string $3 Password.
  5082 	 *     @type string $content
  5108 	 *     @type string $4 Content.
  5083 	 *     @type string $publish
  5109 	 *     @type int    $5 Publish flag. 0 for draft, 1 for publish.
  5084 	 * }
  5110 	 * }
  5085 	 * @return int|IXR_Error
  5111 	 * @return int|IXR_Error
  5086 	 */
  5112 	 */
  5087 	public function blogger_newPost( $args ) {
  5113 	public function blogger_newPost( $args ) {
  5088 		$this->escape( $args );
  5114 		$this->escape( $args );
  5116 		$post_date     = current_time( 'mysql' );
  5142 		$post_date     = current_time( 'mysql' );
  5117 		$post_date_gmt = current_time( 'mysql', 1 );
  5143 		$post_date_gmt = current_time( 'mysql', 1 );
  5118 
  5144 
  5119 		$post_data = compact( 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status' );
  5145 		$post_data = compact( 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status' );
  5120 
  5146 
  5121 		$post_ID = wp_insert_post( $post_data );
  5147 		$post_id = wp_insert_post( $post_data );
  5122 		if ( is_wp_error( $post_ID ) ) {
  5148 		if ( is_wp_error( $post_id ) ) {
  5123 			return new IXR_Error( 500, $post_ID->get_error_message() );
  5149 			return new IXR_Error( 500, $post_id->get_error_message() );
  5124 		}
  5150 		}
  5125 
  5151 
  5126 		if ( ! $post_ID ) {
  5152 		if ( ! $post_id ) {
  5127 			return new IXR_Error( 500, __( 'Sorry, the post could not be created.' ) );
  5153 			return new IXR_Error( 500, __( 'Sorry, the post could not be created.' ) );
  5128 		}
  5154 		}
  5129 
  5155 
  5130 		$this->attach_uploads( $post_ID, $post_content );
  5156 		$this->attach_uploads( $post_id, $post_content );
  5131 
  5157 
  5132 		/**
  5158 		/**
  5133 		 * Fires after a new post has been successfully created via the XML-RPC Blogger API.
  5159 		 * Fires after a new post has been successfully created via the XML-RPC Blogger API.
  5134 		 *
  5160 		 *
  5135 		 * @since 3.4.0
  5161 		 * @since 3.4.0
  5136 		 *
  5162 		 *
  5137 		 * @param int   $post_ID ID of the new post.
  5163 		 * @param int   $post_id ID of the new post.
  5138 		 * @param array $args    An array of new post arguments.
  5164 		 * @param array $args    An array of new post arguments.
  5139 		 */
  5165 		 */
  5140 		do_action( 'xmlrpc_call_success_blogger_newPost', $post_ID, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  5166 		do_action( 'xmlrpc_call_success_blogger_newPost', $post_id, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  5141 
  5167 
  5142 		return $post_ID;
  5168 		return $post_id;
  5143 	}
  5169 	}
  5144 
  5170 
  5145 	/**
  5171 	/**
  5146 	 * Edit a post.
  5172 	 * Edits a post.
  5147 	 *
  5173 	 *
  5148 	 * @since 1.5.0
  5174 	 * @since 1.5.0
  5149 	 *
  5175 	 *
  5150 	 * @param array $args {
  5176 	 * @param array $args {
  5151 	 *     Method arguments. Note: arguments must be ordered as documented.
  5177 	 *     Method arguments. Note: arguments must be ordered as documented.
  5152 	 *
  5178 	 *
  5153 	 *     @type int    $blog_id (unused)
  5179 	 *     @type int    $0 Blog ID (unused).
  5154 	 *     @type int    $post_ID
  5180 	 *     @type int    $1 Post ID.
  5155 	 *     @type string $username
  5181 	 *     @type string $2 Username.
  5156 	 *     @type string $password
  5182 	 *     @type string $3 Password.
  5157 	 *     @type string $content
  5183 	 *     @type string $4 Content
  5158 	 *     @type bool   $publish
  5184 	 *     @type int    $5 Publish flag. 0 for draft, 1 for publish.
  5159 	 * }
  5185 	 * }
  5160 	 * @return true|IXR_Error true when done.
  5186 	 * @return true|IXR_Error true when done.
  5161 	 */
  5187 	 */
  5162 	public function blogger_editPost( $args ) {
  5188 	public function blogger_editPost( $args ) {
  5163 
  5189 
  5164 		$this->escape( $args );
  5190 		$this->escape( $args );
  5165 
  5191 
  5166 		$post_ID  = (int) $args[1];
  5192 		$post_id  = (int) $args[1];
  5167 		$username = $args[2];
  5193 		$username = $args[2];
  5168 		$password = $args[3];
  5194 		$password = $args[3];
  5169 		$content  = $args[4];
  5195 		$content  = $args[4];
  5170 		$publish  = $args[5];
  5196 		$publish  = $args[5];
  5171 
  5197 
  5175 		}
  5201 		}
  5176 
  5202 
  5177 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5203 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5178 		do_action( 'xmlrpc_call', 'blogger.editPost', $args, $this );
  5204 		do_action( 'xmlrpc_call', 'blogger.editPost', $args, $this );
  5179 
  5205 
  5180 		$actual_post = get_post( $post_ID, ARRAY_A );
  5206 		$actual_post = get_post( $post_id, ARRAY_A );
  5181 
  5207 
  5182 		if ( ! $actual_post || 'post' !== $actual_post['post_type'] ) {
  5208 		if ( ! $actual_post || 'post' !== $actual_post['post_type'] ) {
  5183 			return new IXR_Error( 404, __( 'Sorry, no such post.' ) );
  5209 			return new IXR_Error( 404, __( 'Sorry, no such post.' ) );
  5184 		}
  5210 		}
  5185 
  5211 
  5186 		$this->escape( $actual_post );
  5212 		$this->escape( $actual_post );
  5187 
  5213 
  5188 		if ( ! current_user_can( 'edit_post', $post_ID ) ) {
  5214 		if ( ! current_user_can( 'edit_post', $post_id ) ) {
  5189 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  5215 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  5190 		}
  5216 		}
  5191 		if ( 'publish' === $actual_post['post_status'] && ! current_user_can( 'publish_posts' ) ) {
  5217 		if ( 'publish' === $actual_post['post_status'] && ! current_user_can( 'publish_posts' ) ) {
  5192 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish this post.' ) );
  5218 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish this post.' ) );
  5193 		}
  5219 		}
  5211 		/**
  5237 		/**
  5212 		 * Fires after a post has been successfully updated via the XML-RPC Blogger API.
  5238 		 * Fires after a post has been successfully updated via the XML-RPC Blogger API.
  5213 		 *
  5239 		 *
  5214 		 * @since 3.4.0
  5240 		 * @since 3.4.0
  5215 		 *
  5241 		 *
  5216 		 * @param int   $post_ID ID of the updated post.
  5242 		 * @param int   $post_id ID of the updated post.
  5217 		 * @param array $args    An array of arguments for the post to edit.
  5243 		 * @param array $args    An array of arguments for the post to edit.
  5218 		 */
  5244 		 */
  5219 		do_action( 'xmlrpc_call_success_blogger_editPost', $post_ID, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  5245 		do_action( 'xmlrpc_call_success_blogger_editPost', $post_id, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  5220 
  5246 
  5221 		return true;
  5247 		return true;
  5222 	}
  5248 	}
  5223 
  5249 
  5224 	/**
  5250 	/**
  5225 	 * Remove a post.
  5251 	 * Deletes a post.
  5226 	 *
  5252 	 *
  5227 	 * @since 1.5.0
  5253 	 * @since 1.5.0
  5228 	 *
  5254 	 *
  5229 	 * @param array $args {
  5255 	 * @param array $args {
  5230 	 *     Method arguments. Note: arguments must be ordered as documented.
  5256 	 *     Method arguments. Note: arguments must be ordered as documented.
  5231 	 *
  5257 	 *
  5232 	 *     @type int    $blog_id (unused)
  5258 	 *     @type int    $0 Blog ID (unused).
  5233 	 *     @type int    $post_ID
  5259 	 *     @type int    $1 Post ID.
  5234 	 *     @type string $username
  5260 	 *     @type string $2 Username.
  5235 	 *     @type string $password
  5261 	 *     @type string $3 Password.
  5236 	 * }
  5262 	 * }
  5237 	 * @return true|IXR_Error True when post is deleted.
  5263 	 * @return true|IXR_Error True when post is deleted.
  5238 	 */
  5264 	 */
  5239 	public function blogger_deletePost( $args ) {
  5265 	public function blogger_deletePost( $args ) {
  5240 		$this->escape( $args );
  5266 		$this->escape( $args );
  5241 
  5267 
  5242 		$post_ID  = (int) $args[1];
  5268 		$post_id  = (int) $args[1];
  5243 		$username = $args[2];
  5269 		$username = $args[2];
  5244 		$password = $args[3];
  5270 		$password = $args[3];
  5245 
  5271 
  5246 		$user = $this->login( $username, $password );
  5272 		$user = $this->login( $username, $password );
  5247 		if ( ! $user ) {
  5273 		if ( ! $user ) {
  5249 		}
  5275 		}
  5250 
  5276 
  5251 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5277 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5252 		do_action( 'xmlrpc_call', 'blogger.deletePost', $args, $this );
  5278 		do_action( 'xmlrpc_call', 'blogger.deletePost', $args, $this );
  5253 
  5279 
  5254 		$actual_post = get_post( $post_ID, ARRAY_A );
  5280 		$actual_post = get_post( $post_id, ARRAY_A );
  5255 
  5281 
  5256 		if ( ! $actual_post || 'post' !== $actual_post['post_type'] ) {
  5282 		if ( ! $actual_post || 'post' !== $actual_post['post_type'] ) {
  5257 			return new IXR_Error( 404, __( 'Sorry, no such post.' ) );
  5283 			return new IXR_Error( 404, __( 'Sorry, no such post.' ) );
  5258 		}
  5284 		}
  5259 
  5285 
  5260 		if ( ! current_user_can( 'delete_post', $post_ID ) ) {
  5286 		if ( ! current_user_can( 'delete_post', $post_id ) ) {
  5261 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to delete this post.' ) );
  5287 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to delete this post.' ) );
  5262 		}
  5288 		}
  5263 
  5289 
  5264 		$result = wp_delete_post( $post_ID );
  5290 		$result = wp_delete_post( $post_id );
  5265 
  5291 
  5266 		if ( ! $result ) {
  5292 		if ( ! $result ) {
  5267 			return new IXR_Error( 500, __( 'Sorry, the post could not be deleted.' ) );
  5293 			return new IXR_Error( 500, __( 'Sorry, the post could not be deleted.' ) );
  5268 		}
  5294 		}
  5269 
  5295 
  5270 		/**
  5296 		/**
  5271 		 * Fires after a post has been successfully deleted via the XML-RPC Blogger API.
  5297 		 * Fires after a post has been successfully deleted via the XML-RPC Blogger API.
  5272 		 *
  5298 		 *
  5273 		 * @since 3.4.0
  5299 		 * @since 3.4.0
  5274 		 *
  5300 		 *
  5275 		 * @param int   $post_ID ID of the deleted post.
  5301 		 * @param int   $post_id ID of the deleted post.
  5276 		 * @param array $args    An array of arguments to delete the post.
  5302 		 * @param array $args    An array of arguments to delete the post.
  5277 		 */
  5303 		 */
  5278 		do_action( 'xmlrpc_call_success_blogger_deletePost', $post_ID, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  5304 		do_action( 'xmlrpc_call_success_blogger_deletePost', $post_id, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  5279 
  5305 
  5280 		return true;
  5306 		return true;
  5281 	}
  5307 	}
  5282 
  5308 
  5283 	/*
  5309 	/*
  5284 	 * MetaWeblog API functions.
  5310 	 * MetaWeblog API functions.
  5285 	 * Specs on wherever Dave Winer wants them to be.
  5311 	 * Specs on wherever Dave Winer wants them to be.
  5286 	 */
  5312 	 */
  5287 
  5313 
  5288 	/**
  5314 	/**
  5289 	 * Create a new post.
  5315 	 * Creates a new post.
  5290 	 *
  5316 	 *
  5291 	 * The 'content_struct' argument must contain:
  5317 	 * The 'content_struct' argument must contain:
  5292 	 *  - title
  5318 	 *  - title
  5293 	 *  - description
  5319 	 *  - description
  5294 	 *  - mt_excerpt
  5320 	 *  - mt_excerpt
  5313 	 * @since 1.5.0
  5339 	 * @since 1.5.0
  5314 	 *
  5340 	 *
  5315 	 * @param array $args {
  5341 	 * @param array $args {
  5316 	 *     Method arguments. Note: arguments must be ordered as documented.
  5342 	 *     Method arguments. Note: arguments must be ordered as documented.
  5317 	 *
  5343 	 *
  5318 	 *     @type int    $blog_id (unused)
  5344 	 *     @type int    $0 Blog ID (unused).
  5319 	 *     @type string $username
  5345 	 *     @type string $1 Username.
  5320 	 *     @type string $password
  5346 	 *     @type string $2 Password.
  5321 	 *     @type array  $content_struct
  5347 	 *     @type array  $3 Content structure.
  5322 	 *     @type int    $publish
  5348 	 *     @type int    $4 Optional. Publish flag. 0 for draft, 1 for publish. Default 0.
  5323 	 * }
  5349 	 * }
  5324 	 * @return int|IXR_Error
  5350 	 * @return int|IXR_Error
  5325 	 */
  5351 	 */
  5326 	public function mw_newPost( $args ) {
  5352 	public function mw_newPost( $args ) {
  5327 		$this->escape( $args );
  5353 		$this->escape( $args );
  5395 			}
  5421 			}
  5396 		}
  5422 		}
  5397 
  5423 
  5398 		// Let WordPress generate the 'post_name' (slug) unless
  5424 		// Let WordPress generate the 'post_name' (slug) unless
  5399 		// one has been provided.
  5425 		// one has been provided.
  5400 		$post_name = '';
  5426 		$post_name = null;
  5401 		if ( isset( $content_struct['wp_slug'] ) ) {
  5427 		if ( isset( $content_struct['wp_slug'] ) ) {
  5402 			$post_name = $content_struct['wp_slug'];
  5428 			$post_name = $content_struct['wp_slug'];
  5403 		}
  5429 		}
  5404 
  5430 
  5405 		// Only use a password if one was given.
  5431 		// Only use a password if one was given.
       
  5432 		$post_password = '';
  5406 		if ( isset( $content_struct['wp_password'] ) ) {
  5433 		if ( isset( $content_struct['wp_password'] ) ) {
  5407 			$post_password = $content_struct['wp_password'];
  5434 			$post_password = $content_struct['wp_password'];
  5408 		} else {
       
  5409 			$post_password = '';
       
  5410 		}
  5435 		}
  5411 
  5436 
  5412 		// Only set a post parent if one was given.
  5437 		// Only set a post parent if one was given.
       
  5438 		$post_parent = 0;
  5413 		if ( isset( $content_struct['wp_page_parent_id'] ) ) {
  5439 		if ( isset( $content_struct['wp_page_parent_id'] ) ) {
  5414 			$post_parent = $content_struct['wp_page_parent_id'];
  5440 			$post_parent = $content_struct['wp_page_parent_id'];
  5415 		} else {
       
  5416 			$post_parent = 0;
       
  5417 		}
  5441 		}
  5418 
  5442 
  5419 		// Only set the 'menu_order' if it was given.
  5443 		// Only set the 'menu_order' if it was given.
       
  5444 		$menu_order = 0;
  5420 		if ( isset( $content_struct['wp_page_order'] ) ) {
  5445 		if ( isset( $content_struct['wp_page_order'] ) ) {
  5421 			$menu_order = $content_struct['wp_page_order'];
  5446 			$menu_order = $content_struct['wp_page_order'];
  5422 		} else {
       
  5423 			$menu_order = 0;
       
  5424 		}
  5447 		}
  5425 
  5448 
  5426 		$post_author = $user->ID;
  5449 		$post_author = $user->ID;
  5427 
  5450 
  5428 		// If an author id was provided then use it instead.
  5451 		// If an author id was provided then use it instead.
  5446 				return new IXR_Error( 404, __( 'Invalid author ID.' ) );
  5469 				return new IXR_Error( 404, __( 'Invalid author ID.' ) );
  5447 			}
  5470 			}
  5448 			$post_author = $content_struct['wp_author_id'];
  5471 			$post_author = $content_struct['wp_author_id'];
  5449 		}
  5472 		}
  5450 
  5473 
  5451 		$post_title   = isset( $content_struct['title'] ) ? $content_struct['title'] : null;
  5474 		$post_title   = isset( $content_struct['title'] ) ? $content_struct['title'] : '';
  5452 		$post_content = isset( $content_struct['description'] ) ? $content_struct['description'] : null;
  5475 		$post_content = isset( $content_struct['description'] ) ? $content_struct['description'] : '';
  5453 
  5476 
  5454 		$post_status = $publish ? 'publish' : 'draft';
  5477 		$post_status = $publish ? 'publish' : 'draft';
  5455 
  5478 
  5456 		if ( isset( $content_struct[ "{$post_type}_status" ] ) ) {
  5479 		if ( isset( $content_struct[ "{$post_type}_status" ] ) ) {
  5457 			switch ( $content_struct[ "{$post_type}_status" ] ) {
  5480 			switch ( $content_struct[ "{$post_type}_status" ] ) {
  5460 				case 'private':
  5483 				case 'private':
  5461 				case 'publish':
  5484 				case 'publish':
  5462 					$post_status = $content_struct[ "{$post_type}_status" ];
  5485 					$post_status = $content_struct[ "{$post_type}_status" ];
  5463 					break;
  5486 					break;
  5464 				default:
  5487 				default:
  5465 					$post_status = $publish ? 'publish' : 'draft';
  5488 					// Deliberably left empty.
  5466 					break;
  5489 					break;
  5467 			}
  5490 			}
  5468 		}
  5491 		}
  5469 
  5492 
  5470 		$post_excerpt = isset( $content_struct['mt_excerpt'] ) ? $content_struct['mt_excerpt'] : null;
  5493 		$post_excerpt = isset( $content_struct['mt_excerpt'] ) ? $content_struct['mt_excerpt'] : '';
  5471 		$post_more    = isset( $content_struct['mt_text_more'] ) ? $content_struct['mt_text_more'] : null;
  5494 		$post_more    = isset( $content_struct['mt_text_more'] ) ? $content_struct['mt_text_more'] : '';
  5472 
  5495 
  5473 		$tags_input = isset( $content_struct['mt_keywords'] ) ? $content_struct['mt_keywords'] : null;
  5496 		$tags_input = isset( $content_struct['mt_keywords'] ) ? $content_struct['mt_keywords'] : array();
  5474 
  5497 
  5475 		if ( isset( $content_struct['mt_allow_comments'] ) ) {
  5498 		if ( isset( $content_struct['mt_allow_comments'] ) ) {
  5476 			if ( ! is_numeric( $content_struct['mt_allow_comments'] ) ) {
  5499 			if ( ! is_numeric( $content_struct['mt_allow_comments'] ) ) {
  5477 				switch ( $content_struct['mt_allow_comments'] ) {
  5500 				switch ( $content_struct['mt_allow_comments'] ) {
  5478 					case 'closed':
  5501 					case 'closed':
  5532 		} else {
  5555 		} else {
  5533 			$ping_status = get_default_comment_status( $post_type, 'pingback' );
  5556 			$ping_status = get_default_comment_status( $post_type, 'pingback' );
  5534 		}
  5557 		}
  5535 
  5558 
  5536 		if ( $post_more ) {
  5559 		if ( $post_more ) {
  5537 			$post_content = $post_content . '<!--more-->' . $post_more;
  5560 			$post_content .= '<!--more-->' . $post_more;
  5538 		}
  5561 		}
  5539 
  5562 
  5540 		$to_ping = null;
  5563 		$to_ping = '';
  5541 		if ( isset( $content_struct['mt_tb_ping_urls'] ) ) {
  5564 		if ( isset( $content_struct['mt_tb_ping_urls'] ) ) {
  5542 			$to_ping = $content_struct['mt_tb_ping_urls'];
  5565 			$to_ping = $content_struct['mt_tb_ping_urls'];
  5543 			if ( is_array( $to_ping ) ) {
  5566 			if ( is_array( $to_ping ) ) {
  5544 				$to_ping = implode( ' ', $to_ping );
  5567 				$to_ping = implode( ' ', $to_ping );
  5545 			}
  5568 			}
  5551 			$dateCreated = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
  5574 			$dateCreated = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
  5552 		} elseif ( ! empty( $content_struct['dateCreated'] ) ) {
  5575 		} elseif ( ! empty( $content_struct['dateCreated'] ) ) {
  5553 			$dateCreated = $content_struct['dateCreated']->getIso();
  5576 			$dateCreated = $content_struct['dateCreated']->getIso();
  5554 		}
  5577 		}
  5555 
  5578 
       
  5579 		$post_date     = '';
       
  5580 		$post_date_gmt = '';
  5556 		if ( ! empty( $dateCreated ) ) {
  5581 		if ( ! empty( $dateCreated ) ) {
  5557 			$post_date     = iso8601_to_datetime( $dateCreated );
  5582 			$post_date     = iso8601_to_datetime( $dateCreated );
  5558 			$post_date_gmt = iso8601_to_datetime( $dateCreated, 'gmt' );
  5583 			$post_date_gmt = iso8601_to_datetime( $dateCreated, 'gmt' );
  5559 		} else {
       
  5560 			$post_date     = '';
       
  5561 			$post_date_gmt = '';
       
  5562 		}
  5584 		}
  5563 
  5585 
  5564 		$post_category = array();
  5586 		$post_category = array();
  5565 		if ( isset( $content_struct['categories'] ) ) {
  5587 		if ( isset( $content_struct['categories'] ) ) {
  5566 			$catnames = $content_struct['categories'];
  5588 			$catnames = $content_struct['categories'];
  5572 			}
  5594 			}
  5573 		}
  5595 		}
  5574 
  5596 
  5575 		$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' );
  5597 		$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' );
  5576 
  5598 
  5577 		$post_ID        = get_default_post_to_edit( $post_type, true )->ID;
  5599 		$post_id        = get_default_post_to_edit( $post_type, true )->ID;
  5578 		$postdata['ID'] = $post_ID;
  5600 		$postdata['ID'] = $post_id;
  5579 
  5601 
  5580 		// Only posts can be sticky.
  5602 		// Only posts can be sticky.
  5581 		if ( 'post' === $post_type && isset( $content_struct['sticky'] ) ) {
  5603 		if ( 'post' === $post_type && isset( $content_struct['sticky'] ) ) {
  5582 			$data           = $postdata;
  5604 			$data           = $postdata;
  5583 			$data['sticky'] = $content_struct['sticky'];
  5605 			$data['sticky'] = $content_struct['sticky'];
  5586 				return $error;
  5608 				return $error;
  5587 			}
  5609 			}
  5588 		}
  5610 		}
  5589 
  5611 
  5590 		if ( isset( $content_struct['custom_fields'] ) ) {
  5612 		if ( isset( $content_struct['custom_fields'] ) ) {
  5591 			$this->set_custom_fields( $post_ID, $content_struct['custom_fields'] );
  5613 			$this->set_custom_fields( $post_id, $content_struct['custom_fields'] );
  5592 		}
  5614 		}
  5593 
  5615 
  5594 		if ( isset( $content_struct['wp_post_thumbnail'] ) ) {
  5616 		if ( isset( $content_struct['wp_post_thumbnail'] ) ) {
  5595 			if ( set_post_thumbnail( $post_ID, $content_struct['wp_post_thumbnail'] ) === false ) {
  5617 			if ( set_post_thumbnail( $post_id, $content_struct['wp_post_thumbnail'] ) === false ) {
  5596 				return new IXR_Error( 404, __( 'Invalid attachment ID.' ) );
  5618 				return new IXR_Error( 404, __( 'Invalid attachment ID.' ) );
  5597 			}
  5619 			}
  5598 
  5620 
  5599 			unset( $content_struct['wp_post_thumbnail'] );
  5621 			unset( $content_struct['wp_post_thumbnail'] );
  5600 		}
  5622 		}
  5601 
  5623 
  5602 		// Handle enclosures.
  5624 		// Handle enclosures.
  5603 		$thisEnclosure = isset( $content_struct['enclosure'] ) ? $content_struct['enclosure'] : null;
  5625 		$thisEnclosure = isset( $content_struct['enclosure'] ) ? $content_struct['enclosure'] : null;
  5604 		$this->add_enclosure_if_new( $post_ID, $thisEnclosure );
  5626 		$this->add_enclosure_if_new( $post_id, $thisEnclosure );
  5605 
  5627 
  5606 		$this->attach_uploads( $post_ID, $post_content );
  5628 		$this->attach_uploads( $post_id, $post_content );
  5607 
  5629 
  5608 		// Handle post formats if assigned, value is validated earlier
  5630 		/*
  5609 		// in this function.
  5631 		 * Handle post formats if assigned, value is validated earlier
       
  5632 		 * in this function.
       
  5633 		 */
  5610 		if ( isset( $content_struct['wp_post_format'] ) ) {
  5634 		if ( isset( $content_struct['wp_post_format'] ) ) {
  5611 			set_post_format( $post_ID, $content_struct['wp_post_format'] );
  5635 			set_post_format( $post_id, $content_struct['wp_post_format'] );
  5612 		}
  5636 		}
  5613 
  5637 
  5614 		$post_ID = wp_insert_post( $postdata, true );
  5638 		$post_id = wp_insert_post( $postdata, true );
  5615 		if ( is_wp_error( $post_ID ) ) {
  5639 		if ( is_wp_error( $post_id ) ) {
  5616 			return new IXR_Error( 500, $post_ID->get_error_message() );
  5640 			return new IXR_Error( 500, $post_id->get_error_message() );
  5617 		}
  5641 		}
  5618 
  5642 
  5619 		if ( ! $post_ID ) {
  5643 		if ( ! $post_id ) {
  5620 			return new IXR_Error( 500, __( 'Sorry, the post could not be created.' ) );
  5644 			return new IXR_Error( 500, __( 'Sorry, the post could not be created.' ) );
  5621 		}
  5645 		}
  5622 
  5646 
  5623 		/**
  5647 		/**
  5624 		 * Fires after a new post has been successfully created via the XML-RPC MovableType API.
  5648 		 * Fires after a new post has been successfully created via the XML-RPC MovableType API.
  5625 		 *
  5649 		 *
  5626 		 * @since 3.4.0
  5650 		 * @since 3.4.0
  5627 		 *
  5651 		 *
  5628 		 * @param int   $post_ID ID of the new post.
  5652 		 * @param int   $post_id ID of the new post.
  5629 		 * @param array $args    An array of arguments to create the new post.
  5653 		 * @param array $args    An array of arguments to create the new post.
  5630 		 */
  5654 		 */
  5631 		do_action( 'xmlrpc_call_success_mw_newPost', $post_ID, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  5655 		do_action( 'xmlrpc_call_success_mw_newPost', $post_id, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  5632 
  5656 
  5633 		return (string) $post_ID;
  5657 		return (string) $post_id;
  5634 	}
  5658 	}
  5635 
  5659 
  5636 	/**
  5660 	/**
  5637 	 * Adds an enclosure to a post if it's new.
  5661 	 * Adds an enclosure to a post if it's new.
  5638 	 *
  5662 	 *
  5639 	 * @since 2.8.0
  5663 	 * @since 2.8.0
  5640 	 *
  5664 	 *
  5641 	 * @param int   $post_ID   Post ID.
  5665 	 * @param int   $post_id   Post ID.
  5642 	 * @param array $enclosure Enclosure data.
  5666 	 * @param array $enclosure Enclosure data.
  5643 	 */
  5667 	 */
  5644 	public function add_enclosure_if_new( $post_ID, $enclosure ) {
  5668 	public function add_enclosure_if_new( $post_id, $enclosure ) {
  5645 		if ( is_array( $enclosure ) && isset( $enclosure['url'] ) && isset( $enclosure['length'] ) && isset( $enclosure['type'] ) ) {
  5669 		if ( is_array( $enclosure ) && isset( $enclosure['url'] ) && isset( $enclosure['length'] ) && isset( $enclosure['type'] ) ) {
  5646 			$encstring  = $enclosure['url'] . "\n" . $enclosure['length'] . "\n" . $enclosure['type'] . "\n";
  5670 			$encstring  = $enclosure['url'] . "\n" . $enclosure['length'] . "\n" . $enclosure['type'] . "\n";
  5647 			$found      = false;
  5671 			$found      = false;
  5648 			$enclosures = get_post_meta( $post_ID, 'enclosure' );
  5672 			$enclosures = get_post_meta( $post_id, 'enclosure' );
  5649 			if ( $enclosures ) {
  5673 			if ( $enclosures ) {
  5650 				foreach ( $enclosures as $enc ) {
  5674 				foreach ( $enclosures as $enc ) {
  5651 					// This method used to omit the trailing new line. #23219
  5675 					// This method used to omit the trailing new line. #23219
  5652 					if ( rtrim( $enc, "\n" ) == rtrim( $encstring, "\n" ) ) {
  5676 					if ( rtrim( $enc, "\n" ) === rtrim( $encstring, "\n" ) ) {
  5653 						$found = true;
  5677 						$found = true;
  5654 						break;
  5678 						break;
  5655 					}
  5679 					}
  5656 				}
  5680 				}
  5657 			}
  5681 			}
  5658 			if ( ! $found ) {
  5682 			if ( ! $found ) {
  5659 				add_post_meta( $post_ID, 'enclosure', $encstring );
  5683 				add_post_meta( $post_id, 'enclosure', $encstring );
  5660 			}
  5684 			}
  5661 		}
  5685 		}
  5662 	}
  5686 	}
  5663 
  5687 
  5664 	/**
  5688 	/**
  5665 	 * Attach upload to a post.
  5689 	 * Attaches an upload to a post.
  5666 	 *
  5690 	 *
  5667 	 * @since 2.1.0
  5691 	 * @since 2.1.0
  5668 	 *
  5692 	 *
  5669 	 * @global wpdb $wpdb WordPress database abstraction object.
  5693 	 * @global wpdb $wpdb WordPress database abstraction object.
  5670 	 *
  5694 	 *
  5671 	 * @param int    $post_ID      Post ID.
  5695 	 * @param int    $post_id      Post ID.
  5672 	 * @param string $post_content Post Content for attachment.
  5696 	 * @param string $post_content Post Content for attachment.
  5673 	 */
  5697 	 */
  5674 	public function attach_uploads( $post_ID, $post_content ) {
  5698 	public function attach_uploads( $post_id, $post_content ) {
  5675 		global $wpdb;
  5699 		global $wpdb;
  5676 
  5700 
  5677 		// Find any unattached files.
  5701 		// Find any unattached files.
  5678 		$attachments = $wpdb->get_results( "SELECT ID, guid FROM {$wpdb->posts} WHERE post_parent = '0' AND post_type = 'attachment'" );
  5702 		$attachments = $wpdb->get_results( "SELECT ID, guid FROM {$wpdb->posts} WHERE post_parent = '0' AND post_type = 'attachment'" );
  5679 		if ( is_array( $attachments ) ) {
  5703 		if ( is_array( $attachments ) ) {
  5680 			foreach ( $attachments as $file ) {
  5704 			foreach ( $attachments as $file ) {
  5681 				if ( ! empty( $file->guid ) && strpos( $post_content, $file->guid ) !== false ) {
  5705 				if ( ! empty( $file->guid ) && str_contains( $post_content, $file->guid ) ) {
  5682 					$wpdb->update( $wpdb->posts, array( 'post_parent' => $post_ID ), array( 'ID' => $file->ID ) );
  5706 					$wpdb->update( $wpdb->posts, array( 'post_parent' => $post_id ), array( 'ID' => $file->ID ) );
  5683 				}
  5707 				}
  5684 			}
  5708 			}
  5685 		}
  5709 		}
  5686 	}
  5710 	}
  5687 
  5711 
  5688 	/**
  5712 	/**
  5689 	 * Edit a post.
  5713 	 * Edits a post.
  5690 	 *
  5714 	 *
  5691 	 * @since 1.5.0
  5715 	 * @since 1.5.0
  5692 	 *
  5716 	 *
  5693 	 * @param array $args {
  5717 	 * @param array $args {
  5694 	 *     Method arguments. Note: arguments must be ordered as documented.
  5718 	 *     Method arguments. Note: arguments must be ordered as documented.
  5695 	 *
  5719 	 *
  5696 	 *     @type int    $blog_id (unused)
  5720 	 *     @type int    $0 Post ID.
  5697 	 *     @type string $username
  5721 	 *     @type string $1 Username.
  5698 	 *     @type string $password
  5722 	 *     @type string $2 Password.
  5699 	 *     @type array  $content_struct
  5723 	 *     @type array  $3 Content structure.
  5700 	 *     @type int    $publish
  5724 	 *     @type int    $4 Optional. Publish flag. 0 for draft, 1 for publish. Default 0.
  5701 	 * }
  5725 	 * }
  5702 	 * @return true|IXR_Error True on success.
  5726 	 * @return true|IXR_Error True on success.
  5703 	 */
  5727 	 */
  5704 	public function mw_editPost( $args ) {
  5728 	public function mw_editPost( $args ) {
  5705 		$this->escape( $args );
  5729 		$this->escape( $args );
  5706 
  5730 
  5707 		$post_ID        = (int) $args[0];
  5731 		$post_id        = (int) $args[0];
  5708 		$username       = $args[1];
  5732 		$username       = $args[1];
  5709 		$password       = $args[2];
  5733 		$password       = $args[2];
  5710 		$content_struct = $args[3];
  5734 		$content_struct = $args[3];
  5711 		$publish        = isset( $args[4] ) ? $args[4] : 0;
  5735 		$publish        = isset( $args[4] ) ? $args[4] : 0;
  5712 
  5736 
  5716 		}
  5740 		}
  5717 
  5741 
  5718 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5742 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5719 		do_action( 'xmlrpc_call', 'metaWeblog.editPost', $args, $this );
  5743 		do_action( 'xmlrpc_call', 'metaWeblog.editPost', $args, $this );
  5720 
  5744 
  5721 		$postdata = get_post( $post_ID, ARRAY_A );
  5745 		$postdata = get_post( $post_id, ARRAY_A );
  5722 
  5746 
  5723 		/*
  5747 		/*
  5724 		 * If there is no post data for the give post ID, stop now and return an error.
  5748 		 * If there is no post data for the give post ID, stop now and return an error.
  5725 		 * Otherwise a new post will be created (which was the old behavior).
  5749 		 * Otherwise a new post will be created (which was the old behavior).
  5726 		 */
  5750 		 */
  5727 		if ( ! $postdata || empty( $postdata['ID'] ) ) {
  5751 		if ( ! $postdata || empty( $postdata['ID'] ) ) {
  5728 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  5752 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  5729 		}
  5753 		}
  5730 
  5754 
  5731 		if ( ! current_user_can( 'edit_post', $post_ID ) ) {
  5755 		if ( ! current_user_can( 'edit_post', $post_id ) ) {
  5732 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  5756 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  5733 		}
  5757 		}
  5734 
  5758 
  5735 		// Use wp.editPost to edit post types other than post and page.
  5759 		// Use wp.editPost to edit post types other than post and page.
  5736 		if ( ! in_array( $postdata['post_type'], array( 'post', 'page' ), true ) ) {
  5760 		if ( ! in_array( $postdata['post_type'], array( 'post', 'page' ), true ) ) {
  5782 		// Only set the 'menu_order' if it was given.
  5806 		// Only set the 'menu_order' if it was given.
  5783 		if ( isset( $content_struct['wp_page_order'] ) ) {
  5807 		if ( isset( $content_struct['wp_page_order'] ) ) {
  5784 			$menu_order = $content_struct['wp_page_order'];
  5808 			$menu_order = $content_struct['wp_page_order'];
  5785 		}
  5809 		}
  5786 
  5810 
  5787 		$page_template = null;
  5811 		$page_template = '';
  5788 		if ( ! empty( $content_struct['wp_page_template'] ) && 'page' === $post_type ) {
  5812 		if ( ! empty( $content_struct['wp_page_template'] ) && 'page' === $post_type ) {
  5789 			$page_template = $content_struct['wp_page_template'];
  5813 			$page_template = $content_struct['wp_page_template'];
  5790 		}
  5814 		}
  5791 
  5815 
  5792 		$post_author = $postdata['post_author'];
  5816 		$post_author = $postdata['post_author'];
  5890 
  5914 
  5891 		if ( isset( $content_struct['mt_excerpt'] ) ) {
  5915 		if ( isset( $content_struct['mt_excerpt'] ) ) {
  5892 			$post_excerpt = $content_struct['mt_excerpt'];
  5916 			$post_excerpt = $content_struct['mt_excerpt'];
  5893 		}
  5917 		}
  5894 
  5918 
  5895 		$post_more = isset( $content_struct['mt_text_more'] ) ? $content_struct['mt_text_more'] : null;
  5919 		$post_more = isset( $content_struct['mt_text_more'] ) ? $content_struct['mt_text_more'] : '';
  5896 
  5920 
  5897 		$post_status = $publish ? 'publish' : 'draft';
  5921 		$post_status = $publish ? 'publish' : 'draft';
  5898 		if ( isset( $content_struct[ "{$post_type}_status" ] ) ) {
  5922 		if ( isset( $content_struct[ "{$post_type}_status" ] ) ) {
  5899 			switch ( $content_struct[ "{$post_type}_status" ] ) {
  5923 			switch ( $content_struct[ "{$post_type}_status" ] ) {
  5900 				case 'draft':
  5924 				case 'draft':
  5907 					$post_status = $publish ? 'publish' : 'draft';
  5931 					$post_status = $publish ? 'publish' : 'draft';
  5908 					break;
  5932 					break;
  5909 			}
  5933 			}
  5910 		}
  5934 		}
  5911 
  5935 
  5912 		$tags_input = isset( $content_struct['mt_keywords'] ) ? $content_struct['mt_keywords'] : null;
  5936 		$tags_input = isset( $content_struct['mt_keywords'] ) ? $content_struct['mt_keywords'] : array();
  5913 
  5937 
  5914 		if ( 'publish' === $post_status || 'private' === $post_status ) {
  5938 		if ( 'publish' === $post_status || 'private' === $post_status ) {
  5915 			if ( 'page' === $post_type && ! current_user_can( 'publish_pages' ) ) {
  5939 			if ( 'page' === $post_type && ! current_user_can( 'publish_pages' ) ) {
  5916 				return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish this page.' ) );
  5940 				return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish this page.' ) );
  5917 			} elseif ( ! current_user_can( 'publish_posts' ) ) {
  5941 			} elseif ( ! current_user_can( 'publish_posts' ) ) {
  5921 
  5945 
  5922 		if ( $post_more ) {
  5946 		if ( $post_more ) {
  5923 			$post_content = $post_content . '<!--more-->' . $post_more;
  5947 			$post_content = $post_content . '<!--more-->' . $post_more;
  5924 		}
  5948 		}
  5925 
  5949 
  5926 		$to_ping = null;
  5950 		$to_ping = '';
  5927 		if ( isset( $content_struct['mt_tb_ping_urls'] ) ) {
  5951 		if ( isset( $content_struct['mt_tb_ping_urls'] ) ) {
  5928 			$to_ping = $content_struct['mt_tb_ping_urls'];
  5952 			$to_ping = $content_struct['mt_tb_ping_urls'];
  5929 			if ( is_array( $to_ping ) ) {
  5953 			if ( is_array( $to_ping ) ) {
  5930 				$to_ping = implode( ' ', $to_ping );
  5954 				$to_ping = implode( ' ', $to_ping );
  5931 			}
  5955 			}
  5975 				return $error;
  5999 				return $error;
  5976 			}
  6000 			}
  5977 		}
  6001 		}
  5978 
  6002 
  5979 		if ( isset( $content_struct['custom_fields'] ) ) {
  6003 		if ( isset( $content_struct['custom_fields'] ) ) {
  5980 			$this->set_custom_fields( $post_ID, $content_struct['custom_fields'] );
  6004 			$this->set_custom_fields( $post_id, $content_struct['custom_fields'] );
  5981 		}
  6005 		}
  5982 
  6006 
  5983 		if ( isset( $content_struct['wp_post_thumbnail'] ) ) {
  6007 		if ( isset( $content_struct['wp_post_thumbnail'] ) ) {
  5984 
  6008 
  5985 			// Empty value deletes, non-empty value adds/updates.
  6009 			// Empty value deletes, non-empty value adds/updates.
  5986 			if ( empty( $content_struct['wp_post_thumbnail'] ) ) {
  6010 			if ( empty( $content_struct['wp_post_thumbnail'] ) ) {
  5987 				delete_post_thumbnail( $post_ID );
  6011 				delete_post_thumbnail( $post_id );
  5988 			} else {
  6012 			} else {
  5989 				if ( set_post_thumbnail( $post_ID, $content_struct['wp_post_thumbnail'] ) === false ) {
  6013 				if ( set_post_thumbnail( $post_id, $content_struct['wp_post_thumbnail'] ) === false ) {
  5990 					return new IXR_Error( 404, __( 'Invalid attachment ID.' ) );
  6014 					return new IXR_Error( 404, __( 'Invalid attachment ID.' ) );
  5991 				}
  6015 				}
  5992 			}
  6016 			}
  5993 			unset( $content_struct['wp_post_thumbnail'] );
  6017 			unset( $content_struct['wp_post_thumbnail'] );
  5994 		}
  6018 		}
  5995 
  6019 
  5996 		// Handle enclosures.
  6020 		// Handle enclosures.
  5997 		$thisEnclosure = isset( $content_struct['enclosure'] ) ? $content_struct['enclosure'] : null;
  6021 		$thisEnclosure = isset( $content_struct['enclosure'] ) ? $content_struct['enclosure'] : null;
  5998 		$this->add_enclosure_if_new( $post_ID, $thisEnclosure );
  6022 		$this->add_enclosure_if_new( $post_id, $thisEnclosure );
  5999 
  6023 
  6000 		$this->attach_uploads( $ID, $post_content );
  6024 		$this->attach_uploads( $ID, $post_content );
  6001 
  6025 
  6002 		// Handle post formats if assigned, validation is handled earlier in this function.
  6026 		// Handle post formats if assigned, validation is handled earlier in this function.
  6003 		if ( isset( $content_struct['wp_post_format'] ) ) {
  6027 		if ( isset( $content_struct['wp_post_format'] ) ) {
  6004 			set_post_format( $post_ID, $content_struct['wp_post_format'] );
  6028 			set_post_format( $post_id, $content_struct['wp_post_format'] );
  6005 		}
  6029 		}
  6006 
  6030 
  6007 		/**
  6031 		/**
  6008 		 * Fires after a post has been successfully updated via the XML-RPC MovableType API.
  6032 		 * Fires after a post has been successfully updated via the XML-RPC MovableType API.
  6009 		 *
  6033 		 *
  6010 		 * @since 3.4.0
  6034 		 * @since 3.4.0
  6011 		 *
  6035 		 *
  6012 		 * @param int   $post_ID ID of the updated post.
  6036 		 * @param int   $post_id ID of the updated post.
  6013 		 * @param array $args    An array of arguments to update the post.
  6037 		 * @param array $args    An array of arguments to update the post.
  6014 		 */
  6038 		 */
  6015 		do_action( 'xmlrpc_call_success_mw_editPost', $post_ID, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  6039 		do_action( 'xmlrpc_call_success_mw_editPost', $post_id, $args ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
  6016 
  6040 
  6017 		return true;
  6041 		return true;
  6018 	}
  6042 	}
  6019 
  6043 
  6020 	/**
  6044 	/**
  6021 	 * Retrieve post.
  6045 	 * Retrieves a post.
  6022 	 *
  6046 	 *
  6023 	 * @since 1.5.0
  6047 	 * @since 1.5.0
  6024 	 *
  6048 	 *
  6025 	 * @param array $args {
  6049 	 * @param array $args {
  6026 	 *     Method arguments. Note: arguments must be ordered as documented.
  6050 	 *     Method arguments. Note: arguments must be ordered as documented.
  6027 	 *
  6051 	 *
  6028 	 *     @type int    $blog_id (unused)
  6052 	 *     @type int    $0 Post ID.
  6029 	 *     @type int    $post_ID
  6053 	 *     @type string $1 Username.
  6030 	 *     @type string $username
  6054 	 *     @type string $2 Password.
  6031 	 *     @type string $password
       
  6032 	 * }
  6055 	 * }
  6033 	 * @return array|IXR_Error
  6056 	 * @return array|IXR_Error
  6034 	 */
  6057 	 */
  6035 	public function mw_getPost( $args ) {
  6058 	public function mw_getPost( $args ) {
  6036 		$this->escape( $args );
  6059 		$this->escape( $args );
  6037 
  6060 
  6038 		$post_ID  = (int) $args[0];
  6061 		$post_id  = (int) $args[0];
  6039 		$username = $args[1];
  6062 		$username = $args[1];
  6040 		$password = $args[2];
  6063 		$password = $args[2];
  6041 
  6064 
  6042 		$user = $this->login( $username, $password );
  6065 		$user = $this->login( $username, $password );
  6043 		if ( ! $user ) {
  6066 		if ( ! $user ) {
  6044 			return $this->error;
  6067 			return $this->error;
  6045 		}
  6068 		}
  6046 
  6069 
  6047 		$postdata = get_post( $post_ID, ARRAY_A );
  6070 		$postdata = get_post( $post_id, ARRAY_A );
  6048 		if ( ! $postdata ) {
  6071 		if ( ! $postdata ) {
  6049 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  6072 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  6050 		}
  6073 		}
  6051 
  6074 
  6052 		if ( ! current_user_can( 'edit_post', $post_ID ) ) {
  6075 		if ( ! current_user_can( 'edit_post', $post_id ) ) {
  6053 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  6076 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  6054 		}
  6077 		}
  6055 
  6078 
  6056 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6079 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6057 		do_action( 'xmlrpc_call', 'metaWeblog.getPost', $args, $this );
  6080 		do_action( 'xmlrpc_call', 'metaWeblog.getPost', $args, $this );
  6061 			$post_date_gmt     = $this->_convert_date_gmt( $postdata['post_date_gmt'], $postdata['post_date'] );
  6084 			$post_date_gmt     = $this->_convert_date_gmt( $postdata['post_date_gmt'], $postdata['post_date'] );
  6062 			$post_modified     = $this->_convert_date( $postdata['post_modified'] );
  6085 			$post_modified     = $this->_convert_date( $postdata['post_modified'] );
  6063 			$post_modified_gmt = $this->_convert_date_gmt( $postdata['post_modified_gmt'], $postdata['post_modified'] );
  6086 			$post_modified_gmt = $this->_convert_date_gmt( $postdata['post_modified_gmt'], $postdata['post_modified'] );
  6064 
  6087 
  6065 			$categories = array();
  6088 			$categories = array();
  6066 			$catids     = wp_get_post_categories( $post_ID );
  6089 			$catids     = wp_get_post_categories( $post_id );
  6067 			foreach ( $catids as $catid ) {
  6090 			foreach ( $catids as $catid ) {
  6068 				$categories[] = get_cat_name( $catid );
  6091 				$categories[] = get_cat_name( $catid );
  6069 			}
  6092 			}
  6070 
  6093 
  6071 			$tagnames = array();
  6094 			$tagnames = array();
  6072 			$tags     = wp_get_post_tags( $post_ID );
  6095 			$tags     = wp_get_post_tags( $post_id );
  6073 			if ( ! empty( $tags ) ) {
  6096 			if ( ! empty( $tags ) ) {
  6074 				foreach ( $tags as $tag ) {
  6097 				foreach ( $tags as $tag ) {
  6075 					$tagnames[] = $tag->name;
  6098 					$tagnames[] = $tag->name;
  6076 				}
  6099 				}
  6077 				$tagnames = implode( ', ', $tagnames );
  6100 				$tagnames = implode( ', ', $tagnames );
  6092 			if ( 'future' === $postdata['post_status'] ) {
  6115 			if ( 'future' === $postdata['post_status'] ) {
  6093 				$postdata['post_status'] = 'publish';
  6116 				$postdata['post_status'] = 'publish';
  6094 			}
  6117 			}
  6095 
  6118 
  6096 			// Get post format.
  6119 			// Get post format.
  6097 			$post_format = get_post_format( $post_ID );
  6120 			$post_format = get_post_format( $post_id );
  6098 			if ( empty( $post_format ) ) {
  6121 			if ( empty( $post_format ) ) {
  6099 				$post_format = 'standard';
  6122 				$post_format = 'standard';
  6100 			}
  6123 			}
  6101 
  6124 
  6102 			$sticky = false;
  6125 			$sticky = false;
  6103 			if ( is_sticky( $post_ID ) ) {
  6126 			if ( is_sticky( $post_id ) ) {
  6104 				$sticky = true;
  6127 				$sticky = true;
  6105 			}
  6128 			}
  6106 
  6129 
  6107 			$enclosure = array();
  6130 			$enclosure = array();
  6108 			foreach ( (array) get_post_custom( $post_ID ) as $key => $val ) {
  6131 			foreach ( (array) get_post_custom( $post_id ) as $key => $val ) {
  6109 				if ( 'enclosure' === $key ) {
  6132 				if ( 'enclosure' === $key ) {
  6110 					foreach ( (array) $val as $enc ) {
  6133 					foreach ( (array) $val as $enc ) {
  6111 						$encdata             = explode( "\n", $enc );
  6134 						$encdata             = explode( "\n", $enc );
  6112 						$enclosure['url']    = trim( htmlspecialchars( $encdata[0] ) );
  6135 						$enclosure['url']    = trim( htmlspecialchars( $encdata[0] ) );
  6113 						$enclosure['length'] = (int) trim( $encdata[1] );
  6136 						$enclosure['length'] = (int) trim( $encdata[1] );
  6138 				'wp_password'            => $postdata['post_password'],
  6161 				'wp_password'            => $postdata['post_password'],
  6139 				'wp_author_id'           => (string) $author->ID,
  6162 				'wp_author_id'           => (string) $author->ID,
  6140 				'wp_author_display_name' => $author->display_name,
  6163 				'wp_author_display_name' => $author->display_name,
  6141 				'date_created_gmt'       => $post_date_gmt,
  6164 				'date_created_gmt'       => $post_date_gmt,
  6142 				'post_status'            => $postdata['post_status'],
  6165 				'post_status'            => $postdata['post_status'],
  6143 				'custom_fields'          => $this->get_custom_fields( $post_ID ),
  6166 				'custom_fields'          => $this->get_custom_fields( $post_id ),
  6144 				'wp_post_format'         => $post_format,
  6167 				'wp_post_format'         => $post_format,
  6145 				'sticky'                 => $sticky,
  6168 				'sticky'                 => $sticky,
  6146 				'date_modified'          => $post_modified,
  6169 				'date_modified'          => $post_modified,
  6147 				'date_modified_gmt'      => $post_modified_gmt,
  6170 				'date_modified_gmt'      => $post_modified_gmt,
  6148 			);
  6171 			);
  6158 			return new IXR_Error( 404, __( 'Sorry, no such post.' ) );
  6181 			return new IXR_Error( 404, __( 'Sorry, no such post.' ) );
  6159 		}
  6182 		}
  6160 	}
  6183 	}
  6161 
  6184 
  6162 	/**
  6185 	/**
  6163 	 * Retrieve list of recent posts.
  6186 	 * Retrieves list of recent posts.
  6164 	 *
  6187 	 *
  6165 	 * @since 1.5.0
  6188 	 * @since 1.5.0
  6166 	 *
  6189 	 *
  6167 	 * @param array $args {
  6190 	 * @param array $args {
  6168 	 *     Method arguments. Note: arguments must be ordered as documented.
  6191 	 *     Method arguments. Note: arguments must be ordered as documented.
  6169 	 *
  6192 	 *
  6170 	 *     @type int    $blog_id (unused)
  6193 	 *     @type int    $0 Blog ID (unused).
  6171 	 *     @type string $username
  6194 	 *     @type string $1 Username.
  6172 	 *     @type string $password
  6195 	 *     @type string $2 Password.
  6173 	 *     @type int    $numberposts
  6196 	 *     @type int    $3 Optional. Number of posts.
  6174 	 * }
  6197 	 * }
  6175 	 * @return array|IXR_Error
  6198 	 * @return array|IXR_Error
  6176 	 */
  6199 	 */
  6177 	public function mw_getRecentPosts( $args ) {
  6200 	public function mw_getRecentPosts( $args ) {
  6178 		$this->escape( $args );
  6201 		$this->escape( $args );
  6285 
  6308 
  6286 		return $recent_posts;
  6309 		return $recent_posts;
  6287 	}
  6310 	}
  6288 
  6311 
  6289 	/**
  6312 	/**
  6290 	 * Retrieve the list of categories on a given blog.
  6313 	 * Retrieves the list of categories on a given blog.
  6291 	 *
  6314 	 *
  6292 	 * @since 1.5.0
  6315 	 * @since 1.5.0
  6293 	 *
  6316 	 *
  6294 	 * @param array $args {
  6317 	 * @param array $args {
  6295 	 *     Method arguments. Note: arguments must be ordered as documented.
  6318 	 *     Method arguments. Note: arguments must be ordered as documented.
  6296 	 *
  6319 	 *
  6297 	 *     @type int    $blog_id (unused)
  6320 	 *     @type int    $0 Blog ID (unused).
  6298 	 *     @type string $username
  6321 	 *     @type string $1 Username.
  6299 	 *     @type string $password
  6322 	 *     @type string $2 Password.
  6300 	 * }
  6323 	 * }
  6301 	 * @return array|IXR_Error
  6324 	 * @return array|IXR_Error
  6302 	 */
  6325 	 */
  6303 	public function mw_getCategories( $args ) {
  6326 	public function mw_getCategories( $args ) {
  6304 		$this->escape( $args );
  6327 		$this->escape( $args );
  6346 	 *
  6369 	 *
  6347 	 * @link http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/
  6370 	 * @link http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/
  6348 	 *
  6371 	 *
  6349 	 * @since 1.5.0
  6372 	 * @since 1.5.0
  6350 	 *
  6373 	 *
  6351 	 * @global wpdb $wpdb WordPress database abstraction object.
       
  6352 	 *
       
  6353 	 * @param array $args {
  6374 	 * @param array $args {
  6354 	 *     Method arguments. Note: arguments must be ordered as documented.
  6375 	 *     Method arguments. Note: arguments must be ordered as documented.
  6355 	 *
  6376 	 *
  6356 	 *     @type int    $blog_id (unused)
  6377 	 *     @type int    $0 Blog ID (unused).
  6357 	 *     @type string $username
  6378 	 *     @type string $1 Username.
  6358 	 *     @type string $password
  6379 	 *     @type string $2 Password.
  6359 	 *     @type array  $data
  6380 	 *     @type array  $3 Data.
  6360 	 * }
  6381 	 * }
  6361 	 * @return array|IXR_Error
  6382 	 * @return array|IXR_Error
  6362 	 */
  6383 	 */
  6363 	public function mw_newMediaObject( $args ) {
  6384 	public function mw_newMediaObject( $args ) {
  6364 		global $wpdb;
       
  6365 
       
  6366 		$username = $this->escape( $args[1] );
  6385 		$username = $this->escape( $args[1] );
  6367 		$password = $this->escape( $args[2] );
  6386 		$password = $this->escape( $args[2] );
  6368 		$data     = $args[3];
  6387 		$data     = $args[3];
  6369 
  6388 
  6370 		$name = sanitize_file_name( $data['name'] );
  6389 		$name = sanitize_file_name( $data['name'] );
  6459 		return $struct;
  6478 		return $struct;
  6460 	}
  6479 	}
  6461 
  6480 
  6462 	/*
  6481 	/*
  6463 	 * MovableType API functions.
  6482 	 * MovableType API functions.
  6464 	 * Specs on http://www.movabletype.org/docs/mtmanual_programmatic.html
  6483 	 * Specs archive on http://web.archive.org/web/20050220091302/http://www.movabletype.org:80/docs/mtmanual_programmatic.html
  6465 	 */
  6484 	 */
  6466 
  6485 
  6467 	/**
  6486 	/**
  6468 	 * Retrieve the post titles of recent posts.
  6487 	 * Retrieves the post titles of recent posts.
  6469 	 *
  6488 	 *
  6470 	 * @since 1.5.0
  6489 	 * @since 1.5.0
  6471 	 *
  6490 	 *
  6472 	 * @param array $args {
  6491 	 * @param array $args {
  6473 	 *     Method arguments. Note: arguments must be ordered as documented.
  6492 	 *     Method arguments. Note: arguments must be ordered as documented.
  6474 	 *
  6493 	 *
  6475 	 *     @type int    $blog_id (unused)
  6494 	 *     @type int    $0 Blog ID (unused).
  6476 	 *     @type string $username
  6495 	 *     @type string $1 Username.
  6477 	 *     @type string $password
  6496 	 *     @type string $2 Password.
  6478 	 *     @type int    $numberposts
  6497 	 *     @type int    $3 Optional. Number of posts.
  6479 	 * }
  6498 	 * }
  6480 	 * @return array|IXR_Error
  6499 	 * @return array|IXR_Error
  6481 	 */
  6500 	 */
  6482 	public function mt_getRecentPostTitles( $args ) {
  6501 	public function mt_getRecentPostTitles( $args ) {
  6483 		$this->escape( $args );
  6502 		$this->escape( $args );
  6527 
  6546 
  6528 		return $recent_posts;
  6547 		return $recent_posts;
  6529 	}
  6548 	}
  6530 
  6549 
  6531 	/**
  6550 	/**
  6532 	 * Retrieve list of all categories on blog.
  6551 	 * Retrieves the list of all categories on a blog.
  6533 	 *
  6552 	 *
  6534 	 * @since 1.5.0
  6553 	 * @since 1.5.0
  6535 	 *
  6554 	 *
  6536 	 * @param array $args {
  6555 	 * @param array $args {
  6537 	 *     Method arguments. Note: arguments must be ordered as documented.
  6556 	 *     Method arguments. Note: arguments must be ordered as documented.
  6538 	 *
  6557 	 *
  6539 	 *     @type int    $blog_id (unused)
  6558 	 *     @type int    $0 Blog ID (unused).
  6540 	 *     @type string $username
  6559 	 *     @type string $1 Username.
  6541 	 *     @type string $password
  6560 	 *     @type string $2 Password.
  6542 	 * }
  6561 	 * }
  6543 	 * @return array|IXR_Error
  6562 	 * @return array|IXR_Error
  6544 	 */
  6563 	 */
  6545 	public function mt_getCategoryList( $args ) {
  6564 	public function mt_getCategoryList( $args ) {
  6546 		$this->escape( $args );
  6565 		$this->escape( $args );
  6580 
  6599 
  6581 		return $categories_struct;
  6600 		return $categories_struct;
  6582 	}
  6601 	}
  6583 
  6602 
  6584 	/**
  6603 	/**
  6585 	 * Retrieve post categories.
  6604 	 * Retrieves post categories.
  6586 	 *
  6605 	 *
  6587 	 * @since 1.5.0
  6606 	 * @since 1.5.0
  6588 	 *
  6607 	 *
  6589 	 * @param array $args {
  6608 	 * @param array $args {
  6590 	 *     Method arguments. Note: arguments must be ordered as documented.
  6609 	 *     Method arguments. Note: arguments must be ordered as documented.
  6591 	 *
  6610 	 *
  6592 	 *     @type int    $post_ID
  6611 	 *     @type int    $0 Post ID.
  6593 	 *     @type string $username
  6612 	 *     @type string $1 Username.
  6594 	 *     @type string $password
  6613 	 *     @type string $2 Password.
  6595 	 * }
  6614 	 * }
  6596 	 * @return array|IXR_Error
  6615 	 * @return array|IXR_Error
  6597 	 */
  6616 	 */
  6598 	public function mt_getPostCategories( $args ) {
  6617 	public function mt_getPostCategories( $args ) {
  6599 		$this->escape( $args );
  6618 		$this->escape( $args );
  6600 
  6619 
  6601 		$post_ID  = (int) $args[0];
  6620 		$post_id  = (int) $args[0];
  6602 		$username = $args[1];
  6621 		$username = $args[1];
  6603 		$password = $args[2];
  6622 		$password = $args[2];
  6604 
  6623 
  6605 		$user = $this->login( $username, $password );
  6624 		$user = $this->login( $username, $password );
  6606 		if ( ! $user ) {
  6625 		if ( ! $user ) {
  6607 			return $this->error;
  6626 			return $this->error;
  6608 		}
  6627 		}
  6609 
  6628 
  6610 		if ( ! get_post( $post_ID ) ) {
  6629 		if ( ! get_post( $post_id ) ) {
  6611 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  6630 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  6612 		}
  6631 		}
  6613 
  6632 
  6614 		if ( ! current_user_can( 'edit_post', $post_ID ) ) {
  6633 		if ( ! current_user_can( 'edit_post', $post_id ) ) {
  6615 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  6634 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  6616 		}
  6635 		}
  6617 
  6636 
  6618 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6637 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6619 		do_action( 'xmlrpc_call', 'mt.getPostCategories', $args, $this );
  6638 		do_action( 'xmlrpc_call', 'mt.getPostCategories', $args, $this );
  6620 
  6639 
  6621 		$categories = array();
  6640 		$categories = array();
  6622 		$catids     = wp_get_post_categories( (int) $post_ID );
  6641 		$catids     = wp_get_post_categories( (int) $post_id );
  6623 		// First listed category will be the primary category.
  6642 		// First listed category will be the primary category.
  6624 		$isPrimary = true;
  6643 		$isPrimary = true;
  6625 		foreach ( $catids as $catid ) {
  6644 		foreach ( $catids as $catid ) {
  6626 			$categories[] = array(
  6645 			$categories[] = array(
  6627 				'categoryName' => get_cat_name( $catid ),
  6646 				'categoryName' => get_cat_name( $catid ),
  6640 	 * @since 1.5.0
  6659 	 * @since 1.5.0
  6641 	 *
  6660 	 *
  6642 	 * @param array $args {
  6661 	 * @param array $args {
  6643 	 *     Method arguments. Note: arguments must be ordered as documented.
  6662 	 *     Method arguments. Note: arguments must be ordered as documented.
  6644 	 *
  6663 	 *
  6645 	 *     @type int    $post_ID
  6664 	 *     @type int    $0 Post ID.
  6646 	 *     @type string $username
  6665 	 *     @type string $1 Username.
  6647 	 *     @type string $password
  6666 	 *     @type string $2 Password.
  6648 	 *     @type array  $categories
  6667 	 *     @type array  $3 Categories.
  6649 	 * }
  6668 	 * }
  6650 	 * @return true|IXR_Error True on success.
  6669 	 * @return true|IXR_Error True on success.
  6651 	 */
  6670 	 */
  6652 	public function mt_setPostCategories( $args ) {
  6671 	public function mt_setPostCategories( $args ) {
  6653 		$this->escape( $args );
  6672 		$this->escape( $args );
  6654 
  6673 
  6655 		$post_ID    = (int) $args[0];
  6674 		$post_id    = (int) $args[0];
  6656 		$username   = $args[1];
  6675 		$username   = $args[1];
  6657 		$password   = $args[2];
  6676 		$password   = $args[2];
  6658 		$categories = $args[3];
  6677 		$categories = $args[3];
  6659 
  6678 
  6660 		$user = $this->login( $username, $password );
  6679 		$user = $this->login( $username, $password );
  6663 		}
  6682 		}
  6664 
  6683 
  6665 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6684 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6666 		do_action( 'xmlrpc_call', 'mt.setPostCategories', $args, $this );
  6685 		do_action( 'xmlrpc_call', 'mt.setPostCategories', $args, $this );
  6667 
  6686 
  6668 		if ( ! get_post( $post_ID ) ) {
  6687 		if ( ! get_post( $post_id ) ) {
  6669 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  6688 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  6670 		}
  6689 		}
  6671 
  6690 
  6672 		if ( ! current_user_can( 'edit_post', $post_ID ) ) {
  6691 		if ( ! current_user_can( 'edit_post', $post_id ) ) {
  6673 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  6692 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  6674 		}
  6693 		}
  6675 
  6694 
  6676 		$catids = array();
  6695 		$catids = array();
  6677 		foreach ( $categories as $cat ) {
  6696 		foreach ( $categories as $cat ) {
  6678 			$catids[] = $cat['categoryId'];
  6697 			$catids[] = $cat['categoryId'];
  6679 		}
  6698 		}
  6680 
  6699 
  6681 		wp_set_post_categories( $post_ID, $catids );
  6700 		wp_set_post_categories( $post_id, $catids );
  6682 
  6701 
  6683 		return true;
  6702 		return true;
  6684 	}
  6703 	}
  6685 
  6704 
  6686 	/**
  6705 	/**
  6687 	 * Retrieve an array of methods supported by this server.
  6706 	 * Retrieves an array of methods supported by this server.
  6688 	 *
  6707 	 *
  6689 	 * @since 1.5.0
  6708 	 * @since 1.5.0
  6690 	 *
  6709 	 *
  6691 	 * @return array
  6710 	 * @return array
  6692 	 */
  6711 	 */
  6696 
  6715 
  6697 		return array_keys( $this->methods );
  6716 		return array_keys( $this->methods );
  6698 	}
  6717 	}
  6699 
  6718 
  6700 	/**
  6719 	/**
  6701 	 * Retrieve an empty array because we don't support per-post text filters.
  6720 	 * Retrieves an empty array because we don't support per-post text filters.
  6702 	 *
  6721 	 *
  6703 	 * @since 1.5.0
  6722 	 * @since 1.5.0
  6704 	 */
  6723 	 */
  6705 	public function mt_supportedTextFilters() {
  6724 	public function mt_supportedTextFilters() {
  6706 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6725 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6715 		 */
  6734 		 */
  6716 		return apply_filters( 'xmlrpc_text_filters', array() );
  6735 		return apply_filters( 'xmlrpc_text_filters', array() );
  6717 	}
  6736 	}
  6718 
  6737 
  6719 	/**
  6738 	/**
  6720 	 * Retrieve trackbacks sent to a given post.
  6739 	 * Retrieves trackbacks sent to a given post.
  6721 	 *
  6740 	 *
  6722 	 * @since 1.5.0
  6741 	 * @since 1.5.0
  6723 	 *
  6742 	 *
  6724 	 * @global wpdb $wpdb WordPress database abstraction object.
  6743 	 * @global wpdb $wpdb WordPress database abstraction object.
  6725 	 *
  6744 	 *
  6726 	 * @param int $post_ID
  6745 	 * @param int $post_id
  6727 	 * @return array|IXR_Error
  6746 	 * @return array|IXR_Error
  6728 	 */
  6747 	 */
  6729 	public function mt_getTrackbackPings( $post_ID ) {
  6748 	public function mt_getTrackbackPings( $post_id ) {
  6730 		global $wpdb;
  6749 		global $wpdb;
  6731 
  6750 
  6732 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6751 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6733 		do_action( 'xmlrpc_call', 'mt.getTrackbackPings', $post_ID, $this );
  6752 		do_action( 'xmlrpc_call', 'mt.getTrackbackPings', $post_id, $this );
  6734 
  6753 
  6735 		$actual_post = get_post( $post_ID, ARRAY_A );
  6754 		$actual_post = get_post( $post_id, ARRAY_A );
  6736 
  6755 
  6737 		if ( ! $actual_post ) {
  6756 		if ( ! $actual_post ) {
  6738 			return new IXR_Error( 404, __( 'Sorry, no such post.' ) );
  6757 			return new IXR_Error( 404, __( 'Sorry, no such post.' ) );
  6739 		}
  6758 		}
  6740 
  6759 
  6741 		$comments = $wpdb->get_results( $wpdb->prepare( "SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_ID ) );
  6760 		$comments = $wpdb->get_results( $wpdb->prepare( "SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_id ) );
  6742 
  6761 
  6743 		if ( ! $comments ) {
  6762 		if ( ! $comments ) {
  6744 			return array();
  6763 			return array();
  6745 		}
  6764 		}
  6746 
  6765 
  6766 	 * @since 1.5.0
  6785 	 * @since 1.5.0
  6767 	 *
  6786 	 *
  6768 	 * @param array $args {
  6787 	 * @param array $args {
  6769 	 *     Method arguments. Note: arguments must be ordered as documented.
  6788 	 *     Method arguments. Note: arguments must be ordered as documented.
  6770 	 *
  6789 	 *
  6771 	 *     @type int    $post_ID
  6790 	 *     @type int    $0 Post ID.
  6772 	 *     @type string $username
  6791 	 *     @type string $1 Username.
  6773 	 *     @type string $password
  6792 	 *     @type string $2 Password.
  6774 	 * }
  6793 	 * }
  6775 	 * @return int|IXR_Error
  6794 	 * @return int|IXR_Error
  6776 	 */
  6795 	 */
  6777 	public function mt_publishPost( $args ) {
  6796 	public function mt_publishPost( $args ) {
  6778 		$this->escape( $args );
  6797 		$this->escape( $args );
  6779 
  6798 
  6780 		$post_ID  = (int) $args[0];
  6799 		$post_id  = (int) $args[0];
  6781 		$username = $args[1];
  6800 		$username = $args[1];
  6782 		$password = $args[2];
  6801 		$password = $args[2];
  6783 
  6802 
  6784 		$user = $this->login( $username, $password );
  6803 		$user = $this->login( $username, $password );
  6785 		if ( ! $user ) {
  6804 		if ( ! $user ) {
  6787 		}
  6806 		}
  6788 
  6807 
  6789 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6808 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6790 		do_action( 'xmlrpc_call', 'mt.publishPost', $args, $this );
  6809 		do_action( 'xmlrpc_call', 'mt.publishPost', $args, $this );
  6791 
  6810 
  6792 		$postdata = get_post( $post_ID, ARRAY_A );
  6811 		$postdata = get_post( $post_id, ARRAY_A );
  6793 		if ( ! $postdata ) {
  6812 		if ( ! $postdata ) {
  6794 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  6813 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  6795 		}
  6814 		}
  6796 
  6815 
  6797 		if ( ! current_user_can( 'publish_posts' ) || ! current_user_can( 'edit_post', $post_ID ) ) {
  6816 		if ( ! current_user_can( 'publish_posts' ) || ! current_user_can( 'edit_post', $post_id ) ) {
  6798 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish this post.' ) );
  6817 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish this post.' ) );
  6799 		}
  6818 		}
  6800 
  6819 
  6801 		$postdata['post_status'] = 'publish';
  6820 		$postdata['post_status'] = 'publish';
  6802 
  6821 
  6803 		// Retain old categories.
  6822 		// Retain old categories.
  6804 		$postdata['post_category'] = wp_get_post_categories( $post_ID );
  6823 		$postdata['post_category'] = wp_get_post_categories( $post_id );
  6805 		$this->escape( $postdata );
  6824 		$this->escape( $postdata );
  6806 
  6825 
  6807 		return wp_update_post( $postdata );
  6826 		return wp_update_post( $postdata );
  6808 	}
  6827 	}
  6809 
  6828 
  6815 	/**
  6834 	/**
  6816 	 * Retrieves a pingback and registers it.
  6835 	 * Retrieves a pingback and registers it.
  6817 	 *
  6836 	 *
  6818 	 * @since 1.5.0
  6837 	 * @since 1.5.0
  6819 	 *
  6838 	 *
       
  6839 	 * @global wpdb $wpdb WordPress database abstraction object.
       
  6840 	 *
  6820 	 * @param array $args {
  6841 	 * @param array $args {
  6821 	 *     Method arguments. Note: arguments must be ordered as documented.
  6842 	 *     Method arguments. Note: arguments must be ordered as documented.
  6822 	 *
  6843 	 *
  6823 	 *     @type string $pagelinkedfrom
  6844 	 *     @type string $0 URL of page linked from.
  6824 	 *     @type string $pagelinkedto
  6845 	 *     @type string $1 URL of page linked to.
  6825 	 * }
  6846 	 * }
  6826 	 * @return string|IXR_Error
  6847 	 * @return string|IXR_Error
  6827 	 */
  6848 	 */
  6828 	public function pingback_ping( $args ) {
  6849 	public function pingback_ping( $args ) {
  6829 		global $wpdb;
  6850 		global $wpdb;
  6861 		 * Let's find which post is linked to.
  6882 		 * Let's find which post is linked to.
  6862 		 * FIXME: Does url_to_postid() cover all these cases already?
  6883 		 * FIXME: Does url_to_postid() cover all these cases already?
  6863 		 * If so, then let's use it and drop the old code.
  6884 		 * If so, then let's use it and drop the old code.
  6864 		 */
  6885 		 */
  6865 		$urltest = parse_url( $pagelinkedto );
  6886 		$urltest = parse_url( $pagelinkedto );
  6866 		$post_ID = url_to_postid( $pagelinkedto );
  6887 		$post_id = url_to_postid( $pagelinkedto );
  6867 		if ( $post_ID ) {
  6888 		if ( $post_id ) {
  6868 			// $way
  6889 			// $way
  6869 		} elseif ( isset( $urltest['path'] ) && preg_match( '#p/[0-9]{1,}#', $urltest['path'], $match ) ) {
  6890 		} elseif ( isset( $urltest['path'] ) && preg_match( '#p/[0-9]{1,}#', $urltest['path'], $match ) ) {
  6870 			// The path defines the post_ID (archives/p/XXXX).
  6891 			// The path defines the post_ID (archives/p/XXXX).
  6871 			$blah    = explode( '/', $match[0] );
  6892 			$blah    = explode( '/', $match[0] );
  6872 			$post_ID = (int) $blah[1];
  6893 			$post_id = (int) $blah[1];
  6873 		} elseif ( isset( $urltest['query'] ) && preg_match( '#p=[0-9]{1,}#', $urltest['query'], $match ) ) {
  6894 		} elseif ( isset( $urltest['query'] ) && preg_match( '#p=[0-9]{1,}#', $urltest['query'], $match ) ) {
  6874 			// The query string defines the post_ID (?p=XXXX).
  6895 			// The query string defines the post_ID (?p=XXXX).
  6875 			$blah    = explode( '=', $match[0] );
  6896 			$blah    = explode( '=', $match[0] );
  6876 			$post_ID = (int) $blah[1];
  6897 			$post_id = (int) $blah[1];
  6877 		} elseif ( isset( $urltest['fragment'] ) ) {
  6898 		} elseif ( isset( $urltest['fragment'] ) ) {
  6878 			// An #anchor is there, it's either...
  6899 			// An #anchor is there, it's either...
  6879 			if ( (int) $urltest['fragment'] ) {
  6900 			if ( (int) $urltest['fragment'] ) {
  6880 				// ...an integer #XXXX (simplest case),
  6901 				// ...an integer #XXXX (simplest case),
  6881 				$post_ID = (int) $urltest['fragment'];
  6902 				$post_id = (int) $urltest['fragment'];
  6882 			} elseif ( preg_match( '/post-[0-9]+/', $urltest['fragment'] ) ) {
  6903 			} elseif ( preg_match( '/post-[0-9]+/', $urltest['fragment'] ) ) {
  6883 				// ...a post ID in the form 'post-###',
  6904 				// ...a post ID in the form 'post-###',
  6884 				$post_ID = preg_replace( '/[^0-9]+/', '', $urltest['fragment'] );
  6905 				$post_id = preg_replace( '/[^0-9]+/', '', $urltest['fragment'] );
  6885 			} elseif ( is_string( $urltest['fragment'] ) ) {
  6906 			} elseif ( is_string( $urltest['fragment'] ) ) {
  6886 				// ...or a string #title, a little more complicated.
  6907 				// ...or a string #title, a little more complicated.
  6887 				$title   = preg_replace( '/[^a-z0-9]/i', '.', $urltest['fragment'] );
  6908 				$title   = preg_replace( '/[^a-z0-9]/i', '.', $urltest['fragment'] );
  6888 				$sql     = $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_title RLIKE %s", $title );
  6909 				$sql     = $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_title RLIKE %s", $title );
  6889 				$post_ID = $wpdb->get_var( $sql );
  6910 				$post_id = $wpdb->get_var( $sql );
  6890 				if ( ! $post_ID ) {
  6911 				if ( ! $post_id ) {
  6891 					// Returning unknown error '0' is better than die()'ing.
  6912 					// Returning unknown error '0' is better than die()'ing.
  6892 					return $this->pingback_error( 0, '' );
  6913 					return $this->pingback_error( 0, '' );
  6893 				}
  6914 				}
  6894 			}
  6915 			}
  6895 		} else {
  6916 		} else {
  6896 			// TODO: Attempt to extract a post ID from the given URL.
  6917 			// TODO: Attempt to extract a post ID from the given URL.
  6897 			return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either does not exist, or it is not a pingback-enabled resource.' ) );
  6918 			return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either does not exist, or it is not a pingback-enabled resource.' ) );
  6898 		}
  6919 		}
  6899 		$post_ID = (int) $post_ID;
  6920 		$post_id = (int) $post_id;
  6900 
  6921 
  6901 		$post = get_post( $post_ID );
  6922 		$post = get_post( $post_id );
  6902 
  6923 
  6903 		if ( ! $post ) { // Post not found.
  6924 		if ( ! $post ) { // Post not found.
  6904 			return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either does not exist, or it is not a pingback-enabled resource.' ) );
  6925 			return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either does not exist, or it is not a pingback-enabled resource.' ) );
  6905 		}
  6926 		}
  6906 
  6927 
  6907 		if ( url_to_postid( $pagelinkedfrom ) == $post_ID ) {
  6928 		if ( url_to_postid( $pagelinkedfrom ) == $post_id ) {
  6908 			return $this->pingback_error( 0, __( 'The source URL and the target URL cannot both point to the same resource.' ) );
  6929 			return $this->pingback_error( 0, __( 'The source URL and the target URL cannot both point to the same resource.' ) );
  6909 		}
  6930 		}
  6910 
  6931 
  6911 		// Check if pings are on.
  6932 		// Check if pings are on.
  6912 		if ( ! pings_open( $post ) ) {
  6933 		if ( ! pings_open( $post ) ) {
  6913 			return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either does not exist, or it is not a pingback-enabled resource.' ) );
  6934 			return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either does not exist, or it is not a pingback-enabled resource.' ) );
  6914 		}
  6935 		}
  6915 
  6936 
  6916 		// Let's check that the remote site didn't already pingback this entry.
  6937 		// Let's check that the remote site didn't already pingback this entry.
  6917 		if ( $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_author_url = %s", $post_ID, $pagelinkedfrom ) ) ) {
  6938 		if ( $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_author_url = %s", $post_id, $pagelinkedfrom ) ) ) {
  6918 			return $this->pingback_error( 48, __( 'The pingback has already been registered.' ) );
  6939 			return $this->pingback_error( 48, __( 'The pingback has already been registered.' ) );
  6919 		}
  6940 		}
  6920 
  6941 
  6921 		// Very stupid, but gives time to the 'from' server to publish!
  6942 		/*
       
  6943 		 * The remote site may have sent the pingback before it finished publishing its own content
       
  6944 		 * containing this pingback URL. If that happens then it won't be immediately possible to fetch
       
  6945 		 * the pinging post; adding a small delay reduces the likelihood of this happening.
       
  6946 		 *
       
  6947 		 * While there are more robust methods than calling `sleep()` here (because `sleep()` merely
       
  6948 		 * mitigates the risk of requesting the remote post before it's available), this is effective
       
  6949 		 * enough for most cases and avoids introducing more complexity into this code.
       
  6950 		 *
       
  6951 		 * One way to improve the reliability of this code might be to add failure-handling to the remote
       
  6952 		 * fetch and retry up to a set number of times if it receives a 404. This could also handle 401 and
       
  6953 		 * 403 responses to differentiate the "does not exist" failure from the "may not access" failure.
       
  6954 		 */
  6922 		sleep( 1 );
  6955 		sleep( 1 );
  6923 
  6956 
  6924 		$remote_ip = preg_replace( '/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR'] );
  6957 		$remote_ip = preg_replace( '/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR'] );
  6925 
  6958 
  6926 		/** This filter is documented in wp-includes/class-wp-http.php */
  6959 		/** This filter is documented in wp-includes/class-wp-http.php */
  6974 		$p = explode( "\n\n", $remote_source );
  7007 		$p = explode( "\n\n", $remote_source );
  6975 
  7008 
  6976 		$preg_target = preg_quote( $pagelinkedto, '|' );
  7009 		$preg_target = preg_quote( $pagelinkedto, '|' );
  6977 
  7010 
  6978 		foreach ( $p as $para ) {
  7011 		foreach ( $p as $para ) {
  6979 			if ( strpos( $para, $pagelinkedto ) !== false ) { // It exists, but is it a link?
  7012 			if ( str_contains( $para, $pagelinkedto ) ) { // It exists, but is it a link?
  6980 				preg_match( '|<a[^>]+?' . $preg_target . '[^>]*>([^>]+?)</a>|', $para, $context );
  7013 				preg_match( '|<a[^>]+?' . $preg_target . '[^>]*>([^>]+?)</a>|', $para, $context );
  6981 
  7014 
  6982 				// If the URL isn't in a link context, keep looking.
  7015 				// If the URL isn't in a link context, keep looking.
  6983 				if ( empty( $context ) ) {
  7016 				if ( empty( $context ) ) {
  6984 					continue;
  7017 					continue;
  6985 				}
  7018 				}
  6986 
  7019 
  6987 				// We're going to use this fake tag to mark the context in a bit.
  7020 				/*
  6988 				// The marker is needed in case the link text appears more than once in the paragraph.
  7021 				 * We're going to use this fake tag to mark the context in a bit.
       
  7022 				 * The marker is needed in case the link text appears more than once in the paragraph.
       
  7023 				 */
  6989 				$excerpt = preg_replace( '|\</?wpcontext\>|', '', $para );
  7024 				$excerpt = preg_replace( '|\</?wpcontext\>|', '', $para );
  6990 
  7025 
  6991 				// prevent really long link text
  7026 				// prevent really long link text
  6992 				if ( strlen( $context[1] ) > 100 ) {
  7027 				if ( strlen( $context[1] ) > 100 ) {
  6993 					$context[1] = substr( $context[1], 0, 100 ) . '&#8230;';
  7028 					$context[1] = substr( $context[1], 0, 100 ) . '&#8230;';
  7011 		$pagelinkedfrom = str_replace( '&', '&amp;', $pagelinkedfrom );
  7046 		$pagelinkedfrom = str_replace( '&', '&amp;', $pagelinkedfrom );
  7012 
  7047 
  7013 		$context        = '[&#8230;] ' . esc_html( $excerpt ) . ' [&#8230;]';
  7048 		$context        = '[&#8230;] ' . esc_html( $excerpt ) . ' [&#8230;]';
  7014 		$pagelinkedfrom = $this->escape( $pagelinkedfrom );
  7049 		$pagelinkedfrom = $this->escape( $pagelinkedfrom );
  7015 
  7050 
  7016 		$comment_post_ID      = (int) $post_ID;
  7051 		$comment_post_id      = (int) $post_id;
  7017 		$comment_author       = $title;
  7052 		$comment_author       = $title;
  7018 		$comment_author_email = '';
  7053 		$comment_author_email = '';
  7019 		$this->escape( $comment_author );
  7054 		$this->escape( $comment_author );
  7020 		$comment_author_url = $pagelinkedfrom;
  7055 		$comment_author_url = $pagelinkedfrom;
  7021 		$comment_content    = $context;
  7056 		$comment_content    = $context;
  7022 		$this->escape( $comment_content );
  7057 		$this->escape( $comment_content );
  7023 		$comment_type = 'pingback';
  7058 		$comment_type = 'pingback';
  7024 
  7059 
  7025 		$commentdata = compact(
  7060 		$commentdata = array(
  7026 			'comment_post_ID',
  7061 			'comment_post_ID' => $comment_post_id,
       
  7062 		);
       
  7063 
       
  7064 		$commentdata += compact(
  7027 			'comment_author',
  7065 			'comment_author',
  7028 			'comment_author_url',
  7066 			'comment_author_url',
  7029 			'comment_author_email',
  7067 			'comment_author_email',
  7030 			'comment_content',
  7068 			'comment_content',
  7031 			'comment_type',
  7069 			'comment_type',
  7032 			'remote_source',
  7070 			'remote_source',
  7033 			'remote_source_original'
  7071 			'remote_source_original'
  7034 		);
  7072 		);
  7035 
  7073 
  7036 		$comment_ID = wp_new_comment( $commentdata );
  7074 		$comment_id = wp_new_comment( $commentdata );
  7037 
  7075 
  7038 		if ( is_wp_error( $comment_ID ) ) {
  7076 		if ( is_wp_error( $comment_id ) ) {
  7039 			return $this->pingback_error( 0, $comment_ID->get_error_message() );
  7077 			return $this->pingback_error( 0, $comment_id->get_error_message() );
  7040 		}
  7078 		}
  7041 
  7079 
  7042 		/**
  7080 		/**
  7043 		 * Fires after a post pingback has been sent.
  7081 		 * Fires after a post pingback has been sent.
  7044 		 *
  7082 		 *
  7045 		 * @since 0.71
  7083 		 * @since 0.71
  7046 		 *
  7084 		 *
  7047 		 * @param int $comment_ID Comment ID.
  7085 		 * @param int $comment_id Comment ID.
  7048 		 */
  7086 		 */
  7049 		do_action( 'pingback_post', $comment_ID );
  7087 		do_action( 'pingback_post', $comment_id );
  7050 
  7088 
  7051 		/* translators: 1: URL of the page linked from, 2: URL of the page linked to. */
  7089 		/* translators: 1: URL of the page linked from, 2: URL of the page linked to. */
  7052 		return sprintf( __( 'Pingback from %1$s to %2$s registered. Keep the web talking! :-)' ), $pagelinkedfrom, $pagelinkedto );
  7090 		return sprintf( __( 'Pingback from %1$s to %2$s registered. Keep the web talking! :-)' ), $pagelinkedfrom, $pagelinkedto );
  7053 	}
  7091 	}
  7054 
  7092 
  7055 	/**
  7093 	/**
  7056 	 * Retrieve array of URLs that pingbacked the given URL.
  7094 	 * Retrieves an array of URLs that pingbacked the given URL.
  7057 	 *
  7095 	 *
  7058 	 * Specs on http://www.aquarionics.com/misc/archives/blogite/0198.html
  7096 	 * Specs on http://www.aquarionics.com/misc/archives/blogite/0198.html
  7059 	 *
  7097 	 *
  7060 	 * @since 1.5.0
  7098 	 * @since 1.5.0
  7061 	 *
  7099 	 *
  7070 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  7108 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  7071 		do_action( 'xmlrpc_call', 'pingback.extensions.getPingbacks', $url, $this );
  7109 		do_action( 'xmlrpc_call', 'pingback.extensions.getPingbacks', $url, $this );
  7072 
  7110 
  7073 		$url = $this->escape( $url );
  7111 		$url = $this->escape( $url );
  7074 
  7112 
  7075 		$post_ID = url_to_postid( $url );
  7113 		$post_id = url_to_postid( $url );
  7076 		if ( ! $post_ID ) {
  7114 		if ( ! $post_id ) {
  7077 			// We aren't sure that the resource is available and/or pingback enabled.
  7115 			// We aren't sure that the resource is available and/or pingback enabled.
  7078 			return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either does not exist, or it is not a pingback-enabled resource.' ) );
  7116 			return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either does not exist, or it is not a pingback-enabled resource.' ) );
  7079 		}
  7117 		}
  7080 
  7118 
  7081 		$actual_post = get_post( $post_ID, ARRAY_A );
  7119 		$actual_post = get_post( $post_id, ARRAY_A );
  7082 
  7120 
  7083 		if ( ! $actual_post ) {
  7121 		if ( ! $actual_post ) {
  7084 			// No such post = resource not found.
  7122 			// No such post = resource not found.
  7085 			return $this->pingback_error( 32, __( 'The specified target URL does not exist.' ) );
  7123 			return $this->pingback_error( 32, __( 'The specified target URL does not exist.' ) );
  7086 		}
  7124 		}
  7087 
  7125 
  7088 		$comments = $wpdb->get_results( $wpdb->prepare( "SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_ID ) );
  7126 		$comments = $wpdb->get_results( $wpdb->prepare( "SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_id ) );
  7089 
  7127 
  7090 		if ( ! $comments ) {
  7128 		if ( ! $comments ) {
  7091 			return array();
  7129 			return array();
  7092 		}
  7130 		}
  7093 
  7131