Merge branch 'master' into rewrite-followers

This commit is contained in:
Matthias Pfefferle 2023-04-28 17:38:30 +02:00 committed by GitHub
commit a673504d36
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 157 additions and 21 deletions

View file

@ -25,6 +25,7 @@ function init() {
\defined( 'ACTIVITYPUB_USERNAME_REGEXP' ) || \define( 'ACTIVITYPUB_USERNAME_REGEXP', '(?:([A-Za-z0-9_-]+)@((?:[A-Za-z0-9_-]+\.)+[A-Za-z]+))' );
\defined( 'ACTIVITYPUB_ALLOWED_HTML' ) || \define( 'ACTIVITYPUB_ALLOWED_HTML', '<strong><a><p><ul><ol><li><code><blockquote><pre><img>' );
\defined( 'ACTIVITYPUB_CUSTOM_POST_CONTENT' ) || \define( 'ACTIVITYPUB_CUSTOM_POST_CONTENT', "<p><strong>[ap_title]</strong></p>\n\n[ap_content]\n\n<p>[ap_hashtags]</p>\n\n<p>[ap_shortlink]</p>" );
\defined( 'ACTIVITYPUB_USER_DESCRIPTION_KEY' ) || \define( 'ACTIVITYPUB_USER_DESCRIPTION_KEY', 'activitypub_user_description' );
\define( 'ACTIVITYPUB_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
\define( 'ACTIVITYPUB_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
\define( 'ACTIVITYPUB_PLUGIN_FILE', plugin_dir_path( __FILE__ ) . '/' . basename( __FILE__ ) );

View file

@ -39,6 +39,9 @@ class Activitypub {
return $template;
}
// Ensure that edge caches know that this page can deliver both HTML and JSON.
header( 'Vary: Accept' );
// check if user can publish posts
if ( \is_author() && ! user_can( \get_the_author_meta( 'ID' ), 'publish_posts' ) ) {
return $template;

View file

@ -1,6 +1,8 @@
<?php
namespace Activitypub;
use Activitypub\Model\Post;
/**
* ActivityPub Admin Class
*
@ -15,6 +17,7 @@ class Admin {
\add_action( 'admin_init', array( self::class, 'register_settings' ) );
\add_action( 'admin_init', array( self::class, 'schedule_migration' ) );
\add_action( 'show_user_profile', array( self::class, 'add_profile' ) );
\add_action( 'personal_options_update', array( self::class, 'save_user_description' ) );
\add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_scripts' ) );
}
@ -51,9 +54,9 @@ class Admin {
switch ( $tab ) {
case 'settings':
\Activitypub\Model\Post::upgrade_post_content_template();
Post::upgrade_post_content_template();
\load_template( \dirname( __FILE__ ) . '/../templates/settings.php' );
\load_template( ACTIVITYPUB_PLUGIN_DIR . 'templates/settings.php' );
break;
case 'welcome':
default:
@ -61,7 +64,7 @@ class Admin {
add_thickbox();
wp_enqueue_script( 'updates' );
\load_template( \dirname( __FILE__ ) . '/../templates/welcome.php' );
\load_template( ACTIVITYPUB_PLUGIN_DIR . 'templates/welcome.php' );
break;
}
}
@ -70,7 +73,7 @@ class Admin {
* Load user settings page
*/
public static function followers_list_page() {
\load_template( \dirname( __FILE__ ) . '/../templates/followers-list.php' );
\load_template( ACTIVITYPUB_PLUGIN_DIR . 'templates/followers-list.php' );
}
/**
@ -152,7 +155,7 @@ class Admin {
}
public static function add_settings_help_tab() {
require_once \dirname( __FILE__ ) . '/help.php';
require_once ACTIVITYPUB_PLUGIN_DIR . 'includes/help.php';
}
public static function add_followers_list_help_tab() {
@ -160,10 +163,25 @@ class Admin {
}
public static function add_profile( $user ) {
?>
<h2 id="activitypub"><?php \esc_html_e( 'ActivityPub', 'activitypub' ); ?></h2>
<?php
\Activitypub\get_identifier_settings( $user->ID );
$description = get_user_meta( $user->ID, ACTIVITYPUB_USER_DESCRIPTION_KEY, true );
\load_template(
ACTIVITYPUB_PLUGIN_DIR . 'templates/user-settings.php',
true,
array(
'description' => $description,
)
);
}
public static function save_user_description( $user_id ) {
if ( isset( $_REQUEST['_apnonce'] ) && ! wp_verify_nonce( $_REQUEST['_apnonce'], 'activitypub-user-description' ) ) {
return false;
}
if ( ! current_user_can( 'edit_user', $user_id ) ) {
return false;
}
update_user_meta( $user_id, ACTIVITYPUB_USER_DESCRIPTION_KEY, sanitize_text_field( $_POST['activitypub-user-description'] ) );
}
public static function enqueue_scripts( $hook_suffix ) {

View file

@ -48,6 +48,12 @@ class Mention {
$the_content
);
$the_content = preg_replace_callback(
'#<img.*?[^>]+>#i',
$protect,
$the_content
);
$the_content = \preg_replace_callback( '/@' . ACTIVITYPUB_USERNAME_REGEXP . '/', array( self::class, 'replace_with_links' ), $the_content );
$the_content = str_replace( array_reverse( array_keys( $protected_tags ) ), array_reverse( array_values( $protected_tags ) ), $the_content );

View file

@ -197,3 +197,17 @@ function url_to_authorid( $url ) {
return 0;
}
/**
* Return the custom Activity Pub description, if set, or default author description.
*
* @param int $user_id The user ID.
* @return string
*/
function get_author_description( $user_id ) {
$description = get_user_meta( $user_id, ACTIVITYPUB_USER_DESCRIPTION_KEY, true );
if ( empty( $description ) ) {
$description = get_user_meta( $user_id, 'description', true );
}
return $description;
}

View file

@ -28,6 +28,13 @@ class Post {
*/
private $id;
/**
* The Object URL.
*
* @var string
*/
private $url;
/**
* The Object Summary.
*
@ -179,6 +186,7 @@ class Post {
$array = array(
'id' => $this->get_id(),
'url' => $this->get_url(),
'type' => $this->get_object_type(),
'published' => \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $post->post_date_gmt ) ),
'attributedTo' => \get_author_posts_url( $post->post_author ),
@ -207,13 +215,13 @@ class Post {
}
/**
* Returns the ID of an Activity Object
* Returns the URL of an Activity Object
*
* @return string
*/
public function get_id() {
if ( $this->id ) {
return $this->id;
public function get_url() {
if ( $this->url ) {
return $this->url;
}
$post = $this->post;
@ -224,11 +232,26 @@ class Post {
$permalink = \get_permalink( $post );
}
$this->id = $permalink;
$this->url = $permalink;
return $permalink;
}
/**
* Returns the ID of an Activity Object
*
* @return string
*/
public function get_id() {
if ( $this->id ) {
return $this->id;
}
$this->id = $this->get_url();
return $this->id;
}
/**
* Returns a list of Image Attachments
*
@ -283,7 +306,32 @@ class Post {
// get URLs for each image
foreach ( $image_ids as $id ) {
$alt = \get_post_meta( $id, '_wp_attachment_image_alt', true );
/**
* If you use the Jetpack plugin and its Image CDN, aka Photon,
* the image strings returned will use the Photon URL.
* We don't want that since Fediverse instances already do caching on their end.
* Let the CDN only be used for visitors of the site.
*
* Old versions of Jetpack used the Jetpack_Photon class to do this.
* New versions use the Image_CDN class.
* Let's handle both.
*/
if ( \class_exists( '\Automattic\Jetpack\Image_CDN\Image_CDN' ) ) {
\remove_filter( 'image_downsize', array( \Automattic\Jetpack\Image_CDN\Image_CDN::instance(), 'filter_image_downsize' ) );
} elseif ( \class_exists( 'Jetpack_Photon' ) ) {
\remove_filter( 'image_downsize', array( \Jetpack_Photon::instance(), 'filter_image_downsize' ) );
}
$thumbnail = \wp_get_attachment_image_src( $id, 'full' );
// Re-enable Photon now that the image URL has been built.
if ( \class_exists( '\Automattic\Jetpack\Image_CDN\Image_CDN' ) ) {
\add_filter( 'image_downsize', array( \Automattic\Jetpack\Image_CDN\Image_CDN::instance(), 'filter_image_downsize' ), 10, 3 );
} elseif ( \class_exists( 'Jetpack_Photon' ) ) {
\add_filter( 'image_downsize', array( \Jetpack_Photon::instance(), 'filter_image_downsize' ), 10, 3 );
}
$mimetype = \get_post_mime_type( $id );
if ( $thumbnail ) {

View file

@ -75,13 +75,24 @@ class Nodeinfo {
'version' => \get_bloginfo( 'version' ),
);
$users = \count_users();
$users = \get_users(
array(
'capability__in' => array( 'publish_posts' ),
)
);
if ( is_array( $users ) ) {
$users = count( $users );
} else {
$users = 1;
}
$posts = \wp_count_posts();
$comments = \wp_count_comments();
$nodeinfo['usage'] = array(
'users' => array(
'total' => (int) $users['total_users'],
'total' => $users,
),
'localPosts' => (int) $posts->publish,
'localComments' => (int) $comments->approved,

View file

@ -54,15 +54,16 @@ class Webfinger {
$resource = \str_replace( 'acct:', '', $resource );
$resource_identifier = \substr( $resource, 0, \strrpos( $resource, '@' ) );
$resource_host = \substr( \strrchr( $resource, '@' ), 1 );
$resource_host = \str_replace( 'www.', '', \substr( \strrchr( $resource, '@' ), 1 ) );
$blog_host = \str_replace( 'www.', '', \wp_parse_url( \home_url( '/' ), \PHP_URL_HOST ) );
if ( \wp_parse_url( \home_url( '/' ), \PHP_URL_HOST ) !== $resource_host ) {
if ( $blog_host !== $resource_host ) {
return new WP_Error( 'activitypub_wrong_host', \__( 'Resource host does not match blog host', 'activitypub' ), array( 'status' => 404 ) );
}
$user = \get_user_by( 'login', \esc_sql( $resource_identifier ) );
if ( ! $user || ! user_can( $user, 'publish_posts' ) ) {
if ( ! $user || ! \user_can( $user, 'publish_posts' ) ) {
return new WP_Error( 'activitypub_user_not_found', \__( 'User not found', 'activitypub' ), array( 'status' => 404 ) );
}

View file

@ -2,7 +2,7 @@
Contributors: pfefferle, mediaformat, akirk, automattic
Tags: OStatus, fediverse, activitypub, activitystream
Requires at least: 4.7
Tested up to: 6.1
Tested up to: 6.2
Stable tag: 0.17.0
Requires PHP: 5.6
License: MIT
@ -113,6 +113,10 @@ Where 'blog' is the path to the subdirectory at which your blog resides.
Project maintained on GitHub at [pfefferle/wordpress-activitypub](https://github.com/pfefferle/wordpress-activitypub).
= Next =
* Compatibility: indicate that the plugin is compatible and has been tested with the latest version of WordPress, 6.2.
= 0.17.0 =
* Fix type-selector

View file

@ -8,7 +8,7 @@ $json->id = \get_author_posts_url( $author_id );
$json->type = 'Person';
$json->name = \get_the_author_meta( 'display_name', $author_id );
$json->summary = \html_entity_decode(
\get_the_author_meta( 'description', $author_id ),
\Activitypub\get_author_description( $author_id ),
\ENT_QUOTES,
'UTF-8'
);

View file

@ -0,0 +1,29 @@
<h2 id="activitypub"><?php \esc_html_e( 'ActivityPub', 'activitypub' ); ?></h2>
<table class="form-table">
<tbody>
<tr>
<th scope="row">
<label><?php \esc_html_e( 'Profile identifier', 'activitypub' ); ?></label>
</th>
<td>
<p>
<code><?php echo \esc_html( \Activitypub\get_webfinger_resource( \get_current_user_id() ) ); ?></code> or
<code><?php echo \esc_url( \get_author_posts_url( \get_current_user_id() ) ); ?></code>
</p>
<?php // translators: the webfinger resource ?>
<p class="description"><?php \printf( \esc_html__( 'Try to follow "@%s" by searching for it on Mastodon,Friendica & Co.', 'activitypub' ), \esc_html( \Activitypub\get_webfinger_resource( \get_current_user_id() ) ) ); ?></p>
</td>
</tr>
<tr class="activitypub-user-description-wrap">
<th>
<label for="activitypub-user-description"><?php \esc_html_e( 'Biography', 'activitypub' ); ?></label>
</th>
<td>
<textarea name="activitypub-user-description" id="activitypub-user-description" rows="5" cols="30" placeholder="<?php echo \esc_html( get_user_meta( \get_current_user_id(), 'description', true ) ); ?>"><?php echo \esc_html( $args['description'] ); ?></textarea>
<p class="description"><?php \esc_html_e( 'If you wish to use different biographical info for the fediverse, enter your alternate bio here.', 'activitypub' ); ?></p>
</td>
<?php wp_nonce_field( 'activitypub-user-description', '_apnonce' ); ?>
</tr>
</tbody>
</table>

View file

@ -31,6 +31,7 @@ ENDPRE;
array( 'hallo <a rel="mention" class="u-url mention" href="https://notiz.blog/author/matthias-pfefferle/">@<span>pfefferle</span>@notiz.blog</a> test', 'hallo <a rel="mention" class="u-url mention" href="https://notiz.blog/author/matthias-pfefferle/">@<span>pfefferle</span>@notiz.blog</a> test' ),
array( 'hallo <a rel="mention" class="u-url mention" href="https://notiz.blog/author/matthias-pfefferle/">@pfefferle@notiz.blog</a> test', 'hallo <a rel="mention" class="u-url mention" href="https://notiz.blog/author/matthias-pfefferle/">@pfefferle@notiz.blog</a> test' ),
array( 'hallo <a rel="mention" class="u-url mention" href="https://notiz.blog/@pfefferle/">@pfefferle@notiz.blog</a> test', 'hallo <a rel="mention" class="u-url mention" href="https://notiz.blog/@pfefferle/">@pfefferle@notiz.blog</a> test' ),
array( 'hallo <img src="abc" alt="https://notiz.blog/@pfefferle/" title="@pfefferle@notiz.blog"/> test', 'hallo <img src="abc" alt="https://notiz.blog/@pfefferle/" title="@pfefferle@notiz.blog"/> test' ),
array( $code, $code ),
array( $pre, $pre ),
);