PluginProbe
AliNext – WooCommerce Dropshipping Plugin for AliExpress / trunk
AliNext – WooCommerce Dropshipping Plugin for AliExpress vtrunk
ali2woo-lite / includes / classes / model / Review.php

Review.php in AliNext – WooCommerce Dropshipping Plugin for AliExpress trunk, at includes/classes/model/Review.php

446 lines 18.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Description of Review
5 *
6 * @author MA_GROUP
7 */
8
9 namespace AliNext_Lite;;
10
11 use WC_Comments;
12
13 class Review {
14
15 protected $aliexpress_loader;
16 protected $attachment_model;
17 protected $helper;
18
19 private $allowed_countries;
20 private $review_translated;
21 private $review_load_attributes;
22 private $raiting_from;
23 private $raiting_to;
24 private $max_number_reviews_per_product;
25 private $min_number_reviews_per_product;
26
27 public function __construct(Aliexpress $AliexpressModel, Attachment $AttachmentModel, Helper $Helper) {
28 $this->aliexpress_loader = $AliexpressModel;
29 $this->attachment_model = $AttachmentModel;
30 $this->helper = $Helper;
31
32 //todo: in the very old plugin version we used "review_allow_country" option
33 //need to do the code to remove it completely because now we use another option "review_country"
34
35 $this->allowed_countries = get_setting('review_country');
36
37 $this->review_translated = get_setting('review_translated');
38 $this->review_load_attributes = get_setting('review_load_attributes');
39
40 $this->raiting_from = intval(get_setting('review_raiting_from', 1));
41 $this->raiting_to = intval(get_setting('review_raiting_to', 5));
42
43 $tmp = intval(get_setting('review_max_per_product'));
44 $this->max_number_reviews_per_product = ($tmp > 0) ? $tmp : 20;
45
46 $tmp = intval(get_setting('review_min_per_product'));
47 $this->min_number_reviews_per_product = ($tmp > 0) ? $tmp : $this->max_number_reviews_per_product;
48 }
49
50 /**
51 * Get reviews and save them in Woocommerce
52 */
53 public function load(int $post_id, bool $force_clean = false, array $params = []): ?array
54 {
55 global $wpdb;
56
57 $step = $params['step'] ?? false;
58
59 $external_id = get_post_meta($post_id, "_a2w_external_id", true);
60 if (!$external_id) {
61 return null;
62 }
63
64 $new_steps = [];
65
66 if ($step === false || $step === 'reviews') {
67 $comment_number = get_comments(
68 [
69 'post_id' => $post_id,
70 'meta_key' => 'rating',
71 'count' => true
72 ]
73 );
74
75 $max_number_reviews_per_product = $this->get_max_reviews_number_by_product($post_id);
76 $remaining_comment_number = $max_number_reviews_per_product - $comment_number;
77
78 if ($remaining_comment_number > 0) {
79 $pageNumber = intval(get_post_meta($post_id, '_a2w_review_page', true));
80 $pageNumber = ($pageNumber > 0) ? $pageNumber : 1;
81
82 $res = $this->aliexpress_loader->load_reviews($external_id, $pageNumber, 100);
83
84 if ($res['state'] !== 'error' && !empty($res['reviews'])) {
85 //remove these meta fields from the post to recalculate review values for the product
86 delete_post_meta($post_id, '_wc_average_rating');
87 delete_post_meta($post_id, '_wc_review_count');
88 delete_post_meta($post_id, '_wc_rating_count');
89
90 WC_Comments::clear_transients($post_id);
91
92 $nextPageNumber = ($remaining_comment_number < count($res['reviews'])) ?
93 $pageNumber :
94 ($pageNumber + 1);
95
96 $added_review_cash = [];
97
98 foreach ($res['reviews'] as $item) {
99 if ($remaining_comment_number === 0) {
100 break;
101 }
102
103 $rating = intval($item['review']['reviewStarts']);
104 if ($rating < $this->raiting_from || $rating > $this->raiting_to) {
105 continue;
106 }
107
108 if (!$this->check_review_country($item)) {
109 continue;
110 }
111
112 $review_cache = md5(
113 $post_id . $external_id .
114 ($item['buyer']['buyerTitle'] ?? '') .
115 ($item['review']['reviewContent'] ?? '') .
116 ($item['review']['itemSpecInfo'] ?? '') .
117 ($item['review']['itemLogistics'] ?? '')
118 );
119
120 $queryTemplate = "SELECT count(c.comment_ID) FROM {$wpdb->comments} c " .
121 "LEFT JOIN {$wpdb->commentmeta} cm " .
122 "ON (c.comment_ID = cm.comment_id and cm.meta_key='a2wl_cash') " .
123 "WHERE cm.meta_value=%s";
124 $has_same_comment = $wpdb->get_var($wpdb->prepare($queryTemplate, $review_cache)) > 0;
125 if ($has_same_comment || !empty($added_review_cash[$review_cache])) {
126 continue;
127 }
128
129
130 $tmp_text = ($this->review_translated && isset($item['review']['translation']['reviewContent']))
131 ? $item['review']['translation']['reviewContent'] :
132 ($item['review']['reviewContent'] ?? "");
133
134 $tmp_text = trim(str_replace("\\u0000", '', $tmp_text));
135 if ($this->review_load_attributes && isset($item['review']['itemSpecInfo'])) {
136 $tmp_text = $tmp_text . "<br/><br/>" .
137 preg_replace('#([\w\-]+:)#', '<b>$1</b>',
138 str_replace(':', ': ',
139 PhraseFilter::apply_filter_to_text($item['review']['itemSpecInfo'])));
140 }
141
142 $maybe_skip_review = $this->maybe_skip_review($tmp_text);
143
144 if ($maybe_skip_review) {
145 continue;
146 }
147
148 $review_text = PhraseFilter::apply_filter_to_text($tmp_text);
149
150 $author = PhraseFilter::apply_filter_to_text($item['buyer']['buyerTitle']);
151
152 $date = gmdate('Y-m-d H:i:s', strtotime($item['review']['reviewDate']));
153
154 $comment_approved = get_setting('moderation_reviews') ? 0 : 1;
155
156 $data = [
157 'comment_post_ID' => $post_id,
158 'comment_author' => $author,
159 'comment_author_email' => '',
160 'comment_author_url' => '',
161 'comment_content' => wp_slash($review_text),
162 'comment_agent' =>'',
163 'comment_date' => $date,
164 'comment_date_gmt' => $date,
165 'comment_parent' => 0,
166 'comment_type' => 'review',
167 'comment_approved' => $comment_approved,
168 ];
169
170 $comment_id = wp_insert_comment($data);
171
172 add_comment_meta($comment_id, 'rating', (int) esc_attr($rating), true);
173 add_comment_meta($comment_id, 'a2wl_cash', $review_cache, true);
174 add_comment_meta($comment_id, 'a2wl_country', $item['buyer']['buyerCountry'], true);
175
176 if ($step === false) {
177 // if this is one thread import, then load images
178 if (get_setting('review_avatar_import')) {
179 $author_photo = $item['buyer']['buyerImage'] ?? false;
180 if ($author_photo !== false) {
181 $author_photo = $this->helper->image_http_to_https($author_photo);
182 $photo_id = $this->attachment_model->create_attachment($comment_id, $author_photo);
183 if ($photo_id) {
184 add_comment_meta($comment_id, 'a2wl_avatar', $photo_id, true);
185 }
186 }
187 }
188
189 $photo_ids = [];
190
191 if (get_setting('review_show_image_list')) {
192
193 $photo_list = !empty($item['review']['reviewImages']) ?
194 (is_array($item['review']['reviewImages']) ?
195 $item['review']['reviewImages'] :
196 [$item['review']['reviewImages']]) : [];
197
198 foreach ($photo_list as $photo) {
199 $photo = $this->helper->image_http_to_https($photo);
200 if ($photo_id = $this->attachment_model->create_attachment(
201 $post_id,
202 $photo,
203 ['inner_post_id' => $post_id, 'inner_attach_type' => 'comment'])
204 ) {
205 $photo_ids[] = $photo_id;
206 }
207 }
208 if ($photo_ids) {
209 add_comment_meta($comment_id, 'a2wl_photo_list', $photo_ids, true);
210 }
211 }
212 } else {
213 // step by step flow. Prepare steps.
214 if (get_setting('review_avatar_import')) {
215 $author_photo = $item['buyer']['buyerImage'] ?? false;
216 if ($author_photo) {
217 $author_photo = $this->helper->image_http_to_https($author_photo);
218 $new_steps[] = "reviews#avatar#".$comment_id."#".$author_photo;
219 }
220 }
221
222 if (get_setting('review_show_image_list')) {
223
224 $photo_list = !empty($item['review']['reviewImages']) ?
225 (is_array($item['review']['reviewImages']) ?
226 $item['review']['reviewImages'] :
227 [$item['review']['reviewImages']]) : [];
228
229 foreach ($photo_list as $photo) {
230 $photo = $this->helper->image_http_to_https($photo);
231 $new_steps[] = "reviews#photo#".$comment_id."#".$photo;
232 }
233 }
234 }
235
236 $added_review_cash[$review_cache] = $review_cache;
237
238 $remaining_comment_number--;
239 }
240
241 if ($remaining_comment_number === 0) {
242 update_post_meta($post_id, '_a2w_reviews_last_update', time() + WEEK_IN_SECONDS);
243 update_post_meta($post_id, '_a2w_review_page', 1);
244 } else {
245 update_post_meta($post_id, '_a2w_reviews_last_update', time());
246 update_post_meta($post_id, '_a2w_review_page', $nextPageNumber);
247 }
248 } else {
249 if (!empty($res['message'])) {
250 a2wl_error_log('load_reviews error: ' . $res['message']);
251 }
252 update_post_meta($post_id, '_a2w_reviews_last_update', time() + WEEK_IN_SECONDS);
253 update_post_meta($post_id, '_a2w_review_page', 1);
254 }
255 }
256
257 //make sure that post comment status is 'open'
258 $post_arr = [
259 'ID' => $post_id,
260 'comment_status'=>'open'
261 ];
262 wp_update_post($post_arr);
263
264 if ($force_clean) {
265 WC_Comments::clear_transients($post_id);
266 }
267 }
268
269 if (str_starts_with($step, 'reviews#avatar')) {
270 $parts = explode('#', $step, 4);
271 if(count($parts)==4){
272 $comment_id = $parts[2];
273 $photo = $parts[3];
274
275 $photo_id = $this->attachment_model->create_attachment($comment_id, $photo);
276 if ($photo_id) {
277 add_comment_meta($comment_id, 'a2wl_avatar', $photo_id, true);
278 }
279 }
280 }
281
282 if (str_starts_with($step, 'reviews#photo')) {
283 $parts = explode('#', $step, 4);
284 if (count($parts) == 4) {
285 $comment_id = $parts[2];
286 $photo = $parts[3];
287
288 $photo_id = $this->attachment_model->create_attachment($post_id, $photo,
289 [
290 'inner_post_id' => $post_id,
291 'inner_attach_type' => 'comment'
292 ]
293 );
294 if ($photo_id) {
295 $photo_ids = get_comment_meta($comment_id, 'a2wl_photo_list', true);
296 if ($photo_ids) {
297 $photo_ids[] = $photo_id;
298 update_comment_meta($comment_id, 'a2wl_photo_list', $photo_ids);
299 } else {
300 $photo_ids = [
301 $photo_id
302 ];
303 add_comment_meta($comment_id, 'a2wl_photo_list', $photo_ids, true);
304 }
305 }
306 }
307 }
308
309 return ResultBuilder::buildOk(['new_steps' => $new_steps]);
310 }
311
312 public function get_max_reviews_number_by_product($post_id){
313 $result = get_post_meta( $post_id, Constants::product_reviews_max_number_meta(), true);
314
315 if (!$result){
316 $result = wp_rand( $this->max_number_reviews_per_product, $this->min_number_reviews_per_product );
317 update_post_meta( $post_id, Constants::product_reviews_max_number_meta(), $result );
318 }
319
320 return $result;
321 }
322
323 public function maybe_skip_review($text){
324 if (get_setting('review_skip_empty') && empty($text)) {
325 return true;
326 }
327 $keywords_str = trim(trim(get_setting('review_skip_keywords')),',');
328 if ($keywords_str) {
329 $keywords = array_map('trim', explode(',', $keywords_str));
330 return $this->found_keywords($keywords, $text);
331 }
332 return false;
333 }
334
335 private function found_keywords($keywords, $text) {
336 return array_reduce($keywords, function ($match_found, $keyword) use ($text) {
337 return $match_found || $this->found_keyword($keyword, $text);
338 }, FALSE);
339 }
340
341 private function found_keyword($keyword, $text) {
342 $keyword = trim($keyword);
343 return preg_match('/\b' . preg_quote($keyword) . '\b/iu', $text);
344 }
345
346 private function check_review_country($item) {
347
348 if (empty($this->allowed_countries)){
349 return true;
350 }
351
352 $review_country = strtoupper($item['buyer']['buyerCountry']);
353
354 if (array_search($review_country, $this->allowed_countries) !== false){
355 return true;
356 }
357
358 return false;
359 }
360
361 public static function get_all_review_ids() {
362 global $wpdb;
363
364 $comments = $wpdb->get_results("SELECT cm.comment_id as comment_id FROM {$wpdb->commentmeta} cm WHERE cm.meta_key = 'a2wl_country'");
365
366 return $comments;
367 }
368
369 public static function get_product_review_ids($id) {
370 global $wpdb;
371 $comments = $wpdb->get_results("SELECT c.comment_ID as comment_id FROM {$wpdb->comments} c WHERE c.comment_post_ID = " . intval($id));
372 return $comments;
373 }
374
375 public static function remove_reviews_by_ids($comments) {
376 $comments_count = count($comments);
377
378 if ($comments_count > 0) {
379
380 $comment_ids = '';
381
382 for ($i = 0; $i <= $comments_count - 1; $i++) {
383
384 $comment_ids .= $comments[$i]->comment_id;
385 if ($i < $comments_count - 1)
386 $comment_ids .= ',';
387 }
388
389 global $wpdb;
390
391 //delete reviews
392 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
393 $query_result = $wpdb->query("DELETE FROM {$wpdb->comments} WHERE comment_ID IN ($comment_ids)");
394
395 //delete reviews meta
396 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
397 $query_result = $wpdb->query("DELETE FROM {$wpdb->commentmeta} WHERE comment_id IN ($comment_ids)");
398
399
400 //delete product meta related with review
401 $query_result = $wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE meta_key = '_a2w_reviews_last_update' OR meta_key = '_a2w_review_page' OR meta_key = '_wc_average_rating'");
402
403 //reset review count meta in posts
404 $query_result = $wpdb->query("UPDATE {$wpdb->postmeta} SET meta_value = 0 WHERE meta_key = '_wc_review_count'");
405
406 WC_Comments::delete_comments_count_cache();
407 }
408 }
409
410 public static function get_comment_photos($comment_id) {
411 $photos = array();
412 if ($photos_meta = get_comment_meta($comment_id, 'a2wl_photo_list', true)) {
413 if (is_array($photos_meta)) {
414 foreach ($photos_meta as $photo_id) {
415 $full_img = wp_get_attachment_image_src($photo_id, 'full');
416 if ($full_img) {
417 $thumb_img = wp_get_attachment_image_src($photo_id, 'thumbnail');
418 $photos[] = array('image' => $full_img[0], 'thumb' => $thumb_img ? $thumb_img[0] : $full_img[0], 'photo_id' => $photo_id);
419 }
420 }
421 } else {
422 $photos = json_decode($photos_meta);
423 }
424 }
425 return $photos;
426 }
427
428 public static function save_comment_photos($comment_id, $photo_list): void
429 {
430 update_comment_meta($comment_id, 'a2wl_photo_list', $photo_list);
431 }
432
433 public static function clear_all_product_max_number_review_meta(){
434
435 global $wpdb;
436
437 $wpdb->query(
438 $wpdb->prepare(
439 "DELETE FROM {$wpdb->postmeta} WHERE meta_key=%s",
440 Constants::product_reviews_max_number_meta()
441 )
442 );
443 }
444
445 }
446