wip
This commit is contained in:
parent
7f23ed17c0
commit
64ad7d61ef
9 changed files with 709 additions and 2 deletions
164
includes/activitypub/collection/class-event-sources.php
Normal file
164
includes/activitypub/collection/class-event-sources.php
Normal file
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
/**
|
||||
* Event sources collection file.
|
||||
*
|
||||
* @package ActivityPub_Event_Bridge
|
||||
* @license AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace ActivityPub_Event_Bridge\ActivityPub\Collection;
|
||||
|
||||
use WP_Error;
|
||||
use WP_Query;
|
||||
use ActivityPub_Event_Bridge\ActivityPub\Event_Source;
|
||||
|
||||
use function Activitypub\is_tombstone;
|
||||
use function Activitypub\get_remote_metadata_by_actor;
|
||||
|
||||
/**
|
||||
* ActivityPub Event Sources (=Followed Actors) Collection.
|
||||
*/
|
||||
class Event_Sources {
|
||||
/**
|
||||
* The custom post type.
|
||||
*/
|
||||
const POST_TYPE = 'activitypub_event_bridge_follow';
|
||||
|
||||
/**
|
||||
* Register the post type used to store the external event sources (i.e., followed ActivityPub actors).
|
||||
*/
|
||||
public static function register_post_type() {
|
||||
register_post_type(
|
||||
self::POST_TYPE,
|
||||
array(
|
||||
'labels' => array(
|
||||
'name' => _x( 'Event Sources', 'post_type plural name', 'activitypub' ),
|
||||
'singular_name' => _x( 'Event Source', 'post_type single name', 'activitypub' ),
|
||||
),
|
||||
'public' => false,
|
||||
'hierarchical' => false,
|
||||
'rewrite' => false,
|
||||
'query_var' => false,
|
||||
'delete_with_user' => false,
|
||||
'can_export' => true,
|
||||
'supports' => array(),
|
||||
)
|
||||
);
|
||||
|
||||
\register_post_meta(
|
||||
self::POST_TYPE,
|
||||
'activitypub_inbox',
|
||||
array(
|
||||
'type' => 'string',
|
||||
'single' => true,
|
||||
'sanitize_callback' => 'sanitize_url',
|
||||
)
|
||||
);
|
||||
|
||||
\register_post_meta(
|
||||
self::POST_TYPE,
|
||||
'activitypub_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 );
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
\register_post_meta(
|
||||
self::POST_TYPE,
|
||||
'activitypub_user_id',
|
||||
array(
|
||||
'type' => 'string',
|
||||
'single' => false,
|
||||
'sanitize_callback' => function ( $value ) {
|
||||
return esc_sql( $value );
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
\register_post_meta(
|
||||
self::POST_TYPE,
|
||||
'activitypub_actor_json',
|
||||
array(
|
||||
'type' => 'string',
|
||||
'single' => true,
|
||||
'sanitize_callback' => function ( $value ) {
|
||||
return sanitize_text_field( $value );
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new Event Source.
|
||||
*
|
||||
* @param string $actor The Actor ID.
|
||||
*
|
||||
* @return Event_Source|WP_Error The Followed (WP_Post array) or an WP_Error.
|
||||
*/
|
||||
public static function add_event_source( $actor ) {
|
||||
$meta = get_remote_metadata_by_actor( $actor );
|
||||
|
||||
if ( is_tombstone( $meta ) ) {
|
||||
return $meta;
|
||||
}
|
||||
|
||||
if ( empty( $meta ) || ! is_array( $meta ) || is_wp_error( $meta ) ) {
|
||||
return new WP_Error( 'activitypub_invalid_follower', __( 'Invalid Follower', 'activitypub' ), array( 'status' => 400 ) );
|
||||
}
|
||||
|
||||
$event_source = new Event_Source();
|
||||
$event_source->from_array( $meta );
|
||||
|
||||
$post_id = $event_source->save();
|
||||
|
||||
if ( is_wp_error( $post_id ) ) {
|
||||
return $post_id;
|
||||
}
|
||||
|
||||
return $event_source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an Event Source (=Followed ActivityPub actor).
|
||||
*
|
||||
* @param string $actor The Actor URL.
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
public static function remove_event_source( $actor ) {
|
||||
$actor = true;
|
||||
return $actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Followers.
|
||||
*
|
||||
* @return array The Term list of Followers.
|
||||
*/
|
||||
public static function get_all_followers() {
|
||||
$args = array(
|
||||
'nopaging' => true,
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'activitypub_inbox',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
array(
|
||||
'key' => 'activitypub_actor_json',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
);
|
||||
return self::get_followers( null, null, null, $args );
|
||||
}
|
||||
}
|
59
includes/activitypub/model/class-event-source.php
Normal file
59
includes/activitypub/model/class-event-source.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
/**
|
||||
* Event-Source (=ActivityPub Actor that is followed) model.
|
||||
*
|
||||
* @package ActivityPub_Event_Bridge
|
||||
* @license AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace ActivityPub_Event_Bridge\ActivityPub;
|
||||
|
||||
use Activitypub\Activity\Actor;
|
||||
use ActivityPub_Event_Bridge\ActivityPub\Collection\Event_Sources;
|
||||
use WP_Error;
|
||||
|
||||
/**
|
||||
* Event-Source (=ActivityPub Actor that is followed) model.
|
||||
*/
|
||||
class Event_Source extends Actor {
|
||||
/**
|
||||
* Get the Icon URL (Avatar).
|
||||
*
|
||||
* @return string The URL to the Avatar.
|
||||
*/
|
||||
public function get_icon_url() {
|
||||
$icon = $this->get_icon();
|
||||
|
||||
if ( ! $icon ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( is_array( $icon ) ) {
|
||||
return $icon['url'];
|
||||
}
|
||||
|
||||
return $icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Custom-Post-Type input to an \ActivityPub_Event_Bridge\ActivityPub\Model\Event_Source.
|
||||
*
|
||||
* @param \WP_Post $post The post object.
|
||||
* @return \ActivityPub_Event_Bridge\ActivityPub\Event_Source|WP_Error
|
||||
*/
|
||||
public static function init_from_cpt( $post ) {
|
||||
if ( Event_Sources::POST_TYPE !== $post->post_type ) {
|
||||
return false;
|
||||
}
|
||||
$actor_json = get_post_meta( $post->ID, 'activitypub_actor_json', true );
|
||||
$object = self::init_from_json( $actor_json );
|
||||
$object->set__id( $post->ID );
|
||||
$object->set_id( $post->guid );
|
||||
$object->set_name( $post->post_title );
|
||||
$object->set_summary( $post->post_excerpt );
|
||||
$object->set_published( gmdate( 'Y-m-d H:i:s', strtotime( $post->post_date ) ) );
|
||||
$object->set_updated( gmdate( 'Y-m-d H:i:s', strtotime( $post->post_modified ) ) );
|
||||
|
||||
return $object;
|
||||
}
|
||||
}
|
85
includes/admin/class-event-sources.php
Normal file
85
includes/admin/class-event-sources.php
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
* Event Sources.
|
||||
*
|
||||
* @package Activitypub_Event_Bridge
|
||||
*/
|
||||
|
||||
namespace ActivityPub_Event_Bridge\Admin;
|
||||
|
||||
use Activitypub\Collection\Actors;
|
||||
use Activitypub\Activity\Extended_Object\Event;
|
||||
|
||||
use function Activitypub\get_remote_metadata_by_actor;
|
||||
|
||||
/**
|
||||
* Manage following other Event Sources (ActivityPub actors) and importing their Events.
|
||||
*/
|
||||
class Event_Sources {
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
\add_action( 'init', array( $this, 'register_post_meta' ) );
|
||||
|
||||
\add_action( 'activitypub_inbox', array( $this, 'handle_activitypub_inbox' ), 15, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the ActivityPub Inbox.
|
||||
*
|
||||
* @param array $data The raw post data JSON object as an associative array.
|
||||
* @param int $user_id The target user id.
|
||||
* @param string $type The activity type.
|
||||
*/
|
||||
public static function handle_activitypub_inbox( $data, $user_id, $type ) {
|
||||
if ( Actors::APPLICATION_USER_ID !== $user_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! in_array( $type, array( 'Create', 'Delete', 'Announce', 'Undo Announce' ), true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event = Event::init_from_array( $data );
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get metadata.
|
||||
*
|
||||
* @param string $url The URL.
|
||||
*/
|
||||
public static function get_metadata( $url ) {
|
||||
if ( ! is_string( $url ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if ( false !== strpos( $url, '@' ) ) {
|
||||
if ( false === strpos( $url, '/' ) && preg_match( '#^https?://#', $url, $m ) ) {
|
||||
$url = substr( $url, strlen( $m[0] ) );
|
||||
}
|
||||
}
|
||||
return get_remote_metadata_by_actor( $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond to the Ajax request to fetch feeds
|
||||
*/
|
||||
public function ajax_fetch_events() {
|
||||
if ( ! isset( $_POST['activitypub_event_bridge'] ) ) {
|
||||
wp_send_json_error( 'missing-parameters' );
|
||||
}
|
||||
|
||||
check_ajax_referer( 'fetch-events-' . sanitize_user( wp_unslash( $_POST['actor'] ) ) );
|
||||
|
||||
$actor = Actors::get_by_resource( sanitize_user( wp_unslash( $_POST['actor'] ) ) );
|
||||
if ( ! $actor ) {
|
||||
wp_send_json_error( 'unknown-actor' );
|
||||
}
|
||||
|
||||
$actor->retrieve();
|
||||
|
||||
wp_send_json_success();
|
||||
}
|
||||
}
|
|
@ -116,6 +116,11 @@ class Settings_Page {
|
|||
|
||||
\load_template( ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_DIR . 'templates/settings.php', true, $args );
|
||||
break;
|
||||
case 'event-sources':
|
||||
wp_enqueue_script( 'thickbox' );
|
||||
wp_enqueue_style( 'thickbox' );
|
||||
\load_template( ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_DIR . 'templates/event-sources.php', true );
|
||||
break;
|
||||
case 'welcome':
|
||||
default:
|
||||
wp_enqueue_script( 'plugin-install' );
|
||||
|
|
97
includes/class-event-sources.php
Normal file
97
includes/class-event-sources.php
Normal file
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
/**
|
||||
* Class for handling and saving the ActivityPub event sources (i.e. follows).
|
||||
*
|
||||
* @package ActivityPub_Event_Bridge
|
||||
*/
|
||||
|
||||
namespace ActivityPub_Event_Bridge;
|
||||
|
||||
use Activitypub\Http;
|
||||
use Exception;
|
||||
|
||||
use function register_post_type;
|
||||
|
||||
/**
|
||||
* Class for handling and saving the ActivityPub event sources (i.e. follows).
|
||||
*
|
||||
* @package ActivityPub_Event_Bridge
|
||||
*/
|
||||
class Event_Sources {
|
||||
/**
|
||||
* The custom post type.
|
||||
*/
|
||||
const POST_TYPE = 'activitypub_event_bridge_follow';
|
||||
|
||||
/**
|
||||
* Register the post type used to store the external event sources (i.e., followed ActivityPub actors).
|
||||
*/
|
||||
public static function register_post_type() {
|
||||
register_post_type(
|
||||
self::POST_TYPE,
|
||||
array(
|
||||
'labels' => array(
|
||||
'name' => _x( 'Event Sources', 'post_type plural name', 'activitypub' ),
|
||||
'singular_name' => _x( 'Event Source', 'post_type single name', 'activitypub' ),
|
||||
),
|
||||
'public' => false,
|
||||
'hierarchical' => false,
|
||||
'rewrite' => false,
|
||||
'query_var' => false,
|
||||
'delete_with_user' => false,
|
||||
'can_export' => true,
|
||||
'supports' => array(),
|
||||
)
|
||||
);
|
||||
|
||||
\register_post_meta(
|
||||
self::POST_TYPE,
|
||||
'activitypub_inbox',
|
||||
array(
|
||||
'type' => 'string',
|
||||
'single' => true,
|
||||
'sanitize_callback' => 'sanitize_url',
|
||||
)
|
||||
);
|
||||
|
||||
\register_post_meta(
|
||||
self::POST_TYPE,
|
||||
'activitypub_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 );
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
\register_post_meta(
|
||||
self::POST_TYPE,
|
||||
'activitypub_user_id',
|
||||
array(
|
||||
'type' => 'string',
|
||||
'single' => false,
|
||||
'sanitize_callback' => function ( $value ) {
|
||||
return esc_sql( $value );
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
\register_post_meta(
|
||||
self::POST_TYPE,
|
||||
'activitypub_actor_json',
|
||||
array(
|
||||
'type' => 'string',
|
||||
'single' => true,
|
||||
'sanitize_callback' => function ( $value ) {
|
||||
return sanitize_text_field( $value );
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -181,6 +181,7 @@ class Setup {
|
|||
}
|
||||
|
||||
add_action( 'init', array( Health_Check::class, 'init' ) );
|
||||
add_action( 'init', array( Event_Sources::class, 'register_taxonomy' ) );
|
||||
|
||||
// Check if the minimum required version of the ActivityPub plugin is installed.
|
||||
if ( ! version_compare( $this->activitypub_plugin_version, ACTIVITYPUB_EVENT_BRIDGE_ACTIVITYPUB_PLUGIN_MIN_VERSION ) ) {
|
||||
|
|
240
includes/table/class-event-sources.php
Normal file
240
includes/table/class-event-sources.php
Normal file
|
@ -0,0 +1,240 @@
|
|||
<?php
|
||||
/**
|
||||
* Event Sources Table-Class file.
|
||||
*
|
||||
* @package ActivityPub_Event_Bridge
|
||||
*/
|
||||
|
||||
namespace ActivityPub_Event_Bridge\Table;
|
||||
|
||||
use WP_List_Table;
|
||||
use Activitypub\Collection\Followers as FollowerCollection;
|
||||
use ActivityPub_Event_Bridge\ActivityPub\Event_Source;
|
||||
|
||||
use function Activitypub\object_to_uri;
|
||||
|
||||
if ( ! \class_exists( '\WP_List_Table' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Followers Table-Class.
|
||||
*/
|
||||
class Event_Sources extends WP_List_Table {
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct(
|
||||
array(
|
||||
'singular' => \__( 'Event Source', 'activitypub' ),
|
||||
'plural' => \__( 'Event Sources', 'activitypub' ),
|
||||
'ajax' => false,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get columns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_columns() {
|
||||
return array(
|
||||
'cb' => '<input type="checkbox" />',
|
||||
'avatar' => \__( 'Avatar', 'activitypub' ),
|
||||
'post_title' => \__( 'Name', 'activitypub' ),
|
||||
'username' => \__( 'Username', 'activitypub' ),
|
||||
'url' => \__( 'URL', 'activitypub' ),
|
||||
'published' => \__( 'Followed', 'activitypub' ),
|
||||
'modified' => \__( 'Last updated', 'activitypub' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sortable columns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_sortable_columns() {
|
||||
return array(
|
||||
'post_title' => array( 'post_title', true ),
|
||||
'modified' => array( 'modified', false ),
|
||||
'published' => array( 'published', false ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare items.
|
||||
*/
|
||||
public function prepare_items() {
|
||||
$columns = $this->get_columns();
|
||||
$hidden = array();
|
||||
|
||||
$this->process_action();
|
||||
$this->_column_headers = array( $columns, $hidden, $this->get_sortable_columns() );
|
||||
|
||||
$page_num = $this->get_pagenum();
|
||||
$per_page = 20;
|
||||
|
||||
$args = array();
|
||||
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||
if ( isset( $_GET['orderby'] ) ) {
|
||||
$args['orderby'] = sanitize_text_field( wp_unslash( $_GET['orderby'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $_GET['order'] ) ) {
|
||||
$args['order'] = sanitize_text_field( wp_unslash( $_GET['order'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $_GET['s'] ) && isset( $_REQUEST['_wpnonce'] ) ) {
|
||||
$nonce = sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) );
|
||||
if ( wp_verify_nonce( $nonce, 'bulk-' . $this->_args['plural'] ) ) {
|
||||
$args['s'] = sanitize_text_field( wp_unslash( $_GET['s'] ) );
|
||||
}
|
||||
}
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
$dummy_event_sources = array(
|
||||
'total' => 1,
|
||||
'actors' => array(
|
||||
Event_Source::init_from_array(
|
||||
array(
|
||||
'id' => 'https://graz.social/@linos',
|
||||
'url' => 'https://graz.social/@linos',
|
||||
'preferredUsername' => 'linos',
|
||||
'name' => 'André Menrath',
|
||||
'icon' => 'https://graz.social/system/accounts/avatars/000/000/001/original/fe1c795256720361.jpeg',
|
||||
)
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$event_sources = $dummy_event_sources;
|
||||
$actors = $event_sources['actors'];
|
||||
$counter = $event_sources['total'];
|
||||
|
||||
$this->items = array();
|
||||
$this->set_pagination_args(
|
||||
array(
|
||||
'total_items' => $counter,
|
||||
'total_pages' => ceil( $counter / $per_page ),
|
||||
'per_page' => $per_page,
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $actors as $actor ) {
|
||||
$item = array(
|
||||
'icon' => esc_attr( $actor->get_icon_url() ),
|
||||
'post_title' => esc_attr( $actor->get_name() ),
|
||||
'username' => esc_attr( $actor->get_preferred_username() ),
|
||||
'url' => esc_attr( object_to_uri( $actor->get_url() ) ),
|
||||
'identifier' => esc_attr( $actor->get_id() ),
|
||||
'published' => esc_attr( $actor->get_published() ),
|
||||
'modified' => esc_attr( $actor->get_updated() ),
|
||||
);
|
||||
|
||||
$this->items[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bulk actions.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_bulk_actions() {
|
||||
return array(
|
||||
'delete' => __( 'Delete', 'activitypub' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Column default.
|
||||
*
|
||||
* @param array $item Item.
|
||||
* @param string $column_name Column name.
|
||||
* @return string
|
||||
*/
|
||||
public function column_default( $item, $column_name ) {
|
||||
if ( ! array_key_exists( $column_name, $item ) ) {
|
||||
return __( 'None', 'activitypub' );
|
||||
}
|
||||
return $item[ $column_name ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Column avatar.
|
||||
*
|
||||
* @param array $item Item.
|
||||
* @return string
|
||||
*/
|
||||
public function column_avatar( $item ) {
|
||||
return sprintf(
|
||||
'<img src="%s" width="25px;" />',
|
||||
$item['icon']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Column url.
|
||||
*
|
||||
* @param array $item Item.
|
||||
* @return string
|
||||
*/
|
||||
public function column_url( $item ) {
|
||||
return sprintf(
|
||||
'<a href="%s" target="_blank">%s</a>',
|
||||
esc_url( $item['url'] ),
|
||||
$item['url']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Column cb.
|
||||
*
|
||||
* @param array $item Item.
|
||||
* @return string
|
||||
*/
|
||||
public function column_cb( $item ) {
|
||||
return sprintf( '<input type="checkbox" name="followers[]" value="%s" />', esc_attr( $item['identifier'] ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Process action.
|
||||
*/
|
||||
public function process_action() {
|
||||
if ( ! isset( $_REQUEST['followers'] ) || ! isset( $_REQUEST['_wpnonce'] ) ) {
|
||||
return;
|
||||
}
|
||||
$nonce = sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) );
|
||||
if ( ! wp_verify_nonce( $nonce, 'bulk-' . $this->_args['plural'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'edit_user', $this->user_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$followers = $_REQUEST['followers']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
||||
|
||||
if ( $this->current_action() === 'delete' ) {
|
||||
if ( ! is_array( $followers ) ) {
|
||||
$followers = array( $followers );
|
||||
}
|
||||
foreach ( $followers as $follower ) {
|
||||
FollowerCollection::remove_follower( $this->user_id, $follower );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns user count.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_user_count() {
|
||||
return FollowerCollection::count_followers( $this->user_id );
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ $args = wp_parse_args(
|
|||
array(
|
||||
'welcome' => '',
|
||||
'settings' => '',
|
||||
'event-sources' => '',
|
||||
)
|
||||
);
|
||||
?>
|
||||
|
@ -28,6 +29,10 @@ $args = wp_parse_args(
|
|||
<a href="<?php echo \esc_url( admin_url( 'options-general.php?page=activitypub-event-bridge&tab=settings' ) ); ?>" class="activitypub-event-bridge-settings-tab <?php echo \esc_attr( $args['settings'] ); ?>">
|
||||
<?php \esc_html_e( 'Settings', 'activitypub-event-bridge' ); ?>
|
||||
</a>
|
||||
|
||||
<a href="<?php echo \esc_url( admin_url( 'options-general.php?page=activitypub-event-bridge&tab=event-sources' ) ); ?>" class="activitypub-event-bridge-settings-tab <?php echo \esc_attr( $args['event-sources'] ); ?>">
|
||||
<?php \esc_html_e( 'Event Sources', 'activitypub-event-bridge' ); ?>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
<hr class="wp-header-end">
|
||||
|
|
51
templates/event-sources.php
Normal file
51
templates/event-sources.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/**
|
||||
* Event Sources management page for the ActivityPub Event Bridge.
|
||||
*
|
||||
* @package ActivityPub_Event_Bridge
|
||||
*/
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
\load_template(
|
||||
__DIR__ . '/admin-header.php',
|
||||
true,
|
||||
array(
|
||||
'event-sources' => 'active',
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$table = new \ActivityPub_Event_Bridge\Table\Event_Sources();
|
||||
?>
|
||||
|
||||
<div class="activitypub-event-bridge-settings activitypub-event-bridge-settings-page hide-if-no-js">
|
||||
|
||||
<div class="box">
|
||||
<h2> <?php esc_html_e( 'Federated event sources', 'activitypub-event-bridge' ); ?> </h2>
|
||||
<p> <?php esc_html_e( 'Here you can add any Fediverse Account.', 'activitypub-event-bridge' ); ?> </p>
|
||||
|
||||
<!-- Button that triggers ThickBox -->
|
||||
<a href="#TB_inline?width=600&height=400&inlineId=activitypub_event_bridge_add_new_source" class="thickbox button button-primary">
|
||||
<?php esc_html_e( 'Add new', 'activitypub-event-bridge' ); ?>
|
||||
</a>
|
||||
|
||||
<!-- ThickBox content (hidden initially) -->
|
||||
<div id="activitypub_event_bridge_add_new_source" style="display:none;">
|
||||
<h2><?php esc_html_e( 'Add new ActivityPub follow', 'activitypub-event-bridge' ); ?> </h2>
|
||||
<p> <?php esc_html_e( 'Here you can enter either a handle or instance URL.', 'activitypub-event-bridge' ); ?> </p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wrap activitypub-followers-page">
|
||||
<form method="get">
|
||||
<input type="hidden" name="page" value="activitypub" />
|
||||
<input type="hidden" name="tab" value="followers" />
|
||||
<?php
|
||||
$table->prepare_items();
|
||||
$table->search_box( 'Search', 'search' );
|
||||
$table->display();
|
||||
?>
|
||||
</form>
|
||||
</div>
|
Loading…
Reference in a new issue