diff --git a/assets/js/admin-pull.js b/assets/js/admin-pull.js index 4488187a4..8d2594b48 100755 --- a/assets/js/admin-pull.js +++ b/assets/js/admin-pull.js @@ -22,6 +22,7 @@ const escapeURLComponent = ( str ) => { const chooseConnection = document.getElementById( 'pull_connections' ); const choosePostType = document.getElementById( 'pull_post_type' ); const choosePostTypeBtn = document.getElementById( 'pull_post_type_submit' ); +const choosePostCategory = document.getElementById( 'pull_post_category' ); const searchField = document.getElementById( 'post-search-input' ); const searchBtn = document.getElementById( 'search-submit' ); const form = document.getElementById( 'posts-filter' ); @@ -38,7 +39,7 @@ jQuery( chooseConnection ).on( 'change', ( event ) => { document.body.className += ' ' + 'dt-loading'; } ); -if ( chooseConnection && choosePostType && form ) { +if ( chooseConnection && ( choosePostType || choosePostCategory ) && form ) { if ( choosePostTypeBtn ) { jQuery( choosePostTypeBtn ).on( 'click', ( event ) => { event.preventDefault(); @@ -99,6 +100,8 @@ const getURL = () => { const postType = escapeURLComponent( choosePostType.options[ choosePostType.selectedIndex ].value ); + const postCategory = + choosePostCategory.options[ choosePostCategory.selectedIndex ].value; const pullUrlId = escapeURLComponent( chooseConnection.options[ chooseConnection.selectedIndex ].getAttribute( 'data-pull-url-id' @@ -113,5 +116,5 @@ const getURL = () => { status = 'pulled'; } - return `${ baseURL }&pull_post_type=${ postType }&status=${ status }`; + return `${ baseURL }&pull_post_type=${ postType }&pull_post_category=${ postCategory }&status=${ status }`; }; diff --git a/includes/classes/Connection.php b/includes/classes/Connection.php index 9e22f5441..e40dcef52 100644 --- a/includes/classes/Connection.php +++ b/includes/classes/Connection.php @@ -65,6 +65,14 @@ abstract public function get_sync_log( $id ); */ abstract public function get_post_types(); + /** + * Get available post types from a connection + * + * @since 1.3 + * @return array|\WP_Error + */ + abstract public function get_post_categories(); + /** * This method is called on every page load. It's helpful for canonicalization * diff --git a/includes/classes/ExternalConnections/WordPressExternalConnection.php b/includes/classes/ExternalConnections/WordPressExternalConnection.php index 75f3a7f0c..3843c720a 100644 --- a/includes/classes/ExternalConnections/WordPressExternalConnection.php +++ b/includes/classes/ExternalConnections/WordPressExternalConnection.php @@ -72,6 +72,20 @@ class WordPressExternalConnection extends ExternalConnection { */ public $pull_post_types; + /** + * Default posts category to pull. + * + * @var string + */ + public $pull_post_category; + + /** + * Default posts categories to show in filter. + * + * @var string + */ + public $pull_post_categories; + /** * This is a utility function for parsing annoying API link headers returned by the types endpoint * @@ -168,6 +182,10 @@ public function remote_get( $args = array() ) { } } + if ( isset( $args['tax_query'] ) ) { + $query_args['tax_query'] = $args['tax_query']; + } + // When running a query for the Pull screen, make a POST request instead if ( empty( $id ) ) { $query_args['post_type'] = isset( $post_type ) ? $post_type : 'post'; @@ -682,6 +700,41 @@ public function get_post_types() { return $types_body_array; } + /** + * Get the available post categories. + * + * @since 1.3 + * @return array|\WP_Error + */ + public function get_post_categories() { + $path = self::$namespace; + + $categories_path = untrailingslashit( $this->base_url ) . '/' . $path . '/categories'; + + $categories_response = Utils\remote_http_request( + $categories_path, + $this->auth_handler->format_get_args( array( 'timeout' => self::$timeout ) ) + ); + + if ( is_wp_error( $categories_response ) ) { + return $categories_response; + } + + if ( 404 === wp_remote_retrieve_response_code( $categories_response ) ) { + return new \WP_Error( 'bad-endpoint', esc_html__( 'Could not connect to API endpoint.', 'distributor' ) ); + } + + $categories_body = wp_remote_retrieve_body( $categories_response ); + + if ( empty( $categories_body ) ) { + return new \WP_Error( 'no-response-body', esc_html__( 'Response body is empty.', 'distributor' ) ); + } + + $categories_body_array = json_decode( $categories_body, true ); + + return $categories_body_array; + } + /** * Check what we can do with a given external connection (push or pull) * diff --git a/includes/classes/InternalConnections/NetworkSiteConnection.php b/includes/classes/InternalConnections/NetworkSiteConnection.php index 12d5742d2..764929ced 100644 --- a/includes/classes/InternalConnections/NetworkSiteConnection.php +++ b/includes/classes/InternalConnections/NetworkSiteConnection.php @@ -46,6 +46,20 @@ class NetworkSiteConnection extends Connection { */ public $pull_post_types; + /** + * Default posts category to pull. + * + * @var string + */ + public $pull_post_category; + + /** + * Default posts categories to show in filter. + * + * @var string + */ + public $pull_post_categories; + /** * Set up network site connection * @@ -520,6 +534,20 @@ public function get_post_types() { return $post_types; } + /** + * Get the available post categories. + * + * @since 1.3 + * @return array + */ + public function get_post_categories() { + switch_to_blog( $this->site->blog_id ); + $post_categories = Utils\distributable_categories(); + restore_current_blog(); + + return $post_categories; + } + /** * Remotely get posts so we can list them for pulling * @@ -567,6 +595,10 @@ public function remote_get( $args = array(), $new_post_args = array() ) { $query_args['post__not_in'] = $args['post__not_in']; } + if ( isset( $args['tax_query'] ) ) { + $query_args['tax_query'] = $args['tax_query']; + } + $query_args['post_type'] = ( empty( $args['post_type'] ) ) ? 'post' : $args['post_type']; $query_args['post_status'] = ( empty( $args['post_status'] ) ) ? [ 'publish', 'draft', 'private', 'pending', 'future' ] : $args['post_status']; $query_args['posts_per_page'] = ( empty( $args['posts_per_page'] ) ) ? get_option( 'posts_per_page' ) : $args['posts_per_page']; diff --git a/includes/classes/PullListTable.php b/includes/classes/PullListTable.php index ce770828d..f206020f2 100644 --- a/includes/classes/PullListTable.php +++ b/includes/classes/PullListTable.php @@ -463,10 +463,21 @@ public function prepare_items() { $current_page = $this->get_pagenum(); // Support 'View all' filtering for internal connections. - if ( empty( $connection_now->pull_post_type ) || 'all' === $connection_now->pull_post_type ) { - $post_type = wp_list_pluck( $connection_now->pull_post_types, 'slug' ); + if ( is_a( $connection_now, '\Distributor\InternalConnections\NetworkSiteConnection' ) ) { + if ( empty( $connection_now->pull_post_type ) || 'all' === $connection_now->pull_post_type ) { + $post_type = wp_list_pluck( $connection_now->pull_post_types, 'slug' ); + } else { + $post_type = $connection_now->pull_post_type; + } + + if ( empty( $connection_now->pull_post_category ) || 'all' === $connection_now->pull_post_category ) { + $post_category = wp_list_pluck( $connection_now->pull_post_categories, 'slug' ); + } else { + $post_category = $connection_now->pull_post_category; + } } else { - $post_type = $connection_now->pull_post_type; + $post_type = $connection_now->pull_post_type ? $connection_now->pull_post_type : 'post'; + $post_category = $connection_now->pull_post_category ? $connection_now->pull_post_category : 'all'; } $remote_get_args = [ @@ -480,6 +491,16 @@ public function prepare_items() { $remote_get_args['s'] = rawurlencode( $_GET['s'] ); // @codingStandardsIgnoreLine Nonce isn't required. } + if ( ! empty( $post_category ) && 'all' !== $post_category ) { + $remote_get_args['tax_query'] = [ + [ + 'taxonomy' => 'category', + 'field' => 'slug', + 'terms' => $post_category, + ], + ]; + } + if ( is_a( $connection_now, '\Distributor\ExternalConnection' ) ) { $this->sync_log = get_post_meta( $connection_now->id, 'dt_sync_log', true ); } else { @@ -626,6 +647,14 @@ public function get_bulk_actions() { * @param string $which Whether above or below the table. */ public function extra_tablenav( $which ) { + + /** + * This is to avoid the filter being displayed twice with the same HTML id. + */ + if ( 'bottom' === $which ) { + return; + } + global $connection_now; if ( is_a( $connection_now, '\Distributor\InternalConnections\NetworkSiteConnection' ) ) { @@ -634,21 +663,34 @@ public function extra_tablenav( $which ) { $connection_type = 'external'; } - if ( $connection_now && $connection_now->pull_post_types ) : + if ( $connection_now && $connection_now->pull_post_types && $connection_now->pull_post_type && $connection_now->pull_post_categories ) : ?>