/**
  * @param RequestResponseEvent $event
  */
 public function listen(RequestResponseEvent $event)
 {
     $exception = $event->getData();
     if ($exception instanceof CmsException) {
         $response = new SupraJsonResponse(null);
         $response->setStatus(0);
         $response->setErrorMessage($exception->getMessageKey() ? '{#' . $exception->getMessageKey() . '#}' : $exception->getMessage());
         $event->setResponse($response);
     }
 }
    /**
     * Returns localization properties, inner html and placeholder contents.
     *
     * @return SupraJsonResponse
     */
    public function getAction()
    {
        $localization = $this->getPageLocalization();
        $pageRequest = $this->createPageRequest();
        $pageController = $this->getPageController();
        $templateException = $response = $internalHtml = null;
        try {
            $response = $pageController->execute($pageRequest);
        } catch (\Twig_Error_Loader $e) {
            $templateException = $e;
        } catch (LayoutNotFound $e) {
            $templateException = $e;
        } catch (\Exception $e) {
            throw $e;
        }
        $localizationData = $this->getLocalizationData($localization);
        if ($templateException) {
            $internalHtml = '<h1>Page template or layout not found.</h1>
				<p>Please make sure the template is assigned and the template is published in this locale and it has layout assigned.</p>';
        } elseif ($response instanceof Response) {
            $internalHtml = $response->getContent();
        }
        $localizationData['internal_html'] = $internalHtml;
        $placeHolders = $pageRequest->getPlaceHolderSet()->getFinalPlaceHolders();
        $blocks = $pageRequest->getBlockSet();
        $placeHoldersData =& $localizationData['contents'];
        foreach ($placeHolders as $placeHolder) {
            $blocksData = array();
            foreach ($blocks->getPlaceHolderBlockSet($placeHolder) as $block) {
                /* @var $block Block */
                $blocksData[] = $this->getBlockData($block);
            }
            $placeHolderData = array('id' => $placeHolder->getName(), 'title' => $placeHolder->getTitle(), 'locked' => $placeHolder->isLocked(), 'closed' => !$localization->isPlaceHolderEditable($placeHolder), 'contents' => $blocksData, 'type' => 'list');
            $placeHoldersData[] = $placeHolderData;
        }
        $jsonResponse = new SupraJsonResponse($localizationData);
        // @FIXME: dummy. when needed, move to prefilter.
        $jsonResponse->setPermissions(array(array('edit_page' => true, 'supervise_page' => true)));
        return $jsonResponse;
    }
 /**
  * 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;
 }
 /**
  * Sends confirmation message to JavaScript or returns answer if already received
  * @param string $question
  * @param string $id
  * @param boolean $answer by default next request is made only when "Yes"
  * 		is pressed. Setting to null will make callback for both answers.
  */
 protected function getConfirmation($question, $id = '0', $answer = true)
 {
     $request = $this->container->getRequest();
     $confirmationPool = $request->get(self::CONFIRMATION_ANSWER_CONTEXT, array());
     if (isset($confirmationPool[$id])) {
         $userAnswer = filter_var($confirmationPool[$id], FILTER_VALIDATE_BOOLEAN);
         // Any answer is OK
         if (is_null($answer)) {
             return $userAnswer;
         }
         // Match
         if ($userAnswer === $answer) {
             return $userAnswer;
             // Wrong answer, in fact JS didn't need to do this request anymore
         } else {
             throw new CmsException(null, "Wrong answer");
         }
     }
     $response = new SupraJsonResponse();
     $response->addPart('confirmation', array('id' => $id, 'question' => $question, 'answer' => $answer));
     return $response;
 }