reverb.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <?php
  2. class ControllerExtensionModuleReverb extends Controller {
  3. private $error = [];
  4. // -------------------------------------------------------------------------
  5. // Main settings page
  6. // -------------------------------------------------------------------------
  7. public function index() {
  8. $this->load->language('extension/module/reverb');
  9. $this->load->model('extension/module/reverb');
  10. $this->load->model('setting/setting');
  11. $this->load->model('catalog/category');
  12. $this->document->setTitle($this->language->get('heading_title'));
  13. if ($this->request->server['REQUEST_METHOD'] === 'POST' && $this->validate()) {
  14. $this->model_setting_setting->editSetting('module_reverb', $this->request->post);
  15. // Save category mappings separately (they come as a sub-array)
  16. if (isset($this->request->post['module_reverb_category_mappings'])) {
  17. $this->model_extension_module_reverb->saveCategoryMappings(
  18. $this->request->post['module_reverb_category_mappings']
  19. );
  20. }
  21. $this->session->data['success'] = $this->language->get('text_success');
  22. $this->response->redirect($this->url->link('extension/module/reverb', 'user_token=' . $this->session->data['user_token'], true));
  23. }
  24. $data = $this->buildBreadcrumbs();
  25. // Pull saved settings into $data
  26. $fields = [
  27. 'module_reverb_api_token',
  28. 'module_reverb_status',
  29. 'module_reverb_sync_direction',
  30. 'module_reverb_sync_categories',
  31. 'module_reverb_shipping_domestic',
  32. 'module_reverb_shipping_international',
  33. ];
  34. foreach ($fields as $key) {
  35. $data[$key] = $this->request->post[$key] ?? $this->config->get($key);
  36. }
  37. // Defaults
  38. $data['module_reverb_sync_direction'] = $data['module_reverb_sync_direction'] ?? 'push';
  39. $data['module_reverb_sync_categories'] = $data['module_reverb_sync_categories'] ?? [];
  40. $data['module_reverb_shipping_domestic'] = $data['module_reverb_shipping_domestic'] ?? '0.00';
  41. $data['module_reverb_shipping_international'] = $data['module_reverb_shipping_international'] ?? '0.00';
  42. // All OC categories for the multi-select
  43. $data['categories'] = $this->getCategoryTree();
  44. // Category mappings for the mapping tab
  45. $data['category_mappings'] = $this->model_extension_module_reverb->getCategoryMappings();
  46. $data['reverb_categories'] = $this->model_extension_module_reverb->getReverbCategories();
  47. $data['module_reverb_category_mappings'] = $data['category_mappings'];
  48. // Sync log
  49. $data['sync_log'] = $this->model_extension_module_reverb->getSyncLog(200);
  50. // Alerts
  51. $data['error_warning'] = $this->error['warning'] ?? '';
  52. $data['success'] = $this->session->data['success'] ?? '';
  53. unset($this->session->data['success']);
  54. $data['action'] = $this->url->link('extension/module/reverb', 'user_token=' . $this->session->data['user_token'], true);
  55. $data['cancel'] = $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=module', true);
  56. $data['sync_url'] = $this->url->link('extension/module/reverb/sync', 'user_token=' . $this->session->data['user_token'], true);
  57. $data['categories_url'] = $this->url->link('extension/module/reverb/reverbCategories', 'user_token=' . $this->session->data['user_token'], true);
  58. $data['header'] = $this->load->controller('common/header');
  59. $data['column_left'] = $this->load->controller('common/column_left');
  60. $data['footer'] = $this->load->controller('common/footer');
  61. $this->response->setOutput($this->load->view('extension/module/reverb', $data));
  62. }
  63. // -------------------------------------------------------------------------
  64. // Install / Uninstall
  65. // -------------------------------------------------------------------------
  66. public function install() {
  67. $this->load->model('extension/module/reverb');
  68. $this->model_extension_module_reverb->install();
  69. // Register events for order pulling (admin side)
  70. $this->load->model('setting/event');
  71. $this->model_setting_event->addEvent(
  72. 'reverb',
  73. 'admin/model/catalog/product/editProduct/after',
  74. 'extension/module/reverb/eventProductSave'
  75. );
  76. $this->model_setting_event->addEvent(
  77. 'reverb',
  78. 'admin/model/catalog/product/addProduct/after',
  79. 'extension/module/reverb/eventProductAddSave'
  80. );
  81. }
  82. public function uninstall() {
  83. $this->load->model('extension/module/reverb');
  84. $this->model_extension_module_reverb->uninstall();
  85. $this->load->model('setting/event');
  86. $this->model_setting_event->deleteEventByCode('reverb');
  87. }
  88. // -------------------------------------------------------------------------
  89. // Event handlers (called by OC event system on product save)
  90. // -------------------------------------------------------------------------
  91. public function eventProductSave(&$route, &$args, &$output) {
  92. $product_id = (int)$args[0];
  93. $this->saveProductReverb($product_id);
  94. }
  95. public function eventProductAddSave(&$route, &$args, &$output) {
  96. // $output holds the new product_id for addProduct
  97. $product_id = (int)$output;
  98. if ($product_id) {
  99. $this->saveProductReverb($product_id);
  100. }
  101. }
  102. private function saveProductReverb($product_id) {
  103. if (!isset($this->request->post['reverb_sync_enabled'])) {
  104. return;
  105. }
  106. $this->load->model('extension/module/reverb');
  107. $this->model_extension_module_reverb->saveProductMap($product_id, [
  108. 'sync_enabled' => (int)(bool)$this->request->post['reverb_sync_enabled'],
  109. 'condition_uuid' => $this->request->post['reverb_condition_uuid'] ?? '',
  110. 'reverb_category_uuid' => $this->request->post['reverb_category_uuid'] ?? '',
  111. ]);
  112. }
  113. // -------------------------------------------------------------------------
  114. // Manual sync (AJAX)
  115. // -------------------------------------------------------------------------
  116. public function sync() {
  117. $this->load->language('extension/module/reverb');
  118. $this->load->model('extension/module/reverb');
  119. $json = ['success' => false];
  120. if (!$this->user->hasPermission('modify', 'extension/module/reverb')) {
  121. $json['error'] = $this->language->get('error_permission');
  122. $this->response->addHeader('Content-Type: application/json');
  123. $this->response->setOutput(json_encode($json));
  124. return;
  125. }
  126. $settings = $this->buildSettings();
  127. if (empty($settings['api_token'])) {
  128. $json['error'] = $this->language->get('error_api_token');
  129. $this->response->addHeader('Content-Type: application/json');
  130. $this->response->setOutput(json_encode($json));
  131. return;
  132. }
  133. $allowed_categories = $this->config->get('module_reverb_sync_categories') ?? [];
  134. $products = $this->model_extension_module_reverb->getSyncEnabledProducts((array)$allowed_categories);
  135. $pushed = 0;
  136. $errors = 0;
  137. foreach ($products as $product) {
  138. try {
  139. $this->model_extension_module_reverb->syncProductToReverb($product, $product, $settings);
  140. $this->model_extension_module_reverb->log($product['product_id'], 'push', 'success', 'Synced: ' . $product['name']);
  141. $pushed++;
  142. } catch (Exception $e) {
  143. $this->model_extension_module_reverb->log($product['product_id'], 'push', 'error', $e->getMessage());
  144. $errors++;
  145. }
  146. }
  147. $json['success'] = true;
  148. $json['message'] = sprintf($this->language->get('text_sync_complete'), $pushed, $errors);
  149. $this->response->addHeader('Content-Type: application/json');
  150. $this->response->setOutput(json_encode($json));
  151. }
  152. // -------------------------------------------------------------------------
  153. // Reverb categories (AJAX — for category mapping dropdowns)
  154. // -------------------------------------------------------------------------
  155. public function reverbCategories() {
  156. $this->load->model('extension/module/reverb');
  157. $categories = $this->model_extension_module_reverb->getReverbCategories();
  158. $this->response->addHeader('Content-Type: application/json');
  159. $this->response->setOutput(json_encode(['categories' => $categories]));
  160. }
  161. // -------------------------------------------------------------------------
  162. // Per-product tab (loaded inline via OCMOD template include)
  163. // The data is passed through the OCMOD PHP patch, not via a separate request.
  164. // -------------------------------------------------------------------------
  165. // -------------------------------------------------------------------------
  166. // Helpers
  167. // -------------------------------------------------------------------------
  168. private function validate() {
  169. if (!$this->user->hasPermission('modify', 'extension/module/reverb')) {
  170. $this->error['warning'] = $this->language->get('error_permission');
  171. }
  172. $token = $this->request->post['module_reverb_api_token'] ?? '';
  173. if (empty(trim($token))) {
  174. $this->error['warning'] = $this->language->get('error_api_token');
  175. }
  176. return empty($this->error);
  177. }
  178. private function buildBreadcrumbs() {
  179. return [
  180. 'heading_title' => $this->language->get('heading_title'),
  181. 'breadcrumbs' => [
  182. [
  183. 'text' => $this->language->get('text_home'),
  184. 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true),
  185. ],
  186. [
  187. 'text' => $this->language->get('text_extension'),
  188. 'href' => $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=module', true),
  189. ],
  190. [
  191. 'text' => $this->language->get('heading_title'),
  192. 'href' => $this->url->link('extension/module/reverb', 'user_token=' . $this->session->data['user_token'], true),
  193. ],
  194. ],
  195. ];
  196. }
  197. private function buildSettings() {
  198. return [
  199. 'api_token' => $this->config->get('module_reverb_api_token'),
  200. 'sync_direction' => $this->config->get('module_reverb_sync_direction') ?? 'push',
  201. 'shipping_domestic' => $this->config->get('module_reverb_shipping_domestic') ?? '0',
  202. 'shipping_international' => $this->config->get('module_reverb_shipping_international') ?? '0',
  203. 'currency' => $this->config->get('config_currency') ?? 'AUD',
  204. 'store_url' => $this->config->get('config_url') ?? '',
  205. ];
  206. }
  207. private function getCategoryTree($parent_id = 0, $indent = '') {
  208. $this->load->model('catalog/category');
  209. $categories = [];
  210. $results = $this->model_catalog_category->getCategories(['parent_id' => $parent_id]);
  211. foreach ($results as $cat) {
  212. $categories[] = [
  213. 'category_id' => $cat['category_id'],
  214. 'name' => $indent . $cat['name'],
  215. ];
  216. $children = $this->getCategoryTree($cat['category_id'], $indent . '&nbsp;&nbsp;&nbsp;');
  217. $categories = array_merge($categories, $children);
  218. }
  219. return $categories;
  220. }
  221. }