installed plugin Event Bridge for ActivityPub version 1.1.0

This commit is contained in:
2025-04-29 21:32:06 +00:00
committed by Gitium
parent fc3d7ab181
commit cf022e2628
93 changed files with 14432 additions and 0 deletions

View File

@ -0,0 +1,103 @@
<?php
/**
* Class responsible for Event Plugin related admin notices.
*
* Notices for guiding to proper configuration of ActivityPub with event plugins.
*
* @package Event_Bridge_For_ActivityPub
* @since 1.0.0
* @license AGPL-3.0-or-later
*/
namespace Event_Bridge_For_ActivityPub\Admin;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use Event_Bridge_For_ActivityPub\Integrations\Event_Plugin_Integration;
/**
* Class responsible for Event Plugin related admin notices.
*
* Notices for guiding to proper configuration of ActivityPub with event plugins.
*
* @since 1.0.0
*/
class Event_Plugin_Admin_Notices {
/**
* Information about the event plugin.
*
* @var Event_Plugin_Integration
*/
protected $event_plugin;
/**
* Adds admin notices to an active supported event plugin.
*
* @param Event_Plugin_Integration $event_plugin Class that has implements functions to handle a certain supported activate event plugin.
*/
public function __construct( $event_plugin ) {
$this->event_plugin = $event_plugin;
if ( $this->event_post_type_is_not_activitypub_enabled() ) {
add_action( 'admin_notices', array( $this, 'admin_notice_activitypub_not_enabled_for_post_type' ), 10, 1 );
}
}
/**
* Check if ActivityPub is enabled for the custom post type of the event plugin.
*
* @return bool
*/
private function event_post_type_is_not_activitypub_enabled(): bool {
return ! in_array( $this->event_plugin::get_post_type(), get_option( 'activitypub_support_post_types', array() ), true );
}
/**
* Display the admin notices for the plugins.
*
* @return void
*/
public function admin_notice_activitypub_not_enabled_for_post_type(): void {
if ( $this->event_plugin::is_plugin_page() ) {
$this->do_admin_notice_post_type_not_activitypub_enabled();
}
}
/**
* Print admin notice that the current post type is not enabled in the ActivityPub plugin.
*
* @return void
*/
private function do_admin_notice_post_type_not_activitypub_enabled(): void {
$all_plugins = get_plugins();
$event_plugin_file = $this->event_plugin::get_relative_plugin_file();
if ( isset( $all_plugins[ $event_plugin_file ]['Name'] ) ) {
$event_plugin_name = $all_plugins[ $event_plugin_file ]['Name'];
} elseif ( isset( get_mu_plugins()[ $event_plugin_file ]['Name'] ) ) {
$event_plugin_name = get_mu_plugins()[ $event_plugin_file ]['Name'];
} else {
return;
}
$activitypub_plugin_data = get_plugin_data( ACTIVITYPUB_PLUGIN_FILE );
$notice = sprintf(
/* translators: 1: the name of the event plugin a admin notice is shown. 2: The name of the ActivityPub plugin. */
_x(
'You have installed the <i>%1$s</i> plugin, but the event post type of the plugin <i>%2$s</i> is <b>not enabled</b> in the <a href="%3$s">%1$s settings</a>.',
'admin notice',
'event-bridge-for-activitypub'
),
esc_html( $activitypub_plugin_data['Name'] ),
esc_html( $event_plugin_name ),
admin_url( 'options-general.php?page=activitypub&tab=settings' )
);
$allowed_html = array(
'a' => array(
'href' => true,
'title' => true,
),
'b' => array(),
'i' => array(),
);
echo '<div class="notice notice-warning is-dismissible"><p>' . \wp_kses( $notice, $allowed_html ) . '</p></div>';
}
}

View File

@ -0,0 +1,152 @@
<?php
/**
* Class responsible for general admin notices.
*
* Notices for guiding to proper configuration of this plugin.
*
* @package Event_Bridge_For_ActivityPub
* @since 1.0.0
* @license AGPL-3.0-or-later
*/
namespace Event_Bridge_For_ActivityPub\Admin;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
/**
* Class responsible for general admin notices.
*
* Notices for guiding to proper configuration of this plugin.
* - ActivityPub plugin not installed and activated
* - No supported Event Plugin installed and activated
*
* @since 1.0.0
*/
class General_Admin_Notices {
/**
* URL of the ActivityPub plugin. Needed when the ActivityPub plugin is not installed.
*/
const ACTIVITYPUB_PLUGIN_URL = 'https://wordpress.org/plugins/activitypub';
const EVENT_BRIDGE_FOR_ACTIVITYPUB_SUPPORTED_EVENT_PLUGINS_URL = 'https://wordpress.org/plugins/event-bridge-for-activitypub/#installation';
/**
* Allowed HTML for admin notices.
*
* @var array
*/
const ALLOWED_HTML = array(
'a' => array(
'href' => true,
'title' => true,
'target' => true,
),
'br',
'i',
);
/**
* Admin notice when the ActivityPub plugin is not enabled.
*
* @return string
*/
public static function get_admin_notice_activitypub_plugin_not_enabled(): string {
return sprintf(
/* translators: 1: An URL that points to the ActivityPub plugin. */
_x(
'For the Event Bridge for ActivityPub to work, you will need to install and activate the <a href="%1$s">ActivityPub</a> plugin.',
'admin notice',
'event-bridge-for-activitypub'
),
esc_html( self::ACTIVITYPUB_PLUGIN_URL )
);
}
/**
* Admin notice when the ActivityPub plugin version is too old.
*
* @return string
*/
public static function get_admin_notice_activitypub_plugin_version_too_old(): string {
return sprintf(
/* translators: 1: The name of the ActivityPub plugin. 2: The minimum required version number of the ActivityPub plugin. */
_x(
'Please upgrade your <a href="%1$s">ActivityPub</a> plugin. At least version %2$s is required for the Event Bridge for ActivityPub to work.',
'admin notice',
'event-bridge-for-activitypub'
),
esc_html( self::ACTIVITYPUB_PLUGIN_URL ),
esc_html( EVENT_BRIDGE_FOR_ACTIVITYPUB_ACTIVITYPUB_PLUGIN_MIN_VERSION )
);
}
/**
* Warning that no supported event plugin can be found.
*
* @return string
*/
public static function get_admin_notice_no_supported_event_plugin_active(): string {
return sprintf(
/* translators: 1: An URL to the list of supported event plugins. */
_x(
'The Plugin <i>Event Bridge for ActivityPub</i> is of no use, because you do not have installed and activated a supported Event Plugin.
<br> For a list of supported Event Plugins see <a href="%1$s" target="_blank">here</a>.',
'admin notice',
'event-bridge-for-activitypub'
),
esc_url( self::EVENT_BRIDGE_FOR_ACTIVITYPUB_SUPPORTED_EVENT_PLUGINS_URL )
);
}
/**
* Warning to fix status issues first.
*
* @return string
*/
public static function get_admin_notice_status_not_ok(): string {
return sprintf(
/* translators: 1: An URL to the list of supported event plugins. */
_x(
'The Plugin <i>Event Bridge for ActivityPub</i> is of no use, because you do not have installed and activated a supported Event Plugin.
<br> For a list of supported Event Plugins see <a href="%1$s">here</a>.',
'admin notice',
'event-bridge-for-activitypub'
),
esc_html( self::EVENT_BRIDGE_FOR_ACTIVITYPUB_SUPPORTED_EVENT_PLUGINS_URL )
);
}
/**
* Warning if the plugin is Active and the ActivityPub plugin is not.
*
* @return void
*/
public static function activitypub_plugin_not_enabled(): void {
$notice = self::get_admin_notice_activitypub_plugin_not_enabled();
// @phpstan-ignore-next-line
echo '<div class="notice notice-warning"><p>' . \wp_kses( $notice, self::ALLOWED_HTML ) . '</p></div>';
}
/**
* Warning if the plugin is Active and the ActivityPub plugins version is too old.
*
* @return void
*/
public static function activitypub_plugin_version_too_old(): void {
$notice = self::get_admin_notice_activitypub_plugin_version_too_old();
// @phpstan-ignore-next-line
echo '<div class="notice notice-warning"><p>' . \wp_kses( $notice, self::ALLOWED_HTML ) . '</p></div>';
}
/**
* Warning when no supported Even Plugin is installed and active.
*
* @return void
*/
public static function no_supported_event_plugin_active(): void {
$notice = self::get_admin_notice_no_supported_event_plugin_active();
// @phpstan-ignore-next-line
echo '<div class="notice notice-warning"><p>' . \wp_kses( $notice, self::ALLOWED_HTML ) . '</p></div>';
}
}

View File

@ -0,0 +1,211 @@
<?php
/**
* Health_Check class.
*
* @package Event_Bridge_For_ActivityPub
*/
namespace Event_Bridge_For_ActivityPub\Admin;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use Activitypub\Transformer\Factory as Transformer_Factory;
use Event_Bridge_For_ActivityPub\Integrations\Event_Plugin_Integration;
use Event_Bridge_For_ActivityPub\Setup;
use WP_Post;
use WP_Query;
/**
* ActivityPub Health_Check Class.
*/
class Health_Check {
/**
* Initialize health checks.
*/
public static function init() {
\add_filter( 'site_status_tests', array( self::class, 'add_tests' ) );
\add_filter( 'debug_information', array( self::class, 'add_debug_information' ) );
}
/**
* Add tests to the Site Health Check.
*
* @param array $tests The test array.
*
* @return array The filtered test array.
*/
public static function add_tests( $tests ): array {
$tests['direct']['event_bridge_for_activitypub_test'] = array(
'label' => __( 'ActivityPub Event Transformer Test', 'event-bridge-for-activitypub' ),
'test' => array( self::class, 'test_event_transformation' ),
);
return $tests;
}
/**
* The the transformation of the most recent event posts.
*
* @return array
*/
public static function test_event_transformation(): array {
$result = array(
'label' => \__( 'Transformation of Events to a valid ActivityStreams representation.', 'event-bridge-for-activitypub' ),
'status' => 'good',
'badge' => array(
'label' => \__( 'Event Bridge for ActivityPub', 'event-bridge-for-activitypub' ),
'color' => 'green',
),
'description' => \sprintf(
'<p>%s</p>',
\__( 'The transformation to ActivityPub of your most recent events was successful.', 'event-bridge-for-activitypub' )
),
'actions' => '',
'test' => 'test_event_transformation',
);
$check = self::transform_most_recent_event_posts();
if ( true === $check ) {
return $result;
}
$result['status'] = 'critical';
$result['label'] = \__( 'One or more of your most recent events failed to transform to ActivityPub', 'event-bridge-for-activitypub' );
$result['badge']['color'] = 'red';
$result['description'] = \sprintf(
'<p>%s</p>',
\__( 'The transformation to ActivityPub of your most recent events was not successful.', 'event-bridge-for-activitypub' )
);
return $result;
}
/**
* Test if right transformer gets applied.
*
* @param Event_Plugin_Integration $event_plugin The event plugin definition.
*
* @return bool True if the check passed.
*/
public static function test_if_event_transformer_is_used( $event_plugin ): bool {
if ( ! Setup::get_instance()->is_activitypub_plugin_active() ) {
return false;
}
// Get a (random) event post.
$event_posts = self::get_most_recent_event_posts( $event_plugin->get_post_type(), 1 );
// If no post is found, we can not do this test.
if ( isset( $event_posts[0] ) || empty( $event_posts ) ) {
return true;
}
// Call the transformer Factory.
$transformer = Transformer_Factory::get_transformer( \get_post( $event_posts[0] ) );
// Check that we got the right transformer.
$desired_transformer_class = $event_plugin::get_activitypub_event_transformer( $event_posts[0] );
if ( $transformer instanceof $desired_transformer_class ) {
return true;
}
return false;
}
/**
* Retrieves the most recently published event posts of a certain event post type.
*
* @param ?string $event_post_type The post type of the events.
* @param ?int $number_of_posts The maximum number of events to return.
*
* @return \WP_Post[] Array of event posts, or false if none are found.
*/
public static function get_most_recent_event_posts( $event_post_type = null, $number_of_posts = 5 ): array {
if ( ! Setup::get_instance()->is_activitypub_plugin_active() ) {
return array();
}
if ( ! $event_post_type ) {
$active_event_plugins = Setup::get_instance()->get_active_event_plugins();
$active_event_plugin = reset( $active_event_plugins );
if ( ! $active_event_plugin ) {
return array();
}
$event_post_type = $active_event_plugin->get_post_type();
}
$args = array(
'numberposts' => $number_of_posts,
'category' => 0,
'orderby' => 'date',
'order' => 'DESC',
'include' => array(),
'exclude' => array(),
'meta_query' => array(
'relation' => 'OR',
array(
'key' => '_event_bridge_for_activitypub_event_source',
'compare' => 'NOT EXISTS',
),
array(
'key' => '_event_bridge_for_activitypub_event_source',
'value' => '',
'compare' => '=',
),
),
'post_type' => $event_post_type,
'suppress_filters' => true,
);
$query = new WP_Query();
return $query->query( $args );
}
/**
* Transform the most recent event posts.
*/
public static function transform_most_recent_event_posts(): bool {
return true;
}
/**
* Retrieves information like name and version from active event plugins.
*/
private static function get_info_about_active_event_plugins(): array {
$active_event_plugins = Setup::get_instance()->get_active_event_plugins();
$info = array();
foreach ( $active_event_plugins as $active_event_plugin ) {
$event_plugin_file = $active_event_plugin->get_relative_plugin_file();
$event_plugin_data = \get_plugin_data( $event_plugin_file );
$info[] = array(
'event_plugin_name' => $event_plugin_data['Name'],
'event_plugin_version' => $event_plugin_data['Version'],
'event_plugin_file' => $event_plugin_file,
);
}
return $info;
}
/**
* Static function for generating site debug data when required.
*
* @param array $info The debug information to be added to the core information page.
* @return array The extended information.
*/
public static function add_debug_information( $info ): array {
$info['event_bridge_for_activitypub'] = array(
'label' => __( 'Event Bridge for ActivityPub', 'event-bridge-for-activitypub' ),
'fields' => array(
'plugin_version' => array(
'label' => __( 'Plugin Version', 'event-bridge-for-activitypub' ),
'value' => EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_VERSION,
'private' => true,
),
'active_event_plugins' => self::get_info_about_active_event_plugins(),
),
);
return $info;
}
}

View File

@ -0,0 +1,280 @@
<?php
/**
* General settings class.
*
* This file contains the General class definition, which handles the "General" settings
* page for the Event Bridge for ActivityPub Plugin, providing options for configuring various general settings.
*
* @package Event_Bridge_For_ActivityPub
* @since 1.0.0
*/
namespace Event_Bridge_For_ActivityPub\Admin;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use Activitypub\Webfinger;
use Event_Bridge_For_ActivityPub\ActivityPub\Model\Event_Source;
use Event_Bridge_For_ActivityPub\Event_Sources;
use Event_Bridge_For_ActivityPub\ActivityPub\Collection\Event_Sources as Event_Source_Collection;
use Event_Bridge_For_ActivityPub\Integrations\Event_Plugin_Integration;
use Event_Bridge_For_ActivityPub\Integrations\Feature_Event_Sources;
use Event_Bridge_For_ActivityPub\Setup;
/**
* Class responsible for the Event Bridge for ActivityPub related Settings.
*
* Class which handles the "General" settings page for the Event Bridge for ActivityPub Plugin,
* providing options for configuring various general settings.
*
* @since 1.0.0
*/
class Settings_Page {
const STATIC = 'Event_Bridge_For_ActivityPub\Admin\Settings_Page';
const SETTINGS_SLUG = 'event-bridge-for-activitypub';
/**
* Init settings pages.
*
* @return void
*/
public static function init() {
\add_filter( 'activitypub_admin_settings_tabs', array( self::class, 'add_settings_tab' ) );
\add_action(
'admin_init',
array( self::class, 'maybe_add_event_source' ),
);
}
/**
* Adds a custom tab to the ActivityPub settings.
*
* @param array $tabs The existing tabs array.
* @return array The modified tabs array.
*/
public static function add_settings_tab( $tabs ): array {
$tabs['event-bridge-for-activitypub'] = array(
'label' => __( 'Event Bridge', 'event-bridge-for-activitypub' ),
'template' => EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_DIR . 'templates/settings/tab.php',
);
return $tabs;
}
/**
* Checks whether the current request wants to add an event source (ActivityPub follow) and passed on to actual handler.
*
* @return void
*/
public static function maybe_add_event_source() {
if ( ! isset( $_POST['event_bridge_for_activitypub_add_event_source'] ) ) {
return;
}
// Check and verify request and check capabilities.
if ( ! \wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'event-bridge-for-activitypub_add-event-source-options' ) ) {
return;
}
if ( ! \current_user_can( 'manage_options' ) ) {
return;
}
$event_source = \sanitize_text_field( $_POST['event_bridge_for_activitypub_add_event_source'] );
$actor_url = false;
$url = \wp_parse_url( $event_source );
$error_message = \esc_html__( 'Failed to add Event Source', 'event-bridge-for-activitypub' );
// Check if URL is a Collection or a single Actor.
$maybe_collection = \wp_safe_remote_get( $event_source );
if ( ! \is_wp_error( $maybe_collection ) ) {
$maybe_collection = \json_decode( \wp_remote_retrieve_body( $maybe_collection ), true );
}
$event_sources = array();
if ( isset( $maybe_collection['type'] ) && in_array( $maybe_collection['type'], array( 'Collection', 'OrderedCollection' ), true ) ) {
// Return only the IDs of the items in the collection.
$event_sources = \wp_list_pluck( $maybe_collection['items'], 'id' );
} else {
$event_sources[] = $event_source;
}
// Iterate over all event sources and add them to the collection.
foreach ( $event_sources as $event_source ) {
$url = \wp_parse_url( $event_source );
if ( isset( $url['path'], $url['host'], $url['scheme'] ) ) {
$actor_url = \sanitize_url( $event_source );
} elseif ( preg_match( '/^@?' . Event_Source::ACTIVITYPUB_USER_HANDLE_REGEXP . '$/i', $event_source ) ) {
$actor_url = Webfinger::resolve( $event_source );
if ( \is_wp_error( $actor_url ) ) {
\add_settings_error(
'event-bridge-for-activitypub_add-event-source',
'event_bridge_for_activitypub_cannot_follow_actor',
$error_message . ': ' . esc_html__( 'Cannot find an ActivityPub actor for this user handle via Webfinger.', 'event-bridge-for-activitypub' ),
'error'
);
continue;
}
} else {
if ( ! isset( $url['path'] ) && isset( $url['host'] ) ) {
$actor_url = Event_Sources::get_application_actor( $url['host'] );
} elseif ( self::is_domain( $event_source ) ) {
$actor_url = Event_Sources::get_application_actor( $event_source );
}
if ( ! $actor_url ) {
\add_settings_error(
'event-bridge-for-activitypub_add-event-source',
'event_bridge_for_activitypub_cannot_follow_actor',
$error_message . ': ' . \esc_html__( 'Unable to identify the ActivityPub relay actor to follow for this domain.', 'event-bridge-for-activitypub' ),
'error'
);
continue;
}
}
if ( ! $actor_url ) {
\add_settings_error(
'event-bridge-for-activitypub_add-event-source',
'event_bridge_for_activitypub_cannot_follow_actor',
$error_message . ': ' . \esc_html__( 'ActivityPub actor does not exist.', 'event-bridge-for-activitypub' ),
'error'
);
continue;
}
// Don't proceed if on the same host!
if ( \wp_parse_url( \home_url(), PHP_URL_HOST ) === \wp_parse_url( $actor_url, PHP_URL_HOST ) ) {
\add_settings_error(
'event-bridge-for-activitypub_add-event-source',
'event_bridge_for_activitypub_cannot_follow_actor',
$error_message . ': ' . \esc_html__( 'Cannot follow own actor on own domain.', 'event-bridge-for-activitypub' ),
'error'
);
continue;
}
Event_Source_Collection::add_event_source( $actor_url );
}
}
/**
* Check if a string is a valid domain name.
*
* @param string $domain The input string which might be a domain.
* @return bool
*/
private static function is_domain( $domain ): bool {
$pattern = '/^(?!\-)(?:(?:[a-zA-Z\d](?:[a-zA-Z\d\-]{0,61}[a-zA-Z\d])?)\.)+(?!\d+$)[a-zA-Z\d]{2,63}$/';
return 1 === preg_match( $pattern, $domain );
}
/**
* Adds Link to the settings page in the plugin page.
* It's called via apply_filter('plugin_action_links_' . PLUGIN_NAME).
*
* @param array $links Already added links.
*
* @return array Original links but with link to setting page added.
*/
public static function settings_link( $links ): array {
$links[] = \sprintf(
'<a href="%1s">%2s</a>',
\add_query_arg( 'tab', 'event-bridge-for-activitypub', \menu_page_url( 'activitypub', false ) ),
\__( 'Settings', 'event-bridge-for-activitypub' )
);
return $links;
}
/**
* Receive the event categories (terms) used by the event plugin.
*
* @param Event_Plugin_Integration $event_plugin Contains info about a certain event plugin.
*
* @return array An array of Terms.
*/
private static function get_event_terms( $event_plugin ): array {
$taxonomy = $event_plugin::get_event_category_taxonomy();
if ( $taxonomy ) {
$event_terms = get_terms(
array(
'taxonomy' => $taxonomy,
'hide_empty' => true,
)
);
return ! is_wp_error( $event_terms ) ? $event_terms : array();
} else {
return array();
}
}
/**
* Preparing the data and loading the template for the settings page.
*
* @return void
*/
public static function do_settings_page(): void {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( empty( $_GET['subpage'] ) ) {
$tab = 'welcome';
} else {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$tab = \sanitize_key( $_GET['subpage'] );
}
// Fallback to always re-scan active event plugins, when user visits admin area of this plugin.
$plugin_setup = Setup::get_instance();
$plugin_setup->redetect_active_event_plugins();
$event_plugins = $plugin_setup->get_active_event_plugins();
switch ( $tab ) {
case 'settings':
$event_terms = array();
foreach ( $event_plugins as $event_plugin_integration ) {
$event_terms = array_merge( $event_terms, self::get_event_terms( $event_plugin_integration ) );
}
$args = array(
'slug' => self::SETTINGS_SLUG,
'event_terms' => $event_terms,
);
\load_template( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_DIR . 'templates/settings/subpages/settings.php', true, $args );
break;
case 'event-sources':
$supports_event_sources = array();
foreach ( $event_plugins as $event_plugin_integration ) {
if ( is_a( $event_plugin_integration, Feature_Event_Sources::class ) ) {
$class_name = get_class( $event_plugin_integration );
$supports_event_sources[ $class_name ] = $event_plugin_integration::get_plugin_name();
}
}
$args = array(
'supports_event_sources' => $supports_event_sources,
);
\wp_enqueue_script( 'thickbox' );
\wp_enqueue_style( 'thickbox' );
\load_template( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_DIR . 'templates/settings/subpages/event-sources.php', true, $args );
break;
case 'welcome':
default:
\wp_enqueue_script( 'plugin-install' );
\add_thickbox();
\wp_enqueue_script( 'updates' );
\load_template( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_DIR . 'templates/settings/subpages/welcome.php', true );
break;
}
}
}

View File

@ -0,0 +1,100 @@
<?php
/**
* Class responsible for User Interface additions in the Admin UI.
*
* @package Event_Bridge_For_ActivityPub
* @since 1.0.0
* @license AGPL-3.0-or-later
*/
namespace Event_Bridge_For_ActivityPub\Admin;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use Event_Bridge_For_ActivityPub\ActivityPub\Model\Event_Source;
use Event_Bridge_For_ActivityPub\ActivityPub\Collection\Event_Sources as Event_Sources_Collection;
use Event_Bridge_For_ActivityPub\Event_Sources;
/**
* Class responsible for Event Plugin related admin notices.
*
* Notices for guiding to proper configuration of ActivityPub with event plugins.
*
* @since 1.0.0
*/
class User_Interface {
/**
* Init.
*/
public static function init() {
\add_filter( 'page_row_actions', array( self::class, 'row_actions' ), 10, 2 );
\add_filter( 'post_row_actions', array( self::class, 'row_actions' ), 10, 2 );
\add_filter( 'map_meta_cap', array( self::class, 'disable_editing_for_external_events' ), 10, 4 );
}
/**
* Add an column that shows the origin of an external event.
*
* @param array $columns The current columns.
* @return array
*/
public static function add_origin_column( $columns ) {
// Add a new column after the title column.
$columns['activitypub_origin'] = __( 'ActivityPub origin', 'event-bridge-for-activitypub' );
return $columns;
}
/**
* Add a "⁂ Preview" link to the row actions.
*
* @param array $actions The existing actions.
* @param \WP_Post $post The post object.
*
* @return array The modified actions.
*/
public static function row_actions( $actions, $post ): array {
// check if the post is enabled for ActivityPub.
if ( ! Event_Sources::is_cached_external_post( $post ) ) {
return $actions;
}
$url = $post->guid;
$parent = get_post_parent();
if ( $parent && Event_Sources_Collection::POST_TYPE === $parent->post_type ) {
$url = \get_post_meta( $parent->ID, '_activitypub_actor_id', true );
}
$actions['view_origin'] = sprintf(
'<a href="%s" target="_blank">⁂ %s</a>',
\esc_url( $url ),
\esc_html__( 'Open original page', 'event-bridge-for-activitypub' )
);
return $actions;
}
/**
* Modify the user capabilities so that nobody can edit external events.
*
* @param array $caps Concerned user's capabilities.
* @param mixed $cap Required primitive capabilities for the requested capability.
* @param array $user_id The WordPress user ID.
* @param array $args Additional args.
*
* @return array
*/
public static function disable_editing_for_external_events( $caps, $cap, $user_id, $args ) {
if ( 'edit_post' === $cap && isset( $args[0] ) ) {
$post_id = $args[0];
$post = get_post( $post_id );
if ( $post && Event_Sources::is_cached_external_post( $post ) ) {
// Deny editing by returning 'do_not_allow'.
return array( 'do_not_allow' );
}
}
return $caps;
}
}