use Exception;
use Illuminate\Contracts\Cache\Repository as Cache;
use Illuminate\Contracts\Filesystem\Factory as FileSystem;
+use Illuminate\Support\Str;
use Intervention\Image\Exception\NotSupportedException;
use Intervention\Image\ImageManager;
use phpDocumentor\Reflection\Types\Integer;
*/
protected function getStorage($type = '')
{
- $storageType = config('filesystems.default');
+ $storageType = config('filesystems.images');
- // Override default location if set to local public to ensure not visible.
+ // Ensure system images (App logo) are uploaded to a public space
if ($type === 'system' && $storageType === 'local_secure') {
$storageType = 'local';
}
}
/**
- * Saves a new image
- * @param string $imageName
- * @param string $imageData
- * @param string $type
- * @param int $uploadedTo
- * @return Image
+ * Save a new image into storage.
* @throws ImageUploadException
*/
- private function saveNew($imageName, $imageData, $type, $uploadedTo = 0)
+ private function saveNew(string $imageName, string $imageData, string $type, int $uploadedTo = 0): Image
{
$storage = $this->getStorage($type);
$secureUploads = setting('app-secure-images');
- $imageName = str_replace(' ', '-', $imageName);
+ $fileName = $this->cleanImageFileName($imageName);
$imagePath = '/uploads/images/' . $type . '/' . Date('Y-m') . '/';
- while ($storage->exists($imagePath . $imageName)) {
- $imageName = str_random(3) . $imageName;
+ while ($storage->exists($imagePath . $fileName)) {
+ $fileName = Str::random(3) . $fileName;
}
- $fullPath = $imagePath . $imageName;
+ $fullPath = $imagePath . $fileName;
if ($secureUploads) {
- $fullPath = $imagePath . str_random(16) . '-' . $imageName;
+ $fullPath = $imagePath . Str::random(16) . '-' . $fileName;
}
try {
return $image;
}
+ /**
+ * Clean up an image file name to be both URL and storage safe.
+ */
+ protected function cleanImageFileName(string $name): string
+ {
+ $name = str_replace(' ', '-', $name);
+ $nameParts = explode('.', $name);
+ $extension = array_pop($nameParts);
+ $name = implode('.', $nameParts);
+ $name = Str::slug($name);
+
+ if (strlen($name) === 0) {
+ $name = Str::random(10);
+ }
+
+ return $name . '.' . $extension;
+ }
/**
* Checks if the image is a gif. Returns true if it is, else false.
$storage->put($thumbFilePath, $thumbData);
$storage->setVisibility($thumbFilePath, 'public');
- $this->cache->put('images-' . $image->id . '-' . $thumbFilePath, $thumbFilePath, 60 * 72);
+ $this->cache->put('images-' . $image->id . '-' . $thumbFilePath, $thumbFilePath, 60 * 60 * 72);
+
return $this->getPublicUrl($thumbFilePath);
}
} else {
$thumb->fit($width, $height);
}
- return (string)$thumb->encode();
+
+ $thumbData = (string)$thumb->encode();
+
+ // Use original image data if we're keeping the ratio
+ // and the resizing does not save any space.
+ if ($keepRatio && strlen($thumbData) > strlen($imageData)) {
+ return $imageData;
+ }
+
+ return $thumbData;
}
/**
/**
* Destroys an image at the given path.
- * Searches for image thumbnails in addition to main provided path..
- * @param string $path
- * @return bool
+ * Searches for image thumbnails in addition to main provided path.
*/
- protected function destroyImagesFromPath(string $path)
+ protected function destroyImagesFromPath(string $path): bool
{
$storage = $this->getStorage();
// Delete image files
$imagesToDelete = $allImages->filter(function ($imagePath) use ($imageFileName) {
- $expectedIndex = strlen($imagePath) - strlen($imageFileName);
- return strpos($imagePath, $imageFileName) === $expectedIndex;
+ return basename($imagePath) === $imageFileName;
});
$storage->delete($imagesToDelete->all());
$isLocal = strpos(trim($uri), 'http') !== 0;
// Attempt to find local files even if url not absolute
- $base = baseUrl('/');
+ $base = url('/');
if (!$isLocal && strpos($uri, $base) === 0) {
$isLocal = true;
$uri = str_replace($base, '', $uri);
return null;
}
- return 'data:image/' . pathinfo($uri, PATHINFO_EXTENSION) . ';base64,' . base64_encode($imageData);
+ $extension = pathinfo($uri, PATHINFO_EXTENSION);
+ if ($extension === 'svg') {
+ $extension = 'svg+xml';
+ }
+
+ return 'data:image/' . $extension . ';base64,' . base64_encode($imageData);
}
/**
// Get the standard public s3 url if s3 is set as storage type
// Uses the nice, short URL if bucket name has no periods in otherwise the longer
// region-based url will be used to prevent http issues.
- if ($storageUrl == false && config('filesystems.default') === 's3') {
+ if ($storageUrl == false && config('filesystems.images') === 's3') {
$storageDetails = config('filesystems.disks.s3');
if (strpos($storageDetails['bucket'], '.') === false) {
$storageUrl = 'https://' . $storageDetails['bucket'] . '.s3.amazonaws.com';
$this->storageUrl = $storageUrl;
}
- $basePath = ($this->storageUrl == false) ? baseUrl('/') : $this->storageUrl;
+ $basePath = ($this->storageUrl == false) ? url('/') : $this->storageUrl;
return rtrim($basePath, '/') . $filePath;
}
}