| @@ -9,12 +9,9 @@ | ||
| 9 | 9 | |
| 10 | 10 | use Activitypub\Activity\Base_Object; |
| 11 | 11 | use Activitypub\Collection\Replies; |
| 12 | 12 | use Activitypub\Comment; |
| 13 | -use Activitypub\Sanitize; | |
| 14 | -use Activitypub\Webfinger; | |
| 15 | 13 | |
| 16 | -use function Activitypub\get_post_id; | |
| 17 | 14 | use function Activitypub\get_rest_url_by_path; |
| 18 | 15 | |
| 19 | 16 | /** |
| 20 | 17 | * Class Post_Controller |
| @@ -34,9 +31,9 @@ | ||
| 34 | 31 | * The base of this controller's route. |
| 35 | 32 | * |
| 36 | 33 | * @var string |
| 37 | 34 | */ |
| 38 | - protected $rest_base = 'posts/(?P<id>[\d]+)'; | |
| 35 | + protected $rest_base = 'posts/(?P<id>[-]?\d+)'; | |
| 39 | 36 | |
| 40 | 37 | /** |
| 41 | 38 | * Register routes. |
| 42 | 39 | */ |
| @@ -46,12 +43,10 @@ | ||
| 46 | 43 | '/' . $this->rest_base . '/reactions', |
| 47 | 44 | array( |
| 48 | 45 | 'args' => array( |
| 49 | 46 | 'id' => array( |
| 50 | - 'required' => true, | |
| 51 | - 'type' => 'integer', | |
| 52 | - 'minimum' => 1, | |
| 53 | - 'validate_callback' => 'Activitypub\is_post_publicly_queryable', | |
| 47 | + 'required' => true, | |
| 48 | + 'type' => 'integer', | |
| 54 | 49 | ), |
| 55 | 50 | ), |
| 56 | 51 | array( |
| 57 | 52 | 'methods' => \WP_REST_Server::READABLE, |
| @@ -66,12 +61,10 @@ | ||
| 66 | 61 | '/' . $this->rest_base . '/context', |
| 67 | 62 | array( |
| 68 | 63 | 'args' => array( |
| 69 | 64 | 'id' => array( |
| 70 | - 'required' => true, | |
| 71 | - 'type' => 'integer', | |
| 72 | - 'minimum' => 1, | |
| 73 | - 'validate_callback' => 'Activitypub\is_post_publicly_queryable', | |
| 65 | + 'required' => true, | |
| 66 | + 'type' => 'integer', | |
| 74 | 67 | ), |
| 75 | 68 | ), |
| 76 | 69 | array( |
| 77 | 70 | 'methods' => \WP_REST_Server::READABLE, |
| @@ -79,44 +72,8 @@ | ||
| 79 | 72 | 'permission_callback' => '__return_true', |
| 80 | 73 | ), |
| 81 | 74 | ) |
| 82 | 75 | ); |
| 83 | - | |
| 84 | - \register_rest_route( | |
| 85 | - $this->namespace, | |
| 86 | - '/' . $this->rest_base . '/remote-intent', | |
| 87 | - array( | |
| 88 | - 'args' => array( | |
| 89 | - 'id' => array( | |
| 90 | - 'description' => 'Unique identifier for the post.', | |
| 91 | - 'type' => 'integer', | |
| 92 | - 'minimum' => 1, | |
| 93 | - 'required' => true, | |
| 94 | - 'validate_callback' => 'Activitypub\is_post_publicly_queryable', | |
| 95 | - ), | |
| 96 | - ), | |
| 97 | - array( | |
| 98 | - 'methods' => \WP_REST_Server::READABLE, | |
| 99 | - 'callback' => array( $this, 'get_remote_intent_template' ), | |
| 100 | - 'permission_callback' => '__return_true', | |
| 101 | - 'args' => array( | |
| 102 | - 'resource' => array( | |
| 103 | - 'description' => 'The Fediverse profile handle or URL.', | |
| 104 | - 'type' => 'string', | |
| 105 | - 'required' => true, | |
| 106 | - 'sanitize_callback' => array( Sanitize::class, 'webfinger' ), | |
| 107 | - ), | |
| 108 | - 'intent' => array( | |
| 109 | - 'description' => 'The intent type.', | |
| 110 | - 'type' => 'string', | |
| 111 | - 'default' => 'like', | |
| 112 | - 'enum' => array( 'like', 'announce', 'create' ), | |
| 113 | - 'sanitize_callback' => 'sanitize_text_field', | |
| 114 | - ), | |
| 115 | - ), | |
| 116 | - ), | |
| 117 | - ) | |
| 118 | - ); | |
| 119 | 76 | } |
| 120 | 77 | |
| 121 | 78 | /** |
| 122 | 79 | * Get reactions for a post. |
| @@ -126,9 +83,14 @@ | ||
| 126 | 83 | * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. |
| 127 | 84 | */ |
| 128 | 85 | public function get_reactions( $request ) { |
| 129 | 86 | $post_id = $request->get_param( 'id' ); |
| 87 | + $post = \get_post( $post_id ); | |
| 130 | 88 | |
| 89 | + if ( ! $post ) { | |
| 90 | + return new \WP_Error( 'activitypub_post_not_found', 'Post not found', array( 'status' => 404 ) ); | |
| 91 | + } | |
| 92 | + | |
| 131 | 93 | $reactions = array(); |
| 132 | 94 | |
| 133 | 95 | foreach ( Comment::get_comment_types() as $type_object ) { |
| 134 | 96 | $comments = \get_comments( |
| @@ -160,19 +122,12 @@ | ||
| 160 | 122 | $reactions[ $type_object['collection'] ] = array( |
| 161 | 123 | 'label' => $label, |
| 162 | 124 | 'items' => \array_map( |
| 163 | 125 | static function ( $comment ) { |
| 164 | - /* | |
| 165 | - * Decode entities first so a stored pseudo-tag like | |
| 166 | - * `<img>` becomes a real `<img>` for the next | |
| 167 | - * step to remove, then strip any tags so the JSON | |
| 168 | - * response contains only plain text. `esc_url()` | |
| 169 | - * rejects `javascript:` and other unsafe schemes. | |
| 170 | - */ | |
| 171 | 126 | return array( |
| 172 | - 'name' => \wp_strip_all_tags( \html_entity_decode( $comment->comment_author, ENT_QUOTES ) ), | |
| 173 | - 'url' => \esc_url( $comment->comment_author_url ), | |
| 174 | - 'avatar' => \esc_url( \get_avatar_url( $comment ) ), | |
| 127 | + 'name' => html_entity_decode( $comment->comment_author ), | |
| 128 | + 'url' => $comment->comment_author_url, | |
| 129 | + 'avatar' => \get_avatar_url( $comment ), | |
| 175 | 130 | ); |
| 176 | 131 | }, |
| 177 | 132 | $comments |
| 178 | 133 | ), |
| @@ -189,13 +144,14 @@ | ||
| 189 | 144 | * |
| 190 | 145 | * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. |
| 191 | 146 | */ |
| 192 | 147 | public function get_context( $request ) { |
| 193 | - $post_id = $request->get_param( 'id' ); | |
| 148 | + $post_id = $request->get_param( 'id' ); | |
| 149 | + | |
| 194 | 150 | $collection = Replies::get_context_collection( $post_id ); |
| 195 | 151 | |
| 196 | 152 | if ( false === $collection ) { |
| 197 | - return new \WP_Error( 'activitypub_post_not_found', \__( 'Post not found', 'activitypub' ), array( 'status' => 404 ) ); | |
| 153 | + return new \WP_Error( 'activitypub_post_not_found', 'Post not found', array( 'status' => 404 ) ); | |
| 198 | 154 | } |
| 199 | 155 | |
| 200 | 156 | $response = array_merge( |
| 201 | 157 | array( |
| @@ -208,58 +164,6 @@ | ||
| 208 | 164 | $response = \rest_ensure_response( $response ); |
| 209 | 165 | $response->header( 'Content-Type', 'application/activity+json; charset=' . \get_option( 'blog_charset' ) ); |
| 210 | 166 | |
| 211 | 167 | return $response; |
| 212 | - } | |
| 213 | - | |
| 214 | - /** | |
| 215 | - * Get the remote intent template for a post. | |
| 216 | - * | |
| 217 | - * @since 8.0.0 | |
| 218 | - * | |
| 219 | - * @param \WP_REST_Request $request The request. | |
| 220 | - * | |
| 221 | - * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. | |
| 222 | - */ | |
| 223 | - public function get_remote_intent_template( $request ) { | |
| 224 | - $post_id = $request->get_param( 'id' ); | |
| 225 | - $resource = $request->get_param( 'resource' ); | |
| 226 | - $intent = $request->get_param( 'intent' ); | |
| 227 | - $post = \get_post( $post_id ); | |
| 228 | - | |
| 229 | - $template = Webfinger::get_intent_endpoint( $resource, $intent, true ); | |
| 230 | - | |
| 231 | - if ( \is_wp_error( $template ) ) { | |
| 232 | - return $template; | |
| 233 | - } | |
| 234 | - | |
| 235 | - $id = get_post_id( $post_id ); | |
| 236 | - | |
| 237 | - $url = \str_replace( | |
| 238 | - array( | |
| 239 | - '{object}', | |
| 240 | - '{uri}', | |
| 241 | - '{inReplyTo}', | |
| 242 | - '{name}', | |
| 243 | - '{target}', | |
| 244 | - ), | |
| 245 | - array( | |
| 246 | - \rawurlencode( $id ), | |
| 247 | - \rawurlencode( $id ), | |
| 248 | - \rawurlencode( $id ), | |
| 249 | - \rawurlencode( $post->post_title ), | |
| 250 | - \rawurlencode( $resource ), | |
| 251 | - ), | |
| 252 | - $template | |
| 253 | - ); | |
| 254 | - | |
| 255 | - // Remove any other GET-Params with placeholders to avoid confusion. | |
| 256 | - $url = \preg_replace( '/([&?][^=]+=\{[^}]+\})/', '', $url ); | |
| 257 | - | |
| 258 | - return \rest_ensure_response( | |
| 259 | - array( | |
| 260 | - 'url' => $url, | |
| 261 | - 'template' => $template, | |
| 262 | - ) | |
| 263 | - ); | |
| 264 | 168 | } |
| 265 | 169 | } |