Zip   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 140
Duplicated Lines 0 %

Test Coverage

Coverage 96.3%

Importance

Changes 0
Metric Value
wmc 22
eloc 78
dl 0
loc 140
c 0
b 0
f 0
ccs 78
cts 81
cp 0.963
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
B insertLegend() 0 56 6
A getExtension() 0 3 1
A write() 0 5 2
A row() 0 7 2
A initialize() 0 9 2
A insertImage() 0 22 6
A __construct() 0 4 1
A finalize() 0 7 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Service\Exporter;
6
7
use Application\Model\Card;
8
use Application\Model\Export;
9
use Application\Model\User;
10
use Application\Service\ImageResizer;
11
use Application\Utility;
0 ignored issues
show
Bug introduced by
The type Application\Utility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Ecodev\Felix\Api\Exception;
13
use Laminas\Escaper\Escaper;
14
use ZipArchive;
15
16
/**
17
 * Export multiples cards as zip file.
18
 */
19
class Zip implements Writer
20
{
21
    private ?ZipArchive $zip = null;
22
23
    private int $fileIndex = 0;
24
25
    private Export $export;
26
27
    private readonly Escaper $escape;
28
29 1
    public function __construct(
30
        private readonly ImageResizer $imageResizer,
31
    ) {
32 1
        $this->escape = new Escaper();
0 ignored issues
show
Bug introduced by
The property escape is declared read-only in Application\Service\Exporter\Zip.
Loading history...
33
    }
34
35 2
    public function getExtension(): string
36
    {
37 2
        return 'zip';
38
    }
39
40 3
    public function initialize(Export $export, string $title): void
41
    {
42 3
        $this->fileIndex = 0;
43 3
        $this->export = $export;
44 3
        $this->zip = new ZipArchive();
45 3
        $result = $this->zip->open($export->getPath(), ZipArchive::CREATE | ZipArchive::OVERWRITE);
46
47 3
        if ($result !== true) {
48
            throw new Exception($this->zip->getStatusString());
49
        }
50
    }
51
52 3
    public function write(Card $card): void
53
    {
54 3
        $image = $this->insertImage($card);
55 3
        if ($this->export->isIncludeLegend()) {
56 3
            $this->insertLegend($card, $image);
57
        }
58
    }
59
60 3
    public function finalize(): void
61
    {
62 3
        if ($this->fileIndex === 0) {
63
            $this->zip->addFromString('readme.txt', "Aucune fiche n'était exportable. Probablement parce qu'aucune fiche n'avait d'images.");
0 ignored issues
show
Bug introduced by
The method addFromString() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

63
            $this->zip->/** @scrutinizer ignore-call */ 
64
                        addFromString('readme.txt', "Aucune fiche n'était exportable. Probablement parce qu'aucune fiche n'avait d'images.");

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
64
        }
65
66 3
        $this->zip->close();
67
    }
68
69 3
    private function insertImage(Card $card): string
70
    {
71
        // Skip if no image
72 3
        if (!$card->hasImage() || !is_readable($card->getPath())) {
73 1
            return '';
74
        }
75
76 3
        if ($this->export->getMaxHeight()) {
77
            $path = $this->imageResizer->resize($card, $this->export->getMaxHeight(), false);
78
        } else {
79 3
            $path = $card->getPath();
80
        }
81
82 3
        $extension = pathinfo($path, PATHINFO_EXTENSION);
83 3
        $filename = $card->getId() . ($extension ? '.' . $extension : '');
0 ignored issues
show
Bug introduced by
Are you sure $extension of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

83
        $filename = $card->getId() . ($extension ? '.' . /** @scrutinizer ignore-type */ $extension : '');
Loading history...
84 3
        $added = $this->zip->addFile($path, $filename);
85
86 3
        if ($added) {
87 3
            $this->zip->setCompressionIndex($this->fileIndex++, ZipArchive::CM_STORE);
88
        }
89
90 3
        return $filename;
91
    }
92
93 3
    private function insertLegend(Card $card, string $image): void
94
    {
95 3
        $html = '<!DOCTYPE html>';
96 3
        $html .= '<html lang="fr">';
97 3
        $html .= '<head>';
98 3
        $html .= '<title>Base de données ' . $this->export->getSite()->getDescription() . '</title>';
99 3
        $html .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
100 3
        $html .= '<meta name="author" content="' . $this->escape->escapeHtmlAttr(User::getCurrent() ? User::getCurrent()->getLogin() : '') . '" />';
101 3
        $html .= '<style>';
102 3
        $html .= '.detail table { margin:auto; padding:5px; background-color:#d8e7f3; }';
103 3
        $html .= '.detail th { width:150px; padding-right:5px; text-align:right; }';
104 3
        $html .= '.detail th:first-letter {text-transform:uppercase}';
105 3
        $html .= '.detail td { min-width: 500px }';
106 3
        $html .= '.detail img { max-width:800px; max-height:600px; }';
107 3
        $html .= '</style>';
108 3
        $html .= '</head><body>';
109 3
        $html .= '<div class="detail">';
110 3
        $html .= '<table>';
111 3
        $html .= '<tr><td colspan="2"><a href="' . $this->escape->escapeHtmlAttr($image) . '"><img src="' . $this->escape->escapeHtmlAttr($image) . '" alt="' . $this->escape->escapeHtmlAttr(Utility::richTextToPlainText($card->getName())) . '"/></a></td></tr>';
112
113 3
        $html .= $this->row('titre', $card->getName());
114 3
        $html .= $this->row('titre étendu', $card->getExpandedName());
115
116 3
        $artists = [];
117 3
        foreach ($card->getArtists() as $artist) {
118 1
            $artists[] = $artist->getName();
119
        }
120 3
        $html .= $this->row('artistes', implode('<br>', $artists));
121
122 3
        $html .= $this->row('supplément', $card->getAddition());
123 3
        $html .= $this->row('datation', $card->getDating());
124
125 3
        $domains = array_map(
126 3
            fn ($domain) => $domain->getName(),
127 3
            $card->getDomains()->toArray(),
128 3
        );
129 3
        $html .= $this->row('domaines', implode('<br>', $domains));
130
131 3
        $html .= $this->row('technique & matériel', $card->getMaterial());
132 3
        $html .= $this->row('format', $card->getFormat());
133 3
        $html .= $this->row('adresse', implode(', ', array_filter([$card->getStreet(), $card->getPostcode(), $card->getLocality(), $card->getArea(), $card->getCountry() ? $card->getCountry()->getName() : ''])));
134 3
        $html .= $this->row('institution', $card->getInstitution() ? $card->getInstitution()->getName() : '');
135 3
        $html .= $this->row('literature', $card->getLiterature());
136 3
        $html .= $this->row('page', $card->getPage());
137 3
        $html .= $this->row('planche', $card->getFigure());
138 3
        $html .= $this->row('table', $card->getTable());
139 3
        $html .= $this->row('ISBN', $card->getIsbn());
140
141 3
        $html .= '</table>';
142 3
        $html .= '</div>';
143 3
        $html .= '</body></html>';
144
145 3
        $added = $this->zip->addFromString($card->getId() . '.html', $html);
146
147 3
        if ($added) {
148 3
            $this->zip->setCompressionIndex($this->fileIndex++, ZipArchive::CM_STORE);
149
        }
150
    }
151
152 3
    private function row(string $label, string $value): string
153
    {
154 3
        if (!$value) {
155 3
            return '';
156
        }
157
158 3
        return '<tr><th>' . $label . '</th><td>' . $value . '</td></tr>' . PHP_EOL;
159
    }
160
}
161