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-traffic-boost.php +117 -15 3.23.5 → 3.24.2 View file →
@@ -304,15 +304,18 @@
304 304 * @param WP_REST_Request $request The request object.
305 305 * @return WP_REST_Response|WP_Error The response object.
306 306 */
307 307 public function generate_link_suggestions( WP_REST_Request $request ) {
308 - /**
309 - * The post object.
310 - *
311 - * @var WP_Post $post
312 - */
313 - $post = $request->get_param( 'post' );
308 + $post = $this->get_request_post( $request );
314 309
310 + if ( ! $post instanceof WP_Post ) {
311 + return new WP_Error(
312 + 'invalid_post',
313 + __( 'Invalid post.', 'wp-parsely' ),
314 + array( 'status' => 404 )
315 + );
316 + }
317 +
315 318 /**
316 319 * The maximum number of suggestions to return.
317 320 *
318 321 * @var int $max_items
@@ -351,8 +354,12 @@
351 354 if ( is_wp_error( $inbound_suggestions ) ) {
352 355 return $inbound_suggestions;
353 356 }
354 357
358 + $inbound_suggestions = $this->filter_accessible_links(
359 + $inbound_suggestions
360 + );
361 +
355 362 $discard_result = null;
356 363
357 364 // If the discard_previous flag is set, discard the previous suggestions.
358 365 if ( $discard_previous ) {
@@ -397,15 +404,19 @@
397 404 * @param WP_REST_Request $request The request object.
398 405 * @return WP_REST_Response|WP_Error The response object.
399 406 */
400 407 public function generate_placement_suggestions( WP_REST_Request $request ) {
401 - /**
402 - * The destination post, that the inbound link links to.
403 - *
404 - * @var WP_Post $destination_post
405 - */
406 - $destination_post = $request->get_param( 'post' );
408 + // The destination post, that the inbound link links to.
409 + $destination_post = $this->get_request_post( $request );
407 410
411 + if ( ! $destination_post instanceof WP_Post ) {
412 + return new WP_Error(
413 + 'invalid_post',
414 + __( 'Invalid post.', 'wp-parsely' ),
415 + array( 'status' => 404 )
416 + );
417 + }
418 +
408 419 /**
409 420 * The source post ID, where the inbound link will be placed.
410 421 *
411 422 * @var int $source_post_id
@@ -446,8 +457,15 @@
446 457 __( 'Invalid source post.', 'wp-parsely' )
447 458 );
448 459 }
449 460
461 + $source_post_access = $this->validate_source_post_access(
462 + $source_post->ID
463 + );
464 + if ( is_wp_error( $source_post_access ) ) {
465 + return $source_post_access;
466 + }
467 +
450 468 $suggestions = $this->suggestions_api->get_inbound_link_positions(
451 469 $source_post,
452 470 $destination_post,
453 471 array(
@@ -523,9 +541,11 @@
523 541 */
524 542 public function get_existing_suggestions( WP_REST_Request $request ) {
525 543 $post_id = $request->get_param( 'post_id' );
526 544
527 - $suggestions = Inbound_Smart_Link::get_existing_suggestions( $post_id );
545 + $suggestions = $this->filter_accessible_links(
546 + Inbound_Smart_Link::get_existing_suggestions( $post_id )
547 + );
528 548
529 549 // Convert the inbound smart links to an array.
530 550 $suggestions = array_map(
531 551 function ( Inbound_Smart_Link $link ) {
@@ -566,9 +586,14 @@
566 586 public function get_inbound_smart_links( WP_REST_Request $request ) {
567 587 $post_id = $request->get_param( 'post_id' );
568 588
569 589 // Get the inbound smart links for the post.
570 - $inbound_links = Inbound_Smart_Link::get_inbound_smart_links( $post_id, Smart_Link_Status::APPLIED );
590 + $inbound_links = $this->filter_accessible_links(
591 + Inbound_Smart_Link::get_inbound_smart_links(
592 + $post_id,
593 + Smart_Link_Status::APPLIED
594 + )
595 + );
571 596
572 597 // Convert the inbound smart links to an array.
573 598 $inbound_links = array_map(
574 599 function ( Inbound_Smart_Link $link ) {
@@ -605,9 +630,9 @@
605 630 *
606 631 * @since 3.19.0
607 632 *
608 633 * @param WP_REST_Request $request The request object.
609 - * @return WP_REST_Response The response object.
634 + * @return WP_REST_Response|WP_Error The response object.
610 635 */
611 636 public function discard_suggestion( WP_REST_Request $request ) {
612 637 /**
613 638 * The inbound smart link.
@@ -615,8 +640,15 @@
615 640 * @var Inbound_Smart_Link $inbound_link
616 641 */
617 642 $inbound_link = $request->get_param( 'inbound_link' );
618 643
644 + $source_post_access = $this->validate_source_post_access(
645 + $inbound_link->source_post_id
646 + );
647 + if ( is_wp_error( $source_post_access ) ) {
648 + return $source_post_access;
649 + }
650 +
619 651 $deleted = $inbound_link->delete();
620 652
621 653 return new WP_REST_Response( array( 'data' => array( 'success' => $deleted ) ), 200 );
622 654 }
@@ -645,8 +677,15 @@
645 677 * @var bool $restore_original_link
646 678 */
647 679 $restore_original_link = $request->get_param( 'restore_original' );
648 680
681 + $source_post_access = $this->validate_source_post_access(
682 + $inbound_link->source_post_id
683 + );
684 + if ( is_wp_error( $source_post_access ) ) {
685 + return $source_post_access;
686 + }
687 +
649 688 $deleted = $inbound_link->remove( $restore_original_link );
650 689
651 690 if ( is_wp_error( $deleted ) ) {
652 691 return $deleted;
@@ -701,8 +740,15 @@
701 740 * @var bool $restore_original_link
702 741 */
703 742 $restore_original_link = (bool) $request->get_param( 'restore_original' );
704 743
744 + $source_post_access = $this->validate_source_post_access(
745 + $inbound_link->source_post_id
746 + );
747 + if ( is_wp_error( $source_post_access ) ) {
748 + return $source_post_access;
749 + }
750 +
705 751 $updated = $inbound_link->update_link_text( $text, $offset, $restore_original_link );
706 752
707 753 $post = get_post( $inbound_link->source_post_id );
708 754 if ( null === $post ) {
@@ -779,8 +825,15 @@
779 825 __( 'Smart Link already applied.', 'wp-parsely' )
780 826 );
781 827 }
782 828
829 + $source_post_access = $this->validate_source_post_access(
830 + $inbound_link->source_post_id
831 + );
832 + if ( is_wp_error( $source_post_access ) ) {
833 + return $source_post_access;
834 + }
835 +
783 836 $applied = $inbound_link->apply();
784 837
785 838 if ( is_wp_error( $applied ) ) {
786 839 return $applied;
@@ -805,8 +858,57 @@
805 858 'post_content' => $post->post_content,
806 859 ),
807 860 ),
808 861 200
862 + );
863 + }
864 +
865 + /**
866 + * Removes Smart Links whose source post the current user cannot use the
867 + * feature on.
868 + *
869 + * Also stops the list endpoints from returning data about source posts the
870 + * user has no access to.
871 + *
872 + * @since 3.23.6
873 + *
874 + * @param array<Inbound_Smart_Link> $links The Smart Links to filter.
875 + * @return array<Inbound_Smart_Link> The accessible Smart Links.
876 + */
877 + private function filter_accessible_links( array $links ): array {
878 + return array_values(
879 + array_filter(
880 + $links,
881 + function ( Inbound_Smart_Link $link ): bool {
882 + return $this->is_pch_feature_enabled_for_user(
883 + $link->source_post_id
884 + );
885 + }
886 + )
887 + );
888 + }
889 +
890 + /**
891 + * Validates that the current user can use the feature on the source post.
892 + *
893 + * The source post is the post that gets read and modified when a placement
894 + * is generated or accepted. It is not always known at permission callback
895 + * time, as it can be derived from a stored Smart Link.
896 + *
897 + * @since 3.23.6
898 + *
899 + * @param int $source_post_id The ID of the source post.
900 + * @return bool|WP_Error True if access is allowed, WP_Error otherwise.
901 + */
902 + private function validate_source_post_access( int $source_post_id ) {
903 + if ( $this->is_pch_feature_enabled_for_user( $source_post_id ) ) {
904 + return true;
905 + }
906 +
907 + return new WP_Error(
908 + 'parsely_cannot_access_source_post',
909 + __( 'You are not allowed to modify the source post.', 'wp-parsely' ),
910 + array( 'status' => 403 )
809 911 );
810 912 }
811 913
812 914 /**