| 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; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 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(private readonly ImageResizer $imageResizer) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 | 1 |  |         $this->escape = new Escaper(); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 33 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 34 | 2 |  |     public function getExtension(): string | 
            
                                                                        
                            
            
                                    
            
            
                | 35 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 36 | 2 |  |         return 'zip'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 | 3 |  |     public function initialize(Export $export, string $title): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 | 3 |  |         $this->fileIndex = 0; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 | 3 |  |         $this->export = $export; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 | 3 |  |         $this->zip = new ZipArchive(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 | 3 |  |         $result = $this->zip->open($export->getPath(), ZipArchive::CREATE | ZipArchive::OVERWRITE); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 | 3 |  |         if ($result !== true) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |             throw new Exception($this->zip->getStatusString()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 | 3 |  |     public function write(Card $card): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 | 3 |  |         $image = $this->insertImage($card); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 | 3 |  |         if ($this->export->isIncludeLegend()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 | 3 |  |             $this->insertLegend($card, $image); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 | 3 |  |     public function finalize(): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 | 3 |  |         if ($this->fileIndex === 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |             $this->zip->addFromString('readme.txt', "Aucune fiche n'était exportable. Probablement parce qu'aucune fiche n'avait d'images."); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 | 3 |  |         $this->zip->close(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 | 3 |  |     private function insertImage(Card $card): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |         // Skip if no image | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 | 3 |  |         if (!$card->hasImage() || !is_readable($card->getPath())) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 | 1 |  |             return ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 | 3 |  |         if ($this->export->getMaxHeight()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |             $path = $this->imageResizer->resize($card, $this->export->getMaxHeight(), false); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |         } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 | 3 |  |             $path = $card->getPath(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 | 3 |  |         $extension = pathinfo($path, PATHINFO_EXTENSION); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 | 3 |  |         $filename = $card->getId() . ($extension ? '.' . $extension : ''); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 | 3 |  |         $added = $this->zip->addFile($path, $filename); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 | 3 |  |         if ($added) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 | 3 |  |             $this->zip->setCompressionIndex($this->fileIndex++, ZipArchive::CM_STORE); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 | 3 |  |         return $filename; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 | 3 |  |     private function insertLegend(Card $card, string $image): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 | 3 |  |         $html = '<!DOCTYPE html>'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 | 3 |  |         $html .= '<html lang="fr">'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 | 3 |  |         $html .= '<head>'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 | 3 |  |         $html .= '<title>Base de données ' . $this->export->getSite()->getDescription() . '</title>'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 | 3 |  |         $html .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 | 3 |  |         $html .= '<meta name="author" content="' . $this->escape->escapeHtmlAttr(User::getCurrent() ? User::getCurrent()->getLogin() : '') . '" />'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 | 3 |  |         $html .= '<style>'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 | 3 |  |         $html .= '.detail table { margin:auto; padding:5px; background-color:#d8e7f3; }'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 | 3 |  |         $html .= '.detail th { width:150px; padding-right:5px; text-align:right; }'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 | 3 |  |         $html .= '.detail th:first-letter {text-transform:uppercase}'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 | 3 |  |         $html .= '.detail td { min-width: 500px }'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 | 3 |  |         $html .= '.detail img { max-width:800px; max-height:600px; }'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 | 3 |  |         $html .= '</style>'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 | 3 |  |         $html .= '</head><body>'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 | 3 |  |         $html .= '<div class="detail">'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 | 3 |  |         $html .= '<table>'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 | 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>'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 | 3 |  |         $html .= $this->row('titre', $card->getName()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 | 3 |  |         $html .= $this->row('titre étendu', $card->getExpandedName()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 | 3 |  |         $artists = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 | 3 |  |         foreach ($card->getArtists() as $artist) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 | 1 |  |             $artists[] = $artist->getName(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 | 3 |  |         $html .= $this->row('artistes', implode('<br>', $artists)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 | 3 |  |         $html .= $this->row('supplément', $card->getAddition()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 | 3 |  |         $html .= $this->row('datation', $card->getDating()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 | 3 |  |         $domains = array_map( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 | 3 |  |             fn ($domain) => $domain->getName(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 | 3 |  |             $card->getDomains()->toArray(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 | 3 |  |         ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 | 3 |  |         $html .= $this->row('domaines', implode('<br>', $domains)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 | 3 |  |         $html .= $this->row('technique & matériel', $card->getMaterial()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 | 3 |  |         $html .= $this->row('format', $card->getFormat()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 | 3 |  |         $html .= $this->row('adresse', implode(', ', array_filter([$card->getStreet(), $card->getPostcode(), $card->getLocality(), $card->getArea(), $card->getCountry() ? $card->getCountry()->getName() : '']))); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 | 3 |  |         $html .= $this->row('institution', $card->getInstitution() ? $card->getInstitution()->getName() : ''); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 | 3 |  |         $html .= $this->row('literature', $card->getLiterature()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 | 3 |  |         $html .= $this->row('page', $card->getPage()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 | 3 |  |         $html .= $this->row('planche', $card->getFigure()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 | 3 |  |         $html .= $this->row('table', $card->getTable()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 | 3 |  |         $html .= $this->row('ISBN', $card->getIsbn()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 | 3 |  |         $html .= '</table>'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 | 3 |  |         $html .= '</div>'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 | 3 |  |         $html .= '</body></html>'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 | 3 |  |         $added = $this->zip->addFromString($card->getId() . '.html', $html); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 | 3 |  |         if ($added) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 | 3 |  |             $this->zip->setCompressionIndex($this->fileIndex++, ZipArchive::CM_STORE); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 | 3 |  |     private function row(string $label, string $value): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 | 3 |  |         if (!$value) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 | 3 |  |             return ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 | 3 |  |         return '<tr><th>' . $label . '</th><td>' . $value . '</td></tr>' . PHP_EOL; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 159 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 160 |  |  |  |