WordPress.org

Make WordPress Core

Ticket #18429: cycle1.patch

File cycle1.patch, 22.0 KB (added by maxcutler, 6 years ago)

Combined patch for #18429, #18430, #18431, #18432, and #18433

  • wp-includes/class-wp-xmlrpc-server.php

     
    3636                $this->methods = array(
    3737                        // WordPress API
    3838                        'wp.getUsersBlogs'              => 'this:wp_getUsersBlogs',
     39                        'wp.newPost'                    => 'this:wp_newPost',
     40                        'wp.editPost'                   => 'this:wp_editPost',
     41                        'wp.deletePost'                 => 'this:wp_deletePost',
     42                        'wp.getPost'                    => 'this:wp_getPost',
     43                        'wp.getPosts'                   => 'this:wp_getPosts',
    3944                        'wp.getPage'                    => 'this:wp_getPage',
    4045                        'wp.getPages'                   => 'this:wp_getPages',
    4146                        'wp.newPage'                    => 'this:wp_newPage',
     
    447452        }
    448453
    449454        /**
     455         * Prepares post data for return in an XML-RPC object.
     456         *
     457         * @param array $post The unprepared post data
     458         * @param array $fields The subset of post fields to return
     459         * @return array The prepared post data
     460         */
     461        function prepare_post( $post, $fields ) {
     462                // holds the data for this post. built up based on $fields
     463                $_post = array( 'post_id' => $post['ID'] );
     464
     465                // prepare common post fields
     466                $post_fields = array(
     467                        'post_title'        => $post['post_title'],
     468                        'post_date'         => new IXR_Date( mysql2date( 'Ymd\TH:i:s', $post['post_date'], false ) ),
     469                        'post_date_gmt'     => new IXR_Date( mysql2date( 'Ymd\TH:i:s', $post['post_date_gmt'], false ) ),
     470                        'post_modified'     => new IXR_Date( mysql2date( 'Ymd\TH:i:s', $post['post_modified'], false ) ),
     471                        'post_modified_gmt' => new IXR_Date( mysql2date( 'Ymd\TH:i:s', $post['post_modified_gmt'], false ) ),
     472                        'post_status'       => $post['post_status'],
     473                        'post_type'         => $post['post_type'],
     474                        'post_name'         => $post['post_name'],
     475                        'post_author'       => $post['post_author'],
     476                        'post_password'     => $post['post_password'],
     477                        'post_excerpt'      => $post['post_excerpt'],
     478                        'post_content'      => $post['post_content'],
     479                        'link'              => post_permalink( $post['ID'] ),
     480                        'comment_status'    => $post['comment_status'],
     481                        'ping_status'       => $post['ping_status'],
     482                        'sticky'            => ( $post['post_type'] === 'post' && is_sticky( $post['ID'] ) ),
     483                );
     484
     485                // Consider future posts as published
     486                if ( $post_fields['post_status'] === 'future' )
     487                        $post_fields['post_status'] = 'publish';
     488
     489                // Fill in blank post format
     490                $post_fields['post_format'] = get_post_format( $post['ID'] );
     491                if ( empty( $post_fields['post_format'] ) )
     492                        $post_fields['post_format'] = 'standard';
     493
     494                // Merge requested $post_fields fields into $_post
     495                if ( in_array( 'post', $fields ) ) {
     496                        $_post = array_merge( $_post, $post_fields );
     497                } else {
     498                        $requested_fields = array_intersect_key( $post_fields, array_flip( $fields ) );
     499                        $_post = array_merge( $_post, $requested_fields );
     500                }
     501
     502                $all_taxonomy_fields = in_array( 'taxonomies', $fields );
     503
     504                if ( $all_taxonomy_fields || in_array( 'terms', $fields ) ) {
     505                        $post_type_taxonomies = get_object_taxonomies( $post['post_type'], 'names' );
     506                        $terms = wp_get_object_terms( $post['ID'], $post_type_taxonomies );
     507                        $_post['terms'] = array();
     508                        foreach ( $terms as $term ) {
     509                                $_post['terms'][] = (array) $term;
     510                        }
     511                }
     512
     513                // backward compatiblity
     514                if ( $all_taxonomy_fields || in_array( 'tags', $fields ) ) {
     515                        $tagnames = array();
     516                        $tags = wp_get_post_tags( $post['ID'] );
     517                        if ( ! empty( $tags ) ) {
     518                                foreach ( $tags as $tag ) {
     519                                        $tagnames[] = $tag->name;
     520                                }
     521                                $tagnames = implode( ', ', $tagnames );
     522                        } else {
     523                                $tagnames = '';
     524                        }
     525                        $_post['tags'] = $tagnames;
     526                }
     527
     528                // backward compatiblity
     529                if ( $all_taxonomy_fields || in_array( 'categories', $fields ) ) {
     530                        $categories = array();
     531                        $catids = wp_get_post_categories( $post['ID'] );
     532                        foreach ( $catids as $catid ) {
     533                                $categories[] = get_cat_name( $catid );
     534                        }
     535                        $_post['categories'] = $categories;
     536                }
     537
     538                if ( in_array( 'custom_fields', $fields ) )
     539                        $_post['custom_fields'] = $this->get_custom_fields( $post['ID'] );
     540
     541                if ( in_array( 'enclosure', $fields ) ) {
     542                        $_post['enclosure'] = array();
     543                        $enclosures = (array) get_post_meta( $post['ID'], 'enclosure' );
     544                        if ( ! empty( $enclosures ) ) {
     545                                $encdata = explode( "\n", $enclosures[0] );
     546                                $_post['enclosure']['url'] = trim( htmlspecialchars( $encdata[0] ) );
     547                                $_post['enclosure']['length'] = (int) trim( $encdata[1] );
     548                                $_post['enclosure']['type'] = trim( $encdata[2] );
     549                        }
     550                }
     551
     552                return apply_filters( 'xmlrpc_prepare_post', $_post, $post, $fields );
     553        }
     554
     555        /**
     556         * Create a new post for any registered post type.
     557         *
     558         * @uses wp_insert_post()
     559         * @param array $args Method parameters. Contains:
     560         *  - int     $blog_id
     561         *  - string  $username
     562         *  - string  $password
     563         *  - array   $content_struct
     564         *      $content_struct can contain:
     565         *      - post_type (default: 'post')
     566         *      - post_status (default: 'draft')
     567         *      - post_title
     568         *      - post_author
     569         *      - post_exerpt
     570         *      - post_content
     571         *      - post_date_gmt | post_date
     572         *      - post_format
     573         *      - post_password
     574         *      - comment_status - can be 'open' | 'closed'
     575         *      - ping_status - can be 'open' | 'closed'
     576         *      - sticky
     577         *      - custom_fields - array, with each element containing 'key' and 'value'
     578         *      - terms - array, with taxonomy names as keys and arrays of term IDs as values
     579         *      - terms_names - array, with taxonomy names as keys and arrays of term names as values
     580         *      - enclosure
     581         *      - any other fields supported by wp_insert_post()
     582         * @return string post_id
     583         */
     584        function wp_newPost( $args ) {
     585                $this->escape( $args );
     586
     587                $blog_id        = (int) $args[0];
     588                $username       = $args[1];
     589                $password       = $args[2];
     590                $content_struct = $args[3];
     591
     592                if ( ! $user = $this->login( $username, $password ) )
     593                        return $this->error;
     594
     595                do_action( 'xmlrpc_call', 'wp.newPost' );
     596
     597                unset( $content_struct['ID'] );
     598
     599                return $this->_wp_insertPost( $user, $content_struct );
     600        }
     601
     602        /*
     603         * Helper method for wp_newPost and wp_editPost, containing shared logic.
     604         */
     605        function _wp_insertPost( $user, $content_struct ) {
     606                $defaults = array( 'post_status' => 'draft', 'post_type' => 'post', 'post_author' => 0,
     607                        'post_password' => '', 'post_excerpt' => '', 'post_content' => '', 'post_title' => '', 'sticky' => 0 );
     608
     609                $post_data = wp_parse_args( $content_struct, $defaults );
     610
     611                $post_type = get_post_type_object( $post_data['post_type'] );
     612                if( ! ( (bool) $post_type ) )
     613                        return new IXR_Error( 403, __( 'Invalid post type' ) );
     614
     615                if( ! current_user_can( $post_type->cap->edit_posts ) )
     616                        return new IXR_Error( 401, __( 'Sorry, you are not allowed to post on this site.' ) );
     617
     618                switch ( $post_data['post_status'] ) {
     619                        case 'draft':
     620                        case 'pending':
     621                                break;
     622                        case 'private':
     623                                if( ! current_user_can( $post_type->cap->publish_posts ) )
     624                                        return new IXR_Error( 401, __( 'Sorry, you are not allowed to create private posts in this post type' ));
     625                                break;
     626                        case 'publish':
     627                        case 'future':
     628                                if( ! current_user_can( $post_type->cap->publish_posts ) )
     629                                        return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish posts in this post type' ));
     630                                break;
     631                        default:
     632                                $post_data['post_status'] = 'draft';
     633                        break;
     634                }
     635
     636                if ( ! empty( $post_data['post_password'] ) && ! current_user_can( $post_type->cap->publish_posts ) )
     637                        return new IXR_Error( 401, __( 'Sorry, you are not allowed to create password protected posts in this post type' ) );
     638
     639
     640                $post_data['post_author'] = absint( $post_data['post_author'] );
     641                if( ! empty( $post_data['post_author'] ) && $post_data['post_author'] != $user->ID ) {
     642                        if( ! current_user_can( $post_type->cap->edit_others_posts ) )
     643                                return new IXR_Error( 401, __( 'You are not allowed to create posts as this user.' ) );
     644
     645                        $author = get_userdata( $post_data['post_author'] );
     646
     647                        if( ! $author )
     648                                return new IXR_Error( 404, __( 'Invalid author ID.' ) );
     649                }
     650                else {
     651                        $post_data['post_author'] = $user->ID;
     652                }
     653
     654                if( isset( $post_data['comment_status'] ) )
     655                        if( ! post_type_supports( $post_data['post_type'], 'comments' ) || ( $post_data['comment_status'] != 'open' && $post_data['comment_status'] != 'closed' ) )
     656                                unset( $post_data['comment_status'] );
     657
     658                if( isset( $post_data['ping_status'] ) )
     659                        if( ! post_type_supports( $post_data['post_type'], 'trackbacks' ) || ( $post_data['ping_status'] != 'open' && $post_data['ping_status'] != 'closed' ) )
     660                                unset( $post_data['ping_status'] );
     661
     662                // Do some timestamp voodoo
     663                if ( ! empty( $post_data['post_date_gmt'] ) )
     664                        $dateCreated = str_replace( 'Z', '', $post_data['post_date_gmt']->getIso() ) . 'Z'; // We know this is supposed to be GMT, so we're going to slap that Z on there by force
     665                elseif ( ! empty( $post_data['post_date'] ) )
     666                        $dateCreated = $post_data['post_date']->getIso();
     667
     668                if ( ! empty( $dateCreated ) ) {
     669                        $post_data['post_date'] = get_date_from_gmt( iso8601_to_datetime( $dateCreated ) );
     670                        $post_data['post_date_gmt'] = iso8601_to_datetime( $dateCreated, 'GMT' );
     671                }
     672
     673                if ( ! isset( $post_data['ID'] ) ) {
     674                        $post_data['ID'] = get_default_post_to_edit( $post_data['post_type'], true )->ID;
     675                }
     676                $post_ID = $post_data['ID'];
     677
     678                $sticky = $post_data['sticky'] ? true : false;
     679
     680                if( $post_data['post_type'] == 'post' && $sticky == true ) {
     681                        if( ! current_user_can( $post_type->cap->edit_others_posts ) )
     682                                return new IXR_Error( 401, __( 'Sorry, you are not allowed to stick this post.' ) );
     683
     684                        if( $post_data['post_status'] != 'publish' )
     685                                return new IXR_Error( 401, __( 'Only published posts can be made sticky.' ) );
     686
     687                        stick_post( $post_ID );
     688                }
     689
     690                if( isset ( $post_data['custom_fields'] ) && post_type_supports( $post_data['post_type'], 'custom-fields' ) ) {
     691                        $this->set_custom_fields( $post_ID, $post_data['custom_fields'] );
     692                }
     693
     694                if( isset( $post_data['terms'] ) || isset( $post_data['terms_names'] ) ) {
     695                        $post_type_taxonomies = get_object_taxonomies( $post_data['post_type'], 'objects' );
     696
     697                        // accumulate term IDs from terms and terms_names
     698                        $terms = array();
     699
     700                        // first validate the terms specified by ID
     701                        if( isset( $post_data['terms'] ) && is_array( $post_data['terms'] ) ) {
     702                                $taxonomies = array_keys( $post_data['terms'] );
     703
     704                                // validating term ids
     705                                foreach ( $taxonomies as $taxonomy ) {
     706                                        if ( ! array_key_exists( $taxonomy , $post_type_taxonomies ) )
     707                                                return new IXR_Error( 401, __( 'Sorry, one of the given taxonomy is not supported by the post type.' ) );
     708
     709                                        if( ! current_user_can( $post_type_taxonomies[$taxonomy]->cap->assign_terms ) )
     710                                                return new IXR_Error( 401, __( 'Sorry, you are not allowed to assign a term to one of the given taxonomies' ) );
     711
     712                                        $term_ids = $post_data['terms'][$taxonomy];
     713                                        foreach ( $term_ids as $term_id ) {
     714                                                $term = get_term_by( 'id', $term_id, $taxonomy );
     715
     716                                                if ( ! $term )
     717                                                        return new IXR_Error( 403, __( 'Invalid term ID' ) );
     718
     719                                                $terms[$taxonomy][] = (int) $term_id;
     720                                        }
     721                                }
     722                        }
     723
     724                        // now validate terms specified by name
     725                        if ( isset( $post_data['terms_names'] ) && is_array( $post_data['terms_names'] ) ) {
     726                                $taxonomies = array_keys( $post_data['terms_names'] );
     727
     728                                foreach ( $taxonomies as $taxonomy ) {
     729                                        if ( ! array_key_exists( $taxonomy , $post_type_taxonomies ) )
     730                                                return new IXR_Error( 401, __( 'Sorry, one of the given taxonomy is not supported by the post type.' ) );
     731
     732                                        if( ! current_user_can( $post_type_taxonomies[$taxonomy]->cap->assign_terms ) )
     733                                                return new IXR_Error( 401, __( 'Sorry, you are not allowed to assign a term to one of the given taxonomies.' ) );
     734
     735                                        // for hierarchical taxonomies, we can't assign a term when multiple terms in the hierarchy share the same name
     736                                        $ambiguous_terms = array();
     737                                        if( is_taxonomy_hierarchical( $taxonomy ) ) {
     738                                                $tax_term_names = get_terms( $taxonomy, array( 'fields' => 'names', 'hide_empty' => false ) );
     739
     740                                                // count the number of terms with the same name
     741                                                $tax_term_names_count = array_count_values( $tax_term_names );
     742
     743                                                // filter out non-ambiguous term names
     744                                                $ambiguous_tax_term_counts = array_filter( $tax_term_names_count, function( $count ){
     745                                                        return $count > 1;
     746                                                } );
     747
     748                                                $ambiguous_terms = array_keys( $ambiguous_tax_term_counts );
     749                                        }
     750
     751                                        $term_names = $post_data['terms_names'][$taxonomy];
     752                                        foreach ( $term_names as $term_name ) {
     753                                                if ( in_array( $term_name, $ambiguous_terms ) )
     754                                                        return new IXR_Error( 401, __( 'Ambiguous term name used in a hierarhical taxonomy. Please use term ID instead.' ) );
     755
     756                                                $term = get_term_by( 'name', $term_name, $taxonomy );
     757
     758                                                if ( ! $term ) {
     759                                                        // term doesn't exist, so check that the user is allowed to create new terms
     760                                                        if( ! current_user_can( $post_type_taxonomies[$taxonomy]->cap->edit_terms ) )
     761                                                                return new IXR_Error( 401, __( 'Sorry, you are not allowed to add a term to one of the given taxonomies.' ) );
     762
     763                                                        // create the new term
     764                                                        $term_info = wp_insert_term( $term_name, $taxonomy );
     765                                                        if ( is_wp_error( $term_info ) )
     766                                                                return new IXR_Error( 500, $term_info->get_error_message() );
     767
     768                                                        $terms[$taxonomy][] = (int) $term_info['term_id'];
     769                                                }
     770                                                else {
     771                                                        $terms[$taxonomy][] = (int) $term->term_id;
     772                                                }
     773                                        }
     774                                }
     775                        }
     776
     777                        $post_data['tax_input'] = $terms;
     778                        unset( $post_data['terms'] );
     779                        unset( $post_data['terms_names'] );
     780                }
     781                else {
     782                        // do not allow direct submission of 'tax_input', clients must use 'terms' and/or 'terms_names'
     783                        unset( $post_data['tax_input'] );
     784                }
     785
     786                if( isset( $post_data['post_format'] ) ) {
     787                        $format = set_post_format( $post_ID, $post_data['post_format'] );
     788
     789                        if ( is_wp_error( $format ) )
     790                                return new IXR_Error( 500, $format->get_error_message() );
     791
     792                        unset( $post_data['post_format'] );
     793                }
     794
     795                // Handle enclosures
     796                $enclosure = isset( $post_data['enclosure'] ) ? $post_data['enclosure'] : null;
     797                $this->add_enclosure_if_new( $post_ID, $enclosure );
     798
     799                $this->attach_uploads( $post_ID, $post_data['post_content'] );
     800
     801                $post_data = apply_filters( 'xmlrpc_wp_insert_post_data', $post_data, $content_struct );
     802
     803                $post_ID = wp_insert_post( $post_data, true );
     804                if ( is_wp_error( $post_ID ) )
     805                        return new IXR_Error( 500, $post_ID->get_error_message() );
     806
     807                if ( ! $post_ID )
     808                        return new IXR_Error( 401, __( 'Sorry, your entry could not be posted. Something wrong happened.' ) );
     809
     810                return strval( $post_ID );
     811        }
     812
     813        /*
     814         * Edit a post for any registered post type.
     815         *
     816         * The $content_struct parameter only needs to contain fields that
     817         * should be changed. All other fields will retain their existing values.
     818         *
     819         * @uses wp_insert_post()
     820         * @param array $args Method parameters. Contains:
     821         *  - int     $blog_id
     822         *  - string  $username
     823         *  - string  $password
     824         *  - int     $post_id
     825         *  - array   $content_struct
     826         * @return true on success
     827         */
     828        function wp_editPost( $args ) {
     829                $this->escape( $args );
     830
     831                $blog_id        = (int) $args[0]; // we will support this in the near future
     832                $username       = $args[1];
     833                $password       = $args[2];
     834                $post_id        = (int) $args[3];
     835                $content_struct = $args[4];
     836
     837                if ( ! $user = $this->login( $username, $password ) )
     838                        return $this->error;
     839
     840                do_action( 'xmlrpc_call', 'wp.editPost' );
     841
     842                $post = get_post( $post_id, ARRAY_A );
     843
     844                if ( empty( $post["ID"] ) )
     845                        return new IXR_Error( 404, __( 'Invalid post ID.' ) );
     846
     847                // convert the date field back to IXR form
     848                $post['post_date'] = new IXR_Date( mysql2date( 'Ymd\TH:i:s', $post['post_date'], false ) );
     849
     850                // ignore the existing GMT date if it is empty or a non-GMT date was supplied in $content_struct,
     851                // since _wp_insertPost will ignore the non-GMT date if the GMT date is set
     852                if ( $post['post_date_gmt'] == '0000-00-00 00:00:00' || isset( $content_struct['post_date'] ) )
     853                        unset( $post['post_date_gmt'] );
     854                else
     855                        $post['post_date_gmt'] = new IXR_Date( mysql2date( 'Ymd\TH:i:s', $post['post_date_gmt'], false ) );
     856
     857                $this->escape( $post );
     858                $merged_content_struct = array_merge( $post, $content_struct );
     859
     860                $retval = $this->_wp_insertPost( $user, $merged_content_struct );
     861                if ( $retval instanceof IXR_Error )
     862                        return $retval;
     863
     864                return true;
     865        }
     866
     867        /**
     868         * Delete a post for any registered post type.
     869         *
     870         * @uses wp_delete_post()
     871         * @param array $args Method parameters. Contains:
     872         *  - int     $blog_id
     873         *  - string  $username
     874         *  - string  $password
     875         *  - int     $post_id
     876         * @return true on success
     877         */
     878        function wp_deletePost( $args ) {
     879                $this->escape( $args );
     880
     881                $blog_id    = (int) $args[0];
     882                $username   = $args[1];
     883                $password   = $args[2];
     884                $post_id    = (int) $args[3];
     885
     886                if ( ! $user = $this->login( $username, $password ) )
     887                        return $this->error;
     888
     889                do_action( 'xmlrpc_call', 'wp.deletePost' );
     890
     891                $post = wp_get_single_post( $post_id, ARRAY_A );
     892                if ( empty( $post['ID'] ) )
     893                        return new IXR_Error( 404, __( 'Invalid post ID.' ) );
     894
     895                $post_type = get_post_type_object( $post['post_type'] );
     896                if( ! current_user_can( $post_type->cap->delete_post, $post_id ) )
     897                        return new IXR_Error( 401, __( 'Sorry, you are not allowed to delete this post.' ) );
     898
     899                $result = wp_delete_post( $post_id );
     900
     901                if ( ! $result )
     902                        return new IXR_Error( 500, __( 'The post cannot be deleted.' ) );
     903
     904                return true;
     905        }
     906
     907        /**
     908         * Retrieve a post.
     909         *
     910         * The optional $fields parameter specifies what fields will be included
     911         * in the response array. This should be a list of field names. 'post_id' will
     912         * always be included in the response regardless of the value of $fields.
     913         *
     914         * Instead of, or in addition to, individual field names, conceptual group
     915         * names can be used to specify multiple fields. The available conceptual
     916         * groups are 'post' (all basic fields), 'taxonomies', 'custom_fields',
     917         * and 'enclosure'.
     918         *
     919         * @uses wp_get_single_post()
     920         * @param array $args Method parameters. Contains:
     921         *  - int     $post_id
     922         *  - string  $username
     923         *  - string  $password
     924         *  - array   $fields optional
     925         * @return array contains (based on $fields parameter):
     926         *  - 'post_id'
     927         *  - 'post_title'
     928         *  - 'post_date'
     929         *  - 'post_date_gmt'
     930         *  - 'post_modified'
     931         *  - 'post_modified_gmt'
     932         *  - 'post_status'
     933         *  - 'post_type'
     934         *  - 'post_name'
     935         *  - 'post_author'
     936         *  - 'post_password'
     937         *  - 'post_excerpt'
     938         *  - 'post_content'
     939         *  - 'link'
     940         *  - 'comment_status'
     941         *  - 'ping_status'
     942         *  - 'sticky'
     943         *  - 'custom_fields'
     944         *  - 'terms'
     945         *  - 'categories'
     946         *  - 'tags'
     947         *  - 'enclosure'
     948         */
     949        function wp_getPost( $args ) {
     950                $this->escape( $args );
     951
     952                $blog_id            = (int) $args[0];
     953                $username           = $args[1];
     954                $password           = $args[2];
     955                $post_id            = (int) $args[3];
     956
     957                if ( isset( $args[4] ) )
     958                        $fields = $args[4];
     959                else
     960                        $fields = apply_filters( 'xmlrpc_default_post_fields', array( 'post', 'terms', 'custom_fields' ), 'wp.getPost' );
     961
     962                if ( ! $user = $this->login( $username, $password ) )
     963                        return $this->error;
     964
     965                do_action( 'xmlrpc_call', 'wp.getPost' );
     966
     967                $post = wp_get_single_post( $post_id, ARRAY_A );
     968
     969                if ( empty( $post["ID"] ) )
     970                        return new IXR_Error( 404, __( 'Invalid post ID.' ) );
     971
     972                $post_type = get_post_type_object( $post['post_type'] );
     973                if ( ! current_user_can( $post_type->cap->edit_posts, $post_id ) )
     974                        return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) );
     975
     976                return $this->prepare_post( $post, $fields );
     977        }
     978
     979        /**
     980         * Retrieve posts.
     981         *
     982         * The optional $filter parameter modifies the query used to retrieve posts.
     983         * Accepted keys are 'post_type', 'post_status', 'number', 'offset',
     984         * 'orderby', and 'order'.
     985         *
     986         * The optional $fields parameter specifies what fields will be included
     987         * in the response array.
     988         *
     989         * @uses wp_get_recent_posts()
     990         * @see wp_getPost() for more on $fields
     991         * @see get_posts() for more on $filter values
     992         *
     993         * @param array $args Method parameters. Contains:
     994         *  - int     $blog_id
     995         *  - string  $username
     996         *  - string  $password
     997         *  - array   $filter optional
     998         *  - array   $fields optional
     999         * @return array cntains a collection of posts.
     1000         */
     1001        function wp_getPosts( $args ) {
     1002                $this->escape( $args );
     1003
     1004                $blog_id    = (int) $args[0];
     1005                $username   = $args[1];
     1006                $password   = $args[2];
     1007                $filter     = isset( $args[3] ) ? $args[3] : array();
     1008
     1009                if ( isset( $args[4] ) )
     1010                        $fields = $args[4];
     1011                else
     1012                        $fields = apply_filters( 'xmlrpc_default_post_fields', array( 'post', 'terms', 'custom_fields' ), 'wp.getPosts' );
     1013
     1014                if ( ! $user = $this->login( $username, $password ) )
     1015                        return $this->error;
     1016
     1017                do_action( 'xmlrpc_call', 'wp.getPosts' );
     1018
     1019                $query = array();
     1020
     1021                if ( isset( $filter['post_type'] ) ) {
     1022                        $post_type = get_post_type_object( $filter['post_type'] );
     1023                        if ( ! ( (bool) $post_type ) )
     1024                                return new IXR_Error( 403, __( 'The post type specified is not valid' ) );
     1025
     1026                        if ( ! current_user_can( $post_type->cap->edit_posts ) )
     1027                                return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit posts in this post type' ));
     1028
     1029                        $query['post_type'] = $filter['post_type'];
     1030                }
     1031
     1032                if ( isset( $filter['post_status'] ) )
     1033                        $query['post_status'] = $filter['post_status'];
     1034
     1035                if ( isset( $filter['number'] ) )
     1036                        $query['number'] = absint( $filter['number'] );
     1037
     1038                if ( isset( $filter['offset'] ) )
     1039                        $query['offset'] = absint( $filter['offset'] );
     1040
     1041                if ( isset( $filter['orderby'] ) ) {
     1042                        $query['orderby'] = $filter['orderby'];
     1043
     1044                        if ( isset( $filter['order'] ) )
     1045                                $query['order'] = $filter['order'];
     1046                }
     1047
     1048                do_action( 'xmlrpc_call', 'wp.getPosts' );
     1049
     1050                $posts_list = wp_get_recent_posts( $query );
     1051
     1052                if ( ! $posts_list )
     1053                        return array( );
     1054
     1055                // holds all the posts data
     1056                $struct = array();
     1057
     1058                foreach ( $posts_list as $post ) {
     1059                        $post_type = get_post_type_object( $post['post_type'] );
     1060                        if ( ! current_user_can( $post_type->cap->edit_posts, $post['ID'] ) )
     1061                                continue;
     1062
     1063                        $struct[] = $this->prepare_post( $post, $fields );
     1064                }
     1065
     1066                return $struct;
     1067        }
     1068
     1069        /**
    4501070         * Retrieve page.
    4511071         *
    4521072         * @since 2.2.0