Index: src/__phutil_library_map__.php =================================================================== --- src/__phutil_library_map__.php +++ src/__phutil_library_map__.php @@ -2182,9 +2182,11 @@ 'PhragmentFragmentQuery' => 'applications/phragment/query/PhragmentFragmentQuery.php', 'PhragmentFragmentVersion' => 'applications/phragment/storage/PhragmentFragmentVersion.php', 'PhragmentFragmentVersionQuery' => 'applications/phragment/query/PhragmentFragmentVersionQuery.php', + 'PhragmentHistoryController' => 'applications/phragment/controller/PhragmentHistoryController.php', 'PhragmentPHIDTypeFragment' => 'applications/phragment/phid/PhragmentPHIDTypeFragment.php', 'PhragmentPHIDTypeFragmentVersion' => 'applications/phragment/phid/PhragmentPHIDTypeFragmentVersion.php', 'PhragmentPatchUtil' => 'applications/phragment/util/PhragmentPatchUtil.php', + 'PhragmentUpdateController' => 'applications/phragment/controller/PhragmentUpdateController.php', 'PhrequentController' => 'applications/phrequent/controller/PhrequentController.php', 'PhrequentDAO' => 'applications/phrequent/storage/PhrequentDAO.php', 'PhrequentListController' => 'applications/phrequent/controller/PhrequentListController.php', @@ -4778,9 +4780,11 @@ 1 => 'PhabricatorPolicyInterface', ), 'PhragmentFragmentVersionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhragmentHistoryController' => 'PhragmentController', 'PhragmentPHIDTypeFragment' => 'PhabricatorPHIDType', 'PhragmentPHIDTypeFragmentVersion' => 'PhabricatorPHIDType', 'PhragmentPatchUtil' => 'Phobject', + 'PhragmentUpdateController' => 'PhragmentController', 'PhrequentController' => 'PhabricatorController', 'PhrequentDAO' => 'PhabricatorLiskDAO', 'PhrequentListController' => Index: src/applications/phragment/application/PhabricatorApplicationPhragment.php =================================================================== --- src/applications/phragment/application/PhabricatorApplicationPhragment.php +++ src/applications/phragment/application/PhabricatorApplicationPhragment.php @@ -36,6 +36,8 @@ '' => 'PhragmentBrowseController', 'browse/(?P.*)' => 'PhragmentBrowseController', 'create/(?P.*)' => 'PhragmentCreateController', + 'update/(?P.*)' => 'PhragmentUpdateController', + 'history/(?P.*)' => 'PhragmentHistoryController', ), ); } Index: src/applications/phragment/controller/PhragmentBrowseController.php =================================================================== --- src/applications/phragment/controller/PhragmentBrowseController.php +++ src/applications/phragment/controller/PhragmentBrowseController.php @@ -30,7 +30,7 @@ ->setHref($this->getApplicationURI('/create/'.$path)) ->setIcon('create')); - $current_box = $this->createCurrentFragmentView($current); + $current_box = $this->createCurrentFragmentView($current, false); $list = id(new PHUIObjectItemListView()) ->setUser($viewer); @@ -74,35 +74,8 @@ $current_box, $list), array( - 'title' => pht('Browse Phragments'), + 'title' => pht('Browse Fragments'), 'device' => true)); } - private function createCurrentFragmentView($fragment) { - if ($fragment === null) { - return null; - } - - $viewer = $this->getRequest()->getUser(); - - $header = id(new PHUIHeaderView()) - ->setHeader($fragment->getName()) - ->setPolicyObject($fragment) - ->setUser($viewer); - $properties = new PHUIPropertyListView(); - - $phids = array(); - $phids[] = $fragment->getLatestVersionPHID(); - - $this->loadHandles($phids); - - $properties->addProperty( - pht('Latest Version'), - $this->renderHandlesForPHIDs(array($fragment->getLatestVersionPHID()))); - - return id(new PHUIObjectBoxView()) - ->setHeader($header) - ->addPropertyList($properties); - } - } Index: src/applications/phragment/controller/PhragmentController.php =================================================================== --- src/applications/phragment/controller/PhragmentController.php +++ src/applications/phragment/controller/PhragmentController.php @@ -20,6 +20,7 @@ $fragments = array(); $results = id(new PhragmentFragmentQuery()) ->setViewer($this->getRequest()->getUser()) + ->needLatestVersion(true) ->withPaths($combinations) ->execute(); foreach ($combinations as $combination) { @@ -53,4 +54,74 @@ 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 = id(new PhabricatorFileQuery()) + ->setViewer($viewer) + ->withPHIDs(array($fragment->getLatestVersion()->getPHID())) + ->executeOne(); + $file_uri = null; + 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('Update Fragment')) + ->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); + + $properties->addProperty( + pht('Latest Version'), + $this->renderHandlesForPHIDs(array($fragment->getLatestVersionPHID()))); + + return id(new PHUIObjectBoxView()) + ->setHeader($header) + ->addPropertyList($properties); + } + } Index: src/applications/phragment/controller/PhragmentCreateController.php =================================================================== --- src/applications/phragment/controller/PhragmentCreateController.php +++ src/applications/phragment/controller/PhragmentCreateController.php @@ -134,7 +134,7 @@ $crumbs, $box), array( - 'title' => pht('Create Phragment'), + 'title' => pht('Create Fragment'), 'device' => true)); } Index: src/applications/phragment/controller/PhragmentHistoryController.php =================================================================== --- /dev/null +++ src/applications/phragment/controller/PhragmentHistoryController.php @@ -0,0 +1,77 @@ +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->addAttribute(phabricator_datetime( + $version->getDateCreated(), + $viewer)); + + $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)); + } + +} Index: src/applications/phragment/controller/PhragmentUpdateController.php =================================================================== --- /dev/null +++ src/applications/phragment/controller/PhragmentUpdateController.php @@ -0,0 +1,91 @@ +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); + + $error_view = null; + + if ($request->isFormPost()) { + $errors = array(); + + $v_fileid = $request->getInt('fileID'); + + $file = id(new PhabricatorFile())->load($v_fileid); + if ($file === null) { + $errors[] = pht('The specified file doesn\'t exist.'); + } + + if (!count($errors)) { + $existing = id(new PhragmentFragmentVersionQuery()) + ->setViewer($viewer) + ->withFragmentPHIDs(array($fragment->getPHID())) + ->execute(); + $sequence = count($existing); + + $fragment->openTransaction(); + $version = id(new PhragmentFragmentVersion()); + $version->setSequence($sequence); + $version->setFragmentPHID($fragment->getPHID()); + $version->setFilePHID($file->getPHID()); + $version->save(); + + $fragment->setLatestVersionPHID($version->getPHID()); + $fragment->save(); + $fragment->saveTransaction(); + + return id(new AphrontRedirectResponse()) + ->setURI('/phragment/browse/'.$fragment->getPath()); + } else { + $error_view = id(new AphrontErrorView()) + ->setErrors($errors) + ->setTitle(pht('Errors while updating fragment')); + } + } + + $form = id(new AphrontFormView()) + ->setUser($viewer) + ->appendChild( + id(new AphrontFormTextControl()) + ->setLabel(pht('File ID')) + ->setName('fileID')) + ->appendChild( + id(new AphrontFormSubmitControl()) + ->setValue(pht('Update Fragment')) + ->addCancelButton( + $this->getApplicationURI('browse/'.$fragment->getPath()))); + + $crumbs = $this->buildApplicationCrumbsWithPath($parents); + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName(pht('Update Fragment'))); + + $box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Update Fragment: %s', $fragment->getPath())) + ->setValidationException(null) + ->setForm($form); + + return $this->buildApplicationPage( + array( + $crumbs, + $box), + array( + 'title' => pht('Update Fragment'), + 'device' => true)); + } + +}