WIP : upload documents : add action, ctrl, event

This commit is contained in:
gmorel
2013-09-24 10:54:52 +02:00
parent 695b2b4d94
commit 084f66589a
24 changed files with 1507 additions and 284 deletions

View File

@@ -25,8 +25,13 @@ namespace Thelia\Action;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\File\File;
use Thelia\Core\Event\DocumentCreateOrUpdateEvent;
use Thelia\Core\Event\DocumentDeleteEvent;
use Thelia\Core\Event\DocumentEvent;
use Thelia\Exception\ImageException;
use Thelia\Model\ConfigQuery;
use Thelia\Tools\FileManager;
use Thelia\Tools\URL;
use Imagine\Document\ImagineInterface;
@@ -129,11 +134,139 @@ class Document extends BaseCachedFile implements EventSubscriberInterface
$event->setDocumentUrl(URL::getInstance()->absoluteUrl($document_url, null, URL::PATH_TO_FILE));
}
/**
* Take care of saving document in the database and file storage
*
* @param DocumentCreateOrUpdateEvent $event Document event
*
* @throws \Thelia\Exception\ImageException
* @todo refactor make all documents using propel inheritance and factorise image behaviour into one single clean action
*/
public function saveDocument(DocumentCreateOrUpdateEvent $event)
{
$this->adminLogAppend(
$this->container->get('thelia.translator')->trans(
'Saving documents for %parentName% parent id %parentId% (%parentType%)',
array(
'%parentName%' => $event->getParentName(),
'%parentId%' => $event->getParentId(),
'%parentType%' => $event->getDocumentType()
),
'document'
)
);
$fileManager = new FileManager($this->container);
$model = $event->getModelDocument();
$nbModifiedLines = $model->save();
$event->setModelDocument($model);
if (!$nbModifiedLines) {
throw new ImageException(
sprintf(
'Document "%s" with parent id %s (%s) failed to be saved',
$event->getParentName(),
$event->getParentId(),
$event->getDocumentType()
)
);
}
$newUploadedFile = $fileManager->copyUploadedFile($event->getParentId(), $event->getDocumentType(), $event->getModelDocument(), $event->getUploadedFile());
$event->setUploadedFile($newUploadedFile);
}
/**
* Take care of updating document in the database and file storage
*
* @param DocumentCreateOrUpdateEvent $event Document event
*
* @throws \Thelia\Exception\ImageException
* @todo refactor make all documents using propel inheritance and factorise image behaviour into one single clean action
*/
public function updateDocument(DocumentCreateOrUpdateEvent $event)
{
$this->adminLogAppend(
$this->container->get('thelia.translator')->trans(
'Updating documents for %parentName% parent id %parentId% (%parentType%)',
array(
'%parentName%' => $event->getParentName(),
'%parentId%' => $event->getParentId(),
'%parentType%' => $event->getDocumentType()
),
'image'
)
);
$fileManager = new FileManager($this->container);
// Copy and save file
if ($event->getUploadedFile()) {
// Remove old picture file from file storage
$url = $fileManager->getUploadDir($event->getDocumentType(), FileManager::FILE_TYPE_DOCUMENTS) . '/' . $event->getOldModelDocument()->getFile();
unlink(str_replace('..', '', $url));
$newUploadedFile = $fileManager->copyUploadedFile(
$event->getModelDocument()->getParentId(),
$event->getDocumentType(),
$event->getModelDocument(), $event->getUploadedFile());
$event->setUploadedFile($newUploadedFile);
}
// Update document modifications
$event->getModelDocument()->save();
$event->setModelDocument($event->getModelDocument());
}
/**
* Take care of deleting document in the database and file storage
*
* @param DocumentDeleteEvent $event Image event
*
* @throws \Exception
* @todo refactor make all documents using propel inheritance and factorise image behaviour into one single clean action
*/
public function deleteDocument(DocumentDeleteEvent $event)
{
$fileManager = new FileManager($this->container);
try {
$fileManager->deleteFile($event->getDocumentToDelete(), $event->getDocumentType(), FileManager::FILE_TYPE_DOCUMENTS);
$this->adminLogAppend(
$this->container->get('thelia.translator')->trans(
'Deleting document for %id% with parent id %parentId%',
array(
'%id%' => $event->getDocumentToDelete()->getId(),
'%parentId%' => $event->getDocumentToDelete()->getParentId(),
),
'document'
)
);
} catch(\Exception $e) {
$this->adminLogAppend(
$this->container->get('thelia.translator')->trans(
'Fail to delete document for %id% with parent id %parentId% (Exception : %e%)',
array(
'%id%' => $event->getDocumentToDelete()->getId(),
'%parentId%' => $event->getDocumentToDelete()->getParentId(),
'%e%' => $e->getMessage()
),
'document'
)
);
throw $e;
}
}
public static function getSubscribedEvents()
{
return array(
TheliaEvents::DOCUMENT_PROCESS => array("processDocument", 128),
TheliaEvents::DOCUMENT_CLEAR_CACHE => array("clearCache", 128),
TheliaEvents::DOCUMENT_DELETE => array("deleteDocument", 128),
TheliaEvents::DOCUMENT_SAVE => array("saveDocument", 128),
TheliaEvents::DOCUMENT_UPDATE => array("updateDocument", 128),
);
}
}

View File

@@ -334,7 +334,6 @@ class Image extends BaseCachedFile implements EventSubscriberInterface
// Update image modifications
$event->getModelImage()->save();
$event->setModelImage($event->getModelImage());
}
/**
@@ -350,7 +349,7 @@ class Image extends BaseCachedFile implements EventSubscriberInterface
$fileManager = new FileManager($this->container);
try {
$fileManager->deleteImage($event->getImageToDelete(), $event->getImageType());
$fileManager->deleteFile($event->getImageToDelete(), $event->getImageType(), FileManager::FILE_TYPE_IMAGES);
$this->adminLogAppend(
$this->container->get('thelia.translator')->trans(
@@ -362,7 +361,7 @@ class Image extends BaseCachedFile implements EventSubscriberInterface
'image'
)
);
} catch(\Exception $e) {
} catch(\Exception $e){
$this->adminLogAppend(
$this->container->get('thelia.translator')->trans(
'Fail to delete image for %id% with parent id %parentId% (Exception : %e%)',

View File

@@ -36,6 +36,10 @@
<argument type="service" id="service_container"/>
<tag name="kernel.event_subscriber"/>
</service>
<service id="thelia.action.document" class="Thelia\Action\Document">
<argument type="service" id="service_container"/>
<tag name="kernel.event_subscriber"/>
</service>
<service id="thelia.action.category" class="Thelia\Action\Category">
<argument type="service" id="service_container"/>

View File

@@ -35,6 +35,7 @@
<loop class="Thelia\Core\Template\Loop\FolderTree" name="folder-tree"/>
<loop class="Thelia\Core\Template\Loop\Cart" name="cart"/>
<loop class="Thelia\Core\Template\Loop\Image" name="image"/>
<loop class="Thelia\Core\Template\Loop\Document" name="document"/>
<loop class="Thelia\Core\Template\Loop\Config" name="config"/>
<loop class="Thelia\Core\Template\Loop\Coupon" name="coupon"/>
<loop class="Thelia\Core\Template\Loop\Message" name="message"/>
@@ -59,19 +60,25 @@
<form name="thelia.admin.category.creation" class="Thelia\Form\CategoryCreationForm"/>
<form name="thelia.admin.category.modification" class="Thelia\Form\CategoryModificationForm"/>
<form name="thelia.admin.category.image.modification" class="Thelia\Form\CategoryImageModification"/>
<form name="thelia.admin.category.image.modification" class="Thelia\Form\CategoryDocumentModification"/>
<form name="thelia.admin.product.creation" class="Thelia\Form\ProductCreationForm"/>
<form name="thelia.admin.product.modification" class="Thelia\Form\ProductModificationForm"/>
<form name="thelia.admin.product.details.modification" class="Thelia\Form\ProductDetailsModificationForm"/>
<form name="thelia.admin.product.image.modification" class="Thelia\Form\ProductImageModification"/>
<form name="thelia.admin.product.image.modification" class="Thelia\Form\ProductDocumentModification"/>
<form name="thelia.admin.product.creation" class="Thelia\Form\ProductCreationForm"/>
<form name="thelia.admin.product.deletion" class="Thelia\Form\ProductModificationForm"/>
<form name="thelia.admin.folder.creation" class="Thelia\Form\FolderCreationForm"/>
<form name="thelia.admin.folder.modification" class="Thelia\Form\FolderModificationForm"/>
<form name="thelia.admin.folder.image.modification" class="Thelia\Form\FolderImageModification"/>
<form name="thelia.admin.folder.image.modification" class="Thelia\Form\FolderDocumentModification"/>
<form name="thelia.admin.content.creation" class="Thelia\Form\ContentCreationForm"/>
<form name="thelia.admin.content.modification" class="Thelia\Form\ContentModificationForm"/>
<form name="thelia.admin.content.image.modification" class="Thelia\Form\ContentImageModification"/>
<form name="thelia.admin.content.image.modification" class="Thelia\Form\ContentDocumentModification"/>
<form name="thelia.cart.add" class="Thelia\Form\CartAdd"/>

View File

@@ -63,7 +63,36 @@
<requirement key="customer_id">\d+</requirement>
</route>
<route id="admin.image.delete" path="/admin/image/type/{parentType}/delete/{imageId}">
<default key="_controller">Thelia\Controller\Admin\FileController::deleteImagesAction</default>
<default key="_controller">Thelia\Controller\Admin\FileController::deleteImageAction</default>
<requirement key="parentType">.*</requirement>
<requirement key="parentId">\d+</requirement>
</route>
<route id="admin.document.save-ajax" path="/admin/document/type/{parentType}/{parentId}/save-ajax">
<default key="_controller">Thelia\Controller\Admin\FileController::saveDocumentAjaxAction</default>
<requirement key="parentType">.*</requirement>
<requirement key="parentId">\d+</requirement>
</route>
<route id="admin.document.form-ajax" path="/admin/document/type/{parentType}/{parentId}/form-ajax">
<default key="_controller">Thelia\Controller\Admin\FileController::getDocumentFormAjaxAction</default>
<requirement key="parentType">.*</requirement>
<requirement key="parentId">\d+</requirement>
</route>
<route id="admin.document.list-ajax" path="/admin/document/type/{parentType}/{parentId}/list-ajax">
<default key="_controller">Thelia\Controller\Admin\FileController::getDocumentListAjaxAction</default>
<requirement key="parentType">.*</requirement>
<requirement key="parentId">\d+</requirement>
</route>
<route id="admin.document.update.view" path="/admin/document/type/{parentType}/{documentId}/update" methods="get">
<default key="_controller">Thelia\Controller\Admin\FileController::viewDocumentAction</default>
<requirement key="customer_id">\d+</requirement>
</route>
<route id="admin.document.update.process" path="/admin/document/type/{parentType}/{documentId}/update" methods="post">
<default key="_controller">Thelia\Controller\Admin\FileController::updateDocumentAction</default>
<requirement key="customer_id">\d+</requirement>
</route>
<route id="admin.document.delete" path="/admin/document/type/{parentType}/delete/{documentId}">
<default key="_controller">Thelia\Controller\Admin\FileController::deleteDocumentAction</default>
<requirement key="parentType">.*</requirement>
<requirement key="parentId">\d+</requirement>
</route>

View File

@@ -28,19 +28,21 @@ use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Router;
use Symfony\Component\Validator\Constraints\Image;
use Symfony\Component\Validator\Constraints\ImageValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Thelia\Core\Event\DocumentCreateOrUpdateEvent;
use Thelia\Core\Event\DocumentDeleteEvent;
use Thelia\Core\Event\ImageCreateOrUpdateEvent;
use Thelia\Core\Event\ImagesCreateOrUpdateEvent;
use Thelia\Core\Event\ImageDeleteEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Translation\Translator;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Log\Tlog;
use Thelia\Model\CategoryDocument;
use Thelia\Model\CategoryImage;
use Thelia\Model\ContentDocument;
use Thelia\Model\ContentImage;
use Thelia\Model\FolderDocument;
use Thelia\Model\FolderImage;
use Thelia\Model\ProductDocument;
use Thelia\Model\ProductImage;
use Thelia\Tools\FileManager;
use Thelia\Tools\Rest\ResponseRest;
@@ -59,21 +61,8 @@ use Thelia\Tools\Rest\ResponseRest;
*/
class FileController extends BaseAdminController
{
/**
* Manage how a file collection has to be saved
*
* @param int $parentId Parent id owning files being saved
* @param string $parentType Parent Type owning files being saved
*
* @return Response
*/
public function saveFilesAction($parentId, $parentType)
{
}
/**
* Manage how a image collection has to be saved
*
@@ -118,7 +107,7 @@ class FileController extends BaseAdminController
return new ResponseRest($message, 'text', 415);
}
$parentModel = $fileManager->getParentImageModel($parentType, $parentId);
$parentModel = $fileManager->getParentFIleModel($parentType, $parentId);
$imageModel = $fileManager->getImageModel($parentType);
if ($parentModel === null || $imageModel === null || $fileBeingUploaded === null) {
@@ -152,6 +141,73 @@ class FileController extends BaseAdminController
return new Response('', 404);
}
/**
* Manage how a document collection has to be saved
*
* @param int $parentId Parent id owning documents being saved
* @param string $parentType Parent Type owning documents being saved
*
* @return Response
*/
public function saveDocumentAjaxAction($parentId, $parentType)
{
$this->checkAuth('ADMIN', 'admin.document.save');
$this->checkXmlHttpRequest();
if ($this->isParentTypeValid($parentType)) {
if ($this->getRequest()->isMethod('POST')) {
/** @var UploadedFile $fileBeingUploaded */
$fileBeingUploaded = $this->getRequest()->files->get('file');
$fileManager = new FileManager($this->container);
// Validate if file is too big
if ($fileBeingUploaded->getError() == 1) {
$message = $this->getTranslator()
->trans(
'File is too heavy, please retry with a file having a size less than %size%.',
array('%size%' => ini_get('post_max_size')),
'document'
);
return new ResponseRest($message, 'text', 403);
}
$parentModel = $fileManager->getParentFileModel($parentType, $parentId);
$documentModel = $fileManager->getDocumentModel($parentType);
if ($parentModel === null || $documentModel === null || $fileBeingUploaded === null) {
return new Response('', 404);
}
$defaultTitle = $parentModel->getTitle();
$documentModel->setParentId($parentId);
$documentModel->setTitle($defaultTitle);
$documentCreateOrUpdateEvent = new DocumentCreateOrUpdateEvent(
$parentType,
$parentId
);
$documentCreateOrUpdateEvent->setModelDocument($documentModel);
$documentCreateOrUpdateEvent->setUploadedFile($fileBeingUploaded);
$documentCreateOrUpdateEvent->setParentName($parentModel->getTitle());
// Dispatch Event to the Action
$this->dispatch(
TheliaEvents::DOCUMENT_SAVE,
$documentCreateOrUpdateEvent
);
return new ResponseRest(array('status' => true, 'message' => ''));
}
}
return new Response('', 404);
}
/**
* Manage how a image list will be displayed in AJAX
*
@@ -169,6 +225,23 @@ class FileController extends BaseAdminController
return $this->render('includes/image-upload-list-ajax', $args);
}
/**
* Manage how a document list will be displayed in AJAX
*
* @param int $parentId Parent id owning documents being saved
* @param string $parentType Parent Type owning documents being saved
*
* @return Response
*/
public function getDocumentListAjaxAction($parentId, $parentType)
{
$this->checkAuth('ADMIN', 'admin.document.save');
$this->checkXmlHttpRequest();
$args = array('documentType' => $parentType, 'parentId' => $parentId);
return $this->render('includes/document-upload-list-ajax', $args);
}
/**
* Manage how an image list will be uploaded in AJAX
*
@@ -186,6 +259,23 @@ class FileController extends BaseAdminController
return $this->render('includes/image-upload-form', $args);
}
/**
* Manage how an document list will be uploaded in AJAX
*
* @param int $parentId Parent id owning documents being saved
* @param string $parentType Parent Type owning documents being saved
*
* @return Response
*/
public function getDocumentFormAjaxAction($parentId, $parentType)
{
$this->checkAuth('ADMIN', 'admin.document.save');
$this->checkXmlHttpRequest();
$args = array('documentType' => $parentType, 'parentId' => $parentId);
return $this->render('includes/document-upload-form', $args);
}
/**
* Manage how an image is viewed
*
@@ -209,7 +299,35 @@ class FileController extends BaseAdminController
'imageType' => $parentType,
'redirectUrl' => $redirectUrl
));
} catch (Exception $e) {
} catch (\Exception $e) {
$this->pageNotFound();
}
}
/**
* Manage how an document is viewed
*
* @param int $documentId Parent id owning images being saved
* @param string $parentType Parent Type owning images being saved
*
* @return Response
*/
public function viewDocumentAction($documentId, $parentType)
{
if (null !== $response = $this->checkAuth('admin.document.view')) {
return $response;
}
try {
$fileManager = new FileManager($this->container);
$document = $fileManager->getDocumentModelQuery($parentType)->findPk($documentId);
$redirectUrl = $fileManager->getRedirectionUrl($parentType, $document->getParentId());
return $this->render('document-edit', array(
'documentId' => $documentId,
'documentType' => $parentType,
'redirectUrl' => $redirectUrl
));
} catch (\Exception $e) {
$this->pageNotFound();
}
}
@@ -237,12 +355,12 @@ class FileController extends BaseAdminController
$image = $fileManager->getImageModelQuery($parentType)->findPk($imageId);
$oldImage = clone $image;
if (null === $image) {
throw new \InvalidArgumentException(sprintf('%d image id does not exists', $imageId));
throw new \InvalidArgumentException(sprintf('%d image id does not exist', $imageId));
}
$form = $this->validateForm($imageModification);
$event = $this->createEventInstance($parentType, $image, $form->getData());
$event = $this->createImageEventInstance($parentType, $image, $form->getData());
$event->setOldModelImage($oldImage);
$files = $this->getRequest()->files;
@@ -288,14 +406,87 @@ class FileController extends BaseAdminController
}
/**
* Manage how a image has to be deleted (AJAX)
* Manage how an document is updated
*
* @param int $imageId Parent id owning images being saved
* @param string $parentType Parent Type owning images being saved
* @param int $documentId Parent id owning documents being saved
* @param string $parentType Parent Type owning documents being saved
*
* @return Response
*/
public function deleteImagesAction($imageId, $parentType)
public function updateDocumentAction($documentId, $parentType)
{
if (null !== $response = $this->checkAuth('admin.image.update')) {
return $response;
}
$message = false;
$fileManager = new FileManager($this->container);
$documentModification = $fileManager->getImageForm($parentType, $this->getRequest());
try {
$document = $fileManager->getDocumentModelQuery($parentType)->findPk($documentId);
$oldDocument = clone $document;
if (null === $document) {
throw new \InvalidArgumentException(sprintf('%d document id does not exist', $documentId));
}
$form = $this->validateForm($documentModification);
$event = $this->createImageEventInstance($parentType, $document, $form->getData());
$event->setOldModelImage($oldDocument);
$files = $this->getRequest()->files;
$fileForm = $files->get($documentModification->getName());
if (isset($fileForm['file'])) {
$event->setUploadedFile($fileForm['file']);
}
$this->dispatch(TheliaEvents::DOCUMENT_UPDATE, $event);
$documentUpdated = $event->getModelImage();
$this->adminLogAppend(sprintf('Document with Ref %s (ID %d) modified', $documentUpdated->getTitle(), $documentUpdated->getId()));
if ($this->getRequest()->get('save_mode') == 'close') {
$this->redirectToRoute('admin.documents');
} else {
$this->redirectSuccess($documentModification);
}
} catch (FormValidationException $e) {
$message = sprintf('Please check your input: %s', $e->getMessage());
} catch (PropelException $e) {
$message = $e->getMessage();
} catch (\Exception $e) {
$message = sprintf('Sorry, an error occurred: %s', $e->getMessage().' '.$e->getFile());
}
if ($message !== false) {
Tlog::getInstance()->error(sprintf('Error during document editing : %s.', $message));
$documentModification->setErrorMessage($message);
$this->getParserContext()
->addForm($documentModification)
->setGeneralError($message);
}
return $this->render('document-edit', array(
'documentId' => $documentId,
'documentType' => $parentType
));
}
/**
* Manage how a image has to be deleted (AJAX)
*
* @param int $imageId Parent id owning image being deleted
* @param string $parentType Parent Type owning image being deleted
*
* @return Response
*/
public function deleteImageAction($imageId, $parentType)
{
$this->checkAuth('ADMIN', 'admin.image.delete');
$this->checkXmlHttpRequest();
@@ -330,6 +521,49 @@ class FileController extends BaseAdminController
return new Response($message);
}
/**
* Manage how a document has to be deleted (AJAX)
*
* @param int $documentId Parent id owning document being deleted
* @param string $parentType Parent Type owning document being deleted
*
* @return Response
*/
public function deleteDocumentAction($documentId, $parentType)
{
$this->checkAuth('ADMIN', 'admin.document.delete');
$this->checkXmlHttpRequest();
$fileManager = new FileManager($this->container);
$documentModelQuery = $fileManager->getDocumentModelQuery($parentType);
$model = $documentModelQuery->findPk($documentId);
if ($model == null) {
return $this->pageNotFound();
}
// Feed event
$documentDeleteEvent = new DocumentDeleteEvent(
$model,
$parentType
);
// Dispatch Event to the Action
$this->dispatch(
TheliaEvents::DOCUMENT_DELETE,
$documentDeleteEvent
);
$message = $this->getTranslator()
->trans(
'Document deleted successfully',
array(),
'document'
);
return new Response($message);
}
/**
* Log error message
*
@@ -362,11 +596,11 @@ class FileController extends BaseAdminController
*/
public function isParentTypeValid($parentType)
{
return (in_array($parentType, ImagesCreateOrUpdateEvent::getAvailableType()));
return (in_array($parentType, FileManager::getAvailableTypes()));
}
/**
* Create Event instance
* Create Image Event instance
*
* @param string $parentType Parent Type owning images being saved
* @param CategoryImage|ProductImage|ContentImage|FolderImage $model Image model
@@ -374,7 +608,7 @@ class FileController extends BaseAdminController
*
* @return ImageCreateOrUpdateEvent
*/
private function createEventInstance($parentType, $model, $data)
protected function createImageEventInstance($parentType, $model, $data)
{
$imageCreateEvent = new ImageCreateOrUpdateEvent($parentType, null);
@@ -399,5 +633,39 @@ class FileController extends BaseAdminController
return $imageCreateEvent;
}
/**
* Create Document Event instance
*
* @param string $parentType Parent Type owning documents being saved
* @param CategoryDocument|ProductDocument|ContentDocument|FolderDocument $model Document model
* @param array $data Post data
*
* @return ImageCreateOrUpdateEvent
*/
protected function createDocumentEventInstance($parentType, $model, $data)
{
$documentCreateEvent = new DocumentCreateOrUpdateEvent($parentType, null);
if (isset($data['title'])) {
$model->setTitle($data['title']);
}
if (isset($data['chapo'])) {
$model->setChapo($data['chapo']);
}
if (isset($data['description'])) {
$model->setDescription($data['description']);
}
if (isset($data['file'])) {
$model->setFile($data['file']);
}
if (isset($data['postscriptum'])) {
$model->setPostscriptum($data['postscriptum']);
}
$documentCreateEvent->setModelDocument($model);
return $documentCreateEvent;
}
}

View File

@@ -0,0 +1,217 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Core\Event;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Thelia\Model\CategoryDocument;
use Thelia\Model\ContentDocument;
use Thelia\Model\FolderDocument;
use Thelia\Model\ProductDocument;
/**
* Created by JetBrains PhpStorm.
* Date: 9/18/13
* Time: 3:56 PM
*
* Occurring when a Document is saved
*
* @package Document
* @author Guillaume MOREL <gmorel@openstudio.fr>
*
*/
class DocumentCreateOrUpdateEvent extends ActionEvent
{
/** @var CategoryDocument|ProductDocument|ContentDocument|FolderDocument model to save */
protected $modelDocument = array();
/** @var CategoryDocument|ProductDocument|ContentDocument|FolderDocument model to save */
protected $oldModelDocument = array();
/** @var UploadedFile Document file to save */
protected $uploadedFile = null;
/** @var int Document parent id */
protected $parentId = null;
/** @var string Document type */
protected $documentType = null;
/** @var string Parent name */
protected $parentName = null;
/**
* Constructor
*
* @param string $documentType Document type
* ex : FileManager::TYPE_CATEGORY
* @param int $parentId Document parent id
*/
public function __construct($documentType, $parentId)
{
$this->imageType = $documentType;
$this->parentId = $parentId;
}
/**
* Set Document to save
*
* @param CategoryDocument|ProductDocument|ContentDocument|FolderDocument $document Document to save
*
* @return $this
*/
public function setModelDocument($document)
{
$this->modelDocument = $document;
return $this;
}
/**
* Get Document being saved
*
* @return CategoryDocument|ProductDocument|ContentDocument|FolderDocument
*/
public function getModelDocument()
{
return $this->modelDocument;
}
/**
* Set document type
*
* @param string $documentType Document type
*
* @return $this
*/
public function setDocumentType($documentType)
{
$this->imageType = $documentType;
return $this;
}
/**
* Get document type
*
* @return string
*/
public function getDocumentType()
{
return $this->documentType;
}
/**
* Set Document parent id
*
* @param int $parentId Document parent id
*
* @return $this
*/
public function setParentId($parentId)
{
$this->parentId = $parentId;
return $this;
}
/**
* Get Document parent id
*
* @return int
*/
public function getParentId()
{
return $this->parentId;
}
/**
* Set uploaded file
*
* @param UploadedFile $uploadedFile File being uploaded
*
* @return $this
*/
public function setUploadedFile($uploadedFile)
{
$this->uploadedFile = $uploadedFile;
return $this;
}
/**
* Get uploaded file
*
* @return UploadedFile
*/
public function getUploadedFile()
{
return $this->uploadedFile;
}
/**
* Set parent name
*
* @param string $parentName Parent name
*
* @return $this
*/
public function setParentName($parentName)
{
$this->parentName = $parentName;
return $this;
}
/**
* Get parent name
*
* @return string
*/
public function getParentName()
{
return $this->parentName;
}
/**
* Set old model value
*
* @param CategoryDocument|ContentDocument|FolderDocument|ProductDocument $oldModelDocument
*/
public function setOldModelDocument($oldModelDocument)
{
$this->oldModelDocument = $oldModelDocument;
}
/**
* Get old model value
*
* @return CategoryDocument|ContentDocument|FolderDocument|ProductDocument
*/
public function getOldModelDocument()
{
return $this->oldModelDocument;
}
}

View File

@@ -0,0 +1,112 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Core\Event;
use Thelia\Model\CategoryDocument;
use Thelia\Model\ContentDocument;
use Thelia\Model\FolderDocument;
use Thelia\Model\ProductDocument;
/**
* Created by JetBrains PhpStorm.
* Date: 9/18/13
* Time: 3:56 PM
*
* Occurring when a Document is about to be deleted
*
* @package Document
* @author Guillaume MOREL <gmorel@openstudio.fr>
*
*/
class DocumentDeleteEvent extends ActionEvent
{
/** @var string Document type */
protected $documentType = null;
/** @var CategoryDocument|ProductDocument|ContentDocument|FolderDocument Document about to be deleted */
protected $documentToDelete = null;
/**
* Constructor
*
* @param CategoryDocument|ProductDocument|ContentDocument|FolderDocument $documentToDelete Document about to be deleted
* @param string $documentType Document type
* ex : FileManager::TYPE_CATEGORY
*/
public function __construct($documentToDelete, $documentType)
{
$this->imageToDelete = $documentToDelete;
$this->documentType = $documentType;
}
/**
* Set picture type
*
* @param string $documentType Document type
*
* @return $this
*/
public function setDocumentType($documentType)
{
$this->documentType = $documentType;
return $this;
}
/**
* Get picture type
*
* @return string
*/
public function getDocumentType()
{
return $this->documentType;
}
/**
* Set Document about to be deleted
*
* @param CategoryDocument|ProductDocument|ContentDocument|FolderDocument $documentToDelete Document about to be deleted
*
* @return $this
*/
public function setDocumentToDelete($documentToDelete)
{
$this->imageToDelete = $documentToDelete;
return $this;
}
/**
* Get Document about to be deleted
*
* @return CategoryDocument|ProductDocument|ContentDocument|FolderDocument
*/
public function getDocumentToDelete()
{
return $this->documentToDelete;
}
}

View File

@@ -1,184 +0,0 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Core\Event;
/**
* Created by JetBrains PhpStorm.
* Date: 9/18/13
* Time: 3:56 PM
*
* Occurring when a Image list is saved
*
* @package Image
* @author Guillaume MOREL <gmorel@openstudio.fr>
*
*/
class ImagesCreateOrUpdateEvent extends ActionEvent
{
CONST TYPE_PRODUCT = 'product';
CONST TYPE_CATEGORY = 'category';
CONST TYPE_CONTENT = 'content';
CONST TYPE_FOLDER = 'folder';
/** @var array Images model to save */
protected $modelImages = array();
/** @var array Images file to save */
protected $uploadedFiles = array();
/** @var int Image parent id */
protected $parentId = null;
/** @var string Image type */
protected $imageType = null;
/** @var array Available image parent type */
protected static $availableType = array(
self::TYPE_PRODUCT,
self::TYPE_CATEGORY,
self::TYPE_CONTENT,
self::TYPE_FOLDER,
);
/**
* Constructor
*
* @param string $pictureType Picture type
* ex : ImageCreateOrUpdateEvent::TYPE_CATEGORY
* @param int $parentId Image parent id
*/
public function __construct($pictureType, $parentId)
{
$this->imageType = $pictureType;
$this->parentId = $parentId;
}
/**
* Set Images to save
*
* @param array $images Thelia\Model\CategoryImage Array
*
* @return $this
*/
public function setModelImages($images)
{
$this->modelImages = $images;
return $this;
}
/**
* Get Images being saved
*
* @return array Array of Thelia\Model\CategoryImage
*/
public function getModelImages()
{
return $this->modelImages;
}
/**
* Set Images to save
*
* @param array $images Thelia\Model\CategoryImage Array
*
* @return $this
*/
public function setUploadedFiles($images)
{
$this->uploadedFiles = $images;
return $this;
}
/**
* Get Images being saved
*
* @return array Array of Thelia\Model\CategoryImage
*/
public function getUploadedFiles()
{
return $this->uploadedFiles;
}
/**
* Set picture type
*
* @param string $pictureType Picture type
*
* @return $this
*/
public function setImageType($pictureType)
{
$this->imageType = $pictureType;
return $this;
}
/**
* Get picture type
*
* @return string
*/
public function getImageType()
{
return $this->imageType;
}
/**
* Get all image parent type available
*
* @return array
*/
public static function getAvailableType()
{
return self::$availableType;
}
/**
* Set Image parent id
*
* @param int $parentId Image parent id
*
* @return $this
*/
public function setParentId($parentId)
{
$this->parentId = $parentId;
return $this;
}
/**
* Get Image parent id
*
* @return int
*/
public function getParentId()
{
return $this->parentId;
}
}

View File

@@ -337,6 +337,26 @@ final class TheliaEvents
*/
const DOCUMENT_PROCESS = "action.processDocument";
/**
* Sent on image cache clear request
*/
const DOCUMENT_CLEAR_CACHE = "action.clearDocumentCache";
/**
* Save given documents
*/
const DOCUMENT_SAVE = "action.saveDocument";
/**
* Save given documents
*/
const DOCUMENT_UPDATE = "action.updateDocument";
/**
* Delete given document
*/
const DOCUMENT_DELETE = "action.deleteDocument";
/**
* Sent on image cache clear request
*/

View File

@@ -69,7 +69,7 @@ abstract class DocumentModification extends BaseForm
'file',
array(
'constraints' => array(),
'label' => Translator::getInstance()->trans('File'),
'label' => Translator::getInstance()->trans('Replace current document by this file'),
'label_attr' => array(
'for' => 'file'
)

View File

@@ -72,12 +72,12 @@ abstract class ImageModification extends BaseForm
'constraints' => array(
new Image(
array(
'minWidth' => 200,
'minHeight' => 200
// 'minWidth' => 200,
// 'minHeight' => 200
)
)
),
'label' => Translator::getInstance()->trans('File'),
'label' => Translator::getInstance()->trans('Replace current image by this file'),
'label_attr' => array(
'for' => 'file'
)

View File

@@ -25,4 +25,28 @@ class CategoryDocument extends BaseCategoryDocument
return true;
}
/**
* Set Document parent id
*
* @param int $parentId parent id
*
* @return $this
*/
public function setParentId($parentId)
{
$this->setCategoryId($parentId);
return $this;
}
/**
* Get Document parent id
*
* @return int parent id
*/
public function getParentId()
{
return $this->getCategoryId();
}
}

View File

@@ -25,4 +25,28 @@ class ContentDocument extends BaseContentDocument
return true;
}
/**
* Set Document parent id
*
* @param int $parentId parent id
*
* @return $this
*/
public function setParentId($parentId)
{
$this->setContentId($parentId);
return $this;
}
/**
* Get Document parent id
*
* @return int parent id
*/
public function getParentId()
{
return $this->getContentId();
}
}

View File

@@ -25,4 +25,28 @@ class FolderDocument extends BaseFolderDocument
return true;
}
/**
* Set Document parent id
*
* @param int $parentId parent id
*
* @return $this
*/
public function setParentId($parentId)
{
$this->setFolderId($parentId);
return $this;
}
/**
* Get Document parent id
*
* @return int parent id
*/
public function getParentId()
{
return $this->getFolderId();
}
}

View File

@@ -26,4 +26,28 @@ class ProductDocument extends BaseProductDocument
return true;
}
/**
* Set Document parent id
*
* @param int $parentId parent id
*
* @return $this
*/
public function setParentId($parentId)
{
$this->setProductId($parentId);
return $this;
}
/**
* Get Document parent id
*
* @return int parent id
*/
public function getParentId()
{
return $this->getProductId();
}
}

View File

@@ -24,24 +24,38 @@ namespace Thelia\Tools;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Thelia\Core\Event\ImagesCreateOrUpdateEvent;
use Thelia\Core\Event\DocumentCreateOrUpdateEvent;
use Thelia\Core\Event\ImageCreateOrUpdateEvent;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\Translation\Translator;
use Thelia\Exception\ImageException;
use Thelia\Form\CategoryDocumentModification;
use Thelia\Form\CategoryImageModification;
use Thelia\Form\ContentDocumentModification;
use Thelia\Form\ContentImageModification;
use Thelia\Form\FolderDocumentModification;
use Thelia\Form\FolderImageModification;
use Thelia\Form\ProductDocumentModification;
use Thelia\Form\ProductImageModification;
use Thelia\Model\AdminLog;
use Thelia\Model\CategoryDocument;
use Thelia\Model\CategoryDocumentQuery;
use Thelia\Model\CategoryImage;
use Thelia\Model\CategoryImageQuery;
use Thelia\Model\CategoryQuery;
use Thelia\Model\ContentDocument;
use Thelia\Model\ContentDocumentQuery;
use Thelia\Model\ContentImage;
use Thelia\Model\ContentImageQuery;
use Thelia\Model\ContentQuery;
use Thelia\Model\Exception\InvalidArgumentException;
use Thelia\Model\FolderDocument;
use Thelia\Model\FolderDocumentQuery;
use Thelia\Model\FolderImage;
use Thelia\Model\FolderImageQuery;
use Thelia\Model\FolderQuery;
use Thelia\Model\ProductDocument;
use Thelia\Model\ProductDocumentQuery;
use Thelia\Model\ProductImage;
use Thelia\Model\ProductImageQuery;
use Thelia\Model\ProductQuery;
@@ -65,6 +79,9 @@ class FileManager
CONST TYPE_FOLDER = 'folder';
CONST TYPE_MODULE = 'module';
CONST FILE_TYPE_IMAGES = 'images';
CONST FILE_TYPE_DOCUMENTS = 'documents';
/** @var ContainerInterface Service Container */
protected $container = null;
@@ -86,41 +103,44 @@ class FileManager
* Copy UploadedFile into the server storage directory
*
* @param int $parentId Parent id
* @param string $imageType Image type
* @param FolderImage|ContentImage|CategoryImage|ProductImage $modelImage Image saved
* @param string $fileType Image type
* @param FolderImage|ContentImage|CategoryImage|ProductImage|FolderDocument|ContentDocument|CategoryDocument|ProductDocument $model Model saved
* @param UploadedFile $uploadedFile Ready to be uploaded file
*
* @throws \Thelia\Exception\ImageException
* @return UploadedFile
*/
public function copyUploadedFile($parentId, $imageType, $modelImage, $uploadedFile)
public function copyUploadedFile($parentId, $fileType, $model, $uploadedFile)
{
$newUploadedFile = null;
if ($uploadedFile !== null) {
$directory = $this->getUploadDir($imageType);
$fileName = $this->renameFile($modelImage->getId(), $uploadedFile);
$directory = $this->getUploadDir($fileType, FileManager::FILE_TYPE_IMAGES);
$fileName = $this->renameFile($model->getId(), $uploadedFile);
$this->adminLogAppend(
$this->translator->trans(
'Uploading picture %pictureName% to %directory% for parent_id %parentId% (%parentType%)',
'Uploading %type% %fileName% to %directory% for parent_id %parentId% (%parentType%)',
array(
'%pictureName%' => $uploadedFile->getClientOriginalName(),
'%type%' => $fileType,
'%fileName%' => $uploadedFile->getClientOriginalName(),
'%directory%' => $directory . '/' . $fileName,
'%parentId%' => $parentId,
'%parentType%' => $imageType
'%parentType%' => $fileType
),
'image'
)
);
$newUploadedFile = $uploadedFile->move($directory, $fileName);
$modelImage->setFile($fileName);
$model->setFile($fileName);
if (!$modelImage->save()) {
if (!$model->save()) {
throw new ImageException(
sprintf(
'Image %s (%s) failed to be saved (image file)',
$modelImage->getFile(),
$imageType
'*s %s (%s) failed to be saved (image file)',
ucfirst($fileType),
$model->getFile(),
$fileType
)
);
}
@@ -132,32 +152,32 @@ class FileManager
/**
* Save image into the database
*
* @param ImagesCreateOrUpdateEvent $event Image event
* @param ImageCreateOrUpdateEvent $event Image event
* @param FolderImage|ContentImage|CategoryImage|ProductImage $modelImage Image to save
*
* @return int Nb lines modified
* @throws \Thelia\Exception\ImageException
* @todo refactor make all pictures using propel inheritance and factorise image behaviour into one single clean action
*/
public function saveImage(ImagesCreateOrUpdateEvent $event, $modelImage)
public function saveImage(ImageCreateOrUpdateEvent $event, $modelImage)
{
$nbModifiedLines = 0;
if ($modelImage->getFile() !== null) {
switch ($event->getImageType()) {
case ImagesCreateOrUpdateEvent::TYPE_PRODUCT:
case self::TYPE_PRODUCT:
/** @var ProductImage $modelImage */
$modelImage->setProductId($event->getParentId());
break;
case ImagesCreateOrUpdateEvent::TYPE_CATEGORY:
case self::TYPE_CATEGORY:
/** @var CategoryImage $modelImage */
$modelImage->setCategoryId($event->getParentId());
break;
case ImagesCreateOrUpdateEvent::TYPE_CONTENT:
case self::TYPE_CONTENT:
/** @var ContentImage $modelImage */
$modelImage->setContentId($event->getParentId());
break;
case ImagesCreateOrUpdateEvent::TYPE_FOLDER:
case self::TYPE_FOLDER:
/** @var FolderImage $modelImage */
$modelImage->setFolderId($event->getParentId());
break;
@@ -167,7 +187,7 @@ class FileManager
'Picture parent type is unknown (available types : %s)',
implode(
',',
$event->getAvailableType()
self::getAvailableTypes()
)
)
);
@@ -187,6 +207,64 @@ class FileManager
return $nbModifiedLines;
}
/**
* Save document into the database
*
* @param DocumentCreateOrUpdateEvent $event Image event
* @param FolderDocument|ContentDocument|CategoryDocument|ProductDocument $modelDocument Document to save
*
* @throws \Thelia\Model\Exception\InvalidArgumentException
* @return int Nb lines modified
* @todo refactor make all documents using propel inheritance and factorise image behaviour into one single clean action
*/
public function saveDocument(DocumentCreateOrUpdateEvent $event, $modelDocument)
{
$nbModifiedLines = 0;
if ($modelDocument->getFile() !== null) {
switch ($event->getDocumentType()) {
case self::TYPE_PRODUCT:
/** @var ProductImage $modelImage */
$modelDocument->setProductId($event->getParentId());
break;
case self::TYPE_CATEGORY:
/** @var CategoryImage $modelImage */
$modelDocument->setCategoryId($event->getParentId());
break;
case self::TYPE_CONTENT:
/** @var ContentImage $modelImage */
$modelDocument->setContentId($event->getParentId());
break;
case self::TYPE_FOLDER:
/** @var FolderImage $modelImage */
$modelDocument->setFolderId($event->getParentId());
break;
default:
throw new InvalidArgumentException(
sprintf(
'Document parent type is unknown (available types : %s)',
implode(
',',
self::getAvailableTypes()
)
)
);
}
$nbModifiedLines = $modelDocument->save();
if (!$nbModifiedLines) {
throw new InvalidArgumentException(
sprintf(
'Document %s failed to be saved (document content)',
$modelDocument->getFile()
)
);
}
}
return $nbModifiedLines;
}
/**
* Sanitizes a filename replacing whitespace with dashes
*
@@ -226,14 +304,17 @@ class FileManager
/**
* Delete image from file storage and database
*
* @param CategoryImage|ProductImage|ContentImage|FolderImage $imageModel Image being deleted
* @param CategoryImage|ProductImage|ContentImage|FolderImage|CategoryDocument|ProductDocument|ContentDocument|FolderDocument $model File being deleted
* @param string $parentType Parent type
* @param string $fileType File type ex FileManager::FILE_TYPE_DOCUMENTS
*
* @todo refactor make all pictures using propel inheritance and factorise image behaviour into one single clean action
*/
public function deleteImage($imageModel, $parentType)
public function deleteFile($model, $parentType, $fileType)
{
$url = $this->getUploadDir($parentType) . '/' . $imageModel->getFile();
$url = $this->getUploadDir($parentType, $fileType) . '/' . $model->getFile();
unlink(str_replace('..', '', $url));
$imageModel->delete();
$model->delete();
}
@@ -249,16 +330,16 @@ class FileManager
public function getImageModel($parentType)
{
switch ($parentType) {
case ImagesCreateOrUpdateEvent::TYPE_PRODUCT:
case self::TYPE_PRODUCT:
$model = new ProductImage();
break;
case ImagesCreateOrUpdateEvent::TYPE_CATEGORY:
case self::TYPE_CATEGORY:
$model = new CategoryImage();
break;
case ImagesCreateOrUpdateEvent::TYPE_CONTENT:
case self::TYPE_CONTENT:
$model = new ContentImage();
break;
case ImagesCreateOrUpdateEvent::TYPE_FOLDER:
case self::TYPE_FOLDER:
$model = new FolderImage();
break;
default:
@@ -268,6 +349,37 @@ class FileManager
return $model;
}
/**
* Get document model from type
*
* @param string $parentType Parent type
*
* @return null|ProductDocument|CategoryDocument|ContentDocument|FolderDocument
*
* @todo refactor make all documents using propel inheritance and factorise image behaviour into one single clean action
*/
public function getDocumentModel($parentType)
{
switch ($parentType) {
case self::TYPE_PRODUCT:
$model = new ProductDocument();
break;
case self::TYPE_CATEGORY:
$model = new CategoryDocument();
break;
case self::TYPE_CONTENT:
$model = new ContentDocument();
break;
case self::TYPE_FOLDER:
$model = new FolderDocument();
break;
default:
$model = null;
}
return $model;
}
/**
* Get image model query from type
*
@@ -280,16 +392,16 @@ class FileManager
public function getImageModelQuery($parentType)
{
switch ($parentType) {
case ImagesCreateOrUpdateEvent::TYPE_PRODUCT:
case self::TYPE_PRODUCT:
$model = new ProductImageQuery();
break;
case ImagesCreateOrUpdateEvent::TYPE_CATEGORY:
case self::TYPE_CATEGORY:
$model = new CategoryImageQuery();
break;
case ImagesCreateOrUpdateEvent::TYPE_CONTENT:
case self::TYPE_CONTENT:
$model = new ContentImageQuery();
break;
case ImagesCreateOrUpdateEvent::TYPE_FOLDER:
case self::TYPE_FOLDER:
$model = new FolderImageQuery();
break;
default:
@@ -299,6 +411,37 @@ class FileManager
return $model;
}
/**
* Get document model query from type
*
* @param string $parentType
*
* @return null|ProductDocumentQuery|CategoryDocumentQuery|ContentDocumentQuery|FolderDocumentQuery
*
* @todo refactor make all documents using propel inheritance and factorise image behaviour into one single clean action
*/
public function getDocumentModelQuery($parentType)
{
switch ($parentType) {
case self::TYPE_PRODUCT:
$model = new ProductDocumentQuery();
break;
case self::TYPE_CATEGORY:
$model = new CategoryDocumentQuery();
break;
case self::TYPE_CONTENT:
$model = new ContentDocumentQuery();
break;
case self::TYPE_FOLDER:
$model = new FolderDocumentQuery();
break;
default:
$model = null;
}
return $model;
}
/**
* Get image parent model from type
*
@@ -309,19 +452,19 @@ class FileManager
*
* @todo refactor make all pictures using propel inheritance and factorise image behaviour into one single clean action
*/
public function getParentImageModel($parentType, $parentId)
public function getParentFIleModel($parentType, $parentId)
{
switch ($parentType) {
case ImagesCreateOrUpdateEvent::TYPE_PRODUCT:
case self::TYPE_PRODUCT:
$model = ProductQuery::create()->findPk($parentId);
break;
case ImagesCreateOrUpdateEvent::TYPE_CATEGORY:
case self::TYPE_CATEGORY:
$model = CategoryQuery::create()->findPk($parentId);
break;
case ImagesCreateOrUpdateEvent::TYPE_CONTENT:
case self::TYPE_CONTENT:
$model = ContentQuery::create()->findPk($parentId);
break;
case ImagesCreateOrUpdateEvent::TYPE_FOLDER:
case self::TYPE_FOLDER:
$model = FolderQuery::create()->findPk($parentId);
break;
default:
@@ -343,20 +486,52 @@ class FileManager
public function getImageForm($parentType, Request $request)
{
switch ($parentType) {
case ImagesCreateOrUpdateEvent::TYPE_PRODUCT:
case self::TYPE_PRODUCT:
$form = new ProductImageModification($request);
break;
case ImagesCreateOrUpdateEvent::TYPE_CATEGORY:
case self::TYPE_CATEGORY:
$form = new CategoryImageModification($request);
break;
case ImagesCreateOrUpdateEvent::TYPE_CONTENT:
case self::TYPE_CONTENT:
$form = new ContentImageModification($request);
break;
case ImagesCreateOrUpdateEvent::TYPE_FOLDER:
case self::TYPE_FOLDER:
$form = new FolderImageModification($request);
break;
default:
$model = null;
$form = null;
}
return $form;
}
/**
* Get document parent model from type
*
* @param string $parentType Parent type
* @param Request $request Request service
*
* @todo refactor make all document using propel inheritance and factorise image behaviour into one single clean action
* @return ProductDocumentModification|CategoryDocumentModification|ContentDocumentModification|FolderDocumentModification
*/
public function getDocumentForm($parentType, Request $request)
{
switch ($parentType) {
case self::TYPE_PRODUCT:
$form = new ProductDocumentModification($request);
break;
case self::TYPE_CATEGORY:
$form = new CategoryDocumentModification($request);
break;
case self::TYPE_CONTENT:
$form = new ContentDocumentModification($request);
break;
case self::TYPE_FOLDER:
$form = new FolderDocumentModification($request);
break;
default:
$form = null;
}
return $form;
@@ -366,27 +541,32 @@ class FileManager
/**
* Get image upload dir
*
* @param string $parentType Parent type
* @param string $parentType Parent type ex FileManager::TYPE_PRODUCT
* @param string $fileType File type
*
* @return string Uri
*/
public function getUploadDir($parentType)
public function getUploadDir($parentType, $fileType)
{
if (!in_array($fileType, self::$availableFileType)) {
return false;
}
switch ($parentType) {
case ImagesCreateOrUpdateEvent::TYPE_PRODUCT:
$uri = THELIA_LOCAL_DIR . 'media/images/' . ImagesCreateOrUpdateEvent::TYPE_PRODUCT;
case self::TYPE_PRODUCT:
$uri = THELIA_LOCAL_DIR . 'media/' . $fileType . '/' . self::TYPE_PRODUCT;
break;
case ImagesCreateOrUpdateEvent::TYPE_CATEGORY:
$uri = THELIA_LOCAL_DIR . 'media/images/' . ImagesCreateOrUpdateEvent::TYPE_CATEGORY;
case self::TYPE_CATEGORY:
$uri = THELIA_LOCAL_DIR . 'media/' . $fileType . '/' . self::TYPE_CATEGORY;
break;
case ImagesCreateOrUpdateEvent::TYPE_CONTENT:
$uri = THELIA_LOCAL_DIR . 'media/images/' . ImagesCreateOrUpdateEvent::TYPE_CONTENT;
case self::TYPE_CONTENT:
$uri = THELIA_LOCAL_DIR . 'media/' . $fileType . '/' . self::TYPE_CONTENT;
break;
case ImagesCreateOrUpdateEvent::TYPE_FOLDER:
$uri = THELIA_LOCAL_DIR . 'media/images/' . ImagesCreateOrUpdateEvent::TYPE_FOLDER;
case self::TYPE_FOLDER:
$uri = THELIA_LOCAL_DIR . 'media/' . $fileType . '/' . self::TYPE_FOLDER;
break;
default:
$uri = null;
$uri = false;
}
return $uri;
@@ -403,16 +583,16 @@ class FileManager
public function getRedirectionUrl($parentType, $parentId)
{
switch ($parentType) {
case ImagesCreateOrUpdateEvent::TYPE_PRODUCT:
case self::TYPE_PRODUCT:
$uri = '/admin/products/update?product_id=' . $parentId . '&current_tab=images';
break;
case ImagesCreateOrUpdateEvent::TYPE_CATEGORY:
case self::TYPE_CATEGORY:
$uri = '/admin/categories/update?category_id=' . $parentId . '&current_tab=images';
break;
case ImagesCreateOrUpdateEvent::TYPE_CONTENT:
case self::TYPE_CONTENT:
$uri = '/admin/content/update/' . $parentId . '&current_tab=images';
break;
case ImagesCreateOrUpdateEvent::TYPE_FOLDER:
case self::TYPE_FOLDER:
$uri = '/admin/folders/update/' . $parentId . '&current_tab=images';
break;
default:
@@ -423,7 +603,7 @@ class FileManager
}
/** @var array Available image parent type */
/** @var array Available file parent type */
public static $availableType = array(
self::TYPE_PRODUCT,
self::TYPE_CATEGORY,
@@ -432,6 +612,12 @@ class FileManager
self::TYPE_MODULE
);
/** @var array Available file type type */
public static $availableFileType = array(
self::FILE_TYPE_DOCUMENTS,
self::FILE_TYPE_IMAGES
);
/**
* Rename file with image model id
*
@@ -470,4 +656,20 @@ class FileManager
return $isValid;
}
/**
* Return all document and image types
*
* @return array
*/
public static function getAvailableTypes()
{
return array(
self::TYPE_CATEGORY,
self::TYPE_CONTENT,
self::TYPE_FOLDER,
self::TYPE_PRODUCT,
self::TYPE_MODULE,
);
}
}

View File

@@ -0,0 +1,99 @@
$(function($){
// Manage document upload
$.documentUploadManager = {};
Dropzone.autoDiscover = false;
// Remove image on click
$.documentUploadManager.initDocumentDropZone = function() {
var documentDropzone = new Dropzone("#documents-dropzone", {
dictDefaultMessage : $('.btn-browse').html(),
uploadMultiple: false,
maxFilesize: 8
});
var totalFiles = 0,
completedFiles = 0;
documentDropzone.on("addedfile", function(file){
totalFiles += 1;
if(totalFiles == 1){
$('.dz-message').hide();
}
});
documentDropzone.on("complete", function(file){
completedFiles += 1;
if (completedFiles === totalFiles){
$('.dz-message').slideDown();
}
});
documentDropzone.on("success", function(file) {
documentDropzone.removeFile(file);
$.documentUploadManager.updateDocumentListAjax();
$.documentUploadManager.onClickDeleteDocument();
});
};
// Update picture list via AJAX call
$.documentUploadManager.updateDocumentListAjax = function() {
var $documentListArea = $(".document-manager .existing-document");
$documentListArea.html('<div class="loading" ></div>');
$.ajax({
type: "POST",
url: documentListUrl,
statusCode: {
404: function() {
$documentListArea.html(
documentListErrorMessage
);
}
}
}).done(function(data) {
$documentListArea.html(
data
);
$.documentUploadManager.onClickDeleteDocument();
});
};
// Remove image on click
$.documentUploadManager.onClickDeleteDocument = function() {
$('.document-manager .document-delete-btn').on('click', function (e) {
e.preventDefault();
var $this = $(this);
var $parent = $this.parent();
$parent.find('a').remove();
$parent.append('<div class="loading" ></div>');
var $url = $this.attr("href");
var errorMessage = $this.attr("data-error-message");
$.ajax({
type: "POST",
url: $url,
statusCode: {
404: function() {
$(".document-manager .message").html(
errorMessage
);
}
}
}).done(function(data) {
$parent.parents('tr').remove();
$(".document-manager .message").html(
data
);
});
return false;
});
};
$.documentUploadManager.onClickDeleteDocument();
});

View File

@@ -260,6 +260,7 @@
</div>
<div class="tab-pane fade {if $current_tab == 'documents'}active in{/if}" id="documents">
{include file='includes/document-upload-form.html' documentType='category' parentId=$category_id}
</div>
<div class="tab-pane fade {if $current_tab == 'modules'}active in{/if}" id="modules">
@@ -303,6 +304,9 @@
{javascripts file='assets/js/image-upload.js'}
<script src="{$asset_url}"></script>
{/javascripts}
{javascripts file='assets/js/document-upload.js'}
<script src="{$asset_url}"></script>
{/javascripts}
@@ -327,6 +331,7 @@
$(function() {
$.imageUploadManager.initImageDropZone();
$.documentUploadManager.initDocumentDropZone();
$('.use_default_rewriten_url').click(function(ev) {
alert("Not functionnal");

View File

@@ -0,0 +1,143 @@
{extends file="admin-layout.tpl"}
{block name="page-title"}{intl l='Edit a document'}{/block}
{block name="check-permissions"}admin.document.edit{/block}
{block name="main-content"}
<div class="documents edit-image">
<div id="wrapper" class="container">
{loop type="document" name="document_edit" source="{$documentType}" id="{$documentId}" backend_context="1" lang="$edit_language_id"}
<ul class="breadcrumb">
<li><a href="{url path='/admin/home'}">{intl l="Home"}</a></li>
<li><a href="{url path="{$redirectUrl}"}">{intl l="Document"}</a></li>
<li>{intl l='Editing document "%name"' name="{$TITLE}"}</li>
</ul>
<div class="row">
<div class="col-md-12 general-block-decorator">
<div class="row">
<div class="col-md-12 title title-without-tabs">
{intl l="Edit document $TITLE"}
</div>
<div class="form-container">
<div class="col-md-12">
{form name="thelia.admin.category.document.modification"}
<form method="POST" action="{url path="/admin/document/type/{$documentType}/{$ID}/update"}" enctype="multipart/form-data" class="clearfix">
<div class="row inner-toolbar clearfix">
<div class="col-md-6 inner-actions pull-right">
<button type="submit" name="save_mode" value="stay" class="btn btn-default btn-primary" title="{intl l='Save'}">{intl l='Save'} <span class="glyphicon glyphicon-ok"></span></button>
<a href="{url path="{$redirectUrl}"}" class="btn btn-default btn-info">{intl l='Close'} <span class="glyphicon glyphicon-remove"></span></a>
</div>
</div>
{form_hidden_fields form=$form}
{form_field form=$form field='success_url'}
<input type="hidden" name="{$name}" value="{url path="/admin/document/type/{$documentType}/{$ID}/update"}" />
{/form_field}
{if $form_error}<div class="alert alert-danger">{$form_error_message}</div>{/if}
<p class="title title-without-tabs">{intl l="Document informations"}</p>
<div class="row">
<div class="col-md-6">
{form_field form=$form field='file'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l="{$label}"} : </label>
<input type="file" id="{$label_attr.for}" name="{$name}" class="form-control" value="" title="{intl l="{$label}"}" placeholder="{intl l='File'}">
</div>
{/form_field}
{form_field form=$form field='title'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l="{$label}"} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$TITLE}" title="{intl l="{$label}"}" placeholder="{intl l='Title'}">
</div>
{/form_field}
{form_field form=$form field='chapo'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l="{$label}"} : </label>
<textarea id="{$label_attr.for}" name="{$name}" class="form-control" title="{intl l="{$label}"}" placeholder="{intl l='Chapo'}">{$CHAPO}</textarea>
</div>
{/form_field}
{form_field form=$form field='postscriptum'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l="{$label}"} : </label>
<textarea id="{$label_attr.for}" name="{$name}" class="form-control" title="{intl l="{$label}"}" placeholder="{intl l='Post Scriptum'}">{$POSTSCRIPTUM}</textarea>
</div>
{/form_field}
</div>
</div>
<div class="row">
<div class="col-md-12">
{form_field form=$form field='description'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l="{$label}"} : </label>
<textarea id="{$label_attr.for}" name="{$name}" class="form-control wysiwyg" title="{intl l="{$label}"}" placeholder="{intl l='Description'}">{$DESCRIPTION}</textarea>
</div>
{/form_field}
</div>
</div>
</form>
{/form}
</div>
</div>
</div>
</div>
</div>
{/loop}
{elseloop rel="document_edit"}
<div class="row">
<div class="col-md-12">
<div class="alert alert-error">
{intl l="Sorry, document ID=$documentId was not found."}
</div>
</div>
</div>
{/elseloop}
</div>
</div>
{/block}
{block name="javascript-initialization"}
{javascripts file='assets/js/main.js'}
<script src="{$asset_url}"></script>
{/javascripts}
<script src="{url file='/tinymce/tinymce.min.js'}"></script>
<script>
tinymce.init({
selector: ".wysiwyg",
theme: "modern",
menubar : false,
language: "",
plugins: [
"advlist autolink link image lists charmap print preview hr anchor pagebreak",
"searchreplace wordcount visualblocks visualchars insertdatetime media nonbreaking",
"table contextmenu directionality emoticons paste textcolor filemanager"
],
toolbar1: "undo redo | bold italic underline | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | styleselect | filemanager | link unlink anchor | image media | forecolor backcolor | print preview code ",
image_advtab: true ,
external_filemanager_path:"{url file='/tinymce/plugins/filemanager/'}'",
filemanager_title:"{intl l='Files manager'}" ,
external_plugins: { "filemanager" : "{url file='/tinymce/plugins/filemanager/plugin.min.js'}"}
});
</script>
{/block}

View File

@@ -250,6 +250,7 @@
</div>
<div class="tab-pane fade" id="documents">
{include file='includes/document-upload-form.html' documentType='folder' parentId=$folder_id}
</div>
<div class="tab-pane fade" id="modules">
@@ -293,9 +294,14 @@
{javascripts file='assets/js/image-upload.js'}
<script src="{$asset_url}"></script>
{/javascripts}
{javascripts file='assets/js/document-upload.js'}
<script src="{$asset_url}"></script>
{/javascripts}
<script>
$(function() {
$.imageUploadManager.initImageDropZone();
$.documentUploadManager.initDocumentDropZone();
$('.use_default_rewriten_url').click(function(ev) {
alert("Not functionnal");

View File

@@ -5,7 +5,7 @@
{block name="check-permissions"}admin.image.edit{/block}
{block name="main-content"}
<div class="customers edit-image">
<div class="documents edit-image">
<div id="wrapper" class="container">

View File

@@ -0,0 +1,36 @@
{*
A generic document upload form
Parameters:
documentType = Document type (category, product, folder, content, module)
parentId = Document parent id, ex: category id
*}
<div class="document-manager" >
<form action="{url path="/admin/document/type/$documentType/$parentId/save-ajax"}" class="dropzone" id="documents-dropzone" enctype="multipart/form-data">
<div class="fallback">
<input name="file" type="file" />
<button type="submit" class="btn btn-info btn-upload"><span class="glyphicon glyphicon-send"></span> {intl l="Send files"}</button>
</div>
<div class="btn-browse hide">
{intl l="Drop files to upload"}
<span>Or</span>
<button type="button" class="btn btn-info btn-upload"><span class="glyphicon glyphicon-upload"></span> {intl l="Browse files"}</button>
</div>
</form>
<div class="existing-document">
{include file='includes/document-upload-list-ajax.html'}
</div>
</div>
<script>
var documentDropZoneUrl = "{url path="/admin/document/type/$documentType/$parentId/save-ajax"}";
var documentListUrl = "{url path="/admin/document/type/$documentType/$parentId/list-ajax"}";
var documentListErrorMessage = "{intl l='Can\'t load documents, please refresh this page.'}";
</script>

View File

@@ -0,0 +1,31 @@
{*
A generic document upload form
Parameters:
documentType = Document type (category, product, folder, content, module)
parentId = Document parent id, ex: category id
*}
{ifloop rel="document"}
<table class="table table-striped table-condensed table-left-aligned">
{loop type="document" name="document" source="{$documentType}" order="manual-reverse" source_id="{$parentId}"}
<tr>
<td>
<a href="{$DOCUMENT_URL}" title="{$TITLE}" class="">{$TITLE}</a>
</td>
<td>
<div class="btn-group">
<a class="document-update-btn btn btn-default btn-xs" href="{url path="/admin/document/type/$documentType/$ID/update"}" data-error-message="{intl l='Please retry'}">
<span class="glyphicon glyphicon-edit"></span>
</a>
<a class="document-delete-btn btn btn-default btn-xs" href="{url path="/admin/document/type/$documentType/delete/$ID"}" data-error-message="{intl l='Please retry'}">
<span class="glyphicon glyphicon-trash"></span>
</a>
</div>
<td>
</tr>
{/loop}
</table>
{/ifloop}