← All changes
|
includes/Admin/Product/Data/Services/PhotoService.php
+138
-127
1.8.5
→
1.10.21
View file →
| @@ -1,127 +1,138 @@ | ||
| 1 | -<?php | |
| 2 | - | |
| 3 | -namespace SyncBasalam\Admin\Product\Data\Services; | |
| 4 | - | |
| 5 | -use SyncBasalam\Services\FileUploader; | |
| 6 | - | |
| 7 | -defined('ABSPATH') || exit; | |
| 8 | - | |
| 9 | -class PhotoService | |
| 10 | -{ | |
| 11 | - private $fileUploader; | |
| 12 | - | |
| 13 | - public function __construct() | |
| 14 | - { | |
| 15 | - $this->fileUploader = new FileUploader(); | |
| 16 | - } | |
| 17 | - public function getMainPhotoId($product): ?int | |
| 18 | - { | |
| 19 | - $mainImageId = $product->get_image_id(); | |
| 20 | - if (!$mainImageId) return null; | |
| 21 | - | |
| 22 | - $existingPhoto = $this->getExistingPhoto($mainImageId); | |
| 23 | - if ($existingPhoto) return $existingPhoto['file_id']; | |
| 24 | - | |
| 25 | - $uploadedPhoto = $this->uploadPhoto($mainImageId); | |
| 26 | - if ($uploadedPhoto) { | |
| 27 | - $this->storePhotoRecord($mainImageId, $uploadedPhoto); | |
| 28 | - return $uploadedPhoto['file_id']; | |
| 29 | - } | |
| 30 | - | |
| 31 | - return null; | |
| 32 | - } | |
| 33 | - | |
| 34 | - public function getGalleryPhotoIds($product) | |
| 35 | - { | |
| 36 | - $galleryPhotoIds = []; | |
| 37 | - $galleryImageIds = $product->get_gallery_image_ids(); | |
| 38 | - | |
| 39 | - if (empty($galleryImageIds)) return []; | |
| 40 | - | |
| 41 | - // Limit to 10 photos maximum | |
| 42 | - $galleryImageIds = array_slice($galleryImageIds, 0, 10); | |
| 43 | - foreach ($galleryImageIds as $index => $imageId) { | |
| 44 | - | |
| 45 | - $existingPhoto = $this->getExistingPhoto($imageId); | |
| 46 | - | |
| 47 | - if ($existingPhoto) { | |
| 48 | - $galleryPhotoIds[] = $existingPhoto['file_id']; | |
| 49 | - } else { | |
| 50 | - $uploadedPhoto = $this->uploadPhoto($imageId); | |
| 51 | - if ($uploadedPhoto) { | |
| 52 | - $this->storePhotoRecord($imageId, $uploadedPhoto); | |
| 53 | - $galleryPhotoIds[] = $uploadedPhoto['file_id']; | |
| 54 | - } | |
| 55 | - } | |
| 56 | - } | |
| 57 | - | |
| 58 | - return $galleryPhotoIds; | |
| 59 | - } | |
| 60 | - | |
| 61 | - private function uploadPhoto(int $imageId) | |
| 62 | - { | |
| 63 | - $imagePathOrUrl = $this->getImagePathOrUrl($imageId); | |
| 64 | - if (!$imagePathOrUrl) return null; | |
| 65 | - | |
| 66 | - try { | |
| 67 | - $data = $this->fileUploader->upload($imagePathOrUrl); | |
| 68 | - return $data; | |
| 69 | - } catch (\Exception $e) { | |
| 70 | - return null; | |
| 71 | - } | |
| 72 | - } | |
| 73 | - | |
| 74 | - private function getImagePathOrUrl(int $imageId): ?string | |
| 75 | - { | |
| 76 | - $url = wp_get_attachment_url($imageId); | |
| 77 | - $path = get_attached_file($imageId); | |
| 78 | - | |
| 79 | - if ($path && file_exists($path)) return $path; | |
| 80 | - | |
| 81 | - return $url; | |
| 82 | - } | |
| 83 | - | |
| 84 | - private function getExistingPhoto(int $wooPhotoId) | |
| 85 | - { | |
| 86 | - global $wpdb; | |
| 87 | - $tableName = $wpdb->prefix . 'sync_basalam_uploaded_photo'; | |
| 88 | - | |
| 89 | - $result = $wpdb->get_row($wpdb->prepare( | |
| 90 | - "SELECT sync_basalam_photo_id AS file_id, sync_basalam_photo_url AS url, created_at | |
| 91 | - FROM $tableName | |
| 92 | - WHERE woo_photo_id = %d", | |
| 93 | - $wooPhotoId | |
| 94 | - ), ARRAY_A); | |
| 95 | - | |
| 96 | - if (!$result) return null; | |
| 97 | - | |
| 98 | - // Check if photo is older than 14 days | |
| 99 | - $createdAt = strtotime($result['created_at']); | |
| 100 | - $now = current_time('timestamp'); | |
| 101 | - $fourteenDays = 14 * DAY_IN_SECONDS; | |
| 102 | - | |
| 103 | - $age = $now - $createdAt; | |
| 104 | - | |
| 105 | - if ($age >= $fourteenDays) { | |
| 106 | - $wpdb->delete($tableName, ['woo_photo_id' => $wooPhotoId], ['%d']); | |
| 107 | - return null; | |
| 108 | - } | |
| 109 | - | |
| 110 | - return $result; | |
| 111 | - } | |
| 112 | - | |
| 113 | - private function storePhotoRecord(int $wooPhotoId, array $basalamPhoto): void | |
| 114 | - { | |
| 115 | - global $wpdb; | |
| 116 | - $tableName = $wpdb->prefix . 'sync_basalam_uploaded_photo'; | |
| 117 | - | |
| 118 | - $insertData = [ | |
| 119 | - 'woo_photo_id' => $wooPhotoId, | |
| 120 | - 'sync_basalam_photo_id' => $basalamPhoto['file_id'], | |
| 121 | - 'sync_basalam_photo_url' => $basalamPhoto['url'], | |
| 122 | - 'created_at' => current_time('mysql'), | |
| 123 | - ]; | |
| 124 | - | |
| 125 | - $wpdb->insert($tableName, $insertData, ['%d', '%d', '%s', '%s']); | |
| 126 | - } | |
| 127 | -} | |
| 1 | +<?php | |
| 2 | + | |
| 3 | +namespace SyncBasalam\Admin\Product\Data\Services; | |
| 4 | + | |
| 5 | +use SyncBasalam\Logger\Logger; | |
| 6 | +use SyncBasalam\Services\FileUploader; | |
| 7 | + | |
| 8 | +defined('ABSPATH') || exit; | |
| 9 | + | |
| 10 | +class PhotoService | |
| 11 | +{ | |
| 12 | + private $fileUploader; | |
| 13 | + | |
| 14 | + public function __construct() | |
| 15 | + { | |
| 16 | + $this->fileUploader = new FileUploader(); | |
| 17 | + } | |
| 18 | + | |
| 19 | + public function getMainPhotoId($product): ?int | |
| 20 | + { | |
| 21 | + $mainImageId = $product->get_image_id(); | |
| 22 | + if (!$mainImageId) return null; | |
| 23 | + | |
| 24 | + $existingPhoto = $this->getExistingPhoto($mainImageId); | |
| 25 | + if ($existingPhoto) return $existingPhoto['file_id']; | |
| 26 | + | |
| 27 | + $uploadedPhoto = $this->uploadPhoto($mainImageId); | |
| 28 | + if ($uploadedPhoto) { | |
| 29 | + $this->storePhotoRecord($mainImageId, $uploadedPhoto); | |
| 30 | + return $uploadedPhoto['file_id']; | |
| 31 | + } | |
| 32 | + | |
| 33 | + return null; | |
| 34 | + } | |
| 35 | + | |
| 36 | + public function getGalleryPhotoIds($product) | |
| 37 | + { | |
| 38 | + $galleryPhotoIds = []; | |
| 39 | + $galleryImageIds = $product->get_gallery_image_ids(); | |
| 40 | + | |
| 41 | + if (empty($galleryImageIds)) return []; | |
| 42 | + | |
| 43 | + $galleryImageIds = array_slice($galleryImageIds, 0, 20); | |
| 44 | + foreach ($galleryImageIds as $imageId) { | |
| 45 | + $existingPhoto = $this->getExistingPhoto($imageId); | |
| 46 | + | |
| 47 | + if ($existingPhoto) { | |
| 48 | + $galleryPhotoIds[] = $existingPhoto['file_id']; | |
| 49 | + } else { | |
| 50 | + $uploadedPhoto = $this->uploadPhoto($imageId); | |
| 51 | + if ($uploadedPhoto) { | |
| 52 | + $this->storePhotoRecord($imageId, $uploadedPhoto); | |
| 53 | + $galleryPhotoIds[] = $uploadedPhoto['file_id']; | |
| 54 | + } | |
| 55 | + } | |
| 56 | + } | |
| 57 | + | |
| 58 | + return $galleryPhotoIds; | |
| 59 | + } | |
| 60 | + | |
| 61 | + private function uploadPhoto(int $imageId) | |
| 62 | + { | |
| 63 | + $imagePathOrUrl = $this->getImagePathOrUrl($imageId); | |
| 64 | + if (!$imagePathOrUrl) return null; | |
| 65 | + | |
| 66 | + try { | |
| 67 | + return $this->fileUploader->upload($imagePathOrUrl); | |
| 68 | + } catch (\Throwable $e) { | |
| 69 | + // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Message is escaped; $e is the previous Throwable passed for exception chaining, not output. | |
| 70 | + throw new \RuntimeException(esc_html('آپلود تصویر محصول به باسلام ناموفق بود: ' . $e->getMessage()), 0, $e); | |
| 71 | + } | |
| 72 | + } | |
| 73 | + | |
| 74 | + private function getImagePathOrUrl(int $imageId): ?string | |
| 75 | + { | |
| 76 | + $url = wp_get_attachment_url($imageId); | |
| 77 | + $path = get_attached_file($imageId); | |
| 78 | + | |
| 79 | + if ($path && file_exists($path)) return $path; | |
| 80 | + | |
| 81 | + return $url; | |
| 82 | + } | |
| 83 | + | |
| 84 | + private function getExistingPhoto(int $wooPhotoId) | |
| 85 | + { | |
| 86 | + global $wpdb; | |
| 87 | + $tableName = $wpdb->prefix . 'sync_basalam_uploaded_media'; | |
| 88 | + $sourceIdentity = 'attachment:' . $wooPhotoId; | |
| 89 | + | |
| 90 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom plugin table; identifier from $wpdb->prefix, not user input. | |
| 91 | + $result = $wpdb->get_row($wpdb->prepare( | |
| 92 | + "SELECT media_id AS file_id, media_url AS url, created_at | |
| 93 | + FROM $tableName | |
| 94 | + WHERE type = %s AND source_identity = %s", | |
| 95 | + 'photo', | |
| 96 | + $sourceIdentity | |
| 97 | + ), ARRAY_A); | |
| 98 | + | |
| 99 | + if (!$result) return null; | |
| 100 | + | |
| 101 | + $createdAt = strtotime($result['created_at']); | |
| 102 | + $now = current_time('timestamp'); | |
| 103 | + $fourteenDays = 14 * DAY_IN_SECONDS; | |
| 104 | + | |
| 105 | + $age = $now - $createdAt; | |
| 106 | + | |
| 107 | + if ($age >= $fourteenDays) { | |
| 108 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom plugin table; no object cache for these operational queries. | |
| 109 | + $wpdb->delete( | |
| 110 | + $tableName, | |
| 111 | + ['type' => 'photo', 'source_identity' => $sourceIdentity], | |
| 112 | + ['%s', '%s'] | |
| 113 | + ); | |
| 114 | + return null; | |
| 115 | + } | |
| 116 | + | |
| 117 | + return $result; | |
| 118 | + } | |
| 119 | + | |
| 120 | + private function storePhotoRecord(int $wooPhotoId, array $basalamPhoto): void | |
| 121 | + { | |
| 122 | + global $wpdb; | |
| 123 | + $tableName = $wpdb->prefix . 'sync_basalam_uploaded_media'; | |
| 124 | + | |
| 125 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom plugin table; no object cache for these operational queries. | |
| 126 | + $wpdb->replace( | |
| 127 | + $tableName, | |
| 128 | + [ | |
| 129 | + 'type' => 'photo', | |
| 130 | + 'source_identity' => 'attachment:' . $wooPhotoId, | |
| 131 | + 'media_id' => (int) $basalamPhoto['file_id'], | |
| 132 | + 'media_url' => $basalamPhoto['url'] ?? '', | |
| 133 | + 'created_at' => current_time('mysql'), | |
| 134 | + ], | |
| 135 | + ['%s', '%s', '%d', '%s', '%s'] | |
| 136 | + ); | |
| 137 | + } | |
| 138 | +} | |