Skip to content

Instantly share code, notes, and snippets.

@Thijzer
Created November 5, 2015 15:20
Show Gist options
  • Save Thijzer/6fb74b6539e2a2b2edb9 to your computer and use it in GitHub Desktop.
Save Thijzer/6fb74b6539e2a2b2edb9 to your computer and use it in GitHub Desktop.
ForkCMS Image library
<?php
/*
* This file is part of Fork CMS.
*
* For the full copyright and license information, please view the license
* file that was distributed with this source code.
*/
namespace Common;
use Common\Uri;
use Backend\Core\Engine\Exception;
use Backend\Core\Engine\Model as BackendModel;
use Backend\Core\Engine\FormImage as BackendFormImage;
use Backend\Core\Engine\Language as BL;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpFoundation\File\File;
/**
* This is an Image Store Class to simplify Image handling
*
* @author <thijs@wijs.be>
*/
class Image
{
/**
* @var array
*/
private $sizes;
/**
* @var boolean
*/
private $isGeneratedFilename = false;
private $isValidated = false;
/**
* @var string
*/
private $imagePath;
private $sourcePath;
private $currentFilename;
private $extension = null;
/**
* @var Filesystem
*/
private $fs;
/**
* @var Finder
*/
private $finder;
/**
* @var BackendFormImage
*/
private $image;
/**
* Constructor
*
* @param array $settings required
* @param string $currentFilename
*/
public function __construct(array $settings, $currentFilename = null)
{
// create folders if needed
$this->fs = new Filesystem();
$this->finder = new Finder();
// setup Settings
$this->settings['required'] = true;
$this->settings['check_dimensions'] = false;
$this->settings['store_path'] = '';
$this->settings['sources'] = array('source');
$this->settings['max_width'] = 0;
$this->settings['max_height'] = 0;
$this->settings['mimetypes'] = array(
'jpg' => 'image/jpg',
'jpeg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
);
$this->settings['filesize'] = null;
$this->settings = array_merge($this->settings, $settings);
$this->settings['extensions'] = array_keys($this->settings['mimetypes']);
// size and dimensions
if (!is_bool($this->settings['required']) && empty($settings['store_path'])) {
new Exception('minimail settings "required" & "store_path" are required');
}
$this->imagePath = FRONTEND_FILES_PATH;
$this->imagePath .= '/'.strtolower($this->settings['store_path']);
// setup your sources
$this->sourcePath = $this->imagePath . '/source/';
$this->sizes = $this->getDimensions($this->imagePath);
if (count($this->sizes) === 0) {
$this->sizes = array($this->sourcePath);
}
// set the correct extension and current Filename
$this->currentFilename = $currentFilename;
$this->extension = $this->setExtension($currentFilename);
}
/**
* Validate your Image by Reference
*
* @param BackendFormImage
*/
public function validate(&$image)
{
if (empty($this->currentFilename) && $this->settings['required']) {
$image->isFilled(BL::err('FieldIsRequired'));
}
// validate the image
if ($image->isFilled()) {
// image extension
$image->isAllowedExtension(
$this->extensions,
BL::err('JPGGIFAndPNGOnly')
);
// Mime Validation
$image->isAllowedMimeType(
$this->getMimetypes(),
BL::err('JPGGIFAndPNGOnly')
);
// Minimum Dimensions
$this->hasMinimumDimensions(
$this->settings['width'],
$this->settings['height']
);
$this->extension = $image->getExtension();
}
// set some properties
if (!$image->getErrors()) {
$this->isValidated = true;
$this->image = $image;
}
}
/**
* Store your image
*
* @param string new filename
*
* @return string the set filename
*/
public function save($newFilename = '')
{
// sane validation checker
if ($this->isValidated === false) {
return '';
}
// filename
$newFilename = $this->getCorrectFilename(
$newFilename,
$this->image->isFilled()
);
// default file action
if ($this->image->isFilled()) {
// init dirs
$this->initDirectories();
// remove the old
$this->deletePrevious();
// upload the image & generate thumbnails
$this->image->generateThumbnails($this->imagePath, $newFilename);
return $newFilename;
}
// no image but we can still rename
$this->rename($newFilename);
// only change the name if there is a difference
return $newFilename;
}
/**
* Delete Previous file
*/
public function deletePrevious()
{
if (!empty($this->currentFilename)) {
$this->fs->remove($this->sourcePath.$this->currentFilename);
$this->deleteThumbnails($this->currentFilename);
}
}
/** Is the File Validated */
public function isValidated()
{
return $this->isValidated;
}
/**
* manages the filename
*
* @param string $filename
* @param bool $isFilled Required
* @return string filename
*/
private function getCorrectFilename($filename, $isFilled = false)
{
if ($isFilled && $this->currentFilename.$filename === '') {
$filename = $this->generateNewFilename();
return $filename;
}
$filename = (empty($filename)) ?
$this->currentFilename :
Uri::getUrl($filename).'.'.$this->extension;
return $filename;
}
/**
* Delete Thumbnails
*
* @param string $thumbnail
*/
private function deleteThumbnails($thumbnail = '')
{
// if there is no image provided we can't do anything
if ($thumbnail === '') {
return;
}
foreach ($this->sources as $directory) {
$fileName = $directory.'/'.$thumbnail;
if (is_file($fileName)) {
$this->fs->remove($fileName);
}
}
}
/**
* Set Extension
*
* @param string path
* @return string current filename
*/
private function setExtension($currentFilename)
{
if (!empty($currentFilename)) {
$path = pathinfo($currentFilename);
if (isset($path['extension'])) {
return $path['extension'];
}
}
}
/**
* Get Directories list
*
* @param string path
* @return array source directories
*/
private function getDimensions($path)
{
foreach ($this->finder->directories()->in($path) as $directory) {
$dimensions = null;
$path = $directory->getRealPath();
$directories[] = $path;
$dimensions = explode('x', strtolower($path));
// store the heighest available resolution
if ($this->settings['check_dimensions'] === true &&
$dimensions !== null &&
$this->settings['max_width'] < $dimensions[0] &&
$this->settings['max_height'] < $dimensions[1]
) {
$this->settings['max_width'] = $dimensions[0];
$this->settings['max_height'] = $dimensions[1];
}
}
return $directories;
}
/**
* Get Mimetypes
*
* @return array mimetypes
*/
private function getMimetypes()
{
return array_values($this->settings['mimetypes']);
}
/** Init the Image Directories */
private function initDirectories()
{
foreach ($this->sizes as $source) {
if (!$this->fs->exists($source)) {
$this->fs->mkdir($source);
if (!$this->fs->exists($source.'/.gitignore')) {
$this->fs->dumpfile($source.'/.gitignore', "*\n!.gitignore");
}
}
}
}
/**
* Generate New Filename
*
* @return string filename
*/
private function generateNewFilename()
{
$this->isGeneratedFilename = true;
return uniqid().'.'.$this->extension;
}
/**
* Rename
*
* @param string new
*/
private function rename($new)
{
$old = $this->currentFilename;
if (!empty($old) && $new !== $old) {
// loop over folders
foreach ($this->sizes as $source) {
// move the old file to the new name
$this->fs->rename($source.'/'.$old, $source.'/'.$new);
}
}
}
/**
* Filesize Checker
*
* @param $largestSize string
* @param $size string
*/
public function isFilesize($filesize = null, $size = 'kb')
{
if ($filesize !== null && is_numeric($filesize)) {
$this->image->isFilesize($filesize, $size, null, BL::getError('IncorrectFilesize'));
}
}
/**
* Dimensions Checker
*
* @param $width string
* @param $height string
*/
private function hasMinimumDimensions()
{
if ($this->settings['check_dimensions'] === true && $this->image->getTempFileName()) {
$this->image->hasMinimumDimensions(
$this->settings['max_width'],
$this->settings['max_height'],
BL::getError('FileDimensionsToLow')
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment