updated plugin Simple Local Avatars version 2.7.8

This commit is contained in:
KawaiiPunk 2024-05-09 15:26:55 +00:00 committed by Gitium
parent 496ccfac3d
commit 62f3186aef
18 changed files with 295 additions and 80 deletions

View File

@ -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: 2.3.0 * Version: 2.3.1
* Author: Matthias Pfefferle & Automattic * Author: Matthias Pfefferle & Automattic
* Author URI: https://automattic.com/ * Author URI: https://automattic.com/
* License: MIT * License: MIT
@ -21,7 +21,7 @@ use function Activitypub\site_supports_blocks;
require_once __DIR__ . '/includes/compat.php'; require_once __DIR__ . '/includes/compat.php';
require_once __DIR__ . '/includes/functions.php'; require_once __DIR__ . '/includes/functions.php';
\define( 'ACTIVITYPUB_PLUGIN_VERSION', '2.3.0' ); \define( 'ACTIVITYPUB_PLUGIN_VERSION', '2.3.1' );
/** /**
* Initialize the plugin constants. * Initialize the plugin constants.

View File

@ -98,6 +98,11 @@ class Activity_Dispatcher {
return; return;
} }
// do not announce replies
if ( $wp_object instanceof WP_Comment ) {
return;
}
$transformer = Factory::get_transformer( $wp_object ); $transformer = Factory::get_transformer( $wp_object );
$transformer->change_wp_user_id( Users::BLOG_USER_ID ); $transformer->change_wp_user_id( Users::BLOG_USER_ID );

View File

@ -276,7 +276,7 @@ class Comment {
} }
// check for local comment // check for local comment
if ( \wp_parse_url( \site_url(), \PHP_URL_HOST ) === \wp_parse_url( $url, \PHP_URL_HOST ) ) { if ( \wp_parse_url( \home_url(), \PHP_URL_HOST ) === \wp_parse_url( $url, \PHP_URL_HOST ) ) {
$query = \wp_parse_url( $url, \PHP_URL_QUERY ); $query = \wp_parse_url( $url, \PHP_URL_QUERY );
if ( $query ) { if ( $query ) {
@ -379,12 +379,7 @@ class Comment {
} }
// generate URI based on comment ID // generate URI based on comment ID
return \add_query_arg( return \add_query_arg( 'c', $comment->comment_ID, \home_url() );
array(
'c' => $comment->comment_ID,
),
\trailingslashit( site_url() )
);
} }
/** /**

View File

@ -27,7 +27,7 @@ class Health_Check {
} }
public static function add_tests( $tests ) { public static function add_tests( $tests ) {
if ( ! is_user_type_disabled( 'user' ) ) { if ( ! is_user_disabled( get_current_user_id() ) ) {
$tests['direct']['activitypub_test_author_url'] = array( $tests['direct']['activitypub_test_author_url'] = array(
'label' => \__( 'Author URL test', 'activitypub' ), 'label' => \__( 'Author URL test', 'activitypub' ),
'test' => array( self::class, 'test_author_url' ), 'test' => array( self::class, 'test_author_url' ),

View File

@ -67,13 +67,25 @@ class Http {
* Send a GET Request with the needed HTTP Headers * Send a GET Request with the needed HTTP Headers
* *
* @param string $url The URL endpoint * @param string $url The URL endpoint
* @param int $user_id The WordPress User-ID * @param bool|int $cached If the result should be cached, or its duration. Default: 1hr.
* *
* @return array|WP_Error The GET Response or an WP_ERROR * @return array|WP_Error The GET Response or an WP_ERROR
*/ */
public static function get( $url ) { public static function get( $url, $cached = false ) {
\do_action( 'activitypub_pre_http_get', $url ); \do_action( 'activitypub_pre_http_get', $url );
if ( $cached ) {
$transient_key = self::generate_cache_key( $url );
$response = \get_transient( $transient_key );
if ( $response ) {
\do_action( 'activitypub_safe_remote_get_response', $response, $url );
return $response;
}
}
$date = \gmdate( 'D, d M Y H:i:s T' ); $date = \gmdate( 'D, d M Y H:i:s T' );
$signature = Signature::generate_signature( Users::APPLICATION_USER_ID, 'get', $url, $date ); $signature = Signature::generate_signature( Users::APPLICATION_USER_ID, 'get', $url, $date );
@ -108,6 +120,14 @@ class Http {
\do_action( 'activitypub_safe_remote_get_response', $response, $url ); \do_action( 'activitypub_safe_remote_get_response', $response, $url );
if ( $cached ) {
$cache_duration = $cached;
if ( ! is_int( $cache_duration ) ) {
$cache_duration = HOUR_IN_SECONDS;
}
\set_transient( $transient_key, $response, $cache_duration );
}
return $response; return $response;
} }
@ -130,4 +150,8 @@ class Http {
return false; return false;
} }
public static function generate_cache_key( $url ) {
return 'activitypub_http_' . \md5( $url );
}
} }

View File

@ -253,6 +253,11 @@ class Scheduler {
} elseif ( empty( $meta ) || ! is_array( $meta ) || is_wp_error( $meta ) ) { } elseif ( empty( $meta ) || ! is_array( $meta ) || is_wp_error( $meta ) ) {
if ( $follower->count_errors() >= 5 ) { if ( $follower->count_errors() >= 5 ) {
$follower->delete(); $follower->delete();
\wp_schedule_single_event(
\time(),
'activitypub_delete_actor_interactions',
array( $follower->get_id() )
);
} else { } else {
Followers::add_error( $follower->get__id(), $meta ); Followers::add_error( $follower->get__id(), $meta );
} }

View File

@ -379,10 +379,10 @@ class Signature {
if ( \preg_match( '/keyId="(.*?)"/ism', $signature, $matches ) ) { if ( \preg_match( '/keyId="(.*?)"/ism', $signature, $matches ) ) {
$parsed_header['keyId'] = trim( $matches[1] ); $parsed_header['keyId'] = trim( $matches[1] );
} }
if ( \preg_match( '/created=([0-9]*)/ism', $signature, $matches ) ) { if ( \preg_match( '/created=["|\']*([0-9]*)["|\']*/ism', $signature, $matches ) ) {
$parsed_header['(created)'] = trim( $matches[1] ); $parsed_header['(created)'] = trim( $matches[1] );
} }
if ( \preg_match( '/expires=([0-9]*)/ism', $signature, $matches ) ) { if ( \preg_match( '/expires=["|\']*([0-9]*)["|\']*/ism', $signature, $matches ) ) {
$parsed_header['(expires)'] = trim( $matches[1] ); $parsed_header['(expires)'] = trim( $matches[1] );
} }
if ( \preg_match( '/algorithm="(.*?)"/ism', $signature, $matches ) ) { if ( \preg_match( '/algorithm="(.*?)"/ism', $signature, $matches ) ) {
@ -434,12 +434,22 @@ class Signature {
// created in future // created in future
return false; return false;
} }
if ( ! array_key_exists( '(created)', $headers ) ) {
$signed_data .= $header . ': ' . $signature_block['(created)'] . "\n";
continue;
}
} }
if ( '(expires)' === $header ) { if ( '(expires)' === $header ) {
if ( ! empty( $signature_block['(expires)'] ) && \intval( $signature_block['(expires)'] ) < \time() ) { if ( ! empty( $signature_block['(expires)'] ) && \intval( $signature_block['(expires)'] ) < \time() ) {
// expired in past // expired in past
return false; return false;
} }
if ( ! array_key_exists( '(expires)', $headers ) ) {
$signed_data .= $header . ': ' . $signature_block['(expires)'] . "\n";
continue;
}
} }
if ( 'date' === $header ) { if ( 'date' === $header ) {
// allow a bit of leeway for misconfigured clocks. // allow a bit of leeway for misconfigured clocks.

View File

@ -4,6 +4,7 @@ namespace Activitypub\Collection;
use WP_Error; use WP_Error;
use WP_Comment_Query; use WP_Comment_Query;
use function Activitypub\object_to_uri;
use function Activitypub\url_to_commentid; use function Activitypub\url_to_commentid;
use function Activitypub\object_id_to_comment; use function Activitypub\object_id_to_comment;
use function Activitypub\get_remote_metadata_by_actor; use function Activitypub\get_remote_metadata_by_actor;
@ -46,7 +47,8 @@ class Interactions {
return false; return false;
} }
$meta = get_remote_metadata_by_actor( $activity['actor'] ); $actor = object_to_uri( $activity['actor'] );
$meta = get_remote_metadata_by_actor( $actor );
if ( ! $meta || \is_wp_error( $meta ) ) { if ( ! $meta || \is_wp_error( $meta ) ) {
return false; return false;

View File

@ -7,6 +7,7 @@ use Activitypub\Model\User;
use Activitypub\Model\Blog_User; use Activitypub\Model\Blog_User;
use Activitypub\Model\Application_User; use Activitypub\Model\Application_User;
use function Activitypub\object_to_uri;
use function Activitypub\url_to_authorid; use function Activitypub\url_to_authorid;
use function Activitypub\is_user_disabled; use function Activitypub\is_user_disabled;
@ -136,6 +137,8 @@ class Users {
* @return \Acitvitypub\Model\User The User. * @return \Acitvitypub\Model\User The User.
*/ */
public static function get_by_resource( $resource ) { public static function get_by_resource( $resource ) {
$resource = object_to_uri( $resource );
$scheme = 'acct'; $scheme = 'acct';
$match = array(); $match = array();
// try to extract the scheme and the host // try to extract the scheme and the host

View File

@ -52,6 +52,17 @@ function get_remote_metadata_by_actor( $actor, $cached = true ) {
if ( $pre ) { if ( $pre ) {
return $pre; return $pre;
} }
if ( is_array( $actor ) ) {
if ( array_key_exists( 'id', $actor ) ) {
$actor = $actor['id'];
} elseif ( array_key_exists( 'url', $actor ) ) {
$actor = $actor['url'];
} else {
return new WP_Error( 'activitypub_no_valid_actor_identifier', \__( 'The "actor" identifier is not valid', 'activitypub' ), array( 'status' => 404, 'actor' => $actor ) );
}
}
if ( preg_match( '/^@?' . ACTIVITYPUB_USERNAME_REGEXP . '$/i', $actor ) ) { if ( preg_match( '/^@?' . ACTIVITYPUB_USERNAME_REGEXP . '$/i', $actor ) ) {
$actor = Webfinger::resolve( $actor ); $actor = Webfinger::resolve( $actor );
} }
@ -134,7 +145,7 @@ function url_to_authorid( $url ) {
global $wp_rewrite; global $wp_rewrite;
// check if url hase the same host // check if url hase the same host
if ( \wp_parse_url( \site_url(), \PHP_URL_HOST ) !== \wp_parse_url( $url, \PHP_URL_HOST ) ) { if ( \wp_parse_url( \home_url(), \PHP_URL_HOST ) !== \wp_parse_url( $url, \PHP_URL_HOST ) ) {
return 0; return 0;
} }

View File

@ -4,6 +4,8 @@ namespace Activitypub\Handler;
use Activitypub\Collection\Users; use Activitypub\Collection\Users;
use Activitypub\Collection\Followers; use Activitypub\Collection\Followers;
use function Activitypub\object_to_uri;
/** /**
* Handle Undo requests * Handle Undo requests
*/ */
@ -28,10 +30,10 @@ class Undo {
if ( if (
isset( $activity['object']['type'] ) && isset( $activity['object']['type'] ) &&
'Follow' === $activity['object']['type'] && 'Follow' === $activity['object']['type'] &&
isset( $activity['object']['object'] ) && isset( $activity['object']['object'] )
filter_var( $activity['object']['object'], FILTER_VALIDATE_URL )
) { ) {
$user = Users::get_by_resource( $activity['object']['object'] ); $user_id = object_to_uri( $activity['object']['object'] );
$user = Users::get_by_resource( $user_id );
if ( ! $user || is_wp_error( $user ) ) { if ( ! $user || is_wp_error( $user ) ) {
// If we can not find a user, // If we can not find a user,
@ -40,8 +42,9 @@ class Undo {
} }
$user_id = $user->get__id(); $user_id = $user->get__id();
$actor = object_to_uri( $activity['actor'] );
Followers::remove_follower( $user_id, $activity['actor'] ); Followers::remove_follower( $user_id, $actor );
} }
} }
} }

View File

@ -343,10 +343,10 @@ class Post extends Base {
case 'core/cover': case 'core/cover':
if ( ! empty( $block['attrs']['id'] ) ) { if ( ! empty( $block['attrs']['id'] ) ) {
$alt = ''; $alt = '';
$check = preg_match( '/<img.*?alt=[\"\'](.*?)[\"\'].*>/i', $block['innerHTML'], $match ); $check = preg_match( '/<img.*?alt\s*=\s*([\"\'])(.*?)\1.*>/i', $block['innerHTML'], $match );
if ( $check ) { if ( $check ) {
$alt = $match[1]; $alt = $match[2];
} }
$media['image'][] = array( $media['image'][] = array(
@ -451,11 +451,11 @@ class Post extends Base {
); );
if ( ! empty( $media['alt'] ) ) { if ( ! empty( $media['alt'] ) ) {
$image['name'] = \esc_attr( $media['alt'] ); $image['name'] = \wp_strip_all_tags( \html_entity_decode( $media['alt'] ) );
} else { } else {
$alt = \get_post_meta( $id, '_wp_attachment_image_alt', true ); $alt = \get_post_meta( $id, '_wp_attachment_image_alt', true );
if ( $alt ) { if ( $alt ) {
$image['name'] = \esc_attr( $alt ); $image['name'] = \wp_strip_all_tags( \html_entity_decode( $alt ) );
} }
} }

View File

@ -3,10 +3,14 @@ namespace Activitypub\Integration;
use DateTime; use DateTime;
use Activitypub\Webfinger as Webfinger_Util; use Activitypub\Webfinger as Webfinger_Util;
use Activitypub\Http;
use Activitypub\Collection\Users; use Activitypub\Collection\Users;
use Activitypub\Collection\Followers; use Activitypub\Collection\Followers;
use Activitypub\Integration\Nodeinfo; use Activitypub\Integration\Nodeinfo;
use Enable_Mastodon_Apps\Mastodon_API;
use Enable_Mastodon_Apps\Entity\Account; use Enable_Mastodon_Apps\Entity\Account;
use Enable_Mastodon_Apps\Entity\Status;
use Enable_Mastodon_Apps\Entity\Media_Attachment;
use function Activitypub\get_remote_metadata_by_actor; use function Activitypub\get_remote_metadata_by_actor;
@ -23,9 +27,11 @@ class Enable_Mastodon_Apps {
*/ */
public static function init() { public static function init() {
\add_filter( 'mastodon_api_account_followers', array( self::class, 'api_account_followers' ), 10, 2 ); \add_filter( 'mastodon_api_account_followers', array( self::class, 'api_account_followers' ), 10, 2 );
\add_filter( 'mastodon_api_account', array( self::class, 'api_account' ), 20, 2 ); \add_filter( 'mastodon_api_account', array( self::class, 'api_account_add_followers' ), 20, 2 );
\add_filter( 'mastodon_api_account', array( self::class, 'api_account_external' ), 10, 2 ); \add_filter( 'mastodon_api_account', array( self::class, 'api_account_external' ), 10, 2 );
\add_filter( 'mastodon_api_search', array( self::class, 'api_search' ), 40, 2 ); \add_filter( 'mastodon_api_search', array( self::class, 'api_search' ), 40, 2 );
\add_filter( 'mastodon_api_get_posts_query_args', array( self::class, 'api_get_posts_query_args' ) );
\add_filter( 'mastodon_api_statuses', array( self::class, 'api_statuses_external' ), 10, 2 );
} }
/** /**
@ -95,8 +101,8 @@ class Enable_Mastodon_Apps {
* *
* @return Enable_Mastodon_Apps\Entity\Account The filtered Account * @return Enable_Mastodon_Apps\Entity\Account The filtered Account
*/ */
public static function api_account( $account, $user_id ) { public static function api_account_add_followers( $account, $user_id ) {
if ( ! $account instanceof Account ) { if ( ! $account instanceof Account || ! is_numeric( $user_id ) ) {
return $account; return $account;
} }
@ -121,8 +127,9 @@ class Enable_Mastodon_Apps {
} }
} }
$account->acct = $user->get_webfinger(); $account->acct = $user->get_preferred_username();
$account->note = $user->get_summary(); $account->note = $user->get_summary();
$account->followers_count = Followers::count_followers( $user_id ); $account->followers_count = Followers::count_followers( $user_id );
return $account; return $account;
} }
@ -136,34 +143,47 @@ class Enable_Mastodon_Apps {
* @return Enable_Mastodon_Apps\Entity\Account The filtered Account * @return Enable_Mastodon_Apps\Entity\Account The filtered Account
*/ */
public static function api_account_external( $user_data, $user_id ) { public static function api_account_external( $user_data, $user_id ) {
if ( ! preg_match( '/^' . ACTIVITYPUB_USERNAME_REGEXP . '$/', $user_id ) ) { if ( $user_data || is_numeric( $user_id ) ) {
// Only augment.
return $user_data; return $user_data;
} }
$uri = Webfinger_Util::resolve( $user_id ); $uri = Webfinger_Util::resolve( $user_id );
if ( ! $uri ) { if ( ! $uri || is_wp_error( $uri ) ) {
return $user_data; return $user_data;
} }
$acct = Webfinger_Util::uri_to_acct( $uri ); $account = self::get_account_for_actor( $uri );
if ( $account ) {
return $account;
}
return $user_data;
}
private static function get_account_for_actor( $uri ) {
if ( ! is_string( $uri ) ) {
return null;
}
$data = get_remote_metadata_by_actor( $uri ); $data = get_remote_metadata_by_actor( $uri );
if ( ! $data || is_wp_error( $data ) ) { if ( ! $data || is_wp_error( $data ) ) {
return $user_data; return null;
} }
if ( $user_data instanceof Account ) {
$account = $user_data;
} else {
$account = new Account(); $account = new Account();
$acct = Webfinger_Util::uri_to_acct( $uri );
if ( str_starts_with( $acct, 'acct:' ) ) {
$acct = substr( $acct, 5 );
} }
$account->id = strval( $user_id ); $account->id = $acct;
$account->username = $acct; $account->username = $acct;
$account->acct = $acct; $account->acct = $acct;
$account->display_name = $data['name']; $account->display_name = $data['name'];
$account->url = $uri; $account->url = $uri;
if ( ! empty( $data['summary'] ) ) { if ( ! empty( $data['summary'] ) ) {
$account->note = $data['summary']; $account->note = $data['summary'];
} }
@ -178,8 +198,8 @@ class Enable_Mastodon_Apps {
} }
if ( isset( $data['image'] ) ) { if ( isset( $data['image'] ) ) {
$account->header = $data['image']; $account->header = $data['image']['url'];
$account->header_static = $data['image']; $account->header_static = $data['image']['url'];
} }
$account->created_at = new DateTime( $data['published'] ); $account->created_at = new DateTime( $data['published'] );
@ -233,4 +253,114 @@ class Enable_Mastodon_Apps {
return $search_data; return $search_data;
} }
public function api_get_posts_query_args( $args ) {
if ( isset( $args['author'] ) && is_string( $args['author'] ) ) {
$uri = Webfinger_Util::resolve( $args['author'] );
if ( $uri && ! is_wp_error( $uri ) ) {
$args['activitypub'] = $uri;
unset( $args['author'] );
}
}
return $args;
}
public static function api_statuses_external( $statuses, $args ) {
if ( ! isset( $args['activitypub'] ) ) {
return $statuses;
}
$data = get_remote_metadata_by_actor( $args['activitypub'] );
if ( ! $data || is_wp_error( $data ) || ! isset( $data['outbox'] ) ) {
return $statuses;
}
$response = Http::get( $data['outbox'], true );
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) {
return $statuses;
}
$outbox = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! $outbox || is_wp_error( $outbox ) || ! isset( $outbox['first'] ) ) {
return $statuses;
}
$account = self::get_account_for_actor( $args['activitypub'] );
if ( ! $account ) {
return $statuses;
}
$response = Http::get( $outbox['first'], true );
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) {
return $statuses;
}
$posts = json_decode( wp_remote_retrieve_body( $response ), true );
$activitypub_statuses = array_map(
function ( $item ) use ( $account ) {
$object = $item['object'];
if ( ! isset( $object['type'] ) || 'Note' !== $object['type'] ) {
return null;
}
$status = new Status();
$status->id = Mastodon_API::remap_url( $object['id'] );
$status->created_at = new DateTime( $object['published'] );
$status->content = $object['content'];
$status->account = $account;
if ( ! empty( $object['inReplyTo'] ) ) {
$status->in_reply_to_id = $object['inReplyTo'];
}
if ( ! empty( $object['visibility'] ) ) {
$status->visibility = $object['visibility'];
}
$status->uri = $object['url'];
if ( ! empty( $object['attachment'] ) ) {
$status->media_attachments = array_map(
function ( $attachment ) {
$default_attachment = array(
'url' => null,
'mediaType' => null,
'name' => null,
'width' => 0,
'height' => 0,
'blurhash' => null,
);
$attachment = array_merge( $default_attachment, $attachment );
$media_attachment = new Media_Attachment();
$media_attachment->id = Mastodon_API::remap_url( $attachment['url'], $attachment );
$media_attachment->type = strtok( $attachment['mediaType'], '/' );
$media_attachment->url = $attachment['url'];
$media_attachment->preview_url = $attachment['url'];
$media_attachment->description = $attachment['name'];
$media_attachment->blurhash = $attachment['blurhash'];
$media_attachment->meta = array(
'original' => array(
'width' => $attachment['width'],
'height' => $attachment['height'],
'size' => $attachment['width'] . 'x' . $attachment['height'],
'aspect' => $attachment['width'] / $attachment['height'],
),
);
return $media_attachment;
},
$object['attachment']
);
}
return $status;
},
$posts['orderedItems']
);
return $activitypub_statuses;
}
} }

View File

@ -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: 5.5 Requires at least: 5.5
Tested up to: 6.5 Tested up to: 6.5
Stable tag: 2.3.0 Stable tag: 2.3.1
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
@ -133,6 +133,17 @@ For reasons of data protection, it is not possible to see the followers of other
== Changelog == == Changelog ==
= 2.3.1 =
* Added: Enable Mastodon Apps: Add remote outbox fetching
* Added: Help texts
* Fixed: Compatibility issues with Discourse
* Fixed: Do not announce replies
* Fixed: Also delete interactions with deleted person
* Fixed: Check Author-URL only if user is enabled for ActivityPub
* Fixed: Generate comment IDs for federation from home_url
* Removed: Beta label from the #Hashtag settings
= 2.3.0 = = 2.3.0 =
* Added: Mark links as "unhandled-link" and "status-link", for a better UX in the Mastodon App * Added: Mark links as "unhandled-link" and "status-link", for a better UX in the Mastodon App
@ -152,13 +163,6 @@ For reasons of data protection, it is not possible to see the followers of other
* Changed: Remote Reply: limit enqueue to when needed * Changed: Remote Reply: limit enqueue to when needed
* Changed: Abstract shared Dialog code * Changed: Abstract shared Dialog code
= 2.2.0 =
* Added: Remote-Reply lightbox
* Added: Support `application/ld+json` mime-type with AP profile in WebFinger
* Fixed: Prevent scheduler overload
See full Changelog on [GitHub](https://github.com/Automattic/wordpress-activitypub/blob/master/CHANGELOG.md). See full Changelog on [GitHub](https://github.com/Automattic/wordpress-activitypub/blob/master/CHANGELOG.md).
== Upgrade Notice == == Upgrade Notice ==

View File

@ -30,7 +30,10 @@
</label> </label>
</p> </p>
<p class="description"> <p class="description">
<?php echo \wp_kses( \__( 'Every author on this blog (with the <code>publish_posts</code> capability) gets their own ActivityPub profile.', 'activitypub' ), array( 'code' => array() ) ); ?> <?php echo \wp_kses( \__( 'Every author on this blog (with the <code>activitypub</code> capability) gets their own ActivityPub profile.', 'activitypub' ), array( 'code' => array() ) ); ?>
<?php // translators: %s is a URL. ?>
<strong><?php echo \wp_kses( sprintf( \__( 'You can add/remove the capability in the <a href="%s">user settings.</a>', 'activitypub' ), admin_url( '/users.php' ) ), array( 'a' => array( 'href' => array() ) ) ); ?></strong>
<?php echo \wp_kses( \__( 'Select all the users you want to update, choose the method from the drop-down list and click on the "Apply" button.', 'activitypub' ), array( 'code' => array() ) ); ?>
</p> </p>
<p> <p>
<label> <label>
@ -218,11 +221,11 @@
</tr> </tr>
<tr> <tr>
<th scope="row"> <th scope="row">
<?php \esc_html_e( 'Hashtags (beta)', 'activitypub' ); ?> <?php \esc_html_e( 'Hashtags', 'activitypub' ); ?>
</th> </th>
<td> <td>
<p> <p>
<label><input type="checkbox" name="activitypub_use_hashtags" id="activitypub_use_hashtags" value="1" <?php echo \checked( '1', \get_option( 'activitypub_use_hashtags', '1' ) ); ?> /> <?php echo wp_kses( \__( 'Add hashtags in the content as native tags and replace the <code>#tag</code> with the tag link. <strong>This feature is experimental! Please disable it, if you find any HTML or CSS errors.</strong>', 'activitypub' ), 'default' ); ?></label> <label><input type="checkbox" name="activitypub_use_hashtags" id="activitypub_use_hashtags" value="1" <?php echo \checked( '1', \get_option( 'activitypub_use_hashtags', '1' ) ); ?> /> <?php echo wp_kses( \__( 'Add hashtags in the content as native tags and replace the <code>#tag</code> with the tag link.', 'activitypub' ), 'default' ); ?></label>
</p> </p>
</td> </td>
</tr> </tr>

View File

@ -275,7 +275,7 @@ class Simple_Local_Avatars {
} }
// Local only mode // Local only mode
if ( ! $simple_local_avatar_url && ! empty( $this->options['only'] ) ) { if ( ! $simple_local_avatar_url ) {
$args['url'] = $this->get_default_avatar_url( $args['size'] ); $args['url'] = $this->get_default_avatar_url( $args['size'] );
} }
@ -344,8 +344,11 @@ class Simple_Local_Avatars {
// check rating // check rating
$avatar_rating = get_user_meta( $user_id, $this->rating_key, true ); $avatar_rating = get_user_meta( $user_id, $this->rating_key, true );
$site_rating = get_option( 'avatar_rating' ); $site_rating = get_option( 'avatar_rating' );
$all_avatar_ratings = ! empty( $this->avatar_ratings ) && is_array( $this->avatar_ratings )
? $this->avatar_ratings
: array();
if ( ! empty( $avatar_rating ) && 'G' !== $avatar_rating && $site_rating ) { if ( ! empty( $avatar_rating ) && 'G' !== $avatar_rating && $site_rating ) {
$ratings = array_keys( $this->avatar_ratings ); $ratings = array_keys( $all_avatar_ratings );
$site_rating_weight = array_search( $site_rating, $ratings, true ); $site_rating_weight = array_search( $site_rating, $ratings, true );
$avatar_rating_weight = array_search( $avatar_rating, $ratings, true ); $avatar_rating_weight = array_search( $avatar_rating, $ratings, true );
if ( false !== $avatar_rating_weight && $avatar_rating_weight > $site_rating_weight ) { if ( false !== $avatar_rating_weight && $avatar_rating_weight > $site_rating_weight ) {
@ -910,7 +913,7 @@ class Simple_Local_Avatars {
<div id="simple-local-avatar-photo" class="image-container" style="width: 100px; height: 100px; display: flex; align-items: center; justify-content: center; flex-direction: column;"> <div id="simple-local-avatar-photo" class="image-container" style="width: 100px; height: 100px; display: flex; align-items: center; justify-content: center; flex-direction: column;">
<?php <?php
add_filter( 'pre_option_avatar_rating', '__return_empty_string' ); // ignore ratings here add_filter( 'pre_option_avatar_rating', '__return_empty_string' ); // ignore ratings here
echo wp_kses_post( get_simple_local_avatar( $profileuser->ID ) ); echo get_simple_local_avatar( $profileuser->ID );
remove_filter( 'pre_option_avatar_rating', '__return_empty_string' ); remove_filter( 'pre_option_avatar_rating', '__return_empty_string' );
?> ?>
<span class="spinner" id="simple-local-avatar-spinner"></span> <span class="spinner" id="simple-local-avatar-spinner"></span>
@ -1042,7 +1045,7 @@ class Simple_Local_Avatars {
// check for uploaded files // check for uploaded files
if ( ! empty( $_FILES['simple-local-avatar']['name'] ) && 0 === $_FILES['simple-local-avatar']['error'] ) : if ( ! empty( $_FILES['simple-local-avatar']['name'] ) && 0 === $_FILES['simple-local-avatar']['error'] ) :
// need to be more secure since low privelege users can upload // need to be more secure since low privilege users can upload
$allowed_mime_types = wp_get_mime_types(); $allowed_mime_types = wp_get_mime_types();
$file_mime_type = strtolower( $_FILES['simple-local-avatar']['type'] ); $file_mime_type = strtolower( $_FILES['simple-local-avatar']['type'] );
@ -1132,17 +1135,8 @@ class Simple_Local_Avatars {
$this->avatar_delete( $user_id ); // delete old images if successful $this->avatar_delete( $user_id ); // delete old images if successful
/**
* Enable themes and other plugins to react to avatar deletions.
*
* @since 2.6.0
*
* @param int $user_id Id of the user who's avatar was deleted.
*/
do_action( 'simple_local_avatar_deleted', $user_id );
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
echo wp_kses_post( get_simple_local_avatar( $user_id ) ); echo get_simple_local_avatar( $user_id );
} }
} }
@ -1168,7 +1162,7 @@ class Simple_Local_Avatars {
$this->assign_new_user_avatar( $media_id, $user_id ); $this->assign_new_user_avatar( $media_id, $user_id );
} }
echo wp_kses_post( get_simple_local_avatar( $user_id ) ); echo get_simple_local_avatar( $user_id );
die; die;
} }
@ -1204,6 +1198,15 @@ class Simple_Local_Avatars {
delete_user_meta( $user_id, $this->user_key ); delete_user_meta( $user_id, $this->user_key );
delete_user_meta( $user_id, $this->rating_key ); delete_user_meta( $user_id, $this->rating_key );
/**
* Enable themes and other plugins to react to avatar deletions.
*
* @since 2.6.0
*
* @param int $user_id Id of the user who's avatar was deleted.
*/
do_action( 'simple_local_avatar_deleted', $user_id );
} }
/** /**

View File

@ -2,10 +2,8 @@
Contributors: jakemgold, 10up, thinkoomph, jeffpaul, faisal03 Contributors: jakemgold, 10up, thinkoomph, jeffpaul, faisal03
Donate link: https://10up.com/plugins/simple-local-avatars-wordpress/ Donate link: https://10up.com/plugins/simple-local-avatars-wordpress/
Tags: avatar, gravatar, user photos, users, profile Tags: avatar, gravatar, user photos, users, profile
Requires at least: 5.7 Tested up to: 6.5
Tested up to: 6.4 Stable tag: 2.7.8
Requires PHP: 7.4
Stable tag: 2.7.7
License: GPLv2 or later License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html License URI: http://www.gnu.org/licenses/gpl-2.0.html
@ -33,7 +31,7 @@ Just edit a user profile, and scroll down to the new "Avatar" field. The plug-in
Use avatars in your theme using WordPress' built in `get_avatar()` function: [http://codex.wordpress.org/Function_Reference/get_avatar](http://codex.wordpress.org/Function_Reference/get_avatar "get_avatar function") Use avatars in your theme using WordPress' built in `get_avatar()` function: [http://codex.wordpress.org/Function_Reference/get_avatar](http://codex.wordpress.org/Function_Reference/get_avatar "get_avatar function")
You can also use `get_simple_local_avatar()` (with the same arguments) to retreive local avatars a bit faster, but this will make your theme dependent on this plug-in. You can also use `get_simple_local_avatar()` (with the same arguments) to retrieve local avatars a bit faster, but this will make your theme dependent on this plug-in.
== Frequently Asked Questions == == Frequently Asked Questions ==
@ -47,6 +45,22 @@ No. Simple Local Avatars neither collects, stores, nor sends any PII data of vi
== Changelog == == Changelog ==
= 2.7.8 - 2024-05-06 =
**Note that this release bumps the minimum required version of WordPress from 5.7 to 6.3.**
* **Added:** "Testing" section in the `CONTRIBUTING.md` file (props [@kmgalanakis](https://github.com/kmgalanakis), [@jeffpaul](https://github.com/jeffpaul) via [#274](https://github.com/10up/simple-local-avatars/pull/274)).
* **Changed:** Bumped WordPress "tested up to" version 6.5 (props [@sudip-md](https://github.com/sudip-md), [@dkotter](https://github.com/dkotter), [@jeffpaul](https://github.com/jeffpaul) via [#270](https://github.com/10up/simple-local-avatars/pull/270)).
* **Changed:** Move `simple_local_avatar_deleted` action to `avatar_delete` (props [@lllopo](https://github.com/lllopo), [@faisal-alvi](https://github.com/faisal-alvi), [@dkotter](https://github.com/dkotter) via [#255](https://github.com/10up/simple-local-avatars/pull/255)).
* **Changed:** Clean up NPM dependencies and update node to `v20` (props [@Sidsector9](https://github.com/Sidsector9), [@dkotter](https://github.com/dkotter) via [#257](https://github.com/10up/simple-local-avatars/pull/257)).
* **Changed:** Update `CODEOWNERS` of the plugin (props [@jeffpaul](https://github.com/jeffpaul), [@dkotter](https://github.com/dkotter) via [#253](https://github.com/10up/simple-local-avatars/pull/253)).
* **Changed:** Disabled auto sync pull requests with target branch (props [@iamdharmesh](https://github.com/iamdharmesh), [@jeffpaul](https://github.com/jeffpaul) via [#263](https://github.com/10up/simple-local-avatars/pull/263)).
* **Changed:** Upgrade `download-artifact` from v3 to v4 (props [@iamdharmesh](https://github.com/iamdharmesh), [@jeffpaul](https://github.com/jeffpaul) via [#265](https://github.com/10up/simple-local-avatars/pull/265)).
* **Changed:** Replaced `lee-dohm/no-response` with `actions/stale` to help with closing `no-response/stale` issues (props [@jeffpaul](https://github.com/jeffpaul), [@dkotter](https://github.com/dkotter) via [#266](https://github.com/10up/simple-local-avatars/pull/266)).
* **Fixed:** Broken default avatar when `Local Avatars Only` is unchecked (props [@faisal-alvi](https://github.com/faisal-alvi), [@ankitguptaindia](https://github.com/ankitguptaindia), [@qasumitbagthariya](https://github.com/qasumitbagthariya) via [#260](https://github.com/10up/simple-local-avatars/pull/260)).
* **Fixed:** Ensure high-quality avatar preview on profile edit screen (props [@ocean90](https://github.com/ocean90), [@dkotter](https://github.com/dkotter) via [#273](https://github.com/10up/simple-local-avatars/pull/273)).
* **Fixed:** Possible PHP warning (props [@BhargavBhandari90](https://github.com/BhargavBhandari90), [@dkotter](https://github.com/dkotter) via [#261](https://github.com/10up/simple-local-avatars/pull/261)).
* **Fixed:** Fixed typos (props [@szepeviktor](https://github.com/szepeviktor), [@dkotter](https://github.com/dkotter) via [#268](https://github.com/10up/simple-local-avatars/pull/268)).
= 2.7.7 - 2023-12-13 = = 2.7.7 - 2023-12-13 =
* **Fixed:** Revert the Host/Domain support for local avatar URL (props [@faisal-alvi](https://github.com/faisal-alvi), [@jakejackson1](https://github.com/jakejackson1), [@leogermani](https://github.com/leogermani), [@dkotter](https://github.com/dkotter) via [#247](https://github.com/10up/simple-local-avatars/pull/247)). * **Fixed:** Revert the Host/Domain support for local avatar URL (props [@faisal-alvi](https://github.com/faisal-alvi), [@jakejackson1](https://github.com/jakejackson1), [@leogermani](https://github.com/leogermani), [@dkotter](https://github.com/dkotter) via [#247](https://github.com/10up/simple-local-avatars/pull/247)).
* **Security:** Bump `axios` from 0.25.0 to 1.6.2 and `@wordpress/scripts` from 23.7.2 to 26.18.0 (props [@dependabot](https://github.com/apps/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#250](https://github.com/10up/simple-local-avatars/pull/250)). * **Security:** Bump `axios` from 0.25.0 to 1.6.2 and `@wordpress/scripts` from 23.7.2 to 26.18.0 (props [@dependabot](https://github.com/apps/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#250](https://github.com/10up/simple-local-avatars/pull/250)).
@ -245,6 +259,9 @@ No. Simple Local Avatars neither collects, stores, nor sends any PII data of vi
== Upgrade Notice == == Upgrade Notice ==
= 2.7.8 =
**Note that this release bumps the minimum required version of WordPress from 5.7 to 6.3.**
= 2.6.0 = = 2.6.0 =
**Note that this release bumps the minimum required version of WordPress from 4.6 to 5.7 and PHP from 5.6 to 7.4.** **Note that this release bumps the minimum required version of WordPress from 4.6 to 5.7 and PHP from 5.6 to 7.4.**

View File

@ -3,8 +3,8 @@
* Plugin Name: Simple Local Avatars * Plugin Name: Simple Local Avatars
* Plugin URI: https://10up.com/plugins/simple-local-avatars-wordpress/ * Plugin URI: https://10up.com/plugins/simple-local-avatars-wordpress/
* Description: Adds an avatar upload field to user profiles. Generates requested sizes on demand, just like Gravatar! Simple and lightweight. * Description: Adds an avatar upload field to user profiles. Generates requested sizes on demand, just like Gravatar! Simple and lightweight.
* Version: 2.7.7 * Version: 2.7.8
* Requires at least: 5.7 * Requires at least: 6.3
* Requires PHP: 7.4 * Requires PHP: 7.4
* Author: 10up * Author: 10up
* Author URI: https://10up.com * Author URI: https://10up.com
@ -67,7 +67,7 @@ define( 'SLA_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
require_once dirname( __FILE__ ) . '/includes/class-simple-local-avatars.php'; require_once dirname( __FILE__ ) . '/includes/class-simple-local-avatars.php';
// Global constants. // Global constants.
define( 'SLA_VERSION', '2.7.7' ); define( 'SLA_VERSION', '2.7.8' );
define( 'SLA_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); define( 'SLA_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
if ( ! defined( 'SLA_IS_NETWORK' ) ) { if ( ! defined( 'SLA_IS_NETWORK' ) ) {