Skip to content

Instantly share code, notes, and snippets.

@phptek
Created July 2, 2019 20:50
Show Gist options
  • Save phptek/f60d895f032c8d05756841b366eb7d96 to your computer and use it in GitHub Desktop.
Save phptek/f60d895f032c8d05756841b366eb7d96 to your computer and use it in GitHub Desktop.
Add the following methods to your `Image` subclass to allow SVG uploads via `$has_one` `UploadField`'s and uploads via the Asset Admin.
Hat-tip to https://github.com/restruct/silverstripe-svg-images. All I've done is:
* Removed superfluous SVG template logic
* Called `isSVG()` from everywhere
* Added comments where appropriate
* Put all necessary YML config into one place
YML config:
# SVG Capabilities
SilverStripe\Assets\File:
app_categories:
image:
- svg
image/supported:
- svg
allowed_extensions:
- 'svg'
class_for_file_extension:
# Unknown at this time, whether this is even needed
svg: My\Image\Subclass
Image subclass:
/**
* @return string
*/
public function getFileType()
{
if ($this->isSVG()) {
return 'SVG image - good for line drawings';
}
return parent::getFileType();
}
/**
* @param string $dim
* @return mixed array|string
*/
public function getDimensions(string $dim = 'string')
{
if (!$this->isSVG() || !$this->exists()) {
return parent::getDimensions($dim);
}
if (!$this->getField('Filename')) {
return [];
}
$filePath = $this->getFullPath();
// parse SVG
$out = new DOMDocument();
$out->load($filePath);
if (!is_object($out) || !is_object($out->documentElement)) {
return [];
}
// Get dimensions from viewbox or else from width/height on root svg element
$root = $out->documentElement;
if ($root->hasAttribute('viewBox')) {
$vbox = explode(' ', $root->getAttribute('viewBox'));
$size[0] = $vbox[2] - $vbox[0];
$size[1] = $vbox[3] - $vbox[1];
} else if ($root->hasAttribute('width')) {
$size[0] = $root->getAttribute('width');
$size[1] = $root->getAttribute('height');
} else {
return ($dim === 'string') ? 'No size set (scalable)' : 0;
}
// (regular logic/from Image class)
return ($dim === 'string') ? "$size[0]x$size[1]" : $size[$dim];
}
/**
* Scale image proportionally to fit within the specified bounds
*
* @param int $width The width to size within
* @param int $height The height to size within
* @return AssetContainer
*/
public function Fit($width, $height)
{
if ($this->isSVG()) {
return $this;
}
// Forward to regular Image class
return parent::Fit($width, $height);
}
/**
* @param int $width
* @param int $height
* @return AssetContainer
*/
public function FitMax($width, $height)
{
if ($this->isSVG()) {
return $this;
}
// Forward to regular Image class
return parent::FitMax($width, $height);
}
/**
* Called from {@link ThumbnailGenerator::generateThumbnail()}
*
* @return AssetContainer
*/
public function existingOnly()
{
if ($this->isSVG()) {
return $this;
}
return parent::existingOnly();
}
/**
* @return bool
*/
public function isSVG()
{
return $this->getExtension() === 'svg';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment