wp/wp-includes/class-wp-xmlrpc-server.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
    12  * Implements compatibility for Blogger API, MetaWeblog API, MovableType, and
    12  * Implements compatibility for Blogger API, MetaWeblog API, MovableType, and
    13  * pingback. Additional WordPress API for managing comments, pages, posts,
    13  * pingback. Additional WordPress API for managing comments, pages, posts,
    14  * options, etc.
    14  * options, etc.
    15  *
    15  *
    16  * As of WordPress 3.5.0, XML-RPC is enabled by default. It can be disabled
    16  * As of WordPress 3.5.0, XML-RPC is enabled by default. It can be disabled
    17  * via the xmlrpc_enabled filter found in wp_xmlrpc_server::login().
    17  * via the {@see 'xmlrpc_enabled'} filter found in wp_xmlrpc_server::login().
    18  *
    18  *
    19  * @package WordPress
       
    20  * @subpackage Publishing
       
    21  * @since 1.5.0
    19  * @since 1.5.0
       
    20  *
       
    21  * @see IXR_Server
    22  */
    22  */
    23 class wp_xmlrpc_server extends IXR_Server {
    23 class wp_xmlrpc_server extends IXR_Server {
    24 	/**
    24 	/**
       
    25 	 * Methods.
       
    26 	 *
    25 	 * @var array
    27 	 * @var array
    26 	 */
    28 	 */
    27 	public $methods;
    29 	public $methods;
    28 	/**
    30 
       
    31 	/**
       
    32 	 * Blog options.
       
    33 	 *
    29 	 * @var array
    34 	 * @var array
    30 	 */
    35 	 */
    31 	public $blog_options;
    36 	public $blog_options;
    32 	/**
    37 
       
    38 	/**
       
    39 	 * IXR_Error instance.
       
    40 	 *
    33 	 * @var IXR_Error
    41 	 * @var IXR_Error
    34 	 */
    42 	 */
    35 	public $error;
    43 	public $error;
    36 	/**
    44 
    37 	 * Register all of the XMLRPC methods that XMLRPC server understands.
    45 	/**
       
    46 	 * Flags that the user authentication has failed in this instance of wp_xmlrpc_server.
       
    47 	 *
       
    48 	 * @var bool
       
    49 	 */
       
    50 	protected $auth_failed = false;
       
    51 
       
    52 	/**
       
    53 	 * Registers all of the XMLRPC methods that XMLRPC server understands.
    38 	 *
    54 	 *
    39 	 * Sets up server and method property. Passes XMLRPC
    55 	 * Sets up server and method property. Passes XMLRPC
    40 	 * methods through the 'xmlrpc_methods' filter to allow plugins to extend
    56 	 * methods through the {@see 'xmlrpc_methods'} filter to allow plugins to extend
    41 	 * or replace XMLRPC methods.
    57 	 * or replace XML-RPC methods.
    42 	 *
    58 	 *
    43 	 * @since 1.5.0
    59 	 * @since 1.5.0
    44 	 */
    60 	 */
    45 	public function __construct() {
    61 	public function __construct() {
    46 		$this->methods = array(
    62 		$this->methods = array(
   137 		);
   153 		);
   138 
   154 
   139 		$this->initialise_blog_option_info();
   155 		$this->initialise_blog_option_info();
   140 
   156 
   141 		/**
   157 		/**
   142 		 * Filter the methods exposed by the XML-RPC server.
   158 		 * Filters the methods exposed by the XML-RPC server.
   143 		 *
   159 		 *
   144 		 * This filter can be used to add new methods, and remove built-in methods.
   160 		 * This filter can be used to add new methods, and remove built-in methods.
   145 		 *
   161 		 *
   146 		 * @since 1.5.0
   162 		 * @since 1.5.0
   147 		 *
   163 		 *
   149 		 */
   165 		 */
   150 		$this->methods = apply_filters( 'xmlrpc_methods', $this->methods );
   166 		$this->methods = apply_filters( 'xmlrpc_methods', $this->methods );
   151 	}
   167 	}
   152 
   168 
   153 	/**
   169 	/**
   154 	 * Make private/protected methods readable for backwards compatibility.
   170 	 * Make private/protected methods readable for backward compatibility.
   155 	 *
   171 	 *
   156 	 * @since 4.0.0
   172 	 * @since 4.0.0
   157 	 * @access public
       
   158 	 *
   173 	 *
   159 	 * @param callable $name      Method to call.
   174 	 * @param callable $name      Method to call.
   160 	 * @param array    $arguments Arguments to pass when calling.
   175 	 * @param array    $arguments Arguments to pass when calling.
   161 	 * @return mixed|bool Return value of the callback, false otherwise.
   176 	 * @return array|IXR_Error|false Return value of the callback, false otherwise.
   162 	 */
   177 	 */
   163 	public function __call( $name, $arguments ) {
   178 	public function __call( $name, $arguments ) {
   164 		if ( '_multisite_getUsersBlogs' === $name ) {
   179 		if ( '_multisite_getUsersBlogs' === $name ) {
   165 			return call_user_func_array( array( $this, $name ), $arguments );
   180 			return call_user_func_array( array( $this, $name ), $arguments );
   166 		}
   181 		}
   167 		return false;
   182 		return false;
   168 	}
   183 	}
   169 
   184 
       
   185 	/**
       
   186 	 * Serves the XML-RPC request.
       
   187 	 *
       
   188 	 * @since 2.9.0
       
   189 	 */
   170 	public function serve_request() {
   190 	public function serve_request() {
   171 		$this->IXR_Server($this->methods);
   191 		$this->IXR_Server($this->methods);
   172 	}
   192 	}
   173 
   193 
   174 	/**
   194 	/**
   175 	 * Test XMLRPC API by saying, "Hello!" to client.
   195 	 * Test XMLRPC API by saying, "Hello!" to client.
   176 	 *
   196 	 *
   177 	 * @since 1.5.0
   197 	 * @since 1.5.0
   178 	 *
   198 	 *
   179 	 * @param array $args Method Parameters.
   199 	 * @return string Hello string response.
   180 	 * @return string
   200 	 */
   181 	 */
   201 	public function sayHello() {
   182 	public function sayHello($args) {
       
   183 		return 'Hello!';
   202 		return 'Hello!';
   184 	}
   203 	}
   185 
   204 
   186 	/**
   205 	/**
   187 	 * Test XMLRPC API by adding two numbers for client.
   206 	 * Test XMLRPC API by adding two numbers for client.
   188 	 *
   207 	 *
   189 	 * @since 1.5.0
   208 	 * @since 1.5.0
   190 	 *
   209 	 *
   191 	 * @param array $args Method Parameters.
   210 	 * @param array  $args {
   192 	 * @return int
   211 	 *     Method arguments. Note: arguments must be ordered as documented.
   193 	 */
   212 	 *
   194 	public function addTwoNumbers($args) {
   213 	 *     @type int $number1 A number to add.
       
   214 	 *     @type int $number2 A second number to add.
       
   215 	 * }
       
   216 	 * @return int Sum of the two given numbers.
       
   217 	 */
       
   218 	public function addTwoNumbers( $args ) {
   195 		$number1 = $args[0];
   219 		$number1 = $args[0];
   196 		$number2 = $args[1];
   220 		$number2 = $args[1];
   197 		return $number1 + $number2;
   221 		return $number1 + $number2;
   198 	}
   222 	}
   199 
   223 
   215 		if ( false === $enabled ) {
   239 		if ( false === $enabled ) {
   216 			$enabled = apply_filters( 'option_enable_xmlrpc', true );
   240 			$enabled = apply_filters( 'option_enable_xmlrpc', true );
   217 		}
   241 		}
   218 
   242 
   219 		/**
   243 		/**
   220 		 * Filter whether XML-RPC is enabled.
   244 		 * Filters whether XML-RPC methods requiring authentication are enabled.
   221 		 *
   245 		 *
   222 		 * This is the proper filter for turning off XML-RPC.
   246 		 * Contrary to the way it's named, this filter does not control whether XML-RPC is *fully*
       
   247 		 * enabled, rather, it only controls whether XML-RPC methods requiring authentication - such
       
   248 		 * as for publishing purposes - are enabled.
       
   249 		 *
       
   250 		 * Further, the filter does not control whether pingbacks or other custom endpoints that don't
       
   251 		 * require authentication are enabled. This behavior is expected, and due to how parity was matched
       
   252 		 * with the `enable_xmlrpc` UI option the filter replaced when it was introduced in 3.5.
       
   253 		 *
       
   254 		 * To disable XML-RPC methods that require authentication, use:
       
   255 		 *
       
   256 		 *     add_filter( 'xmlrpc_enabled', '__return_false' );
       
   257 		 *
       
   258 		 * For more granular control over all XML-RPC methods and requests, see the {@see 'xmlrpc_methods'}
       
   259 		 * and {@see 'xmlrpc_element_limit'} hooks.
   223 		 *
   260 		 *
   224 		 * @since 3.5.0
   261 		 * @since 3.5.0
   225 		 *
   262 		 *
   226 		 * @param bool $enabled Whether XML-RPC is enabled. Default true.
   263 		 * @param bool $enabled Whether XML-RPC is enabled. Default true.
   227 		 */
   264 		 */
   230 		if ( ! $enabled ) {
   267 		if ( ! $enabled ) {
   231 			$this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site.' ) ) );
   268 			$this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site.' ) ) );
   232 			return false;
   269 			return false;
   233 		}
   270 		}
   234 
   271 
   235 		$user = wp_authenticate($username, $password);
   272 		if ( $this->auth_failed ) {
   236 
   273 			$user = new WP_Error( 'login_prevented' );
   237 		if (is_wp_error($user)) {
   274 		} else {
       
   275 			$user = wp_authenticate( $username, $password );
       
   276 		}
       
   277 
       
   278 		if ( is_wp_error( $user ) ) {
   238 			$this->error = new IXR_Error( 403, __( 'Incorrect username or password.' ) );
   279 			$this->error = new IXR_Error( 403, __( 'Incorrect username or password.' ) );
   239 
   280 
       
   281 			// Flag that authentication has failed once on this wp_xmlrpc_server instance
       
   282 			$this->auth_failed = true;
       
   283 
   240 			/**
   284 			/**
   241 			 * Filter the XML-RPC user login error message.
   285 			 * Filters the XML-RPC user login error message.
   242 			 *
   286 			 *
   243 			 * @since 3.5.0
   287 			 * @since 3.5.0
   244 			 *
   288 			 *
   245 			 * @param string  $error The XML-RPC error message.
   289 			 * @param string  $error The XML-RPC error message.
   246 			 * @param WP_User $user  WP_User object.
   290 			 * @param WP_User $user  WP_User object.
   255 
   299 
   256 	/**
   300 	/**
   257 	 * Check user's credentials. Deprecated.
   301 	 * Check user's credentials. Deprecated.
   258 	 *
   302 	 *
   259 	 * @since 1.5.0
   303 	 * @since 1.5.0
   260 	 * @deprecated 2.8.0
   304 	 * @deprecated 2.8.0 Use wp_xmlrpc_server::login()
   261 	 * @deprecated use wp_xmlrpc_server::login
   305 	 * @see wp_xmlrpc_server::login()
   262 	 * @see wp_xmlrpc_server::login
       
   263 	 *
   306 	 *
   264 	 * @param string $username User's username.
   307 	 * @param string $username User's username.
   265 	 * @param string $password User's password.
   308 	 * @param string $password User's password.
   266 	 * @return bool Whether authentication passed.
   309 	 * @return bool Whether authentication passed.
   267 	 */
   310 	 */
   273 	 * Escape string or array of strings for database.
   316 	 * Escape string or array of strings for database.
   274 	 *
   317 	 *
   275 	 * @since 1.5.2
   318 	 * @since 1.5.2
   276 	 *
   319 	 *
   277 	 * @param string|array $data Escape single string or array of strings.
   320 	 * @param string|array $data Escape single string or array of strings.
   278 	 * @return string|array Type matches $data and sanitized for the database.
   321 	 * @return string|void Returns with string is passed, alters by-reference
       
   322 	 *                     when array is passed.
   279 	 */
   323 	 */
   280 	public function escape( &$data ) {
   324 	public function escape( &$data ) {
   281 		if ( ! is_array( $data ) )
   325 		if ( ! is_array( $data ) )
   282 			return wp_slash( $data );
   326 			return wp_slash( $data );
   283 
   327 
   330 
   374 
   331 		foreach ( (array) $fields as $meta ) {
   375 		foreach ( (array) $fields as $meta ) {
   332 			if ( isset($meta['id']) ) {
   376 			if ( isset($meta['id']) ) {
   333 				$meta['id'] = (int) $meta['id'];
   377 				$meta['id'] = (int) $meta['id'];
   334 				$pmeta = get_metadata_by_mid( 'post', $meta['id'] );
   378 				$pmeta = get_metadata_by_mid( 'post', $meta['id'] );
       
   379 
       
   380 				if ( ! $pmeta || $pmeta->post_id != $post_id ) {
       
   381 					continue;
       
   382 				}
       
   383 
   335 				if ( isset($meta['key']) ) {
   384 				if ( isset($meta['key']) ) {
   336 					$meta['key'] = wp_unslash( $meta['key'] );
   385 					$meta['key'] = wp_unslash( $meta['key'] );
   337 					if ( $meta['key'] !== $pmeta->meta_key )
   386 					if ( $meta['key'] !== $pmeta->meta_key )
   338 						continue;
   387 						continue;
   339 					$meta['value'] = wp_unslash( $meta['value'] );
   388 					$meta['value'] = wp_unslash( $meta['value'] );
   347 			}
   396 			}
   348 		}
   397 		}
   349 	}
   398 	}
   350 
   399 
   351 	/**
   400 	/**
       
   401 	 * Retrieve custom fields for a term.
       
   402 	 *
       
   403 	 * @since 4.9.0
       
   404 	 *
       
   405 	 * @param int $term_id Term ID.
       
   406 	 * @return array Array of custom fields, if they exist.
       
   407 	 */
       
   408 	public function get_term_custom_fields( $term_id ) {
       
   409 		$term_id = (int) $term_id;
       
   410 
       
   411 		$custom_fields = array();
       
   412 
       
   413 		foreach ( (array) has_term_meta( $term_id ) as $meta ) {
       
   414 
       
   415 			if ( ! current_user_can( 'edit_term_meta', $term_id ) ) {
       
   416 				continue;
       
   417 			}
       
   418 
       
   419 			$custom_fields[] = array(
       
   420 				'id'    => $meta['meta_id'],
       
   421 				'key'   => $meta['meta_key'],
       
   422 				'value' => $meta['meta_value'],
       
   423 			);
       
   424 		}
       
   425 
       
   426 		return $custom_fields;
       
   427 	}
       
   428 
       
   429 	/**
       
   430 	 * Set custom fields for a term.
       
   431 	 *
       
   432 	 * @since 4.9.0
       
   433 	 *
       
   434 	 * @param int $term_id Term ID.
       
   435 	 * @param array $fields Custom fields.
       
   436 	 */
       
   437 	public function set_term_custom_fields( $term_id, $fields ) {
       
   438 		$term_id = (int) $term_id;
       
   439 
       
   440 		foreach ( (array) $fields as $meta ) {
       
   441 			if ( isset( $meta['id'] ) ) {
       
   442 				$meta['id'] = (int) $meta['id'];
       
   443 				$pmeta = get_metadata_by_mid( 'term', $meta['id'] );
       
   444 				if ( isset( $meta['key'] ) ) {
       
   445 					$meta['key'] = wp_unslash( $meta['key'] );
       
   446 					if ( $meta['key'] !== $pmeta->meta_key ) {
       
   447 						continue;
       
   448 					}
       
   449 					$meta['value'] = wp_unslash( $meta['value'] );
       
   450 					if ( current_user_can( 'edit_term_meta', $term_id ) ) {
       
   451 						update_metadata_by_mid( 'term', $meta['id'], $meta['value'] );
       
   452 					}
       
   453 				} elseif ( current_user_can( 'delete_term_meta', $term_id ) ) {
       
   454 					delete_metadata_by_mid( 'term', $meta['id'] );
       
   455 				}
       
   456 			} elseif ( current_user_can( 'add_term_meta', $term_id ) ) {
       
   457 				add_term_meta( $term_id, $meta['key'], $meta['value'] );
       
   458 			}
       
   459 		}
       
   460 	}
       
   461 
       
   462 	/**
   352 	 * Set up blog options property.
   463 	 * Set up blog options property.
   353 	 *
   464 	 *
   354 	 * Passes property through 'xmlrpc_blog_options' filter.
   465 	 * Passes property through {@see 'xmlrpc_blog_options'} filter.
   355 	 *
   466 	 *
   356 	 * @since 2.6.0
   467 	 * @since 2.6.0
   357 	 */
   468 	 */
   358 	public function initialise_blog_option_info() {
   469 	public function initialise_blog_option_info() {
   359 		global $wp_version;
       
   360 
       
   361 		$this->blog_options = array(
   470 		$this->blog_options = array(
   362 			// Read only options
   471 			// Read only options
   363 			'software_name'     => array(
   472 			'software_name'     => array(
   364 				'desc'          => __( 'Software Name' ),
   473 				'desc'          => __( 'Software Name' ),
   365 				'readonly'      => true,
   474 				'readonly'      => true,
   366 				'value'         => 'WordPress'
   475 				'value'         => 'WordPress'
   367 			),
   476 			),
   368 			'software_version'  => array(
   477 			'software_version'  => array(
   369 				'desc'          => __( 'Software Version' ),
   478 				'desc'          => __( 'Software Version' ),
   370 				'readonly'      => true,
   479 				'readonly'      => true,
   371 				'value'         => $wp_version
   480 				'value'         => get_bloginfo( 'version' )
   372 			),
   481 			),
   373 			'blog_url'          => array(
   482 			'blog_url'          => array(
   374 				'desc'          => __( 'WordPress Address (URL)' ),
   483 				'desc'          => __( 'WordPress Address (URL)' ),
   375 				'readonly'      => true,
   484 				'readonly'      => true,
   376 				'option'        => 'siteurl'
   485 				'option'        => 'siteurl'
   475 			'medium_size_h'     => array(
   584 			'medium_size_h'     => array(
   476 				'desc'          => __( 'Medium size image height' ),
   585 				'desc'          => __( 'Medium size image height' ),
   477 				'readonly'      => false,
   586 				'readonly'      => false,
   478 				'option'        => 'medium_size_h'
   587 				'option'        => 'medium_size_h'
   479 			),
   588 			),
       
   589 			'medium_large_size_w'   => array(
       
   590 				'desc'          => __( 'Medium-Large size image width' ),
       
   591 				'readonly'      => false,
       
   592 				'option'        => 'medium_large_size_w'
       
   593 			),
       
   594 			'medium_large_size_h'   => array(
       
   595 				'desc'          => __( 'Medium-Large size image height' ),
       
   596 				'readonly'      => false,
       
   597 				'option'        => 'medium_large_size_h'
       
   598 			),
   480 			'large_size_w'      => array(
   599 			'large_size_w'      => array(
   481 				'desc'          => __( 'Large size image width' ),
   600 				'desc'          => __( 'Large size image width' ),
   482 				'readonly'      => false,
   601 				'readonly'      => false,
   483 				'option'        => 'large_size_w'
   602 				'option'        => 'large_size_w'
   484 			),
   603 			),
   491 				'desc'          => __( 'Allow people to post comments on new articles' ),
   610 				'desc'          => __( 'Allow people to post comments on new articles' ),
   492 				'readonly'      => false,
   611 				'readonly'      => false,
   493 				'option'        => 'default_comment_status'
   612 				'option'        => 'default_comment_status'
   494 			),
   613 			),
   495 			'default_ping_status' => array(
   614 			'default_ping_status' => array(
   496 				'desc'          => __( 'Allow link notifications from other blogs (pingbacks and trackbacks)' ),
   615 				'desc'          => __( 'Allow link notifications from other blogs (pingbacks and trackbacks) on new articles' ),
   497 				'readonly'      => false,
   616 				'readonly'      => false,
   498 				'option'        => 'default_ping_status'
   617 				'option'        => 'default_ping_status'
   499 			)
   618 			)
   500 		);
   619 		);
   501 
   620 
   502 		/**
   621 		/**
   503 		 * Filter the XML-RPC blog options property.
   622 		 * Filters the XML-RPC blog options property.
   504 		 *
   623 		 *
   505 		 * @since 2.6.0
   624 		 * @since 2.6.0
   506 		 *
   625 		 *
   507 		 * @param array $blog_options An array of XML-RPC blog options.
   626 		 * @param array $blog_options An array of XML-RPC blog options.
   508 		 */
   627 		 */
   512 	/**
   631 	/**
   513 	 * Retrieve the blogs of the user.
   632 	 * Retrieve the blogs of the user.
   514 	 *
   633 	 *
   515 	 * @since 2.6.0
   634 	 * @since 2.6.0
   516 	 *
   635 	 *
   517 	 * @param array $args Method parameters. Contains:
   636 	 * @param array $args {
   518 	 *  - username
   637 	 *     Method arguments. Note: arguments must be ordered as documented.
   519 	 *  - password
   638 	 *
       
   639 	 *     @type string $username Username.
       
   640 	 *     @type string $password Password.
       
   641 	 * }
   520 	 * @return array|IXR_Error Array contains:
   642 	 * @return array|IXR_Error Array contains:
   521 	 *  - 'isAdmin'
   643 	 *  - 'isAdmin'
       
   644 	 *  - 'isPrimary' - whether the blog is the user's primary blog
   522 	 *  - 'url'
   645 	 *  - 'url'
   523 	 *  - 'blogid'
   646 	 *  - 'blogid'
   524 	 *  - 'blogName'
   647 	 *  - 'blogName'
   525 	 *  - 'xmlrpc' - url of xmlrpc endpoint
   648 	 *  - 'xmlrpc' - url of xmlrpc endpoint
   526 	 */
   649 	 */
   527 	public function wp_getUsersBlogs( $args ) {
   650 	public function wp_getUsersBlogs( $args ) {
       
   651 		if ( ! $this->minimum_args( $args, 2 ) ) {
       
   652 			return $this->error;
       
   653 		}
       
   654 
   528 		// If this isn't on WPMU then just use blogger_getUsersBlogs
   655 		// If this isn't on WPMU then just use blogger_getUsersBlogs
   529 		if ( !is_multisite() ) {
   656 		if ( !is_multisite() ) {
   530 			array_unshift( $args, 1 );
   657 			array_unshift( $args, 1 );
   531 			return $this->blogger_getUsersBlogs( $args );
   658 			return $this->blogger_getUsersBlogs( $args );
   532 		}
   659 		}
   546 		 * All built-in XML-RPC methods use the action xmlrpc_call, with a parameter
   673 		 * All built-in XML-RPC methods use the action xmlrpc_call, with a parameter
   547 		 * equal to the method's name, e.g., wp.getUsersBlogs, wp.newPost, etc.
   674 		 * equal to the method's name, e.g., wp.getUsersBlogs, wp.newPost, etc.
   548 		 *
   675 		 *
   549 		 * @since 2.5.0
   676 		 * @since 2.5.0
   550 		 *
   677 		 *
   551 		 * @param method $name The method name.
   678 		 * @param string $name The method name.
   552 		 */
   679 		 */
   553 		do_action( 'xmlrpc_call', 'wp.getUsersBlogs' );
   680 		do_action( 'xmlrpc_call', 'wp.getUsersBlogs' );
   554 
   681 
   555 		$blogs = (array) get_blogs_of_user( $user->ID );
   682 		$blogs = (array) get_blogs_of_user( $user->ID );
   556 		$struct = array();
   683 		$struct = array();
       
   684 		$primary_blog_id = 0;
       
   685 		$active_blog = get_active_blog_for_user( $user->ID );
       
   686 		if ( $active_blog ) {
       
   687 			$primary_blog_id = (int) $active_blog->blog_id;
       
   688 		}
   557 
   689 
   558 		foreach ( $blogs as $blog ) {
   690 		foreach ( $blogs as $blog ) {
   559 			// Don't include blogs that aren't hosted at this site
   691 			// Don't include blogs that aren't hosted at this site.
   560 			if ( $blog->site_id != get_current_site()->id )
   692 			if ( $blog->site_id != get_current_network_id() )
   561 				continue;
   693 				continue;
   562 
   694 
   563 			$blog_id = $blog->userblog_id;
   695 			$blog_id = $blog->userblog_id;
   564 
   696 
   565 			switch_to_blog( $blog_id );
   697 			switch_to_blog( $blog_id );
   566 
   698 
   567 			$is_admin = current_user_can( 'manage_options' );
   699 			$is_admin = current_user_can( 'manage_options' );
       
   700 			$is_primary = ( (int) $blog_id === $primary_blog_id );
   568 
   701 
   569 			$struct[] = array(
   702 			$struct[] = array(
   570 				'isAdmin'		=> $is_admin,
   703 				'isAdmin'   => $is_admin,
   571 				'url'			=> home_url( '/' ),
   704 				'isPrimary' => $is_primary,
   572 				'blogid'		=> (string) $blog_id,
   705 				'url'       => home_url( '/' ),
   573 				'blogName'		=> get_option( 'blogname' ),
   706 				'blogid'    => (string) $blog_id,
   574 				'xmlrpc'		=> site_url( 'xmlrpc.php', 'rpc' ),
   707 				'blogName'  => get_option( 'blogname' ),
       
   708 				'xmlrpc'    => site_url( 'xmlrpc.php', 'rpc' ),
   575 			);
   709 			);
   576 
   710 
   577 			restore_current_blog();
   711 			restore_current_blog();
   578 		}
   712 		}
   579 
   713 
   584 	 * Checks if the method received at least the minimum number of arguments.
   718 	 * Checks if the method received at least the minimum number of arguments.
   585 	 *
   719 	 *
   586 	 * @since 3.4.0
   720 	 * @since 3.4.0
   587 	 *
   721 	 *
   588 	 * @param string|array $args Sanitize single string or array of strings.
   722 	 * @param string|array $args Sanitize single string or array of strings.
   589 	 * @param int $count Minimum number of arguments.
   723 	 * @param int $count         Minimum number of arguments.
   590 	 * @return boolean if $args contains at least $count arguments.
   724 	 * @return bool if `$args` contains at least $count arguments.
   591 	 */
   725 	 */
   592 	protected function minimum_args( $args, $count ) {
   726 	protected function minimum_args( $args, $count ) {
   593 		if ( count( $args ) < $count ) {
   727 		if ( count( $args ) < $count ) {
   594 			$this->error = new IXR_Error( 400, __( 'Insufficient arguments passed to this XML-RPC method.' ) );
   728 			$this->error = new IXR_Error( 400, __( 'Insufficient arguments passed to this XML-RPC method.' ) );
   595 			return false;
   729 			return false;
   599 	}
   733 	}
   600 
   734 
   601 	/**
   735 	/**
   602 	 * Prepares taxonomy data for return in an XML-RPC object.
   736 	 * Prepares taxonomy data for return in an XML-RPC object.
   603 	 *
   737 	 *
   604 	 * @access protected
   738 	 *
   605 	 *
   739 	 * @param object $taxonomy The unprepared taxonomy data.
   606 	 * @param object $taxonomy The unprepared taxonomy data
   740 	 * @param array $fields    The subset of taxonomy fields to return.
   607 	 * @param array $fields The subset of taxonomy fields to return
   741 	 * @return array The prepared taxonomy data.
   608 	 * @return array The prepared taxonomy data
       
   609 	 */
   742 	 */
   610 	protected function _prepare_taxonomy( $taxonomy, $fields ) {
   743 	protected function _prepare_taxonomy( $taxonomy, $fields ) {
   611 		$_taxonomy = array(
   744 		$_taxonomy = array(
   612 			'name' => $taxonomy->name,
   745 			'name' => $taxonomy->name,
   613 			'label' => $taxonomy->label,
   746 			'label' => $taxonomy->label,
   628 
   761 
   629 		if ( in_array( 'object_type', $fields ) )
   762 		if ( in_array( 'object_type', $fields ) )
   630 			$_taxonomy['object_type'] = array_unique( (array) $taxonomy->object_type );
   763 			$_taxonomy['object_type'] = array_unique( (array) $taxonomy->object_type );
   631 
   764 
   632 		/**
   765 		/**
   633 		 * Filter XML-RPC-prepared data for the given taxonomy.
   766 		 * Filters XML-RPC-prepared data for the given taxonomy.
   634 		 *
   767 		 *
   635 		 * @since 3.4.0
   768 		 * @since 3.4.0
   636 		 *
   769 		 *
   637 		 * @param array  $_taxonomy An array of taxonomy data.
   770 		 * @param array       $_taxonomy An array of taxonomy data.
   638 		 * @param object $taxonomy  Taxonomy object.
   771 		 * @param WP_Taxonomy $taxonomy  Taxonomy object.
   639 		 * @param array  $fields    The subset of taxonomy fields to return.
   772 		 * @param array       $fields    The subset of taxonomy fields to return.
   640 		 */
   773 		 */
   641 		return apply_filters( 'xmlrpc_prepare_taxonomy', $_taxonomy, $taxonomy, $fields );
   774 		return apply_filters( 'xmlrpc_prepare_taxonomy', $_taxonomy, $taxonomy, $fields );
   642 	}
   775 	}
   643 
   776 
   644 	/**
   777 	/**
   645 	 * Prepares term data for return in an XML-RPC object.
   778 	 * Prepares term data for return in an XML-RPC object.
   646 	 *
   779 	 *
   647 	 * @access protected
   780 	 *
   648 	 *
   781 	 * @param array|object $term The unprepared term data.
   649 	 * @param array|object $term The unprepared term data
   782 	 * @return array The prepared term data.
   650 	 * @return array The prepared term data
       
   651 	 */
   783 	 */
   652 	protected function _prepare_term( $term ) {
   784 	protected function _prepare_term( $term ) {
   653 		$_term = $term;
   785 		$_term = $term;
   654 		if ( ! is_array( $_term) )
   786 		if ( ! is_array( $_term ) )
   655 			$_term = get_object_vars( $_term );
   787 			$_term = get_object_vars( $_term );
   656 
   788 
   657 		// For integers which may be larger than XML-RPC supports ensure we return strings.
   789 		// For integers which may be larger than XML-RPC supports ensure we return strings.
   658 		$_term['term_id'] = strval( $_term['term_id'] );
   790 		$_term['term_id'] = strval( $_term['term_id'] );
   659 		$_term['term_group'] = strval( $_term['term_group'] );
   791 		$_term['term_group'] = strval( $_term['term_group'] );
   661 		$_term['parent'] = strval( $_term['parent'] );
   793 		$_term['parent'] = strval( $_term['parent'] );
   662 
   794 
   663 		// Count we are happy to return as an integer because people really shouldn't use terms that much.
   795 		// Count we are happy to return as an integer because people really shouldn't use terms that much.
   664 		$_term['count'] = intval( $_term['count'] );
   796 		$_term['count'] = intval( $_term['count'] );
   665 
   797 
       
   798 		// Get term meta.
       
   799 		$_term['custom_fields'] = $this->get_term_custom_fields( $_term['term_id'] );
       
   800 
   666 		/**
   801 		/**
   667 		 * Filter XML-RPC-prepared data for the given term.
   802 		 * Filters XML-RPC-prepared data for the given term.
   668 		 *
   803 		 *
   669 		 * @since 3.4.0
   804 		 * @since 3.4.0
   670 		 *
   805 		 *
   671 		 * @param array        $_term An array of term data.
   806 		 * @param array        $_term An array of term data.
   672 		 * @param array|object $term  Term object or array.
   807 		 * @param array|object $term  Term object or array.
   675 	}
   810 	}
   676 
   811 
   677 	/**
   812 	/**
   678 	 * Convert a WordPress date string to an IXR_Date object.
   813 	 * Convert a WordPress date string to an IXR_Date object.
   679 	 *
   814 	 *
   680 	 * @access protected
   815 	 *
   681 	 *
   816 	 * @param string $date Date string to convert.
   682 	 * @param string $date
   817 	 * @return IXR_Date IXR_Date object.
   683 	 * @return IXR_Date
       
   684 	 */
   818 	 */
   685 	protected function _convert_date( $date ) {
   819 	protected function _convert_date( $date ) {
   686 		if ( $date === '0000-00-00 00:00:00' ) {
   820 		if ( $date === '0000-00-00 00:00:00' ) {
   687 			return new IXR_Date( '00000000T00:00:00Z' );
   821 			return new IXR_Date( '00000000T00:00:00Z' );
   688 		}
   822 		}
   690 	}
   824 	}
   691 
   825 
   692 	/**
   826 	/**
   693 	 * Convert a WordPress GMT date string to an IXR_Date object.
   827 	 * Convert a WordPress GMT date string to an IXR_Date object.
   694 	 *
   828 	 *
   695 	 * @access protected
   829 	 *
   696 	 *
   830 	 * @param string $date_gmt WordPress GMT date string.
   697 	 * @param string $date_gmt
   831 	 * @param string $date     Date string.
   698 	 * @param string $date
   832 	 * @return IXR_Date IXR_Date object.
   699 	 * @return IXR_Date
       
   700 	 */
   833 	 */
   701 	protected function _convert_date_gmt( $date_gmt, $date ) {
   834 	protected function _convert_date_gmt( $date_gmt, $date ) {
   702 		if ( $date !== '0000-00-00 00:00:00' && $date_gmt === '0000-00-00 00:00:00' ) {
   835 		if ( $date !== '0000-00-00 00:00:00' && $date_gmt === '0000-00-00 00:00:00' ) {
   703 			return new IXR_Date( get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $date, false ), 'Ymd\TH:i:s' ) );
   836 			return new IXR_Date( get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $date, false ), 'Ymd\TH:i:s' ) );
   704 		}
   837 		}
   706 	}
   839 	}
   707 
   840 
   708 	/**
   841 	/**
   709 	 * Prepares post data for return in an XML-RPC object.
   842 	 * Prepares post data for return in an XML-RPC object.
   710 	 *
   843 	 *
   711 	 * @access protected
   844 	 *
   712 	 *
   845 	 * @param array $post   The unprepared post data.
   713 	 * @param array $post The unprepared post data
   846 	 * @param array $fields The subset of post type fields to return.
   714 	 * @param array $fields The subset of post type fields to return
   847 	 * @return array The prepared post data.
   715 	 * @return array The prepared post data
       
   716 	 */
   848 	 */
   717 	protected function _prepare_post( $post, $fields ) {
   849 	protected function _prepare_post( $post, $fields ) {
   718 		// holds the data for this post. built up based on $fields
   850 		// Holds the data for this post. built up based on $fields.
   719 		$_post = array( 'post_id' => strval( $post['ID'] ) );
   851 		$_post = array( 'post_id' => strval( $post['ID'] ) );
   720 
   852 
   721 		// prepare common post fields
   853 		// Prepare common post fields.
   722 		$post_fields = array(
   854 		$post_fields = array(
   723 			'post_title'        => $post['post_title'],
   855 			'post_title'        => $post['post_title'],
   724 			'post_date'         => $this->_convert_date( $post['post_date'] ),
   856 			'post_date'         => $this->_convert_date( $post['post_date'] ),
   725 			'post_date_gmt'     => $this->_convert_date_gmt( $post['post_date_gmt'], $post['post_date'] ),
   857 			'post_date_gmt'     => $this->_convert_date_gmt( $post['post_date_gmt'], $post['post_date'] ),
   726 			'post_modified'     => $this->_convert_date( $post['post_modified'] ),
   858 			'post_modified'     => $this->_convert_date( $post['post_modified'] ),
   732 			'post_password'     => $post['post_password'],
   864 			'post_password'     => $post['post_password'],
   733 			'post_excerpt'      => $post['post_excerpt'],
   865 			'post_excerpt'      => $post['post_excerpt'],
   734 			'post_content'      => $post['post_content'],
   866 			'post_content'      => $post['post_content'],
   735 			'post_parent'       => strval( $post['post_parent'] ),
   867 			'post_parent'       => strval( $post['post_parent'] ),
   736 			'post_mime_type'    => $post['post_mime_type'],
   868 			'post_mime_type'    => $post['post_mime_type'],
   737 			'link'              => post_permalink( $post['ID'] ),
   869 			'link'              => get_permalink( $post['ID'] ),
   738 			'guid'              => $post['guid'],
   870 			'guid'              => $post['guid'],
   739 			'menu_order'        => intval( $post['menu_order'] ),
   871 			'menu_order'        => intval( $post['menu_order'] ),
   740 			'comment_status'    => $post['comment_status'],
   872 			'comment_status'    => $post['comment_status'],
   741 			'ping_status'       => $post['ping_status'],
   873 			'ping_status'       => $post['ping_status'],
   742 			'sticky'            => ( $post['post_type'] === 'post' && is_sticky( $post['ID'] ) ),
   874 			'sticky'            => ( $post['post_type'] === 'post' && is_sticky( $post['ID'] ) ),
   743 		);
   875 		);
   744 
   876 
   745 		// Thumbnail
   877 		// Thumbnail.
   746 		$post_fields['post_thumbnail'] = array();
   878 		$post_fields['post_thumbnail'] = array();
   747 		$thumbnail_id = get_post_thumbnail_id( $post['ID'] );
   879 		$thumbnail_id = get_post_thumbnail_id( $post['ID'] );
   748 		if ( $thumbnail_id ) {
   880 		if ( $thumbnail_id ) {
   749 			$thumbnail_size = current_theme_supports('post-thumbnail') ? 'post-thumbnail' : 'thumbnail';
   881 			$thumbnail_size = current_theme_supports('post-thumbnail') ? 'post-thumbnail' : 'thumbnail';
   750 			$post_fields['post_thumbnail'] = $this->_prepare_media_item( get_post( $thumbnail_id ), $thumbnail_size );
   882 			$post_fields['post_thumbnail'] = $this->_prepare_media_item( get_post( $thumbnail_id ), $thumbnail_size );
   751 		}
   883 		}
   752 
   884 
   753 		// Consider future posts as published
   885 		// Consider future posts as published.
   754 		if ( $post_fields['post_status'] === 'future' )
   886 		if ( $post_fields['post_status'] === 'future' )
   755 			$post_fields['post_status'] = 'publish';
   887 			$post_fields['post_status'] = 'publish';
   756 
   888 
   757 		// Fill in blank post format
   889 		// Fill in blank post format.
   758 		$post_fields['post_format'] = get_post_format( $post['ID'] );
   890 		$post_fields['post_format'] = get_post_format( $post['ID'] );
   759 		if ( empty( $post_fields['post_format'] ) )
   891 		if ( empty( $post_fields['post_format'] ) )
   760 			$post_fields['post_format'] = 'standard';
   892 			$post_fields['post_format'] = 'standard';
   761 
   893 
   762 		// Merge requested $post_fields fields into $_post
   894 		// Merge requested $post_fields fields into $_post.
   763 		if ( in_array( 'post', $fields ) ) {
   895 		if ( in_array( 'post', $fields ) ) {
   764 			$_post = array_merge( $_post, $post_fields );
   896 			$_post = array_merge( $_post, $post_fields );
   765 		} else {
   897 		} else {
   766 			$requested_fields = array_intersect_key( $post_fields, array_flip( $fields ) );
   898 			$requested_fields = array_intersect_key( $post_fields, array_flip( $fields ) );
   767 			$_post = array_merge( $_post, $requested_fields );
   899 			$_post = array_merge( $_post, $requested_fields );
   791 				$_post['enclosure']['type'] = trim( $encdata[2] );
   923 				$_post['enclosure']['type'] = trim( $encdata[2] );
   792 			}
   924 			}
   793 		}
   925 		}
   794 
   926 
   795 		/**
   927 		/**
   796 		 * Filter XML-RPC-prepared date for the given post.
   928 		 * Filters XML-RPC-prepared date for the given post.
   797 		 *
   929 		 *
   798 		 * @since 3.4.0
   930 		 * @since 3.4.0
   799 		 *
   931 		 *
   800 		 * @param array $_post  An array of modified post data.
   932 		 * @param array $_post  An array of modified post data.
   801 		 * @param array $post   An array of post data.
   933 		 * @param array $post   An array of post data.
   805 	}
   937 	}
   806 
   938 
   807 	/**
   939 	/**
   808 	 * Prepares post data for return in an XML-RPC object.
   940 	 * Prepares post data for return in an XML-RPC object.
   809 	 *
   941 	 *
   810 	 * @access protected
   942 	 * @since 3.4.0
   811 	 *
   943 	 * @since 4.6.0 Converted the `$post_type` parameter to accept a WP_Post_Type object.
   812 	 * @param object $post_type Post type object
   944 	 *
   813 	 * @param array $fields The subset of post fields to return
   945 	 * @param WP_Post_Type $post_type Post type object.
   814 	 * @return array The prepared post type data
   946 	 * @param array        $fields    The subset of post fields to return.
       
   947 	 * @return array The prepared post type data.
   815 	 */
   948 	 */
   816 	protected function _prepare_post_type( $post_type, $fields ) {
   949 	protected function _prepare_post_type( $post_type, $fields ) {
   817 		$_post_type = array(
   950 		$_post_type = array(
   818 			'name' => $post_type->name,
   951 			'name' => $post_type->name,
   819 			'label' => $post_type->label,
   952 			'label' => $post_type->label,
   842 
   975 
   843 		if ( in_array( 'taxonomies', $fields ) )
   976 		if ( in_array( 'taxonomies', $fields ) )
   844 			$_post_type['taxonomies'] = get_object_taxonomies( $post_type->name, 'names' );
   977 			$_post_type['taxonomies'] = get_object_taxonomies( $post_type->name, 'names' );
   845 
   978 
   846 		/**
   979 		/**
   847 		 * Filter XML-RPC-prepared date for the given post type.
   980 		 * Filters XML-RPC-prepared date for the given post type.
   848 		 *
   981 		 *
   849 		 * @since 3.4.0
   982 		 * @since 3.4.0
   850 		 *
   983 		 * @since 4.6.0 Converted the `$post_type` parameter to accept a WP_Post_Type object.
   851 		 * @param array  $_post_type An array of post type data.
   984 		 *
   852 		 * @param object $post_type  Post type object.
   985 		 * @param array        $_post_type An array of post type data.
       
   986 		 * @param WP_Post_Type $post_type  Post type object.
   853 		 */
   987 		 */
   854 		return apply_filters( 'xmlrpc_prepare_post_type', $_post_type, $post_type );
   988 		return apply_filters( 'xmlrpc_prepare_post_type', $_post_type, $post_type );
   855 	}
   989 	}
   856 
   990 
   857 	/**
   991 	/**
   858 	 * Prepares media item data for return in an XML-RPC object.
   992 	 * Prepares media item data for return in an XML-RPC object.
   859 	 *
   993 	 *
   860 	 * @access protected
   994 	 *
   861 	 *
   995 	 * @param object $media_item     The unprepared media item data.
   862 	 * @param object $media_item The unprepared media item data
   996 	 * @param string $thumbnail_size The image size to use for the thumbnail URL.
   863 	 * @param string $thumbnail_size The image size to use for the thumbnail URL
   997 	 * @return array The prepared media item data.
   864 	 * @return array The prepared media item data
       
   865 	 */
   998 	 */
   866 	protected function _prepare_media_item( $media_item, $thumbnail_size = 'thumbnail' ) {
   999 	protected function _prepare_media_item( $media_item, $thumbnail_size = 'thumbnail' ) {
   867 		$_media_item = array(
  1000 		$_media_item = array(
   868 			'attachment_id'    => strval( $media_item->ID ),
  1001 			'attachment_id'    => strval( $media_item->ID ),
   869 			'date_created_gmt' => $this->_convert_date_gmt( $media_item->post_date_gmt, $media_item->post_date ),
  1002 			'date_created_gmt' => $this->_convert_date_gmt( $media_item->post_date_gmt, $media_item->post_date ),
   871 			'link'             => wp_get_attachment_url( $media_item->ID ),
  1004 			'link'             => wp_get_attachment_url( $media_item->ID ),
   872 			'title'            => $media_item->post_title,
  1005 			'title'            => $media_item->post_title,
   873 			'caption'          => $media_item->post_excerpt,
  1006 			'caption'          => $media_item->post_excerpt,
   874 			'description'      => $media_item->post_content,
  1007 			'description'      => $media_item->post_content,
   875 			'metadata'         => wp_get_attachment_metadata( $media_item->ID ),
  1008 			'metadata'         => wp_get_attachment_metadata( $media_item->ID ),
       
  1009 			'type'             => $media_item->post_mime_type
   876 		);
  1010 		);
   877 
  1011 
   878 		$thumbnail_src = image_downsize( $media_item->ID, $thumbnail_size );
  1012 		$thumbnail_src = image_downsize( $media_item->ID, $thumbnail_size );
   879 		if ( $thumbnail_src )
  1013 		if ( $thumbnail_src )
   880 			$_media_item['thumbnail'] = $thumbnail_src[0];
  1014 			$_media_item['thumbnail'] = $thumbnail_src[0];
   881 		else
  1015 		else
   882 			$_media_item['thumbnail'] = $_media_item['link'];
  1016 			$_media_item['thumbnail'] = $_media_item['link'];
   883 
  1017 
   884 		/**
  1018 		/**
   885 		 * Filter XML-RPC-prepared data for the given media item.
  1019 		 * Filters XML-RPC-prepared data for the given media item.
   886 		 *
  1020 		 *
   887 		 * @since 3.4.0
  1021 		 * @since 3.4.0
   888 		 *
  1022 		 *
   889 		 * @param array  $_media_item    An array of media item data.
  1023 		 * @param array  $_media_item    An array of media item data.
   890 		 * @param object $media_item     Media item object.
  1024 		 * @param object $media_item     Media item object.
   894 	}
  1028 	}
   895 
  1029 
   896 	/**
  1030 	/**
   897 	 * Prepares page data for return in an XML-RPC object.
  1031 	 * Prepares page data for return in an XML-RPC object.
   898 	 *
  1032 	 *
   899 	 * @access protected
  1033 	 *
   900 	 *
  1034 	 * @param object $page The unprepared page data.
   901 	 * @param object $page The unprepared page data
  1035 	 * @return array The prepared page data.
   902 	 * @return array The prepared page data
       
   903 	 */
  1036 	 */
   904 	protected function _prepare_page( $page ) {
  1037 	protected function _prepare_page( $page ) {
   905 		// Get all of the page content and link.
  1038 		// Get all of the page content and link.
   906 		$full_page = get_extended( $page->post_content );
  1039 		$full_page = get_extended( $page->post_content );
   907 		$link = post_permalink( $page->ID );
  1040 		$link = get_permalink( $page->ID );
   908 
  1041 
   909 		// Get info the page parent if there is one.
  1042 		// Get info the page parent if there is one.
   910 		$parent_title = "";
  1043 		$parent_title = "";
   911 		if ( ! empty( $page->post_parent ) ) {
  1044 		if ( ! empty( $page->post_parent ) ) {
   912 			$parent = get_post( $page->post_parent );
  1045 			$parent = get_post( $page->post_parent );
   962 			'custom_fields'          => $this->get_custom_fields( $page->ID ),
  1095 			'custom_fields'          => $this->get_custom_fields( $page->ID ),
   963 			'wp_page_template'       => $page_template
  1096 			'wp_page_template'       => $page_template
   964 		);
  1097 		);
   965 
  1098 
   966 		/**
  1099 		/**
   967 		 * Filter XML-RPC-prepared data for the given page.
  1100 		 * Filters XML-RPC-prepared data for the given page.
   968 		 *
  1101 		 *
   969 		 * @since 3.4.0
  1102 		 * @since 3.4.0
   970 		 *
  1103 		 *
   971 		 * @param array   $_page An array of page data.
  1104 		 * @param array   $_page An array of page data.
   972 		 * @param WP_Post $page  Page object.
  1105 		 * @param WP_Post $page  Page object.
   975 	}
  1108 	}
   976 
  1109 
   977 	/**
  1110 	/**
   978 	 * Prepares comment data for return in an XML-RPC object.
  1111 	 * Prepares comment data for return in an XML-RPC object.
   979 	 *
  1112 	 *
   980 	 * @access protected
  1113 	 *
   981 	 *
  1114 	 * @param object $comment The unprepared comment data.
   982 	 * @param object $comment The unprepared comment data
  1115 	 * @return array The prepared comment data.
   983 	 * @return array The prepared comment data
       
   984 	 */
  1116 	 */
   985 	protected function _prepare_comment( $comment ) {
  1117 	protected function _prepare_comment( $comment ) {
   986 		// Format page date.
  1118 		// Format page date.
   987 		$comment_date_gmt = $this->_convert_date_gmt( $comment->comment_date_gmt, $comment->comment_date );
  1119 		$comment_date_gmt = $this->_convert_date_gmt( $comment->comment_date_gmt, $comment->comment_date );
   988 
  1120 
  1011 			'author_ip'        => $comment->comment_author_IP,
  1143 			'author_ip'        => $comment->comment_author_IP,
  1012 			'type'             => $comment->comment_type,
  1144 			'type'             => $comment->comment_type,
  1013 		);
  1145 		);
  1014 
  1146 
  1015 		/**
  1147 		/**
  1016 		 * Filter XML-RPC-prepared data for the given comment.
  1148 		 * Filters XML-RPC-prepared data for the given comment.
  1017 		 *
  1149 		 *
  1018 		 * @since 3.4.0
  1150 		 * @since 3.4.0
  1019 		 *
  1151 		 *
  1020 		 * @param array  $_comment An array of prepared comment data.
  1152 		 * @param array      $_comment An array of prepared comment data.
  1021 		 * @param object $comment  Comment object.
  1153 		 * @param WP_Comment $comment  Comment object.
  1022 		 */
  1154 		 */
  1023 		return apply_filters( 'xmlrpc_prepare_comment', $_comment, $comment );
  1155 		return apply_filters( 'xmlrpc_prepare_comment', $_comment, $comment );
  1024 	}
  1156 	}
  1025 
  1157 
  1026 	/**
  1158 	/**
  1027 	 * Prepares user data for return in an XML-RPC object.
  1159 	 * Prepares user data for return in an XML-RPC object.
  1028 	 *
  1160 	 *
  1029 	 * @access protected
  1161 	 *
  1030 	 *
  1162 	 * @param WP_User $user   The unprepared user object.
  1031 	 * @param WP_User $user The unprepared user object
  1163 	 * @param array   $fields The subset of user fields to return.
  1032 	 * @param array $fields The subset of user fields to return
  1164 	 * @return array The prepared user data.
  1033 	 * @return array The prepared user data
       
  1034 	 */
  1165 	 */
  1035 	protected function _prepare_user( $user, $fields ) {
  1166 	protected function _prepare_user( $user, $fields ) {
  1036 		$_user = array( 'user_id' => strval( $user->ID ) );
  1167 		$_user = array( 'user_id' => strval( $user->ID ) );
  1037 
  1168 
  1038 		$user_fields = array(
  1169 		$user_fields = array(
  1059 			$requested_fields = array_intersect_key( $user_fields, array_flip( $fields ) );
  1190 			$requested_fields = array_intersect_key( $user_fields, array_flip( $fields ) );
  1060 			$_user = array_merge( $_user, $requested_fields );
  1191 			$_user = array_merge( $_user, $requested_fields );
  1061 		}
  1192 		}
  1062 
  1193 
  1063 		/**
  1194 		/**
  1064 		 * Filter XML-RPC-prepared data for the given user.
  1195 		 * Filters XML-RPC-prepared data for the given user.
  1065 		 *
  1196 		 *
  1066 		 * @since 3.5.0
  1197 		 * @since 3.5.0
  1067 		 *
  1198 		 *
  1068 		 * @param array   $_user  An array of user data.
  1199 		 * @param array   $_user  An array of user data.
  1069 		 * @param WP_User $user   User object.
  1200 		 * @param WP_User $user   User object.
  1075 	/**
  1206 	/**
  1076 	 * Create a new post for any registered post type.
  1207 	 * Create a new post for any registered post type.
  1077 	 *
  1208 	 *
  1078 	 * @since 3.4.0
  1209 	 * @since 3.4.0
  1079 	 *
  1210 	 *
  1080 	 * @param array $args Method parameters. Contains:
  1211 	 * @link https://en.wikipedia.org/wiki/RSS_enclosure for information on RSS enclosures.
  1081 	 *  - int     $blog_id (unused)
  1212 	 *
  1082 	 *  - string  $username
  1213 	 * @param array  $args {
  1083 	 *  - string  $password
  1214 	 *     Method arguments. Note: top-level arguments must be ordered as documented.
  1084 	 *  - array   $content_struct
  1215 	 *
  1085 	 *      $content_struct can contain:
  1216 	 *     @type int    $blog_id        Blog ID (unused).
  1086 	 *      - post_type (default: 'post')
  1217 	 *     @type string $username       Username.
  1087 	 *      - post_status (default: 'draft')
  1218 	 *     @type string $password       Password.
  1088 	 *      - post_title
  1219 	 *     @type array  $content_struct {
  1089 	 *      - post_author
  1220 	 *         Content struct for adding a new post. See wp_insert_post() for information on
  1090 	 *      - post_excerpt
  1221 	 *         additional post fields
  1091 	 *      - post_content
  1222 	 *
  1092 	 *      - post_date_gmt | post_date
  1223 	 *         @type string $post_type      Post type. Default 'post'.
  1093 	 *      - post_format
  1224 	 *         @type string $post_status    Post status. Default 'draft'
  1094 	 *      - post_password
  1225 	 *         @type string $post_title     Post title.
  1095 	 *      - comment_status - can be 'open' | 'closed'
  1226 	 *         @type int    $post_author    Post author ID.
  1096 	 *      - ping_status - can be 'open' | 'closed'
  1227 	 *         @type string $post_excerpt   Post excerpt.
  1097 	 *      - sticky
  1228 	 *         @type string $post_content   Post content.
  1098 	 *      - post_thumbnail - ID of a media item to use as the post thumbnail/featured image
  1229 	 *         @type string $post_date_gmt  Post date in GMT.
  1099 	 *      - custom_fields - array, with each element containing 'key' and 'value'
  1230 	 *         @type string $post_date      Post date.
  1100 	 *      - terms - array, with taxonomy names as keys and arrays of term IDs as values
  1231 	 *         @type string $post_password  Post password (20-character limit).
  1101 	 *      - terms_names - array, with taxonomy names as keys and arrays of term names as values
  1232 	 *         @type string $comment_status Post comment enabled status. Accepts 'open' or 'closed'.
  1102 	 *      - enclosure
  1233 	 *         @type string $ping_status    Post ping status. Accepts 'open' or 'closed'.
  1103 	 *      - any other fields supported by wp_insert_post()
  1234 	 *         @type bool   $sticky         Whether the post should be sticky. Automatically false if
  1104 	 * @return string|IXR_Error post_id
  1235 	 *                                      `$post_status` is 'private'.
       
  1236 	 *         @type int    $post_thumbnail ID of an image to use as the post thumbnail/featured image.
       
  1237 	 *         @type array  $custom_fields  Array of meta key/value pairs to add to the post.
       
  1238 	 *         @type array  $terms          Associative array with taxonomy names as keys and arrays
       
  1239 	 *                                      of term IDs as values.
       
  1240 	 *         @type array  $terms_names    Associative array with taxonomy names as keys and arrays
       
  1241 	 *                                      of term names as values.
       
  1242 	 *         @type array  $enclosure      {
       
  1243 	 *             Array of feed enclosure data to add to post meta.
       
  1244 	 *
       
  1245 	 *             @type string $url    URL for the feed enclosure.
       
  1246 	 *             @type int    $length Size in bytes of the enclosure.
       
  1247 	 *             @type string $type   Mime-type for the enclosure.
       
  1248 	 *         }
       
  1249 	 *     }
       
  1250 	 * }
       
  1251 	 * @return int|IXR_Error Post ID on success, IXR_Error instance otherwise.
  1105 	 */
  1252 	 */
  1106 	public function wp_newPost( $args ) {
  1253 	public function wp_newPost( $args ) {
  1107 		if ( ! $this->minimum_args( $args, 4 ) )
  1254 		if ( ! $this->minimum_args( $args, 4 ) )
  1108 			return $this->error;
  1255 			return $this->error;
  1109 
  1256 
  1149 	private function _is_greater_than_one( $count ) {
  1296 	private function _is_greater_than_one( $count ) {
  1150 		return $count > 1;
  1297 		return $count > 1;
  1151 	}
  1298 	}
  1152 
  1299 
  1153 	/**
  1300 	/**
  1154 	 * Helper method for wp_newPost and wp_editPost, containing shared logic.
  1301 	 * Encapsulate the logic for sticking a post
       
  1302 	 * and determining if the user has permission to do so
       
  1303 	 *
       
  1304 	 * @since 4.3.0
       
  1305 	 *
       
  1306 	 * @param array $post_data
       
  1307 	 * @param bool  $update
       
  1308 	 * @return void|IXR_Error
       
  1309 	 */
       
  1310 	private function _toggle_sticky( $post_data, $update = false ) {
       
  1311 		$post_type = get_post_type_object( $post_data['post_type'] );
       
  1312 
       
  1313 		// Private and password-protected posts cannot be stickied.
       
  1314 		if ( 'private' === $post_data['post_status'] || ! empty( $post_data['post_password'] ) ) {
       
  1315 			// Error if the client tried to stick the post, otherwise, silently unstick.
       
  1316 			if ( ! empty( $post_data['sticky'] ) ) {
       
  1317 				return new IXR_Error( 401, __( 'Sorry, you cannot stick a private post.' ) );
       
  1318 			}
       
  1319 
       
  1320 			if ( $update ) {
       
  1321 				unstick_post( $post_data['ID'] );
       
  1322 			}
       
  1323 		} elseif ( isset( $post_data['sticky'] ) )  {
       
  1324 			if ( ! current_user_can( $post_type->cap->edit_others_posts ) ) {
       
  1325 				return new IXR_Error( 401, __( 'Sorry, you are not allowed to make posts sticky.' ) );
       
  1326 			}
       
  1327 
       
  1328 			$sticky = wp_validate_boolean( $post_data['sticky'] );
       
  1329 			if ( $sticky ) {
       
  1330 				stick_post( $post_data['ID'] );
       
  1331 			} else {
       
  1332 				unstick_post( $post_data['ID'] );
       
  1333 			}
       
  1334 		}
       
  1335 	}
       
  1336 
       
  1337 	/**
       
  1338 	 * Helper method for wp_newPost() and wp_editPost(), containing shared logic.
  1155 	 *
  1339 	 *
  1156 	 * @since 3.4.0
  1340 	 * @since 3.4.0
  1157 	 * @uses wp_insert_post()
  1341 	 *
  1158 	 *
  1342 	 * @see wp_insert_post()
  1159 	 * @param WP_User $user The post author if post_author isn't set in $content_struct.
  1343 	 *
       
  1344 	 * @param WP_User         $user           The post author if post_author isn't set in $content_struct.
  1160 	 * @param array|IXR_Error $content_struct Post data to insert.
  1345 	 * @param array|IXR_Error $content_struct Post data to insert.
       
  1346 	 * @return IXR_Error|string
  1161 	 */
  1347 	 */
  1162 	protected function _insert_post( $user, $content_struct ) {
  1348 	protected function _insert_post( $user, $content_struct ) {
  1163 		$defaults = array( 'post_status' => 'draft', 'post_type' => 'post', 'post_author' => 0,
  1349 		$defaults = array(
  1164 			'post_password' => '', 'post_excerpt' => '', 'post_content' => '', 'post_title' => '' );
  1350 			'post_status'    => 'draft',
  1165 
  1351 			'post_type'      => 'post',
  1166 		$post_data = wp_parse_args( $content_struct, $defaults );
  1352 			'post_author'    => null,
       
  1353 			'post_password'  => null,
       
  1354 			'post_excerpt'   => null,
       
  1355 			'post_content'   => null,
       
  1356 			'post_title'     => null,
       
  1357 			'post_date'      => null,
       
  1358 			'post_date_gmt'  => null,
       
  1359 			'post_format'    => null,
       
  1360 			'post_name'      => null,
       
  1361 			'post_thumbnail' => null,
       
  1362 			'post_parent'    => null,
       
  1363 			'ping_status'    => null,
       
  1364 			'comment_status' => null,
       
  1365 			'custom_fields'  => null,
       
  1366 			'terms_names'    => null,
       
  1367 			'terms'          => null,
       
  1368 			'sticky'         => null,
       
  1369 			'enclosure'      => null,
       
  1370 			'ID'             => null,
       
  1371 		);
       
  1372 
       
  1373 		$post_data = wp_parse_args( array_intersect_key( $content_struct, $defaults ), $defaults );
  1167 
  1374 
  1168 		$post_type = get_post_type_object( $post_data['post_type'] );
  1375 		$post_type = get_post_type_object( $post_data['post_type'] );
  1169 		if ( ! $post_type )
  1376 		if ( ! $post_type )
  1170 			return new IXR_Error( 403, __( 'Invalid post type' ) );
  1377 			return new IXR_Error( 403, __( 'Invalid post type.' ) );
  1171 
  1378 
  1172 		$update = ! empty( $post_data['ID'] );
  1379 		$update = ! empty( $post_data['ID'] );
  1173 
  1380 
  1174 		if ( $update ) {
  1381 		if ( $update ) {
  1175 			if ( ! get_post( $post_data['ID'] ) )
  1382 			if ( ! get_post( $post_data['ID'] ) )
  1187 			case 'draft':
  1394 			case 'draft':
  1188 			case 'pending':
  1395 			case 'pending':
  1189 				break;
  1396 				break;
  1190 			case 'private':
  1397 			case 'private':
  1191 				if ( ! current_user_can( $post_type->cap->publish_posts ) )
  1398 				if ( ! current_user_can( $post_type->cap->publish_posts ) )
  1192 					return new IXR_Error( 401, __( 'Sorry, you are not allowed to create private posts in this post type' ) );
  1399 					return new IXR_Error( 401, __( 'Sorry, you are not allowed to create private posts in this post type.' ) );
  1193 				break;
  1400 				break;
  1194 			case 'publish':
  1401 			case 'publish':
  1195 			case 'future':
  1402 			case 'future':
  1196 				if ( ! current_user_can( $post_type->cap->publish_posts ) )
  1403 				if ( ! current_user_can( $post_type->cap->publish_posts ) )
  1197 					return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish posts in this post type' ) );
  1404 					return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish posts in this post type.' ) );
  1198 				break;
  1405 				break;
  1199 			default:
  1406 			default:
  1200 				if ( ! get_post_status_object( $post_data['post_status'] ) )
  1407 				if ( ! get_post_status_object( $post_data['post_status'] ) )
  1201 					$post_data['post_status'] = 'draft';
  1408 					$post_data['post_status'] = 'draft';
  1202 			break;
  1409 			break;
  1203 		}
  1410 		}
  1204 
  1411 
  1205 		if ( ! empty( $post_data['post_password'] ) && ! current_user_can( $post_type->cap->publish_posts ) )
  1412 		if ( ! empty( $post_data['post_password'] ) && ! current_user_can( $post_type->cap->publish_posts ) )
  1206 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to create password protected posts in this post type' ) );
  1413 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to create password protected posts in this post type.' ) );
  1207 
  1414 
  1208 		$post_data['post_author'] = absint( $post_data['post_author'] );
  1415 		$post_data['post_author'] = absint( $post_data['post_author'] );
  1209 		if ( ! empty( $post_data['post_author'] ) && $post_data['post_author'] != $user->ID ) {
  1416 		if ( ! empty( $post_data['post_author'] ) && $post_data['post_author'] != $user->ID ) {
  1210 			if ( ! current_user_can( $post_type->cap->edit_others_posts ) )
  1417 			if ( ! current_user_can( $post_type->cap->edit_others_posts ) )
  1211 				return new IXR_Error( 401, __( 'You are not allowed to create posts as this user.' ) );
  1418 				return new IXR_Error( 401, __( 'Sorry, you are not allowed to create posts as this user.' ) );
  1212 
  1419 
  1213 			$author = get_userdata( $post_data['post_author'] );
  1420 			$author = get_userdata( $post_data['post_author'] );
  1214 
  1421 
  1215 			if ( ! $author )
  1422 			if ( ! $author )
  1216 				return new IXR_Error( 404, __( 'Invalid author ID.' ) );
  1423 				return new IXR_Error( 404, __( 'Invalid author ID.' ) );
  1222 			unset( $post_data['comment_status'] );
  1429 			unset( $post_data['comment_status'] );
  1223 
  1430 
  1224 		if ( isset( $post_data['ping_status'] ) && $post_data['ping_status'] != 'open' && $post_data['ping_status'] != 'closed' )
  1431 		if ( isset( $post_data['ping_status'] ) && $post_data['ping_status'] != 'open' && $post_data['ping_status'] != 'closed' )
  1225 			unset( $post_data['ping_status'] );
  1432 			unset( $post_data['ping_status'] );
  1226 
  1433 
  1227 		// Do some timestamp voodoo
  1434 		// Do some timestamp voodoo.
  1228 		if ( ! empty( $post_data['post_date_gmt'] ) ) {
  1435 		if ( ! empty( $post_data['post_date_gmt'] ) ) {
  1229 			// We know this is supposed to be GMT, so we're going to slap that Z on there by force
  1436 			// We know this is supposed to be GMT, so we're going to slap that Z on there by force.
  1230 			$dateCreated = rtrim( $post_data['post_date_gmt']->getIso(), 'Z' ) . 'Z';
  1437 			$dateCreated = rtrim( $post_data['post_date_gmt']->getIso(), 'Z' ) . 'Z';
  1231 		} elseif ( ! empty( $post_data['post_date'] ) ) {
  1438 		} elseif ( ! empty( $post_data['post_date'] ) ) {
  1232 			$dateCreated = $post_data['post_date']->getIso();
  1439 			$dateCreated = $post_data['post_date']->getIso();
  1233 		}
  1440 		}
  1234 
  1441 
       
  1442 		// Default to not flagging the post date to be edited unless it's intentional.
       
  1443 		$post_data['edit_date'] = false;
       
  1444 
  1235 		if ( ! empty( $dateCreated ) ) {
  1445 		if ( ! empty( $dateCreated ) ) {
  1236 			$post_data['post_date'] = get_date_from_gmt( iso8601_to_datetime( $dateCreated ) );
  1446 			$post_data['post_date'] = get_date_from_gmt( iso8601_to_datetime( $dateCreated ) );
  1237 			$post_data['post_date_gmt'] = iso8601_to_datetime( $dateCreated, 'GMT' );
  1447 			$post_data['post_date_gmt'] = iso8601_to_datetime( $dateCreated, 'GMT' );
       
  1448 
       
  1449 			// Flag the post date to be edited.
       
  1450 			$post_data['edit_date'] = true;
  1238 		}
  1451 		}
  1239 
  1452 
  1240 		if ( ! isset( $post_data['ID'] ) )
  1453 		if ( ! isset( $post_data['ID'] ) )
  1241 			$post_data['ID'] = get_default_post_to_edit( $post_data['post_type'], true )->ID;
  1454 			$post_data['ID'] = get_default_post_to_edit( $post_data['post_type'], true )->ID;
  1242 		$post_ID = $post_data['ID'];
  1455 		$post_ID = $post_data['ID'];
  1243 
  1456 
  1244 		if ( $post_data['post_type'] == 'post' ) {
  1457 		if ( $post_data['post_type'] == 'post' ) {
  1245 			// Private and password-protected posts cannot be stickied.
  1458 			$error = $this->_toggle_sticky( $post_data, $update );
  1246 			if ( $post_data['post_status'] == 'private' || ! empty( $post_data['post_password'] ) ) {
  1459 			if ( $error ) {
  1247 				// Error if the client tried to stick the post, otherwise, silently unstick.
  1460 				return $error;
  1248 				if ( ! empty( $post_data['sticky'] ) )
       
  1249 					return new IXR_Error( 401, __( 'Sorry, you cannot stick a private post.' ) );
       
  1250 				if ( $update )
       
  1251 					unstick_post( $post_ID );
       
  1252 			} elseif ( isset( $post_data['sticky'] ) )  {
       
  1253 				if ( ! current_user_can( $post_type->cap->edit_others_posts ) )
       
  1254 					return new IXR_Error( 401, __( 'Sorry, you are not allowed to stick this post.' ) );
       
  1255 				if ( $post_data['sticky'] )
       
  1256 					stick_post( $post_ID );
       
  1257 				else
       
  1258 					unstick_post( $post_ID );
       
  1259 			}
  1461 			}
  1260 		}
  1462 		}
  1261 
  1463 
  1262 		if ( isset( $post_data['post_thumbnail'] ) ) {
  1464 		if ( isset( $post_data['post_thumbnail'] ) ) {
  1263 			// empty value deletes, non-empty value adds/updates
  1465 			// empty value deletes, non-empty value adds/updates.
  1264 			if ( ! $post_data['post_thumbnail'] )
  1466 			if ( ! $post_data['post_thumbnail'] )
  1265 				delete_post_thumbnail( $post_ID );
  1467 				delete_post_thumbnail( $post_ID );
  1266 			elseif ( ! get_post( absint( $post_data['post_thumbnail'] ) ) )
  1468 			elseif ( ! get_post( absint( $post_data['post_thumbnail'] ) ) )
  1267 				return new IXR_Error( 404, __( 'Invalid attachment ID.' ) );
  1469 				return new IXR_Error( 404, __( 'Invalid attachment ID.' ) );
  1268 			set_post_thumbnail( $post_ID, $post_data['post_thumbnail'] );
  1470 			set_post_thumbnail( $post_ID, $post_data['post_thumbnail'] );
  1273 			$this->set_custom_fields( $post_ID, $post_data['custom_fields'] );
  1475 			$this->set_custom_fields( $post_ID, $post_data['custom_fields'] );
  1274 
  1476 
  1275 		if ( isset( $post_data['terms'] ) || isset( $post_data['terms_names'] ) ) {
  1477 		if ( isset( $post_data['terms'] ) || isset( $post_data['terms_names'] ) ) {
  1276 			$post_type_taxonomies = get_object_taxonomies( $post_data['post_type'], 'objects' );
  1478 			$post_type_taxonomies = get_object_taxonomies( $post_data['post_type'], 'objects' );
  1277 
  1479 
  1278 			// accumulate term IDs from terms and terms_names
  1480 			// Accumulate term IDs from terms and terms_names.
  1279 			$terms = array();
  1481 			$terms = array();
  1280 
  1482 
  1281 			// first validate the terms specified by ID
  1483 			// First validate the terms specified by ID.
  1282 			if ( isset( $post_data['terms'] ) && is_array( $post_data['terms'] ) ) {
  1484 			if ( isset( $post_data['terms'] ) && is_array( $post_data['terms'] ) ) {
  1283 				$taxonomies = array_keys( $post_data['terms'] );
  1485 				$taxonomies = array_keys( $post_data['terms'] );
  1284 
  1486 
  1285 				// validating term ids
  1487 				// Validating term ids.
  1286 				foreach ( $taxonomies as $taxonomy ) {
  1488 				foreach ( $taxonomies as $taxonomy ) {
  1287 					if ( ! array_key_exists( $taxonomy , $post_type_taxonomies ) )
  1489 					if ( ! array_key_exists( $taxonomy , $post_type_taxonomies ) )
  1288 						return new IXR_Error( 401, __( 'Sorry, one of the given taxonomies is not supported by the post type.' ) );
  1490 						return new IXR_Error( 401, __( 'Sorry, one of the given taxonomies is not supported by the post type.' ) );
  1289 
  1491 
  1290 					if ( ! current_user_can( $post_type_taxonomies[$taxonomy]->cap->assign_terms ) )
  1492 					if ( ! current_user_can( $post_type_taxonomies[$taxonomy]->cap->assign_terms ) )
  1294 					$terms[ $taxonomy ] = array();
  1496 					$terms[ $taxonomy ] = array();
  1295 					foreach ( $term_ids as $term_id ) {
  1497 					foreach ( $term_ids as $term_id ) {
  1296 						$term = get_term_by( 'id', $term_id, $taxonomy );
  1498 						$term = get_term_by( 'id', $term_id, $taxonomy );
  1297 
  1499 
  1298 						if ( ! $term )
  1500 						if ( ! $term )
  1299 							return new IXR_Error( 403, __( 'Invalid term ID' ) );
  1501 							return new IXR_Error( 403, __( 'Invalid term ID.' ) );
  1300 
  1502 
  1301 						$terms[$taxonomy][] = (int) $term_id;
  1503 						$terms[$taxonomy][] = (int) $term_id;
  1302 					}
  1504 					}
  1303 				}
  1505 				}
  1304 			}
  1506 			}
  1305 
  1507 
  1306 			// now validate terms specified by name
  1508 			// Now validate terms specified by name.
  1307 			if ( isset( $post_data['terms_names'] ) && is_array( $post_data['terms_names'] ) ) {
  1509 			if ( isset( $post_data['terms_names'] ) && is_array( $post_data['terms_names'] ) ) {
  1308 				$taxonomies = array_keys( $post_data['terms_names'] );
  1510 				$taxonomies = array_keys( $post_data['terms_names'] );
  1309 
  1511 
  1310 				foreach ( $taxonomies as $taxonomy ) {
  1512 				foreach ( $taxonomies as $taxonomy ) {
  1311 					if ( ! array_key_exists( $taxonomy , $post_type_taxonomies ) )
  1513 					if ( ! array_key_exists( $taxonomy , $post_type_taxonomies ) )
  1312 						return new IXR_Error( 401, __( 'Sorry, one of the given taxonomies is not supported by the post type.' ) );
  1514 						return new IXR_Error( 401, __( 'Sorry, one of the given taxonomies is not supported by the post type.' ) );
  1313 
  1515 
  1314 					if ( ! current_user_can( $post_type_taxonomies[$taxonomy]->cap->assign_terms ) )
  1516 					if ( ! current_user_can( $post_type_taxonomies[$taxonomy]->cap->assign_terms ) )
  1315 						return new IXR_Error( 401, __( 'Sorry, you are not allowed to assign a term to one of the given taxonomies.' ) );
  1517 						return new IXR_Error( 401, __( 'Sorry, you are not allowed to assign a term to one of the given taxonomies.' ) );
  1316 
  1518 
  1317 					// for hierarchical taxonomies, we can't assign a term when multiple terms in the hierarchy share the same name
  1519 					/*
       
  1520 					 * For hierarchical taxonomies, we can't assign a term when multiple terms
       
  1521 					 * in the hierarchy share the same name.
       
  1522 					 */
  1318 					$ambiguous_terms = array();
  1523 					$ambiguous_terms = array();
  1319 					if ( is_taxonomy_hierarchical( $taxonomy ) ) {
  1524 					if ( is_taxonomy_hierarchical( $taxonomy ) ) {
  1320 						$tax_term_names = get_terms( $taxonomy, array( 'fields' => 'names', 'hide_empty' => false ) );
  1525 						$tax_term_names = get_terms( $taxonomy, array( 'fields' => 'names', 'hide_empty' => false ) );
  1321 
  1526 
  1322 						// count the number of terms with the same name
  1527 						// Count the number of terms with the same name.
  1323 						$tax_term_names_count = array_count_values( $tax_term_names );
  1528 						$tax_term_names_count = array_count_values( $tax_term_names );
  1324 
  1529 
  1325 						// filter out non-ambiguous term names
  1530 						// Filter out non-ambiguous term names.
  1326 						$ambiguous_tax_term_counts = array_filter( $tax_term_names_count, array( $this, '_is_greater_than_one') );
  1531 						$ambiguous_tax_term_counts = array_filter( $tax_term_names_count, array( $this, '_is_greater_than_one') );
  1327 
  1532 
  1328 						$ambiguous_terms = array_keys( $ambiguous_tax_term_counts );
  1533 						$ambiguous_terms = array_keys( $ambiguous_tax_term_counts );
  1329 					}
  1534 					}
  1330 
  1535 
  1334 							return new IXR_Error( 401, __( 'Ambiguous term name used in a hierarchical taxonomy. Please use term ID instead.' ) );
  1539 							return new IXR_Error( 401, __( 'Ambiguous term name used in a hierarchical taxonomy. Please use term ID instead.' ) );
  1335 
  1540 
  1336 						$term = get_term_by( 'name', $term_name, $taxonomy );
  1541 						$term = get_term_by( 'name', $term_name, $taxonomy );
  1337 
  1542 
  1338 						if ( ! $term ) {
  1543 						if ( ! $term ) {
  1339 							// term doesn't exist, so check that the user is allowed to create new terms
  1544 							// Term doesn't exist, so check that the user is allowed to create new terms.
  1340 							if ( ! current_user_can( $post_type_taxonomies[$taxonomy]->cap->edit_terms ) )
  1545 							if ( ! current_user_can( $post_type_taxonomies[$taxonomy]->cap->edit_terms ) )
  1341 								return new IXR_Error( 401, __( 'Sorry, you are not allowed to add a term to one of the given taxonomies.' ) );
  1546 								return new IXR_Error( 401, __( 'Sorry, you are not allowed to add a term to one of the given taxonomies.' ) );
  1342 
  1547 
  1343 							// create the new term
  1548 							// Create the new term.
  1344 							$term_info = wp_insert_term( $term_name, $taxonomy );
  1549 							$term_info = wp_insert_term( $term_name, $taxonomy );
  1345 							if ( is_wp_error( $term_info ) )
  1550 							if ( is_wp_error( $term_info ) )
  1346 								return new IXR_Error( 500, $term_info->get_error_message() );
  1551 								return new IXR_Error( 500, $term_info->get_error_message() );
  1347 
  1552 
  1348 							$terms[$taxonomy][] = (int) $term_info['term_id'];
  1553 							$terms[$taxonomy][] = (int) $term_info['term_id'];
  1353 				}
  1558 				}
  1354 			}
  1559 			}
  1355 
  1560 
  1356 			$post_data['tax_input'] = $terms;
  1561 			$post_data['tax_input'] = $terms;
  1357 			unset( $post_data['terms'], $post_data['terms_names'] );
  1562 			unset( $post_data['terms'], $post_data['terms_names'] );
  1358 		} else {
       
  1359 			// do not allow direct submission of 'tax_input', clients must use 'terms' and/or 'terms_names'
       
  1360 			unset( $post_data['tax_input'], $post_data['post_category'], $post_data['tags_input'] );
       
  1361 		}
  1563 		}
  1362 
  1564 
  1363 		if ( isset( $post_data['post_format'] ) ) {
  1565 		if ( isset( $post_data['post_format'] ) ) {
  1364 			$format = set_post_format( $post_ID, $post_data['post_format'] );
  1566 			$format = set_post_format( $post_ID, $post_data['post_format'] );
  1365 
  1567 
  1367 				return new IXR_Error( 500, $format->get_error_message() );
  1569 				return new IXR_Error( 500, $format->get_error_message() );
  1368 
  1570 
  1369 			unset( $post_data['post_format'] );
  1571 			unset( $post_data['post_format'] );
  1370 		}
  1572 		}
  1371 
  1573 
  1372 		// Handle enclosures
  1574 		// Handle enclosures.
  1373 		$enclosure = isset( $post_data['enclosure'] ) ? $post_data['enclosure'] : null;
  1575 		$enclosure = isset( $post_data['enclosure'] ) ? $post_data['enclosure'] : null;
  1374 		$this->add_enclosure_if_new( $post_ID, $enclosure );
  1576 		$this->add_enclosure_if_new( $post_ID, $enclosure );
  1375 
  1577 
  1376 		$this->attach_uploads( $post_ID, $post_data['post_content'] );
  1578 		$this->attach_uploads( $post_ID, $post_data['post_content'] );
  1377 
  1579 
  1378 		/**
  1580 		/**
  1379 		 * Filter post data array to be inserted via XML-RPC.
  1581 		 * Filters post data array to be inserted via XML-RPC.
  1380 		 *
  1582 		 *
  1381 		 * @since 3.4.0
  1583 		 * @since 3.4.0
  1382 		 *
  1584 		 *
  1383 		 * @param array $post_data      Parsed array of post data.
  1585 		 * @param array $post_data      Parsed array of post data.
  1384 		 * @param array $content_struct Post data array.
  1586 		 * @param array $content_struct Post data array.
  1388 		$post_ID = $update ? wp_update_post( $post_data, true ) : wp_insert_post( $post_data, true );
  1590 		$post_ID = $update ? wp_update_post( $post_data, true ) : wp_insert_post( $post_data, true );
  1389 		if ( is_wp_error( $post_ID ) )
  1591 		if ( is_wp_error( $post_ID ) )
  1390 			return new IXR_Error( 500, $post_ID->get_error_message() );
  1592 			return new IXR_Error( 500, $post_ID->get_error_message() );
  1391 
  1593 
  1392 		if ( ! $post_ID )
  1594 		if ( ! $post_ID )
  1393 			return new IXR_Error( 401, __( 'Sorry, your entry could not be posted. Something wrong happened.' ) );
  1595 			return new IXR_Error( 401, __( 'Sorry, your entry could not be posted.' ) );
  1394 
  1596 
  1395 		return strval( $post_ID );
  1597 		return strval( $post_ID );
  1396 	}
  1598 	}
  1397 
  1599 
  1398 	/**
  1600 	/**
  1401 	 * The $content_struct parameter only needs to contain fields that
  1603 	 * The $content_struct parameter only needs to contain fields that
  1402 	 * should be changed. All other fields will retain their existing values.
  1604 	 * should be changed. All other fields will retain their existing values.
  1403 	 *
  1605 	 *
  1404 	 * @since 3.4.0
  1606 	 * @since 3.4.0
  1405 	 *
  1607 	 *
  1406 	 * @param array $args Method parameters. Contains:
  1608 	 * @param array  $args {
  1407 	 *  - int     $blog_id (unused)
  1609 	 *     Method arguments. Note: arguments must be ordered as documented.
  1408 	 *  - string  $username
  1610 	 *
  1409 	 *  - string  $password
  1611 	 *     @type int    $blog_id        Blog ID (unused).
  1410 	 *  - int     $post_id
  1612 	 *     @type string $username       Username.
  1411 	 *  - array   $content_struct
  1613 	 *     @type string $password       Password.
  1412 	 * @return bool|IXR_Error true on success
  1614 	 *     @type int    $post_id        Post ID.
       
  1615 	 *     @type array  $content_struct Extra content arguments.
       
  1616 	 * }
       
  1617 	 * @return true|IXR_Error True on success, IXR_Error on failure.
  1413 	 */
  1618 	 */
  1414 	public function wp_editPost( $args ) {
  1619 	public function wp_editPost( $args ) {
  1415 		if ( ! $this->minimum_args( $args, 5 ) )
  1620 		if ( ! $this->minimum_args( $args, 5 ) )
  1416 			return $this->error;
  1621 			return $this->error;
  1417 
  1622 
  1438 			if ( mysql2date( 'U', $post['post_modified_gmt'] ) > $content_struct['if_not_modified_since']->getTimestamp() ) {
  1643 			if ( mysql2date( 'U', $post['post_modified_gmt'] ) > $content_struct['if_not_modified_since']->getTimestamp() ) {
  1439 				return new IXR_Error( 409, __( 'There is a revision of this post that is more recent.' ) );
  1644 				return new IXR_Error( 409, __( 'There is a revision of this post that is more recent.' ) );
  1440 			}
  1645 			}
  1441 		}
  1646 		}
  1442 
  1647 
  1443 		// convert the date field back to IXR form
  1648 		// Convert the date field back to IXR form.
  1444 		$post['post_date'] = $this->_convert_date( $post['post_date'] );
  1649 		$post['post_date'] = $this->_convert_date( $post['post_date'] );
  1445 
  1650 
  1446 		// ignore the existing GMT date if it is empty or a non-GMT date was supplied in $content_struct,
  1651 		/*
  1447 		// since _insert_post will ignore the non-GMT date if the GMT date is set
  1652 		 * Ignore the existing GMT date if it is empty or a non-GMT date was supplied in $content_struct,
       
  1653 		 * since _insert_post() will ignore the non-GMT date if the GMT date is set.
       
  1654 		 */
  1448 		if ( $post['post_date_gmt'] == '0000-00-00 00:00:00' || isset( $content_struct['post_date'] ) )
  1655 		if ( $post['post_date_gmt'] == '0000-00-00 00:00:00' || isset( $content_struct['post_date'] ) )
  1449 			unset( $post['post_date_gmt'] );
  1656 			unset( $post['post_date_gmt'] );
  1450 		else
  1657 		else
  1451 			$post['post_date_gmt'] = $this->_convert_date( $post['post_date_gmt'] );
  1658 			$post['post_date_gmt'] = $this->_convert_date( $post['post_date_gmt'] );
  1452 
  1659 
  1463 	/**
  1670 	/**
  1464 	 * Delete a post for any registered post type.
  1671 	 * Delete a post for any registered post type.
  1465 	 *
  1672 	 *
  1466 	 * @since 3.4.0
  1673 	 * @since 3.4.0
  1467 	 *
  1674 	 *
  1468 	 * @uses wp_delete_post()
  1675 	 * @see wp_delete_post()
  1469 	 * @param array $args Method parameters. Contains:
  1676 	 *
  1470 	 *  - int     $blog_id (unused)
  1677 	 * @param array  $args {
  1471 	 *  - string  $username
  1678 	 *     Method arguments. Note: arguments must be ordered as documented.
  1472 	 *  - string  $password
  1679 	 *
  1473 	 *  - int     $post_id
  1680 	 *     @type int    $blog_id  Blog ID (unused).
  1474 	 * @return bool|IXR_Error true on success
  1681 	 *     @type string $username Username.
       
  1682 	 *     @type string $password Password.
       
  1683 	 *     @type int    $post_id  Post ID.
       
  1684 	 * }
       
  1685 	 * @return true|IXR_Error True on success, IXR_Error instance on failure.
  1475 	 */
  1686 	 */
  1476 	public function wp_deletePost( $args ) {
  1687 	public function wp_deletePost( $args ) {
  1477 		if ( ! $this->minimum_args( $args, 4 ) )
  1688 		if ( ! $this->minimum_args( $args, 4 ) )
  1478 			return $this->error;
  1689 			return $this->error;
  1479 
  1690 
  1488 
  1699 
  1489 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  1700 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  1490 		do_action( 'xmlrpc_call', 'wp.deletePost' );
  1701 		do_action( 'xmlrpc_call', 'wp.deletePost' );
  1491 
  1702 
  1492 		$post = get_post( $post_id, ARRAY_A );
  1703 		$post = get_post( $post_id, ARRAY_A );
  1493 		if ( empty( $post['ID'] ) )
  1704 		if ( empty( $post['ID'] ) ) {
  1494 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  1705 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  1495 
  1706 		}
  1496 		if ( ! current_user_can( 'delete_post', $post_id ) )
  1707 
       
  1708 		if ( ! current_user_can( 'delete_post', $post_id ) ) {
  1497 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to delete this post.' ) );
  1709 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to delete this post.' ) );
       
  1710 		}
  1498 
  1711 
  1499 		$result = wp_delete_post( $post_id );
  1712 		$result = wp_delete_post( $post_id );
  1500 
  1713 
  1501 		if ( ! $result )
  1714 		if ( ! $result ) {
  1502 			return new IXR_Error( 500, __( 'The post cannot be deleted.' ) );
  1715 			return new IXR_Error( 500, __( 'The post cannot be deleted.' ) );
       
  1716 		}
  1503 
  1717 
  1504 		return true;
  1718 		return true;
  1505 	}
  1719 	}
  1506 
  1720 
  1507 	/**
  1721 	/**
  1516 	 * Instead of, or in addition to, individual field names, conceptual group
  1730 	 * Instead of, or in addition to, individual field names, conceptual group
  1517 	 * names can be used to specify multiple fields. The available conceptual
  1731 	 * names can be used to specify multiple fields. The available conceptual
  1518 	 * groups are 'post' (all basic fields), 'taxonomies', 'custom_fields',
  1732 	 * groups are 'post' (all basic fields), 'taxonomies', 'custom_fields',
  1519 	 * and 'enclosure'.
  1733 	 * and 'enclosure'.
  1520 	 *
  1734 	 *
  1521 	 * @uses get_post()
  1735 	 * @see get_post()
  1522 	 * @param array $args Method parameters. Contains:
  1736 	 *
  1523 	 *  - int     $blog_id (unused)
  1737 	 * @param array $args {
  1524 	 *  - string  $username
  1738 	 *     Method arguments. Note: arguments must be ordered as documented.
  1525 	 *  - string  $password
  1739 	 *
  1526 	 *  - int     $post_id
  1740 	 *     @type int    $blog_id  Blog ID (unused).
  1527 	 *  - array   $fields optional
  1741 	 *     @type string $username Username.
       
  1742 	 *     @type string $password Password.
       
  1743 	 *     @type int    $post_id  Post ID.
       
  1744 	 *     @type array  $fields   The subset of post type fields to return.
       
  1745 	 * }
  1528 	 * @return array|IXR_Error Array contains (based on $fields parameter):
  1746 	 * @return array|IXR_Error Array contains (based on $fields parameter):
  1529 	 *  - 'post_id'
  1747 	 *  - 'post_id'
  1530 	 *  - 'post_title'
  1748 	 *  - 'post_title'
  1531 	 *  - 'post_date'
  1749 	 *  - 'post_date'
  1532 	 *  - 'post_date_gmt'
  1750 	 *  - 'post_date_gmt'
  1553 		if ( ! $this->minimum_args( $args, 4 ) )
  1771 		if ( ! $this->minimum_args( $args, 4 ) )
  1554 			return $this->error;
  1772 			return $this->error;
  1555 
  1773 
  1556 		$this->escape( $args );
  1774 		$this->escape( $args );
  1557 
  1775 
  1558 		$username           = $args[1];
  1776 		$username = $args[1];
  1559 		$password           = $args[2];
  1777 		$password = $args[2];
  1560 		$post_id            = (int) $args[3];
  1778 		$post_id  = (int) $args[3];
  1561 
  1779 
  1562 		if ( isset( $args[4] ) ) {
  1780 		if ( isset( $args[4] ) ) {
  1563 			$fields = $args[4];
  1781 			$fields = $args[4];
  1564 		} else {
  1782 		} else {
  1565 			/**
  1783 			/**
  1566 			 * Filter the list of post query fields used by the given XML-RPC method.
  1784 			 * Filters the list of post query fields used by the given XML-RPC method.
  1567 			 *
  1785 			 *
  1568 			 * @since 3.4.0
  1786 			 * @since 3.4.0
  1569 			 *
  1787 			 *
  1570 			 * @param array $fields  Array of post fields.
  1788 			 * @param array  $fields Array of post fields. Default array contains 'post', 'terms', and 'custom_fields'.
  1571 			 * @param string $method Method name.
  1789 			 * @param string $method Method name.
  1572 			 */
  1790 			 */
  1573 			$fields = apply_filters( 'xmlrpc_default_post_fields', array( 'post', 'terms', 'custom_fields' ), 'wp.getPost' );
  1791 			$fields = apply_filters( 'xmlrpc_default_post_fields', array( 'post', 'terms', 'custom_fields' ), 'wp.getPost' );
  1574 		}
  1792 		}
  1575 
  1793 
  1583 
  1801 
  1584 		if ( empty( $post['ID'] ) )
  1802 		if ( empty( $post['ID'] ) )
  1585 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  1803 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  1586 
  1804 
  1587 		if ( ! current_user_can( 'edit_post', $post_id ) )
  1805 		if ( ! current_user_can( 'edit_post', $post_id ) )
  1588 			return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) );
  1806 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  1589 
  1807 
  1590 		return $this->_prepare_post( $post, $fields );
  1808 		return $this->_prepare_post( $post, $fields );
  1591 	}
  1809 	}
  1592 
  1810 
  1593 	/**
  1811 	/**
  1594 	 * Retrieve posts.
  1812 	 * Retrieve posts.
  1595 	 *
  1813 	 *
  1596 	 * @since 3.4.0
  1814 	 * @since 3.4.0
  1597 	 *
  1815 	 *
  1598 	 * The optional $filter parameter modifies the query used to retrieve posts.
  1816 	 * @see wp_get_recent_posts()
  1599 	 * Accepted keys are 'post_type', 'post_status', 'number', 'offset',
  1817 	 * @see wp_getPost() for more on `$fields`
  1600 	 * 'orderby', and 'order'.
  1818 	 * @see get_posts() for more on `$filter` values
  1601 	 *
  1819 	 *
  1602 	 * The optional $fields parameter specifies what fields will be included
  1820 	 * @param array $args {
  1603 	 * in the response array.
  1821 	 *     Method arguments. Note: arguments must be ordered as documented.
  1604 	 *
  1822 	 *
  1605 	 * @uses wp_get_recent_posts()
  1823 	 *     @type int    $blog_id  Blog ID (unused).
  1606 	 * @see wp_getPost() for more on $fields
  1824 	 *     @type string $username Username.
  1607 	 * @see get_posts() for more on $filter values
  1825 	 *     @type string $password Password.
  1608 	 *
  1826 	 *     @type array  $filter   Optional. Modifies the query used to retrieve posts. Accepts 'post_type',
  1609 	 * @param array $args Method parameters. Contains:
  1827 	 *                            'post_status', 'number', 'offset', 'orderby', 's', and 'order'.
  1610 	 *  - int     $blog_id (unused)
  1828 	 *                            Default empty array.
  1611 	 *  - string  $username
  1829 	 *     @type array  $fields   Optional. The subset of post type fields to return in the response array.
  1612 	 *  - string  $password
  1830 	 * }
  1613 	 *  - array   $filter optional
       
  1614 	 *  - array   $fields optional
       
  1615 	 * @return array|IXR_Error Array contains a collection of posts.
  1831 	 * @return array|IXR_Error Array contains a collection of posts.
  1616 	 */
  1832 	 */
  1617 	public function wp_getPosts( $args ) {
  1833 	public function wp_getPosts( $args ) {
  1618 		if ( ! $this->minimum_args( $args, 3 ) )
  1834 		if ( ! $this->minimum_args( $args, 3 ) )
  1619 			return $this->error;
  1835 			return $this->error;
  1620 
  1836 
  1621 		$this->escape( $args );
  1837 		$this->escape( $args );
  1622 
  1838 
  1623 		$username   = $args[1];
  1839 		$username = $args[1];
  1624 		$password   = $args[2];
  1840 		$password = $args[2];
  1625 		$filter     = isset( $args[3] ) ? $args[3] : array();
  1841 		$filter   = isset( $args[3] ) ? $args[3] : array();
  1626 
  1842 
  1627 		if ( isset( $args[4] ) ) {
  1843 		if ( isset( $args[4] ) ) {
  1628 			$fields = $args[4];
  1844 			$fields = $args[4];
  1629 		} else {
  1845 		} else {
  1630 			/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  1846 			/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  1640 		$query = array();
  1856 		$query = array();
  1641 
  1857 
  1642 		if ( isset( $filter['post_type'] ) ) {
  1858 		if ( isset( $filter['post_type'] ) ) {
  1643 			$post_type = get_post_type_object( $filter['post_type'] );
  1859 			$post_type = get_post_type_object( $filter['post_type'] );
  1644 			if ( ! ( (bool) $post_type ) )
  1860 			if ( ! ( (bool) $post_type ) )
  1645 				return new IXR_Error( 403, __( 'The post type specified is not valid' ) );
  1861 				return new IXR_Error( 403, __( 'Invalid post type.' ) );
  1646 		} else {
  1862 		} else {
  1647 			$post_type = get_post_type_object( 'post' );
  1863 			$post_type = get_post_type_object( 'post' );
  1648 		}
  1864 		}
  1649 
  1865 
  1650 		if ( ! current_user_can( $post_type->cap->edit_posts ) )
  1866 		if ( ! current_user_can( $post_type->cap->edit_posts ) )
  1651 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit posts in this post type' ));
  1867 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit posts in this post type.' ) );
  1652 
  1868 
  1653 		$query['post_type'] = $post_type->name;
  1869 		$query['post_type'] = $post_type->name;
  1654 
  1870 
  1655 		if ( isset( $filter['post_status'] ) )
  1871 		if ( isset( $filter['post_status'] ) )
  1656 			$query['post_status'] = $filter['post_status'];
  1872 			$query['post_status'] = $filter['post_status'];
  1675 		$posts_list = wp_get_recent_posts( $query );
  1891 		$posts_list = wp_get_recent_posts( $query );
  1676 
  1892 
  1677 		if ( ! $posts_list )
  1893 		if ( ! $posts_list )
  1678 			return array();
  1894 			return array();
  1679 
  1895 
  1680 		// holds all the posts data
  1896 		// Holds all the posts data.
  1681 		$struct = array();
  1897 		$struct = array();
  1682 
  1898 
  1683 		foreach ( $posts_list as $post ) {
  1899 		foreach ( $posts_list as $post ) {
  1684 			if ( ! current_user_can( 'edit_post', $post['ID'] ) )
  1900 			if ( ! current_user_can( 'edit_post', $post['ID'] ) )
  1685 				continue;
  1901 				continue;
  1693 	/**
  1909 	/**
  1694 	 * Create a new term.
  1910 	 * Create a new term.
  1695 	 *
  1911 	 *
  1696 	 * @since 3.4.0
  1912 	 * @since 3.4.0
  1697 	 *
  1913 	 *
  1698 	 * @uses wp_insert_term()
  1914 	 * @see wp_insert_term()
  1699 	 * @param array $args Method parameters. Contains:
  1915 	 *
  1700 	 *  - int     $blog_id (unused)
  1916 	 * @param array $args {
  1701 	 *  - string  $username
  1917 	 *     Method arguments. Note: arguments must be ordered as documented.
  1702 	 *  - string  $password
  1918 	 *
  1703 	 *  - array   $content_struct
  1919 	 *     @type int    $blog_id        Blog ID (unused).
  1704 	 *      The $content_struct must contain:
  1920 	 *     @type string $username       Username.
  1705 	 *      - 'name'
  1921 	 *     @type string $password       Password.
  1706 	 *      - 'taxonomy'
  1922 	 *     @type array  $content_struct Content struct for adding a new term. The struct must contain
  1707 	 *      Also, it can optionally contain:
  1923 	 *                                  the term 'name' and 'taxonomy'. Optional accepted values include
  1708 	 *      - 'parent'
  1924 	 *                                  'parent', 'description', and 'slug'.
  1709 	 *      - 'description'
  1925 	 * }
  1710 	 *      - 'slug'
  1926 	 * @return int|IXR_Error The term ID on success, or an IXR_Error object on failure.
  1711 	 * @return string|IXR_Error term_id
       
  1712 	 */
  1927 	 */
  1713 	public function wp_newTerm( $args ) {
  1928 	public function wp_newTerm( $args ) {
  1714 		if ( ! $this->minimum_args( $args, 4 ) )
  1929 		if ( ! $this->minimum_args( $args, 4 ) )
  1715 			return $this->error;
  1930 			return $this->error;
  1716 
  1931 
  1717 		$this->escape( $args );
  1932 		$this->escape( $args );
  1718 
  1933 
  1719 		$username           = $args[1];
  1934 		$username       = $args[1];
  1720 		$password           = $args[2];
  1935 		$password       = $args[2];
  1721 		$content_struct     = $args[3];
  1936 		$content_struct = $args[3];
  1722 
  1937 
  1723 		if ( ! $user = $this->login( $username, $password ) )
  1938 		if ( ! $user = $this->login( $username, $password ) )
  1724 			return $this->error;
  1939 			return $this->error;
  1725 
  1940 
  1726 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  1941 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  1727 		do_action( 'xmlrpc_call', 'wp.newTerm' );
  1942 		do_action( 'xmlrpc_call', 'wp.newTerm' );
  1728 
  1943 
  1729 		if ( ! taxonomy_exists( $content_struct['taxonomy'] ) )
  1944 		if ( ! taxonomy_exists( $content_struct['taxonomy'] ) )
  1730 			return new IXR_Error( 403, __( 'Invalid taxonomy' ) );
  1945 			return new IXR_Error( 403, __( 'Invalid taxonomy.' ) );
  1731 
  1946 
  1732 		$taxonomy = get_taxonomy( $content_struct['taxonomy'] );
  1947 		$taxonomy = get_taxonomy( $content_struct['taxonomy'] );
  1733 
  1948 
  1734 		if ( ! current_user_can( $taxonomy->cap->manage_terms ) )
  1949 		if ( ! current_user_can( $taxonomy->cap->edit_terms ) ) {
  1735 			return new IXR_Error( 401, __( 'You are not allowed to create terms in this taxonomy.' ) );
  1950 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to create terms in this taxonomy.' ) );
       
  1951 		}
  1736 
  1952 
  1737 		$taxonomy = (array) $taxonomy;
  1953 		$taxonomy = (array) $taxonomy;
  1738 
  1954 
  1739 		// hold the data of the term
  1955 		// hold the data of the term
  1740 		$term_data = array();
  1956 		$term_data = array();
  1769 
  1985 
  1770 		if ( is_wp_error( $term ) )
  1986 		if ( is_wp_error( $term ) )
  1771 			return new IXR_Error( 500, $term->get_error_message() );
  1987 			return new IXR_Error( 500, $term->get_error_message() );
  1772 
  1988 
  1773 		if ( ! $term )
  1989 		if ( ! $term )
  1774 			return new IXR_Error( 500, __( 'Sorry, your term could not be created. Something wrong happened.' ) );
  1990 			return new IXR_Error( 500, __( 'Sorry, your term could not be created.' ) );
       
  1991 
       
  1992 		// Add term meta.
       
  1993 		if ( isset( $content_struct['custom_fields'] ) ) {
       
  1994 			$this->set_term_custom_fields( $term['term_id'], $content_struct['custom_fields'] );
       
  1995 		}
  1775 
  1996 
  1776 		return strval( $term['term_id'] );
  1997 		return strval( $term['term_id'] );
  1777 	}
  1998 	}
  1778 
  1999 
  1779 	/**
  2000 	/**
  1780 	 * Edit a term.
  2001 	 * Edit a term.
  1781 	 *
  2002 	 *
  1782 	 * @since 3.4.0
  2003 	 * @since 3.4.0
  1783 	 *
  2004 	 *
  1784 	 * @uses wp_update_term()
  2005 	 * @see wp_update_term()
  1785 	 * @param array $args Method parameters. Contains:
  2006 	 *
  1786 	 *  - int     $blog_id (unused)
  2007 	 * @param array $args {
  1787 	 *  - string  $username
  2008 	 *     Method arguments. Note: arguments must be ordered as documented.
  1788 	 *  - string  $password
  2009 	 *
  1789 	 *  - string  $term_id
  2010 	 *     @type int    $blog_id        Blog ID (unused).
  1790 	 *  - array   $content_struct
  2011 	 *     @type string $username       Username.
  1791 	 *      The $content_struct must contain:
  2012 	 *     @type string $password       Password.
  1792 	 *      - 'taxonomy'
  2013 	 *     @type int    $term_id        Term ID.
  1793 	 *      Also, it can optionally contain:
  2014 	 *     @type array  $content_struct Content struct for editing a term. The struct must contain the
  1794 	 *      - 'name'
  2015 	 *                                  term ''taxonomy'. Optional accepted values include 'name', 'parent',
  1795 	 *      - 'parent'
  2016 	 *                                  'description', and 'slug'.
  1796 	 *      - 'description'
  2017 	 * }
  1797 	 *      - 'slug'
  2018 	 * @return true|IXR_Error True on success, IXR_Error instance on failure.
  1798 	 * @return bool|IXR_Error True, on success.
       
  1799 	 */
  2019 	 */
  1800 	public function wp_editTerm( $args ) {
  2020 	public function wp_editTerm( $args ) {
  1801 		if ( ! $this->minimum_args( $args, 5 ) )
  2021 		if ( ! $this->minimum_args( $args, 5 ) )
  1802 			return $this->error;
  2022 			return $this->error;
  1803 
  2023 
  1804 		$this->escape( $args );
  2024 		$this->escape( $args );
  1805 
  2025 
  1806 		$username           = $args[1];
  2026 		$username       = $args[1];
  1807 		$password           = $args[2];
  2027 		$password       = $args[2];
  1808 		$term_id            = (int) $args[3];
  2028 		$term_id        = (int) $args[3];
  1809 		$content_struct     = $args[4];
  2029 		$content_struct = $args[4];
  1810 
  2030 
  1811 		if ( ! $user = $this->login( $username, $password ) )
  2031 		if ( ! $user = $this->login( $username, $password ) )
  1812 			return $this->error;
  2032 			return $this->error;
  1813 
  2033 
  1814 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2034 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  1815 		do_action( 'xmlrpc_call', 'wp.editTerm' );
  2035 		do_action( 'xmlrpc_call', 'wp.editTerm' );
  1816 
  2036 
  1817 		if ( ! taxonomy_exists( $content_struct['taxonomy'] ) )
  2037 		if ( ! taxonomy_exists( $content_struct['taxonomy'] ) )
  1818 			return new IXR_Error( 403, __( 'Invalid taxonomy' ) );
  2038 			return new IXR_Error( 403, __( 'Invalid taxonomy.' ) );
  1819 
  2039 
  1820 		$taxonomy = get_taxonomy( $content_struct['taxonomy'] );
  2040 		$taxonomy = get_taxonomy( $content_struct['taxonomy'] );
  1821 
       
  1822 		if ( ! current_user_can( $taxonomy->cap->edit_terms ) )
       
  1823 			return new IXR_Error( 401, __( 'You are not allowed to edit terms in this taxonomy.' ) );
       
  1824 
  2041 
  1825 		$taxonomy = (array) $taxonomy;
  2042 		$taxonomy = (array) $taxonomy;
  1826 
  2043 
  1827 		// hold the data of the term
  2044 		// hold the data of the term
  1828 		$term_data = array();
  2045 		$term_data = array();
  1831 
  2048 
  1832 		if ( is_wp_error( $term ) )
  2049 		if ( is_wp_error( $term ) )
  1833 			return new IXR_Error( 500, $term->get_error_message() );
  2050 			return new IXR_Error( 500, $term->get_error_message() );
  1834 
  2051 
  1835 		if ( ! $term )
  2052 		if ( ! $term )
  1836 			return new IXR_Error( 404, __( 'Invalid term ID' ) );
  2053 			return new IXR_Error( 404, __( 'Invalid term ID.' ) );
       
  2054 
       
  2055 		if ( ! current_user_can( 'edit_term', $term_id ) ) {
       
  2056 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this term.' ) );
       
  2057 		}
  1837 
  2058 
  1838 		if ( isset( $content_struct['name'] ) ) {
  2059 		if ( isset( $content_struct['name'] ) ) {
  1839 			$term_data['name'] = trim( $content_struct['name'] );
  2060 			$term_data['name'] = trim( $content_struct['name'] );
  1840 
  2061 
  1841 			if ( empty( $term_data['name'] ) )
  2062 			if ( empty( $term_data['name'] ) )
  1842 				return new IXR_Error( 403, __( 'The term name cannot be empty.' ) );
  2063 				return new IXR_Error( 403, __( 'The term name cannot be empty.' ) );
  1843 		}
  2064 		}
  1844 
  2065 
  1845 		if ( isset( $content_struct['parent'] ) ) {
  2066 		if ( ! empty( $content_struct['parent'] ) ) {
  1846 			if ( ! $taxonomy['hierarchical'] )
  2067 			if ( ! $taxonomy['hierarchical'] )
  1847 				return new IXR_Error( 403, __( "This taxonomy is not hierarchical so you can't set a parent." ) );
  2068 				return new IXR_Error( 403, __( 'Cannot set parent term, taxonomy is not hierarchical.' ) );
  1848 
  2069 
  1849 			$parent_term_id = (int) $content_struct['parent'];
  2070 			$parent_term_id = (int) $content_struct['parent'];
  1850 			$parent_term = get_term( $parent_term_id , $taxonomy['name'] );
  2071 			$parent_term = get_term( $parent_term_id , $taxonomy['name'] );
  1851 
  2072 
  1852 			if ( is_wp_error( $parent_term ) )
  2073 			if ( is_wp_error( $parent_term ) )
  1870 			return new IXR_Error( 500, $term->get_error_message() );
  2091 			return new IXR_Error( 500, $term->get_error_message() );
  1871 
  2092 
  1872 		if ( ! $term )
  2093 		if ( ! $term )
  1873 			return new IXR_Error( 500, __( 'Sorry, editing the term failed.' ) );
  2094 			return new IXR_Error( 500, __( 'Sorry, editing the term failed.' ) );
  1874 
  2095 
       
  2096 		// Update term meta.
       
  2097 		if ( isset( $content_struct['custom_fields'] ) ) {
       
  2098 			$this->set_term_custom_fields( $term_id, $content_struct['custom_fields'] );
       
  2099 		}
       
  2100 
  1875 		return true;
  2101 		return true;
  1876 	}
  2102 	}
  1877 
  2103 
  1878 	/**
  2104 	/**
  1879 	 * Delete a term.
  2105 	 * Delete a term.
  1880 	 *
  2106 	 *
  1881 	 * @since 3.4.0
  2107 	 * @since 3.4.0
  1882 	 *
  2108 	 *
  1883 	 * @uses wp_delete_term()
  2109 	 * @see wp_delete_term()
  1884 	 * @param array $args Method parameters. Contains:
  2110 	 *
  1885 	 *  - int     $blog_id (unused)
  2111 	 * @param array  $args {
  1886 	 *  - string  $username
  2112 	 *     Method arguments. Note: arguments must be ordered as documented.
  1887 	 *  - string  $password
  2113 	 *
  1888 	 *  - string  $taxnomy_name
  2114 	 *     @type int    $blog_id      Blog ID (unused).
  1889 	 *  - string     $term_id
  2115 	 *     @type string $username     Username.
  1890 	 * @return boolean|IXR_Error If it suceeded true else a reason why not
  2116 	 *     @type string $password     Password.
       
  2117 	 *     @type string $taxnomy_name Taxonomy name.
       
  2118 	 *     @type int    $term_id      Term ID.
       
  2119 	 * }
       
  2120 	 * @return bool|IXR_Error True on success, IXR_Error instance on failure.
  1891 	 */
  2121 	 */
  1892 	public function wp_deleteTerm( $args ) {
  2122 	public function wp_deleteTerm( $args ) {
  1893 		if ( ! $this->minimum_args( $args, 5 ) )
  2123 		if ( ! $this->minimum_args( $args, 5 ) )
  1894 			return $this->error;
  2124 			return $this->error;
  1895 
  2125 
  1905 
  2135 
  1906 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2136 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  1907 		do_action( 'xmlrpc_call', 'wp.deleteTerm' );
  2137 		do_action( 'xmlrpc_call', 'wp.deleteTerm' );
  1908 
  2138 
  1909 		if ( ! taxonomy_exists( $taxonomy ) )
  2139 		if ( ! taxonomy_exists( $taxonomy ) )
  1910 			return new IXR_Error( 403, __( 'Invalid taxonomy' ) );
  2140 			return new IXR_Error( 403, __( 'Invalid taxonomy.' ) );
  1911 
  2141 
  1912 		$taxonomy = get_taxonomy( $taxonomy );
  2142 		$taxonomy = get_taxonomy( $taxonomy );
  1913 
       
  1914 		if ( ! current_user_can( $taxonomy->cap->delete_terms ) )
       
  1915 			return new IXR_Error( 401, __( 'You are not allowed to delete terms in this taxonomy.' ) );
       
  1916 
       
  1917 		$term = get_term( $term_id, $taxonomy->name );
  2143 		$term = get_term( $term_id, $taxonomy->name );
  1918 
  2144 
  1919 		if ( is_wp_error( $term ) )
  2145 		if ( is_wp_error( $term ) )
  1920 			return new IXR_Error( 500, $term->get_error_message() );
  2146 			return new IXR_Error( 500, $term->get_error_message() );
  1921 
  2147 
  1922 		if ( ! $term )
  2148 		if ( ! $term )
  1923 			return new IXR_Error( 404, __( 'Invalid term ID' ) );
  2149 			return new IXR_Error( 404, __( 'Invalid term ID.' ) );
       
  2150 
       
  2151 		if ( ! current_user_can( 'delete_term', $term_id ) ) {
       
  2152 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to delete this term.' ) );
       
  2153 		}
  1924 
  2154 
  1925 		$result = wp_delete_term( $term_id, $taxonomy->name );
  2155 		$result = wp_delete_term( $term_id, $taxonomy->name );
  1926 
  2156 
  1927 		if ( is_wp_error( $result ) )
  2157 		if ( is_wp_error( $result ) )
  1928 			return new IXR_Error( 500, $term->get_error_message() );
  2158 			return new IXR_Error( 500, $term->get_error_message() );
  1936 	/**
  2166 	/**
  1937 	 * Retrieve a term.
  2167 	 * Retrieve a term.
  1938 	 *
  2168 	 *
  1939 	 * @since 3.4.0
  2169 	 * @since 3.4.0
  1940 	 *
  2170 	 *
  1941 	 * @uses get_term()
  2171 	 * @see get_term()
  1942 	 * @param array $args Method parameters. Contains:
  2172 	 *
  1943 	 *  - int     $blog_id (unused)
  2173 	 * @param array  $args {
  1944 	 *  - string  $username
  2174 	 *     Method arguments. Note: arguments must be ordered as documented.
  1945 	 *  - string  $password
  2175 	 *
  1946 	 *  - string  $taxonomy
  2176 	 *     @type int    $blog_id  Blog ID (unused).
  1947 	 *  - string  $term_id
  2177 	 *     @type string $username Username.
  1948 	 * @return array|IXR_Error Array contains:
  2178 	 *     @type string $password Password.
       
  2179 	 *     @type string $taxnomy  Taxonomy name.
       
  2180 	 *     @type string $term_id  Term ID.
       
  2181 	 * }
       
  2182 	 * @return array|IXR_Error IXR_Error on failure, array on success, containing:
  1949 	 *  - 'term_id'
  2183 	 *  - 'term_id'
  1950 	 *  - 'name'
  2184 	 *  - 'name'
  1951 	 *  - 'slug'
  2185 	 *  - 'slug'
  1952 	 *  - 'term_group'
  2186 	 *  - 'term_group'
  1953 	 *  - 'term_taxonomy_id'
  2187 	 *  - 'term_taxonomy_id'
  1972 
  2206 
  1973 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2207 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  1974 		do_action( 'xmlrpc_call', 'wp.getTerm' );
  2208 		do_action( 'xmlrpc_call', 'wp.getTerm' );
  1975 
  2209 
  1976 		if ( ! taxonomy_exists( $taxonomy ) )
  2210 		if ( ! taxonomy_exists( $taxonomy ) )
  1977 			return new IXR_Error( 403, __( 'Invalid taxonomy' ) );
  2211 			return new IXR_Error( 403, __( 'Invalid taxonomy.' ) );
  1978 
  2212 
  1979 		$taxonomy = get_taxonomy( $taxonomy );
  2213 		$taxonomy = get_taxonomy( $taxonomy );
  1980 
       
  1981 		if ( ! current_user_can( $taxonomy->cap->assign_terms ) )
       
  1982 			return new IXR_Error( 401, __( 'You are not allowed to assign terms in this taxonomy.' ) );
       
  1983 
  2214 
  1984 		$term = get_term( $term_id , $taxonomy->name, ARRAY_A );
  2215 		$term = get_term( $term_id , $taxonomy->name, ARRAY_A );
  1985 
  2216 
  1986 		if ( is_wp_error( $term ) )
  2217 		if ( is_wp_error( $term ) )
  1987 			return new IXR_Error( 500, $term->get_error_message() );
  2218 			return new IXR_Error( 500, $term->get_error_message() );
  1988 
  2219 
  1989 		if ( ! $term )
  2220 		if ( ! $term )
  1990 			return new IXR_Error( 404, __( 'Invalid term ID' ) );
  2221 			return new IXR_Error( 404, __( 'Invalid term ID.' ) );
       
  2222 
       
  2223 		if ( ! current_user_can( 'assign_term', $term_id ) ) {
       
  2224 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to assign this term.' ) );
       
  2225 		}
  1991 
  2226 
  1992 		return $this->_prepare_term( $term );
  2227 		return $this->_prepare_term( $term );
  1993 	}
  2228 	}
  1994 
  2229 
  1995 	/**
  2230 	/**
  1998 	 * @since 3.4.0
  2233 	 * @since 3.4.0
  1999 	 *
  2234 	 *
  2000 	 * The optional $filter parameter modifies the query used to retrieve terms.
  2235 	 * The optional $filter parameter modifies the query used to retrieve terms.
  2001 	 * Accepted keys are 'number', 'offset', 'orderby', 'order', 'hide_empty', and 'search'.
  2236 	 * Accepted keys are 'number', 'offset', 'orderby', 'order', 'hide_empty', and 'search'.
  2002 	 *
  2237 	 *
  2003 	 * @uses get_terms()
  2238 	 * @see get_terms()
  2004 	 * @param array $args Method parameters. Contains:
  2239 	 *
  2005 	 *  - int     $blog_id (unused)
  2240 	 * @param array  $args {
  2006 	 *  - string  $username
  2241 	 *     Method arguments. Note: arguments must be ordered as documented.
  2007 	 *  - string  $password
  2242 	 *
  2008 	 *  - string  $taxonomy
  2243 	 *     @type int    $blog_id  Blog ID (unused).
  2009 	 *  - array   $filter optional
  2244 	 *     @type string $username Username.
  2010 	 * @return array|IXR_Error terms
  2245 	 *     @type string $password Password.
       
  2246 	 *     @type string $taxnomy  Taxonomy name.
       
  2247 	 *     @type array  $filter   Optional. Modifies the query used to retrieve posts. Accepts 'number',
       
  2248 	 *                            'offset', 'orderby', 'order', 'hide_empty', and 'search'. Default empty array.
       
  2249 	 * }
       
  2250 	 * @return array|IXR_Error An associative array of terms data on success, IXR_Error instance otherwise.
  2011 	 */
  2251 	 */
  2012 	public function wp_getTerms( $args ) {
  2252 	public function wp_getTerms( $args ) {
  2013 		if ( ! $this->minimum_args( $args, 4 ) )
  2253 		if ( ! $this->minimum_args( $args, 4 ) )
  2014 			return $this->error;
  2254 			return $this->error;
  2015 
  2255 
  2025 
  2265 
  2026 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2266 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2027 		do_action( 'xmlrpc_call', 'wp.getTerms' );
  2267 		do_action( 'xmlrpc_call', 'wp.getTerms' );
  2028 
  2268 
  2029 		if ( ! taxonomy_exists( $taxonomy ) )
  2269 		if ( ! taxonomy_exists( $taxonomy ) )
  2030 			return new IXR_Error( 403, __( 'Invalid taxonomy' ) );
  2270 			return new IXR_Error( 403, __( 'Invalid taxonomy.' ) );
  2031 
  2271 
  2032 		$taxonomy = get_taxonomy( $taxonomy );
  2272 		$taxonomy = get_taxonomy( $taxonomy );
  2033 
  2273 
  2034 		if ( ! current_user_can( $taxonomy->cap->assign_terms ) )
  2274 		if ( ! current_user_can( $taxonomy->cap->assign_terms ) )
  2035 			return new IXR_Error( 401, __( 'You are not allowed to assign terms in this taxonomy.' ) );
  2275 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to assign terms in this taxonomy.' ) );
  2036 
  2276 
  2037 		$query = array();
  2277 		$query = array();
  2038 
  2278 
  2039 		if ( isset( $filter['number'] ) )
  2279 		if ( isset( $filter['number'] ) )
  2040 			$query['number'] = absint( $filter['number'] );
  2280 			$query['number'] = absint( $filter['number'] );
  2074 	/**
  2314 	/**
  2075 	 * Retrieve a taxonomy.
  2315 	 * Retrieve a taxonomy.
  2076 	 *
  2316 	 *
  2077 	 * @since 3.4.0
  2317 	 * @since 3.4.0
  2078 	 *
  2318 	 *
  2079 	 * @uses get_taxonomy()
  2319 	 * @see get_taxonomy()
  2080 	 * @param array $args Method parameters. Contains:
  2320 	 *
  2081 	 *  - int     $blog_id (unused)
  2321 	 * @param array  $args {
  2082 	 *  - string  $username
  2322 	 *     Method arguments. Note: arguments must be ordered as documented.
  2083 	 *  - string  $password
  2323 	 *
  2084 	 *  - string  $taxonomy
  2324 	 *     @type int    $blog_id  Blog ID (unused).
  2085 	 * @return array|IXR_Error (@see get_taxonomy())
  2325 	 *     @type string $username Username.
       
  2326 	 *     @type string $password Password.
       
  2327 	 *     @type string $taxnomy  Taxonomy name.
       
  2328 	 *     @type array  $fields   Optional. Array of taxonomy fields to limit to in the return.
       
  2329 	 *                            Accepts 'labels', 'cap', 'menu', and 'object_type'.
       
  2330 	 *                            Default empty array.
       
  2331 	 * }
       
  2332 	 * @return array|IXR_Error An array of taxonomy data on success, IXR_Error instance otherwise.
  2086 	 */
  2333 	 */
  2087 	public function wp_getTaxonomy( $args ) {
  2334 	public function wp_getTaxonomy( $args ) {
  2088 		if ( ! $this->minimum_args( $args, 4 ) )
  2335 		if ( ! $this->minimum_args( $args, 4 ) )
  2089 			return $this->error;
  2336 			return $this->error;
  2090 
  2337 
  2091 		$this->escape( $args );
  2338 		$this->escape( $args );
  2092 
  2339 
  2093 		$username       = $args[1];
  2340 		$username = $args[1];
  2094 		$password       = $args[2];
  2341 		$password = $args[2];
  2095 		$taxonomy       = $args[3];
  2342 		$taxonomy = $args[3];
  2096 
  2343 
  2097 		if ( isset( $args[4] ) ) {
  2344 		if ( isset( $args[4] ) ) {
  2098 			$fields = $args[4];
  2345 			$fields = $args[4];
  2099 		} else {
  2346 		} else {
  2100 			/**
  2347 			/**
  2101 			 * Filter the taxonomy query fields used by the given XML-RPC method.
  2348 			 * Filters the taxonomy query fields used by the given XML-RPC method.
  2102 			 *
  2349 			 *
  2103 			 * @since 3.4.0
  2350 			 * @since 3.4.0
  2104 			 *
  2351 			 *
  2105 			 * @param array  $fields An array of taxonomy fields to retrieve.
  2352 			 * @param array  $fields An array of taxonomy fields to retrieve.
  2106 			 * @param string $method The method name.
  2353 			 * @param string $method The method name.
  2113 
  2360 
  2114 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2361 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2115 		do_action( 'xmlrpc_call', 'wp.getTaxonomy' );
  2362 		do_action( 'xmlrpc_call', 'wp.getTaxonomy' );
  2116 
  2363 
  2117 		if ( ! taxonomy_exists( $taxonomy ) )
  2364 		if ( ! taxonomy_exists( $taxonomy ) )
  2118 			return new IXR_Error( 403, __( 'Invalid taxonomy' ) );
  2365 			return new IXR_Error( 403, __( 'Invalid taxonomy.' ) );
  2119 
  2366 
  2120 		$taxonomy = get_taxonomy( $taxonomy );
  2367 		$taxonomy = get_taxonomy( $taxonomy );
  2121 
  2368 
  2122 		if ( ! current_user_can( $taxonomy->cap->assign_terms ) )
  2369 		if ( ! current_user_can( $taxonomy->cap->assign_terms ) )
  2123 			return new IXR_Error( 401, __( 'You are not allowed to assign terms in this taxonomy.' ) );
  2370 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to assign terms in this taxonomy.' ) );
  2124 
  2371 
  2125 		return $this->_prepare_taxonomy( $taxonomy, $fields );
  2372 		return $this->_prepare_taxonomy( $taxonomy, $fields );
  2126 	}
  2373 	}
  2127 
  2374 
  2128 	/**
  2375 	/**
  2129 	 * Retrieve all taxonomies.
  2376 	 * Retrieve all taxonomies.
  2130 	 *
  2377 	 *
  2131 	 * @since 3.4.0
  2378 	 * @since 3.4.0
  2132 	 *
  2379 	 *
  2133 	 * @uses get_taxonomies()
  2380 	 * @see get_taxonomies()
  2134 	 * @param array $args Method parameters. Contains:
  2381 	 *
  2135 	 *  - int     $blog_id (unused)
  2382 	 * @param array  $args {
  2136 	 *  - string  $username
  2383 	 *     Method arguments. Note: arguments must be ordered as documented.
  2137 	 *  - string  $password
  2384 	 *
  2138 	 * @return array taxonomies
  2385 	 *     @type int    $blog_id  Blog ID (unused).
       
  2386 	 *     @type string $username Username.
       
  2387 	 *     @type string $password Password.
       
  2388 	 *     @type array  $filter   Optional. An array of arguments for retrieving taxonomies.
       
  2389 	 *     @type array  $fields   Optional. The subset of taxonomy fields to return.
       
  2390 	 * }
       
  2391 	 * @return array|IXR_Error An associative array of taxonomy data with returned fields determined
       
  2392 	 *                         by `$fields`, or an IXR_Error instance on failure.
  2139 	 */
  2393 	 */
  2140 	public function wp_getTaxonomies( $args ) {
  2394 	public function wp_getTaxonomies( $args ) {
  2141 		if ( ! $this->minimum_args( $args, 3 ) )
  2395 		if ( ! $this->minimum_args( $args, 3 ) )
  2142 			return $this->error;
  2396 			return $this->error;
  2143 
  2397 
  2144 		$this->escape( $args );
  2398 		$this->escape( $args );
  2145 
  2399 
  2146 		$username           = $args[1];
  2400 		$username = $args[1];
  2147 		$password           = $args[2];
  2401 		$password = $args[2];
  2148 		$filter             = isset( $args[3] ) ? $args[3] : array( 'public' => true );
  2402 		$filter   = isset( $args[3] ) ? $args[3] : array( 'public' => true );
  2149 
  2403 
  2150 		if ( isset( $args[4] ) ) {
  2404 		if ( isset( $args[4] ) ) {
  2151 			$fields = $args[4];
  2405 			$fields = $args[4];
  2152 		} else {
  2406 		} else {
  2153 			/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2407 			/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2186 	 * Instead of, or in addition to, individual field names, conceptual group
  2440 	 * Instead of, or in addition to, individual field names, conceptual group
  2187 	 * names can be used to specify multiple fields. The available conceptual
  2441 	 * names can be used to specify multiple fields. The available conceptual
  2188 	 * groups are 'basic' and 'all'.
  2442 	 * groups are 'basic' and 'all'.
  2189 	 *
  2443 	 *
  2190 	 * @uses get_userdata()
  2444 	 * @uses get_userdata()
  2191 	 * @param array $args Method parameters. Contains:
  2445 	 *
  2192 	 *  - int     $blog_id (unused)
  2446 	 * @param array  $args {
  2193 	 *  - string  $username
  2447 	 *     Method arguments. Note: arguments must be ordered as documented.
  2194 	 *  - string  $password
  2448 	 *
  2195 	 *  - int     $user_id
  2449 	 *     @type int    $blog_id (unused)
  2196 	 *  - array   $fields optional
  2450 	 *     @type string $username
       
  2451 	 *     @type string $password
       
  2452 	 *     @type int    $user_id
       
  2453 	 *     @type array  $fields (optional)
       
  2454 	 * }
  2197 	 * @return array|IXR_Error Array contains (based on $fields parameter):
  2455 	 * @return array|IXR_Error Array contains (based on $fields parameter):
  2198 	 *  - 'user_id'
  2456 	 *  - 'user_id'
  2199 	 *  - 'username'
  2457 	 *  - 'username'
  2200 	 *  - 'first_name'
  2458 	 *  - 'first_name'
  2201 	 *  - 'last_name'
  2459 	 *  - 'last_name'
  2212 		if ( ! $this->minimum_args( $args, 4 ) )
  2470 		if ( ! $this->minimum_args( $args, 4 ) )
  2213 			return $this->error;
  2471 			return $this->error;
  2214 
  2472 
  2215 		$this->escape( $args );
  2473 		$this->escape( $args );
  2216 
  2474 
  2217 		$username   = $args[1];
  2475 		$username = $args[1];
  2218 		$password   = $args[2];
  2476 		$password = $args[2];
  2219 		$user_id    = (int) $args[3];
  2477 		$user_id  = (int) $args[3];
  2220 
  2478 
  2221 		if ( isset( $args[4] ) ) {
  2479 		if ( isset( $args[4] ) ) {
  2222 			$fields = $args[4];
  2480 			$fields = $args[4];
  2223 		} else {
  2481 		} else {
  2224 			/**
  2482 			/**
  2225 			 * Filter the default user query fields used by the given XML-RPC method.
  2483 			 * Filters the default user query fields used by the given XML-RPC method.
  2226 			 *
  2484 			 *
  2227 			 * @since 3.5.0
  2485 			 * @since 3.5.0
  2228 			 *
  2486 			 *
  2229 			 * @param array  $fields User query fields for given method. Default 'all'.
  2487 			 * @param array  $fields User query fields for given method. Default 'all'.
  2230 			 * @param string $method The method name.
  2488 			 * @param string $method The method name.
  2237 
  2495 
  2238 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2496 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2239 		do_action( 'xmlrpc_call', 'wp.getUser' );
  2497 		do_action( 'xmlrpc_call', 'wp.getUser' );
  2240 
  2498 
  2241 		if ( ! current_user_can( 'edit_user', $user_id ) )
  2499 		if ( ! current_user_can( 'edit_user', $user_id ) )
  2242 			return new IXR_Error( 401, __( 'Sorry, you cannot edit users.' ) );
  2500 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this user.' ) );
  2243 
  2501 
  2244 		$user_data = get_userdata( $user_id );
  2502 		$user_data = get_userdata( $user_id );
  2245 
  2503 
  2246 		if ( ! $user_data )
  2504 		if ( ! $user_data )
  2247 			return new IXR_Error( 404, __( 'Invalid user ID' ) );
  2505 			return new IXR_Error( 404, __( 'Invalid user ID.' ) );
  2248 
  2506 
  2249 		return $this->_prepare_user( $user_data, $fields );
  2507 		return $this->_prepare_user( $user_data, $fields );
  2250 	}
  2508 	}
  2251 
  2509 
  2252 	/**
  2510 	/**
  2260 	 * in the response array.
  2518 	 * in the response array.
  2261 	 *
  2519 	 *
  2262 	 * @uses get_users()
  2520 	 * @uses get_users()
  2263 	 * @see wp_getUser() for more on $fields and return values
  2521 	 * @see wp_getUser() for more on $fields and return values
  2264 	 *
  2522 	 *
  2265 	 * @param array $args Method parameters. Contains:
  2523 	 * @param array  $args {
  2266 	 *  - int     $blog_id (unused)
  2524 	 *     Method arguments. Note: arguments must be ordered as documented.
  2267 	 *  - string  $username
  2525 	 *
  2268 	 *  - string  $password
  2526 	 *     @type int    $blog_id (unused)
  2269 	 *  - array   $filter optional
  2527 	 *     @type string $username
  2270 	 *  - array   $fields optional
  2528 	 *     @type string $password
       
  2529 	 *     @type array  $filter (optional)
       
  2530 	 *     @type array  $fields (optional)
       
  2531 	 * }
  2271 	 * @return array|IXR_Error users data
  2532 	 * @return array|IXR_Error users data
  2272 	 */
  2533 	 */
  2273 	public function wp_getUsers( $args ) {
  2534 	public function wp_getUsers( $args ) {
  2274 		if ( ! $this->minimum_args( $args, 3 ) )
  2535 		if ( ! $this->minimum_args( $args, 3 ) )
  2275 			return $this->error;
  2536 			return $this->error;
  2276 
  2537 
  2277 		$this->escape( $args );
  2538 		$this->escape( $args );
  2278 
  2539 
  2279 		$username   = $args[1];
  2540 		$username = $args[1];
  2280 		$password   = $args[2];
  2541 		$password = $args[2];
  2281 		$filter     = isset( $args[3] ) ? $args[3] : array();
  2542 		$filter   = isset( $args[3] ) ? $args[3] : array();
  2282 
  2543 
  2283 		if ( isset( $args[4] ) ) {
  2544 		if ( isset( $args[4] ) ) {
  2284 			$fields = $args[4];
  2545 			$fields = $args[4];
  2285 		} else {
  2546 		} else {
  2286 			/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2547 			/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2292 
  2553 
  2293 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2554 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2294 		do_action( 'xmlrpc_call', 'wp.getUsers' );
  2555 		do_action( 'xmlrpc_call', 'wp.getUsers' );
  2295 
  2556 
  2296 		if ( ! current_user_can( 'list_users' ) )
  2557 		if ( ! current_user_can( 'list_users' ) )
  2297 			return new IXR_Error( 401, __( 'Sorry, you cannot list users.' ) );
  2558 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to list users.' ) );
  2298 
  2559 
  2299 		$query = array( 'fields' => 'all_with_meta' );
  2560 		$query = array( 'fields' => 'all_with_meta' );
  2300 
  2561 
  2301 		$query['number'] = ( isset( $filter['number'] ) ) ? absint( $filter['number'] ) : 50;
  2562 		$query['number'] = ( isset( $filter['number'] ) ) ? absint( $filter['number'] ) : 50;
  2302 		$query['offset'] = ( isset( $filter['offset'] ) ) ? absint( $filter['offset'] ) : 0;
  2563 		$query['offset'] = ( isset( $filter['offset'] ) ) ? absint( $filter['offset'] ) : 0;
  2308 				$query['order'] = $filter['order'];
  2569 				$query['order'] = $filter['order'];
  2309 		}
  2570 		}
  2310 
  2571 
  2311 		if ( isset( $filter['role'] ) ) {
  2572 		if ( isset( $filter['role'] ) ) {
  2312 			if ( get_role( $filter['role'] ) === null )
  2573 			if ( get_role( $filter['role'] ) === null )
  2313 				return new IXR_Error( 403, __( 'The role specified is not valid' ) );
  2574 				return new IXR_Error( 403, __( 'Invalid role.' ) );
  2314 
  2575 
  2315 			$query['role'] = $filter['role'];
  2576 			$query['role'] = $filter['role'];
  2316 		}
  2577 		}
  2317 
  2578 
  2318 		if ( isset( $filter['who'] ) ) {
  2579 		if ( isset( $filter['who'] ) ) {
  2331 
  2592 
  2332 	/**
  2593 	/**
  2333 	 * Retrieve information about the requesting user.
  2594 	 * Retrieve information about the requesting user.
  2334 	 *
  2595 	 *
  2335 	 * @uses get_userdata()
  2596 	 * @uses get_userdata()
  2336 	 * @param array $args Method parameters. Contains:
  2597 	 *
  2337 	 *  - int     $blog_id (unused)
  2598 	 * @param array  $args {
  2338 	 *  - string  $username
  2599 	 *     Method arguments. Note: arguments must be ordered as documented.
  2339 	 *  - string  $password
  2600 	 *
  2340 	 *  - array   $fields optional
  2601 	 *     @type int    $blog_id (unused)
       
  2602 	 *     @type string $username
       
  2603 	 *     @type string $password
       
  2604 	 *     @type array  $fields (optional)
       
  2605 	 * }
  2341 	 * @return array|IXR_Error (@see wp_getUser)
  2606 	 * @return array|IXR_Error (@see wp_getUser)
  2342 	 */
  2607 	 */
  2343 	public function wp_getProfile( $args ) {
  2608 	public function wp_getProfile( $args ) {
  2344 		if ( ! $this->minimum_args( $args, 3 ) )
  2609 		if ( ! $this->minimum_args( $args, 3 ) )
  2345 			return $this->error;
  2610 			return $this->error;
  2346 
  2611 
  2347 		$this->escape( $args );
  2612 		$this->escape( $args );
  2348 
  2613 
  2349 		$username   = $args[1];
  2614 		$username = $args[1];
  2350 		$password   = $args[2];
  2615 		$password = $args[2];
  2351 
  2616 
  2352 		if ( isset( $args[3] ) ) {
  2617 		if ( isset( $args[3] ) ) {
  2353 			$fields = $args[3];
  2618 			$fields = $args[3];
  2354 		} else {
  2619 		} else {
  2355 			/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2620 			/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2361 
  2626 
  2362 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2627 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2363 		do_action( 'xmlrpc_call', 'wp.getProfile' );
  2628 		do_action( 'xmlrpc_call', 'wp.getProfile' );
  2364 
  2629 
  2365 		if ( ! current_user_can( 'edit_user', $user->ID ) )
  2630 		if ( ! current_user_can( 'edit_user', $user->ID ) )
  2366 			return new IXR_Error( 401, __( 'Sorry, you cannot edit your profile.' ) );
  2631 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit your profile.' ) );
  2367 
  2632 
  2368 		$user_data = get_userdata( $user->ID );
  2633 		$user_data = get_userdata( $user->ID );
  2369 
  2634 
  2370 		return $this->_prepare_user( $user_data, $fields );
  2635 		return $this->_prepare_user( $user_data, $fields );
  2371 	}
  2636 	}
  2372 
  2637 
  2373 	/**
  2638 	/**
  2374 	 * Edit user's profile.
  2639 	 * Edit user's profile.
  2375 	 *
  2640 	 *
  2376 	 * @uses wp_update_user()
  2641 	 * @uses wp_update_user()
  2377 	 * @param array $args Method parameters. Contains:
  2642 	 *
  2378 	 *  - int     $blog_id (unused)
  2643 	 * @param array  $args {
  2379 	 *  - string  $username
  2644 	 *     Method arguments. Note: arguments must be ordered as documented.
  2380 	 *  - string  $password
  2645 	 *
  2381 	 *  - array   $content_struct
  2646 	 *     @type int    $blog_id (unused)
  2382 	 *      It can optionally contain:
  2647 	 *     @type string $username
       
  2648 	 *     @type string $password
       
  2649 	 *     @type array  $content_struct It can optionally contain:
  2383 	 *      - 'first_name'
  2650 	 *      - 'first_name'
  2384 	 *      - 'last_name'
  2651 	 *      - 'last_name'
  2385 	 *      - 'website'
  2652 	 *      - 'website'
  2386 	 *      - 'display_name'
  2653 	 *      - 'display_name'
  2387 	 *      - 'nickname'
  2654 	 *      - 'nickname'
  2388 	 *      - 'nicename'
  2655 	 *      - 'nicename'
  2389 	 *      - 'bio'
  2656 	 *      - 'bio'
  2390 	 * @return bool|IXR_Error True, on success.
  2657 	 * }
       
  2658 	 * @return true|IXR_Error True, on success.
  2391 	 */
  2659 	 */
  2392 	public function wp_editProfile( $args ) {
  2660 	public function wp_editProfile( $args ) {
  2393 		if ( ! $this->minimum_args( $args, 4 ) )
  2661 		if ( ! $this->minimum_args( $args, 4 ) )
  2394 			return $this->error;
  2662 			return $this->error;
  2395 
  2663 
  2404 
  2672 
  2405 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2673 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2406 		do_action( 'xmlrpc_call', 'wp.editProfile' );
  2674 		do_action( 'xmlrpc_call', 'wp.editProfile' );
  2407 
  2675 
  2408 		if ( ! current_user_can( 'edit_user', $user->ID ) )
  2676 		if ( ! current_user_can( 'edit_user', $user->ID ) )
  2409 			return new IXR_Error( 401, __( 'Sorry, you cannot edit your profile.' ) );
  2677 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit your profile.' ) );
  2410 
  2678 
  2411 		// holds data of the user
  2679 		// holds data of the user
  2412 		$user_data = array();
  2680 		$user_data = array();
  2413 		$user_data['ID'] = $user->ID;
  2681 		$user_data['ID'] = $user->ID;
  2414 
  2682 
  2448 	/**
  2716 	/**
  2449 	 * Retrieve page.
  2717 	 * Retrieve page.
  2450 	 *
  2718 	 *
  2451 	 * @since 2.2.0
  2719 	 * @since 2.2.0
  2452 	 *
  2720 	 *
  2453 	 * @param array $args Method parameters. Contains:
  2721 	 * @param array  $args {
  2454 	 *  - blog_id (unused)
  2722 	 *     Method arguments. Note: arguments must be ordered as documented.
  2455 	 *  - page_id
  2723 	 *
  2456 	 *  - username
  2724 	 *     @type int    $blog_id (unused)
  2457 	 *  - password
  2725 	 *     @type int    $page_id
       
  2726 	 *     @type string $username
       
  2727 	 *     @type string $password
       
  2728 	 * }
  2458 	 * @return array|IXR_Error
  2729 	 * @return array|IXR_Error
  2459 	 */
  2730 	 */
  2460 	public function wp_getPage($args) {
  2731 	public function wp_getPage( $args ) {
  2461 		$this->escape($args);
  2732 		$this->escape( $args );
  2462 
  2733 
  2463 		$page_id	= (int) $args[1];
  2734 		$page_id  = (int) $args[1];
  2464 		$username	= $args[2];
  2735 		$username = $args[2];
  2465 		$password	= $args[3];
  2736 		$password = $args[3];
  2466 
  2737 
  2467 		if ( !$user = $this->login($username, $password) ) {
  2738 		if ( !$user = $this->login($username, $password) ) {
  2468 			return $this->error;
  2739 			return $this->error;
  2469 		}
  2740 		}
  2470 
  2741 
  2471 		$page = get_post($page_id);
  2742 		$page = get_post($page_id);
  2472 		if ( ! $page )
  2743 		if ( ! $page )
  2473 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  2744 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  2474 
  2745 
  2475 		if ( !current_user_can( 'edit_page', $page_id ) )
  2746 		if ( !current_user_can( 'edit_page', $page_id ) )
  2476 			return new IXR_Error( 401, __( 'Sorry, you cannot edit this page.' ) );
  2747 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this page.' ) );
  2477 
  2748 
  2478 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2749 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2479 		do_action( 'xmlrpc_call', 'wp.getPage' );
  2750 		do_action( 'xmlrpc_call', 'wp.getPage' );
  2480 
  2751 
  2481 		// If we found the page then format the data.
  2752 		// If we found the page then format the data.
  2491 	/**
  2762 	/**
  2492 	 * Retrieve Pages.
  2763 	 * Retrieve Pages.
  2493 	 *
  2764 	 *
  2494 	 * @since 2.2.0
  2765 	 * @since 2.2.0
  2495 	 *
  2766 	 *
  2496 	 * @param array $args Method parameters. Contains:
  2767 	 * @param array  $args {
  2497 	 *  - blog_id (unused)
  2768 	 *     Method arguments. Note: arguments must be ordered as documented.
  2498 	 *  - username
  2769 	 *
  2499 	 *  - password
  2770 	 *     @type int    $blog_id (unused)
  2500 	 *  - num_pages
  2771 	 *     @type string $username
       
  2772 	 *     @type string $password
       
  2773 	 *     @type int    $num_pages
       
  2774 	 * }
  2501 	 * @return array|IXR_Error
  2775 	 * @return array|IXR_Error
  2502 	 */
  2776 	 */
  2503 	public function wp_getPages($args) {
  2777 	public function wp_getPages( $args ) {
  2504 		$this->escape($args);
  2778 		$this->escape( $args );
  2505 
  2779 
  2506 		$username	= $args[1];
  2780 		$username  = $args[1];
  2507 		$password	= $args[2];
  2781 		$password  = $args[2];
  2508 		$num_pages	= isset($args[3]) ? (int) $args[3] : 10;
  2782 		$num_pages = isset($args[3]) ? (int) $args[3] : 10;
  2509 
  2783 
  2510 		if ( !$user = $this->login($username, $password) )
  2784 		if ( !$user = $this->login($username, $password) )
  2511 			return $this->error;
  2785 			return $this->error;
  2512 
  2786 
  2513 		if ( !current_user_can( 'edit_pages' ) )
  2787 		if ( !current_user_can( 'edit_pages' ) )
  2514 			return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) );
  2788 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit pages.' ) );
  2515 
  2789 
  2516 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2790 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2517 		do_action( 'xmlrpc_call', 'wp.getPages' );
  2791 		do_action( 'xmlrpc_call', 'wp.getPages' );
  2518 
  2792 
  2519 		$pages = get_posts( array('post_type' => 'page', 'post_status' => 'any', 'numberposts' => $num_pages) );
  2793 		$pages = get_posts( array('post_type' => 'page', 'post_status' => 'any', 'numberposts' => $num_pages) );
  2537 	/**
  2811 	/**
  2538 	 * Create new page.
  2812 	 * Create new page.
  2539 	 *
  2813 	 *
  2540 	 * @since 2.2.0
  2814 	 * @since 2.2.0
  2541 	 *
  2815 	 *
  2542 	 * @param array $args Method parameters. See {@link wp_xmlrpc_server::mw_newPost()}
  2816 	 * @see wp_xmlrpc_server::mw_newPost()
       
  2817 	 *
       
  2818 	 * @param array  $args {
       
  2819 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  2820 	 *
       
  2821 	 *     @type int    $blog_id (unused)
       
  2822 	 *     @type string $username
       
  2823 	 *     @type string $password
       
  2824 	 *     @type array  $content_struct
       
  2825 	 * }
  2543 	 * @return int|IXR_Error
  2826 	 * @return int|IXR_Error
  2544 	 */
  2827 	 */
  2545 	public function wp_newPage($args) {
  2828 	public function wp_newPage( $args ) {
  2546 		// Items not escaped here will be escaped in newPost.
  2829 		// Items not escaped here will be escaped in newPost.
  2547 		$username	= $this->escape($args[1]);
  2830 		$username = $this->escape( $args[1] );
  2548 		$password	= $this->escape($args[2]);
  2831 		$password = $this->escape( $args[2] );
  2549 
  2832 
  2550 		if ( !$user = $this->login($username, $password) )
  2833 		if ( !$user = $this->login($username, $password) )
  2551 			return $this->error;
  2834 			return $this->error;
  2552 
  2835 
  2553 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2836 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2563 	/**
  2846 	/**
  2564 	 * Delete page.
  2847 	 * Delete page.
  2565 	 *
  2848 	 *
  2566 	 * @since 2.2.0
  2849 	 * @since 2.2.0
  2567 	 *
  2850 	 *
  2568 	 * @param array $args Method parameters.
  2851 	 * @param array  $args {
  2569 	 * @return bool|IXR_Error True, if success.
  2852 	 *     Method arguments. Note: arguments must be ordered as documented.
  2570 	 */
  2853 	 *
  2571 	public function wp_deletePage($args) {
  2854 	 *     @type int    $blog_id (unused)
  2572 		$this->escape($args);
  2855 	 *     @type string $username
  2573 
  2856 	 *     @type string $password
  2574 		$username	= $args[1];
  2857 	 *     @type int    $page_id
  2575 		$password	= $args[2];
  2858 	 * }
  2576 		$page_id	= (int) $args[3];
  2859 	 * @return true|IXR_Error True, if success.
       
  2860 	 */
       
  2861 	public function wp_deletePage( $args ) {
       
  2862 		$this->escape( $args );
       
  2863 
       
  2864 		$username = $args[1];
       
  2865 		$password = $args[2];
       
  2866 		$page_id  = (int) $args[3];
  2577 
  2867 
  2578 		if ( !$user = $this->login($username, $password) )
  2868 		if ( !$user = $this->login($username, $password) )
  2579 			return $this->error;
  2869 			return $this->error;
  2580 
  2870 
  2581 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2871 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2587 		if ( !$actual_page || ($actual_page['post_type'] != 'page') )
  2877 		if ( !$actual_page || ($actual_page['post_type'] != 'page') )
  2588 			return new IXR_Error( 404, __( 'Sorry, no such page.' ) );
  2878 			return new IXR_Error( 404, __( 'Sorry, no such page.' ) );
  2589 
  2879 
  2590 		// Make sure the user can delete pages.
  2880 		// Make sure the user can delete pages.
  2591 		if ( !current_user_can('delete_page', $page_id) )
  2881 		if ( !current_user_can('delete_page', $page_id) )
  2592 			return new IXR_Error( 401, __( 'Sorry, you do not have the right to delete this page.' ) );
  2882 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to delete this page.' ) );
  2593 
  2883 
  2594 		// Attempt to delete the page.
  2884 		// Attempt to delete the page.
  2595 		$result = wp_delete_post($page_id);
  2885 		$result = wp_delete_post($page_id);
  2596 		if ( !$result )
  2886 		if ( !$result )
  2597 			return new IXR_Error( 500, __( 'Failed to delete the page.' ) );
  2887 			return new IXR_Error( 500, __( 'Failed to delete the page.' ) );
  2612 	/**
  2902 	/**
  2613 	 * Edit page.
  2903 	 * Edit page.
  2614 	 *
  2904 	 *
  2615 	 * @since 2.2.0
  2905 	 * @since 2.2.0
  2616 	 *
  2906 	 *
  2617 	 * @param array $args Method parameters.
  2907 	 * @param array  $args {
       
  2908 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  2909 	 *
       
  2910 	 *     @type int    $blog_id (unused)
       
  2911 	 *     @type int    $page_id
       
  2912 	 *     @type string $username
       
  2913 	 *     @type string $password
       
  2914 	 *     @type string $content
       
  2915 	 *     @type string $publish
       
  2916 	 * }
  2618 	 * @return array|IXR_Error
  2917 	 * @return array|IXR_Error
  2619 	 */
  2918 	 */
  2620 	public function wp_editPage($args) {
  2919 	public function wp_editPage( $args ) {
  2621 		// Items not escaped here will be escaped in editPost.
  2920 		// Items will be escaped in mw_editPost.
  2622 		$page_id	= (int) $this->escape($args[1]);
  2921 		$page_id  = (int) $args[1];
  2623 		$username	= $this->escape($args[2]);
  2922 		$username = $args[2];
  2624 		$password	= $this->escape($args[3]);
  2923 		$password = $args[3];
  2625 		$content	= $args[4];
  2924 		$content  = $args[4];
  2626 		$publish	= $args[5];
  2925 		$publish  = $args[5];
  2627 
  2926 
  2628 		if ( !$user = $this->login($username, $password) )
  2927 		$escaped_username = $this->escape( $username );
  2629 			return $this->error;
  2928 		$escaped_password = $this->escape( $password );
       
  2929 
       
  2930 		if ( !$user = $this->login( $escaped_username, $escaped_password ) ) {
       
  2931 			return $this->error;
       
  2932 		}
  2630 
  2933 
  2631 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2934 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2632 		do_action( 'xmlrpc_call', 'wp.editPage' );
  2935 		do_action( 'xmlrpc_call', 'wp.editPage' );
  2633 
  2936 
  2634 		// Get the page data and make sure it is a page.
  2937 		// Get the page data and make sure it is a page.
  2636 		if ( !$actual_page || ($actual_page['post_type'] != 'page') )
  2939 		if ( !$actual_page || ($actual_page['post_type'] != 'page') )
  2637 			return new IXR_Error( 404, __( 'Sorry, no such page.' ) );
  2940 			return new IXR_Error( 404, __( 'Sorry, no such page.' ) );
  2638 
  2941 
  2639 		// Make sure the user is allowed to edit pages.
  2942 		// Make sure the user is allowed to edit pages.
  2640 		if ( !current_user_can('edit_page', $page_id) )
  2943 		if ( !current_user_can('edit_page', $page_id) )
  2641 			return new IXR_Error( 401, __( 'Sorry, you do not have the right to edit this page.' ) );
  2944 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this page.' ) );
  2642 
  2945 
  2643 		// Mark this as content for a page.
  2946 		// Mark this as content for a page.
  2644 		$content['post_type'] = 'page';
  2947 		$content['post_type'] = 'page';
  2645 
  2948 
  2646 		// Arrange args in the way mw_editPost understands.
  2949 		// Arrange args in the way mw_editPost understands.
  2659 	/**
  2962 	/**
  2660 	 * Retrieve page list.
  2963 	 * Retrieve page list.
  2661 	 *
  2964 	 *
  2662 	 * @since 2.2.0
  2965 	 * @since 2.2.0
  2663 	 *
  2966 	 *
  2664 	 * @param array $args Method parameters.
  2967 	 * @global wpdb $wpdb WordPress database abstraction object.
       
  2968 	 *
       
  2969 	 * @param array  $args {
       
  2970 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  2971 	 *
       
  2972 	 *     @type int    $blog_id (unused)
       
  2973 	 *     @type string $username
       
  2974 	 *     @type string $password
       
  2975 	 * }
  2665 	 * @return array|IXR_Error
  2976 	 * @return array|IXR_Error
  2666 	 */
  2977 	 */
  2667 	public function wp_getPageList($args) {
  2978 	public function wp_getPageList( $args ) {
  2668 		global $wpdb;
  2979 		global $wpdb;
  2669 
  2980 
  2670 		$this->escape($args);
  2981 		$this->escape( $args );
  2671 
  2982 
  2672 		$username				= $args[1];
  2983 		$username = $args[1];
  2673 		$password				= $args[2];
  2984 		$password = $args[2];
  2674 
  2985 
  2675 		if ( !$user = $this->login($username, $password) )
  2986 		if ( !$user = $this->login($username, $password) )
  2676 			return $this->error;
  2987 			return $this->error;
  2677 
  2988 
  2678 		if ( !current_user_can( 'edit_pages' ) )
  2989 		if ( !current_user_can( 'edit_pages' ) )
  2679 			return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) );
  2990 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit pages.' ) );
  2680 
  2991 
  2681 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2992 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2682 		do_action( 'xmlrpc_call', 'wp.getPageList' );
  2993 		do_action( 'xmlrpc_call', 'wp.getPageList' );
  2683 
  2994 
  2684 		// Get list of pages ids and titles
  2995 		// Get list of pages ids and titles
  2711 	/**
  3022 	/**
  2712 	 * Retrieve authors list.
  3023 	 * Retrieve authors list.
  2713 	 *
  3024 	 *
  2714 	 * @since 2.2.0
  3025 	 * @since 2.2.0
  2715 	 *
  3026 	 *
  2716 	 * @param array $args Method parameters.
  3027 	 * @param array  $args {
       
  3028 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3029 	 *
       
  3030 	 *     @type int    $blog_id (unused)
       
  3031 	 *     @type string $username
       
  3032 	 *     @type string $password
       
  3033 	 * }
  2717 	 * @return array|IXR_Error
  3034 	 * @return array|IXR_Error
  2718 	 */
  3035 	 */
  2719 	public function wp_getAuthors($args) {
  3036 	public function wp_getAuthors( $args ) {
  2720 
  3037 		$this->escape( $args );
  2721 		$this->escape($args);
  3038 
  2722 
  3039 		$username = $args[1];
  2723 		$username	= $args[1];
  3040 		$password = $args[2];
  2724 		$password	= $args[2];
       
  2725 
  3041 
  2726 		if ( !$user = $this->login($username, $password) )
  3042 		if ( !$user = $this->login($username, $password) )
  2727 			return $this->error;
  3043 			return $this->error;
  2728 
  3044 
  2729 		if ( !current_user_can('edit_posts') )
  3045 		if ( !current_user_can('edit_posts') )
  2730 			return new IXR_Error( 401, __( 'Sorry, you cannot edit posts on this site.' ) );
  3046 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit posts.' ) );
  2731 
  3047 
  2732 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3048 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2733 		do_action( 'xmlrpc_call', 'wp.getAuthors' );
  3049 		do_action( 'xmlrpc_call', 'wp.getAuthors' );
  2734 
  3050 
  2735 		$authors = array();
  3051 		$authors = array();
  2747 	/**
  3063 	/**
  2748 	 * Get list of all tags
  3064 	 * Get list of all tags
  2749 	 *
  3065 	 *
  2750 	 * @since 2.7.0
  3066 	 * @since 2.7.0
  2751 	 *
  3067 	 *
  2752 	 * @param array $args Method parameters.
  3068 	 * @param array  $args {
       
  3069 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3070 	 *
       
  3071 	 *     @type int    $blog_id (unused)
       
  3072 	 *     @type string $username
       
  3073 	 *     @type string $password
       
  3074 	 * }
  2753 	 * @return array|IXR_Error
  3075 	 * @return array|IXR_Error
  2754 	 */
  3076 	 */
  2755 	public function wp_getTags( $args ) {
  3077 	public function wp_getTags( $args ) {
  2756 		$this->escape( $args );
  3078 		$this->escape( $args );
  2757 
  3079 
  2758 		$username		= $args[1];
  3080 		$username = $args[1];
  2759 		$password		= $args[2];
  3081 		$password = $args[2];
  2760 
  3082 
  2761 		if ( !$user = $this->login($username, $password) )
  3083 		if ( !$user = $this->login($username, $password) )
  2762 			return $this->error;
  3084 			return $this->error;
  2763 
  3085 
  2764 		if ( !current_user_can( 'edit_posts' ) )
  3086 		if ( !current_user_can( 'edit_posts' ) )
  2768 		do_action( 'xmlrpc_call', 'wp.getKeywords' );
  3090 		do_action( 'xmlrpc_call', 'wp.getKeywords' );
  2769 
  3091 
  2770 		$tags = array();
  3092 		$tags = array();
  2771 
  3093 
  2772 		if ( $all_tags = get_tags() ) {
  3094 		if ( $all_tags = get_tags() ) {
  2773 			foreach( (array) $all_tags as $tag ) {
  3095 			foreach ( (array) $all_tags as $tag ) {
  2774 				$struct = array();
  3096 				$struct = array();
  2775 				$struct['tag_id']			= $tag->term_id;
  3097 				$struct['tag_id']			= $tag->term_id;
  2776 				$struct['name']				= $tag->name;
  3098 				$struct['name']				= $tag->name;
  2777 				$struct['count']			= $tag->count;
  3099 				$struct['count']			= $tag->count;
  2778 				$struct['slug']				= $tag->slug;
  3100 				$struct['slug']				= $tag->slug;
  2789 	/**
  3111 	/**
  2790 	 * Create new category.
  3112 	 * Create new category.
  2791 	 *
  3113 	 *
  2792 	 * @since 2.2.0
  3114 	 * @since 2.2.0
  2793 	 *
  3115 	 *
  2794 	 * @param array $args Method parameters.
  3116 	 * @param array  $args {
       
  3117 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3118 	 *
       
  3119 	 *     @type int    $blog_id (unused)
       
  3120 	 *     @type string $username
       
  3121 	 *     @type string $password
       
  3122 	 *     @type array  $category
       
  3123 	 * }
  2795 	 * @return int|IXR_Error Category ID.
  3124 	 * @return int|IXR_Error Category ID.
  2796 	 */
  3125 	 */
  2797 	public function wp_newCategory($args) {
  3126 	public function wp_newCategory( $args ) {
  2798 		$this->escape($args);
  3127 		$this->escape( $args );
  2799 
  3128 
  2800 		$username				= $args[1];
  3129 		$username = $args[1];
  2801 		$password				= $args[2];
  3130 		$password = $args[2];
  2802 		$category				= $args[3];
  3131 		$category = $args[3];
  2803 
  3132 
  2804 		if ( !$user = $this->login($username, $password) )
  3133 		if ( !$user = $this->login($username, $password) )
  2805 			return $this->error;
  3134 			return $this->error;
  2806 
  3135 
  2807 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3136 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2808 		do_action( 'xmlrpc_call', 'wp.newCategory' );
  3137 		do_action( 'xmlrpc_call', 'wp.newCategory' );
  2809 
  3138 
  2810 		// Make sure the user is allowed to add a category.
  3139 		// Make sure the user is allowed to add a category.
  2811 		if ( !current_user_can('manage_categories') )
  3140 		if ( ! current_user_can( 'manage_categories' ) ) {
  2812 			return new IXR_Error(401, __('Sorry, you do not have the right to add a category.'));
  3141 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to add a category.' ) );
       
  3142 		}
  2813 
  3143 
  2814 		// If no slug was provided make it empty so that
  3144 		// If no slug was provided make it empty so that
  2815 		// WordPress will generate one.
  3145 		// WordPress will generate one.
  2816 		if ( empty($category['slug']) )
  3146 		if ( empty($category['slug']) )
  2817 			$category['slug'] = '';
  3147 			$category['slug'] = '';
  2858 	/**
  3188 	/**
  2859 	 * Remove category.
  3189 	 * Remove category.
  2860 	 *
  3190 	 *
  2861 	 * @since 2.5.0
  3191 	 * @since 2.5.0
  2862 	 *
  3192 	 *
  2863 	 * @param array $args Method parameters.
  3193 	 * @param array  $args {
  2864 	 * @return bool|IXR_Error See {@link wp_delete_term()} for return info.
  3194 	 *     Method arguments. Note: arguments must be ordered as documented.
  2865 	 */
  3195 	 *
  2866 	public function wp_deleteCategory($args) {
  3196 	 *     @type int    $blog_id (unused)
  2867 		$this->escape($args);
  3197 	 *     @type string $username
  2868 
  3198 	 *     @type string $password
  2869 		$username		= $args[1];
  3199 	 *     @type int    $category_id
  2870 		$password		= $args[2];
  3200 	 * }
  2871 		$category_id	= (int) $args[3];
  3201 	 * @return bool|IXR_Error See wp_delete_term() for return info.
       
  3202 	 */
       
  3203 	public function wp_deleteCategory( $args ) {
       
  3204 		$this->escape( $args );
       
  3205 
       
  3206 		$username    = $args[1];
       
  3207 		$password    = $args[2];
       
  3208 		$category_id = (int) $args[3];
  2872 
  3209 
  2873 		if ( !$user = $this->login($username, $password) )
  3210 		if ( !$user = $this->login($username, $password) )
  2874 			return $this->error;
  3211 			return $this->error;
  2875 
  3212 
  2876 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3213 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2877 		do_action( 'xmlrpc_call', 'wp.deleteCategory' );
  3214 		do_action( 'xmlrpc_call', 'wp.deleteCategory' );
  2878 
  3215 
  2879 		if ( !current_user_can('manage_categories') )
  3216 		if ( ! current_user_can( 'delete_term', $category_id ) ) {
  2880 			return new IXR_Error( 401, __( 'Sorry, you do not have the right to delete a category.' ) );
  3217 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to delete this category.' ) );
       
  3218 		}
  2881 
  3219 
  2882 		$status = wp_delete_term( $category_id, 'category' );
  3220 		$status = wp_delete_term( $category_id, 'category' );
  2883 
  3221 
  2884 		if ( true == $status ) {
  3222 		if ( true == $status ) {
  2885 			/**
  3223 			/**
  2899 	/**
  3237 	/**
  2900 	 * Retrieve category list.
  3238 	 * Retrieve category list.
  2901 	 *
  3239 	 *
  2902 	 * @since 2.2.0
  3240 	 * @since 2.2.0
  2903 	 *
  3241 	 *
  2904 	 * @param array $args Method parameters.
  3242 	 * @param array  $args {
       
  3243 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3244 	 *
       
  3245 	 *     @type int    $blog_id (unused)
       
  3246 	 *     @type string $username
       
  3247 	 *     @type string $password
       
  3248 	 *     @type array  $category
       
  3249 	 *     @type int    $max_results
       
  3250 	 * }
  2905 	 * @return array|IXR_Error
  3251 	 * @return array|IXR_Error
  2906 	 */
  3252 	 */
  2907 	public function wp_suggestCategories($args) {
  3253 	public function wp_suggestCategories( $args ) {
  2908 		$this->escape($args);
  3254 		$this->escape( $args );
  2909 
  3255 
  2910 		$username				= $args[1];
  3256 		$username    = $args[1];
  2911 		$password				= $args[2];
  3257 		$password    = $args[2];
  2912 		$category				= $args[3];
  3258 		$category    = $args[3];
  2913 		$max_results			= (int) $args[4];
  3259 		$max_results = (int) $args[4];
  2914 
  3260 
  2915 		if ( !$user = $this->login($username, $password) )
  3261 		if ( !$user = $this->login($username, $password) )
  2916 			return $this->error;
  3262 			return $this->error;
  2917 
  3263 
  2918 		if ( !current_user_can( 'edit_posts' ) )
  3264 		if ( !current_user_can( 'edit_posts' ) )
  2936 	/**
  3282 	/**
  2937 	 * Retrieve comment.
  3283 	 * Retrieve comment.
  2938 	 *
  3284 	 *
  2939 	 * @since 2.7.0
  3285 	 * @since 2.7.0
  2940 	 *
  3286 	 *
  2941 	 * @param array $args Method parameters.
  3287 	 * @param array  $args {
       
  3288 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3289 	 *
       
  3290 	 *     @type int    $blog_id (unused)
       
  3291 	 *     @type string $username
       
  3292 	 *     @type string $password
       
  3293 	 *     @type int    $comment_id
       
  3294 	 * }
  2942 	 * @return array|IXR_Error
  3295 	 * @return array|IXR_Error
  2943 	 */
  3296 	 */
  2944 	public function wp_getComment($args) {
  3297 	public function wp_getComment($args) {
  2945 		$this->escape($args);
  3298 		$this->escape($args);
  2946 
  3299 
  2947 		$username	= $args[1];
  3300 		$username	= $args[1];
  2948 		$password	= $args[2];
  3301 		$password	= $args[2];
  2949 		$comment_id	= (int) $args[3];
  3302 		$comment_id	= (int) $args[3];
  2950 
  3303 
  2951 		if ( !$user = $this->login($username, $password) )
  3304 		if ( ! $user = $this->login( $username, $password ) ) {
  2952 			return $this->error;
  3305 			return $this->error;
  2953 
  3306 		}
  2954 		if ( !current_user_can( 'moderate_comments' ) )
       
  2955 			return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) );
       
  2956 
  3307 
  2957 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3308 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2958 		do_action( 'xmlrpc_call', 'wp.getComment' );
  3309 		do_action( 'xmlrpc_call', 'wp.getComment' );
  2959 
  3310 
  2960 		if ( ! $comment = get_comment($comment_id) )
  3311 		if ( ! $comment = get_comment( $comment_id ) ) {
  2961 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
  3312 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
       
  3313 		}
       
  3314 
       
  3315 		if ( ! current_user_can( 'edit_comment', $comment_id ) ) {
       
  3316 			return new IXR_Error( 403, __( 'Sorry, you are not allowed to moderate or edit this comment.' ) );
       
  3317 		}
  2962 
  3318 
  2963 		return $this->_prepare_comment( $comment );
  3319 		return $this->_prepare_comment( $comment );
  2964 	}
  3320 	}
  2965 
  3321 
  2966 	/**
  3322 	/**
  2973 	 *
  3329 	 *
  2974 	 * The defaults are as follows:
  3330 	 * The defaults are as follows:
  2975 	 * - 'status' - Default is ''. Filter by status (e.g., 'approve', 'hold')
  3331 	 * - 'status' - Default is ''. Filter by status (e.g., 'approve', 'hold')
  2976 	 * - 'post_id' - Default is ''. The post where the comment is posted. Empty string shows all comments.
  3332 	 * - 'post_id' - Default is ''. The post where the comment is posted. Empty string shows all comments.
  2977 	 * - 'number' - Default is 10. Total number of media items to retrieve.
  3333 	 * - 'number' - Default is 10. Total number of media items to retrieve.
  2978 	 * - 'offset' - Default is 0. See {@link WP_Query::query()} for more.
  3334 	 * - 'offset' - Default is 0. See WP_Query::query() for more.
  2979 	 *
  3335 	 *
  2980 	 * @since 2.7.0
  3336 	 * @since 2.7.0
  2981 	 *
  3337 	 *
  2982 	 * @param array $args Method parameters.
  3338 	 * @param array  $args {
  2983 	 * @return array|IXR_Error Contains a collection of comments. See {@link wp_xmlrpc_server::wp_getComment()} for a description of each item contents
  3339 	 *     Method arguments. Note: arguments must be ordered as documented.
  2984 	 */
  3340 	 *
  2985 	public function wp_getComments($args) {
  3341 	 *     @type int    $blog_id (unused)
  2986 		$this->escape($args);
  3342 	 *     @type string $username
  2987 
  3343 	 *     @type string $password
  2988 		$username	= $args[1];
  3344 	 *     @type array  $struct
  2989 		$password	= $args[2];
  3345 	 * }
  2990 		$struct		= isset( $args[3] ) ? $args[3] : array();
  3346 	 * @return array|IXR_Error Contains a collection of comments. See wp_xmlrpc_server::wp_getComment() for a description of each item contents
  2991 
  3347 	 */
  2992 		if ( !$user = $this->login($username, $password) )
  3348 	public function wp_getComments( $args ) {
  2993 			return $this->error;
  3349 		$this->escape( $args );
  2994 
  3350 
  2995 		if ( !current_user_can( 'moderate_comments' ) )
  3351 		$username = $args[1];
  2996 			return new IXR_Error( 401, __( 'Sorry, you cannot edit comments.' ) );
  3352 		$password = $args[2];
       
  3353 		$struct	  = isset( $args[3] ) ? $args[3] : array();
       
  3354 
       
  3355 		if ( ! $user = $this->login( $username, $password ) ) {
       
  3356 			return $this->error;
       
  3357 		}
  2997 
  3358 
  2998 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3359 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  2999 		do_action( 'xmlrpc_call', 'wp.getComments' );
  3360 		do_action( 'xmlrpc_call', 'wp.getComments' );
  3000 
  3361 
  3001 		if ( isset($struct['status']) )
  3362 		if ( isset( $struct['status'] ) ) {
  3002 			$status = $struct['status'];
  3363 			$status = $struct['status'];
  3003 		else
  3364 		} else {
  3004 			$status = '';
  3365 			$status = '';
       
  3366 		}
       
  3367 
       
  3368 		if ( ! current_user_can( 'moderate_comments' ) && 'approve' !== $status ) {
       
  3369 			return new IXR_Error( 401, __( 'Invalid comment status.' ) );
       
  3370 		}
  3005 
  3371 
  3006 		$post_id = '';
  3372 		$post_id = '';
  3007 		if ( isset($struct['post_id']) )
  3373 		if ( isset( $struct['post_id'] ) ) {
  3008 			$post_id = absint($struct['post_id']);
  3374 			$post_id = absint( $struct['post_id'] );
       
  3375 		}
       
  3376 
       
  3377 		$post_type = '';
       
  3378 		if ( isset( $struct['post_type'] ) ) {
       
  3379 			$post_type_object = get_post_type_object( $struct['post_type'] );
       
  3380 			if ( ! $post_type_object || ! post_type_supports( $post_type_object->name, 'comments' ) ) {
       
  3381 				return new IXR_Error( 404, __( 'Invalid post type.' ) );
       
  3382 			}
       
  3383 			$post_type = $struct['post_type'];
       
  3384 		}
  3009 
  3385 
  3010 		$offset = 0;
  3386 		$offset = 0;
  3011 		if ( isset($struct['offset']) )
  3387 		if ( isset( $struct['offset'] ) ) {
  3012 			$offset = absint($struct['offset']);
  3388 			$offset = absint( $struct['offset'] );
       
  3389 		}
  3013 
  3390 
  3014 		$number = 10;
  3391 		$number = 10;
  3015 		if ( isset($struct['number']) )
  3392 		if ( isset( $struct['number'] ) ) {
  3016 			$number = absint($struct['number']);
  3393 			$number = absint( $struct['number'] );
  3017 
  3394 		}
  3018 		$comments = get_comments( array('status' => $status, 'post_id' => $post_id, 'offset' => $offset, 'number' => $number ) );
  3395 
       
  3396 		$comments = get_comments( array(
       
  3397 			'status' => $status,
       
  3398 			'post_id' => $post_id,
       
  3399 			'offset' => $offset,
       
  3400 			'number' => $number,
       
  3401 			'post_type' => $post_type,
       
  3402 		) );
  3019 
  3403 
  3020 		$comments_struct = array();
  3404 		$comments_struct = array();
  3021 
  3405 		if ( is_array( $comments ) ) {
  3022 		foreach ( $comments as $comment ) {
  3406 			foreach ( $comments as $comment ) {
  3023 			$comments_struct[] = $this->_prepare_comment( $comment );
  3407 				$comments_struct[] = $this->_prepare_comment( $comment );
       
  3408 			}
  3024 		}
  3409 		}
  3025 
  3410 
  3026 		return $comments_struct;
  3411 		return $comments_struct;
  3027 	}
  3412 	}
  3028 
  3413 
  3029 	/**
  3414 	/**
  3030 	 * Delete a comment.
  3415 	 * Delete a comment.
  3031 	 *
  3416 	 *
  3032 	 * By default, the comment will be moved to the trash instead of deleted.
  3417 	 * By default, the comment will be moved to the trash instead of deleted.
  3033 	 * See {@link wp_delete_comment()} for more information on
  3418 	 * See wp_delete_comment() for more information on this behavior.
  3034 	 * this behavior.
       
  3035 	 *
  3419 	 *
  3036 	 * @since 2.7.0
  3420 	 * @since 2.7.0
  3037 	 *
  3421 	 *
  3038 	 * @param array $args Method parameters. Contains:
  3422 	 * @param array  $args {
  3039 	 *  - blog_id (unused)
  3423 	 *     Method arguments. Note: arguments must be ordered as documented.
  3040 	 *  - username
  3424 	 *
  3041 	 *  - password
  3425 	 *     @type int    $blog_id (unused)
  3042 	 *  - comment_id
  3426 	 *     @type string $username
  3043 	 * @return bool|IXR_Error {@link wp_delete_comment()}
  3427 	 *     @type string $password
  3044 	 */
  3428 	 *     @type int    $comment_ID
  3045 	public function wp_deleteComment($args) {
  3429 	 * }
       
  3430 	 * @return bool|IXR_Error See wp_delete_comment().
       
  3431 	 */
       
  3432 	public function wp_deleteComment( $args ) {
  3046 		$this->escape($args);
  3433 		$this->escape($args);
  3047 
  3434 
  3048 		$username	= $args[1];
  3435 		$username	= $args[1];
  3049 		$password	= $args[2];
  3436 		$password	= $args[2];
  3050 		$comment_ID	= (int) $args[3];
  3437 		$comment_ID	= (int) $args[3];
  3051 
  3438 
  3052 		if ( !$user = $this->login($username, $password) )
  3439 		if ( ! $user = $this->login( $username, $password ) ) {
  3053 			return $this->error;
  3440 			return $this->error;
  3054 
  3441 		}
  3055 		if ( !current_user_can( 'moderate_comments' ) )
  3442 
  3056 			return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) );
  3443 		if ( ! get_comment( $comment_ID ) ) {
  3057 
       
  3058 		if ( ! get_comment($comment_ID) )
       
  3059 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
  3444 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
  3060 
  3445 		}
  3061 		if ( !current_user_can( 'edit_comment', $comment_ID ) )
  3446 
  3062 			return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) );
  3447 		if ( ! current_user_can( 'edit_comment', $comment_ID ) ) {
       
  3448 			return new IXR_Error( 403, __( 'Sorry, you are not allowed to delete this comment.' ) );
       
  3449 		}
  3063 
  3450 
  3064 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3451 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3065 		do_action( 'xmlrpc_call', 'wp.deleteComment' );
  3452 		do_action( 'xmlrpc_call', 'wp.deleteComment' );
  3066 
  3453 
  3067 		$status = wp_delete_comment( $comment_ID );
  3454 		$status = wp_delete_comment( $comment_ID );
  3068 
  3455 
  3069 		if ( true == $status ) {
  3456 		if ( $status ) {
  3070 			/**
  3457 			/**
  3071 			 * Fires after a comment has been successfully deleted via XML-RPC.
  3458 			 * Fires after a comment has been successfully deleted via XML-RPC.
  3072 			 *
  3459 			 *
  3073 			 * @since 3.4.0
  3460 			 * @since 3.4.0
  3074 			 *
  3461 			 *
  3091 	 *  - 'author'
  3478 	 *  - 'author'
  3092 	 *  - 'author_url'
  3479 	 *  - 'author_url'
  3093 	 *  - 'author_email'
  3480 	 *  - 'author_email'
  3094 	 *  - 'content'
  3481 	 *  - 'content'
  3095 	 *  - 'date_created_gmt'
  3482 	 *  - 'date_created_gmt'
  3096 	 *  - 'status'. Common statuses are 'approve', 'hold', 'spam'. See {@link get_comment_statuses()} for more details
  3483 	 *  - 'status'. Common statuses are 'approve', 'hold', 'spam'. See get_comment_statuses() for more details
  3097 	 *
  3484 	 *
  3098 	 * @since 2.7.0
  3485 	 * @since 2.7.0
  3099 	 *
  3486 	 *
  3100 	 * @param array $args Contains:
  3487 	 * @param array  $args {
  3101 	 *  - blog_id (unused)
  3488 	 *     Method arguments. Note: arguments must be ordered as documented.
  3102 	 *  - username
  3489 	 *
  3103 	 *  - password
  3490 	 *     @type int    $blog_id (unused)
  3104 	 *  - comment_id
  3491 	 *     @type string $username
  3105 	 *  - content_struct
  3492 	 *     @type string $password
  3106 	 * @return bool|IXR_Error True, on success.
  3493 	 *     @type int    $comment_ID
  3107 	 */
  3494 	 *     @type array  $content_struct
  3108 	public function wp_editComment($args) {
  3495 	 * }
  3109 		$this->escape($args);
  3496 	 * @return true|IXR_Error True, on success.
       
  3497 	 */
       
  3498 	public function wp_editComment( $args ) {
       
  3499 		$this->escape( $args );
  3110 
  3500 
  3111 		$username	= $args[1];
  3501 		$username	= $args[1];
  3112 		$password	= $args[2];
  3502 		$password	= $args[2];
  3113 		$comment_ID	= (int) $args[3];
  3503 		$comment_ID	= (int) $args[3];
  3114 		$content_struct = $args[4];
  3504 		$content_struct = $args[4];
  3115 
  3505 
  3116 		if ( !$user = $this->login($username, $password) )
  3506 		if ( !$user = $this->login( $username, $password ) ) {
  3117 			return $this->error;
  3507 			return $this->error;
  3118 
  3508 		}
  3119 		if ( !current_user_can( 'moderate_comments' ) )
  3509 
  3120 			return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) );
  3510 		if ( ! get_comment( $comment_ID ) ) {
  3121 
       
  3122 		if ( ! get_comment($comment_ID) )
       
  3123 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
  3511 			return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
  3124 
  3512 		}
  3125 		if ( !current_user_can( 'edit_comment', $comment_ID ) )
  3513 
  3126 			return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) );
  3514 		if ( ! current_user_can( 'edit_comment', $comment_ID ) ) {
       
  3515 			return new IXR_Error( 403, __( 'Sorry, you are not allowed to moderate or edit this comment.' ) );
       
  3516 		}
  3127 
  3517 
  3128 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3518 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3129 		do_action( 'xmlrpc_call', 'wp.editComment' );
  3519 		do_action( 'xmlrpc_call', 'wp.editComment' );
  3130 
  3520 
  3131 		if ( isset($content_struct['status']) ) {
  3521 		if ( isset($content_struct['status']) ) {
  3163 		$result = wp_update_comment($comment);
  3553 		$result = wp_update_comment($comment);
  3164 		if ( is_wp_error( $result ) )
  3554 		if ( is_wp_error( $result ) )
  3165 			return new IXR_Error(500, $result->get_error_message());
  3555 			return new IXR_Error(500, $result->get_error_message());
  3166 
  3556 
  3167 		if ( !$result )
  3557 		if ( !$result )
  3168 			return new IXR_Error(500, __('Sorry, the comment could not be edited. Something wrong happened.'));
  3558 			return new IXR_Error(500, __('Sorry, the comment could not be edited.'));
  3169 
  3559 
  3170 		/**
  3560 		/**
  3171 		 * Fires after a comment has been successfully updated via XML-RPC.
  3561 		 * Fires after a comment has been successfully updated via XML-RPC.
  3172 		 *
  3562 		 *
  3173 		 * @since 3.4.0
  3563 		 * @since 3.4.0
  3183 	/**
  3573 	/**
  3184 	 * Create new comment.
  3574 	 * Create new comment.
  3185 	 *
  3575 	 *
  3186 	 * @since 2.7.0
  3576 	 * @since 2.7.0
  3187 	 *
  3577 	 *
  3188 	 * @param array $args Method parameters.
  3578 	 * @param array  $args {
  3189 	 * @return int|IXR_Error {@link wp_new_comment()}
  3579 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3580 	 *
       
  3581 	 *     @type int        $blog_id (unused)
       
  3582 	 *     @type string     $username
       
  3583 	 *     @type string     $password
       
  3584 	 *     @type string|int $post
       
  3585 	 *     @type array      $content_struct
       
  3586 	 * }
       
  3587 	 * @return int|IXR_Error See wp_new_comment().
  3190 	 */
  3588 	 */
  3191 	public function wp_newComment($args) {
  3589 	public function wp_newComment($args) {
  3192 		$this->escape($args);
  3590 		$this->escape($args);
  3193 
  3591 
  3194 		$username	= $args[1];
  3592 		$username       = $args[1];
  3195 		$password	= $args[2];
  3593 		$password       = $args[2];
  3196 		$post		= $args[3];
  3594 		$post           = $args[3];
  3197 		$content_struct = $args[4];
  3595 		$content_struct = $args[4];
  3198 
  3596 
  3199 		/**
  3597 		/**
  3200 		 * Filter whether to allow anonymous comments over XML-RPC.
  3598 		 * Filters whether to allow anonymous comments over XML-RPC.
  3201 		 *
  3599 		 *
  3202 		 * @since 2.7.0
  3600 		 * @since 2.7.0
  3203 		 *
  3601 		 *
  3204 		 * @param bool $allow Whether to allow anonymous commenting via XML-RPC.
  3602 		 * @param bool $allow Whether to allow anonymous commenting via XML-RPC.
  3205 		 *                    Default false.
  3603 		 *                    Default false.
  3209 		$user = $this->login($username, $password);
  3607 		$user = $this->login($username, $password);
  3210 
  3608 
  3211 		if ( !$user ) {
  3609 		if ( !$user ) {
  3212 			$logged_in = false;
  3610 			$logged_in = false;
  3213 			if ( $allow_anon && get_option('comment_registration') ) {
  3611 			if ( $allow_anon && get_option('comment_registration') ) {
  3214 				return new IXR_Error( 403, __( 'You must be registered to comment' ) );
  3612 				return new IXR_Error( 403, __( 'You must be registered to comment.' ) );
  3215 			} elseif ( ! $allow_anon ) {
  3613 			} elseif ( ! $allow_anon ) {
  3216 				return $this->error;
  3614 				return $this->error;
  3217 			}
  3615 			}
  3218 		} else {
  3616 		} else {
  3219 			$logged_in = true;
  3617 			$logged_in = true;
  3222 		if ( is_numeric($post) )
  3620 		if ( is_numeric($post) )
  3223 			$post_id = absint($post);
  3621 			$post_id = absint($post);
  3224 		else
  3622 		else
  3225 			$post_id = url_to_postid($post);
  3623 			$post_id = url_to_postid($post);
  3226 
  3624 
  3227 		if ( ! $post_id )
  3625 		if ( ! $post_id ) {
  3228 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  3626 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  3229 
  3627 		}
  3230 		if ( ! get_post($post_id) )
  3628 
       
  3629 		if ( ! get_post( $post_id ) ) {
  3231 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  3630 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  3232 
  3631 		}
  3233 		$comment = array();
  3632 
  3234 		$comment['comment_post_ID'] = $post_id;
  3633 		if ( ! comments_open( $post_id ) ) {
       
  3634 			return new IXR_Error( 403, __( 'Sorry, comments are closed for this item.' ) );
       
  3635 		}
       
  3636 
       
  3637 		if ( empty( $content_struct['content'] ) ) {
       
  3638 			return new IXR_Error( 403, __( 'Comment is required.' ) );
       
  3639 		}
       
  3640 
       
  3641 		$comment = array(
       
  3642 			'comment_post_ID' => $post_id,
       
  3643 			'comment_content' => $content_struct['content'],
       
  3644 		);
  3235 
  3645 
  3236 		if ( $logged_in ) {
  3646 		if ( $logged_in ) {
  3237 			$comment['comment_author'] = $this->escape( $user->display_name );
  3647 			$display_name = $user->display_name;
  3238 			$comment['comment_author_email'] = $this->escape( $user->user_email );
  3648 			$user_email = $user->user_email;
  3239 			$comment['comment_author_url'] = $this->escape( $user->user_url );
  3649 			$user_url = $user->user_url;
       
  3650 
       
  3651 			$comment['comment_author'] = $this->escape( $display_name );
       
  3652 			$comment['comment_author_email'] = $this->escape( $user_email );
       
  3653 			$comment['comment_author_url'] = $this->escape( $user_url );
  3240 			$comment['user_ID'] = $user->ID;
  3654 			$comment['user_ID'] = $user->ID;
  3241 		} else {
  3655 		} else {
  3242 			$comment['comment_author'] = '';
  3656 			$comment['comment_author'] = '';
  3243 			if ( isset($content_struct['author']) )
  3657 			if ( isset($content_struct['author']) )
  3244 				$comment['comment_author'] = $content_struct['author'];
  3658 				$comment['comment_author'] = $content_struct['author'];
  3253 
  3667 
  3254 			$comment['user_ID'] = 0;
  3668 			$comment['user_ID'] = 0;
  3255 
  3669 
  3256 			if ( get_option('require_name_email') ) {
  3670 			if ( get_option('require_name_email') ) {
  3257 				if ( 6 > strlen($comment['comment_author_email']) || '' == $comment['comment_author'] )
  3671 				if ( 6 > strlen($comment['comment_author_email']) || '' == $comment['comment_author'] )
  3258 					return new IXR_Error( 403, __( 'Comment author name and email are required' ) );
  3672 					return new IXR_Error( 403, __( 'Comment author name and email are required.' ) );
  3259 				elseif ( !is_email($comment['comment_author_email']) )
  3673 				elseif ( !is_email($comment['comment_author_email']) )
  3260 					return new IXR_Error( 403, __( 'A valid email address is required' ) );
  3674 					return new IXR_Error( 403, __( 'A valid email address is required.' ) );
  3261 			}
  3675 			}
  3262 		}
  3676 		}
  3263 
  3677 
  3264 		$comment['comment_parent'] = isset($content_struct['comment_parent']) ? absint($content_struct['comment_parent']) : 0;
  3678 		$comment['comment_parent'] = isset($content_struct['comment_parent']) ? absint($content_struct['comment_parent']) : 0;
  3265 
       
  3266 		$comment['comment_content'] =  isset($content_struct['content']) ? $content_struct['content'] : null;
       
  3267 
  3679 
  3268 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3680 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3269 		do_action( 'xmlrpc_call', 'wp.newComment' );
  3681 		do_action( 'xmlrpc_call', 'wp.newComment' );
  3270 
  3682 
  3271 		$comment_ID = wp_new_comment( $comment );
  3683 		$comment_ID = wp_new_comment( $comment, true );
       
  3684 		if ( is_wp_error( $comment_ID ) ) {
       
  3685 			return new IXR_Error( 403, $comment_ID->get_error_message() );
       
  3686 		}
       
  3687 
       
  3688 		if ( ! $comment_ID ) {
       
  3689 			return new IXR_Error( 403, __( 'Something went wrong.' ) );
       
  3690 		}
  3272 
  3691 
  3273 		/**
  3692 		/**
  3274 		 * Fires after a new comment has been successfully created via XML-RPC.
  3693 		 * Fires after a new comment has been successfully created via XML-RPC.
  3275 		 *
  3694 		 *
  3276 		 * @since 3.4.0
  3695 		 * @since 3.4.0
  3286 	/**
  3705 	/**
  3287 	 * Retrieve all of the comment status.
  3706 	 * Retrieve all of the comment status.
  3288 	 *
  3707 	 *
  3289 	 * @since 2.7.0
  3708 	 * @since 2.7.0
  3290 	 *
  3709 	 *
  3291 	 * @param array $args Method parameters.
  3710 	 * @param array  $args {
       
  3711 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3712 	 *
       
  3713 	 *     @type int    $blog_id (unused)
       
  3714 	 *     @type string $username
       
  3715 	 *     @type string $password
       
  3716 	 * }
  3292 	 * @return array|IXR_Error
  3717 	 * @return array|IXR_Error
  3293 	 */
  3718 	 */
  3294 	public function wp_getCommentStatusList($args) {
  3719 	public function wp_getCommentStatusList( $args ) {
  3295 		$this->escape( $args );
  3720 		$this->escape( $args );
  3296 
  3721 
  3297 		$username	= $args[1];
  3722 		$username = $args[1];
  3298 		$password	= $args[2];
  3723 		$password = $args[2];
  3299 
  3724 
  3300 		if ( !$user = $this->login($username, $password) )
  3725 		if ( ! $user = $this->login( $username, $password ) ) {
  3301 			return $this->error;
  3726 			return $this->error;
  3302 
  3727 		}
  3303 		if ( !current_user_can( 'moderate_comments' ) )
  3728 
  3304 			return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
  3729 		if ( ! current_user_can( 'publish_posts' ) ) {
       
  3730 			return new IXR_Error( 403, __( 'Sorry, you are not allowed access to details about this site.' ) );
       
  3731 		}
  3305 
  3732 
  3306 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3733 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3307 		do_action( 'xmlrpc_call', 'wp.getCommentStatusList' );
  3734 		do_action( 'xmlrpc_call', 'wp.getCommentStatusList' );
  3308 
  3735 
  3309 		return get_comment_statuses();
  3736 		return get_comment_statuses();
  3312 	/**
  3739 	/**
  3313 	 * Retrieve comment count.
  3740 	 * Retrieve comment count.
  3314 	 *
  3741 	 *
  3315 	 * @since 2.5.0
  3742 	 * @since 2.5.0
  3316 	 *
  3743 	 *
  3317 	 * @param array $args Method parameters.
  3744 	 * @param array  $args {
       
  3745 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3746 	 *
       
  3747 	 *     @type int    $blog_id (unused)
       
  3748 	 *     @type string $username
       
  3749 	 *     @type string $password
       
  3750 	 *     @type int    $post_id
       
  3751 	 * }
  3318 	 * @return array|IXR_Error
  3752 	 * @return array|IXR_Error
  3319 	 */
  3753 	 */
  3320 	public function wp_getCommentCount( $args ) {
  3754 	public function wp_getCommentCount( $args ) {
  3321 		$this->escape($args);
  3755 		$this->escape( $args );
  3322 
  3756 
  3323 		$username	= $args[1];
  3757 		$username	= $args[1];
  3324 		$password	= $args[2];
  3758 		$password	= $args[2];
  3325 		$post_id	= (int) $args[3];
  3759 		$post_id	= (int) $args[3];
  3326 
  3760 
  3327 		if ( !$user = $this->login($username, $password) )
  3761 		if ( ! $user = $this->login( $username, $password ) ) {
  3328 			return $this->error;
  3762 			return $this->error;
  3329 
  3763 		}
  3330 		if ( !current_user_can( 'edit_posts' ) )
  3764 
  3331 			return new IXR_Error( 403, __( 'You are not allowed access to details about comments.' ) );
  3765 		$post = get_post( $post_id, ARRAY_A );
       
  3766 		if ( empty( $post['ID'] ) ) {
       
  3767 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
       
  3768 		}
       
  3769 
       
  3770 		if ( ! current_user_can( 'edit_post', $post_id ) ) {
       
  3771 			return new IXR_Error( 403, __( 'Sorry, you are not allowed access to details of this post.' ) );
       
  3772 		}
  3332 
  3773 
  3333 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3774 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3334 		do_action( 'xmlrpc_call', 'wp.getCommentCount' );
  3775 		do_action( 'xmlrpc_call', 'wp.getCommentCount' );
  3335 
  3776 
  3336 		$count = wp_count_comments( $post_id );
  3777 		$count = wp_count_comments( $post_id );
       
  3778 
  3337 		return array(
  3779 		return array(
  3338 			'approved' => $count->approved,
  3780 			'approved' => $count->approved,
  3339 			'awaiting_moderation' => $count->moderated,
  3781 			'awaiting_moderation' => $count->moderated,
  3340 			'spam' => $count->spam,
  3782 			'spam' => $count->spam,
  3341 			'total_comments' => $count->total_comments
  3783 			'total_comments' => $count->total_comments
  3345 	/**
  3787 	/**
  3346 	 * Retrieve post statuses.
  3788 	 * Retrieve post statuses.
  3347 	 *
  3789 	 *
  3348 	 * @since 2.5.0
  3790 	 * @since 2.5.0
  3349 	 *
  3791 	 *
  3350 	 * @param array $args Method parameters.
  3792 	 * @param array  $args {
       
  3793 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3794 	 *
       
  3795 	 *     @type int    $blog_id (unused)
       
  3796 	 *     @type string $username
       
  3797 	 *     @type string $password
       
  3798 	 * }
  3351 	 * @return array|IXR_Error
  3799 	 * @return array|IXR_Error
  3352 	 */
  3800 	 */
  3353 	public function wp_getPostStatusList( $args ) {
  3801 	public function wp_getPostStatusList( $args ) {
  3354 		$this->escape( $args );
  3802 		$this->escape( $args );
  3355 
  3803 
  3356 		$username	= $args[1];
  3804 		$username = $args[1];
  3357 		$password	= $args[2];
  3805 		$password = $args[2];
  3358 
  3806 
  3359 		if ( !$user = $this->login($username, $password) )
  3807 		if ( !$user = $this->login($username, $password) )
  3360 			return $this->error;
  3808 			return $this->error;
  3361 
  3809 
  3362 		if ( !current_user_can( 'edit_posts' ) )
  3810 		if ( !current_user_can( 'edit_posts' ) )
  3363 			return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
  3811 			return new IXR_Error( 403, __( 'Sorry, you are not allowed access to details about this site.' ) );
  3364 
  3812 
  3365 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3813 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3366 		do_action( 'xmlrpc_call', 'wp.getPostStatusList' );
  3814 		do_action( 'xmlrpc_call', 'wp.getPostStatusList' );
  3367 
  3815 
  3368 		return get_post_statuses();
  3816 		return get_post_statuses();
  3371 	/**
  3819 	/**
  3372 	 * Retrieve page statuses.
  3820 	 * Retrieve page statuses.
  3373 	 *
  3821 	 *
  3374 	 * @since 2.5.0
  3822 	 * @since 2.5.0
  3375 	 *
  3823 	 *
  3376 	 * @param array $args Method parameters.
  3824 	 * @param array  $args {
       
  3825 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3826 	 *
       
  3827 	 *     @type int    $blog_id (unused)
       
  3828 	 *     @type string $username
       
  3829 	 *     @type string $password
       
  3830 	 * }
  3377 	 * @return array|IXR_Error
  3831 	 * @return array|IXR_Error
  3378 	 */
  3832 	 */
  3379 	public function wp_getPageStatusList( $args ) {
  3833 	public function wp_getPageStatusList( $args ) {
  3380 		$this->escape( $args );
  3834 		$this->escape( $args );
  3381 
  3835 
  3382 		$username	= $args[1];
  3836 		$username = $args[1];
  3383 		$password	= $args[2];
  3837 		$password = $args[2];
  3384 
  3838 
  3385 		if ( !$user = $this->login($username, $password) )
  3839 		if ( !$user = $this->login($username, $password) )
  3386 			return $this->error;
  3840 			return $this->error;
  3387 
  3841 
  3388 		if ( !current_user_can( 'edit_pages' ) )
  3842 		if ( !current_user_can( 'edit_pages' ) )
  3389 			return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
  3843 			return new IXR_Error( 403, __( 'Sorry, you are not allowed access to details about this site.' ) );
  3390 
  3844 
  3391 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3845 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3392 		do_action( 'xmlrpc_call', 'wp.getPageStatusList' );
  3846 		do_action( 'xmlrpc_call', 'wp.getPageStatusList' );
  3393 
  3847 
  3394 		return get_page_statuses();
  3848 		return get_page_statuses();
  3397 	/**
  3851 	/**
  3398 	 * Retrieve page templates.
  3852 	 * Retrieve page templates.
  3399 	 *
  3853 	 *
  3400 	 * @since 2.6.0
  3854 	 * @since 2.6.0
  3401 	 *
  3855 	 *
  3402 	 * @param array $args Method parameters.
  3856 	 * @param array  $args {
       
  3857 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3858 	 *
       
  3859 	 *     @type int    $blog_id (unused)
       
  3860 	 *     @type string $username
       
  3861 	 *     @type string $password
       
  3862 	 * }
  3403 	 * @return array|IXR_Error
  3863 	 * @return array|IXR_Error
  3404 	 */
  3864 	 */
  3405 	public function wp_getPageTemplates( $args ) {
  3865 	public function wp_getPageTemplates( $args ) {
  3406 		$this->escape( $args );
  3866 		$this->escape( $args );
  3407 
  3867 
  3408 		$username	= $args[1];
  3868 		$username = $args[1];
  3409 		$password	= $args[2];
  3869 		$password = $args[2];
  3410 
  3870 
  3411 		if ( !$user = $this->login($username, $password) )
  3871 		if ( !$user = $this->login($username, $password) )
  3412 			return $this->error;
  3872 			return $this->error;
  3413 
  3873 
  3414 		if ( !current_user_can( 'edit_pages' ) )
  3874 		if ( !current_user_can( 'edit_pages' ) )
  3415 			return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
  3875 			return new IXR_Error( 403, __( 'Sorry, you are not allowed access to details about this site.' ) );
  3416 
  3876 
  3417 		$templates = get_page_templates();
  3877 		$templates = get_page_templates();
  3418 		$templates['Default'] = 'default';
  3878 		$templates['Default'] = 'default';
  3419 
  3879 
  3420 		return $templates;
  3880 		return $templates;
  3423 	/**
  3883 	/**
  3424 	 * Retrieve blog options.
  3884 	 * Retrieve blog options.
  3425 	 *
  3885 	 *
  3426 	 * @since 2.6.0
  3886 	 * @since 2.6.0
  3427 	 *
  3887 	 *
  3428 	 * @param array $args Method parameters.
  3888 	 * @param array  $args {
       
  3889 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3890 	 *
       
  3891 	 *     @type int    $blog_id (unused)
       
  3892 	 *     @type string $username
       
  3893 	 *     @type string $password
       
  3894 	 *     @type array  $options
       
  3895 	 * }
  3429 	 * @return array|IXR_Error
  3896 	 * @return array|IXR_Error
  3430 	 */
  3897 	 */
  3431 	public function wp_getOptions( $args ) {
  3898 	public function wp_getOptions( $args ) {
  3432 		$this->escape( $args );
  3899 		$this->escape( $args );
  3433 
  3900 
  3476 	/**
  3943 	/**
  3477 	 * Update blog options.
  3944 	 * Update blog options.
  3478 	 *
  3945 	 *
  3479 	 * @since 2.6.0
  3946 	 * @since 2.6.0
  3480 	 *
  3947 	 *
  3481 	 * @param array $args Method parameters.
  3948 	 * @param array  $args {
       
  3949 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  3950 	 *
       
  3951 	 *     @type int    $blog_id (unused)
       
  3952 	 *     @type string $username
       
  3953 	 *     @type string $password
       
  3954 	 *     @type array  $options
       
  3955 	 * }
  3482 	 * @return array|IXR_Error
  3956 	 * @return array|IXR_Error
  3483 	 */
  3957 	 */
  3484 	public function wp_setOptions( $args ) {
  3958 	public function wp_setOptions( $args ) {
  3485 		$this->escape( $args );
  3959 		$this->escape( $args );
  3486 
  3960 
  3490 
  3964 
  3491 		if ( !$user = $this->login($username, $password) )
  3965 		if ( !$user = $this->login($username, $password) )
  3492 			return $this->error;
  3966 			return $this->error;
  3493 
  3967 
  3494 		if ( !current_user_can( 'manage_options' ) )
  3968 		if ( !current_user_can( 'manage_options' ) )
  3495 			return new IXR_Error( 403, __( 'You are not allowed to update options.' ) );
  3969 			return new IXR_Error( 403, __( 'Sorry, you are not allowed to update options.' ) );
  3496 
  3970 
  3497 		$option_names = array();
  3971 		$option_names = array();
  3498 		foreach ( $options as $o_name => $o_value ) {
  3972 		foreach ( $options as $o_name => $o_value ) {
  3499 			$option_names[] = $o_name;
  3973 			$option_names[] = $o_name;
  3500 			if ( !array_key_exists( $o_name, $this->blog_options ) )
  3974 			if ( !array_key_exists( $o_name, $this->blog_options ) )
  3513 	/**
  3987 	/**
  3514 	 * Retrieve a media item by ID
  3988 	 * Retrieve a media item by ID
  3515 	 *
  3989 	 *
  3516 	 * @since 3.1.0
  3990 	 * @since 3.1.0
  3517 	 *
  3991 	 *
  3518 	 * @param array $args Method parameters. Contains:
  3992 	 * @param array  $args {
  3519 	 *  - blog_id (unused)
  3993 	 *     Method arguments. Note: arguments must be ordered as documented.
  3520 	 *  - username
  3994 	 *
  3521 	 *  - password
  3995 	 *     @type int    $blog_id (unused)
  3522 	 *  - attachment_id
  3996 	 *     @type string $username
       
  3997 	 *     @type string $password
       
  3998 	 *     @type int    $attachment_id
       
  3999 	 * }
  3523 	 * @return array|IXR_Error Associative array contains:
  4000 	 * @return array|IXR_Error Associative array contains:
  3524 	 *  - 'date_created_gmt'
  4001 	 *  - 'date_created_gmt'
  3525 	 *  - 'parent'
  4002 	 *  - 'parent'
  3526 	 *  - 'link'
  4003 	 *  - 'link'
  3527 	 *  - 'thumbnail'
  4004 	 *  - 'thumbnail'
  3528 	 *  - 'title'
  4005 	 *  - 'title'
  3529 	 *  - 'caption'
  4006 	 *  - 'caption'
  3530 	 *  - 'description'
  4007 	 *  - 'description'
  3531 	 *  - 'metadata'
  4008 	 *  - 'metadata'
  3532 	 */
  4009 	 */
  3533 	public function wp_getMediaItem($args) {
  4010 	public function wp_getMediaItem( $args ) {
  3534 		$this->escape($args);
  4011 		$this->escape( $args );
  3535 
  4012 
  3536 		$username		= $args[1];
  4013 		$username		= $args[1];
  3537 		$password		= $args[2];
  4014 		$password		= $args[2];
  3538 		$attachment_id	= (int) $args[3];
  4015 		$attachment_id	= (int) $args[3];
  3539 
  4016 
  3540 		if ( !$user = $this->login($username, $password) )
  4017 		if ( !$user = $this->login($username, $password) )
  3541 			return $this->error;
  4018 			return $this->error;
  3542 
  4019 
  3543 		if ( !current_user_can( 'upload_files' ) )
  4020 		if ( !current_user_can( 'upload_files' ) )
  3544 			return new IXR_Error( 403, __( 'You do not have permission to upload files.' ) );
  4021 			return new IXR_Error( 403, __( 'Sorry, you are not allowed to upload files.' ) );
  3545 
  4022 
  3546 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4023 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3547 		do_action( 'xmlrpc_call', 'wp.getMediaItem' );
  4024 		do_action( 'xmlrpc_call', 'wp.getMediaItem' );
  3548 
  4025 
  3549 		if ( ! $attachment = get_post($attachment_id) )
  4026 		if ( ! $attachment = get_post($attachment_id) )
  3560 	 *
  4037 	 *
  3561 	 * Accepted 'filter' keys are 'parent_id', 'mime_type', 'offset', and 'number'.
  4038 	 * Accepted 'filter' keys are 'parent_id', 'mime_type', 'offset', and 'number'.
  3562 	 *
  4039 	 *
  3563 	 * The defaults are as follows:
  4040 	 * The defaults are as follows:
  3564 	 * - 'number' - Default is 5. Total number of media items to retrieve.
  4041 	 * - 'number' - Default is 5. Total number of media items to retrieve.
  3565 	 * - 'offset' - Default is 0. See {@link WP_Query::query()} for more.
  4042 	 * - 'offset' - Default is 0. See WP_Query::query() for more.
  3566 	 * - 'parent_id' - Default is ''. The post where the media item is attached. Empty string shows all media items. 0 shows unattached media items.
  4043 	 * - 'parent_id' - Default is ''. The post where the media item is attached. Empty string shows all media items. 0 shows unattached media items.
  3567 	 * - 'mime_type' - Default is ''. Filter by mime type (e.g., 'image/jpeg', 'application/pdf')
  4044 	 * - 'mime_type' - Default is ''. Filter by mime type (e.g., 'image/jpeg', 'application/pdf')
  3568 	 *
  4045 	 *
  3569 	 * @since 3.1.0
  4046 	 * @since 3.1.0
  3570 	 *
  4047 	 *
  3571 	 * @param array $args Method parameters. Contains:
  4048 	 * @param array  $args {
  3572 	 *  - blog_id (unused)
  4049 	 *     Method arguments. Note: arguments must be ordered as documented.
  3573 	 *  - username
  4050 	 *
  3574 	 *  - password
  4051 	 *     @type int    $blog_id (unused)
  3575 	 *  - filter
  4052 	 *     @type string $username
  3576 	 * @return array|IXR_Error Contains a collection of media items. See {@link wp_xmlrpc_server::wp_getMediaItem()} for a description of each item contents
  4053 	 *     @type string $password
       
  4054 	 *     @type array  $struct
       
  4055 	 * }
       
  4056 	 * @return array|IXR_Error Contains a collection of media items. See wp_xmlrpc_server::wp_getMediaItem() for a description of each item contents
  3577 	 */
  4057 	 */
  3578 	public function wp_getMediaLibrary($args) {
  4058 	public function wp_getMediaLibrary($args) {
  3579 		$this->escape($args);
  4059 		$this->escape($args);
  3580 
  4060 
  3581 		$username	= $args[1];
  4061 		$username	= $args[1];
  3584 
  4064 
  3585 		if ( !$user = $this->login($username, $password) )
  4065 		if ( !$user = $this->login($username, $password) )
  3586 			return $this->error;
  4066 			return $this->error;
  3587 
  4067 
  3588 		if ( !current_user_can( 'upload_files' ) )
  4068 		if ( !current_user_can( 'upload_files' ) )
  3589 			return new IXR_Error( 401, __( 'You do not have permission to upload files.' ) );
  4069 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to upload files.' ) );
  3590 
  4070 
  3591 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4071 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3592 		do_action( 'xmlrpc_call', 'wp.getMediaLibrary' );
  4072 		do_action( 'xmlrpc_call', 'wp.getMediaLibrary' );
  3593 
  4073 
  3594 		$parent_id = ( isset($struct['parent_id']) ) ? absint($struct['parent_id']) : '' ;
  4074 		$parent_id = ( isset($struct['parent_id']) ) ? absint($struct['parent_id']) : '' ;
  3605 
  4085 
  3606 		return $attachments_struct;
  4086 		return $attachments_struct;
  3607 	}
  4087 	}
  3608 
  4088 
  3609 	/**
  4089 	/**
  3610 	  * Retrieves a list of post formats used by the site
  4090 	 * Retrieves a list of post formats used by the site.
  3611 	  *
  4091 	 *
  3612 	  * @since 3.1.0
  4092 	 * @since 3.1.0
  3613 	  *
  4093 	 *
  3614 	  * @param array $args Method parameters. Contains:
  4094 	 * @param array  $args {
  3615 	  *  - blog_id (unused)
  4095 	 *     Method arguments. Note: arguments must be ordered as documented.
  3616 	  *  - username
  4096 	 *
  3617 	  *  - password
  4097 	 *     @type int    $blog_id (unused)
  3618 	  * @return array|IXR_Error
  4098 	 *     @type string $username
  3619 	  */
  4099 	 *     @type string $password
       
  4100 	 * }
       
  4101 	 * @return array|IXR_Error List of post formats, otherwise IXR_Error object.
       
  4102 	 */
  3620 	public function wp_getPostFormats( $args ) {
  4103 	public function wp_getPostFormats( $args ) {
  3621 		$this->escape( $args );
  4104 		$this->escape( $args );
  3622 
  4105 
  3623 		$username = $args[1];
  4106 		$username = $args[1];
  3624 		$password = $args[2];
  4107 		$password = $args[2];
  3625 
  4108 
  3626 		if ( !$user = $this->login( $username, $password ) )
  4109 		if ( !$user = $this->login( $username, $password ) )
  3627 			return $this->error;
  4110 			return $this->error;
  3628 
  4111 
  3629 		if ( !current_user_can( 'edit_posts' ) )
  4112 		if ( !current_user_can( 'edit_posts' ) )
  3630 			return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
  4113 			return new IXR_Error( 403, __( 'Sorry, you are not allowed access to details about this site.' ) );
  3631 
  4114 
  3632 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4115 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3633 		do_action( 'xmlrpc_call', 'wp.getPostFormats' );
  4116 		do_action( 'xmlrpc_call', 'wp.getPostFormats' );
  3634 
  4117 
  3635 		$formats = get_post_format_strings();
  4118 		$formats = get_post_format_strings();
  3655 	/**
  4138 	/**
  3656 	 * Retrieves a post type
  4139 	 * Retrieves a post type
  3657 	 *
  4140 	 *
  3658 	 * @since 3.4.0
  4141 	 * @since 3.4.0
  3659 	 *
  4142 	 *
  3660 	 * @uses get_post_type_object()
  4143 	 * @see get_post_type_object()
  3661 	 * @param array $args Method parameters. Contains:
  4144 	 *
  3662 	 *  - int     $blog_id (unused)
  4145 	 * @param array  $args {
  3663 	 *  - string  $username
  4146 	 *     Method arguments. Note: arguments must be ordered as documented.
  3664 	 *  - string  $password
  4147 	 *
  3665 	 *  - string  $post_type_name
  4148 	 *     @type int    $blog_id (unused)
  3666 	 *  - array   $fields
  4149 	 *     @type string $username
       
  4150 	 *     @type string $password
       
  4151 	 *     @type string $post_type_name
       
  4152 	 *     @type array  $fields (optional)
       
  4153 	 * }
  3667 	 * @return array|IXR_Error Array contains:
  4154 	 * @return array|IXR_Error Array contains:
  3668 	 *  - 'labels'
  4155 	 *  - 'labels'
  3669 	 *  - 'description'
  4156 	 *  - 'description'
  3670 	 *  - 'capability_type'
  4157 	 *  - 'capability_type'
  3671 	 *  - 'cap'
  4158 	 *  - 'cap'
  3687 
  4174 
  3688 		if ( isset( $args[4] ) ) {
  4175 		if ( isset( $args[4] ) ) {
  3689 			$fields = $args[4];
  4176 			$fields = $args[4];
  3690 		} else {
  4177 		} else {
  3691 			/**
  4178 			/**
  3692 			 * Filter the default query fields used by the given XML-RPC method.
  4179 			 * Filters the default query fields used by the given XML-RPC method.
  3693 			 *
  4180 			 *
  3694 			 * @since 3.4.0
  4181 			 * @since 3.4.0
  3695 			 *
  4182 			 *
  3696 			 * @param array  $fields An array of post type query fields for the given method.
  4183 			 * @param array  $fields An array of post type query fields for the given method.
  3697 			 * @param string $method The method name.
  4184 			 * @param string $method The method name.
  3703 			return $this->error;
  4190 			return $this->error;
  3704 
  4191 
  3705 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4192 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3706 		do_action( 'xmlrpc_call', 'wp.getPostType' );
  4193 		do_action( 'xmlrpc_call', 'wp.getPostType' );
  3707 
  4194 
  3708 		if( ! post_type_exists( $post_type_name ) )
  4195 		if ( ! post_type_exists( $post_type_name ) )
  3709 			return new IXR_Error( 403, __( 'Invalid post type' ) );
  4196 			return new IXR_Error( 403, __( 'Invalid post type.' ) );
  3710 
  4197 
  3711 		$post_type = get_post_type_object( $post_type_name );
  4198 		$post_type = get_post_type_object( $post_type_name );
  3712 
  4199 
  3713 		if( ! current_user_can( $post_type->cap->edit_posts ) )
  4200 		if ( ! current_user_can( $post_type->cap->edit_posts ) )
  3714 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post type.' ) );
  4201 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit posts in this post type.' ) );
  3715 
  4202 
  3716 		return $this->_prepare_post_type( $post_type, $fields );
  4203 		return $this->_prepare_post_type( $post_type, $fields );
  3717 	}
  4204 	}
  3718 
  4205 
  3719 	/**
  4206 	/**
  3720 	 * Retrieves a post types
  4207 	 * Retrieves a post types
  3721 	 *
  4208 	 *
  3722 	 * @since 3.4.0
  4209 	 * @since 3.4.0
  3723 	 *
  4210 	 *
  3724 	 * @uses get_post_types()
  4211 	 * @see get_post_types()
  3725 	 * @param array $args Method parameters. Contains:
  4212 	 *
  3726 	 *  - int     $blog_id (unused)
  4213 	 * @param array  $args {
  3727 	 *  - string  $username
  4214 	 *     Method arguments. Note: arguments must be ordered as documented.
  3728 	 *  - string  $password
  4215 	 *
  3729 	 *  - array   $filter
  4216 	 *     @type int    $blog_id (unused)
  3730 	 *  - array   $fields
  4217 	 *     @type string $username
       
  4218 	 *     @type string $password
       
  4219 	 *     @type array  $filter (optional)
       
  4220 	 *     @type array  $fields (optional)
       
  4221 	 * }
  3731 	 * @return array|IXR_Error
  4222 	 * @return array|IXR_Error
  3732 	 */
  4223 	 */
  3733 	public function wp_getPostTypes( $args ) {
  4224 	public function wp_getPostTypes( $args ) {
  3734 		if ( ! $this->minimum_args( $args, 3 ) )
  4225 		if ( ! $this->minimum_args( $args, 3 ) )
  3735 			return $this->error;
  4226 			return $this->error;
  3736 
  4227 
  3737 		$this->escape( $args );
  4228 		$this->escape( $args );
  3738 
  4229 
  3739 		$username           = $args[1];
  4230 		$username = $args[1];
  3740 		$password           = $args[2];
  4231 		$password = $args[2];
  3741 		$filter             = isset( $args[3] ) ? $args[3] : array( 'public' => true );
  4232 		$filter   = isset( $args[3] ) ? $args[3] : array( 'public' => true );
  3742 
  4233 
  3743 		if ( isset( $args[4] ) ) {
  4234 		if ( isset( $args[4] ) ) {
  3744 			$fields = $args[4];
  4235 			$fields = $args[4];
  3745 		} else {
  4236 		} else {
  3746 			/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4237 			/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3755 
  4246 
  3756 		$post_types = get_post_types( $filter, 'objects' );
  4247 		$post_types = get_post_types( $filter, 'objects' );
  3757 
  4248 
  3758 		$struct = array();
  4249 		$struct = array();
  3759 
  4250 
  3760 		foreach( $post_types as $post_type ) {
  4251 		foreach ( $post_types as $post_type ) {
  3761 			if( ! current_user_can( $post_type->cap->edit_posts ) )
  4252 			if ( ! current_user_can( $post_type->cap->edit_posts ) )
  3762 				continue;
  4253 				continue;
  3763 
  4254 
  3764 			$struct[$post_type->name] = $this->_prepare_post_type( $post_type, $fields );
  4255 			$struct[$post_type->name] = $this->_prepare_post_type( $post_type, $fields );
  3765 		}
  4256 		}
  3766 
  4257 
  3776 	 * in the response array.
  4267 	 * in the response array.
  3777 	 *
  4268 	 *
  3778 	 * @uses wp_get_post_revisions()
  4269 	 * @uses wp_get_post_revisions()
  3779 	 * @see wp_getPost() for more on $fields
  4270 	 * @see wp_getPost() for more on $fields
  3780 	 *
  4271 	 *
  3781 	 * @param array $args Method parameters. Contains:
  4272 	 * @param array  $args {
  3782 	 *  - int     $blog_id (unused)
  4273 	 *     Method arguments. Note: arguments must be ordered as documented.
  3783 	 *  - string  $username
  4274 	 *
  3784 	 *  - string  $password
  4275 	 *     @type int    $blog_id (unused)
  3785 	 *  - int     $post_id
  4276 	 *     @type string $username
  3786 	 *  - array   $fields
  4277 	 *     @type string $password
       
  4278 	 *     @type int    $post_id
       
  4279 	 *     @type array  $fields (optional)
       
  4280 	 * }
  3787 	 * @return array|IXR_Error contains a collection of posts.
  4281 	 * @return array|IXR_Error contains a collection of posts.
  3788 	 */
  4282 	 */
  3789 	public function wp_getRevisions( $args ) {
  4283 	public function wp_getRevisions( $args ) {
  3790 		if ( ! $this->minimum_args( $args, 4 ) )
  4284 		if ( ! $this->minimum_args( $args, 4 ) )
  3791 			return $this->error;
  4285 			return $this->error;
  3792 
  4286 
  3793 		$this->escape( $args );
  4287 		$this->escape( $args );
  3794 
  4288 
  3795 		$username   = $args[1];
  4289 		$username = $args[1];
  3796 		$password   = $args[2];
  4290 		$password = $args[2];
  3797 		$post_id    = (int) $args[3];
  4291 		$post_id  = (int) $args[3];
  3798 
  4292 
  3799 		if ( isset( $args[4] ) ) {
  4293 		if ( isset( $args[4] ) ) {
  3800 			$fields = $args[4];
  4294 			$fields = $args[4];
  3801 		} else {
  4295 		} else {
  3802 			/**
  4296 			/**
  3803 			 * Filter the default revision query fields used by the given XML-RPC method.
  4297 			 * Filters the default revision query fields used by the given XML-RPC method.
  3804 			 *
  4298 			 *
  3805 			 * @since 3.5.0
  4299 			 * @since 3.5.0
  3806 			 *
  4300 			 *
  3807 			 * @param array  $field  An array of revision query fields.
  4301 			 * @param array  $field  An array of revision query fields.
  3808 			 * @param string $method The method name.
  4302 			 * @param string $method The method name.
  3815 
  4309 
  3816 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4310 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3817 		do_action( 'xmlrpc_call', 'wp.getRevisions' );
  4311 		do_action( 'xmlrpc_call', 'wp.getRevisions' );
  3818 
  4312 
  3819 		if ( ! $post = get_post( $post_id ) )
  4313 		if ( ! $post = get_post( $post_id ) )
  3820 			return new IXR_Error( 404, __( 'Invalid post ID' ) );
  4314 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  3821 
  4315 
  3822 		if ( ! current_user_can( 'edit_post', $post_id ) )
  4316 		if ( ! current_user_can( 'edit_post', $post_id ) )
  3823 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit posts.' ) );
  4317 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit posts.' ) );
  3824 
  4318 
  3825 		// Check if revisions are enabled.
  4319 		// Check if revisions are enabled.
  3852 	 *
  4346 	 *
  3853 	 * @since 3.5.0
  4347 	 * @since 3.5.0
  3854 	 *
  4348 	 *
  3855 	 * @uses wp_restore_post_revision()
  4349 	 * @uses wp_restore_post_revision()
  3856 	 *
  4350 	 *
  3857 	 * @param array $args Method parameters. Contains:
  4351 	 * @param array  $args {
  3858 	 *  - int     $blog_id (unused)
  4352 	 *     Method arguments. Note: arguments must be ordered as documented.
  3859 	 *  - string  $username
  4353 	 *
  3860 	 *  - string  $password
  4354 	 *     @type int    $blog_id (unused)
  3861 	 *  - int     $post_id
  4355 	 *     @type string $username
       
  4356 	 *     @type string $password
       
  4357 	 *     @type int    $revision_id
       
  4358 	 * }
  3862 	 * @return bool|IXR_Error false if there was an error restoring, true if success.
  4359 	 * @return bool|IXR_Error false if there was an error restoring, true if success.
  3863 	 */
  4360 	 */
  3864 	public function wp_restoreRevision( $args ) {
  4361 	public function wp_restoreRevision( $args ) {
  3865 		if ( ! $this->minimum_args( $args, 3 ) )
  4362 		if ( ! $this->minimum_args( $args, 3 ) )
  3866 			return $this->error;
  4363 			return $this->error;
  3876 
  4373 
  3877 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4374 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3878 		do_action( 'xmlrpc_call', 'wp.restoreRevision' );
  4375 		do_action( 'xmlrpc_call', 'wp.restoreRevision' );
  3879 
  4376 
  3880 		if ( ! $revision = wp_get_post_revision( $revision_id ) )
  4377 		if ( ! $revision = wp_get_post_revision( $revision_id ) )
  3881 			return new IXR_Error( 404, __( 'Invalid post ID' ) );
  4378 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  3882 
  4379 
  3883 		if ( wp_is_post_autosave( $revision ) )
  4380 		if ( wp_is_post_autosave( $revision ) )
  3884 			return new IXR_Error( 404, __( 'Invalid post ID' ) );
  4381 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  3885 
  4382 
  3886 		if ( ! $post = get_post( $revision->post_parent ) )
  4383 		if ( ! $post = get_post( $revision->post_parent ) )
  3887 			return new IXR_Error( 404, __( 'Invalid post ID' ) );
  4384 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  3888 
  4385 
  3889 		if ( ! current_user_can( 'edit_post', $revision->post_parent ) )
  4386 		if ( ! current_user_can( 'edit_post', $revision->post_parent ) )
  3890 			return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) );
  4387 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  3891 
  4388 
  3892 		// Check if revisions are disabled.
  4389 		// Check if revisions are disabled.
  3893 		if ( ! wp_revisions_enabled( $post ) )
  4390 		if ( ! wp_revisions_enabled( $post ) )
  3894 			return new IXR_Error( 401, __( 'Sorry, revisions are disabled.' ) );
  4391 			return new IXR_Error( 401, __( 'Sorry, revisions are disabled.' ) );
  3895 
  4392 
  3897 
  4394 
  3898 		return (bool) $post;
  4395 		return (bool) $post;
  3899 	}
  4396 	}
  3900 
  4397 
  3901 	/* Blogger API functions.
  4398 	/* Blogger API functions.
  3902 	 * specs on http://plant.blogger.com/api and http://groups.yahoo.com/group/bloggerDev/
  4399 	 * specs on http://plant.blogger.com/api and https://groups.yahoo.com/group/bloggerDev/
  3903 	 */
  4400 	 */
  3904 
  4401 
  3905 	/**
  4402 	/**
  3906 	 * Retrieve blogs that user owns.
  4403 	 * Retrieve blogs that user owns.
  3907 	 *
  4404 	 *
  3908 	 * Will make more sense once we support multiple blogs.
  4405 	 * Will make more sense once we support multiple blogs.
  3909 	 *
  4406 	 *
  3910 	 * @since 1.5.0
  4407 	 * @since 1.5.0
  3911 	 *
  4408 	 *
  3912 	 * @param array $args Method parameters.
  4409 	 * @param array  $args {
       
  4410 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  4411 	 *
       
  4412 	 *     @type int    $blog_id (unused)
       
  4413 	 *     @type string $username
       
  4414 	 *     @type string $password
       
  4415 	 * }
  3913 	 * @return array|IXR_Error
  4416 	 * @return array|IXR_Error
  3914 	 */
  4417 	 */
  3915 	public function blogger_getUsersBlogs($args) {
  4418 	public function blogger_getUsersBlogs($args) {
  3916 		if ( is_multisite() )
  4419 		if ( ! $this->minimum_args( $args, 3 ) ) {
       
  4420 			return $this->error;
       
  4421 		}
       
  4422 
       
  4423 		if ( is_multisite() ) {
  3917 			return $this->_multisite_getUsersBlogs($args);
  4424 			return $this->_multisite_getUsersBlogs($args);
       
  4425 		}
  3918 
  4426 
  3919 		$this->escape($args);
  4427 		$this->escape($args);
  3920 
  4428 
  3921 		$username = $args[1];
  4429 		$username = $args[1];
  3922 		$password  = $args[2];
  4430 		$password = $args[2];
  3923 
  4431 
  3924 		if ( !$user = $this->login($username, $password) )
  4432 		if ( !$user = $this->login($username, $password) )
  3925 			return $this->error;
  4433 			return $this->error;
  3926 
  4434 
  3927 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4435 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3941 	}
  4449 	}
  3942 
  4450 
  3943 	/**
  4451 	/**
  3944 	 * Private function for retrieving a users blogs for multisite setups
  4452 	 * Private function for retrieving a users blogs for multisite setups
  3945 	 *
  4453 	 *
  3946 	 * @access protected
  4454 	 * @since 3.0.0
  3947 	 *
  4455 	 *
       
  4456 	 * @param array $args {
       
  4457 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  4458 	 *
       
  4459 	 *     @type string $username Username.
       
  4460 	 *     @type string $password Password.
       
  4461 	 * }
  3948 	 * @return array|IXR_Error
  4462 	 * @return array|IXR_Error
  3949 	 */
  4463 	 */
  3950 	protected function _multisite_getUsersBlogs($args) {
  4464 	protected function _multisite_getUsersBlogs( $args ) {
  3951 		$current_blog = get_blog_details();
  4465 		$current_blog = get_site();
  3952 
  4466 
  3953 		$domain = $current_blog->domain;
  4467 		$domain = $current_blog->domain;
  3954 		$path = $current_blog->path . 'xmlrpc.php';
  4468 		$path = $current_blog->path . 'xmlrpc.php';
  3955 
  4469 
  3956 		$rpc = new IXR_Client( set_url_scheme( "http://{$domain}{$path}" ) );
  4470 		$rpc = new IXR_Client( set_url_scheme( "http://{$domain}{$path}" ) );
  3976 	 *
  4490 	 *
  3977 	 * Gives your client some info about you, so you don't have to.
  4491 	 * Gives your client some info about you, so you don't have to.
  3978 	 *
  4492 	 *
  3979 	 * @since 1.5.0
  4493 	 * @since 1.5.0
  3980 	 *
  4494 	 *
  3981 	 * @param array $args Method parameters.
  4495 	 * @param array  $args {
       
  4496 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  4497 	 *
       
  4498 	 *     @type int    $blog_id (unused)
       
  4499 	 *     @type string $username
       
  4500 	 *     @type string $password
       
  4501 	 * }
  3982 	 * @return array|IXR_Error
  4502 	 * @return array|IXR_Error
  3983 	 */
  4503 	 */
  3984 	public function blogger_getUserInfo($args) {
  4504 	public function blogger_getUserInfo( $args ) {
  3985 
  4505 		$this->escape( $args );
  3986 		$this->escape($args);
       
  3987 
  4506 
  3988 		$username = $args[1];
  4507 		$username = $args[1];
  3989 		$password  = $args[2];
  4508 		$password = $args[2];
  3990 
  4509 
  3991 		if ( !$user = $this->login($username, $password) )
  4510 		if ( !$user = $this->login($username, $password) )
  3992 			return $this->error;
  4511 			return $this->error;
  3993 
  4512 
  3994 		if ( !current_user_can( 'edit_posts' ) )
  4513 		if ( !current_user_can( 'edit_posts' ) )
  3995 			return new IXR_Error( 401, __( 'Sorry, you do not have access to user data on this site.' ) );
  4514 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to access user data on this site.' ) );
  3996 
  4515 
  3997 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4516 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  3998 		do_action( 'xmlrpc_call', 'blogger.getUserInfo' );
  4517 		do_action( 'xmlrpc_call', 'blogger.getUserInfo' );
  3999 
  4518 
  4000 		$struct = array(
  4519 		$struct = array(
  4011 	/**
  4530 	/**
  4012 	 * Retrieve post.
  4531 	 * Retrieve post.
  4013 	 *
  4532 	 *
  4014 	 * @since 1.5.0
  4533 	 * @since 1.5.0
  4015 	 *
  4534 	 *
  4016 	 * @param array $args Method parameters.
  4535 	 * @param array  $args {
       
  4536 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  4537 	 *
       
  4538 	 *     @type int    $blog_id (unused)
       
  4539 	 *     @type int    $post_ID
       
  4540 	 *     @type string $username
       
  4541 	 *     @type string $password
       
  4542 	 * }
  4017 	 * @return array|IXR_Error
  4543 	 * @return array|IXR_Error
  4018 	 */
  4544 	 */
  4019 	public function blogger_getPost($args) {
  4545 	public function blogger_getPost( $args ) {
  4020 
  4546 		$this->escape( $args );
  4021 		$this->escape($args);
  4547 
  4022 
  4548 		$post_ID  = (int) $args[1];
  4023 		$post_ID    = (int) $args[1];
       
  4024 		$username = $args[2];
  4549 		$username = $args[2];
  4025 		$password  = $args[3];
  4550 		$password = $args[3];
  4026 
  4551 
  4027 		if ( !$user = $this->login($username, $password) )
  4552 		if ( !$user = $this->login($username, $password) )
  4028 			return $this->error;
  4553 			return $this->error;
  4029 
  4554 
  4030 		$post_data = get_post($post_ID, ARRAY_A);
  4555 		$post_data = get_post($post_ID, ARRAY_A);
  4031 		if ( ! $post_data )
  4556 		if ( ! $post_data )
  4032 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  4557 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  4033 
  4558 
  4034 		if ( !current_user_can( 'edit_post', $post_ID ) )
  4559 		if ( !current_user_can( 'edit_post', $post_ID ) )
  4035 			return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) );
  4560 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  4036 
  4561 
  4037 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4562 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4038 		do_action( 'xmlrpc_call', 'blogger.getPost' );
  4563 		do_action( 'xmlrpc_call', 'blogger.getPost' );
  4039 
  4564 
  4040 		$categories = implode(',', wp_get_post_categories($post_ID));
  4565 		$categories = implode(',', wp_get_post_categories($post_ID));
  4056 	/**
  4581 	/**
  4057 	 * Retrieve list of recent posts.
  4582 	 * Retrieve list of recent posts.
  4058 	 *
  4583 	 *
  4059 	 * @since 1.5.0
  4584 	 * @since 1.5.0
  4060 	 *
  4585 	 *
  4061 	 * @param array $args Method parameters.
  4586 	 * @param array  $args {
       
  4587 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  4588 	 *
       
  4589 	 *     @type string $appkey (unused)
       
  4590 	 *     @type int    $blog_id (unused)
       
  4591 	 *     @type string $username
       
  4592 	 *     @type string $password
       
  4593 	 *     @type int    $numberposts (optional)
       
  4594 	 * }
  4062 	 * @return array|IXR_Error
  4595 	 * @return array|IXR_Error
  4063 	 */
  4596 	 */
  4064 	public function blogger_getRecentPosts($args) {
  4597 	public function blogger_getRecentPosts( $args ) {
  4065 
  4598 
  4066 		$this->escape($args);
  4599 		$this->escape($args);
  4067 
  4600 
  4068 		// $args[0] = appkey - ignored
  4601 		// $args[0] = appkey - ignored
  4069 		$username = $args[2];
  4602 		$username = $args[2];
  4070 		$password  = $args[3];
  4603 		$password = $args[3];
  4071 		if ( isset( $args[4] ) )
  4604 		if ( isset( $args[4] ) )
  4072 			$query = array( 'numberposts' => absint( $args[4] ) );
  4605 			$query = array( 'numberposts' => absint( $args[4] ) );
  4073 		else
  4606 		else
  4074 			$query = array();
  4607 			$query = array();
  4075 
  4608 
  4076 		if ( !$user = $this->login($username, $password) )
  4609 		if ( !$user = $this->login($username, $password) )
  4077 			return $this->error;
  4610 			return $this->error;
  4078 
  4611 
  4079 		if ( ! current_user_can( 'edit_posts' ) )
  4612 		if ( ! current_user_can( 'edit_posts' ) )
  4080 			return new IXR_Error( 401, __( 'Sorry, you cannot edit posts on this site.' ) );
  4613 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit posts.' ) );
  4081 
  4614 
  4082 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4615 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4083 		do_action( 'xmlrpc_call', 'blogger.getRecentPosts' );
  4616 		do_action( 'xmlrpc_call', 'blogger.getRecentPosts' );
  4084 
  4617 
  4085 		$posts_list = wp_get_recent_posts( $query );
  4618 		$posts_list = wp_get_recent_posts( $query );
  4115 	/**
  4648 	/**
  4116 	 * Deprecated.
  4649 	 * Deprecated.
  4117 	 *
  4650 	 *
  4118 	 * @since 1.5.0
  4651 	 * @since 1.5.0
  4119 	 * @deprecated 3.5.0
  4652 	 * @deprecated 3.5.0
  4120 	 * @return IXR_Error
  4653 	 *
       
  4654 	 * @param array $args Unused.
       
  4655 	 * @return IXR_Error Error object.
  4121 	 */
  4656 	 */
  4122 	public function blogger_getTemplate($args) {
  4657 	public function blogger_getTemplate($args) {
  4123 		return new IXR_Error( 403, __('Sorry, that file cannot be edited.' ) );
  4658 		return new IXR_Error( 403, __('Sorry, that file cannot be edited.' ) );
  4124 	}
  4659 	}
  4125 
  4660 
  4126 	/**
  4661 	/**
  4127 	 * Deprecated.
  4662 	 * Deprecated.
  4128 	 *
  4663 	 *
  4129 	 * @since 1.5.0
  4664 	 * @since 1.5.0
  4130 	 * @deprecated 3.5.0
  4665 	 * @deprecated 3.5.0
  4131 	 * @return IXR_Error
  4666 	 *
       
  4667 	 * @param array $args Unused.
       
  4668 	 * @return IXR_Error Error object.
  4132 	 */
  4669 	 */
  4133 	public function blogger_setTemplate($args) {
  4670 	public function blogger_setTemplate($args) {
  4134 		return new IXR_Error( 403, __('Sorry, that file cannot be edited.' ) );
  4671 		return new IXR_Error( 403, __('Sorry, that file cannot be edited.' ) );
  4135 	}
  4672 	}
  4136 
  4673 
  4137 	/**
  4674 	/**
  4138 	 * Create new post.
  4675 	 * Creates new post.
  4139 	 *
  4676 	 *
  4140 	 * @since 1.5.0
  4677 	 * @since 1.5.0
  4141 	 *
  4678 	 *
  4142 	 * @param array $args Method parameters.
  4679 	 * @param array $args {
       
  4680 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  4681 	 *
       
  4682 	 *     @type string $appkey (unused)
       
  4683 	 *     @type int    $blog_id (unused)
       
  4684 	 *     @type string $username
       
  4685 	 *     @type string $password
       
  4686 	 *     @type string $content
       
  4687 	 *     @type string $publish
       
  4688 	 * }
  4143 	 * @return int|IXR_Error
  4689 	 * @return int|IXR_Error
  4144 	 */
  4690 	 */
  4145 	public function blogger_newPost($args) {
  4691 	public function blogger_newPost( $args ) {
  4146 
  4692 		$this->escape( $args );
  4147 		$this->escape($args);
       
  4148 
  4693 
  4149 		$username = $args[2];
  4694 		$username = $args[2];
  4150 		$password  = $args[3];
  4695 		$password = $args[3];
  4151 		$content    = $args[4];
  4696 		$content  = $args[4];
  4152 		$publish    = $args[5];
  4697 		$publish  = $args[5];
  4153 
  4698 
  4154 		if ( !$user = $this->login($username, $password) )
  4699 		if ( !$user = $this->login($username, $password) )
  4155 			return $this->error;
  4700 			return $this->error;
  4156 
  4701 
  4157 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4702 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4177 		$post_ID = wp_insert_post($post_data);
  4722 		$post_ID = wp_insert_post($post_data);
  4178 		if ( is_wp_error( $post_ID ) )
  4723 		if ( is_wp_error( $post_ID ) )
  4179 			return new IXR_Error(500, $post_ID->get_error_message());
  4724 			return new IXR_Error(500, $post_ID->get_error_message());
  4180 
  4725 
  4181 		if ( !$post_ID )
  4726 		if ( !$post_ID )
  4182 			return new IXR_Error(500, __('Sorry, your entry could not be posted. Something wrong happened.'));
  4727 			return new IXR_Error(500, __('Sorry, your entry could not be posted.'));
  4183 
  4728 
  4184 		$this->attach_uploads( $post_ID, $post_content );
  4729 		$this->attach_uploads( $post_ID, $post_content );
  4185 
  4730 
  4186 		/**
  4731 		/**
  4187 		 * Fires after a new post has been successfully created via the XML-RPC Blogger API.
  4732 		 * Fires after a new post has been successfully created via the XML-RPC Blogger API.
  4199 	/**
  4744 	/**
  4200 	 * Edit a post.
  4745 	 * Edit a post.
  4201 	 *
  4746 	 *
  4202 	 * @since 1.5.0
  4747 	 * @since 1.5.0
  4203 	 *
  4748 	 *
  4204 	 * @param array $args Method parameters.
  4749 	 * @param array  $args {
  4205 	 * @return bool|IXR_Error true when done.
  4750 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  4751 	 *
       
  4752 	 *     @type int    $blog_id (unused)
       
  4753 	 *     @type int    $post_ID
       
  4754 	 *     @type string $username
       
  4755 	 *     @type string $password
       
  4756 	 *     @type string $content
       
  4757 	 *     @type bool   $publish
       
  4758 	 * }
       
  4759 	 * @return true|IXR_Error true when done.
  4206 	 */
  4760 	 */
  4207 	public function blogger_editPost( $args ) {
  4761 	public function blogger_editPost( $args ) {
  4208 
  4762 
  4209 		$this->escape($args);
  4763 		$this->escape($args);
  4210 
  4764 
  4211 		$post_ID     = (int) $args[1];
  4765 		$post_ID  = (int) $args[1];
  4212 		$username  = $args[2];
  4766 		$username = $args[2];
  4213 		$password   = $args[3];
  4767 		$password = $args[3];
  4214 		$content     = $args[4];
  4768 		$content  = $args[4];
       
  4769 		$publish  = $args[5];
  4215 
  4770 
  4216 		if ( ! $user = $this->login( $username, $password ) ) {
  4771 		if ( ! $user = $this->login( $username, $password ) ) {
  4217 			return $this->error;
  4772 			return $this->error;
  4218 		}
  4773 		}
  4219 
  4774 
  4227 		}
  4782 		}
  4228 
  4783 
  4229 		$this->escape($actual_post);
  4784 		$this->escape($actual_post);
  4230 
  4785 
  4231 		if ( ! current_user_can( 'edit_post', $post_ID ) ) {
  4786 		if ( ! current_user_can( 'edit_post', $post_ID ) ) {
  4232 			return new IXR_Error(401, __('Sorry, you do not have the right to edit this post.'));
  4787 			return new IXR_Error(401, __('Sorry, you are not allowed to edit this post.'));
  4233 		}
  4788 		}
  4234 		if ( 'publish' == $actual_post['post_status'] && ! current_user_can( 'publish_posts' ) ) {
  4789 		if ( 'publish' == $actual_post['post_status'] && ! current_user_can( 'publish_posts' ) ) {
  4235 			return new IXR_Error( 401, __( 'Sorry, you do not have the right to publish this post.' ) );
  4790 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish this post.' ) );
  4236 		}
  4791 		}
  4237 
  4792 
  4238 		$postdata = array();
  4793 		$postdata = array();
  4239 		$postdata['ID'] = $actual_post['ID'];
  4794 		$postdata['ID'] = $actual_post['ID'];
  4240 		$postdata['post_content'] = xmlrpc_removepostdata( $content );
  4795 		$postdata['post_content'] = xmlrpc_removepostdata( $content );
  4241 		$postdata['post_title'] = xmlrpc_getposttitle( $content );
  4796 		$postdata['post_title'] = xmlrpc_getposttitle( $content );
  4242 		$postdata['post_category'] = xmlrpc_getpostcategory( $content );
  4797 		$postdata['post_category'] = xmlrpc_getpostcategory( $content );
  4243 		$postdata['post_status'] = $actual_post['post_status'];
  4798 		$postdata['post_status'] = $actual_post['post_status'];
  4244 		$postdata['post_excerpt'] = $actual_post['post_excerpt'];
  4799 		$postdata['post_excerpt'] = $actual_post['post_excerpt'];
       
  4800 		$postdata['post_status'] = $publish ? 'publish' : 'draft';
  4245 
  4801 
  4246 		$result = wp_update_post( $postdata );
  4802 		$result = wp_update_post( $postdata );
  4247 
  4803 
  4248 		if ( ! $result ) {
  4804 		if ( ! $result ) {
  4249 			return new IXR_Error(500, __('For some strange yet very annoying reason, this post could not be edited.'));
  4805 			return new IXR_Error(500, __('For some strange yet very annoying reason, this post could not be edited.'));
  4266 	/**
  4822 	/**
  4267 	 * Remove a post.
  4823 	 * Remove a post.
  4268 	 *
  4824 	 *
  4269 	 * @since 1.5.0
  4825 	 * @since 1.5.0
  4270 	 *
  4826 	 *
  4271 	 * @param array $args Method parameters.
  4827 	 * @param array  $args {
  4272 	 * @return bool|IXR_Error True when post is deleted.
  4828 	 *     Method arguments. Note: arguments must be ordered as documented.
  4273 	 */
  4829 	 *
  4274 	public function blogger_deletePost($args) {
  4830 	 *     @type int    $blog_id (unused)
  4275 		$this->escape($args);
  4831 	 *     @type int    $post_ID
  4276 
  4832 	 *     @type string $username
  4277 		$post_ID     = (int) $args[1];
  4833 	 *     @type string $password
  4278 		$username  = $args[2];
  4834 	 * }
  4279 		$password   = $args[3];
  4835 	 * @return true|IXR_Error True when post is deleted.
       
  4836 	 */
       
  4837 	public function blogger_deletePost( $args ) {
       
  4838 		$this->escape( $args );
       
  4839 
       
  4840 		$post_ID  = (int) $args[1];
       
  4841 		$username = $args[2];
       
  4842 		$password = $args[3];
  4280 
  4843 
  4281 		if ( !$user = $this->login($username, $password) )
  4844 		if ( !$user = $this->login($username, $password) )
  4282 			return $this->error;
  4845 			return $this->error;
  4283 
  4846 
  4284 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4847 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4285 		do_action( 'xmlrpc_call', 'blogger.deletePost' );
  4848 		do_action( 'xmlrpc_call', 'blogger.deletePost' );
  4286 
  4849 
  4287 		$actual_post = get_post($post_ID,ARRAY_A);
  4850 		$actual_post = get_post( $post_ID, ARRAY_A );
  4288 
  4851 
  4289 		if ( !$actual_post || $actual_post['post_type'] != 'post' )
  4852 		if ( ! $actual_post || $actual_post['post_type'] != 'post' ) {
  4290 			return new IXR_Error(404, __('Sorry, no such post.'));
  4853 			return new IXR_Error( 404, __( 'Sorry, no such post.' ) );
  4291 
  4854 		}
  4292 		if ( !current_user_can('delete_post', $post_ID) )
  4855 
  4293 			return new IXR_Error(401, __('Sorry, you do not have the right to delete this post.'));
  4856 		if ( ! current_user_can( 'delete_post', $post_ID ) ) {
  4294 
  4857 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to delete this post.' ) );
  4295 		$result = wp_delete_post($post_ID);
  4858 		}
  4296 
  4859 
  4297 		if ( !$result )
  4860 		$result = wp_delete_post( $post_ID );
  4298 			return new IXR_Error(500, __('For some strange yet very annoying reason, this post could not be deleted.'));
  4861 
       
  4862 		if ( ! $result ) {
       
  4863 			return new IXR_Error( 500, __( 'The post cannot be deleted.' ) );
       
  4864 		}
  4299 
  4865 
  4300 		/**
  4866 		/**
  4301 		 * Fires after a post has been successfully deleted via the XML-RPC Blogger API.
  4867 		 * Fires after a post has been successfully deleted via the XML-RPC Blogger API.
  4302 		 *
  4868 		 *
  4303 		 * @since 3.4.0
  4869 		 * @since 3.4.0
  4339 	 *  - dateCreated
  4905 	 *  - dateCreated
  4340 	 *  - wp_post_thumbnail
  4906 	 *  - wp_post_thumbnail
  4341 	 *
  4907 	 *
  4342 	 * @since 1.5.0
  4908 	 * @since 1.5.0
  4343 	 *
  4909 	 *
  4344 	 * @param array $args Method parameters. Contains:
  4910 	 * @param array  $args {
  4345 	 *  - blog_id (unused)
  4911 	 *     Method arguments. Note: arguments must be ordered as documented.
  4346 	 *  - username
  4912 	 *
  4347 	 *  - password
  4913 	 *     @type int    $blog_id (unused)
  4348 	 *  - content_struct
  4914 	 *     @type string $username
  4349 	 *  - publish
  4915 	 *     @type string $password
       
  4916 	 *     @type array  $content_struct
       
  4917 	 *     @type int    $publish
       
  4918 	 * }
  4350 	 * @return int|IXR_Error
  4919 	 * @return int|IXR_Error
  4351 	 */
  4920 	 */
  4352 	public function mw_newPost($args) {
  4921 	public function mw_newPost($args) {
  4353 		$this->escape($args);
  4922 		$this->escape($args);
  4354 
  4923 
  4355 		$username  = $args[1];
  4924 		$username       = $args[1];
  4356 		$password   = $args[2];
  4925 		$password       = $args[2];
  4357 		$content_struct = $args[3];
  4926 		$content_struct = $args[3];
  4358 		$publish     = isset( $args[4] ) ? $args[4] : 0;
  4927 		$publish        = isset( $args[4] ) ? $args[4] : 0;
  4359 
  4928 
  4360 		if ( !$user = $this->login($username, $password) )
  4929 		if ( !$user = $this->login($username, $password) )
  4361 			return $this->error;
  4930 			return $this->error;
  4362 
  4931 
  4363 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4932 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4385 					$cap = 'edit_posts';
  4954 					$cap = 'edit_posts';
  4386 				$error_message = __( 'Sorry, you are not allowed to publish posts on this site.' );
  4955 				$error_message = __( 'Sorry, you are not allowed to publish posts on this site.' );
  4387 				$post_type = 'post';
  4956 				$post_type = 'post';
  4388 			} else {
  4957 			} else {
  4389 				// No other post_type values are allowed here
  4958 				// No other post_type values are allowed here
  4390 				return new IXR_Error( 401, __( 'Invalid post type' ) );
  4959 				return new IXR_Error( 401, __( 'Invalid post type.' ) );
  4391 			}
  4960 			}
  4392 		} else {
  4961 		} else {
  4393 			if ( $publish )
  4962 			if ( $publish )
  4394 				$cap  = 'publish_posts';
  4963 				$cap  = 'publish_posts';
  4395 			elseif ( isset( $content_struct['post_status'] ) && 'publish' == $content_struct['post_status'])
  4964 			elseif ( isset( $content_struct['post_status'] ) && 'publish' == $content_struct['post_status'])
  4407 
  4976 
  4408 		// Check for a valid post format if one was given
  4977 		// Check for a valid post format if one was given
  4409 		if ( isset( $content_struct['wp_post_format'] ) ) {
  4978 		if ( isset( $content_struct['wp_post_format'] ) ) {
  4410 			$content_struct['wp_post_format'] = sanitize_key( $content_struct['wp_post_format'] );
  4979 			$content_struct['wp_post_format'] = sanitize_key( $content_struct['wp_post_format'] );
  4411 			if ( !array_key_exists( $content_struct['wp_post_format'], get_post_format_strings() ) ) {
  4980 			if ( !array_key_exists( $content_struct['wp_post_format'], get_post_format_strings() ) ) {
  4412 				return new IXR_Error( 404, __( 'Invalid post format' ) );
  4981 				return new IXR_Error( 404, __( 'Invalid post format.' ) );
  4413 			}
  4982 			}
  4414 		}
  4983 		}
  4415 
  4984 
  4416 		// Let WordPress generate the post_name (slug) unless
  4985 		// Let WordPress generate the post_name (slug) unless
  4417 		// one has been provided.
  4986 		// one has been provided.
  4436 		// If an author id was provided then use it instead.
  5005 		// If an author id was provided then use it instead.
  4437 		if ( isset( $content_struct['wp_author_id'] ) && ( $user->ID != $content_struct['wp_author_id'] ) ) {
  5006 		if ( isset( $content_struct['wp_author_id'] ) && ( $user->ID != $content_struct['wp_author_id'] ) ) {
  4438 			switch ( $post_type ) {
  5007 			switch ( $post_type ) {
  4439 				case "post":
  5008 				case "post":
  4440 					if ( !current_user_can( 'edit_others_posts' ) )
  5009 					if ( !current_user_can( 'edit_others_posts' ) )
  4441 						return new IXR_Error( 401, __( 'You are not allowed to create posts as this user.' ) );
  5010 						return new IXR_Error( 401, __( 'Sorry, you are not allowed to create posts as this user.' ) );
  4442 					break;
  5011 					break;
  4443 				case "page":
  5012 				case "page":
  4444 					if ( !current_user_can( 'edit_others_pages' ) )
  5013 					if ( !current_user_can( 'edit_others_pages' ) )
  4445 						return new IXR_Error( 401, __( 'You are not allowed to create pages as this user.' ) );
  5014 						return new IXR_Error( 401, __( 'Sorry, you are not allowed to create pages as this user.' ) );
  4446 					break;
  5015 					break;
  4447 				default:
  5016 				default:
  4448 					return new IXR_Error( 401, __( 'Invalid post type' ) );
  5017 					return new IXR_Error( 401, __( 'Invalid post type.' ) );
  4449 			}
  5018 			}
  4450 			$author = get_userdata( $content_struct['wp_author_id'] );
  5019 			$author = get_userdata( $content_struct['wp_author_id'] );
  4451 			if ( ! $author )
  5020 			if ( ! $author )
  4452 				return new IXR_Error( 404, __( 'Invalid author ID.' ) );
  5021 				return new IXR_Error( 404, __( 'Invalid author ID.' ) );
  4453 			$post_author = $content_struct['wp_author_id'];
  5022 			$post_author = $content_struct['wp_author_id'];
  4485 						break;
  5054 						break;
  4486 					case 'open':
  5055 					case 'open':
  4487 						$comment_status = 'open';
  5056 						$comment_status = 'open';
  4488 						break;
  5057 						break;
  4489 					default:
  5058 					default:
  4490 						$comment_status = get_option('default_comment_status');
  5059 						$comment_status = get_default_comment_status( $post_type );
  4491 						break;
  5060 						break;
  4492 				}
  5061 				}
  4493 			} else {
  5062 			} else {
  4494 				switch ( (int) $content_struct['mt_allow_comments'] ) {
  5063 				switch ( (int) $content_struct['mt_allow_comments'] ) {
  4495 					case 0:
  5064 					case 0:
  4498 						break;
  5067 						break;
  4499 					case 1:
  5068 					case 1:
  4500 						$comment_status = 'open';
  5069 						$comment_status = 'open';
  4501 						break;
  5070 						break;
  4502 					default:
  5071 					default:
  4503 						$comment_status = get_option('default_comment_status');
  5072 						$comment_status = get_default_comment_status( $post_type );
  4504 						break;
  5073 						break;
  4505 				}
  5074 				}
  4506 			}
  5075 			}
  4507 		} else {
  5076 		} else {
  4508 			$comment_status = get_option('default_comment_status');
  5077 			$comment_status = get_default_comment_status( $post_type );
  4509 		}
  5078 		}
  4510 
  5079 
  4511 		if ( isset($content_struct['mt_allow_pings']) ) {
  5080 		if ( isset($content_struct['mt_allow_pings']) ) {
  4512 			if ( !is_numeric($content_struct['mt_allow_pings']) ) {
  5081 			if ( !is_numeric($content_struct['mt_allow_pings']) ) {
  4513 				switch ( $content_struct['mt_allow_pings'] ) {
  5082 				switch ( $content_struct['mt_allow_pings'] ) {
  4516 						break;
  5085 						break;
  4517 					case 'open':
  5086 					case 'open':
  4518 						$ping_status = 'open';
  5087 						$ping_status = 'open';
  4519 						break;
  5088 						break;
  4520 					default:
  5089 					default:
  4521 						$ping_status = get_option('default_ping_status');
  5090 						$ping_status = get_default_comment_status( $post_type, 'pingback' );
  4522 						break;
  5091 						break;
  4523 				}
  5092 				}
  4524 			} else {
  5093 			} else {
  4525 				switch ( (int) $content_struct['mt_allow_pings'] ) {
  5094 				switch ( (int) $content_struct['mt_allow_pings'] ) {
  4526 					case 0:
  5095 					case 0:
  4528 						break;
  5097 						break;
  4529 					case 1:
  5098 					case 1:
  4530 						$ping_status = 'open';
  5099 						$ping_status = 'open';
  4531 						break;
  5100 						break;
  4532 					default:
  5101 					default:
  4533 						$ping_status = get_option('default_ping_status');
  5102 						$ping_status = get_default_comment_status( $post_type, 'pingback' );
  4534 						break;
  5103 						break;
  4535 				}
  5104 				}
  4536 			}
  5105 			}
  4537 		} else {
  5106 		} else {
  4538 			$ping_status = get_option('default_ping_status');
  5107 			$ping_status = get_default_comment_status( $post_type, 'pingback' );
  4539 		}
  5108 		}
  4540 
  5109 
  4541 		if ( $post_more )
  5110 		if ( $post_more )
  4542 			$post_content = $post_content . '<!--more-->' . $post_more;
  5111 			$post_content = $post_content . '<!--more-->' . $post_more;
  4543 
  5112 
  4557 
  5126 
  4558 		if ( !empty( $dateCreated ) ) {
  5127 		if ( !empty( $dateCreated ) ) {
  4559 			$post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated));
  5128 			$post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated));
  4560 			$post_date_gmt = iso8601_to_datetime($dateCreated, 'GMT');
  5129 			$post_date_gmt = iso8601_to_datetime($dateCreated, 'GMT');
  4561 		} else {
  5130 		} else {
  4562 			$post_date = current_time('mysql');
  5131 			$post_date = '';
  4563 			$post_date_gmt = current_time('mysql', 1);
  5132 			$post_date_gmt = '';
  4564 		}
  5133 		}
  4565 
  5134 
  4566 		$post_category = array();
  5135 		$post_category = array();
  4567 		if ( isset( $content_struct['categories'] ) ) {
  5136 		if ( isset( $content_struct['categories'] ) ) {
  4568 			$catnames = $content_struct['categories'];
  5137 			$catnames = $content_struct['categories'];
  4578 
  5147 
  4579 		$post_ID = $postdata['ID'] = get_default_post_to_edit( $post_type, true )->ID;
  5148 		$post_ID = $postdata['ID'] = get_default_post_to_edit( $post_type, true )->ID;
  4580 
  5149 
  4581 		// Only posts can be sticky
  5150 		// Only posts can be sticky
  4582 		if ( $post_type == 'post' && isset( $content_struct['sticky'] ) ) {
  5151 		if ( $post_type == 'post' && isset( $content_struct['sticky'] ) ) {
  4583 			if ( $content_struct['sticky'] == true )
  5152 			$data = $postdata;
  4584 				stick_post( $post_ID );
  5153 			$data['sticky'] = $content_struct['sticky'];
  4585 			elseif ( $content_struct['sticky'] == false )
  5154 			$error = $this->_toggle_sticky( $data );
  4586 				unstick_post( $post_ID );
  5155 			if ( $error ) {
       
  5156 				return $error;
       
  5157 			}
  4587 		}
  5158 		}
  4588 
  5159 
  4589 		if ( isset($content_struct['custom_fields']) )
  5160 		if ( isset($content_struct['custom_fields']) )
  4590 			$this->set_custom_fields($post_ID, $content_struct['custom_fields']);
  5161 			$this->set_custom_fields($post_ID, $content_struct['custom_fields']);
  4591 
  5162 
  4610 		$post_ID = wp_insert_post( $postdata, true );
  5181 		$post_ID = wp_insert_post( $postdata, true );
  4611 		if ( is_wp_error( $post_ID ) )
  5182 		if ( is_wp_error( $post_ID ) )
  4612 			return new IXR_Error(500, $post_ID->get_error_message());
  5183 			return new IXR_Error(500, $post_ID->get_error_message());
  4613 
  5184 
  4614 		if ( !$post_ID )
  5185 		if ( !$post_ID )
  4615 			return new IXR_Error(500, __('Sorry, your entry could not be posted. Something wrong happened.'));
  5186 			return new IXR_Error(500, __('Sorry, your entry could not be posted.'));
  4616 
  5187 
  4617 		/**
  5188 		/**
  4618 		 * Fires after a new post has been successfully created via the XML-RPC MovableType API.
  5189 		 * Fires after a new post has been successfully created via the XML-RPC MovableType API.
  4619 		 *
  5190 		 *
  4620 		 * @since 3.4.0
  5191 		 * @since 3.4.0
  4626 
  5197 
  4627 		return strval($post_ID);
  5198 		return strval($post_ID);
  4628 	}
  5199 	}
  4629 
  5200 
  4630 	/**
  5201 	/**
  4631 	 * @param integer $post_ID
  5202 	 * Adds an enclosure to a post if it's new.
  4632 	 * @param array   $enclosure
  5203 	 *
       
  5204 	 * @since 2.8.0
       
  5205 	 *
       
  5206 	 * @param integer $post_ID   Post ID.
       
  5207 	 * @param array   $enclosure Enclosure data.
  4633 	 */
  5208 	 */
  4634 	public function add_enclosure_if_new( $post_ID, $enclosure ) {
  5209 	public function add_enclosure_if_new( $post_ID, $enclosure ) {
  4635 		if ( is_array( $enclosure ) && isset( $enclosure['url'] ) && isset( $enclosure['length'] ) && isset( $enclosure['type'] ) ) {
  5210 		if ( is_array( $enclosure ) && isset( $enclosure['url'] ) && isset( $enclosure['length'] ) && isset( $enclosure['type'] ) ) {
  4636 			$encstring = $enclosure['url'] . "\n" . $enclosure['length'] . "\n" . $enclosure['type'] . "\n";
  5211 			$encstring = $enclosure['url'] . "\n" . $enclosure['length'] . "\n" . $enclosure['type'] . "\n";
  4637 			$found = false;
  5212 			$found = false;
  4652 	/**
  5227 	/**
  4653 	 * Attach upload to a post.
  5228 	 * Attach upload to a post.
  4654 	 *
  5229 	 *
  4655 	 * @since 2.1.0
  5230 	 * @since 2.1.0
  4656 	 *
  5231 	 *
       
  5232 	 * @global wpdb $wpdb WordPress database abstraction object.
       
  5233 	 *
  4657 	 * @param int $post_ID Post ID.
  5234 	 * @param int $post_ID Post ID.
  4658 	 * @param string $post_content Post Content for attachment.
  5235 	 * @param string $post_content Post Content for attachment.
  4659 	 */
  5236 	 */
  4660 	public function attach_uploads( $post_ID, $post_content ) {
  5237 	public function attach_uploads( $post_ID, $post_content ) {
  4661 		global $wpdb;
  5238 		global $wpdb;
  4673 	/**
  5250 	/**
  4674 	 * Edit a post.
  5251 	 * Edit a post.
  4675 	 *
  5252 	 *
  4676 	 * @since 1.5.0
  5253 	 * @since 1.5.0
  4677 	 *
  5254 	 *
  4678 	 * @param array $args Method parameters.
  5255 	 * @param array  $args {
       
  5256 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  5257 	 *
       
  5258 	 *     @type int    $blog_id (unused)
       
  5259 	 *     @type string $username
       
  5260 	 *     @type string $password
       
  5261 	 *     @type array  $content_struct
       
  5262 	 *     @type int    $publish
       
  5263 	 * }
  4679 	 * @return bool|IXR_Error True on success.
  5264 	 * @return bool|IXR_Error True on success.
  4680 	 */
  5265 	 */
  4681 	public function mw_editPost($args) {
  5266 	public function mw_editPost( $args ) {
  4682 
  5267 		$this->escape( $args );
  4683 		$this->escape($args);
       
  4684 
  5268 
  4685 		$post_ID        = (int) $args[0];
  5269 		$post_ID        = (int) $args[0];
  4686 		$username       = $args[1];
  5270 		$username       = $args[1];
  4687 		$password       = $args[2];
  5271 		$password       = $args[2];
  4688 		$content_struct = $args[3];
  5272 		$content_struct = $args[3];
  4694 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5278 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4695 		do_action( 'xmlrpc_call', 'metaWeblog.editPost' );
  5279 		do_action( 'xmlrpc_call', 'metaWeblog.editPost' );
  4696 
  5280 
  4697 		$postdata = get_post( $post_ID, ARRAY_A );
  5281 		$postdata = get_post( $post_ID, ARRAY_A );
  4698 
  5282 
  4699 		// If there is no post data for the give post id, stop
  5283 		/*
  4700 		// now and return an error. Other wise a new post will be
  5284 		 * If there is no post data for the give post id, stop now and return an error.
  4701 		// created (which was the old behavior).
  5285 		 * Otherwise a new post will be created (which was the old behavior).
       
  5286 		 */
  4702 		if ( ! $postdata || empty( $postdata[ 'ID' ] ) )
  5287 		if ( ! $postdata || empty( $postdata[ 'ID' ] ) )
  4703 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  5288 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  4704 
  5289 
  4705 		if ( ! current_user_can( 'edit_post', $post_ID ) )
  5290 		if ( ! current_user_can( 'edit_post', $post_ID ) )
  4706 			return new IXR_Error( 401, __( 'Sorry, you do not have the right to edit this post.' ) );
  5291 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  4707 
  5292 
  4708 		// Use wp.editPost to edit post types other than post and page.
  5293 		// Use wp.editPost to edit post types other than post and page.
  4709 		if ( ! in_array( $postdata[ 'post_type' ], array( 'post', 'page' ) ) )
  5294 		if ( ! in_array( $postdata[ 'post_type' ], array( 'post', 'page' ) ) )
  4710 			return new IXR_Error( 401, __( 'Invalid post type' ) );
  5295 			return new IXR_Error( 401, __( 'Invalid post type.' ) );
  4711 
  5296 
  4712 		// Thwart attempt to change the post type.
  5297 		// Thwart attempt to change the post type.
  4713 		if ( ! empty( $content_struct[ 'post_type' ] ) && ( $content_struct['post_type'] != $postdata[ 'post_type' ] ) )
  5298 		if ( ! empty( $content_struct[ 'post_type' ] ) && ( $content_struct['post_type'] != $postdata[ 'post_type' ] ) )
  4714 			return new IXR_Error( 401, __( 'The post type may not be changed.' ) );
  5299 			return new IXR_Error( 401, __( 'The post type may not be changed.' ) );
  4715 
  5300 
  4716 		// Check for a valid post format if one was given
  5301 		// Check for a valid post format if one was given
  4717 		if ( isset( $content_struct['wp_post_format'] ) ) {
  5302 		if ( isset( $content_struct['wp_post_format'] ) ) {
  4718 			$content_struct['wp_post_format'] = sanitize_key( $content_struct['wp_post_format'] );
  5303 			$content_struct['wp_post_format'] = sanitize_key( $content_struct['wp_post_format'] );
  4719 			if ( !array_key_exists( $content_struct['wp_post_format'], get_post_format_strings() ) ) {
  5304 			if ( !array_key_exists( $content_struct['wp_post_format'], get_post_format_strings() ) ) {
  4720 				return new IXR_Error( 404, __( 'Invalid post format' ) );
  5305 				return new IXR_Error( 404, __( 'Invalid post format.' ) );
  4721 			}
  5306 			}
  4722 		}
  5307 		}
  4723 
  5308 
  4724 		$this->escape($postdata);
  5309 		$this->escape($postdata);
  4725 
  5310 
  4760 			// Check permissions if attempting to switch author to or from another user.
  5345 			// Check permissions if attempting to switch author to or from another user.
  4761 			if ( $user->ID != $content_struct['wp_author_id'] || $user->ID != $post_author ) {
  5346 			if ( $user->ID != $content_struct['wp_author_id'] || $user->ID != $post_author ) {
  4762 				switch ( $post_type ) {
  5347 				switch ( $post_type ) {
  4763 					case 'post':
  5348 					case 'post':
  4764 						if ( ! current_user_can( 'edit_others_posts' ) ) {
  5349 						if ( ! current_user_can( 'edit_others_posts' ) ) {
  4765 							return new IXR_Error( 401, __( 'You are not allowed to change the post author as this user.' ) );
  5350 							return new IXR_Error( 401, __( 'Sorry, you are not allowed to change the post author as this user.' ) );
  4766 						}
  5351 						}
  4767 						break;
  5352 						break;
  4768 					case 'page':
  5353 					case 'page':
  4769 						if ( ! current_user_can( 'edit_others_pages' ) ) {
  5354 						if ( ! current_user_can( 'edit_others_pages' ) ) {
  4770 							return new IXR_Error( 401, __( 'You are not allowed to change the page author as this user.' ) );
  5355 							return new IXR_Error( 401, __( 'Sorry, you are not allowed to change the page author as this user.' ) );
  4771 						}
  5356 						}
  4772 						break;
  5357 						break;
  4773 					default:
  5358 					default:
  4774 						return new IXR_Error( 401, __( 'Invalid post type' ) );
  5359 						return new IXR_Error( 401, __( 'Invalid post type.' ) );
  4775 						break;
       
  4776 				}
  5360 				}
  4777 				$post_author = $content_struct['wp_author_id'];
  5361 				$post_author = $content_struct['wp_author_id'];
  4778 			}
  5362 			}
  4779 		}
  5363 		}
  4780 
  5364 
  4786 						break;
  5370 						break;
  4787 					case 'open':
  5371 					case 'open':
  4788 						$comment_status = 'open';
  5372 						$comment_status = 'open';
  4789 						break;
  5373 						break;
  4790 					default:
  5374 					default:
  4791 						$comment_status = get_option('default_comment_status');
  5375 						$comment_status = get_default_comment_status( $post_type );
  4792 						break;
  5376 						break;
  4793 				}
  5377 				}
  4794 			} else {
  5378 			} else {
  4795 				switch ( (int) $content_struct['mt_allow_comments'] ) {
  5379 				switch ( (int) $content_struct['mt_allow_comments'] ) {
  4796 					case 0:
  5380 					case 0:
  4799 						break;
  5383 						break;
  4800 					case 1:
  5384 					case 1:
  4801 						$comment_status = 'open';
  5385 						$comment_status = 'open';
  4802 						break;
  5386 						break;
  4803 					default:
  5387 					default:
  4804 						$comment_status = get_option('default_comment_status');
  5388 						$comment_status = get_default_comment_status( $post_type );
  4805 						break;
  5389 						break;
  4806 				}
  5390 				}
  4807 			}
  5391 			}
  4808 		}
  5392 		}
  4809 
  5393 
  4815 						break;
  5399 						break;
  4816 					case 'open':
  5400 					case 'open':
  4817 						$ping_status = 'open';
  5401 						$ping_status = 'open';
  4818 						break;
  5402 						break;
  4819 					default:
  5403 					default:
  4820 						$ping_status = get_option('default_ping_status');
  5404 						$ping_status = get_default_comment_status( $post_type, 'pingback' );
  4821 						break;
  5405 						break;
  4822 				}
  5406 				}
  4823 			} else {
  5407 			} else {
  4824 				switch ( (int) $content_struct["mt_allow_pings"] ) {
  5408 				switch ( (int) $content_struct["mt_allow_pings"] ) {
  4825 					case 0:
  5409 					case 0:
  4827 						break;
  5411 						break;
  4828 					case 1:
  5412 					case 1:
  4829 						$ping_status = 'open';
  5413 						$ping_status = 'open';
  4830 						break;
  5414 						break;
  4831 					default:
  5415 					default:
  4832 						$ping_status = get_option('default_ping_status');
  5416 						$ping_status = get_default_comment_status( $post_type, 'pingback' );
  4833 						break;
  5417 						break;
  4834 				}
  5418 				}
  4835 			}
  5419 			}
  4836 		}
  5420 		}
  4837 
  5421 
  4871 			}
  5455 			}
  4872 		}
  5456 		}
  4873 
  5457 
  4874 		$tags_input = isset( $content_struct['mt_keywords'] ) ? $content_struct['mt_keywords'] : null;
  5458 		$tags_input = isset( $content_struct['mt_keywords'] ) ? $content_struct['mt_keywords'] : null;
  4875 
  5459 
  4876 		if ( ('publish' == $post_status) ) {
  5460 		if ( 'publish' == $post_status || 'private' == $post_status ) {
  4877 			if ( ( 'page' == $post_type ) && ! current_user_can( 'publish_pages' ) ) {
  5461 			if ( 'page' == $post_type && ! current_user_can( 'publish_pages' ) ) {
  4878 				return new IXR_Error( 401, __( 'Sorry, you do not have the right to publish this page.' ) );
  5462 				return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish this page.' ) );
  4879 			} elseif ( ! current_user_can( 'publish_posts' ) ) {
  5463 			} elseif ( ! current_user_can( 'publish_posts' ) ) {
  4880 				return new IXR_Error( 401, __( 'Sorry, you do not have the right to publish this post.' ) );
  5464 				return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish this post.' ) );
  4881 			}
  5465 			}
  4882 		}
  5466 		}
  4883 
  5467 
  4884 		if ( $post_more )
  5468 		if ( $post_more )
  4885 			$post_content = $post_content . "<!--more-->" . $post_more;
  5469 			$post_content = $post_content . "<!--more-->" . $post_more;
  4889 			$to_ping = $content_struct['mt_tb_ping_urls'];
  5473 			$to_ping = $content_struct['mt_tb_ping_urls'];
  4890 			if ( is_array($to_ping) )
  5474 			if ( is_array($to_ping) )
  4891 				$to_ping = implode(' ', $to_ping);
  5475 				$to_ping = implode(' ', $to_ping);
  4892 		}
  5476 		}
  4893 
  5477 
  4894 		// Do some timestamp voodoo
  5478 		// Do some timestamp voodoo.
  4895 		if ( !empty( $content_struct['date_created_gmt'] ) )
  5479 		if ( !empty( $content_struct['date_created_gmt'] ) )
  4896 			// We know this is supposed to be GMT, so we're going to slap that Z on there by force
  5480 			// We know this is supposed to be GMT, so we're going to slap that Z on there by force.
  4897 			$dateCreated = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
  5481 			$dateCreated = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
  4898 		elseif ( !empty( $content_struct['dateCreated']) )
  5482 		elseif ( !empty( $content_struct['dateCreated']) )
  4899 			$dateCreated = $content_struct['dateCreated']->getIso();
  5483 			$dateCreated = $content_struct['dateCreated']->getIso();
  4900 
  5484 
       
  5485 		// Default to not flagging the post date to be edited unless it's intentional.
       
  5486 		$edit_date = false;
       
  5487 
  4901 		if ( !empty( $dateCreated ) ) {
  5488 		if ( !empty( $dateCreated ) ) {
  4902 			$post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated));
  5489 			$post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated));
  4903 			$post_date_gmt = iso8601_to_datetime($dateCreated, 'GMT');
  5490 			$post_date_gmt = iso8601_to_datetime($dateCreated, 'GMT');
       
  5491 
       
  5492 			// Flag the post date to be edited.
       
  5493 			$edit_date = true;
  4904 		} else {
  5494 		} else {
  4905 			$post_date     = $postdata['post_date'];
  5495 			$post_date     = $postdata['post_date'];
  4906 			$post_date_gmt = $postdata['post_date_gmt'];
  5496 			$post_date_gmt = $postdata['post_date_gmt'];
  4907 		}
  5497 		}
  4908 
  5498 
  4909 		// We've got all the data -- post it:
  5499 		// We've got all the data -- post it.
  4910 		$newpost = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'post_date', 'post_date_gmt', 'to_ping', 'post_name', 'post_password', 'post_parent', 'menu_order', 'post_author', 'tags_input', 'page_template');
  5500 		$newpost = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'edit_date', 'post_date', 'post_date_gmt', 'to_ping', 'post_name', 'post_password', 'post_parent', 'menu_order', 'post_author', 'tags_input', 'page_template');
  4911 
  5501 
  4912 		$result = wp_update_post($newpost, true);
  5502 		$result = wp_update_post($newpost, true);
  4913 		if ( is_wp_error( $result ) )
  5503 		if ( is_wp_error( $result ) )
  4914 			return new IXR_Error(500, $result->get_error_message());
  5504 			return new IXR_Error(500, $result->get_error_message());
  4915 
  5505 
  4916 		if ( !$result )
  5506 		if ( !$result )
  4917 			return new IXR_Error(500, __('Sorry, your entry could not be edited. Something wrong happened.'));
  5507 			return new IXR_Error(500, __('Sorry, your entry could not be edited.'));
  4918 
  5508 
  4919 		// Only posts can be sticky
  5509 		// Only posts can be sticky
  4920 		if ( $post_type == 'post' && isset( $content_struct['sticky'] ) ) {
  5510 		if ( $post_type == 'post' && isset( $content_struct['sticky'] ) ) {
  4921 			if ( $content_struct['sticky'] == true )
  5511 			$data = $newpost;
  4922 				stick_post( $post_ID );
  5512 			$data['sticky'] = $content_struct['sticky'];
  4923 			elseif ( $content_struct['sticky'] == false )
  5513 			$data['post_type'] = 'post';
  4924 				unstick_post( $post_ID );
  5514 			$error = $this->_toggle_sticky( $data, true );
       
  5515 			if ( $error ) {
       
  5516 				return $error;
       
  5517 			}
  4925 		}
  5518 		}
  4926 
  5519 
  4927 		if ( isset($content_struct['custom_fields']) )
  5520 		if ( isset($content_struct['custom_fields']) )
  4928 			$this->set_custom_fields($post_ID, $content_struct['custom_fields']);
  5521 			$this->set_custom_fields($post_ID, $content_struct['custom_fields']);
  4929 
  5522 
  4930 		if ( isset ( $content_struct['wp_post_thumbnail'] ) ) {
  5523 		if ( isset ( $content_struct['wp_post_thumbnail'] ) ) {
  4931 			// empty value deletes, non-empty value adds/updates
  5524 
       
  5525 			// Empty value deletes, non-empty value adds/updates.
  4932 			if ( empty( $content_struct['wp_post_thumbnail'] ) ) {
  5526 			if ( empty( $content_struct['wp_post_thumbnail'] ) ) {
  4933 				delete_post_thumbnail( $post_ID );
  5527 				delete_post_thumbnail( $post_ID );
  4934 			} else {
  5528 			} else {
  4935 				if ( set_post_thumbnail( $post_ID, $content_struct['wp_post_thumbnail'] ) === false )
  5529 				if ( set_post_thumbnail( $post_ID, $content_struct['wp_post_thumbnail'] ) === false )
  4936 					return new IXR_Error( 404, __( 'Invalid attachment ID.' ) );
  5530 					return new IXR_Error( 404, __( 'Invalid attachment ID.' ) );
  4937 			}
  5531 			}
  4938 			unset( $content_struct['wp_post_thumbnail'] );
  5532 			unset( $content_struct['wp_post_thumbnail'] );
  4939 		}
  5533 		}
  4940 
  5534 
  4941 		// Handle enclosures
  5535 		// Handle enclosures.
  4942 		$thisEnclosure = isset($content_struct['enclosure']) ? $content_struct['enclosure'] : null;
  5536 		$thisEnclosure = isset($content_struct['enclosure']) ? $content_struct['enclosure'] : null;
  4943 		$this->add_enclosure_if_new($post_ID, $thisEnclosure);
  5537 		$this->add_enclosure_if_new($post_ID, $thisEnclosure);
  4944 
  5538 
  4945 		$this->attach_uploads( $ID, $post_content );
  5539 		$this->attach_uploads( $ID, $post_content );
  4946 
  5540 
  4947 		// Handle post formats if assigned, validation is handled
  5541 		// Handle post formats if assigned, validation is handled earlier in this function.
  4948 		// earlier in this function
       
  4949 		if ( isset( $content_struct['wp_post_format'] ) )
  5542 		if ( isset( $content_struct['wp_post_format'] ) )
  4950 			set_post_format( $post_ID, $content_struct['wp_post_format'] );
  5543 			set_post_format( $post_ID, $content_struct['wp_post_format'] );
  4951 
  5544 
  4952 		/**
  5545 		/**
  4953 		 * Fires after a post has been successfully updated via the XML-RPC MovableType API.
  5546 		 * Fires after a post has been successfully updated via the XML-RPC MovableType API.
  4965 	/**
  5558 	/**
  4966 	 * Retrieve post.
  5559 	 * Retrieve post.
  4967 	 *
  5560 	 *
  4968 	 * @since 1.5.0
  5561 	 * @since 1.5.0
  4969 	 *
  5562 	 *
  4970 	 * @param array $args Method parameters.
  5563 	 * @param array  $args {
       
  5564 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  5565 	 *
       
  5566 	 *     @type int    $blog_id (unused)
       
  5567 	 *     @type int    $post_ID
       
  5568 	 *     @type string $username
       
  5569 	 *     @type string $password
       
  5570 	 * }
  4971 	 * @return array|IXR_Error
  5571 	 * @return array|IXR_Error
  4972 	 */
  5572 	 */
  4973 	public function mw_getPost($args) {
  5573 	public function mw_getPost( $args ) {
  4974 
  5574 		$this->escape( $args );
  4975 		$this->escape($args);
  5575 
  4976 
  5576 		$post_ID  = (int) $args[0];
  4977 		$post_ID     = (int) $args[0];
  5577 		$username = $args[1];
  4978 		$username  = $args[1];
  5578 		$password = $args[2];
  4979 		$password   = $args[2];
       
  4980 
  5579 
  4981 		if ( !$user = $this->login($username, $password) )
  5580 		if ( !$user = $this->login($username, $password) )
  4982 			return $this->error;
  5581 			return $this->error;
  4983 
  5582 
  4984 		$postdata = get_post($post_ID, ARRAY_A);
  5583 		$postdata = get_post($post_ID, ARRAY_A);
  4985 		if ( ! $postdata )
  5584 		if ( ! $postdata )
  4986 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  5585 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  4987 
  5586 
  4988 		if ( !current_user_can( 'edit_post', $post_ID ) )
  5587 		if ( !current_user_can( 'edit_post', $post_ID ) )
  4989 			return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) );
  5588 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  4990 
  5589 
  4991 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5590 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  4992 		do_action( 'xmlrpc_call', 'metaWeblog.getPost' );
  5591 		do_action( 'xmlrpc_call', 'metaWeblog.getPost' );
  4993 
  5592 
  4994 		if ($postdata['post_date'] != '') {
  5593 		if ($postdata['post_date'] != '') {
  4997 			$post_modified = $this->_convert_date( $postdata['post_modified'] );
  5596 			$post_modified = $this->_convert_date( $postdata['post_modified'] );
  4998 			$post_modified_gmt = $this->_convert_date_gmt( $postdata['post_modified_gmt'], $postdata['post_modified'] );
  5597 			$post_modified_gmt = $this->_convert_date_gmt( $postdata['post_modified_gmt'], $postdata['post_modified'] );
  4999 
  5598 
  5000 			$categories = array();
  5599 			$categories = array();
  5001 			$catids = wp_get_post_categories($post_ID);
  5600 			$catids = wp_get_post_categories($post_ID);
  5002 			foreach($catids as $catid)
  5601 			foreach ($catids as $catid)
  5003 				$categories[] = get_cat_name($catid);
  5602 				$categories[] = get_cat_name($catid);
  5004 
  5603 
  5005 			$tagnames = array();
  5604 			$tagnames = array();
  5006 			$tags = wp_get_post_tags( $post_ID );
  5605 			$tags = wp_get_post_tags( $post_ID );
  5007 			if ( !empty( $tags ) ) {
  5606 			if ( !empty( $tags ) ) {
  5011 			} else {
  5610 			} else {
  5012 				$tagnames = '';
  5611 				$tagnames = '';
  5013 			}
  5612 			}
  5014 
  5613 
  5015 			$post = get_extended($postdata['post_content']);
  5614 			$post = get_extended($postdata['post_content']);
  5016 			$link = post_permalink($postdata['ID']);
  5615 			$link = get_permalink($postdata['ID']);
  5017 
  5616 
  5018 			// Get the author info.
  5617 			// Get the author info.
  5019 			$author = get_userdata($postdata['post_author']);
  5618 			$author = get_userdata($postdata['post_author']);
  5020 
  5619 
  5021 			$allow_comments = ('open' == $postdata['comment_status']) ? 1 : 0;
  5620 			$allow_comments = ('open' == $postdata['comment_status']) ? 1 : 0;
  5090 	/**
  5689 	/**
  5091 	 * Retrieve list of recent posts.
  5690 	 * Retrieve list of recent posts.
  5092 	 *
  5691 	 *
  5093 	 * @since 1.5.0
  5692 	 * @since 1.5.0
  5094 	 *
  5693 	 *
  5095 	 * @param array $args Method parameters.
  5694 	 * @param array  $args {
       
  5695 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  5696 	 *
       
  5697 	 *     @type int    $blog_id (unused)
       
  5698 	 *     @type string $username
       
  5699 	 *     @type string $password
       
  5700 	 *     @type int    $numberposts
       
  5701 	 * }
  5096 	 * @return array|IXR_Error
  5702 	 * @return array|IXR_Error
  5097 	 */
  5703 	 */
  5098 	public function mw_getRecentPosts($args) {
  5704 	public function mw_getRecentPosts( $args ) {
  5099 
  5705 		$this->escape( $args );
  5100 		$this->escape($args);
  5706 
  5101 
  5707 		$username = $args[1];
  5102 		$username  = $args[1];
  5708 		$password = $args[2];
  5103 		$password   = $args[2];
       
  5104 		if ( isset( $args[3] ) )
  5709 		if ( isset( $args[3] ) )
  5105 			$query = array( 'numberposts' => absint( $args[3] ) );
  5710 			$query = array( 'numberposts' => absint( $args[3] ) );
  5106 		else
  5711 		else
  5107 			$query = array();
  5712 			$query = array();
  5108 
  5713 
  5109 		if ( !$user = $this->login($username, $password) )
  5714 		if ( !$user = $this->login($username, $password) )
  5110 			return $this->error;
  5715 			return $this->error;
  5111 
  5716 
  5112 		if ( ! current_user_can( 'edit_posts' ) )
  5717 		if ( ! current_user_can( 'edit_posts' ) )
  5113 			return new IXR_Error( 401, __( 'Sorry, you cannot edit posts on this site.' ) );
  5718 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit posts.' ) );
  5114 
  5719 
  5115 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5720 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5116 		do_action( 'xmlrpc_call', 'metaWeblog.getRecentPosts' );
  5721 		do_action( 'xmlrpc_call', 'metaWeblog.getRecentPosts' );
  5117 
  5722 
  5118 		$posts_list = wp_get_recent_posts( $query );
  5723 		$posts_list = wp_get_recent_posts( $query );
  5130 			$post_modified = $this->_convert_date( $entry['post_modified'] );
  5735 			$post_modified = $this->_convert_date( $entry['post_modified'] );
  5131 			$post_modified_gmt = $this->_convert_date_gmt( $entry['post_modified_gmt'], $entry['post_modified'] );
  5736 			$post_modified_gmt = $this->_convert_date_gmt( $entry['post_modified_gmt'], $entry['post_modified'] );
  5132 
  5737 
  5133 			$categories = array();
  5738 			$categories = array();
  5134 			$catids = wp_get_post_categories($entry['ID']);
  5739 			$catids = wp_get_post_categories($entry['ID']);
  5135 			foreach( $catids as $catid )
  5740 			foreach ( $catids as $catid )
  5136 				$categories[] = get_cat_name($catid);
  5741 				$categories[] = get_cat_name($catid);
  5137 
  5742 
  5138 			$tagnames = array();
  5743 			$tagnames = array();
  5139 			$tags = wp_get_post_tags( $entry['ID'] );
  5744 			$tags = wp_get_post_tags( $entry['ID'] );
  5140 			if ( !empty( $tags ) ) {
  5745 			if ( !empty( $tags ) ) {
  5145 			} else {
  5750 			} else {
  5146 				$tagnames = '';
  5751 				$tagnames = '';
  5147 			}
  5752 			}
  5148 
  5753 
  5149 			$post = get_extended($entry['post_content']);
  5754 			$post = get_extended($entry['post_content']);
  5150 			$link = post_permalink($entry['ID']);
  5755 			$link = get_permalink($entry['ID']);
  5151 
  5756 
  5152 			// Get the post author info.
  5757 			// Get the post author info.
  5153 			$author = get_userdata($entry['post_author']);
  5758 			$author = get_userdata($entry['post_author']);
  5154 
  5759 
  5155 			$allow_comments = ('open' == $entry['comment_status']) ? 1 : 0;
  5760 			$allow_comments = ('open' == $entry['comment_status']) ? 1 : 0;
  5202 	/**
  5807 	/**
  5203 	 * Retrieve the list of categories on a given blog.
  5808 	 * Retrieve the list of categories on a given blog.
  5204 	 *
  5809 	 *
  5205 	 * @since 1.5.0
  5810 	 * @since 1.5.0
  5206 	 *
  5811 	 *
  5207 	 * @param array $args Method parameters.
  5812 	 * @param array  $args {
       
  5813 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  5814 	 *
       
  5815 	 *     @type int    $blog_id (unused)
       
  5816 	 *     @type string $username
       
  5817 	 *     @type string $password
       
  5818 	 * }
  5208 	 * @return array|IXR_Error
  5819 	 * @return array|IXR_Error
  5209 	 */
  5820 	 */
  5210 	public function mw_getCategories($args) {
  5821 	public function mw_getCategories( $args ) {
  5211 
  5822 		$this->escape( $args );
  5212 		$this->escape($args);
  5823 
  5213 
  5824 		$username = $args[1];
  5214 		$username  = $args[1];
  5825 		$password = $args[2];
  5215 		$password   = $args[2];
       
  5216 
  5826 
  5217 		if ( !$user = $this->login($username, $password) )
  5827 		if ( !$user = $this->login($username, $password) )
  5218 			return $this->error;
  5828 			return $this->error;
  5219 
  5829 
  5220 		if ( !current_user_can( 'edit_posts' ) )
  5830 		if ( !current_user_can( 'edit_posts' ) )
  5250 	 *
  5860 	 *
  5251 	 * @link http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/
  5861 	 * @link http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/
  5252 	 *
  5862 	 *
  5253 	 * @since 1.5.0
  5863 	 * @since 1.5.0
  5254 	 *
  5864 	 *
  5255 	 * @param array $args Method parameters.
  5865 	 * @global wpdb $wpdb WordPress database abstraction object.
       
  5866 	 *
       
  5867 	 * @param array  $args {
       
  5868 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  5869 	 *
       
  5870 	 *     @type int    $blog_id (unused)
       
  5871 	 *     @type string $username
       
  5872 	 *     @type string $password
       
  5873 	 *     @type array  $data
       
  5874 	 * }
  5256 	 * @return array|IXR_Error
  5875 	 * @return array|IXR_Error
  5257 	 */
  5876 	 */
  5258 	public function mw_newMediaObject($args) {
  5877 	public function mw_newMediaObject( $args ) {
  5259 		global $wpdb;
  5878 		global $wpdb;
  5260 
  5879 
  5261 		$username  = $this->escape($args[1]);
  5880 		$username = $this->escape( $args[1] );
  5262 		$password   = $this->escape($args[2]);
  5881 		$password = $this->escape( $args[2] );
  5263 		$data        = $args[3];
  5882 		$data     = $args[3];
  5264 
  5883 
  5265 		$name = sanitize_file_name( $data['name'] );
  5884 		$name = sanitize_file_name( $data['name'] );
  5266 		$type = $data['type'];
  5885 		$type = $data['type'];
  5267 		$bits = $data['bits'];
  5886 		$bits = $data['bits'];
  5268 
  5887 
  5271 
  5890 
  5272 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5891 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5273 		do_action( 'xmlrpc_call', 'metaWeblog.newMediaObject' );
  5892 		do_action( 'xmlrpc_call', 'metaWeblog.newMediaObject' );
  5274 
  5893 
  5275 		if ( !current_user_can('upload_files') ) {
  5894 		if ( !current_user_can('upload_files') ) {
  5276 			$this->error = new IXR_Error( 401, __( 'You do not have permission to upload files.' ) );
  5895 			$this->error = new IXR_Error( 401, __( 'Sorry, you are not allowed to upload files.' ) );
       
  5896 			return $this->error;
       
  5897 		}
       
  5898 
       
  5899 		if ( is_multisite() && upload_is_user_over_quota( false ) ) {
       
  5900 			$this->error = new IXR_Error( 401, __( 'Sorry, you have used your space allocation.' ) );
  5277 			return $this->error;
  5901 			return $this->error;
  5278 		}
  5902 		}
  5279 
  5903 
  5280 		/**
  5904 		/**
  5281 		 * Filter whether to preempt the XML-RPC media upload.
  5905 		 * Filters whether to preempt the XML-RPC media upload.
  5282 		 *
  5906 		 *
  5283 		 * Passing a truthy value will effectively short-circuit the media upload,
  5907 		 * Passing a truthy value will effectively short-circuit the media upload,
  5284 		 * returning that value as a 500 error instead.
  5908 		 * returning that value as a 500 error instead.
  5285 		 *
  5909 		 *
  5286 		 * @since 2.1.0
  5910 		 * @since 2.1.0
  5289 		 */
  5913 		 */
  5290 		if ( $upload_err = apply_filters( 'pre_upload_error', false ) ) {
  5914 		if ( $upload_err = apply_filters( 'pre_upload_error', false ) ) {
  5291 			return new IXR_Error( 500, $upload_err );
  5915 			return new IXR_Error( 500, $upload_err );
  5292 		}
  5916 		}
  5293 
  5917 
  5294 		if ( !empty($data['overwrite']) && ($data['overwrite'] == true) ) {
       
  5295 			// Get postmeta info on the object.
       
  5296 			$old_file = $wpdb->get_row("
       
  5297 				SELECT ID
       
  5298 				FROM {$wpdb->posts}
       
  5299 				WHERE post_title = '{$name}'
       
  5300 					AND post_type = 'attachment'
       
  5301 			");
       
  5302 
       
  5303 			// Delete previous file.
       
  5304 			wp_delete_attachment($old_file->ID);
       
  5305 
       
  5306 			// Make sure the new name is different by pre-pending the
       
  5307 			// previous post id.
       
  5308 			$filename = preg_replace('/^wpid\d+-/', '', $name);
       
  5309 			$name = "wpid{$old_file->ID}-{$filename}";
       
  5310 		}
       
  5311 
       
  5312 		$upload = wp_upload_bits($name, null, $bits);
  5918 		$upload = wp_upload_bits($name, null, $bits);
  5313 		if ( ! empty($upload['error']) ) {
  5919 		if ( ! empty($upload['error']) ) {
  5314 			$errorString = sprintf(__('Could not write file %1$s (%2$s)'), $name, $upload['error']);
  5920 			/* translators: 1: file name, 2: error message */
  5315 			return new IXR_Error(500, $errorString);
  5921 			$errorString = sprintf( __( 'Could not write file %1$s (%2$s).' ), $name, $upload['error'] );
       
  5922 			return new IXR_Error( 500, $errorString );
  5316 		}
  5923 		}
  5317 		// Construct the attachment array
  5924 		// Construct the attachment array
  5318 		$post_id = 0;
  5925 		$post_id = 0;
  5319 		if ( ! empty( $data['post_id'] ) ) {
  5926 		if ( ! empty( $data['post_id'] ) ) {
  5320 			$post_id = (int) $data['post_id'];
  5927 			$post_id = (int) $data['post_id'];
  5321 
  5928 
  5322 			if ( ! current_user_can( 'edit_post', $post_id ) )
  5929 			if ( ! current_user_can( 'edit_post', $post_id ) )
  5323 				return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) );
  5930 				return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  5324 		}
  5931 		}
  5325 		$attachment = array(
  5932 		$attachment = array(
  5326 			'post_title' => $name,
  5933 			'post_title' => $name,
  5327 			'post_content' => '',
  5934 			'post_content' => '',
  5328 			'post_type' => 'attachment',
  5935 			'post_type' => 'attachment',
  5343 		 * @param int   $id   ID of the new attachment.
  5950 		 * @param int   $id   ID of the new attachment.
  5344 		 * @param array $args An array of arguments to add the attachment.
  5951 		 * @param array $args An array of arguments to add the attachment.
  5345 		 */
  5952 		 */
  5346 		do_action( 'xmlrpc_call_success_mw_newMediaObject', $id, $args );
  5953 		do_action( 'xmlrpc_call_success_mw_newMediaObject', $id, $args );
  5347 
  5954 
  5348 		$struct = array(
  5955 		$struct = $this->_prepare_media_item( get_post( $id ) );
  5349 			'id'   => strval( $id ),
  5956 
  5350 			'file' => $name,
  5957 		// Deprecated values
  5351 			'url'  => $upload[ 'url' ],
  5958 		$struct['id']   = $struct['attachment_id'];
  5352 			'type' => $type
  5959 		$struct['file'] = $struct['title'];
  5353 		);
  5960 		$struct['url']  = $struct['link'];
  5354 
  5961 
  5355 		/** This filter is documented in wp-admin/includes/file.php */
  5962 		return $struct;
  5356 		return apply_filters( 'wp_handle_upload', $struct, 'upload' );
       
  5357 	}
  5963 	}
  5358 
  5964 
  5359 	/* MovableType API functions
  5965 	/* MovableType API functions
  5360 	 * specs on http://www.movabletype.org/docs/mtmanual_programmatic.html
  5966 	 * specs on http://www.movabletype.org/docs/mtmanual_programmatic.html
  5361 	 */
  5967 	 */
  5363 	/**
  5969 	/**
  5364 	 * Retrieve the post titles of recent posts.
  5970 	 * Retrieve the post titles of recent posts.
  5365 	 *
  5971 	 *
  5366 	 * @since 1.5.0
  5972 	 * @since 1.5.0
  5367 	 *
  5973 	 *
  5368 	 * @param array $args Method parameters.
  5974 	 * @param array  $args {
       
  5975 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  5976 	 *
       
  5977 	 *     @type int    $blog_id (unused)
       
  5978 	 *     @type string $username
       
  5979 	 *     @type string $password
       
  5980 	 *     @type int    $numberposts
       
  5981 	 * }
  5369 	 * @return array|IXR_Error
  5982 	 * @return array|IXR_Error
  5370 	 */
  5983 	 */
  5371 	public function mt_getRecentPostTitles($args) {
  5984 	public function mt_getRecentPostTitles( $args ) {
  5372 
  5985 		$this->escape( $args );
  5373 		$this->escape($args);
  5986 
  5374 
  5987 		$username = $args[1];
  5375 		$username  = $args[1];
  5988 		$password = $args[2];
  5376 		$password   = $args[2];
       
  5377 		if ( isset( $args[3] ) )
  5989 		if ( isset( $args[3] ) )
  5378 			$query = array( 'numberposts' => absint( $args[3] ) );
  5990 			$query = array( 'numberposts' => absint( $args[3] ) );
  5379 		else
  5991 		else
  5380 			$query = array();
  5992 			$query = array();
  5381 
  5993 
  5417 	/**
  6029 	/**
  5418 	 * Retrieve list of all categories on blog.
  6030 	 * Retrieve list of all categories on blog.
  5419 	 *
  6031 	 *
  5420 	 * @since 1.5.0
  6032 	 * @since 1.5.0
  5421 	 *
  6033 	 *
  5422 	 * @param array $args Method parameters.
  6034 	 * @param array  $args {
       
  6035 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  6036 	 *
       
  6037 	 *     @type int    $blog_id (unused)
       
  6038 	 *     @type string $username
       
  6039 	 *     @type string $password
       
  6040 	 * }
  5423 	 * @return array|IXR_Error
  6041 	 * @return array|IXR_Error
  5424 	 */
  6042 	 */
  5425 	public function mt_getCategoryList($args) {
  6043 	public function mt_getCategoryList( $args ) {
  5426 
  6044 		$this->escape( $args );
  5427 		$this->escape($args);
  6045 
  5428 
  6046 		$username = $args[1];
  5429 		$username  = $args[1];
  6047 		$password = $args[2];
  5430 		$password   = $args[2];
       
  5431 
  6048 
  5432 		if ( !$user = $this->login($username, $password) )
  6049 		if ( !$user = $this->login($username, $password) )
  5433 			return $this->error;
  6050 			return $this->error;
  5434 
  6051 
  5435 		if ( !current_user_can( 'edit_posts' ) )
  6052 		if ( !current_user_can( 'edit_posts' ) )
  5456 	/**
  6073 	/**
  5457 	 * Retrieve post categories.
  6074 	 * Retrieve post categories.
  5458 	 *
  6075 	 *
  5459 	 * @since 1.5.0
  6076 	 * @since 1.5.0
  5460 	 *
  6077 	 *
  5461 	 * @param array $args Method parameters.
  6078 	 * @param array  $args {
       
  6079 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  6080 	 *
       
  6081 	 *     @type int    $post_ID
       
  6082 	 *     @type string $username
       
  6083 	 *     @type string $password
       
  6084 	 * }
  5462 	 * @return array|IXR_Error
  6085 	 * @return array|IXR_Error
  5463 	 */
  6086 	 */
  5464 	public function mt_getPostCategories($args) {
  6087 	public function mt_getPostCategories( $args ) {
  5465 
  6088 		$this->escape( $args );
  5466 		$this->escape($args);
  6089 
  5467 
  6090 		$post_ID  = (int) $args[0];
  5468 		$post_ID     = (int) $args[0];
  6091 		$username = $args[1];
  5469 		$username  = $args[1];
  6092 		$password = $args[2];
  5470 		$password   = $args[2];
       
  5471 
  6093 
  5472 		if ( !$user = $this->login($username, $password) )
  6094 		if ( !$user = $this->login($username, $password) )
  5473 			return $this->error;
  6095 			return $this->error;
  5474 
  6096 
  5475 		if ( ! get_post( $post_ID ) )
  6097 		if ( ! get_post( $post_ID ) )
  5476 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  6098 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  5477 
  6099 
  5478 		if ( !current_user_can( 'edit_post', $post_ID ) )
  6100 		if ( !current_user_can( 'edit_post', $post_ID ) )
  5479 			return new IXR_Error( 401, __( 'Sorry, you can not edit this post.' ) );
  6101 			return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) );
  5480 
  6102 
  5481 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6103 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5482 		do_action( 'xmlrpc_call', 'mt.getPostCategories' );
  6104 		do_action( 'xmlrpc_call', 'mt.getPostCategories' );
  5483 
  6105 
  5484 		$categories = array();
  6106 		$categories = array();
  5500 	/**
  6122 	/**
  5501 	 * Sets categories for a post.
  6123 	 * Sets categories for a post.
  5502 	 *
  6124 	 *
  5503 	 * @since 1.5.0
  6125 	 * @since 1.5.0
  5504 	 *
  6126 	 *
  5505 	 * @param array $args Method parameters.
  6127 	 * @param array  $args {
  5506 	 * @return bool|IXR_Error True on success.
  6128 	 *     Method arguments. Note: arguments must be ordered as documented.
  5507 	 */
  6129 	 *
  5508 	public function mt_setPostCategories($args) {
  6130 	 *     @type int    $post_ID
  5509 
  6131 	 *     @type string $username
  5510 		$this->escape($args);
  6132 	 *     @type string $password
  5511 
  6133 	 *     @type array  $categories
  5512 		$post_ID     = (int) $args[0];
  6134 	 * }
  5513 		$username  = $args[1];
  6135 	 * @return true|IXR_Error True on success.
       
  6136 	 */
       
  6137 	public function mt_setPostCategories( $args ) {
       
  6138 		$this->escape( $args );
       
  6139 
       
  6140 		$post_ID    = (int) $args[0];
       
  6141 		$username   = $args[1];
  5514 		$password   = $args[2];
  6142 		$password   = $args[2];
  5515 		$categories  = $args[3];
  6143 		$categories = $args[3];
  5516 
  6144 
  5517 		if ( !$user = $this->login($username, $password) )
  6145 		if ( !$user = $this->login($username, $password) )
  5518 			return $this->error;
  6146 			return $this->error;
  5519 
  6147 
  5520 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6148 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5522 
  6150 
  5523 		if ( ! get_post( $post_ID ) )
  6151 		if ( ! get_post( $post_ID ) )
  5524 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  6152 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  5525 
  6153 
  5526 		if ( !current_user_can('edit_post', $post_ID) )
  6154 		if ( !current_user_can('edit_post', $post_ID) )
  5527 			return new IXR_Error(401, __('Sorry, you cannot edit this post.'));
  6155 			return new IXR_Error(401, __('Sorry, you are not allowed to edit this post.'));
  5528 
  6156 
  5529 		$catids = array();
  6157 		$catids = array();
  5530 		foreach ( $categories as $cat ) {
  6158 		foreach ( $categories as $cat ) {
  5531 			$catids[] = $cat['categoryId'];
  6159 			$catids[] = $cat['categoryId'];
  5532 		}
  6160 		}
  5539 	/**
  6167 	/**
  5540 	 * Retrieve an array of methods supported by this server.
  6168 	 * Retrieve an array of methods supported by this server.
  5541 	 *
  6169 	 *
  5542 	 * @since 1.5.0
  6170 	 * @since 1.5.0
  5543 	 *
  6171 	 *
  5544 	 * @param array $args Method parameters.
       
  5545 	 * @return array
  6172 	 * @return array
  5546 	 */
  6173 	 */
  5547 	public function mt_supportedMethods($args) {
  6174 	public function mt_supportedMethods() {
  5548 
       
  5549 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6175 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5550 		do_action( 'xmlrpc_call', 'mt.supportedMethods' );
  6176 		do_action( 'xmlrpc_call', 'mt.supportedMethods' );
  5551 
  6177 
  5552 		$supported_methods = array();
  6178 		return array_keys( $this->methods );
  5553 		foreach ( $this->methods as $key => $value ) {
       
  5554 			$supported_methods[] = $key;
       
  5555 		}
       
  5556 
       
  5557 		return $supported_methods;
       
  5558 	}
  6179 	}
  5559 
  6180 
  5560 	/**
  6181 	/**
  5561 	 * Retrieve an empty array because we don't support per-post text filters.
  6182 	 * Retrieve an empty array because we don't support per-post text filters.
  5562 	 *
  6183 	 *
  5563 	 * @since 1.5.0
  6184 	 * @since 1.5.0
  5564 	 *
  6185 	 */
  5565 	 * @param array $args Method parameters.
  6186 	public function mt_supportedTextFilters() {
  5566 	 */
       
  5567 	public function mt_supportedTextFilters($args) {
       
  5568 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6187 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5569 		do_action( 'xmlrpc_call', 'mt.supportedTextFilters' );
  6188 		do_action( 'xmlrpc_call', 'mt.supportedTextFilters' );
  5570 
  6189 
  5571 		/**
  6190 		/**
  5572 		 * Filter the MoveableType text filters list for XML-RPC.
  6191 		 * Filters the MoveableType text filters list for XML-RPC.
  5573 		 *
  6192 		 *
  5574 		 * @since 2.2.0
  6193 		 * @since 2.2.0
  5575 		 *
  6194 		 *
  5576 		 * @param array $filters An array of text filters.
  6195 		 * @param array $filters An array of text filters.
  5577 		 */
  6196 		 */
  5581 	/**
  6200 	/**
  5582 	 * Retrieve trackbacks sent to a given post.
  6201 	 * Retrieve trackbacks sent to a given post.
  5583 	 *
  6202 	 *
  5584 	 * @since 1.5.0
  6203 	 * @since 1.5.0
  5585 	 *
  6204 	 *
  5586 	 * @param array $args Method parameters.
  6205 	 * @global wpdb $wpdb WordPress database abstraction object.
       
  6206 	 *
       
  6207 	 * @param int $post_ID
  5587 	 * @return array|IXR_Error
  6208 	 * @return array|IXR_Error
  5588 	 */
  6209 	 */
  5589 	public function mt_getTrackbackPings($args) {
  6210 	public function mt_getTrackbackPings( $post_ID ) {
  5590 
       
  5591 		global $wpdb;
  6211 		global $wpdb;
  5592 
       
  5593 		$post_ID = intval($args);
       
  5594 
  6212 
  5595 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6213 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5596 		do_action( 'xmlrpc_call', 'mt.getTrackbackPings' );
  6214 		do_action( 'xmlrpc_call', 'mt.getTrackbackPings' );
  5597 
  6215 
  5598 		$actual_post = get_post($post_ID, ARRAY_A);
  6216 		$actual_post = get_post($post_ID, ARRAY_A);
  5624 	/**
  6242 	/**
  5625 	 * Sets a post's publish status to 'publish'.
  6243 	 * Sets a post's publish status to 'publish'.
  5626 	 *
  6244 	 *
  5627 	 * @since 1.5.0
  6245 	 * @since 1.5.0
  5628 	 *
  6246 	 *
  5629 	 * @param array $args Method parameters.
  6247 	 * @param array  $args {
       
  6248 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  6249 	 *
       
  6250 	 *     @type int    $post_ID
       
  6251 	 *     @type string $username
       
  6252 	 *     @type string $password
       
  6253 	 * }
  5630 	 * @return int|IXR_Error
  6254 	 * @return int|IXR_Error
  5631 	 */
  6255 	 */
  5632 	public function mt_publishPost($args) {
  6256 	public function mt_publishPost( $args ) {
  5633 
  6257 		$this->escape( $args );
  5634 		$this->escape($args);
  6258 
  5635 
  6259 		$post_ID  = (int) $args[0];
  5636 		$post_ID     = (int) $args[0];
  6260 		$username = $args[1];
  5637 		$username  = $args[1];
  6261 		$password = $args[2];
  5638 		$password   = $args[2];
       
  5639 
  6262 
  5640 		if ( !$user = $this->login($username, $password) )
  6263 		if ( !$user = $this->login($username, $password) )
  5641 			return $this->error;
  6264 			return $this->error;
  5642 
  6265 
  5643 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6266 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5646 		$postdata = get_post($post_ID, ARRAY_A);
  6269 		$postdata = get_post($post_ID, ARRAY_A);
  5647 		if ( ! $postdata )
  6270 		if ( ! $postdata )
  5648 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  6271 			return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  5649 
  6272 
  5650 		if ( !current_user_can('publish_posts') || !current_user_can('edit_post', $post_ID) )
  6273 		if ( !current_user_can('publish_posts') || !current_user_can('edit_post', $post_ID) )
  5651 			return new IXR_Error(401, __('Sorry, you cannot publish this post.'));
  6274 			return new IXR_Error(401, __('Sorry, you are not allowed to publish this post.'));
  5652 
  6275 
  5653 		$postdata['post_status'] = 'publish';
  6276 		$postdata['post_status'] = 'publish';
  5654 
  6277 
  5655 		// retain old cats
  6278 		// retain old cats
  5656 		$cats = wp_get_post_categories($post_ID);
  6279 		$cats = wp_get_post_categories($post_ID);
  5657 		$postdata['post_category'] = $cats;
  6280 		$postdata['post_category'] = $cats;
  5658 		$this->escape($postdata);
  6281 		$this->escape($postdata);
  5659 
  6282 
  5660 		$result = wp_update_post($postdata);
  6283 		return wp_update_post( $postdata );
  5661 
       
  5662 		return $result;
       
  5663 	}
  6284 	}
  5664 
  6285 
  5665 	/* PingBack functions
  6286 	/* PingBack functions
  5666 	 * specs on www.hixie.ch/specs/pingback/pingback
  6287 	 * specs on www.hixie.ch/specs/pingback/pingback
  5667 	 */
  6288 	 */
  5669 	/**
  6290 	/**
  5670 	 * Retrieves a pingback and registers it.
  6291 	 * Retrieves a pingback and registers it.
  5671 	 *
  6292 	 *
  5672 	 * @since 1.5.0
  6293 	 * @since 1.5.0
  5673 	 *
  6294 	 *
  5674 	 * @param array $args Method parameters.
  6295 	 * @param array  $args {
       
  6296 	 *     Method arguments. Note: arguments must be ordered as documented.
       
  6297 	 *
       
  6298 	 *     @type string $pagelinkedfrom
       
  6299 	 *     @type string $pagelinkedto
       
  6300 	 * }
  5675 	 * @return string|IXR_Error
  6301 	 * @return string|IXR_Error
  5676 	 */
  6302 	 */
  5677 	public function pingback_ping($args) {
  6303 	public function pingback_ping( $args ) {
  5678 		global $wpdb;
  6304 		global $wpdb;
  5679 
  6305 
  5680 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6306 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5681 		do_action( 'xmlrpc_call', 'pingback.ping' );
  6307 		do_action( 'xmlrpc_call', 'pingback.ping' );
  5682 
  6308 
  5683 		$this->escape($args);
  6309 		$this->escape( $args );
  5684 
  6310 
  5685 		$pagelinkedfrom = $args[0];
  6311 		$pagelinkedfrom = str_replace( '&amp;', '&', $args[0] );
  5686 		$pagelinkedto   = $args[1];
  6312 		$pagelinkedto = str_replace( '&amp;', '&', $args[1] );
  5687 
  6313 		$pagelinkedto = str_replace( '&', '&amp;', $pagelinkedto );
  5688 		$pagelinkedfrom = str_replace('&amp;', '&', $pagelinkedfrom);
       
  5689 		$pagelinkedto = str_replace('&amp;', '&', $pagelinkedto);
       
  5690 		$pagelinkedto = str_replace('&', '&amp;', $pagelinkedto);
       
  5691 
  6314 
  5692 		/**
  6315 		/**
  5693 		 * Filter the pingback source URI.
  6316 		 * Filters the pingback source URI.
  5694 		 *
  6317 		 *
  5695 		 * @since 3.6.0
  6318 		 * @since 3.6.0
  5696 		 *
  6319 		 *
  5697 		 * @param string $pagelinkedfrom URI of the page linked from.
  6320 		 * @param string $pagelinkedfrom URI of the page linked from.
  5698 		 * @param string $pagelinkedto   URI of the page linked to.
  6321 		 * @param string $pagelinkedto   URI of the page linked to.
  5764 		sleep(1);
  6387 		sleep(1);
  5765 
  6388 
  5766 		$remote_ip = preg_replace( '/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR'] );
  6389 		$remote_ip = preg_replace( '/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR'] );
  5767 
  6390 
  5768 		/** This filter is documented in wp-includes/class-http.php */
  6391 		/** This filter is documented in wp-includes/class-http.php */
  5769 		$user_agent = apply_filters( 'http_headers_useragent', 'WordPress/' . $GLOBALS['wp_version'] . '; ' . get_bloginfo( 'url' ) );
  6392 		$user_agent = apply_filters( 'http_headers_useragent', 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ) );
  5770 
  6393 
  5771 		// Let's check the remote site
  6394 		// Let's check the remote site
  5772 		$http_api_args = array(
  6395 		$http_api_args = array(
  5773 			'timeout' => 10,
  6396 			'timeout' => 10,
  5774 			'redirection' => 0,
  6397 			'redirection' => 0,
  5776 			'user-agent' => "$user_agent; verifying pingback from $remote_ip",
  6399 			'user-agent' => "$user_agent; verifying pingback from $remote_ip",
  5777 			'headers' => array(
  6400 			'headers' => array(
  5778 				'X-Pingback-Forwarded-For' => $remote_ip,
  6401 				'X-Pingback-Forwarded-For' => $remote_ip,
  5779 			),
  6402 			),
  5780 		);
  6403 		);
       
  6404 
  5781 		$request = wp_safe_remote_get( $pagelinkedfrom, $http_api_args );
  6405 		$request = wp_safe_remote_get( $pagelinkedfrom, $http_api_args );
  5782 		$linea = wp_remote_retrieve_body( $request );
  6406 		$remote_source = $remote_source_original = wp_remote_retrieve_body( $request );
  5783 
  6407 
  5784 		if ( !$linea )
  6408 		if ( ! $remote_source ) {
  5785 			return $this->pingback_error( 16, __( 'The source URL does not exist.' ) );
  6409 			return $this->pingback_error( 16, __( 'The source URL does not exist.' ) );
       
  6410 		}
  5786 
  6411 
  5787 		/**
  6412 		/**
  5788 		 * Filter the pingback remote source.
  6413 		 * Filters the pingback remote source.
  5789 		 *
  6414 		 *
  5790 		 * @since 2.5.0
  6415 		 * @since 2.5.0
  5791 		 *
  6416 		 *
  5792 		 * @param string $linea        Response object for the page linked from.
  6417 		 * @param string $remote_source Response source for the page linked from.
  5793 		 * @param string $pagelinkedto URL of the page linked to.
  6418 		 * @param string $pagelinkedto  URL of the page linked to.
  5794 		 */
  6419 		 */
  5795 		$linea = apply_filters( 'pre_remote_source', $linea, $pagelinkedto );
  6420 		$remote_source = apply_filters( 'pre_remote_source', $remote_source, $pagelinkedto );
  5796 
  6421 
  5797 		// Work around bug in strip_tags():
  6422 		// Work around bug in strip_tags():
  5798 		$linea = str_replace('<!DOC', '<DOC', $linea);
  6423 		$remote_source = str_replace( '<!DOC', '<DOC', $remote_source );
  5799 		$linea = preg_replace( '/[\r\n\t ]+/', ' ', $linea ); // normalize spaces
  6424 		$remote_source = preg_replace( '/[\r\n\t ]+/', ' ', $remote_source ); // normalize spaces
  5800 		$linea = preg_replace( "/<\/*(h1|h2|h3|h4|h5|h6|p|th|td|li|dt|dd|pre|caption|input|textarea|button|body)[^>]*>/", "\n\n", $linea );
  6425 		$remote_source = preg_replace( "/<\/*(h1|h2|h3|h4|h5|h6|p|th|td|li|dt|dd|pre|caption|input|textarea|button|body)[^>]*>/", "\n\n", $remote_source );
  5801 
  6426 
  5802 		preg_match('|<title>([^<]*?)</title>|is', $linea, $matchtitle);
  6427 		preg_match( '|<title>([^<]*?)</title>|is', $remote_source, $matchtitle );
  5803 		$title = $matchtitle[1];
  6428 		$title = isset( $matchtitle[1] ) ? $matchtitle[1] : '';
  5804 		if ( empty( $title ) )
  6429 		if ( empty( $title ) ) {
  5805 			return $this->pingback_error( 32, __('We cannot find a title on that page.' ) );
  6430 			return $this->pingback_error( 32, __( 'We cannot find a title on that page.' ) );
  5806 
  6431 		}
  5807 		$linea = strip_tags( $linea, '<a>' ); // just keep the tag we need
  6432 
  5808 
  6433 		$remote_source = strip_tags( $remote_source, '<a>' ); // just keep the tag we need
  5809 		$p = explode( "\n\n", $linea );
  6434 
       
  6435 		$p = explode( "\n\n", $remote_source );
  5810 
  6436 
  5811 		$preg_target = preg_quote($pagelinkedto, '|');
  6437 		$preg_target = preg_quote($pagelinkedto, '|');
  5812 
  6438 
  5813 		foreach ( $p as $para ) {
  6439 		foreach ( $p as $para ) {
  5814 			if ( strpos($para, $pagelinkedto) !== false ) { // it exists, but is it a link?
  6440 			if ( strpos($para, $pagelinkedto) !== false ) { // it exists, but is it a link?
  5852 		$comment_author_url = $pagelinkedfrom;
  6478 		$comment_author_url = $pagelinkedfrom;
  5853 		$comment_content = $context;
  6479 		$comment_content = $context;
  5854 		$this->escape($comment_content);
  6480 		$this->escape($comment_content);
  5855 		$comment_type = 'pingback';
  6481 		$comment_type = 'pingback';
  5856 
  6482 
  5857 		$commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_url', 'comment_author_email', 'comment_content', 'comment_type');
  6483 		$commentdata = compact(
       
  6484 			'comment_post_ID', 'comment_author', 'comment_author_url', 'comment_author_email',
       
  6485 			'comment_content', 'comment_type', 'remote_source', 'remote_source_original'
       
  6486 		);
  5858 
  6487 
  5859 		$comment_ID = wp_new_comment($commentdata);
  6488 		$comment_ID = wp_new_comment($commentdata);
       
  6489 
       
  6490 		if ( is_wp_error( $comment_ID ) ) {
       
  6491 			return $this->pingback_error( 0, $comment_ID->get_error_message() );
       
  6492 		}
  5860 
  6493 
  5861 		/**
  6494 		/**
  5862 		 * Fires after a post pingback has been sent.
  6495 		 * Fires after a post pingback has been sent.
  5863 		 *
  6496 		 *
  5864 		 * @since 0.71
  6497 		 * @since 0.71
  5865 		 *
  6498 		 *
  5866 		 * @param int $comment_ID Comment ID.
  6499 		 * @param int $comment_ID Comment ID.
  5867 		 */
  6500 		 */
  5868 		do_action( 'pingback_post', $comment_ID );
  6501 		do_action( 'pingback_post', $comment_ID );
  5869 
  6502 
  5870 		return sprintf(__('Pingback from %1$s to %2$s registered. Keep the web talking! :-)'), $pagelinkedfrom, $pagelinkedto);
  6503 		/* translators: 1: URL of the page linked from, 2: URL of the page linked to */
       
  6504 		return sprintf( __( 'Pingback from %1$s to %2$s registered. Keep the web talking! :-)' ), $pagelinkedfrom, $pagelinkedto );
  5871 	}
  6505 	}
  5872 
  6506 
  5873 	/**
  6507 	/**
  5874 	 * Retrieve array of URLs that pingbacked the given URL.
  6508 	 * Retrieve array of URLs that pingbacked the given URL.
  5875 	 *
  6509 	 *
  5876 	 * Specs on http://www.aquarionics.com/misc/archives/blogite/0198.html
  6510 	 * Specs on http://www.aquarionics.com/misc/archives/blogite/0198.html
  5877 	 *
  6511 	 *
  5878 	 * @since 1.5.0
  6512 	 * @since 1.5.0
  5879 	 *
  6513 	 *
  5880 	 * @param array $args Method parameters.
  6514 	 * @global wpdb $wpdb WordPress database abstraction object.
       
  6515 	 *
       
  6516 	 * @param string $url
  5881 	 * @return array|IXR_Error
  6517 	 * @return array|IXR_Error
  5882 	 */
  6518 	 */
  5883 	public function pingback_extensions_getPingbacks($args) {
  6519 	public function pingback_extensions_getPingbacks( $url ) {
  5884 
       
  5885 		global $wpdb;
  6520 		global $wpdb;
  5886 
  6521 
  5887 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  6522 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
  5888 		do_action( 'xmlrpc_call', 'pingback.extensions.getPingbacks' );
  6523 		do_action( 'xmlrpc_call', 'pingback.extensions.getPingbacks' );
  5889 
  6524 
  5890 		$this->escape($args);
  6525 		$url = $this->escape( $url );
  5891 
       
  5892 		$url = $args;
       
  5893 
  6526 
  5894 		$post_ID = url_to_postid($url);
  6527 		$post_ID = url_to_postid($url);
  5895 		if ( !$post_ID ) {
  6528 		if ( !$post_ID ) {
  5896 			// We aren't sure that the resource is available and/or pingback enabled
  6529 			// We aren't sure that the resource is available and/or pingback enabled
  5897 	  		return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either doesn&#8217;t exist, or it is not a pingback-enabled resource.' ) );
  6530 	  		return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either doesn&#8217;t exist, or it is not a pingback-enabled resource.' ) );
  5917 
  6550 
  5918 		return $pingbacks;
  6551 		return $pingbacks;
  5919 	}
  6552 	}
  5920 
  6553 
  5921 	/**
  6554 	/**
  5922 	 * @param integer $code
  6555 	 * Sends a pingback error based on the given error code and message.
  5923 	 * @param string $message
  6556 	 *
       
  6557 	 * @since 3.6.0
       
  6558 	 *
       
  6559 	 * @param int    $code    Error code.
       
  6560 	 * @param string $message Error message.
       
  6561 	 * @return IXR_Error Error object.
  5924 	 */
  6562 	 */
  5925 	protected function pingback_error( $code, $message ) {
  6563 	protected function pingback_error( $code, $message ) {
  5926 		/**
  6564 		/**
  5927 		 * Filter the XML-RPC pingback error return.
  6565 		 * Filters the XML-RPC pingback error return.
  5928 		 *
  6566 		 *
  5929 		 * @since 3.5.1
  6567 		 * @since 3.5.1
  5930 		 *
  6568 		 *
  5931 		 * @param IXR_Error $error An IXR_Error object containing the error code and message.
  6569 		 * @param IXR_Error $error An IXR_Error object containing the error code and message.
  5932 		 */
  6570 		 */