Compare commits

..

8 commits

Author SHA1 Message Date
e8574d26ac Run integration tests and improve transformers for all integrations (#32)
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 33s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 56s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 1m0s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 57s
Reviewed-on: #32
Co-authored-by: André Menrath <andre.menrath@posteo.de>
Co-committed-by: André Menrath <andre.menrath@posteo.de>
2024-09-25 11:27:17 +02:00
1764a7b03f add tests for venue and join mode is always external
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 43s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 1m2s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 1m10s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 58s
2024-09-24 17:16:52 +02:00
893f1d3b7c Add integration tests for The Events Calendar (#31)
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 40s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 1m7s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 1m1s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 52s
Reviewed-on: #31
Co-authored-by: André Menrath <andre.menrath@posteo.de>
Co-committed-by: André Menrath <andre.menrath@posteo.de>
2024-09-24 16:24:31 +02:00
68b7963fe6 fix composer phpunit to make it work with autoloader
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 47s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 1m7s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 1m8s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 59s
2024-09-23 16:21:12 +02:00
2b22013e08 Enhance docs
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 34s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 56s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 59s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 51s
2024-09-21 15:04:06 +02:00
6edc402581 fix docker compose file for running unit tests locally
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 33s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 1m1s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 56s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 56s
2024-09-21 14:59:26 +02:00
c495e65105 cleanup repo
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 40s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 1m0s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 58s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 55s
2024-09-21 14:15:16 +02:00
712e56c87e Improve Actions (#27)
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 34s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 58s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 57s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 54s
Try to make caching in Forgejo Actions work.

Reviewed-on: #27
Co-authored-by: André Menrath <andre.menrath@posteo.de>
Co-committed-by: André Menrath <andre.menrath@posteo.de>
2024-09-21 14:06:11 +02:00
21 changed files with 1105 additions and 189 deletions

View file

@ -46,5 +46,5 @@ jobs:
if: steps.cache-composer.outputs.cache-hit != 'true' if: steps.cache-composer.outputs.cache-hit != 'true'
uses: ramsey/composer-install@v3 uses: ramsey/composer-install@v3
- name: Detect coding standard violations - name: Run PHP_CodeSniffer
run: ./vendor/bin/phpcs run: ./vendor/bin/phpcs

View file

@ -4,6 +4,7 @@ on:
push: push:
branches: branches:
- main - main
- improve_tests
pull_request: pull_request:
env: env:
@ -36,7 +37,7 @@ jobs:
path: | path: |
${{ env.WP_CORE_DIR }} ${{ env.WP_CORE_DIR }}
${{ env.WP_TESTS_DIR }} ${{ env.WP_TESTS_DIR }}
key: cache-wordpress-1 key: cache-wordpress-4
- name: Cache Composer - name: Cache Composer
id: cache-composer-phpunit id: cache-composer-phpunit
@ -73,7 +74,22 @@ jobs:
if: steps.cache-wordpress.outputs.cache-hit != 'false' if: steps.cache-wordpress.outputs.cache-hit != 'false'
run: bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 6.6 false true true true run: bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 6.6 false true true true
- name: Unit Testing - name: Run Integration tests for The Events Calendar
run: cd /workspace/Event-Federation/wordpress-activitypub-event-extensions/ && ./vendor/bin/phpunit run: cd /workspace/Event-Federation/wordpress-activitypub-event-extensions/ && ./vendor/bin/phpunit --filter=the_events_calendar
env:
PHP_VERSION: ${{ matrix.php-version }}
- name: Run Integration tests for VS Event List
run: cd /workspace/Event-Federation/wordpress-activitypub-event-extensions/ && ./vendor/bin/phpunit --filter=vs_event_list
env:
PHP_VERSION: ${{ matrix.php-version }}
- name: Run Integration tests for GatherPress
run: cd /workspace/Event-Federation/wordpress-activitypub-event-extensions/ && ./vendor/bin/phpunit --filter=gatherpress
env:
PHP_VERSION: ${{ matrix.php-version }}
- name: Run Integration tests for Events Manager
run: cd /workspace/Event-Federation/wordpress-activitypub-event-extensions/ && ./vendor/bin/phpunit --filter=events_manager
env: env:
PHP_VERSION: ${{ matrix.php-version }} PHP_VERSION: ${{ matrix.php-version }}

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
vendor vendor
composer.lock composer.lock
.phpunit.result.cache

View file

@ -11,6 +11,17 @@ RUN apk update \
RUN docker-php-ext-install mysqli RUN docker-php-ext-install mysqli
# Install Xdebug
RUN apk add --no-cache $PHPIZE_DEPS \
&& apk add --update linux-headers \
&& pecl install xdebug \
&& docker-php-ext-enable xdebug \
&& apk del --purge $PHPIZE_DEPS \
&& echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
&& echo "xdebug.client_host=host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
&& echo "xdebug.mode=debug" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
&& echo "xdebug.idekey=VSCODE" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
# Install Composer # Install Composer
RUN EXPECTED_CHECKSUM=$(curl -s https://composer.github.io/installer.sig) \ RUN EXPECTED_CHECKSUM=$(curl -s https://composer.github.io/installer.sig) \
&& curl https://getcomposer.org/installer -o composer-setup.php \ && curl https://getcomposer.org/installer -o composer-setup.php \
@ -24,4 +35,9 @@ RUN curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli
chmod +x wp-cli.phar && \ chmod +x wp-cli.phar && \
mv wp-cli.phar /usr/local/bin/wp mv wp-cli.phar /usr/local/bin/wp
COPY composer.json composer.lock /app/
RUN composer install --no-scripts --no-autoloader
RUN composer global require yoast/phpunit-polyfills:"^3.0" --dev
ENV PATH="/root/.composer/vendor/bin:${PATH}"
RUN chmod +x -R ./ RUN chmod +x -R ./

50
bin/install-wp-tests.sh Normal file → Executable file
View file

@ -15,6 +15,16 @@ SKIP_WP_INSTALL=${7-false}
SKIP_PLUGINS_INSTALL=${8-false} SKIP_PLUGINS_INSTALL=${8-false}
SKIP_TEST_SUITE_INSTALL=${9-false} SKIP_TEST_SUITE_INSTALL=${9-false}
# Initialize the plugin list
PLUGINS=""
# Parse optional --plugins argument
while [[ "$#" -gt 0 ]]; do
case $1 in
--plugins) PLUGINS="$2"; shift ;;
esac
shift
done
TMPDIR=${TMPDIR-/tmp} TMPDIR=${TMPDIR-/tmp}
TMPDIR=$(echo $TMPDIR | sed -e "s/\/$//") TMPDIR=$(echo $TMPDIR | sed -e "s/\/$//")
@ -182,20 +192,52 @@ install_db() {
if [ $(mysql --user="$DB_USER" --password="$DB_PASS"$EXTRA --execute='show databases;' | grep ^$DB_NAME$) ] if [ $(mysql --user="$DB_USER" --password="$DB_PASS"$EXTRA --execute='show databases;' | grep ^$DB_NAME$) ]
then then
echo "Reinstalling will delete the existing test database ($DB_NAME)" echo "Reinstalling will delete the existing test database ($DB_NAME)"
read -p 'Are you sure you want to proceed? [y/N]: ' DELETE_EXISTING_DB recreate_db yes
recreate_db $DELETE_EXISTING_DB
else else
create_db create_db
fi fi
} }
install_wp_plugin() {
PLUGIN_NAME=$1
mkdir -p "$WP_CORE_DIR/wp-content/plugins/"
if [ -d "$WP_CORE_DIR/wp-content/plugins/$PLUGIN_NAME" ]; then
return;
fi
# Get the latest tag.
LATEST_TAG=$(svn log https://plugins.svn.wordpress.org/$PLUGIN_NAME/tags --limit 1 | awk 'NR == 4 { print $4 }')
if [ -n "$LATEST_TAG" ]; then
PLUGIN_FILE="$PLUGIN_NAME.$LATEST_TAG.zip"
else
PLUGIN_FILE="$PLUGIN_NAME.zip"
fi
URL="https://downloads.wordpress.org/plugin/$PLUGIN_FILE"
# Check if the plugin file already exists
if ! test -f "$TMPDIR/$PLUGIN_FILE"; then
download $URL "$TMPDIR/$PLUGIN_FILE"
fi
# Unzip the plugin into the WordPress must-use plugins directory
unzip -q -o "$TMPDIR/$PLUGIN_FILE" -d "$WP_CORE_DIR/wp-content/plugins/"
}
install_wp_plugins() { install_wp_plugins() {
if [ "$SKIP_PLUGINS_INSTALL" = "true" ]; then if [ "$SKIP_PLUGINS_INSTALL" = "true" ]; then
echo "Skipping WordPress plugin installation." echo "Skipping WordPress plugin installation."
return 0 return 0
fi fi
download https://downloads.wordpress.org/plugin/activitypub.3.2.5.zip $TMPDIR/activitypub.zip # Install the one and only ActivityPub plugin (greetings @pfefferle).
unzip $TMPDIR/activitypub.zip -d $WP_CORE_DIR/wp-content/plugins/ install_wp_plugin activitypub
# Install (not-activate) all supported event plugins.
install_wp_plugin the-events-calendar
install_wp_plugin very-simple-event-list
install_wp_plugin gatherpress
install_wp_plugin events-manager
} }
install_wp install_wp

View file

@ -3,16 +3,20 @@
"description": "The ActivityPub Event Extensions help for event custom post types to federate properly.", "description": "The ActivityPub Event Extensions help for event custom post types to federate properly.",
"type": "wordpress-plugin", "type": "wordpress-plugin",
"require": { "require": {
"php": ">=5.6.0", "php": ">=8.1.0",
"composer/installers": "^1.0 || ^2.0" "composer/installers": "^2.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^5.7.21 || ^6.5 || ^7.5 || ^8",
"phpcompatibility/php-compatibility": "*", "phpcompatibility/php-compatibility": "*",
"phpcompatibility/phpcompatibility-wp": "*", "phpcompatibility/phpcompatibility-wp": "*",
"squizlabs/php_codesniffer": "3.*", "squizlabs/php_codesniffer": "3.*",
"wp-coding-standards/wpcs": "^3.1.0", "wp-coding-standards/wpcs": "dev-develop",
"yoast/phpunit-polyfills": "^3.0",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0.0", "dealerdirect/phpcodesniffer-composer-installer": "^1.0.0",
"sirbrillig/phpcs-variable-analysis": "^2.11" "sirbrillig/phpcs-variable-analysis": "^2.11",
"phpcsstandards/phpcsextra": "^1.1.0",
"dms/phpunit-arraysubset-asserts": "^0.5.0"
}, },
"config": { "config": {
"allow-plugins": true "allow-plugins": true
@ -36,6 +40,25 @@
], ],
"lint:fix": [ "lint:fix": [
"vendor/bin/phpcbf" "vendor/bin/phpcbf"
] ],
"prepare-test": [
"composer install",
"bin/install-wp-tests.sh wordpress-test root wordpress-test test-db latest true"
],
"test": [
"@prepare-test",
"@test-vs-event-list",
"@test-the-events-calendar",
"@test-gatherpress",
"@test-events-manager"
],
"test-debug": [
"@prepare-test",
"@test-vs-event-list"
],
"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"
} }
} }

View file

@ -1,26 +0,0 @@
version: '3'
services:
test-db:
platform: linux/x86_64
image: mariadb
environment:
MYSQL_DATABASE: wordpress
MYSQL_ROOT_PASSWORD: wordpress
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3306"]
interval: 5s
timeout: 2s
retries: 5
test-php:
build:
context: .
dockerfile: Dockerfile
depends_on:
test-db:
condition: service_healthy
links:
- test-db
volumes:
- .:/app
command: ["composer", "run-script", "test"]

47
docker-compose.yml Normal file
View file

@ -0,0 +1,47 @@
version: '3'
# This files purpose is to run the PHPunit tests locally.
# Install docker and docker compose and than just run:
# docker compose up
# To live debug in VSCode add this launch configuration to your .vscode/launch.json.
# It assumes that the WordPress root-dir is your workspace root.
#
# {
# "name": "Listen for PHPUnit",
# "type": "php",
# "request": "launch",
# "port": 9003,
# "pathMappings": {
# "/app/": "${workspaceRoot}/wp-content/plugins/activitypub-event-extensions/",
# "/tmp/wordpress/": "${workspaceRoot}/"
# },
# },
services:
test-db:
image: mariadb
environment:
MARIADB_DATABASE: wordpress-test
MARIADB_ROOT_PASSWORD: wordpress-test
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
start_period: 2s
interval: 1s
timeout: 5s
retries: 10
test-php:
build:
context: .
dockerfile: Dockerfile
depends_on:
test-db:
condition: service_healthy
links:
- test-db
volumes:
- .:/app
command: ["composer", "run-script", "test-debug"]
extra_hosts:
- "host.docker.internal:host-gateway"

View file

@ -35,7 +35,7 @@ class Event extends Post {
* *
* @return string The User-URL. * @return string The User-URL.
*/ */
protected function get_actor() { protected function get_actor(): ?string {
return $this->get_attributed_to(); return $this->get_attributed_to();
} }
@ -46,10 +46,17 @@ class Event extends Post {
* *
* @return string The Event Object-Type. * @return string The Event Object-Type.
*/ */
protected function get_type() { protected function get_type(): string {
return 'Event'; return 'Event';
} }
/**
* Get a sane default for whether comments are enabled.
*/
protected function get_comments_enabled(): ?bool {
return comments_open( $this->wp_object );
}
/** /**
* Returns the title of the event. * Returns the title of the event.
* *
@ -57,7 +64,7 @@ class Event extends Post {
* *
* @return string The name. * @return string The name.
*/ */
protected function get_name() { protected function get_name(): string {
return $this->wp_object->post_title; return $this->wp_object->post_title;
} }
@ -72,10 +79,33 @@ class Event extends Post {
$this->wp_taxonomy = $wp_taxonomy; $this->wp_taxonomy = $wp_taxonomy;
} }
/**
* Extract the join mode.
*
* Currently we don't handle joins, we always mark events as external.
*
* @return string
*/
public function get_join_mode(): ?string {
return 'external';
}
/**
* Extract the external participation url.
*
* Currently we don't handle joins, we always mark events as external.
* We just link back to the events HTML representation on our WordPress site.
*
* @return ?string The external participation URL.
*/
public function get_external_participation_url(): ?string {
return 'external' === $this->get_join_mode() ? $this->get_url() : null;
}
/** /**
* Set the event category, via the mapping setting. * Set the event category, via the mapping setting.
*/ */
public function get_category() { public function get_category(): ?string {
$current_category_mapping = \get_option( 'activitypub_event_extensions_event_category_mappings', array() ); $current_category_mapping = \get_option( 'activitypub_event_extensions_event_category_mappings', array() );
$terms = \get_the_terms( $this->wp_object, $this->wp_taxonomy ); $terms = \get_the_terms( $this->wp_object, $this->wp_taxonomy );
@ -93,7 +123,7 @@ class Event extends Post {
* *
* @return Event_Object * @return Event_Object
*/ */
public function to_object() { public function to_object(): Event_Object {
$activitypub_object = new Event_Object(); $activitypub_object = new Event_Object();
$activitypub_object = $this->transform_object_properties( $activitypub_object ); $activitypub_object = $this->transform_object_properties( $activitypub_object );

View file

@ -94,16 +94,21 @@ final class Events_Manager extends Event_Transformer {
return null; return null;
} }
$location = new Place();
$em_location = $this->em_event->get_location(); $em_location = $this->em_event->get_location();
if ( '' === $em_location->location_id ) {
return null;
}
$location = new Place();
$location->set_name( $em_location->location_name ); $location->set_name( $em_location->location_name );
$address = array( $address = array(
'type' => 'PostalAddress', 'type' => 'PostalAddress',
'addressCountry' => $em_location->location_country, 'addressCountry' => $em_location->location_country,
'addressLocality' => $em_location->location_town, 'addressLocality' => $em_location->location_town,
'streetAddress' => $em_location->location_address, 'postalAddress' => $em_location->location_address,
'postalCode' => $em_location->location_postcode,
'name' => $em_location->location_name, 'name' => $em_location->location_name,
); );
if ( $em_location->location_state ) { if ( $em_location->location_state ) {
@ -249,8 +254,10 @@ final class Events_Manager extends Event_Transformer {
/** /**
* Get the events title/name. * Get the events title/name.
*
* @return string
*/ */
protected function get_name() { protected function get_name(): string {
return $this->em_event->event_name; return $this->em_event->event_name;
} }
@ -259,7 +266,7 @@ final class Events_Manager extends Event_Transformer {
* *
* @return Activitypub\Activity\Event * @return Activitypub\Activity\Event
*/ */
public function to_object() { public function to_object(): Event {
$this->em_event = new EM_Event( $this->wp_object->ID, 'post_id' ); $this->em_event = new EM_Event( $this->wp_object->ID, 'post_id' );
$activitypub_object = new Event(); $activitypub_object = new Event();

View file

@ -49,29 +49,18 @@ final class GatherPress extends Event {
protected $gp_venue; protected $gp_venue;
/** /**
* Get transformer name. * Extend the constructor, to also set the GatherPress objects.
* *
* Retrieve the transformers name. * This is a special class object form The Events Calendar which
* has a lot of useful functions, we make use of our getter functions.
* *
* @since 1.0.0 * @param WP_Post $wp_object The WordPress object.
* @access public * @param string $wp_taxonomy The taxonomy slug of the event post type.
* @return string Widget name.
*/ */
public function get_transformer_name() { public function __construct( $wp_object, $wp_taxonomy ) {
return 'gatherpress/gp-event'; parent::__construct( $wp_object, $wp_taxonomy );
} $this->gp_event = new GatherPress_Event( $this->wp_object->ID );
$this->gp_venue = $this->gp_event->get_venue_information();
/**
* Get transformer title.
*
* Retrieve the transformers label.
*
* @since 1.0.0
* @access public
* @return string Widget title.
*/
public function get_transformer_label() {
return 'GatherPress Event';
} }
/** /**
@ -90,15 +79,19 @@ final class GatherPress extends Event {
/** /**
* Get the event location. * Get the event location.
* *
* @return array The Place. * @return Place|null The place objector null if not place set.
*/ */
public function get_location() { public function get_location(): Place|null {
$address = $this->gp_venue['full_address']; $address = $this->gp_venue['full_address'];
if ( $address ) {
$place = new Place(); $place = new Place();
$place->set_type( 'Place' ); $place->set_type( 'Place' );
$place->set_name( $address ); $place->set_name( $address );
$place->set_address( $address ); $place->set_address( $address );
return $place; return $place;
} else {
return null;
}
} }
/** /**
@ -134,7 +127,7 @@ final class GatherPress extends Event {
/** /**
* Overrides/extends the get_attachments function to also add the event Link. * Overrides/extends the get_attachments function to also add the event Link.
*/ */
protected function get_attachment() { protected function get_attachment(): array {
$attachments = parent::get_attachment(); $attachments = parent::get_attachment();
if ( count( $attachments ) ) { if ( count( $attachments ) ) {
$attachments[0]['type'] = 'Document'; $attachments[0]['type'] = 'Document';
@ -154,7 +147,7 @@ final class GatherPress extends Event {
* *
* @return string The User-URL. * @return string The User-URL.
*/ */
protected function get_attributed_to() { protected function get_attributed_to(): string {
$user = new Blog(); $user = new Blog();
return $user->get_url(); return $user->get_url();
} }
@ -167,7 +160,7 @@ final class GatherPress extends Event {
* *
* @return string $summary The custom event summary. * @return string $summary The custom event summary.
*/ */
public function get_summary() { public function get_summary(): string {
if ( $this->wp_object->excerpt ) { if ( $this->wp_object->excerpt ) {
$excerpt = $this->wp_object->post_excerpt; $excerpt = $this->wp_object->post_excerpt;
} elseif ( get_post_meta( $this->wp_object->ID, 'event-summary', true ) ) { } elseif ( get_post_meta( $this->wp_object->ID, 'event-summary', true ) ) {
@ -184,38 +177,31 @@ final class GatherPress extends Event {
return $summary; return $summary;
} }
/**
* Get the content.
*/
public function get_content(): string {
return $this->wp_object->post_content;
}
/**
* Determine whether the event is online.
*
* @return bool
*/
public function get_is_online(): bool {
return $this->gp_event->maybe_get_online_event_link() ? true : false;
}
/** /**
* Transform the WordPress Object into an ActivityPub Object. * Transform the WordPress Object into an ActivityPub Object.
* *
* @return Activitypub\Activity\Event * @return Activitypub\Activity\Event
*/ */
public function to_object() { public function to_object(): Event_Object {
$this->ap_object = new Event_Object(); $activitypub_object = parent::to_object();
$this->gp_event = new GatherPress_Event( $this->wp_object->ID );
$this->gp_venue = $this->gp_event->get_venue_information();
$this->ap_object = parent::to_object(); return $activitypub_object;
$this->ap_object->set_comments_enabled( 'open' === $this->wp_object->comment_status ? true : false );
$this->ap_object->set_external_participation_url( $this->get_url() );
$online_event_link = $this->gp_event->maybe_get_online_event_link();
if ( $online_event_link ) {
$this->ap_object->set_is_online( true );
} else {
$this->ap_object->set_is_online( false );
}
$this->ap_object->set_status( 'CONFIRMED' );
$this->ap_object->set_name( get_the_title( $this->wp_object->ID ) );
$this->ap_object->set_actor( get_rest_url_by_path( 'application' ) );
$this->ap_object->set_to( array( 'https://www.w3.org/ns/activitystreams#Public' ) );
$this->ap_object->set_location();
return $this->ap_object;
} }
} }

View file

@ -14,6 +14,7 @@ if ( ! defined( 'ABSPATH' ) ) {
use Activitypub_Event_Extensions\Activitypub\Transformer\Event; use Activitypub_Event_Extensions\Activitypub\Transformer\Event;
use Activitypub\Activity\Extended_Object\Place; use Activitypub\Activity\Extended_Object\Place;
use Activitypub\Activity\Extended_Object\Event as Event_Object;
use WP_Error; use WP_Error;
use WP_Post; use WP_Post;
@ -96,17 +97,6 @@ final class The_Events_Calendar extends Event {
return new WP_Error( 'invalid event_status value', __( 'invalid event_status', 'activitypub' ), array( 'status' => 404 ) ); return new WP_Error( 'invalid event_status value', __( 'invalid event_status', 'activitypub' ), array( 'status' => 404 ) );
} }
/**
* Extract the join mode.
*
* If the ticket sale is active set it to restricted.
*
* @return string
*/
public function get_join_mode() {
return empty( $this->tribe_event->tickets ) ? 'free' : 'restricted';
}
/** /**
* Check if the comments are enabled for the current event. * Check if the comments are enabled for the current event.
*/ */
@ -145,25 +135,55 @@ final class The_Events_Calendar extends Event {
* @return Place|array The place/venue if one is set. * @return Place|array The place/venue if one is set.
*/ */
public function get_location(): Place|null { public function get_location(): Place|null {
if ( empty( $this->wp_object->venues ) || ! empty( $this->wp_object->venues[0] ) ) { // Get short handle for the venues.
$venues = $this->wp_object->venues;
// Get first venue. We currently only support a single venue.
if ( $venues instanceof \Tribe\Events\Collections\Lazy_Post_Collection ) {
$venue = $venues->first();
} elseif ( empty( $this->wp_object->venues ) || ! empty( $this->wp_object->venues[0] ) ) {
return null;
} else {
$venue = $venues[0];
}
if ( ! $venue ) {
return null; return null;
} }
// We currently only support a single venue.
$event_venue = $this->wp_object->venues[0];
$address = array( // Set the address.
'addressCountry' => $event_venue->country, $address = array();
'addressLocality' => $event_venue->city,
'addressRegion' => $event_venue->province, if ( ! empty( $venue->country ) ) {
'postalCode' => $event_venue->zip, $address['addressCountry'] = $venue->country;
'streetAddress' => $event_venue->address, }
'type' => 'PostalAddress',
); if ( ! empty( $venue->city ) ) {
$address['addressLocality'] = $venue->city;
}
if ( ! empty( $venue->province ) ) {
$address['addressRegion'] = $venue->province;
}
if ( ! empty( $venue->zip ) ) {
$address['postalCode'] = $venue->zip;
}
if ( ! empty( $venue->address ) ) {
$address['streetAddress'] = $venue->address;
}
if ( ! empty( $venue->post_title ) ) {
$address['name'] = $venue->post_title;
}
$address['type'] = 'PostalAddress';
$location = new Place(); $location = new Place();
if ( count( $address ) > 1 ) {
$location->set_address( $address ); $location->set_address( $address );
$location->set_id( $event_venue->permalink ); }
$location->set_name( $event_venue->post_name ); $location->set_id( $venue->permalink );
$location->set_name( $venue->post_title );
return $location; return $location;
} }
@ -175,7 +195,7 @@ final class The_Events_Calendar extends Event {
* *
* @return Event_Object * @return Event_Object
*/ */
public function to_object() { public function to_object(): Event_Object {
$activitypub_object = parent::to_object(); $activitypub_object = parent::to_object();
return $activitypub_object; return $activitypub_object;

View file

@ -27,7 +27,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* @since 1.0.0 * @since 1.0.0
*/ */
final class VS_Event_List extends Event_Transformer { final class VS_Event_List extends Event_Transformer {
/** /**
* The target transformer ActivityPub Event object. * The target transformer ActivityPub Event object.
* *
@ -35,19 +34,6 @@ final class VS_Event_List extends Event_Transformer {
*/ */
protected $ap_object; protected $ap_object;
/**
* Get transformer name.
*
* Retrieve the transformers name.
*
* @since 1.0.0
* @access public
* @return string Widget name.
*/
public function get_transformer_name(): string {
return 'activitypub-event-transformers/vs-event';
}
/** /**
* Returns the ActivityStreams 2.0 Object-Type for an Event. * Returns the ActivityStreams 2.0 Object-Type for an Event.
* *
@ -64,21 +50,28 @@ final class VS_Event_List extends Event_Transformer {
* *
* @return Place The Place. * @return Place The Place.
*/ */
public function get_location(): Place { public function get_location(): ?Place {
$address = get_post_meta( $this->wp_object->ID, 'event-location', true ); $address = get_post_meta( $this->wp_object->ID, 'event-location', true );
if ( $address ) {
$place = new Place(); $place = new Place();
$place->set_type( 'Place' ); $place->set_type( 'Place' );
$place->set_name( $address ); $place->set_name( $address );
$place->set_address( $address ); $place->set_address( $address );
return $place; return $place;
} else {
return null;
}
} }
/** /**
* Get the end time from the events metadata. * Get the end time from the events metadata.
*/ */
protected function get_end_time(): string { protected function get_end_time(): ?string {
if ( 'yes' === get_post_meta( $this->wp_object->ID, 'event-hide-end-time', true ) ) {
return null;
}
$end_time = get_post_meta( $this->wp_object->ID, 'event-date', true ); $end_time = get_post_meta( $this->wp_object->ID, 'event-date', true );
return \gmdate( 'Y-m-d\TH:i:s\Z', $end_time ); return $end_time ? \gmdate( 'Y-m-d\TH:i:s\Z', $end_time ) : null;
} }
/** /**
@ -86,28 +79,32 @@ final class VS_Event_List extends Event_Transformer {
*/ */
protected function get_start_time(): string { protected function get_start_time(): string {
$start_time = get_post_meta( $this->wp_object->ID, 'event-start-date', true ); $start_time = get_post_meta( $this->wp_object->ID, 'event-start-date', true );
return \gmdate( 'Y-m-d\TH:i:s\Z', $start_time ); return $start_time ? \gmdate( 'Y-m-d\TH:i:s\Z', $start_time ) : null;
} }
/** /**
* Get the event link from the events metadata. * Get the event link from the events metadata.
*
* @return ?array Associated array of an ActivityStreams Link object with the events URL.
*/ */
private function get_event_link(): array { private function get_event_link(): ?array {
$event_link = get_post_meta( $this->wp_object->ID, 'event-link', true ); $event_link = get_post_meta( $this->wp_object->ID, 'event-link', true );
$event_link_label = get_post_meta( $this->wp_object->ID, 'event-link-label', true ) ?? 'Event Link';
if ( $event_link ) { if ( $event_link ) {
return array( return array(
'type' => 'Link', 'type' => 'Link',
'name' => 'Website', 'name' => $event_link_label,
'href' => \esc_url( $event_link ), 'href' => \esc_url( $event_link ),
'mediaType' => 'text/html', 'mediaType' => 'text/html',
); );
} }
return null;
} }
/** /**
* Overrides/extends the get_attachments function to also add the event Link. * Overrides/extends the get_attachments function to also add the event Link.
*/ */
protected function get_attachment() { protected function get_attachment(): ?array {
$attachments = parent::get_attachment(); $attachments = parent::get_attachment();
if ( count( $attachments ) ) { if ( count( $attachments ) ) {
$attachments[0]['type'] = 'Document'; $attachments[0]['type'] = 'Document';
@ -128,7 +125,7 @@ final class VS_Event_List extends Event_Transformer {
* *
* @return string $summary The custom event summary. * @return string $summary The custom event summary.
*/ */
public function get_summary() { public function get_summary(): ?string {
if ( $this->wp_object->excerpt ) { if ( $this->wp_object->excerpt ) {
$excerpt = $this->wp_object->post_excerpt; $excerpt = $this->wp_object->post_excerpt;
} elseif ( get_post_meta( $this->wp_object->ID, 'event-summary', true ) ) { } elseif ( get_post_meta( $this->wp_object->ID, 'event-summary', true ) ) {

View file

@ -59,14 +59,15 @@ class Setup {
* @since 1.0.0 * @since 1.0.0
*/ */
protected function __construct() { protected function __construct() {
$this->activitypub_plugin_is_active = is_plugin_active( 'activitypub/activitypub.php' ); $this->activitypub_plugin_is_active = defined( 'ACTIVITYPUB_PLUGIN_VERSION' ) ||
is_plugin_active( 'activitypub/activitypub.php' );
// BeforeFirstRelease: decide whether we want to do anything at all when ActivityPub plugin is note active. // BeforeFirstRelease: decide whether we want to do anything at all when ActivityPub plugin is note active.
// if ( ! $this->activitypub_plugin_is_active ) { // if ( ! $this->activitypub_plugin_is_active ) {
// deactivate_plugins( ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_FILE ); // deactivate_plugins( ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_FILE );
// return; // return;
// }. // }.
$this->active_event_plugins = self::detect_active_event_plugins(); $this->active_event_plugins = self::detect_active_event_plugins();
$this->activitypub_plugin_version = get_file_data( WP_PLUGIN_DIR . '/activitypub/activitypub.php', array( 'Version' ) )[0]; $this->activitypub_plugin_version = self::get_activitypub_plugin_version();
$this->setup_hooks(); $this->setup_hooks();
} }
@ -95,6 +96,19 @@ class Setup {
return self::$instance; return self::$instance;
} }
/**
* LooksUp the current version of the ActivityPub.
*
* @return string The semantic Version.
*/
private static function get_activitypub_plugin_version(): string {
if ( defined( 'ACTIVITYPUB_PLUGIN_VERSION' ) ) {
return constant( 'ACTIVITYPUB_PLUGIN_VERSION' );
}
$version = get_file_data( WP_PLUGIN_DIR . '/activitypub/activitypub.php', array( 'Version' ) )[0];
return $version ?? '0.0.0';
}
/** /**
* Getter function for the active event plugins. * Getter function for the active event plugins.
* *
@ -166,7 +180,7 @@ class Setup {
); );
// Check if the minimum required version of the ActivityPub plugin is installed. // Check if the minimum required version of the ActivityPub plugin is installed.
if ( version_compare( $this->activitypub_plugin_version, ACTIVITYPUB_EVENT_EXTENSIONS_ACTIVITYPUB_PLUGIN_MIN_VERSION ) ) { if ( ! version_compare( $this->activitypub_plugin_version, ACTIVITYPUB_EVENT_EXTENSIONS_ACTIVITYPUB_PLUGIN_MIN_VERSION ) ) {
return; return;
} }
@ -206,7 +220,7 @@ class Setup {
// The ActivityPub plugin is not active. // The ActivityPub plugin is not active.
add_action( 'admin_notices', array( 'Activitypub_Event_Extensions\Admin\General_Admin_Notices', 'activitypub_plugin_not_enabled' ), 10, 1 ); add_action( 'admin_notices', array( 'Activitypub_Event_Extensions\Admin\General_Admin_Notices', 'activitypub_plugin_not_enabled' ), 10, 1 );
} }
if ( version_compare( $this->activitypub_plugin_version, ACTIVITYPUB_EVENT_EXTENSIONS_ACTIVITYPUB_PLUGIN_MIN_VERSION ) ) { if ( ! version_compare( $this->activitypub_plugin_version, ACTIVITYPUB_EVENT_EXTENSIONS_ACTIVITYPUB_PLUGIN_MIN_VERSION ) ) {
// The ActivityPub plugin is too old. // The ActivityPub plugin is too old.
add_action( 'admin_notices', array( 'Activitypub_Event_Extensions\Admin\General_Admin_Notices', 'activitypub_plugin_version_too_old' ), 10, 1 ); add_action( 'admin_notices', array( 'Activitypub_Event_Extensions\Admin\General_Admin_Notices', 'activitypub_plugin_version_too_old' ), 10, 1 );
} }
@ -234,9 +248,9 @@ class Setup {
// Get the transformer for a specific event plugins event-post type. // Get the transformer for a specific event plugins event-post type.
foreach ( $this->active_event_plugins as $event_plugin ) { foreach ( $this->active_event_plugins as $event_plugin ) {
if ( $wp_object->post_type === $event_plugin->get_post_type() ) { if ( $wp_object->post_type === $event_plugin->get_post_type() ) {
$transformer_class = $event_plugin->get_activitypub_event_transformer_class(); $transformer_class = $event_plugin::get_activitypub_event_transformer_class();
if ( class_exists( $transformer_class ) ) { if ( class_exists( $transformer_class ) ) {
return new $transformer_class( $wp_object, $event_plugin->get_event_category_taxonomy() ); return new $transformer_class( $wp_object, $event_plugin::get_event_category_taxonomy() );
} }
} }
} }
@ -256,8 +270,8 @@ class Setup {
// If someone installs this plugin, we simply enable ActivityPub support for all currently active event post types. // If someone installs this plugin, we simply enable ActivityPub support for all currently active event post types.
$activitypub_supported_post_types = get_option( 'activitypub_support_post_types', array() ); $activitypub_supported_post_types = get_option( 'activitypub_support_post_types', array() );
foreach ( $this->active_event_plugins as $event_plugin ) { foreach ( $this->active_event_plugins as $event_plugin ) {
if ( ! in_array( $event_plugin['post_type'], $activitypub_supported_post_types, true ) ) { if ( ! in_array( $event_plugin->get_post_type(), $activitypub_supported_post_types, true ) ) {
$activitypub_supported_post_types[] = $event_plugin['post_type']; $activitypub_supported_post_types[] = $event_plugin->get_post_type();
} }
} }
update_option( 'activitypub_support_post_types', $activitypub_supported_post_types ); update_option( 'activitypub_support_post_types', $activitypub_supported_post_types );

View file

@ -26,9 +26,58 @@ if ( ! file_exists( "{$_tests_dir}/includes/functions.php" ) ) {
require_once "{$_tests_dir}/includes/functions.php"; require_once "{$_tests_dir}/includes/functions.php";
/** /**
* Manually load the plugin being tested. * Manually load the plugin being tested and its integrations.
*/ */
function _manually_load_plugin() { function _manually_load_plugin() {
$plugin_dir = ABSPATH . '/wp-content/plugins/';
// Always manually load the ActivityPub plugin.
require_once $plugin_dir . 'activitypub/activitypub.php';
// Capture the --filter argument.
$activitypub_event_extension_integration_filter = null;
foreach ( $_SERVER['argv'] as $arg ) {
if ( strpos( $arg, '--filter=' ) === 0 ) {
$activitypub_event_extension_integration_filter = substr( $arg, strlen( '--filter=' ) );
break;
}
}
$plugin_file = null;
// See if we want to run integration tests for a specific event-plugin.
switch ( $activitypub_event_extension_integration_filter ) {
case 'the_events_calendar':
$plugin_file = 'the-events-calendar/the-events-calendar.php';
break;
case 'vs_event_list':
$plugin_file = 'very-simple-event-list/vsel.php';
break;
case 'events_manager':
$plugin_file = 'events-manager/events-manager.php';
break;
case 'gatherpress':
$plugin_file = 'gatherpress/gatherpress.php';
break;
}
if ( $plugin_file ) {
// Manually load the event plugin.
require_once $plugin_dir . $plugin_file;
$current = get_option( 'active_plugins', array() );
$current[] = $plugin_file;
sort( $current );
update_option( 'active_plugins', $current );
}
// Hot fix that allows using Events Manager within unit tests, because the em_init() is later not run as admin.
if ( 'events_manager' === $activitypub_event_extension_integration_filter ) {
require_once $plugin_dir . 'events-manager/em-install.php';
em_create_events_table();
em_create_events_meta_table();
em_create_locations_table();
}
// At last manually load our WordPress plugin.
require dirname( __DIR__ ) . '/activitypub-event-extensions.php'; require dirname( __DIR__ ) . '/activitypub-event-extensions.php';
} }

View file

@ -0,0 +1,184 @@
<?php
/**
* Class SampleTest
*
* @package Activitypub_Event_Extensions
*/
/**
* Sample test case.
*/
class Test_Events_Manager extends WP_UnitTestCase {
/**
* 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 ( ! class_exists( 'EM_Events' ) ) {
self::markTestSkipped( 'VS Event List plugin is not active.' );
}
// For tests allow every user to create new events.
update_option( 'dbem_events_anonymous_submissions', true );
// Make sure that ActivityPub support is enabled for Events Manager.
$aec = \Activitypub_Event_Extensions\Setup::get_instance();
$aec->activate_activitypub_support_for_active_event_plugins();
// Delete all posts afterwards.
_delete_all_posts();
}
/**
* Test that the right transformer gets applied.
*/
public function test_transformer_class() {
// We only test for one event plugin being active at the same time,
// even though we support multiple onces in theory.
// But testing all combinations is beyond scope.
$active_event_plugins = \Activitypub_Event_Extensions\Setup::get_instance()->get_active_event_plugins();
$this->assertEquals( 1, count( $active_event_plugins ) );
// Enable ActivityPub support for the event plugin.
$this->assertContains( EM_POST_TYPE_EVENT, get_option( 'activitypub_support_post_types' ) );
// Insert a new Event.
$wp_post_id = wp_insert_post(
array(
'post_title' => 'Events Manager Test event',
'post_status' => 'published',
'post_type' => EM_POST_TYPE_EVENT,
'meta_input' => array(
'event_start_time' => strtotime( '+10 days 15:00:00' ),
),
)
);
$wp_object = get_post( $wp_post_id );
// Call the transformer Factory.
$transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object );
// Check that we got the right transformer.
$this->assertInstanceOf( \Activitypub_Event_Extensions\Activitypub\Transformer\Events_Manager::class, $transformer );
}
/**
* Test the transformation of a minimal event.
*/
public function test_transform_of_minimal_event() {
// Create mockup event.
$event = new EM_Event();
$event->event_name = 'Events Manager Test event';
$event->post_content = 'Event description';
$event->event_start_date = gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) );
$event->event_start_time = '15:00:00';
$event->start = strtotime( $event->event_start_date . ' ' . $event->event_start_time );
$event->force_status = 'published';
$event->event_rsvp = false;
$this->assertTrue( $event->save() );
// Call the transformer Factory.
$event_array = \Activitypub\Transformer\Factory::get_transformer( get_post( $event->post_id ) )->to_object()->to_array();
// Check that we got the right transformer.
$this->assertEquals( 'Event', $event_array['type'] );
$this->assertEquals( 'Events Manager Test event', $event_array['name'] );
$this->assertEquals( '', $event_array['content'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) ) . 'T15:00:00Z', $event_array['startTime'] );
$this->assertEquals( comments_open( $event->post_id ), $event_array['commentsEnabled'] );
$this->assertEquals( comments_open( $event->post_id ) ? 'allow_all' : 'closed', $event_array['repliesModerationOption'] );
$this->assertEquals( 'external', $event_array['joinMode'] );
$this->assertArrayNotHasKey( 'location', $event_array );
$this->assertArrayNotHasKey( 'endTime', $event_array );
$this->assertEquals( 'MEETING', $event_array['category'] );
}
/**
* Test the transformation of a event with full location.
*/
public function test_transform_of__full_event_with_location() {
// Create a mockup location.
$location = new EM_Location();
$location->location_name = 'Test location';
$location->location_address = 'Test Address';
$location->location_town = 'Test Town';
$location->location_state = 'Test state';
$location->location_postcode = '1337';
$location->location_region = 'Test region';
$location->location_country = 'AT'; // Must be a two char country code.
$this->assertTrue( $location->save() );
// Create mockup event.
$event = new EM_Event();
$event->event_name = 'Events Manager Test event';
$event->post_content = 'Event description';
$event->location_id = $location->location_id;
$event->event_start_date = gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) );
$event->event_end_date = gmdate( 'Y-m-d', strtotime( '+10 days 16:00:00' ) );
$event->event_start_time = '15:00:00';
$event->event_end_time = '16:00:00';
$event->start = strtotime( $event->event_start_date . ' ' . $event->event_start_time );
$event->end = strtotime( $event->event_end_date . ' ' . $event->event_end_time );
$event->force_status = 'published';
$event->event_rsvp = false;
$this->assertTrue( $event->save() );
// Call the transformer Factory.
$event_array = \Activitypub\Transformer\Factory::get_transformer( get_post( $event->post_id ) )->to_object()->to_array();
// Check that we got the right transformer.
$this->assertEquals( 'Event', $event_array['type'] );
$this->assertEquals( 'Events Manager Test event', $event_array['name'] );
$this->assertEquals( '', $event_array['content'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) ) . 'T15:00:00Z', $event_array['startTime'] );
$this->assertEquals( 'external', $event_array['joinMode'] );
$this->assertEquals( 'MEETING', $event_array['category'] );
$this->assertArrayHasKey( 'location', $event_array );
$this->assertEquals( 'Test location', $event_array['location']['name'] );
$this->assertEquals( 'Test Address', $event_array['location']['address']['postalAddress'] );
$this->assertEquals( 'Test Town', $event_array['location']['address']['addressLocality'] );
$this->assertEquals( 'Test state', $event_array['location']['address']['addressRegion'] );
$this->assertEquals( '1337', $event_array['location']['address']['postalCode'] );
$this->assertEquals( 'AT', $event_array['location']['address']['addressCountry'] );
}
/**
* Test the transformation of a minimal event.
*/
public function test_transform_of_event_with_name_only_location() {
// Create a mockup location.
$location = new EM_Location();
$location->location_name = 'Name only location';
$this->assertTrue( $location->save() );
// Create mockup event.
$event = new EM_Event();
$event->event_name = 'Events Manager Test event';
$event->post_content = 'Event description';
$event->location_id = $location->location_id;
$event->event_start_date = gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) );
$event->event_end_date = gmdate( 'Y-m-d', strtotime( '+10 days 16:00:00' ) );
$event->event_start_time = '15:00:00';
$event->event_end_time = '16:00:00';
$event->start = strtotime( $event->event_start_date . ' ' . $event->event_start_time );
$event->end = strtotime( $event->event_end_date . ' ' . $event->event_end_time );
$event->force_status = 'published';
$event->event_rsvp = false;
$this->assertTrue( $event->save() );
// Call the transformer Factory.
$event_array = \Activitypub\Transformer\Factory::get_transformer( get_post( $event->post_id ) )->to_object()->to_array();
// Check that we got the right transformer.
$this->assertEquals( 'Event', $event_array['type'] );
$this->assertEquals( 'Events Manager Test event', $event_array['name'] );
$this->assertEquals( '', $event_array['content'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) ) . 'T15:00:00Z', $event_array['startTime'] );
$this->assertEquals( 'external', $event_array['joinMode'] );
$this->assertEquals( 'MEETING', $event_array['category'] );
$this->assertArrayHasKey( 'location', $event_array );
$this->assertEquals( 'Name only location', $event_array['location']['name'] );
}
}

View file

@ -0,0 +1,103 @@
<?php
/**
* Class SampleTest
*
* @package Activitypub_Event_Extensions
*/
/**
* Sample test case.
*/
class Test_GatherPress extends WP_UnitTestCase {
/**
* 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 ( ! defined( 'GATHERPRESS_CORE_FILE' ) ) {
self::markTestSkipped( 'GatherPress plugin is not active.' );
}
// Mock the plugin activation.
GatherPress\Core\Setup::get_instance()->activate_gatherpress_plugin( false );
// Make sure that ActivityPub support is enabled for The Events Calendar.
$aec = \Activitypub_Event_Extensions\Setup::get_instance();
$aec->activate_activitypub_support_for_active_event_plugins();
// Delete all posts afterwards.
_delete_all_posts();
}
/**
* Test that the right transformer gets applied.
*/
public function test_transformer_class() {
// We only test for one event plugin being active at the same time,
// even though we support multiple onces in theory.
// But testing all combinations is beyond scope.
$active_event_plugins = \Activitypub_Event_Extensions\Setup::get_instance()->get_active_event_plugins();
$this->assertEquals( 1, count( $active_event_plugins ) );
// Enable ActivityPub support for the event plugin.
$this->assertContains( 'gatherpress_event', get_option( 'activitypub_support_post_types' ) );
// Mock GatherPress Event.
$post_id = wp_insert_post(
array(
'post_title' => 'Unit Test Event',
'post_type' => 'gatherpress_event',
'post_content' => 'Unit Test description.',
)
);
$event = new \GatherPress\Core\Event( $post_id );
$params = array(
'datetime_start' => '+10 days 15:00:00',
'datetime_end' => '+10 days 16:00:00',
'timezone' => 'America/New_York',
);
$event->save_datetimes( $params );
// Call the transformer Factory.
$transformer = \Activitypub\Transformer\Factory::get_transformer( $event->event );
// Check that we got the right transformer.
$this->assertInstanceOf( \Activitypub_Event_Extensions\Activitypub\Transformer\GatherPress::class, $transformer );
}
/**
* Test transformation to ActivityPUb for basic event.
*/
public function test_transform_of_basic_event() {
// Mock GatherPress Event.
$post_id = wp_insert_post(
array(
'post_title' => 'Unit Test Event',
'post_type' => 'gatherpress_event',
'post_content' => 'Unit Test description.',
'post_status' => 'published',
)
);
$event = new \GatherPress\Core\Event( $post_id );
$params = array(
'datetime_start' => '+10 days 15:00:00',
'datetime_end' => '+10 days 16:00:00',
'timezone' => 'America/New_York',
);
$event->save_datetimes( $params );
// Call the transformer Factory.
$event_array = \Activitypub\Transformer\Factory::get_transformer( $event->event )->to_object()->to_array();
// Check that the event ActivityStreams representation contains everything as expected.
$this->assertEquals( 'Event', $event_array['type'] );
$this->assertEquals( 'Unit Test Event', $event_array['name'] );
$this->assertEquals( 'Unit Test description.', $event_array['content'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) ) . 'T15:00:00Z', $event_array['startTime'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 16:00:00' ) ) . 'T16:00:00Z', $event_array['endTime'] );
$this->assertEquals( 'external', $event_array['joinMode'] );
$this->assertArrayNotHasKey( 'location', $event_array );
}
}

View file

@ -0,0 +1,216 @@
<?php
/**
* Class SampleTest
*
* @package Activitypub_Event_Extensions
*/
/**
* Sample test case.
*/
class Test_The_Events_Calendar extends WP_UnitTestCase {
/**
* Mockup events of certain complexity.
*/
public const MOCKUP_VENUS = array(
'minimal_venue' => array(
'venue' => 'Minimal Venue',
'status' => 'publish',
),
'complex_venue' => array(
'venue' => 'Complex Venue',
'status' => 'publish',
'show_map' => false,
'show_map_link' => false,
'address' => 'Venue address',
'city' => 'Venue city',
'country' => 'Venue country',
'province' => 'Venue province',
'state' => 'Venue state',
'stateprovince' => 'Venue stateprovince',
'zip' => 'Venue zip',
'phone' => 'Venue phone',
'website' => 'http://venue.com',
),
);
public const MOCKUP_EVENTS = array(
'minimal_event' => array(
'title' => 'My Event',
'content' => 'Come to my event. Let\'s connect!',
'start_date' => '+10 days 15:00:00',
'duration' => HOUR_IN_SECONDS,
'status' => 'publish',
),
'complex_event' => array(
'title' => 'My Event',
'content' => 'Come to my event. Let\'s connect!',
'start_date' => '+10 days 15:00:00',
'duration' => HOUR_IN_SECONDS,
'status' => 'publish',
),
);
/**
* 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 ( ! class_exists( '\Tribe__Events__Main' ) ) {
self::markTestSkipped( 'The Events Calendar plugin is not active.' );
}
// Make sure that ActivityPub support is enabled for The Events Calendar.
$aec = \Activitypub_Event_Extensions\Setup::get_instance();
$aec->activate_activitypub_support_for_active_event_plugins();
// Delete all posts afterwards.
_delete_all_posts();
}
/**
* Test that the right transformer gets applied.
*/
public function test_the_events_calendar_transformer_class() {
// We only test for one event plugin being active at the same time,
// even though we support multiple onces in theory.
// But testing all combinations is beyond scope.
$active_event_plugins = \Activitypub_Event_Extensions\Setup::get_instance()->get_active_event_plugins();
$this->assertEquals( 1, count( $active_event_plugins ) );
// Enable ActivityPub support for the event plugin.
$this->assertContains( 'tribe_events', get_option( 'activitypub_support_post_types' ) );
// Create a The Events Calendar Event without content.
$wp_object = tribe_events()
->set_args( self::MOCKUP_EVENTS['minimal_event'] )
->create();
// Call the transformer Factory.
$transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object );
// Check that we got the right transformer.
$this->assertInstanceOf( \Activitypub_Event_Extensions\Activitypub\Transformer\The_Events_Calendar::class, $transformer );
}
/**
* Test transformation of minimal event without venue.
*/
public function test_transform_of_minimal_event_without_venue() {
// Create a The Events Calendar Event.
$wp_object = tribe_events()
->set_args( self::MOCKUP_EVENTS['minimal_event'] )
->create();
// Call the transformer.
$event_array = \Activitypub\Transformer\Factory::get_transformer( $wp_object )->to_object()->to_array();
// Check that the event ActivityStreams representation contains everything as expected.
$this->assertEquals( 'Event', $event_array['type'] );
$this->assertEquals( 'My Event', $event_array['name'] );
$this->assertEquals( '', $event_array['content'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) ) . 'T15:00:00Z', $event_array['startTime'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 16:00:00' ) ) . 'T16:00:00Z', $event_array['endTime'] );
$this->assertTrue( $event_array['commentsEnabled'] );
$this->assertEquals( 'allow_all', $event_array['repliesModerationOption'] );
$this->assertEquals( 'external', $event_array['joinMode'] );
$this->assertArrayNotHasKey( 'location', $event_array );
$this->assertEquals( 'MEETING', $event_array['category'] );
}
/**
* Test transformation of event with mapped category.
*/
public function test_transform_event_with_mapped_categories() {
// Create category.
$category_id_music = wp_insert_term( 'Music', Tribe__Events__Main::TAXONOMY, array( 'slug' => 'music' ) );
$category_id_theatre = wp_insert_term( 'Theatre', Tribe__Events__Main::TAXONOMY, array( 'slug' => 'theatre' ) );
// Set default mapping for event categories.
update_option( 'activitypub_event_extensions_default_event_category', 'MUSIC' );
// Set an override for the category with the slug theatre.
update_option( 'activitypub_event_extensions_event_category_mappings', array( 'theatre' => 'THEATRE' ) );
// Create a The Events Calendar event with the music category.
$wp_object = tribe_events()
->set_args( self::MOCKUP_EVENTS['minimal_event'] )
->create();
// Set the post term music to the event.
wp_set_post_terms( $wp_object->ID, $category_id_music['term_id'], Tribe__Events__Main::TAXONOMY );
// Call the transformer.
$event_array = \Activitypub\Transformer\Factory::get_transformer( $wp_object )->to_object()->to_array();
// See if the default category mapping is applied.
$this->assertEquals( 'MUSIC', $event_array['category'] );
// Set the post term theatre to the event.
wp_set_post_terms( $wp_object->ID, $category_id_theatre['term_id'], Tribe__Events__Main::TAXONOMY, false );
// Call the transformer.
$event_array = \Activitypub\Transformer\Factory::get_transformer( $wp_object )->to_object()->to_array();
// See if the default category mapping is applied.
$this->assertEquals( 'THEATRE', $event_array['category'] );
}
/**
* Test transformation of minimal event with minimal venue.
*/
public function test_transform_of_minimal_event_with_venue() {
// Create Venue.
$venue = tribe_venues()->set_args( self::MOCKUP_VENUS['minimal_venue'] )->create();
// Create a The Events Calendar Event.
$wp_object = tribe_events()
->set_args( self::MOCKUP_EVENTS['complex_event'] )
->set( 'venue', $venue->ID )
->create();
// Call the transformer.
$event_array = \Activitypub\Transformer\Factory::get_transformer( $wp_object )->to_object()->to_array();
// Check that the event ActivityStreams representation contains everything as expected.
$this->assertEquals( 'Event', $event_array['type'] );
$this->assertEquals( 'My Event', $event_array['name'] );
$this->assertEquals( '', $event_array['content'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) ) . 'T15:00:00Z', $event_array['startTime'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 16:00:00' ) ) . 'T16:00:00Z', $event_array['endTime'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 16:00:00' ) ) . 'T16:00:00Z', $event_array['commentsEnabled'] );
$this->assertArrayHasKey( 'location', $event_array );
$this->assertEquals( 'Place', $event_array['location']['type'] );
$this->assertEquals( self::MOCKUP_VENUS['minimal_venue']['venue'], $event_array['location']['name'] );
}
/**
* Test transformation of minimal event with fully filled venue.
*/
public function test_transform_of_minimal_event_with_address_venue() {
// Create Venue.
$venue = tribe_venues()->set_args( self::MOCKUP_VENUS['complex_venue'] )->create();
// Create a The Events Calendar Event.
$wp_object = tribe_events()
->set_args( self::MOCKUP_EVENTS['minimal_event'] )
->set( 'venue', $venue->ID )
->create();
// Call the transformer.
$event_array = \Activitypub\Transformer\Factory::get_transformer( $wp_object )->to_object()->to_array();
// Check that the event ActivityStreams representation contains everything as expected.
$this->assertEquals( 'Event', $event_array['type'] );
$this->assertEquals( 'My Event', $event_array['name'] );
$this->assertEquals( '', $event_array['content'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) ) . 'T15:00:00Z', $event_array['startTime'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 16:00:00' ) ) . 'T16:00:00Z', $event_array['endTime'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 16:00:00' ) ) . 'T16:00:00Z', $event_array['commentsEnabled'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 16:00:00' ) ) . 'T16:00:00Z', $event_array['endTime'] );
$this->assertArrayHasKey( 'location', $event_array );
$this->assertEquals( 'Place', $event_array['location']['type'] );
$this->assertEquals( 'PostalAddress', $event_array['location']['address']['type'] );
$this->assertEquals( self::MOCKUP_VENUS['complex_venue']['venue'], $event_array['location']['name'] );
$this->assertEquals( self::MOCKUP_VENUS['complex_venue']['venue'], $event_array['location']['address']['name'] );
$this->assertEquals( self::MOCKUP_VENUS['complex_venue']['province'], $event_array['location']['address']['addressRegion'] );
$this->assertEquals( self::MOCKUP_VENUS['complex_venue']['address'], $event_array['location']['address']['streetAddress'] );
$this->assertEquals( self::MOCKUP_VENUS['complex_venue']['city'], $event_array['location']['address']['addressLocality'] );
$this->assertEquals( self::MOCKUP_VENUS['complex_venue']['country'], $event_array['location']['address']['addressCountry'] );
$this->assertEquals( self::MOCKUP_VENUS['complex_venue']['zip'], $event_array['location']['address']['postalCode'] );
}
}

View file

@ -0,0 +1,211 @@
<?php
/**
* Class SampleTest
*
* @package Activitypub_Event_Extensions
*/
/**
* Sample test case.
*/
class Test_VS_Event_List extends WP_UnitTestCase {
/**
* 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 ( ! function_exists( 'vsel_custom_post_type' ) ) {
self::markTestSkipped( 'VS Event List plugin is not active.' );
}
// Make sure that ActivityPub support is enabled for The Events Calendar.
$aec = \Activitypub_Event_Extensions\Setup::get_instance();
$aec->activate_activitypub_support_for_active_event_plugins();
// Delete all posts afterwards.
_delete_all_posts();
}
/**
* Test that the right transformer gets applied.
*/
public function test_transformer_class() {
// We only test for one event plugin being active at the same time,
// even though we support multiple onces in theory.
// But testing all combinations is beyond scope.
$active_event_plugins = \Activitypub_Event_Extensions\Setup::get_instance()->get_active_event_plugins();
$this->assertEquals( 1, count( $active_event_plugins ) );
// Enable ActivityPub support for the event plugin.
$this->assertContains( 'event', get_option( 'activitypub_support_post_types' ) );
// Insert a new Event.
$wp_post_id = wp_insert_post(
array(
'post_title' => 'VSEL Test Event',
'post_status' => 'published',
'post_type' => 'event',
'meta_input' => array(
'event-start-date' => strtotime( '+10 days 15:00:00' ),
),
)
);
$wp_object = get_post( $wp_post_id );
// Call the transformer Factory.
$transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object );
// Check that we got the right transformer.
$this->assertInstanceOf( \Activitypub_Event_Extensions\Activitypub\Transformer\VS_Event_List::class, $transformer );
}
/**
* Test the transformation to ActivityStreams of minimal event.
*/
public function test_transform_of_minimal_event() {
// Insert a new Event.
$wp_post_id = wp_insert_post(
array(
'post_title' => 'VSEL Test Event',
'post_status' => 'published',
'post_type' => 'event',
'meta_input' => array(
'event-start-date' => strtotime( '+10 days 15:00:00' ),
),
)
);
// Transform the event to ActivityStreams.
$event_array = \Activitypub\Transformer\Factory::get_transformer( get_post( $wp_post_id ) )->to_object()->to_array();
// Check that the event ActivityStreams representation contains everything as expected.
$this->assertEquals( 'Event', $event_array['type'] );
$this->assertEquals( 'VSEL Test Event', $event_array['name'] );
$this->assertEquals( '', $event_array['content'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) ) . 'T15:00:00Z', $event_array['startTime'] );
$this->assertArrayNotHasKey( 'endTime', $event_array );
$this->assertEquals( comments_open( $wp_post_id ), $event_array['commentsEnabled'] );
$this->assertEquals( comments_open( $wp_post_id ) ? 'allow_all' : 'closed', $event_array['repliesModerationOption'] );
$this->assertEquals( 'external', $event_array['joinMode'] );
$this->assertEquals( esc_url( get_permalink( $wp_post_id ) ), $event_array['externalParticipationUrl'] );
$this->assertArrayNotHasKey( 'location', $event_array );
$this->assertEquals( 'MEETING', $event_array['category'] );
}
/**
* Test the transformation to ActivityStreams of minimal event.
*/
public function test_transform_of_full_event() {
// Insert a new Event.
$wp_post_id = wp_insert_post(
array(
'post_title' => 'VSEL Test Event',
'post_status' => 'published',
'post_type' => 'event',
'meta_input' => array(
'event-start-date' => strtotime( '+10 days 15:00:00' ),
'event-date' => strtotime( '+10 days 16:00:00' ),
'event-link' => 'https://event-federation.eu/vsel-test-event',
'event-link-label' => 'Website',
),
)
);
// Transform the event to ActivityStreams.
$event_array = \Activitypub\Transformer\Factory::get_transformer( get_post( $wp_post_id ) )->to_object()->to_array();
// Check that the event ActivityStreams representation contains everything as expected.
$this->assertEquals( 'Event', $event_array['type'] );
$this->assertEquals( 'VSEL Test Event', $event_array['name'] );
$this->assertEquals( '', $event_array['content'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) ) . 'T15:00:00Z', $event_array['startTime'] );
$this->assertEquals( gmdate( 'Y-m-d', strtotime( '+10 days 15:00:00' ) ) . 'T16:00:00Z', $event_array['endTime'] );
$this->assertEquals( comments_open( $wp_post_id ), $event_array['commentsEnabled'] );
$this->assertEquals( comments_open( $wp_post_id ) ? 'allow_all' : 'closed', $event_array['repliesModerationOption'] );
$this->assertEquals( 'external', $event_array['joinMode'] );
$this->assertEquals( esc_url( get_permalink( $wp_post_id ) ), $event_array['externalParticipationUrl'] );
$this->assertArrayNotHasKey( 'location', $event_array );
$this->assertEquals( 'MEETING', $event_array['category'] );
$this->assertContains(
array(
'type' => 'Link',
'name' => 'Website',
'href' => 'https://event-federation.eu/vsel-test-event',
'mediaType' => 'text/html',
),
$event_array['attachment']
);
}
/**
* Test the transformation to ActivityStreams of event with hidden end time.
*/
public function test_transform_of_event_with_hidden_end_time() {
// Insert a new Event.
$wp_post_id = wp_insert_post(
array(
'post_title' => 'VSEL Test Event',
'post_status' => 'published',
'post_type' => 'event',
'meta_input' => array(
'event-start-date' => strtotime( '+10 days 15:00:00' ),
'event-date' => strtotime( '+10 days 16:00:00' ),
'event-hide-end-time' => 'yes',
),
)
);
// Transform the event to ActivityStreams.
$event_array = \Activitypub\Transformer\Factory::get_transformer( get_post( $wp_post_id ) )->to_object()->to_array();
// Check that the event ActivityStreams representation contains everything as expected.
$this->assertArrayNotHasKey( 'endTime', $event_array );
}
/**
* Test transformation of event with mapped category.
*/
public function test_transform_event_with_mapped_categories() {
// Create category.
$category_id_music = wp_insert_term( 'Music', 'event_cat', array( 'slug' => 'music' ) );
$category_id_theatre = wp_insert_term( 'Theatre', 'event_cat', array( 'slug' => 'theatre' ) );
// Set default mapping for event categories.
update_option( 'activitypub_event_extensions_default_event_category', 'MUSIC' );
// Set an override for the category with the slug theatre.
update_option( 'activitypub_event_extensions_event_category_mappings', array( 'theatre' => 'THEATRE' ) );
// Create a VS Event List event with the music category.
$wp_post_id = wp_insert_post(
array(
'post_title' => 'VSEL Test Event',
'post_status' => 'published',
'post_type' => 'event',
'meta_input' => array(
'event-start-date' => strtotime( '+10 days 15:00:00' ),
'event-date' => strtotime( '+10 days 16:00:00' ),
'event-hide-end-time' => 'yes',
),
)
);
wp_set_post_terms( $wp_post_id, $category_id_music['term_id'], 'event_cat' );
// Call the transformer.
$event_array = \Activitypub\Transformer\Factory::get_transformer( get_post( $wp_post_id ) )->to_object()->to_array();
// See if the default category mapping is applied.
$this->assertEquals( 'MUSIC', $event_array['category'] );
// Change the event category to theatre.
wp_set_post_terms( $wp_post_id, $category_id_theatre['term_id'], 'event_cat', false );
// Call the transformer.
$event_array = \Activitypub\Transformer\Factory::get_transformer( get_post( $wp_post_id ) )->to_object()->to_array();
// See if the default category mapping is applied.
$this->assertEquals( 'THEATRE', $event_array['category'] );
}
}

View file

@ -1,20 +0,0 @@
<?php
/**
* Class SampleTest
*
* @package Activitypub_Event_Extensions
*/
/**
* Sample test case.
*/
class Test_Sample extends WP_UnitTestCase {
/**
* A single example test.
*/
public function test_sample() {
// Replace this with some actual testing code.
$this->assertTrue( true );
}
}