Merge branch 'master' into Comments
BIN
.wordpress-org/banner-1544x500.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 272 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
BIN
.wordpress-org/icon-512x512.png
Normal file
After Width: | Height: | Size: 29 KiB |
19
README.md
|
@ -3,7 +3,7 @@
|
||||||
**Tags:** OStatus, fediverse, activitypub, activitystream
|
**Tags:** OStatus, fediverse, activitypub, activitystream
|
||||||
**Requires at least:** 4.7
|
**Requires at least:** 4.7
|
||||||
**Tested up to:** 6.3
|
**Tested up to:** 6.3
|
||||||
**Stable tag:** 1.0.2
|
**Stable tag:** 1.0.5
|
||||||
**Requires PHP:** 5.6
|
**Requires PHP:** 5.6
|
||||||
**License:** MIT
|
**License:** MIT
|
||||||
**License URI:** http://opensource.org/licenses/MIT
|
**License URI:** http://opensource.org/licenses/MIT
|
||||||
|
@ -105,6 +105,23 @@ Where 'blog' is the path to the subdirectory at which your blog resides.
|
||||||
|
|
||||||
Project maintained on GitHub at [automattic/wordpress-activitypub](https://github.com/automattic/wordpress-activitypub).
|
Project maintained on GitHub at [automattic/wordpress-activitypub](https://github.com/automattic/wordpress-activitypub).
|
||||||
|
|
||||||
|
### 1.0.5 ###
|
||||||
|
|
||||||
|
* Fixed: compatibility with WebFinger and NodeInfo plugin
|
||||||
|
|
||||||
|
### 1.0.4 ###
|
||||||
|
|
||||||
|
* Fixed: Constants were not loaded early enough, resulting in a race condition
|
||||||
|
* Fixed: Featured image was ignored when using the block editor
|
||||||
|
|
||||||
|
### 1.0.3 ###
|
||||||
|
|
||||||
|
* Fixed: compatibility with older WordPress/PHP versions
|
||||||
|
* Update: refactoring of the Plugin init process
|
||||||
|
* Update: better frontend UX and improved theme compat for blocks
|
||||||
|
* Compatibility: add a ACTIVITYPUB_DISABLE_REWRITES constant
|
||||||
|
* Compatibility: add pre-fetch hook to allow plugins to hang filters on
|
||||||
|
|
||||||
### 1.0.2 ###
|
### 1.0.2 ###
|
||||||
|
|
||||||
* Updated: improved hashtag visibility in default template
|
* Updated: improved hashtag visibility in default template
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* Plugin Name: ActivityPub
|
* Plugin Name: ActivityPub
|
||||||
* Plugin URI: https://github.com/pfefferle/wordpress-activitypub/
|
* Plugin URI: https://github.com/pfefferle/wordpress-activitypub/
|
||||||
* Description: The ActivityPub protocol is a decentralized social networking protocol based upon the ActivityStreams 2.0 data format.
|
* Description: The ActivityPub protocol is a decentralized social networking protocol based upon the ActivityStreams 2.0 data format.
|
||||||
* Version: 1.0.2
|
* Version: 1.0.5
|
||||||
* Author: Matthias Pfefferle & Automattic
|
* Author: Matthias Pfefferle & Automattic
|
||||||
* Author URI: https://automattic.com/
|
* Author URI: https://automattic.com/
|
||||||
* License: MIT
|
* License: MIT
|
||||||
|
@ -17,12 +17,12 @@ namespace Activitypub;
|
||||||
|
|
||||||
use function Activitypub\site_supports_blocks;
|
use function Activitypub\site_supports_blocks;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/includes/compat.php';
|
||||||
require_once __DIR__ . '/includes/functions.php';
|
require_once __DIR__ . '/includes/functions.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the plugin constants.
|
* Initialize the plugin constants.
|
||||||
*/
|
*/
|
||||||
function define_constants() {
|
|
||||||
\defined( 'ACTIVITYPUB_REST_NAMESPACE' ) || \define( 'ACTIVITYPUB_REST_NAMESPACE', 'activitypub/1.0' );
|
\defined( 'ACTIVITYPUB_REST_NAMESPACE' ) || \define( 'ACTIVITYPUB_REST_NAMESPACE', 'activitypub/1.0' );
|
||||||
\defined( 'ACTIVITYPUB_EXCERPT_LENGTH' ) || \define( 'ACTIVITYPUB_EXCERPT_LENGTH', 400 );
|
\defined( 'ACTIVITYPUB_EXCERPT_LENGTH' ) || \define( 'ACTIVITYPUB_EXCERPT_LENGTH', 400 );
|
||||||
\defined( 'ACTIVITYPUB_SHOW_PLUGIN_RECOMMENDATIONS' ) || \define( 'ACTIVITYPUB_SHOW_PLUGIN_RECOMMENDATIONS', true );
|
\defined( 'ACTIVITYPUB_SHOW_PLUGIN_RECOMMENDATIONS' ) || \define( 'ACTIVITYPUB_SHOW_PLUGIN_RECOMMENDATIONS', true );
|
||||||
|
@ -37,7 +37,6 @@ function define_constants() {
|
||||||
\define( 'ACTIVITYPUB_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
|
\define( 'ACTIVITYPUB_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
|
||||||
\define( 'ACTIVITYPUB_PLUGIN_FILE', plugin_dir_path( __FILE__ ) . '/' . basename( __FILE__ ) );
|
\define( 'ACTIVITYPUB_PLUGIN_FILE', plugin_dir_path( __FILE__ ) . '/' . basename( __FILE__ ) );
|
||||||
\define( 'ACTIVITYPUB_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
|
\define( 'ACTIVITYPUB_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize REST routes.
|
* Initialize REST routes.
|
||||||
|
@ -63,8 +62,6 @@ function rest_init() {
|
||||||
* Initialize plugin.
|
* Initialize plugin.
|
||||||
*/
|
*/
|
||||||
function plugin_init() {
|
function plugin_init() {
|
||||||
define_constants();
|
|
||||||
|
|
||||||
\add_action( 'init', array( __NAMESPACE__ . '\Migration', 'init' ) );
|
\add_action( 'init', array( __NAMESPACE__ . '\Migration', 'init' ) );
|
||||||
\add_action( 'init', array( __NAMESPACE__ . '\Activitypub', 'init' ) );
|
\add_action( 'init', array( __NAMESPACE__ . '\Activitypub', 'init' ) );
|
||||||
\add_action( 'init', array( __NAMESPACE__ . '\Activity_Dispatcher', 'init' ) );
|
\add_action( 'init', array( __NAMESPACE__ . '\Activity_Dispatcher', 'init' ) );
|
||||||
|
@ -85,6 +82,12 @@ function plugin_init() {
|
||||||
require_once $debug_file;
|
require_once $debug_file;
|
||||||
Debug::init();
|
Debug::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/integration/class-webfinger.php';
|
||||||
|
Integration\Webfinger::init();
|
||||||
|
|
||||||
|
require_once __DIR__ . '/integration/class-nodeinfo.php';
|
||||||
|
Integration\Nodeinfo::init();
|
||||||
}
|
}
|
||||||
\add_action( 'plugins_loaded', __NAMESPACE__ . '\plugin_init' );
|
\add_action( 'plugins_loaded', __NAMESPACE__ . '\plugin_init' );
|
||||||
|
|
||||||
|
|
37
includes/compat.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ActivityPub implementation for WordPress/PHP functions either missing from older WordPress/PHP versions or not included by default.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! function_exists( 'str_starts_with' ) ) {
|
||||||
|
/**
|
||||||
|
* Polyfill for `str_starts_with()` function added in PHP 8.0.
|
||||||
|
*
|
||||||
|
* Performs a case-sensitive check indicating if
|
||||||
|
* the haystack begins with needle.
|
||||||
|
*
|
||||||
|
* @param string $haystack The string to search in.
|
||||||
|
* @param string $needle The substring to search for in the `$haystack`.
|
||||||
|
* @return bool True if `$haystack` starts with `$needle`, otherwise false.
|
||||||
|
*/
|
||||||
|
function str_starts_with( $haystack, $needle ) {
|
||||||
|
if ( '' === $needle ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0 === strpos( $haystack, $needle );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! function_exists( 'get_self_link' ) ) {
|
||||||
|
/**
|
||||||
|
* Returns the link for the currently displayed feed.
|
||||||
|
*
|
||||||
|
* @return string Correct link for the atom:self element.
|
||||||
|
*/
|
||||||
|
function get_self_link() {
|
||||||
|
$host = wp_parse_url( home_url() );
|
||||||
|
$path = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
|
||||||
|
return esc_url( apply_filters( 'self_link', set_url_scheme( 'http://' . $host['host'] . $path ) ) );
|
||||||
|
}
|
||||||
|
}
|
|
@ -682,19 +682,6 @@ function is_single_user() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! function_exists( 'get_self_link' ) ) {
|
|
||||||
/**
|
|
||||||
* Returns the link for the currently displayed feed.
|
|
||||||
*
|
|
||||||
* @return string Correct link for the atom:self element.
|
|
||||||
*/
|
|
||||||
function get_self_link() {
|
|
||||||
$host = wp_parse_url( home_url() );
|
|
||||||
$path = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
|
|
||||||
return esc_url( apply_filters( 'self_link', set_url_scheme( 'http://' . $host['host'] . $path ) ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a site supports the block editor.
|
* Check if a site supports the block editor.
|
||||||
*
|
*
|
||||||
|
|
|
@ -18,9 +18,6 @@ class Nodeinfo {
|
||||||
*/
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
self::register_routes();
|
self::register_routes();
|
||||||
|
|
||||||
\add_filter( 'nodeinfo_data', array( self::class, 'add_nodeinfo_discovery' ), 10, 2 );
|
|
||||||
\add_filter( 'nodeinfo2_data', array( self::class, 'add_nodeinfo2_discovery' ), 10 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -194,36 +191,4 @@ class Nodeinfo {
|
||||||
|
|
||||||
return new \WP_REST_Response( $discovery, 200 );
|
return new \WP_REST_Response( $discovery, 200 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Extend NodeInfo data
|
|
||||||
*
|
|
||||||
* @param array $nodeinfo NodeInfo data
|
|
||||||
* @param string The NodeInfo Version
|
|
||||||
*
|
|
||||||
* @return array The extended array
|
|
||||||
*/
|
|
||||||
public static function add_nodeinfo_discovery( $nodeinfo, $version ) {
|
|
||||||
if ( '2.0' === $version ) {
|
|
||||||
$nodeinfo['protocols'][] = 'activitypub';
|
|
||||||
} else {
|
|
||||||
$nodeinfo['protocols']['inbound'][] = 'activitypub';
|
|
||||||
$nodeinfo['protocols']['outbound'][] = 'activitypub';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $nodeinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extend NodeInfo2 data
|
|
||||||
*
|
|
||||||
* @param array $nodeinfo NodeInfo2 data
|
|
||||||
*
|
|
||||||
* @return array The extended array
|
|
||||||
*/
|
|
||||||
public static function add_nodeinfo2_discovery( $nodeinfo ) {
|
|
||||||
$nodeinfo['protocols'][] = 'activitypub';
|
|
||||||
|
|
||||||
return $nodeinfo;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,6 @@ class Webfinger {
|
||||||
*/
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
self::register_routes();
|
self::register_routes();
|
||||||
|
|
||||||
\add_filter( 'webfinger_user_data', array( self::class, 'add_user_discovery' ), 10, 3 );
|
|
||||||
\add_filter( 'webfinger_data', array( self::class, 'add_pseudo_user_discovery' ), 99, 2 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,44 +78,6 @@ class Webfinger {
|
||||||
return $params;
|
return $params;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add WebFinger discovery links
|
|
||||||
*
|
|
||||||
* @param array $array the jrd array
|
|
||||||
* @param string $resource the WebFinger resource
|
|
||||||
* @param WP_User $user the WordPress user
|
|
||||||
*
|
|
||||||
* @return array the jrd array
|
|
||||||
*/
|
|
||||||
public static function add_user_discovery( $array, $resource, $user ) {
|
|
||||||
$user = User_Collection::get_by_id( $user->ID );
|
|
||||||
|
|
||||||
$array['links'][] = array(
|
|
||||||
'rel' => 'self',
|
|
||||||
'type' => 'application/activity+json',
|
|
||||||
'href' => $user->get_url(),
|
|
||||||
);
|
|
||||||
|
|
||||||
return $array;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add WebFinger discovery links
|
|
||||||
*
|
|
||||||
* @param array $array the jrd array
|
|
||||||
* @param string $resource the WebFinger resource
|
|
||||||
* @param WP_User $user the WordPress user
|
|
||||||
*
|
|
||||||
* @return array the jrd array
|
|
||||||
*/
|
|
||||||
public static function add_pseudo_user_discovery( $array, $resource ) {
|
|
||||||
if ( $array ) {
|
|
||||||
return $array;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::get_profile( $resource );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the WebFinger profile.
|
* Get the WebFinger profile.
|
||||||
*
|
*
|
||||||
|
|
|
@ -229,7 +229,8 @@ class Post {
|
||||||
if ( $max_images > 0 ) {
|
if ( $max_images > 0 ) {
|
||||||
// first try to get images that are actually in the post content
|
// first try to get images that are actually in the post content
|
||||||
if ( site_supports_blocks() && \has_blocks( $this->wp_post->post_content ) ) {
|
if ( site_supports_blocks() && \has_blocks( $this->wp_post->post_content ) ) {
|
||||||
$image_ids = $this->get_block_image_ids( $max_images, $image_ids );
|
$block_image_ids = $this->get_block_image_ids( $max_images, $image_ids );
|
||||||
|
$image_ids = \array_merge( $image_ids, $block_image_ids );
|
||||||
} else {
|
} else {
|
||||||
// fallback to images attached to the post
|
// fallback to images attached to the post
|
||||||
$query = new \WP_Query(
|
$query = new \WP_Query(
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Activitypub\Integration;
|
namespace Activitypub\Integration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compatibility with the BuddyPress plugin
|
||||||
|
*
|
||||||
|
* @see https://buddypress.org/
|
||||||
|
*/
|
||||||
class Buddypress {
|
class Buddypress {
|
||||||
|
/**
|
||||||
|
* Initialize the class, registering WordPress hooks
|
||||||
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
\add_filter( 'activitypub_json_author_array', array( self::class, 'add_user_metadata' ), 11, 2 );
|
\add_filter( 'activitypub_json_author_array', array( self::class, 'add_user_metadata' ), 11, 2 );
|
||||||
}
|
}
|
||||||
|
|
49
integration/class-nodeinfo.php
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
namespace Activitypub\Integration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compatibility with the NodeInfo plugin
|
||||||
|
*
|
||||||
|
* @see https://wordpress.org/plugins/nodeinfo/
|
||||||
|
*/
|
||||||
|
class Nodeinfo {
|
||||||
|
/**
|
||||||
|
* Initialize the class, registering WordPress hooks
|
||||||
|
*/
|
||||||
|
public static function init() {
|
||||||
|
\add_filter( 'nodeinfo_data', array( self::class, 'add_nodeinfo_discovery' ), 10, 2 );
|
||||||
|
\add_filter( 'nodeinfo2_data', array( self::class, 'add_nodeinfo2_discovery' ), 10 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend NodeInfo data
|
||||||
|
*
|
||||||
|
* @param array $nodeinfo NodeInfo data
|
||||||
|
* @param string The NodeInfo Version
|
||||||
|
*
|
||||||
|
* @return array The extended array
|
||||||
|
*/
|
||||||
|
public static function add_nodeinfo_discovery( $nodeinfo, $version ) {
|
||||||
|
if ( $version >= '2.0' ) {
|
||||||
|
$nodeinfo['protocols'][] = 'activitypub';
|
||||||
|
} else {
|
||||||
|
$nodeinfo['protocols']['inbound'][] = 'activitypub';
|
||||||
|
$nodeinfo['protocols']['outbound'][] = 'activitypub';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $nodeinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend NodeInfo2 data
|
||||||
|
*
|
||||||
|
* @param array $nodeinfo NodeInfo2 data
|
||||||
|
*
|
||||||
|
* @return array The extended array
|
||||||
|
*/
|
||||||
|
public static function add_nodeinfo2_discovery( $nodeinfo ) {
|
||||||
|
$nodeinfo['protocols'][] = 'activitypub';
|
||||||
|
|
||||||
|
return $nodeinfo;
|
||||||
|
}
|
||||||
|
}
|
57
integration/class-webfinger.php
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
namespace Activitypub\Integration;
|
||||||
|
|
||||||
|
use Activitypub\Collection\Users as User_Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compatibility with the WebFinger plugin
|
||||||
|
*
|
||||||
|
* @see https://wordpress.org/plugins/webfinger/
|
||||||
|
*/
|
||||||
|
class Webfinger {
|
||||||
|
/**
|
||||||
|
* Initialize the class, registering WordPress hooks
|
||||||
|
*/
|
||||||
|
public static function init() {
|
||||||
|
\add_filter( 'webfinger_user_data', array( self::class, 'add_user_discovery' ), 10, 3 );
|
||||||
|
\add_filter( 'webfinger_data', array( self::class, 'add_pseudo_user_discovery' ), 99, 2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add WebFinger discovery links
|
||||||
|
*
|
||||||
|
* @param array $array the jrd array
|
||||||
|
* @param string $resource the WebFinger resource
|
||||||
|
* @param WP_User $user the WordPress user
|
||||||
|
*
|
||||||
|
* @return array the jrd array
|
||||||
|
*/
|
||||||
|
public static function add_user_discovery( $array, $resource, $user ) {
|
||||||
|
$user = User_Collection::get_by_id( $user->ID );
|
||||||
|
|
||||||
|
$array['links'][] = array(
|
||||||
|
'rel' => 'self',
|
||||||
|
'type' => 'application/activity+json',
|
||||||
|
'href' => $user->get_url(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add WebFinger discovery links
|
||||||
|
*
|
||||||
|
* @param array $array the jrd array
|
||||||
|
* @param string $resource the WebFinger resource
|
||||||
|
* @param WP_User $user the WordPress user
|
||||||
|
*
|
||||||
|
* @return array the jrd array
|
||||||
|
*/
|
||||||
|
public static function add_pseudo_user_discovery( $array, $resource ) {
|
||||||
|
if ( $array ) {
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::get_profile( $resource );
|
||||||
|
}
|
||||||
|
}
|
19
readme.txt
|
@ -3,7 +3,7 @@ Contributors: automattic, pfefferle, mediaformat, mattwiebe, akirk, jeherve, nur
|
||||||
Tags: OStatus, fediverse, activitypub, activitystream
|
Tags: OStatus, fediverse, activitypub, activitystream
|
||||||
Requires at least: 4.7
|
Requires at least: 4.7
|
||||||
Tested up to: 6.3
|
Tested up to: 6.3
|
||||||
Stable tag: 1.0.2
|
Stable tag: 1.0.5
|
||||||
Requires PHP: 5.6
|
Requires PHP: 5.6
|
||||||
License: MIT
|
License: MIT
|
||||||
License URI: http://opensource.org/licenses/MIT
|
License URI: http://opensource.org/licenses/MIT
|
||||||
|
@ -105,6 +105,23 @@ Where 'blog' is the path to the subdirectory at which your blog resides.
|
||||||
|
|
||||||
Project maintained on GitHub at [automattic/wordpress-activitypub](https://github.com/automattic/wordpress-activitypub).
|
Project maintained on GitHub at [automattic/wordpress-activitypub](https://github.com/automattic/wordpress-activitypub).
|
||||||
|
|
||||||
|
= 1.0.5 =
|
||||||
|
|
||||||
|
* Fixed: compatibility with WebFinger and NodeInfo plugin
|
||||||
|
|
||||||
|
= 1.0.4 =
|
||||||
|
|
||||||
|
* Fixed: Constants were not loaded early enough, resulting in a race condition
|
||||||
|
* Fixed: Featured image was ignored when using the block editor
|
||||||
|
|
||||||
|
= 1.0.3 =
|
||||||
|
|
||||||
|
* Fixed: compatibility with older WordPress/PHP versions
|
||||||
|
* Update: refactoring of the Plugin init process
|
||||||
|
* Update: better frontend UX and improved theme compat for blocks
|
||||||
|
* Compatibility: add a ACTIVITYPUB_DISABLE_REWRITES constant
|
||||||
|
* Compatibility: add pre-fetch hook to allow plugins to hang filters on
|
||||||
|
|
||||||
= 1.0.2 =
|
= 1.0.2 =
|
||||||
|
|
||||||
* Updated: improved hashtag visibility in default template
|
* Updated: improved hashtag visibility in default template
|
||||||
|
|