Add abstract storage layer
This commit is contained in:
parent
8bc141a286
commit
62fd225cfb
|
|
@ -60,7 +60,7 @@ class File extends Base
|
|||
{
|
||||
$task = $this->getTask();
|
||||
|
||||
if (! $this->file->upload($task['project_id'], $task['id'], 'files')) {
|
||||
if (! $this->file->uploadFiles($task['project_id'], $task['id'], 'files')) {
|
||||
$this->session->flashError(t('Unable to upload the file.'));
|
||||
}
|
||||
|
||||
|
|
@ -76,14 +76,13 @@ class File extends Base
|
|||
{
|
||||
$task = $this->getTask();
|
||||
$file = $this->file->getById($this->request->getIntegerParam('file_id'));
|
||||
$filename = FILES_DIR.$file['path'];
|
||||
|
||||
if ($file['task_id'] == $task['id'] && file_exists($filename)) {
|
||||
$this->response->forceDownload($file['name']);
|
||||
$this->response->binary(file_get_contents($filename));
|
||||
if ($file['task_id'] != $task['id']) {
|
||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||
}
|
||||
|
||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||
$this->response->forceDownload($file['name']);
|
||||
$this->objectStorage->passthru($file['path']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -113,16 +112,13 @@ class File extends Base
|
|||
{
|
||||
$task = $this->getTask();
|
||||
$file = $this->file->getById($this->request->getIntegerParam('file_id'));
|
||||
$filename = FILES_DIR.$file['path'];
|
||||
|
||||
if ($file['task_id'] == $task['id'] && file_exists($filename)) {
|
||||
$metadata = getimagesize($filename);
|
||||
|
||||
if (isset($metadata['mime'])) {
|
||||
$this->response->contentType($metadata['mime']);
|
||||
readfile($filename);
|
||||
}
|
||||
if ($file['task_id'] != $task['id']) {
|
||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||
}
|
||||
|
||||
$this->response->contentType($this->file->getImageMimeType($file['name']));
|
||||
$this->objectStorage->passthru($file['path']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -134,17 +130,13 @@ class File extends Base
|
|||
{
|
||||
$task = $this->getTask();
|
||||
$file = $this->file->getById($this->request->getIntegerParam('file_id'));
|
||||
$filename = FILES_DIR.$file['path'];
|
||||
|
||||
if ($file['task_id'] == $task['id'] && file_exists($filename)) {
|
||||
|
||||
$this->response->contentType('image/jpeg');
|
||||
$this->file->generateThumbnail(
|
||||
$filename,
|
||||
$this->request->getIntegerParam('width'),
|
||||
$this->request->getIntegerParam('height')
|
||||
);
|
||||
if ($file['task_id'] != $task['id']) {
|
||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||
}
|
||||
|
||||
$this->response->contentType('image/jpeg');
|
||||
$this->objectStorage->passthru($this->file->getThumbnailPath($file['path']));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
|
||||
namespace Core\ObjectStorage;
|
||||
|
||||
/**
|
||||
* Local File Storage
|
||||
*
|
||||
* @package ObjectStorage
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class FileStorage implements ObjectStorageInterface
|
||||
{
|
||||
/**
|
||||
* Base path
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $path = '';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @param string $path
|
||||
*/
|
||||
public function __construct($path)
|
||||
{
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch object contents
|
||||
*
|
||||
* @access public
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
$filename = $this->path.DIRECTORY_SEPARATOR.$key;
|
||||
|
||||
if (! file_exists($filename)) {
|
||||
throw new ObjectStorageException('File not found: '.$filename);
|
||||
}
|
||||
|
||||
return file_get_contents($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save object
|
||||
*
|
||||
* @access public
|
||||
* @param string $key
|
||||
* @param string $blob
|
||||
* @return string
|
||||
*/
|
||||
public function put($key, &$blob)
|
||||
{
|
||||
$this->createFolder($key);
|
||||
|
||||
if (file_put_contents($this->path.DIRECTORY_SEPARATOR.$key, $blob) === false) {
|
||||
throw new ObjectStorageException('Unable to write the file: '.$this->path.DIRECTORY_SEPARATOR.$key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output directly object content
|
||||
*
|
||||
* @access public
|
||||
* @param string $key
|
||||
*/
|
||||
public function passthru($key)
|
||||
{
|
||||
$filename = $this->path.DIRECTORY_SEPARATOR.$key;
|
||||
|
||||
if (! file_exists($filename)) {
|
||||
throw new ObjectStorageException('File not found: '.$filename);
|
||||
}
|
||||
|
||||
return readfile($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move local file to object storage
|
||||
*
|
||||
* @access public
|
||||
* @param string $filename
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function moveFile($src_filename, $key)
|
||||
{
|
||||
$this->createFolder($key);
|
||||
$dst_filename = $this->path.DIRECTORY_SEPARATOR.$key;
|
||||
|
||||
if (! rename($src_filename, $dst_filename)) {
|
||||
throw new ObjectStorageException('Unable to move the file: '.$src_filename.' to '.$dst_filename);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move uploaded file to object storage
|
||||
*
|
||||
* @access public
|
||||
* @param string $filename
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function moveUploadedFile($filename, $key)
|
||||
{
|
||||
$this->createFolder($key);
|
||||
return move_uploaded_file($filename, $this->path.DIRECTORY_SEPARATOR.$key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove object
|
||||
*
|
||||
* @access public
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function remove($key)
|
||||
{
|
||||
$filename = $this->path.DIRECTORY_SEPARATOR.$key;
|
||||
|
||||
if (file_exists($filename)) {
|
||||
return unlink($filename);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create object folder
|
||||
*
|
||||
* @access private
|
||||
* @param string $key
|
||||
*/
|
||||
private function createFolder($key)
|
||||
{
|
||||
$folder = $this->path.DIRECTORY_SEPARATOR.dirname($key);
|
||||
|
||||
if (! is_dir($folder) && ! mkdir($folder, 0755, true)) {
|
||||
throw new ObjectStorageException('Unable to create folder: '.$folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace Core\ObjectStorage;
|
||||
|
||||
use Exception;
|
||||
|
||||
class ObjectStorageException extends Exception
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace Core\ObjectStorage;
|
||||
|
||||
/**
|
||||
* Object Storage Interface
|
||||
*
|
||||
* @package ObjectStorage
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
interface ObjectStorageInterface
|
||||
{
|
||||
/**
|
||||
* Fetch object contents
|
||||
*
|
||||
* @access public
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
public function get($key);
|
||||
|
||||
/**
|
||||
* Save object
|
||||
*
|
||||
* @access public
|
||||
* @param string $key
|
||||
* @param string $blob
|
||||
* @return string
|
||||
*/
|
||||
public function put($key, &$blob);
|
||||
|
||||
/**
|
||||
* Output directly object content
|
||||
*
|
||||
* @access public
|
||||
* @param string $key
|
||||
*/
|
||||
public function passthru($key);
|
||||
|
||||
/**
|
||||
* Move local file to object storage
|
||||
*
|
||||
* @access public
|
||||
* @param string $filename
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function moveFile($filename, $key);
|
||||
|
||||
/**
|
||||
* Move uploaded file to object storage
|
||||
*
|
||||
* @access public
|
||||
* @param string $filename
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function moveUploadedFile($filename, $key);
|
||||
|
||||
/**
|
||||
* Remove object
|
||||
*
|
||||
* @access public
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function remove($key);
|
||||
}
|
||||
|
|
@ -72,4 +72,82 @@ class Tool
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a jpeg thumbnail from an image
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @param string $src_file Source file image
|
||||
* @param string $dst_file Destination file image
|
||||
* @param integer $resize_width Desired image width
|
||||
* @param integer $resize_height Desired image height
|
||||
*/
|
||||
public static function generateThumbnail($src_file, $dst_file, $resize_width = 250, $resize_height = 100)
|
||||
{
|
||||
$metadata = getimagesize($src_file);
|
||||
$src_width = $metadata[0];
|
||||
$src_height = $metadata[1];
|
||||
$dst_y = 0;
|
||||
$dst_x = 0;
|
||||
|
||||
if (empty($metadata['mime'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($resize_width == 0 && $resize_height == 0) {
|
||||
$resize_width = 100;
|
||||
$resize_height = 100;
|
||||
}
|
||||
|
||||
if ($resize_width > 0 && $resize_height == 0) {
|
||||
$dst_width = $resize_width;
|
||||
$dst_height = floor($src_height * ($resize_width / $src_width));
|
||||
$dst_image = imagecreatetruecolor($dst_width, $dst_height);
|
||||
}
|
||||
elseif ($resize_width == 0 && $resize_height > 0) {
|
||||
$dst_width = floor($src_width * ($resize_height / $src_height));
|
||||
$dst_height = $resize_height;
|
||||
$dst_image = imagecreatetruecolor($dst_width, $dst_height);
|
||||
}
|
||||
else {
|
||||
|
||||
$src_ratio = $src_width / $src_height;
|
||||
$resize_ratio = $resize_width / $resize_height;
|
||||
|
||||
if ($src_ratio <= $resize_ratio) {
|
||||
$dst_width = $resize_width;
|
||||
$dst_height = floor($src_height * ($resize_width / $src_width));
|
||||
|
||||
$dst_y = ($dst_height - $resize_height) / 2 * (-1);
|
||||
}
|
||||
else {
|
||||
$dst_width = floor($src_width * ($resize_height / $src_height));
|
||||
$dst_height = $resize_height;
|
||||
|
||||
$dst_x = ($dst_width - $resize_width) / 2 * (-1);
|
||||
}
|
||||
|
||||
$dst_image = imagecreatetruecolor($resize_width, $resize_height);
|
||||
}
|
||||
|
||||
switch ($metadata['mime']) {
|
||||
case 'image/jpeg':
|
||||
case 'image/jpg':
|
||||
$src_image = imagecreatefromjpeg($src_file);
|
||||
break;
|
||||
case 'image/png':
|
||||
$src_image = imagecreatefrompng($src_file);
|
||||
break;
|
||||
case 'image/gif':
|
||||
$src_image = imagecreatefromgif($src_file);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, 0, 0, $dst_width, $dst_height, $src_width, $src_height);
|
||||
imagejpeg($dst_image, $dst_file);
|
||||
imagedestroy($dst_image);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
namespace Model;
|
||||
|
||||
use Event\FileEvent;
|
||||
use Core\Tool;
|
||||
use Core\ObjectStorage\ObjectStorageException;
|
||||
|
||||
/**
|
||||
* File model
|
||||
|
|
@ -47,14 +49,17 @@ class File extends Base
|
|||
*/
|
||||
public function remove($file_id)
|
||||
{
|
||||
$file = $this->getbyId($file_id);
|
||||
try {
|
||||
|
||||
if (! empty($file)) {
|
||||
@unlink(FILES_DIR.$file['path']);
|
||||
return $this->db->table(self::TABLE)->eq('id', $file_id)->remove();
|
||||
$file = $this->getbyId($file_id);
|
||||
$this->objectStorage->remove($file['path']);
|
||||
|
||||
return $this->db->table(self::TABLE)->eq('id', $file['id'])->remove();
|
||||
}
|
||||
catch (ObjectStorageException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -66,11 +71,11 @@ class File extends Base
|
|||
*/
|
||||
public function removeAll($task_id)
|
||||
{
|
||||
$files = $this->getAll($task_id);
|
||||
$file_ids = $this->db->table(self::TABLE)->eq('task_id', $task_id)->asc('id')->findAllByColumn('id');
|
||||
$results = array();
|
||||
|
||||
foreach ($files as $file) {
|
||||
$results[] = $this->remove($file['id']);
|
||||
foreach ($file_ids as $file_id) {
|
||||
$results[] = $this->remove($file_id);
|
||||
}
|
||||
|
||||
return ! in_array(false, $results, true);
|
||||
|
|
@ -195,6 +200,30 @@ class File extends Base
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the image mimetype based on the file extension
|
||||
*
|
||||
* @access public
|
||||
* @param $filename
|
||||
* @return string
|
||||
*/
|
||||
public function getImageMimeType($filename)
|
||||
{
|
||||
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||
|
||||
switch ($extension) {
|
||||
case 'jpeg':
|
||||
case 'jpg':
|
||||
return 'image/jpeg';
|
||||
case 'png':
|
||||
return 'image/png';
|
||||
case 'gif':
|
||||
return 'image/gif';
|
||||
default:
|
||||
return 'image/jpeg';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the path for a new filename
|
||||
*
|
||||
|
|
@ -209,6 +238,18 @@ class File extends Base
|
|||
return $project_id.DIRECTORY_SEPARATOR.$task_id.DIRECTORY_SEPARATOR.hash('sha1', $filename.time());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the path for a thumbnails
|
||||
*
|
||||
* @access public
|
||||
* @param string $key Storage key
|
||||
* @return string
|
||||
*/
|
||||
public function getThumbnailPath($key)
|
||||
{
|
||||
return 'thumbnails'.DIRECTORY_SEPARATOR.$key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle file upload
|
||||
*
|
||||
|
|
@ -218,11 +259,13 @@ class File extends Base
|
|||
* @param string $form_name File form name
|
||||
* @return bool
|
||||
*/
|
||||
public function upload($project_id, $task_id, $form_name)
|
||||
public function uploadFiles($project_id, $task_id, $form_name)
|
||||
{
|
||||
$results = array();
|
||||
try {
|
||||
|
||||
if (! empty($_FILES[$form_name])) {
|
||||
if (empty($_FILES[$form_name])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($_FILES[$form_name]['error'] as $key => $error) {
|
||||
|
||||
|
|
@ -232,22 +275,27 @@ class File extends Base
|
|||
$uploaded_filename = $_FILES[$form_name]['tmp_name'][$key];
|
||||
$destination_filename = $this->generatePath($project_id, $task_id, $original_filename);
|
||||
|
||||
@mkdir(FILES_DIR.dirname($destination_filename), 0755, true);
|
||||
|
||||
if (@move_uploaded_file($uploaded_filename, FILES_DIR.$destination_filename)) {
|
||||
|
||||
$results[] = $this->create(
|
||||
$task_id,
|
||||
$original_filename,
|
||||
$destination_filename,
|
||||
$_FILES[$form_name]['size'][$key]
|
||||
);
|
||||
if ($this->isImage($original_filename)) {
|
||||
$this->generateThumbnailFromFile($uploaded_filename, $destination_filename);
|
||||
}
|
||||
|
||||
$this->objectStorage->moveUploadedFile($uploaded_filename, $destination_filename);
|
||||
|
||||
$this->create(
|
||||
$task_id,
|
||||
$original_filename,
|
||||
$destination_filename,
|
||||
$_FILES[$form_name]['size'][$key]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ! in_array(false, $results, true);
|
||||
return true;
|
||||
}
|
||||
catch (ObjectStorageException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -261,129 +309,77 @@ class File extends Base
|
|||
*/
|
||||
public function uploadScreenshot($project_id, $task_id, $blob)
|
||||
{
|
||||
$data = base64_decode($blob);
|
||||
|
||||
if (empty($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$original_filename = e('Screenshot taken %s', dt('%B %e, %Y at %k:%M %p', time())).'.png';
|
||||
$destination_filename = $this->generatePath($project_id, $task_id, $original_filename);
|
||||
|
||||
@mkdir(FILES_DIR.dirname($destination_filename), 0755, true);
|
||||
@file_put_contents(FILES_DIR.$destination_filename, $data);
|
||||
|
||||
return $this->create(
|
||||
$task_id,
|
||||
$original_filename,
|
||||
$destination_filename,
|
||||
strlen($data)
|
||||
);
|
||||
return $this->uploadContent($project_id, $task_id, $original_filename, $blob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle file upload (base64 encoded content)
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @param integer $task_id Task id
|
||||
* @param string $filename Filename
|
||||
* @param string $blob Base64 encoded image
|
||||
* @param integer $project_id Project id
|
||||
* @param integer $task_id Task id
|
||||
* @param string $original_filename Filename
|
||||
* @param string $blob Base64 encoded file
|
||||
* @return bool|integer
|
||||
*/
|
||||
public function uploadContent($project_id, $task_id, $filename, $blob)
|
||||
public function uploadContent($project_id, $task_id, $original_filename, $blob)
|
||||
{
|
||||
$data = base64_decode($blob);
|
||||
try {
|
||||
|
||||
if (empty($data)) {
|
||||
$data = base64_decode($blob);
|
||||
|
||||
if (empty($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$destination_filename = $this->generatePath($project_id, $task_id, $original_filename);
|
||||
$this->objectStorage->put($destination_filename, $data);
|
||||
|
||||
if ($this->isImage($original_filename)) {
|
||||
$this->generateThumbnailFromData($destination_filename, $data);
|
||||
}
|
||||
|
||||
return $this->create(
|
||||
$task_id,
|
||||
$original_filename,
|
||||
$destination_filename,
|
||||
strlen($data)
|
||||
);
|
||||
}
|
||||
catch (ObjectStorageException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
$destination_filename = $this->generatePath($project_id, $task_id, $filename);
|
||||
|
||||
@mkdir(FILES_DIR.dirname($destination_filename), 0755, true);
|
||||
@file_put_contents(FILES_DIR.$destination_filename, $data);
|
||||
|
||||
return $this->create(
|
||||
$task_id,
|
||||
$filename,
|
||||
$destination_filename,
|
||||
strlen($data)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a jpeg thumbnail from an image (output directly the image)
|
||||
* Generate thumbnail from a blob
|
||||
*
|
||||
* @access public
|
||||
* @param string $filename Source image
|
||||
* @param integer $resize_width Desired image width
|
||||
* @param integer $resize_height Desired image height
|
||||
* @param string $destination_filename
|
||||
* @param string $data
|
||||
*/
|
||||
public function generateThumbnail($filename, $resize_width, $resize_height)
|
||||
public function generateThumbnailFromData($destination_filename, &$data)
|
||||
{
|
||||
$metadata = getimagesize($filename);
|
||||
$src_width = $metadata[0];
|
||||
$src_height = $metadata[1];
|
||||
$dst_y = 0;
|
||||
$dst_x = 0;
|
||||
$temp_filename = tempnam(sys_get_temp_dir(), 'datafile');
|
||||
|
||||
if (empty($metadata['mime'])) {
|
||||
return;
|
||||
}
|
||||
file_put_contents($temp_filename, $data);
|
||||
$this->generateThumbnailFromFile($temp_filename, $destination_filename);
|
||||
unlink($temp_filename);
|
||||
}
|
||||
|
||||
if ($resize_width == 0 && $resize_height == 0) {
|
||||
$resize_width = 100;
|
||||
$resize_height = 100;
|
||||
}
|
||||
|
||||
if ($resize_width > 0 && $resize_height == 0) {
|
||||
$dst_width = $resize_width;
|
||||
$dst_height = floor($src_height * ($resize_width / $src_width));
|
||||
$dst_image = imagecreatetruecolor($dst_width, $dst_height);
|
||||
}
|
||||
elseif ($resize_width == 0 && $resize_height > 0) {
|
||||
$dst_width = floor($src_width * ($resize_height / $src_height));
|
||||
$dst_height = $resize_height;
|
||||
$dst_image = imagecreatetruecolor($dst_width, $dst_height);
|
||||
}
|
||||
else {
|
||||
|
||||
$src_ratio = $src_width / $src_height;
|
||||
$resize_ratio = $resize_width / $resize_height;
|
||||
|
||||
if ($src_ratio <= $resize_ratio) {
|
||||
$dst_width = $resize_width;
|
||||
$dst_height = floor($src_height * ($resize_width / $src_width));
|
||||
|
||||
$dst_y = ($dst_height - $resize_height) / 2 * (-1);
|
||||
}
|
||||
else {
|
||||
$dst_width = floor($src_width * ($resize_height / $src_height));
|
||||
$dst_height = $resize_height;
|
||||
|
||||
$dst_x = ($dst_width - $resize_width) / 2 * (-1);
|
||||
}
|
||||
|
||||
$dst_image = imagecreatetruecolor($resize_width, $resize_height);
|
||||
}
|
||||
|
||||
switch ($metadata['mime']) {
|
||||
case 'image/jpeg':
|
||||
case 'image/jpg':
|
||||
$src_image = imagecreatefromjpeg($filename);
|
||||
break;
|
||||
case 'image/png':
|
||||
$src_image = imagecreatefrompng($filename);
|
||||
break;
|
||||
case 'image/gif':
|
||||
$src_image = imagecreatefromgif($filename);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, 0, 0, $dst_width, $dst_height, $src_width, $src_height);
|
||||
imagejpeg($dst_image);
|
||||
/**
|
||||
* Generate thumbnail from a blob
|
||||
*
|
||||
* @access public
|
||||
* @param string $uploaded_filename
|
||||
* @param string $destination_filename
|
||||
*/
|
||||
public function generateThumbnailFromFile($uploaded_filename, $destination_filename)
|
||||
{
|
||||
$thumbnail_filename = tempnam(sys_get_temp_dir(), 'thumbnail');
|
||||
Tool::generateThumbnail($uploaded_filename, $thumbnail_filename);
|
||||
$this->objectStorage->moveFile($thumbnail_filename, $this->getThumbnailPath($destination_filename));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace ServiceProvider;
|
||||
|
||||
use Core\ObjectStorage\FileStorage;
|
||||
use Core\Paginator;
|
||||
use Core\OAuth2;
|
||||
use Core\Tool;
|
||||
|
|
@ -106,5 +107,9 @@ class ClassProvider implements ServiceProviderInterface
|
|||
$container['htmlConverter'] = function($c) {
|
||||
return new HtmlConverter(array('strip_tags' => true));
|
||||
};
|
||||
|
||||
$container['objectStorage'] = function($c) {
|
||||
return new FileStorage(FILES_DIR);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<li>
|
||||
<?php if (function_exists('imagecreatetruecolor')): ?>
|
||||
<div class="img_container">
|
||||
<img src="<?= $this->url->href('file', 'thumbnail', array('width' => 250, 'height' => 100, 'file_id' => $file['id'], 'project_id' => $task['project_id'], 'task_id' => $file['task_id'])) ?>" alt="<?= $this->e($file['name']) ?>"/>
|
||||
<img src="<?= $this->url->href('file', 'thumbnail', array('file_id' => $file['id'], 'project_id' => $task['project_id'], 'task_id' => $file['task_id'])) ?>" alt="<?= $this->e($file['name']) ?>"/>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,17 @@ use Model\Project;
|
|||
|
||||
class FileTest extends Base
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->container['objectStorage'] = $this
|
||||
->getMockBuilder('\Core\ObjectStorage\FileStorage')
|
||||
->setConstructorArgs(array($this->container))
|
||||
->setMethods(array('put', 'moveFile', 'remove'))
|
||||
->getMock();
|
||||
}
|
||||
|
||||
public function testCreation()
|
||||
{
|
||||
$p = new Project($this->container);
|
||||
|
|
@ -85,13 +96,32 @@ class FileTest extends Base
|
|||
public function testUploadScreenshot()
|
||||
{
|
||||
$p = new Project($this->container);
|
||||
$f = new File($this->container);
|
||||
$tc = new TaskCreation($this->container);
|
||||
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
$this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'test')));
|
||||
|
||||
$this->assertEquals(1, $f->uploadScreenshot(1, 1, base64_encode('image data')));
|
||||
$data = base64_encode('image data');
|
||||
|
||||
$f = $this
|
||||
->getMockBuilder('\Model\File')
|
||||
->setConstructorArgs(array($this->container))
|
||||
->setMethods(array('generateThumbnailFromData'))
|
||||
->getMock();
|
||||
|
||||
$this->container['objectStorage']
|
||||
->expects($this->once())
|
||||
->method('put')
|
||||
->with(
|
||||
$this->stringContains('1/1/'),
|
||||
$this->equalTo(base64_decode($data))
|
||||
)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$f->expects($this->once())
|
||||
->method('generateThumbnailFromData');
|
||||
|
||||
$this->assertEquals(1, $f->uploadScreenshot(1, 1, $data));
|
||||
|
||||
$file = $f->getById(1);
|
||||
$this->assertNotEmpty($file);
|
||||
|
|
@ -113,7 +143,18 @@ class FileTest extends Base
|
|||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
$this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'test')));
|
||||
|
||||
$this->assertEquals(1, $f->uploadContent(1, 1, 'my file.pdf', base64_encode('file data')));
|
||||
$data = base64_encode('file data');
|
||||
|
||||
$this->container['objectStorage']
|
||||
->expects($this->once())
|
||||
->method('put')
|
||||
->with(
|
||||
$this->stringContains('1/1/'),
|
||||
$this->equalTo(base64_decode($data))
|
||||
)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$this->assertEquals(1, $f->uploadContent(1, 1, 'my file.pdf', $data));
|
||||
|
||||
$file = $f->getById(1);
|
||||
$this->assertNotEmpty($file);
|
||||
|
|
@ -170,9 +211,33 @@ class FileTest extends Base
|
|||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
$this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'test')));
|
||||
|
||||
$this->assertEquals(1, $f->create(1, 'B.pdf', '/tmp/foo', 10));
|
||||
$this->assertEquals(2, $f->create(1, 'A.png', '/tmp/foo', 10));
|
||||
$this->assertEquals(3, $f->create(1, 'D.doc', '/tmp/foo', 10));
|
||||
$this->assertEquals(1, $f->create(1, 'B.pdf', '/tmp/foo1', 10));
|
||||
$this->assertEquals(2, $f->create(1, 'A.png', '/tmp/foo2', 10));
|
||||
$this->assertEquals(3, $f->create(1, 'D.doc', '/tmp/foo3', 10));
|
||||
|
||||
$this->container['objectStorage']
|
||||
->expects($this->at(0))
|
||||
->method('remove')
|
||||
->with(
|
||||
$this->equalTo('/tmp/foo2')
|
||||
)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$this->container['objectStorage']
|
||||
->expects($this->at(1))
|
||||
->method('remove')
|
||||
->with(
|
||||
$this->equalTo('/tmp/foo1')
|
||||
)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$this->container['objectStorage']
|
||||
->expects($this->at(2))
|
||||
->method('remove')
|
||||
->with(
|
||||
$this->equalTo('/tmp/foo3')
|
||||
)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$this->assertTrue($f->remove(2));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue