Page MenuHomePhorge

No OneTemporary

diff --git a/src/applications/phriction/controller/PhrictionDocumentController.php b/src/applications/phriction/controller/PhrictionDocumentController.php
index e424a7f148..1853dd1ee1 100644
--- a/src/applications/phriction/controller/PhrictionDocumentController.php
+++ b/src/applications/phriction/controller/PhrictionDocumentController.php
@@ -1,669 +1,698 @@
<?php
final class PhrictionDocumentController
extends PhrictionController {
private $slug;
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$this->slug = $request->getURIData('slug');
$slug = PhabricatorSlug::normalize($this->slug);
if ($slug != $this->slug) {
$uri = PhrictionDocument::getSlugURI($slug);
// Canonicalize pages to their one true URI.
return id(new AphrontRedirectResponse())->setURI($uri);
}
$version_note = null;
$core_content = '';
$move_notice = '';
$properties = null;
$content = null;
$toc = null;
$is_draft = false;
$document = id(new PhrictionDocumentQuery())
->setViewer($viewer)
->withSlugs(array($slug))
->needContent(true)
->executeOne();
if (!$document) {
$document = PhrictionDocument::initializeNewDocument($viewer, $slug);
if ($slug == '/') {
$title = pht('Welcome to Phriction');
$subtitle = pht('Phriction is a simple and easy to use wiki for '.
'keeping track of documents and their changes.');
$page_title = pht('Welcome');
$create_text = pht('Edit this Document');
} else {
$title = pht('No Document Here');
$subtitle = pht('There is no document here, but you may create it.');
$page_title = pht('Page Not Found');
$create_text = pht('Create this Document');
}
$create_uri = '/phriction/edit/?slug='.$slug;
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText($create_text)
->setHref($create_uri)
->setColor(PHUIButtonView::GREEN);
$core_content = id(new PHUIBigInfoView())
->setIcon('fa-book')
->setTitle($title)
->setDescription($subtitle)
->addAction($create_button);
} else {
$max_version = (int)$document->getMaxVersion();
$version = $request->getInt('v');
if ($version) {
$content = id(new PhrictionContentQuery())
->setViewer($viewer)
->withDocumentPHIDs(array($document->getPHID()))
->withVersions(array($version))
->executeOne();
if (!$content) {
return new Aphront404Response();
}
// When the "v" parameter exists, the user is in history mode so we
// show this header even if they're looking at the current version
// of the document. This keeps the next/previous links working.
$view_version = (int)$content->getVersion();
$published_version = (int)$document->getContent()->getVersion();
if ($view_version < $published_version) {
$version_note = pht(
'You are viewing an older version of this document, as it '.
'appeared on %s.',
phabricator_datetime($content->getDateCreated(), $viewer));
} else if ($view_version > $published_version) {
$is_draft = true;
$version_note = pht(
'You are viewing an unpublished draft of this document.');
} else {
$version_note = pht(
'You are viewing the current published version of this document.');
}
$version_note = array(
phutil_tag(
'strong',
array(),
pht('Version %d of %d: ', $view_version, $max_version)),
' ',
$version_note,
);
$version_note = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->appendChild($version_note);
$document_uri = new PhutilURI($document->getURI());
if ($view_version > 1) {
$previous_uri = $document_uri->alter('v', ($view_version - 1));
} else {
$previous_uri = null;
}
if ($view_version !== $published_version) {
$current_uri = $document_uri->alter('v', $published_version);
} else {
$current_uri = null;
}
if ($view_version < $max_version) {
$next_uri = $document_uri->alter('v', ($view_version + 1));
} else {
$next_uri = null;
}
if ($view_version !== $max_version) {
$draft_uri = $document_uri->alter('v', $max_version);
} else {
$draft_uri = null;
}
$button_bar = id(new PHUIButtonBarView())
->addButton(
id(new PHUIButtonView())
->setTag('a')
->setColor('grey')
->setIcon('fa-backward')
->setDisabled(!$previous_uri)
->setHref($previous_uri)
->setText(pht('Previous')))
->addButton(
id(new PHUIButtonView())
->setTag('a')
->setColor('grey')
->setIcon('fa-file-o')
->setDisabled(!$current_uri)
->setHref($current_uri)
->setText(pht('Published')))
->addButton(
id(new PHUIButtonView())
->setTag('a')
->setColor('grey')
->setIcon('fa-forward', false)
->setDisabled(!$next_uri)
->setHref($next_uri)
->setText(pht('Next')))
->addButton(
id(new PHUIButtonView())
->setTag('a')
->setColor('grey')
->setIcon('fa-fast-forward', false)
->setDisabled(!$draft_uri)
->setHref($draft_uri)
->setText(pht('Draft')));
require_celerity_resource('phui-document-view-css');
$version_note = array(
$version_note,
phutil_tag(
'div',
array(
'class' => 'phui-document-version-navigation',
),
$button_bar),
);
} else {
$content = $document->getContent();
+
+ if ($content->getVersion() < $document->getMaxVersion()) {
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $document,
+ PhabricatorPolicyCapability::CAN_EDIT);
+ if ($can_edit) {
+ $document_uri = new PhutilURI($document->getURI());
+ $draft_uri = $document_uri->alter('v', $document->getMaxVersion());
+
+ $draft_link = phutil_tag(
+ 'a',
+ array(
+ 'href' => $draft_uri,
+ ),
+ pht('View Draft Version'));
+
+ $draft_link = phutil_tag('strong', array(), $draft_link);
+
+ $version_note = id(new PHUIInfoView())
+ ->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
+ ->appendChild(
+ array(
+ pht('This document has unpublished draft changes.'),
+ ' ',
+ $draft_link,
+ ));
+ }
+ }
}
$page_title = $content->getTitle();
$properties = $this
->buildPropertyListView($document, $content, $slug);
$doc_status = $document->getStatus();
$current_status = $content->getChangeType();
if ($current_status == PhrictionChangeType::CHANGE_EDIT ||
$current_status == PhrictionChangeType::CHANGE_MOVE_HERE) {
$remarkup_view = $content->newRemarkupView($viewer);
$core_content = $remarkup_view->render();
$toc = $remarkup_view->getTableOfContents();
$toc = $this->getToc($toc);
} else if ($current_status == PhrictionChangeType::CHANGE_DELETE) {
$notice = new PHUIInfoView();
$notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
$notice->setTitle(pht('Document Deleted'));
$notice->appendChild(
pht('This document has been deleted. You can edit it to put new '.
'content here, or use history to revert to an earlier version.'));
$core_content = $notice->render();
} else if ($current_status == PhrictionChangeType::CHANGE_STUB) {
$notice = new PHUIInfoView();
$notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
$notice->setTitle(pht('Empty Document'));
$notice->appendChild(
pht('This document is empty. You can edit it to put some proper '.
'content here.'));
$core_content = $notice->render();
} else if ($current_status == PhrictionChangeType::CHANGE_MOVE_AWAY) {
$new_doc_id = $content->getChangeRef();
$slug_uri = null;
// If the new document exists and the viewer can see it, provide a link
// to it. Otherwise, render a generic message.
$new_docs = id(new PhrictionDocumentQuery())
->setViewer($viewer)
->withIDs(array($new_doc_id))
->execute();
if ($new_docs) {
$new_doc = head($new_docs);
$slug_uri = PhrictionDocument::getSlugURI($new_doc->getSlug());
}
$notice = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
if ($slug_uri) {
$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))));
} else {
$notice->appendChild(
phutil_tag(
'p',
array(),
pht(
'This document has been moved. You can edit it to put new '.
'content here, or use history to revert to an earlier '.
'version.')));
}
$core_content = $notice->render();
} else {
throw new Exception(pht("Unknown document status '%s'!", $doc_status));
}
$move_notice = null;
if ($current_status == PhrictionChangeType::CHANGE_MOVE_HERE) {
$from_doc_id = $content->getChangeRef();
$slug_uri = null;
// If the old document exists and is visible, provide a link to it.
$from_docs = id(new PhrictionDocumentQuery())
->setViewer($viewer)
->withIDs(array($from_doc_id))
->execute();
if ($from_docs) {
$from_doc = head($from_docs);
$slug_uri = PhrictionDocument::getSlugURI($from_doc->getSlug());
}
$move_notice = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
if ($slug_uri) {
$move_notice->appendChild(
pht(
'This document was moved from %s.',
phutil_tag('a', array('href' => $slug_uri), $slug_uri)));
} else {
// Render this for consistency, even though it's a bit silly.
$move_notice->appendChild(
pht('This document was moved from elsewhere.'));
}
}
}
$children = $this->renderDocumentChildren($slug);
$curtain = null;
if ($document->getID()) {
$curtain = $this->buildCurtain($document, $content);
}
$crumbs = $this->buildApplicationCrumbs();
$crumbs->setBorder(true);
$crumb_views = $this->renderBreadcrumbs($slug);
foreach ($crumb_views as $view) {
$crumbs->addCrumb($view);
}
$header = id(new PHUIHeaderView())
->setUser($viewer)
->setPolicyObject($document)
->setHeader($page_title);
if ($is_draft) {
$draft_tag = id(new PHUITagView())
->setName(pht('Draft'))
->setIcon('fa-spinner')
->setColor('pink')
->setType(PHUITagView::TYPE_SHADE);
$header->addTag($draft_tag);
} else if ($content) {
$header->setEpoch($content->getDateCreated());
}
$prop_list = null;
if ($properties) {
$prop_list = new PHUIPropertyGroupView();
$prop_list->addPropertyList($properties);
}
$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(
$move_notice,
$core_content,
));
if ($curtain) {
$page_content->setCurtain($curtain);
}
$timeline = $this->buildTransactionTimeline(
$document,
new PhrictionTransactionQuery());
$edit_engine = id(new PhrictionDocumentEditEngine())
->setViewer($viewer)
->setTargetObject($document);
$comment_view = $edit_engine
->buildEditEngineCommentView($document);
return $this->newPage()
->setTitle($page_title)
->setCrumbs($crumbs)
->setPageObjectPHIDs(array($document->getPHID()))
->appendChild(
array(
$page_content,
$prop_list,
phutil_tag(
'div',
array(
'class' => 'phui-document-view-pro-box',
),
array(
$children,
$timeline,
$comment_view,
)),
));
}
private function buildPropertyListView(
PhrictionDocument $document,
PhrictionContent $content,
$slug) {
$viewer = $this->getViewer();
$view = id(new PHUIPropertyListView())
->setUser($viewer);
$view->addProperty(
pht('Last Author'),
$viewer->renderHandle($content->getAuthorPHID()));
$view->addProperty(
pht('Last Edited'),
phabricator_datetime($content->getDateCreated(), $viewer));
return $view;
}
private function buildCurtain(
PhrictionDocument $document,
PhrictionContent $content) {
$viewer = $this->getViewer();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$document,
PhabricatorPolicyCapability::CAN_EDIT);
$slug = PhabricatorSlug::normalize($this->slug);
$id = $document->getID();
$curtain = $this->newCurtainView($document);
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Document'))
->setDisabled(!$can_edit)
->setIcon('fa-pencil')
->setHref('/phriction/edit/'.$document->getID().'/'));
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('View History'))
->setIcon('fa-history')
->setHref(PhrictionDocument::getSlugURI($slug, 'history')));
$is_current = false;
$content_id = null;
$is_draft = false;
if ($content) {
if ($content->getPHID() == $document->getContentPHID()) {
$is_current = true;
}
$content_id = $content->getID();
$current_version = $document->getContent()->getVersion();
$is_draft = ($content->getVersion() >= $current_version);
}
$can_publish = ($can_edit && $content && !$is_current);
if ($is_draft) {
$publish_name = pht('Publish Draft');
} else {
$publish_name = pht('Publish Revert');
}
// If you're looking at the current version; and it's an unpublished
// draft; and you can publish it, add a UI hint that this might be an
// interesting action to take.
$hint_publish = false;
if ($is_draft) {
if ($can_publish) {
if ($document->getMaxVersion() == $content->getVersion()) {
$hint_publish = true;
}
}
}
$publish_uri = "/phriction/publish/{$id}/{$content_id}/";
$curtain->addAction(
id(new PhabricatorActionView())
->setName($publish_name)
->setIcon('fa-upload')
->setSelected($hint_publish)
->setDisabled(!$can_publish)
->setWorkflow(true)
->setHref($publish_uri));
if ($document->getStatus() == PhrictionDocumentStatus::STATUS_EXISTS) {
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Move Document'))
->setDisabled(!$can_edit)
->setIcon('fa-arrows')
->setHref('/phriction/move/'.$document->getID().'/')
->setWorkflow(true));
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Delete Document'))
->setDisabled(!$can_edit)
->setIcon('fa-times')
->setHref('/phriction/delete/'.$document->getID().'/')
->setWorkflow(true));
}
$print_uri = PhrictionDocument::getSlugURI($slug).'?__print__=1';
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Printable Page'))
->setIcon('fa-print')
->setOpenInNewWindow(true)
->setHref($print_uri));
return $curtain;
}
private function renderDocumentChildren($slug) {
$d_child = PhabricatorSlug::getDepth($slug) + 1;
$d_grandchild = PhabricatorSlug::getDepth($slug) + 2;
$limit = 250;
$query = id(new PhrictionDocumentQuery())
->setViewer($this->getRequest()->getUser())
->withDepths(array($d_child, $d_grandchild))
->withSlugPrefix($slug == '/' ? '' : $slug)
->withStatuses(array(
PhrictionDocumentStatus::STATUS_EXISTS,
PhrictionDocumentStatus::STATUS_STUB,
))
->setLimit($limit)
->setOrder(PhrictionDocumentQuery::ORDER_HIERARCHY)
->needContent(true);
$children = $query->execute();
if (!$children) {
return;
}
// We're going to render in one of three modes to try to accommodate
// different information scales:
//
// - If we found fewer than $limit rows, we know we have all the children
// and grandchildren and there aren't all that many. We can just render
// everything.
// - If we found $limit rows but the results included some grandchildren,
// we just throw them out and render only the children, as we know we
// have them all.
// - If we found $limit rows and the results have no grandchildren, we
// have a ton of children. Render them and then let the user know that
// this is not an exhaustive list.
if (count($children) == $limit) {
$more_children = true;
foreach ($children as $child) {
if ($child->getDepth() == $d_grandchild) {
$more_children = false;
}
}
$show_grandchildren = false;
} else {
$show_grandchildren = true;
$more_children = false;
}
$children_dicts = array();
$grandchildren_dicts = array();
foreach ($children as $key => $child) {
$child_dict = array(
'slug' => $child->getSlug(),
'depth' => $child->getDepth(),
'title' => $child->getContent()->getTitle(),
);
if ($child->getDepth() == $d_child) {
$children_dicts[] = $child_dict;
continue;
} else {
unset($children[$key]);
if ($show_grandchildren) {
$ancestors = PhabricatorSlug::getAncestry($child->getSlug());
$grandchildren_dicts[end($ancestors)][] = $child_dict;
}
}
}
// Fill in any missing children.
$known_slugs = mpull($children, null, 'getSlug');
foreach ($grandchildren_dicts as $slug => $ignored) {
if (empty($known_slugs[$slug])) {
$children_dicts[] = array(
'slug' => $slug,
'depth' => $d_child,
'title' => PhabricatorSlug::getDefaultTitle($slug),
'empty' => true,
);
}
}
$children_dicts = isort($children_dicts, 'title');
$list = array();
foreach ($children_dicts as $child) {
$list[] = hsprintf('<li class="remarkup-list-item">');
$list[] = $this->renderChildDocumentLink($child);
$grand = idx($grandchildren_dicts, $child['slug'], array());
if ($grand) {
$list[] = hsprintf('<ul class="remarkup-list">');
foreach ($grand as $grandchild) {
$list[] = hsprintf('<li class="remarkup-list-item">');
$list[] = $this->renderChildDocumentLink($grandchild);
$list[] = hsprintf('</li>');
}
$list[] = hsprintf('</ul>');
}
$list[] = hsprintf('</li>');
}
if ($more_children) {
$list[] = phutil_tag(
'li',
array(
'class' => 'remarkup-list-item',
),
pht('More...'));
}
$header = id(new PHUIHeaderView())
->setHeader(pht('Document Hierarchy'));
$box = id(new PHUIObjectBoxView())
->setHeader($header)
->appendChild(phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup mlt mlb',
),
phutil_tag(
'ul',
array(
'class' => 'remarkup-list',
),
$list)));
return $box;
}
private function renderChildDocumentLink(array $info) {
$title = nonempty($info['title'], pht('(Untitled Document)'));
$item = phutil_tag(
'a',
array(
'href' => PhrictionDocument::getSlugURI($info['slug']),
),
$title);
if (isset($info['empty'])) {
$item = phutil_tag('em', array(), $item);
}
return $item;
}
protected function getDocumentSlug() {
return $this->slug;
}
protected function getToc($toc) {
if ($toc) {
$toc = phutil_tag_div('phui-document-toc-content', array(
phutil_tag_div(
'phui-document-toc-header',
pht('Contents')),
$toc,
));
}
return $toc;
}
}
diff --git a/src/applications/phriction/controller/PhrictionEditController.php b/src/applications/phriction/controller/PhrictionEditController.php
index 31879632de..9f59b63121 100644
--- a/src/applications/phriction/controller/PhrictionEditController.php
+++ b/src/applications/phriction/controller/PhrictionEditController.php
@@ -1,327 +1,337 @@
<?php
final class PhrictionEditController
extends PhrictionController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$max_version = null;
if ($id) {
$is_new = false;
$document = id(new PhrictionDocumentQuery())
->setViewer($viewer)
->withIDs(array($id))
->needContent(true)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$document) {
return new Aphront404Response();
}
$max_version = $document->getMaxVersion();
$revert = $request->getInt('revert');
if ($revert) {
$content = id(new PhrictionContentQuery())
->setViewer($viewer)
->withDocumentPHIDs(array($document->getPHID()))
->withVersions(array($revert))
->executeOne();
if (!$content) {
return new Aphront404Response();
}
} else {
$content = id(new PhrictionContentQuery())
->setViewer($viewer)
->withDocumentPHIDs(array($document->getPHID()))
->setLimit(1)
->executeOne();
}
} else {
$slug = $request->getStr('slug');
$slug = PhabricatorSlug::normalize($slug);
if (!$slug) {
return new Aphront404Response();
}
$document = id(new PhrictionDocumentQuery())
->setViewer($viewer)
->withSlugs(array($slug))
->needContent(true)
->executeOne();
if ($document) {
$content = id(new PhrictionContentQuery())
->setViewer($viewer)
->withDocumentPHIDs(array($document->getPHID()))
->setLimit(1)
->executeOne();
$max_version = $document->getMaxVersion();
$is_new = false;
} else {
$document = PhrictionDocument::initializeNewDocument($viewer, $slug);
$content = $document->getContent();
$is_new = true;
}
}
require_celerity_resource('phriction-document-css');
$e_title = true;
$e_content = true;
$validation_exception = null;
$notes = null;
$title = $content->getTitle();
$overwrite = false;
$v_cc = PhabricatorSubscribersQuery::loadSubscribersForPHID(
$document->getPHID());
if ($is_new) {
$v_projects = array();
} else {
$v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs(
$document->getPHID(),
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
$v_projects = array_reverse($v_projects);
}
$v_space = $document->getSpacePHID();
$content_text = $content->getContent();
$is_draft_mode = ($document->getContent()->getVersion() != $max_version);
if ($request->isFormPost()) {
- $save_as_draft = ($is_draft_mode || $request->getExists('draft'));
+ if ($is_new) {
+ $save_as_draft = false;
+ } else {
+ $save_as_draft = ($is_draft_mode || $request->getExists('draft'));
+ }
$title = $request->getStr('title');
$content_text = $request->getStr('content');
$notes = $request->getStr('description');
$max_version = $request->getInt('contentVersion');
$v_view = $request->getStr('viewPolicy');
$v_edit = $request->getStr('editPolicy');
$v_cc = $request->getArr('cc');
$v_projects = $request->getArr('projects');
$v_space = $request->getStr('spacePHID');
if ($save_as_draft) {
$edit_type = PhrictionDocumentDraftTransaction::TRANSACTIONTYPE;
} else {
$edit_type = PhrictionDocumentContentTransaction::TRANSACTIONTYPE;
}
$xactions = array();
+
$xactions[] = id(new PhrictionTransaction())
->setTransactionType(PhrictionDocumentTitleTransaction::TRANSACTIONTYPE)
->setNewValue($title);
$xactions[] = id(new PhrictionTransaction())
->setTransactionType($edit_type)
->setNewValue($content_text);
$xactions[] = id(new PhrictionTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($v_view);
$xactions[] = id(new PhrictionTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
->setNewValue($v_edit);
$xactions[] = id(new PhrictionTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_SPACE)
->setNewValue($v_space);
$xactions[] = id(new PhrictionTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setNewValue(array('=' => $v_cc));
$proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$xactions[] = id(new PhrictionTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $proj_edge_type)
->setNewValue(array('=' => array_fuse($v_projects)));
$editor = id(new PhrictionTransactionEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->setDescription($notes)
->setProcessContentVersionError(!$request->getBool('overwrite'))
->setContentVersion($max_version);
try {
$editor->applyTransactions($document, $xactions);
$uri = PhrictionDocument::getSlugURI($document->getSlug());
$uri = new PhutilURI($uri);
// If the user clicked "Save as Draft", take them to the draft, not
// to the current published page.
if ($save_as_draft) {
$uri = $uri->alter('v', $document->getMaxVersion());
}
return id(new AphrontRedirectResponse())->setURI($uri);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$e_title = nonempty(
$ex->getShortMessage(
PhrictionDocumentTitleTransaction::TRANSACTIONTYPE),
true);
$e_content = nonempty(
$ex->getShortMessage(
PhrictionDocumentContentTransaction::TRANSACTIONTYPE),
true);
// if we're not supposed to process the content version error, then
// overwrite that content...!
if (!$editor->getProcessContentVersionError()) {
$overwrite = true;
}
$document->setViewPolicy($v_view);
$document->setEditPolicy($v_edit);
$document->setSpacePHID($v_space);
}
}
if ($document->getID()) {
$page_title = pht('Edit Document: %s', $content->getTitle());
if ($overwrite) {
$submit_button = pht('Overwrite Changes');
} else {
$submit_button = pht('Save and Publish');
}
} else {
$submit_button = pht('Create Document');
$page_title = pht('Create Document');
}
$uri = $document->getSlug();
$uri = PhrictionDocument::getSlugURI($uri);
$uri = PhabricatorEnv::getProductionURI($uri);
$cancel_uri = PhrictionDocument::getSlugURI($document->getSlug());
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($document)
->execute();
$view_capability = PhabricatorPolicyCapability::CAN_VIEW;
$edit_capability = PhabricatorPolicyCapability::CAN_EDIT;
$form = id(new AphrontFormView())
->setUser($viewer)
->addHiddenInput('slug', $document->getSlug())
->addHiddenInput('contentVersion', $max_version)
->addHiddenInput('overwrite', $overwrite)
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Title'))
->setValue($title)
->setError($e_title)
->setName('title'))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel(pht('URI'))
->setValue($uri))
->appendChild(
id(new PhabricatorRemarkupControl())
->setLabel(pht('Content'))
->setValue($content_text)
->setError($e_content)
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
->setName('content')
->setID('document-textarea')
->setUser($viewer))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Tags'))
->setName('projects')
->setValue($v_projects)
->setDatasource(new PhabricatorProjectDatasource()))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Subscribers'))
->setName('cc')
->setValue($v_cc)
->setUser($viewer)
->setDatasource(new PhabricatorMetaMTAMailableDatasource()))
->appendChild(
id(new AphrontFormPolicyControl())
->setViewer($viewer)
->setName('viewPolicy')
->setSpacePHID($v_space)
->setPolicyObject($document)
->setCapability($view_capability)
->setPolicies($policies))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('editPolicy')
->setPolicyObject($document)
->setCapability($edit_capability)
->setPolicies($policies))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Edit Notes'))
->setValue($notes)
->setError(null)
->setName('description'));
if ($is_draft_mode) {
$form->appendControl(
id(new AphrontFormSubmitControl())
->addCancelButton($cancel_uri)
->setValue(pht('Save Draft')));
} else {
- $draft_button = id(new PHUIButtonView())
- ->setTag('input')
- ->setName('draft')
- ->setText(pht('Save as Draft'))
- ->setColor(PHUIButtonView::GREEN);
+ $submit = id(new AphrontFormSubmitControl());
+
+ if (!$is_new) {
+ $draft_button = id(new PHUIButtonView())
+ ->setTag('input')
+ ->setName('draft')
+ ->setText(pht('Save as Draft'))
+ ->setColor(PHUIButtonView::GREEN);
+ $submit->addButton($draft_button);
+ }
- $form->appendControl(
- id(new AphrontFormSubmitControl())
- ->addButton($draft_button)
- ->addCancelButton($cancel_uri)
- ->setValue($submit_button));
+ $submit
+ ->addCancelButton($cancel_uri)
+ ->setValue($submit_button);
+
+ $form->appendControl($submit);
}
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($page_title)
->setValidationException($validation_exception)
->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
->setForm($form);
$preview = id(new PHUIRemarkupPreviewPanel())
->setHeader($content->getTitle())
->setPreviewURI('/phriction/preview/'.$document->getSlug())
->setControlID('document-textarea')
->setPreviewType(PHUIRemarkupPreviewPanel::DOCUMENT);
$crumbs = $this->buildApplicationCrumbs();
if ($document->getID()) {
$crumbs->addTextCrumb(
$content->getTitle(),
PhrictionDocument::getSlugURI($document->getSlug()));
$crumbs->addTextCrumb(pht('Edit'));
} else {
$crumbs->addTextCrumb(pht('Create'));
}
$crumbs->setBorder(true);
$view = id(new PHUITwoColumnView())
->setFooter(
array(
$form_box,
$preview,
));
return $this->newPage()
->setTitle($page_title)
->setCrumbs($crumbs)
->appendChild($view);
}
}
diff --git a/src/applications/phriction/xaction/PhrictionDocumentContentTransaction.php b/src/applications/phriction/xaction/PhrictionDocumentContentTransaction.php
index de6d92aac6..f5f1305279 100644
--- a/src/applications/phriction/xaction/PhrictionDocumentContentTransaction.php
+++ b/src/applications/phriction/xaction/PhrictionDocumentContentTransaction.php
@@ -1,16 +1,32 @@
<?php
final class PhrictionDocumentContentTransaction
extends PhrictionDocumentEditTransaction {
const TRANSACTIONTYPE = 'content';
public function applyInternalEffects($object, $value) {
parent::applyInternalEffects($object, $value);
$object->setStatus(PhrictionDocumentStatus::STATUS_EXISTS);
$this->getEditor()->setShouldPublishContent($object, true);
}
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ // NOTE: This is slightly different from the draft validation. Here,
+ // we're validating that: you can't edit away a document; and you can't
+ // create an empty document.
+
+ $content = $object->getContent()->getContent();
+ if ($this->isEmptyTextTransaction($content, $xactions)) {
+ $errors[] = $this->newRequiredError(
+ pht('Documents must have content.'));
+ }
+
+ return $errors;
+ }
+
}
diff --git a/src/applications/phriction/xaction/PhrictionDocumentDraftTransaction.php b/src/applications/phriction/xaction/PhrictionDocumentDraftTransaction.php
index 91a4b4ade5..b2f39485fc 100644
--- a/src/applications/phriction/xaction/PhrictionDocumentDraftTransaction.php
+++ b/src/applications/phriction/xaction/PhrictionDocumentDraftTransaction.php
@@ -1,14 +1,35 @@
<?php
final class PhrictionDocumentDraftTransaction
extends PhrictionDocumentEditTransaction {
const TRANSACTIONTYPE = 'draft';
public function applyInternalEffects($object, $value) {
parent::applyInternalEffects($object, $value);
$this->getEditor()->setShouldPublishContent($object, false);
}
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ // NOTE: We're only validating that you can't edit a document down to
+ // nothing in a draft transaction. Alone, this doesn't prevent you from
+ // creating a document with no content. The content transaction has
+ // validation for that.
+
+ if (!$xactions) {
+ return $errors;
+ }
+
+ $content = $object->getContent()->getContent();
+ if ($this->isEmptyTextTransaction($content, $xactions)) {
+ $errors[] = $this->newRequiredError(
+ pht('Documents must have content.'));
+ }
+
+ return $errors;
+ }
+
}
diff --git a/src/applications/phriction/xaction/PhrictionDocumentEditTransaction.php b/src/applications/phriction/xaction/PhrictionDocumentEditTransaction.php
index 551e8c8c2a..3130658311 100644
--- a/src/applications/phriction/xaction/PhrictionDocumentEditTransaction.php
+++ b/src/applications/phriction/xaction/PhrictionDocumentEditTransaction.php
@@ -1,95 +1,82 @@
<?php
abstract class PhrictionDocumentEditTransaction
extends PhrictionDocumentVersionTransaction {
public function generateOldValue($object) {
if ($this->getEditor()->getIsNewObject()) {
return null;
}
// NOTE: We want to get the newest version of the content here, regardless
// of whether it's published or not.
$actor = $this->getActor();
return id(new PhrictionContentQuery())
->setViewer($actor)
->withDocumentPHIDs(array($object->getPHID()))
->setOrder('newest')
->setLimit(1)
->executeOne()
->getContent();
}
public function generateNewValue($object, $value) {
return $value;
}
public function applyInternalEffects($object, $value) {
$content = $this->getNewDocumentContent($object);
$content->setContent($value);
}
public function getActionStrength() {
return 1.3;
}
public function getActionName() {
return pht('Edited');
}
public function getTitle() {
return pht(
'%s edited the content of this document.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s edited the content of %s.',
$this->renderAuthor(),
$this->renderObject());
}
public function getMailDiffSectionHeader() {
return pht('CHANGES TO DOCUMENT CONTENT');
}
public function hasChangeDetailView() {
return true;
}
public function newChangeDetailView() {
$viewer = $this->getViewer();
return id(new PhabricatorApplicationTransactionTextDiffDetailView())
->setViewer($viewer)
->setOldText($this->getOldValue())
->setNewText($this->getNewValue());
}
public function newRemarkupChanges() {
$changes = array();
$changes[] = $this->newRemarkupChange()
->setOldValue($this->getOldValue())
->setNewValue($this->getNewValue());
return $changes;
}
- public function validateTransactions($object, array $xactions) {
- $errors = array();
-
- $content = $object->getContent()->getContent();
- if ($this->isEmptyTextTransaction($content, $xactions)) {
- $errors[] = $this->newRequiredError(
- pht('Documents must have content.'));
- }
-
- return $errors;
- }
-
-
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 13:39 (3 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1125148
Default Alt Text
(38 KB)

Event Timeline