TemplateHandler::export()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 55
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 42
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 40
c 0
b 0
f 0
dl 0
loc 55
ccs 42
cts 42
cp 1
rs 9.28
cc 2
nc 2
nop 0
crap 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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