implement cleanup_followers
and update_followers
This commit is contained in:
parent
f64a765129
commit
17b66cb23d
8 changed files with 281 additions and 58 deletions
|
@ -49,6 +49,7 @@ function init() {
|
||||||
Mention::init();
|
Mention::init();
|
||||||
Debug::init();
|
Debug::init();
|
||||||
Health_Check::init();
|
Health_Check::init();
|
||||||
|
Scheduler::init();
|
||||||
}
|
}
|
||||||
\add_action( 'plugins_loaded', '\Activitypub\init' );
|
\add_action( 'plugins_loaded', '\Activitypub\init' );
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ class Activitypub {
|
||||||
\add_post_type_support( $post_type, 'activitypub' );
|
\add_post_type_support( $post_type, 'activitypub' );
|
||||||
}
|
}
|
||||||
|
|
||||||
\add_action( 'transition_post_status', array( self::class, 'schedule_post_activity' ), 33, 3 );
|
|
||||||
\add_action( 'wp_trash_post', array( self::class, 'trash_post' ), 1 );
|
\add_action( 'wp_trash_post', array( self::class, 'trash_post' ), 1 );
|
||||||
\add_action( 'untrash_post', array( self::class, 'untrash_post' ), 1 );
|
\add_action( 'untrash_post', array( self::class, 'untrash_post' ), 1 );
|
||||||
|
|
||||||
|
@ -37,13 +36,7 @@ class Activitypub {
|
||||||
public static function activate() {
|
public static function activate() {
|
||||||
self::flush_rewrite_rules();
|
self::flush_rewrite_rules();
|
||||||
|
|
||||||
if ( ! \wp_next_scheduled( 'activitypub_update_followers' ) ) {
|
Scheduler::register_schedules();
|
||||||
\wp_schedule_event( time(), 'hourly', 'activitypub_update_followers' );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! \wp_next_scheduled( 'activitypub_cleanup_followers' ) ) {
|
|
||||||
\wp_schedule_event( time(), 'daily', 'activitypub_cleanup_followers' );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,8 +47,7 @@ class Activitypub {
|
||||||
public static function deactivate() {
|
public static function deactivate() {
|
||||||
self::flush_rewrite_rules();
|
self::flush_rewrite_rules();
|
||||||
|
|
||||||
wp_unschedule_hook( 'activitypub_update_followers' );
|
Scheduler::deregister_schedules();
|
||||||
wp_unschedule_hook( 'activitypub_cleanup_followers' );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -137,48 +129,6 @@ class Activitypub {
|
||||||
return $vars;
|
return $vars;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedule Activities.
|
|
||||||
*
|
|
||||||
* @param string $new_status New post status.
|
|
||||||
* @param string $old_status Old post status.
|
|
||||||
* @param WP_Post $post Post object.
|
|
||||||
*/
|
|
||||||
public static function schedule_post_activity( $new_status, $old_status, $post ) {
|
|
||||||
// Do not send activities if post is password protected.
|
|
||||||
if ( \post_password_required( $post ) ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if post-type supports ActivityPub.
|
|
||||||
$post_types = \get_post_types_by_support( 'activitypub' );
|
|
||||||
if ( ! \in_array( $post->post_type, $post_types, true ) ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$activitypub_post = new \Activitypub\Model\Post( $post );
|
|
||||||
|
|
||||||
if ( 'publish' === $new_status && 'publish' !== $old_status ) {
|
|
||||||
\wp_schedule_single_event(
|
|
||||||
\time(),
|
|
||||||
'activitypub_send_create_activity',
|
|
||||||
array( $activitypub_post )
|
|
||||||
);
|
|
||||||
} elseif ( 'publish' === $new_status ) {
|
|
||||||
\wp_schedule_single_event(
|
|
||||||
\time(),
|
|
||||||
'activitypub_send_update_activity',
|
|
||||||
array( $activitypub_post )
|
|
||||||
);
|
|
||||||
} elseif ( 'trash' === $new_status ) {
|
|
||||||
\wp_schedule_single_event(
|
|
||||||
\time(),
|
|
||||||
'activitypub_send_delete_activity',
|
|
||||||
array( $activitypub_post )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the default avatar.
|
* Replaces the default avatar.
|
||||||
*
|
*
|
||||||
|
|
|
@ -3,7 +3,15 @@ namespace Activitypub;
|
||||||
|
|
||||||
use Acctivitypub\Model\Follower;
|
use Acctivitypub\Model\Follower;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ActivityPub Migration Class
|
||||||
|
*
|
||||||
|
* @author Matthias Pfefferle
|
||||||
|
*/
|
||||||
class Migration {
|
class Migration {
|
||||||
|
/**
|
||||||
|
* Initialize the class, registering WordPress hooks
|
||||||
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
\add_action( 'activitypub_schedule_migration', array( self::class, 'maybe_migrate' ) );
|
\add_action( 'activitypub_schedule_migration', array( self::class, 'maybe_migrate' ) );
|
||||||
}
|
}
|
||||||
|
@ -59,7 +67,7 @@ class Migration {
|
||||||
$followers = get_user_meta( $user_id, 'activitypub_followers', true );
|
$followers = get_user_meta( $user_id, 'activitypub_followers', true );
|
||||||
|
|
||||||
if ( $followers ) {
|
if ( $followers ) {
|
||||||
foreach ( $followers as $follower ) {
|
foreach ( $followers as $actor ) {
|
||||||
$meta = get_remote_metadata_by_actor( $actor );
|
$meta = get_remote_metadata_by_actor( $actor );
|
||||||
|
|
||||||
$follower = new Follower( $actor );
|
$follower = new Follower( $actor );
|
||||||
|
|
126
includes/class-scheduler.php
Normal file
126
includes/class-scheduler.php
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Activitypub;
|
||||||
|
|
||||||
|
use Activitypub\Model\Post;
|
||||||
|
use Activitypub\Collection\Followers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ActivityPub Scheduler Class
|
||||||
|
*
|
||||||
|
* @author Matthias Pfefferle
|
||||||
|
*/
|
||||||
|
class Scheduler {
|
||||||
|
/**
|
||||||
|
* Initialize the class, registering WordPress hooks
|
||||||
|
*/
|
||||||
|
public static function init() {
|
||||||
|
\add_action( 'transition_post_status', array( self::class, 'schedule_post_activity' ), 33, 3 );
|
||||||
|
|
||||||
|
\add_action( 'activitypub_update_followers', array( self::class, 'update_followers' ) );
|
||||||
|
\add_action( 'activitypub_cleanup_followers', array( self::class, 'cleanup_followers' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function register_schedules() {
|
||||||
|
if ( ! \wp_next_scheduled( 'activitypub_update_followers' ) ) {
|
||||||
|
\wp_schedule_event( time(), 'hourly', 'activitypub_update_followers' );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! \wp_next_scheduled( 'activitypub_cleanup_followers' ) ) {
|
||||||
|
\wp_schedule_event( time(), 'daily', 'activitypub_cleanup_followers' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function deregister_schedules() {
|
||||||
|
wp_unschedule_hook( 'activitypub_update_followers' );
|
||||||
|
wp_unschedule_hook( 'activitypub_cleanup_followers' );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule Activities.
|
||||||
|
*
|
||||||
|
* @param string $new_status New post status.
|
||||||
|
* @param string $old_status Old post status.
|
||||||
|
* @param WP_Post $post Post object.
|
||||||
|
*/
|
||||||
|
public static function schedule_post_activity( $new_status, $old_status, $post ) {
|
||||||
|
// Do not send activities if post is password protected.
|
||||||
|
if ( \post_password_required( $post ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if post-type supports ActivityPub.
|
||||||
|
$post_types = \get_post_types_by_support( 'activitypub' );
|
||||||
|
if ( ! \in_array( $post->post_type, $post_types, true ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$activitypub_post = new Post( $post );
|
||||||
|
|
||||||
|
if ( 'publish' === $new_status && 'publish' !== $old_status ) {
|
||||||
|
\wp_schedule_single_event(
|
||||||
|
\time(),
|
||||||
|
'activitypub_send_create_activity',
|
||||||
|
array( $activitypub_post )
|
||||||
|
);
|
||||||
|
} elseif ( 'publish' === $new_status ) {
|
||||||
|
\wp_schedule_single_event(
|
||||||
|
\time(),
|
||||||
|
'activitypub_send_update_activity',
|
||||||
|
array( $activitypub_post )
|
||||||
|
);
|
||||||
|
} elseif ( 'trash' === $new_status ) {
|
||||||
|
\wp_schedule_single_event(
|
||||||
|
\time(),
|
||||||
|
'activitypub_send_delete_activity',
|
||||||
|
array( $activitypub_post )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update followers
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function update_followers() {
|
||||||
|
$followers = Followers::get_outdated_followers( ACTIVITYPUB_OBJECT );
|
||||||
|
|
||||||
|
foreach ( $followers as $follower ) {
|
||||||
|
$meta = get_remote_metadata_by_actor( $follower->get_actor() );
|
||||||
|
|
||||||
|
if ( empty( $meta ) || ! is_array( $meta ) || is_wp_error( $meta ) ) {
|
||||||
|
$follower->set_error( $meta );
|
||||||
|
} else {
|
||||||
|
$follower->from_meta( $meta );
|
||||||
|
}
|
||||||
|
|
||||||
|
$follower->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup followers
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function cleanup_followers() {
|
||||||
|
$followers = Followers::get_faulty_followers( ACTIVITYPUB_OBJECT );
|
||||||
|
|
||||||
|
foreach ( $followers as $follower ) {
|
||||||
|
$meta = get_remote_metadata_by_actor( $follower->get_actor() );
|
||||||
|
|
||||||
|
if ( empty( $meta ) || ! is_array( $meta ) || is_wp_error( $meta ) ) {
|
||||||
|
if ( 5 >= $follower->count_errors() ) {
|
||||||
|
$follower->delete();
|
||||||
|
} else {
|
||||||
|
$follower->set_error( $meta );
|
||||||
|
$follower->update();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$follower->reset_errors();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,14 +3,12 @@ namespace Activitypub;
|
||||||
|
|
||||||
class Shortcodes {
|
class Shortcodes {
|
||||||
/**
|
/**
|
||||||
* Class constructor, registering WordPress then shortcodes
|
* Initialize the class, registering WordPress hooks
|
||||||
*
|
|
||||||
* @param WP_Post $post A WordPress Post Object
|
|
||||||
*/
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
foreach ( get_class_methods( 'Activitypub\Shortcodes' ) as $shortcode ) {
|
foreach ( get_class_methods( self::class ) as $shortcode ) {
|
||||||
if ( 'init' !== $shortcode ) {
|
if ( 'init' !== $shortcode ) {
|
||||||
add_shortcode( 'ap_' . $shortcode, array( 'Activitypub\Shortcodes', $shortcode ) );
|
add_shortcode( 'ap_' . $shortcode, array( self::class, $shortcode ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -404,4 +404,82 @@ class Followers {
|
||||||
|
|
||||||
return array_filter( $results );
|
return array_filter( $results );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undocumented function
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function get_outdated_followers( $output = ARRAY_N, $number = 50, $older_than = 604800 ) {
|
||||||
|
$args = array(
|
||||||
|
'taxonomy' => self::TAXONOMY,
|
||||||
|
'number' => $number,
|
||||||
|
'meta_key' => 'updated_at',
|
||||||
|
'orderby' => 'meta_value_num',
|
||||||
|
'order' => 'DESC',
|
||||||
|
'meta_query' => array(
|
||||||
|
array(
|
||||||
|
'key' => 'updated_at',
|
||||||
|
'value' => strtotime( 'now' ) - $older_than,
|
||||||
|
'type' => 'numeric',
|
||||||
|
'compare' => '<=',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$terms = new WP_Term_Query( $args );
|
||||||
|
|
||||||
|
$items = array();
|
||||||
|
|
||||||
|
// change output format
|
||||||
|
switch ( $output ) {
|
||||||
|
case ACTIVITYPUB_OBJECT:
|
||||||
|
foreach ( $terms->get_terms() as $follower ) {
|
||||||
|
$items[] = new Follower( $follower->name ); // phpcs:ignore
|
||||||
|
}
|
||||||
|
return $items;
|
||||||
|
case OBJECT:
|
||||||
|
return $terms->get_terms();
|
||||||
|
case ARRAY_N:
|
||||||
|
default:
|
||||||
|
foreach ( $terms->get_terms() as $follower ) {
|
||||||
|
$items[] = $follower->name; // phpcs:ignore
|
||||||
|
}
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get_faulty_followers( $output = ARRAY_N, $number = 10 ) {
|
||||||
|
$args = array(
|
||||||
|
'taxonomy' => self::TAXONOMY,
|
||||||
|
'number' => $number,
|
||||||
|
'meta_query' => array(
|
||||||
|
array(
|
||||||
|
'key' => 'errors',
|
||||||
|
'compare' => 'EXISTS',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$terms = new WP_Term_Query( $args );
|
||||||
|
|
||||||
|
$items = array();
|
||||||
|
|
||||||
|
// change output format
|
||||||
|
switch ( $output ) {
|
||||||
|
case ACTIVITYPUB_OBJECT:
|
||||||
|
foreach ( $terms->get_terms() as $follower ) {
|
||||||
|
$items[] = new Follower( $follower->name ); // phpcs:ignore
|
||||||
|
}
|
||||||
|
return $items;
|
||||||
|
case OBJECT:
|
||||||
|
return $terms->get_terms();
|
||||||
|
case ARRAY_N:
|
||||||
|
default:
|
||||||
|
foreach ( $terms->get_terms() as $follower ) {
|
||||||
|
$items[] = $follower->name; // phpcs:ignore
|
||||||
|
}
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,6 +210,10 @@ class Follower {
|
||||||
return $this->errors;
|
return $this->errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function reset_errors() {
|
||||||
|
delete_term_meta( $this->id, 'errors' );
|
||||||
|
}
|
||||||
|
|
||||||
public function count_errors() {
|
public function count_errors() {
|
||||||
$errors = $this->get_errors();
|
$errors = $this->get_errors();
|
||||||
|
|
||||||
|
@ -292,6 +296,10 @@ class Follower {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function delete() {
|
||||||
|
wp_delete_term( $this->id, Followers::TAXONOMY );
|
||||||
|
}
|
||||||
|
|
||||||
protected function update_term_meta() {
|
protected function update_term_meta() {
|
||||||
$attributes = array( 'inbox', 'shared_inbox', 'avatar', 'updated_at', 'name', 'username' );
|
$attributes = array( 'inbox', 'shared_inbox', 'avatar', 'updated_at', 'name', 'username' );
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,60 @@ class Test_Db_Activitypub_Followers extends WP_UnitTestCase {
|
||||||
$this->assertNull( $follower );
|
$this->assertNull( $follower );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_get_outdated_followers() {
|
||||||
|
$followers = array( 'https://example.com/author/jon', 'https://example.org/author/doe', 'http://sally.example.org' );
|
||||||
|
|
||||||
|
$pre_http_request = new MockAction();
|
||||||
|
add_filter( 'pre_http_request', array( $pre_http_request, 'filter' ), 10, 3 );
|
||||||
|
|
||||||
|
foreach ( $followers as $follower ) {
|
||||||
|
\Activitypub\Collection\Followers::add_follower( 1, $follower );
|
||||||
|
}
|
||||||
|
|
||||||
|
$follower = new \Activitypub\Model\Follower( 'https://example.com/author/jon' );
|
||||||
|
|
||||||
|
update_term_meta( $follower->get_id(), 'updated_at', strtotime( 'now' ) - 804800 );
|
||||||
|
|
||||||
|
$followers = \Activitypub\Collection\Followers::get_outdated_followers();
|
||||||
|
$this->assertEquals( 1, count( $followers ) );
|
||||||
|
$this->assertEquals( 'https://example.com/author/jon', $followers[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_get_faulty_followers() {
|
||||||
|
$followers = array( 'https://example.com/author/jon', 'https://example.org/author/doe', 'http://sally.example.org' );
|
||||||
|
|
||||||
|
$pre_http_request = new MockAction();
|
||||||
|
add_filter( 'pre_http_request', array( $pre_http_request, 'filter' ), 10, 3 );
|
||||||
|
|
||||||
|
foreach ( $followers as $follower ) {
|
||||||
|
\Activitypub\Collection\Followers::add_follower( 1, $follower );
|
||||||
|
}
|
||||||
|
|
||||||
|
$follower = new \Activitypub\Model\Follower( 'http://sally.example.org' );
|
||||||
|
|
||||||
|
for ( $i = 1; $i <= 15; $i++ ) {
|
||||||
|
add_term_meta( $follower->get_id(), 'errors', 'error ' . $i );
|
||||||
|
}
|
||||||
|
|
||||||
|
$follower = new \Activitypub\Model\Follower( 'http://sally.example.org' );
|
||||||
|
$count = $follower->count_errors();
|
||||||
|
|
||||||
|
$followers = \Activitypub\Collection\Followers::get_faulty_followers();
|
||||||
|
|
||||||
|
$this->assertEquals( 1, count( $followers ) );
|
||||||
|
$this->assertEquals( 'http://sally.example.org', $followers[0] );
|
||||||
|
|
||||||
|
$follower->reset_errors();
|
||||||
|
|
||||||
|
$follower = new \Activitypub\Model\Follower( 'http://sally.example.org' );
|
||||||
|
$count = $follower->count_errors();
|
||||||
|
|
||||||
|
$followers = \Activitypub\Collection\Followers::get_faulty_followers();
|
||||||
|
|
||||||
|
$this->assertEquals( 0, count( $followers ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static function http_request_host_is_external( $in, $host ) {
|
public static function http_request_host_is_external( $in, $host ) {
|
||||||
if ( in_array( $host, array( 'example.com', 'example.org' ), true ) ) {
|
if ( in_array( $host, array( 'example.com', 'example.org' ), true ) ) {
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in a new issue