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 / includes / class-premed-design-library.php

class-premed-design-library.php in Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News 4.0.7, at blocks/includes/class-premed-design-library.php

266 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Register REST route for getting and refreshing the premade pattern library.
4 *
5 * @package Post_Carousel
6 */
7
8 namespace SmartPostShow\Blocks;
9
10 // Exit if accessed directly.
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 /**
16 * Class Premade_Design_Library
17 *
18 * Handles fetching, caching and serving the premade pattern library via the REST API,
19 * including sanitizing request parameters, storing the fetched JSON in the uploads
20 * directory, and returning cached data when appropriate.
21 */
22 class Premade_Design_Library {
23
24
25 /**
26 * Constructor.
27 *
28 * Registers REST routes for the premade design library.
29 *
30 * @return void
31 */
32 public function __construct() {
33 add_action(
34 'rest_api_init',
35 array( $this, 'register_rest_route' )
36 );
37 }
38 /**
39 * Register REST route for getting and refreshing the premade pattern library.
40 *
41 * @return void
42 */
43 public function register_rest_route() {
44 register_rest_route(
45 'smart-post-show/v2',
46 '/get_premade_patterns/',
47 array(
48 array(
49 'methods' => 'POST',
50 'callback' => array( $this, 'get_premade_patterns_callback' ),
51 'permission_callback' => function () {
52 return current_user_can( 'edit_others_posts' );
53 },
54 ),
55 )
56 );
57 register_rest_route(
58 'sp-smart-post/v2',
59 '/save_wishlist_item',
60 array(
61 array(
62 'methods' => 'POST',
63 'callback' => array( $this, 'save_wishlist_item' ),
64 'permission_callback' => function () {
65 return current_user_can( 'edit_others_posts' );
66 },
67 'args' => array(),
68 ),
69 )
70 );
71 }
72
73
74 /**
75 * Handle saving and retrieving the premade wishlist.
76 *
77 * @param WP_REST_Request $request REST request object.
78 * @return WP_REST_Response
79 */
80 public function save_wishlist_item( $request ) {
81 $params = $request->get_params();
82 $id = isset( $params['id'] ) ? $this->sanitize_params( $params['id'] ) : '';
83 $action = isset( $params['action'] ) ? $this->sanitize_params( $params['action'] ) : '';
84 $request_type = isset( $params['type'] ) ? $this->sanitize_params( $params['type'] ) : '';
85 $wishlist = get_option( 'smart_post_premade_wishlist', array() );
86
87 // Process add/remove only when ID is provided and not a fetch request.
88 if ( $id && 'fetchData' !== $request_type ) {
89 if ( 'remove' === $action ) {
90 $index = array_search( $id, $wishlist, true );
91 if ( false !== $index ) {
92 unset( $wishlist[ $index ] );
93 }
94 $message = __( 'Item has been removed from wishlist.', 'post-carousel' );
95 } else {
96 if ( ! in_array( $id, $wishlist, true ) ) {
97 $wishlist[] = $id;
98 }
99 $message = __( 'Item added to wishlist.', 'post-carousel' );
100 }
101
102 update_option( 'smart_post_premade_wishlist', array_values( $wishlist ) );
103 } else {
104 $message = __( 'Wishlist fetched successfully.', 'post-carousel' );
105 }
106
107 return rest_ensure_response(
108 array(
109 'success' => true,
110 'message' => $message,
111 'wishListArr' => $wishlist, // No need for wp_json_encode(), REST API does this automatically.
112 )
113 );
114 }
115
116 /**
117 * Sanitize REST API parameters recursively.
118 *
119 * @param mixed $params Parameters to sanitize.
120 * @return mixed Sanitized parameters.
121 */
122 public function sanitize_params( $params ) {
123 if ( is_array( $params ) ) {
124 return array_map( array( $this, 'sanitize_params' ), $params );
125 } elseif ( is_bool( $params ) ) {
126 return rest_sanitize_boolean( $params );
127 } elseif ( is_object( $params ) ) {
128 return $params;
129 }
130 return sanitize_text_field( $params );
131 }
132
133 /**
134 * Callback for REST API endpoint to fetch or refresh premade pattern data.
135 *
136 * @param \WP_REST_Request $request REST request.
137 * @return array Response data.
138 */
139 public function get_premade_patterns_callback( $request ) {
140 try {
141 $params = $this->sanitize_params( $request->get_params() );
142 $type = isset( $params['type'] ) ? $params['type'] : '';
143
144 $file_path = $this->get_local_file_path();
145
146 // If type is 'refresh' — force fetch new data.
147 if ( 'refresh' === $type ) {
148 return $this->fetch_and_cache_patterns( true );
149 }
150
151 // Auto refresh if file older than 3 days.
152 if ( file_exists( $file_path ) && ( time() - filemtime( $file_path ) >= 3 * DAY_IN_SECONDS ) ) {
153 $this->fetch_and_cache_patterns( true );
154 } elseif ( ! file_exists( $file_path ) ) {
155 $this->fetch_and_cache_patterns( true );
156 }
157
158 // If cached file exists, return it.
159 if ( file_exists( $file_path ) ) {
160 return array(
161 'success' => true,
162 'data' => $this->get_file_contents( $file_path ),
163 );
164 }
165
166 // Otherwise fetch and return.
167 return $this->fetch_and_cache_patterns( true );
168
169 } catch ( \Exception $e ) {
170 return array(
171 'success' => false,
172 'message' => $e->getMessage(),
173 );
174 }
175 }
176
177 /**
178 * Fetch the latest pattern library from remote and store it locally.
179 *
180 * @param bool $force Whether to overwrite existing file.
181 * @return array Response data.
182 */
183 private function fetch_and_cache_patterns( $force = false ) {
184 global $wp_filesystem;
185
186 if ( ! $wp_filesystem ) {
187 require_once ABSPATH . 'wp-admin/includes/file.php';
188 WP_Filesystem();
189 }
190
191 $file_path = $this->get_local_file_path();
192
193 if ( file_exists( $file_path ) && ! $force ) {
194 return array(
195 'success' => true,
196 'data' => $this->get_file_contents( $file_path ),
197 'cached' => true,
198 );
199 }
200
201 $response = wp_remote_get(
202 'https://demo.wpsmartpost.com/wp-json/smart-post/v1/pattern-list',
203 array( 'timeout' => 150 )
204 );
205
206 if ( is_wp_error( $response ) ) {
207 return array(
208 'success' => false,
209 'message' => __( 'Failed to fetch remote data.', 'post-carousel' ),
210 );
211 }
212
213 $body = wp_remote_retrieve_body( $response );
214
215 if ( empty( $body ) ) {
216 return array(
217 'success' => false,
218 'message' => __( 'Empty response from remote server.', 'post-carousel' ),
219 );
220 }
221
222 $wp_filesystem->put_contents( $file_path, $body );
223
224 return array(
225 'success' => true,
226 'data' => json_decode( $body, true ),
227 'cached' => false,
228 'message' => __( 'Data fetched successfully!', 'post-carousel' ),
229 );
230 }
231
232 /**
233 * Get the full local file path for the cached JSON.
234 *
235 * @return string File path.
236 */
237 private function get_local_file_path() {
238 $upload_dir = wp_upload_dir();
239 $dir = trailingslashit( $upload_dir['basedir'] ) . 'smart-post-show/';
240 wp_mkdir_p( $dir );
241
242 return $dir . 'premede-patterns.json';
243 }
244
245 /**
246 * Read the contents of a file using WP_Filesystem.
247 *
248 * @param string $path File path.
249 * @return string File contents.
250 */
251 private function get_file_contents( $path ) {
252 global $wp_filesystem;
253
254 if ( ! $wp_filesystem ) {
255 require_once ABSPATH . 'wp-admin/includes/file.php';
256 WP_Filesystem();
257 }
258
259 if ( $wp_filesystem->exists( $path ) ) {
260 return $wp_filesystem->get_contents( $path );
261 }
262
263 return '';
264 }
265 }
266