defaultLangId = (int) Configuration::get("PS_LANG_DEFAULT"); $this->defaultShopId = (int) Context::getContext()->shop->id; EcomZoneLogger::log("Category Handler initialized", "INFO", [ "default_lang" => $this->defaultLangId, "shop_id" => $this->defaultShopId, ]); } public function createCategory(string $name, ?int $parentId = null): int { try { if (isset($this->categoryCache[$name])) { return $this->categoryCache[$name]; } $parentId = $parentId ?: (int) Configuration::get("PS_HOME_CATEGORY"); $category = new Category(); $category->name = [$this->defaultLangId => trim($name)]; $category->link_rewrite = [ $this->defaultLangId => $this->generateLinkRewrite($name), ]; $category->id_parent = $parentId; $category->active = true; $category->id_shop_default = $this->defaultShopId; // Set shop association for multistore if (Shop::isFeatureActive()) { $category->id_shop_list = [$this->defaultShopId]; } if (!$category->add()) { throw new EcomZoneException( "Failed to create category: $name", EcomZoneException::CATEGORY_CREATE_ERROR ); } $this->categoryCache[$name] = (int) $category->id; EcomZoneLogger::log("Category created", "INFO", [ "name" => $name, "id" => $category->id, "parent_id" => $parentId, ]); return $this->categoryCache[$name]; } catch (Exception $e) { EcomZoneLogger::log("Category creation failed", "ERROR", [ "name" => $name, "error" => $e->getMessage(), ]); throw new EcomZoneException( "Category creation failed: " . $e->getMessage(), EcomZoneException::CATEGORY_CREATE_ERROR, $e ); } } public function getCategoryIdByName(string $name, ?int $parentId = null): ?int { try { if (isset($this->categoryCache[$name])) { return $this->categoryCache[$name]; } $name = trim($name); $sql = 'SELECT c.id_category FROM `' . _DB_PREFIX_ . 'category_lang` cl JOIN `' . _DB_PREFIX_ . 'category` c ON c.id_category = cl.id_category WHERE cl.name = "' . pSQL($name) . '" AND cl.id_lang = ' . (int) $this->defaultLangId . ' AND c.active = 1'; if ($parentId !== null) { $sql .= ' AND c.id_parent = ' . (int) $parentId; } $categoryId = (int) Db::getInstance()->getValue($sql); if ($categoryId) { $this->categoryCache[$name] = $categoryId; return $categoryId; } return null; } catch (Exception $e) { EcomZoneLogger::log("Category lookup failed", "ERROR", [ "name" => $name, "error" => $e->getMessage(), ]); return null; } } public function processCategoriesFromString(string $categories): array { $categoryNames = array_map('trim', explode('>', $categories)); $categoryIds = []; $parentId = null; foreach ($categoryNames as $name) { $categoryId = $this->getCategoryIdByName($name, $parentId); if (!$categoryId) { $categoryId = $this->createCategory($name, $parentId); } if ($categoryId) { $categoryIds[] = $categoryId; $parentId = $categoryId; } } return $categoryIds; } private function generateLinkRewrite(string $name): string { if (isset($this->categoryLinkRewriteCache[$name])) { return $this->categoryLinkRewriteCache[$name]; } $linkRewrite = Tools::str2url($name); // Ensure uniqueness $suffix = 1; $originalLinkRewrite = $linkRewrite; while ($this->linkRewriteExists($linkRewrite)) { $linkRewrite = $originalLinkRewrite . "-" . $suffix++; } $this->categoryLinkRewriteCache[$name] = $linkRewrite; return $linkRewrite; } private function linkRewriteExists(string $linkRewrite): bool { return (bool) Db::getInstance()->getValue( 'SELECT COUNT(*) FROM `' . _DB_PREFIX_ . 'category_lang` cl JOIN `' . _DB_PREFIX_ . 'category_shop` cs ON cl.id_category = cs.id_category WHERE cl.link_rewrite = "' . pSQL($linkRewrite) . '" AND cl.id_lang = ' . (int) $this->defaultLangId . ' AND cs.id_shop = ' . (int) $this->defaultShopId ); } public function createCategoryPath(array $categoryNames): int { $parentId = (int) Configuration::get("PS_HOME_CATEGORY"); $lastCategoryId = $parentId; foreach ($categoryNames as $categoryName) { $categoryName = trim($categoryName); if (empty($categoryName)) { continue; } try { $categoryId = $this->getCategoryIdByName($categoryName); if (!$categoryId) { $categoryId = $this->createCategory( $categoryName, $parentId ); } $lastCategoryId = $categoryId; $parentId = $categoryId; } catch (Exception $e) { EcomZoneLogger::log("Category path creation failed", "ERROR", [ "category" => $categoryName, "error" => $e->getMessage(), ]); break; } } return $lastCategoryId; } }