Improve migration UX

This commit is contained in:
Django Doucet 2022-10-07 15:41:46 -06:00
parent ecbe724b82
commit 8707387ab8
6 changed files with 168 additions and 88 deletions

View file

@ -3,7 +3,7 @@
* Plugin Name: ActivityPub
* Plugin URI: https://github.com/pfefferle/wordpress-activitypub/
* Description: The ActivityPub protocol is a decentralized social networking protocol based upon the ActivityStreams 2.0 data format.
* Version: 0.13.4
* Version: 0.14.0-RC1
* Author: Matthias Pfefferle
* Author URI: https://notiz.blog/
* License: MIT

View file

@ -2,21 +2,53 @@
/**
* Reply Comment-edit screen
*/
//Insert Mentions into comment content on reply
$('.comment-inline.button-link').on('click', function( event){
// Summary/ContentWarning Syntax [CW]
var summary = $(this).attr('data-summary') ? '[' + $(this).attr('data-summary') + '] ' : '';
var recipients = $(this).attr('data-recipients') ? $(this).attr('data-recipients') + ' ' : '';
setTimeout(function() {
if ( summary || recipients ){
$('#replycontent').val( summary + recipients )
}
}, 100);
})
//Clear Mentions from content on cancel
$('.cancel.button').on('click', function(){
$('#replycontent').val('');
});
if ( $('body').hasClass('edit-comments-php') ) {
//Insert Mentions into comment content on reply
$( '.comment-inline.button-link' ).on( 'click', function( event ) {
// Summary/ContentWarning Syntax [CW]
var summary = $(this).attr('data-summary') ? '[' + $(this).attr('data-summary') + '] ' : '';
var recipients = $(this).attr('data-recipients') ? $(this).attr('data-recipients') + ' ' : '';
setTimeout(function() {
if ( summary || recipients ){
$('#replycontent').val( summary + recipients )
}
}, 100);
})
//Clear Mentions from content on cancel
$('.cancel.button').on('click', function(){
$('#replycontent').val('');
});
}
})( jQuery );
/**
* Tools screen
*/
if ( $('body').hasClass('tools_page_activitypub_tools') ) {
$('.delete_annouce' ).on('click', function(event) {
event.preventDefault();
var row = $(this).parents('tr') ? $(this).parents('tr') : '';
var nonce = $(this).attr('data-nonce') ? $(this).attr('data-nonce') : '';
var post_url = $(this).attr('data-post_url') ? $(this).attr('data-post_url') : '';
var post_author = $(this).attr('data-post_author') ? $(this).attr('data-post_author') : '';
var data = {
'action': 'migrate_post',
'nonce': nonce,
'post_url': post_url,
'post_author': post_author
}
$.ajax({
url: ajaxurl,
type: 'POST',
data: data,
success: function () {
row.remove()
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(textStatus + errorThrown);
}
})
});
}
})( jQuery );

View file

@ -15,7 +15,8 @@ class Admin {
\add_action( 'admin_init', array( '\Activitypub\Admin', 'register_settings' ) );
\add_action( 'admin_init', array( '\Activitypub\Admin', 'version_check' ), 1 );
\add_action( 'show_user_profile', array( '\Activitypub\Admin', 'add_fediverse_profile' ) );
\add_action( 'admin_enqueue_scripts', array( '\Activitypub\Admin', 'scripts_reply_comments' ), 10, 2 );
\add_action( 'admin_enqueue_scripts', array( '\Activitypub\Admin', 'enqueue_script_actions' ), 10, 2 );
\add_action( 'wp_ajax_migrate_post', array( '\Activitypub\Admin', 'migrate_post_action' ) );
\add_filter( 'comment_row_actions', array( '\Activitypub\Admin', 'reply_comments_actions' ), 10, 2 );
}
@ -144,21 +145,15 @@ class Admin {
$plugin_data = \get_plugin_data( ACTIVITYPUB_PLUGIN );
$activitypub_db_version = \get_option( 'activitypub_version' );
// Needs update
if ( empty( $activitypub_db_version ) || \version_compare( $plugin_data['Version'], $activitypub_db_version, '>' ) ) {
// Check for specific migrations
if ( version_compare( '0.13.5', $activitypub_db_version, '>' ) ) {
// This updates post_meta with _activitypub_permalink_compat.
// Posts that have this meta will be backwards compatible with their permalink based ActivityPub ID (URI)
// This may create false positives, where the permalink has changed (slug, permalink structure) since federation,
// for those cases a delete_url will allow for federating a delete based on the federated object ID (the old permalink)
if ( version_compare( '0.13.4', $activitypub_db_version, '>' ) ) {
\Activitypub\Tools\Posts::mark_posts_to_migrate();
}
}
\update_option( 'activitypub_version', $plugin_data['Version'] );
//\delete_option( 'activitypub_version' );
}
public static function add_settings_help_tab() {
@ -192,13 +187,35 @@ class Admin {
\Activitypub\get_identifier_settings( $user->ID );
}
public static function enqueue_script_actions( $hook ) {
if ( 'edit-comments.php' === $hook || 'tools_page_activitypub_tools' === $hook ) {
\wp_enqueue_script(
'activitypub_actions',
\plugin_dir_url( __FILE__ ) . '/activitypub.js',
array( 'jquery' ),
\filemtime( \plugin_dir_path( __FILE__ ) . '/activitypub.js' ),
true
);
}
}
/**
* Migrate post (Ajax)
*/
public static function migrate_post_action() {
if ( wp_verify_nonce( $_POST['nonce'], 'activitypub_migrate_actions' ) ) {
\Activitypub\Tools\Posts::migrate_post( rawurldecode( $_POST['post_url'] ), absint( $_POST['post_author'] ) );
\delete_post_meta( \url_to_postid( $_POST['post_url'] ), '_activitypub_permalink_compat' );
} else {
$error = new WP_Error( 'nonce_failure', __( 'Unauthorized', 'activitypub' ) );
wp_send_json_error( $error );
}
wp_die();
}
public static function reply_comments_actions( $actions, $comment ) {
//unset( $actions['reply'] );
$recipients = \Activitypub\get_recipients( $comment->comment_ID );
$summary = \Activitypub\get_summary( $comment->comment_ID );
//TODO revise for non-js reply action
// Public Reply
$reply_button = '<button type="button" data-comment-id="%d" data-post-id="%d" data-action="%s" class="%s button-link" aria-expanded="false" aria-label="%s" data-recipients="%s" data-summary="%s">%s</button>';
$actions['reply'] = \sprintf(
$reply_button,
@ -211,20 +228,6 @@ class Admin {
$summary,
\__( 'Reply', 'activitypub' )
);
return $actions;
}
public static function scripts_reply_comments( $hook ) {
if ( 'edit-comments.php' !== $hook ) {
return;
}
\wp_enqueue_script(
'activitypub_client',
\plugin_dir_url( __FILE__ ) . '/activitypub.js',
array( 'jquery' ),
\filemtime( \plugin_dir_path( __FILE__ ) . '/activitypub.js' ),
true
);
}
}

View file

@ -33,8 +33,19 @@ class Posts {
'meta_key' => '_activitypub_permalink_compat',
'order' => 'ASC',
);
$posts_to_migrate = \get_posts( $args );
return $posts_to_migrate;
return \get_posts( $args );
}
public static function get_posts_with_activitypub_comments() {
$args = array(
'comment_type' => 'activitypub',
);
$activitypub_comments = \get_comments( $args );
$activitypub_comments_posts = array();
foreach ( $activitypub_comments as $comment ) {
$activitypub_comments_posts[] = $comment->comment_post_ID;
}
return \get_posts( \array_unique( $activitypub_comments_posts ) );
}
public static function count_posts_to_migrate() {

View file

@ -6,12 +6,14 @@ if ( ! \class_exists( '\WP_List_Table' ) ) {
}
class Migrate_List extends \WP_List_Table {
public function get_columns() {
return array(
'cb' => '<input type="checkbox" />',
'post_author' => \__( 'Post Author (user_id)', 'activitypub' ),
'title' => \__( 'Post', 'activitypub' ),
'date' => \__( 'Publication Date', 'activitypub' ),
'comments' => \__( 'Comments', 'activitypub' ),
'date' => \__( 'Publication Date', 'activitypub' ),
'migrate' => \__( 'Migrate', 'activitypub' ),
);
}
@ -36,8 +38,8 @@ class Migrate_List extends \WP_List_Table {
\get_permalink( $post->ID ),
$post->post_title
),
'date' => $post->post_date,
'comments' => $post->comment_count,
'date' => $post->post_date,
'migrate' => \get_post_meta( $post->ID, '_activitypub_permalink_compat', true ),
);
}
@ -60,21 +62,39 @@ class Migrate_List extends \WP_List_Table {
$nonce = \esc_attr( $_REQUEST['_wpnonce'] );
}
// delete
if ( isset( $_REQUEST['action'] ) && 'activitypub_tools' === $_REQUEST['page'] && 'delete' === $_REQUEST['action'] ) {
if ( wp_verify_nonce( $nonce, 'activitypub_delete_post' ) ) {
\Activitypub\Tools\Posts::delete_url( rawurldecode( $_REQUEST['post_url'] ), absint( $_REQUEST['post_author'] ) );
if ( isset( $_REQUEST['action'] ) && 'activitypub_tools' === $_REQUEST['page'] && 'delete_notice' === $_REQUEST['action'] ) {
if ( wp_verify_nonce( $nonce, 'activitypub_migrate_actions' ) ) {
//\Activitypub\Tools\Posts::delete_url( rawurldecode( $_REQUEST['post_url'] ), absint( $_REQUEST['post_author'] ) );
\delete_post_meta( \url_to_postid( $_REQUEST['post_url'] ), '_activitypub_permalink_compat' );
}
}
// delete and announce
if ( isset( $_REQUEST['action'] ) && 'activitypub_tools' === $_REQUEST['page'] && 'delete_announce' === $_REQUEST['action'] ) {
if ( wp_verify_nonce( $nonce, 'activitypub_delete_announce_post' ) ) {
if ( isset( $_REQUEST['action'] ) && 'activitypub_tools' === $_REQUEST['page'] && 'delete' === $_REQUEST['action'] ) {
if ( wp_verify_nonce( $nonce, 'activitypub_migrate_actions' ) ) {
\Activitypub\Tools\Posts::migrate_post( rawurldecode( $_REQUEST['post_url'] ), absint( $_REQUEST['post_author'] ) );
\delete_post_meta( \url_to_postid( $_REQUEST['post_url'] ), '_activitypub_permalink_compat' );
}
}
}
public function single_row( $item ) {
$inline_styles = ( $item['comments'] > 0 ) ? 'warning' : ''; ?>
<tr class="<?php echo $inline_styles; ?>"><?php $this->single_row_columns( $item ); ?></tr><?php
}
/**
* Render the bulk edit checkbox
*
* @param array $item
*
* @return string
*/
function column_cb( $item ) {
return sprintf(
'<input type="checkbox" name="selected[]" value="%s" />', $item['migrate']
);
}
/**
* Render a column when no column specific method exists.
*
@ -85,10 +105,11 @@ class Migrate_List extends \WP_List_Table {
*/
public function column_default( $item, $column_name ) {
switch ( $column_name ) {
case 'cb':
case 'post_author':
case 'title':
case 'date':
case 'comments':
case 'date':
case 'migrate':
return $item[ $column_name ];
default:
@ -97,29 +118,36 @@ class Migrate_List extends \WP_List_Table {
}
public function column_title( $item ) {
$delete_announce_nonce = wp_create_nonce( 'activitypub_delete_announce_post' );
$delete_nonce = wp_create_nonce( 'activitypub_delete_post' );
$migrate_action_nonce = wp_create_nonce( 'activitypub_migrate_actions' );
$actions = array(
'delete_announce' => sprintf(
'<a href="?page=%s&action=%s&post_author=%s&post_url=%s&_wpnonce=%s" title="%s">%s</a>',
esc_attr( $_REQUEST['page'] ),
'delete_announce',
$item['post_author'],
\rawurlencode( $item['migrate'] ),
$delete_announce_nonce,
__( 'Delete the federated post, and re-share the original post', 'activitypub' ),
__( 'Delete & Re-share original', 'activitypub' )
),
'delete' => sprintf(
'<a href="?page=%s&action=%s&post_author=%s&post_url=%s&_wpnonce=%s" title="%s">%s</a>',
'<a href="?page=%s&action=%s&post_author=%s&post_url=%s&_wpnonce=%s" class="%s" title="%s" data-post_author="%s" data-post_url="%s" data-nonce="%s">%s</a>',
esc_attr( $_REQUEST['page'] ),
'delete',
'delete',// using this id for style reasons
$item['post_author'],
\rawurlencode( $item['migrate'] ),
$delete_nonce,
__( 'Delete the federated post', 'activitypub' ),
__( 'Delete', 'activitypub' )
$migrate_action_nonce,
'delete_annouce aria-button-ui-if-js',
__( 'Delete the federated post, and re-share the post with a new id', 'activitypub' ),
$item['post_author'],
\rawurlencode( $item['migrate'] ),
$migrate_action_nonce,
__( 'Migrate post', 'activitypub' )
),
'delete_notice' => sprintf(
'<a href="?page=%s&action=%s&post_author=%s&post_url=%s&_wpnonce=%s" class="%s" title="%s" data-post_author="%s" data-post_url="%s" data-nonce="%s">%s</a>',
esc_attr( $_REQUEST['page'] ),
'delete_notice',
$item['post_author'],
\rawurlencode( $item['migrate'] ),
$migrate_action_nonce,
'delete aria-button-ui-if-js',
__( 'Delete this notice and backwards compatibility', 'activitypub' ),
$item['post_author'],
\rawurlencode( $item['migrate'] ),
$migrate_action_nonce,
__( 'Remove notice', 'activitypub' )
),
);
return sprintf( '%1$s %2$s', $item['title'], $this->row_actions( $actions, true ) );

View file

@ -10,26 +10,32 @@ if ( isset( $_REQUEST['post_url'] ) && $_REQUEST['page'] == "activitypub_tools"
}
?>
<div class="wrap">
<h1><?php \esc_html_e( 'Migrate posts (Fediverse)', 'activitypub' ); ?></h1>
<h1><?php \esc_html_e( 'Manage ActivityPub posts (Fediverse)', 'activitypub' ); ?></h1>
<p><?php \printf(
\__( 'You currently have %s posts to migrate.', 'activitypub' ),
\esc_attr( \Activitypub\Tools\Posts::count_posts_to_migrate() )
); ?></p>
<?php if ( \Activitypub\Tools\Posts::count_posts_to_migrate() > 0 ): ?>
<p><?php \printf(
\__( 'Posts with ActivityPub Comments, should be treated with care, existing interactions in the fediverse but not on site will be lost.', 'activitypub' ),
\esc_attr( \Activitypub\Tools\Posts::count_posts_to_migrate() )
); ?></p>
<div class="notice notice-warning">
<p><?php \printf(
\__( 'The following table lists ActivityPub posts which have been marked as backwards compatible, and ready for migration. <br>
Migration here means updating the Activity ID by federating a Delete activity removing the original post from the fediverse, and then Sharing the new post ID with an Announce activity. <br>
Posts with comments should be treated with care, existing interactions in the fediverse will be lost.', 'activitypub' ),
\esc_attr( \Activitypub\Tools\Posts::count_posts_to_migrate() )
); ?></p>
</div>
<?php $token_table = new \Activitypub\Table\Migrate_List(); ?>
<p><?php \printf(
\__( 'You currently have %s posts to migrate.', 'activitypub' ),
\esc_attr( \Activitypub\Tools\Posts::count_posts_to_migrate() )
); ?></p>
<form method="POST" id="table">
<?php
$token_table->prepare_items();
$token_table->display();
?>
</form>
<?php $token_table = new \Activitypub\Table\Migrate_List(); ?>
<form method="POST" id="table">
<?php
$token_table->prepare_items();
$token_table->display();
?>
</form>
<?php endif; ?>
<hr class="separator">
<form method="POST" id="delete">
<div>