Skip to content

Commit

Permalink
*8148* introduce base PKP file api handler class
Browse files Browse the repository at this point in the history
  • Loading branch information
jnugent committed Mar 11, 2013
1 parent 51f4f73 commit 669d0ab
Showing 1 changed file with 240 additions and 0 deletions.
240 changes: 240 additions & 0 deletions controllers/api/file/PKPFileApiHandler.inc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
<?php
/**
* @defgroup controllers_api_file
*/

/**
* @file controllers/api/file/PKPFileApiHandler.inc.php
*
* Copyright (c) 2000-2013 John Willinsky
* Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
*
* @class FileApiHandler
* @ingroup controllers_api_file
*
* @brief Base Class defining an AJAX API for supplying file information.
*/

// Import the base handler.
import('classes.handler.Handler');
import('lib.pkp.classes.core.JSONMessage');

class PKPFileApiHandler extends Handler {

/**
* Constructor.
*/
function PKPFileApiHandler() {
parent::Handler();
$this->addRoleAssignment(
array(ROLE_ID_MANAGER, ROLE_ID_SUB_EDITOR, ROLE_ID_ASSISTANT, ROLE_ID_REVIEWER, ROLE_ID_AUTHOR),
array('downloadFile', 'downloadLibraryFile', 'viewFile', 'downloadAllFiles', 'recordDownload', 'enableLinkAction')
);
}


//
// Implement methods from PKPHandler
//
function authorize(&$request, &$args, $roleAssignments) {
$fileIds = $request->getUserVar('filesIdsAndRevisions');
$libraryFileId = $request->getUserVar('libraryFileId');

if (is_string($fileIds)) {
$fileIdsArray = explode(';', $fileIds);
array_pop($fileIdsArray);
}
if (!empty($fileIdsArray)) {
$multipleSubmissionFileAccessPolicy = new PolicySet(COMBINING_DENY_OVERRIDES);
foreach ($fileIdsArray as $fileIdAndRevision) {
$multipleSubmissionFileAccessPolicy->addPolicy($this->_getAccessPolicy($request, $args, $roleAssignments, SUBMISSION_FILE_ACCESS_READ, $fileIdAndRevision));
}
$this->addPolicy($multipleSubmissionFileAccessPolicy);
}else if (is_numeric($libraryFileId)) {
import('lib.pkp.classes.security.authorization.PkpContextAccessPolicy');
$this->addPolicy(new PkpContextAccessPolicy($request, $roleAssignments));
}else {
$this->addPolicy($this->_getAccessPolicy($request, $args, $roleAssignments, SUBMISSION_FILE_ACCESS_READ));
}

return parent::authorize($request, $args, $roleAssignments);
}

//
// Public handler methods
//
/**
* Download a file.
* @param $args array
* @param $request Request
*/
function downloadFile($args, &$request) {
$submissionFile =& $this->getAuthorizedContextObject(ASSOC_TYPE_SUBMISSION_FILE);
assert($submissionFile); // Should have been validated already
$context =& $request->getContext();
$fileManager = $this->_getFileManager($context->getId(), $submissionFile->getSubmissionId());
$fileManager->downloadFile($submissionFile->getFileId(), $submissionFile->getRevision());
}

/**
* Download a library file.
* @param $args array
* @param $request Request
*/
function downloadLibraryFile($args, &$request) {
import('lib.pkp.classes.file.LibraryFileManager');
$context =& $request->getContext();
$libraryFileManager = new LibraryFileManager($context->getId());
$libraryFileDao =& DAORegistry::getDAO('LibraryFileDAO');
$libraryFile =& $libraryFileDao->getById($request->getUserVar('libraryFileId'));
if ($libraryFile) {

// If this file has a submission ID, ensure that the current
// user is assigned to that submission.
if ($libraryFile->getSubmissionId()) {
$user =& $request->getUser();
$allowedAccess = false;
$userStageAssignmentDao =& DAORegistry::getDAO('UserStageAssignmentDAO');
$assignedUsers = $userStageAssignmentDao->getUsersBySubmissionAndStageId($libraryFile->getSubmissionId(), WORKFLOW_STAGE_ID_SUBMISSION);
if (!$assignedUsers->wasEmpty()) {
while ($assignedUser =& $assignedUsers->next()) {
if ($assignedUser->getId() == $user->getId()) {
$allowedAccess = true;
break;
}
}
}
} else {
$allowedAccess = true; // this is a Context submission document, default to access policy.
}

if ($allowedAccess) {
$filePath = $libraryFileManager->getBasePath() . $libraryFile->getOriginalFileName();
$libraryFileManager->downloadFile($filePath);
} else {
fatalError('Unauthorized access to library file.');
}
}
}

/**
* View a file.
* @param $args array
* @param $request Request
*/
function viewFile($args, &$request) {
$submissionFile =& $this->getAuthorizedContextObject(ASSOC_TYPE_SUBMISSION_FILE);
assert($submissionFile); // Should have been validated already
$context =& $request->getContext();
$fileManager = $this->_getFileManager($context->getId(), $submissionFile->getSubmissionId());
$fileManager->downloadFile($submissionFile->getFileId(), $submissionFile->getRevision(), true);
}

/**
* Download all passed files.
* @param $args array
* @param $request Request
*/
function downloadAllFiles($args, &$request) {
// Retrieve the authorized objects.
$submissionFiles = $this->getAuthorizedContextObject(ASSOC_TYPE_SUBMISSION_FILES);
$submission =& $this->getAuthorizedContextObject(ASSOC_TYPE_SUBMISSION);

// Find out the paths of all files in this grid.
$fileManager = $this->_getFileManager($context->getId(), $submissionFile->getSubmissionId());
$filesDir = $fileManager->getBasePath();
$filePaths = array();
foreach ($submissionFiles as $submissionFile) {
// Remove absolute path so the archive doesn't include it (otherwise all files are organized by absolute path)
$filePaths[] = str_replace($filesDir, '', $submissionFile->getFilePath());

unset($submissionFile);
}

import('lib.pkp.classes.file.FileArchive');
$fileArchive = new FileArchive();
$archivePath = $fileArchive->create($filePaths, $filesDir);

if (file_exists($archivePath)) {
$fileManager = new FileManager();
if ($fileArchive->zipFunctional()) {
$fileManager->downloadFile($archivePath, 'application/x-zip', false, 'files.zip');
} else {
$fileManager->downloadFile($archivePath, 'application/x-gtar', false, 'files.tar.gz');
}
$fileManager->deleteFile($archivePath);
} else {
fatalError('Creating archive with submission files failed!');
}
}

/**
* Record file download and return js event to update grid rows.
* @param $args array
* @param $request Request
* @return string
*/
function recordDownload($args, &$request) {
$submissionFiles = $this->getAuthorizedContextObject(ASSOC_TYPE_SUBMISSION_FILES);
$fileId = null;

foreach ($submissionFiles as $submissionFile) {
$this->recordView($submissionFile);
$fileId = $submissionFile->getFileId();
unset($submissionFile);
}

if (count($submissionFiles) > 1) {
$fileId = null;
}

return $this->enableLinkAction($args, $request);
}

/**
* Returns a data changd event to re-enable the link action. Refactored out of
* recordDownload since library files do not have downloads recorded and are in a
* different context.
* @param $args aray
* @param $request Request
* @return string
*/
function enableLinkAction($args, &$request) {
return DAO::getDataChangedEvent();
}

/**
* return the application specific file manager.
* Must be overridden in subclases.
* @param $contextId int the context for this manager.
* @param $submissionId int the submission id.
* @return FileManager
*/
function _getFileManager($contextId, $submissionId) {
assert(false);
}

/**
* return the application specific file access policy.
* Must be overridden in subclases.
* @param $request PKPRequest
* @param $args
* @param $roleAssignments array
* @param $fileIdAndRevision array optional
* @return SubmissionAccessPolicy
*/
function _getAccessPolicy($request, $args, $roleAssignments, $fileIdAndRevision = null) {
assert(false);
}

/**
* record a file view.
* Must be overridden in subclases.
* @param $submissionFile SubmissionFile the file to record.
*/
function recordView($submissionFile) {
assert(false);
}
}

?>

0 comments on commit 669d0ab

Please sign in to comment.