Skip to content

Commit

Permalink
Merge pull request #1207 from alleyinteractive/feature/APPLE-191/allo…
Browse files Browse the repository at this point in the history
…w-bulk-article-deletions

Allow bulk article deletions from Apple News list table
  • Loading branch information
dlh01 authored Dec 4, 2024
2 parents 0536c0b + 0ab4d9c commit 5717353
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 92 deletions.
1 change: 1 addition & 0 deletions admin/apple-actions/class-api-action.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,6 @@ protected function delete_post_meta( $post_id ): void {
delete_post_meta( $post_id, 'apple_news_api_created_at' );
delete_post_meta( $post_id, 'apple_news_api_modified_at' );
delete_post_meta( $post_id, 'apple_news_api_share_url' );
delete_post_meta( $post_id, 'apple_news_article_checksum' );
}
}
151 changes: 88 additions & 63 deletions admin/class-admin-apple-bulk-export-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ public function __construct( $settings ) {

add_action( 'admin_menu', [ $this, 'register_page' ] );
add_action( 'admin_enqueue_scripts', [ $this, 'register_assets' ] );
add_action( 'wp_ajax_push_post', [ $this, 'ajax_push_post' ] );
add_filter( 'admin_title', [ $this, 'set_title' ] );
add_action( 'wp_ajax_apple_news_push_post', [ $this, 'ajax_push_post' ] );
add_action( 'wp_ajax_apple_news_delete_post', [ $this, 'ajax_delete_post' ] );
}

/**
Expand All @@ -66,45 +66,52 @@ public function register_page() {
);
}

/**
* Fix the title since WordPress doesn't set one.
*
* @param string $admin_title The title to be filtered.
* @access public
* @return string The title for the screen.
*/
public function set_title( $admin_title ) {
$screen = get_current_screen();
if ( 'admin_page_apple_news_bulk_export' === $screen->base ) {
$admin_title = __( 'Bulk Export', 'apple-news' ) . $admin_title;
}

return $admin_title;
}

/**
* Builds the plugin submenu page.
*
* @access public
*/
public function build_page() {
$ids = isset( $_GET['ids'] ) ? sanitize_text_field( wp_unslash( $_GET['ids'] ) ) : null; // phpcs:ignore WordPress.VIP.SuperGlobalInputUsage.AccessDetected, WordPress.Security.NonceVerification.Recommended
if ( ! $ids ) {
$post_ids = isset( $_GET['post_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['post_ids'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

if ( ! $post_ids ) {
wp_safe_redirect( esc_url_raw( menu_page_url( $this->plugin_slug . '_index', false ) ) ); // phpcs:ignore WordPressVIPMinimum.Security.ExitAfterRedirect.NoExit

if ( ! defined( 'APPLE_NEWS_UNIT_TESTS' ) || ! APPLE_NEWS_UNIT_TESTS ) {
exit;
}
}

// Populate $articles array with a set of valid posts.
$articles = [];
foreach ( explode( '.', $ids ) as $id ) {
$post = get_post( absint( $id ) );
// Allow only specific actions.
if ( ! in_array( $action, [ 'apple_news_push_post', 'apple_news_delete_post' ], true ) ) {
wp_die( esc_html__( 'Invalid action.', 'apple-news' ), '', [ 'response' => 400 ] );
}

// Populate articles array with a set of valid posts.
$apple_posts = [];
foreach ( explode( ',', $post_ids ) as $post_id ) {
$post = get_post( (int) $post_id );

if ( ! empty( $post ) ) {
$articles[] = $post;
$apple_posts[] = $post;
}
}

// Override text within the partial depending on the action.
$apple_page_title = match ( $action ) {
'apple_news_push_post' => __( 'Bulk Export Articles', 'apple-news' ),
'apple_news_delete_post' => __( 'Bulk Delete Articles', 'apple-news' ),
};
$apple_page_description = match ( $action ) {
'apple_news_push_post' => __( 'The following articles will be exported.', 'apple-news' ),
'apple_news_delete_post' => __( 'The following articles will be deleted.', 'apple-news' ),
};
$apple_submit_text = match ( $action ) {
'apple_news_push_post' => __( 'Publish All', 'apple-news' ),
'apple_news_delete_post' => __( 'Delete All', 'apple-news' ),
};

require_once __DIR__ . '/partials/page-bulk-export.php';
}

Expand All @@ -123,41 +130,25 @@ public function ajax_push_post() {
// Ensure the post exists and that it's published.
$post = get_post( $id );
if ( empty( $post ) ) {
echo wp_json_encode(
[
'success' => false,
'error' => __( 'This post no longer exists.', 'apple-news' ),
]
);
wp_die();
wp_send_json_error( __( 'This post no longer exists.', 'apple-news' ) );
}

// Check capabilities.
if ( ! current_user_can(
/** This filter is documented in admin/class-admin-apple-post-sync.php */
apply_filters( 'apple_news_publish_capability', self::get_capability_for_post_type( 'publish_posts', $post->post_type ) )
) ) {
echo wp_json_encode(
[
'success' => false,
'error' => __( 'You do not have permission to publish to Apple News', 'apple-news' ),
]
);
wp_die();
wp_send_json_error( __( 'You do not have permission to publish to Apple News', 'apple-news' ) );
}

if ( 'publish' !== $post->post_status ) {
echo wp_json_encode(
[
'success' => false,
'error' => sprintf(
// translators: token is a post ID.
__( 'Article %s is not published and cannot be pushed to Apple News.', 'apple-news' ),
$id
),
]
wp_send_json_error(
sprintf(
/* translators: %s: post ID */
__( 'Article %s is not published and cannot be pushed to Apple News.', 'apple-news' ),
$id
)
);
wp_die();
}

$action = new Apple_Actions\Index\Push( $this->settings, $id );
Expand All @@ -168,22 +159,56 @@ public function ajax_push_post() {
}

if ( $errors ) {
echo wp_json_encode(
[
'success' => false,
'error' => $errors,
]
);
} else {
echo wp_json_encode(
[
'success' => true,
]
);
wp_send_json_error( $errors );
}

wp_send_json_success();
}

/**
* Handles the ajax action to delete a post from Apple News.
*
* @access public
*/
public function ajax_delete_post() {
// Check the nonce.
check_ajax_referer( self::ACTION );

// Sanitize input data.
$id = isset( $_GET['id'] ) ? (int) $_GET['id'] : -1;

$post = get_post( $id );

if ( empty( $post ) ) {
wp_send_json_error( __( 'This post no longer exists.', 'apple-news' ) );
}

/** This filter is documented in admin/class-admin-apple-post-sync.php */
$cap = apply_filters( 'apple_news_delete_capability', self::get_capability_for_post_type( 'delete_posts', $post->post_type ) );

// Check capabilities.
if ( ! current_user_can( $cap ) ) {
wp_send_json_error( __( 'You do not have permission to delete posts from Apple News', 'apple-news' ) );
}

$errors = null;

// Try to sync only if the post has a remote ID. Ref `Admin_Apple_Post_Sync::do_delete()`.
if ( get_post_meta( $id, 'apple_news_api_id', true ) ) {
$action = new Apple_Actions\Index\Delete( $this->settings, $id );

try {
$errors = $action->perform();
} catch ( Apple_Actions\Action_Exception $e ) {
$errors = $e->getMessage();
}
}

if ( $errors ) {
wp_send_json_error( $errors );
}

// This is required to terminate immediately and return a valid response.
wp_die();
wp_send_json_success();
}

/**
Expand Down
54 changes: 44 additions & 10 deletions admin/class-admin-apple-index-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public function admin_page() {
*
* @since 0.4.0
* @access public
* @return mixed The result of the requested action.
* @return mixed|void The result of the requested action.
*/
public function page_router() {
$id = isset( $_GET['post_id'] ) ? absint( $_GET['post_id'] ) : null; // phpcs:ignore WordPress.VIP.SuperGlobalInputUsage.AccessDetected, WordPress.Security.NonceVerification.Recommended
Expand All @@ -130,22 +130,56 @@ public function page_router() {
return $this->export_action( $id );
case self::namespace_action( 'reset' ):
return $this->reset_action( $id );
case self::namespace_action( 'push' ): // phpcs:ignore PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
if ( ! $id ) {
case self::namespace_action( 'push' ):
if ( $id ) {
$this->push_action( $id );
} else {
$url = menu_page_url( $this->plugin_slug . '_bulk_export', false );
if ( isset( $_GET['article'] ) ) { // phpcs:ignore WordPress.VIP.SuperGlobalInputUsage.AccessDetected, WordPress.Security.NonceVerification.Recommended
$ids = is_array( $_GET['article'] ) ? array_map( 'absint', $_GET['article'] ) : absint( $_GET['article'] ); // phpcs:ignore WordPress.VIP.SuperGlobalInputUsage.AccessDetected, WordPress.Security.NonceVerification.Recommended
$url .= '&ids=' . implode( '.', $ids );

if ( isset( $_GET['article'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$post_ids = is_array( $_GET['article'] ) ? array_map( 'intval', $_GET['article'] ) : (int) $_GET['article']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$url = add_query_arg(
[
'action' => 'apple_news_push_post',
'post_ids' => implode( ',', $post_ids ),
],
$url,
);
}

wp_safe_redirect( esc_url_raw( $url ) ); // phpcs:ignore WordPressVIPMinimum.Security.ExitAfterRedirect.NoExit

if ( ! defined( 'APPLE_NEWS_UNIT_TESTS' ) || ! APPLE_NEWS_UNIT_TESTS ) {
exit;
}
} else {
return $this->push_action( $id );
}

break;
case self::namespace_action( 'delete' ):
return $this->delete_action( $id );
if ( $id ) {
$this->delete_action( $id );
} else {
$url = menu_page_url( $this->plugin_slug . '_bulk_export', false );

if ( isset( $_GET['article'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$post_ids = is_array( $_GET['article'] ) ? array_map( 'intval', $_GET['article'] ) : (int) $_GET['article']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$url = add_query_arg(
[
'action' => 'apple_news_delete_post',
'post_ids' => implode( ',', $post_ids ),
],
$url,
);
}

wp_safe_redirect( esc_url_raw( $url ) ); // phpcs:ignore WordPressVIPMinimum.Security.ExitAfterRedirect.NoExit

if ( ! defined( 'APPLE_NEWS_UNIT_TESTS' ) || ! APPLE_NEWS_UNIT_TESTS ) {
exit;
}
}

break;
}
}

Expand Down Expand Up @@ -401,7 +435,7 @@ private function delete_action( $id ) {
$action = new Apple_Actions\Index\Delete( $this->settings, $id );
try {
$action->perform();
$this->notice_success( __( 'Your article has been removed from apple news.', 'apple-news' ) );
$this->notice_success( __( 'Your article has been removed from Apple News.', 'apple-news' ) );
} catch ( Apple_Actions\Action_Exception $e ) {
$this->notice_error( $e->getMessage() );
}
Expand Down
5 changes: 3 additions & 2 deletions admin/class-admin-apple-news-list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,9 @@ public function get_bulk_actions() {
return apply_filters(
'apple_news_bulk_actions',
[
Admin_Apple_Index_Page::namespace_action( 'push' ) => __( 'Publish', 'apple-news' ),
]
Admin_Apple_Index_Page::namespace_action( 'push' ) => __( 'Publish', 'apple-news' ),
Admin_Apple_Index_Page::namespace_action( 'delete' ) => __( 'Delete', 'apple-news' ),
],
);
}

Expand Down
19 changes: 11 additions & 8 deletions admin/partials/page-bulk-export.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,28 @@
/**
* Publish to Apple News partials: Bulk Export page template
*
* phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
*
* @global array $articles
*
* @package Apple_News
*/

// Expect these variables to be defined in Admin_Apple_Bulk_Export_Page::build_page() but make sure they're set.
$apple_page_title ??= __( 'Bulk Export', 'apple-news' );
$apple_page_description ??= __( 'The following articles will be affected.', 'apple-news' );
$apple_posts ??= [];
$apple_submit_text ??= __( 'Go', 'apple-news' );

?>
<div class="wrap">
<h1><?php esc_html_e( 'Bulk Export Articles', 'apple-news' ); ?></h1>
<p><?php esc_html_e( "The following articles will be published to Apple News. Once started, it might take a while, please don't close the browser window.", 'apple-news' ); ?></p>
<h1><?php echo esc_html( $apple_page_title ); ?></h1>
<p><?php echo esc_html( $apple_page_description ); ?></p>
<p><?php esc_html_e( "Once started, it might take a while. Please don't close the browser window.", 'apple-news' ); ?></p>
<?php
/**
* Allows for custom HTML to be printed before the bulk export table.
*/
do_action( 'apple_news_before_bulk_export_table' );
?>
<ul class="bulk-export-list" data-nonce="<?php echo esc_attr( wp_create_nonce( Admin_Apple_Bulk_Export_Page::ACTION ) ); ?>">
<?php foreach ( $articles as $apple_post ) : ?>
<?php foreach ( $apple_posts as $apple_post ) : ?>
<li class="bulk-export-list-item" data-post-id="<?php echo esc_attr( $apple_post->ID ); ?>">
<span class="bulk-export-list-item-title">
<?php echo esc_html( $apple_post->post_title ); ?>
Expand All @@ -39,5 +42,5 @@
?>

<a class="button" href="<?php echo esc_url( menu_page_url( $this->plugin_slug . '_index', false ) ); ?>"><?php esc_html_e( 'Back', 'apple-news' ); ?></a>
<a class="button button-primary bulk-export-submit" href="#"><?php esc_html_e( 'Publish All', 'apple-news' ); ?></a>
<a class="button button-primary bulk-export-submit" href="#"><?php echo esc_html( $apple_submit_text ); ?></a>
</div>
Loading

0 comments on commit 5717353

Please sign in to comment.