PluginProbe
ElasticPress / 5.0.0
ElasticPress v5.0.0
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
elasticpress / includes / classes / Feature / RelatedPosts / RelatedPosts.php

RelatedPosts.php in ElasticPress 5.0.0, at includes/classes/Feature/RelatedPosts/RelatedPosts.php

290 lines 7.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ElasticPress related posts feature
4 *
5 * @since 2.1
6 * @package elasticpress
7 */
8
9 namespace ElasticPress\Feature\RelatedPosts;
10
11 use \WP_Query;
12 use ElasticPress\Elasticsearch;
13 use ElasticPress\Feature;
14 use ElasticPress\REST;
15 use ElasticPress\Utils;
16
17 /**
18 * Related posts feature class
19 */
20 class RelatedPosts extends Feature {
21 /**
22 * Initialize feature setting it's config
23 *
24 * @since 3.0
25 */
26 public function __construct() {
27 $this->slug = 'related_posts';
28
29 $this->title = esc_html__( 'Related Posts', 'elasticpress' );
30
31 $this->summary = '<p>' . __( 'Instantly deliver engaging and precise related content with no impact on site performance. Output related content using our block or directly in your theme using our <a href="https://elasticpress.zendesk.com/hc/en-us/articles/16671825423501-Features#related-posts">API functions</a>.', 'elasticpress' ) . '</p>';
32
33 $this->docs_url = __( 'https://elasticpress.zendesk.com/hc/en-us/articles/360050447492-Configuring-ElasticPress-via-the-Plugin-Dashboard#related-posts', 'elasticpress' );
34
35 $this->requires_install_reindex = false;
36
37 parent::__construct();
38 }
39
40 /**
41 * Format args for related posts
42 *
43 * @param array $formatted_args Formatted ES args
44 * @param array $args WP_Query args
45 * @return array
46 */
47 public function formatted_args( $formatted_args, $args ) {
48 if ( ! empty( $args['more_like'] ) ) {
49 // lets compare ES version to see if new MLT structure applies
50 $new_mlt = version_compare( (string) Elasticsearch::factory()->get_elasticsearch_version(), 6.0, '>=' );
51
52 if ( $new_mlt && is_array( $args['more_like'] ) ) {
53 foreach ( $args['more_like'] as $id ) {
54 $ids[] = array( '_id' => $id );
55 }
56 } elseif ( $new_mlt && ! is_array( $args['more_like'] ) ) {
57 $ids = array( '_id' => $args['more_like'] );
58 } else {
59 $ids = is_array( $args['more_like'] ) ? $args['more_like'] : array( $args['more_like'] );
60 }
61
62 $mlt_key = ( $new_mlt ) ? 'like' : 'ids';
63
64 $formatted_args['query'] = array(
65 'more_like_this' => array(
66 $mlt_key => $ids,
67 /**
68 * Filter fields used to determine related posts
69 *
70 * @hook ep_related_posts_fields
71 * @param {array} $fields Related post fields
72 * @return {array} New fields
73 */
74 'fields' => apply_filters(
75 'ep_related_posts_fields',
76 array(
77 'post_title',
78 'post_content',
79 'terms.post_tag.name',
80 )
81 ),
82 /**
83 * Filter related posts minimum term frequency
84 *
85 * @hook ep_related_posts_min_term_freq
86 * @param {int} $minimum Minimum term frequency
87 * @return {array} New value
88 */
89 'min_term_freq' => apply_filters( 'ep_related_posts_min_term_freq', 1 ),
90 /**
91 * Filter related posts maximum query terms
92 *
93 * @hook ep_related_posts_max_query_terms
94 * @param {int} $maximum Maximum query terms
95 * @return {array} New value
96 */
97 'max_query_terms' => apply_filters( 'ep_related_posts_max_query_terms', 12 ),
98 /**
99 * Filter related posts minimum document frequency
100 *
101 * @hook ep_related_posts_min_doc_freq
102 * @param {int} $minimum Minimum document frequency
103 * @return {array} New value
104 */
105 'min_doc_freq' => apply_filters( 'ep_related_posts_min_doc_freq', 1 ),
106 ),
107 );
108 }
109
110 return $formatted_args;
111 }
112
113 /**
114 * Search Elasticsearch for related content
115 *
116 * @param int $post_id Post ID
117 * @param int $return Return code
118 * @since 4.1.0
119 * @return WP_Query
120 */
121 public function get_related_query( $post_id, $return = 5 ) {
122 $args = array(
123 'more_like' => $post_id,
124 'posts_per_page' => $return,
125 'ep_integrate' => true,
126 'ignore_sticky_posts' => true,
127 );
128
129 /**
130 * Filter WP Query related post arguments
131 *
132 * @hook ep_find_related_args
133 * @param {array} $args WP Query arguments
134 * @since 2.1
135 * @return {array} New arguments
136 */
137 return new WP_Query( apply_filters( 'ep_find_related_args', $args ) );
138 }
139
140 /**
141 * Search Elasticsearch for related content
142 *
143 * @param int $post_id Post ID
144 * @param int $return Return code
145 *
146 * @since 2.1
147 * @uses get_related_query
148 *
149 * @return array|bool
150 */
151 public function find_related( $post_id, $return = 5 ) {
152 $query = $this->get_related_query( $post_id, $return );
153
154 if ( ! $query->have_posts() ) {
155 return false;
156 }
157 return $query->posts;
158 }
159
160 /**
161 * Setup all feature filters
162 *
163 * @since 2.1
164 */
165 public function setup() {
166 add_action( 'widgets_init', [ $this, 'register_widget' ] );
167 add_filter( 'widget_types_to_hide_from_legacy_widget_block', [ $this, 'hide_legacy_widget' ] );
168 add_filter( 'ep_formatted_args', [ $this, 'formatted_args' ], 10, 2 );
169 add_action( 'init', [ $this, 'register_block' ] );
170 add_action( 'rest_api_init', [ $this, 'setup_endpoint' ] );
171 }
172
173 /**
174 * Setup REST endpoints
175 *
176 * @since 3.2
177 */
178 public function setup_endpoint() {
179 $controller = new REST\RelatedPosts();
180 $controller->register_routes();
181 }
182
183 /**
184 * Register gutenberg block
185 *
186 * @since 3.2
187 */
188 public function register_block() {
189 /**
190 * Registering it here so translation works
191 *
192 * @see https://core.trac.wordpress.org/ticket/54797#comment:20
193 */
194 wp_register_script(
195 'ep-related-posts-block-script',
196 EP_URL . 'dist/js/related-posts-block-script.js',
197 Utils\get_asset_info( 'related-posts-block-script.js', 'dependencies' ),
198 Utils\get_asset_info( 'related-posts-block-script.js', 'version' ),
199 true
200 );
201
202 wp_set_script_translations( 'ep-related-posts-block-script', 'elasticpress' );
203
204 register_block_type_from_metadata(
205 EP_PATH . 'assets/js/blocks/related-posts',
206 [
207 'render_callback' => [ $this, 'render_block' ],
208 ]
209 );
210 }
211
212 /**
213 * Render Gutenberg block
214 *
215 * @param array $attributes Block attributes
216 * @since 3.2
217 * @return string
218 */
219 public function render_block( $attributes ) {
220 $posts = $this->find_related( get_the_ID(), $attributes['number'] );
221
222 if ( empty( $posts ) ) {
223 return '';
224 }
225
226 $class = 'wp-block-elasticpress-related-posts';
227
228 if ( ! empty( $attributes['align'] ) ) {
229 $class .= ' align' . $attributes['align'];
230 }
231
232 ob_start();
233
234 $wrapper_attributes = get_block_wrapper_attributes( [ 'class' => $class ] );
235 ?>
236 <section <?php echo wp_kses_data( $wrapper_attributes ); ?>">
237 <ul>
238 <?php foreach ( $posts as $related_post ) : ?>
239 <li>
240 <a href="<?php echo esc_url( get_permalink( $related_post->ID ) ); ?>">
241 <?php echo wp_kses( get_the_title( $related_post->ID ), 'ep-html' ); ?>
242 </a>
243 </li>
244 <?php endforeach; ?>
245 </ul>
246 </section>
247 <?php
248
249 $block_content = ob_get_clean();
250
251 return $block_content;
252 }
253
254 /**
255 * Register related posts widget
256 *
257 * @since 2.2
258 */
259 public function register_widget() {
260 register_widget( __NAMESPACE__ . '\Widget' );
261 }
262
263 /**
264 * Hide the legacy widget.
265 *
266 * Hides the legacy widget in favor of the Block when the block editor
267 * is in use and the legacy widget has not been used.
268 *
269 * @since 4.3
270 * @param array $widgets An array of excluded widget-type IDs.
271 * @return array array of excluded widget-type IDs to hide.
272 */
273 public function hide_legacy_widget( $widgets ) {
274 $widgets[] = 'ep-related-posts';
275
276 return $widgets;
277 }
278
279 /**
280 * Output feature box long
281 *
282 * @since 2.1
283 */
284 public function output_feature_box_long() {
285 ?>
286 <p><?php echo wp_kses_post( __( 'Output related content using our Widget or directly in your theme using our <a href="https://elasticpress.zendesk.com/hc/en-us/articles/16671825423501-Features#related-posts">API functions.</a>', 'elasticpress' ) ); ?></p>
287 <?php
288 }
289 }
290