updated plugin ActivityPub version 3.3.3

This commit is contained in:
2024-10-09 12:44:17 +00:00
committed by Gitium
parent fb4b27bbc6
commit c54fa007bd
106 changed files with 7070 additions and 2918 deletions

View File

@ -1,4 +1,10 @@
<?php
/**
* Application model file.
*
* @package Activitypub
*/
namespace Activitypub\Model;
use WP_Query;
@ -8,6 +14,9 @@ use Activitypub\Collection\Users;
use function Activitypub\get_rest_url_by_path;
/**
* Application class.
*/
class Application extends Actor {
/**
* The User-ID
@ -17,7 +26,7 @@ class Application extends Actor {
protected $_id = Users::APPLICATION_USER_ID; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
/**
* If the User is discoverable.
* Whether the Application is discoverable.
*
* @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
*
@ -28,7 +37,7 @@ class Application extends Actor {
protected $discoverable = false;
/**
* If the User is indexable.
* Whether the Application is indexable.
*
* @context http://joinmastodon.org/ns#indexable
*
@ -39,18 +48,33 @@ class Application extends Actor {
/**
* The WebFinger Resource.
*
* @var string<url>
* @var string
*/
protected $webfinger;
/**
* Returns the type of the object.
*
* @return string The type of the object.
*/
public function get_type() {
return 'Application';
}
/**
* Returns whether the Application manually approves followers.
*
* @return true Whether the Application manually approves followers.
*/
public function get_manually_approves_followers() {
return true;
}
/**
* Returns the ID of the Application.
*
* @return string The ID of the Application.
*/
public function get_id() {
return get_rest_url_by_path( 'application' );
}
@ -73,24 +97,34 @@ class Application extends Actor {
return $this->get_url();
}
/**
* Get the Username.
*
* @return string The Username.
*/
public function get_name() {
return 'application';
}
/**
* Get the preferred username.
*
* @return string The preferred username.
*/
public function get_preferred_username() {
return $this->get_name();
}
/**
/**
* Get the User-Icon.
*
* @return array The User-Icon.
*/
public function get_icon() {
// try site icon first
// Try site icon first.
$icon_id = get_option( 'site_icon' );
// try custom logo second
// Try custom logo second.
if ( ! $icon_id ) {
$icon_id = get_theme_mod( 'custom_logo' );
}
@ -105,7 +139,7 @@ class Application extends Actor {
}
if ( ! $icon_url ) {
// fallback to default icon
// Fallback to default icon.
$icon_url = plugins_url( '/assets/img/wp-logo.png', ACTIVITYPUB_PLUGIN_FILE );
}
@ -131,6 +165,11 @@ class Application extends Actor {
return null;
}
/**
* Get the first published date.
*
* @return string The published date.
*/
public function get_published() {
$first_post = new WP_Query(
array(
@ -176,18 +215,23 @@ class Application extends Actor {
return $this->get_preferred_username() . '@' . \wp_parse_url( \home_url(), \PHP_URL_HOST );
}
/**
* Returns the public key.
*
* @return array The public key.
*/
public function get_public_key() {
return array(
'id' => $this->get_id() . '#main-key',
'owner' => $this->get_id(),
'id' => $this->get_id() . '#main-key',
'owner' => $this->get_id(),
'publicKeyPem' => Signature::get_public_key_for( Users::APPLICATION_USER_ID ),
);
}
/**
* Get the User-Description.
* Get the User description.
*
* @return string The User-Description.
* @return string The User description.
*/
public function get_summary() {
return \wpautop(
@ -198,6 +242,11 @@ class Application extends Actor {
);
}
/**
* Returns the canonical URL of the object.
*
* @return string|null The canonical URL of the object.
*/
public function get_canonical_url() {
return \home_url();
}

View File

@ -1,17 +1,27 @@
<?php
/**
* Blog model file.
*
* @package Activitypub
*/
namespace Activitypub\Model;
use WP_Query;
use WP_Error;
use Activitypub\Signature;
use Activitypub\Activity\Actor;
use Activitypub\Collection\Users;
use Activitypub\Collection\Extra_Fields;
use function Activitypub\esc_hashtag;
use function Activitypub\is_single_user;
use function Activitypub\is_user_disabled;
use function Activitypub\is_blog_public;
use function Activitypub\get_rest_url_by_path;
/**
* Blog class.
*/
class Blog extends Actor {
/**
* The Featured-Posts.
@ -55,12 +65,12 @@ class Blog extends Actor {
/**
* The WebFinger Resource.
*
* @var string<url>
* @var string
*/
protected $webfinger;
/**
* If the User is discoverable.
* Whether the User is discoverable.
*
* @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
*
@ -71,7 +81,7 @@ class Blog extends Actor {
protected $discoverable;
/**
* Restrict posting to mods
* Restrict posting to mods.
*
* @see https://join-lemmy.org/docs/contributors/05-federation.html
*
@ -79,18 +89,28 @@ class Blog extends Actor {
*/
protected $posting_restricted_to_mods;
/**
* Whether the User manually approves followers.
*
* @return false
*/
public function get_manually_approves_followers() {
return false;
}
/**
* Whether the User is discoverable.
*
* @return boolean
*/
public function get_discoverable() {
return true;
}
/**
* Get the User-ID.
* Get the User ID.
*
* @return string The User-ID.
* @return string The User ID.
*/
public function get_id() {
return $this->get_url();
@ -112,9 +132,9 @@ class Blog extends Actor {
}
/**
* Get the User-Name.
* Get the Username.
*
* @return string The User-Name.
* @return string The Username.
*/
public function get_name() {
return \wp_strip_all_tags(
@ -127,23 +147,29 @@ class Blog extends Actor {
}
/**
* Get the User-Description.
* Get the User description.
*
* @return string The User-Description.
* @return string The User description.
*/
public function get_summary() {
$summary = \get_option( 'activitypub_blog_description', null );
if ( ! $summary ) {
$summary = \get_bloginfo( 'description' );
}
return \wpautop(
\wp_kses(
\get_bloginfo( 'description' ),
$summary,
'default'
)
);
}
/**
* Get the User-Url.
* Get the User url.
*
* @return string The User-Url.
* @return string The User url.
*/
public function get_url() {
return \esc_url( \trailingslashit( get_home_url() ) . '@' . $this->get_preferred_username() );
@ -164,12 +190,12 @@ class Blog extends Actor {
* @return string The auto-generated Username.
*/
public static function get_default_username() {
// check if domain host has a subdomain
// Check if domain host has a subdomain.
$host = \wp_parse_url( \get_home_url(), \PHP_URL_HOST );
$host = \preg_replace( '/^www\./i', '', $host );
/**
* Filter the default blog username.
* Filters the default blog username.
*
* @param string $host The default username.
*/
@ -177,12 +203,12 @@ class Blog extends Actor {
}
/**
* Get the preferred User-Name.
* Get the preferred Username.
*
* @return string The User-Name.
* @return string The Username.
*/
public function get_preferred_username() {
$username = \get_option( 'activitypub_blog_user_identifier' );
$username = \get_option( 'activitypub_blog_identifier' );
if ( $username ) {
return $username;
@ -192,15 +218,15 @@ class Blog extends Actor {
}
/**
* Get the User-Icon.
* Get the User icon.
*
* @return array The User-Icon.
* @return array The User icon.
*/
public function get_icon() {
// try site icon first
// Try site_logo, falling back to site_icon, first.
$icon_id = get_option( 'site_icon' );
// try custom logo second
// Try custom logo second.
if ( ! $icon_id ) {
$icon_id = get_theme_mod( 'custom_logo' );
}
@ -215,7 +241,7 @@ class Blog extends Actor {
}
if ( ! $icon_url ) {
// fallback to default icon
// Fallback to default icon.
$icon_url = plugins_url( '/assets/img/wp-logo.png', ACTIVITYPUB_PLUGIN_FILE );
}
@ -231,16 +257,32 @@ class Blog extends Actor {
* @return array|null The User-Header-Image.
*/
public function get_image() {
if ( \has_header_image() ) {
$header_image = get_option( 'activitypub_header_image' );
$image_url = null;
if ( $header_image ) {
$image_url = \wp_get_attachment_url( $header_image );
}
if ( ! $image_url && \has_header_image() ) {
$image_url = \get_header_image();
}
if ( $image_url ) {
return array(
'type' => 'Image',
'url' => esc_url( \get_header_image() ),
'url' => esc_url( $image_url ),
);
}
return null;
}
/**
* Get the published date.
*
* @return string The published date.
*/
public function get_published() {
$first_post = new WP_Query(
array(
@ -259,10 +301,20 @@ class Blog extends Actor {
return \gmdate( 'Y-m-d\TH:i:s\Z', $time );
}
/**
* Get the canonical URL.
*
* @return string|null The canonical URL.
*/
public function get_canonical_url() {
return \home_url();
}
/**
* Get the Moderators endpoint.
*
* @return string|null The Moderators endpoint.
*/
public function get_moderators() {
if ( is_single_user() || 'Group' !== $this->get_type() ) {
return null;
@ -271,6 +323,11 @@ class Blog extends Actor {
return get_rest_url_by_path( 'collections/moderators' );
}
/**
* Get attributedTo value.
*
* @return string|null The attributedTo value.
*/
public function get_attributed_to() {
if ( is_single_user() || 'Group' !== $this->get_type() ) {
return null;
@ -279,14 +336,24 @@ class Blog extends Actor {
return get_rest_url_by_path( 'collections/moderators' );
}
/**
* Get the public key information.
*
* @return array The public key.
*/
public function get_public_key() {
return array(
'id' => $this->get_id() . '#main-key',
'owner' => $this->get_id(),
'id' => $this->get_id() . '#main-key',
'owner' => $this->get_id(),
'publicKeyPem' => Signature::get_public_key_for( $this->get__id() ),
);
}
/**
* Returns whether posting is restricted to mods.
*
* @return bool|null True if posting is restricted to mods, null if not applicable.
*/
public function get_posting_restricted_to_mods() {
if ( 'Group' === $this->get_type() ) {
return true;
@ -331,6 +398,11 @@ class Blog extends Actor {
return get_rest_url_by_path( sprintf( 'actors/%d/following', $this->get__id() ) );
}
/**
* Returns endpoints.
*
* @return array|null The endpoints.
*/
public function get_endpoints() {
$endpoints = null;
@ -361,45 +433,101 @@ class Blog extends Actor {
return get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $this->get__id() ) );
}
/**
* Returns whether the site is indexable.
*
* @return bool Whether the site is indexable.
*/
public function get_indexable() {
if ( \get_option( 'blog_public', 1 ) ) {
if ( is_blog_public() ) {
return true;
} else {
return false;
}
}
/**
* Update the Username.
*
* @param mixed $value The new value.
* @return bool True if the attribute was updated, false otherwise.
*/
public function update_name( $value ) {
return \update_option( 'blogname', $value );
}
/**
* Update the User description.
*
* @param mixed $value The new value.
* @return bool True if the attribute was updated, false otherwise.
*/
public function update_summary( $value ) {
return \update_option( 'blogdescription', $value );
}
/**
* Update the User icon.
*
* @param mixed $value The new value.
* @return bool True if the attribute was updated, false otherwise.
*/
public function update_icon( $value ) {
if ( ! wp_attachment_is_image( $value ) ) {
return false;
}
return \update_option( 'site_icon', $value );
}
/**
* Update the User-Header-Image.
*
* @param mixed $value The new value.
* @return bool True if the attribute was updated, false otherwise.
*/
public function update_header( $value ) {
if ( ! wp_attachment_is_image( $value ) ) {
return false;
}
return \update_option( 'activitypub_header_image', $value );
}
/**
* Get the User - Hashtags.
*
* @see https://docs.joinmastodon.org/spec/activitypub/#Hashtag
*
* @return array The User - Hashtags.
*/
public function get_tag() {
$hashtags = array();
$args = array(
'orderby' => 'count',
'order' => 'DESC',
'number' => 10,
);
$tags = get_tags( $args );
foreach ( $tags as $tag ) {
$hashtags[] = array(
'type' => 'Hashtag',
'href' => \get_tag_link( $tag->term_id ),
'name' => esc_hashtag( $tag->name ),
);
}
return $hashtags;
}
/**
* Extend the User-Output with Attachments.
*
* @return array The extended User-Output.
*/
public function get_attachment() {
$array = array();
$array[] = array(
'type' => 'PropertyValue',
'name' => \__( 'Blog', 'activitypub' ),
'value' => \html_entity_decode(
sprintf(
'<a rel="me" title="%s" target="_blank" href="%s">%s</a>',
\esc_attr( \home_url( '/' ) ),
\esc_url( \home_url( '/' ) ),
\wp_parse_url( \home_url( '/' ), \PHP_URL_HOST )
),
\ENT_QUOTES,
'UTF-8'
),
);
// Add support for FEP-fb2a, for more information see FEDERATION.md
$array[] = array(
'type' => 'Link',
'name' => \__( 'Blog', 'activitypub' ),
'href' => \esc_url( \home_url( '/' ) ),
'rel' => array( 'me' ),
);
return $array;
$extra_fields = Extra_Fields::get_actor_fields( $this->_id );
return Extra_Fields::fields_to_attachments( $extra_fields );
}
}

View File

@ -1,13 +1,18 @@
<?php
/**
* Follower class file.
*
* @package Activitypub
*/
namespace Activitypub\Model;
use WP_Error;
use WP_Query;
use Activitypub\Activity\Actor;
use Activitypub\Collection\Followers;
/**
* ActivityPub Follower Class
* ActivityPub Follower Class.
*
* This Object represents a single Follower.
* There is no direct reference to a WordPress User here.
@ -19,9 +24,9 @@ use Activitypub\Collection\Followers;
*/
class Follower extends Actor {
/**
* The complete Remote-Profile of the Follower
* The complete Remote-Profile of the Follower.
*
* @var array
* @var int
*/
protected $_id; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
@ -31,13 +36,13 @@ class Follower extends Actor {
* @return mixed
*/
public function get_errors() {
return get_post_meta( $this->_id, 'activitypub_errors' );
return get_post_meta( $this->_id, 'activitypub_errors', false );
}
/**
* Get the Summary.
*
* @return int The Summary.
* @return string The Summary.
*/
public function get_summary() {
if ( isset( $this->summary ) ) {
@ -51,7 +56,7 @@ class Follower extends Actor {
* Getter for URL attribute.
*
* Falls back to ID, if no URL is set. This is relevant for
* Plattforms like Lemmy, where the ID is the URL.
* Platforms like Lemmy, where the ID is the URL.
*
* @return string The URL.
*/
@ -65,8 +70,6 @@ class Follower extends Actor {
/**
* Reset (delete) all errors.
*
* @return void
*/
public function reset_errors() {
delete_post_meta( $this->_id, 'activitypub_errors' );
@ -103,21 +106,19 @@ class Follower extends Actor {
}
/**
* Update the current Follower-Object.
*
* @return void
* Update the current Follower object.
*/
public function update() {
$this->save();
}
/**
* Validate the current Follower-Object.
* Validate the current Follower object.
*
* @return boolean True if the verification was successful.
*/
public function is_valid() {
// the minimum required attributes
// The minimum required attributes.
$required_attributes = array(
'id',
'preferredUsername',
@ -136,9 +137,9 @@ class Follower extends Actor {
}
/**
* Save the current Follower-Object.
* Save the current Follower object.
*
* @return int|WP_Error The Post-ID or an WP_Error.
* @return int|WP_Error The post ID or an WP_Error.
*/
public function save() {
if ( ! $this->is_valid() ) {
@ -148,7 +149,7 @@ class Follower extends Actor {
if ( ! $this->get__id() ) {
global $wpdb;
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
// phpcs:ignore WordPress.DB.DirectDatabaseQuery
$post_id = $wpdb->get_var(
$wpdb->prepare(
"SELECT ID FROM $wpdb->posts WHERE guid=%s",
@ -177,37 +178,35 @@ class Follower extends Actor {
);
if ( ! empty( $post_id ) ) {
// If this is an update, prevent the "followed" date from being
// overwritten by the current date.
// If this is an update, prevent the "followed" date from being overwritten by the current date.
$post = get_post( $post_id );
$args['post_date'] = $post->post_date;
$args['post_date_gmt'] = $post->post_date_gmt;
}
$post_id = wp_insert_post( $args );
$post_id = wp_insert_post( $args );
$this->_id = $post_id;
return $post_id;
}
/**
* Upsert the current Follower-Object.
* Upsert the current Follower object.
*
* @return int|WP_Error The Post-ID or an WP_Error.
* @return int|WP_Error The post ID or an WP_Error.
*/
public function upsert() {
return $this->save();
}
/**
* Delete the current Follower-Object.
* Delete the current Follower object.
*
* Beware that this os deleting a Follower for ALL users!!!
*
* To delete only the User connection (unfollow)
* @see \Activitypub\Rest\Followers::remove_follower()
*
* @return void
* @see \Activitypub\Rest\Followers::remove_follower()
*/
public function delete() {
wp_delete_post( $this->_id );
@ -215,12 +214,10 @@ class Follower extends Actor {
/**
* Update the post meta.
*
* @return void
*/
protected function get_post_meta_input() {
$meta_input = array();
$meta_input['activitypub_inbox'] = $this->get_shared_inbox();
$meta_input = array();
$meta_input['activitypub_inbox'] = $this->get_shared_inbox();
$meta_input['activitypub_actor_json'] = $this->to_json();
return $meta_input;
@ -239,9 +236,9 @@ class Follower extends Actor {
}
return array(
'type' => 'Image',
'type' => 'Image',
'mediaType' => 'image/jpeg',
'url' => ACTIVITYPUB_PLUGIN_URL . 'assets/img/mp.jpg',
'url' => ACTIVITYPUB_PLUGIN_URL . 'assets/img/mp.jpg',
);
}
@ -278,7 +275,7 @@ class Follower extends Actor {
}
/**
* Get the Icon URL (Avatar)
* Get the Icon URL (Avatar).
*
* @return string The URL to the Avatar.
*/
@ -297,7 +294,7 @@ class Follower extends Actor {
}
/**
* Get the Icon URL (Avatar)
* Get the Icon URL (Avatar).
*
* @return string The URL to the Avatar.
*/
@ -333,13 +330,12 @@ class Follower extends Actor {
/**
* Convert a Custom-Post-Type input to an Activitypub\Model\Follower.
*
* @return string The JSON string.
*
* @return array Activitypub\Model\Follower
* @param \WP_Post $post The post object.
* @return \Activitypub\Activity\Base_Object|WP_Error
*/
public static function init_from_cpt( $post ) {
$actor_json = get_post_meta( $post->ID, 'activitypub_actor_json', true );
$object = self::init_from_json( $actor_json );
$object = self::init_from_json( $actor_json );
$object->set__id( $post->ID );
$object->set_id( $post->guid );
$object->set_name( $post->post_title );
@ -370,10 +366,10 @@ class Follower extends Actor {
if ( $path ) {
if ( \strpos( $name, '@' ) !== false ) {
// expected: https://example.com/@user (default URL pattern)
// Expected: https://example.com/@user (default URL pattern).
$name = \preg_replace( '|^/@?|', '', $path );
} else {
// expected: https://example.com/users/user (default ID pattern)
// Expected: https://example.com/users/user (default ID pattern).
$parts = \explode( '/', $path );
$name = \array_pop( $parts );
}
@ -383,7 +379,7 @@ class Follower extends Actor {
\strpos( $name, 'acct' ) === 0 ||
\strpos( $name, '@' ) === 0
) {
// expected: user@example.com or acct:user@example (WebFinger)
// Expected: user@example.com or acct:user@example (WebFinger).
$name = \ltrim( $name, '@' );
$name = \ltrim( $name, 'acct:' );
$parts = \explode( '@', $name );

View File

@ -1,136 +0,0 @@
<?php
namespace Activitypub\Model;
use Activitypub\Collection\Users;
use Activitypub\Transformer\Factory;
/**
* ActivityPub Post Class
*
* @author Matthias Pfefferle
*/
class Post {
/**
* The \Activitypub\Activity\Base_Object object.
*
* @var \Activitypub\Activity\Base_Object
*/
protected $object;
/**
* The WordPress Post Object.
*
* @var WP_Post
*/
private $post;
/**
* Constructor
*
* @param WP_Post $post
* @param int $post_author
*/
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
public function __construct( $post, $post_author = null ) {
_deprecated_function( __METHOD__, '1.0.0', '\Activitypub\Transformer\Factory::get_transformer' );
$transformer = Factory::get_transformer( $post );
if ( ! \is_wp_error( $transformer ) ) {
$this->post = $post;
$this->object = $transformer->to_object();
}
}
/**
* Returns the User ID.
*
* @return int the User ID.
*/
public function get_user_id() {
return apply_filters( 'activitypub_post_user_id', $this->post->post_author, $this->post );
}
/**
* Converts this Object into an Array.
*
* @return array the array representation of a Post.
*/
public function to_array() {
return \apply_filters( 'activitypub_post', $this->object->to_array(), $this->post );
}
/**
* Returns the Actor of this Object.
*
* @return string The URL of the Actor.
*/
public function get_actor() {
$user = Users::get_by_id( $this->get_user_id() );
return $user->get_url();
}
/**
* Converts this Object into a JSON String
*
* @return string
*/
public function to_json() {
return \wp_json_encode( $this->to_array(), \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT );
}
/**
* Returns the URL of an Activity Object
*
* @return string
*/
public function get_url() {
return $this->object->get_url();
}
/**
* Returns the ID of an Activity Object
*
* @return string
*/
public function get_id() {
return $this->object->get_id();
}
/**
* Returns a list of Image Attachments
*
* @return array
*/
public function get_attachments() {
return $this->object->get_attachment();
}
/**
* Returns a list of Tags, used in the Post
*
* @return array
*/
public function get_tags() {
return $this->object->get_tag();
}
/**
* Returns the as2 object-type for a given post
*
* @return string the object-type
*/
public function get_object_type() {
return $this->object->get_type();
}
/**
* Returns the content for the ActivityPub Item.
*
* @return string the content
*/
public function get_content() {
return $this->object->get_content();
}
}

View File

@ -1,18 +1,24 @@
<?php
/**
* User model file.
*
* @package Activitypub
*/
namespace Activitypub\Model;
use WP_Query;
use WP_Error;
use Activitypub\Migration;
use Activitypub\Signature;
use Activitypub\Model\Blog;
use Activitypub\Activity\Actor;
use Activitypub\Collection\Users;
use Activitypub\Collection\Extra_Fields;
use function Activitypub\is_blog_public;
use function Activitypub\is_user_disabled;
use function Activitypub\get_rest_url_by_path;
use function Activitypub\get_actor_extra_fields;
/**
* User class.
*/
class User extends Actor {
/**
* The local User-ID (WP_User).
@ -36,7 +42,7 @@ class User extends Actor {
protected $featured;
/**
* If the User is discoverable.
* Whether the User is discoverable.
*
* @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
*
@ -47,7 +53,7 @@ class User extends Actor {
protected $discoverable = true;
/**
* If the User is indexable.
* Whether the User is indexable.
*
* @context http://joinmastodon.org/ns#indexable
*
@ -58,14 +64,26 @@ class User extends Actor {
/**
* The WebFinger Resource.
*
* @var string<url>
* @var string
*/
protected $webfinger;
/**
* The type of the object.
*
* @return string The type of the object.
*/
public function get_type() {
return 'Person';
}
/**
* Generate a User object from a WP_User.
*
* @param int $user_id The user ID.
*
* @return WP_Error|User The User object or WP_Error if user not found.
*/
public static function from_wp_user( $user_id ) {
if ( is_user_disabled( $user_id ) ) {
return new WP_Error(
@ -75,37 +93,37 @@ class User extends Actor {
);
}
$object = new static();
$object = new static();
$object->_id = $user_id;
return $object;
}
/**
* Get the User-ID.
* Get the user ID.
*
* @return string The User-ID.
* @return string The user ID.
*/
public function get_id() {
return $this->get_url();
}
/**
* Get the User-Name.
* Get the Username.
*
* @return string The User-Name.
* @return string The Username.
*/
public function get_name() {
return \esc_attr( \get_the_author_meta( 'display_name', $this->_id ) );
}
/**
* Get the User-Description.
* Get the User description.
*
* @return string The User-Description.
* @return string The User description.
*/
public function get_summary() {
$description = get_user_meta( $this->_id, 'activitypub_user_description', true );
$description = get_user_option( 'activitypub_description', $this->_id );
if ( empty( $description ) ) {
$description = get_user_meta( $this->_id, 'description', true );
}
@ -113,28 +131,46 @@ class User extends Actor {
}
/**
* Get the User-Url.
* Get the User url.
*
* @return string The User-Url.
* @return string The User url.
*/
public function get_url() {
return \esc_url( \get_author_posts_url( $this->_id ) );
}
/**
* Returns the User-URL with @-Prefix for the username.
* Returns the User URL with @-Prefix for the username.
*
* @return string The User-URL with @-Prefix for the username.
* @return string The User URL with @-Prefix for the username.
*/
public function get_alternate_url() {
return \esc_url( \trailingslashit( get_home_url() ) . '@' . $this->get_preferred_username() );
}
/**
* Get the preferred username.
*
* @return string The preferred username.
*/
public function get_preferred_username() {
return \esc_attr( \get_the_author_meta( 'login', $this->_id ) );
}
/**
* Get the User icon.
*
* @return array The User icon.
*/
public function get_icon() {
$icon = \get_user_option( 'activitypub_icon', $this->_id );
if ( wp_attachment_is_image( $icon ) ) {
return array(
'type' => 'Image',
'url' => esc_url( wp_get_attachment_url( $icon ) ),
);
}
$icon = \esc_url(
\get_avatar_url(
$this->_id,
@ -148,26 +184,51 @@ class User extends Actor {
);
}
/**
* Returns the header image.
*
* @return array|null The header image.
*/
public function get_image() {
if ( \has_header_image() ) {
$image = \esc_url( \get_header_image() );
$header_image = get_user_option( 'activitypub_header_image', $this->_id );
$image_url = null;
if ( ! $header_image && \has_header_image() ) {
$image_url = \get_header_image();
}
if ( $header_image ) {
$image_url = \wp_get_attachment_url( $header_image );
}
if ( $image_url ) {
return array(
'type' => 'Image',
'url' => $image,
'url' => esc_url( $image_url ),
);
}
return null;
}
/**
* Returns the date the user was created.
*
* @return false|string The date the user was created.
*/
public function get_published() {
return \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( \get_the_author_meta( 'registered', $this->_id ) ) );
}
/**
* Returns the public key.
*
* @return array The public key.
*/
public function get_public_key() {
return array(
'id' => $this->get_id() . '#main-key',
'owner' => $this->get_id(),
'id' => $this->get_id() . '#main-key',
'owner' => $this->get_id(),
'publicKeyPem' => Signature::get_public_key_for( $this->get__id() ),
);
}
@ -217,6 +278,11 @@ class User extends Actor {
return get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $this->get__id() ) );
}
/**
* Returns the endpoints.
*
* @return array|null The endpoints.
*/
public function get_endpoints() {
$endpoints = null;
@ -235,74 +301,8 @@ class User extends Actor {
* @return array The extended User-Output.
*/
public function get_attachment() {
$extra_fields = get_actor_extra_fields( $this->_id );
$attachments = array();
foreach ( $extra_fields as $post ) {
$content = \get_the_content( null, false, $post );
$content = \make_clickable( $content );
$content = \do_blocks( $content );
$content = \wptexturize( $content );
$content = \wp_filter_content_tags( $content );
// replace script and style elements
$content = \preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $content );
$content = \strip_shortcodes( $content );
$content = \trim( \preg_replace( '/[\n\r\t]/', '', $content ) );
$attachments[] = array(
'type' => 'PropertyValue',
'name' => \get_the_title( $post ),
'value' => \html_entity_decode(
$content,
\ENT_QUOTES,
'UTF-8'
),
);
$link_added = false;
// Add support for FEP-fb2a, for more information see FEDERATION.md
if ( \class_exists( '\WP_HTML_Tag_Processor' ) ) {
$tags = new \WP_HTML_Tag_Processor( $content );
$tags->next_tag();
if ( 'P' === $tags->get_tag() ) {
$tags->next_tag();
}
if ( 'A' === $tags->get_tag() ) {
$tags->set_bookmark( 'link' );
if ( ! $tags->next_tag() ) {
$tags->seek( 'link' );
$attachment = array(
'type' => 'Link',
'name' => \get_the_title( $post ),
'href' => \esc_url( $tags->get_attribute( 'href' ) ),
'rel' => explode( ' ', $tags->get_attribute( 'rel' ) ),
);
$link_added = true;
}
}
}
if ( ! $link_added ) {
$attachment = array(
'type' => 'Note',
'name' => \get_the_title( $post ),
'content' => \html_entity_decode(
$content,
\ENT_QUOTES,
'UTF-8'
),
);
}
$attachments[] = $attachment;
}
return $attachments;
$extra_fields = Extra_Fields::get_actor_fields( $this->_id );
return Extra_Fields::fields_to_attachments( $extra_fields );
}
/**
@ -314,23 +314,93 @@ class User extends Actor {
return $this->get_preferred_username() . '@' . \wp_parse_url( \home_url(), \PHP_URL_HOST );
}
/**
* Returns the canonical URL.
*
* @return string The canonical URL.
*/
public function get_canonical_url() {
return $this->get_url();
}
/**
* Returns the streams.
*
* @return null The streams.
*/
public function get_streams() {
return null;
}
/**
* Returns the tag.
*
* @return array The tag.
*/
public function get_tag() {
return array();
}
/**
* Returns the indexable state.
*
* @return bool Whether the user is indexable.
*/
public function get_indexable() {
if ( \get_option( 'blog_public', 1 ) ) {
if ( is_blog_public() ) {
return true;
} else {
return false;
}
}
/**
* Update the username.
*
* @param string $value The new value.
* @return int|WP_Error The updated user ID or WP_Error on failure.
*/
public function update_name( $value ) {
$userdata = array(
'ID' => $this->_id,
'display_name' => $value,
);
return \wp_update_user( $userdata );
}
/**
* Update the User description.
*
* @param string $value The new value.
* @return bool True if the attribute was updated, false otherwise.
*/
public function update_summary( $value ) {
return \update_user_option( $this->_id, 'activitypub_description', $value );
}
/**
* Update the User icon.
*
* @param int $value The new value. Should be an attachment ID.
* @return bool True if the attribute was updated, false otherwise.
*/
public function update_icon( $value ) {
if ( ! wp_attachment_is_image( $value ) ) {
return false;
}
return update_user_option( $this->_id, 'activitypub_icon', $value );
}
/**
* Update the User-Header-Image.
*
* @param int $value The new value. Should be an attachment ID.
* @return bool True if the attribute was updated, false otherwise.
*/
public function update_header( $value ) {
if ( ! wp_attachment_is_image( $value ) ) {
return false;
}
return \update_user_option( $this->_id, 'activitypub_header_image', $value );
}
}