PluginProbe
Parse.ly / 3.24.2
Parse.ly v3.24.2
3.24.2 3.24.1 3.24.0 3.23.7 3.23.6 3.23.5 3.23.4 3.23.3 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.17.0 3.18.0 3.18.1 3.19.0 3.19.1 3.19.2 3.19.3 3.2.0 3.2.1 3.20.0 3.20.1 3.20.2 All 106 releases
← All changes | src/rest-api/content-helper/class-endpoint-smart-linking.php +91 -25 3.19.3 → 3.24.2 View file →
@@ -1,8 +1,8 @@
1 1 <?php
2 2 /**
3 3 * Endpoint: Smart Linking
4 - * Parse.ly Content Helper `/smart-linking` API endpoint class
4 + * Parse.ly Content Intelligence `/smart-linking` API endpoint class
5 5 *
6 6 * @package Parsely
7 7 * @since 3.17.0
8 8 */
@@ -46,9 +46,9 @@
46 46 * Initializes the class.
47 47 *
48 48 * @since 3.17.0
49 49 *
50 - * @param Content_Helper_Controller $controller The content helper controller.
50 + * @param Content_Helper_Controller $controller The Content Intelligence controller.
51 51 */
52 52 public function __construct( Content_Helper_Controller $controller ) {
53 53 parent::__construct( $controller );
54 54 $this->suggestions_api = $controller->get_parsely()->get_suggestions_api();
@@ -196,8 +196,10 @@
196 196 array(
197 197 'urls' => array(
198 198 'required' => true,
199 199 'type' => 'array',
200 + 'items' => array( 'type' => 'string' ),
201 + 'maxItems' => 500,
200 202 'description' => __( 'The URLs to get meta information for.', 'wp-parsely' ),
201 203 ),
202 204 )
203 205 );
@@ -265,26 +267,30 @@
265 267 *
266 268 * Gets the smart links for a post.
267 269 *
268 270 * @since 3.16.0
271 + * @since 3.24.2 Inbound links of non-visible source posts are omitted.
269 272 *
270 273 * @param WP_REST_Request $request The request object.
271 - * @return WP_REST_Response The response object.
274 + * @return WP_REST_Response|WP_Error The response object.
272 275 */
273 - public function get_smart_links( WP_REST_Request $request ): WP_REST_Response {
274 - /**
275 - * The post object.
276 - *
277 - * @var WP_Post $post
278 - */
279 - $post = $request->get_param( 'post' );
276 + public function get_smart_links( WP_REST_Request $request ) {
277 + $post = $this->get_request_post( $request );
280 278
279 + if ( ! $post instanceof WP_Post ) {
280 + return new WP_Error(
281 + 'invalid_post',
282 + __( 'Invalid post.', 'wp-parsely' ),
283 + array( 'status' => 404 )
284 + );
285 + }
286 +
281 287 $outbound_links = Smart_Link::get_outbound_smart_links( $post->ID, Smart_Link_Status::APPLIED );
282 288 $inbound_links = Smart_Link::get_inbound_smart_links( $post->ID, Smart_Link_Status::APPLIED );
283 289
284 290 $response = array(
285 291 'outbound' => $this->serialize_smart_links( $outbound_links ),
286 - 'inbound' => $this->serialize_smart_links( $inbound_links ),
292 + 'inbound' => $this->serialize_visible_inbound_links( $inbound_links ),
287 293 );
288 294
289 295 return new WP_REST_Response( array( 'data' => $response ), 200 );
290 296 }
@@ -440,18 +446,21 @@
440 446 *
441 447 * @since 3.16.0
442 448 *
443 449 * @param WP_REST_Request $request The request object.
444 - * @return WP_REST_Response The response object.
450 + * @return WP_REST_Response|WP_Error The response object.
445 451 */
446 - public function set_smart_links( WP_REST_Request $request ): WP_REST_Response {
447 - /**
448 - * The post object.
449 - *
450 - * @var WP_Post $post
451 - */
452 - $post = $request->get_param( 'post' );
452 + public function set_smart_links( WP_REST_Request $request ) {
453 + $post = $this->get_request_post( $request );
453 454
455 + if ( ! $post instanceof WP_Post ) {
456 + return new WP_Error(
457 + 'invalid_post',
458 + __( 'Invalid post.', 'wp-parsely' ),
459 + array( 'status' => 404 )
460 + );
461 + }
462 +
454 463 /**
455 464 * Array of Smart Link models provided in the request.
456 465 *
457 466 * @var Smart_Link[] $smart_links
@@ -532,9 +541,10 @@
532 541
533 542 if ( $post_id > 0 ) {
534 543 $post = get_post( $post_id );
535 544
536 - if ( null !== $post ) {
545 + // URLs resolve by slug, irrespective of the post's status.
546 + if ( null !== $post && current_user_can( 'read_post', $post_id ) ) {
537 547 $post_type_obj = get_post_type_object( $post->post_type );
538 548 $post_type_name = $post_type_obj instanceof \WP_Post_Type ? $post_type_obj->labels->singular_name : '';
539 549
540 550 $posts_meta[] = array(
@@ -558,15 +568,20 @@
558 568 *
559 569 * The callback sets the smart link object in the request object if the parameters are valid.
560 570 *
561 571 * @since 3.16.0
572 + * @since 3.24.2 Rejects non-arrays.
562 573 * @access private
563 574 *
564 - * @param array<mixed> $params The parameters.
575 + * @param mixed $params The raw parameter value, as validation runs before type checks.
565 576 * @param WP_REST_Request $request The request object.
566 577 * @return bool Whether the parameters are valid.
567 578 */
568 - public function validate_smart_link_params( array $params, WP_REST_Request $request ): bool {
579 + public function validate_smart_link_params( $params, WP_REST_Request $request ): bool {
580 + if ( ! is_array( $params ) ) {
581 + return false;
582 + }
583 +
569 584 $required_params = array( 'uid', 'href', 'title', 'text', 'offset' );
570 585
571 586 foreach ( $required_params as $param ) {
572 587 if ( ! isset( $params[ $param ] ) ) {
@@ -595,8 +610,12 @@
595 610 if ( ! is_string( $params['href']['raw'] ) ) {
596 611 return false;
597 612 }
598 613
614 + if ( ! Smart_Link::is_valid_href( $params['href']['raw'] ) ) {
615 + return false;
616 + }
617 +
599 618 // Try to get the smart link from the UID.
600 619 $smart_link = Smart_Link::get_smart_link( $params['uid'], intval( $post_id ) );
601 620 if ( $smart_link->exists() ) {
602 621 // Update the smart link with the new data.
@@ -630,15 +649,20 @@
630 649 *
631 650 * The callback sets the smart links object in the request object if the parameters are valid.
632 651 *
633 652 * @since 3.16.0
653 + * @since 3.24.2 Rejects non-arrays.
634 654 * @access private
635 655 *
636 - * @param array<array<mixed>> $param The parameter value.
637 - * @param WP_REST_Request $request The request object.
656 + * @param mixed $param The raw parameter value, as validation runs before type checks.
657 + * @param WP_REST_Request $request The request object.
638 658 * @return bool Whether the parameter is valid.
639 659 */
640 - public function validate_multiple_smart_links( array $param, WP_REST_Request $request ): bool {
660 + public function validate_multiple_smart_links( $param, WP_REST_Request $request ): bool {
661 + if ( ! is_array( $param ) ) {
662 + return false;
663 + }
664 +
641 665 $smart_links = array();
642 666
643 667 foreach ( $param as $link ) {
644 668 if ( $this->validate_smart_link_params( $link, $request ) ) {
@@ -651,8 +675,50 @@
651 675 $request->set_param( 'smart_link', null );
652 676 $request->set_param( 'smart_links', $smart_links );
653 677
654 678 return true;
679 + }
680 +
681 + /**
682 + * Serializes inbound Smart Links, dropping the ones whose source post the
683 + * current user cannot see.
684 + *
685 + * @since 3.24.2
686 + *
687 + * @param Smart_Link[] $links The inbound Smart Links to serialize.
688 + * @return array<mixed> The serialized Smart Links.
689 + */
690 + private function serialize_visible_inbound_links( array $links ): array {
691 + $serialized = array();
692 +
693 + foreach ( $links as $link ) {
694 + $source_post_id = $link->source_post_id;
695 + $can_edit = current_user_can( 'edit_post', $source_post_id );
696 +
697 + if ( ! $can_edit && ! is_post_publicly_viewable( $source_post_id ) ) {
698 + continue;
699 + }
700 +
701 + $data = json_decode( $link->serialize(), true );
702 +
703 + if ( ! is_array( $data ) ) {
704 + continue;
705 + }
706 +
707 + // WordPress withholds a protected post's content; the anchor text
708 + // and the paragraph are both drawn from it.
709 + if ( ! $can_edit && post_password_required( $source_post_id ) ) {
710 + $data['text'] = '';
711 +
712 + if ( isset( $data['post_data'] ) && is_array( $data['post_data'] ) ) {
713 + $data['post_data']['paragraph'] = '';
714 + }
715 + }
716 +
717 + $serialized[] = $data;
718 + }
719 +
720 + return $serialized;
655 721 }
656 722
657 723 /**
658 724 * Serializes an array of Smart Links.