wordpress-activitypub/includes/model/class-user.php

347 lines
7.4 KiB
PHP
Raw Normal View History

2023-05-15 08:48:34 +00:00
<?php
namespace Activitypub\Model;
use WP_Query;
use WP_Error;
use Activitypub\Migration;
2023-05-24 15:27:46 +00:00
use Activitypub\Signature;
use Activitypub\Model\Blog;
2023-06-28 12:22:27 +00:00
use Activitypub\Activity\Actor;
use Activitypub\Collection\Users;
2023-06-28 12:22:27 +00:00
use function Activitypub\is_user_disabled;
use function Activitypub\get_rest_url_by_path;
use function Activitypub\get_actor_extra_fields;
2023-06-28 12:22:27 +00:00
class User extends Actor {
2023-05-15 08:48:34 +00:00
/**
2023-07-03 09:20:44 +00:00
* The local User-ID (WP_User).
2023-05-15 08:48:34 +00:00
*
* @var int
*/
2023-06-28 12:22:27 +00:00
protected $_id; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
2023-05-15 08:48:34 +00:00
/**
* The Featured-Posts.
*
* @see https://docs.joinmastodon.org/spec/activitypub/#featured
*
Add/event objects (#629) * remove redundant property definitions * Add redused context for actors. * Add classes to construct Moblizon compatible events * Bind the context to the activitypub object - change the propertyname which stores the json-ld context from context to _context, because context is already reserved in the ActivityStreams vocabulary. - cleanup currently unused code * fix phpcs * Remove PostalAddress object: it's enough (at least atm) to directly write the array in transformers. * Remove _context property from ActivityPub objects in favour of getter function get_json_ld_context() * fix unit tests: ActivityPub Activity objects have a custom getter for the JsonLD context * fix phpcs * fix unit-tests to also support php5.6 * fix phpcs * add param include_json_ld_context to to_array function This allows to not set the @context in the resulting array. * propagate the param include_json_ld_context to nested calls of to_array. * fix phpcs * Nested AcitivityPub objects: never build context in inner items in to_array function * fix: param of set_address may also be an array * fix typo in comment * always prefix json-ld context with json-ld and move event class to sub-namespace * fix usage of reserved object keyword seems it should not be used as a namespace either * Merge commit 'b2271cda6b857f879e0abd4f3c6683642d725267' into add/event-objects * Fix calling non-static function as static Co-authored-by: Matthias Pfefferle <pfefferle@users.noreply.github.com> * Partly fix Json-LD contexts in collections * Update includes/activity/class-base-object.php * this is implicit We already set the correct user with `$transformer->change_wp_user_id( $user_id );` so the Actor will be generated properly. We can change the behaviour, but we should not use both. * this change prevents the Activity to re-use Object vars this should stay as is, because it pre-fills the Activity with data (for example cc and to) and it will no longer be done with your change. It is on purpose that it first sets the object and then replaces it with the URI. See: https://github.com/Automattic/wordpress-activitypub/blob/master/includes/activity/class-activity.php#L195 * add `$include_json_ld_context` support to `to_json` * disable some more contexts * remove whitespace * Add php-comment for 7ed17c042a2651e08afc790adbdfc5ccf46c2708 * Fix JSON-LD context for ActivityPub objects: child classes may override it. * coding standards * call folder/namespace `Extended_Object` to be consistent with folder names in singular * fix: unnessesary nesting of extended-objects * remove license I hope this is fine, to have the complete plugin under the MIT @Menrath ?!? --------- Co-authored-by: Matthias Pfefferle <pfefferle@users.noreply.github.com>
2024-01-18 15:35:52 +00:00
* @context {
* "@id": "http://joinmastodon.org/ns#featured",
* "@type": "@id"
* }
*
* @var string
*/
protected $featured;
2023-05-15 08:48:34 +00:00
/**
* If the User is discoverable.
2023-05-15 08:48:34 +00:00
*
* @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
*
Add/event objects (#629) * remove redundant property definitions * Add redused context for actors. * Add classes to construct Moblizon compatible events * Bind the context to the activitypub object - change the propertyname which stores the json-ld context from context to _context, because context is already reserved in the ActivityStreams vocabulary. - cleanup currently unused code * fix phpcs * Remove PostalAddress object: it's enough (at least atm) to directly write the array in transformers. * Remove _context property from ActivityPub objects in favour of getter function get_json_ld_context() * fix unit tests: ActivityPub Activity objects have a custom getter for the JsonLD context * fix phpcs * fix unit-tests to also support php5.6 * fix phpcs * add param include_json_ld_context to to_array function This allows to not set the @context in the resulting array. * propagate the param include_json_ld_context to nested calls of to_array. * fix phpcs * Nested AcitivityPub objects: never build context in inner items in to_array function * fix: param of set_address may also be an array * fix typo in comment * always prefix json-ld context with json-ld and move event class to sub-namespace * fix usage of reserved object keyword seems it should not be used as a namespace either * Merge commit 'b2271cda6b857f879e0abd4f3c6683642d725267' into add/event-objects * Fix calling non-static function as static Co-authored-by: Matthias Pfefferle <pfefferle@users.noreply.github.com> * Partly fix Json-LD contexts in collections * Update includes/activity/class-base-object.php * this is implicit We already set the correct user with `$transformer->change_wp_user_id( $user_id );` so the Actor will be generated properly. We can change the behaviour, but we should not use both. * this change prevents the Activity to re-use Object vars this should stay as is, because it pre-fills the Activity with data (for example cc and to) and it will no longer be done with your change. It is on purpose that it first sets the object and then replaces it with the URI. See: https://github.com/Automattic/wordpress-activitypub/blob/master/includes/activity/class-activity.php#L195 * add `$include_json_ld_context` support to `to_json` * disable some more contexts * remove whitespace * Add php-comment for 7ed17c042a2651e08afc790adbdfc5ccf46c2708 * Fix JSON-LD context for ActivityPub objects: child classes may override it. * coding standards * call folder/namespace `Extended_Object` to be consistent with folder names in singular * fix: unnessesary nesting of extended-objects * remove license I hope this is fine, to have the complete plugin under the MIT @Menrath ?!? --------- Co-authored-by: Matthias Pfefferle <pfefferle@users.noreply.github.com>
2024-01-18 15:35:52 +00:00
* @context http://joinmastodon.org/ns#discoverable
*
* @var boolean
2023-05-15 08:48:34 +00:00
*/
protected $discoverable = true;
/**
* If the User is indexable.
*
Add/event objects (#629) * remove redundant property definitions * Add redused context for actors. * Add classes to construct Moblizon compatible events * Bind the context to the activitypub object - change the propertyname which stores the json-ld context from context to _context, because context is already reserved in the ActivityStreams vocabulary. - cleanup currently unused code * fix phpcs * Remove PostalAddress object: it's enough (at least atm) to directly write the array in transformers. * Remove _context property from ActivityPub objects in favour of getter function get_json_ld_context() * fix unit tests: ActivityPub Activity objects have a custom getter for the JsonLD context * fix phpcs * fix unit-tests to also support php5.6 * fix phpcs * add param include_json_ld_context to to_array function This allows to not set the @context in the resulting array. * propagate the param include_json_ld_context to nested calls of to_array. * fix phpcs * Nested AcitivityPub objects: never build context in inner items in to_array function * fix: param of set_address may also be an array * fix typo in comment * always prefix json-ld context with json-ld and move event class to sub-namespace * fix usage of reserved object keyword seems it should not be used as a namespace either * Merge commit 'b2271cda6b857f879e0abd4f3c6683642d725267' into add/event-objects * Fix calling non-static function as static Co-authored-by: Matthias Pfefferle <pfefferle@users.noreply.github.com> * Partly fix Json-LD contexts in collections * Update includes/activity/class-base-object.php * this is implicit We already set the correct user with `$transformer->change_wp_user_id( $user_id );` so the Actor will be generated properly. We can change the behaviour, but we should not use both. * this change prevents the Activity to re-use Object vars this should stay as is, because it pre-fills the Activity with data (for example cc and to) and it will no longer be done with your change. It is on purpose that it first sets the object and then replaces it with the URI. See: https://github.com/Automattic/wordpress-activitypub/blob/master/includes/activity/class-activity.php#L195 * add `$include_json_ld_context` support to `to_json` * disable some more contexts * remove whitespace * Add php-comment for 7ed17c042a2651e08afc790adbdfc5ccf46c2708 * Fix JSON-LD context for ActivityPub objects: child classes may override it. * coding standards * call folder/namespace `Extended_Object` to be consistent with folder names in singular * fix: unnessesary nesting of extended-objects * remove license I hope this is fine, to have the complete plugin under the MIT @Menrath ?!? --------- Co-authored-by: Matthias Pfefferle <pfefferle@users.noreply.github.com>
2024-01-18 15:35:52 +00:00
* @context http://joinmastodon.org/ns#indexable
*
* @var boolean
*/
protected $indexable;
/**
* The WebFinger Resource.
*
* @var string<url>
*/
protected $webfinger;
public function get_type() {
return 'Person';
}
2023-06-28 12:22:27 +00:00
public static function from_wp_user( $user_id ) {
2023-07-11 07:09:37 +00:00
if ( is_user_disabled( $user_id ) ) {
2023-06-28 14:43:41 +00:00
return new WP_Error(
'activitypub_user_not_found',
\__( 'User not found', 'activitypub' ),
array( 'status' => 404 )
);
2023-06-28 12:22:27 +00:00
}
2023-06-28 12:22:27 +00:00
$object = new static();
$object->_id = $user_id;
return $object;
}
/**
* Get the User-ID.
*
* @return string The User-ID.
*/
public function get_id() {
return $this->get_url();
}
/**
* Get the User-Name.
*
* @return string The User-Name.
*/
public function get_name() {
2023-06-28 12:22:27 +00:00
return \esc_attr( \get_the_author_meta( 'display_name', $this->_id ) );
}
/**
* Get the User-Description.
*
* @return string The User-Description.
*/
public function get_summary() {
$description = get_user_option( 'activitypub_description', $this->_id );
if ( empty( $description ) ) {
2023-06-28 12:22:27 +00:00
$description = get_user_meta( $this->_id, 'description', true );
}
return \wpautop( \wp_kses( $description, 'default' ) );
}
/**
* Get the User-Url.
*
* @return string The User-Url.
*/
public function get_url() {
2023-06-28 12:22:27 +00:00
return \esc_url( \get_author_posts_url( $this->_id ) );
}
/**
* Returns 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() );
2023-05-30 09:37:21 +00:00
}
2023-06-28 12:22:27 +00:00
public function get_preferred_username() {
return \esc_attr( \get_the_author_meta( 'login', $this->_id ) );
}
2023-06-28 12:22:27 +00:00
public function get_icon() {
$icon = \esc_url(
\get_avatar_url(
2023-06-28 12:22:27 +00:00
$this->_id,
array( 'size' => 120 )
)
);
2023-06-28 12:22:27 +00:00
return array(
'type' => 'Image',
'url' => $icon,
);
}
2023-06-28 12:22:27 +00:00
public function get_image() {
$header_image = get_user_option( 'activitypub_header_image', $this->_id );
2024-07-24 13:20:38 +00:00
$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 ) {
2023-06-28 12:22:27 +00:00
return array(
'type' => 'Image',
'url' => esc_url( $image_url ),
2023-06-28 12:22:27 +00:00
);
}
return null;
}
public function get_published() {
2023-06-28 12:22:27 +00:00
return \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( \get_the_author_meta( 'registered', $this->_id ) ) );
}
public function get_public_key() {
return array(
'id' => $this->get_id() . '#main-key',
'owner' => $this->get_id(),
'publicKeyPem' => Signature::get_public_key_for( $this->get__id() ),
);
}
/**
2023-06-28 14:43:41 +00:00
* Returns the Inbox-API-Endpoint.
*
2023-06-28 14:43:41 +00:00
* @return string The Inbox-Endpoint.
*/
public function get_inbox() {
return get_rest_url_by_path( sprintf( 'actors/%d/inbox', $this->get__id() ) );
2023-06-28 14:43:41 +00:00
}
/**
* Returns the Outbox-API-Endpoint.
*
2023-06-28 14:43:41 +00:00
* @return string The Outbox-Endpoint.
*/
2023-06-28 14:43:41 +00:00
public function get_outbox() {
return get_rest_url_by_path( sprintf( 'actors/%d/outbox', $this->get__id() ) );
2023-06-28 14:43:41 +00:00
}
2023-06-28 14:43:41 +00:00
/**
* Returns the Followers-API-Endpoint.
*
* @return string The Followers-Endpoint.
*/
public function get_followers() {
return get_rest_url_by_path( sprintf( 'actors/%d/followers', $this->get__id() ) );
}
/**
2023-06-28 14:43:41 +00:00
* Returns the Following-API-Endpoint.
*
2023-06-28 14:43:41 +00:00
* @return string The Following-Endpoint.
*/
public function get_following() {
return get_rest_url_by_path( sprintf( 'actors/%d/following', $this->get__id() ) );
2023-06-28 14:43:41 +00:00
}
/**
* Returns the Featured-API-Endpoint.
*
* @return string The Featured-Endpoint.
*/
public function get_featured() {
return get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $this->get__id() ) );
}
public function get_endpoints() {
$endpoints = null;
if ( ACTIVITYPUB_SHARED_INBOX_FEATURE ) {
$endpoints = array(
'sharedInbox' => get_rest_url_by_path( 'inbox' ),
);
}
return $endpoints;
}
2023-06-28 14:43:41 +00:00
/**
* Extend the User-Output with Attachments.
*
* @return array The extended User-Output.
*/
2023-06-28 14:43:41 +00:00
public function get_attachment() {
2024-07-18 06:23:34 +00:00
$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;
}
/**
* Returns a user@domain type of identifier for the user.
*
* @return string The Webfinger-Identifier.
*/
public function get_webfinger() {
2023-06-28 12:22:27 +00:00
return $this->get_preferred_username() . '@' . \wp_parse_url( \home_url(), \PHP_URL_HOST );
}
public function get_canonical_url() {
return $this->get_url();
}
public function get_streams() {
return null;
}
2023-09-28 12:38:48 +00:00
public function get_tag() {
return array();
}
public function get_indexable() {
if ( \get_option( 'blog_public', 1 ) ) {
return true;
} else {
return false;
}
}
2023-05-15 08:48:34 +00:00
}