directory; } /** Legt eine Variante ab. Scheitert still: das Abbild ist eine Abkürzung, keine Voraussetzung. */ public function publish(string $id, int $width, string $source): void { if (!$this->enabled() || 1 !== preg_match('/^[a-f0-9]{32}$/D', $id) || $width < 1 || $width > 9999) { return; } $folder = $this->directory.'/'.$id; $target = $folder.'/'.$width.'.webp'; if (is_file($target)) { return; } if (!is_dir($folder) && !@mkdir($folder, 0o775, true) && !is_dir($folder)) { return; } // Ein harter Verweis kostet keinen zweiten Platz auf der Platte. Wo das Dateisystem ihn // nicht kennt oder der Medienordner woanders liegt, wird kopiert - über eine Zwischendatei, // damit der Webserver nie ein halbes Bild ausliefert. if (@link($source, $target)) { return; } $teil = $target.'.'.bin2hex(random_bytes(4)).'.tmp'; if (@copy($source, $teil) && filesize($source) === filesize($teil) && @rename($teil, $target)) { return; } @unlink($teil); } /** * Entfernt aus dem Abbild, was es im Medienordner nicht mehr gibt - nach dem Import eines * Website-Pakets etwa. Ohne das lieferte der Webserver Bilder weiter aus, die die Anwendung * selbst nicht mehr kennt. * * @return int entfernte Dateien */ public function prune(): int { if (!$this->enabled() || !is_dir($this->directory)) { return 0; } $removed = 0; foreach (scandir($this->directory) ?: [] as $id) { if (1 !== preg_match('/^[a-f0-9]{32}$/D', $id) || !is_dir($this->directory.'/'.$id)) { continue; } foreach (scandir($this->directory.'/'.$id) ?: [] as $name) { if ('.' === $name || '..' === $name) { continue; } $width = 1 === preg_match('/^(\d{1,4})\.webp$/D', $name, $treffer) ? $treffer[1] : null; if (null === $width || !is_file($this->mediaDirectory.'/'.$id.'-'.$width.'.webp')) { $removed += (int) @unlink($this->directory.'/'.$id.'/'.$name); } } // Gelingt nur, wenn der Ordner leer ist - genau dann soll er weg. @rmdir($this->directory.'/'.$id); } return $removed; } }