TemplateHandler   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 197
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 14
eloc 119
c 0
b 0
f 0
dl 0
loc 197
ccs 109
cts 109
cp 1
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 2 1
A createSpreadsheet() 0 14 2
A handle() 0 5 1
A headers() 0 21 4
A writeSelect() 0 17 1
A export() 0 55 2
A createList() 0 18 2
A createResponse() 0 18 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Handler;
6
7
use Application\Enum\Precision;
8
use Application\Enum\Site;
9
use Application\Model\User;
10
use Application\Repository\CountryRepository;
11
use Application\Repository\DocumentTypeRepository;
12
use Application\Repository\DomainRepository;
13
use Application\Repository\MaterialRepository;
14
use Application\Repository\PeriodRepository;
15
use Application\Stream\TemporaryFile;
16
use Laminas\Diactoros\Response;
17
use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
18
use PhpOffice\PhpSpreadsheet\NamedRange;
19
use PhpOffice\PhpSpreadsheet\Spreadsheet;
20
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
21
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
22
use Psr\Http\Message\ResponseInterface;
23
use Psr\Http\Message\ServerRequestInterface;
24
use Psr\Http\Server\RequestHandlerInterface;
25
26
/**
27
 * Serve XLSX template file.
28
 */
29
class TemplateHandler implements RequestHandlerInterface
30
{
31
    final public const HEADERS = [
32
        'Fichier image (avec ou sans extension)',
33
        'Titre',
34
        'Titre étendu',
35
        'Domaine',
36
        'Matériaux',
37
        'Période',
38
        'Date précise début',
39
        'Date précise fin',
40
        'Pays de découverte',
41
        'Site/Lieu de découverte',
42
        'Lieu de production',
43
        'Référence de l\'objet',
44
        'Type de document',
45
        'Auteur du document',
46
        'Année du document',
47
        'Latitude',
48
        'Longitude',
49
        'Précision',
50
    ];
51
52
    private int $row = 1;
53
54
    private int $col = 1;
55
56 1
    public function __construct(private readonly Site $site, private readonly DomainRepository $domainRepository, private readonly PeriodRepository $periodRepository, private readonly CountryRepository $countryRepository, private readonly MaterialRepository $materialRepository, private readonly DocumentTypeRepository $documentTypeRepository)
57
    {
58 1
    }
59
60
    /**
61
     * Serve multiples cards as PowerPoint file.
62
     */
63 1
    public function handle(ServerRequestInterface $request): ResponseInterface
64
    {
65 1
        $spreadsheet = $this->export();
66
67 1
        return $this->createResponse($spreadsheet);
68
    }
69
70
    /**
71
     * Export all cards into a presentation.
72
     */
73 1
    private function export(): Spreadsheet
74
    {
75 1
        $title = $this->site->getDescription() . '_' . date('c', time());
76
77 1
        $spreadsheet = self::createSpreadsheet(User::getCurrent(), $this->site, $title);
78 1
        $sheet = $spreadsheet->getActiveSheet();
79
80 1
        $this->headers($sheet);
81
82 1
        $domainName = 'Domaines';
83 1
        $domains = $this->domainRepository->getFullNames($this->site);
84 1
        $this->createList($spreadsheet, array_keys($domains), $domainName);
85
86 1
        $materialName = 'Matériaux';
87 1
        $materials = $this->materialRepository->getFullNames($this->site);
88 1
        $this->createList($spreadsheet, array_keys($materials), $materialName);
89
90 1
        $periodName = 'Périodes';
91 1
        $periods = $this->periodRepository->getFullNames($this->site);
92 1
        $this->createList($spreadsheet, array_keys($periods), $periodName);
93
94 1
        $documentTypeName = 'Document';
95 1
        $documentTypes = $this->documentTypeRepository->getNames($this->site);
96 1
        $this->createList($spreadsheet, array_keys($documentTypes), $documentTypeName);
97
98 1
        $countryName = 'Pays';
99 1
        $countries = $this->countryRepository->getNames();
100 1
        $this->createList($spreadsheet, array_keys($countries), $countryName);
101
102 1
        $precisionName = 'Précisions';
103 1
        $precisions = [
104 1
            Precision::Locality->value,
105 1
            Precision::Site->value,
106 1
            Precision::Building->value,
107 1
        ];
108 1
        $this->createList($spreadsheet, $precisions, $precisionName);
109
110 1
        foreach (range(1, 100) as $row) {
111 1
            $this->col = 4;
112 1
            $this->writeSelect($sheet, $domainName);
113 1
            $this->writeSelect($sheet, $materialName);
114 1
            $this->writeSelect($sheet, $periodName);
115 1
            $this->col += 2;
116 1
            $this->writeSelect($sheet, $countryName);
117 1
            $this->col += 3;
118 1
            $this->writeSelect($sheet, $documentTypeName);
119 1
            $this->col = 18;
120 1
            $this->writeSelect($sheet, $precisionName);
121 1
            ++$this->row;
122
        }
123
124 1
        $style = $sheet->getStyle([1, 1, $this->col, $this->row]);
125 1
        $style->getAlignment()->setWrapText(true);
126
127 1
        return $spreadsheet;
128
    }
129
130 1
    private function headers(Worksheet $sheet): void
131
    {
132 1
        foreach (self::HEADERS as $header) {
133 1
            $sheet->setCellValue([$this->col++, $this->row], $header);
134
        }
135
136 1
        $style = $sheet->getStyle([1, $this->row, $this->col, $this->row]);
137 1
        $style->getFont()->setBold(true);
138
139
        // Adjust column width
140 1
        for ($col = 1; $col < $this->col; ++$col) {
141 1
            if ($col !== 3) {
142 1
                $sheet->getColumnDimensionByColumn($col)->setAutoSize(true);
143
            } else {
144 1
                $sheet->getColumnDimensionByColumn($col)->setWidth(50);
145
            }
146
        }
147
148 1
        $sheet->freezePane([1, $this->row + 1]);
149
150 1
        ++$this->row;
151
    }
152
153 1
    private function createList(Spreadsheet $spreadsheet, array $data, string $name): string
154
    {
155 1
        $sheet = $spreadsheet->createSheet();
156 1
        $sheet->setTitle($name);
157 1
        $row = 1;
158 1
        foreach ($data as $d) {
159 1
            $sheet->setCellValue([1, $row++], $d);
160
        }
161
162 1
        $spreadsheet->addNamedRange(
163 1
            new NamedRange(
164 1
                $name,
165 1
                $sheet,
166 1
                'A1:A' . ($row - 1)
167 1
            )
168 1
        );
169
170 1
        return $name;
171
    }
172
173 1
    private function writeSelect(Worksheet $sheet, string $name): void
174
    {
175 1
        $validation = $sheet
176 1
            ->getCell([$this->col++, $this->row])
177 1
            ->getDataValidation();
178
179 1
        $validation->setType(DataValidation::TYPE_LIST)
180 1
            ->setErrorStyle(DataValidation::STYLE_INFORMATION)
181 1
            ->setAllowBlank(true)
182 1
            ->setShowInputMessage(true)
183 1
            ->setShowErrorMessage(true)
184 1
            ->setShowDropDown(true)
185 1
            ->setErrorTitle('Erreur de saisie')
186 1
            ->setError('Cette valeur est introuvable dans la liste.')
187 1
            ->setPromptTitle('Choisissez dans la liste')
188 1
            ->setPrompt('Choisissez un élément de la liste.')
189 1
            ->setFormula1('=' . $name);
190
    }
191
192 1
    public static function createSpreadsheet(?User $user, Site $site, string $title): Spreadsheet
193
    {
194 1
        $spreadsheet = new Spreadsheet();
195
196
        // Set a few meta data
197 1
        $properties = $spreadsheet->getProperties();
198 1
        $properties->setCreator($user ? $user->getLogin() : '');
199 1
        $properties->setLastModifiedBy($site->getDescription());
200 1
        $properties->setTitle($title);
201 1
        $properties->setSubject('Généré par le système ' . $site->getDescription());
202 1
        $properties->setDescription("Certaines images sont soumises aux droits d'auteurs. Vous pouvez nous contactez à [email protected] pour plus d'informations.");
203 1
        $properties->setKeywords('Université de Lausanne');
204
205 1
        return $spreadsheet;
206
    }
207
208 1
    private function createResponse(Spreadsheet $spreadsheet): ResponseInterface
209
    {
210
        // Write to disk
211 1
        $tempFile = tempnam('data/tmp/', 'xlsx');
212
213 1
        $writer = new Xlsx($spreadsheet);
214 1
        $writer->save($tempFile);
215
216 1
        $headers = [
217 1
            'content-type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
218 1
            'content-length' => filesize($tempFile),
219 1
            'content-disposition' => 'inline; filename="' . $spreadsheet->getProperties()->getTitle() . '.xlsx"',
220 1
        ];
221
222 1
        $stream = new TemporaryFile($tempFile);
223 1
        $response = new Response($stream, 200, $headers);
224
225 1
        return $response;
226
    }
227
}
228