'Not Authorized'], 403); $response->send(); exit; } } /** * @see FrontController::initContent() */ public function initContent() { parent::initContent(); $format = Tools::getValue('format', 'json'); $productsData = []; $collection = new PrestaShopCollection('Product'); // This temporary array will help flatten attributes for CSV $attributes_list = []; foreach ((array)Tools::getValue('plc_id_shop', Shop::getShops(true, null, true)) as $id_shop) { foreach ((array)Tools::getValue('plc_id_lang', Language::getLanguages(false, false, true)) as $id_lang) { foreach ($collection as $p) { $product = new Product((int)$p->id, false, $id_lang, $id_shop); if (!Validate::isLoadedObject($product)) { continue; } if (Tools::getValue('plc_only_active') && !$product->active) { continue; } // Handle products with attribute combinations if ($product->hasAttributes()) { $combinations = $product->getAttributeCombinations($id_lang); foreach ($combinations as $combination) { $index = $product->id . '_' . $combination['id_product_attribute']; if (!isset($productsData[$index])) { $productsData[$index] = $this->getBaseProductData($product, $id_lang, $id_shop, (int)$combination['id_product_attribute']); } // Store attributes for later processing (both JSON and CSV) $attributes_list[$index][] = [ 'group_name' => $combination['group_name'] ?? null, 'attribute_name' => $combination['attribute_name'] ?? null, ]; } } else { // Handle simple products (without combinations) $index = $product->id . '_' . 0; $productsData[$index] = $this->getBaseProductData($product, $id_lang, $id_shop, 0); } } } } // Post-process the data based on the requested format foreach ($productsData as $index => &$data) { if (isset($attributes_list[$index])) { if ($format === 'csv') { // Flatten attributes into a single string for CSV $flat_attributes = []; foreach ($attributes_list[$index] as $attr) { $flat_attributes[] = $attr['group_name'] . ':' . $attr['attribute_name']; } $data['attributes'] = implode(' | ', $flat_attributes); } else { // Keep the structured array for JSON $data['attributes'] = $attributes_list[$index]; } } elseif ($format === 'csv') { // Ensure the attributes column exists for simple products in CSV $data['attributes'] = ''; } } unset($data); if ($format === 'csv') { $this->sendCsvResponse(array_values($productsData), 'products.csv'); } else { $response = new JsonResponse($productsData); $response->send(); exit; } } /** * Helper to get common product data fields. */ private function getBaseProductData(Product $product, $id_lang, $id_shop, $id_product_attribute) { $combination = new Combination($id_product_attribute); $data = [ 'id_lang' => (int)$id_lang, 'id_shop' => (int)$id_shop, 'id_product' => (int)$product->id, 'id_product_attribute' => $id_product_attribute, 'active' => (bool)$product->active, 'link' => $this->context->link->getProductLink($product, null, null, null, (int)$id_lang, (int)$id_shop, $id_product_attribute, false), ]; // Conditionally add data based on URL flags Tools::getValue('plc_name') ? $data['name'] = $product->name : null; Tools::getValue('plc_link_rewrite') ? $data['link_rewrite'] = $product->link_rewrite : null; Tools::getValue('plc_description') ? $data['description'] = $product->description : null; Tools::getValue('plc_description_short') ? $data['description_short'] = $product->description_short : null; Tools::getValue('plc_meta_title') ? $data['meta_title'] = $product->meta_title : null; Tools::getValue('plc_meta_description') ? $data['meta_description'] = $product->meta_description : null; // Use combination specific data if it exists, otherwise fallback to product Tools::getValue('plc_reference') ? $data['reference'] = ($id_product_attribute && !empty($combination->reference)) ? $combination->reference : $product->reference : null; Tools::getValue('plc_ean13') ? $data['ean13'] = ($id_product_attribute && !empty($combination->ean13)) ? $combination->ean13 : $product->ean13 : null; Tools::getValue('plc_upc') ? $data['upc'] = ($id_product_attribute && !empty($combination->upc)) ? $combination->upc : $product->upc : null; Tools::getValue('plc_mpn') ? $data['mpn'] = ($id_product_attribute && !empty($combination->mpn)) ? $combination->mpn : $product->mpn : null; return $data; } /** * Encodes data as CSV and sends it as a downloadable file. */ private function sendCsvResponse(array $data, $filename) { if (empty($data)) { $response = new Response('', 204); // No Content $response->send(); exit; } $csvEncoder = new CsvEncoder(); $csvContent = $csvEncoder->encode($data, 'csv', [ CsvEncoder::DELIMITER_KEY => ';', // Semicolon for better Excel compatibility ]); $response = new Response($csvContent); $response->headers->set('Content-Type', 'text/csv'); $response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"'); $response->send(); exit; } }