Browse Source

Fix memory exhaustion caused by recursive category tree loading

OC3's ModelCatalogCategory::getCategories() ignores the parent_id filter,
so the recursive getCategoryTree() was re-querying all categories on every
call, causing infinite recursion and PHP memory exhaustion (128 MB limit).

Replaced with a single direct SQL query + iterative stack-based tree builder.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Benjamin Harris 2 weeks ago
parent
commit
ead903d0d8
1 changed files with 34 additions and 12 deletions
  1. 34 12
      upload/admin/controller/extension/module/reverb.php

+ 34 - 12
upload/admin/controller/extension/module/reverb.php

@@ -278,18 +278,40 @@ class ControllerExtensionModuleReverb extends Controller {
         ];
         ];
     }
     }
 
 
-    private function getCategoryTree($parent_id = 0, $indent = '') {
-        $this->load->model('catalog/category');
-        $categories = [];
-        $results = $this->model_catalog_category->getCategories(['parent_id' => $parent_id]);
-        foreach ($results as $cat) {
-            $categories[] = [
-                'category_id' => $cat['category_id'],
-                'name'        => $indent . $cat['name'],
-            ];
-            $children = $this->getCategoryTree($cat['category_id'], $indent . '&nbsp;&nbsp;&nbsp;');
-            $categories = array_merge($categories, $children);
+    private function getCategoryTree() {
+        $language_id = (int)$this->config->get('config_language_id');
+
+        $query = $this->db->query("
+            SELECT c.category_id, c.parent_id, cd.name
+            FROM `" . DB_PREFIX . "category` c
+            LEFT JOIN `" . DB_PREFIX . "category_description` cd
+                ON cd.category_id = c.category_id AND cd.language_id = '" . $language_id . "'
+            WHERE c.status = 1
+            ORDER BY c.parent_id ASC, cd.name ASC
+        ");
+
+        $all    = $query->rows;
+        $byPid  = [];
+        foreach ($all as $row) {
+            $byPid[(int)$row['parent_id']][] = $row;
+        }
+
+        $result = [];
+        $stack  = [[0, '']];
+        while ($stack) {
+            [$pid, $indent] = array_pop($stack);
+            if (empty($byPid[$pid])) {
+                continue;
+            }
+            foreach (array_reverse($byPid[$pid]) as $cat) {
+                $result[] = [
+                    'category_id' => $cat['category_id'],
+                    'name'        => $indent . $cat['name'],
+                ];
+                array_push($stack, [(int)$cat['category_id'], $indent . '&nbsp;&nbsp;&nbsp;']);
+            }
         }
         }
-        return $categories;
+
+        return $result;
     }
     }
 }
 }