diff --git a/.forgejo/workflows/phpunit.yml b/.forgejo/workflows/phpunit.yml index 5bdae8d..a893dce 100644 --- a/.forgejo/workflows/phpunit.yml +++ b/.forgejo/workflows/phpunit.yml @@ -37,7 +37,7 @@ jobs: path: | ${{ env.WP_CORE_DIR }} ${{ env.WP_TESTS_DIR }} - key: cache-wordpress-4 + key: cache-wordpress-9 - name: Cache Composer id: cache-composer-phpunit @@ -91,5 +91,20 @@ jobs: - name: Run Integration tests for Events Manager run: cd /workspace/Event-Federation/wordpress-activitypub-event-bridge/ && ./vendor/bin/phpunit --filter=events_manager + env: + PHP_VERSION: ${{ matrix.php-version }} + + - name: Run Integration tests for WP Event Manager + run: cd /workspace/Event-Federation/wordpress-activitypub-event-bridge/ && ./vendor/bin/phpunit --filter=wp_event_manager + env: + PHP_VERSION: ${{ matrix.php-version }} + + - name: Run Integration tests for Eventin (WP Event Solution) + run: cd /workspace/Event-Federation/wordpress-activitypub-event-bridge/ && ./vendor/bin/phpunit --filter=eventin + env: + PHP_VERSION: ${{ matrix.php-version }} + + - name: Run Integration tests for Modern Events Calendar Lite + run: cd /workspace/Event-Federation/wordpress-activitypub-event-bridge/ && ./vendor/bin/phpunit --filter=modern_events_calendar_lite env: PHP_VERSION: ${{ matrix.php-version }} \ No newline at end of file diff --git a/.wordpress-org/banner-1544x500.jpg b/.wordpress-org/banner-1544x500.jpg new file mode 100644 index 0000000..0f1839b Binary files /dev/null and b/.wordpress-org/banner-1544x500.jpg differ diff --git a/.wordpress-org/banner-772x250.jpg b/.wordpress-org/banner-772x250.jpg new file mode 100644 index 0000000..9f5a437 Binary files /dev/null and b/.wordpress-org/banner-772x250.jpg differ diff --git a/.wordpress-org/icon-128x128.gif b/.wordpress-org/icon-128x128.gif new file mode 100644 index 0000000..25ebcc0 Binary files /dev/null and b/.wordpress-org/icon-128x128.gif differ diff --git a/.wordpress-org/icon-256x256.gif b/.wordpress-org/icon-256x256.gif new file mode 100644 index 0000000..9385c37 Binary files /dev/null and b/.wordpress-org/icon-256x256.gif differ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9a605a7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.1.0] - 2024-10-20 + +### Added + +* Initial version tag. diff --git a/README.md b/README.md index 3462494..07aceea 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,19 @@ These platforms create public event calendars by pulling in events from various
-Even platforms that don’t yet fully support events, like [Mastodon](https://joinmastodon.org), will still receive a detailed, well-composed summary of your event. +Even platforms that don't yet fully support events, like [Mastodon](https://joinmastodon.org), will still receive a detailed, well-composed summary of your event. The Event Federation plugin ensures that users from those platforms are provided with all important information about an event. +### Features for Your WordPress Events and the Fediverse + +**ActivityPub-Enabled Event Sharing:** Your WordPress events are not part of the Fediverse and + +**Automatic Event Summaries:** When your event is shared on the Fediverse, platforms like Mastodon that don't fully support events will display a brief HTML summary of key details — such as the event's title, start time, and location. This ensures that even if someone can't view the full event on their platform, they still get the important info at a glance, with a link to your WordPress event page. + +**Improved Event Discoverability:** Your custom event categories are mapped to a set of default categories used in the Fediverse, helping your events reach a wider audience. This improves the chances that users searching for similar events on other platforms will find yours. + +**Event Reminders for Your Followers:** Often, events are planned well in advance. To keep your followers informed right in time, you can set up reminders that are supposed to trigger the events showing up in their timelines right before the event starts. At the moment this reminder is implemented as a self-boost of your original event post. While this feature may behave differently across various platforms, we are working on a more robust solution that will let you schedule dedicated reminder notes that appear in all followers' timelines. + ## Installation This plugin depends on the [ActivityPub plugin](https://wordpress.org/plugins/activitypub/). Additionally, you need to use one of the supported event plugins. See below. @@ -51,6 +61,10 @@ This plugin depends on the [ActivityPub plugin](https://wordpress.org/plugins/ac * [The Events Calendar](https://de.wordpress.org/plugins/the-events-calendar/) * [VS Event List](https://de.wordpress.org/plugins/very-simple-event-list/) * [Events Manager](https://de.wordpress.org/plugins/events-manager/) +* [WP Event Manager](https://de.wordpress.org/plugins/wp-event-manager/) +* [Eventin](https://de.wordpress.org/plugins/wp-event-solution/) +* [Modern Events Calendar Lite](https://webnus.net/modern-events-calendar/) +* [GatherPress](https://gatherpress.org/) ## Configuration diff --git a/activitypub-event-bridge.php b/activitypub-event-bridge.php index a4e0cad..b1cb2ea 100644 --- a/activitypub-event-bridge.php +++ b/activitypub-event-bridge.php @@ -3,7 +3,7 @@ * Plugin Name: ActivityPub Event Bridge * Description: Integrating popular event plugins with the ActivityPub plugin. * Plugin URI: https://event-federation.eu/ - * Version: 0.1.0 + * Version: 0.1.1 * Author: André Menrath * Author URI: https://graz.social/@linos * Text Domain: activitypub-event-bridge @@ -11,7 +11,7 @@ * License URI: https://www.gnu.org/licenses/agpl-3.0.de.html * Requires PHP: 8.1 * - * Requires at least ActivityPub plugin with version >= 3.2.2. ActivityPub plugin tested up to: 3.2.2. + * Requires at least ActivityPub plugin with version >= 3.2.2. ActivityPub plugin tested up to: 3.3.3. * * @package ActivityPub_Event_Bridge * @license AGPL-3.0-or-later diff --git a/assets/css/activitypub-event-bridge-admin.css b/assets/css/activitypub-event-bridge-admin.css new file mode 100644 index 0000000..c89ec6e --- /dev/null +++ b/assets/css/activitypub-event-bridge-admin.css @@ -0,0 +1,179 @@ +.settings_page_activitypub-event-bridge #wpcontent { + padding-left: 0; +} + +.activitypub-event-bridge-settings-page .box { + border: 1px solid #c3c4c7; + background-color: #fff; + padding: 1em 1.5em; + margin-bottom: 1.5em; +} + +.activitypub-event-bridge-settings-page .box ul.activitypub-event-bridge-list { + margin-left: 0.6em; +} + +.activitypub-event-bridge-settings-page .box pre { + padding: 1rem; + min-height: 200px; + box-shadow: none; + border-radius: 15px; + border: 1px solid #dfe0e2; + background-color: #f7f7f7; +} + +.activitypub-event-bridge-settings { + max-width: 800px; + margin: 0 auto; +} + +.activitypub-event-bridge-settings-header { + text-align: center; + margin: 0 0 1rem; + background: #fff; + border-bottom: 1px solid #dcdcde; +} + +.activitypub-event-bridge-settings-title-section { + display: flex; + align-items: center; + justify-content: center; + clear: both; + padding-top: 8px; +} + +.activitypub-event-bridge-settings-tabs-wrapper { + display: -ms-inline-grid; + -ms-grid-columns: auto auto auto auto; + vertical-align: top; + display: inline-grid; + grid-template-columns: auto auto auto auto; +} + +.activitypub-event-bridge-settings-tab.active { + box-shadow: inset 0 -3px #3582c4; + font-weight: 600; +} + +.activitypub-event-bridge-settings-tab { + display: block; + text-decoration: none; + color: inherit; + padding: .5rem 1rem 1rem; + margin: 0 1rem; + transition: box-shadow .5s ease-in-out; +} + +.activitypub-event-bridge-settings .box h3 { + font-size: 1.15em; + margin-bottom: 0em; +} + +#activitypub_event_bridge_initially_activated { + display: hidden; +} + +/* Accordions for admin pages */ +.activitypub-event-bridge-settings-accordion { + border: 1px solid #c3c4c7; +} + +.activitypub-event-bridge-settings-accordion-heading { + margin: 0; + border-top: 1px solid #c3c4c7; + font-size: inherit; + line-height: inherit; + font-weight: 600; + color: inherit; +} + +.activitypub-event-bridge-settings-accordion-heading:first-child { + border-top: none; +} + +.activitypub-event-bridge-settings-accordion-panel { + margin: 0; + padding: 1em 1.5em; + background: #fff; +} + +.activitypub-event-bridge-settings-accordion-trigger { + background: #fff; + border: 0; + color: #2c3338; + cursor: pointer; + display: flex; + font-weight: 400; + margin: 0; + padding: 1em 3.5em 1em 1.5em; + min-height: 46px; + position: relative; + text-align: left; + width: 100%; + align-items: center; + justify-content: space-between; + -webkit-user-select: auto; + user-select: auto; +} + +.activitypub-event-bridge-settings-accordion-trigger { + color: #2c3338; + cursor: pointer; + font-weight: 400; + text-align: left; +} + +.activitypub-event-bridge-settings-accordion-trigger .title { + pointer-events: none; + font-weight: 600; + flex-grow: 1; +} + +.activitypub-event-bridge-settings-accordion-trigger .icon, +.activitypub-event-bridge-settings-accordion-viewed .icon { + border: solid #50575e medium; + border-width: 0 2px 2px 0; + height: .5rem; + pointer-events: none; + position: absolute; + right: 1.5em; + top: 50%; + transform: translateY(-70%) rotate(45deg); + width: .5rem; +} + +.activitypub-event-bridge-settings-accordion-trigger[aria-expanded="true"] .icon { + transform: translateY(-30%) rotate(-135deg); +} + +.activitypub-event-bridge-settings-accordion-trigger:active, +.activitypub-event-bridge-settings-accordion-trigger:hover { + background: #f6f7f7; +} + +.activitypub-event-bridge-settings-accordion-trigger:focus { + color: #1d2327; + border: none; + box-shadow: none; + outline-offset: -1px; + outline: 2px solid #2271b1; + background-color: #f6f7f7; +} + +.activitypub-event-bridge-settings-inline-icon { + width: 1.5em; + height: 1.5em; + vertical-align: middle; + margin: 0 0.3em; +} + +code.activitypub-event-bridge-settings-example-url { + display: block; + background: rgb(28, 29, 33); + padding: 8px; + margin: 10px 0px 10px 0; + border-radius: 7px; + color: #d5d5d6; + overflow-x: auto; + word-break: break-all; +} diff --git a/assets/css/activitypub-event-extensions-admin.css b/assets/css/activitypub-event-extensions-admin.css deleted file mode 100644 index c59d1a1..0000000 --- a/assets/css/activitypub-event-extensions-admin.css +++ /dev/null @@ -1,6 +0,0 @@ -.activitypub-event-bridge-settings-page .box { - border: 1px solid #c3c4c7; - background-color: #fff; - padding: 1em 1.5em; - margin-bottom: 1.5em; -} diff --git a/assets/img/activitypub.svg b/assets/img/activitypub.svg new file mode 100644 index 0000000..f56d428 --- /dev/null +++ b/assets/img/activitypub.svg @@ -0,0 +1,288 @@ + + + + diff --git a/assets/img/fediverse.svg b/assets/img/fediverse.svg new file mode 100644 index 0000000..a789df2 --- /dev/null +++ b/assets/img/fediverse.svg @@ -0,0 +1,17 @@ + diff --git a/assets/img/mastodon.svg b/assets/img/mastodon.svg new file mode 100644 index 0000000..0f8baeb --- /dev/null +++ b/assets/img/mastodon.svg @@ -0,0 +1,10 @@ + diff --git a/assets/img/mobilizon.svg b/assets/img/mobilizon.svg new file mode 100644 index 0000000..8b5d57e --- /dev/null +++ b/assets/img/mobilizon.svg @@ -0,0 +1 @@ + diff --git a/assets/js/activitypub-event-bridge-admin.js b/assets/js/activitypub-event-bridge-admin.js new file mode 100644 index 0000000..bf00a1c --- /dev/null +++ b/assets/js/activitypub-event-bridge-admin.js @@ -0,0 +1,14 @@ +jQuery( function( $ ) { + // Accordion handling in various areas. + $( '.activitypub-event-bridge-settings-accordion' ).on( 'click', '.activitypub-event-bridge-settings-accordion-trigger', function() { + var isExpanded = ( 'true' === $( this ).attr( 'aria-expanded' ) ); + + if ( isExpanded ) { + $( this ).attr( 'aria-expanded', 'false' ); + $( '#' + $( this ).attr( 'aria-controls' ) ).attr( 'hidden', true ); + } else { + $( this ).attr( 'aria-expanded', 'true' ); + $( '#' + $( this ).attr( 'aria-controls' ) ).attr( 'hidden', false ); + } + } ); +} ); diff --git a/bin/install-wp-tests.sh b/bin/install-wp-tests.sh index 8d495bf..f0bf333 100755 --- a/bin/install-wp-tests.sh +++ b/bin/install-wp-tests.sh @@ -226,6 +226,20 @@ install_wp_plugin() { unzip -q -o "$TMPDIR/$PLUGIN_FILE" -d "$WP_CORE_DIR/wp-content/plugins/" } +install_wp_plugin_mec() { + mkdir -p "$WP_CORE_DIR/wp-content/plugins/" + + if [ -d "$WP_CORE_DIR/wp-content/plugins/modern-events-calendar-lite" ]; then + return; + fi + + PLUGIN_VERSION="v7.15.0" + + URL="https://code.event-federation.eu/Event-Federation/modern-events-calendar-lite" + + git clone $URL "$WP_CORE_DIR/wp-content/plugins/modern-events-calendar-lite" +} + install_wp_plugins() { if [ "$SKIP_PLUGINS_INSTALL" = "true" ]; then echo "Skipping WordPress plugin installation." @@ -238,6 +252,10 @@ install_wp_plugins() { install_wp_plugin very-simple-event-list install_wp_plugin gatherpress install_wp_plugin events-manager + install_wp_plugin wp-event-manager + install_wp_plugin wp-event-solution + # Mec is not installable via wordpress.org, we use our own mirror. + install_wp_plugin_mec } install_wp diff --git a/composer.json b/composer.json index 44b5406..6236dfc 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,6 @@ { "name": "menrath/wordpress-activitypub-event-bridge", + "version": "1.0.0", "description": "The ActivityPub Event Bridge help for event custom post types to federate properly.", "type": "wordpress-plugin", "require": { @@ -50,7 +51,10 @@ "@test-vs-event-list", "@test-the-events-calendar", "@test-gatherpress", - "@test-events-manager" + "@test-events-manager", + "@test-wp-event-manager", + "@test-eventin", + "@test-modern-events-calendar-lite" ], "test-debug": [ "@prepare-test", @@ -59,6 +63,10 @@ "test-vs-event-list": "phpunit --filter=vs_event_list", "test-the-events-calendar": "phpunit --filter=the_events_calendar", "test-gatherpress": "phpunit --filter=gatherpress", - "test-events-manager": "phpunit --filter=events_manager" + "test-events-manager": "phpunit --filter=events_manager", + "test-wp-event-manager": "phpunit --filter=wp_event_manager", + "test-eventin": "phpunit --filter=eventin", + "test-modern-events-calendar-lite": "phpunit --filter=modern_events_calendar_lite", + "test-all": "phpunit" } } diff --git a/docker-compose.yml b/docker-compose.yml index dc71501..d39760b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,9 @@ version: '3' # This files purpose is to run the PHPunit tests locally. +# Prerequisites: +# Run "composer install" to generate a composer.lock file and install PHP dev dependencies. +# # Install docker and docker compose and than just run: # docker compose up diff --git a/docs/add_your_event_plugin.md b/docs/add_your_event_plugin.md index 8c387a4..44ec1f4 100644 --- a/docs/add_your_event_plugin.md +++ b/docs/add_your_event_plugin.md @@ -28,6 +28,15 @@ First you need to add some basic information about your event plugin. Just creat final class My_Event_Plugin extends Event_Plugin { ``` +Then you need to tell the ActivityPub Event Bridge about that class by adding it to the `EVENT_PLUGIN_CLASSES` constant in the `includes/setup.php` file: + +```php + private const EVENT_PLUGIN_CLASSES = array( + ... + '\ActivityPub_Event_Bridge\Plugins\My_Event_Plugin', + ); +``` + The ActivityPub Event Bridge then takes care of applying the transformer, so you can jump right into implementing it. ## Writing an event transformer class @@ -107,3 +116,107 @@ In order to ensure your events are compatible with other ActivityPub Event imple * **`get_tag`** * **`timezone`** * **`commentsEnabled`** + +## Writing integration tests + +Create a new tests class in `tests/test-class-plugin-my-event-plugin.php`. + +``` +/** + * Sample test case. + */ +class Test_My_Event_Plugin extends WP_UnitTestCase { +``` + +Implement a check whether your event plugin is active in the `set_up` function. It may be the presence of a class, function or constant. + +```php + /** + * Override the setup function, so that tests don't run if the Events Calendar is not active. + */ + public function set_up() { + parent::set_up(); + + if ( !%s
', + \__( 'The transformation of your most recent events was successful.', 'activitypub-event-bridge' ) + ), + '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', 'activitypub-event-bridge' ); + $result['badge']['color'] = 'red'; + $result['description'] = \sprintf( + '%s
', + $check->get_error_message() + ); + + return $result; + } + + /** + * Test if right transformer gets applied. + * + * @param Event_Plugin $event_plugin The event plugin definition. + * + * @return bool True if the check passed. + */ + public static function test_if_event_transformer_is_used( $event_plugin ) { + // 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 ( ! $event_posts || is_wp_error( $event_posts ) || empty( $event_posts ) ) { + return true; + } + + // Call the transformer Factory. + $transformer = Transformer_Factory::get_transformer( $event_posts[0] ); + // Check that we got the right transformer. + $desired_transformer_class = $event_plugin::get_activitypub_event_transformer_class(); + 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[]|false 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 ) { + if ( ! $event_post_type ) { + $event_post_type = Setup::get_instance()->get_active_event_plugins()[0]->get_post_type(); + } + + $args = array( + 'numberposts' => $number_of_posts, + 'category' => 0, + 'orderby' => 'date', + 'order' => 'DESC', + 'include' => array(), + 'exclude' => array(), + 'meta_key' => '', + 'meta_value' => '', + '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() { + return true; + } + + /** + * Retrieves information like name and version from active event plugins. + */ + private static function get_info_about_active_event_plugins() { + $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_plugin_file(); + $event_plugin_data = \get_plugin_data( $event_plugin_file ); + $event_plugin_name = isset( $event_plugin_data['Plugin Name'] ) ? $event_plugin_data['Plugin Name'] : 'Name not found'; + $event_plugin_version = isset( $event_plugin_version['Plugin Version'] ) ? $event_plugin_version['Plugin Version'] : 'Version not found'; + + $info[] = array( + 'event_plugin_name' => $event_plugin_name, + 'event_plugin_version' => $event_plugin_version, + 'event_plugin_file' => $event_plugin_file, + ); + } + } + + /** + * 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 ) { + $info['activitypub_event_bridge'] = array( + 'label' => __( 'ActivityPub Event Bridge', 'activitypub-event-bridge' ), + 'fields' => array( + 'plugin_version' => array( + 'label' => __( 'Plugin Version', 'activitypub' ), + 'value' => ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_VERSION, + 'private' => true, + ), + 'active_event_plugins' => self::get_info_about_active_event_plugins(), + ), + ); + + return $info; + } +} diff --git a/includes/admin/class-settings-page.php b/includes/admin/class-settings-page.php index 08a36d6..b2dbb3e 100644 --- a/includes/admin/class-settings-page.php +++ b/includes/admin/class-settings-page.php @@ -3,7 +3,7 @@ * General settings class. * * This file contains the General class definition, which handles the "General" settings - * page for the ActivityPub Event Extension Plugin, providing options for configuring various general settings. + * page for the Activitypub Event Bridge Plugin, providing options for configuring various general settings. * * @package ActivityPub_Event_Bridge * @since 1.0.0 @@ -18,9 +18,9 @@ use ActivityPub_Event_Bridge\Plugins\Event_Plugin; use ActivityPub_Event_Bridge\Setup; /** - * Class responsible for the ActivityPub Event Extension related Settings. + * Class responsible for the Activitypub Event Bridge related Settings. * - * Class which handles the "General" settings page for the ActivityPub Event Extension Plugin, + * Class which handles the "General" settings page for the Activitypub Event Bridge Plugin, * providing options for configuring various general settings. * * @since 1.0.0 @@ -36,11 +36,11 @@ class Settings_Page { */ public static function admin_menu(): void { \add_options_page( - 'Activitypub Event Extension', - __( 'ActivityPub Events', 'activitypub-event-bridge' ), + 'Activitypub Event Bridge', + __( 'ActivityPub Event Bridge', 'activitypub-event-bridge' ), 'manage_options', self::SETTINGS_SLUG, - array( self::STATIC, 'settings_page' ) + array( self::STATIC, 'settings_page' ), ); } @@ -89,21 +89,41 @@ class Settings_Page { * @return void */ public static function settings_page(): void { - $plugin_setup = Setup::get_instance(); - - $event_plugins = $plugin_setup->get_active_event_plugins(); - - $event_terms = array(); - - foreach ( $event_plugins as $event_plugin ) { - $event_terms = array_merge( $event_terms, self::get_event_terms( $event_plugin ) ); + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + if ( empty( $_GET['tab'] ) ) { + $tab = 'welcome'; + } else { + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $tab = sanitize_key( $_GET['tab'] ); } - $args = array( - 'slug' => self::SETTINGS_SLUG, - 'event_terms' => $event_terms, - ); + switch ( $tab ) { + case 'settings': + $plugin_setup = Setup::get_instance(); - \load_template( ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_DIR . 'templates/settings.php', true, $args ); + $event_plugins = $plugin_setup->get_active_event_plugins(); + + $event_terms = array(); + + foreach ( $event_plugins as $event_plugin ) { + $event_terms = array_merge( $event_terms, self::get_event_terms( $event_plugin ) ); + } + + $args = array( + 'slug' => self::SETTINGS_SLUG, + 'event_terms' => $event_terms, + ); + + \load_template( ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_DIR . 'templates/settings.php', true, $args ); + break; + case 'welcome': + default: + wp_enqueue_script( 'plugin-install' ); + add_thickbox(); + wp_enqueue_script( 'updates' ); + + \load_template( ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_DIR . 'templates/welcome.php', true ); + break; + } } } diff --git a/includes/class-settings.php b/includes/class-settings.php index 922531f..3367dd1 100644 --- a/includes/class-settings.php +++ b/includes/class-settings.php @@ -3,7 +3,7 @@ * General settings class. * * This file contains the General class definition, which handles the "General" settings - * page for the ActivityPub Event Extension Plugin, providing options for configuring various general settings. + * page for the Activitypub Event Bridge Plugin, providing options for configuring various general settings. * * @package ActivityPub_Event_Bridge * @since 1.0.0 @@ -61,6 +61,16 @@ class Settings { 'sanitize_callback' => array( self::class, 'sanitize_event_category_mappings' ), ) ); + + \register_setting( + 'activitypub-event-bridge', + 'activitypub_event_bridge_initially_activated', + array( + 'type' => 'boolean', + 'description' => \__( 'Whether the plugin just got activated for the first time.', 'activitypub' ), + 'default' => 1, + ) + ); } /** diff --git a/includes/class-setup.php b/includes/class-setup.php index fc742e5..c717619 100644 --- a/includes/class-setup.php +++ b/includes/class-setup.php @@ -17,6 +17,7 @@ defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore use ActivityPub_Event_Bridge\Admin\Event_Plugin_Admin_Notices; use ActivityPub_Event_Bridge\Admin\General_Admin_Notices; +use ActivityPub_Event_Bridge\Admin\Health_Check; use ActivityPub_Event_Bridge\Admin\Settings_Page; use ActivityPub_Event_Bridge\Plugins\Event_Plugin; @@ -129,6 +130,9 @@ class Setup { '\ActivityPub_Event_Bridge\Plugins\The_Events_Calendar', '\ActivityPub_Event_Bridge\Plugins\VS_Event_List', '\ActivityPub_Event_Bridge\Plugins\My_Calendar', + '\ActivityPub_Event_Bridge\Plugins\WP_Event_Manager', + '\ActivityPub_Event_Bridge\Plugins\Eventin', + '\ActivityPub_Event_Bridge\Plugins\Modern_Events_Calendar_Lite', ); /** @@ -165,20 +169,19 @@ class Setup { add_action( 'admin_init', array( $this, 'do_admin_notices' ) ); add_action( 'admin_init', array( Settings::class, 'register_settings' ) ); + add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_styles' ) ); + add_action( 'admin_menu', array( Settings_Page::class, 'admin_menu' ) ); + add_filter( + 'plugin_action_links_' . ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_BASENAME, + array( Settings_Page::class, 'settings_link' ) + ); // If we don't have any active event plugins, or the ActivityPub plugin is not enabled, abort here. if ( empty( $this->active_event_plugins ) || ! $this->activitypub_plugin_is_active ) { return; } - add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_styles' ) ); - - add_action( 'admin_menu', array( Settings_Page::class, 'admin_menu' ) ); - - add_filter( - 'plugin_action_links_' . ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_BASENAME, - array( Settings_Page::class, 'settings_link' ) - ); + add_action( 'init', array( Health_Check::class, 'init' ) ); // 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 ) ) { @@ -206,6 +209,16 @@ class Setup { array(), ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_VERSION ); + wp_enqueue_script( + 'activitypub-event-bridge-admin-script', + plugins_url( + 'assets/js/activitypub-event-bridge-admin.js', + ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_FILE + ), + array( 'jquery' ), + ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_VERSION, + false + ); } } @@ -285,7 +298,7 @@ class Setup { * This method handles the activation of the ActivityPub Event Bridge plugin. * * @since 1.0.0 - * + * @see register_activation_hook() * @return void */ public function activate(): void { diff --git a/includes/plugins/class-event-plugin.php b/includes/plugins/class-event-plugin.php index f70cfa0..a5c5734 100644 --- a/includes/plugins/class-event-plugin.php +++ b/includes/plugins/class-event-plugin.php @@ -45,12 +45,24 @@ abstract class Event_Plugin { abstract public static function get_event_category_taxonomy(): string; /** - * Returns the ID of the main settings page of the plugin. + * Returns the IDs of the admin pages of the plugin. * - * @return string The settings page url. + * @return array The IDs of one or several admin/settings pages. */ - public static function get_settings_page(): string { - return ''; + public static function get_settings_pages(): array { + return array(); + } + + /** + * Get the plugins name from the main plugin-file's top-level-file-comment. + */ + final public static function get_plugin_name(): string { + $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . static::get_plugin_file() ); + if ( isset( $plugin_data['Name'] ) ) { + return $plugin_data['Name']; + } else { + return ''; + } } /** @@ -62,7 +74,7 @@ abstract class Event_Plugin { // Check if we are on a edit page for the event, or on the settings page of the event plugin. $is_event_plugins_edit_page = 'edit' === $screen->base && static::get_post_type() === $screen->post_type; - $is_event_plugins_settings_page = static::get_settings_page() === $screen->id; + $is_event_plugins_settings_page = in_array( $screen->id, static::get_settings_pages(), true ); return $is_event_plugins_edit_page || $is_event_plugins_settings_page; } diff --git a/includes/plugins/class-eventin.php b/includes/plugins/class-eventin.php new file mode 100644 index 0000000..6584e85 --- /dev/null +++ b/includes/plugins/class-eventin.php @@ -0,0 +1,60 @@ +get_main_post_type(). + return apply_filters( 'mec_post_type_name', 'mec-events' ); // phpcs:ignore + } + + /** + * Returns the IDs of the admin pages of the plugin. + * + * @return array The settings page urls. + */ + public static function get_settings_pages(): array { + return array( 'MEC-settings', 'MEC-support', 'MEC-ix', 'MEC-wizard', 'MEC-addons', 'mec-intro' ); + } + + /** + * Returns the taxonomy used for the plugin's event categories. + * + * @return string + */ + public static function get_event_category_taxonomy(): string { + return 'mec_category'; + } +} diff --git a/includes/plugins/class-the-events-calendar.php b/includes/plugins/class-the-events-calendar.php index ef07590..36ab8e0 100644 --- a/includes/plugins/class-the-events-calendar.php +++ b/includes/plugins/class-the-events-calendar.php @@ -41,17 +41,17 @@ final class The_Events_Calendar extends Event_plugin { } /** - * Returns the ID of the main settings page of the plugin. + * Returns the IDs of the admin pages of the plugin. * - * @return string The settings page url. + * @return array The settings page urls. */ - public static function get_settings_page(): string { + public static function get_settings_pages(): array { if ( class_exists( '\Tribe\Events\Admin\Settings' ) ) { $page = \Tribe\Events\Admin\Settings::$settings_page_id; } else { $page = 'tec-events-settings'; } - return sprintf( 'edit.php?post_type=tribe_events&page=%s', $page ); + return array( $page ); } /** diff --git a/includes/plugins/class-vs-event-list.php b/includes/plugins/class-vs-event-list.php index 0e1b0dc..f1bd96b 100644 --- a/includes/plugins/class-vs-event-list.php +++ b/includes/plugins/class-vs-event-list.php @@ -44,12 +44,12 @@ final class VS_Event_List extends Event_Plugin { } /** - * Returns the ID of the main settings page of the plugin. + * Returns the IDs of the admin pages of the plugin. * - * @return string The settings page url. + * @return array The settings page urls. */ - public static function get_settings_page(): string { - return 'settings_page_vsel'; + public static function get_settings_pages(): array { + return array( 'settings_page_vsel' ); } /** diff --git a/includes/plugins/class-wp-event-manager.php b/includes/plugins/class-wp-event-manager.php new file mode 100644 index 0000000..28a852a --- /dev/null +++ b/includes/plugins/class-wp-event-manager.php @@ -0,0 +1,72 @@ + '', + 'settings' => '', + ) +); +?> + +