| @@ -6,15 +6,14 @@ | ||
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | namespace Activitypub\Rest; |
| 9 | 9 | |
| 10 | -use Activitypub\Activity\Base_Object; | |
| 11 | 10 | use Activitypub\Collection\Actors; |
| 12 | -use Activitypub\Collection\Following; | |
| 13 | -use Activitypub\Collection\Remote_Actors; | |
| 14 | 11 | |
| 12 | +use function Activitypub\get_context; | |
| 13 | +use function Activitypub\is_single_user; | |
| 14 | +use function Activitypub\get_rest_url_by_path; | |
| 15 | 15 | use function Activitypub\get_masked_wp_version; |
| 16 | -use function Activitypub\get_rest_url_by_path; | |
| 17 | 16 | |
| 18 | 17 | /** |
| 19 | 18 | * Following_Controller class. |
| 20 | 19 | * |
| @@ -25,8 +24,15 @@ | ||
| 25 | 24 | class Following_Controller extends Actors_Controller { |
| 26 | 25 | use Collection; |
| 27 | 26 | |
| 28 | 27 | /** |
| 28 | + * Initialize the class, registering WordPress hooks. | |
| 29 | + */ | |
| 30 | + public function __construct() { | |
| 31 | + \add_filter( 'activitypub_rest_following', array( self::class, 'default_following' ), 10, 2 ); | |
| 32 | + } | |
| 33 | + | |
| 34 | + /** | |
| 29 | 35 | * Register routes. |
| 30 | 36 | */ |
| 31 | 37 | public function register_routes() { |
| 32 | 38 | \register_rest_route( |
| @@ -34,18 +40,18 @@ | ||
| 34 | 40 | '/' . $this->rest_base . '/following', |
| 35 | 41 | array( |
| 36 | 42 | 'args' => array( |
| 37 | 43 | 'user_id' => array( |
| 38 | - 'description' => 'The ID of the actor.', | |
| 39 | - 'type' => 'integer', | |
| 40 | - 'required' => true, | |
| 41 | - 'validate_callback' => array( $this, 'validate_user_id' ), | |
| 44 | + 'description' => 'The ID or username of the actor.', | |
| 45 | + 'type' => 'string', | |
| 46 | + 'required' => true, | |
| 47 | + 'pattern' => '[\w\-\.]+', | |
| 42 | 48 | ), |
| 43 | 49 | ), |
| 44 | 50 | array( |
| 45 | 51 | 'methods' => \WP_REST_Server::READABLE, |
| 46 | 52 | 'callback' => array( $this, 'get_items' ), |
| 47 | - 'permission_callback' => array( $this, 'verify_signature' ), | |
| 53 | + 'permission_callback' => array( 'Activitypub\Rest\Server', 'verify_signature' ), | |
| 48 | 54 | 'args' => array( |
| 49 | 55 | 'page' => array( |
| 50 | 56 | 'description' => 'Current page of the collection.', |
| 51 | 57 | 'type' => 'integer', |
| @@ -58,20 +64,8 @@ | ||
| 58 | 64 | 'default' => 10, |
| 59 | 65 | 'minimum' => 1, |
| 60 | 66 | 'maximum' => 100, |
| 61 | 67 | ), |
| 62 | - 'order' => array( | |
| 63 | - 'description' => 'Order sort attribute ascending or descending.', | |
| 64 | - 'type' => 'string', | |
| 65 | - 'default' => 'desc', | |
| 66 | - 'enum' => array( 'asc', 'desc' ), | |
| 67 | - ), | |
| 68 | - 'context' => array( | |
| 69 | - 'description' => 'The context in which the request is made.', | |
| 70 | - 'type' => 'string', | |
| 71 | - 'default' => 'simple', | |
| 72 | - 'enum' => array( 'simple', 'full' ), | |
| 73 | - ), | |
| 74 | 68 | ), |
| 75 | 69 | ), |
| 76 | 70 | 'schema' => array( $this, 'get_public_item_schema' ), |
| 77 | 71 | ) |
| @@ -85,11 +79,12 @@ | ||
| 85 | 79 | * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. |
| 86 | 80 | */ |
| 87 | 81 | public function get_items( $request ) { |
| 88 | 82 | $user_id = $request->get_param( 'user_id' ); |
| 89 | - $user = null; | |
| 90 | - if ( \has_filter( 'activitypub_rest_following' ) ) { | |
| 91 | - $user = Actors::get_by_id( $user_id ); | |
| 83 | + $user = Actors::get_by_various( $user_id ); | |
| 84 | + | |
| 85 | + if ( \is_wp_error( $user ) ) { | |
| 86 | + return $user; | |
| 92 | 87 | } |
| 93 | 88 | |
| 94 | 89 | /** |
| 95 | 90 | * Action triggered prior to the ActivityPub profile being created and sent to the client. |
| @@ -95,62 +90,29 @@ | ||
| 95 | 90 | * Action triggered prior to the ActivityPub profile being created and sent to the client. |
| 96 | 91 | */ |
| 97 | 92 | \do_action( 'activitypub_rest_following_pre' ); |
| 98 | 93 | |
| 99 | - $order = $request->get_param( 'order' ); | |
| 100 | - $per_page = $request->get_param( 'per_page' ); | |
| 101 | - $page = $request->get_param( 'page' ) ?? 1; | |
| 102 | - $context = $request->get_param( 'context' ); | |
| 103 | - | |
| 104 | - $data = Following::query( $user_id, $per_page, $page, array( 'order' => \ucwords( $order ) ) ); | |
| 105 | - | |
| 106 | 94 | $response = array( |
| 107 | - 'id' => get_rest_url_by_path( \sprintf( 'actors/%d/following', $user_id ) ), | |
| 108 | - 'generator' => 'https://wordpress.org/?v=' . get_masked_wp_version(), | |
| 109 | - 'type' => 'OrderedCollection', | |
| 110 | - 'totalItems' => $data['total'], | |
| 95 | + '@context' => get_context(), | |
| 96 | + 'id' => get_rest_url_by_path( \sprintf( 'actors/%d/following', $user->get__id() ) ), | |
| 97 | + 'generator' => 'https://wordpress.org/?v=' . get_masked_wp_version(), | |
| 98 | + 'actor' => $user->get_id(), | |
| 99 | + 'type' => 'OrderedCollection', | |
| 111 | 100 | ); |
| 112 | 101 | |
| 113 | - if ( 'full' === $context ) { | |
| 114 | - // Ensure the context is the first element in the response. | |
| 115 | - $response = array( '@context' => Base_Object::JSON_LD_CONTEXT ) + $response; | |
| 116 | - } | |
| 117 | - | |
| 118 | - if ( $this->show_social_graph( $request ) ) { | |
| 119 | - $response['orderedItems'] = \array_filter( | |
| 120 | - \array_map( | |
| 121 | - static function ( $item ) use ( $context ) { | |
| 122 | - if ( 'full' === $context ) { | |
| 123 | - $actor = Remote_Actors::get_actor( $item ); | |
| 124 | - if ( \is_wp_error( $actor ) ) { | |
| 125 | - return false; | |
| 126 | - } | |
| 127 | - return $actor->to_array( false ); | |
| 128 | - } | |
| 129 | - return $item->guid; | |
| 130 | - }, | |
| 131 | - $data['following'] | |
| 132 | - ) | |
| 133 | - ); | |
| 134 | - } | |
| 135 | - | |
| 136 | 102 | /** |
| 137 | - * Filter the list of following urls | |
| 103 | + * Filter the list of following urls. | |
| 138 | 104 | * |
| 139 | 105 | * @param array $items The array of following urls. |
| 140 | 106 | * @param \Activitypub\Model\User $user The user object. |
| 141 | - * | |
| 142 | - * @deprecated 7.1.0 Please migrate your Followings to the new internal Following structure. | |
| 143 | 107 | */ |
| 144 | - $items = \apply_filters_deprecated( 'activitypub_rest_following', array( array(), $user ), '7.1.0', 'Please migrate your Followings to the new internal Following structure.' ); | |
| 108 | + $items = \apply_filters( 'activitypub_rest_following', array(), $user ); | |
| 145 | 109 | |
| 146 | - if ( ! empty( $items ) ) { | |
| 147 | - $response['totalItems'] = count( $items ); | |
| 148 | - $response['orderedItems'] = $items; | |
| 149 | - } | |
| 110 | + $response['totalItems'] = \is_countable( $items ) ? \count( $items ) : 0; | |
| 111 | + $response['orderedItems'] = $items; | |
| 150 | 112 | |
| 151 | 113 | $response = $this->prepare_collection_response( $response, $request ); |
| 152 | - if ( \is_wp_error( $response ) ) { | |
| 114 | + if ( is_wp_error( $response ) ) { | |
| 153 | 115 | return $response; |
| 154 | 116 | } |
| 155 | 117 | |
| 156 | 118 | $response = \rest_ensure_response( $response ); |
| @@ -159,8 +121,31 @@ | ||
| 159 | 121 | return $response; |
| 160 | 122 | } |
| 161 | 123 | |
| 162 | 124 | /** |
| 125 | + * Add the Blog Authors to the following list of the Blog Actor | |
| 126 | + * if Blog not in single mode. | |
| 127 | + * | |
| 128 | + * @param array $follow_list The array of following urls. | |
| 129 | + * @param \Activitypub\Model\User $user The user object. | |
| 130 | + * | |
| 131 | + * @return array The array of following urls. | |
| 132 | + */ | |
| 133 | + public static function default_following( $follow_list, $user ) { | |
| 134 | + if ( 0 !== $user->get__id() || is_single_user() ) { | |
| 135 | + return $follow_list; | |
| 136 | + } | |
| 137 | + | |
| 138 | + $users = Actors::get_collection(); | |
| 139 | + | |
| 140 | + foreach ( $users as $user ) { | |
| 141 | + $follow_list[] = $user->get_id(); | |
| 142 | + } | |
| 143 | + | |
| 144 | + return $follow_list; | |
| 145 | + } | |
| 146 | + | |
| 147 | + /** | |
| 163 | 148 | * Retrieves the following schema, conforming to JSON Schema. |
| 164 | 149 | * |
| 165 | 150 | * @return array Item schema data. |
| 166 | 151 | */ |
| @@ -168,67 +153,11 @@ | ||
| 168 | 153 | if ( $this->schema ) { |
| 169 | 154 | return $this->add_additional_fields_schema( $this->schema ); |
| 170 | 155 | } |
| 171 | 156 | |
| 172 | - // Define the schema for items in the following collection. | |
| 173 | 157 | $item_schema = array( |
| 174 | - 'oneOf' => array( | |
| 175 | - array( | |
| 176 | - 'type' => 'string', | |
| 177 | - 'format' => 'uri', | |
| 178 | - ), | |
| 179 | - array( | |
| 180 | - 'type' => 'object', | |
| 181 | - 'properties' => array( | |
| 182 | - 'id' => array( | |
| 183 | - 'type' => 'string', | |
| 184 | - 'format' => 'uri', | |
| 185 | - ), | |
| 186 | - 'type' => array( | |
| 187 | - 'type' => 'string', | |
| 188 | - ), | |
| 189 | - 'name' => array( | |
| 190 | - 'type' => 'string', | |
| 191 | - ), | |
| 192 | - 'icon' => array( | |
| 193 | - 'type' => 'object', | |
| 194 | - 'properties' => array( | |
| 195 | - 'type' => array( | |
| 196 | - 'type' => 'string', | |
| 197 | - ), | |
| 198 | - 'mediaType' => array( | |
| 199 | - 'type' => 'string', | |
| 200 | - ), | |
| 201 | - 'url' => array( | |
| 202 | - 'type' => 'string', | |
| 203 | - 'format' => 'uri', | |
| 204 | - ), | |
| 205 | - ), | |
| 206 | - ), | |
| 207 | - 'published' => array( | |
| 208 | - 'type' => 'string', | |
| 209 | - 'format' => 'date-time', | |
| 210 | - ), | |
| 211 | - 'summary' => array( | |
| 212 | - 'type' => 'string', | |
| 213 | - ), | |
| 214 | - 'updated' => array( | |
| 215 | - 'type' => 'string', | |
| 216 | - 'format' => 'date-time', | |
| 217 | - ), | |
| 218 | - 'url' => array( | |
| 219 | - 'type' => 'string', | |
| 220 | - 'format' => 'uri', | |
| 221 | - ), | |
| 222 | - 'streams' => array( | |
| 223 | - 'type' => 'array', | |
| 224 | - ), | |
| 225 | - 'preferredUsername' => array( | |
| 226 | - 'type' => 'string', | |
| 227 | - ), | |
| 228 | - ), | |
| 229 | - ), | |
| 230 | - ), | |
| 158 | + 'type' => 'string', | |
| 159 | + 'format' => 'uri', | |
| 231 | 160 | ); |
| 232 | 161 | |
| 233 | 162 | $schema = $this->get_collection_schema( $item_schema ); |
| 234 | 163 | |