diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 1260289c10..ea3fb0b884 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1538,6 +1538,7 @@ phutil_register_library_map(array( 'PhabricatorFileDataController' => 'applications/files/controller/PhabricatorFileDataController.php', 'PhabricatorFileDeleteController' => 'applications/files/controller/PhabricatorFileDeleteController.php', 'PhabricatorFileDropUploadController' => 'applications/files/controller/PhabricatorFileDropUploadController.php', + 'PhabricatorFileEditController' => 'applications/files/controller/PhabricatorFileEditController.php', 'PhabricatorFileEditor' => 'applications/files/editor/PhabricatorFileEditor.php', 'PhabricatorFileFilePHIDType' => 'applications/files/phid/PhabricatorFileFilePHIDType.php', 'PhabricatorFileImageMacro' => 'applications/macro/storage/PhabricatorFileImageMacro.php', @@ -4354,6 +4355,7 @@ phutil_register_library_map(array( 'PhabricatorFileDataController' => 'PhabricatorFileController', 'PhabricatorFileDeleteController' => 'PhabricatorFileController', 'PhabricatorFileDropUploadController' => 'PhabricatorFileController', + 'PhabricatorFileEditController' => 'PhabricatorFileController', 'PhabricatorFileEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorFileFilePHIDType' => 'PhabricatorPHIDType', 'PhabricatorFileImageMacro' => array( diff --git a/src/applications/files/application/PhabricatorFilesApplication.php b/src/applications/files/application/PhabricatorFilesApplication.php index 15d1160475..3a4a879dc2 100644 --- a/src/applications/files/application/PhabricatorFilesApplication.php +++ b/src/applications/files/application/PhabricatorFilesApplication.php @@ -50,6 +50,7 @@ final class PhabricatorFilesApplication extends PhabricatorApplication { 'compose/' => 'PhabricatorFileComposeController', 'comment/(?P[1-9]\d*)/' => 'PhabricatorFileCommentController', 'delete/(?P[1-9]\d*)/' => 'PhabricatorFileDeleteController', + 'edit/(?P[1-9]\d*)/' => 'PhabricatorFileEditController', 'info/(?P[^/]+)/' => 'PhabricatorFileInfoController', 'data/(?P[^/]+)/(?P[^/]+)/.*' => 'PhabricatorFileDataController', diff --git a/src/applications/files/controller/PhabricatorFileEditController.php b/src/applications/files/controller/PhabricatorFileEditController.php new file mode 100644 index 0000000000..744f8890c1 --- /dev/null +++ b/src/applications/files/controller/PhabricatorFileEditController.php @@ -0,0 +1,95 @@ +id = $data['id']; + } + + public function processRequest() { + $request = $this->getRequest(); + $viewer = $request->getUser(); + + $file = id(new PhabricatorFileQuery()) + ->setViewer($viewer) + ->withIDs(array($this->id)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$file) { + return new Aphront404Response(); + } + + $title = pht('Edit %s', $file->getName()); + $view_uri = '/'.$file->getMonogram(); + + $validation_exception = null; + if ($request->isFormPost()) { + $can_view = $request->getStr('canView'); + + $xactions = array(); + + $xactions[] = id(new PhabricatorFileTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) + ->setNewValue($can_view); + + $editor = id(new PhabricatorFileEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true); + + try { + $editor->applyTransactions($file, $xactions); + return id(new AphrontRedirectResponse())->setURI($view_uri); + } catch (PhabricatorApplicationTransactionValidationException $ex) { + $validation_exception = $ex; + + $file->setViewPolicy($can_view); + } + } + + + $policies = id(new PhabricatorPolicyQuery()) + ->setViewer($viewer) + ->setObject($file) + ->execute(); + + $form = id(new AphrontFormView()) + ->setUser($viewer) + ->appendChild( + id(new AphrontFormPolicyControl()) + ->setUser($viewer) + ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) + ->setPolicyObject($file) + ->setPolicies($policies) + ->setName('canView')) + ->appendChild( + id(new AphrontFormSubmitControl()) + ->addCancelButton($view_uri) + ->setValue(pht('Save Changes'))); + + $crumbs = $this->buildApplicationCrumbs() + ->addTextCrumb($file->getMonogram(), $view_uri) + ->addTextCrumb(pht('Edit')); + + $object_box = id(new PHUIObjectBoxView()) + ->setHeaderText($title) + ->setValidationException($validation_exception) + ->appendChild($form); + + return $this->buildApplicationPage( + array( + $crumbs, + $object_box, + ), + array( + 'title' => $title, + )); + } + +} diff --git a/src/applications/files/controller/PhabricatorFileInfoController.php b/src/applications/files/controller/PhabricatorFileInfoController.php index 5c03d05b4d..1bee4da668 100644 --- a/src/applications/files/controller/PhabricatorFileInfoController.php +++ b/src/applications/files/controller/PhabricatorFileInfoController.php @@ -115,12 +115,17 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { private function buildActionView(PhabricatorFile $file) { $request = $this->getRequest(); - $user = $request->getUser(); + $viewer = $request->getUser(); $id = $file->getID(); + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $file, + PhabricatorPolicyCapability::CAN_EDIT); + $view = id(new PhabricatorActionListView()) - ->setUser($user) + ->setUser($viewer) ->setObjectURI($this->getRequest()->getRequestURI()) ->setObject($file); @@ -133,7 +138,7 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { } else { $view->addAction( id(new PhabricatorActionView()) - ->setUser($user) + ->setUser($viewer) ->setRenderAsForm(true) ->setDownload(true) ->setName(pht('Download File')) @@ -141,12 +146,21 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { ->setHref($file->getViewURI())); } + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Edit File')) + ->setIcon('fa-pencil') + ->setHref($this->getApplicationURI("/edit/{$id}/")) + ->setWorkflow(!$can_edit) + ->setDisabled(!$can_edit)); + $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Delete File')) ->setIcon('fa-times') ->setHref($this->getApplicationURI("/delete/{$id}/")) - ->setWorkflow(true)); + ->setWorkflow(true) + ->setDisabled(!$can_edit)); return $view; } diff --git a/src/applications/files/controller/PhabricatorFileShortcutController.php b/src/applications/files/controller/PhabricatorFileShortcutController.php index 30eb9fa995..922482f197 100644 --- a/src/applications/files/controller/PhabricatorFileShortcutController.php +++ b/src/applications/files/controller/PhabricatorFileShortcutController.php @@ -18,7 +18,7 @@ final class PhabricatorFileShortcutController return new Aphront404Response(); } - return id(new AphrontRedirectResponse())->setURI($file->getBestURI()); + return id(new AphrontRedirectResponse())->setURI($file->getInfoURI()); } } diff --git a/src/applications/files/editor/PhabricatorFileEditor.php b/src/applications/files/editor/PhabricatorFileEditor.php index 52411c9e5e..ef20413260 100644 --- a/src/applications/files/editor/PhabricatorFileEditor.php +++ b/src/applications/files/editor/PhabricatorFileEditor.php @@ -7,6 +7,7 @@ final class PhabricatorFileEditor $types = parent::getTransactionTypes(); $types[] = PhabricatorTransactions::TYPE_COMMENT; + $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; return $types; } @@ -26,6 +27,12 @@ final class PhabricatorFileEditor protected function applyCustomInternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { + + switch ($xaction->getTransactionType()) { + case PhabricatorTransactions::TYPE_VIEW_POLICY: + $object->setViewPolicy($xaction->getNewValue()); + break; + } } protected function applyCustomExternalTransaction( diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php index 9153f16ce1..5e45d8f62c 100644 --- a/src/applications/files/storage/PhabricatorFile.php +++ b/src/applications/files/storage/PhabricatorFile.php @@ -56,6 +56,10 @@ final class PhabricatorFile extends PhabricatorFileDAO return parent::save(); } + public function getMonogram() { + return 'F'.$this->getID(); + } + public static function readUploadedFileData($spec) { if (!$spec) { throw new Exception('No file was uploaded!');