-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The trait is a bit ugly - much nicer to have that functionality in an abstract class that the concrete helpers can extend. This also means we can refactor those classes a bit to reduce unnecessary code duplication.
- Loading branch information
1 parent
8d5eb94
commit f75efd4
Showing
6 changed files
with
176 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
<?php | ||
|
||
namespace SilverStripe\Assets\FilenameParsing; | ||
|
||
use SilverStripe\Core\Convert; | ||
use SilverStripe\Core\Injector\Injectable; | ||
|
||
abstract class AbstractFileIDHelper implements FileIDHelper | ||
{ | ||
use Injectable; | ||
|
||
/** | ||
* A variant type for encoding a variant filename with a different extension than the original. | ||
*/ | ||
public const EXTENSION_REWRITE_VARIANT = 'extRewrite'; | ||
|
||
/** | ||
* use the original file's extension | ||
*/ | ||
private const EXT_ORIGINAL = 0; | ||
|
||
/** | ||
* use the variant file's extension | ||
*/ | ||
private const EXT_VARIANT = 1; | ||
|
||
public function buildFileID($filename, $hash = null, $variant = null, $cleanfilename = true) | ||
{ | ||
if ($filename instanceof ParsedFileID) { | ||
$hash = $filename->getHash(); | ||
$variant = $filename->getVariant(); | ||
$filename = $filename->getFilename(); | ||
} | ||
|
||
$this->validateFileParts($filename, $hash, $variant); | ||
|
||
// Since we use double underscore to delimit variants, eradicate them from filename | ||
if ($cleanfilename) { | ||
$filename = $this->cleanFilename($filename); | ||
} | ||
|
||
if ($variant) { | ||
$filename = $this->rewriteVariantExtension($filename, $variant); | ||
} | ||
|
||
$name = basename($filename ?? ''); | ||
|
||
// Split extension | ||
$extension = null; | ||
if (($pos = strpos($name ?? '', '.')) !== false) { | ||
$extension = substr($name ?? '', $pos ?? 0); | ||
$name = substr($name ?? '', 0, $pos); | ||
} | ||
|
||
$fileID = $this->getFileIDBase($name, $filename, $hash, $variant); | ||
|
||
// Add directory | ||
$dirname = ltrim(dirname($filename ?? ''), '.'); | ||
if ($dirname) { | ||
$fileID = $dirname . '/' . $fileID; | ||
} | ||
|
||
// Add variant | ||
if ($variant) { | ||
$fileID .= '__' . $variant; | ||
} | ||
|
||
// Add extension | ||
if ($extension) { | ||
$fileID .= $extension; | ||
} | ||
|
||
return $fileID; | ||
} | ||
|
||
/** | ||
* Get the original filename with the extension rewritten to be the same as the variant file extension. | ||
* | ||
* @param string $filename Original filename without variant | ||
*/ | ||
public function rewriteVariantExtension(string $filename, string $variant): string | ||
{ | ||
return $this->swapExtension($filename, $variant, self::EXT_VARIANT); | ||
} | ||
|
||
/** | ||
* Get the variant filename with the extension rewritten to be the same as the original file extension. | ||
* | ||
* @param string $filename Original filename without variant | ||
*/ | ||
public function restoreOriginalExtension(string $filename, string $variant): string | ||
{ | ||
return $this->swapExtension($filename, $variant, self::EXT_ORIGINAL); | ||
} | ||
|
||
/** | ||
* Get the original file's filename with the extension rewritten to be the same as either the original | ||
* or the variant extension. | ||
* | ||
* @param string $filename Original filename without variant | ||
* @param int $extIndex One of self::EXT_ORIGINAL or self::EXT_VARIANT | ||
*/ | ||
private function swapExtension(string $filename, string $variant, int $extIndex): string | ||
{ | ||
// If there's no variant at all, we can rewrite the filenmane | ||
if (empty($variant)) { | ||
return $filename; | ||
} | ||
|
||
// Split variant string in variant list | ||
$subVariants = explode('_', $variant); | ||
|
||
// Split our filename into a filename and extension part | ||
if (!preg_match('/(?<basename>.+)\.(?<ext>[a-z\d]+)$/i', $filename, $matches)) { | ||
return $filename; | ||
} | ||
$filenameWithoutExtension = $matches['basename']; | ||
$extension = $matches['ext']; | ||
|
||
// Loop our variant list until we find our special file extension swap variant | ||
// Reverse the list first so the variant extension we find is the last extension rewrite variant in a chain | ||
$extSwapVariant = preg_quote(self::EXTENSION_REWRITE_VARIANT, '/'); | ||
foreach (array_reverse($subVariants) as $subVariant) { | ||
if (preg_match("/^$extSwapVariant(?<base64>.+)$/", $subVariant, $matches)) { | ||
// This array always contain 2 values: The original extension at index 0 and the variant extension at index 1 | ||
/** @var array $extensionData */ | ||
$extensionData = Convert::base64url_decode($matches['base64']); | ||
$extension = $extensionData[$extIndex]; | ||
break; | ||
} | ||
} | ||
|
||
return $filenameWithoutExtension . '.' . $extension; | ||
} | ||
|
||
public function cleanFilename($filename) | ||
{ | ||
// Swap backslash for forward slash | ||
$filename = str_replace('\\', '/', $filename ?? ''); | ||
|
||
// Since we use double underscore to delimit variants, eradicate them from filename | ||
return preg_replace('/_{2,}/', '_', $filename ?? ''); | ||
} | ||
|
||
public function lookForVariantRecursive(): bool | ||
{ | ||
return false; | ||
} | ||
|
||
abstract protected function getFileIDBase($shortFilename, $fullFilename, $hash, $variant): string; | ||
|
||
abstract protected function validateFileParts($filename, $hash, $variant): void; | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.