mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-20 20:40:56 +01:00
Implement "Download ZIP" controller for Phragment
Summary: Depends on D7727. This adds support for downloading a fragment and all it's children as a ZIP file. Fragments that have children automatically become directories in the ZIP file. Test Plan: Downloaded a fragment as a ZIP and was able to extract the contents successfully. Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley CC: Korvin, epriestley, aran Maniphest Tasks: T4205 Differential Revision: https://secure.phabricator.com/D7728
This commit is contained in:
parent
f7f5a5dd34
commit
ccd4ae5638
4 changed files with 120 additions and 0 deletions
|
@ -2187,6 +2187,7 @@ phutil_register_library_map(array(
|
||||||
'PhragmentPHIDTypeFragmentVersion' => 'applications/phragment/phid/PhragmentPHIDTypeFragmentVersion.php',
|
'PhragmentPHIDTypeFragmentVersion' => 'applications/phragment/phid/PhragmentPHIDTypeFragmentVersion.php',
|
||||||
'PhragmentPatchUtil' => 'applications/phragment/util/PhragmentPatchUtil.php',
|
'PhragmentPatchUtil' => 'applications/phragment/util/PhragmentPatchUtil.php',
|
||||||
'PhragmentUpdateController' => 'applications/phragment/controller/PhragmentUpdateController.php',
|
'PhragmentUpdateController' => 'applications/phragment/controller/PhragmentUpdateController.php',
|
||||||
|
'PhragmentZIPController' => 'applications/phragment/controller/PhragmentZIPController.php',
|
||||||
'PhrequentController' => 'applications/phrequent/controller/PhrequentController.php',
|
'PhrequentController' => 'applications/phrequent/controller/PhrequentController.php',
|
||||||
'PhrequentDAO' => 'applications/phrequent/storage/PhrequentDAO.php',
|
'PhrequentDAO' => 'applications/phrequent/storage/PhrequentDAO.php',
|
||||||
'PhrequentListController' => 'applications/phrequent/controller/PhrequentListController.php',
|
'PhrequentListController' => 'applications/phrequent/controller/PhrequentListController.php',
|
||||||
|
@ -4785,6 +4786,7 @@ phutil_register_library_map(array(
|
||||||
'PhragmentPHIDTypeFragmentVersion' => 'PhabricatorPHIDType',
|
'PhragmentPHIDTypeFragmentVersion' => 'PhabricatorPHIDType',
|
||||||
'PhragmentPatchUtil' => 'Phobject',
|
'PhragmentPatchUtil' => 'Phobject',
|
||||||
'PhragmentUpdateController' => 'PhragmentController',
|
'PhragmentUpdateController' => 'PhragmentController',
|
||||||
|
'PhragmentZIPController' => 'PhragmentController',
|
||||||
'PhrequentController' => 'PhabricatorController',
|
'PhrequentController' => 'PhabricatorController',
|
||||||
'PhrequentDAO' => 'PhabricatorLiskDAO',
|
'PhrequentDAO' => 'PhabricatorLiskDAO',
|
||||||
'PhrequentListController' =>
|
'PhrequentListController' =>
|
||||||
|
|
|
@ -38,6 +38,7 @@ final class PhabricatorApplicationPhragment extends PhabricatorApplication {
|
||||||
'create/(?P<dblob>.*)' => 'PhragmentCreateController',
|
'create/(?P<dblob>.*)' => 'PhragmentCreateController',
|
||||||
'update/(?P<dblob>.*)' => 'PhragmentUpdateController',
|
'update/(?P<dblob>.*)' => 'PhragmentUpdateController',
|
||||||
'history/(?P<dblob>.*)' => 'PhragmentHistoryController',
|
'history/(?P<dblob>.*)' => 'PhragmentHistoryController',
|
||||||
|
'zip/(?P<dblob>.*)' => 'PhragmentZIPController',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,12 @@ abstract class PhragmentController extends PhabricatorController {
|
||||||
->setHref($file_uri)
|
->setHref($file_uri)
|
||||||
->setDisabled($file === null)
|
->setDisabled($file === null)
|
||||||
->setIcon('download'));
|
->setIcon('download'));
|
||||||
|
$actions->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setName(pht('Download Contents as ZIP'))
|
||||||
|
->setHref($this->getApplicationURI("zip/".$fragment->getPath()))
|
||||||
|
->setDisabled(false) // TODO: Policy
|
||||||
|
->setIcon('zip'));
|
||||||
$actions->addAction(
|
$actions->addAction(
|
||||||
id(new PhabricatorActionView())
|
id(new PhabricatorActionView())
|
||||||
->setName(pht('Update Fragment'))
|
->setName(pht('Update Fragment'))
|
||||||
|
|
111
src/applications/phragment/controller/PhragmentZIPController.php
Normal file
111
src/applications/phragment/controller/PhragmentZIPController.php
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhragmentZIPController extends PhragmentController {
|
||||||
|
|
||||||
|
private $dblob;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->dblob = idx($data, "dblob", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$viewer = $request->getUser();
|
||||||
|
|
||||||
|
$parents = $this->loadParentFragments($this->dblob);
|
||||||
|
if ($parents === null) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
$fragment = idx($parents, count($parents) - 1, null);
|
||||||
|
|
||||||
|
$temp = new TempFile();
|
||||||
|
|
||||||
|
$zip = null;
|
||||||
|
try {
|
||||||
|
$zip = new ZipArchive();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$dialog = new AphrontDialogView();
|
||||||
|
$dialog->setUser($viewer);
|
||||||
|
|
||||||
|
$inst = pht(
|
||||||
|
'This system does not have the ZIP PHP extension installed. This '.
|
||||||
|
'is required to download ZIPs from Phragment.');
|
||||||
|
|
||||||
|
$dialog->setTitle(pht('ZIP Extension Not Installed'));
|
||||||
|
$dialog->appendParagraph($inst);
|
||||||
|
|
||||||
|
$dialog->addCancelButton('/phragment/browse/'.$this->dblob);
|
||||||
|
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$zip->open((string)$temp, ZipArchive::CREATE)) {
|
||||||
|
throw new Exception("Unable to create ZIP archive!");
|
||||||
|
}
|
||||||
|
|
||||||
|
$mappings = $this->getFragmentMappings($fragment, $fragment->getPath());
|
||||||
|
|
||||||
|
$phids = array();
|
||||||
|
foreach ($mappings as $path => $file_phid) {
|
||||||
|
$phids[] = $file_phid;
|
||||||
|
}
|
||||||
|
|
||||||
|
$files = id(new PhabricatorFileQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs($phids)
|
||||||
|
->execute();
|
||||||
|
$files = mpull($files, null, 'getPHID');
|
||||||
|
foreach ($mappings as $path => $file_phid) {
|
||||||
|
if (!isset($files[$file_phid])) {
|
||||||
|
unset($mappings[$path]);
|
||||||
|
}
|
||||||
|
$mappings[$path] = $files[$file_phid];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($mappings as $path => $file) {
|
||||||
|
$zip->addFromString($path, $file->loadFileData());
|
||||||
|
}
|
||||||
|
$zip->close();
|
||||||
|
|
||||||
|
$zip_name = $fragment->getName();
|
||||||
|
if (substr($zip_name, -4) !== '.zip') {
|
||||||
|
$zip_name .= '.zip';
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = Filesystem::readFile((string)$temp);
|
||||||
|
$file = PhabricatorFile::buildFromFileDataOrHash(
|
||||||
|
$data,
|
||||||
|
array(
|
||||||
|
'name' => $zip_name,
|
||||||
|
'ttl' => time() + 60 * 60 * 24,
|
||||||
|
));
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI($file->getBestURI());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of mappings like array('some/path.txt' => 'file PHID');
|
||||||
|
*/
|
||||||
|
private function getFragmentMappings(PhragmentFragment $current, $base_path) {
|
||||||
|
$children = id(new PhragmentFragmentQuery())
|
||||||
|
->setViewer($this->getRequest()->getUser())
|
||||||
|
->needLatestVersion(true)
|
||||||
|
->withLeadingPath($current->getPath().'/')
|
||||||
|
->withDepths(array($current->getDepth() + 1))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
if (count($children) === 0) {
|
||||||
|
$path = substr($current->getPath(), strlen($base_path) + 1);
|
||||||
|
return array($path => $current->getLatestVersion()->getFilePHID());
|
||||||
|
} else {
|
||||||
|
$mappings = array();
|
||||||
|
foreach ($children as $child) {
|
||||||
|
$child_mappings = $this->getFragmentMappings($child, $base_path);
|
||||||
|
foreach ($child_mappings as $key => $value) {
|
||||||
|
$mappings[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $mappings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue