mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 16:52:41 +01:00
Allow Phriction documents to be deleted
Summary: - Add a "delete" operation. Delete is just a special edit which removes the page from indexes and shows a notice that the document has been deleted. - When a user deletes all the content on a page, treat it as a delete. - When a conduit call deletes all the content on a page, treat it as a delete. - Add page status to Conduit. - Add change type field to history. - Added a couple of constants to support a future 'move' change, which would move content from one document to another. Test Plan: - Verified deleted pages vanish from the document index (and restoring them puts them back). - Verified deleted pages show "This page has been deleted...". - Created, edited and deleted a document via Conduit. - Deleted pages via "delete" button. - Deleted pages via editing content to nothing. Reviewers: btrahan, jungejason Reviewed By: btrahan CC: skrul, aran, btrahan, epriestley Maniphest Tasks: T680 Differential Revision: 1230
This commit is contained in:
parent
9d372dd54c
commit
afc2f8526b
23 changed files with 341 additions and 17 deletions
8
resources/sql/patches/087.phrictiondelete.sql
Normal file
8
resources/sql/patches/087.phrictiondelete.sql
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
ALTER TABLE phabricator_phriction.phriction_document
|
||||||
|
ADD status INT UNSIGNED NOT NULL DEFAULT 0;
|
||||||
|
|
||||||
|
ALTER TABLE phabricator_phriction.phriction_content
|
||||||
|
ADD changeType INT UNSIGNED NOT NULL DEFAULT 0;
|
||||||
|
|
||||||
|
ALTER TABLE phabricator_phriction.phriction_content
|
||||||
|
ADD changeRef INT UNSIGNED DEFAULT NULL;
|
|
@ -719,15 +719,18 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/symbol',
|
'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/symbol',
|
||||||
'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/toplevel',
|
'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/toplevel',
|
||||||
'PhrictionActionConstants' => 'applications/phriction/constants/action',
|
'PhrictionActionConstants' => 'applications/phriction/constants/action',
|
||||||
|
'PhrictionChangeType' => 'applications/phriction/constants/changetype',
|
||||||
'PhrictionConstants' => 'applications/phriction/constants/base',
|
'PhrictionConstants' => 'applications/phriction/constants/base',
|
||||||
'PhrictionContent' => 'applications/phriction/storage/content',
|
'PhrictionContent' => 'applications/phriction/storage/content',
|
||||||
'PhrictionController' => 'applications/phriction/controller/base',
|
'PhrictionController' => 'applications/phriction/controller/base',
|
||||||
'PhrictionDAO' => 'applications/phriction/storage/base',
|
'PhrictionDAO' => 'applications/phriction/storage/base',
|
||||||
|
'PhrictionDeleteController' => 'applications/phriction/controller/delete',
|
||||||
'PhrictionDiffController' => 'applications/phriction/controller/diff',
|
'PhrictionDiffController' => 'applications/phriction/controller/diff',
|
||||||
'PhrictionDocument' => 'applications/phriction/storage/document',
|
'PhrictionDocument' => 'applications/phriction/storage/document',
|
||||||
'PhrictionDocumentController' => 'applications/phriction/controller/document',
|
'PhrictionDocumentController' => 'applications/phriction/controller/document',
|
||||||
'PhrictionDocumentEditor' => 'applications/phriction/editor/document',
|
'PhrictionDocumentEditor' => 'applications/phriction/editor/document',
|
||||||
'PhrictionDocumentPreviewController' => 'applications/phriction/controller/documentpreview',
|
'PhrictionDocumentPreviewController' => 'applications/phriction/controller/documentpreview',
|
||||||
|
'PhrictionDocumentStatus' => 'applications/phriction/constants/documentstatus',
|
||||||
'PhrictionDocumentTestCase' => 'applications/phriction/storage/document/__tests__',
|
'PhrictionDocumentTestCase' => 'applications/phriction/storage/document/__tests__',
|
||||||
'PhrictionEditController' => 'applications/phriction/controller/edit',
|
'PhrictionEditController' => 'applications/phriction/controller/edit',
|
||||||
'PhrictionHistoryController' => 'applications/phriction/controller/history',
|
'PhrictionHistoryController' => 'applications/phriction/controller/history',
|
||||||
|
@ -1340,13 +1343,16 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorXHProfProfileSymbolView' => 'AphrontView',
|
'PhabricatorXHProfProfileSymbolView' => 'AphrontView',
|
||||||
'PhabricatorXHProfProfileTopLevelView' => 'AphrontView',
|
'PhabricatorXHProfProfileTopLevelView' => 'AphrontView',
|
||||||
'PhrictionActionConstants' => 'PhrictionConstants',
|
'PhrictionActionConstants' => 'PhrictionConstants',
|
||||||
|
'PhrictionChangeType' => 'PhrictionConstants',
|
||||||
'PhrictionContent' => 'PhrictionDAO',
|
'PhrictionContent' => 'PhrictionDAO',
|
||||||
'PhrictionController' => 'PhabricatorController',
|
'PhrictionController' => 'PhabricatorController',
|
||||||
'PhrictionDAO' => 'PhabricatorLiskDAO',
|
'PhrictionDAO' => 'PhabricatorLiskDAO',
|
||||||
|
'PhrictionDeleteController' => 'PhrictionController',
|
||||||
'PhrictionDiffController' => 'PhrictionController',
|
'PhrictionDiffController' => 'PhrictionController',
|
||||||
'PhrictionDocument' => 'PhrictionDAO',
|
'PhrictionDocument' => 'PhrictionDAO',
|
||||||
'PhrictionDocumentController' => 'PhrictionController',
|
'PhrictionDocumentController' => 'PhrictionController',
|
||||||
'PhrictionDocumentPreviewController' => 'PhrictionController',
|
'PhrictionDocumentPreviewController' => 'PhrictionController',
|
||||||
|
'PhrictionDocumentStatus' => 'PhrictionConstants',
|
||||||
'PhrictionDocumentTestCase' => 'PhabricatorTestCase',
|
'PhrictionDocumentTestCase' => 'PhabricatorTestCase',
|
||||||
'PhrictionEditController' => 'PhrictionController',
|
'PhrictionEditController' => 'PhrictionController',
|
||||||
'PhrictionHistoryController' => 'PhrictionController',
|
'PhrictionHistoryController' => 'PhrictionController',
|
||||||
|
|
|
@ -365,6 +365,7 @@ class AphrontDefaultApplicationConfiguration
|
||||||
'history/(?P<slug>.+/)$' => 'PhrictionHistoryController',
|
'history/(?P<slug>.+/)$' => 'PhrictionHistoryController',
|
||||||
|
|
||||||
'edit/(?:(?P<id>\d+)/)?$' => 'PhrictionEditController',
|
'edit/(?:(?P<id>\d+)/)?$' => 'PhrictionEditController',
|
||||||
|
'delete/(?P<id>\d+)/$' => 'PhrictionDeleteController',
|
||||||
|
|
||||||
'preview/$' => 'PhrictionDocumentPreviewController',
|
'preview/$' => 'PhrictionDocumentPreviewController',
|
||||||
'diff/(?P<id>\d+)/$' => 'PhrictionDiffController',
|
'diff/(?P<id>\d+)/$' => 'PhrictionDiffController',
|
||||||
|
|
|
@ -33,6 +33,8 @@ abstract class ConduitAPI_phriction_Method extends ConduitAPIMethod {
|
||||||
$uri = PhrictionDocument::getSlugURI($content->getSlug());
|
$uri = PhrictionDocument::getSlugURI($content->getSlug());
|
||||||
$uri = PhabricatorEnv::getProductionURI($uri);
|
$uri = PhabricatorEnv::getProductionURI($uri);
|
||||||
|
|
||||||
|
$doc_status = $doc->getStatus();
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'phid' => $doc->getPHID(),
|
'phid' => $doc->getPHID(),
|
||||||
'uri' => $uri,
|
'uri' => $uri,
|
||||||
|
@ -41,6 +43,7 @@ abstract class ConduitAPI_phriction_Method extends ConduitAPIMethod {
|
||||||
'authorPHID' => $content->getAuthorPHID(),
|
'authorPHID' => $content->getAuthorPHID(),
|
||||||
'title' => $content->getTitle(),
|
'title' => $content->getTitle(),
|
||||||
'content' => $content->getContent(),
|
'content' => $content->getContent(),
|
||||||
|
'status' => PhrictionDocumentStatus::getConduitConstant($doc_status),
|
||||||
'description' => $content->getDescription(),
|
'description' => $content->getDescription(),
|
||||||
'dateCreated' => $content->getDateCreated(),
|
'dateCreated' => $content->getDateCreated(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'applications/conduit/method/base');
|
phutil_require_module('phabricator', 'applications/conduit/method/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/phriction/constants/documentstatus');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||||
phutil_require_module('phabricator', 'infrastructure/env');
|
phutil_require_module('phabricator', 'infrastructure/env');
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,13 @@ class PhrictionActionConstants extends PhrictionConstants {
|
||||||
|
|
||||||
const ACTION_CREATE = 'create';
|
const ACTION_CREATE = 'create';
|
||||||
const ACTION_EDIT = 'edit';
|
const ACTION_EDIT = 'edit';
|
||||||
|
const ACTION_DELETE = 'delete';
|
||||||
|
|
||||||
public static function getActionPastTenseVerb($action) {
|
public static function getActionPastTenseVerb($action) {
|
||||||
static $map = array(
|
static $map = array(
|
||||||
self::ACTION_CREATE => 'created',
|
self::ACTION_CREATE => 'created',
|
||||||
self::ACTION_EDIT => 'edited',
|
self::ACTION_EDIT => 'edited',
|
||||||
|
self::ACTION_DELETE => 'deleted',
|
||||||
);
|
);
|
||||||
|
|
||||||
return idx($map, $action, "brazenly {$action}'d");
|
return idx($map, $action, "brazenly {$action}'d");
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group phriction
|
||||||
|
*/
|
||||||
|
final class PhrictionChangeType extends PhrictionConstants {
|
||||||
|
|
||||||
|
const CHANGE_EDIT = 0;
|
||||||
|
const CHANGE_DELETE = 1;
|
||||||
|
const CHANGE_MOVE_HERE = 2;
|
||||||
|
const CHANGE_MOVE_AWAY = 3;
|
||||||
|
|
||||||
|
public static function getChangeTypeLabel($const) {
|
||||||
|
static $map = array(
|
||||||
|
self::CHANGE_EDIT => 'Edit',
|
||||||
|
self::CHANGE_DELETE => 'Delete',
|
||||||
|
self::CHANGE_MOVE_HERE => 'Move Here',
|
||||||
|
self::CHANGE_MOVE_AWAY => 'Move Away',
|
||||||
|
);
|
||||||
|
|
||||||
|
return idx($map, $const, '???');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
src/applications/phriction/constants/changetype/__init__.php
Normal file
14
src/applications/phriction/constants/changetype/__init__.php
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'applications/phriction/constants/base');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhrictionChangeType.php');
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group phriction
|
||||||
|
*/
|
||||||
|
final class PhrictionDocumentStatus extends PhrictionConstants {
|
||||||
|
|
||||||
|
const STATUS_EXISTS = 0;
|
||||||
|
const STATUS_DELETED = 1;
|
||||||
|
|
||||||
|
public static function getConduitConstant($const) {
|
||||||
|
static $map = array(
|
||||||
|
self::STATUS_EXISTS => 'exists',
|
||||||
|
self::STATUS_DELETED => 'deleted',
|
||||||
|
);
|
||||||
|
|
||||||
|
return idx($map, $const, 'unknown');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'applications/phriction/constants/base');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhrictionDocumentStatus.php');
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group phriction
|
||||||
|
*/
|
||||||
|
class PhrictionDeleteController extends PhrictionController {
|
||||||
|
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->id = $data['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
|
$document = id(new PhrictionDocument())->load($this->id);
|
||||||
|
if (!$document) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$document_uri = PhrictionDocument::getSlugURI($document->getSlug());
|
||||||
|
|
||||||
|
if ($request->isFormPost()) {
|
||||||
|
$editor = id(PhrictionDocumentEditor::newForSlug($document->getSlug()))
|
||||||
|
->setUser($user)
|
||||||
|
->delete();
|
||||||
|
return id(new AphrontRedirectResponse())->setURI($document_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dialog = id(new AphrontDialogView())
|
||||||
|
->setUser($user)
|
||||||
|
->setTitle('Delete document?')
|
||||||
|
->appendChild(
|
||||||
|
'Really delete this document? You can recover it later by reverting '.
|
||||||
|
'to a previous version.')
|
||||||
|
->addSubmitButton('Delete')
|
||||||
|
->addCancelButton($document_uri);
|
||||||
|
|
||||||
|
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
src/applications/phriction/controller/delete/__init__.php
Normal file
20
src/applications/phriction/controller/delete/__init__.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/404');
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/dialog');
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||||
|
phutil_require_module('phabricator', 'applications/phriction/controller/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/phriction/editor/document');
|
||||||
|
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||||
|
phutil_require_module('phabricator', 'view/dialog');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhrictionDeleteController.php');
|
|
@ -205,6 +205,12 @@ class PhrictionDiffController
|
||||||
$document_id = $content->getDocumentID();
|
$document_id = $content->getDocumentID();
|
||||||
$version = $content->getVersion();
|
$version = $content->getVersion();
|
||||||
|
|
||||||
|
if ($content->getChangeType() == PhrictionChangeType::CHANGE_DELETE) {
|
||||||
|
// Don't show an edit/revert button for changes which deleted the content
|
||||||
|
// since it's silly.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if ($content->getID() == $current->getID()) {
|
if ($content->getID() == $current->getID()) {
|
||||||
return phutil_render_tag(
|
return phutil_render_tag(
|
||||||
'a',
|
'a',
|
||||||
|
|
|
@ -10,6 +10,7 @@ phutil_require_module('phabricator', 'aphront/response/404');
|
||||||
phutil_require_module('phabricator', 'aphront/response/ajax');
|
phutil_require_module('phabricator', 'aphront/response/ajax');
|
||||||
phutil_require_module('phabricator', 'applications/differential/parser/changeset');
|
phutil_require_module('phabricator', 'applications/differential/parser/changeset');
|
||||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||||
|
phutil_require_module('phabricator', 'applications/phriction/constants/changetype');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/controller/base');
|
phutil_require_module('phabricator', 'applications/phriction/controller/base');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||||
|
|
|
@ -120,12 +120,28 @@ class PhrictionDocumentController
|
||||||
|
|
||||||
$engine = PhabricatorMarkupEngine::newPhrictionMarkupEngine();
|
$engine = PhabricatorMarkupEngine::newPhrictionMarkupEngine();
|
||||||
|
|
||||||
|
$doc_status = $document->getStatus();
|
||||||
|
if ($doc_status == PhrictionDocumentStatus::STATUS_EXISTS) {
|
||||||
|
$core_content =
|
||||||
|
'<div class="phabricator-remarkup">'.
|
||||||
|
$engine->markupText($content->getContent()).
|
||||||
|
'</div>';
|
||||||
|
} else if ($doc_status == PhrictionDocumentStatus::STATUS_DELETED) {
|
||||||
|
$notice = new AphrontErrorView();
|
||||||
|
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
|
||||||
|
$notice->setTitle('Document Deleted');
|
||||||
|
$notice->appendChild(
|
||||||
|
'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 {
|
||||||
|
throw new Exception("Unknown document status '{$doc_status}'!");
|
||||||
|
}
|
||||||
|
|
||||||
$page_content =
|
$page_content =
|
||||||
'<div class="phriction-content">'.
|
'<div class="phriction-content">'.
|
||||||
$byline.
|
$byline.
|
||||||
'<div class="phabricator-remarkup">'.
|
$core_content.
|
||||||
$engine->markupText($content->getContent()).
|
|
||||||
'</div>'.
|
|
||||||
'</div>';
|
'</div>';
|
||||||
|
|
||||||
$edit_button = phutil_render_tag(
|
$edit_button = phutil_render_tag(
|
||||||
|
@ -134,7 +150,7 @@ class PhrictionDocumentController
|
||||||
'href' => '/phriction/edit/'.$document->getID().'/',
|
'href' => '/phriction/edit/'.$document->getID().'/',
|
||||||
'class' => 'button',
|
'class' => 'button',
|
||||||
),
|
),
|
||||||
'Edit Page');
|
'Edit Document');
|
||||||
$history_button = phutil_render_tag(
|
$history_button = phutil_render_tag(
|
||||||
'a',
|
'a',
|
||||||
array(
|
array(
|
||||||
|
@ -238,12 +254,14 @@ class PhrictionDocumentController
|
||||||
'SELECT d.slug, d.depth, c.title FROM %T d JOIN %T c
|
'SELECT d.slug, d.depth, c.title FROM %T d JOIN %T c
|
||||||
ON d.contentID = c.id
|
ON d.contentID = c.id
|
||||||
WHERE d.slug LIKE %> AND d.depth IN (%d, %d)
|
WHERE d.slug LIKE %> AND d.depth IN (%d, %d)
|
||||||
|
AND d.status = %d
|
||||||
ORDER BY d.depth, c.title LIMIT %d',
|
ORDER BY d.depth, c.title LIMIT %d',
|
||||||
$document_dao->getTableName(),
|
$document_dao->getTableName(),
|
||||||
$content_dao->getTableName(),
|
$content_dao->getTableName(),
|
||||||
($slug == '/' ? '' : $slug),
|
($slug == '/' ? '' : $slug),
|
||||||
$d_child,
|
$d_child,
|
||||||
$d_grandchild,
|
$d_grandchild,
|
||||||
|
PhrictionDocumentStatus::STATUS_EXISTS,
|
||||||
$limit);
|
$limit);
|
||||||
|
|
||||||
if (!$children) {
|
if (!$children) {
|
||||||
|
@ -329,12 +347,13 @@ class PhrictionDocumentController
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderChildDocumentLink(array $info) {
|
private function renderChildDocumentLink(array $info) {
|
||||||
|
$title = nonempty($info['title'], '(Untitled Document)');
|
||||||
$item = phutil_render_tag(
|
$item = phutil_render_tag(
|
||||||
'a',
|
'a',
|
||||||
array(
|
array(
|
||||||
'href' => PhrictionDocument::getSlugURI($info['slug']),
|
'href' => PhrictionDocument::getSlugURI($info['slug']),
|
||||||
),
|
),
|
||||||
phutil_escape_html($info['title']));
|
phutil_escape_html($title));
|
||||||
|
|
||||||
if (isset($info['empty'])) {
|
if (isset($info['empty'])) {
|
||||||
$item = '<em>'.$item.'</em>';
|
$item = '<em>'.$item.'</em>';
|
||||||
|
|
|
@ -11,6 +11,7 @@ phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||||
phutil_require_module('phabricator', 'applications/markup/engine');
|
phutil_require_module('phabricator', 'applications/markup/engine');
|
||||||
phutil_require_module('phabricator', 'applications/phid/handle');
|
phutil_require_module('phabricator', 'applications/phid/handle');
|
||||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||||
|
phutil_require_module('phabricator', 'applications/phriction/constants/documentstatus');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/controller/base');
|
phutil_require_module('phabricator', 'applications/phriction/controller/base');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||||
|
|
|
@ -116,9 +116,17 @@ class PhrictionEditController
|
||||||
if ($document->getID()) {
|
if ($document->getID()) {
|
||||||
$panel_header = 'Edit Phriction Document';
|
$panel_header = 'Edit Phriction Document';
|
||||||
$submit_button = 'Save Changes';
|
$submit_button = 'Save Changes';
|
||||||
|
$delete_button = phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/phriction/delete/'.$document->getID().'/',
|
||||||
|
'class' => 'grey button',
|
||||||
|
),
|
||||||
|
'Delete Document');
|
||||||
} else {
|
} else {
|
||||||
$panel_header = 'Create New Phriction Document';
|
$panel_header = 'Create New Phriction Document';
|
||||||
$submit_button = 'Create Document';
|
$submit_button = 'Create Document';
|
||||||
|
$delete_button = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$uri = $document->getSlug();
|
$uri = $document->getSlug();
|
||||||
|
@ -146,12 +154,6 @@ class PhrictionEditController
|
||||||
->setValue($content->getTitle())
|
->setValue($content->getTitle())
|
||||||
->setError($e_title)
|
->setError($e_title)
|
||||||
->setName('title'))
|
->setName('title'))
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormTextControl())
|
|
||||||
->setLabel('Description')
|
|
||||||
->setValue($content->getDescription())
|
|
||||||
->setError(null)
|
|
||||||
->setName('description'))
|
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormStaticControl())
|
id(new AphrontFormStaticControl())
|
||||||
->setLabel('URI')
|
->setLabel('URI')
|
||||||
|
@ -165,6 +167,12 @@ class PhrictionEditController
|
||||||
->setID('document-textarea')
|
->setID('document-textarea')
|
||||||
->setEnableDragAndDropFileUploads(true)
|
->setEnableDragAndDropFileUploads(true)
|
||||||
->setCaption($remarkup_reference))
|
->setCaption($remarkup_reference))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormTextControl())
|
||||||
|
->setLabel('Edit Notes')
|
||||||
|
->setValue($content->getDescription())
|
||||||
|
->setError(null)
|
||||||
|
->setName('description'))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormSubmitControl())
|
id(new AphrontFormSubmitControl())
|
||||||
->addCancelButton($cancel_uri)
|
->addCancelButton($cancel_uri)
|
||||||
|
@ -175,6 +183,10 @@ class PhrictionEditController
|
||||||
->setHeader($panel_header)
|
->setHeader($panel_header)
|
||||||
->appendChild($form);
|
->appendChild($form);
|
||||||
|
|
||||||
|
if ($delete_button) {
|
||||||
|
$panel->addButton($delete_button);
|
||||||
|
}
|
||||||
|
|
||||||
$preview_panel =
|
$preview_panel =
|
||||||
'<div class="aphront-panel-preview aphront-panel-preview-wide">
|
'<div class="aphront-panel-preview aphront-panel-preview-wide">
|
||||||
<div class="phriction-document-preview-header">
|
<div class="phriction-document-preview-header">
|
||||||
|
|
|
@ -93,6 +93,9 @@ class PhrictionHistoryController
|
||||||
'Show Later Changes');
|
'Show Later Changes');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$change_type = PhrictionChangeType::getChangeTypeLabel(
|
||||||
|
$content->getChangeType());
|
||||||
|
|
||||||
$rows[] = array(
|
$rows[] = array(
|
||||||
phabricator_date($content->getDateCreated(), $user),
|
phabricator_date($content->getDateCreated(), $user),
|
||||||
phabricator_time($content->getDateCreated(), $user),
|
phabricator_time($content->getDateCreated(), $user),
|
||||||
|
@ -103,6 +106,7 @@ class PhrictionHistoryController
|
||||||
),
|
),
|
||||||
'Version '.$version),
|
'Version '.$version),
|
||||||
$handles[$content->getAuthorPHID()]->renderLink(),
|
$handles[$content->getAuthorPHID()]->renderLink(),
|
||||||
|
$change_type,
|
||||||
phutil_escape_html($content->getDescription()),
|
phutil_escape_html($content->getDescription()),
|
||||||
$vs_previous,
|
$vs_previous,
|
||||||
$vs_head,
|
$vs_head,
|
||||||
|
@ -131,6 +135,7 @@ class PhrictionHistoryController
|
||||||
'Time',
|
'Time',
|
||||||
'Version',
|
'Version',
|
||||||
'Author',
|
'Author',
|
||||||
|
'Type',
|
||||||
'Description',
|
'Description',
|
||||||
'Against Previous',
|
'Against Previous',
|
||||||
'Against Current',
|
'Against Current',
|
||||||
|
@ -141,6 +146,7 @@ class PhrictionHistoryController
|
||||||
'right',
|
'right',
|
||||||
'pri',
|
'pri',
|
||||||
'',
|
'',
|
||||||
|
'',
|
||||||
'wide',
|
'wide',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'aphront/response/404');
|
phutil_require_module('phabricator', 'aphront/response/404');
|
||||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||||
|
phutil_require_module('phabricator', 'applications/phriction/constants/changetype');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/controller/base');
|
phutil_require_module('phabricator', 'applications/phriction/controller/base');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||||
|
|
|
@ -89,17 +89,53 @@ final class PhrictionDocumentEditor {
|
||||||
return $this->document;
|
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() {
|
public function save() {
|
||||||
if (!$this->user) {
|
if (!$this->user) {
|
||||||
throw new Exception("Call setUser() before save()!");
|
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;
|
$document = $this->document;
|
||||||
$content = $this->content;
|
$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 = new PhrictionContent();
|
||||||
$new_content->setSlug($document->getSlug());
|
$new_content->setSlug($document->getSlug());
|
||||||
$new_content->setAuthorPHID($this->user->getPHID());
|
$new_content->setAuthorPHID($this->user->getPHID());
|
||||||
|
$new_content->setChangeType(PhrictionChangeType::CHANGE_EDIT);
|
||||||
|
|
||||||
$new_content->setTitle(
|
$new_content->setTitle(
|
||||||
coalesce(
|
coalesce(
|
||||||
|
@ -115,12 +151,44 @@ final class PhrictionDocumentEditor {
|
||||||
$new_content->setDescription($this->description);
|
$new_content->setDescription($this->description);
|
||||||
}
|
}
|
||||||
|
|
||||||
$new_content->setVersion($content->getVersion() + 1);
|
return $new_content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateDocument($document, $content, $new_content) {
|
||||||
|
|
||||||
// TODO: This should be transactional.
|
|
||||||
$is_new = false;
|
$is_new = false;
|
||||||
if (!$document->getID()) {
|
if (!$document->getID()) {
|
||||||
$is_new = true;
|
$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();
|
$document->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,9 +213,7 @@ final class PhrictionDocumentEditor {
|
||||||
->setStoryData(
|
->setStoryData(
|
||||||
array(
|
array(
|
||||||
'phid' => $document->getPHID(),
|
'phid' => $document->getPHID(),
|
||||||
'action' => $is_new
|
'action' => $feed_action,
|
||||||
? PhrictionActionConstants::ACTION_CREATE
|
|
||||||
: PhrictionActionConstants::ACTION_EDIT,
|
|
||||||
'content' => phutil_utf8_shorten($new_content->getContent(), 140),
|
'content' => phutil_utf8_shorten($new_content->getContent(), 140),
|
||||||
))
|
))
|
||||||
->publish();
|
->publish();
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
phutil_require_module('phabricator', 'applications/feed/constants/story');
|
phutil_require_module('phabricator', 'applications/feed/constants/story');
|
||||||
phutil_require_module('phabricator', 'applications/feed/publisher');
|
phutil_require_module('phabricator', 'applications/feed/publisher');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/constants/action');
|
phutil_require_module('phabricator', 'applications/phriction/constants/action');
|
||||||
|
phutil_require_module('phabricator', 'applications/phriction/constants/changetype');
|
||||||
|
phutil_require_module('phabricator', 'applications/phriction/constants/documentstatus');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
phutil_require_module('phabricator', 'applications/phriction/storage/content');
|
||||||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||||
phutil_require_module('phabricator', 'applications/search/index/indexer/phriction');
|
phutil_require_module('phabricator', 'applications/search/index/indexer/phriction');
|
||||||
|
|
|
@ -31,4 +31,7 @@ class PhrictionContent extends PhrictionDAO {
|
||||||
protected $content;
|
protected $content;
|
||||||
protected $description;
|
protected $description;
|
||||||
|
|
||||||
|
protected $changeType;
|
||||||
|
protected $changeRef;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ class PhrictionDocument extends PhrictionDAO {
|
||||||
protected $slug;
|
protected $slug;
|
||||||
protected $depth;
|
protected $depth;
|
||||||
protected $contentID;
|
protected $contentID;
|
||||||
|
protected $status;
|
||||||
|
|
||||||
private $contentObject;
|
private $contentObject;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue