mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 00:42:41 +01:00
Allow the published version of a Phriction document to differ from the most recent version
Summary: Depends on D19620. Ref T13077. This adds a "Publish" operation which points the current version at some historical version of the document -- not necessarily the most recent version. Newer versions become "drafts". This is still quite rough and missing a lot of hinting in the UI, I'm just making it work so I can start making the UI understand it. Test Plan: Used the "Publish" action to publish older versions of a document, saw the document revert. Many UI hints are missing and this operation is puzzling and not yet usable for normal users. Reviewers: amckinley Maniphest Tasks: T13077 Differential Revision: https://secure.phabricator.com/D19621
This commit is contained in:
parent
50f4adef64
commit
349686319e
6 changed files with 200 additions and 3 deletions
|
@ -5029,6 +5029,7 @@ phutil_register_library_map(array(
|
|||
'PhrictionDocumentPHIDType' => 'applications/phriction/phid/PhrictionDocumentPHIDType.php',
|
||||
'PhrictionDocumentPathHeraldField' => 'applications/phriction/herald/PhrictionDocumentPathHeraldField.php',
|
||||
'PhrictionDocumentPolicyCodex' => 'applications/phriction/codex/PhrictionDocumentPolicyCodex.php',
|
||||
'PhrictionDocumentPublishTransaction' => 'applications/phriction/xaction/PhrictionDocumentPublishTransaction.php',
|
||||
'PhrictionDocumentQuery' => 'applications/phriction/query/PhrictionDocumentQuery.php',
|
||||
'PhrictionDocumentSearchConduitAPIMethod' => 'applications/phriction/conduit/PhrictionDocumentSearchConduitAPIMethod.php',
|
||||
'PhrictionDocumentSearchEngine' => 'applications/phriction/query/PhrictionDocumentSearchEngine.php',
|
||||
|
@ -5046,6 +5047,7 @@ phutil_register_library_map(array(
|
|||
'PhrictionMarkupPreviewController' => 'applications/phriction/controller/PhrictionMarkupPreviewController.php',
|
||||
'PhrictionMoveController' => 'applications/phriction/controller/PhrictionMoveController.php',
|
||||
'PhrictionNewController' => 'applications/phriction/controller/PhrictionNewController.php',
|
||||
'PhrictionPublishController' => 'applications/phriction/controller/PhrictionPublishController.php',
|
||||
'PhrictionRemarkupRule' => 'applications/phriction/markup/PhrictionRemarkupRule.php',
|
||||
'PhrictionReplyHandler' => 'applications/phriction/mail/PhrictionReplyHandler.php',
|
||||
'PhrictionSchemaSpec' => 'applications/phriction/storage/PhrictionSchemaSpec.php',
|
||||
|
@ -11144,6 +11146,7 @@ phutil_register_library_map(array(
|
|||
'PhrictionDocumentPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhrictionDocumentPathHeraldField' => 'PhrictionDocumentHeraldField',
|
||||
'PhrictionDocumentPolicyCodex' => 'PhabricatorPolicyCodex',
|
||||
'PhrictionDocumentPublishTransaction' => 'PhrictionDocumentTransactionType',
|
||||
'PhrictionDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhrictionDocumentSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
|
||||
'PhrictionDocumentSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
|
@ -11161,6 +11164,7 @@ phutil_register_library_map(array(
|
|||
'PhrictionMarkupPreviewController' => 'PhabricatorController',
|
||||
'PhrictionMoveController' => 'PhrictionController',
|
||||
'PhrictionNewController' => 'PhrictionController',
|
||||
'PhrictionPublishController' => 'PhrictionController',
|
||||
'PhrictionRemarkupRule' => 'PhutilRemarkupRule',
|
||||
'PhrictionReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
|
||||
'PhrictionSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||
|
|
|
@ -56,6 +56,8 @@ final class PhabricatorPhrictionApplication extends PhabricatorApplication {
|
|||
|
||||
'edit/(?:(?P<id>[1-9]\d*)/)?' => 'PhrictionEditController',
|
||||
'delete/(?P<id>[1-9]\d*)/' => 'PhrictionDeleteController',
|
||||
'publish/(?P<documentID>[1-9]\d*)/(?P<contentID>[1-9]\d*)/'
|
||||
=> 'PhrictionPublishController',
|
||||
'new/' => 'PhrictionNewController',
|
||||
'move/(?P<id>[1-9]\d*)/' => 'PhrictionMoveController',
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ final class PhrictionDocumentController
|
|||
|
||||
$curtain = null;
|
||||
if ($document->getID()) {
|
||||
$curtain = $this->buildCurtain($document);
|
||||
$curtain = $this->buildCurtain($document, $content);
|
||||
}
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
|
@ -230,11 +230,11 @@ final class PhrictionDocumentController
|
|||
$prop_list = phutil_tag_div('phui-document-view-pro-box', $prop_list);
|
||||
|
||||
$page_content = id(new PHUIDocumentView())
|
||||
->setBanner($version_note)
|
||||
->setHeader($header)
|
||||
->setToc($toc)
|
||||
->appendChild(
|
||||
array(
|
||||
$version_note,
|
||||
$move_notice,
|
||||
$core_content,
|
||||
));
|
||||
|
@ -277,7 +277,9 @@ final class PhrictionDocumentController
|
|||
return $view;
|
||||
}
|
||||
|
||||
private function buildCurtain(PhrictionDocument $document) {
|
||||
private function buildCurtain(
|
||||
PhrictionDocument $document,
|
||||
PhrictionContent $content) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
|
@ -286,6 +288,7 @@ final class PhrictionDocumentController
|
|||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$slug = PhabricatorSlug::normalize($this->slug);
|
||||
$id = $document->getID();
|
||||
|
||||
$curtain = $this->newCurtainView($document);
|
||||
|
||||
|
@ -296,6 +299,26 @@ final class PhrictionDocumentController
|
|||
->setIcon('fa-pencil')
|
||||
->setHref('/phriction/edit/'.$document->getID().'/'));
|
||||
|
||||
$is_current = false;
|
||||
$content_id = null;
|
||||
if ($content) {
|
||||
if ($content->getPHID() == $document->getContentPHID()) {
|
||||
$is_current = true;
|
||||
}
|
||||
$content_id = $content->getID();
|
||||
}
|
||||
$can_publish = ($can_edit && $content && !$is_current);
|
||||
|
||||
$publish_uri = "/phriction/publish/{$id}/{$content_id}/";
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Publish'))
|
||||
->setIcon('fa-upload')
|
||||
->setDisabled(!$can_publish)
|
||||
->setWorkflow(true)
|
||||
->setHref($publish_uri));
|
||||
|
||||
if ($document->getStatus() == PhrictionDocumentStatus::STATUS_EXISTS) {
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
final class PhrictionPublishController
|
||||
extends PhrictionController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$id = $request->getURIData('documentID');
|
||||
$content_id = $request->getURIData('contentID');
|
||||
|
||||
$document = id(new PhrictionDocumentQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->needContent(true)
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$document) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$document_uri = $document->getURI();
|
||||
|
||||
$content = id(new PhrictionContentQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($content_id))
|
||||
->executeOne();
|
||||
if (!$content) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
if ($content->getPHID() == $document->getContentPHID()) {
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('Already Published'))
|
||||
->appendChild(
|
||||
pht(
|
||||
'This version of the document is already the published '.
|
||||
'version.'))
|
||||
->addCancelButton($document_uri);
|
||||
}
|
||||
|
||||
$content_uri = $document_uri.'?v='.$content->getVersion();
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$xactions = array();
|
||||
|
||||
$xactions[] = id(new PhrictionTransaction())
|
||||
->setTransactionType(
|
||||
PhrictionDocumentPublishTransaction::TRANSACTIONTYPE)
|
||||
->setNewValue($content->getPHID());
|
||||
|
||||
id(new PhrictionTransactionEditor())
|
||||
->setActor($viewer)
|
||||
->setContentSourceFromRequest($request)
|
||||
->setContinueOnNoEffect(true)
|
||||
->setContinueOnMissingFields(true)
|
||||
->applyTransactions($document, $xactions);
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI($document_uri);
|
||||
}
|
||||
|
||||
if ($content->getVersion() < $document->getContent()->getVersion()) {
|
||||
$title = pht('Revert Document?');
|
||||
$body = pht(
|
||||
'Revert the published version of this document to an older '.
|
||||
'version?');
|
||||
$button = pht('Revert');
|
||||
} else {
|
||||
$title = pht('Publish Draft?');
|
||||
$body = pht(
|
||||
'Update the published version of this document to this newer '.
|
||||
'version?');
|
||||
$button = pht('Publish');
|
||||
}
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle($title)
|
||||
->appendChild($body)
|
||||
->addSubmitButton($button)
|
||||
->addCancelButton($content_uri);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
final class PhrictionDocumentPublishTransaction
|
||||
extends PhrictionDocumentTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'publish';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getContentPHID();
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setContentPHID($value);
|
||||
}
|
||||
|
||||
public function getActionName() {
|
||||
return pht('Published');
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
return pht(
|
||||
'%s published a new version of this document.',
|
||||
$this->renderAuthor());
|
||||
}
|
||||
|
||||
public function getTitleForFeed() {
|
||||
return pht(
|
||||
'%s published a new version of %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderObject());
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$actor = $this->getActor();
|
||||
$errors = array();
|
||||
|
||||
foreach ($xactions as $xaction) {
|
||||
$content_phid = $xaction->getNewValue();
|
||||
|
||||
// If this isn't changing anything, skip it.
|
||||
if ($content_phid === $object->getContentPHID()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$content = id(new PhrictionContentQuery())
|
||||
->setViewer($actor)
|
||||
->withPHIDs(array($content_phid))
|
||||
->executeOne();
|
||||
if (!$content) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht(
|
||||
'Unable to load Content object with PHID "%s".',
|
||||
$content_phid),
|
||||
$xaction);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($content->getDocumentPHID() !== $object->getPHID()) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht(
|
||||
'Content object "%s" can not be published because it belongs '.
|
||||
'to a different document.',
|
||||
$content_phid));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,7 @@ final class PHUIDocumentView extends AphrontTagView {
|
|||
private $toc;
|
||||
private $foot;
|
||||
private $curtain;
|
||||
private $banner;
|
||||
|
||||
public function setHeader(PHUIHeaderView $header) {
|
||||
$header->setTall(true);
|
||||
|
@ -46,6 +47,15 @@ final class PHUIDocumentView extends AphrontTagView {
|
|||
return $this->curtain;
|
||||
}
|
||||
|
||||
public function setBanner($banner) {
|
||||
$this->banner = $banner;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBanner() {
|
||||
return $this->banner;
|
||||
}
|
||||
|
||||
protected function getTagAttributes() {
|
||||
$classes = array();
|
||||
|
||||
|
@ -160,6 +170,7 @@ final class PHUIDocumentView extends AphrontTagView {
|
|||
array(
|
||||
$table_of_contents,
|
||||
$this->header,
|
||||
$this->banner,
|
||||
array(
|
||||
$curtain,
|
||||
$main_content,
|
||||
|
|
Loading…
Reference in a new issue