diff --git a/core/lib/Thelia/Action/Document.php b/core/lib/Thelia/Action/Document.php index 86fc51ac5..6b5188ba8 100644 --- a/core/lib/Thelia/Action/Document.php +++ b/core/lib/Thelia/Action/Document.php @@ -25,8 +25,12 @@ namespace Thelia\Action; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +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; @@ -88,45 +92,175 @@ class Document extends BaseCachedFile implements EventSubscriberInterface * * This method updates the cache_file_path and file_url attributes of the event * - * @param DocumentEvent $event - * @throws \InvalidArgumentException, DocumentException + * @param DocumentEvent $event Event + * + * @throws \Thelia\Exception\DocumentException + * @throws \InvalidArgumentException , DocumentException */ public function processDocument(DocumentEvent $event) { $subdir = $event->getCacheSubdirectory(); - $source_file = $event->getSourceFilepath(); + $sourceFile = $event->getSourceFilepath(); - if (null == $subdir || null == $source_file) { + if (null == $subdir || null == $sourceFile) { throw new \InvalidArgumentException("Cache sub-directory and source file path cannot be null"); } - $originalDocumentPathInCache = $this->getCacheFilePath($subdir, $source_file, true); + $originalDocumentPathInCache = $this->getCacheFilePath($subdir, $sourceFile, true); if (! file_exists($originalDocumentPathInCache)) { - if (! file_exists($source_file)) { - throw new DocumentException(sprintf("Source document file %s does not exists.", $source_file)); + if (! file_exists($sourceFile)) { + throw new DocumentException(sprintf("Source document file %s does not exists.", $sourceFile)); } $mode = ConfigQuery::read('original_document_delivery_mode', 'symlink'); if ($mode == 'symlink') { - if (false == symlink($source_file, $originalDocumentPathInCache)) { - throw new DocumentException(sprintf("Failed to create symbolic link for %s in %s document cache directory", basename($source_file), $subdir)); + if (false == symlink($sourceFile, $originalDocumentPathInCache)) { + throw new DocumentException(sprintf("Failed to create symbolic link for %s in %s document cache directory", basename($sourceFile), $subdir)); } - } else {// mode = 'copy' - if (false == @copy($source_file, $originalDocumentPathInCache)) { - throw new DocumentException(sprintf("Failed to copy %s in %s document cache directory", basename($source_file), $subdir)); + } else { + // mode = 'copy' + if (false == @copy($sourceFile, $originalDocumentPathInCache)) { + throw new DocumentException(sprintf("Failed to copy %s in %s document cache directory", basename($sourceFile), $subdir)); } } } // Compute the document URL - $document_url = $this->getCacheFileURL($subdir, basename($originalDocumentPathInCache)); + $documentUrl = $this->getCacheFileURL($subdir, basename($originalDocumentPathInCache)); // Update the event with file path and file URL - $event->setDocumentPath($originalDocumentPathInCache); - $event->setDocumentUrl(URL::getInstance()->absoluteUrl($document_url, null, URL::PATH_TO_FILE)); + $event->setDocumentPath($documentUrl); + $event->setDocumentUrl(URL::getInstance()->absoluteUrl($documentUrl, 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(), FileManager::FILE_TYPE_DOCUMENTS); + $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' + ) + ); + + if (null !== $event->getUploadedFile()) { + $event->getModelDocument()->setTitle($event->getUploadedFile()->getClientOriginalName()); + } + + $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->getParentId(), $event->getDocumentType(), $event->getModelDocument(), $event->getUploadedFile(), FileManager::FILE_TYPE_DOCUMENTS); + $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() @@ -134,6 +268,9 @@ class Document extends BaseCachedFile implements EventSubscriberInterface 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), ); } } diff --git a/core/lib/Thelia/Action/Image.php b/core/lib/Thelia/Action/Image.php index 989c9c516..9de87182b 100755 --- a/core/lib/Thelia/Action/Image.php +++ b/core/lib/Thelia/Action/Image.php @@ -291,7 +291,7 @@ class Image extends BaseCachedFile implements EventSubscriberInterface ); } - $newUploadedFile = $fileManager->copyUploadedFile($event->getParentId(), $event->getImageType(), $event->getModelImage(), $event->getUploadedFile()); + $newUploadedFile = $fileManager->copyUploadedFile($event->getParentId(), $event->getImageType(), $event->getModelImage(), $event->getUploadedFile(), FileManager::FILE_TYPE_IMAGES); $event->setUploadedFile($newUploadedFile); } @@ -321,20 +321,16 @@ class Image extends BaseCachedFile implements EventSubscriberInterface // Copy and save file if ($event->getUploadedFile()) { // Remove old picture file from file storage - $url = $fileManager->getUploadDir($event->getImageType()) . '/' . $event->getOldModelImage()->getFile(); + $url = $fileManager->getUploadDir($event->getImageType(), FileManager::FILE_TYPE_IMAGES) . '/' . $event->getOldModelImage()->getFile(); unlink(str_replace('..', '', $url)); - $newUploadedFile = $fileManager->copyUploadedFile( - $event->getModelImage()->getParentId(), - $event->getImageType(), - $event->getModelImage(), $event->getUploadedFile()); + $newUploadedFile = $fileManager->copyUploadedFile($event->getParentId(), $event->getImageType(), $event->getModelImage(), $event->getUploadedFile(), FileManager::FILE_TYPE_IMAGES); $event->setUploadedFile($newUploadedFile); } // Update image modifications $event->getModelImage()->save(); $event->setModelImage($event->getModelImage()); - } /** @@ -350,7 +346,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 +358,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%)', diff --git a/core/lib/Thelia/Config/Resources/action.xml b/core/lib/Thelia/Config/Resources/action.xml index 15839df95..f153a8de0 100755 --- a/core/lib/Thelia/Config/Resources/action.xml +++ b/core/lib/Thelia/Config/Resources/action.xml @@ -36,6 +36,10 @@ + + + + diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index 623067123..2f06e9606 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -35,6 +35,7 @@ + @@ -59,19 +60,25 @@
+ + + - + + + + diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml index 0d7327e4c..57deb3ae5 100755 --- a/core/lib/Thelia/Config/Resources/routing/admin.xml +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -56,17 +56,50 @@ Thelia\Controller\Admin\FileController::viewImageAction - \d+ + .* + \d+ Thelia\Controller\Admin\FileController::updateImageAction - \d+ + .* + \d+ - Thelia\Controller\Admin\FileController::deleteImagesAction + Thelia\Controller\Admin\FileController::deleteImageAction + .* + \d+ + + + + Thelia\Controller\Admin\FileController::saveDocumentAjaxAction .* \d+ + + Thelia\Controller\Admin\FileController::getDocumentFormAjaxAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::getDocumentListAjaxAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::viewDocumentAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::updateDocumentAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::deleteDocumentAction + .* + \d+ + diff --git a/core/lib/Thelia/Controller/Admin/FileController.php b/core/lib/Thelia/Controller/Admin/FileController.php index e0f469173..f43f30fe6 100755 --- a/core/lib/Thelia/Controller/Admin/FileController.php +++ b/core/lib/Thelia/Controller/Admin/FileController.php @@ -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,72 @@ 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); + } + + $documentModel->setParentId($parentId); + $documentModel->setTitle($fileBeingUploaded->getClientOriginalName()); + + $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 +224,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 +258,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 * @@ -202,14 +291,44 @@ class FileController extends BaseAdminController try { $fileManager = new FileManager($this->container); $image = $fileManager->getImageModelQuery($parentType)->findPk($imageId); - $redirectUrl = $fileManager->getRedirectionUrl($parentType, $image->getParentId()); + $redirectUrl = $fileManager->getRedirectionUrl($parentType, $image->getParentId(), FileManager::FILE_TYPE_IMAGES); return $this->render('image-edit', array( 'imageId' => $imageId, 'imageType' => $parentType, - 'redirectUrl' => $redirectUrl + 'redirectUrl' => $redirectUrl, + 'formId' => $fileManager->getFormId($parentType, FileManager::FILE_TYPE_IMAGES) )); - } 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(), FileManager::FILE_TYPE_DOCUMENTS); + + return $this->render('document-edit', array( + 'documentId' => $documentId, + 'documentType' => $parentType, + 'redirectUrl' => $redirectUrl, + 'formId' => $fileManager->getFormId($parentType, FileManager::FILE_TYPE_DOCUMENTS) + )); + } catch (\Exception $e) { $this->pageNotFound(); } } @@ -237,12 +356,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; @@ -281,21 +400,102 @@ class FileController extends BaseAdminController ->setGeneralError($message); } + $redirectUrl = $fileManager->getRedirectionUrl($parentType, $image->getParentId(), FileManager::FILE_TYPE_IMAGES); + return $this->render('image-edit', array( 'imageId' => $imageId, - 'imageType' => $parentType + 'imageType' => $parentType, + 'redirectUrl' => $redirectUrl, + 'formId' => $fileManager->getFormId($parentType, FileManager::FILE_TYPE_IMAGES) )); } + /** + * Manage how an document is updated + * + * @param int $documentId Parent id owning documents being saved + * @param string $parentType Parent Type owning documents being saved + * + * @return Response + */ + public function updateDocumentAction($documentId, $parentType) + { + if (null !== $response = $this->checkAuth('admin.document.update')) { + return $response; + } + + $message = false; + + $fileManager = new FileManager($this->container); + $documentModification = $fileManager->getDocumentForm($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->createDocumentEventInstance($parentType, $document, $form->getData()); + $event->setOldModelDocument($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->getModelDocument(); + + $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); + } + + $redirectUrl = $fileManager->getRedirectionUrl($parentType, $document->getParentId(), FileManager::FILE_TYPE_DOCUMENTS); + + return $this->render('document-edit', array( + 'documentId' => $documentId, + 'documentType' => $parentType, + 'redirectUrl' => $redirectUrl, + 'formId' => $fileManager->getFormId($parentType, FileManager::FILE_TYPE_DOCUMENTS) + )); + } + /** * Manage how a image has to be deleted (AJAX) * - * @param int $imageId Parent id owning images being saved - * @param string $parentType Parent Type owning images being saved + * @param int $imageId Parent id owning image being deleted + * @param string $parentType Parent Type owning image being deleted * * @return Response */ - public function deleteImagesAction($imageId, $parentType) + public function deleteImageAction($imageId, $parentType) { $this->checkAuth('ADMIN', 'admin.image.delete'); $this->checkXmlHttpRequest(); @@ -330,6 +530,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 +605,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 +617,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 +642,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 DocumentCreateOrUpdateEvent + */ + 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; + } + } diff --git a/core/lib/Thelia/Core/Event/DocumentCreateOrUpdateEvent.php b/core/lib/Thelia/Core/Event/DocumentCreateOrUpdateEvent.php new file mode 100755 index 000000000..81e52257e --- /dev/null +++ b/core/lib/Thelia/Core/Event/DocumentCreateOrUpdateEvent.php @@ -0,0 +1,217 @@ +. */ +/* */ +/*************************************************************************************/ + +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 + * + */ +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->documentType = $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->documentType = $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; + } + + +} diff --git a/core/lib/Thelia/Core/Event/DocumentDeleteEvent.php b/core/lib/Thelia/Core/Event/DocumentDeleteEvent.php new file mode 100755 index 000000000..d9e2b7161 --- /dev/null +++ b/core/lib/Thelia/Core/Event/DocumentDeleteEvent.php @@ -0,0 +1,112 @@ +. */ +/* */ +/*************************************************************************************/ + +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 + * + */ +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->documentToDelete = $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->documentToDelete = $documentToDelete; + + return $this; + } + + /** + * Get Document about to be deleted + * + * @return CategoryDocument|ProductDocument|ContentDocument|FolderDocument + */ + public function getDocumentToDelete() + { + return $this->documentToDelete; + } + + +} diff --git a/core/lib/Thelia/Core/Event/DocumentEvent.php b/core/lib/Thelia/Core/Event/DocumentEvent.php index f58d51083..6248b8d9a 100644 --- a/core/lib/Thelia/Core/Event/DocumentEvent.php +++ b/core/lib/Thelia/Core/Event/DocumentEvent.php @@ -23,43 +23,60 @@ namespace Thelia\Core\Event; +/** + * Class DocumentEvent + * + * @package Thelia\Core\Event + */ class DocumentEvent extends CachedFileEvent { - protected $document_path; - protected $document_url; + protected $documentPath; + protected $documentUrl; /** - * @return the document file path + * Get Document path + * + * @return string The document file path */ public function getDocumentPath() { - return $this->document_path; + return $this->documentPath; } /** - * @param string $document_path the document file path + * Set Document path + * + * @param string $documentPath the document file path + * + * @return $this */ - public function setDocumentPath($document_path) + public function setDocumentPath($documentPath) { - $this->document_path = $document_path; + $this->documentPath = $documentPath; return $this; } /** - * @return the document URL + * Get Document URL + * + * @return string The document URL */ public function getDocumentUrl() { - return $this->document_url; + return $this->documentUrl; } /** - * @param string $document_url the document URL + * Set Document URL + * + * @param string $documentUrl the document URL + * + * @return $this */ - public function setDocumentUrl($document_url) + public function setDocumentUrl($documentUrl) { - $this->document_url = $document_url; + $this->documentUrl = $documentUrl; return $this; } diff --git a/core/lib/Thelia/Core/Event/ImagesCreateOrUpdateEvent.php b/core/lib/Thelia/Core/Event/ImagesCreateOrUpdateEvent.php deleted file mode 100755 index 62c189fc5..000000000 --- a/core/lib/Thelia/Core/Event/ImagesCreateOrUpdateEvent.php +++ /dev/null @@ -1,184 +0,0 @@ -. */ -/* */ -/*************************************************************************************/ - -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 - * - */ -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; - } - - -} diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index faeed50f3..12e42831c 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -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 */ diff --git a/core/lib/Thelia/Core/Template/Loop/Document.php b/core/lib/Thelia/Core/Template/Loop/Document.php index 0e7e979c9..d60aaf7b2 100644 --- a/core/lib/Thelia/Core/Template/Loop/Document.php +++ b/core/lib/Thelia/Core/Template/Loop/Document.php @@ -251,9 +251,9 @@ class Document extends BaseI18nLoop $loopResultRow ->set("ID" , $result->getId()) - ->set("LOCALE" ,$locale) + ->set("LOCALE" , $locale) ->set("DOCUMENT_URL" , $event->getFileUrl()) - ->set("DOCUMENT_PATH" , $event->getCacheFilepath()) + ->set("DOCUMENT_PATH" , $event->getDocumentPath()) ->set("ORIGINAL_DOCUMENT_PATH", $source_filepath) ->set("TITLE" , $result->getVirtualColumn('i18n_TITLE')) ->set("CHAPO" , $result->getVirtualColumn('i18n_CHAPO')) diff --git a/core/lib/Thelia/Form/Image/DocumentModification.php b/core/lib/Thelia/Form/Image/DocumentModification.php index 412da0660..39ba559be 100644 --- a/core/lib/Thelia/Form/Image/DocumentModification.php +++ b/core/lib/Thelia/Form/Image/DocumentModification.php @@ -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' ) diff --git a/core/lib/Thelia/Form/Image/ImageModification.php b/core/lib/Thelia/Form/Image/ImageModification.php index 99e12d72c..c4d26378b 100644 --- a/core/lib/Thelia/Form/Image/ImageModification.php +++ b/core/lib/Thelia/Form/Image/ImageModification.php @@ -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' ) diff --git a/core/lib/Thelia/Model/CategoryDocument.php b/core/lib/Thelia/Model/CategoryDocument.php index 5724e2df1..0917ab30c 100755 --- a/core/lib/Thelia/Model/CategoryDocument.php +++ b/core/lib/Thelia/Model/CategoryDocument.php @@ -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(); + } } \ No newline at end of file diff --git a/core/lib/Thelia/Model/ContentDocument.php b/core/lib/Thelia/Model/ContentDocument.php index 8ecf3a3a9..1409b2713 100755 --- a/core/lib/Thelia/Model/ContentDocument.php +++ b/core/lib/Thelia/Model/ContentDocument.php @@ -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(); + } } diff --git a/core/lib/Thelia/Model/FolderDocument.php b/core/lib/Thelia/Model/FolderDocument.php index 0a86995d2..1d84d9e55 100755 --- a/core/lib/Thelia/Model/FolderDocument.php +++ b/core/lib/Thelia/Model/FolderDocument.php @@ -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(); + } } diff --git a/core/lib/Thelia/Model/ProductDocument.php b/core/lib/Thelia/Model/ProductDocument.php index 53515ff3c..b0f8032da 100755 --- a/core/lib/Thelia/Model/ProductDocument.php +++ b/core/lib/Thelia/Model/ProductDocument.php @@ -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(); + } + } diff --git a/core/lib/Thelia/Tests/Tools/FileManagerTest.php b/core/lib/Thelia/Tests/Tools/FileManagerTest.php index 04fa23144..8dce5afcc 100644 --- a/core/lib/Thelia/Tests/Tools/FileManagerTest.php +++ b/core/lib/Thelia/Tests/Tools/FileManagerTest.php @@ -10,11 +10,18 @@ namespace Thelia\Tests\Type; -use Thelia\Core\Event\ImagesCreateOrUpdateEvent; +use Thelia\Core\Event\DocumentCreateOrUpdateEvent; +use Thelia\Core\Event\ImageCreateOrUpdateEvent; +use Thelia\Core\Translation\Translator; use Thelia\Exception\ImageException; use Thelia\Model\Admin; use Thelia\Tools\FileManager; +/** + * Class FileManagerTest + * + * @package Thelia\Tests\Type + */ class FileManagerTest extends \PHPUnit_Framework_TestCase { @@ -93,7 +100,7 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { $newUploadedFiles = array(); - $actual = $fileManager->copyUploadedFile(24, ImagesCreateOrUpdateEvent::TYPE_PRODUCT, $stubProductImage, $stubUploadedFile, $newUploadedFiles); + $actual = $fileManager->copyUploadedFile(24, FileManager::TYPE_PRODUCT, $stubProductImage, $stubUploadedFile, $newUploadedFiles, FileManager::FILE_TYPE_IMAGES); $this->assertCount(1, $actual); } @@ -175,7 +182,7 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { $newUploadedFiles = array(); - $actual = $fileManager->copyUploadedFile(24, ImagesCreateOrUpdateEvent::TYPE_PRODUCT, $stubProductImage, $stubUploadedFile, $newUploadedFiles); + $actual = $fileManager->copyUploadedFile(24, FileManager::TYPE_PRODUCT, $stubProductImage, $stubUploadedFile, $newUploadedFiles, FileManager::FILE_TYPE_DOCUMENTS); } @@ -200,7 +207,7 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { $fileManager = new FileManager($stubContainer); - $event = new ImagesCreateOrUpdateEvent(ImagesCreateOrUpdateEvent::TYPE_PRODUCT, 24); + $event = new ImageCreateOrUpdateEvent(FileManager::TYPE_PRODUCT, 24); $expected = 10; $actual = $fileManager->saveImage($event, $stubProductImage); @@ -208,6 +215,35 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($expected, $actual); } + /** + * @covers Thelia\Tools\FileManager::saveDocument + */ + public function testSaveDocumentProductDocument() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $stubProductDocument = $this->getMockBuilder('\Thelia\Model\ProductDocument') + ->disableOriginalConstructor() + ->getMock(); + $stubProductDocument->expects($this->any()) + ->method('save') + ->will($this->returnValue(10)); + $stubProductDocument->expects($this->any()) + ->method('getFile') + ->will($this->returnValue('file')); + + $fileManager = new FileManager($stubContainer); + + $event = new DocumentCreateOrUpdateEvent(FileManager::TYPE_PRODUCT, 24); + + $expected = 10; + $actual = $fileManager->saveDocument($event, $stubProductDocument); + + $this->assertEquals($expected, $actual); + } + /** * @covers Thelia\Tools\FileManager::saveImage */ @@ -229,7 +265,7 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { $fileManager = new FileManager($stubContainer); - $event = new ImagesCreateOrUpdateEvent(ImagesCreateOrUpdateEvent::TYPE_CATEGORY, 24); + $event = new ImageCreateOrUpdateEvent(FileManager::TYPE_CATEGORY, 24); $expected = 10; $actual = $fileManager->saveImage($event, $stubCategoryImage); @@ -237,6 +273,35 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($expected, $actual); } + /** + * @covers Thelia\Tools\FileManager::saveDocument + */ + public function testSaveDocumentCategoryDocument() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $stubCategoryDocument = $this->getMockBuilder('\Thelia\Model\CategoryDocument') + ->disableOriginalConstructor() + ->getMock(); + $stubCategoryDocument->expects($this->any()) + ->method('save') + ->will($this->returnValue(10)); + $stubCategoryDocument->expects($this->any()) + ->method('getFile') + ->will($this->returnValue('file')); + + $fileManager = new FileManager($stubContainer); + + $event = new DocumentCreateOrUpdateEvent(FileManager::TYPE_CATEGORY, 24); + + $expected = 10; + $actual = $fileManager->saveDocument($event, $stubCategoryDocument); + + $this->assertEquals($expected, $actual); + } + /** * @covers Thelia\Tools\FileManager::saveImage */ @@ -258,7 +323,7 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { $fileManager = new FileManager($stubContainer); - $event = new ImagesCreateOrUpdateEvent(ImagesCreateOrUpdateEvent::TYPE_FOLDER, 24); + $event = new ImageCreateOrUpdateEvent(FileManager::TYPE_FOLDER, 24); $expected = 10; $actual = $fileManager->saveImage($event, $stubFolderImage); @@ -266,6 +331,35 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($expected, $actual); } + /** + * @covers Thelia\Tools\FileManager::saveDocument + */ + public function testSaveDocumentFolderDocument() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $stubFolderDocument = $this->getMockBuilder('\Thelia\Model\FolderDocument') + ->disableOriginalConstructor() + ->getMock(); + $stubFolderDocument->expects($this->any()) + ->method('save') + ->will($this->returnValue(10)); + $stubFolderDocument->expects($this->any()) + ->method('getFile') + ->will($this->returnValue('file')); + + $fileManager = new FileManager($stubContainer); + + $event = new DocumentCreateOrUpdateEvent(FileManager::TYPE_FOLDER, 24); + + $expected = 10; + $actual = $fileManager->saveDocument($event, $stubFolderDocument); + + $this->assertEquals($expected, $actual); + } + /** * @covers Thelia\Tools\FileManager::saveImage */ @@ -287,7 +381,7 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { $fileManager = new FileManager($stubContainer); - $event = new ImagesCreateOrUpdateEvent(ImagesCreateOrUpdateEvent::TYPE_CONTENT, 24); + $event = new ImageCreateOrUpdateEvent(FileManager::TYPE_CONTENT, 24); $expected = 10; $actual = $fileManager->saveImage($event, $stubContentImage); @@ -295,6 +389,35 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($expected, $actual); } + /** + * @covers Thelia\Tools\FileManager::saveDocument + */ + public function testSaveDocumentContentDocument() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $stubContentDocument = $this->getMockBuilder('\Thelia\Model\ContentDocument') + ->disableOriginalConstructor() + ->getMock(); + $stubContentDocument->expects($this->any()) + ->method('save') + ->will($this->returnValue(10)); + $stubContentDocument->expects($this->any()) + ->method('getFile') + ->will($this->returnValue('file')); + + $fileManager = new FileManager($stubContainer); + + $event = new DocumentCreateOrUpdateEvent(FileManager::TYPE_CONTENT, 24); + + $expected = 10; + $actual = $fileManager->saveDocument($event, $stubContentDocument); + + $this->assertEquals($expected, $actual); + } + /** * @covers Thelia\Tools\FileManager::saveImage * @expectedException \Thelia\Exception\ImageException @@ -316,11 +439,37 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { ->method('getFile') ->will($this->returnValue('file')); - $event = new ImagesCreateOrUpdateEvent('bad', 24); + $event = new ImageCreateOrUpdateEvent('bad', 24); $fileManager->saveImage($event, $stubProductImage); } + /** + * @covers Thelia\Tools\FileManager::saveDocument + * @expectedException \Thelia\Model\Exception\InvalidArgumentException + */ + public function testSaveDocumentExceptionDocumentException() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + $fileManager = new FileManager($stubContainer); + + $stubProductDocument = $this->getMockBuilder('\Thelia\Model\ProductDocument') + ->disableOriginalConstructor() + ->getMock(); + $stubProductDocument->expects($this->any()) + ->method('save') + ->will($this->returnValue(10)); + $stubProductDocument->expects($this->any()) + ->method('getFile') + ->will($this->returnValue('file')); + + $event = new DocumentCreateOrUpdateEvent('bad', 24); + + $fileManager->saveDocument($event, $stubProductDocument); + } + /** * @covers Thelia\Tools\FileManager::saveImage * @expectedException \Thelia\Exception\ImageException @@ -342,11 +491,37 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { ->method('getFile') ->will($this->returnValue('file')); - $event = new ImagesCreateOrUpdateEvent(ImagesCreateOrUpdateEvent::TYPE_PRODUCT, 24); + $event = new ImageCreateOrUpdateEvent(FileManager::TYPE_PRODUCT, 24); $fileManager->saveImage($event, $stubProductImage); } + /** + * @covers Thelia\Tools\FileManager::saveDocument + * @expectedException \Thelia\Model\Exception\InvalidArgumentException + */ + public function testSaveDocumentExceptionDocumentException2() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + $fileManager = new FileManager($stubContainer); + + $stubProductDocument = $this->getMockBuilder('\Thelia\Model\ProductDocument') + ->disableOriginalConstructor() + ->getMock(); + $stubProductDocument->expects($this->any()) + ->method('save') + ->will($this->returnValue(0)); + $stubProductDocument->expects($this->any()) + ->method('getFile') + ->will($this->returnValue('file')); + + $event = new DocumentCreateOrUpdateEvent(FileManager::TYPE_PRODUCT, 24); + + $fileManager->saveDocument($event, $stubProductDocument); + } + /** * @covers Thelia\Tools\FileManager::sanitizeFileName */ @@ -365,6 +540,349 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($expected, $actual); } + /** + * @covers Thelia\Tools\FileManager::getImageModel + */ + public function testGetImageModel() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $fileManager = new FileManager($stubContainer); + $actual = $fileManager->getImageModel(FileManager::TYPE_PRODUCT); + $this->assertInstanceOf('\Thelia\Model\ProductImage', $actual); + $actual = $fileManager->getImageModel(FileManager::TYPE_CATEGORY); + $this->assertInstanceOf('\Thelia\Model\CategoryImage', $actual); + $actual = $fileManager->getImageModel(FileManager::TYPE_CONTENT); + $this->assertInstanceOf('\Thelia\Model\ContentImage', $actual); + $actual = $fileManager->getImageModel(FileManager::TYPE_FOLDER); + $this->assertInstanceOf('\Thelia\Model\FolderImage', $actual); + $actual = $fileManager->getImageModel('bad'); + $this->assertNull($actual); + } + + /** + * @covers Thelia\Tools\FileManager::getDocumentModel + */ + public function testGetDocumentModel() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $fileManager = new FileManager($stubContainer); + $actual = $fileManager->getDocumentModel(FileManager::TYPE_PRODUCT); + $this->assertInstanceOf('\Thelia\Model\ProductDocument', $actual); + $actual = $fileManager->getDocumentModel(FileManager::TYPE_CATEGORY); + $this->assertInstanceOf('\Thelia\Model\CategoryDocument', $actual); + $actual = $fileManager->getDocumentModel(FileManager::TYPE_CONTENT); + $this->assertInstanceOf('\Thelia\Model\ContentDocument', $actual); + $actual = $fileManager->getDocumentModel(FileManager::TYPE_FOLDER); + $this->assertInstanceOf('\Thelia\Model\FolderDocument', $actual); + $actual = $fileManager->getDocumentModel('bad'); + $this->assertNull($actual); + } + + /** + * @covers Thelia\Tools\FileManager::getImageModelQuery + */ + public function testGetImageModelQuery() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $fileManager = new FileManager($stubContainer); + $actual = $fileManager->getImageModelQuery(FileManager::TYPE_PRODUCT); + $this->assertInstanceOf('\Thelia\Model\ProductImageQuery', $actual); + $actual = $fileManager->getImageModelQuery(FileManager::TYPE_CATEGORY); + $this->assertInstanceOf('\Thelia\Model\CategoryImageQuery', $actual); + $actual = $fileManager->getImageModelQuery(FileManager::TYPE_CONTENT); + $this->assertInstanceOf('\Thelia\Model\ContentImageQuery', $actual); + $actual = $fileManager->getImageModelQuery(FileManager::TYPE_FOLDER); + $this->assertInstanceOf('\Thelia\Model\FolderImageQuery', $actual); + $actual = $fileManager->getImageModelQuery('bad'); + $this->assertNull($actual); + } + + /** + * @covers Thelia\Tools\FileManager::getDocumentModelQuery + */ + public function testGetDocumentModelQuery() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $fileManager = new FileManager($stubContainer); + $actual = $fileManager->getDocumentModelQuery(FileManager::TYPE_PRODUCT); + $this->assertInstanceOf('\Thelia\Model\ProductDocumentQuery', $actual); + $actual = $fileManager->getDocumentModelQuery(FileManager::TYPE_CATEGORY); + $this->assertInstanceOf('\Thelia\Model\CategoryDocumentQuery', $actual); + $actual = $fileManager->getDocumentModelQuery(FileManager::TYPE_CONTENT); + $this->assertInstanceOf('\Thelia\Model\ContentDocumentQuery', $actual); + $actual = $fileManager->getDocumentModelQuery(FileManager::TYPE_FOLDER); + $this->assertInstanceOf('\Thelia\Model\FolderDocumentQuery', $actual); + $actual = $fileManager->getDocumentModelQuery('bad'); + $this->assertNull($actual); + } + + /** + * @covers Thelia\Tools\FileManager::getParentFileModel + */ + public function testGetParentFileModel() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $fileManager = new FileManager($stubContainer); + $actual = $fileManager->getParentFileModel(FileManager::TYPE_PRODUCT, 1); + $this->assertInstanceOf('\Thelia\Model\Product', $actual); + $actual = $fileManager->getParentFileModel(FileManager::TYPE_CATEGORY, 1); + $this->assertInstanceOf('\Thelia\Model\Category', $actual); + $actual = $fileManager->getParentFileModel(FileManager::TYPE_CONTENT, 1); + $this->assertInstanceOf('\Thelia\Model\Content', $actual); + $actual = $fileManager->getParentFileModel(FileManager::TYPE_FOLDER, 1); + $this->assertInstanceOf('\Thelia\Model\Folder', $actual, 1); + $actual = $fileManager->getParentFileModel('bad', 1); + $this->assertNull($actual); + } + + /** + * @covers Thelia\Tools\FileManager::getImageForm + */ + public function testGetImageForm() + { + // Mock issue + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } + /** + * @covers Thelia\Tools\FileManager::getDocumentForm + */ + public function testGetDocumentForm() + { + // Mock issue + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } + + /** + * @covers Thelia\Tools\FileManager::getUploadDir + */ + public function testGetUploadDir() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $fileManager = new FileManager($stubContainer); + + $actual = $fileManager->getUploadDir(FileManager::TYPE_PRODUCT, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals(THELIA_LOCAL_DIR . 'media/images/product', $actual); + $actual = $fileManager->getUploadDir(FileManager::TYPE_CATEGORY, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals(THELIA_LOCAL_DIR . 'media/images/category', $actual); + $actual = $fileManager->getUploadDir(FileManager::TYPE_CONTENT, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals(THELIA_LOCAL_DIR . 'media/images/content', $actual); + $actual = $fileManager->getUploadDir(FileManager::TYPE_FOLDER, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals(THELIA_LOCAL_DIR . 'media/images/folder', $actual); + $actual = $fileManager->getUploadDir('bad', FileManager::FILE_TYPE_IMAGES); + $this->assertEquals(false, $actual); + + $actual = $fileManager->getUploadDir(FileManager::TYPE_PRODUCT, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals(THELIA_LOCAL_DIR . 'media/documents/product', $actual); + $actual = $fileManager->getUploadDir(FileManager::TYPE_CATEGORY, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals(THELIA_LOCAL_DIR . 'media/documents/category', $actual); + $actual = $fileManager->getUploadDir(FileManager::TYPE_CONTENT, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals(THELIA_LOCAL_DIR . 'media/documents/content', $actual); + $actual = $fileManager->getUploadDir(FileManager::TYPE_FOLDER, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals(THELIA_LOCAL_DIR . 'media/documents/folder', $actual); + $actual = $fileManager->getUploadDir('bad', FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals(false, $actual); + + $actual = $fileManager->getUploadDir(FileManager::TYPE_FOLDER, 'bad'); + $this->assertEquals(false, $actual); + } + + /** + * @covers Thelia\Tools\FileManager::getRedirectionUrl + */ + public function testGetRedirectionUrl() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $fileManager = new FileManager($stubContainer); + + $actual = $fileManager->getRedirectionUrl(FileManager::TYPE_PRODUCT, 1, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals('/admin/products/update?product_id=1¤t_tab=images', $actual); + $actual = $fileManager->getRedirectionUrl(FileManager::TYPE_CATEGORY, 1, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals('/admin/categories/update?category_id=1¤t_tab=images', $actual); + $actual = $fileManager->getRedirectionUrl(FileManager::TYPE_CONTENT, 1, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals('/admin/content/update/1?current_tab=images', $actual); + $actual = $fileManager->getRedirectionUrl(FileManager::TYPE_FOLDER, 1, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals('/admin/folders/update/1?current_tab=images', $actual); + $actual = $fileManager->getRedirectionUrl('bad', 1, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals(false, $actual); + + $actual = $fileManager->getRedirectionUrl(FileManager::TYPE_PRODUCT, 1, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals('/admin/products/update?product_id=1¤t_tab=documents', $actual); + $actual = $fileManager->getRedirectionUrl(FileManager::TYPE_CATEGORY, 1, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals('/admin/categories/update?category_id=1¤t_tab=documents', $actual); + $actual = $fileManager->getRedirectionUrl(FileManager::TYPE_CONTENT, 1, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals('/admin/content/update/1?current_tab=documents', $actual); + $actual = $fileManager->getRedirectionUrl(FileManager::TYPE_FOLDER, 1, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals('/admin/folders/update/1?current_tab=documents', $actual); + $actual = $fileManager->getRedirectionUrl('bad', 1, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals(false, $actual); + + $actual = $fileManager->getRedirectionUrl(FileManager::TYPE_FOLDER, 1, 'bad'); + $this->assertEquals(false, $actual); + } + + + /** + * @covers Thelia\Tools\FileManager::getFormId + */ + public function testGetFormId() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $fileManager = new FileManager($stubContainer); + + $actual = $fileManager->getFormId(FileManager::TYPE_PRODUCT, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals('thelia.admin.product.image.modification', $actual); + $actual = $fileManager->getFormId(FileManager::TYPE_CATEGORY, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals('thelia.admin.category.image.modification', $actual); + $actual = $fileManager->getFormId(FileManager::TYPE_CONTENT, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals('thelia.admin.content.image.modification', $actual); + $actual = $fileManager->getFormId(FileManager::TYPE_FOLDER, FileManager::FILE_TYPE_IMAGES); + $this->assertEquals('thelia.admin.folder.image.modification', $actual); + $actual = $fileManager->getFormId('bad', FileManager::FILE_TYPE_IMAGES); + $this->assertEquals(false, $actual); + + $actual = $fileManager->getFormId(FileManager::TYPE_PRODUCT, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals('thelia.admin.product.document.modification', $actual); + $actual = $fileManager->getFormId(FileManager::TYPE_CATEGORY, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals('thelia.admin.category.document.modification', $actual); + $actual = $fileManager->getFormId(FileManager::TYPE_CONTENT, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals('thelia.admin.content.document.modification', $actual); + $actual = $fileManager->getFormId(FileManager::TYPE_FOLDER, FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals('thelia.admin.folder.document.modification', $actual); + $actual = $fileManager->getFormId('bad', FileManager::FILE_TYPE_DOCUMENTS); + $this->assertEquals(false, $actual); + } + + /** + * @covers Thelia\Tools\FileManager::renameFile + */ + public function testRenameFile() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $stubUploadedFile = $this->getMockBuilder('\Symfony\Component\HttpFoundation\File\UploadedFile') + ->disableOriginalConstructor() + ->getMock(); + $stubUploadedFile->expects($this->any()) + ->method('getClientOriginalExtension') + ->will($this->returnValue('yml')); + $stubUploadedFile->expects($this->any()) + ->method('getClientOriginalName') + ->will($this->returnValue('or1-g_n?al*/&é"filen@me#')); + + + $fileManager = new FileManager($stubContainer); + + $expected = 'or1-g_nalyfilenme-1.yml'; + $actual = $fileManager->renameFile(1, $stubUploadedFile); + + $this->assertEquals($expected, $actual); + } + + /** + * @covers Thelia\Tools\FileManager::renameFile + */ + public function testRenameFileWithoutExtension() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $stubUploadedFile = $this->getMockBuilder('\Symfony\Component\HttpFoundation\File\UploadedFile') + ->disableOriginalConstructor() + ->getMock(); + $stubUploadedFile->expects($this->any()) + ->method('getClientOriginalExtension') + ->will($this->returnValue('')); + $stubUploadedFile->expects($this->any()) + ->method('getClientOriginalName') + ->will($this->returnValue('or1-g_n?al*/&é"filen@me#')); + + + $fileManager = new FileManager($stubContainer); + + $expected = 'or1-g_nalyfilenme-1'; + $actual = $fileManager->renameFile(1, $stubUploadedFile); + + $this->assertEquals($expected, $actual); + } + + /** + * @covers Thelia\Tools\FileManager::isImage + */ + public function testIsImage() + { + $stubContainer = $this->getMockBuilder('\Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $fileManager = new FileManager($stubContainer); + + $actual = $fileManager->isImage('image/jpeg'); + $this->assertTrue($actual); + $actual = $fileManager->isImage('image/png'); + $this->assertTrue($actual); + $actual = $fileManager->isImage('image/gif'); + $this->assertTrue($actual); + + $actual = $fileManager->isImage('bad'); + $this->assertFalse($actual); + $actual = $fileManager->isImage('image/jpg'); + $this->assertFalse($actual); + $actual = $fileManager->isImage('application/x-msdownload'); + $this->assertFalse($actual); + $actual = $fileManager->isImage('application/x-sh'); + $this->assertFalse($actual); + + } + + + /** + * @covers Thelia\Tools\FileManager::getAvailableTypes + */ + public function testGetAvailableTypes() + { + $expected = array( + FileManager::TYPE_CATEGORY, + FileManager::TYPE_CONTENT, + FileManager::TYPE_FOLDER, + FileManager::TYPE_PRODUCT, + FileManager::TYPE_MODULE, + ); + $actual = FileManager::getAvailableTypes(); + + $this->assertEquals($expected, $actual); + } + /** * @covers Thelia\Tools\FileManager::adminLogAppend */ @@ -374,4 +892,15 @@ class FileManagerTest extends \PHPUnit_Framework_TestCase { 'This test has not been implemented yet.' ); } + + /** + * @covers Thelia\Tools\FileManager::deleteFile + */ + public function testDeleteFile() + { + // @todo see http://tech.vg.no/2011/03/09/mocking-the-file-system-using-phpunit-and-vfsstream/ + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } } diff --git a/core/lib/Thelia/Tools/FileManager.php b/core/lib/Thelia/Tools/FileManager.php index e18ef58d0..6c06fb416 100644 --- a/core/lib/Thelia/Tools/FileManager.php +++ b/core/lib/Thelia/Tools/FileManager.php @@ -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; @@ -85,42 +102,46 @@ 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 UploadedFile $uploadedFile Ready to be uploaded file + * @param int $parentId Parent id + * @param string $parentType Image type + * @param FolderImage|ContentImage|CategoryImage|ProductImage|FolderDocument|ContentDocument|CategoryDocument|ProductDocument $model Model saved + * @param UploadedFile $uploadedFile Ready to be uploaded file + * @param string $fileType File type ex FileManager::FILE_TYPE_IMAGES * * @throws \Thelia\Exception\ImageException * @return UploadedFile */ - public function copyUploadedFile($parentId, $imageType, $modelImage, $uploadedFile) + public function copyUploadedFile($parentId, $parentType, $model, $uploadedFile, $fileType) { + $newUploadedFile = null; if ($uploadedFile !== null) { - $directory = $this->getUploadDir($imageType); - $fileName = $this->renameFile($modelImage->getId(), $uploadedFile); + $directory = $this->getUploadDir($parentType, $fileType); + $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%' => $parentType ), '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($parentType), + $model->getFile(), + $fileType ) ); } @@ -132,32 +153,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 +188,7 @@ class FileManager 'Picture parent type is unknown (available types : %s)', implode( ',', - $event->getAvailableType() + self::getAvailableTypes() ) ) ); @@ -187,6 +208,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,21 +305,24 @@ class FileManager /** * Delete image from file storage and database * - * @param CategoryImage|ProductImage|ContentImage|FolderImage $imageModel Image being deleted - * @param string $parentType Parent type + * @param CategoryImage|ProductImage|ContentImage|FolderImage|CategoryDocument|ProductDocument|ContentDocument|FolderDocument $model File being deleted + * @param string $parentType Parent type ex : self::TYPE_PRODUCT + * @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(); } /** * Get image model from type * - * @param string $parentType Parent type + * @param string $parentType Parent type ex : self::TYPE_PRODUCT * * @return null|\Thelia\Model\CategoryImage|\Thelia\Model\ContentImage|\Thelia\Model\FolderImage|\Thelia\Model\ProductImage * @@ -249,16 +331,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,10 +350,41 @@ class FileManager return $model; } + /** + * Get document model from type + * + * @param string $parentType Parent type ex : self::TYPE_PRODUCT + * + * @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 * - * @param string $parentType + * @param string $parentType Parent type ex : self::TYPE_PRODUCT * * @return null|\Thelia\Model\CategoryImageQuery|\Thelia\Model\ContentImageQuery|\Thelia\Model\FolderImageQuery|\Thelia\Model\ProductImageQuery * @@ -280,16 +393,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,29 +412,103 @@ class FileManager return $model; } + /** + * Get document model query from type + * + * @param string $parentType Parent type ex : self::TYPE_PRODUCT + * + * @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 form service id from type + * + * @param string $parentType Parent type ex : self::TYPE_PRODUCT + * @param string $fileType Parent id + * + * @return string + * + * @todo refactor make all documents using propel inheritance and factorise image behaviour into one single clean action + */ + public function getFormId($parentType, $fileType) + { + switch ($fileType) { + case self::FILE_TYPE_IMAGES: + $type = 'image'; + break; + case self::FILE_TYPE_DOCUMENTS: + $type = 'document'; + break; + default: + return false; + } + + switch ($parentType) { + case self::TYPE_PRODUCT: + $formId = 'thelia.admin.product.' . $type . '.modification'; + break; + case self::TYPE_CATEGORY: + $formId = 'thelia.admin.category.' . $type . '.modification'; + break; + case self::TYPE_CONTENT: + $formId = 'thelia.admin.content.' . $type . '.modification'; + break; + case self::TYPE_FOLDER: + $formId = 'thelia.admin.folder.' . $type . '.modification'; + break; + default: + $formId = false; + } + + return $formId; + } + /** * Get image parent model from type * - * @param string $parentType - * @param int $parentId + * @param string $parentType Parent type ex : self::TYPE_PRODUCT + * @param int $parentId Parent Id * * @return null|\Thelia\Model\Category|\Thelia\Model\Content|\Thelia\Model\Folder|\Thelia\Model\Product * * @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: @@ -334,7 +521,7 @@ class FileManager /** * Get image parent model from type * - * @param string $parentType Parent type + * @param string $parentType Parent type ex : self::TYPE_PRODUCT * @param Request $request Request service * * @todo refactor make all pictures using propel inheritance and factorise image behaviour into one single clean action @@ -343,20 +530,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 ex : self::TYPE_PRODUCT + * @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,54 +585,29 @@ 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 ex : self::FILE_TYPE_DOCUMENTS * * @return string Uri */ - public function getUploadDir($parentType) + public function getUploadDir($parentType, $fileType) { - switch ($parentType) { - case ImagesCreateOrUpdateEvent::TYPE_PRODUCT: - $uri = THELIA_LOCAL_DIR . 'media/images/' . ImagesCreateOrUpdateEvent::TYPE_PRODUCT; - break; - case ImagesCreateOrUpdateEvent::TYPE_CATEGORY: - $uri = THELIA_LOCAL_DIR . 'media/images/' . ImagesCreateOrUpdateEvent::TYPE_CATEGORY; - break; - case ImagesCreateOrUpdateEvent::TYPE_CONTENT: - $uri = THELIA_LOCAL_DIR . 'media/images/' . ImagesCreateOrUpdateEvent::TYPE_CONTENT; - break; - case ImagesCreateOrUpdateEvent::TYPE_FOLDER: - $uri = THELIA_LOCAL_DIR . 'media/images/' . ImagesCreateOrUpdateEvent::TYPE_FOLDER; - break; - default: - $uri = null; + if (!in_array($fileType, self::$availableFileType)) { + return false; } - return $uri; - - } - - /** - * Deduce image redirecting URL from parent type - * - * @param string $parentType Parent type - * @param int $parentId Parent id - * @return string - */ - public function getRedirectionUrl($parentType, $parentId) - { switch ($parentType) { - case ImagesCreateOrUpdateEvent::TYPE_PRODUCT: - $uri = '/admin/products/update?product_id=' . $parentId . '¤t_tab=images'; + case self::TYPE_PRODUCT: + $uri = THELIA_LOCAL_DIR . 'media/' . $fileType . '/' . self::TYPE_PRODUCT; break; - case ImagesCreateOrUpdateEvent::TYPE_CATEGORY: - $uri = '/admin/categories/update?category_id=' . $parentId . '¤t_tab=images'; + case self::TYPE_CATEGORY: + $uri = THELIA_LOCAL_DIR . 'media/' . $fileType . '/' . self::TYPE_CATEGORY; break; - case ImagesCreateOrUpdateEvent::TYPE_CONTENT: - $uri = '/admin/content/update/' . $parentId . '¤t_tab=images'; + case self::TYPE_CONTENT: + $uri = THELIA_LOCAL_DIR . 'media/' . $fileType . '/' . self::TYPE_CONTENT; break; - case ImagesCreateOrUpdateEvent::TYPE_FOLDER: - $uri = '/admin/folders/update/' . $parentId . '¤t_tab=images'; + case self::TYPE_FOLDER: + $uri = THELIA_LOCAL_DIR . 'media/' . $fileType . '/' . self::TYPE_FOLDER; break; default: $uri = false; @@ -423,7 +617,43 @@ class FileManager } - /** @var array Available image parent type */ + /** + * Deduce image redirecting URL from parent type + * + * @param string $parentType Parent type ex : self::TYPE_PRODUCT + * @param int $parentId Parent id + * @param string $fileType File type ex : self::FILE_TYPE_DOCUMENTS + * + * @return string + */ + public function getRedirectionUrl($parentType, $parentId, $fileType) + { + if (!in_array($fileType, self::$availableFileType)) { + return false; + } + + switch ($parentType) { + case self::TYPE_PRODUCT: + $uri = '/admin/products/update?product_id=' . $parentId . '¤t_tab=' . $fileType; + break; + case self::TYPE_CATEGORY: + $uri = '/admin/categories/update?category_id=' . $parentId . '¤t_tab=' . $fileType; + break; + case self::TYPE_CONTENT: + $uri = '/admin/content/update/' . $parentId . '?current_tab=' . $fileType; + break; + case self::TYPE_FOLDER: + $uri = '/admin/folders/update/' . $parentId . '?current_tab=' . $fileType; + break; + default: + $uri = false; + } + + return $uri; + + } + + /** @var array Available file parent type */ public static $availableType = array( self::TYPE_PRODUCT, self::TYPE_CATEGORY, @@ -432,6 +662,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 * @@ -443,11 +679,17 @@ class FileManager public function renameFile($modelId, $uploadedFile) { $extension = $uploadedFile->getClientOriginalExtension(); + if (!empty($extension)) { + $extension = '.' . strtolower($extension); + } $fileName = $this->sanitizeFileName( - str_replace('.' . $extension, '', $uploadedFile->getClientOriginalName()) . "-" . $modelId . "." . strtolower( - $extension - ) + str_replace( + $extension, + '', + $uploadedFile->getClientOriginalName() + ) . '-' . $modelId . $extension ); + return $fileName; } @@ -470,4 +712,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, + ); + } } \ No newline at end of file diff --git a/templates/admin/default/assets/js/document-upload.js b/templates/admin/default/assets/js/document-upload.js new file mode 100644 index 000000000..dc35ea943 --- /dev/null +++ b/templates/admin/default/assets/js/document-upload.js @@ -0,0 +1,100 @@ +$(function($){ + // Manage document upload + $.documentUploadManager = {}; + + Dropzone.autoDiscover = false; + + + + // Remove image on click + $.documentUploadManager.initDocumentDropZone = function() { + $.documentUploadManager.onClickDeleteDocument(); + + 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('
'); + $.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('
'); + 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; + }); + }; +}); diff --git a/templates/admin/default/assets/js/image-upload.js b/templates/admin/default/assets/js/image-upload.js index bd3d12dea..c2ef15ad4 100644 --- a/templates/admin/default/assets/js/image-upload.js +++ b/templates/admin/default/assets/js/image-upload.js @@ -8,6 +8,8 @@ $(function($){ // Remove image on click $.imageUploadManager.initImageDropZone = function() { + $.imageUploadManager.onClickDeleteImage(); + var imageDropzone = new Dropzone("#images-dropzone", { dictDefaultMessage : $('.btn-browse').html(), uploadMultiple: false, @@ -96,5 +98,4 @@ $(function($){ return false; }); }; - $.imageUploadManager.onClickDeleteImage(); }); diff --git a/templates/admin/default/category-edit.html b/templates/admin/default/category-edit.html index b7e1d9ed9..f8b564822 100755 --- a/templates/admin/default/category-edit.html +++ b/templates/admin/default/category-edit.html @@ -260,6 +260,7 @@
+ {include file='includes/document-upload-form.html' documentType='category' parentId=$category_id}
@@ -303,6 +304,9 @@ {javascripts file='assets/js/image-upload.js'} {/javascripts} + {javascripts file='assets/js/document-upload.js'} + + {/javascripts} @@ -327,6 +331,7 @@ $(function() { $.imageUploadManager.initImageDropZone(); + $.documentUploadManager.initDocumentDropZone(); $('.use_default_rewriten_url').click(function(ev) { alert("Not functionnal"); diff --git a/templates/admin/default/content-edit.html b/templates/admin/default/content-edit.html index f4eb063cf..c891897cc 100644 --- a/templates/admin/default/content-edit.html +++ b/templates/admin/default/content-edit.html @@ -250,6 +250,7 @@
+ {include file='includes/document-upload-form.html' documentType='content' parentId=$content_id}
@@ -293,10 +294,14 @@ form_content = {$smarty.capture.delete_content_dialog nofilter} {javascripts file='assets/js/image-upload.js'} {/javascripts} + {javascripts file='assets/js/document-upload.js'} + + {/javascripts} + {/javascripts} + + + + +{/block} \ No newline at end of file diff --git a/templates/admin/default/folder-edit.html b/templates/admin/default/folder-edit.html index 7e5021d6e..bac087096 100644 --- a/templates/admin/default/folder-edit.html +++ b/templates/admin/default/folder-edit.html @@ -250,6 +250,7 @@
+ {include file='includes/document-upload-form.html' documentType='folder' parentId=$folder_id}
@@ -293,9 +294,14 @@ {javascripts file='assets/js/image-upload.js'} {/javascripts} + {javascripts file='assets/js/document-upload.js'} + + {/javascripts} + diff --git a/templates/admin/default/includes/document-upload-list-ajax.html b/templates/admin/default/includes/document-upload-list-ajax.html new file mode 100644 index 000000000..1233e06a8 --- /dev/null +++ b/templates/admin/default/includes/document-upload-list-ajax.html @@ -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"} + + {loop type="document" name="document" source="{$documentType}" order="manual-reverse" source_id="{$parentId}"} + + + + {/loop} +
+ {$TITLE} + + + +
+{/ifloop} diff --git a/templates/admin/default/includes/image-upload-list-ajax.html b/templates/admin/default/includes/image-upload-list-ajax.html index 5a9f60aef..a0bebd722 100644 --- a/templates/admin/default/includes/image-upload-list-ajax.html +++ b/templates/admin/default/includes/image-upload-list-ajax.html @@ -13,7 +13,9 @@ Parameters: {loop type="image" name="image" source="{$imageType}" order="manual-reverse" source_id="{$parentId}" width="200" height="100" resize_mode="borders"} - {$TITLE} + + {$TITLE} +
diff --git a/templates/admin/default/product-edit.html b/templates/admin/default/product-edit.html index 38f1a03e8..2e3ef3615 100644 --- a/templates/admin/default/product-edit.html +++ b/templates/admin/default/product-edit.html @@ -70,7 +70,13 @@ {intl l="Images"} -
  • {intl l="Documents"}
  • +
  • + + {intl l="Documents"} +
  • {intl l="Modules"}
  • @@ -122,6 +128,9 @@ {javascripts file='assets/js/image-upload.js'} {/javascripts} + {javascripts file='assets/js/document-upload.js'} + + {/javascripts} {javascripts file='assets/js/bootstrap-editable/bootstrap-editable.js'} {/javascripts} diff --git a/tests/functionnal/casperjs/exe/00_parameters.js b/tests/functionnal/casperjs/exe/00_parameters.js index df5470229..813f73c32 100644 --- a/tests/functionnal/casperjs/exe/00_parameters.js +++ b/tests/functionnal/casperjs/exe/00_parameters.js @@ -9,6 +9,13 @@ var thelia2_login_coupon_update_url = thelia2_base_url + 'admin/coupon/update/1' +var thelia2_category_image_list_url = thelia2_base_url + 'admin/categories/update?category_id=1'; +var thelia2_product_image_list_url = thelia2_base_url + 'admin/products/update?product_id=1'; +var thelia2_folder_image_list_url = thelia2_base_url + 'admin/folders/update/1'; +var thelia2_content_image_list_url = thelia2_base_url + 'admin/content/update/1'; + + + //var findMyId = /([0-9]+)$/; //var currentId; diff --git a/tests/functionnal/casperjs/exe/30_coupons.js b/tests/functionnal/casperjs/exe/30_coupons.js index 2147c14cf..073ccbb08 100644 --- a/tests/functionnal/casperjs/exe/30_coupons.js +++ b/tests/functionnal/casperjs/exe/30_coupons.js @@ -12,145 +12,145 @@ casper.test.comment('Testing coupons'); ////LIST -// @todo implement - -////CREATE -casper.start(thelia2_login_coupon_create_url, function() { - this.test.assertHttpStatus(200); - this.test.comment('Now on : ' + this.getCurrentUrl()); - this.capture('tests/functionnal/casperjs/screenshot/coupons/init.png'); - this.test.comment('COUPON - CREATE EMPTY'); - - // Click on is unlimited button - this.click("form #is-unlimited"); - this.sendKeys('input#max-usage', '-2'); - - // cleaning expiration date default value - this.evaluate(function() { - $("#expiration-date").val('').change(); - return true; - }); - - this.capture('tests/functionnal/casperjs/screenshot/coupons/creating-new-coupon.png'); - this.click("form .control-group .btn.btn-default.btn-primary"); - -}); - -casper.wait(1000, function() { - this.echo("\nWaiting...."); -}); - -// Test Coupon creation if no input -casper.then(function(){ - this.test.assertHttpStatus(200); - this.capture('tests/functionnal/casperjs/screenshot/coupons/created-new-empty-coupon.png'); - this.test.assertExists('.has-error #code', 'Error on code input found'); - this.test.assertExists('.has-error #title', 'Error on title input found'); - - this.test.assertExists('.has-error #expiration-date', 'Error on expiration date input found'); - this.test.assertExists('.has-error #max-usage', 'Error on max usage input found'); - this.test.assertExists('.has-error #description', 'Error on description input found'); - this.test.assertExists('.has-error #effect', 'Error on effect input found'); - this.test.assertExists('.has-error #amount', 'Error on amount input found'); - this.test.assertExists('.has-error #short-description', 'Error on short-description input found'); -}); - -// Test Coupon creation if good input -casper.then(function(){ - - this.sendKeys('input#code', 'XMAS10'); - this.sendKeys('input#title', 'christmas'); - this.click("form #is-enabled"); - this.click("form #is-available-on-special-offers"); - this.click("form #is-cumulative"); - this.click("form #is-removing-postage"); - - this.evaluate(function() { - $("#expiration-date").val('2013-11-14').change(); - return true; - }); - - // Click on is unlimited button - this.click("form #is-unlimited"); - this.sendKeys('input#max-usage', '40'); - - this.evaluate(function() { - $('#effect').val('thelia.coupon.type.remove_x_amount').change(); - return true; - }); - - this.test.assertSelectorHasText( - '#effectToolTip', - this.evaluate(function () { - return $("#effect option[value^='thelia.coupon.type.remove_x_amount']").attr('data-description'); - }), - 'Tooltip found' - ); - this.sendKeys('input#amount', '42.12'); - this.sendKeys('#short-description', 'Mauris sed risus imperdiet, blandit arcu ac, tempus metus. Aliquam erat volutpat. Nullam dictum sed.'); - this.sendKeys('#description', 'Etiam sodales non nisi a condimentum. Morbi luctus mauris mattis sem ornare; ac blandit tortor porta! Sed vel viverra dolor. Nulla eget viverra eros. Donec rutrum felis ut quam blandit, eu massa nunc.'); - - this.capture('tests/functionnal/casperjs/screenshot/coupons/coupon-created-ready-to-be-saved.png'); - this.click("#save-coupon-btn"); -}); - -casper.wait(2000, function() { - this.echo("\nWaiting...."); -}); - -// Test Coupon creation if good input is well saved -casper.then(function(){ - this.test.assertHttpStatus(302); - this.test.comment('Now on : ' + this.getCurrentUrl()); - this.capture('tests/functionnal/casperjs/screenshot/coupons/created-new-coupon.png'); - this.test.assertField('thelia_coupon_creation[code]', 'XMAS10', 'Code found'); - this.test.assertField('thelia_coupon_creation[title]', 'christmas', 'Title found'); - - this.test.assert(this.evaluate(function () { - return document.getElementById('is-enabled').checked; - }), 'Checkbox is enabled checked'); - this.test.assert(this.evaluate(function () { - return document.getElementById('is-available-on-special-offers').checked; - }), 'Checkbox is available on special offers checked'); - this.test.assert(this.evaluate(function () { - return document.getElementById('is-cumulative').checked; - }), 'Checkbox is cumulative checked'); - this.test.assert(this.evaluate(function () { - return document.getElementById('is-removing-postage').checked; - }), 'Checkbox is cumulative checked'); - - this.test.assertField('thelia_coupon_creation[expirationDate]', '2013-11-14', 'Expiration date found'); - this.test.assertField('thelia_coupon_creation[maxUsage]', '40', 'Max usage found'); - this.test.assert(this.evaluate(function () { - return !document.getElementById('is-unlimited').checked; - }), 'Checkbox is unlimited not checked'); - - this.test.assert( - this.evaluate(function () { - return $("#effect").val(); - }), - 'thelia.coupon.type.remove_x_amount', - 'Effect found' - ); - this.test.assertSelectorHasText( - '#effectToolTip', - this.evaluate(function () { - return $("#effect option[value^='thelia.coupon.type.remove_x_amount']").attr('data-description'); - }), - 'Tooltip found' - ); - this.test.assertField('thelia_coupon_creation[amount]', '42.12', 'Amount found'); - - this.test.assertField('thelia_coupon_creation[shortDescription]', 'Mauris sed risus imperdiet, blandit arcu ac, tempus metus. Aliquam erat volutpat. Nullam dictum sed.', 'Short description found'); - this.test.assertField('thelia_coupon_creation[description]', 'Etiam sodales non nisi a condimentum. Morbi luctus mauris mattis sem ornare; ac blandit tortor porta! Sed vel viverra dolor. Nulla eget viverra eros. Donec rutrum felis ut quam blandit, eu massa nunc.', 'Description found'); - - -}); -////EDIT CHECK -// @todo implement - -////DELETE -// @todo implement +////@todo implement +// +//////CREATE +//casper.start(thelia2_login_coupon_create_url, function() { +// this.test.assertHttpStatus(200); +// this.test.comment('Now on : ' + this.getCurrentUrl()); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/init.png'); +// this.test.comment('COUPON - CREATE EMPTY'); +// +// // Click on is unlimited button +// this.click("form #is-unlimited"); +// this.sendKeys('input#max-usage', '-2'); +// +// // cleaning expiration date default value +// this.evaluate(function() { +// $("#expiration-date").val('').change(); +// return true; +// }); +// +// this.capture('tests/functionnal/casperjs/screenshot/coupons/creating-new-coupon.png'); +// this.click("form .control-group .btn.btn-default.btn-primary"); +// +//}); +// +//casper.wait(1000, function() { +// this.echo("\nWaiting...."); +//}); +// +//// Test Coupon creation if no input +//casper.then(function(){ +// this.test.assertHttpStatus(200); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/created-new-empty-coupon.png'); +// this.test.assertExists('.has-error #code', 'Error on code input found'); +// this.test.assertExists('.has-error #title', 'Error on title input found'); +// +// this.test.assertExists('.has-error #expiration-date', 'Error on expiration date input found'); +// this.test.assertExists('.has-error #max-usage', 'Error on max usage input found'); +// this.test.assertExists('.has-error #description', 'Error on description input found'); +// this.test.assertExists('.has-error #effect', 'Error on effect input found'); +// this.test.assertExists('.has-error #amount', 'Error on amount input found'); +// this.test.assertExists('.has-error #short-description', 'Error on short-description input found'); +//}); +// +//// Test Coupon creation if good input +//casper.then(function(){ +// +// this.sendKeys('input#code', 'XMAS10'); +// this.sendKeys('input#title', 'christmas'); +// this.click("form #is-enabled"); +// this.click("form #is-available-on-special-offers"); +// this.click("form #is-cumulative"); +// this.click("form #is-removing-postage"); +// +// this.evaluate(function() { +// $("#expiration-date").val('2013-11-14').change(); +// return true; +// }); +// +// // Click on is unlimited button +// this.click("form #is-unlimited"); +// this.sendKeys('input#max-usage', '40'); +// +// this.evaluate(function() { +// $('#effect').val('thelia.coupon.type.remove_x_amount').change(); +// return true; +// }); +// +// this.test.assertSelectorHasText( +// '#effectToolTip', +// this.evaluate(function () { +// return $("#effect option[value^='thelia.coupon.type.remove_x_amount']").attr('data-description'); +// }), +// 'Tooltip found' +// ); +// this.sendKeys('input#amount', '42.12'); +// this.sendKeys('#short-description', 'Mauris sed risus imperdiet, blandit arcu ac, tempus metus. Aliquam erat volutpat. Nullam dictum sed.'); +// this.sendKeys('#description', 'Etiam sodales non nisi a condimentum. Morbi luctus mauris mattis sem ornare; ac blandit tortor porta! Sed vel viverra dolor. Nulla eget viverra eros. Donec rutrum felis ut quam blandit, eu massa nunc.'); +// +// this.capture('tests/functionnal/casperjs/screenshot/coupons/coupon-created-ready-to-be-saved.png'); +// this.click("#save-coupon-btn"); +//}); +// +//casper.wait(2000, function() { +// this.echo("\nWaiting...."); +//}); +// +//// Test Coupon creation if good input is well saved +//casper.then(function(){ +// this.test.assertHttpStatus(302); +// this.test.comment('Now on : ' + this.getCurrentUrl()); +// this.capture('tests/functionnal/casperjs/screenshot/coupons/created-new-coupon.png'); +// this.test.assertField('thelia_coupon_creation[code]', 'XMAS10', 'Code found'); +// this.test.assertField('thelia_coupon_creation[title]', 'christmas', 'Title found'); +// +// this.test.assert(this.evaluate(function () { +// return document.getElementById('is-enabled').checked; +// }), 'Checkbox is enabled checked'); +// this.test.assert(this.evaluate(function () { +// return document.getElementById('is-available-on-special-offers').checked; +// }), 'Checkbox is available on special offers checked'); +// this.test.assert(this.evaluate(function () { +// return document.getElementById('is-cumulative').checked; +// }), 'Checkbox is cumulative checked'); +// this.test.assert(this.evaluate(function () { +// return document.getElementById('is-removing-postage').checked; +// }), 'Checkbox is cumulative checked'); +// +// this.test.assertField('thelia_coupon_creation[expirationDate]', '2013-11-14', 'Expiration date found'); +// this.test.assertField('thelia_coupon_creation[maxUsage]', '40', 'Max usage found'); +// this.test.assert(this.evaluate(function () { +// return !document.getElementById('is-unlimited').checked; +// }), 'Checkbox is unlimited not checked'); +// +// this.test.assert( +// this.evaluate(function () { +// return $("#effect").val(); +// }), +// 'thelia.coupon.type.remove_x_amount', +// 'Effect found' +// ); +// this.test.assertSelectorHasText( +// '#effectToolTip', +// this.evaluate(function () { +// return $("#effect option[value^='thelia.coupon.type.remove_x_amount']").attr('data-description'); +// }), +// 'Tooltip found' +// ); +// this.test.assertField('thelia_coupon_creation[amount]', '42.12', 'Amount found'); +// +// this.test.assertField('thelia_coupon_creation[shortDescription]', 'Mauris sed risus imperdiet, blandit arcu ac, tempus metus. Aliquam erat volutpat. Nullam dictum sed.', 'Short description found'); +// this.test.assertField('thelia_coupon_creation[description]', 'Etiam sodales non nisi a condimentum. Morbi luctus mauris mattis sem ornare; ac blandit tortor porta! Sed vel viverra dolor. Nulla eget viverra eros. Donec rutrum felis ut quam blandit, eu massa nunc.', 'Description found'); +// +// +//}); +//////EDIT CHECK +//// @todo implement +// +//////DELETE +//// @todo implement //RUN casper.run(function() { diff --git a/tests/functionnal/casperjs/exe/31_coupons_rule.js b/tests/functionnal/casperjs/exe/31_coupons_rule.js index 66706aada..219802903 100644 --- a/tests/functionnal/casperjs/exe/31_coupons_rule.js +++ b/tests/functionnal/casperjs/exe/31_coupons_rule.js @@ -9,7 +9,7 @@ //// verbose:true ////}); // -//casper.test.comment('Testing coupons rules'); +casper.test.comment('Testing coupons rules'); // ////UPDATE COUPON RULE //casper.start(thelia2_login_coupon_update_url, function() { @@ -306,7 +306,7 @@ // test.assertDoesntExist('tbody#constraint-list tr:nth-child(2)'); //}); // -////RUN -//casper.run(function() { -// this.test.done(); -//}); \ No newline at end of file +//RUN +casper.run(function() { + this.test.done(); +}); \ No newline at end of file diff --git a/tests/functionnal/casperjs/exe/40_images_management.js b/tests/functionnal/casperjs/exe/40_images_management.js new file mode 100644 index 000000000..a982f84ff --- /dev/null +++ b/tests/functionnal/casperjs/exe/40_images_management.js @@ -0,0 +1,77 @@ +// +//var casper = require('casper').create({ +// viewportSize:{ +// width:1024, height:768 +// }, +// pageSettings:{ +// userAgent:'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.79 Safari/535.11' +// }, +// verbose:true +//}); + +casper.test.comment('Testing Image Management'); + +// Image list +// @todo implement +////CREATE +casper.start(thelia2_category_image_list_url, function() { + this.test.assertHttpStatus(200); + this.test.comment('Now on : ' + this.getCurrentUrl()); + this.capture('tests/functionnal/casperjs/screenshot/category/images/init.png'); + this.test.comment('CATEGORY : IMAGES - CREATE'); + + // Click on is unlimited button + this.clickLabel('Images', 'a'); + +}); + +casper.wait(1000, function() { + this.echo("\nWaiting...."); +}); + +// Test Coupon creation if no input +casper.then(function(){ + this.capture('tests/functionnal/casperjs/screenshot/category/images/init-tab-image.png'); + this.test.assertExists('.existing-image tr:nth-child(1)', 'First image found'); + + this.click('.existing-image tr:nth-child(1) .image-update-btn'); + +}); + +casper.wait(1000, function() { + this.echo("\nWaiting...."); + +}); + +// Test Coupon creation if no input +casper.then(function(){ + this.test.assertHttpStatus(200); + this.test.comment('Now on : ' + this.getCurrentUrl()); + this.capture('tests/functionnal/casperjs/screenshot/category/images/read-image.png'); +}); + +// Image add 1 +// @todo implement + +// Image add 4 +// @todo implement + +// Image read +// @todo implement + +// Image update +// @todo implement + +// Image delete +// @todo implement + +// Image links +// @todo implement + +// Image i18n +// @todo implement + +//RUN +casper.run(function() { + this.test.done(); +}); \ No newline at end of file