/**
  * File upload action
  */
 public function uploadAction(Request $request)
 {
     $postRequest = $request->request;
     $files = $request->files;
     if (!$files->has('file') || !$files->get('file') instanceof UploadedFile || !$files->get('file')->isValid()) {
         $message = 'Error uploading the file';
         throw new CmsException(null, $message);
     }
     $file = $files->get('file');
     /* @var $file UploadedFile */
     $em = $this->container->getDoctrine()->getManager();
     $em->beginTransaction();
     $repository = $em->getRepository(FileAbstraction::CN());
     /* @var $repository FileNestedSetRepository */
     $repository->getNestedSetRepository()->lock();
     // Permission check
     $uploadPermissionCheckFolder = null;
     if ($postRequest->get('folder')) {
         $uploadPermissionCheckFolder = $this->getFolder('folder');
     } else {
         $uploadPermissionCheckFolder = new SlashFolder();
     }
     $this->checkActionPermission($uploadPermissionCheckFolder, FileAbstraction::PERMISSION_UPLOAD_NAME);
     try {
         // getting the folder to upload in
         $folder = null;
         if ($postRequest->get('folder')) {
             $folder = $this->getFolder('folder');
         }
         // Will return the top folder created/found from folderPath string
         $firstSubFolder = null;
         // Create/get folder by path provided
         $folderPath = $postRequest->get('folderPath', '');
         $folderPath = trim(str_replace('\\', '/', $folderPath), '/');
         if (!empty($folderPath)) {
             $folderPathParts = explode('/', $folderPath);
             foreach ($folderPathParts as $part) {
                 $folderFound = false;
                 $children = null;
                 if ($folder instanceof Folder) {
                     $children = $folder->getChildren();
                 } elseif (is_null($folder)) {
                     $children = $repository->getRootNodes();
                 } else {
                     throw new \LogicException("Not supported folder type: " . gettype($folder) . ', class: ' . get_class($folder));
                 }
                 foreach ($children as $child) {
                     if ($child instanceof Folder) {
                         $_name = $child->getTitle();
                         if (strcasecmp($_name, $part) === 0) {
                             $folderFound = $child;
                             break;
                         }
                     }
                 }
                 if ($folderFound) {
                     $folder = $folderFound;
                 } else {
                     $folder = $this->createFolder($part, $folder);
                 }
                 if (empty($firstSubFolder)) {
                     $firstSubFolder = $folder;
                 }
             }
         }
         // checking for replace action
         if ($postRequest->has('file_id')) {
             $fileToReplace = $this->getFile('file_id');
             $this->getFileStorage()->replaceFile($fileToReplace, $file);
             // close transaction and unlock the nested set
             $em->commit();
             $repository->getNestedSetRepository()->unlock();
             return new SupraJsonResponse($this->imageAndFileOutput($fileToReplace));
         }
         $fileEntity = null;
         if ($this->getFileStorage()->isSupportedImageFormat($file->getPathname())) {
             $fileEntity = new Image();
         } else {
             $fileEntity = new File();
         }
         $em->persist($fileEntity);
         $fileEntity->setFileName($file->getClientOriginalName());
         $fileEntity->setSize($file->getSize());
         $fileEntity->setMimeType($file->getMimeType());
         // additional jobs for images
         if ($fileEntity instanceof Image) {
             // store original size
             $imageProcessor = $this->getFileStorage()->getImageResizer();
             $imageInfo = $imageProcessor->getImageInfo($file->getPathname());
             $fileEntity->setWidth($imageInfo->getWidth());
             $fileEntity->setHeight($imageInfo->getHeight());
         }
         if (!empty($folder)) {
             // get parent folder private/public status
             $publicStatus = $folder->isPublic();
             $fileEntity->setPublic($publicStatus);
             // Flush before nested set UPDATE
             $em->flush();
             $folder->addChild($fileEntity);
         }
         // when "force" set to true, then we need to ignore duplicate
         // filename exception, so postfix will be added to filename
         if ($fileEntity instanceof File) {
             if ($postRequest->has('force') && $postRequest->filter('force', null, false, FILTER_VALIDATE_BOOLEAN)) {
                 try {
                     $this->getFileStorage()->validateFileUpload($fileEntity, $file['tmp_name']);
                 } catch (DuplicateFileNameException $e) {
                     $siblings = $fileEntity->getSiblings();
                     $existingNames = array();
                     foreach ($siblings as $siblingEntity) {
                         if (!$siblingEntity->equals($fileEntity)) {
                             $existingNames[] = $siblingEntity->getFileName();
                         }
                     }
                     $extension = $fileEntity->getExtension();
                     $fileNamePart = $fileEntity->getFileNameWithoutExtension();
                     $possibleName = null;
                     // assume that 1000 iterations is enough, to create unique name
                     // if not, well... duplicate file name exception will be thrown
                     for ($i = 1; $i < 1000; $i++) {
                         $possibleName = sprintf(self::DUPLICATE_NAME_PATTERN, $fileNamePart, $i, $extension);
                         if (!in_array($possibleName, $existingNames)) {
                             $fileEntity->setFileName($possibleName);
                             break;
                         }
                     }
                 }
             }
         }
         // when it is not enough available memory to complete Image resize/crop
         // file will be uploaded as simple File entity
         if ($fileEntity instanceof Image) {
             try {
                 $this->getFileStorage()->validateFileUpload($fileEntity, $file->getPathname());
             } catch (InsufficientSystemResources $e) {
                 // Removing image
                 $em->remove($fileEntity);
                 $em->flush();
                 $fileEntity = new File();
                 $em->persist($fileEntity);
                 $fileEntity->setFileName($file->getClientOriginalName());
                 $fileEntity->setSize($file->getSize());
                 $fileEntity->setMimeType($file->getType());
                 if (!is_null($folder)) {
                     $publicStatus = $folder->isPublic();
                     $fileEntity->setPublic($publicStatus);
                     // Flush before nested set UPDATE
                     $em->flush();
                     $folder->addChild($fileEntity);
                 }
                 $message = "Amount of memory required for image [{$file['name']}] resizing exceeds available, it will be uploaded as a document";
                 $responseWarning = $message;
             }
         }
         $em->flush();
         // trying to upload file
         $this->getFileStorage()->storeFileData($fileEntity, $file->getPathname());
     } catch (\Exception $e) {
         try {
             // close transaction and unlock the nested set
             $em->flush();
             $em->rollback();
             $repository->getNestedSetRepository()->unlock();
         } catch (\Exception $e) {
             $this->container->getLogger()->error("Failure on rollback/unlock: " . $e->__toString());
         }
         throw new CmsException(null, $e->getMessage(), $e);
     }
     // close transaction and unlock the nested set
     $em->commit();
     $repository->getNestedSetRepository()->unlock();
     // generating output
     $output = $this->imageAndFileOutput($fileEntity);
     if (!empty($firstSubFolder)) {
         $firstSubFolderOutput = $this->entityToArray($firstSubFolder);
         $output['folder'] = $firstSubFolderOutput;
     }
     $response = new SupraJsonResponse();
     $response->setData($output);
     if (isset($responseWarning)) {
         $response->setWarningMessage($responseWarning);
     }
     return $response;
 }