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

407 lines
8.3 KiB
PHP
Raw Permalink Normal View History

2023-05-15 08:48:34 +00:00
<?php
/**
* User model file.
*
* @package Activitypub
*/
2023-05-15 08:48:34 +00:00
namespace Activitypub\Model;
use WP_Error;
2023-05-24 15:27:46 +00:00
use Activitypub\Signature;
2023-06-28 12:22:27 +00:00
use Activitypub\Activity\Actor;
use Activitypub\Collection\Extra_Fields;
2024-09-12 14:55:14 +00:00
use function Activitypub\is_blog_public;
2023-06-28 12:22:27 +00:00
use function Activitypub\is_user_disabled;
use function Activitypub\get_rest_url_by_path;
/**
* User class.
*/
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
/**
* Whether 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;
/**
* Whether 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
*/
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.
*/
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
}
$object = new static();
2023-06-28 12:22:27 +00:00
$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 Username.
*
* @return string The Username.
*/
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
}
/**
* Get the preferred username.
*
* @return string The preferred username.
*/
2023-06-28 12:22:27 +00:00
public function get_preferred_username() {
return \esc_attr( \get_the_author_meta( 'login', $this->_id ) );
}
/**
* Get the User icon.
*
* @return array The User icon.
*/
2023-06-28 12:22:27 +00:00
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 ) ),
);
}
2023-06-28 12:22:27 +00:00
$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,
);
}
/**
* Returns the header image.
*
* @return array|null The header image.
*/
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 && \has_header_image() ) {
$image_url = \get_header_image();
}
if ( $header_image ) {
$image_url = \wp_get_attachment_url( $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;
}
/**
* Returns the date the user was created.
*
* @return false|string The date the user was created.
*/
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 ) ) );
}
/**
* 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(),
'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() ) );
}
/**
* Returns the endpoints.
*
* @return array|null The endpoints.
*/
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() {
$extra_fields = Extra_Fields::get_actor_fields( $this->_id );
return Extra_Fields::fields_to_attachments( $extra_fields );
}
/**
* 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 );
}
/**
* 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.
*/
2023-09-28 12:38:48 +00:00
public function get_tag() {
return array();
}
/**
* Returns the indexable state.
*
* @return bool Whether the user is indexable.
*/
public function get_indexable() {
2024-09-12 14:55:14 +00:00
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 );
}
2023-05-15 08:48:34 +00:00
}