better error handling

This commit is contained in:
Matthias Pfefferle 2023-05-02 14:39:25 +02:00
parent 077c43bf95
commit dea5f38561
4 changed files with 146 additions and 28 deletions

View file

@ -9,8 +9,7 @@ use Activitypub\Webfinger;
use Activitypub\Model\Activity; use Activitypub\Model\Activity;
use Activitypub\Model\Follower; use Activitypub\Model\Follower;
use function Activitypub\safe_remote_get; use function Activitypub\is_tombstone;
use function Activitypub\safe_remote_post;
use function Activitypub\get_remote_metadata_by_actor; use function Activitypub\get_remote_metadata_by_actor;
/** /**
@ -152,6 +151,22 @@ class Followers {
) )
); );
register_term_meta(
self::TAXONOMY,
'errors',
array(
'type' => 'string',
'single' => false,
'sanitize_callback' => function( $value ) {
if ( ! is_string( $value ) ) {
throw new Exception( 'Error message is no valid string' );
}
return esc_sql( $value );
},
)
);
do_action( 'activitypub_after_register_taxonomy' ); do_action( 'activitypub_after_register_taxonomy' );
} }
@ -197,12 +212,16 @@ class Followers {
public static function add_follower( $user_id, $actor ) { public static function add_follower( $user_id, $actor ) {
$meta = get_remote_metadata_by_actor( $actor ); $meta = get_remote_metadata_by_actor( $actor );
if ( ! $meta || is_wp_error( $meta ) || ! is_array( $meta ) ) { $follower = new Follower( $actor );
return $meta;
if ( is_tombstone( $meta ) ) {
return;
} if ( empty( $meta ) || ! is_array( $meta ) || is_wp_error( $meta ) ) {
$follower->set_error( $meta );
} else {
$follower->from_meta( $meta );
} }
$follower = new Follower( $actor );
$follower->from_meta( $meta );
$follower->upsert(); $follower->upsert();
$result = wp_set_object_terms( $user_id, $follower->get_actor(), self::TAXONOMY, true ); $result = wp_set_object_terms( $user_id, $follower->get_actor(), self::TAXONOMY, true );
@ -299,19 +318,29 @@ class Followers {
* *
* @return array The Term list of Followers, the format depends on $output * @return array The Term list of Followers, the format depends on $output
*/ */
public static function get_followers( $user_id, $output = ARRAY_N, $number = null, $offset = null ) { public static function get_followers( $user_id, $output = ARRAY_N, $number = null, $offset = null, $hide_errors = false, $args = array() ) {
$terms = new WP_Term_Query( $defaults = array(
array( 'taxonomy' => self::TAXONOMY,
'taxonomy' => self::TAXONOMY, 'hide_empty' => false,
'hide_empty' => false, 'object_ids' => $user_id,
'object_ids' => $user_id, 'number' => $number,
'number' => $number, 'offset' => $offset,
'offset' => $offset, 'orderby' => 'id',
'orderby' => 'id', 'order' => 'ASC',
'order' => 'ASC',
)
); );
if ( true === $hide_errors ) {
$defaults['meta_query'] = array(
array(
'key' => 'errors',
'compare' => 'NOT EXISTS',
),
);
}
$args = wp_parse_args( $args, $defaults );
$terms = new WP_Term_Query( $args );
$items = array(); $items = array();
// change output format // change output format
@ -358,6 +387,12 @@ class Followers {
'hide_empty' => false, 'hide_empty' => false,
'object_ids' => $user_id, 'object_ids' => $user_id,
'fields' => 'ids', 'fields' => 'ids',
'meta_query' => array(
array(
'key' => 'inbox',
'compare' => 'EXISTS',
),
),
) )
); );

View file

@ -211,3 +211,24 @@ function get_author_description( $user_id ) {
} }
return $description; return $description;
} }
/**
* Check for Tombstone Objects
*
* @see https://www.w3.org/TR/activitypub/#delete-activity-outbox
*
* @param WP_Error $wp_error A WP_Error-Response of an HTTP-Request
*
* @return boolean true if HTTP-Code is 410 or 404
*/
function is_tombstone( $wp_error ) {
if ( ! is_wp_error( $wp_error ) ) {
return false;
}
if ( in_array( (int) $wp_error->get_error_code(), array( 404, 410 ), true ) ) {
return true;
}
return false;
}

View file

@ -92,6 +92,22 @@ class Follower {
*/ */
private $meta; private $meta;
/**
* The latest received error.
*
* This will only temporary and will saved to $this->errors
*
* @var string
*/
private $error;
/**
* A list of errors
*
* @var array
*/
private $errors;
/** /**
* Maps the meta fields to the local db fields * Maps the meta fields to the local db fields
* *
@ -185,10 +201,39 @@ class Follower {
return null; return null;
} }
public function get_errors() {
if ( $this->errors ) {
return $this->errors;
}
$this->errors = get_term_meta( $this->id, 'errors' );
return $this->errors;
}
public function count_errors() {
$errors = $this->get_errors();
if ( is_array( $errors ) && ! empty( $errors ) ) {
return count( $errors );
}
return 0;
}
public function get_latest_error_message() {
$errors = $this->get_errors();
if ( is_array( $errors ) && ! empty( $errors ) ) {
return reset( $errors );
}
return '';
}
public function get_meta_by( $attribute ) { public function get_meta_by( $attribute ) {
$meta = $this->get_meta(); $meta = $this->get_meta();
// try mapped data ($this->map_meta) // try mapped data (see $this->map_meta)
foreach ( $this->map_meta as $remote => $local ) { foreach ( $this->map_meta as $remote => $local ) {
if ( $attribute === $local && isset( $meta[ $remote ] ) ) { if ( $attribute === $local && isset( $meta[ $remote ] ) ) {
return $meta[ $remote ]; return $meta[ $remote ];
@ -251,8 +296,21 @@ class Follower {
foreach ( $attributes as $attribute ) { foreach ( $attributes as $attribute ) {
if ( $this->get( $attribute ) ) { if ( $this->get( $attribute ) ) {
update_term_meta( $this->id, $attribute, $this->get( $attribute ), true ); update_term_meta( $this->id, $attribute, $this->get( $attribute ) );
} }
} }
if ( $this->error ) {
if ( is_string( $this->error ) ) {
$error = $this->error;
} elseif ( is_wp_error( $this->error ) ) {
$error = $this->error->get_error_message();
} else {
$error = __( 'Unknown Error or misconfigured Error-Message', 'activitypub' );
}
add_term_meta( $this->id, 'errors', $error );
}
} }
} }

View file

@ -11,11 +11,13 @@ if ( ! \class_exists( '\WP_List_Table' ) ) {
class Followers extends WP_List_Table { class Followers extends WP_List_Table {
public function get_columns() { public function get_columns() {
return array( return array(
'cb' => '<input type="checkbox" />', 'cb' => '<input type="checkbox" />',
'avatar' => \__( 'Avatar', 'activitypub' ), 'avatar' => \__( 'Avatar', 'activitypub' ),
'name' => \__( 'Name', 'activitypub' ), 'name' => \__( 'Name', 'activitypub' ),
'username' => \__( 'Username', 'activitypub' ), 'username' => \__( 'Username', 'activitypub' ),
'identifier' => \__( 'Identifier', 'activitypub' ), 'identifier' => \__( 'Identifier', 'activitypub' ),
'errors' => \__( 'Errors', 'activitypub' ),
'latest-error' => \__( 'Latest Error Message', 'activitypub' ),
); );
} }
@ -47,10 +49,12 @@ class Followers extends WP_List_Table {
foreach ( $follower as $follower ) { foreach ( $follower as $follower ) {
$item = array( $item = array(
'avatar' => esc_attr( $follower->get_avatar() ), 'avatar' => esc_attr( $follower->get_avatar() ),
'name' => esc_attr( $follower->get_name() ), 'name' => esc_attr( $follower->get_name() ),
'username' => esc_attr( $follower->get_username() ), 'username' => esc_attr( $follower->get_username() ),
'identifier' => esc_attr( $follower->get_actor() ), 'identifier' => esc_attr( $follower->get_actor() ),
'errors' => $follower->count_errors(),
'latest-error' => $follower->get_latest_error_message(),
); );
$this->items[] = $item; $this->items[] = $item;