PluginProbe
ReviewX – Multi-Criteria Reviews for WooCommerce with Google Reviews & Schema / trunk
ReviewX – Multi-Criteria Reviews for WooCommerce with Google Reviews & Schema vtrunk
2.5.1 2.5.0 2.4.1 2.4.0 2.3.11 2.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 All 143 releases
reviewx / app / Rest / Controllers / StoreFrontReviewController.php

StoreFrontReviewController.php in ReviewX – Multi-Criteria Reviews for WooCommerce with Google Reviews & Schema trunk, at app/Rest/Controllers/StoreFrontReviewController.php

398 lines 16.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ReviewX\Rest\Controllers;
4
5 \defined("ABSPATH") || exit;
6 use Exception;
7 use ReviewX\Services\Api\LoginService;
8 use ReviewX\Services\ReviewService;
9 use ReviewX\Services\CacheServices;
10 use ReviewX\Services\SettingService;
11 use ReviewX\Utilities\Auth\Client;
12 use ReviewX\Utilities\Helper;
13 use Throwable;
14 use ReviewX\WPDrill\Contracts\InvokableContract;
15 use ReviewX\WPDrill\Response;
16 class StoreFrontReviewController implements InvokableContract
17 {
18 protected ReviewService $reviewService;
19 protected SettingService $settingService;
20 protected LoginService $loginService;
21 protected CacheServices $cacheService;
22 public function __construct()
23 {
24 $this->reviewService = new ReviewService();
25 $this->settingService = new SettingService();
26 $this->loginService = new LoginService();
27 $this->cacheService = new CacheServices();
28 }
29 /**
30 * @return void
31 */
32 public function __invoke()
33 {
34 }
35 public function settingMeta($request) : Response
36 {
37 try {
38 $this->reviewService->settingMeta($request);
39 return Helper::rest()->success("Success");
40 } catch (Exception $e) {
41 return Helper::rest()->fails("Fails");
42 }
43 }
44 public function dataGetFromSaas($request)
45 {
46 $response = $this->reviewService->getWidgetReviewsForProduct($request);
47 if ($response->getStatusCode() !== Response::HTTP_OK) {
48 return \false;
49 }
50 return $response->getApiData();
51 }
52 public function getWidgetReviewsForProduct($request)
53 {
54 $diffReviewCount = $this->reviewCountDifferent($request["product_id"]);
55 if ($diffReviewCount === \true) {
56 \delete_transient("rvx_{$request["product_id"]}_latest_reviews");
57 return $this->dataGetFormSaas($request);
58 }
59 $productId = $request["product_id"];
60 $postMata = \get_transient("rvx_{$productId}_latest_reviews");
61 if ($postMata) {
62 if (\count($postMata["reviews"]) != $this->insightReviewCount($request["product_id"])) {
63 \delete_transient("rvx_{$request["product_id"]}_latest_reviews");
64 return $this->dataGetFormSaas($request);
65 }
66 if ($request->get_param("cursor") || $request->get_param("rating") || $request->get_param("sortBy") || $request->get_param("sort_by") || $request->get_param("attachment")) {
67 $response = $this->reviewService->getWidgetReviewsForProduct($request);
68 return Helper::saasResponse($response);
69 } else {
70 if ($this->is_valid_data($postMata)) {
71 //valid
72 $response = ["reviews" => $postMata["reviews"], "meta" => $postMata["meta"]];
73 if ($response) {
74 return Helper::rest($response)->success("Success");
75 } else {
76 return Helper::rest()->fails("Fails");
77 }
78 } else {
79 //invalid
80 $this->loginService->resetProductWisePostMeta($request["product_id"]);
81 return $this->dataGetFormSaas($request);
82 }
83 }
84 } else {
85 return $this->dataGetFormSaas($request);
86 }
87 }
88 public function getAllReviewsDataFromSaas($request, $site_id)
89 {
90 $response = $this->reviewService->getWidgetAllReviewsForSite($request, $site_id);
91 if ($response->getStatusCode() !== Response::HTTP_OK) {
92 return \false;
93 }
94 return $response->getApiData();
95 }
96 public function getWidgetAllReviewsListForSite($request)
97 {
98 $site_id = Client::getUid();
99 $post_type = $request['post_type'] ?? 'all';
100 $postMata = \get_transient("rvx_{$site_id}_{$post_type}_reviews");
101 if ($post_type === 'all') {
102 $post_type = null;
103 }
104 if (!$postMata) {
105 return $this->getAllReviewsFromSaas($request, $site_id, $post_type);
106 }
107 if ($request->get_param("cursor") || $request->get_param("rating") || $request->get_param("sort_by") || $request->get_param("sortBy") || $request->get_param("attachment")) {
108 $response = $this->reviewService->getWidgetAllReviewsForSite($request, $site_id);
109 return Helper::saasResponse($response);
110 }
111 if ($this->is_valid_data($postMata)) {
112 $response = ["reviews" => $postMata["reviews"], "meta" => $postMata["meta"]];
113 if ($response) {
114 return Helper::rest($response)->success("Success");
115 }
116 return Helper::rest()->fails("Fails");
117 }
118 // invalid cached data → reset and fetch fresh
119 $this->resetSiteWiseTransientMeta($site_id, $post_type);
120 return $this->getAllReviewsFromSaas($request, $site_id, $post_type);
121 }
122 public function resetSiteWiseTransientMeta($site_id, $post_type)
123 {
124 $post_type = $post_type != null ? $post_type : 'all';
125 $review_key = "rvx_{$site_id}_{$post_type}_reviews";
126 \delete_transient($review_key);
127 }
128 public function getWidgetReviewsListShortcode($request)
129 {
130 $productId = $request['product_id'];
131 // mismatch in review count → reset + fetch
132 if ($this->reviewCountDifferent($productId)) {
133 \delete_transient("rvx_{$productId}_latest_reviews");
134 return $this->dataGetFormSaas($request);
135 }
136 $postMeta = \get_transient("rvx_{$productId}_latest_reviews");
137 // no cache → fetch
138 if (!$postMeta) {
139 return $this->dataGetFormSaas($request);
140 }
141 // cache count mismatch → reset + fetch
142 if (\count($postMeta['reviews']) !== $this->insightReviewCount($productId)) {
143 \delete_transient("rvx_{$productId}_latest_reviews");
144 return $this->dataGetFormSaas($request);
145 }
146 // request has filters → always fetch fresh
147 if ($request->get_param('cursor') || $request->get_param('rating') || $request->get_param('sortBy') || $request->get_param('sort_by') || $request->get_param('attachment')) {
148 $response = $this->reviewService->getWidgetReviewsListShortcode($request);
149 return Helper::saasResponse($response);
150 }
151 // cached data valid → return
152 if ($this->is_valid_data($postMeta)) {
153 return Helper::rest(['reviews' => $postMeta['reviews'], 'meta' => $postMeta['meta']])->success('Success');
154 }
155 // invalid cached data → reset + fetch
156 $this->loginService->resetProductWisePostMeta($productId);
157 return $this->dataGetFormSaas($request);
158 }
159 public function getAllReviewsFromSaas($request, $site_id, $post_type)
160 {
161 $latestReviews = $this->getAllReviewsDataFromSaas($request, $site_id);
162 if (!$latestReviews) {
163 return Helper::rvxApi(["error" => "Fails"])->fails("failed");
164 }
165 $reviews = Helper::arrayGet($latestReviews, "reviews");
166 if (\count($reviews) > 0) {
167 $this->reviewService->setAllReviewsMetaTransient($site_id, $post_type, $latestReviews);
168 }
169 return ["data" => $latestReviews];
170 }
171 public function dataGetFormSaas($request)
172 {
173 $latestReview = $this->dataGetFromSaas($request);
174 if (!$latestReview) {
175 return Helper::rvxApi(["error" => "Fails"])->fails("failed");
176 }
177 $reviews = Helper::arrayGet($latestReview, "reviews");
178 if (\count($reviews) > 0) {
179 $this->reviewService->postMetaReviewInsert($request->get_param("product_id"), $latestReview);
180 }
181 return ["data" => $latestReview];
182 }
183 public function is_valid_data($postMata)
184 {
185 if (\is_array($postMata)) {
186 return \true;
187 }
188 return \false;
189 }
190 public function insightDataGetInSaas($request)
191 {
192 $response = $this->reviewService->getWidgetInsight($request);
193 if ($response->getStatusCode() !== Response::HTTP_OK) {
194 return \false;
195 }
196 return $response->getApiData();
197 }
198 public function getWidgetInsight($request)
199 {
200 try {
201 $diffReviewCount = $this->reviewCountDifferent($request["product_id"]);
202 if ($diffReviewCount === \true) {
203 return ["data" => $this->insightDataelsePart($request)];
204 }
205 $data = \get_transient("rvx_{$request["product_id"]}_latest_reviews_insight");
206 if ($data) {
207 $aggregation = \json_decode($data, \true);
208 if (\is_array($aggregation)) {
209 $aggregation['product']['title'] = \htmlspecialchars_decode($aggregation['product']['title'], \ENT_QUOTES);
210 }
211 if (!\is_array($aggregation)) {
212 $modData = $this->productTitleAndDescriptionBackSlashRemove($data);
213 $aggregation = \json_decode($modData, \true);
214 }
215 if ($aggregation) {
216 return Helper::rest($aggregation)->success("Success");
217 } else {
218 return Helper::rest()->fails("Fails");
219 }
220 } else {
221 // Fetch the latest aggregation data
222 return ["data" => $this->insightDataelsePart($request)];
223 }
224 } catch (Throwable $e) {
225 return Helper::rvxApi(["error" => $e->getMessage()])->fails("failed", $e->getCode());
226 }
227 }
228 public function insightDataelsePart($request)
229 {
230 $latestAggregation = $this->insightDataGetInSaas($request);
231 // Check if the data retrieval fails
232 if (!$latestAggregation) {
233 return Helper::rvxApi(["error" => "Fails"])->fails("failed");
234 }
235 // Extract 'criteria_stats' from the latest aggregation data (always an array)
236 $criteriaStat = Helper::arrayGet($latestAggregation, "criteria_stats");
237 // No need to decode since it's always an array, just assign back
238 $latestAggregation["criteria_stats"] = $criteriaStat;
239 \delete_transient("rvx_{$request->get_param("product_id")}_latest_reviews_insight");
240 // Store the data in post meta as a JSON string
241 $latestAggregationJson = \json_encode($latestAggregation, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES);
242 \set_transient("rvx_{$request->get_param("product_id")}_latest_reviews_insight", $latestAggregationJson, 604800);
243 // Expires in 7 days
244 return $latestAggregation;
245 }
246 public function productTitleAndDescriptionBackSlashRemove($data)
247 {
248 return \preg_replace('/("title":")([^"\\\\]+)\\\\\'/', '$1$2\'', $data);
249 }
250 public function reviewCountDifferent($id) : bool
251 {
252 $wpReview = $this->getOnlyApproveReviewCount($id);
253 $saasReview = $this->insightReviewCount($id);
254 if ($wpReview > $saasReview) {
255 return \true;
256 }
257 if ($wpReview < $saasReview) {
258 return \true;
259 }
260 return \false;
261 }
262 public function getOnlyApproveReviewCount($id) : int
263 {
264 $count = \get_comments(['post_id' => (int) $id, 'status' => 'approve', 'parent' => 0, 'type__in' => ['comment', 'review'], 'count' => \true, 'no_found_rows' => \true, 'update_comment_meta_cache' => \false, 'update_comment_post_cache' => \false]);
265 return (int) $count;
266 }
267 public function insightReviewCount($id) : int
268 {
269 $data = \get_transient("rvx_{$id}_latest_reviews_insight");
270 if ($data) {
271 $reviewAggregation = \json_decode($data, \true);
272 return $reviewAggregation['aggregation']['total_reviews'] ?? 0;
273 }
274 return 0;
275 }
276 /**
277 * @param $request
278 * @return Response
279 */
280 public function saveWidgetReviewsForProduct($request)
281 {
282 try {
283 $response = $this->reviewService->saveWidgetReviewsForProduct($request);
284 $this->cacheService->removeCache();
285 $this->cacheService->refreshPendingReviewNoticeSummary();
286 return Helper::saasResponse($response);
287 } catch (Throwable $e) {
288 return Helper::rvxApi(["error" => $e->getMessage()])->fails("failed", $e->getCode());
289 }
290 }
291 /**
292 * @param $request
293 * @return Response
294 */
295 public function requestReviewEmailAttachment($request) : Response
296 {
297 try {
298 $data = $this->reviewService->requestReviewEmailAttachment($request);
299 return Helper::rvxApi(["reviews" => $data])->success("Review Successfully sent", 200);
300 } catch (Throwable $e) {
301 return Helper::rvxApi(["error" => $e->getMessage()])->fails("failed", $e->getCode());
302 }
303 }
304 /**
305 * @param $request
306 * @return Response
307 */
308 public function likeDislikePreference($request)
309 {
310 try {
311 $response = $this->reviewService->likeDIslikePreference($request->get_params());
312 return Helper::saasResponse($response);
313 } catch (Throwable $e) {
314 return Helper::rvxApi(["error" => $e->getMessage()])->fails("failed", $e->getCode());
315 }
316 }
317 public function singleActionProductMata($request)
318 {
319 $reviewData = Helper::arrayGet($request->get_params(), "review");
320 $aggregationData = Helper::arrayGet($request->get_params(), "aggregation");
321 $productId = Helper::arrayGet($aggregationData, "product_wp_id");
322 if (!$productId) {
323 return;
324 }
325 $this->storeReviewMeta($productId, $reviewData);
326 $this->storeAggregationMeta($productId, $aggregationData);
327 }
328 public function storeReviewMeta($productId, $payload)
329 {
330 $reviewAndMeta = ["reviews" => Helper::arrayGet($payload, "reviews"), "meta" => Helper::arrayGet($payload, "meta")];
331 $this->reviewService->postMetaReviewInsert($productId, $reviewAndMeta);
332 }
333 public function storeAggregationMeta($productId, $payload)
334 {
335 $aggregation_data = \json_encode(\wp_slash(Helper::arrayGet($payload, "meta")), \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES);
336 \set_transient("rvx_{$productId}_latest_reviews_insight", $aggregation_data, 604800);
337 // Expires in 7 days
338 }
339 public function reviewRequestStoreItem($request)
340 {
341 try {
342 $review = $this->reviewService->reviewRequestStoreItem($request->get_params());
343 return $review;
344 // return Helper::saasResponse($response);
345 } catch (Throwable $e) {
346 return Helper::rvxApi(["error" => $e->getMessage()])->fails("failed", $e->getCode());
347 }
348 }
349 public function thanksMessage($request)
350 {
351 try {
352 $response = $this->reviewService->thanksMessage($request);
353 return $response;
354 } catch (Throwable $e) {
355 return Helper::rvxApi(["error" => $e->getMessage()])->fails("failed", $e->getCode());
356 }
357 }
358 public function getSpecificReviewItem($request)
359 {
360 try {
361 $defferentIds = $this->cacheService->clearShortcodesCache(\get_option('_rvx_reviews_ids'), $request->get_params());
362 if ($defferentIds == \false) {
363 \delete_transient('rvx_shortcode_transient');
364 }
365 $transient_key = 'rvx_shortcode_transient';
366 $resp = \get_transient($transient_key);
367 if ($resp !== \false) {
368 $data = ['reviews' => $resp['reviews'], 'meta' => $resp['meta']];
369 return Helper::rest($data)->success("Success (from transient)");
370 } else {
371 $response = $this->reviewService->getSpecificReviewItem($request);
372 $api_data = $response->getApiData();
373 \set_transient($transient_key, $api_data, 12 * HOUR_IN_SECONDS);
374 \update_option('_rvx_reviews_ids', $request->get_params());
375 return Helper::saasResponse($response);
376 }
377 } catch (Throwable $e) {
378 return Helper::rvxApi(["error" => $e->getMessage()])->fails("Specific Review Item Fails", $e->getCode());
379 }
380 }
381 public function getLocalSettings($request)
382 {
383 // Get API param
384 $post_type = $request->get_param('cpt_type') ? \strtolower($request->get_param('cpt_type')) : 'product';
385 $settings_data = (new SettingService())->getSettingsData($post_type);
386 $data = \is_array($settings_data) ? $settings_data : [];
387 if ($data) {
388 return Helper::rest($data)->success("Success");
389 } else {
390 $response = $this->settingService->getLocalSettings($post_type);
391 $apiResponse = Helper::getApiResponse($response);
392 $review_setting = $apiResponse->data['data']['setting']['review_settings'] ?? [];
393 $this->settingService->updateReviewSettings($review_setting, $post_type);
394 return $apiResponse;
395 }
396 }
397 }
398