ProductMapper.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <?php
  2. class ProductMapper {
  3. /**
  4. * Build a Reverb listing payload from an OpenCart product array.
  5. *
  6. * @param array $product Row from oc_product joined with oc_product_description.
  7. * @param array $reverb_data Row from oc_reverb_product_map (condition_uuid, reverb_category_uuid).
  8. * @param array $settings Global Reverb settings (currency, shipping_domestic, shipping_international, store_image_url).
  9. * @return array Ready to POST/PUT to /listings.
  10. */
  11. public static function toReverb(array $product, array $reverb_data, array $settings) {
  12. $currency = !empty($settings['currency']) ? $settings['currency'] : 'AUD';
  13. // Convert HTML description to clean plain text
  14. $desc = $product['description'];
  15. $desc = preg_replace('/<br\s*\/?>/i', "\n", $desc);
  16. $desc = preg_replace('/<\/p>/i', "\n\n", $desc);
  17. $desc = strip_tags($desc);
  18. $desc = html_entity_decode($desc, ENT_QUOTES | ENT_HTML5, 'UTF-8');
  19. $desc = trim(preg_replace('/\n{3,}/', "\n\n", $desc));
  20. $payload = [
  21. 'title' => html_entity_decode($product['name'], ENT_QUOTES | ENT_HTML5, 'UTF-8'),
  22. 'description' => $desc,
  23. 'sku' => $product['model'],
  24. 'inventory' => max(0, (int)$product['quantity']),
  25. 'has_inventory' => true,
  26. 'handmade' => !empty($reverb_data['handmade']),
  27. 'upc_does_not_apply' => !isset($reverb_data['upc_does_not_apply']) || (bool)$reverb_data['upc_does_not_apply'],
  28. 'price' => [
  29. 'amount' => number_format((float)$product['price'], 2, '.', ''),
  30. 'currency' => $currency,
  31. ],
  32. ];
  33. if (!empty($product['manufacturer'])) {
  34. $payload['make'] = $product['manufacturer'];
  35. }
  36. if (!empty($reverb_data['condition_uuid'])) {
  37. $payload['condition'] = ['uuid' => $reverb_data['condition_uuid']];
  38. }
  39. if (!empty($reverb_data['reverb_category_uuid'])) {
  40. $payload['categories'] = [['uuid' => $reverb_data['reverb_category_uuid']]];
  41. }
  42. if (!empty($reverb_data['origin_country_code'])) {
  43. $payload['origin_country_code'] = strtoupper($reverb_data['origin_country_code']);
  44. }
  45. // Shipping rates
  46. $rates = [];
  47. if (!empty($settings['shipping_domestic'])) {
  48. $rates[] = [
  49. 'region_code' => 'AU',
  50. 'rate' => [
  51. 'amount' => number_format((float)$settings['shipping_domestic'], 2, '.', ''),
  52. 'currency' => $currency,
  53. ],
  54. ];
  55. }
  56. if (!empty($settings['shipping_international'])) {
  57. $rates[] = [
  58. 'region_code' => 'XX',
  59. 'rate' => [
  60. 'amount' => number_format((float)$settings['shipping_international'], 2, '.', ''),
  61. 'currency' => $currency,
  62. ],
  63. ];
  64. }
  65. if ($rates) {
  66. $payload['shipping'] = ['rates' => $rates];
  67. }
  68. return $payload;
  69. }
  70. /**
  71. * Extract updatable OC product fields from a Reverb listing payload
  72. * (used for Reverb → OpenCart sync).
  73. *
  74. * @param array $listing A listing object from the Reverb API.
  75. * @return array Partial product data to merge into OC.
  76. */
  77. public static function fromReverb(array $listing) {
  78. $data = [];
  79. if (isset($listing['title'])) {
  80. $data['name'] = $listing['title'];
  81. }
  82. if (isset($listing['description'])) {
  83. $data['description'] = $listing['description'];
  84. }
  85. if (isset($listing['price']['amount'])) {
  86. $data['price'] = (float)$listing['price']['amount'];
  87. }
  88. if (isset($listing['inventory'])) {
  89. $data['quantity'] = (int)$listing['inventory'];
  90. }
  91. return $data;
  92. }
  93. /**
  94. * Build photo upload payloads for a product's images.
  95. *
  96. * @param array $images Array of image paths relative to OC image dir.
  97. * @param string $store_url Full base URL of the store (e.g. https://example.com/).
  98. * @return array Array of ['image_url' => '...'] payloads.
  99. */
  100. public static function buildPhotoPayloads(array $images, $store_url) {
  101. $payloads = [];
  102. $base = rtrim($store_url, '/') . '/image/';
  103. foreach ($images as $path) {
  104. if (!empty($path)) {
  105. $payloads[] = ['image_url' => $base . ltrim($path, '/')];
  106. }
  107. }
  108. return $payloads;
  109. }
  110. }