Explorar el Código

Make sync() always return valid JSON with a readable error message

Set Content-Type: application/json before any code runs so uncaught
exceptions cannot produce HTML output that breaks jQuery's JSON parser.
Wrap the entire sync body in a top-level try/catch. Move log() calls
into safeLog() so a missing reverb_sync_log table cannot propagate an
exception out of the inner catch block and crash the response.
Also surface the "no categories configured" case explicitly instead
of silently returning a 0-product success.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Benjamin Harris hace 2 semanas
padre
commit
797dd687b7
Se han modificado 1 ficheros con 46 adiciones y 39 borrados
  1. 46 39
      upload/admin/controller/extension/module/reverb.php

+ 46 - 39
upload/admin/controller/extension/module/reverb.php

@@ -170,53 +170,60 @@ class ControllerExtensionModuleReverb extends Controller {
         $this->load->language('extension/module/reverb');
         $this->load->model('extension/module/reverb');
 
-        $json = ['success' => false];
+        // Set JSON header first so any uncaught error still returns parseable JSON.
+        $this->response->addHeader('Content-Type: application/json');
 
-        if (!$this->user->hasPermission('modify', 'extension/module/reverb')) {
-            $json['error'] = $this->language->get('error_permission');
-            $this->response->addHeader('Content-Type: application/json');
-            $this->response->setOutput(json_encode($json));
-            return;
-        }
+        try {
+            if (!$this->user->hasPermission('modify', 'extension/module/reverb')) {
+                $this->response->setOutput(json_encode(['success' => false, 'error' => $this->language->get('error_permission')]));
+                return;
+            }
 
-        $settings = $this->buildSettings();
+            $settings = $this->buildSettings();
 
-        if (empty($settings['api_token'])) {
-            $json['error'] = $this->language->get('error_api_token');
-            $this->response->addHeader('Content-Type: application/json');
-            $this->response->setOutput(json_encode($json));
-            return;
-        }
+            if (empty($settings['api_token'])) {
+                $this->response->setOutput(json_encode(['success' => false, 'error' => $this->language->get('error_api_token')]));
+                return;
+            }
 
-        try {
-            $allowed_categories = $this->config->get('module_reverb_sync_categories') ?? [];
-            $products           = $this->model_extension_module_reverb->getSyncEnabledProducts((array)$allowed_categories);
-        } catch (Exception $e) {
-            $json['error'] = 'Database error: ' . $e->getMessage();
-            $this->response->addHeader('Content-Type: application/json');
-            $this->response->setOutput(json_encode($json));
-            return;
-        }
+            $allowed_categories = $this->config->get('module_reverb_sync_categories');
+            if (empty($allowed_categories)) {
+                $this->response->setOutput(json_encode(['success' => false, 'error' => 'No sync categories configured. Select at least one category in the Settings tab.']));
+                return;
+            }
+
+            $products = $this->model_extension_module_reverb->getSyncEnabledProducts((array)$allowed_categories);
+
+            $pushed = 0;
+            $errors = 0;
 
-        $pushed = 0;
-        $errors = 0;
-
-        foreach ($products as $product) {
-            try {
-                $this->model_extension_module_reverb->syncProductToReverb($product, $product, $settings);
-                $this->model_extension_module_reverb->log($product['product_id'], 'push', 'success', 'Synced: ' . $product['name']);
-                $pushed++;
-            } catch (Exception $e) {
-                $this->model_extension_module_reverb->log($product['product_id'], 'push', 'error', $e->getMessage());
-                $errors++;
+            foreach ($products as $product) {
+                try {
+                    $this->model_extension_module_reverb->syncProductToReverb($product, $product, $settings);
+                    $pushed++;
+                    $this->safeLog($product['product_id'], 'push', 'success', 'Synced: ' . $product['name']);
+                } catch (Exception $e) {
+                    $errors++;
+                    $this->safeLog($product['product_id'], 'push', 'error', $e->getMessage());
+                }
             }
-        }
 
-        $json['success'] = true;
-        $json['message'] = sprintf($this->language->get('text_sync_complete'), $pushed, $errors);
+            $this->response->setOutput(json_encode([
+                'success' => true,
+                'message' => sprintf($this->language->get('text_sync_complete'), $pushed, $errors),
+            ]));
 
-        $this->response->addHeader('Content-Type: application/json');
-        $this->response->setOutput(json_encode($json));
+        } catch (Exception $e) {
+            $this->response->setOutput(json_encode(['success' => false, 'error' => $e->getMessage()]));
+        }
+    }
+
+    private function safeLog($product_id, $direction, $status, $message) {
+        try {
+            $this->model_extension_module_reverb->log($product_id, $direction, $status, $message);
+        } catch (Exception $e) {
+            // Log table missing or unavailable — ignore silently.
+        }
     }
 
     // -------------------------------------------------------------------------