mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-19 13:22:42 +01:00
Phriction - move "move" to modern editor + transactions
Summary: Ref T4029. Much like D10756, D10761 this does the bare minimum to get things in there. I have a sticky with "TODOs" about moving the error-checking business logic into the editor in all three cases. Up next - policy... Test Plan: moved a document and it worked! verified no feed story. verified both documents involved looked good Reviewers: epriestley Reviewed By: epriestley Subscribers: epriestley, Korvin Maniphest Tasks: T4029 Differential Revision: https://secure.phabricator.com/D10763
This commit is contained in:
parent
bdbb771830
commit
dd7d8cf910
3 changed files with 169 additions and 51 deletions
|
@ -16,6 +16,7 @@ final class PhrictionMoveController extends PhrictionController {
|
||||||
$document = id(new PhrictionDocumentQuery())
|
$document = id(new PhrictionDocumentQuery())
|
||||||
->setViewer($user)
|
->setViewer($user)
|
||||||
->withIDs(array($this->id))
|
->withIDs(array($this->id))
|
||||||
|
->needContent(true)
|
||||||
->requireCapabilities(
|
->requireCapabilities(
|
||||||
array(
|
array(
|
||||||
PhabricatorPolicyCapability::CAN_VIEW,
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
@ -32,6 +33,7 @@ final class PhrictionMoveController extends PhrictionController {
|
||||||
$document = id(new PhrictionDocumentQuery())
|
$document = id(new PhrictionDocumentQuery())
|
||||||
->setViewer($user)
|
->setViewer($user)
|
||||||
->withSlugs(array($slug))
|
->withSlugs(array($slug))
|
||||||
|
->needContent(true)
|
||||||
->requireCapabilities(
|
->requireCapabilities(
|
||||||
array(
|
array(
|
||||||
PhabricatorPolicyCapability::CAN_VIEW,
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
@ -74,50 +76,46 @@ final class PhrictionMoveController extends PhrictionController {
|
||||||
return id(new AphrontDialogResponse())->setDialog($error_dialog);
|
return id(new AphrontDialogResponse())->setDialog($error_dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = id(new PhrictionContent())->load($document->getContentID());
|
$content = $document->getContent();
|
||||||
|
|
||||||
if ($request->isFormPost() && !count($errors)) {
|
if ($request->isFormPost() && !count($errors)) {
|
||||||
if (!count($errors)) { // First check if the target document exists
|
|
||||||
|
|
||||||
// NOTE: We use the ominpotent user because we can't let users overwrite
|
// NOTE: We use the ominpotent user because we can't let users overwrite
|
||||||
// documents even if they can't see them.
|
// documents even if they can't see them.
|
||||||
$target_document = id(new PhrictionDocumentQuery())
|
$target_document = id(new PhrictionDocumentQuery())
|
||||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||||
->withSlugs(array($target_slug))
|
->withSlugs(array($target_slug))
|
||||||
->executeOne();
|
->needContent(true)
|
||||||
|
->executeOne();
|
||||||
|
|
||||||
// Considering to overwrite existing docs? Nuke this!
|
// Considering to overwrite existing docs? Nuke this!
|
||||||
if ($target_document && $target_document->getStatus() ==
|
$exists = PhrictionDocumentStatus::STATUS_EXISTS;
|
||||||
PhrictionDocumentStatus::STATUS_EXISTS) {
|
if ($target_document && $target_document->getStatus() == $exists) {
|
||||||
|
$errors[] = pht('Can not overwrite existing target document.');
|
||||||
$errors[] = pht('Can not overwrite existing target document.');
|
$e_url = pht('Already exists.');
|
||||||
$e_url = pht('Already exists.');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!count($errors)) { // I like to move it, move it!
|
if (!count($errors)) {
|
||||||
$from_editor = id(PhrictionDocumentEditor::newForSlug($slug))
|
|
||||||
|
$editor = id(new PhrictionTransactionEditor())
|
||||||
->setActor($user)
|
->setActor($user)
|
||||||
->setTitle($content->getTitle())
|
->setContentSourceFromRequest($request)
|
||||||
->setContent($content->getContent())
|
->setContinueOnNoEffect(true)
|
||||||
->setDescription($content->getDescription());
|
->setDescription($request->getStr('description'));
|
||||||
|
|
||||||
$target_editor = id(PhrictionDocumentEditor::newForSlug(
|
$xactions = array();
|
||||||
$target_slug))
|
$xactions[] = id(new PhrictionTransaction())
|
||||||
->setActor($user)
|
->setTransactionType(PhrictionTransaction::TYPE_MOVE_TO)
|
||||||
->setTitle($content->getTitle())
|
->setNewValue($document);
|
||||||
->setContent($content->getContent())
|
if (!$target_document) {
|
||||||
->setDescription($content->getDescription());
|
$target_document = PhrictionDocument::initializeNewDocument(
|
||||||
|
$user,
|
||||||
|
$target_slug);
|
||||||
|
}
|
||||||
|
$editor->applyTransactions($target_document, $xactions);
|
||||||
|
|
||||||
// Move it!
|
$redir_uri = PhrictionDocument::getSlugURI(
|
||||||
$target_editor->moveHere($document->getID(), $document->getPHID());
|
$target_document->getSlug());
|
||||||
|
|
||||||
// Retrieve the target doc directly from the editor
|
|
||||||
// No need to load it per Sql again
|
|
||||||
$target_document = $target_editor->getDocument();
|
|
||||||
$from_editor->moveAway($target_document->getID());
|
|
||||||
|
|
||||||
$redir_uri = PhrictionDocument::getSlugURI($target_document->getSlug());
|
|
||||||
return id(new AphrontRedirectResponse())->setURI($redir_uri);
|
return id(new AphrontRedirectResponse())->setURI($redir_uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,21 +129,21 @@ final class PhrictionMoveController extends PhrictionController {
|
||||||
->setUser($user)
|
->setUser($user)
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormStaticControl())
|
id(new AphrontFormStaticControl())
|
||||||
->setLabel(pht('Title'))
|
->setLabel(pht('Title'))
|
||||||
->setValue($content->getTitle()))
|
->setValue($content->getTitle()))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormTextControl())
|
id(new AphrontFormTextControl())
|
||||||
->setLabel(pht('New URI'))
|
->setLabel(pht('New URI'))
|
||||||
->setValue($target_slug)
|
->setValue($target_slug)
|
||||||
->setError($e_url)
|
->setError($e_url)
|
||||||
->setName('new-slug')
|
->setName('new-slug')
|
||||||
->setCaption(pht('The new location of the document.')))
|
->setCaption(pht('The new location of the document.')))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormTextControl())
|
id(new AphrontFormTextControl())
|
||||||
->setLabel(pht('Edit Notes'))
|
->setLabel(pht('Edit Notes'))
|
||||||
->setValue($content->getDescription())
|
->setValue($content->getDescription())
|
||||||
->setError(null)
|
->setError(null)
|
||||||
->setName('description'));
|
->setName('description'));
|
||||||
|
|
||||||
$dialog = id(new AphrontDialogView())
|
$dialog = id(new AphrontDialogView())
|
||||||
->setUser($user)
|
->setUser($user)
|
||||||
|
|
|
@ -6,6 +6,7 @@ final class PhrictionTransactionEditor
|
||||||
private $description;
|
private $description;
|
||||||
private $oldContent;
|
private $oldContent;
|
||||||
private $newContent;
|
private $newContent;
|
||||||
|
private $moveAwayDocument;
|
||||||
|
|
||||||
public function setDescription($description) {
|
public function setDescription($description) {
|
||||||
$this->description = $description;
|
$this->description = $description;
|
||||||
|
@ -49,6 +50,8 @@ final class PhrictionTransactionEditor
|
||||||
$types[] = PhrictionTransaction::TYPE_TITLE;
|
$types[] = PhrictionTransaction::TYPE_TITLE;
|
||||||
$types[] = PhrictionTransaction::TYPE_CONTENT;
|
$types[] = PhrictionTransaction::TYPE_CONTENT;
|
||||||
$types[] = PhrictionTransaction::TYPE_DELETE;
|
$types[] = PhrictionTransaction::TYPE_DELETE;
|
||||||
|
$types[] = PhrictionTransaction::TYPE_MOVE_TO;
|
||||||
|
$types[] = PhrictionTransaction::TYPE_MOVE_AWAY;
|
||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
||||||
|
@ -74,6 +77,8 @@ final class PhrictionTransactionEditor
|
||||||
}
|
}
|
||||||
return $this->getOldContent()->getContent();
|
return $this->getOldContent()->getContent();
|
||||||
case PhrictionTransaction::TYPE_DELETE:
|
case PhrictionTransaction::TYPE_DELETE:
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_TO:
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_AWAY:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,6 +92,22 @@ final class PhrictionTransactionEditor
|
||||||
case PhrictionTransaction::TYPE_CONTENT:
|
case PhrictionTransaction::TYPE_CONTENT:
|
||||||
case PhrictionTransaction::TYPE_DELETE:
|
case PhrictionTransaction::TYPE_DELETE:
|
||||||
return $xaction->getNewValue();
|
return $xaction->getNewValue();
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_TO:
|
||||||
|
$document = $xaction->getNewValue();
|
||||||
|
// grab the real object now for the sub-editor to come
|
||||||
|
$this->moveAwayDocument = $document;
|
||||||
|
$dict = array(
|
||||||
|
'id' => $document->getID(),
|
||||||
|
'phid' => $document->getPHID(),
|
||||||
|
'content' => $document->getContent()->getContent(),);
|
||||||
|
return $dict;
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_AWAY:
|
||||||
|
$document = $xaction->getNewValue();
|
||||||
|
$dict = array(
|
||||||
|
'id' => $document->getID(),
|
||||||
|
'phid' => $document->getPHID(),
|
||||||
|
'content' => $document->getContent()->getContent(),);
|
||||||
|
return $dict;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +120,8 @@ final class PhrictionTransactionEditor
|
||||||
case PhrictionTransaction::TYPE_TITLE:
|
case PhrictionTransaction::TYPE_TITLE:
|
||||||
case PhrictionTransaction::TYPE_CONTENT:
|
case PhrictionTransaction::TYPE_CONTENT:
|
||||||
case PhrictionTransaction::TYPE_DELETE:
|
case PhrictionTransaction::TYPE_DELETE:
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_TO:
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_AWAY:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,8 +143,12 @@ final class PhrictionTransactionEditor
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
case PhrictionTransaction::TYPE_TITLE:
|
case PhrictionTransaction::TYPE_TITLE:
|
||||||
case PhrictionTransaction::TYPE_CONTENT:
|
case PhrictionTransaction::TYPE_CONTENT:
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_TO:
|
||||||
$object->setStatus(PhrictionDocumentStatus::STATUS_EXISTS);
|
$object->setStatus(PhrictionDocumentStatus::STATUS_EXISTS);
|
||||||
return;
|
return;
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_AWAY:
|
||||||
|
$object->setStatus(PhrictionDocumentStatus::STATUS_MOVED);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +168,20 @@ final class PhrictionTransactionEditor
|
||||||
$this->getNewContent()->setChangeType(
|
$this->getNewContent()->setChangeType(
|
||||||
PhrictionChangeType::CHANGE_DELETE);
|
PhrictionChangeType::CHANGE_DELETE);
|
||||||
break;
|
break;
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_TO:
|
||||||
|
$dict = $xaction->getNewValue();
|
||||||
|
$this->getNewContent()->setContent($dict['content']);
|
||||||
|
$this->getNewContent()->setChangeType(
|
||||||
|
PhrictionChangeType::CHANGE_MOVE_HERE);
|
||||||
|
$this->getNewContent()->setChangeRef($dict['id']);
|
||||||
|
break;
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_AWAY:
|
||||||
|
$dict = $xaction->getNewValue();
|
||||||
|
$this->getNewContent()->setContent('');
|
||||||
|
$this->getNewContent()->setChangeType(
|
||||||
|
PhrictionChangeType::CHANGE_MOVE_AWAY);
|
||||||
|
$this->getNewContent()->setChangeRef($dict['id']);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -156,6 +197,8 @@ final class PhrictionTransactionEditor
|
||||||
case PhrictionTransaction::TYPE_TITLE:
|
case PhrictionTransaction::TYPE_TITLE:
|
||||||
case PhrictionTransaction::TYPE_CONTENT:
|
case PhrictionTransaction::TYPE_CONTENT:
|
||||||
case PhrictionTransaction::TYPE_DELETE:
|
case PhrictionTransaction::TYPE_DELETE:
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_AWAY:
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_TO:
|
||||||
$save_content = true;
|
$save_content = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -196,15 +239,27 @@ final class PhrictionTransactionEditor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->moveAwayDocument !== null) {
|
||||||
|
$move_away_xactions = array();
|
||||||
|
$move_away_xactions[] = id(new PhrictionTransaction())
|
||||||
|
->setTransactionType(PhrictionTransaction::TYPE_MOVE_AWAY)
|
||||||
|
->setNewValue($object);
|
||||||
|
$sub_editor = id(new PhrictionTransactionEditor())
|
||||||
|
->setActor($this->getActor())
|
||||||
|
->setContentSource($this->getContentSource())
|
||||||
|
->setContinueOnNoEffect($this->getContinueOnNoEffect())
|
||||||
|
->setDescription($this->getDescription())
|
||||||
|
->applyTransactions($this->moveAwayDocument, $move_away_xactions);
|
||||||
|
}
|
||||||
|
|
||||||
return $xactions;
|
return $xactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function shouldSendMail(
|
protected function shouldSendMail(
|
||||||
PhabricatorLiskDAO $object,
|
PhabricatorLiskDAO $object,
|
||||||
array $xactions) {
|
array $xactions) {
|
||||||
|
return true;
|
||||||
$xactions = mfilter($xactions, 'shouldHide', true);
|
|
||||||
return $xactions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getMailSubjectPrefix() {
|
protected function getMailSubjectPrefix() {
|
||||||
|
@ -274,8 +329,16 @@ final class PhrictionTransactionEditor
|
||||||
array $xactions) {
|
array $xactions) {
|
||||||
|
|
||||||
$phids = parent::getFeedRelatedPHIDs($object, $xactions);
|
$phids = parent::getFeedRelatedPHIDs($object, $xactions);
|
||||||
// TODO - once the editor supports moves, we'll need to surface the
|
|
||||||
// "from document phid" to related phids.
|
foreach ($xactions as $xaction) {
|
||||||
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case PhrictionTransaction::TYPE_MOVE_TO:
|
||||||
|
$dict = $xaction->getNewValue();
|
||||||
|
$phids[] = $dict['phid'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $phids;
|
return $phids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@ final class PhrictionTransaction
|
||||||
const TYPE_TITLE = 'title';
|
const TYPE_TITLE = 'title';
|
||||||
const TYPE_CONTENT = 'content';
|
const TYPE_CONTENT = 'content';
|
||||||
const TYPE_DELETE = 'delete';
|
const TYPE_DELETE = 'delete';
|
||||||
|
const TYPE_MOVE_TO = 'move-to';
|
||||||
|
const TYPE_MOVE_AWAY = 'move-away';
|
||||||
|
|
||||||
const MAILTAG_TITLE = 'phriction-title';
|
const MAILTAG_TITLE = 'phriction-title';
|
||||||
const MAILTAG_CONTENT = 'phriction-content';
|
const MAILTAG_CONTENT = 'phriction-content';
|
||||||
|
@ -23,6 +25,20 @@ final class PhrictionTransaction
|
||||||
return new PhrictionTransactionComment();
|
return new PhrictionTransactionComment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRequiredHandlePHIDs() {
|
||||||
|
$phids = parent::getRequiredHandlePHIDs();
|
||||||
|
$new = $this->getNewValue();
|
||||||
|
switch ($this->getTransactionType()) {
|
||||||
|
case self::TYPE_MOVE_TO:
|
||||||
|
case self::TYPE_MOVE_AWAY:
|
||||||
|
$phids[] = $new['phid'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $phids;
|
||||||
|
}
|
||||||
|
|
||||||
public function getRemarkupBlocks() {
|
public function getRemarkupBlocks() {
|
||||||
$blocks = parent::getRemarkupBlocks();
|
$blocks = parent::getRemarkupBlocks();
|
||||||
|
|
||||||
|
@ -49,6 +65,24 @@ final class PhrictionTransaction
|
||||||
return parent::shouldHide();
|
return parent::shouldHide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldHideForMail(array $xactions) {
|
||||||
|
switch ($this->getTransactionType()) {
|
||||||
|
case self::TYPE_MOVE_TO:
|
||||||
|
case self::TYPE_MOVE_AWAY:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return parent::shouldHideForMail($xactions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldHideForFeed() {
|
||||||
|
switch ($this->getTransactionType()) {
|
||||||
|
case self::TYPE_MOVE_TO:
|
||||||
|
case self::TYPE_MOVE_AWAY:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return parent::shouldHideForFeed();
|
||||||
|
}
|
||||||
|
|
||||||
public function getActionStrength() {
|
public function getActionStrength() {
|
||||||
switch ($this->getTransactionType()) {
|
switch ($this->getTransactionType()) {
|
||||||
case self::TYPE_TITLE:
|
case self::TYPE_TITLE:
|
||||||
|
@ -57,6 +91,9 @@ final class PhrictionTransaction
|
||||||
return 1.3;
|
return 1.3;
|
||||||
case self::TYPE_DELETE:
|
case self::TYPE_DELETE:
|
||||||
return 1.5;
|
return 1.5;
|
||||||
|
case self::TYPE_MOVE_TO:
|
||||||
|
case self::TYPE_MOVE_AWAY:
|
||||||
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getActionStrength();
|
return parent::getActionStrength();
|
||||||
|
@ -80,6 +117,12 @@ final class PhrictionTransaction
|
||||||
case self::TYPE_DELETE:
|
case self::TYPE_DELETE:
|
||||||
return pht('Deleted');
|
return pht('Deleted');
|
||||||
|
|
||||||
|
case self::TYPE_MOVE_TO:
|
||||||
|
return pht('Moved');
|
||||||
|
|
||||||
|
case self::TYPE_MOVE_AWAY:
|
||||||
|
return pht('Moved Away');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getActionName();
|
return parent::getActionName();
|
||||||
|
@ -95,6 +138,9 @@ final class PhrictionTransaction
|
||||||
return 'fa-pencil';
|
return 'fa-pencil';
|
||||||
case self::TYPE_DELETE:
|
case self::TYPE_DELETE:
|
||||||
return 'fa-times';
|
return 'fa-times';
|
||||||
|
case self::TYPE_MOVE_TO:
|
||||||
|
case self::TYPE_MOVE_AWAY:
|
||||||
|
return 'fa-arrows';
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getIcon();
|
return parent::getIcon();
|
||||||
|
@ -130,6 +176,17 @@ final class PhrictionTransaction
|
||||||
'%s deleted this document.',
|
'%s deleted this document.',
|
||||||
$this->renderHandleLink($author_phid));
|
$this->renderHandleLink($author_phid));
|
||||||
|
|
||||||
|
case self::TYPE_MOVE_TO:
|
||||||
|
return pht(
|
||||||
|
'%s moved this document from %s',
|
||||||
|
$this->renderHandleLink($author_phid),
|
||||||
|
$this->renderHandleLink($new['phid']));
|
||||||
|
|
||||||
|
case self::TYPE_MOVE_AWAY:
|
||||||
|
return pht(
|
||||||
|
'%s moved this document to %s',
|
||||||
|
$this->renderHandleLink($author_phid),
|
||||||
|
$this->renderHandleLink($new['phid']));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue