Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/phragment/controller/PhragmentBrowseController.php b/src/applications/phragment/controller/PhragmentBrowseController.php
index adb4c0d796..852f1e8644 100644
--- a/src/applications/phragment/controller/PhragmentBrowseController.php
+++ b/src/applications/phragment/controller/PhragmentBrowseController.php
@@ -1,85 +1,89 @@
<?php
final class PhragmentBrowseController 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();
}
$current = nonempty(last($parents), null);
$path = '';
if ($current !== null) {
$path = $current->getPath();
}
$crumbs = $this->buildApplicationCrumbsWithPath($parents);
$crumbs->addAction(
id(new PHUIListItemView())
->setName(pht('Create Fragment'))
->setHref($this->getApplicationURI('/create/'.$path))
->setIcon('create'));
$current_box = $this->createCurrentFragmentView($current, false);
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
$fragments = null;
if ($current === null) {
// Find all root fragments.
$fragments = id(new PhragmentFragmentQuery())
->setViewer($this->getRequest()->getUser())
->needLatestVersion(true)
->withDepths(array(1))
->execute();
} else {
// Find all child fragments.
$fragments = id(new PhragmentFragmentQuery())
->setViewer($this->getRequest()->getUser())
->needLatestVersion(true)
->withLeadingPath($current->getPath().'/')
->withDepths(array($current->getDepth() + 1))
->execute();
}
foreach ($fragments as $fragment) {
$item = id(new PHUIObjectItemView());
$item->setHeader($fragment->getName());
$item->setHref($this->getApplicationURI('/browse/'.$fragment->getPath()));
if (!$fragment->isDirectory()) {
$item->addAttribute(pht(
'Last Updated %s',
phabricator_datetime(
$fragment->getLatestVersion()->getDateCreated(),
$viewer)));
$item->addAttribute(pht(
'Latest Version %s',
$fragment->getLatestVersion()->getSequence()));
+ if ($fragment->isDeleted()) {
+ $item->setDisabled(true);
+ $item->addAttribute(pht('Deleted'));
+ }
} else {
$item->addAttribute('Directory');
}
$list->addItem($item);
}
return $this->buildApplicationPage(
array(
$crumbs,
$current_box,
$list),
array(
'title' => pht('Browse Fragments'),
'device' => true));
}
}
diff --git a/src/applications/phragment/controller/PhragmentController.php b/src/applications/phragment/controller/PhragmentController.php
index d156745f4b..ac5d43c032 100644
--- a/src/applications/phragment/controller/PhragmentController.php
+++ b/src/applications/phragment/controller/PhragmentController.php
@@ -1,154 +1,160 @@
<?php
abstract class PhragmentController extends PhabricatorController {
protected function loadParentFragments($path) {
$components = explode('/', $path);
$combinations = array();
$current = '';
foreach ($components as $component) {
$current .= '/'.$component;
$current = trim($current, '/');
if (trim($current) === '') {
continue;
}
$combinations[] = $current;
}
$fragments = array();
$results = id(new PhragmentFragmentQuery())
->setViewer($this->getRequest()->getUser())
->needLatestVersion(true)
->withPaths($combinations)
->execute();
foreach ($combinations as $combination) {
$found = false;
foreach ($results as $fragment) {
if ($fragment->getPath() === $combination) {
$fragments[] = $fragment;
$found = true;
break;
}
}
if (!$found) {
return null;
}
}
return $fragments;
}
protected function buildApplicationCrumbsWithPath(array $fragments) {
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName('/')
->setHref('/phragment/'));
foreach ($fragments as $parent) {
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($parent->getName())
->setHref('/phragment/browse/'.$parent->getPath()));
}
return $crumbs;
}
protected function createCurrentFragmentView($fragment, $is_history_view) {
if ($fragment === null) {
return null;
}
$viewer = $this->getRequest()->getUser();
$phids = array();
$phids[] = $fragment->getLatestVersionPHID();
$this->loadHandles($phids);
$file = null;
$file_uri = null;
if (!$fragment->isDirectory()) {
$file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($fragment->getLatestVersion()->getFilePHID()))
->executeOne();
if ($file !== null) {
$file_uri = $file->getBestURI();
}
}
$header = id(new PHUIHeaderView())
->setHeader($fragment->getName())
->setPolicyObject($fragment)
->setUser($viewer);
$actions = id(new PhabricatorActionListView())
->setUser($viewer)
->setObject($fragment)
->setObjectURI($fragment->getURI());
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Download Fragment'))
->setHref($file_uri)
->setDisabled($file === null)
->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'));
if (!$fragment->isDirectory()) {
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Update Fragment'))
->setHref($this->getApplicationURI("update/".$fragment->getPath()))
->setDisabled(false) // TODO: Policy
->setIcon('edit'));
} else {
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Convert to File'))
->setHref($this->getApplicationURI("update/".$fragment->getPath()))
->setDisabled(false) // TODO: Policy
->setIcon('edit'));
}
if ($is_history_view) {
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('View Child Fragments'))
->setHref($this->getApplicationURI("browse/".$fragment->getPath()))
->setIcon('browse'));
} else {
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('View History'))
->setHref($this->getApplicationURI("history/".$fragment->getPath()))
->setIcon('history'));
}
$properties = id(new PHUIPropertyListView())
->setUser($viewer)
->setObject($fragment)
->setActionList($actions);
if (!$fragment->isDirectory()) {
- $properties->addProperty(
- pht('Type'),
- pht('File'));
+ if ($fragment->isDeleted()) {
+ $properties->addProperty(
+ pht('Type'),
+ pht('File (Deleted)'));
+ } else {
+ $properties->addProperty(
+ pht('Type'),
+ pht('File'));
+ }
$properties->addProperty(
pht('Latest Version'),
$this->renderHandlesForPHIDs(array($fragment->getLatestVersionPHID())));
} else {
$properties->addProperty(
pht('Type'),
pht('Directory'));
}
return id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
}
}
diff --git a/src/applications/phragment/controller/PhragmentHistoryController.php b/src/applications/phragment/controller/PhragmentHistoryController.php
index 4ca50c0f3a..53cac0c360 100644
--- a/src/applications/phragment/controller/PhragmentHistoryController.php
+++ b/src/applications/phragment/controller/PhragmentHistoryController.php
@@ -1,78 +1,83 @@
<?php
final class PhragmentHistoryController 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();
}
$current = idx($parents, count($parents) - 1, null);
$path = $current->getPath();
$crumbs = $this->buildApplicationCrumbsWithPath($parents);
$crumbs->addAction(
id(new PHUIListItemView())
->setName(pht('Create Fragment'))
->setHref($this->getApplicationURI('/create/'.$path))
->setIcon('create'));
$current_box = $this->createCurrentFragmentView($current, true);
$versions = id(new PhragmentFragmentVersionQuery())
->setViewer($viewer)
->withFragmentPHIDs(array($current->getPHID()))
->execute();
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
$file_phids = mpull($versions, 'getFilePHID');
$files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
foreach ($versions as $version) {
$item = id(new PHUIObjectItemView());
$item->setHeader('Version '.$version->getSequence());
$item->setHref($version->getURI());
$item->addAttribute(phabricator_datetime(
$version->getDateCreated(),
$viewer));
+ if ($version->getFilePHID() === null) {
+ $item->setDisabled(true);
+ $item->addAttribute('Deletion');
+ }
+
$disabled = !isset($files[$version->getFilePHID()]);
$action = id(new PHUIListItemView())
->setIcon('download')
->setDisabled($disabled)
->setRenderNameAsTooltip(true)
->setName(pht("Download"));
if (!$disabled) {
$action->setHref($files[$version->getFilePHID()]->getBestURI());
}
$item->addAction($action);
$list->addItem($item);
}
return $this->buildApplicationPage(
array(
$crumbs,
$current_box,
$list),
array(
'title' => pht('Fragment History'),
'device' => true));
}
}
diff --git a/src/applications/phragment/storage/PhragmentFragment.php b/src/applications/phragment/storage/PhragmentFragment.php
index 87caf483e3..446c306acd 100644
--- a/src/applications/phragment/storage/PhragmentFragment.php
+++ b/src/applications/phragment/storage/PhragmentFragment.php
@@ -1,302 +1,306 @@
<?php
final class PhragmentFragment extends PhragmentDAO
implements PhabricatorPolicyInterface {
protected $path;
protected $depth;
protected $latestVersionPHID;
protected $viewPolicy;
protected $editPolicy;
private $latestVersion = self::ATTACHABLE;
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhragmentPHIDTypeFragment::TYPECONST);
}
public function getURI() {
return '/phragment/fragment/'.$this->getID().'/';
}
public function getName() {
return basename($this->path);
}
public function getFile() {
return $this->assertAttached($this->file);
}
public function attachFile(PhabricatorFile $file) {
return $this->file = $file;
}
public function isDirectory() {
return $this->latestVersionPHID === null;
}
+ public function isDeleted() {
+ return $this->getLatestVersion()->getFilePHID() === null;
+ }
+
public function getLatestVersion() {
if ($this->latestVersionPHID === null) {
return null;
}
return $this->assertAttached($this->latestVersion);
}
public function attachLatestVersion(PhragmentFragmentVersion $version) {
return $this->latestVersion = $version;
}
/* -( Updating ) --------------------------------------------------------- */
/**
* Create a new fragment from a file.
*/
public static function createFromFile(
PhabricatorUser $viewer,
PhabricatorFile $file = null,
$path,
$view_policy,
$edit_policy) {
$fragment = id(new PhragmentFragment());
$fragment->setPath($path);
$fragment->setDepth(count(explode('/', $path)));
$fragment->setLatestVersionPHID(null);
$fragment->setViewPolicy($view_policy);
$fragment->setEditPolicy($edit_policy);
$fragment->save();
// Directory fragments have no versions associated with them, so we
// just return the fragment at this point.
if ($file === null) {
return $fragment;
}
if ($file->getMimeType() === "application/zip") {
$fragment->updateFromZIP($viewer, $file);
} else {
$fragment->updateFromFile($viewer, $file);
}
return $fragment;
}
/**
* Set the specified file as the next version for the fragment.
*/
public function updateFromFile(
PhabricatorUser $viewer,
PhabricatorFile $file) {
$existing = id(new PhragmentFragmentVersionQuery())
->setViewer($viewer)
->withFragmentPHIDs(array($this->getPHID()))
->execute();
$sequence = count($existing);
$this->openTransaction();
$version = id(new PhragmentFragmentVersion());
$version->setSequence($sequence);
$version->setFragmentPHID($this->getPHID());
$version->setFilePHID($file->getPHID());
$version->save();
$this->setLatestVersionPHID($version->getPHID());
$this->save();
$this->saveTransaction();
}
/**
* Apply the specified ZIP archive onto the fragment, removing
* and creating fragments as needed.
*/
public function updateFromZIP(
PhabricatorUser $viewer,
PhabricatorFile $file) {
if ($file->getMimeType() !== "application/zip") {
throw new Exception("File must have mimetype 'application/zip'");
}
// First apply the ZIP as normal.
$this->updateFromFile($viewer, $file);
// Ensure we have ZIP support.
$zip = null;
try {
$zip = new ZipArchive();
} catch (Exception $e) {
// The server doesn't have php5-zip, so we can't do recursive updates.
return;
}
$temp = new TempFile();
Filesystem::writeFile($temp, $file->loadFileData());
if (!$zip->open($temp)) {
throw new Exception("Unable to open ZIP");
}
// Get all of the paths and their data from the ZIP.
$mappings = array();
for ($i = 0; $i < $zip->numFiles; $i++) {
$path = trim($zip->getNameIndex($i), '/');
$stream = $zip->getStream($path);
$data = null;
// If the stream is false, then it is a directory entry. We leave
// $data set to null for directories so we know not to create a
// version entry for them.
if ($stream !== false) {
$data = stream_get_contents($stream);
fclose($stream);
}
$mappings[$path] = $data;
}
// We need to detect any directories that are in the ZIP folder that
// aren't explicitly noted in the ZIP. This can happen if the file
// entries in the ZIP look like:
//
// * something/blah.png
// * something/other.png
// * test.png
//
// Where there is no explicit "something/" entry.
foreach ($mappings as $path_key => $data) {
if ($data === null) {
continue;
}
$directory = dirname($path_key);
while ($directory !== ".") {
if (!array_key_exists($directory, $mappings)) {
$mappings[$directory] = null;
}
if (dirname($directory) === $directory) {
// dirname() will not reduce this directory any further; to
// prevent infinite loop we just break out here.
break;
}
$directory = dirname($directory);
}
}
// Adjust the paths relative to this fragment so we can look existing
// fragments up in the DB.
$base_path = $this->getPath();
$paths = array();
foreach ($mappings as $p => $data) {
$paths[] = $base_path.'/'.$p;
}
// FIXME: What happens when a child exists, but the current user
// can't see it. We're going to create a new child with the exact
// same path and then bad things will happen.
$children = id(new PhragmentFragmentQuery())
->setViewer($viewer)
->needLatestVersion(true)
->withLeadingPath($this->getPath().'/')
->execute();
$children = mpull($children, null, 'getPath');
// Iterate over the existing fragments.
foreach ($children as $full_path => $child) {
$path = substr($full_path, strlen($base_path) + 1);
if (array_key_exists($path, $mappings)) {
if ($child->isDirectory() && $mappings[$path] === null) {
// Don't create a version entry for a directory
// (unless it's been converted into a file).
continue;
}
// The file is being updated.
$file = PhabricatorFile::newFromFileData(
$mappings[$path],
array('name' => basename($path)));
$child->updateFromFile($viewer, $file);
} else {
// The file is being deleted.
$child->deleteFile($viewer);
}
}
// Iterate over the mappings to find new files.
foreach ($mappings as $path => $data) {
if (!array_key_exists($base_path.'/'.$path, $children)) {
// The file is being created. If the data is null,
// then this is explicitly a directory being created.
$file = null;
if ($mappings[$path] !== null) {
$file = PhabricatorFile::newFromFileData(
$mappings[$path],
array('name' => basename($path)));
}
PhragmentFragment::createFromFile(
$viewer,
$file,
$base_path.'/'.$path,
$this->getViewPolicy(),
$this->getEditPolicy());
}
}
}
/**
* Delete the contents of the specified fragment.
*/
public function deleteFile(PhabricatorUser $viewer) {
$existing = id(new PhragmentFragmentVersionQuery())
->setViewer($viewer)
->withFragmentPHIDs(array($this->getPHID()))
->execute();
$sequence = count($existing);
$this->openTransaction();
$version = id(new PhragmentFragmentVersion());
$version->setSequence($sequence);
$version->setFragmentPHID($this->getPHID());
$version->setFilePHID(null);
$version->save();
$this->setLatestVersionPHID($version->getPHID());
$this->save();
$this->saveTransaction();
}
/* -( Policy Interface )--------------------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->getEditPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
public function describeAutomaticCapability($capability) {
return null;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Apr 28, 7:22 PM (5 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1335686
Default Alt Text
(19 KB)

Event Timeline