diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index 789b202bc..f6c63fb9b 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -15,13 +15,11 @@ jobs: options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=10s --health-retries=10 strategy: matrix: - php-versions: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] + php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] include: - wp-version: latest - - wp-version: '6.5' - php-versions: '7.0' - - wp-version: '6.5' - php-versions: '7.1' + - wp-version: '5.9' + php-versions: '7.2' steps: - name: Install svn run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index e335646bb..e0c625a64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,16 +9,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +* Comment counts get updated when the plugin is activated/deactivated/deleted * Added a filter to make custom comment types manageable in WP.com Calypso * Cleanup of options, post meta, and user meta when the plugin is uninstalled ### Changed * Hide ActivityPub post meta keys from the custom Fields UI +* Bumped minimum required PHP version to 7.2 ### Fixed * Undefined array key warnings in various places +* @-mentions in federated comments being displayed with a line break * Fetching replies from the same instance for Enable Mastodon Apps * Image captions not being included in the ActivityPub representation when the image is attached to the post diff --git a/activitypub.php b/activitypub.php index e394dba11..f59ede795 100644 --- a/activitypub.php +++ b/activitypub.php @@ -8,7 +8,7 @@ * Author URI: https://automattic.com/ * License: MIT * License URI: http://opensource.org/licenses/MIT - * Requires PHP: 7.0 + * Requires PHP: 7.2 * Text Domain: activitypub * Domain Path: /languages * diff --git a/composer.json b/composer.json index 8aaefd3d7..f55a1d517 100644 --- a/composer.json +++ b/composer.json @@ -3,11 +3,11 @@ "description": "The ActivityPub protocol is a decentralized social networking protocol based upon the ActivityStreams 2.0 data format.", "type": "wordpress-plugin", "require": { - "php": ">=7.0", + "php": ">=7.2", "composer/installers": "^1.0 || ^2.0" }, "require-dev": { - "phpunit/phpunit": "^5.7.21 || ^6.5 || ^7.5 || ^8", + "phpunit/phpunit": "^8 || ^9", "phpcompatibility/php-compatibility": "*", "phpcompatibility/phpcompatibility-wp": "*", "squizlabs/php_codesniffer": "3.*", diff --git a/includes/class-activitypub.php b/includes/class-activitypub.php index 7c1da2bc8..f0ab1e352 100644 --- a/includes/class-activitypub.php +++ b/includes/class-activitypub.php @@ -62,6 +62,9 @@ public static function init() { public static function activate() { self::flush_rewrite_rules(); Scheduler::register_schedules(); + + \add_filter( 'pre_wp_update_comment_count_now', array( Comment::class, 'pre_wp_update_comment_count_now' ), 10, 3 ); + Migration::update_comment_counts(); } /** @@ -70,6 +73,9 @@ public static function activate() { public static function deactivate() { self::flush_rewrite_rules(); Scheduler::deregister_schedules(); + + \remove_filter( 'pre_wp_update_comment_count_now', array( Comment::class, 'pre_wp_update_comment_count_now' ) ); + Migration::update_comment_counts( 2000 ); } /** @@ -77,6 +83,9 @@ public static function deactivate() { */ public static function uninstall() { Scheduler::deregister_schedules(); + + \remove_filter( 'pre_wp_update_comment_count_now', array( Comment::class, 'pre_wp_update_comment_count_now' ) ); + Migration::update_comment_counts( 2000 ); delete_metadata( 'user', 0, '_activitypub_user_identifier', '', true ); delete_metadata( 'user', 0, 'activitypub_default_extra_fields', '', true ); diff --git a/includes/transformer/class-comment.php b/includes/transformer/class-comment.php index f689b8cf2..9b1ec64ff 100644 --- a/includes/transformer/class-comment.php +++ b/includes/transformer/class-comment.php @@ -45,44 +45,6 @@ public function change_wp_user_id( $user_id ) { $this->wp_object->user_id = $user_id; } - /** - * Transforms the WP_Comment object to an ActivityPub Object. - * - * @see \Activitypub\Activity\Base_Object - * - * @return \Activitypub\Activity\Base_Object The ActivityPub Object. - */ - public function to_object() { - $object = parent::to_object(); - - $content = $this->get_content(); - $at_replies = ''; - $reply_context = $this->extract_reply_context( array() ); - - foreach ( $reply_context as $acct => $url ) { - $at_replies .= sprintf( - '%s ', - esc_url( $url ), - esc_html( $acct ) - ); - } - - $at_replies = trim( $at_replies ); - - if ( $at_replies ) { - $content = sprintf( '
%s
%s', $at_replies, $content ); - } - - $object->set_content( $content ); - $object->set_content_map( - array( - $this->get_locale() => $content, - ) - ); - - return $object; - } - /** * Returns the User-URL of the Author of the Post. * @@ -107,8 +69,18 @@ protected function get_attributed_to() { * @return string The content. */ protected function get_content() { - $comment = $this->wp_object; - $content = $comment->comment_content; + $comment = $this->wp_object; + $content = $comment->comment_content; + $mentions = ''; + + foreach ( $this->extract_reply_context() as $acct => $url ) { + $mentions .= sprintf( + '%s ', + esc_url( $url ), + esc_html( $acct ) + ); + } + $content = $mentions . $content; /** * Filter the content of the comment. @@ -258,11 +230,11 @@ function ( $comment_id ) { * Collect all other Users that participated in this comment-thread * to send them a notification about the new reply. * - * @param array $mentions The already mentioned ActivityPub users. + * @param array $mentions Optional. The already mentioned ActivityPub users. Default empty array. * * @return array The list of all Repliers. */ - public function extract_reply_context( $mentions ) { + public function extract_reply_context( $mentions = array() ) { // Check if `$this->wp_object` is a WP_Comment. if ( 'WP_Comment' !== get_class( $this->wp_object ) ) { return $mentions; @@ -364,4 +336,15 @@ public function get_to() { get_rest_url_by_path( $path ), ); } + + /** + * Returns the content map for the comment. + * + * @return array The content map for the comment. + */ + public function get_content_map() { + return array( + $this->get_locale() => $this->get_content(), + ); + } } diff --git a/phpcs.xml b/phpcs.xml index 8c155257f..7f4b346e5 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -14,9 +14,9 @@@remote@example.net @author@remote.example
This is a comment
', $content ); + $this->assertSame( '@remote@example.net @author@remote.example This is a comment
', $content ); // Clean up. wp_delete_comment( $reply_comment_id, true ); diff --git a/tests/includes/transformer/class-test-post.php b/tests/includes/transformer/class-test-post.php index a6a07202c..803d86f5c 100644 --- a/tests/includes/transformer/class-test-post.php +++ b/tests/includes/transformer/class-test-post.php @@ -370,6 +370,16 @@ public function test_block_attachments_with_fallback() { ) ); + // For WP versions 6.1 and prior, we only look for attached images. + if ( ! class_exists( 'WP_HTML_Tag_Processor' ) ) { + wp_update_post( + array( + 'ID' => $attachment_id, + 'post_parent' => $post_id, + ) + ); + } + $object = Post::transform( get_post( $post_id ) )->to_object(); $this->assertEquals(