PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.1
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 13.9.2 14.0.1 All 504 releases
← All changes | modules/infinite-scroll/infinity.php +109 -97 13.6.216.3-a.1 View file →
@@ -2,10 +2,13 @@
2 2
3 3 // phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move classes to appropriately-named class files.
4 4
5 5 use Automattic\Jetpack\Assets;
6 -use Automattic\Jetpack\Redirect;
7 6
7 +if ( ! defined( 'ABSPATH' ) ) {
8 + exit( 0 );
9 +}
10 +
8 11 /*
9 12 Plugin Name: The Neverending Home Page.
10 13 Plugin URI: https://automattic.com/
11 14 Description: Adds infinite scrolling support to the front-end blog post view for themes, pulling the next set of posts automatically into view when the reader approaches the bottom of the page.
@@ -19,8 +22,10 @@
19 22
20 23 /**
21 24 * Class: The_Neverending_Home_Page relies on add_theme_support, expects specific
22 25 * styling from each theme; including fixed footer.
26 + *
27 + * @phan-constructor-used-for-side-effects
23 28 */
24 29 class The_Neverending_Home_Page {
25 30 /**
26 31 * Maximum allowed number of posts per page in $_REQUEST.
@@ -89,23 +94,24 @@
89 94 * @uses get_theme_support, infinite_scroll_has_footer_widgets, sanitize_title, add_action, get_option, wp_parse_args, is_active_sidebar
90 95 * @return object
91 96 */
92 97 public static function get_settings() {
98 + $defaults = array(
99 + 'type' => 'scroll', // scroll | click
100 + 'requested_type' => 'scroll', // store the original type for use when logic overrides it
101 + 'footer_widgets' => false, // true | false | sidebar_id | array of sidebar_ids -- last two are checked with is_active_sidebar
102 + 'container' => 'content', // container html id
103 + 'wrapper' => true, // true | false | html class -- the html class.
104 + 'render' => false, // optional function, otherwise the `content` template part will be used
105 + 'footer' => true, // boolean to enable or disable the infinite footer | string to provide an html id to derive footer width from
106 + 'footer_callback' => false, // function to be called to render the IS footer, in place of the default
107 + 'posts_per_page' => false,
108 + 'click_handle' => true, // boolean to enable or disable rendering the click handler div. If type is click and this is false, page must include its own trigger with the HTML ID `infinite-handle`.
109 + );
110 +
93 111 if ( self::$settings === null ) {
94 112 $css_pattern = '#[^A-Z\d\-_]#i';
95 113
96 - $defaults = array(
97 - 'type' => 'scroll', // scroll | click
98 - 'requested_type' => 'scroll', // store the original type for use when logic overrides it
99 - 'footer_widgets' => false, // true | false | sidebar_id | array of sidebar_ids -- last two are checked with is_active_sidebar
100 - 'container' => 'content', // container html id
101 - 'wrapper' => true, // true | false | html class -- the html class.
102 - 'render' => false, // optional function, otherwise the `content` template part will be used
103 - 'footer' => true, // boolean to enable or disable the infinite footer | string to provide an html id to derive footer width from
104 - 'footer_callback' => false, // function to be called to render the IS footer, in place of the default
105 - 'posts_per_page' => false, // phpcs:ignore WordPress.WP.PostsPerPage.posts_per_page_posts_per_page -- int | false to set based on IS type
106 - 'click_handle' => true, // boolean to enable or disable rendering the click handler div. If type is click and this is false, page must include its own trigger with the HTML ID `infinite-handle`.
107 - );
108 114 $settings = $defaults;
109 115 // Validate settings passed through add_theme_support()
110 116 $_settings = get_theme_support( 'infinite-scroll' );
111 117
@@ -251,9 +257,9 @@
251 257
252 258 // Ensure that IS is enabled and no footer widgets exist if the IS type isn't already "click".
253 259 if ( 'click' !== $settings['type'] ) {
254 260 // Check the setting status
255 - $disabled = '' === get_option( self::$option_name_enabled ) ? true : false;
261 + $disabled = '' === get_option( self::$option_name_enabled );
256 262
257 263 // Footer content or Reading option check
258 264 if ( $settings['footer_widgets'] || $disabled ) {
259 265 $settings['type'] = 'click';
@@ -265,22 +271,24 @@
265 271 $settings['click_handle'] = true;
266 272 }
267 273
268 274 // Store final settings in a class static to avoid reparsing
269 - /**
270 - * Filter the array of Infinite Scroll settings.
271 - *
272 - * @module infinite-scroll
273 - *
274 - * @since 2.0.0
275 - *
276 - * @param array $settings Array of Infinite Scroll settings.
277 - */
278 - self::$settings = apply_filters( 'infinite_scroll_settings', $settings );
275 + self::$settings = $settings;
279 276 }
280 277
281 - /** This filter is already documented in modules/infinite-scroll/infinity.php */
282 - return (object) apply_filters( 'infinite_scroll_settings', self::$settings );
278 + /**
279 + * Filter the array of Infinite Scroll settings.
280 + *
281 + * @module infinite-scroll
282 + *
283 + * @since 2.0.0
284 + *
285 + * @param array $settings Array of Infinite Scroll settings.
286 + */
287 + $filtered_settings = apply_filters( 'infinite_scroll_settings', self::$settings );
288 +
289 + // Ensure all properties are still set.
290 + return (object) wp_parse_args( $filtered_settings, $defaults );
283 291 }
284 292
285 293 /**
286 294 * Number of posts per page.
@@ -288,14 +296,15 @@
288 296 * @uses self::wp_query, self::get_settings, apply_filters
289 297 * @return int
290 298 */
291 299 public static function posts_per_page() {
292 - $posts_per_page = self::get_settings()->posts_per_page ? self::get_settings()->posts_per_page : self::wp_query()->get( 'posts_per_page' );
300 + $settings = self::get_settings();
301 + $posts_per_page = $settings->posts_per_page ? $settings->posts_per_page : self::wp_query()->get( 'posts_per_page' );
293 302 $posts_per_page_core_option = get_option( 'posts_per_page' );
294 303
295 304 // If Infinite Scroll is set to click, and if the site owner changed posts_per_page, let's use that.
296 305 if (
297 - 'click' === self::get_settings()->type
306 + 'click' === $settings->type
298 307 && ( '10' !== $posts_per_page_core_option )
299 308 ) {
300 309 $posts_per_page = $posts_per_page_core_option;
301 310 }
@@ -371,9 +380,9 @@
371 380 * @param bool|null null Bool if value should be overridden, null to determine from query
372 381 * @param object self::wp_query() WP_Query object for current request
373 382 * @param object self::get_settings() Infinite Scroll settings
374 383 */
375 - $override = apply_filters( 'infinite_scroll_is_last_batch', null, self::wp_query(), self::get_settings() ); // phpcs:ignore WordPress.WP.ClassNameCase.Incorrect -- False positive.
384 + $override = apply_filters( 'infinite_scroll_is_last_batch', null, self::wp_query(), self::get_settings() );
376 385 if ( is_bool( $override ) ) {
377 386 return $override;
378 387 }
379 388
@@ -381,11 +390,11 @@
381 390 $posts_per_page = self::posts_per_page();
382 391
383 392 // This is to cope with an issue in certain themes or setups where posts are returned but found_posts is 0.
384 393 if ( 0 === $entries ) {
385 - return (bool) ( ! is_countable( self::wp_query()->posts ) || ( count( self::wp_query()->posts ) < $posts_per_page ) );
394 + return ( ! is_countable( self::wp_query()->posts ) || ( count( self::wp_query()->posts ) < $posts_per_page ) );
386 395 }
387 - $paged = max( 1, self::wp_query()->get( 'paged' ) );
396 + $paged = max( 1, (int) self::wp_query()->get( 'paged' ) );
388 397
389 398 // Are there enough posts for more than the first page?
390 399 if ( $entries <= $posts_per_page ) {
391 400 return true;
@@ -431,19 +440,8 @@
431 440 if ( ! current_theme_supports( 'infinite-scroll' ) ) {
432 441 return;
433 442 }
434 443
435 - if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
436 - // This setting is no longer configurable in wp-admin on WordPress.com -- leave a pointer
437 - add_settings_field(
438 - self::$option_name_enabled,
439 - '<span id="infinite-scroll-options">' . esc_html__( 'Infinite Scroll Behavior', 'jetpack' ) . '</span>',
440 - array( $this, 'infinite_setting_html_calypso_placeholder' ),
441 - 'reading'
442 - );
443 - return;
444 - }
445 -
446 444 // Add the setting field [infinite_scroll] and place it in Settings > Reading
447 445 add_settings_field( self::$option_name_enabled, '<span id="infinite-scroll-options">' . esc_html__( 'Infinite Scroll Behavior', 'jetpack' ) . '</span>', array( $this, 'infinite_setting_html' ), 'reading' );
448 446 register_setting( 'reading', self::$option_name_enabled, 'esc_attr' );
449 447 }
@@ -448,29 +446,16 @@
448 446 register_setting( 'reading', self::$option_name_enabled, 'esc_attr' );
449 447 }
450 448
451 449 /**
452 - * Render the redirect link to the infinite scroll settings in Calypso.
453 - */
454 - public function infinite_setting_html_calypso_placeholder() {
455 - $details = get_blog_details();
456 - $writing_url = Redirect::get_url( 'calypso-settings-writing', array( 'site' => $details->domain ) );
457 - echo '<span>' . sprintf(
458 - /* translators: Variables are the enclosing link to the settings page */
459 - esc_html__( 'This option has moved. You can now manage it %1$shere%2$s.', 'jetpack' ),
460 - '<a href="' . esc_url( $writing_url ) . '">',
461 - '</a>'
462 - ) . '</span>';
463 - }
464 -
465 - /**
466 450 * HTML code to display a checkbox true/false option
467 451 * for the infinite_scroll setting.
468 452 */
469 453 public function infinite_setting_html() {
454 + $settings = self::get_settings();
470 455
471 456 // If the blog has footer widgets, show a notice instead of the checkbox
472 - if ( self::get_settings()->footer_widgets || 'click' === self::get_settings()->requested_type ) {
457 + if ( $settings->footer_widgets || 'click' === $settings->requested_type ) {
473 458 echo '<label><em>' . esc_html__( 'We&rsquo;ve changed this option to a click-to-scroll version for you since you have footer widgets in Appearance &rarr; Widgets, or your theme uses click-to-scroll as the default behavior.', 'jetpack' ) . '</em></label>';
474 459 } else {
475 460 echo '<label><input name="infinite_scroll" type="checkbox" value="1" ' . checked( 1, '' !== get_option( self::$option_name_enabled ), false ) . ' /> ' . esc_html__( 'Check to load posts as you scroll. Uncheck to show clickable button to load posts', 'jetpack' ) . '</label>';
476 461 // translators: the number of posts to show on each page load.
@@ -564,15 +549,16 @@
564 549 *
565 550 * @return string
566 551 */
567 552 public function body_class() {
568 - $classes = '';
553 + $settings = self::get_settings();
554 + $classes = '';
569 555 // Do not add infinity-scroll class if disabled through the Reading page
570 - $disabled = '' === get_option( self::$option_name_enabled ) ? true : false;
571 - if ( ! $disabled || 'click' === self::get_settings()->type ) {
556 + $disabled = '' === get_option( self::$option_name_enabled );
557 + if ( ! $disabled || 'click' === $settings->type ) {
572 558 $classes = 'infinite-scroll';
573 559
574 - if ( 'scroll' === self::get_settings()->type ) {
560 + if ( 'scroll' === $settings->type ) {
575 561 $classes .= ' neverending';
576 562 }
577 563 }
578 564
@@ -591,9 +577,13 @@
591 577
592 578 $excluded_posts = array();
593 579 // loop through posts returned by wp_query call
594 580 foreach ( self::wp_query()->get_posts() as $post ) {
581 + if ( ! $post instanceof \WP_Post ) {
582 + continue;
583 + }
595 584
585 + // @phan-suppress-next-line PhanPluginDuplicateConditionalNullCoalescing -- probably would be safe to collapse, but not changing just in case.
596 586 $orderby = isset( self::wp_query()->query_vars['orderby'] ) ? self::wp_query()->query_vars['orderby'] : '';
597 587 $post_date = ( ! empty( $post->post_date ) ? $post->post_date : false );
598 588 if ( 'modified' === $orderby || false === $post_date ) {
599 589 $post_date = $post->post_modified;
@@ -620,9 +610,9 @@
620 610 $query_vars = self::wp_query()->query_vars;
621 611 // applies to search page only
622 612 if ( true === self::wp_query()->is_search() ) {
623 613 // set post__not_in array in query_vars in case it does not exists
624 - if ( false === isset( $query_vars['post__not_in'] ) ) {
614 + if ( ! isset( $query_vars['post__not_in'] ) ) {
625 615 $query_vars['post__not_in'] = array();
626 616 }
627 617 // get excluded posts
628 618 $excluded = self::get_excluded_posts();
@@ -647,12 +637,15 @@
647 637 }
648 638
649 639 // grab the last posts in the stack as if the last one is title-matching the rest is title-matching as well
650 640 $post = end( self::wp_query()->posts );
641 + if ( ! $post instanceof WP_Post ) {
642 + return false;
643 + }
651 644
652 645 // code inspired by WP_Query class
653 646 if ( preg_match_all( '/".*?("|$)|((?<=[\t ",+])|^)[^\t ",+]+/', self::wp_query()->get( 's' ), $matches ) ) {
654 - $search_terms = self::wp_query()->query_vars['search_terms'];
647 + $search_terms = self::wp_query()->query_vars['search_terms'] ?? null;
655 648 // if the search string has only short terms or stopwords, or is 10+ terms long, match it as sentence
656 649 if ( empty( $search_terms ) || ! is_countable( $search_terms ) || count( $search_terms ) > 9 ) {
657 650 $search_terms = array( self::wp_query()->get( 's' ) );
658 651 }
@@ -693,11 +686,11 @@
693 686 if ( true === self::has_only_title_matching_posts() ) {
694 687 return false;
695 688 }
696 689
697 - $post = end( self::wp_query()->posts );
698 - $orderby = isset( self::wp_query()->query_vars['orderby'] ) ?
699 - self::wp_query()->query_vars['orderby'] : '';
690 + $post = end( self::wp_query()->posts );
691 + // @phan-suppress-next-line PhanPluginDuplicateConditionalNullCoalescing -- probably would be safe to collapse, but not changing just in case.
692 + $orderby = isset( self::wp_query()->query_vars['orderby'] ) ? self::wp_query()->query_vars['orderby'] : '';
700 693 $post_date = ( ! empty( $post->post_date ) ? $post->post_date : false );
701 694 switch ( $orderby ) {
702 695 case 'modified':
703 696 return $post->post_modified;
@@ -721,9 +714,9 @@
721 714 if ( empty( $query ) ) {
722 715 $query = self::wp_query();
723 716 }
724 717
725 - $orderby = isset( $query->query_vars['orderby'] ) ? $query->query_vars['orderby'] : '';
718 + $orderby = $query->query_vars['orderby'] ?? '';
726 719
727 720 switch ( $orderby ) {
728 721 case 'modified':
729 722 return 'post_modified';
@@ -752,13 +745,14 @@
752 745 global $wpdb;
753 746
754 747 $sort_field = self::get_query_sort_field( $query );
755 748
756 - if ( 'post_date' !== $sort_field || 'DESC' !== $_REQUEST['query_args']['order'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- no changes made to the site.
749 + if ( 'post_date' !== $sort_field ||
750 + ! isset( $_REQUEST['query_args']['order'] ) || 'DESC' !== $_REQUEST['query_args']['order'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no changes made to the site.
757 751 return $where;
758 752 }
759 753
760 - $query_before = sanitize_text_field( wp_unslash( $_REQUEST['query_before'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- no changes made to the site.
754 + $query_before = isset( $_REQUEST['query_before'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['query_before'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no changes made to the site.
761 755
762 756 if ( empty( $query_before ) ) {
763 757 return $where;
764 758 }
@@ -770,8 +764,10 @@
770 764 * Filter Infinite Scroll's SQL date query making sure post queries
771 765 * will always return results prior to (descending sort)
772 766 * or before (ascending sort) the last post date.
773 767 *
768 + * @deprecated 14.0
769 + *
774 770 * @module infinite-scroll
775 771 *
776 772 * @param string $clause SQL Date query.
777 773 * @param object $query Query.
@@ -777,11 +773,11 @@
777 773 * @param object $query Query.
778 774 * @param string $operator @deprecated Query operator.
779 775 * @param string $last_post_date @deprecated Last Post Date timestamp.
780 776 */
781 - $operator = 'ASC' === $_REQUEST['query_args']['order'] ? '>' : '<'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- no changes to the site.
782 - $last_post_date = sanitize_text_field( wp_unslash( $_REQUEST['last_post_date'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- no changes to the site.
783 - $where .= apply_filters( 'infinite_scroll_posts_where', $clause, $query, $operator, $last_post_date );
777 + $operator = '<';
778 + $last_post_date = isset( $_REQUEST['last_post_date'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['last_post_date'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no changes to the site
779 + $where .= apply_filters_deprecated( 'infinite_scroll_posts_where', array( $clause, $query, $operator, $last_post_date ), '14.0', '' );
784 780 }
785 781
786 782 return $where;
787 783 }
@@ -881,8 +877,10 @@
881 877 public function action_wp_footer_settings() {
882 878 global $wp_rewrite;
883 879 global $currentday;
884 880
881 + $settings = self::get_settings();
882 +
885 883 // Default click handle text
886 884 $click_handle_text = __( 'Older posts', 'jetpack' );
887 885
888 886 // If a single CPT is displayed, use its plural name instead of "posts"
@@ -902,11 +900,13 @@
902 900 // If not, use "Posts" without confusing the users.
903 901 if (
904 902 is_a( $taxonomy, 'WP_Taxonomy' )
905 903 && is_countable( $taxonomy->object_type )
904 + && ! empty( $taxonomy->object_type )
906 905 && count( $taxonomy->object_type ) < 2
907 906 ) {
908 - $post_type = $taxonomy->object_type[0];
907 + // It seems [0] doesn't work, as sometimes plugins can deregister a taxonomy but not reindex.
908 + $post_type = reset( $taxonomy->object_type );
909 909 }
910 910 }
911 911
912 912 if ( is_string( $post_type ) && ! empty( $post_type ) ) {
@@ -930,17 +930,17 @@
930 930 unset( $post_type );
931 931
932 932 // Base JS settings
933 933 $js_settings = array(
934 - 'id' => self::get_settings()->container,
934 + 'id' => $settings->container,
935 935 'ajaxurl' => esc_url_raw( self::ajax_url() ),
936 - 'type' => esc_js( self::get_settings()->type ),
936 + 'type' => esc_js( $settings->type ),
937 937 'wrapper' => self::has_wrapper(),
938 - 'wrapper_class' => is_string( self::get_settings()->wrapper ) ? esc_js( self::get_settings()->wrapper ) : 'infinite-wrap',
939 - 'footer' => is_string( self::get_settings()->footer ) ? esc_js( self::get_settings()->footer ) : self::get_settings()->footer,
940 - 'click_handle' => esc_js( self::get_settings()->click_handle ),
941 - 'text' => esc_js( $click_handle_text ),
942 - 'totop' => esc_js( __( 'Scroll back to top', 'jetpack' ) ),
938 + 'wrapper_class' => is_string( $settings->wrapper ) ? esc_js( $settings->wrapper ) : 'infinite-wrap',
939 + 'footer' => is_string( $settings->footer ) ? esc_js( $settings->footer ) : $settings->footer,
940 + 'click_handle' => esc_js( $settings->click_handle ),
941 + 'text' => $click_handle_text,
942 + 'totop' => __( 'Scroll back to top', 'jetpack' ),
943 943 'currentday' => $currentday,
944 944 'order' => 'DESC',
945 945 'scripts' => array(),
946 946 'styles' => array(),
@@ -955,9 +955,9 @@
955 955 'query_args' => self::get_query_vars(),
956 956 'query_before' => current_time( 'mysql' ),
957 957 'last_post_date' => self::get_last_post_date(),
958 958 'body_class' => self::body_class(),
959 - 'loading_text' => esc_js( __( 'Loading new page', 'jetpack' ) ),
959 + 'loading_text' => __( 'Loading new page', 'jetpack' ),
960 960 );
961 961
962 962 // Optional order param
963 963 if ( isset( $_REQUEST['order'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no changes made to the site.
@@ -989,9 +989,9 @@
989 989 do_action( 'infinite_scroll_wp_head' );
990 990
991 991 ?>
992 992 <script type="text/javascript">
993 - var infiniteScroll = <?php echo wp_json_encode( array( 'settings' => $js_settings ), JSON_HEX_TAG ); ?>;
993 + var infiniteScroll = <?php echo wp_json_encode( array( 'settings' => $js_settings ), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?>;
994 994 </script>
995 995 <?php
996 996 }
997 997
@@ -1108,10 +1108,10 @@
1108 1108 }
1109 1109
1110 1110 return out;
1111 1111 };
1112 - extend( window.infiniteScroll.settings.scripts, <?php echo wp_json_encode( $scripts ); ?> );
1113 - extend( window.infiniteScroll.settings.styles, <?php echo wp_json_encode( $styles ); ?> );
1112 + extend( window.infiniteScroll.settings.scripts, <?php echo wp_json_encode( $scripts, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?> );
1113 + extend( window.infiniteScroll.settings.styles, <?php echo wp_json_encode( $styles, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?> );
1114 1114 })();
1115 1115 </script>
1116 1116 <?php
1117 1117 $aria_live = 'assertive';
@@ -1373,9 +1373,9 @@
1373 1373 * @uses current_theme_supports, get_option, self::wp_query, current_user_can, apply_filters, self::get_settings, add_filter, WP_Query, remove_filter, have_posts, wp_head, do_action, add_action, this::render, this::has_wrapper, esc_attr, wp_footer, sharing_register_post_for_share_counts, get_the_id
1374 1374 */
1375 1375 public function query() {
1376 1376 if ( ! isset( $_REQUEST['page'] ) || ! current_theme_supports( 'infinite-scroll' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no changes to the site.
1377 - die;
1377 + die( 0 );
1378 1378 }
1379 1379
1380 1380 // @todo see if we should validate this nonce since we use it to form a query.
1381 1381 $page = (int) $_REQUEST['page']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- we're casting this to an int and not making changes to the site.
@@ -1380,9 +1380,9 @@
1380 1380 // @todo see if we should validate this nonce since we use it to form a query.
1381 1381 $page = (int) $_REQUEST['page']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- we're casting this to an int and not making changes to the site.
1382 1382
1383 1383 // Sanitize and set $previousday. Expected format: dd.mm.yy
1384 - if ( isset( $_REQUEST['currentday'] ) && preg_match( '/^\d{2}\.\d{2}\.\d{2}$/', $_REQUEST['currentday'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput, WordPress.Security.NonceVerification.Recommended -- manually validating, no changes to site
1384 + if ( isset( $_REQUEST['currentday'] ) && is_string( $_REQUEST['currentday'] ) && preg_match( '/^\d{2}\.\d{2}\.\d{2}$/', $_REQUEST['currentday'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput, WordPress.Security.NonceVerification.Recommended -- manually validating, no changes to site
1385 1385 global $previousday;
1386 1386 $previousday = $_REQUEST['currentday']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput
1387 1387 }
1388 1388
@@ -1397,9 +1397,9 @@
1397 1397 self::wp_query()->query_vars,
1398 1398 array(
1399 1399 'paged' => $page,
1400 1400 'post_status' => $post_status,
1401 - 'posts_per_page' => self::posts_per_page(), // phpcs:ignore WordPress.WP.PostsPerPage.posts_per_page_posts_per_page
1401 + 'posts_per_page' => self::posts_per_page(),
1402 1402 'order' => $order,
1403 1403 )
1404 1404 );
1405 1405
@@ -1431,9 +1431,9 @@
1431 1431 $GLOBALS['wp_query'] = $infinite_scroll_query;
1432 1432
1433 1433 $infinite_scroll_query->query( $query_args );
1434 1434
1435 - remove_filter( 'posts_where', array( $this, 'query_time_filter' ), 10, 2 );
1435 + remove_filter( 'posts_where', array( $this, 'query_time_filter' ), 10 );
1436 1436
1437 1437 $results = array();
1438 1438
1439 1439 if ( have_posts() ) {
@@ -1547,11 +1547,19 @@
1547 1547
1548 1548 // If sharing counts are not initialized for any reason, we initialize them here.
1549 1549 if ( ! is_array( $jetpack_sharing_counts ) ) {
1550 1550 $jetpack_sharing_counts = array();
1551 + } else {
1552 + // Filter out non-string and non-integer values to avoid warnings with array_flip.
1553 + $flippable_jetpack_sharing_counts = array_filter(
1554 + $jetpack_sharing_counts,
1555 + function ( $value ) {
1556 + return is_string( $value ) || is_int( $value );
1557 + }
1558 + );
1551 1559 }
1552 1560
1553 - $results['postflair'] = array_flip( $jetpack_sharing_counts );
1561 + $results['postflair'] = array_flip( $flippable_jetpack_sharing_counts ?? array() );
1554 1562 }
1555 1563 } else {
1556 1564 /** This action is already documented in modules/infinite-scroll/infinity.php */
1557 1565 do_action( 'infinite_scroll_empty' );
@@ -1569,9 +1577,11 @@
1569 1577 * @param array $results Array of Infinite Scroll results.
1570 1578 * @param array $query_args Array of main query arguments.
1571 1579 * @param WP_Query $wp_query WP Query.
1572 1580 */
1573 - apply_filters( 'infinite_scroll_results', $results, $query_args, self::wp_query() )
1581 + apply_filters( 'infinite_scroll_results', $results, $query_args, self::wp_query() ),
1582 + null, // @phan-suppress-current-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
1583 + JSON_UNESCAPED_SLASHES
1574 1584 );
1575 1585 }
1576 1586
1577 1587 /**
@@ -1708,15 +1718,17 @@
1708 1718 if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
1709 1719 return;
1710 1720 }
1711 1721
1722 + $settings = self::get_settings();
1723 +
1712 1724 // Bail if theme requested footer not show
1713 - if ( false === self::get_settings()->footer ) {
1725 + if ( false === $settings->footer ) {
1714 1726 return;
1715 1727 }
1716 1728
1717 1729 // We only need the new footer for the 'scroll' type
1718 - if ( 'scroll' !== self::get_settings()->type || ! self::archive_supports_infinity() ) {
1730 + if ( 'scroll' !== $settings->type || ! self::archive_supports_infinity() ) {
1719 1731 return;
1720 1732 }
1721 1733
1722 1734 if ( self::is_last_batch() ) {
@@ -1723,10 +1735,10 @@
1723 1735 return;
1724 1736 }
1725 1737
1726 1738 // Display a footer, either user-specified or a default
1727 - if ( false !== self::get_settings()->footer_callback && is_callable( self::get_settings()->footer_callback ) ) {
1728 - call_user_func( self::get_settings()->footer_callback, self::get_settings() );
1739 + if ( false !== $settings->footer_callback && is_callable( $settings->footer_callback ) ) {
1740 + call_user_func( $settings->footer_callback, $settings );
1729 1741 } else {
1730 1742 self::default_footer();
1731 1743 }
1732 1744 }
@@ -1825,9 +1837,9 @@
1825 1837
1826 1838 $scripts_data[ $key ]['extra_data'] = sprintf(
1827 1839 'window.%s = %s',
1828 1840 '_wpmejsSettings',
1829 - wp_json_encode( apply_filters( 'mejs_settings', $mejs_settings ) )
1841 + wp_json_encode( apply_filters( 'mejs_settings', $mejs_settings ), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP )
1830 1842 );
1831 1843 }
1832 1844 }
1833 1845 return $scripts_data;
@@ -1986,9 +1998,9 @@
1986 1998 ?>
1987 1999 <amp-next-page max-pages="<?php echo esc_attr( static::amp_get_max_pages() ); ?>">
1988 2000 <script type="application/json">
1989 2001 [
1990 - <?php echo wp_json_encode( $this->amp_next_page() ); ?>
2002 + <?php echo wp_json_encode( $this->amp_next_page(), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?>
1991 2003 ]
1992 2004 </script>
1993 2005 <div separator>
1994 2006 <?php
@@ -2084,9 +2096,9 @@
2084 2096 */
2085 2097 protected static function amp_get_max_pages() {
2086 2098 global $wp_query;
2087 2099
2088 - return (int) $wp_query->max_num_pages - $wp_query->query_vars['paged'];
2100 + return (int) $wp_query->max_num_pages - (int) $wp_query->query_vars['paged'];
2089 2101 }
2090 2102
2091 2103 /**
2092 2104 * Is the last page.