Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allows to use remote images #76

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions classes/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

class Image
{
use RemoteImageTrait;

/**
* Original path of image
*/
Expand Down Expand Up @@ -53,6 +55,11 @@ public function __construct($filePath = false)
return;
}

// If file path is a remote image, download and use as local file
if ($this->isRemoteFile($filePath)) {
$filePath = $this->getRemoteFile($filePath);
}

$this->file->file_name = $filePath;

$this->filePath = (file_exists($filePath))
Expand Down
126 changes: 126 additions & 0 deletions classes/RemoteImageTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php

namespace ToughDeveloper\ImageResizer\Classes;

use File as FileHelper;
use October\Rain\Network\Http;
use October\Rain\Database\Attach\File;
use Illuminate\Support\Facades\Storage;

trait RemoteImageTrait
{
/**
* Determine if a file path is a remote image
*
* @param string $filePath
* @return boolean
*/
protected function isRemoteFile($filePath)
{
return filter_var($filePath, FILTER_VALIDATE_URL);
}

/**
* Store a remote image locally
*
* @param string $filePath
* @return string
*/
protected function getRemoteFile($filePath)
{
$tempImage = $this->generateStoragePath($filePath);
$tempFullPath = storage_path('app/' . $tempImage);

// Check if remote image was already downloaded
if (Storage::exists($tempImage)) {
return $tempFullPath;
}

// If URL doesn't have extension, check if exists a file with one of the allowed extensions
$imageExists = $this->checkLocalRemoteImage($tempImage);

// If found, use already downloaded image
if ($imageExists) {
return storage_path('app/' . $imageExists);
}

// Download image from remote location
Http::get($filePath, function ($http) use ($tempFullPath) {
$http->toFile($tempFullPath);
});

// If URL doesn't have extension, discover extension and rename local image
if (!FileHelper::extension($tempFullPath)) {
$extension = $this->discoverImageExtension($tempFullPath);
$newFullPath = sprintf('%s%s', $tempFullPath, $extension);
rename($tempFullPath, $newFullPath);
$tempFullPath = $newFullPath;
}

return $tempFullPath;
}

/**
* Generate storage path to store cached remote images
*
* @param string $filePath
* @return string
*/
protected function generateStoragePath($filePath)
{
$extension = $this->getRemoteFileExtension($filePath);
$tempPath = $this->file->getStorageDirectory() . $this->getPartitionDirectory();
$tempFilename = md5($filePath);

Storage::makeDirectory($tempPath);

$fileMask = $extension ? '%s%s.%s' : '%s%s';

return sprintf($fileMask, $tempPath, $tempFilename, $extension);
}

/**
* Get file extension from remote image URL
*
* @param string $filePath
* @return string
*/
protected function getRemoteFileExtension($filePath)
{
// Remove query string from url
if (parse_url($filePath, PHP_URL_QUERY)) {
$filePath = strtok($filePath, '?');
}

return FileHelper::extension($filePath);
}

/**
* If remote image doesn't expose file extension, discover by looking downloaded file
*
* @param string $filePath
* @return string
*/
protected function discoverImageExtension($filePath)
{
$imageType = exif_imagetype($filePath);
$extension = image_type_to_extension($imageType);
return $extension;
}

/**
* If URL doesn't have extension, check if exists a file with one of the allowed extensions
*
* @param $string $filePath
* @return Collection
*/
protected function checkLocalRemoteImage($filePath)
{
$allowedExtensions = File::$imageExtensions;

return collect($allowedExtensions)->map(function ($imageType) use ($filePath) {
$findImage = sprintf('%s.%s', $filePath, $imageType);
return Storage::exists($findImage) ? $findImage : false;
})->filter()->first();
}
}