]> BookStack Code Mirror - bookstack/blobdiff - app/Uploads/FaviconHandler.php
Enhance changelog input to textarea with character counter
[bookstack] / app / Uploads / FaviconHandler.php
index 39f8b12ca7ca8572cb7c8ba9020c1799f7bee560..d5044943cb7305eb43b03023ab6fcc8acd8aacad 100644 (file)
@@ -3,13 +3,15 @@
 namespace BookStack\Uploads;
 
 use Illuminate\Http\UploadedFile;
-use Intervention\Image\ImageManager;
 
 class FaviconHandler
 {
+    protected string $path;
+
     public function __construct(
-        protected ImageManager $imageTool
+        protected ImageResizer $imageResizer,
     ) {
+        $this->path = public_path('favicon.ico');
     }
 
     /**
@@ -17,49 +19,67 @@ class FaviconHandler
      */
     public function saveForUploadedImage(UploadedFile $file): void
     {
-        $targetPath = public_path('favicon.ico');
-        if (!is_writeable($targetPath)) {
+        if (!is_writeable($this->path)) {
             return;
         }
 
         $imageData = file_get_contents($file->getRealPath());
-        $image = $this->imageTool->make($imageData);
-        $image->resize(32, 32);
-        $bmpData = $image->encode('bmp');
-        $icoData = $this->bmpToIco($bmpData, 32, 32);
-
-//        file_put_contents(public_path('icon.bmp'), $bmpData);
-//        file_put_contents(public_path('icon-test.png'), $image->encode('png'));
-        file_put_contents($targetPath, $icoData);
+        $pngData = $this->imageResizer->resizeImageData($imageData, 32, 32, false, 'png');
+        $icoData = $this->pngToIco($pngData, 32, 32);
+
+        file_put_contents($this->path, $icoData);
     }
 
     /**
      * Restore the original favicon image.
+     * Returned boolean indicates if the copy occurred.
      */
-    public function restoreOriginal(): void
+    public function restoreOriginal(): bool
     {
-        $targetPath = public_path('favicon.ico');
-        $original = public_path('icon.ico');
-        if (!is_writeable($targetPath)) {
-            return;
+        $permissionItem = file_exists($this->path) ? $this->path : dirname($this->path);
+        if (!is_writeable($permissionItem)) {
+            return false;
         }
 
-        copy($original, $targetPath);
+        return copy($this->getOriginalPath(), $this->path);
+    }
+
+    /**
+     * Restore the original favicon image if no favicon image is already in use.
+     * Returns a boolean to indicate if the file exists.
+     */
+    public function restoreOriginalIfNotExists(): bool
+    {
+        if (file_exists($this->path)) {
+            return true;
+        }
+
+        return $this->restoreOriginal();
+    }
+
+    /**
+     * Get the path to the favicon file.
+     */
+    public function getPath(): string
+    {
+        return $this->path;
     }
 
     /**
-     * Convert BMP image data to ICO file format.
+     * Get the path of the original favicon copy.
+     */
+    public function getOriginalPath(): string
+    {
+        return public_path('icon.ico');
+    }
+
+    /**
+     * Convert PNG image data to ICO file format.
      * Built following the file format info from Wikipedia:
      * https://en.wikipedia.org/wiki/ICO_(file_format)
      */
-    protected function bmpToIco(string $bmpData, int $width, int $height): string
+    protected function pngToIco(string $pngData, int $width, int $height): string
     {
-        // Trim off the header of the bitmap file
-        $rawBmpData = substr($bmpData, 14);
-        // Double the height in the "BITMAPINFOHEADER" since, when in an ICO file, half
-        // of the image data is expected to be a mask.
-        $rawBmpData[8] = hex2bin(dechex($height * 2));
-
         // ICO header
         $header = pack('v', 0x00); // Reserved. Must always be 0
         $header .= pack('v', 0x01); // Specifies ico image
@@ -71,23 +91,17 @@ class FaviconHandler
         $entry .= "\0"; // Color palette, typically 0
         $entry .= "\0"; // Reserved
 
-        // AND mask
-//        $pxCount = $width * $height;
-//        $pxMask = hex2bin('00000000');
-//        $mask = str_repeat($pxMask, $pxCount);
-        $mask = '';
-
         // Color planes, Appears to remain 1 for bmp image data
         $entry .= pack('v', 0x01);
         // Bits per pixel, can range from 1 to 32. From testing conversion
         // via intervention from png typically provides this as 24.
-        $entry .= pack('v', 0x18);
+        $entry .= pack('v', 0x00);
         // Size of the image data in bytes
-        $entry .= pack('V', strlen($rawBmpData) + strlen($mask));
+        $entry .= pack('V', strlen($pngData));
         // Offset of the bmp data from file start
         $entry .= pack('V', strlen($header) + strlen($entry) + 4);
 
         // Join & return the combined parts of the ICO image data
-        return $header . $entry . $rawBmpData . $mask;
+        return $header . $entry . $pngData;
     }
 }