-
Notifications
You must be signed in to change notification settings - Fork 68
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
NEW Allow file variants with different extensions #585
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,6 @@ | |
|
||
namespace SilverStripe\Assets\FilenameParsing; | ||
|
||
use SilverStripe\Core\Injector\Injectable; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missed this in the refactor PR - it's not used anymore |
||
|
||
/** | ||
* Parsed Natural path URLs. Natural path is the same hashless path that appears in the CMS. | ||
* | ||
|
@@ -23,10 +21,16 @@ public function parseFileID($fileID) | |
} | ||
|
||
$filename = $matches['folder'] . $matches['basename'] . $matches['extension']; | ||
$variant = $matches['variant'] ?: ''; | ||
|
||
if ($variant) { | ||
$filename = $this->swapExtension($filename, $variant, self::EXTENSION_ORIGINAL); | ||
} | ||
|
||
return new ParsedFileID( | ||
$filename, | ||
'', | ||
isset($matches['variant']) ? $matches['variant'] : '', | ||
$variant, | ||
$fileID | ||
); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,9 +37,15 @@ public function __construct(Factory $creator) | |
*/ | ||
public function create($service, array $params = []) | ||
{ | ||
/** @var AssetContainer $assetContainer */ | ||
/** @var AssetContainer|null $assetContainer */ | ||
$assetContainer = reset($params); | ||
if (!$assetContainer instanceof AssetContainer) { | ||
|
||
// If no asset container was passed in, create a new uncached image backend | ||
if (!$assetContainer) { | ||
return $this->creator->create($service, $params); | ||
} | ||
Comment on lines
+43
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needed so that developers can get an instance of the injected |
||
|
||
if (!($assetContainer instanceof AssetContainer)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This used to be |
||
throw new BadMethodCallException("Can only create Image_Backend for " . AssetContainer::class); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
|
||
use InvalidArgumentException; | ||
use LogicException; | ||
use SilverStripe\Assets\FilenameParsing\AbstractFileIDHelper; | ||
use SilverStripe\Assets\Storage\AssetContainer; | ||
use SilverStripe\Assets\Storage\AssetStore; | ||
use SilverStripe\Assets\Storage\DBFile; | ||
|
@@ -840,13 +841,25 @@ public function isHeight($height) | |
return $this->getHeight() === $height; | ||
} | ||
|
||
/** | ||
* Wrapper for manipulate() that creates a variant file with a different extension than the original file. | ||
* | ||
* @return DBFile|null The manipulated file | ||
*/ | ||
public function manipulateExtension(string $newExtension, callable $callback) | ||
GuySartorelli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
$pathParts = pathinfo($this->getFilename()); | ||
$variant = $this->variantName(AbstractFileIDHelper::EXTENSION_REWRITE_VARIANT, $pathParts['extension'], $newExtension); | ||
return $this->manipulate($variant, $callback); | ||
} | ||
|
||
/** | ||
* Wrapper for manipulate that passes in and stores Image_Backend objects instead of tuples | ||
* | ||
* @param string $variant | ||
* @param callable $callback Callback which takes an Image_Backend object, and returns an Image_Backend result. | ||
* If this callback returns `true` then the current image will be duplicated without modification. | ||
* @return DBFile The manipulated file | ||
* @return DBFile|null The manipulated file | ||
*/ | ||
public function manipulateImage($variant, $callback) | ||
{ | ||
|
@@ -914,7 +927,7 @@ function (AssetStore $store, $filename, $hash, $variant) use ($callback) { | |
* This callback will be passed the backend, filename, hash, and variant | ||
* This will not be called if the file does not | ||
* need to be created. | ||
* @return DBFile The manipulated file | ||
* @return DBFile|null The manipulated file | ||
*/ | ||
public function manipulate($variant, $callback) | ||
{ | ||
|
@@ -999,6 +1012,7 @@ public function variantName($format, $arg = null) | |
* For legacy reasons, there's no delimiter between this part, and the encoded arguments. | ||
* This means we have to use a whitelist of "known formats", based on methods | ||
* available on the {@link Image} class as the "main" user of this trait. | ||
* The one exception to this is the variant for swapping file extensions, which is explicitly allowed. | ||
* This class is commonly decorated with additional manipulation methods through {@link DataExtension}. | ||
* | ||
* @param $variantName | ||
|
@@ -1007,10 +1021,11 @@ public function variantName($format, $arg = null) | |
*/ | ||
public function variantParts($variantName) | ||
{ | ||
$methods = array_map('preg_quote', singleton(Image::class)->allMethodNames() ?? []); | ||
$allowedVariantTypes = array_map('preg_quote', singleton(Image::class)->allMethodNames() ?? []); | ||
$allowedVariantTypes[] = preg_quote(AbstractFileIDHelper::EXTENSION_REWRITE_VARIANT); | ||
|
||
// Regex needs to be case insensitive since allMethodNames() is all lowercased | ||
$regex = '#^(?<format>(' . implode('|', $methods) . '))(?<encodedargs>(.*))#i'; | ||
$regex = '#^(?<format>(' . implode('|', $allowedVariantTypes) . '))(?<encodedargs>(.*))#i'; | ||
preg_match($regex ?? '', $variantName ?? '', $matches); | ||
|
||
if (!$matches) { | ||
|
@@ -1022,7 +1037,7 @@ public function variantParts($variantName) | |
throw new InvalidArgumentException('Invalid variant name arguments: ' . $variantName); | ||
} | ||
|
||
return array_merge([$matches['format']], $args[0]); | ||
return array_merge([$matches['format']], $args); | ||
Comment on lines
-1025
to
+1040
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See the description of c8f0c29 |
||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -366,8 +366,10 @@ public function writeToStore(AssetStore $assetStore, $filename, $hash = null, $v | |
throw new BadMethodCallException("Cannot write corrupt file to store"); | ||
} | ||
|
||
// Make sure we're using the extension of the variant file, which can differ from the original file | ||
$url = $assetStore->getAsURL($filename, $hash, $variant, false); | ||
$extension = pathinfo($url, PATHINFO_EXTENSION); | ||
// Save file | ||
$extension = pathinfo($filename ?? '', PATHINFO_EXTENSION); | ||
Comment on lines
+369
to
-370
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change is vital if using |
||
$result = $assetStore->setFromString( | ||
$resource->encode($extension, $this->getQuality())->getEncoded(), | ||
$filename, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when the original filename has underscores in it? You'll need to add a unit test for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It won't match the variant regex and so it will be ignored.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added underscores to file names in the test scenarios.