Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/feed/story/PhabricatorFeedStoryPhriction.php b/src/applications/feed/story/PhabricatorFeedStoryPhriction.php
index 4791214b75..08f8d37dda 100644
--- a/src/applications/feed/story/PhabricatorFeedStoryPhriction.php
+++ b/src/applications/feed/story/PhabricatorFeedStoryPhriction.php
@@ -1,64 +1,104 @@
<?php
final class PhabricatorFeedStoryPhriction extends PhabricatorFeedStory {
public function getPrimaryObjectPHID() {
return $this->getValue('phid');
}
+ public function getRequiredHandlePHIDs() {
+ $required_phids = parent::getRequiredHandlePHIDs();
+ $from_phid = $this->getStoryData()->getValue('movedFromPHID');
+ if ($from_phid) {
+ $required_phids[] = $from_phid;
+ }
+ return $required_phids;
+ }
+
public function renderView() {
$data = $this->getStoryData();
$author_phid = $data->getAuthorPHID();
$document_phid = $data->getValue('phid');
$view = new PhabricatorFeedStoryView();
$action = $data->getValue('action');
$verb = PhrictionActionConstants::getActionPastTenseVerb($action);
- $view->setTitle(hsprintf(
- '%s %s the document %s.',
- $this->linkTo($author_phid),
- $verb,
- $this->linkTo($document_phid)));
+ switch ($action) {
+ case PhrictionActionConstants::ACTION_MOVE_HERE:
+ $from_phid = $data->getValue('movedFromPHID');
+
+ // Older feed stories may not have 'moved_from_phid', in that case
+ // we fall back to the default behaviour (hence the fallthrough)
+ if ($from_phid) {
+ $document_handle = $this->getHandle($document_phid);
+ $from_handle = $this->getHandle($from_phid);
+ $view->setTitle(pht(
+ '%s moved the document %s from %s to %s.',
+ $this->linkTo($author_phid),
+ $document_handle->renderLink(),
+ phutil_tag(
+ 'a',
+ array(
+ 'href' => $from_handle->getURI(),
+ ),
+ $from_handle->getURI()),
+ phutil_tag(
+ 'a',
+ array(
+ 'href' => $document_handle->getURI(),
+ ),
+ $document_handle->getURI())));
+ break;
+ }
+ /* Fallthrough */
+ default:
+ $view->setTitle(pht(
+ '%s %s the document %s.',
+ $this->linkTo($author_phid),
+ $verb,
+ $this->linkTo($document_phid)));
+ break;
+ }
+
$view->setEpoch($data->getEpoch());
- $action = $data->getValue('action');
switch ($action) {
case PhrictionActionConstants::ACTION_CREATE:
$full_size = true;
break;
default:
$full_size = false;
break;
}
if ($full_size) {
$view->setImage($this->getHandle($author_phid)->getImageURI());
$content = $this->renderSummary($data->getValue('content'));
$view->appendChild($content);
} else {
$view->setOneLineStory(true);
}
return $view;
}
public function renderText() {
$author_name = $this->getHandle($this->getAuthorPHID())->getLinkName();
$document_handle = $this->getHandle($this->getPrimaryObjectPHID());
$document_title = $document_handle->getLinkName();
$document_uri = PhabricatorEnv::getURI($document_handle->getURI());
$action = $this->getValue('action');
$verb = PhrictionActionConstants::getActionPastTenseVerb($action);
$text = "{$author_name} {$verb} the document".
"{$document_title} {$document_uri}";
return $text;
}
}
diff --git a/src/applications/phriction/constants/PhrictionActionConstants.php b/src/applications/phriction/constants/PhrictionActionConstants.php
index 298214adb3..adfd00d7f0 100644
--- a/src/applications/phriction/constants/PhrictionActionConstants.php
+++ b/src/applications/phriction/constants/PhrictionActionConstants.php
@@ -1,26 +1,26 @@
<?php
/**
* @group phriction
*/
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',
+ self::ACTION_MOVE_AWAY => 'moved',
+ self::ACTION_MOVE_HERE => 'moved',
);
return idx($map, $action, "brazenly {$action}'d");
}
}
diff --git a/src/applications/phriction/controller/PhrictionMoveController.php b/src/applications/phriction/controller/PhrictionMoveController.php
index 3eaac68b4e..613eaccee3 100644
--- a/src/applications/phriction/controller/PhrictionMoveController.php
+++ b/src/applications/phriction/controller/PhrictionMoveController.php
@@ -1,157 +1,157 @@
<?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
PhrictionDocumentStatus::STATUS_STUB, // Utterly 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());
+ $target_editor->moveHere($document->getID(), $document->getPHID());
// 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.');
$form = id(new AphrontFormLayoutView())
->setUser($user)
->appendChild(
id(new AphrontFormStaticControl())
->setLabel(pht('Title'))
->setValue($content->getTitle()))
->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));
$dialog = id(new AphrontDialogView())
->setUser($user)
->setTitle(pht('Move Document'))
->appendChild($form)
->setSubmitURI($submit_uri)
->addSubmitButton(pht('Move Document'))
->addCancelButton($cancel_uri);
return id(new AphrontDialogResponse())->setDialog($dialog);
}
}
diff --git a/src/applications/phriction/editor/PhrictionDocumentEditor.php b/src/applications/phriction/editor/PhrictionDocumentEditor.php
index 89d065c616..c32166c13b 100644
--- a/src/applications/phriction/editor/PhrictionDocumentEditor.php
+++ b/src/applications/phriction/editor/PhrictionDocumentEditor.php
@@ -1,275 +1,284 @@
<?php
/**
* Create or update Phriction documents.
*
* @group phriction
*/
final class PhrictionDocumentEditor extends PhabricatorEditor {
private $document;
private $content;
private $newTitle;
private $newContent;
private $description;
+ // For the Feed Story when moving documents
+ private $fromDocumentPHID;
+
private function __construct() {
// <restricted>
}
public static function newForSlug($slug) {
$slug = PhabricatorSlug::normalize($slug);
$document = id(new PhrictionDocument())->loadOneWhere(
'slug = %s',
$slug);
$content = null;
if ($document) {
$content = id(new PhrictionContent())->load($document->getContentID());
} else {
$document = new PhrictionDocument();
$document->setSlug($slug);
}
if (!$content) {
$default_title = PhabricatorSlug::getDefaultTitle($slug);
$content = new PhrictionContent();
$content->setSlug($slug);
$content->setTitle($default_title);
$content->setContent('');
}
$obj = new PhrictionDocumentEditor();
$obj->document = $document;
$obj->content = $content;
return $obj;
}
public function setTitle($title) {
$this->newTitle = $title;
return $this;
}
public function setContent($content) {
$this->newContent = $content;
return $this;
}
public function setDescription($description) {
$this->description = $description;
return $this;
}
public function getDocument() {
return $this->document;
}
public function moveAway($new_doc_id) {
return $this->execute(
PhrictionChangeType::CHANGE_MOVE_AWAY, true, $new_doc_id);
}
- public function moveHere($old_doc_id) {
+ public function moveHere($old_doc_id, $old_doc_phid) {
+ $this->fromDocumentPHID = $old_doc_phid;
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);
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() {
return $this->execute(PhrictionChangeType::CHANGE_STUB, true);
}
public function save() {
$actor = $this->requireActor();
if ($this->newContent === '') {
// If this is an edit which deletes all the content, just treat it as
// a delete. NOTE: null means "don't change the content", not "delete
// the page"! Thus the strict type check.
return $this->delete();
}
$document = $this->document;
$content = $this->content;
$new_content = $this->buildContentTemplate($document, $content);
return $this->updateDocument($document, $content, $new_content);
}
private function buildContentTemplate(
PhrictionDocument $document,
PhrictionContent $content) {
$new_content = new PhrictionContent();
$new_content->setSlug($document->getSlug());
$new_content->setAuthorPHID($this->getActor()->getPHID());
$new_content->setChangeType(PhrictionChangeType::CHANGE_EDIT);
$new_content->setTitle(
coalesce(
$this->newTitle,
$content->getTitle()));
$new_content->setContent(
coalesce(
$this->newContent,
$content->getContent()));
if (strlen($this->description)) {
$new_content->setDescription($this->description);
}
return $new_content;
}
private function updateDocument($document, $content, $new_content) {
$is_new = false;
if (!$document->getID()) {
$is_new = true;
}
$new_content->setVersion($content->getVersion() + 1);
$change_type = $new_content->getChangeType();
switch ($change_type) {
case PhrictionChangeType::CHANGE_EDIT:
$doc_status = PhrictionDocumentStatus::STATUS_EXISTS;
$feed_action = $is_new
? PhrictionActionConstants::ACTION_CREATE
: PhrictionActionConstants::ACTION_EDIT;
break;
case PhrictionChangeType::CHANGE_DELETE:
$doc_status = PhrictionDocumentStatus::STATUS_DELETED;
$feed_action = PhrictionActionConstants::ACTION_DELETE;
if ($is_new) {
throw new Exception(
"You can not delete a document which doesn't exist yet!");
}
break;
case PhrictionChangeType::CHANGE_STUB:
$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;
+ $feed_action = null;
break;
case PhrictionChangeType::CHANGE_MOVE_HERE:
$doc_status = PhrictionDocumentStatus::STATUS_EXISTS;
- $feed_action = null;
+ $feed_action = PhrictionActionConstants::ACTION_MOVE_HERE;
break;
default:
throw new Exception(
"Unsupported content change type '{$change_type}'!");
}
$document->setStatus($doc_status);
// TODO: This should be transactional.
if ($is_new) {
$document->save();
}
$new_content->setDocumentID($document->getID());
$new_content->save();
$document->setContentID($new_content->getID());
$document->save();
$document->attachContent($new_content);
id(new PhabricatorSearchIndexer())
->indexDocumentByPHID($document->getPHID());
// Stub out empty parent documents if they don't exist
$ancestral_slugs = PhabricatorSlug::getAncestry($document->getSlug());
if ($ancestral_slugs) {
$ancestors = id(new PhrictionDocument())->loadAllWhere(
'slug IN (%Ls)',
$ancestral_slugs);
$ancestors = mpull($ancestors, null, 'getSlug');
foreach ($ancestral_slugs as $slug) {
// We check for change type to prevent near-infinite recursion
if (!isset($ancestors[$slug]) &&
$new_content->getChangeType() != PhrictionChangeType::CHANGE_STUB) {
id(PhrictionDocumentEditor::newForSlug($slug))
->setActor($this->getActor())
->setTitle(PhabricatorSlug::getDefaultTitle($slug))
->setContent('')
->setDescription(pht('Empty Parent Document'))
->stub();
}
}
}
$project_phid = null;
$slug = $document->getSlug();
if (PhrictionDocument::isProjectSlug($slug)) {
$project = id(new PhabricatorProject())->loadOneWhere(
'phrictionSlug = %s',
PhrictionDocument::getProjectSlugIdentifier($slug));
if ($project) {
$project_phid = $project->getPHID();
}
}
$related_phids = array(
$document->getPHID(),
$this->getActor()->getPHID(),
);
if ($project_phid) {
$related_phids[] = $project_phid;
}
+ if ($this->fromDocumentPHID) {
+ $related_phids[] = $this->fromDocumentPHID;
+ }
+
if ($feed_action) {
id(new PhabricatorFeedStoryPublisher())
->setRelatedPHIDs($related_phids)
->setStoryAuthorPHID($this->getActor()->getPHID())
->setStoryTime(time())
->setStoryType(PhabricatorFeedStoryTypeConstants::STORY_PHRICTION)
->setStoryData(
array(
- 'phid' => $document->getPHID(),
- 'action' => $feed_action,
- 'content' => phutil_utf8_shorten($new_content->getContent(), 140),
- 'project' => $project_phid,
+ 'phid' => $document->getPHID(),
+ 'action' => $feed_action,
+ 'content' => phutil_utf8_shorten($new_content->getContent(), 140),
+ 'project' => $project_phid,
+ 'movedFromPHID' => $this->fromDocumentPHID,
))
->publish();
}
return $this;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Mar 16, 11:04 PM (1 d, 8 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
961677
Default Alt Text
(18 KB)

Event Timeline