mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-27 01:02:42 +01:00
Phriction Documents can be moved
Summary: Refs T1575 Test Plan: created plenty of pages, did all kind of stuff with them, moved them around, verified expected behaviour. {F34453} {F34455} Reviewers: epriestley, chad, btrahan Reviewed By: epriestley CC: aran, epriestley, Korvin Maniphest Tasks: T1575 Differential Revision: https://secure.phabricator.com/D5198
This commit is contained in:
parent
cd99850cb8
commit
911d02e2d1
8 changed files with 274 additions and 21 deletions
|
@ -1497,6 +1497,7 @@ phutil_register_library_map(array(
|
|||
'PhrictionEditController' => 'applications/phriction/controller/PhrictionEditController.php',
|
||||
'PhrictionHistoryController' => 'applications/phriction/controller/PhrictionHistoryController.php',
|
||||
'PhrictionListController' => 'applications/phriction/controller/PhrictionListController.php',
|
||||
'PhrictionMoveController' => 'applications/phriction/controller/PhrictionMoveController.php',
|
||||
'PhrictionNewController' => 'applications/phriction/controller/PhrictionNewController.php',
|
||||
'PhrictionRemarkupRule' => 'applications/phriction/remarkup/PhrictionRemarkupRule.php',
|
||||
'PhrictionSearchIndexer' => 'applications/phriction/search/PhrictionSearchIndexer.php',
|
||||
|
@ -3003,6 +3004,7 @@ phutil_register_library_map(array(
|
|||
'PhrictionEditController' => 'PhrictionController',
|
||||
'PhrictionHistoryController' => 'PhrictionController',
|
||||
'PhrictionListController' => 'PhrictionController',
|
||||
'PhrictionMoveController' => 'PhrictionController',
|
||||
'PhrictionNewController' => 'PhrictionController',
|
||||
'PhrictionRemarkupRule' => 'PhutilRemarkupRule',
|
||||
'PhrictionSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
|
||||
|
|
|
@ -43,7 +43,7 @@ final class PhabricatorApplicationPhriction extends PhabricatorApplication {
|
|||
'edit/(?:(?P<id>[1-9]\d*)/)?' => 'PhrictionEditController',
|
||||
'delete/(?P<id>[1-9]\d*)/' => 'PhrictionDeleteController',
|
||||
'new/' => 'PhrictionNewController',
|
||||
'move/(?P<id>[1-9]\d*)/' => 'PhrictionMoveController',
|
||||
'move/(?:(?P<id>[1-9]\d*)/)?' => 'PhrictionMoveController',
|
||||
|
||||
'preview/' => 'PhrictionDocumentPreviewController',
|
||||
'diff/(?P<id>[1-9]\d*)/' => 'PhrictionDiffController',
|
||||
|
|
|
@ -8,12 +8,16 @@ final class PhrictionActionConstants extends PhrictionConstants {
|
|||
const ACTION_CREATE = 'create';
|
||||
const ACTION_EDIT = 'edit';
|
||||
const ACTION_DELETE = 'delete';
|
||||
const ACTION_MOVE_AWAY = 'move to';
|
||||
const ACTION_MOVE_HERE = 'move here';
|
||||
|
||||
public static function getActionPastTenseVerb($action) {
|
||||
static $map = array(
|
||||
self::ACTION_CREATE => 'created',
|
||||
self::ACTION_EDIT => 'edited',
|
||||
self::ACTION_DELETE => 'deleted',
|
||||
self::ACTION_MOVE_AWAY => 'moved a document to',
|
||||
self::ACTION_MOVE_HERE => 'moved a document from',
|
||||
);
|
||||
|
||||
return idx($map, $action, "brazenly {$action}'d");
|
||||
|
|
|
@ -12,8 +12,9 @@ final class PhrictionDocumentStatus extends PhrictionConstants {
|
|||
|
||||
public static function getConduitConstant($const) {
|
||||
static $map = array(
|
||||
self::STATUS_EXISTS => 'exists',
|
||||
self::STATUS_EXISTS => 'exists',
|
||||
self::STATUS_DELETED => 'deleted',
|
||||
self::STATUS_MOVED => 'moved',
|
||||
self::STATUS_STUB => 'stubbed',
|
||||
);
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ final class PhrictionDocumentController
|
|||
}
|
||||
|
||||
public function processRequest() {
|
||||
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
|
@ -148,14 +147,43 @@ final class PhrictionDocumentController
|
|||
pht('This document is empty. You can edit it to put some proper '.
|
||||
'content here.'));
|
||||
$core_content = $notice->render();
|
||||
} else if ($doc_status == PhrictionDocumentStatus::STATUS_MOVED) {
|
||||
$new_doc_id = $content->getChangeRef();
|
||||
$new_doc = new PhrictionDocument();
|
||||
$new_doc->load($new_doc_id);
|
||||
|
||||
$slug_uri = PhrictionDocument::getSlugURI($new_doc->getSlug());
|
||||
|
||||
$notice = new AphrontErrorView();
|
||||
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
|
||||
$notice->setTitle(pht('Document Moved'));
|
||||
$notice->appendChild(phutil_tag('p', array(),
|
||||
pht('This document has been moved to %s. You can edit it to put new '.
|
||||
'content here, or use history to revert to an earlier version.',
|
||||
phutil_tag('a', array('href' => $slug_uri), $slug_uri))));
|
||||
$core_content = $notice->render();
|
||||
} else {
|
||||
throw new Exception("Unknown document status '{$doc_status}'!");
|
||||
}
|
||||
|
||||
$move_notice = null;
|
||||
if ($content->getChangeType() == PhrictionChangeType::CHANGE_MOVE_HERE) {
|
||||
$from_doc_id = $content->getChangeRef();
|
||||
$from_doc = id(new PhrictionDocument())->load($from_doc_id);
|
||||
$slug_uri = PhrictionDocument::getSlugURI($from_doc->getSlug());
|
||||
|
||||
$move_notice = id(new AphrontErrorView())
|
||||
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
|
||||
->appendChild(pht('This document was moved from %s',
|
||||
phutil_tag('a', array('href' => $slug_uri), $slug_uri)))
|
||||
->render();
|
||||
}
|
||||
|
||||
$page_content = hsprintf(
|
||||
'<div class="phriction-content">%s%s%s</div>',
|
||||
'<div class="phriction-content">%s%s%s%s</div>',
|
||||
$index_link,
|
||||
$byline,
|
||||
$move_notice,
|
||||
$core_content);
|
||||
}
|
||||
|
||||
|
@ -221,6 +249,13 @@ final class PhrictionDocumentController
|
|||
->setHref('/phriction/edit/'.$document->getID().'/'));
|
||||
|
||||
if ($document->getStatus() == PhrictionDocumentStatus::STATUS_EXISTS) {
|
||||
$action_view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Move Document'))
|
||||
->setIcon('move')
|
||||
->setHref('/phriction/move/'.$document->getID().'/')
|
||||
->setWorkflow(true));
|
||||
|
||||
$action_view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Delete Document'))
|
||||
|
|
|
@ -115,9 +115,13 @@ final class PhrictionListController
|
|||
case 'active':
|
||||
$data = queryfx_all(
|
||||
$conn,
|
||||
'SELECT * FROM %T WHERE status != %d ORDER BY id DESC LIMIT %d, %d',
|
||||
'SELECT * FROM %T WHERE status NOT IN (%Ld) ORDER BY id DESC '.
|
||||
'LIMIT %d, %d',
|
||||
$document_dao->getTableName(),
|
||||
PhrictionDocumentStatus::STATUS_DELETED,
|
||||
array(
|
||||
PhrictionDocumentStatus::STATUS_DELETED,
|
||||
PhrictionDocumentStatus::STATUS_MOVED,
|
||||
),
|
||||
$pager->getOffset(),
|
||||
$pager->getPageSize() + 1);
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @group phriction
|
||||
*/
|
||||
final class PhrictionMoveController
|
||||
extends PhrictionController {
|
||||
|
||||
private $id;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = idx($data, 'id');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
|
||||
|
||||
if ($this->id) {
|
||||
$document = id(new PhrictionDocument())->load($this->id);
|
||||
} else {
|
||||
$slug = PhabricatorSlug::normalize(
|
||||
$request->getStr('slug'));
|
||||
if (!$slug) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$document = id(new PhrictionDocument())->loadOneWhere(
|
||||
'slug = %s',
|
||||
$slug);
|
||||
}
|
||||
|
||||
if (!$document) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
if (!isset($slug)) {
|
||||
$slug = $document->getSlug();
|
||||
}
|
||||
|
||||
$target_slug = PhabricatorSlug::normalize(
|
||||
$request->getStr('new-slug', $slug));
|
||||
|
||||
$submit_uri = $request->getRequestURI()->getPath();
|
||||
$cancel_uri = PhrictionDocument::getSlugURI($slug);
|
||||
|
||||
$errors = array();
|
||||
$error_view = null;
|
||||
$e_url = null;
|
||||
$e_block = false;
|
||||
|
||||
$disallowed_statuses = array(
|
||||
PhrictionDocumentStatus::STATUS_DELETED, // Stupid
|
||||
PhrictionDocumentStatus::STATUS_MOVED, // Plain stupid
|
||||
);
|
||||
if (in_array($document->getStatus(), $disallowed_statuses)) {
|
||||
$error_view = new AphrontErrorView();
|
||||
$error_view->setSeverity(AphrontErrorView::SEVERITY_ERROR);
|
||||
$error_view->appendChild(pht('An already moved or deleted document '.
|
||||
'can not be moved again.'));
|
||||
|
||||
$error_dialog = new AphrontDialogView();
|
||||
$error_dialog->setUser($user);
|
||||
$error_dialog->setTitle("");
|
||||
$error_dialog->appendChild($error_view);
|
||||
$error_dialog->addCancelButton($cancel_uri, pht('I understand'));
|
||||
|
||||
return id(new AphrontDialogResponse())->setDialog($error_dialog);
|
||||
}
|
||||
|
||||
$content = id(new PhrictionContent())->load($document->getContentID());
|
||||
|
||||
if ($request->isFormPost() && !count($errors)) {
|
||||
if (!count($errors)) { // First check if the target document exists
|
||||
$target_document = id(new PhrictionDocument())->loadOneWhere(
|
||||
'slug = %s',
|
||||
$target_slug);
|
||||
|
||||
// Considering to overwrite existing docs? Nuke this!
|
||||
if ($target_document && $target_document->getStatus() ==
|
||||
PhrictionDocumentStatus::STATUS_EXISTS) {
|
||||
|
||||
$errors[] = pht('Can not overwrite existing target document.');
|
||||
$e_url = pht('Already exists.');
|
||||
}
|
||||
}
|
||||
|
||||
if (!count($errors)) { // I like to move it, move it!
|
||||
$from_editor = id(PhrictionDocumentEditor::newForSlug($slug))
|
||||
->setActor($user)
|
||||
->setTitle($content->getTitle())
|
||||
->setContent($content->getContent())
|
||||
->setDescription($content->getDescription());
|
||||
|
||||
$target_editor = id(PhrictionDocumentEditor::newForSlug(
|
||||
$target_slug))
|
||||
->setActor($user)
|
||||
->setTitle($content->getTitle())
|
||||
->setContent($content->getContent())
|
||||
->setDescription($content->getDescription());
|
||||
|
||||
// Move it!
|
||||
$target_editor->moveHere($document->getID());
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$error_view = id(new AphrontErrorView())
|
||||
->setTitle(pht('Form Errors'))
|
||||
->setErrors($errors);
|
||||
}
|
||||
|
||||
$descr_caption = $is_serious ? pht('A reason for the move.') :
|
||||
pht('You better give a good reason for this.');
|
||||
|
||||
if ($request->isAjax()) {
|
||||
$form = new AphrontFormLayoutView();
|
||||
} else {
|
||||
$form = new AphrontFormView();
|
||||
$form->setAction($submit_uri)
|
||||
// Append title so the user can verify that he's touching
|
||||
// the right document
|
||||
->appendChild(
|
||||
id(new AphrontFormStaticControl())
|
||||
->setLabel(pht('Title'))
|
||||
->setValue($content->getTitle()));
|
||||
}
|
||||
|
||||
$form
|
||||
->setUser($user)
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel(pht('New URI'))
|
||||
->setValue($target_slug)
|
||||
->setError($e_url)
|
||||
->setName('new-slug')
|
||||
->setCaption(pht('The new location of the document.')))
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel(pht('Edit Notes'))
|
||||
->setValue($content->getDescription())
|
||||
->setError(null)
|
||||
->setName('description')
|
||||
->setCaption($descr_caption));
|
||||
|
||||
if ($request->isAjax()) {
|
||||
$dialog = new AphrontDialogView();
|
||||
$dialog->setUser($user);
|
||||
$dialog->setTitle(pht('Move Document'));
|
||||
$dialog->appendChild($form);
|
||||
$dialog->setSubmitURI($submit_uri);
|
||||
$dialog->addSubmitButton(pht('Move Document'));
|
||||
$dialog->addCancelButton($cancel_uri);
|
||||
|
||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||
} else {
|
||||
$form->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->addCancelButton($cancel_uri)
|
||||
->setValue(pht('Move Document'))
|
||||
->setDisabled($e_block));
|
||||
|
||||
$panel = id(new AphrontPanelView())
|
||||
->setNoBackground()
|
||||
->setHeader(pht('Move Phriction Document'))
|
||||
->appendChild($form);
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
array(
|
||||
$error_view,
|
||||
$panel,
|
||||
),
|
||||
array(
|
||||
'title' => pht('Move Document'),
|
||||
'device' => true,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -66,33 +66,44 @@ final class PhrictionDocumentEditor extends PhabricatorEditor {
|
|||
return $this->document;
|
||||
}
|
||||
|
||||
public function delete() {
|
||||
$actor = $this->requireActor();
|
||||
public function moveAway($new_doc_id) {
|
||||
return $this->execute(
|
||||
PhrictionChangeType::CHANGE_MOVE_AWAY, true, $new_doc_id);
|
||||
}
|
||||
|
||||
// TODO: Should we do anything about deleting an already-deleted document?
|
||||
// We currently allow it.
|
||||
public function moveHere($old_doc_id) {
|
||||
return $this->execute(
|
||||
PhrictionChangeType::CHANGE_MOVE_HERE, false, $old_doc_id);
|
||||
}
|
||||
|
||||
private function execute(
|
||||
$change_type, $del_new_content = true, $doc_ref = null) {
|
||||
|
||||
$actor = $this->requireActor();
|
||||
|
||||
$document = $this->document;
|
||||
$content = $this->content;
|
||||
|
||||
$new_content = $this->buildContentTemplate($document, $content);
|
||||
$new_content->setChangeType($change_type);
|
||||
|
||||
$new_content->setChangeType(PhrictionChangeType::CHANGE_DELETE);
|
||||
$new_content->setContent('');
|
||||
if ($del_new_content) {
|
||||
$new_content->setContent('');
|
||||
}
|
||||
|
||||
if ($doc_ref) {
|
||||
$new_content->setChangeRef($doc_ref);
|
||||
}
|
||||
|
||||
return $this->updateDocument($document, $content, $new_content);
|
||||
}
|
||||
|
||||
public function delete() {
|
||||
return $this->execute(PhrictionChangeType::CHANGE_DELETE, true);
|
||||
}
|
||||
|
||||
private function stub() {
|
||||
$actor = $this->requireActor();
|
||||
$document = $this->document;
|
||||
$content = $this->content;
|
||||
$new_content = $this->buildContentTemplate($document, $content);
|
||||
|
||||
$new_content->setChangeType(PhrictionChangeType::CHANGE_STUB);
|
||||
$new_content->setContent('');
|
||||
|
||||
return $this->updateDocument($document, $content, $new_content);
|
||||
return $this->execute(PhrictionChangeType::CHANGE_STUB, true);
|
||||
}
|
||||
|
||||
public function save() {
|
||||
|
@ -168,6 +179,14 @@ final class PhrictionDocumentEditor extends PhabricatorEditor {
|
|||
$doc_status = PhrictionDocumentStatus::STATUS_STUB;
|
||||
$feed_action = null;
|
||||
break;
|
||||
case PhrictionChangeType::CHANGE_MOVE_AWAY:
|
||||
$doc_status = PhrictionDocumentStatus::STATUS_MOVED;
|
||||
$feed_action = PhrictionActionConstants::ACTION_MOVE_AWAY;
|
||||
break;
|
||||
case PhrictionChangeType::CHANGE_MOVE_HERE:
|
||||
$doc_status = PhrictionDocumentStatus::STATUS_EXISTS;
|
||||
$feed_action = null;
|
||||
break;
|
||||
default:
|
||||
throw new Exception(
|
||||
"Unsupported content change type '{$change_type}'!");
|
||||
|
|
Loading…
Reference in a new issue