PluginProbe
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News / 4.0.7
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News v4.0.7
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 2.3.5 2.3.6 2.4.0 2.4.1 2.4.10 2.4.11 2.4.12 2.4.13 2.4.14 2.4.15 2.4.16 2.4.17 2.4.18 2.4.19 2.4.2 2.4.20 2.4.21 All 88 releases
post-carousel / blocks / class-smart-post-show-blocks.php

class-smart-post-show-blocks.php in Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News 4.0.7, at blocks/class-smart-post-show-blocks.php

1,428 lines 43.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The plugin gutenberg block Initializer.
4 *
5 * @link https://shapedplugin.com/
6 * @since 2.0.0
7 *
8 * @package Smart_Post_Show
9 * @subpackage Smart_Post_Show/blocks
10 * @author ShapedPlugin <[email protected]>
11 */
12
13 use SmartPostShow\Blocks\Helper;
14 use SmartPostShow\Blocks\Template;
15 use SmartPostShow\Blocks\Template_Part;
16 use SmartPostShow\Blocks\Premade_Design_Library;
17 use SmartPostShow\Blocks\SPS_Table_Of_Contents;
18 use SmartPostShow\Blocks\Assets_Manager;
19
20
21 // Exit if accessed directly.
22 if ( ! defined( 'ABSPATH' ) ) {
23 exit;
24 }
25
26 if ( ! class_exists( 'Sp_Smart_Post_Blocks_Init' ) ) {
27 /**
28 * Smart_Post_Show_Blocks_Init class.
29 */
30 class Sp_Smart_Post_Blocks_Init {
31
32 /**
33 * This plugin's instance.
34 *
35 * @var Blocks
36 */
37 private static $instance;
38 /**
39 * Block slugs.
40 *
41 * @var array
42 */
43 private $block_slugs = array();
44
45 /**
46 * Modules Attributes.
47 *
48 * @var array
49 */
50 private $modules_default = array(
51 array(
52 'module_name' => 'taxonomy',
53 'show' => true,
54 ),
55 array(
56 'module_name' => 'post-badges',
57 'show' => true,
58 ),
59 array(
60 'module_name' => 'image-gallery',
61 'show' => true,
62 ),
63 array(
64 'module_name' => 'featured-video',
65 'show' => true,
66 ),
67 array(
68 'module_name' => 'back-to-top',
69 'show' => false,
70 ),
71 array(
72 'module_name' => 'saved-template',
73 'show' => true,
74 ),
75 array(
76 'module_name' => 'template-library',
77 'show' => true,
78 ),
79 );
80
81 /**
82 * Integration Attributes.
83 *
84 * @var array
85 */
86 private $integration_default = array(
87 array(
88 'name' => 'elementor',
89 'show' => true,
90 ),
91 array(
92 'name' => 'divi',
93 'show' => true,
94 ),
95 array(
96 'name' => 'wpbakery',
97 'show' => true,
98 ),
99 array(
100 'name' => 'oxygen',
101 'show' => true,
102 ),
103 array(
104 'name' => 'beaver',
105 'show' => true,
106 ),
107 array(
108 'name' => 'bricks',
109 'show' => true,
110 ),
111 );
112
113 /**
114 * Block full name.
115 *
116 * @var array
117 */
118 private $block_full_name = array();
119
120 /**
121 * Icon list.
122 *
123 * @var array
124 */
125 private $icon_list = array();
126
127 /**
128 * Modules list.
129 *
130 * @var array
131 */
132 private $modules_list = array();
133
134 /**
135 * Main Blocks Instance.
136 *
137 * Insures that only one instance of Blocks exists in memory at any one
138 * time. Also prevents needing to define globals all over the place.
139 *
140 * @static
141 * @return object|Blocks The one true Blocks
142 */
143 public static function instance() {
144 if ( ! isset( self::$instance ) ) {
145 self::$instance = new Sp_Smart_Post_Blocks_Init();
146 self::$instance->init();
147 }
148 return self::$instance;
149 }
150
151 /**
152 * Load actions.
153 *
154 * @return void
155 */
156 private function init() {
157 $this->load_core_files();
158 $this->block_slugs = Helper::get_block_slugs();
159 $this->load_block_classes();
160 $this->register_block_settings_option();
161 $this->register_blocks();
162 Helper::set_icon_list();
163 Helper::set_modules_show_hide();
164 Helper::set_integration_options();
165
166 $this->icon_list = Helper::get_icon_list();
167 $this->modules_list = Helper::get_modules_show_hide();
168 Sp_Smart_Post_Blocks_Query::instance();
169
170 new Premade_Design_Library();
171 new Assets_Manager( $this->block_slugs );
172 new SPS_Table_Of_Contents();
173 // Create Block category.
174 if ( version_compare( $GLOBALS['wp_version'], '5.7', '<' ) ) {
175 add_filter( 'block_categories', array( $this, 'register_block_category' ), 999999999, 2 );
176 } else {
177 add_filter( 'block_categories_all', array( $this, 'register_block_category' ), 999999999, 2 );
178 }
179 add_action( 'save_post', array( $this, 'clear_cache' ), 10, 1 );
180 add_action( 'deleted_post', array( $this, 'clear_cache' ), 10, 1 );
181 // For Full Site Editor templates.
182 add_action( 'save_post_wp_template', array( $this, 'clear_cache_site_editor' ), 10, 1 );
183 add_action( 'save_post_wp_template_part', array( $this, 'clear_cache_site_editor' ), 10, 1 );
184 // Modal Popup Ajax.
185 add_action( 'wp_ajax_sp_handle_post_id', array( $this, 'sp_handle_post_id_callback' ) );
186 add_action( 'wp_ajax_nopriv_sp_handle_post_id', array( $this, 'sp_handle_post_id_callback' ) );
187
188 add_action( 'rest_api_init', array( $this, 'rest_api_register' ) );
189
190 // Back to Top Button.
191 $enable_back_to_top = $this->modules_list['back-to-top'] || false;
192
193 if ( $enable_back_to_top ) {
194 $back_to_top_btn = new Smart_Post_Show_Back_To_Top();
195 add_action( 'wp_footer', array( $back_to_top_btn, 'back_to_top_init' ), 10 );
196 }
197
198 add_action( 'after_setup_theme', array( $this, 'sp_register_custom_image_sizes' ) );
199 }
200
201
202 /**
203 * Register custom image sizes for Smart Post Show blocks.
204 *
205 * @return void
206 */
207 public function sp_register_custom_image_sizes() {
208
209 add_image_size( 'smart-post-landscape', 870, 570, true );
210 add_image_size( 'smart-post-portrait', 600, 900, true );
211 }
212
213 /**
214 * Register api function
215 *
216 * @return void
217 */
218 public function rest_api_register() {
219 register_rest_route(
220 'sps-blocks/v2',
221 '/filter',
222 array(
223 'methods' => 'POST',
224 'callback' => array( $this, 'ajax_live_filter' ),
225 'permission_callback' => '__return_true',
226 )
227 );
228 register_rest_route(
229 'sps-blocks/v2',
230 '/smart-search',
231 array(
232 'methods' => 'POST',
233 'callback' => array( $this, 'smart_search' ),
234 'permission_callback' => '__return_true',
235 )
236 );
237
238 // Register GET endpoint.
239 register_rest_route(
240 'smart-post/v2',
241 '/get-global-settings',
242 array(
243 'methods' => 'GET',
244 'callback' => array( $this, 'get_global_settings' ),
245 'permission_callback' => function () {
246 return current_user_can( 'manage_options' );
247 },
248 )
249 );
250 // Register POST endpoint.
251 register_rest_route(
252 'smart-post/v2',
253 '/global-settings',
254 array(
255 'methods' => 'POST',
256 'callback' => array( $this, 'smart_post_save_global_settings' ),
257 'permission_callback' => function () {
258 return current_user_can( 'manage_options' );
259 },
260 )
261 );
262
263 // Register POST endpoint.
264 register_rest_route(
265 'smart-post/v2',
266 '/icon-list',
267 array(
268 'methods' => 'POST',
269 'callback' => array( $this, 'sp_smart_icon_list' ),
270 'permission_callback' => function () {
271 return current_user_can( 'manage_options' );
272 },
273 )
274 );
275 }
276 /**
277 * Get icon list.
278 *
279 * @return array
280 */
281 public function sp_smart_icon_list() {
282 return rest_ensure_response( wp_json_encode( $this->icon_list ) );
283 }
284 /**
285 * Load core files.
286 *
287 * @return array
288 */
289 public function get_global_settings() {
290 $settings = get_option( 'sp_smart_post_global_settings', array() );
291 return rest_ensure_response( $settings );
292 }
293
294 /**
295 * Save global settings via REST API.
296 *
297 * @param WP_REST_Request $request The REST request.
298 * @return WP_REST_Response|WP_Error
299 */
300 public function smart_post_save_global_settings( $request ) {
301 $settings = $request->get_json_params();
302 // Basic validation (optional but recommended).
303 if ( ! is_array( $settings ) ) {
304 return new WP_Error( 'invalid_data', 'Settings must be an array', array( 'status' => 400 ) );
305 }
306 update_option( 'sp_smart_post_global_settings', $settings );
307 return $settings;
308 }
309
310 /**
311 * Undocumented function
312 *
313 * @param string $unique_id Block unique id.
314 * @param array $block_location_data Block location data.
315 * @return statement
316 */
317 public function get_template_block( $unique_id, $block_location_data = array() ) {
318 // Validate input.
319 if ( ! is_array( $block_location_data ) || empty( $block_location_data['location'] ) ) {
320 return null;
321 }
322
323 $location = $block_location_data['location'] ?? '';
324 $template_id = $block_location_data['templateId'] ?? '';
325 $area_name = $block_location_data['areaName'] ?? '';
326 $post_type = $block_location_data['postType'] ?? '';
327
328 $template_content = '';
329
330 switch ( $location ) {
331 case 'wp_template':
332 if ( 'wp_block' === $post_type && $template_id ) {
333 // For wp_block.
334 $post = get_post( $template_id );
335 $template_content = $post->post_content ?? '';
336 }
337 if ( $template_id && 'wp_block' !== $post_type ) {
338 $template = get_block_template( $template_id, 'wp_template' );
339 $template_content = $template->content ?? '';
340 }
341 break;
342
343 case 'wp_template_part':
344 if ( $area_name ) {
345 // Try to get template part by area name (header, footer, etc.).
346 $template = get_block_template( get_stylesheet() . '//' . $area_name, 'wp_template_part' );
347 if ( ! $template || empty( $template->content ) ) {
348 // Fallback: try by slug if area name doesn't work.
349 $template = get_block_template( $area_name, 'wp_template_part' );
350 }
351 $template_content = $template->content ?? '';
352 }
353 if ( 'wp_block' === $post_type && $template_id ) {
354 // For wp_block.
355 $post = get_post( $template_id );
356 $template_content = $post->post_content ?? '';
357 }
358 break;
359 case 'widget-area':
360 // Widget areas are handled differently - might need to get sidebar content.
361 if ( $area_name ) {
362 $sidebar_content = $this->get_widget_area_content( $area_name );
363 $template_content = $sidebar_content;
364 }
365 break;
366 case 'post-content':
367 if ( $post_type && $template_id ) {
368 // For regular posts/pages.
369 $post = get_post( $template_id );
370 $template_content = $post->post_content ?? '';
371 }
372 break;
373
374 default:
375 return null;
376 }
377 // Parse blocks and find the specific block.
378 if ( 'widget-area' === $location ) {
379 $blocks = $template_content; // Already parsed blocks from widget area.
380 } else {
381 $blocks = parse_blocks( $template_content );
382 }
383 $block = $this->get_block_by_unique_id( $blocks, $unique_id );
384 if ( ! $block ) {
385 $reusable_block_ids = $this->get_reusable_ids( $template_content, $blocks );
386 if ( ! empty( $reusable_block_ids ) ) {
387 foreach ( $reusable_block_ids as $ref_id ) {
388 $ref_post = get_post( $ref_id );
389 if ( $ref_post && isset( $ref_post->post_content ) ) {
390 $ref_blocks = parse_blocks( $ref_post->post_content );
391 $block = $this->get_block_by_unique_id( $ref_blocks, $unique_id );
392 if ( $block ) {
393 break;
394 }
395 }
396 }
397 }
398 $shortcode_block_ids = $this->get_shortcode_ids( $template_content, $blocks );
399 if ( ! empty( $shortcode_block_ids ) ) {
400 foreach ( $shortcode_block_ids as $ref_id ) {
401 $ref_post = get_post( $ref_id );
402 if ( $ref_post && isset( $ref_post->post_content ) ) {
403 $ref_blocks = parse_blocks( $ref_post->post_content );
404 $block = $this->get_block_by_unique_id( $ref_blocks, $unique_id );
405 if ( $block ) {
406 break;
407 }
408 }
409 }
410 }
411 }
412 return $block;
413 }
414
415 /**
416 * Object to array.
417 *
418 * @param object $data meta data.
419 * @return array
420 */
421 public static function object_to_array( $data ) {
422 if ( is_array( $data ) || is_object( $data ) ) {
423 $result = array();
424 foreach ( $data as $key => $value ) {
425 $result[ $key ] = ( is_array( $value ) || is_object( $value ) ) ? self::object_to_array( $value ) : $value;
426 }
427 return $result;
428 }
429 return $data;
430 }
431
432 /**
433 * Recursively searches for a block with a specific unique ID within a set of blocks.
434 *
435 * @param array $blocks Array of blocks to search.
436 * @param string $unique_id The unique ID to find.
437 * @return array|null The block if found, or null if not found.
438 */
439 public function get_block_by_unique_id( $blocks, $unique_id ) {
440 foreach ( $blocks as $block ) {
441 if ( isset( $block[0] ) && is_array( $block[0] ) && isset( $block[0]['blockName'] ) ) {
442 $block = $block[0];
443 }
444 if ( isset( $block['attrs']['spBlockId'] ) && $block['attrs']['spBlockId'] === $unique_id ) {
445 return $block;
446 }
447 if ( ! empty( $block['innerBlocks'] ) ) {
448 $found = $this->get_block_by_unique_id( $block['innerBlocks'], $unique_id );
449 if ( $found ) {
450 return $found;
451 }
452 }
453 }
454 return null;
455 }
456 /**
457 * Get term counts from post IDs for one or multiple taxonomies.
458 *
459 * @param array $post_ids Array of post IDs.
460 * @param string|array $taxonomies Single taxonomy or array of taxonomies.
461 *
462 * @return array Associative array: taxonomy => [ term_id, slug, count ].
463 */
464 public function get_term_counts_from_post_ids( $post_ids, $taxonomies ) {
465 global $wpdb;
466
467 if ( empty( $post_ids ) || ! is_array( $post_ids ) ) {
468 return array();
469 }
470
471 $post_ids = array_map( 'absint', $post_ids );
472 $placeholders = implode( ',', array_fill( 0, count( $post_ids ), '%d' ) );
473 $terms_count = array();
474
475 // Normalize taxonomy input.
476 $taxonomies = (array) $taxonomies;
477
478 foreach ( $taxonomies as $taxonomy ) {
479 $args = array_merge( $post_ids, array( $taxonomy ) );
480 $sql = $wpdb->prepare(
481 "SELECT tt.term_id, t.slug, COUNT(*) as count
482 FROM {$wpdb->term_relationships} tr
483 INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
484 INNER JOIN {$wpdb->terms} t ON t.term_id = tt.term_id WHERE tr.object_id IN ($placeholders)
485 AND tt.taxonomy = %s
486 GROUP BY tt.term_id",
487 ...$args
488 );
489
490 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Table and column names cannot be prepared; they are trusted values from $wpdb.
491 $results = $wpdb->get_results( $sql );
492
493 $term_counts = array_map(
494 function ( $row ) {
495 return array(
496 'term_id' => (int) $row->term_id,
497 'slug' => $row->slug,
498 'count' => (int) $row->count,
499 );
500 },
501 $results
502 );
503
504 $terms_count[ $taxonomy ] = $term_counts;
505 }
506
507 // Return flat list if only one taxonomy was passed.
508 return $terms_count;
509 }
510 /**
511 * Get authors with post count from given post IDs.
512 *
513 * @param array $post_ids Array of post IDs.
514 * @return array Array of authors with ID, name, and post count.
515 */
516 public function get_authors_from_post_ids( $post_ids ) {
517 global $wpdb;
518
519 if ( empty( $post_ids ) || ! is_array( $post_ids ) ) {
520 return array();
521 }
522 // Ensure all IDs are integers.
523 $post_ids = array_map( 'absint', $post_ids );
524 // Create placeholders for each ID.
525 $placeholders = implode( ', ', array_fill( 0, count( $post_ids ), '%d' ) );
526 // Prepare SQL safely.
527
528 // phpcs:ignore
529 $query = $wpdb->prepare(
530 " SELECT p.post_author AS author_id, u.display_name, COUNT(*) as post_count
531 FROM {$wpdb->posts} p
532 INNER JOIN {$wpdb->users} u ON p.post_author = u.ID
533 WHERE p.ID IN ($placeholders)
534 GROUP BY p.post_author ",
535 ...$post_ids
536 );
537
538 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Table and column names cannot be prepared; they are trusted values from $wpdb.
539 $results = $wpdb->get_results( $query );
540
541 $authors = array();
542 foreach ( $results as $row ) {
543 $authors[] = array(
544 'slug' => (int) $row->author_id,
545 'count' => (int) $row->post_count,
546 );
547 }
548
549 return $authors;
550 }
551 /**
552 * Get All Reusable IDs content.
553 *
554 * @param string $post_content post content.
555 * @param string $blocks post blocks.
556 * @return array
557 */
558 public function get_reusable_ids( $post_content, $blocks ) {
559 $reusable_id = array();
560 if ( ! empty( $post_content ) ) {
561 if (
562 has_blocks( $post_content ) &&
563 strpos( $post_content, 'wp:block' ) &&
564 strpos( $post_content, '"ref"' ) !== false
565 ) {
566 foreach ( $blocks as $key => $value ) {
567 if ( isset( $value['attrs']['ref'] ) ) {
568 $reusable_id[] = $value['attrs']['ref'];
569 }
570 }
571 }
572 }
573 return $reusable_id;
574 }
575 /**
576 * Get All Shortcode IDs content.
577 *
578 * @param string $post_content post content.
579 * @param string $blocks Blocks content.
580 * @return array
581 */
582 public function get_shortcode_ids( $post_content, $blocks ) {
583 $ref_ids = array();
584 $saved_template_count = wp_count_posts( 'sp_post_template' );
585 $total_saved_template = $saved_template_count->publish;
586
587 if ( empty( $post_content ) || 0 === $total_saved_template ) {
588 return $ref_ids;
589 }
590
591 // --- Step 1: Find reusable block IDs ---
592 if (
593 has_blocks( $post_content ) && ! empty( $post_content )
594 ) {
595 foreach ( $blocks as $block ) {
596 if ( isset( $block['attrs']['ref'] ) ) {
597 $ref_ids[] = $block['attrs']['ref'];
598 }
599 }
600 }
601 // --- Step 2: Find shortcode IDs like [smart_post_show id="7476"] or id=7476 ---
602 preg_match_all( '/\[smart_post\s+id=["\']?(\d+)["\']?\]/', $post_content, $matches );
603 if ( ! empty( $matches[1] ) ) {
604 $ref_ids = array_merge( $ref_ids, $matches[1] );
605 }
606 // Remove duplicates just in case.
607 $ref_ids = array_unique( $ref_ids );
608
609 return $ref_ids;
610 }
611
612 /**
613 * Retrieves a block by its unique ID from a given page.
614 *
615 * @param WP_REST_Request $request The REST request containing page_id and unique_id.
616 * @return WP_Error|WP_REST_Response|null Returns the block data or an error if not found.
617 */
618 public function ajax_live_filter( WP_REST_Request $request ) {
619 if ( ! ( $request instanceof \WP_REST_Request ) ) {
620 return;
621 }
622 $query_params = $request->get_params();
623 $page_id = ! empty( $query_params['page_id'] ) ? absint( $query_params['page_id'] ) : '';
624 $unique_id = ! empty( $query_params['block'] ) ? sanitize_text_field( $query_params['block'] ) : '';
625 $block_location = ! empty( $query_params['block_location'] ) ? sanitize_text_field( $query_params['block_location'] ) : '';
626 $block_location = ! empty( $block_location ) ? json_decode( $block_location, true ) : array();
627 $block_editor_type = isset( $block_location['editor'] ) ? $block_location['editor'] : '';
628 $block_editor_location = isset( $block_location['location'] ) ? $block_location['location'] : '';
629 $block_template_slug = isset( $block_location['templateSlug'] ) ? $block_location['templateSlug'] : '';
630 $block_template_type = isset( $block_location['templateType'] ) ? $block_location['templateType'] : '';
631 $block_template_post_type = isset( $block_location['postType'] ) ? $block_location['postType'] : 'wp_template';
632 $block_area_name = isset( $block_location['areaName'] ) ? $block_location['areaName'] : '';
633 if ( 'wp_template_part' === $block_editor_location ) {
634 $block_template_post_type = 'wp_template_part';
635 }
636 if ( 'site-editor' === $block_editor_type || 'widget-area' === $block_editor_location ) {
637 $block = $this->get_template_block( $unique_id, $block_location );
638 } else {
639 $content = get_post_field( 'post_content', $page_id );
640 if ( ! $content ) {
641 return new WP_Error( 'not_found', 'Page not found or has no content.', array( 'status' => 404 ) );
642 }
643 $blocks = parse_blocks( $content );
644 $block = $this->get_block_by_unique_id( $blocks, $unique_id );
645 if ( ! $block ) {
646 $reusable_block_ids = $this->get_reusable_ids( $content, $blocks );
647 if ( ! empty( $reusable_block_ids ) ) {
648 foreach ( $reusable_block_ids as $ref_id ) {
649 $ref_post = get_post( $ref_id );
650 if ( $ref_post && isset( $ref_post->post_content ) ) {
651 $ref_blocks = parse_blocks( $ref_post->post_content );
652 $block = $this->get_block_by_unique_id( $ref_blocks, $unique_id );
653 if ( $block ) {
654 break;
655 }
656 }
657 }
658 }
659 $shortcode_block_ids = $this->get_shortcode_ids( $content, $blocks );
660 if ( ! empty( $shortcode_block_ids ) ) {
661 foreach ( $shortcode_block_ids as $ref_id ) {
662 $ref_post = get_post( $ref_id );
663 if ( $ref_post && isset( $ref_post->post_content ) ) {
664 $ref_blocks = parse_blocks( $ref_post->post_content );
665 $block = $this->get_block_by_unique_id( $ref_blocks, $unique_id );
666 if ( $block ) {
667 break;
668 }
669 }
670 }
671 }
672 }
673 }
674 if ( ! $block ) {
675 return new WP_Error( 'not_found', 'Block with this uniqueId not found.', array( 'status' => 404 ) );
676 }
677
678 if ( $block['attrs'] ) {
679 $attrs = $block['attrs'];
680 $block_name = $attrs['blockName'];
681
682 $block_full_name = 'sp-smart-post-show/' . $block_name;
683 $block_type = \WP_Block_Type_Registry::get_instance()->get_registered( $block_full_name );
684
685 $default_attrs = array_map(
686 function ( $attr ) {
687 return isset( $attr['default'] ) ? $attr['default'] : null;
688 },
689 $block_type->attributes
690 );
691 $attrs = array_merge( $default_attrs, $attrs ?? array() );
692 unset( $attrs['dynamicCss'] );
693 $query_data = json_decode( $attrs['postQuery'], true );
694 // Apply extra filters.
695 if ( ! empty( $query_params['relation'] ) ) {
696 $query_data['relation'] = sanitize_key( $query_params['relation'] );
697 }
698 if ( ! empty( $query_params['sps_search'] ) ) {
699 $query_data['s'] = sanitize_text_field( $query_params['sps_search'] );
700 }
701 $no_result_found = isset( $attrs['noResultFoundResult'] ) ? $attrs['noResultFoundResult'] : 'No post found';
702 // Sorting logic.
703 if ( ! empty( $query_params['sps_sort'] ) ) {
704 $sps_sort = $query_params['sps_sort'];
705 if ( preg_match( '/^([a-zA-Z0-9_]+)_(asc|des)$/i', $sps_sort, $matches ) ) {
706 $query_data['fl_orderBy'] = sanitize_key( $matches[1] );
707 $query_data['fl_orderDirection'] = strtoupper( $matches[2] ) === 'ASC' ? 'ASC' : 'DESC';
708 } elseif ( in_array( strtoupper( $sps_sort ), array( 'ASC', 'DESC' ), true ) ) {
709 $query_data['fl_orderDirection'] = strtoupper( $sps_sort );
710 } else {
711 $query_data['fl_orderBy'] = sanitize_key( $sps_sort );
712 }
713 $query_data['ajax_order'] = true;
714 }
715
716 // Taxonomies & Author filters.
717 $taxonomies = array();
718 $author_filter = array();
719 $is_author_filter_exist = false;
720 $count_taxonomies = array();
721 $all_tax_type = array();
722 foreach ( $query_params as $key => $value ) {
723 $key = sanitize_key( $key );
724 if ( strpos( $key, 'tx_' ) === 0 ) {
725 $tax_type = str_replace( 'tx_', '', $key );
726 $all_tax_type[] = $tax_type;
727 $current_taxonomy = array(
728 'id' => time() + wp_rand( 1, 999 ),
729 'type' => sanitize_key( $tax_type ),
730 'value' => is_array( $value ) ? array_map( 'sanitize_text_field', $value ) : array( sanitize_text_field( $value ) ),
731 'operator' => 'IN',
732 'initialOpen' => true,
733 );
734 if ( ! empty( $value ) ) {
735 $taxonomies[] = $current_taxonomy;
736 }
737 }
738 if ( 'sps_author' === $key ) {
739 if ( ! empty( $value ) ) {
740 $author_filter[] = array(
741 'id' => time() + wp_rand( 1, 999 ),
742 'type' => 'author',
743 'value' => sanitize_text_field( $value ),
744 );
745 }
746 $is_author_filter_exist = true;
747 }
748 }
749
750 if ( ! empty( $author_filter ) ) {
751 $query_data['filterByAuthor'] = $author_filter;
752 }
753 $count_data = array();
754 $query_data['ajaxLiveFilter'] = true;
755 // Generate count data for each taxonomy.
756 if ( ! empty( $taxonomies ) ) {
757 foreach ( $all_tax_type as $taxonomy ) {
758 $filtered_taxonomies = array_filter(
759 $taxonomies,
760 function ( $tax ) use ( $taxonomy ) {
761 return $tax['type'] !== $taxonomy;
762 }
763 );
764 $query_data_for_count = $query_data;
765 $query_data_for_count['taxonomies'] = array_values( $filtered_taxonomies );
766 if ( ! empty( array_values( $filtered_taxonomies ) ) ) {
767 $query_data_for_count['tax_type'] = 'slug';
768 }
769 $count_query_data = \SmartPostShow\Blocks\PostQueryHandler::query( $query_data_for_count, 'args' );
770 $all_post_ids = $count_query_data['post_ids'];
771 $count_data = array_merge(
772 $count_data,
773 $this->get_term_counts_from_post_ids( $all_post_ids, $taxonomy )
774 );
775 }
776 $query_data['tax_type'] = 'slug';
777 $query_data['taxonomies'] = $taxonomies;
778 }
779
780 // Author count data if filter active.
781 if ( ! empty( $author_filter ) ) {
782 $author_query_data = $query_data;
783 unset( $author_query_data['filterByAuthor'] );
784 $author_count_query_data = \SmartPostShow\Blocks\PostQueryHandler::query( $author_query_data, 'args' );
785 $all_post_ids = $author_count_query_data['post_ids'];
786 $count_data['author'] = $this->get_authors_from_post_ids( $all_post_ids );
787 }
788 // Pagination support.
789 $current_page = 1;
790 $pagination_type = '';
791 if ( ! empty( $query_params['sps_page'] ) && $query_params['sps_page'] > 1 ) {
792 $query_data['currentPage'] = absint( $query_params['sps_page'] );
793 $current_page = absint( $query_params['sps_page'] );
794 $pagination_type = ! empty( $query_params['pagination_type'] ) ? sanitize_text_field( $query_params['pagination_type'] ) : '';
795 }
796
797 $post_query = \Sp_Smart_Post_Blocks_Query::post_query_frontend( $query_data );
798 $all_post_ids = $post_query[2] ?? array();
799 $total_pages = $post_query[1] ?? '';
800
801 $count_data['pagination'] = array(
802 'total_pages' => $total_pages,
803 'current_page' => $current_page,
804 );
805
806 // Fallback count calculation if filters are missing.
807 if ( empty( $taxonomies ) && ! empty( $all_tax_type ) ) {
808 $count_data = array_merge( $count_data, $this->get_term_counts_from_post_ids( $all_post_ids, $all_tax_type ) );
809 }
810
811 if ( empty( $author_filter ) && $is_author_filter_exist ) {
812 $count_data['author'] = $this->get_authors_from_post_ids( $all_post_ids );
813 }
814
815 $post_query = $post_query[0] ?? array();
816 $html = '';
817 $full_class_name = '';
818 if ( ! isset( $query_params['html'] ) ) {
819 // Render block content.
820 ob_start();
821 $method_name = str_replace( '-', '_', $block_name );
822 $full_class_name = 'SmartPostShow\\Blocks\\Template';
823
824 if ( method_exists( $full_class_name, $method_name ) ) {
825
826 call_user_func( array( $full_class_name, $method_name ), $attrs, $post_query, $pagination_type );
827 }
828 $html = ob_get_clean();
829 if ( empty( $post_query ) ) {
830 $html = $no_result_found;
831 }
832 }
833 return rest_ensure_response(
834 array(
835 'success' => true,
836 'html' => $html,
837 'count_data' => $count_data,
838 'post_query' => $post_query,
839 'full_class_name' => $full_class_name,
840 )
841 );
842 }
843
844 wp_die();
845 }
846 /**
847 * Process smart search query data.
848 *
849 * @param array $search_settings Search settings including post types, search term, taxonomy filters etc.
850 * @return array Array of post data matching the search criteria.
851 */
852 public function smart_search_query_data( $search_settings ) {
853 // Extract settings.
854 $post_type = $search_settings['postType'] ?? 'post';
855 $search_term = sanitize_text_field( $search_settings['s'] ?? '' );
856 $taxonomy = sanitize_text_field( $search_settings['taxonomyType'] ?? '' );
857 $term = sanitize_text_field( $search_settings['term'] ?? array() );
858 $post_limit = isset( $search_settings['postLimit'] ) ? absint( $search_settings['postLimit'] ) : 4;
859 $load_more = filter_var( $search_settings['loadMore'] ?? false, FILTER_VALIDATE_BOOLEAN );
860
861 // Base query args.
862 $args = array(
863 'post_type' => $post_type,
864 'post_status' => 'publish',
865 's' => $search_term,
866 );
867
868 // if load more is true → show all remaining posts .
869 if ( $load_more ) {
870 $args['posts_per_page'] = -1;
871 } else {
872 $args['posts_per_page'] = $post_limit;
873 }
874
875 // Taxonomy filter.
876 if ( ! empty( $search_settings['isTaxonomyEnabled'] ) && ! empty( $taxonomy ) && ! empty( $term ) ) {
877 $args['tax_query'] = array(
878 array(
879 'taxonomy' => $taxonomy,
880 'field' => 'slug',
881 'terms' => $term,
882 ),
883 );
884 }
885
886 // Run query.
887 $query = new WP_Query( $args );
888 $post_query = array();
889
890 // Total available posts count.
891 $total_posts = $query->found_posts;
892
893 if ( $query->have_posts() ) {
894 while ( $query->have_posts() ) {
895 $query->the_post();
896 $post_id = get_the_ID();
897 $thumbnail_id = get_post_thumbnail_id( $post_id );
898 $thumbnail_url = $thumbnail_id ? wp_get_attachment_image_url( $thumbnail_id, 'medium' ) : '';
899 $thumbnail_alt = $thumbnail_id ? get_post_meta( $thumbnail_id, '_wp_attachment_image_alt', true ) : '';
900 $category_list = array();
901 if ( 'product' === $post_type ) {
902 $product_terms = wp_get_object_terms( $post_id, $taxonomy );
903 if ( ! empty( $product_terms ) && ! is_wp_error( $product_terms ) ) {
904 foreach ( $product_terms as $term ) {
905 $category_list[] = $term->name;
906 }
907 }
908 } else {
909 $category_list = wp_get_post_terms( $post_id, 'category', array( 'fields' => 'names' ) );
910 }
911
912 $post_query[] = array(
913 'id' => $post_id,
914 'title' => get_the_title(),
915 'link' => get_permalink(),
916 'post_thumbnail_url' => $thumbnail_url,
917 'image_alt' => $thumbnail_alt,
918 'excerpt' => get_the_excerpt(),
919 'author' => get_the_author(),
920 'date' => get_the_date(),
921 'categories' => $category_list,
922 );
923 }
924 wp_reset_postdata();
925 }
926
927 // Remaining post count.
928 $remaining_posts = max( 0, $total_posts - count( $post_query ) );
929
930 return array(
931 'post_query' => $post_query,
932 'total_posts' => $total_posts,
933 'remaining_posts' => $remaining_posts,
934 );
935 }
936
937 /**
938 * Handle smart search REST API endpoint.
939 *
940 * @param WP_REST_Request $request Request data.
941 * @return void
942 */
943 public function smart_search( WP_REST_Request $request ) {
944 if ( ! ( $request instanceof \WP_REST_Request ) ) {
945 return;
946 }
947 $query_params = $request->get_params();
948 $page = isset( $query_params['page'] ) ? $query_params['page'] : 'frontend';
949
950 $response = $this->smart_search_query_data( $query_params );
951
952 $post_query = $response['post_query'];
953 $total_posts = $response['total_posts'];
954 $remaining_posts = $response['remaining_posts'];
955
956 if ( 'editor' === $page ) {
957 return rest_ensure_response(
958 array(
959 'success' => true,
960 'posts' => $post_query,
961 'total_posts' => $total_posts,
962 'remaining_posts' => $remaining_posts,
963 )
964 );
965 }
966
967 $html = '';
968 if ( ! isset( $query_params['html'] ) ) {
969 ob_start();
970 $method_name = 'smart_search';
971 $full_class_name = 'SmartPostShow\\Blocks\\Template';
972
973 if ( method_exists( $full_class_name, $method_name ) ) {
974 call_user_func( array( $full_class_name, $method_name ), $query_params, $post_query );
975 }
976
977 $html = ob_get_clean();
978 if ( empty( $post_query ) ) {
979 $no_result_found_text = isset( $query_params['noResultFoundResult'] ) ? $query_params['noResultFoundResult'] : 'No post found';
980 $html = '<span class="sp-search-not-found">' . esc_html( $no_result_found_text ) . '</span>';
981 }
982 }
983
984 return rest_ensure_response(
985 array(
986 'success' => true,
987 'html' => $html,
988 'total_posts' => $total_posts,
989 'remaining_posts' => $remaining_posts,
990 )
991 );
992 }
993
994 /**
995 * Get current block attributes.
996 *
997 * @param array $blocks Array of blocks.
998 * @param string $block_id Block ID.
999 * @param string $block_name Block name.
1000 */
1001 public static function current_block_attr( $blocks, $block_id, $block_name ) {
1002
1003 foreach ( $blocks as $key => $value ) {
1004 if ( $block_name == $value['blockName'] ) {
1005 if ( isset( $value['attrs']['uniqueId'] ) && $value['attrs']['uniqueId'] == $block_id ) {
1006 // $objectBlock = '\\SmartPostShow\\Blocks\\' . Helper::to_studly_case( $block_name );
1007 // if ( class_exists( $objectBlock ) ) {
1008 $attr = $value['attrs'];
1009 $attr['blockName'] = $block_name;
1010 $attr['blockId'] = $block_id;
1011 return $attr;
1012 // } else {
1013 // return array();
1014 // }
1015 } else {
1016 return array();
1017 }
1018 }
1019 }
1020 }
1021
1022
1023 /**
1024 * Loads the core files required for the plugin blocks.
1025 *
1026 * @return void
1027 */
1028 private function load_core_files() {
1029 $core_files = array(
1030 // 'class-block-helper.php',
1031 'class-assets-manager.php',
1032 'class-smart-post-block-query.php',
1033 'class-premed-design-library.php',
1034 'class-smart-block-abstract.php',
1035 'class-template-part.php',
1036 'class-query-filter.php',
1037 'class-toc-manager.php',
1038 'template.php',
1039 );
1040 foreach ( $core_files as $file ) {
1041 require_once SP_PC_PATH . 'blocks/includes/' . $file;
1042 }
1043 require_once SP_PC_PATH . 'blocks/modules/class-smart-post-show-back-to-top.php';
1044 }
1045
1046 /**
1047 * Loads block classes for each block slug.
1048 *
1049 * @return void
1050 */
1051 public function load_block_classes() {
1052 foreach ( $this->block_slugs as $slug ) {
1053 $class_name = Helper::to_studly_case( $slug );
1054 $class_file = SP_PC_PATH . "blocks/includes/{$slug}/{$class_name}.php";
1055 if ( file_exists( $class_file ) ) {
1056 require_once $class_file;
1057 }
1058 }
1059 }
1060
1061 /**
1062 * Register block settings option.
1063 *
1064 * @return void
1065 */
1066 public function register_block_settings_option() {
1067 add_option(
1068 'sp-pcp-blocks-setting-options',
1069 array_map(
1070 function ( $slug ) {
1071 return array(
1072 'block_name' => $slug,
1073 'show' => true,
1074 );
1075 },
1076 $this->block_slugs
1077 )
1078 );
1079
1080 add_option(
1081 'sp-pcp-blocks-modules-options',
1082 array_map(
1083 function ( $item ) {
1084 return array(
1085 'module_name' => $item['module_name'],
1086 'show' => true,
1087 );
1088 },
1089 $this->modules_default
1090 )
1091 );
1092
1093 add_option(
1094 'sp-pcp-integration-options',
1095 array_map(
1096 function ( $item ) {
1097 return array(
1098 'name' => $item['name'],
1099 'show' => true,
1100 );
1101 },
1102 $this->integration_default
1103 )
1104 );
1105 }
1106 /**
1107 * Purge all the transients associated with our plugin.
1108 *
1109 * @return void
1110 */
1111 public function clear_cache_site_editor() {
1112 global $wpdb;
1113
1114 if ( is_multisite() ) {
1115 $table = $wpdb->sitemeta;
1116 $column = 'meta_key';
1117 $like = $wpdb->esc_like( '_site_transient_sp_smart_' ) . '%';
1118 } else {
1119 $table = $wpdb->options;
1120 $column = 'option_name';
1121 $like = $wpdb->esc_like( '_transient_sp_smart_' ) . '%';
1122 }
1123
1124 $sql = "DELETE FROM {$table} WHERE {$column} LIKE %s";
1125
1126 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Table and column names cannot be prepared; they are trusted values from $wpdb.
1127 $wpdb->query( $wpdb->prepare( $sql, $like ) );
1128 }
1129
1130 /**
1131 * Purge all the transients associated with our plugin.
1132 *
1133 * @param int $post_id Post id.
1134 * @return void
1135 */
1136 public function clear_cache( $post_id ) {
1137 // Avoid running during autosave or revisions.
1138 if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
1139 return;
1140 }
1141 $keys = get_option( 'sp_smart_post_transients', array() );
1142 foreach ( $keys as $key ) {
1143 delete_transient( $key ); // Delete query cache.
1144 }
1145 delete_option( 'sp_smart_post_transients' );
1146 // Build transient key for this post.
1147 $transient_key = 'sp_smart_post_dynamic_css_' . $post_id;
1148 // Delete it.
1149 delete_transient( $transient_key );
1150 }
1151
1152
1153 /**
1154 * Register category function
1155 *
1156 * @param array $categories Categories list.
1157 * @param object $post Post.
1158 * @return array
1159 */
1160 public function register_block_category( $categories, $post ) {
1161 return array_merge(
1162 array(
1163 array(
1164 'slug' => 'sp-smart-post-show',
1165 'title' => __( 'SMART POST', 'post-carousel' ),
1166 ),
1167 array(
1168 'slug' => 'sp-smart-post-show-pro-blocks',
1169 'title' => __( 'SMART POST PRO BLOCKS', 'post-carousel' ),
1170 ),
1171 ),
1172 $categories
1173 );
1174 }
1175
1176 /**
1177 * Register blocks.
1178 *
1179 * This function registers all the blocks defined in the plugin.
1180 * It loads attributes from files and applies filters to allow customization.
1181 *
1182 * @return void
1183 */
1184 public function register_blocks() {
1185 $attribute_files = $this->block_slugs;
1186 require_once SP_PC_PATH . 'blocks/includes/attributes/pagination.php';
1187 require_once SP_PC_PATH . 'blocks/includes/attributes/shared.php';
1188 $blocks = array();
1189 foreach ( $attribute_files as $file ) {
1190 $block_name = "sp-smart-post-show/{$file}";
1191 $attribute_file_path = SP_PC_PATH . "blocks/includes/{$file}/attributes.php";
1192 if ( file_exists( $attribute_file_path ) ) {
1193 $blocks[ $block_name ] = require $attribute_file_path;
1194 }
1195 }
1196 $all_blocks_attributes = apply_filters( 'sp_smart_post_show_blocks', $blocks );
1197 $block_options = array();
1198 $actives_blocks = Helper::object_to_array( get_option( 'sp-pcp-blocks-setting-options' ) );
1199 $always_active_blocks = array(
1200 array(
1201 'block_name' => 'smart-post-parent',
1202 'show' => true,
1203 ),
1204 array(
1205 'block_name' => 'live-filter',
1206 'show' => true,
1207 ),
1208 array(
1209 'block_name' => 'search-filter',
1210 'show' => true,
1211 ),
1212 array(
1213 'block_name' => 'sort-filter',
1214 'show' => true,
1215 ),
1216 array(
1217 'block_name' => 'taxonomy-filter',
1218 'show' => true,
1219 ),
1220 array(
1221 'block_name' => 'pagination',
1222 'show' => true,
1223 ),
1224 );
1225 $actives_blocks = array_merge( $actives_blocks, $always_active_blocks );
1226 foreach ( $actives_blocks as $value ) {
1227 $block_options[ $value['block_name'] ] = $value['show'];
1228 }
1229 // Register block type.
1230 foreach ( $this->block_slugs as $slug ) {
1231 $full_block_name = "sp-smart-post-show/{$slug}";
1232 $full_class = '\\SmartPostShow\\Blocks\\' . Helper::to_studly_case( $slug );
1233 if ( class_exists( $full_class ) && ! empty( $block_options[ $slug ] ) ) {
1234 new $full_class( $all_blocks_attributes[ $full_block_name ] );
1235 }
1236 }
1237 }
1238
1239 /**
1240 * Returns the default spacing attribute structure for blocks.
1241 *
1242 * @param string $top Top spacing value.
1243 * @param string $right Right spacing value.
1244 * @param string $bottom Bottom spacing value.
1245 * @param string $left Left spacing value.
1246 * @param string $unit Unit for spacing (default: 'px').
1247 * @param bool $all_change Whether all sides change together.
1248 * @return array The spacing attribute array.
1249 */
1250 public function spacing_attribute( $top = '', $right = '', $bottom = '', $left = '', $unit = 'px', $all_change = false ) {
1251 return array(
1252 'type' => 'object',
1253 'default' => array(
1254 'device' => array(
1255 'Desktop' => array(
1256 'top' => $top,
1257 'right' => $right,
1258 'bottom' => $bottom,
1259 'left' => $left,
1260 ),
1261 'Tablet' => array(
1262 'top' => '',
1263 'right' => '',
1264 'bottom' => '',
1265 'left' => '',
1266 ),
1267 'Mobile' => array(
1268 'top' => '',
1269 'right' => '',
1270 'bottom' => '',
1271 'left' => '',
1272 ),
1273 ),
1274 'unit' => array(
1275 'Desktop' => $unit,
1276 'Tablet' => $unit,
1277 'Mobile' => $unit,
1278 ),
1279 'allChange' => $all_change,
1280 ),
1281 );
1282 }
1283
1284 /**
1285 * Returns the default range attribute structure for blocks.
1286 *
1287 * @param string $desktop Value for Desktop device.
1288 * @param string $tablet Value for Tablet device.
1289 * @param string $mobile Value for Mobile device.
1290 * @param string|bool $unit Unit for the value (default: 'px'). If false, unit is not included.
1291 * @return array The range attribute array.
1292 */
1293 public function ranger_attribute( $desktop = '', $tablet = '', $mobile = '', $unit = 'px' ) {
1294 if ( false === $unit ) {
1295 return array(
1296 'type' => 'object',
1297 'default' => array(
1298 'device' => array(
1299 'Desktop' => $desktop,
1300 'Tablet' => $tablet,
1301 'Mobile' => $mobile,
1302 ),
1303 ),
1304 );
1305 }
1306 return array(
1307 'type' => 'object',
1308 'default' => array(
1309 'device' => array(
1310 'Desktop' => $desktop,
1311 'Tablet' => $tablet,
1312 'Mobile' => $mobile,
1313 ),
1314 'unit' => array(
1315 'Desktop' => $unit,
1316 'Tablet' => $unit,
1317 'Mobile' => $unit,
1318 ),
1319 ),
1320 );
1321 }
1322
1323 /**
1324 * Updates parent attribute data with new values, supporting responsive and object types.
1325 *
1326 * @param array $parent_attr The original parent attribute array.
1327 * @param array $attr The array of attribute changes to apply.
1328 * @return array The updated attribute array.
1329 */
1330 public function change_attribute_data( $parent_attr, $attr ) {
1331 $new_data = $parent_attr;
1332 if ( ! is_array( $attr ) ) {
1333 return $new_data;
1334 }
1335 foreach ( $attr as $data ) {
1336 $attr_name = $data['attrName'] ?? null;
1337 $value = $data['value'] ?? null;
1338 $device_type = $data['deviceType'] ?? 'Desktop';
1339
1340 if ( ! $attr_name || ! isset( $parent_attr[ $attr_name ] ) ) {
1341 continue;
1342 }
1343 $data_type = $parent_attr[ $attr_name ]['type'] ?? null;
1344 switch ( $data_type ) {
1345 case 'string':
1346 case 'boolean':
1347 $new_data[ $attr_name ] = array_merge(
1348 $parent_attr[ $attr_name ],
1349 array( 'default' => $value )
1350 );
1351 break;
1352 case 'object':
1353 $default_value = $parent_attr[ $attr_name ]['default'] ?? array();
1354 if ( isset( $default_value['device'] ) ) {
1355 // It's a responsive value.
1356 $device = $default_value['device'];
1357 $device[ $device_type ] = $value;
1358 $merged_default = array_merge( $default_value, array( 'device' => $device ) );
1359 } else {
1360 // It's a single object value.
1361 $merged_default = array_merge( $default_value, array( 'value' => $value ) );
1362 }
1363 $new_data[ $attr_name ] = array_merge(
1364 $parent_attr[ $attr_name ],
1365 array( 'default' => $merged_default )
1366 );
1367 break;
1368 }
1369 }
1370 return $new_data;
1371 }
1372 /**
1373 * Get Ajax data function
1374 *
1375 * @return void
1376 */
1377 public static function sp_handle_post_id_callback() {
1378 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
1379
1380 if ( ! wp_verify_nonce( $nonce, 'sp_smart_post_block_nonce' ) ) {
1381 return;
1382 }
1383
1384 $post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;
1385 $image_size = isset( $_POST['image_size'] ) ? sanitize_text_field( wp_unslash( $_POST['image_size'] ) ) : 'original';
1386
1387 if ( ! $post_id || get_post_status( $post_id ) !== 'publish' ) {
1388 wp_send_json_error( 'Invalid or unpublished post.' );
1389 }
1390 $image_id = get_post_thumbnail_id( $post_id );
1391
1392 $post = get_post( $post_id );
1393 $post_author = ucwords( get_the_author_meta( 'display_name', $post->post_author ) );
1394 $post_date = get_the_date( 'F j, Y', $post_id );
1395 $categories = get_the_terms( $post_id, 'category' );
1396 $category_list = '';
1397 if ( ! empty( $categories ) ) {
1398 foreach ( $categories as $category ) {
1399 $category_list .= ' ' . ucwords( $category->name );
1400 }
1401 }
1402 $meta_taxonomy = $category_list;
1403 $post_views_count = get_post_meta( $post_id, '_post_views_count', true );
1404 $post_like_count = get_post_meta( $post_id, '_post_like_count', true );
1405 // $like_button_option = array(
1406 // 'like_options' => SP_PCP_User_Like::get_pcp_likes_block_button( $post_id ),
1407 // 'post_id' => $post_id,
1408 // );
1409 // $like_button = Template_Part::like( $like_button_option );
1410
1411 $data = array(
1412 'title' => get_the_title( $post ),
1413 'content' => apply_filters( 'the_content', $post->post_content ),
1414 'post_data' => $post,
1415 // 'post_thumbnail' => get_the_post_thumbnail( $post ),
1416 'meta_taxonomy' => $meta_taxonomy,
1417 'date_time' => $post_date,
1418 'author_name' => $post_author,
1419 'post_views' => $post_views_count,
1420 // 'like_button' => $like_button,
1421 'post_image' => wp_get_attachment_image( $image_id, $image_size ),
1422 // 'post_badges_list' => get_the_terms( $post_id, 'sp_smart_badges' ),
1423 );
1424 wp_send_json_success( $data );
1425 }
1426 }
1427 }
1428