1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-29 02:02:41 +01:00
phorge-phorge/src/applications/phriction/editor/PhrictionDocumentEditor.php

242 lines
6.2 KiB
PHP
Raw Normal View History

<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Create or update Phriction documents.
2011-09-14 17:02:31 +02:00
*
* @group phriction
*/
final class PhrictionDocumentEditor {
private $document;
private $content;
private $user;
private $newTitle;
private $newContent;
private $description;
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 setUser(PhabricatorUser $user) {
$this->user = $user;
return $this;
}
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 delete() {
if (!$this->user) {
throw new Exception("Call setUser() before deleting a document!");
}
// TODO: Should we do anything about deleting an already-deleted document?
// We currently allow it.
$document = $this->document;
$content = $this->content;
$new_content = $this->buildContentTemplate($document, $content);
$new_content->setChangeType(PhrictionChangeType::CHANGE_DELETE);
$new_content->setContent('');
return $this->updateDocument($document, $content, $new_content);
}
public function save() {
if (!$this->user) {
throw new Exception("Call setUser() before updating a document!");
}
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->user->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;
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);
PhabricatorSearchPhrictionIndexer::indexDocument($document);
$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->user->getPHID(),
);
if ($project_phid) {
$related_phids[] = $project_phid;
}
id(new PhabricatorFeedStoryPublisher())
->setRelatedPHIDs($related_phids)
->setStoryAuthorPHID($this->user->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,
))
->publish();
return $this;
}
}