PluginProbe
ElasticPress / 5.3.5
ElasticPress v5.3.5
5.3.5 5.3.4 3.6.5 3.6.6 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.7.0 4.7.1 4.7.2 5.0.0 5.0.1 5.0.2 All 108 releases
← All changes | includes/classes/Indexable/Post/Post.php +208 -82 5.0.25.3.5 View file →
@@ -7,10 +7,10 @@
7 7 */
8 8
9 9 namespace ElasticPress\Indexable\Post;
10 10
11 -use \WP_Query;
12 -use \WP_User;
11 +use WP_Query;
12 +use WP_User;
13 13 use ElasticPress\Elasticsearch;
14 14 use ElasticPress\Indexable;
15 15
16 16 if ( ! defined( 'ABSPATH' ) ) {
@@ -41,13 +41,14 @@
41 41 */
42 42 public $support_indexing_advanced_pagination = true;
43 43
44 44 /**
45 - * Create indexable and initialize dependencies
45 + * Instantiate the indexable SyncManager and QueryIntegration
46 46 *
47 - * @since 3.0
47 + * @since 5.2.0
48 + * @return void
48 49 */
49 - public function __construct() {
50 + public function setup() {
50 51 $this->labels = [
51 52 'plural' => esc_html__( 'Posts', 'elasticpress' ),
52 53 'singular' => esc_html__( 'Post', 'elasticpress' ),
53 54 ];
@@ -102,8 +103,11 @@
102 103 // Disable advanced pagination. Not useful if only indexing specific IDs.
103 104 $args['ep_indexing_advanced_pagination'] = false;
104 105 }
105 106
107 + // Explicitly set the orderby to ID to prevent accidental modifications by other code.
108 + add_filter( 'posts_orderby', [ $this, 'set_posts_orderby' ], 9999, 2 );
109 +
106 110 // Enforce the following query args during advanced pagination to ensure things work correctly.
107 111 if ( $args['ep_indexing_advanced_pagination'] ) {
108 112 $args = array_merge(
109 113 $args,
@@ -115,19 +119,21 @@
115 119 'offset' => 0,
116 120 'no_found_rows' => true,
117 121 ]
118 122 );
119 - add_filter( 'posts_where', array( $this, 'bulk_indexing_filter_posts_where' ), 9999, 2 );
123 + add_filter( 'posts_where', [ $this, 'bulk_indexing_filter_posts_where' ], 9999, 2 );
120 124
121 125 $query = new WP_Query( $args );
122 126 $total_objects = $this->get_total_objects_for_query( $args );
123 127
124 - remove_filter( 'posts_where', array( $this, 'bulk_indexing_filter_posts_where' ), 9999, 2 );
128 + remove_filter( 'posts_where', [ $this, 'bulk_indexing_filter_posts_where' ], 9999, 2 );
125 129 } else {
126 130 $query = new WP_Query( $args );
127 131 $total_objects = $query->found_posts;
128 132 }
129 133
134 + remove_filter( 'posts_orderby', [ $this, 'set_posts_orderby' ], 9999, 2 );
135 +
130 136 return [
131 137 'objects' => $query->posts,
132 138 'total_objects' => $total_objects,
133 139 ];
@@ -132,16 +138,18 @@
132 138 'total_objects' => $total_objects,
133 139 ];
134 140 }
135 141
136 - /**
137 - * Manipulate the WHERE clause of the bulk indexing query to paginate by ID in order to avoid performance issues with SQL offset.
138 - *
139 - * @param string $where The current $where clause.
140 - * @param WP_Query $query WP_Query object.
141 - * @return string WHERE clause with our pagination added if needed.
142 - */
142 + /**
143 + * Manipulate the WHERE clause of the bulk indexing query to paginate by ID in order to avoid performance issues with SQL offset.
144 + *
145 + * @param string $where The current $where clause.
146 + * @param WP_Query $query WP_Query object.
147 + * @return string WHERE clause with our pagination added if needed.
148 + */
143 149 public function bulk_indexing_filter_posts_where( $where, $query ) {
150 + global $wpdb;
151 +
144 152 $using_advanced_pagination = $query->get( 'ep_indexing_advanced_pagination', false );
145 153
146 154 if ( $using_advanced_pagination ) {
147 155 $requested_upper_limit_id = $query->get( 'ep_indexing_upper_limit_object_id', PHP_INT_MAX );
@@ -159,10 +167,10 @@
159 167 return $where;
160 168 }
161 169
162 170 $range = [
163 - 'upper_limit' => "{$GLOBALS['wpdb']->posts}.ID <= {$upper_limit_range_post_id}",
164 - 'lower_limit' => "{$GLOBALS['wpdb']->posts}.ID >= {$requested_lower_limit_post_id}",
171 + 'upper_limit' => "{$wpdb->posts}.ID <= {$upper_limit_range_post_id}",
172 + 'lower_limit' => "{$wpdb->posts}.ID >= {$requested_lower_limit_post_id}",
165 173 ];
166 174
167 175 // Skip the end range if it's unnecessary.
168 176 $skip_ending_range = 0 === $requested_lower_limit_post_id;
@@ -559,11 +567,8 @@
559 567
560 568 /**
561 569 * Filters the image size to use when indexing the post thumbnail.
562 570 *
563 - * Defaults to the `woocommerce_thumbnail` size if WooCommerce is in
564 - * use. Otherwise the `thumbnail` size is used.
565 - *
566 571 * @hook ep_thumbnail_image_size
567 572 * @since 4.0.0
568 573 * @param {string|int[]} $image_size Image size. Can be any registered
569 574 * image size name, or an array of
@@ -573,25 +578,31 @@
573 578 * @return {array} Image size to pass to wp_get_attachment_image_src().
574 579 */
575 580 $image_size = apply_filters(
576 581 'ep_post_thumbnail_image_size',
577 - function_exists( 'WC' ) ? 'woocommerce_thumbnail' : 'thumbnail',
582 + 'medium',
578 583 $post
579 584 );
580 585
581 - $image_src = wp_get_attachment_image_src( $attachment_id, $image_size );
586 + $image = wp_get_attachment_image_src( $attachment_id, $image_size );
582 587 $image_alt = trim( wp_strip_all_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) );
583 588
584 - if ( ! $image_src ) {
589 + if ( ! $image ) {
585 590 return null;
586 591 }
587 592
593 + list( $src, $width, $height ) = $image;
594 +
595 + $image_meta = wp_get_attachment_metadata( $attachment_id );
596 + $srcset = wp_calculate_image_srcset( [ absint( $width ), absint( $height ) ], $src, $image_meta, $attachment_id );
597 +
588 598 return [
589 599 'ID' => $attachment_id,
590 - 'src' => $image_src[0],
591 - 'width' => $image_src[1],
592 - 'height' => $image_src[2],
600 + 'src' => $src,
601 + 'width' => $width,
602 + 'height' => $height,
593 603 'alt' => $image_alt,
604 + 'srcset' => $srcset,
594 605 ];
595 606 }
596 607
597 608 /**
@@ -596,9 +607,9 @@
596 607
597 608 /**
598 609 * Prepare date terms to send to ES.
599 610 *
600 - * @param string $date_to_prepare Post date
611 + * @param null|string $date_to_prepare Post date
601 612 * @since 0.1.4
602 613 * @return array
603 614 */
604 615 public function prepare_date_terms( $date_to_prepare ) {
@@ -617,9 +628,9 @@
617 628 ];
618 629
619 630 // Combine all the date term formats and perform one single call to date_i18n() for performance.
620 631 $date_format = implode( '||', array_values( $terms_to_prepare ) );
621 - $combined_dates = explode( '||', date_i18n( $date_format, strtotime( $date_to_prepare ) ) );
632 + $combined_dates = explode( '||', date_i18n( $date_format, strtotime( (string) $date_to_prepare ) ) );
622 633
623 634 // Then split up the results for individual indexing.
624 635 $date_terms = [];
625 636 foreach ( $terms_to_prepare as $term_name => $date_format ) {
@@ -754,9 +765,9 @@
754 765 * @param \WP_Term $term Term to be formatted
755 766 * @param int $post_id The post ID
756 767 * @return array
757 768 */
758 - private function get_formatted_term( \WP_Term $term, int $post_id ) : array {
769 + private function get_formatted_term( \WP_Term $term, int $post_id ): array {
759 770 $formatted_term = [
760 771 'term_id' => $term->term_id,
761 772 'slug' => $term->slug,
762 773 'name' => $term->name,
@@ -809,9 +820,8 @@
809 820 wp_cache_set( $cache_key, $term_orders );
810 821 }
811 822
812 823 return isset( $term_orders[ $term_taxonomy_id ] ) ? (int) $term_orders[ $term_taxonomy_id ] : 0;
813 -
814 824 }
815 825
816 826 /**
817 827 * Checks if meta key is allowed
@@ -901,9 +911,8 @@
901 911 * @since 3.4
902 912 * @return {array} Prepared meta
903 913 */
904 914 return apply_filters( 'ep_prepared_post_meta', $prepared_meta, $post );
905 -
906 915 }
907 916
908 917 /**
909 918 * Format WP query args for ES
@@ -933,26 +942,26 @@
933 942 $formatted_args = $this->maybe_add_sticky_posts( $formatted_args, $args );
934 943 $formatted_args = $this->maybe_set_aggs( $formatted_args, $args, $filters );
935 944
936 945 /**
937 - * Filter formatted Elasticsearch [ost ]query (entire query)
946 + * Filter formatted Elasticsearch query (entire query)
938 947 *
939 948 * @hook ep_formatted_args
940 949 * @param {array} $formatted_args Formatted Elasticsearch query
941 - * @param {array} $query_vars Query variables
942 - * @param {array} $query Query part
943 - * @return {array} New query
950 + * @param {array} $args WP_Query variables
951 + * @param {object} $wp_query WP_Query object
952 + * @return {array} New query
944 953 */
945 954 $formatted_args = apply_filters( 'ep_formatted_args', $formatted_args, $args, $wp_query );
946 955
947 956 /**
948 - * Filter formatted Elasticsearch [ost ]query (entire query)
957 + * Filter formatted Elasticsearch post query (entire query)
949 958 *
950 959 * @hook ep_post_formatted_args
951 960 * @param {array} $formatted_args Formatted Elasticsearch query
952 - * @param {array} $query_vars Query variables
953 - * @param {array} $query Query part
954 - * @return {array} New query
961 + * @param {array} $args WP_Query variables
962 + * @param {object} $wp_query WP_Query object
963 + * @return {array} New query
955 964 */
956 965 $formatted_args = apply_filters( 'ep_post_formatted_args', $formatted_args, $args, $wp_query );
957 966
958 967 return $formatted_args;
@@ -1189,9 +1198,9 @@
1189 1198 $orderby_clause = $value;
1190 1199 $order = $default_order;
1191 1200 }
1192 1201
1193 - if ( empty( $orderby_clause ) || 'rand' === $orderby_clause ) {
1202 + if ( empty( $orderby_clause ) || 'rand' === $orderby_clause || preg_match( '/^rand\((\d+)\)$/i', $orderby_clause ) ) {
1194 1203 continue;
1195 1204 }
1196 1205
1197 1206 /**
@@ -1417,9 +1426,9 @@
1417 1426 * @param array $search_fields Search fields
1418 1427 * @param array $query_vars Query vars
1419 1428 * @return SearchAlgorithm Instance of search algorithm to be used
1420 1429 */
1421 - public function get_search_algorithm( string $search_text, array $search_fields, array $query_vars ) : \ElasticPress\SearchAlgorithm {
1430 + public function get_search_algorithm( string $search_text, array $search_fields, array $query_vars ): \ElasticPress\SearchAlgorithm {
1422 1431 $search_algorithm_version_option = \ElasticPress\Utils\get_option( 'ep_search_algorithm_version', '4.0' );
1423 1432
1424 1433 /**
1425 1434 * Filter the algorithm version to be used.
@@ -1476,8 +1485,9 @@
1476 1485 'date' => $this->parse_date( $args ),
1477 1486 'meta_query' => $this->parse_meta_queries( $args ),
1478 1487 'post_type' => $this->parse_post_type( $args ),
1479 1488 'post_status' => $this->parse_post_status( $args ),
1489 + 'painless_script' => $this->painless_script_query( $args ),
1480 1490 ];
1481 1491
1482 1492 /**
1483 1493 * Filter the ES filters that will be applied to the ES query.
@@ -1681,19 +1691,33 @@
1681 1691 $formatted_args['sort'] = $default_sort;
1682 1692 }
1683 1693
1684 1694 /**
1685 - * Order by 'rand' support
1695 + * Order by 'rand' and 'Rand(x)' support
1686 1696 *
1687 1697 * Ref: https://github.com/elastic/elasticsearch/issues/1170
1688 1698 */
1689 1699 if ( ! empty( $args['orderby'] ) ) {
1690 - $orderbys = $this->get_orderby_array( $args['orderby'] );
1691 - if ( in_array( 'rand', $orderbys, true ) ) {
1692 - $formatted_args_query = $formatted_args['query'];
1693 - $formatted_args['query'] = [];
1694 - $formatted_args['query']['function_score']['query'] = $formatted_args_query;
1695 - $formatted_args['query']['function_score']['random_score'] = (object) [];
1700 + $orderbys = $this->get_orderby_array( $args['orderby'] );
1701 + $random_orderbys = preg_grep( '/^rand(?:\((\d+)\))?$/i', $orderbys );
1702 +
1703 + if ( ! empty( $random_orderbys ) ) {
1704 + $formatted_args_query = $formatted_args['query'];
1705 + $formatted_args['query'] = [];
1706 + $formatted_args['query']['function_score']['query'] = $formatted_args_query;
1707 +
1708 + // Get the first random orderby found.
1709 + $random_orderby = reset( $random_orderbys );
1710 +
1711 + // check if rand with seed.
1712 + if ( preg_match( '/^rand\((\d+)\)$/i', $random_orderby, $matches ) ) {
1713 + $formatted_args['query']['function_score']['random_score'] = (object) [
1714 + 'seed' => (int) $matches[1],
1715 + 'field' => '_seq_no',
1716 + ];
1717 + } else {
1718 + $formatted_args['query']['function_score']['random_score'] = (object) [];
1719 + }
1696 1720 }
1697 1721 }
1698 1722
1699 1723 return $formatted_args;
@@ -2022,9 +2046,12 @@
2022 2046 $args_post_mime_type[] = $mime_type;
2023 2047 } else {
2024 2048 $filtered_mime_type_by_type = wp_match_mime_types( $mime_type, wp_get_mime_types() );
2025 2049
2026 - $args_post_mime_type = array_merge( $args_post_mime_type, $filtered_mime_type_by_type[ $mime_type ] );
2050 + $args_post_mime_type = array_merge(
2051 + $args_post_mime_type,
2052 + $filtered_mime_type_by_type[ $mime_type ] ?? [ $mime_type ]
2053 + );
2027 2054 }
2028 2055 }
2029 2056
2030 2057 return [
@@ -2066,8 +2093,10 @@
2066 2093 $date_filter = $date_query->get_es_filter();
2067 2094
2068 2095 if ( array_key_exists( 'and', $date_filter ) ) {
2069 2096 return $date_filter['and'];
2097 + } elseif ( array_key_exists( 'or', $date_filter ) ) {
2098 + return $date_filter['or'];
2070 2099 }
2071 2100 }
2072 2101 }
2073 2102
@@ -2201,31 +2230,10 @@
2201 2230 'post_status' => is_array( $post_status ) ? array_values( $post_status ) : $post_status,
2202 2231 ],
2203 2232 ];
2204 2233 }
2205 - } else {
2234 + } elseif ( ! is_admin() ) {
2206 2235 $statuses = get_post_stati( array( 'public' => true ) );
2207 -
2208 - if ( is_admin() ) {
2209 - /**
2210 - * In the admin we will add protected and private post statuses to the default query
2211 - * per WP default behavior.
2212 - */
2213 - $statuses = array_merge(
2214 - $statuses,
2215 - get_post_stati(
2216 - array(
2217 - 'protected' => true,
2218 - 'show_in_admin_all_list' => true,
2219 - )
2220 - )
2221 - );
2222 -
2223 - if ( is_user_logged_in() ) {
2224 - $statuses = array_merge( $statuses, get_post_stati( array( 'private' => true ) ) );
2225 - }
2226 - }
2227 -
2228 2236 $statuses = array_values( $statuses );
2229 2237
2230 2238 $post_status_filter_type = 'terms';
2231 2239
@@ -2239,8 +2247,55 @@
2239 2247 return [];
2240 2248 }
2241 2249
2242 2250 /**
2251 + * Parse the `painless_script` WP Query arg and transform it into an ES query clause.
2252 + *
2253 + * @since 5.3.0
2254 + * @param array $args WP_Query arguments
2255 + * @return array
2256 + */
2257 + protected function painless_script_query( $args ) {
2258 + $scripts = $args['painless_script'] ?? [];
2259 +
2260 + if ( empty( $scripts ) ) {
2261 + return [];
2262 + }
2263 +
2264 + $normalized_scripts = array_map(
2265 + function ( $script_config ) {
2266 + return is_string( $script_config )
2267 + ? [ 'source' => $script_config ]
2268 + : $script_config;
2269 + },
2270 + $scripts
2271 + );
2272 +
2273 + $normalized_scripts = array_filter( $normalized_scripts );
2274 +
2275 + $filters = [];
2276 + foreach ( $normalized_scripts as $script_config ) {
2277 + $script_query = [ 'source' => $script_config['source'] ];
2278 +
2279 + if ( ! empty( $script_config['params'] ) && is_array( $script_config['params'] ) ) {
2280 + $script_query['params'] = $script_config['params'];
2281 + }
2282 +
2283 + $filters['bool']['must'][] = [
2284 + 'bool' => [
2285 + 'filter' => [
2286 + 'script' => [
2287 + 'script' => $script_query,
2288 + ],
2289 + ],
2290 + ],
2291 + ];
2292 + }
2293 +
2294 + return $filters;
2295 + }
2296 +
2297 + /**
2243 2298 * If in a search context set search fields, otherwise query everything.
2244 2299 *
2245 2300 * @since 4.4.0
2246 2301 * @param array $formatted_args Formatted Elasticsearch query
@@ -2464,9 +2519,9 @@
2464 2519 * @since 4.4.0
2465 2520 * @param string $field Field name
2466 2521 * @return string
2467 2522 */
2468 - protected function parse_tax_query_field( string $field ) : string {
2523 + protected function parse_tax_query_field( string $field ): string {
2469 2524
2470 2525 $from_to = [
2471 2526 'name' => 'name.raw',
2472 2527 'slug' => 'slug',
@@ -2589,13 +2644,11 @@
2589 2644
2590 2645 if ( true === $allowed_protected_keys || in_array( $key, $allowed_protected_keys, true ) ) {
2591 2646 $allow_index = true;
2592 2647 }
2593 - } else {
2648 + } elseif ( true !== $excluded_public_keys && ! in_array( $key, $excluded_public_keys, true ) ) {
2594 2649
2595 - if ( true !== $excluded_public_keys && ! in_array( $key, $excluded_public_keys, true ) ) {
2596 2650 $allow_index = true;
2597 - }
2598 2651 }
2599 2652
2600 2653 /**
2601 2654 * Filter force whitelisting a meta key
@@ -2619,9 +2672,9 @@
2619 2672 * @since 4.4.0
2620 2673 * @param bool $force_refresh Whether to use or not a cached value. Default false, use cached.
2621 2674 * @return array
2622 2675 */
2623 - public function get_distinct_meta_field_keys_db( bool $force_refresh = false ) : array {
2676 + public function get_distinct_meta_field_keys_db( bool $force_refresh = false ): array {
2624 2677 global $wpdb;
2625 2678
2626 2679 /**
2627 2680 * Short-circuits the process of getting distinct meta keys from the database.
@@ -2705,9 +2758,9 @@
2705 2758 * @param string $post_type Post type slug
2706 2759 * @param bool $force_refresh Whether to use or not a cached value. Default false, use cached.
2707 2760 * @return array
2708 2761 */
2709 - public function get_distinct_meta_field_keys_db_per_post_type( string $post_type, bool $force_refresh = false ) : array {
2762 + public function get_distinct_meta_field_keys_db_per_post_type( string $post_type, bool $force_refresh = false ): array {
2710 2763 $allowed_screen = 'status-report' === \ElasticPress\Screen::factory()->get_current_screen();
2711 2764
2712 2765 /**
2713 2766 * Filter if the current screen is allowed or not to use the function.
@@ -2793,9 +2846,9 @@
2793 2846 * @param string $post_type Post type slug
2794 2847 * @param bool $force_refresh Whether to use or not a cached value. Default false, use cached.
2795 2848 * @return array
2796 2849 */
2797 - public function get_indexable_meta_keys_per_post_type( string $post_type, bool $force_refresh = false ) : array {
2850 + public function get_indexable_meta_keys_per_post_type( string $post_type, bool $force_refresh = false ): array {
2798 2851 $mock_post = new \WP_Post( (object) [ 'post_type' => $post_type ] );
2799 2852 $meta_keys = $this->get_distinct_meta_field_keys_db_per_post_type( $post_type, $force_refresh );
2800 2853
2801 2854 $fake_meta_values = array_combine( $meta_keys, array_fill( 0, count( $meta_keys ), 'test-value' ) );
@@ -2820,18 +2873,21 @@
2820 2873 * @since 4.4.0
2821 2874 * @param bool $force_refresh Whether to use or not a cached value. Default false, use cached.
2822 2875 * @return array
2823 2876 */
2824 - public function get_predicted_indexable_meta_keys( bool $force_refresh = false ) : array {
2877 + public function get_predicted_indexable_meta_keys( bool $force_refresh = false ): array {
2825 2878 $empty_post = new \WP_Post( (object) [] );
2826 2879 $meta_keys = $this->get_distinct_meta_field_keys_db( $force_refresh );
2827 2880
2828 - $fake_meta_values = array_combine( $meta_keys, array_fill( 0, count( $meta_keys ), 'test-value' ) );
2881 + $fake_meta_values = array_combine(
2882 + $meta_keys,
2883 + array_fill( 0, count( $meta_keys ), $this->get_test_meta_value() )
2884 + );
2829 2885 $filtered_meta = apply_filters( 'ep_prepare_meta_data', $fake_meta_values, $empty_post );
2830 2886
2831 2887 $all_keys = array_filter(
2832 2888 array_keys( $filtered_meta ),
2833 - function( $meta_key ) use ( $empty_post ) {
2889 + function ( $meta_key ) use ( $empty_post ) {
2834 2890 return $this->is_meta_allowed( $meta_key, $empty_post );
2835 2891 }
2836 2892 );
2837 2893
@@ -2840,8 +2896,26 @@
2840 2896 return $all_keys;
2841 2897 }
2842 2898
2843 2899 /**
2900 + * Return the value used to fill meta fields while predicting indexable content.
2901 + *
2902 + * @since 5.1.0
2903 + * @return string
2904 + */
2905 + public function get_test_meta_value(): string {
2906 + /**
2907 + * Filter the value used to fill meta fields while predicting indexable content.
2908 + *
2909 + * @hook ep_post_test_meta_value
2910 + * @since 5.1.0
2911 + * @param {string} $test_meta_value The test meta value. Default: test-value
2912 + * @return {string} New test meta value
2913 + */
2914 + return (string) apply_filters( 'ep_post_test_meta_value', 'test-value' );
2915 + }
2916 +
2917 + /**
2844 2918 * Given a post type, *yields* their Post IDs.
2845 2919 *
2846 2920 * If post IDs are found, this function will return a PHP Generator. To avoid timeout, it will yield 8 groups or 11,000 IDs.
2847 2921 *
@@ -2909,9 +2983,9 @@
2909 2983 * @since 4.4.0
2910 2984 * @param array $post_ids Set of post IDs
2911 2985 * @return array
2912 2986 */
2913 - protected function get_meta_keys_from_post_ids( array $post_ids ) : array {
2987 + protected function get_meta_keys_from_post_ids( array $post_ids ): array {
2914 2988 global $wpdb;
2915 2989
2916 2990 if ( empty( $post_ids ) ) {
2917 2991 return [];
@@ -2937,9 +3011,9 @@
2937 3011 * @since 4.5.0
2938 3012 * @param array $mapping The mapping array
2939 3013 * @return array
2940 3014 */
2941 - public function add_term_suggest_field( array $mapping ) : array {
3015 + public function add_term_suggest_field( array $mapping ): array {
2942 3016 if ( version_compare( (string) Elasticsearch::factory()->get_elasticsearch_version(), '7.0', '<' ) ) {
2943 3017 $mapping_properties = &$mapping['mappings']['post']['properties'];
2944 3018 } else {
2945 3019 $mapping_properties = &$mapping['mappings']['properties'];
@@ -2953,6 +3027,58 @@
2953 3027 'search_analyzer' => 'standard',
2954 3028 );
2955 3029
2956 3030 return $mapping;
3031 + }
3032 +
3033 + /**
3034 + * Return all meta data added to the Weighting Dashboard plus all allowed keys via code.
3035 + *
3036 + * @since 5.1.4
3037 + * @return array
3038 + */
3039 + public function get_all_allowed_metas_manual(): array {
3040 + $post_types = \ElasticPress\Indexables::factory()->get( 'post' )->get_indexable_post_types();
3041 + $search_feature = \ElasticPress\Features::factory()->get_registered_feature( 'search' );
3042 + $weighting = $search_feature->weighting->get_weighting_configuration_with_defaults();
3043 + $fake_post = new \WP_Post( new \stdClass() );
3044 +
3045 + $all_allowed_metas = [];
3046 + foreach ( $post_types as $post_type ) {
3047 + $fake_post->post_type = $post_type;
3048 + $allowed_protected_keys = apply_filters( 'ep_prepare_meta_allowed_protected_keys', [], $fake_post );
3049 +
3050 + $selected_keys = [];
3051 + if ( ! empty( $weighting[ $post_type ] ) ) {
3052 + $selected_keys = array_map(
3053 + function ( $field ) {
3054 + if ( false === strpos( $field, 'meta.' ) ) {
3055 + return null;
3056 + }
3057 + $field_name_parts = explode( '.', $field );
3058 + return $field_name_parts[1];
3059 + },
3060 + array_keys( $weighting[ $post_type ] )
3061 + );
3062 + $selected_keys = array_filter( $selected_keys );
3063 + }
3064 +
3065 + $allowed_keys = apply_filters( 'ep_prepare_meta_allowed_keys', array_merge( $allowed_protected_keys, $selected_keys ), $fake_post );
3066 +
3067 + $all_allowed_metas = array_merge( $all_allowed_metas, $allowed_keys );
3068 + }
3069 +
3070 + return array_unique( $all_allowed_metas );
3071 + }
3072 +
3073 + /**
3074 + * Sets the ORDER BY clause to sort posts by post ID in descending order.
3075 + *
3076 + * @return string The modified order by clause.
3077 + *
3078 + * @since 5.2.0
3079 + */
3080 + public function set_posts_orderby(): string {
3081 + global $wpdb;
3082 + return "{$wpdb->posts}.ID DESC";
2957 3083 }
2958 3084 }