Skip to content

Commit 228496c

Browse files
committed
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
1 parent 4b061a7 commit 228496c

24 files changed

+585
-17
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
echo "Populating Phabricator files with mail keys xactions...\n";
4+
5+
$table = new PhabricatorFile();
6+
$table_name = $table->getTableName();
7+
8+
$conn_w = $table->establishConnection('w');
9+
$conn_w->openTransaction();
10+
11+
$sql = array();
12+
foreach (new LiskRawMigrationIterator($conn_w, 'file') as $row) {
13+
$sql[] = qsprintf(
14+
$conn_w,
15+
'(%d, %s)',
16+
$row['id'],
17+
Filesystem::readRandomCharacters(20));
18+
}
19+
20+
if ($sql) {
21+
foreach (PhabricatorLiskDAO::chunkSQL($sql, ', ') as $chunk) {
22+
queryfx(
23+
$conn_w,
24+
'INSERT INTO %T (id, mailKey) VALUES %Q '.
25+
'ON DUPLICATE KEY UPDATE mailKey = VALUES(mailKey)',
26+
$table_name,
27+
$chunk);
28+
}
29+
}
30+
31+
$table->saveTransaction();
32+
echo "Done.\n";
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE {$NAMESPACE}_file.file
2+
ADD `mailKey` varchar(20) NOT NULL;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
CREATE TABLE {$NAMESPACE}_file.file_transaction (
2+
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
3+
phid VARCHAR(64) NOT NULL COLLATE utf8_bin,
4+
authorPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
5+
objectPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
6+
viewPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
7+
editPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
8+
commentPHID VARCHAR(64) COLLATE utf8_bin,
9+
commentVersion INT UNSIGNED NOT NULL,
10+
transactionType VARCHAR(32) NOT NULL COLLATE utf8_bin,
11+
oldValue LONGTEXT NOT NULL COLLATE utf8_bin,
12+
newValue LONGTEXT NOT NULL COLLATE utf8_bin,
13+
contentSource LONGTEXT NOT NULL COLLATE utf8_bin,
14+
metadata LONGTEXT NOT NULL COLLATE utf8_bin,
15+
dateCreated INT UNSIGNED NOT NULL,
16+
dateModified INT UNSIGNED NOT NULL,
17+
18+
UNIQUE KEY `key_phid` (phid),
19+
KEY `key_object` (objectPHID)
20+
21+
) ENGINE=InnoDB, COLLATE utf8_general_ci;
22+
23+
CREATE TABLE {$NAMESPACE}_file.file_transaction_comment (
24+
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
25+
phid VARCHAR(64) NOT NULL COLLATE utf8_bin,
26+
transactionPHID VARCHAR(64) COLLATE utf8_bin,
27+
authorPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
28+
viewPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
29+
editPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
30+
commentVersion INT UNSIGNED NOT NULL,
31+
content LONGTEXT NOT NULL COLLATE utf8_bin,
32+
contentSource LONGTEXT NOT NULL COLLATE utf8_bin,
33+
isDeleted BOOL NOT NULL,
34+
dateCreated INT UNSIGNED NOT NULL,
35+
dateModified INT UNSIGNED NOT NULL,
36+
37+
UNIQUE KEY `key_phid` (phid),
38+
UNIQUE KEY `key_version` (transactionPHID, commentVersion),
39+
UNIQUE KEY `key_draft` (authorPHID, transactionPHID)
40+
41+
) ENGINE=InnoDB, COLLATE utf8_general_ci;
42+

src/__phutil_library_map__.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,9 @@
596596
'FeedPublisherHTTPWorker' => 'applications/feed/worker/FeedPublisherHTTPWorker.php',
597597
'FeedPublisherWorker' => 'applications/feed/worker/FeedPublisherWorker.php',
598598
'FeedPushWorker' => 'applications/feed/worker/FeedPushWorker.php',
599-
'FilesCreateMailReceiver' => 'applications/files/mail/FilesCreateMailReceiver.php',
599+
'FileCreateMailReceiver' => 'applications/files/mail/FileCreateMailReceiver.php',
600+
'FileMailReceiver' => 'applications/files/mail/FileMailReceiver.php',
601+
'FileReplyHandler' => 'applications/files/mail/FileReplyHandler.php',
600602
'HarbormasterDAO' => 'applications/harbormaster/storage/HarbormasterDAO.php',
601603
'HarbormasterObject' => 'applications/harbormaster/storage/HarbormasterObject.php',
602604
'HarbormasterRunnerWorker' => 'applications/harbormaster/worker/HarbormasterRunnerWorker.php',
@@ -1161,11 +1163,13 @@
11611163
'PhabricatorFeedStoryStatus' => 'applications/feed/story/PhabricatorFeedStoryStatus.php',
11621164
'PhabricatorFeedStoryTypeConstants' => 'applications/feed/constants/PhabricatorFeedStoryTypeConstants.php',
11631165
'PhabricatorFile' => 'applications/files/storage/PhabricatorFile.php',
1166+
'PhabricatorFileCommentController' => 'applications/files/controller/PhabricatorFileCommentController.php',
11641167
'PhabricatorFileController' => 'applications/files/controller/PhabricatorFileController.php',
11651168
'PhabricatorFileDAO' => 'applications/files/storage/PhabricatorFileDAO.php',
11661169
'PhabricatorFileDataController' => 'applications/files/controller/PhabricatorFileDataController.php',
11671170
'PhabricatorFileDeleteController' => 'applications/files/controller/PhabricatorFileDeleteController.php',
11681171
'PhabricatorFileDropUploadController' => 'applications/files/controller/PhabricatorFileDropUploadController.php',
1172+
'PhabricatorFileEditor' => 'applications/files/editor/PhabricatorFileEditor.php',
11691173
'PhabricatorFileImageMacro' => 'applications/macro/storage/PhabricatorFileImageMacro.php',
11701174
'PhabricatorFileInfoController' => 'applications/files/controller/PhabricatorFileInfoController.php',
11711175
'PhabricatorFileLinkListView' => 'view/layout/PhabricatorFileLinkListView.php',
@@ -1181,6 +1185,9 @@
11811185
'PhabricatorFileStorageEngineSelector' => 'applications/files/engineselector/PhabricatorFileStorageEngineSelector.php',
11821186
'PhabricatorFileTestCase' => 'applications/files/storage/__tests__/PhabricatorFileTestCase.php',
11831187
'PhabricatorFileTestDataGenerator' => 'applications/files/lipsum/PhabricatorFileTestDataGenerator.php',
1188+
'PhabricatorFileTransaction' => 'applications/files/storage/PhabricatorFileTransaction.php',
1189+
'PhabricatorFileTransactionComment' => 'applications/files/storage/PhabricatorFileTransactionComment.php',
1190+
'PhabricatorFileTransactionQuery' => 'applications/files/query/PhabricatorFileTransactionQuery.php',
11841191
'PhabricatorFileTransformController' => 'applications/files/controller/PhabricatorFileTransformController.php',
11851192
'PhabricatorFileUploadController' => 'applications/files/controller/PhabricatorFileUploadController.php',
11861193
'PhabricatorFileUploadDialogController' => 'applications/files/controller/PhabricatorFileUploadDialogController.php',
@@ -2631,7 +2638,9 @@
26312638
'FeedPublisherHTTPWorker' => 'FeedPushWorker',
26322639
'FeedPublisherWorker' => 'FeedPushWorker',
26332640
'FeedPushWorker' => 'PhabricatorWorker',
2634-
'FilesCreateMailReceiver' => 'PhabricatorMailReceiver',
2641+
'FileCreateMailReceiver' => 'PhabricatorMailReceiver',
2642+
'FileMailReceiver' => 'PhabricatorObjectMailReceiver',
2643+
'FileReplyHandler' => 'PhabricatorMailReplyHandler',
26352644
'HarbormasterDAO' => 'PhabricatorLiskDAO',
26362645
'HarbormasterObject' => 'HarbormasterDAO',
26372646
'HarbormasterRunnerWorker' => 'PhabricatorWorker',
@@ -3245,13 +3254,17 @@
32453254
'PhabricatorFile' =>
32463255
array(
32473256
0 => 'PhabricatorFileDAO',
3248-
1 => 'PhabricatorPolicyInterface',
3257+
1 => 'PhabricatorTokenReceiverInterface',
3258+
2 => 'PhabricatorSubscribableInterface',
3259+
3 => 'PhabricatorPolicyInterface',
32493260
),
3261+
'PhabricatorFileCommentController' => 'PhabricatorFileController',
32503262
'PhabricatorFileController' => 'PhabricatorController',
32513263
'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
32523264
'PhabricatorFileDataController' => 'PhabricatorFileController',
32533265
'PhabricatorFileDeleteController' => 'PhabricatorFileController',
32543266
'PhabricatorFileDropUploadController' => 'PhabricatorFileController',
3267+
'PhabricatorFileEditor' => 'PhabricatorApplicationTransactionEditor',
32553268
'PhabricatorFileImageMacro' =>
32563269
array(
32573270
0 => 'PhabricatorFileDAO',
@@ -3275,6 +3288,9 @@
32753288
'PhabricatorFileStorageConfigurationException' => 'Exception',
32763289
'PhabricatorFileTestCase' => 'PhabricatorTestCase',
32773290
'PhabricatorFileTestDataGenerator' => 'PhabricatorTestDataGenerator',
3291+
'PhabricatorFileTransaction' => 'PhabricatorApplicationTransaction',
3292+
'PhabricatorFileTransactionComment' => 'PhabricatorApplicationTransactionComment',
3293+
'PhabricatorFileTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
32783294
'PhabricatorFileTransformController' => 'PhabricatorFileController',
32793295
'PhabricatorFileUploadController' => 'PhabricatorFileController',
32803296
'PhabricatorFileUploadDialogController' => 'PhabricatorFileController',

src/applications/files/application/PhabricatorApplicationFiles.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<?php
22

3+
/**
4+
* @group file
5+
*/
36
final class PhabricatorApplicationFiles extends PhabricatorApplication {
47

58
public function getBaseURI() {
@@ -48,6 +51,7 @@ public function getRoutes() {
4851
'(query/(?P<key>[^/]+)/)?' => 'PhabricatorFileListController',
4952
'upload/' => 'PhabricatorFileUploadController',
5053
'dropupload/' => 'PhabricatorFileDropUploadController',
54+
'comment/(?P<id>[1-9]\d*)/' => 'PhabricatorFileCommentController',
5155
'delete/(?P<id>[1-9]\d*)/' => 'PhabricatorFileDeleteController',
5256
'info/(?P<phid>[^/]+)/' => 'PhabricatorFileInfoController',
5357
'data/(?P<key>[^/]+)/(?P<phid>[^/]+)/.*'

src/applications/files/conduit/ConduitAPI_file_Method.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<?php
22

3+
/**
4+
* @group conduit
5+
*/
36
abstract class ConduitAPI_file_Method extends ConduitAPIMethod {
47

58
public function getApplication() {

src/applications/files/config/PhabricatorFilesConfigOptions.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<?php
22

3+
/**
4+
* @group file
5+
*/
36
final class PhabricatorFilesConfigOptions
47
extends PhabricatorApplicationConfigOptions {
58

@@ -158,7 +161,12 @@ public function getOptions() {
158161
'metamta.files.public-create-email',
159162
'string',
160163
null)
161-
->setDescription(pht('Allow uploaded files via email.')),
164+
->setDescription(pht('Allow uploaded files via email.')),
165+
$this->newOption(
166+
'metamta.files.subject-prefix',
167+
'string',
168+
'[File]')
169+
->setDescription(pht('Subject prefix for paste email.')),
162170
$this->newOption('files.enable-imagemagick', 'bool', false)
163171
->setBoolOptions(
164172
array(
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/**
4+
* @group file
5+
*/
6+
final class PhabricatorFileCommentController
7+
extends PhabricatorFileController {
8+
9+
private $id;
10+
11+
public function willProcessRequest(array $data) {
12+
$this->id = idx($data, 'id');
13+
}
14+
15+
public function processRequest() {
16+
$request = $this->getRequest();
17+
$user = $request->getUser();
18+
19+
if (!$request->isFormPost()) {
20+
return new Aphront400Response();
21+
}
22+
23+
$file = id(new PhabricatorFileQuery())
24+
->setViewer($user)
25+
->withIDs(array($this->id))
26+
->executeOne();
27+
if (!$file) {
28+
return new Aphront404Response();
29+
}
30+
31+
$is_preview = $request->isPreviewRequest();
32+
$draft = PhabricatorDraft::buildFromRequest($request);
33+
34+
$view_uri = $file->getInfoURI();
35+
36+
$xactions = array();
37+
$xactions[] = id(new PhabricatorFileTransaction())
38+
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
39+
->attachComment(
40+
id(new PhabricatorFileTransactionComment())
41+
->setContent($request->getStr('comment')));
42+
43+
$editor = id(new PhabricatorFileEditor())
44+
->setActor($user)
45+
->setContinueOnNoEffect($request->isContinueRequest())
46+
->setContentSourceFromRequest($request)
47+
->setIsPreview($is_preview);
48+
49+
try {
50+
$xactions = $editor->applyTransactions($file, $xactions);
51+
} catch (PhabricatorApplicationTransactionNoEffectException $ex) {
52+
return id(new PhabricatorApplicationTransactionNoEffectResponse())
53+
->setCancelURI($view_uri)
54+
->setException($ex);
55+
}
56+
57+
if ($draft) {
58+
$draft->replaceOrDelete();
59+
}
60+
61+
if ($request->isAjax()) {
62+
return id(new PhabricatorApplicationTransactionResponse())
63+
->setViewer($user)
64+
->setTransactions($xactions)
65+
->setIsPreview($is_preview)
66+
->setAnchorOffset($request->getStr('anchor'));
67+
} else {
68+
return id(new AphrontRedirectResponse())
69+
->setURI($view_uri);
70+
}
71+
}
72+
73+
}

src/applications/files/controller/PhabricatorFileInfoController.php

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,13 @@ public function processRequest() {
2121
return new Aphront404Response();
2222
}
2323

24-
$this->loadHandles(array($file->getAuthorPHID()));
2524
$phid = $file->getPHID();
25+
$xactions = id(new PhabricatorFileTransactionQuery())
26+
->setViewer($user)
27+
->withObjectPHIDs(array($phid))
28+
->execute();
29+
30+
$this->loadHandles(array($file->getAuthorPHID()));
2631
$header = id(new PhabricatorHeaderView())
2732
->setHeader($file->getName());
2833

@@ -36,7 +41,7 @@ public function processRequest() {
3641

3742
$actions = $this->buildActionView($file);
3843
$properties = $this->buildPropertyView($file);
39-
44+
$timeline = $this->buildTransactionView($file, $xactions);
4045
$crumbs = $this->buildApplicationCrumbs();
4146
$crumbs->setActionList($actions);
4247
$crumbs->addCrumb(
@@ -50,13 +55,64 @@ public function processRequest() {
5055
$header,
5156
$actions,
5257
$properties,
58+
$timeline
5359
),
5460
array(
5561
'title' => $file->getName(),
5662
'device' => true,
63+
'pageObjects' => array($file->getPHID()),
5764
));
5865
}
5966

67+
private function buildTransactionView(
68+
PhabricatorFile $file,
69+
array $xactions) {
70+
71+
$user = $this->getRequest()->getUser();
72+
$engine = id(new PhabricatorMarkupEngine())
73+
->setViewer($user);
74+
foreach ($xactions as $xaction) {
75+
if ($xaction->getComment()) {
76+
$engine->addObject(
77+
$xaction->getComment(),
78+
PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
79+
}
80+
}
81+
$engine->process();
82+
83+
$timeline = id(new PhabricatorApplicationTransactionView())
84+
->setUser($user)
85+
->setObjectPHID($file->getPHID())
86+
->setTransactions($xactions)
87+
->setMarkupEngine($engine);
88+
89+
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
90+
91+
$add_comment_header = id(new PhabricatorHeaderView())
92+
->setHeader(
93+
$is_serious
94+
? pht('Add Comment')
95+
: pht('Question File Integrity'));
96+
97+
$submit_button_name = $is_serious
98+
? pht('Add Comment')
99+
: pht('Debate the Bits');
100+
101+
$draft = PhabricatorDraft::newFromUserAndKey($user, $file->getPHID());
102+
103+
$add_comment_form = id(new PhabricatorApplicationTransactionCommentView())
104+
->setUser($user)
105+
->setObjectPHID($file->getPHID())
106+
->setDraft($draft)
107+
->setAction($this->getApplicationURI('/comment/'.$file->getID().'/'))
108+
->setSubmitButtonName($submit_button_name);
109+
110+
return array(
111+
$timeline,
112+
$add_comment_header,
113+
$add_comment_form);
114+
}
115+
60116
private function buildActionView(PhabricatorFile $file) {
61117
$request = $this->getRequest();
62118
$user = $request->getUser();

0 commit comments

Comments
 (0)