Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
91.30% covered (success)
91.30%
21 / 23
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
CatalogService
91.30% covered (success)
91.30%
21 / 23
66.67% covered (warning)
66.67%
2 / 3
8.04
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 load
88.24% covered (success)
88.24%
15 / 17
0.00% covered (danger)
0.00%
0 / 1
6.06
 import
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace UppServices;
6
7use Psr\Log\LoggerInterface;
8
9/**
10 * Service for loading the default product catalog from static JSON files and importing catalog into place DB.
11 * JSON files live in Resources/catalog/json; import logic in Services/legacy/catalog/import.php.
12 */
13class CatalogService
14{
15    private const CATALOG_FILES = [
16        'json/coffee.json',
17        'json/sodas.json',
18        'json/beers.json',
19        'json/icecream.json',
20        'json/cocktails.json',
21        'json/wines.json',
22        'json/vermouth.json',
23        'json/shots.json',
24        'json/pastries.json',
25        'json/tapas.json',
26        'json/raciones.json',
27        'json/sandwich.json',
28        'json/bocatas.json',
29        'json/burgers.json',
30        'json/chips.json',
31    ];
32
33    private readonly string $catalogBasePath;
34    private readonly LoggerInterface $logger;
35
36    /**
37     * @param LoggerInterface $logger Logger for warnings and errors.
38     * @param string|null $catalogBasePath Override base path for catalog files (tests only); null uses default.
39     */
40    public function __construct(LoggerInterface $logger, ?string $catalogBasePath = null)
41    {
42        $this->logger = $logger;
43        $this->catalogBasePath = $catalogBasePath ?? (dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Resources' . DIRECTORY_SEPARATOR . 'catalog' . DIRECTORY_SEPARATOR);
44    }
45
46    /**
47     * Loads and merges all catalog JSON files into a single array of products.
48     *
49     * @return array<int, array<string, mixed>> Array of product data from all catalog files.
50     */
51    public function load(): array
52    {
53        $data = [];
54
55        foreach (self::CATALOG_FILES as $catalog) {
56            $file = $this->catalogBasePath . $catalog;
57            if (!file_exists($file)) {
58                $this->logger->warning("Catalog file '{file}' not found.", ['file' => $file]);
59                continue;
60            }
61
62            $content = file_get_contents($file);
63            if ($content === false) {
64                $this->logger->error("Could not read file '{file}'.", ['file' => $file]);
65                continue;
66            }
67
68            $json = json_decode($content, true);
69            if (!is_array($json)) {
70                $this->logger->error("Could not parse JSON in '{file}' or invalid format.", ['file' => $file]);
71                continue;
72            }
73
74            foreach ($json as $product) {
75                $data[] = $product;
76            }
77        }
78
79        return $data;
80    }
81
82    /**
83     * Import catalog (zip with catalog.json) into place DB.
84     *
85     * @param array<string, string> $queryParams GET params: device, session, place.
86     * @param string|null $postBody Raw POST body (JSON with transfer data).
87     * @return array{errorcode: int, percent: int}
88     */
89    public function import(array $queryParams, ?string $postBody): array
90    {
91        require_once __DIR__ . '/legacy/catalog/import.php';
92        $conx = new \ConxHelper(__FILE__);
93        try {
94            return do_catalog_import($conx, $queryParams, $postBody);
95        } finally {
96            $conx->release();
97        }
98    }
99}