PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.7
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.7
16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 All 506 releases
← All changes | modules/related-posts/jetpack-related-posts.php +137 -85 13.4.5 → 16.3-a.7 View file →
@@ -6,8 +6,11 @@
6 6 */
7 7
8 8 use Automattic\Jetpack\Assets;
9 9 use Automattic\Jetpack\Blocks;
10 +use Automattic\Jetpack\Post_Media\Images;
11 +use Automattic\Jetpack\SEO\Content_Gate;
12 +use Automattic\Jetpack\Status\Request;
10 13 use Automattic\Jetpack\Sync\Settings;
11 14
12 15 /**
13 16 * The Jetpack_RelatedPosts class.
@@ -127,9 +130,9 @@
127 130
128 131 /**
129 132 * Get the blog ID.
130 133 *
131 - * @return Object current blog id.
134 + * @return mixed current blog id.
132 135 */
133 136 protected function get_blog_id() {
134 137 return Jetpack_Options::get_option( 'id' );
135 138 }
@@ -196,9 +199,9 @@
196 199 */
197 200 public function get_headline() {
198 201 $options = $this->get_options();
199 202
200 - if ( $options['show_headline'] ) {
203 + if ( ! empty( $options['show_headline'] ) ) {
201 204 $headline = sprintf(
202 205 /** This filter is already documented in modules/sharedaddy/sharing-service.php */
203 206 apply_filters( 'jetpack_sharing_headline_html', '<h3 class="jp-relatedposts-headline"><em>%s</em></h3>', esc_html( $options['headline'] ), 'related-posts' ),
204 207 esc_html( $options['headline'] )
@@ -255,10 +258,10 @@
255 258 'displayThumbnails' => $rp_settings['show_thumbnails'],
256 259 'showHeadline' => $rp_settings['show_headline'],
257 260 'displayDate' => isset( $rp_settings['show_date'] ) ? (bool) $rp_settings['show_date'] : true,
258 261 'displayContext' => isset( $rp_settings['show_context'] ) && $rp_settings['show_context'],
259 - 'postLayout' => isset( $rp_settings['layout'] ) ? $rp_settings['layout'] : 'grid',
260 - 'postsToShow' => isset( $rp_settings['size'] ) ? $rp_settings['size'] : 3,
262 + 'postLayout' => $rp_settings['layout'] ?? 'grid',
263 + 'postsToShow' => $rp_settings['size'] ?? 3,
261 264 /** This filter is already documented in modules/related-posts/jetpack-related-posts.php */
262 265 'headline' => apply_filters( 'jetpack_relatedposts_filter_headline', $this->get_headline() ),
263 266 'isServerRendered' => true,
264 267 );
@@ -453,9 +456,9 @@
453 456 * @param WP_Block $block The block object.
454 457 * @return string
455 458 */
456 459 public function render_block( $attributes, $content, $block = null ) {
457 - if ( ! jetpack_is_frontend() ) {
460 + if ( ! Request::is_frontend() ) {
458 461 return $content;
459 462 }
460 463
461 464 $wrapper_attributes = array();
@@ -460,9 +463,9 @@
460 463
461 464 $wrapper_attributes = array();
462 465 $post_id = get_the_ID();
463 466 $block_attributes = array(
464 - 'headline' => isset( $attributes['headline'] ) ? $attributes['headline'] : null,
467 + 'headline' => $attributes['headline'] ?? null,
465 468 'show_thumbnails' => isset( $attributes['displayThumbnails'] ) && $attributes['displayThumbnails'],
466 469 'show_author' => isset( $attributes['displayAuthor'] ) ? (bool) $attributes['displayAuthor'] : false,
467 470 'show_headline' => isset( $attributes['displayHeadline'] ) ? (bool) $attributes['displayHeadline'] : false,
468 471 'show_date' => isset( $attributes['displayDate'] ) ? (bool) $attributes['displayDate'] : true,
@@ -484,8 +487,21 @@
484 487 if ( empty( $related_posts ) ) {
485 488 return '';
486 489 }
487 490
491 + /*
492 + * The block renders through its own block callback, independently of the
493 + * module's front-end asset gate (enabled_for_request()). That gate only
494 + * enqueues our assets on single posts in classic themes, so a block placed
495 + * on a page (or any view the gate skips) would render as unstyled HTML.
496 + * Enqueue the stylesheet here, whenever the block actually outputs markup,
497 + * to keep it styled everywhere it can be used. We intentionally do not widen
498 + * enabled_for_request() itself: that governs the automatic the_content
499 + * insertion and was deliberately scoped in #39784 to avoid showing related
500 + * posts on classic-theme pages.
501 + */
502 + $this->enqueue_assets( false, true );
503 +
488 504 $list_markup = $this->render_post_list( $related_posts, $block_attributes );
489 505
490 506 if ( empty( $attributes['isServerRendered'] ) ) {
491 507 // The get_server_rendered_html() path won't register a block,
@@ -503,9 +519,9 @@
503 519 }
504 520 }
505 521 }
506 522
507 - if ( empty( $headline_markup ) && $block_attributes['show_headline'] === true ) {
523 + if ( empty( $headline_markup ) && $block_attributes['show_headline'] ) {
508 524 $headline = $block_attributes['headline'];
509 525 if ( strlen( trim( $headline ) ) !== 0 ) {
510 526 $headline_markup = sprintf(
511 527 '<h3 class="jp-relatedposts-headline">%1$s</h3>',
@@ -669,9 +685,9 @@
669 685 $current['show_thumbnails'] = ( isset( $input['show_thumbnails'] ) && '1' == $input['show_thumbnails'] ); // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
670 686 $current['show_date'] = ( isset( $input['show_date'] ) && '1' == $input['show_date'] ); // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
671 687 $current['show_context'] = ( isset( $input['show_context'] ) && '1' == $input['show_context'] ); // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
672 688 $current['layout'] = isset( $input['layout'] ) && in_array( $input['layout'], array( 'grid', 'list' ), true ) ? $input['layout'] : 'grid';
673 - $current['headline'] = isset( $input['headline'] ) ? $input['headline'] : esc_html__( 'Related', 'jetpack' );
689 + $current['headline'] = $input['headline'] ?? esc_html__( 'Related', 'jetpack' );
674 690 } else {
675 691 $current['enabled'] = false;
676 692 }
677 693
@@ -690,9 +706,9 @@
690 706 */
691 707 public function print_setting_html() {
692 708 $options = $this->get_options();
693 709
694 - $ui_settings_template = <<<EOT
710 + $ui_settings_template = <<<'EOT'
695 711 <p class="description">%s</p>
696 712 <ul id="settings-reading-relatedposts-customize">
697 713 <li>
698 714 <label><input name="jetpack_relatedposts[show_headline]" type="checkbox" value="1" %s /> %s</label>
@@ -726,9 +742,9 @@
726 742 esc_html__( 'Preview:', 'jetpack' )
727 743 );
728 744
729 745 if ( ! $this->allow_feature_toggle() ) {
730 - $template = <<<EOT
746 + $template = <<<'EOT'
731 747 <input type="hidden" name="jetpack_relatedposts[enabled]" value="1" />
732 748 %s
733 749 EOT;
734 750 printf(
@@ -735,9 +751,9 @@
735 751 $template, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
736 752 $ui_settings // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- data is escaped when variable is set.
737 753 );
738 754 } else {
739 - $template = <<<EOT
755 + $template = <<<'EOT'
740 756 <ul id="settings-reading-relatedposts">
741 757 <li>
742 758 <label><input type="radio" name="jetpack_relatedposts[enabled]" value="0" class="tog" %s /> %s</label>
743 759 </li>
@@ -929,9 +945,9 @@
929 945 $options['size'] = $args['size'];
930 946 }
931 947
932 948 if (
933 - ! $options['enabled']
949 + empty( $options['enabled'] )
934 950 || 0 === (int) $post_id
935 951 || empty( $options['size'] )
936 952 ) {
937 953 return array();
@@ -1288,9 +1304,9 @@
1288 1304 $related_posts[ $index ]['id'] = $real_post->ID;
1289 1305 $related_posts[ $index ]['url'] = esc_url( get_permalink( $real_post ) );
1290 1306 $related_posts[ $index ]['title'] = $this->to_utf8( $this->get_title( $real_post->post_title, $real_post->post_content, $real_post->ID ) );
1291 1307 $related_posts[ $index ]['date'] = get_the_date( '', $real_post );
1292 - $related_posts[ $index ]['excerpt'] = html_entity_decode( $this->to_utf8( $this->get_excerpt( $real_post->post_excerpt, $real_post->post_content ) ), ENT_QUOTES, 'UTF-8' );
1308 + $related_posts[ $index ]['excerpt'] = html_entity_decode( $this->to_utf8( $this->get_excerpt( $real_post->post_excerpt, $real_post->post_content, $real_post->ID ) ), ENT_QUOTES, 'UTF-8' );
1293 1309 $related_posts[ $index ]['img'] = $this->generate_related_post_image_params( $real_post->ID );
1294 1310 $related_posts[ $index ]['context'] = $this->generate_related_post_context( $real_post->ID );
1295 1311 }
1296 1312 } else {
@@ -1303,23 +1319,22 @@
1303 1319 }
1304 1320
1305 1321 $response = array(
1306 1322 'version' => self::VERSION,
1307 - 'show_thumbnails' => (bool) $options['show_thumbnails'],
1308 - 'show_date' => (bool) $options['show_date'],
1309 - 'show_context' => (bool) $options['show_context'],
1310 - 'layout' => (string) $options['layout'],
1311 - 'headline' => (string) $options['headline'],
1323 + 'show_thumbnails' => (bool) ( $options['show_thumbnails'] ?? false ),
1324 + 'show_date' => (bool) ( $options['show_date'] ?? true ),
1325 + 'show_context' => (bool) ( $options['show_context'] ?? true ),
1326 + 'layout' => (string) ( $options['layout'] ?? 'grid' ),
1327 + 'headline' => (string) ( $options['headline'] ?? '' ),
1312 1328 'items' => array(),
1313 1329 );
1314 1330
1315 - if ( count( $related_posts ) === $options['size'] ) {
1331 + if ( ! empty( $options['size'] ) && count( $related_posts ) === $options['size'] ) {
1316 1332 $response['items'] = $related_posts;
1317 1333 }
1318 1334
1319 - echo wp_json_encode( $response );
1320 -
1321 - exit();
1335 + // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
1336 + wp_send_json( $response, null, JSON_UNESCAPED_SLASHES );
1322 1337 }
1323 1338
1324 1339 /**
1325 1340 * Returns a UTF-8 encoded array of post information for the given post_id
@@ -1342,9 +1357,9 @@
1342 1357 'title' => $this->to_utf8( $this->get_title( $post->post_title, $post->post_content, $post->ID ) ),
1343 1358 'author' => $this->generate_related_post_display_author( $post->ID ),
1344 1359 'date' => get_the_date( '', $post->ID ),
1345 1360 'format' => get_post_format( $post->ID ),
1346 - 'excerpt' => html_entity_decode( $this->to_utf8( $this->get_excerpt( $post->post_excerpt, $post->post_content ) ), ENT_QUOTES, 'UTF-8' ),
1361 + 'excerpt' => html_entity_decode( $this->to_utf8( $this->get_excerpt( $post->post_excerpt, $post->post_content, $post->ID ) ), ENT_QUOTES, 'UTF-8' ),
1347 1362 /**
1348 1363 * Filters the rel attribute for the Related Posts' links.
1349 1364 *
1350 1365 * @module related-posts
@@ -1413,11 +1428,14 @@
1413 1428 apply_filters( 'the_title', $post_title, $post_id )
1414 1429 );
1415 1430 }
1416 1431
1417 - $post_title = wp_trim_words( wp_strip_all_tags( strip_shortcodes( $post_content ) ), 5, '…' );
1418 - if ( ! empty( $post_title ) ) {
1419 - return $post_title;
1432 + // Same gate as get_excerpt(): this fallback is five words of the raw body.
1433 + if ( ! Content_Gate::is_gated( $post_id ) ) {
1434 + $post_title = wp_trim_words( wp_strip_all_tags( strip_shortcodes( $post_content ) ), 5, '…' );
1435 + if ( ! empty( $post_title ) ) {
1436 + return $post_title;
1437 + }
1420 1438 }
1421 1439
1422 1440 return __( 'Untitled Post', 'jetpack' );
1423 1441 }
@@ -1426,16 +1444,20 @@
1426 1444 * Returns a plain text post excerpt for title attribute of links.
1427 1445 *
1428 1446 * @param string $post_excerpt - the post excerpt.
1429 1447 * @param string $post_content - the post content.
1448 + * @param int $post_id - the post ID.
1430 1449 * @uses strip_shortcodes, wp_strip_all_tags, wp_trim_words
1431 1450 * @return string
1432 1451 */
1433 - protected function get_excerpt( $post_excerpt, $post_content ) {
1434 - if ( empty( $post_excerpt ) ) {
1452 + protected function get_excerpt( $post_excerpt, $post_content, $post_id ) {
1453 + if ( ! empty( $post_excerpt ) ) {
1454 + $excerpt = $post_excerpt;
1455 + } elseif ( Content_Gate::is_gated( $post_id ) ) {
1456 + // The body fall-through never passes through the `the_content` paywall, so ask the gate directly.
1457 + return '';
1458 + } else {
1435 1459 $excerpt = $post_content;
1436 - } else {
1437 - $excerpt = $post_excerpt;
1438 1460 }
1439 1461
1440 1462 return wp_trim_words( wp_strip_all_tags( strip_shortcodes( $excerpt ) ), 50, '…' );
1441 1463 }
@@ -1441,12 +1463,12 @@
1441 1463 }
1442 1464
1443 1465 /**
1444 1466 * Generates the thumbnail image to be used for the post. Uses the
1445 - * image as returned by Jetpack_PostImages::get_image()
1467 + * image as returned by Images::get_image()
1446 1468 *
1447 1469 * @param int $post_id - the post ID.
1448 - * @uses self::get_options, apply_filters, Jetpack_PostImages::get_image, Jetpack_PostImages::fit_image_url
1470 + * @uses self::get_options, apply_filters, Images::get_image, Images::fit_image_url
1449 1471 * @return string
1450 1472 */
1451 1473 protected function generate_related_post_image_params( $post_id ) {
1452 1474 $image_params = array(
@@ -1479,60 +1501,70 @@
1479 1501 );
1480 1502 }
1481 1503
1482 1504 // Try to get post image.
1483 - if ( class_exists( 'Jetpack_PostImages' ) ) {
1484 - $img_url = '';
1485 - $post_image = Jetpack_PostImages::get_image(
1486 - $post_id,
1487 - $thumbnail_size
1505 + $img_url = '';
1506 + $is_gated = Content_Gate::is_gated( $post_id );
1507 + $image_args = $thumbnail_size;
1508 + if ( $is_gated ) {
1509 + // Restrict to the featured image; every other source parses the body.
1510 + $image_args = array_merge(
1511 + $image_args,
1512 + array(
1513 + 'from_slideshow' => false,
1514 + 'from_gallery' => false,
1515 + 'from_attachment' => false,
1516 + 'from_blocks' => false,
1517 + 'from_html' => false,
1518 + )
1488 1519 );
1520 + }
1521 + $post_image = Images::get_image( $post_id, $image_args );
1489 1522
1490 - if ( is_array( $post_image ) ) {
1491 - $img_url = $post_image['src'];
1492 - } elseif ( class_exists( 'Jetpack_Media_Summary' ) ) {
1493 - $media = Jetpack_Media_Summary::get( $post_id );
1523 + if ( is_array( $post_image ) ) {
1524 + $img_url = $post_image['src'];
1525 + } elseif ( ! $is_gated && class_exists( 'Jetpack_Media_Summary' ) ) {
1526 + $media = Jetpack_Media_Summary::get( $post_id );
1494 1527
1495 - if ( is_array( $media ) && ! empty( $media['image'] ) ) {
1496 - $img_url = $media['image'];
1497 - }
1528 + if ( is_array( $media ) && ! empty( $media['image'] ) ) {
1529 + $img_url = $media['image'];
1498 1530 }
1531 + }
1499 1532
1500 - if ( ! empty( $img_url ) ) {
1501 - if ( ! empty( $post_image['alt_text'] ) ) {
1502 - $image_params['alt_text'] = $post_image['alt_text'];
1503 - } else {
1504 - $image_params['alt_text'] = '';
1505 - }
1533 + if ( ! empty( $img_url ) ) {
1534 + if ( ! empty( $post_image['alt_text'] ) ) {
1535 + $image_params['alt_text'] = $post_image['alt_text'];
1536 + } else {
1537 + $image_params['alt_text'] = '';
1538 + }
1506 1539
1507 - $thumbnail_width = 0;
1508 - $thumbnail_height = 0;
1540 + $thumbnail_width = 0;
1541 + $thumbnail_height = 0;
1509 1542
1510 - if ( ! empty( $thumbnail_size['width'] ) ) {
1511 - $thumbnail_width = $thumbnail_size['width'];
1512 - $image_params['width'] = $thumbnail_width;
1513 - }
1543 + if ( ! empty( $thumbnail_size['width'] ) ) {
1544 + $thumbnail_width = $thumbnail_size['width'];
1545 + $image_params['width'] = $thumbnail_width;
1546 + }
1514 1547
1515 - if ( ! empty( $thumbnail_size['height'] ) ) {
1516 - $thumbnail_height = $thumbnail_size['height'];
1517 - $image_params['height'] = $thumbnail_height;
1518 - }
1548 + if ( ! empty( $thumbnail_size['height'] ) ) {
1549 + $thumbnail_height = $thumbnail_size['height'];
1550 + $image_params['height'] = $thumbnail_height;
1551 + }
1519 1552
1520 - $image_params['src'] = Jetpack_PostImages::fit_image_url(
1521 - $img_url,
1522 - $thumbnail_width,
1523 - $thumbnail_height
1524 - );
1553 + $image_params['src'] = Images::fit_image_url(
1554 + $img_url,
1555 + $thumbnail_width,
1556 + $thumbnail_height
1557 + );
1525 1558
1526 - // Add a srcset to handle zoomed views and high-density screens.
1527 - $srcset = Jetpack_PostImages::generate_cropped_srcset(
1528 - $post_image,
1529 - $thumbnail_width,
1530 - $thumbnail_height
1531 - );
1532 - if ( ! empty( $srcset ) ) {
1533 - $image_params['srcset'] = $srcset;
1534 - }
1559 + // Add a srcset to handle zoomed views and high-density screens.
1560 + $srcset = Images::generate_cropped_srcset(
1561 + $post_image,
1562 + $thumbnail_width,
1563 + $thumbnail_height
1564 + );
1565 + if ( ! empty( $srcset ) ) {
1566 + $image_params['srcset'] = $srcset;
1535 1567 }
1536 1568 }
1537 1569
1538 1570 return $image_params;
@@ -1756,10 +1788,10 @@
1756 1788 protected function generate_related_post_context_block( $post_id ) {
1757 1789 $categories = get_the_category( $post_id );
1758 1790 if ( is_array( $categories ) ) {
1759 1791 foreach ( $categories as $category ) {
1760 - $cat_link = get_category_link( $category );
1761 - if ( 'uncategorized' !== $category->slug && '' !== trim( $category->name ) ) {
1792 + if ( $category instanceof WP_Term && 'uncategorized' !== $category->slug && '' !== trim( $category->name ) ) {
1793 + $cat_link = get_category_link( $category );
1762 1794 return array(
1763 1795 'text' => trim( $category->name ),
1764 1796 'link' => $cat_link,
1765 1797 );
@@ -1768,10 +1800,10 @@
1768 1800 }
1769 1801 $tags = get_the_terms( $post_id, 'post_tag' );
1770 1802 if ( is_array( $tags ) ) {
1771 1803 foreach ( $tags as $tag ) {
1772 - $tag_link = get_tag_link( $tag );
1773 - if ( '' !== trim( $tag->name ) ) {
1804 + if ( $tag instanceof WP_Term && '' !== trim( $tag->name ) ) {
1805 + $tag_link = get_tag_link( $tag );
1774 1806 return array(
1775 1807 'text' => trim( $tag->name ),
1776 1808 'link' => $tag_link,
1777 1809 );
@@ -1812,9 +1844,9 @@
1812 1844 protected function generate_related_post_context( $post_id ) {
1813 1845 $categories = get_the_category( $post_id );
1814 1846 if ( is_array( $categories ) ) {
1815 1847 foreach ( $categories as $category ) {
1816 - if ( 'uncategorized' !== $category->slug && '' !== trim( $category->name ) ) {
1848 + if ( $category instanceof WP_Term && 'uncategorized' !== $category->slug && '' !== trim( $category->name ) ) {
1817 1849 $post_cat_context = sprintf(
1818 1850 // Translators: The category or tag name.
1819 1851 esc_html_x( 'In "%s"', 'in {category/tag name}', 'jetpack' ),
1820 1852 $category->name
@@ -1836,9 +1868,9 @@
1836 1868
1837 1869 $tags = get_the_terms( $post_id, 'post_tag' );
1838 1870 if ( is_array( $tags ) ) {
1839 1871 foreach ( $tags as $tag ) {
1840 - if ( '' !== trim( $tag->name ) ) {
1872 + if ( $tag instanceof WP_Term && '' !== trim( $tag->name ) ) {
1841 1873 $post_tag_context = sprintf(
1842 1874 // Translators: the category or tag name.
1843 1875 _x( 'In "%s"', 'in {category/tag name}', 'jetpack' ),
1844 1876 $tag->name
@@ -1882,13 +1914,22 @@
1882 1914
1883 1915 /**
1884 1916 * Determines if the current post is able to use related posts.
1885 1917 *
1886 - * @uses self::get_options, is_admin, is_single, apply_filters
1918 + * @since 14.0 Checks for singular instead of single to allow usage on non-posts CPTs in block themes.
1919 + * @uses self::get_options, is_admin, is_singular, apply_filters
1887 1920 * @return bool
1888 1921 */
1889 1922 protected function enabled_for_request() {
1890 - $enabled = is_single()
1923 + /*
1924 + * On block themes, allow usage on any singular view (post, page, CPT).
1925 + * On classic themes, only allow usage on single posts by default.
1926 + */
1927 + $enabled_on_singular_views = wp_is_block_theme()
1928 + ? is_singular()
1929 + : is_single();
1930 +
1931 + $enabled = $enabled_on_singular_views
1891 1932 && ! is_attachment()
1892 1933 && ! is_admin()
1893 1934 && ! is_embed()
1894 1935 && ( ! $this->allow_feature_toggle() || $this->get_option( 'enabled' ) );
@@ -1893,9 +1934,9 @@
1893 1934 && ! is_embed()
1894 1935 && ( ! $this->allow_feature_toggle() || $this->get_option( 'enabled' ) );
1895 1936
1896 1937 /**
1897 - * Filter the Enabled value to allow related posts to be shown on pages as well.
1938 + * Filter the Enabled value to allow related posts to be selectively enabled/disabled.
1898 1939 *
1899 1940 * @module related-posts
1900 1941 *
1901 1942 * @since 3.3.0
@@ -2024,8 +2065,18 @@
2024 2065 */
2025 2066 public function rest_register_related_posts() {
2026 2067 /** This filter is already documented in class.json-api-endpoints.php */
2027 2068 $post_types = apply_filters( 'rest_api_allowed_post_types', array( 'post', 'page', 'revision' ) );
2069 +
2070 + /**
2071 + * Filter the post types that are allowed to have related posts.
2072 + *
2073 + * @since 15.3
2074 + *
2075 + * @param array $post_types The post types that are allowed to have related posts.
2076 + */
2077 + $post_types = apply_filters( 'jetpack_related_posts_rest_api_allowed_post_types', $post_types );
2078 +
2028 2079 foreach ( $post_types as $post_type ) {
2029 2080 register_rest_field(
2030 2081 $post_type,
2031 2082 'jetpack-related-posts',
@@ -2060,10 +2111,11 @@
2060 2111 if ( empty( $options['enabled'] ) || ! $options['enabled'] ) {
2061 2112 return array();
2062 2113 }
2063 2114
2064 - // If the current post don't contain a Related Posts block, don't get the related posts.
2065 - if ( ! has_block( 'jetpack/related-posts' ) ) {
2115 + // If the current post doesn't contain a Related Posts block, and we're also on an admin page, don't get the related posts.
2116 + // This will ensure that if the feature is enabled, we can still retrieve Related Posts via the REST API.
2117 + if ( ! has_block( 'jetpack/related-posts' ) && is_admin() ) {
2066 2118 return array();
2067 2119 }
2068 2120
2069 2121 return $this->get_for_post_id( $object['id'], array( 'size' => 6 ) );