Catalog Export Internals¶
Pipeline overview¶
ExportConfig (per-exporter config snapshot)
└── CatalogExportService::processNextChunk()
├── Acquires file lock (export.lock) — prevents concurrent runs
├── Reads state.json — tracks current_chunk, processed_products, status
├── ProductFetcher::retrieve($config, $offset, $limit) — fetches one page of products
├── For each ProductRowEnricherInterface:
│ └── enrich($rows, $config) — adds/transforms columns
├── For each ExportType (FULL, LANG, COUNTRY):
│ └── CsvChunkWriter::write(chunkPath, filteredRows, isFirstChunk)
├── Updates state.json
└── If last chunk: assembleChunks() → renames chunk file to output file
ExportConfig¶
A readonly value object passed through the pipeline. Built by the CatalogExport Symfony console command from the FbpCatalogExporter entity and the shop's FbpPixelSetting.
Key fields: exportId, token, shopId, langId, currencyId, countryId, productsPerChunk, isStorePerChunkEnabled, exportCombinations, gtinField, categoryIds, manufacturerIds, supplierIds.
ProductFetcher¶
Queries the PS database for products matching the export config's filters (categories, manufacturers, suppliers, stock). Returns an array of raw product rows. Results are cached.
Enricher pipeline¶
ProductRowEnricherInterface — implement this to add or transform columns in the product rows before they are written to CSV.
interface ProductRowEnricherInterface
{
/** @param array<array<string, mixed>> $rows
* @return array<array<string, mixed>> */
public function enrich(array $rows, ExportConfig $config): array;
}
Register enrichers as Symfony services tagged with fabfacebookpixel.catalog_enricher.
ExportType¶
A PHP 8.1 backed enum with three cases:
| Case | Output file | Columns |
|---|---|---|
FULL |
feed_{token}.csv |
All catalog columns (id, title, description, image_link, price, gtin, brand, size, color, etc.) |
LANG |
language_{token}.csv |
Language-specific override columns (id, title, description, product_type, link, override) |
COUNTRY |
country_{token}.csv |
Country-specific price override columns (id, price, sale_price, override, link) |
Chunk mode and file system layout¶
All working files for an export are stored in modules/fabfacebookpixel/var/export/{exportId}/:
| File | Description |
|---|---|
export.lock |
Created at start of chunk, deleted on completion. Prevents concurrent runs. |
state.json |
JSON state: status, current_chunk, processed_products, started_at, completed_at |
chunk_full.csv |
Accumulating CSV during chunked export |
chunk_lang.csv |
Accumulating CSV (LANG type) |
chunk_country.csv |
Accumulating CSV (COUNTRY type) |
feed_{token}.csv |
Final output (FULL) — present only after export completes |
language_{token}.csv |
Final output (LANG) |
country_{token}.csv |
Final output (COUNTRY) |
When a new export cycle starts and the previous state is complete, all files are deleted and the process starts fresh.
Symfony console command¶
- Without
--token: processes all configured exporters. - With
--token: processes only the exporter matching that token. - Without
--all: processes one chunk per exporter (cron-safe). - With
--all: loops until the export is complete (suitable for manual full regeneration).
HTTP endpoints¶
CatalogExportController — chunk processing¶
GET /module/fabfacebookpixel/catalogexport?token={token}
Shells out to php bin/console fbp:catalog-export --token={token} (blocking, one chunk), then reads state.json and returns progress. The JS poller calls this endpoint repeatedly until status is complete, then fetches the file via catalogfeed.
Requires exec() to be enabled in PHP.
- If token is missing: HTTP 400
- If token does not match any exporter: HTTP 404
- If the command exits with a non-zero code: HTTP 500
- Otherwise: HTTP 200 with JSON
{ status, currentChunk, processedProducts }
status is one of idle, in_progress, or complete. The endpoint always returns JSON — it never streams a CSV file.
CatalogfeedController — download only¶
GET /module/fabfacebookpixel/catalogfeed?token={token}&type={full|lang|country}
Serves the pre-built output file. Does not trigger export generation.
- If the output file does not exist (export not yet run): HTTP 404
- If the file exists: streams the CSV as
Content-Type: text/csv