mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-28 23:48:19 +01:00
File - add transactions and editor
Summary: this ends up being a little weird since you can't actually edit files. Also, since we create files all sorts of ways, sometimes without even having a user, we don't bother logging transactions for those events. Fixes T3651. Turns out this work is important for T3612, which is a priority of mine to help get Pholio out the door. Test Plan: left a comment on a file. it worked! use bin/mail to verify mail content looked correct. Reviewers: epriestley Reviewed By: epriestley CC: Korvin, aran, wez Maniphest Tasks: T3651, T3612 Differential Revision: https://secure.phabricator.com/D6789
This commit is contained in:
parent
4b061a766a
commit
228496cdbe
24 changed files with 585 additions and 17 deletions
32
resources/sql/patches/20130820.file-mailkey-populate.php
Normal file
32
resources/sql/patches/20130820.file-mailkey-populate.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
echo "Populating Phabricator files with mail keys xactions...\n";
|
||||||
|
|
||||||
|
$table = new PhabricatorFile();
|
||||||
|
$table_name = $table->getTableName();
|
||||||
|
|
||||||
|
$conn_w = $table->establishConnection('w');
|
||||||
|
$conn_w->openTransaction();
|
||||||
|
|
||||||
|
$sql = array();
|
||||||
|
foreach (new LiskRawMigrationIterator($conn_w, 'file') as $row) {
|
||||||
|
$sql[] = qsprintf(
|
||||||
|
$conn_w,
|
||||||
|
'(%d, %s)',
|
||||||
|
$row['id'],
|
||||||
|
Filesystem::readRandomCharacters(20));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($sql) {
|
||||||
|
foreach (PhabricatorLiskDAO::chunkSQL($sql, ', ') as $chunk) {
|
||||||
|
queryfx(
|
||||||
|
$conn_w,
|
||||||
|
'INSERT INTO %T (id, mailKey) VALUES %Q '.
|
||||||
|
'ON DUPLICATE KEY UPDATE mailKey = VALUES(mailKey)',
|
||||||
|
$table_name,
|
||||||
|
$chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$table->saveTransaction();
|
||||||
|
echo "Done.\n";
|
2
resources/sql/patches/20130820.filemailkey.sql
Normal file
2
resources/sql/patches/20130820.filemailkey.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_file.file
|
||||||
|
ADD `mailKey` varchar(20) NOT NULL;
|
42
resources/sql/patches/20130820.filexactions.sql
Normal file
42
resources/sql/patches/20130820.filexactions.sql
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
CREATE TABLE {$NAMESPACE}_file.file_transaction (
|
||||||
|
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
phid VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
authorPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
objectPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
viewPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
editPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
commentPHID VARCHAR(64) COLLATE utf8_bin,
|
||||||
|
commentVersion INT UNSIGNED NOT NULL,
|
||||||
|
transactionType VARCHAR(32) NOT NULL COLLATE utf8_bin,
|
||||||
|
oldValue LONGTEXT NOT NULL COLLATE utf8_bin,
|
||||||
|
newValue LONGTEXT NOT NULL COLLATE utf8_bin,
|
||||||
|
contentSource LONGTEXT NOT NULL COLLATE utf8_bin,
|
||||||
|
metadata LONGTEXT NOT NULL COLLATE utf8_bin,
|
||||||
|
dateCreated INT UNSIGNED NOT NULL,
|
||||||
|
dateModified INT UNSIGNED NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE KEY `key_phid` (phid),
|
||||||
|
KEY `key_object` (objectPHID)
|
||||||
|
|
||||||
|
) ENGINE=InnoDB, COLLATE utf8_general_ci;
|
||||||
|
|
||||||
|
CREATE TABLE {$NAMESPACE}_file.file_transaction_comment (
|
||||||
|
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
phid VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
transactionPHID VARCHAR(64) COLLATE utf8_bin,
|
||||||
|
authorPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
viewPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
editPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
commentVersion INT UNSIGNED NOT NULL,
|
||||||
|
content LONGTEXT NOT NULL COLLATE utf8_bin,
|
||||||
|
contentSource LONGTEXT NOT NULL COLLATE utf8_bin,
|
||||||
|
isDeleted BOOL NOT NULL,
|
||||||
|
dateCreated INT UNSIGNED NOT NULL,
|
||||||
|
dateModified INT UNSIGNED NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE KEY `key_phid` (phid),
|
||||||
|
UNIQUE KEY `key_version` (transactionPHID, commentVersion),
|
||||||
|
UNIQUE KEY `key_draft` (authorPHID, transactionPHID)
|
||||||
|
|
||||||
|
) ENGINE=InnoDB, COLLATE utf8_general_ci;
|
||||||
|
|
|
@ -596,7 +596,9 @@ phutil_register_library_map(array(
|
||||||
'FeedPublisherHTTPWorker' => 'applications/feed/worker/FeedPublisherHTTPWorker.php',
|
'FeedPublisherHTTPWorker' => 'applications/feed/worker/FeedPublisherHTTPWorker.php',
|
||||||
'FeedPublisherWorker' => 'applications/feed/worker/FeedPublisherWorker.php',
|
'FeedPublisherWorker' => 'applications/feed/worker/FeedPublisherWorker.php',
|
||||||
'FeedPushWorker' => 'applications/feed/worker/FeedPushWorker.php',
|
'FeedPushWorker' => 'applications/feed/worker/FeedPushWorker.php',
|
||||||
'FilesCreateMailReceiver' => 'applications/files/mail/FilesCreateMailReceiver.php',
|
'FileCreateMailReceiver' => 'applications/files/mail/FileCreateMailReceiver.php',
|
||||||
|
'FileMailReceiver' => 'applications/files/mail/FileMailReceiver.php',
|
||||||
|
'FileReplyHandler' => 'applications/files/mail/FileReplyHandler.php',
|
||||||
'HarbormasterDAO' => 'applications/harbormaster/storage/HarbormasterDAO.php',
|
'HarbormasterDAO' => 'applications/harbormaster/storage/HarbormasterDAO.php',
|
||||||
'HarbormasterObject' => 'applications/harbormaster/storage/HarbormasterObject.php',
|
'HarbormasterObject' => 'applications/harbormaster/storage/HarbormasterObject.php',
|
||||||
'HarbormasterRunnerWorker' => 'applications/harbormaster/worker/HarbormasterRunnerWorker.php',
|
'HarbormasterRunnerWorker' => 'applications/harbormaster/worker/HarbormasterRunnerWorker.php',
|
||||||
|
@ -1161,11 +1163,13 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorFeedStoryStatus' => 'applications/feed/story/PhabricatorFeedStoryStatus.php',
|
'PhabricatorFeedStoryStatus' => 'applications/feed/story/PhabricatorFeedStoryStatus.php',
|
||||||
'PhabricatorFeedStoryTypeConstants' => 'applications/feed/constants/PhabricatorFeedStoryTypeConstants.php',
|
'PhabricatorFeedStoryTypeConstants' => 'applications/feed/constants/PhabricatorFeedStoryTypeConstants.php',
|
||||||
'PhabricatorFile' => 'applications/files/storage/PhabricatorFile.php',
|
'PhabricatorFile' => 'applications/files/storage/PhabricatorFile.php',
|
||||||
|
'PhabricatorFileCommentController' => 'applications/files/controller/PhabricatorFileCommentController.php',
|
||||||
'PhabricatorFileController' => 'applications/files/controller/PhabricatorFileController.php',
|
'PhabricatorFileController' => 'applications/files/controller/PhabricatorFileController.php',
|
||||||
'PhabricatorFileDAO' => 'applications/files/storage/PhabricatorFileDAO.php',
|
'PhabricatorFileDAO' => 'applications/files/storage/PhabricatorFileDAO.php',
|
||||||
'PhabricatorFileDataController' => 'applications/files/controller/PhabricatorFileDataController.php',
|
'PhabricatorFileDataController' => 'applications/files/controller/PhabricatorFileDataController.php',
|
||||||
'PhabricatorFileDeleteController' => 'applications/files/controller/PhabricatorFileDeleteController.php',
|
'PhabricatorFileDeleteController' => 'applications/files/controller/PhabricatorFileDeleteController.php',
|
||||||
'PhabricatorFileDropUploadController' => 'applications/files/controller/PhabricatorFileDropUploadController.php',
|
'PhabricatorFileDropUploadController' => 'applications/files/controller/PhabricatorFileDropUploadController.php',
|
||||||
|
'PhabricatorFileEditor' => 'applications/files/editor/PhabricatorFileEditor.php',
|
||||||
'PhabricatorFileImageMacro' => 'applications/macro/storage/PhabricatorFileImageMacro.php',
|
'PhabricatorFileImageMacro' => 'applications/macro/storage/PhabricatorFileImageMacro.php',
|
||||||
'PhabricatorFileInfoController' => 'applications/files/controller/PhabricatorFileInfoController.php',
|
'PhabricatorFileInfoController' => 'applications/files/controller/PhabricatorFileInfoController.php',
|
||||||
'PhabricatorFileLinkListView' => 'view/layout/PhabricatorFileLinkListView.php',
|
'PhabricatorFileLinkListView' => 'view/layout/PhabricatorFileLinkListView.php',
|
||||||
|
@ -1181,6 +1185,9 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorFileStorageEngineSelector' => 'applications/files/engineselector/PhabricatorFileStorageEngineSelector.php',
|
'PhabricatorFileStorageEngineSelector' => 'applications/files/engineselector/PhabricatorFileStorageEngineSelector.php',
|
||||||
'PhabricatorFileTestCase' => 'applications/files/storage/__tests__/PhabricatorFileTestCase.php',
|
'PhabricatorFileTestCase' => 'applications/files/storage/__tests__/PhabricatorFileTestCase.php',
|
||||||
'PhabricatorFileTestDataGenerator' => 'applications/files/lipsum/PhabricatorFileTestDataGenerator.php',
|
'PhabricatorFileTestDataGenerator' => 'applications/files/lipsum/PhabricatorFileTestDataGenerator.php',
|
||||||
|
'PhabricatorFileTransaction' => 'applications/files/storage/PhabricatorFileTransaction.php',
|
||||||
|
'PhabricatorFileTransactionComment' => 'applications/files/storage/PhabricatorFileTransactionComment.php',
|
||||||
|
'PhabricatorFileTransactionQuery' => 'applications/files/query/PhabricatorFileTransactionQuery.php',
|
||||||
'PhabricatorFileTransformController' => 'applications/files/controller/PhabricatorFileTransformController.php',
|
'PhabricatorFileTransformController' => 'applications/files/controller/PhabricatorFileTransformController.php',
|
||||||
'PhabricatorFileUploadController' => 'applications/files/controller/PhabricatorFileUploadController.php',
|
'PhabricatorFileUploadController' => 'applications/files/controller/PhabricatorFileUploadController.php',
|
||||||
'PhabricatorFileUploadDialogController' => 'applications/files/controller/PhabricatorFileUploadDialogController.php',
|
'PhabricatorFileUploadDialogController' => 'applications/files/controller/PhabricatorFileUploadDialogController.php',
|
||||||
|
@ -2631,7 +2638,9 @@ phutil_register_library_map(array(
|
||||||
'FeedPublisherHTTPWorker' => 'FeedPushWorker',
|
'FeedPublisherHTTPWorker' => 'FeedPushWorker',
|
||||||
'FeedPublisherWorker' => 'FeedPushWorker',
|
'FeedPublisherWorker' => 'FeedPushWorker',
|
||||||
'FeedPushWorker' => 'PhabricatorWorker',
|
'FeedPushWorker' => 'PhabricatorWorker',
|
||||||
'FilesCreateMailReceiver' => 'PhabricatorMailReceiver',
|
'FileCreateMailReceiver' => 'PhabricatorMailReceiver',
|
||||||
|
'FileMailReceiver' => 'PhabricatorObjectMailReceiver',
|
||||||
|
'FileReplyHandler' => 'PhabricatorMailReplyHandler',
|
||||||
'HarbormasterDAO' => 'PhabricatorLiskDAO',
|
'HarbormasterDAO' => 'PhabricatorLiskDAO',
|
||||||
'HarbormasterObject' => 'HarbormasterDAO',
|
'HarbormasterObject' => 'HarbormasterDAO',
|
||||||
'HarbormasterRunnerWorker' => 'PhabricatorWorker',
|
'HarbormasterRunnerWorker' => 'PhabricatorWorker',
|
||||||
|
@ -3245,13 +3254,17 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorFile' =>
|
'PhabricatorFile' =>
|
||||||
array(
|
array(
|
||||||
0 => 'PhabricatorFileDAO',
|
0 => 'PhabricatorFileDAO',
|
||||||
1 => 'PhabricatorPolicyInterface',
|
1 => 'PhabricatorTokenReceiverInterface',
|
||||||
|
2 => 'PhabricatorSubscribableInterface',
|
||||||
|
3 => 'PhabricatorPolicyInterface',
|
||||||
),
|
),
|
||||||
|
'PhabricatorFileCommentController' => 'PhabricatorFileController',
|
||||||
'PhabricatorFileController' => 'PhabricatorController',
|
'PhabricatorFileController' => 'PhabricatorController',
|
||||||
'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
|
||||||
'PhabricatorFileDataController' => 'PhabricatorFileController',
|
'PhabricatorFileDataController' => 'PhabricatorFileController',
|
||||||
'PhabricatorFileDeleteController' => 'PhabricatorFileController',
|
'PhabricatorFileDeleteController' => 'PhabricatorFileController',
|
||||||
'PhabricatorFileDropUploadController' => 'PhabricatorFileController',
|
'PhabricatorFileDropUploadController' => 'PhabricatorFileController',
|
||||||
|
'PhabricatorFileEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
'PhabricatorFileImageMacro' =>
|
'PhabricatorFileImageMacro' =>
|
||||||
array(
|
array(
|
||||||
0 => 'PhabricatorFileDAO',
|
0 => 'PhabricatorFileDAO',
|
||||||
|
@ -3275,6 +3288,9 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorFileStorageConfigurationException' => 'Exception',
|
'PhabricatorFileStorageConfigurationException' => 'Exception',
|
||||||
'PhabricatorFileTestCase' => 'PhabricatorTestCase',
|
'PhabricatorFileTestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorFileTestDataGenerator' => 'PhabricatorTestDataGenerator',
|
'PhabricatorFileTestDataGenerator' => 'PhabricatorTestDataGenerator',
|
||||||
|
'PhabricatorFileTransaction' => 'PhabricatorApplicationTransaction',
|
||||||
|
'PhabricatorFileTransactionComment' => 'PhabricatorApplicationTransactionComment',
|
||||||
|
'PhabricatorFileTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
'PhabricatorFileTransformController' => 'PhabricatorFileController',
|
'PhabricatorFileTransformController' => 'PhabricatorFileController',
|
||||||
'PhabricatorFileUploadController' => 'PhabricatorFileController',
|
'PhabricatorFileUploadController' => 'PhabricatorFileController',
|
||||||
'PhabricatorFileUploadDialogController' => 'PhabricatorFileController',
|
'PhabricatorFileUploadDialogController' => 'PhabricatorFileController',
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
final class PhabricatorApplicationFiles extends PhabricatorApplication {
|
final class PhabricatorApplicationFiles extends PhabricatorApplication {
|
||||||
|
|
||||||
public function getBaseURI() {
|
public function getBaseURI() {
|
||||||
|
@ -48,6 +51,7 @@ final class PhabricatorApplicationFiles extends PhabricatorApplication {
|
||||||
'(query/(?P<key>[^/]+)/)?' => 'PhabricatorFileListController',
|
'(query/(?P<key>[^/]+)/)?' => 'PhabricatorFileListController',
|
||||||
'upload/' => 'PhabricatorFileUploadController',
|
'upload/' => 'PhabricatorFileUploadController',
|
||||||
'dropupload/' => 'PhabricatorFileDropUploadController',
|
'dropupload/' => 'PhabricatorFileDropUploadController',
|
||||||
|
'comment/(?P<id>[1-9]\d*)/' => 'PhabricatorFileCommentController',
|
||||||
'delete/(?P<id>[1-9]\d*)/' => 'PhabricatorFileDeleteController',
|
'delete/(?P<id>[1-9]\d*)/' => 'PhabricatorFileDeleteController',
|
||||||
'info/(?P<phid>[^/]+)/' => 'PhabricatorFileInfoController',
|
'info/(?P<phid>[^/]+)/' => 'PhabricatorFileInfoController',
|
||||||
'data/(?P<key>[^/]+)/(?P<phid>[^/]+)/.*'
|
'data/(?P<key>[^/]+)/(?P<phid>[^/]+)/.*'
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group conduit
|
||||||
|
*/
|
||||||
abstract class ConduitAPI_file_Method extends ConduitAPIMethod {
|
abstract class ConduitAPI_file_Method extends ConduitAPIMethod {
|
||||||
|
|
||||||
public function getApplication() {
|
public function getApplication() {
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
final class PhabricatorFilesConfigOptions
|
final class PhabricatorFilesConfigOptions
|
||||||
extends PhabricatorApplicationConfigOptions {
|
extends PhabricatorApplicationConfigOptions {
|
||||||
|
|
||||||
|
@ -158,7 +161,12 @@ final class PhabricatorFilesConfigOptions
|
||||||
'metamta.files.public-create-email',
|
'metamta.files.public-create-email',
|
||||||
'string',
|
'string',
|
||||||
null)
|
null)
|
||||||
->setDescription(pht('Allow uploaded files via email.')),
|
->setDescription(pht('Allow uploaded files via email.')),
|
||||||
|
$this->newOption(
|
||||||
|
'metamta.files.subject-prefix',
|
||||||
|
'string',
|
||||||
|
'[File]')
|
||||||
|
->setDescription(pht('Subject prefix for paste email.')),
|
||||||
$this->newOption('files.enable-imagemagick', 'bool', false)
|
$this->newOption('files.enable-imagemagick', 'bool', false)
|
||||||
->setBoolOptions(
|
->setBoolOptions(
|
||||||
array(
|
array(
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
|
final class PhabricatorFileCommentController
|
||||||
|
extends PhabricatorFileController {
|
||||||
|
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->id = idx($data, 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
|
if (!$request->isFormPost()) {
|
||||||
|
return new Aphront400Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = id(new PhabricatorFileQuery())
|
||||||
|
->setViewer($user)
|
||||||
|
->withIDs(array($this->id))
|
||||||
|
->executeOne();
|
||||||
|
if (!$file) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$is_preview = $request->isPreviewRequest();
|
||||||
|
$draft = PhabricatorDraft::buildFromRequest($request);
|
||||||
|
|
||||||
|
$view_uri = $file->getInfoURI();
|
||||||
|
|
||||||
|
$xactions = array();
|
||||||
|
$xactions[] = id(new PhabricatorFileTransaction())
|
||||||
|
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
|
||||||
|
->attachComment(
|
||||||
|
id(new PhabricatorFileTransactionComment())
|
||||||
|
->setContent($request->getStr('comment')));
|
||||||
|
|
||||||
|
$editor = id(new PhabricatorFileEditor())
|
||||||
|
->setActor($user)
|
||||||
|
->setContinueOnNoEffect($request->isContinueRequest())
|
||||||
|
->setContentSourceFromRequest($request)
|
||||||
|
->setIsPreview($is_preview);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$xactions = $editor->applyTransactions($file, $xactions);
|
||||||
|
} catch (PhabricatorApplicationTransactionNoEffectException $ex) {
|
||||||
|
return id(new PhabricatorApplicationTransactionNoEffectResponse())
|
||||||
|
->setCancelURI($view_uri)
|
||||||
|
->setException($ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($draft) {
|
||||||
|
$draft->replaceOrDelete();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->isAjax()) {
|
||||||
|
return id(new PhabricatorApplicationTransactionResponse())
|
||||||
|
->setViewer($user)
|
||||||
|
->setTransactions($xactions)
|
||||||
|
->setIsPreview($is_preview)
|
||||||
|
->setAnchorOffset($request->getStr('anchor'));
|
||||||
|
} else {
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI($view_uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,8 +21,13 @@ final class PhabricatorFileInfoController extends PhabricatorFileController {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->loadHandles(array($file->getAuthorPHID()));
|
|
||||||
$phid = $file->getPHID();
|
$phid = $file->getPHID();
|
||||||
|
$xactions = id(new PhabricatorFileTransactionQuery())
|
||||||
|
->setViewer($user)
|
||||||
|
->withObjectPHIDs(array($phid))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$this->loadHandles(array($file->getAuthorPHID()));
|
||||||
$header = id(new PhabricatorHeaderView())
|
$header = id(new PhabricatorHeaderView())
|
||||||
->setHeader($file->getName());
|
->setHeader($file->getName());
|
||||||
|
|
||||||
|
@ -36,7 +41,7 @@ final class PhabricatorFileInfoController extends PhabricatorFileController {
|
||||||
|
|
||||||
$actions = $this->buildActionView($file);
|
$actions = $this->buildActionView($file);
|
||||||
$properties = $this->buildPropertyView($file);
|
$properties = $this->buildPropertyView($file);
|
||||||
|
$timeline = $this->buildTransactionView($file, $xactions);
|
||||||
$crumbs = $this->buildApplicationCrumbs();
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
$crumbs->setActionList($actions);
|
$crumbs->setActionList($actions);
|
||||||
$crumbs->addCrumb(
|
$crumbs->addCrumb(
|
||||||
|
@ -50,13 +55,64 @@ final class PhabricatorFileInfoController extends PhabricatorFileController {
|
||||||
$header,
|
$header,
|
||||||
$actions,
|
$actions,
|
||||||
$properties,
|
$properties,
|
||||||
|
$timeline
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'title' => $file->getName(),
|
'title' => $file->getName(),
|
||||||
'device' => true,
|
'device' => true,
|
||||||
|
'pageObjects' => array($file->getPHID()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function buildTransactionView(
|
||||||
|
PhabricatorFile $file,
|
||||||
|
array $xactions) {
|
||||||
|
|
||||||
|
$user = $this->getRequest()->getUser();
|
||||||
|
$engine = id(new PhabricatorMarkupEngine())
|
||||||
|
->setViewer($user);
|
||||||
|
foreach ($xactions as $xaction) {
|
||||||
|
if ($xaction->getComment()) {
|
||||||
|
$engine->addObject(
|
||||||
|
$xaction->getComment(),
|
||||||
|
PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$engine->process();
|
||||||
|
|
||||||
|
$timeline = id(new PhabricatorApplicationTransactionView())
|
||||||
|
->setUser($user)
|
||||||
|
->setObjectPHID($file->getPHID())
|
||||||
|
->setTransactions($xactions)
|
||||||
|
->setMarkupEngine($engine);
|
||||||
|
|
||||||
|
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
|
||||||
|
|
||||||
|
$add_comment_header = id(new PhabricatorHeaderView())
|
||||||
|
->setHeader(
|
||||||
|
$is_serious
|
||||||
|
? pht('Add Comment')
|
||||||
|
: pht('Question File Integrity'));
|
||||||
|
|
||||||
|
$submit_button_name = $is_serious
|
||||||
|
? pht('Add Comment')
|
||||||
|
: pht('Debate the Bits');
|
||||||
|
|
||||||
|
$draft = PhabricatorDraft::newFromUserAndKey($user, $file->getPHID());
|
||||||
|
|
||||||
|
$add_comment_form = id(new PhabricatorApplicationTransactionCommentView())
|
||||||
|
->setUser($user)
|
||||||
|
->setObjectPHID($file->getPHID())
|
||||||
|
->setDraft($draft)
|
||||||
|
->setAction($this->getApplicationURI('/comment/'.$file->getID().'/'))
|
||||||
|
->setSubmitButtonName($submit_button_name);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$timeline,
|
||||||
|
$add_comment_header,
|
||||||
|
$add_comment_form);
|
||||||
|
}
|
||||||
|
|
||||||
private function buildActionView(PhabricatorFile $file) {
|
private function buildActionView(PhabricatorFile $file) {
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$user = $request->getUser();
|
$user = $request->getUser();
|
||||||
|
|
89
src/applications/files/editor/PhabricatorFileEditor.php
Normal file
89
src/applications/files/editor/PhabricatorFileEditor.php
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
|
final class PhabricatorFileEditor
|
||||||
|
extends PhabricatorApplicationTransactionEditor {
|
||||||
|
|
||||||
|
public function getTransactionTypes() {
|
||||||
|
$types = parent::getTransactionTypes();
|
||||||
|
|
||||||
|
$types[] = PhabricatorTransactions::TYPE_COMMENT;
|
||||||
|
|
||||||
|
return $types;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCustomTransactionOldValue(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCustomTransactionNewValue(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function applyCustomInternalTransaction(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function applyCustomExternalTransaction(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function supportsMail() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getMailSubjectPrefix() {
|
||||||
|
return PhabricatorEnv::getEnvConfig('metamta.files.subject-prefix');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||||
|
return array(
|
||||||
|
$object->getAuthorPHID(),
|
||||||
|
$this->requireActor()->getPHID(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
|
||||||
|
return id(new FileReplyHandler())
|
||||||
|
->setMailReceiver($object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
||||||
|
$id = $object->getID();
|
||||||
|
$name = $object->getName();
|
||||||
|
|
||||||
|
return id(new PhabricatorMetaMTAMail())
|
||||||
|
->setSubject("F{$id}: {$name}")
|
||||||
|
->addHeader('Thread-Topic', "F{$id}");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildMailBody(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
array $xactions) {
|
||||||
|
|
||||||
|
$body = parent::buildMailBody($object, $xactions);
|
||||||
|
|
||||||
|
$body->addTextSection(
|
||||||
|
pht('FILE DETAIL'),
|
||||||
|
PhabricatorEnv::getProductionURI($object->getInfoURI()));
|
||||||
|
|
||||||
|
return $body;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function supportsFeed() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function supportsSearch() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
/**
|
/**
|
||||||
* @group files
|
* @group files
|
||||||
*/
|
*/
|
||||||
final class FilesCreateMailReceiver
|
final class FileCreateMailReceiver
|
||||||
extends PhabricatorMailReceiver {
|
extends PhabricatorMailReceiver {
|
||||||
|
|
||||||
public function isEnabled() {
|
public function isEnabled() {
|
||||||
|
@ -48,6 +48,8 @@ final class FilesCreateMailReceiver
|
||||||
} else {
|
} else {
|
||||||
$subject = pht('You successfully uploaded a file.');
|
$subject = pht('You successfully uploaded a file.');
|
||||||
}
|
}
|
||||||
|
$subject_prefix =
|
||||||
|
PhabricatorEnv::getEnvConfig('metamta.files.subject-prefix');
|
||||||
|
|
||||||
$file_uris = array();
|
$file_uris = array();
|
||||||
foreach ($attachment_phids as $phid) {
|
foreach ($attachment_phids as $phid) {
|
||||||
|
@ -61,7 +63,8 @@ final class FilesCreateMailReceiver
|
||||||
|
|
||||||
id(new PhabricatorMetaMTAMail())
|
id(new PhabricatorMetaMTAMail())
|
||||||
->addTos(array($sender->getPHID()))
|
->addTos(array($sender->getPHID()))
|
||||||
->setSubject('[Files] '.$subject)
|
->setSubject($subject)
|
||||||
|
->setSubjectPrefix($subject_prefix)
|
||||||
->setFrom($sender->getPHID())
|
->setFrom($sender->getPHID())
|
||||||
->setRelatedPHID($first_phid)
|
->setRelatedPHID($first_phid)
|
||||||
->setBody($body->render())
|
->setBody($body->render())
|
40
src/applications/files/mail/FileMailReceiver.php
Normal file
40
src/applications/files/mail/FileMailReceiver.php
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
|
final class FileMailReceiver extends PhabricatorObjectMailReceiver {
|
||||||
|
|
||||||
|
public function isEnabled() {
|
||||||
|
$app_class = 'PhabricatorApplicationFiles';
|
||||||
|
return PhabricatorApplication::isClassInstalled($app_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectPattern() {
|
||||||
|
return 'F[1-9]\d*';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function loadObject($pattern, PhabricatorUser $viewer) {
|
||||||
|
$id = (int)trim($pattern, 'F');
|
||||||
|
|
||||||
|
return id(new PhabricatorPasteQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($id))
|
||||||
|
->executeOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processReceivedObjectMail(
|
||||||
|
PhabricatorMetaMTAReceivedMail $mail,
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorUser $sender) {
|
||||||
|
|
||||||
|
$handler = id(new FileReplyHandler())
|
||||||
|
->setMailReceiver($object);
|
||||||
|
|
||||||
|
$handler->setActor($sender);
|
||||||
|
$handler->setExcludeMailRecipientPHIDs(
|
||||||
|
$mail->loadExcludeMailRecipientPHIDs());
|
||||||
|
$handler->processEmail($mail);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
92
src/applications/files/mail/FileReplyHandler.php
Normal file
92
src/applications/files/mail/FileReplyHandler.php
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
|
final class FileReplyHandler extends PhabricatorMailReplyHandler {
|
||||||
|
|
||||||
|
public function validateMailReceiver($mail_receiver) {
|
||||||
|
if (!($mail_receiver instanceof PhabricatorFile)) {
|
||||||
|
throw new Exception('Mail receiver is not a PhabricatorFile.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPrivateReplyHandlerEmailAddress(
|
||||||
|
PhabricatorObjectHandle $handle) {
|
||||||
|
return $this->getDefaultPrivateReplyHandlerEmailAddress($handle, 'F');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPublicReplyHandlerEmailAddress() {
|
||||||
|
return $this->getDefaultPublicReplyHandlerEmailAddress('F');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getReplyHandlerInstructions() {
|
||||||
|
if ($this->supportsReplies()) {
|
||||||
|
return pht('Reply to comment or !unsubscribe.');
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) {
|
||||||
|
$actor = $this->getActor();
|
||||||
|
$file = $this->getMailReceiver();
|
||||||
|
|
||||||
|
$body = $mail->getCleanTextBody();
|
||||||
|
$body = trim($body);
|
||||||
|
$body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments());
|
||||||
|
|
||||||
|
$content_source = PhabricatorContentSource::newForSource(
|
||||||
|
PhabricatorContentSource::SOURCE_EMAIL,
|
||||||
|
array(
|
||||||
|
'id' => $mail->getID(),
|
||||||
|
));
|
||||||
|
|
||||||
|
$lines = explode("\n", trim($body));
|
||||||
|
$first_line = head($lines);
|
||||||
|
|
||||||
|
$xactions = array();
|
||||||
|
$command = null;
|
||||||
|
$matches = null;
|
||||||
|
if (preg_match('/^!(\w+)/', $first_line, $matches)) {
|
||||||
|
$lines = array_slice($lines, 1);
|
||||||
|
$body = implode("\n", $lines);
|
||||||
|
$body = trim($body);
|
||||||
|
|
||||||
|
$command = $matches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($command) {
|
||||||
|
case 'unsubscribe':
|
||||||
|
$xaction = id(new PhabricatorFileTransaction())
|
||||||
|
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
|
||||||
|
->setNewValue(array('-' => array($actor->getPHID())));
|
||||||
|
$xactions[] = $xaction;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$xactions[] = id(new PhabricatorFileTransaction())
|
||||||
|
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
|
||||||
|
->attachComment(
|
||||||
|
id(new PhabricatorFileTransactionComment())
|
||||||
|
->setContent($body));
|
||||||
|
|
||||||
|
$editor = id(new PhabricatorFileEditor())
|
||||||
|
->setActor($actor)
|
||||||
|
->setContentSource($content_source)
|
||||||
|
->setContinueOnNoEffect(true)
|
||||||
|
->setIsPreview(false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$xactions = $editor->applyTransactions($file, $xactions);
|
||||||
|
} catch (PhabricatorApplicationTransactionNoEffectException $ex) {
|
||||||
|
// just do nothing, though unclear why you're sending a blank email
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$head_xaction = head($xactions);
|
||||||
|
return $head_xaction->getID();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
final class PhabricatorFileQuery
|
final class PhabricatorFileQuery
|
||||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
final class PhabricatorFileSearchEngine
|
final class PhabricatorFileSearchEngine
|
||||||
extends PhabricatorApplicationSearchEngine {
|
extends PhabricatorApplicationSearchEngine {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
|
final class PhabricatorFileTransactionQuery
|
||||||
|
extends PhabricatorApplicationTransactionQuery {
|
||||||
|
|
||||||
|
public function getTemplateApplicationTransaction() {
|
||||||
|
return new PhabricatorFileTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,13 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
final class PhabricatorFile extends PhabricatorFileDAO
|
final class PhabricatorFile extends PhabricatorFileDAO
|
||||||
implements PhabricatorPolicyInterface {
|
implements
|
||||||
|
PhabricatorTokenReceiverInterface,
|
||||||
|
PhabricatorSubscribableInterface,
|
||||||
|
PhabricatorPolicyInterface {
|
||||||
|
|
||||||
const STORAGE_FORMAT_RAW = 'raw';
|
const STORAGE_FORMAT_RAW = 'raw';
|
||||||
|
|
||||||
|
@ -16,6 +22,7 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
||||||
protected $secretKey;
|
protected $secretKey;
|
||||||
protected $contentHash;
|
protected $contentHash;
|
||||||
protected $metadata = array();
|
protected $metadata = array();
|
||||||
|
protected $mailKey;
|
||||||
|
|
||||||
protected $storageEngine;
|
protected $storageEngine;
|
||||||
protected $storageFormat;
|
protected $storageFormat;
|
||||||
|
@ -38,6 +45,16 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
||||||
PhabricatorFilePHIDTypeFile::TYPECONST);
|
PhabricatorFilePHIDTypeFile::TYPECONST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function save() {
|
||||||
|
if (!$this->getSecretKey()) {
|
||||||
|
$this->setSecretKey($this->generateSecretKey());
|
||||||
|
}
|
||||||
|
if (!$this->getMailKey()) {
|
||||||
|
$this->setMailKey(Filesystem::readRandomCharacters(20));
|
||||||
|
}
|
||||||
|
return parent::save();
|
||||||
|
}
|
||||||
|
|
||||||
public static function readUploadedFileData($spec) {
|
public static function readUploadedFileData($spec) {
|
||||||
if (!$spec) {
|
if (!$spec) {
|
||||||
throw new Exception("No file was uploaded!");
|
throw new Exception("No file was uploaded!");
|
||||||
|
@ -648,13 +665,6 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
||||||
return ($key == $this->getSecretKey());
|
return ($key == $this->getSecretKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function save() {
|
|
||||||
if (!$this->getSecretKey()) {
|
|
||||||
$this->setSecretKey($this->generateSecretKey());
|
|
||||||
}
|
|
||||||
return parent::save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generateSecretKey() {
|
public function generateSecretKey() {
|
||||||
return Filesystem::readRandomCharacters(20);
|
return Filesystem::readRandomCharacters(20);
|
||||||
}
|
}
|
||||||
|
@ -820,4 +830,23 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorSubscribableInterface Implementation )-------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function isAutomaticallySubscribed($phid) {
|
||||||
|
return ($this->authorPHID == $phid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function getUsersToNotifyOfTokenGiven() {
|
||||||
|
return array(
|
||||||
|
$this->getAuthorPHID(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
abstract class PhabricatorFileDAO extends PhabricatorLiskDAO {
|
abstract class PhabricatorFileDAO extends PhabricatorLiskDAO {
|
||||||
|
|
||||||
public function getApplicationName() {
|
public function getApplicationName() {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/**
|
/**
|
||||||
* Simple blob store DAO for @{class:PhabricatorMySQLFileStorageEngine}.
|
* Simple blob store DAO for @{class:PhabricatorMySQLFileStorageEngine}.
|
||||||
*
|
*
|
||||||
* @group filestorage
|
* @group file
|
||||||
*/
|
*/
|
||||||
final class PhabricatorFileStorageBlob extends PhabricatorFileDAO {
|
final class PhabricatorFileStorageBlob extends PhabricatorFileDAO {
|
||||||
// max_allowed_packet defaults to 1 MiB, escaping can make the data twice
|
// max_allowed_packet defaults to 1 MiB, escaping can make the data twice
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
|
final class PhabricatorFileTransaction
|
||||||
|
extends PhabricatorApplicationTransaction {
|
||||||
|
|
||||||
|
public function getApplicationName() {
|
||||||
|
return 'file';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getApplicationTransactionType() {
|
||||||
|
return PhabricatorFilePHIDTypeFile::TYPECONST;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getApplicationTransactionCommentObject() {
|
||||||
|
return new PhabricatorFileTransactionComment();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
|
final class PhabricatorFileTransactionComment
|
||||||
|
extends PhabricatorApplicationTransactionComment {
|
||||||
|
|
||||||
|
public function getApplicationTransactionObject() {
|
||||||
|
return new PhabricatorFileTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldUseMarkupCache($field) {
|
||||||
|
// Only cache submitted comments.
|
||||||
|
return ($this->getTransactionPHID() != null);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
final class PhabricatorTransformedFile extends PhabricatorFileDAO {
|
final class PhabricatorTransformedFile extends PhabricatorFileDAO {
|
||||||
|
|
||||||
protected $originalPHID;
|
protected $originalPHID;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group file
|
||||||
|
*/
|
||||||
final class PhabricatorFileTestCase extends PhabricatorTestCase {
|
final class PhabricatorFileTestCase extends PhabricatorTestCase {
|
||||||
|
|
||||||
public function getPhabricatorTestCaseConfiguration() {
|
public function getPhabricatorTestCaseConfiguration() {
|
||||||
|
|
|
@ -1559,6 +1559,19 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
||||||
'type' => 'sql',
|
'type' => 'sql',
|
||||||
'name' => $this->getPatchPath('20130826.divinernode.sql'),
|
'name' => $this->getPatchPath('20130826.divinernode.sql'),
|
||||||
),
|
),
|
||||||
|
'20130820.filexactions.sql' => array(
|
||||||
|
'type' => 'sql',
|
||||||
|
'name' => $this->getPatchPath('20130820.filexactions.sql'),
|
||||||
|
),
|
||||||
|
'20130820.filemailkey.sql' => array(
|
||||||
|
'type' => 'sql',
|
||||||
|
'name' => $this->getPatchPath('20130820.filemailkey.sql'),
|
||||||
|
),
|
||||||
|
'20130820.file-mailkey-populate.php' => array(
|
||||||
|
'type' => 'php',
|
||||||
|
'name' =>
|
||||||
|
$this->getPatchPath('20130820.file-mailkey-populate.php'),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue