Pledges: Add UI for setting "deactivated" status (#115)

This adds the ability to deactivate/reactivate pledges from the wp-admin list table. Once deactivated, the pledge is removed from the "published" list, as if it were trashed. It is not rendered in the frontend pledge list either. You can still access the edit screen, but no edits can be made (saving the pledge is disabled by JS, as otherwise it would reactivate itself). This way we can remove a pledge, but still see the activity log.

Fixes #112
This commit is contained in:
Kelly Dwan 2019-12-05 13:20:11 -05:00 committed by GitHub
parent e4deb6809a
commit 8807efb96d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 187 additions and 22 deletions

View file

@ -52,6 +52,7 @@
margin-bottom: 1.5rem;
}
.pledge-contributors.pledge-status__5ftf-deactivated .resend-confirm,
.pledge-contributors.pledge-status__draft .resend-confirm {
display: none;
}

View file

@ -208,7 +208,10 @@ function add_meta_boxes() {
* @param array $box
*/
function render_meta_boxes( $pledge, $box ) {
$readonly = ! current_user_can( 'edit_page', $pledge->ID );
$readonly = (
! current_user_can( 'edit_page', $pledge->ID ) ||
Pledge\DEACTIVE_STATUS === $pledge->post_status
);
$is_manage = true;
$pledge_id = $pledge->ID;

View file

@ -14,9 +14,10 @@ use const WordPressDotOrg\FiveForTheFuture\PledgeMeta\META_PREFIX;
defined( 'WPINC' ) || die();
const SLUG = 'pledge';
const SLUG_PL = 'pledges';
const CPT_ID = FiveForTheFuture\PREFIX . '_' . SLUG;
const SLUG = 'pledge';
const SLUG_PL = 'pledges';
const CPT_ID = FiveForTheFuture\PREFIX . '_' . SLUG;
const DEACTIVE_STATUS = FiveForTheFuture\PREFIX . '-deactivated';
// Admin hooks.
add_action( 'init', __NAMESPACE__ . '\register', 0 );
@ -25,6 +26,13 @@ add_action( 'pre_get_posts', __NAMESPACE__ . '\filter_query' );
// List table columns.
add_filter( 'manage_edit-' . CPT_ID . '_columns', __NAMESPACE__ . '\add_list_table_columns' );
add_action( 'manage_' . CPT_ID . '_posts_custom_column', __NAMESPACE__ . '\populate_list_table_columns', 10, 2 );
// Deactivate & reactivate handling.
add_filter( 'post_row_actions', __NAMESPACE__ . '\add_row_action', 10, 2 );
add_action( 'post_action_deactivate', __NAMESPACE__ . '\handle_activation_action', 10, 3 );
add_action( 'post_action_reactivate', __NAMESPACE__ . '\handle_activation_action', 10, 3 );
add_action( 'admin_notices', __NAMESPACE__ . '\action_success_message' );
add_filter( 'display_post_states', __NAMESPACE__ . '\add_status_to_display', 10, 2 );
add_action( 'post_submitbox_misc_actions', __NAMESPACE__ . '\inject_status_label' );
// Front end hooks.
add_action( 'wp_enqueue_scripts', __NAMESPACE__ . '\enqueue_assets' );
@ -117,19 +125,164 @@ function register_custom_post_type() {
* @return void
*/
function register_custom_post_status() {
$label_count = _n_noop(
'Deactivated <span class="count">(%s)</span>',
'Deactivated <span class="count">(%s)</span>',
'wporg-5ftf'
);
register_post_status(
FiveForTheFuture\PREFIX . '-deactivated',
DEACTIVE_STATUS,
array(
'label' => __( 'Deactivated', 'wporg-5ftf' ),
'label_count' => _n_noop( 'Deactivated <span class="count">(%s)</span>', 'Deactivated <span class="count">(%s)</span>', 'wporg-5ftf' ),
'public' => false,
'internal' => false,
'protected' => true,
CPT_ID => true, // Custom parameter to streamline its use with the Pledge CPT.
'label' => __( 'Deactivated', 'wporg-5ftf' ),
'label_count' => $label_count,
'public' => false,
'internal' => false,
'protected' => true,
'show_in_admin_all_list' => false,
)
);
}
/**
* Inject deactivate/reactivate actions into row actions.
*
* @return array An array of row action links.
*/
function add_row_action( $actions, $post ) {
// Not a pledge, or can't edit the post.
if ( CPT_ID !== $post->post_type || ! current_user_can( 'edit_post', $post->ID ) ) {
return $actions;
}
$post_type_object = get_post_type_object( $post->post_type );
if ( DEACTIVE_STATUS === $post->post_status ) {
$actions['reactivate'] = sprintf(
'<a href="%s" style="color:#297531;" aria-label="%s">%s</a>',
wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=reactivate', $post->ID ) ), 'reactivate-post_' . $post->ID ),
/* translators: %s: Post title. */
esc_attr( sprintf( __( 'Reactivate pledge &#8220;%s&#8221;', 'wporg-5ftf' ), $post->post_title ) ),
__( 'Reactivate', 'wporg-5ftf' )
);
} else {
unset( $actions['trash'] );
$actions['deactivate'] = sprintf(
'<a href="%s" style="color:#dc3232;" aria-label="%s">%s</a>',
wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=deactivate', $post->ID ) ), 'deactivate-post_' . $post->ID ),
/* translators: %s: Post title. */
esc_attr( sprintf( __( 'Deactivate pledge &#8220;%s&#8221;', 'wporg-5ftf' ), $post->post_title ) ),
__( 'Deactivate', 'wporg-5ftf' )
);
}
return $actions;
}
/**
* Trigger the post status change when deactivate or reactivate actions are seen.
*
* @return void
*/
function handle_activation_action( $post_id ) {
$action = $_REQUEST['action'];
if ( ! in_array( $action, [ 'deactivate', 'reactivate' ] ) ) {
return;
}
if ( 'deactivate' === $action ) {
check_admin_referer( 'deactivate-post_' . $post_id );
} else {
check_admin_referer( 'reactivate-post_' . $post_id );
}
$post = get_post( $post_id );
if ( ! is_a( $post, 'WP_Post' ) || CPT_ID !== $post->post_type ) {
return;
}
if ( ! current_user_can( 'edit_post', $post->ID ) ) {
return;
}
$sendback = wp_get_referer();
$sendback = remove_query_arg( [ 'deactivated', 'reactivated' ], $sendback );
if ( 'deactivate' === $action ) {
wp_update_post( array(
'ID' => $post_id,
'post_status' => DEACTIVE_STATUS,
) );
wp_redirect( add_query_arg( 'deactivated', 1, $sendback ) );
exit();
} else {
wp_update_post( array(
'ID' => $post_id,
'post_status' => 'publish',
) );
wp_redirect( add_query_arg( 'reactivated', 1, $sendback ) );
exit();
}
}
/**
* Output success messages when a pledge is deactivated or reactivated.
*
* @return void
*/
function action_success_message() {
if ( isset( $_GET['deactivated'] ) ) : ?>
<div id="message" class="notice notice-success is-dismissable">
<p><?php esc_html_e( 'Pledge deactivated.', 'wporg-5ftf' ); ?></p>
</div>
<?php elseif ( isset( $_GET['reactivated'] ) ) : ?>
<div id="message" class="notice notice-success is-dismissable">
<p><?php esc_html_e( 'Pledge reactivated.', 'wporg-5ftf' ); ?></p>
</div>
<?php endif;
}
/**
* Add "Deactivated" to the list of post states (displayed on each post in the list table).
*
* @param string[] $post_states An array of post display states.
* @param WP_Post $post The current post object.
*
* @return array The filtered list of post display states.
*/
function add_status_to_display( $post_states, $post ) {
if ( isset( $_REQUEST['post_status'] ) ) {
$showing_status = $_REQUEST['post_status'];
} else {
$showing_status = '';
}
$status = DEACTIVE_STATUS;
if ( $showing_status !== $status && $status === $post->post_status ) {
$post_states[ $status ] = _x( 'Deactivated', 'pledge label', 'wporg-5ftf' );
}
return $post_states;
}
/**
* Use JS to replace the empty status label on deactivated pledges.
*
* @param WP_Post $post The current post object.
*
* @return void
*/
function inject_status_label( $post ) {
if ( CPT_ID === $post->post_type && DEACTIVE_STATUS === $post->post_status ) : ?>
<script type="text/javascript">
jQuery( document ).ready( function( $ ) {
$("#post-status-display").text("Deactivated");
$("#save-action").remove();
$("#publishing-action").remove();
} );
</script>
<div class="misc-pub-section misc-pub-visibility">
<p><?php esc_html_e( 'This pledge is deactivated, it cannot be edited.', 'wporg-5ftf' ); ?></p>
</div>
<?php endif;
}
/**
* Add columns to the Pledges list table.
*

View file

@ -5,8 +5,8 @@ use function WordPressDotOrg\FiveForTheFuture\get_views_path;
/** @var array $contributors */
/** @var int $pledge_id */
/** @var bool $readonly */
?>
<script type="text/template" id="tmpl-5ftf-contributor-lists">
<# if ( data.publish.length ) { #>
<h3 class="contributor-list-heading"><?php esc_html_e( 'Confirmed', 'wporg-5ftf' ); ?></h3>
@ -14,7 +14,9 @@ use function WordPressDotOrg\FiveForTheFuture\get_views_path;
<thead>
<th scope="col"><?php esc_html_e( 'Contributor', 'wporg-5ftf' ); ?></th>
<th scope="col"><?php esc_html_e( 'Date Confirmed', 'wporg-5ftf' ); ?></th>
<?php if ( ! $readonly ) : ?>
<th scope="col"><?php esc_html_e( 'Remove Contributor', 'wporg-5ftf' ); ?></th>
<?php endif; ?>
</thead>
<tbody>{{{ data.publish }}}</tbody>
</table>
@ -26,7 +28,9 @@ use function WordPressDotOrg\FiveForTheFuture\get_views_path;
<tr>
<th scope="col"><?php esc_html_e( 'Contributor', 'wporg-5ftf' ); ?></th>
<th scope="col" class="resend-confirm"><?php esc_html_e( 'Resend Confirmation', 'wporg-5ftf' ); ?></th>
<?php if ( ! $readonly ) : ?>
<th scope="col"><?php esc_html_e( 'Remove Contributor', 'wporg-5ftf' ); ?></th>
<?php endif; ?>
</tr>
</thead>
<tbody>{{{ data.pending }}}</tbody>
@ -58,6 +62,7 @@ use function WordPressDotOrg\FiveForTheFuture\get_views_path;
<# } else { #>
<td>{{ data.publishDate }}</td>
<# } #>
<?php if ( ! $readonly ) : ?>
<td>
<button
class="button-link button-link-delete"
@ -70,6 +75,7 @@ use function WordPressDotOrg\FiveForTheFuture\get_views_path;
<?php esc_html_e( 'Remove', 'wporg-5ftf' ); ?>
</button>
</td>
<?php endif; ?>
</tr>
</script>
@ -88,16 +94,18 @@ use function WordPressDotOrg\FiveForTheFuture\get_views_path;
</div>
<?php
$data = [ 'pledge-contributors' => '' ];
require get_views_path() . 'inputs-pledge-contributors.php';
?>
if ( ! $readonly ) :
$data = [ 'pledge-contributors' => '' ];
require get_views_path() . 'inputs-pledge-contributors.php';
?>
<div id="add-contrib-message" role="alert" aria-atomic="true"></div>
<div id="add-contrib-message" role="alert" aria-atomic="true"></div>
<button
class="button-primary"
data-action="add-contributor"
>
<?php esc_html_e( 'Add new contributors', 'wporg-5ftf' ); ?>
</button>
<button
class="button-primary"
data-action="add-contributor"
>
<?php esc_html_e( 'Add new contributors', 'wporg-5ftf' ); ?>
</button>
<?php endif; ?>
</div>