Skip to content

Commit

Permalink
Implements crop image ability.
Browse files Browse the repository at this point in the history
  • Loading branch information
nilov committed Jan 21, 2019
1 parent 03d6881 commit aa965ed
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 3 deletions.
23 changes: 20 additions & 3 deletions Controller/UploadController.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,19 @@ public function editAction(Request $request)
$requestId = $request->get('request_id');
$name = $request->get('name');
$description = $request->get('description');
$cropData = $request->get('crop_data');
$softEdit = $request->get('soft_edit', false);

$modelManager = $this->get('glavweb_uploader.uploader_manager')->getModelManager();
if ($cropData) {
$cropData = json_decode($cropData, true);
}

$uploaderManager = $this->get('glavweb_uploader.uploader_manager');
$modelManager = $uploaderManager->getModelManager();
$media = $modelManager->findOneBySecuredId($id);

if ($media && $requestId && ($name || $description)) {
if ($media->getIsOrphan()) {
if ($media->getIsOrphan() || !$softEdit) {
if ($media->getRequestId() == $requestId) {
$success = $modelManager->editMedia($media, $name, $description);
}
Expand All @@ -211,7 +218,17 @@ public function editAction(Request $request)
}
}

return new JsonResponse(['success' => $success], $success ? Response::HTTP_OK : Response::HTTP_BAD_REQUEST);
if ($media) {
if ($cropData) {
$uploaderManager->cropImage($media, $cropData);
}
$mediaStructure = $this->get('glavweb_uploader.util.media_structure')->getMediaStructure($media);
}

return new JsonResponse([
'success' => $success,
'media' => $mediaStructure
], $success ? Response::HTTP_OK : Response::HTTP_BAD_REQUEST);
}

/**
Expand Down
21 changes: 21 additions & 0 deletions Exception/CropImageException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of the Glavweb UploaderBundle package.
*
* (c) Andrey Nilov <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Glavweb\UploaderBundle\Exception;

/**
* Class CropImageException
*
* @package Glavweb\UploaderBundle
* @author Andrey Nilov <[email protected]>
*/
class CropImageException extends Exception
{}
32 changes: 32 additions & 0 deletions Manager/UploaderManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
namespace Glavweb\UploaderBundle\Manager;

use Glavweb\UploaderBundle\Driver\AnnotationDriver;
use Glavweb\UploaderBundle\Entity\Media;
use Glavweb\UploaderBundle\Exception\CropImageException;
use Glavweb\UploaderBundle\Exception\ProviderNotFoundException;
use Glavweb\UploaderBundle\File\FileInterface;
use Glavweb\UploaderBundle\Model\MediaInterface;
Expand Down Expand Up @@ -422,4 +424,34 @@ protected function checkHackingName($name)
throw new \RuntimeException('Extension "' . $extension . '" not supported.');
}
}

/**
* @param Media $media
* @param array $cropData
* @throws CropImageException
*/
public function cropImage(Media $media, array $cropData): void
{
$storage = $this->getStorage();
$context = $media->getContext();
$contentPath = $media->getContentPath();
$directory = $this->getContextConfig($context, 'upload_directory');

if ($media->getProviderName() !== 'glavweb_uploader.provider.image') {
throw new CropImageException('The provider name must be "glavweb_uploader.provider.image".');
}

if (!$storage->isFile($directory, $contentPath)) {
throw new CropImageException('File is not found.');
}

$file = $storage->getFile($directory, $contentPath);

// update file name
$newFilename = $this->getStorage()->cropImage($file, $cropData);
$media->setContentPath(basename($newFilename));
$media->setThumbnailPath(basename($newFilename));

$this->getModelManager()->updateMedia($media);
}
}
44 changes: 44 additions & 0 deletions Storage/FilesystemStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@

namespace Glavweb\UploaderBundle\Storage;

use Glavweb\UploaderBundle\Exception\CropImageException;
use Glavweb\UploaderBundle\File\FileInterface;
use Glavweb\UploaderBundle\File\FilesystemFile;
use Glavweb\UploaderBundle\Util\CropImage;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Finder\Finder;
Expand Down Expand Up @@ -240,4 +242,46 @@ public function removeFile(FileInterface $file)
$filesystem = new Filesystem();
$filesystem->remove($file);
}

/**
* @param FilesystemFile $file
* @param array $cropData
* @return string
* @throws CropImageException
*/
public function cropImage(FilesystemFile $file, array $cropData): string
{
$pathname = $file->getPathname();
$cropResult = CropImage::crop($pathname, $pathname, $cropData);

$updatedPathname = $pathname;
if ($cropResult) {
$updatedPathname = $this->saveFileWithNewVersion($file);
}

return $updatedPathname;
}

/**
* @param FilesystemFile $file
* @return string
*/
private function saveFileWithNewVersion(FilesystemFile $file): string
{
$pathParts = pathinfo($file->getPathname());
$directory = $pathParts['dirname'];

$filenameFarts = explode('_', $pathParts['filename']);
if (count($filenameFarts) > 1) {
$filenameFarts[1] += 1;

} else {
$filenameFarts[1] = '1';
}
$fileName = implode('_', $filenameFarts) . '.' . $pathParts['extension'];

$newFile = $file->move($directory, $fileName);

return $newFile->getPathname();
}
}
10 changes: 10 additions & 0 deletions Storage/StorageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@

namespace Glavweb\UploaderBundle\Storage;

use Glavweb\UploaderBundle\Exception\CropImageException;
use Glavweb\UploaderBundle\File\FileInterface;
use Glavweb\UploaderBundle\File\FilesystemFile;
use Symfony\Component\HttpFoundation\File\File;

/**
* Interface StorageInterface
Expand Down Expand Up @@ -76,4 +78,12 @@ public function isFile($directory, $name);
* @param FileInterface $file
*/
public function removeFile(FileInterface $file);

/**
* @param FilesystemFile $file
* @param array $cropData
* @return string
* @throws CropImageException
*/
public function cropImage(FilesystemFile $file, array $cropData): string;
}
132 changes: 132 additions & 0 deletions Util/CropImage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?php

/*
* This file is part of the Glavweb UploaderBundle package.
*
* (c) Andrey Nilov <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Glavweb\UploaderBundle\Util;

use Glavweb\UploaderBundle\Exception\CropImageException;

/**
* Class CropImage
*
* @package Glavweb\UploaderBundle
* @author Andrey Nilov <[email protected]>
*/
class CropImage
{
/**
* @param string $sourcePath
* @param string $targetPath
* @param array $cropData
* @throws CropImageException
*/
public static function crop(string $sourcePath, string $targetPath, array $cropData): bool
{
// crop
$sourceImage = self::getImage($sourcePath);

$croppedImage = imagecrop($sourceImage, [
'x' => $cropData['x'],
'y' => $cropData['y'],
'width' => $cropData['width'],
'height' => $cropData['height']
]);

if (!$croppedImage) {
throw new CropImageException('Failed to crop the image file.');
}

$size = getimagesize($sourcePath);

$notChanged =
$size !== false &&
$cropData['x'] == 0 &&
$cropData['y'] == 0 &&
$cropData['width'] == $size[0] &&
$cropData['height'] == $size[1]
;

if ($notChanged) {
return false;
}

self::saveImage($croppedImage, $targetPath);

imagedestroy($sourceImage);
imagedestroy($croppedImage);

return true;
}

/**
* @param string $sourcePath
* @return resource
* @throws CropImageException
*/
private static function getImage(string $sourcePath)
{
$imageType = exif_imagetype($sourcePath);

switch ($imageType) {
case IMAGETYPE_GIF:
$sourceImage = imagecreatefromgif($sourcePath);
break;

case IMAGETYPE_JPEG:
$sourceImage = imagecreatefromjpeg($sourcePath);
break;

case IMAGETYPE_PNG:
$sourceImage = imagecreatefrompng($sourcePath);
break;
}

if (!$sourceImage) {
throw new CropImageException('Failed to read the image file.');
}

return $sourceImage;
}

/**
* @param resource $targetImage
* @param string $targetPath
* @throws CropImageException
*/
private static function saveImage($targetImage, string $targetPath): void
{
$imageType = exif_imagetype($targetPath);

$error = false;
switch ($imageType) {
case IMAGETYPE_JPEG:
if (!imagejpeg($targetImage, $targetPath, 99)) {
$error = true;
}
break;

case IMAGETYPE_PNG:
if (!imagepng($targetImage, $targetPath)) {
$error = true;
}
break;

case IMAGETYPE_GIF:
if (!imagegif($targetImage, $targetPath)) {
$error = true;
}
break;
}

if ($error) {
throw new CropImageException('Failed to save the cropped image file.');
}
}
}

0 comments on commit aa965ed

Please sign in to comment.