1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-28 01:32:42 +01:00

(stable) Promote 2016 Week 39

This commit is contained in:
epriestley 2016-09-23 17:20:19 -07:00
commit 27006fedcc
38 changed files with 507 additions and 545 deletions

View file

@ -111,13 +111,13 @@ class MimeMailParser {
* @param $data String
*/
public function setText($data) {
// NOTE: This has been modified for Phabricator. If the input data does not
// end in a newline, Mailparse fails to include the last line in the mail
// body. This happens somewhere deep, deep inside the mailparse extension,
// so adding a newline here seems like the most straightforward fix.
if (!preg_match('/\n\z/', $data)) {
$data = $data."\n";
}
// NOTE: This has been modified for Phabricator. If the input data does not
// end in a newline, Mailparse fails to include the last line in the mail
// body. This happens somewhere deep, deep inside the mailparse extension,
// so adding a newline here seems like the most straightforward fix.
if (!preg_match('/\n\z/', $data)) {
$data = $data."\n";
}
$this->resource = mailparse_msg_create();
// does not parse incrementally, fast memory hog might explode
@ -203,23 +203,23 @@ class MimeMailParser {
);
if (in_array($type, array_keys($mime_types))) {
foreach($this->parts as $part) {
$disposition = $this->getPartContentDisposition($part);
if ($disposition == 'attachment') {
// text/plain parts with "Content-Disposition: attachment" are
// attachments, not part of the text body.
continue;
}
$disposition = $this->getPartContentDisposition($part);
if ($disposition == 'attachment') {
// text/plain parts with "Content-Disposition: attachment" are
// attachments, not part of the text body.
continue;
}
if ($this->getPartContentType($part) == $mime_types[$type]) {
$headers = $this->getPartHeaders($part);
// Concatenate all the matching parts into the body text. For example,
// if a user sends a message with some text, then an image, and then
// some more text, the text body of the email gets split over several
// attachments.
$headers = $this->getPartHeaders($part);
// Concatenate all the matching parts into the body text. For example,
// if a user sends a message with some text, then an image, and then
// some more text, the text body of the email gets split over several
// attachments.
$body .= $this->decode(
$this->getPartBody($part),
array_key_exists('content-transfer-encoding', $headers)
? $headers['content-transfer-encoding']
: '');
? $headers['content-transfer-encoding']
: '');
}
}
} else {
@ -251,20 +251,42 @@ class MimeMailParser {
return $headers;
}
/**
* Returns the attachments contents in order of appearance
* @return Array
* @param $type Object[optional]
*/
public function getAttachments() {
// NOTE: This has been modified for Phabricator. Some mail clients do not
// send attachments with "Content-Disposition" headers.
$attachments = array();
$dispositions = array("attachment","inline");
foreach($this->parts as $part) {
$non_attachment_types = array("text/plain", "text/html");
$nonameIter = 0;
foreach ($this->parts as $part) {
$disposition = $this->getPartContentDisposition($part);
if (in_array($disposition, $dispositions)) {
$filename = 'noname';
if (isset($part['disposition-filename'])) {
$filename = $part['disposition-filename'];
} elseif (isset($part['content-name'])) {
// if we have no disposition but we have a content-name, it's a valid attachment.
// we simulate the presence of an attachment disposition with a disposition filename
$filename = $part['content-name'];
$disposition = 'attachment';
} elseif (!in_array($part['content-type'], $non_attachment_types, true)
&& substr($part['content-type'], 0, 10) !== 'multipart/'
) {
// if we cannot get it with getMessageBody, we assume it is an attachment
$disposition = 'attachment';
}
if (in_array($disposition, $dispositions) && isset($filename) === true) {
if ($filename == 'noname') {
$nonameIter++;
$filename = 'noname'.$nonameIter;
}
$attachments[] = new MimeMailParser_attachment(
$part['disposition-filename'],
$filename,
$this->getPartContentType($part),
$this->getAttachmentStream($part),
$disposition,
@ -413,7 +435,7 @@ class MimeMailParser {
private function getAttachmentStream(&$part) {
$temp_fp = tmpfile();
array_key_exists('content-transfer-encoding', $part['headers']) ? $encoding = $part['headers']['content-transfer-encoding'] : $encoding = '';
array_key_exists('content-transfer-encoding', $part['headers']) ? $encoding = $part['headers']['content-transfer-encoding'] : $encoding = '';
if ($temp_fp) {
if ($this->stream) {
@ -445,21 +467,21 @@ class MimeMailParser {
}
/**
* Decode the string depending on encoding type.
* @return String the decoded string.
* @param $encodedString The string in its original encoded state.
* @param $encodingType The encoding type from the Content-Transfer-Encoding header of the part.
*/
private function decode($encodedString, $encodingType) {
if (strtolower($encodingType) == 'base64') {
return base64_decode($encodedString);
} else if (strtolower($encodingType) == 'quoted-printable') {
return quoted_printable_decode($encodedString);
} else {
return $encodedString;
}
}
/**
* Decode the string depending on encoding type.
* @return String the decoded string.
* @param $encodedString The string in its original encoded state.
* @param $encodingType The encoding type from the Content-Transfer-Encoding header of the part.
*/
private function decode($encodedString, $encodingType) {
if (strtolower($encodingType) == 'base64') {
return base64_decode($encodedString);
} else if (strtolower($encodingType) == 'quoted-printable') {
return quoted_printable_decode($encodedString);
} else {
return $encodedString;
}
}
}

View file

@ -9,7 +9,7 @@ return array(
'names' => array(
'conpherence.pkg.css' => '80a3fcb3',
'conpherence.pkg.js' => '89b4837e',
'core.pkg.css' => '476e9330',
'core.pkg.css' => 'f7b03076',
'core.pkg.js' => '1d376fa9',
'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => '3fb7f532',
@ -27,7 +27,7 @@ return array(
'rsrc/css/aphront/notification.css' => '3f6c89c9',
'rsrc/css/aphront/panel-view.css' => '8427b78d',
'rsrc/css/aphront/phabricator-nav-view.css' => 'b29426e9',
'rsrc/css/aphront/table-view.css' => '832656fd',
'rsrc/css/aphront/table-view.css' => '3225137a',
'rsrc/css/aphront/tokenizer.css' => '056da01b',
'rsrc/css/aphront/tooltip.css' => '1a07aea8',
'rsrc/css/aphront/typeahead-browse.css' => '8904346a',
@ -38,7 +38,7 @@ return array(
'rsrc/css/application/base/notification-menu.css' => 'b3ab500d',
'rsrc/css/application/base/phabricator-application-launch-view.css' => '95351601',
'rsrc/css/application/base/phui-theme.css' => '027ba77e',
'rsrc/css/application/base/standard-page-view.css' => '2b592894',
'rsrc/css/application/base/standard-page-view.css' => '3026770e',
'rsrc/css/application/chatlog/chatlog.css' => 'd295b020',
'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4',
'rsrc/css/application/config/config-options.css' => '0ede4c9b',
@ -607,7 +607,7 @@ return array(
'aphront-list-filter-view-css' => '5d6f0526',
'aphront-multi-column-view-css' => 'fd18389d',
'aphront-panel-view-css' => '8427b78d',
'aphront-table-view-css' => '832656fd',
'aphront-table-view-css' => '3225137a',
'aphront-tokenizer-control-css' => '056da01b',
'aphront-tooltip-css' => '1a07aea8',
'aphront-typeahead-control-css' => 'd4f16145',
@ -869,7 +869,7 @@ return array(
'phabricator-shaped-request' => '7cbe244b',
'phabricator-slowvote-css' => 'a94b7230',
'phabricator-source-code-view-css' => 'cbeef983',
'phabricator-standard-page-view' => '2b592894',
'phabricator-standard-page-view' => '3026770e',
'phabricator-textareautils' => '320810c8',
'phabricator-title' => 'df5e11d2',
'phabricator-tooltip' => '6323f942',

View file

@ -0,0 +1,14 @@
CREATE TABLE {$NAMESPACE}_file.file_externalrequest (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
filePHID VARBINARY(64),
ttl INT UNSIGNED NOT NULL,
uri LONGTEXT NOT NULL,
uriIndex BINARY(12) NOT NULL,
isSuccessful BOOL NOT NULL,
responseMessage LONGTEXT,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
UNIQUE KEY `key_uriindex` (uriIndex),
KEY `key_ttl` (ttl),
KEY `key_file` (filePHID)
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};

View file

@ -2553,10 +2553,13 @@ phutil_register_library_map(array(
'PhabricatorFileDropUploadController' => 'applications/files/controller/PhabricatorFileDropUploadController.php',
'PhabricatorFileEditController' => 'applications/files/controller/PhabricatorFileEditController.php',
'PhabricatorFileEditor' => 'applications/files/editor/PhabricatorFileEditor.php',
'PhabricatorFileExternalRequest' => 'applications/files/storage/PhabricatorFileExternalRequest.php',
'PhabricatorFileExternalRequestGarbageCollector' => 'applications/files/garbagecollector/PhabricatorFileExternalRequestGarbageCollector.php',
'PhabricatorFileFilePHIDType' => 'applications/files/phid/PhabricatorFileFilePHIDType.php',
'PhabricatorFileHasObjectEdgeType' => 'applications/files/edge/PhabricatorFileHasObjectEdgeType.php',
'PhabricatorFileIconSetSelectController' => 'applications/files/controller/PhabricatorFileIconSetSelectController.php',
'PhabricatorFileImageMacro' => 'applications/macro/storage/PhabricatorFileImageMacro.php',
'PhabricatorFileImageProxyController' => 'applications/files/controller/PhabricatorFileImageProxyController.php',
'PhabricatorFileImageTransform' => 'applications/files/transform/PhabricatorFileImageTransform.php',
'PhabricatorFileInfoController' => 'applications/files/controller/PhabricatorFileInfoController.php',
'PhabricatorFileLinkView' => 'view/layout/PhabricatorFileLinkView.php',
@ -3184,6 +3187,7 @@ phutil_register_library_map(array(
'PhabricatorPhurlURLCommentController' => 'applications/phurl/controller/PhabricatorPhurlURLCommentController.php',
'PhabricatorPhurlURLCreateCapability' => 'applications/phurl/capability/PhabricatorPhurlURLCreateCapability.php',
'PhabricatorPhurlURLEditController' => 'applications/phurl/controller/PhabricatorPhurlURLEditController.php',
'PhabricatorPhurlURLEditEngine' => 'applications/phurl/editor/PhabricatorPhurlURLEditEngine.php',
'PhabricatorPhurlURLEditor' => 'applications/phurl/editor/PhabricatorPhurlURLEditor.php',
'PhabricatorPhurlURLListController' => 'applications/phurl/controller/PhabricatorPhurlURLListController.php',
'PhabricatorPhurlURLMailReceiver' => 'applications/phurl/mail/PhabricatorPhurlURLMailReceiver.php',
@ -7367,6 +7371,11 @@ phutil_register_library_map(array(
'PhabricatorFileDropUploadController' => 'PhabricatorFileController',
'PhabricatorFileEditController' => 'PhabricatorFileController',
'PhabricatorFileEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorFileExternalRequest' => array(
'PhabricatorFileDAO',
'PhabricatorDestructibleInterface',
),
'PhabricatorFileExternalRequestGarbageCollector' => 'PhabricatorGarbageCollector',
'PhabricatorFileFilePHIDType' => 'PhabricatorPHIDType',
'PhabricatorFileHasObjectEdgeType' => 'PhabricatorEdgeType',
'PhabricatorFileIconSetSelectController' => 'PhabricatorFileController',
@ -7378,6 +7387,7 @@ phutil_register_library_map(array(
'PhabricatorTokenReceiverInterface',
'PhabricatorPolicyInterface',
),
'PhabricatorFileImageProxyController' => 'PhabricatorFileController',
'PhabricatorFileImageTransform' => 'PhabricatorFileTransform',
'PhabricatorFileInfoController' => 'PhabricatorFileController',
'PhabricatorFileLinkView' => 'AphrontView',
@ -8097,6 +8107,7 @@ phutil_register_library_map(array(
'PhabricatorPhurlURLCommentController' => 'PhabricatorPhurlController',
'PhabricatorPhurlURLCreateCapability' => 'PhabricatorPolicyCapability',
'PhabricatorPhurlURLEditController' => 'PhabricatorPhurlController',
'PhabricatorPhurlURLEditEngine' => 'PhabricatorEditEngine',
'PhabricatorPhurlURLEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorPhurlURLListController' => 'PhabricatorPhurlController',
'PhabricatorPhurlURLMailReceiver' => 'PhabricatorObjectMailReceiver',

View file

@ -2,9 +2,6 @@
final class PhabricatorRedirectController extends PhabricatorController {
private $uri;
private $allowExternal;
public function shouldRequireLogin() {
return false;
}
@ -13,15 +10,12 @@ final class PhabricatorRedirectController extends PhabricatorController {
return false;
}
public function willProcessRequest(array $data) {
$this->uri = $data['uri'];
$this->allowExternal = idx($data, 'external', false);
}
public function processRequest() {
public function handleRequest(AphrontRequest $request) {
$uri = $request->getURIData('uri');
$external = $request->getURIData('external', false);
return id(new AphrontRedirectResponse())
->setURI($this->uri)
->setIsExternal($this->allowExternal);
->setURI($uri)
->setIsExternal($external);
}
}

View file

@ -143,9 +143,6 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
'phabricator.auth-permanent',
'phabricator.application-id',
'phabricator.application-secret',
'maniphest.priorities.unbreak-now',
'maniphest.priorities.needs-triage',
'welcome.html',
);
$ancient_config = array_fill_keys($auth_config, $reason_auth);
@ -197,6 +194,10 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
'The "Re: Prefix" and "Vary Subjects" settings are now configured '.
'in global settings.');
$dashboard_reason = pht(
'This option has been removed, you can use Dashboards to provide '.
'homepage customization. See T11533 for more details.');
$ancient_config += array(
'phid.external-loaders' =>
pht(
@ -336,17 +337,9 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
'This option has been replaced with `ui.logo`, which provides more '.
'flexible configuration options.'),
'welcome.html' => pht(
'This option has been removed, you can use Dashboards to provide '.
'homepage customization. See T11533 for more details.'),
'maniphest.priorities.unbreak-now' => pht(
'This option has been removed, you can use Dashboards to provide '.
'homepage customization. See T11533 for more details.'),
'maniphest.priorities.needs-triage' => pht(
'This option has been removed, you can use Dashboards to provide '.
'homepage customization. See T11533 for more details.'),
'welcome.html' => $dashboard_reason,
'maniphest.priorities.unbreak-now' => $dashboard_reason,
'maniphest.priorities.needs-triage' => $dashboard_reason,
);

View file

@ -112,25 +112,6 @@ final class ConpherenceRoomTestCase extends ConpherenceTestCase {
}
}
public function testAddMessageWithFileAttachments() {
$creator = $this->generateNewTestUser();
$friend_1 = $this->generateNewTestUser();
$participant_map = array(
$creator->getPHID() => $creator,
$friend_1->getPHID() => $friend_1,
);
$conpherence = $this->createRoom(
$creator,
array_keys($participant_map));
foreach ($participant_map as $phid => $user) {
$xactions = $this->addMessageWithFile($user, $conpherence);
$this->assertEqual(2, count($xactions));
}
}
private function createRoom(
PhabricatorUser $creator,
array $participant_phids) {

View file

@ -37,8 +37,7 @@ final class ConpherenceQueryThreadConduitAPIMethod
$query = id(new ConpherenceThreadQuery())
->setViewer($user)
->needParticipantCache(true)
->needFilePHIDs(true);
->needParticipantCache(true);
if ($ids) {
$conpherences = $query
@ -73,7 +72,6 @@ final class ConpherenceQueryThreadConduitAPIMethod
'conpherenceTitle' => $conpherence->getTitle(),
'messageCount' => $conpherence->getMessageCount(),
'recentParticipantPHIDs' => $conpherence->getRecentParticipantPHIDs(),
'filePHIDs' => $conpherence->getFilePHIDs(),
'conpherenceURI' => $this->getConpherenceURI($conpherence),
);
}

View file

@ -44,8 +44,7 @@ final class ConpherenceUpdateThreadConduitAPIMethod
$id = $request->getValue('id');
$phid = $request->getValue('phid');
$query = id(new ConpherenceThreadQuery())
->setViewer($user)
->needFilePHIDs(true);
->setViewer($user);
if ($id) {
$query->withIDs(array($id));
} else if ($phid) {

View file

@ -36,7 +36,6 @@ final class ConpherenceUpdateController
$conpherence = id(new ConpherenceThreadQuery())
->setViewer($user)
->withIDs(array($conpherence_id))
->needFilePHIDs(true)
->needOrigPics(true)
->needCropPics(true)
->needParticipants($need_participants)

View file

@ -22,7 +22,6 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
$topic) {
$conpherence = ConpherenceThread::initializeNewRoom($creator);
$files = array();
$errors = array();
if (empty($participant_phids)) {
$errors[] = self::ERROR_EMPTY_PARTICIPANTS;
@ -35,26 +34,11 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
$errors[] = self::ERROR_EMPTY_MESSAGE;
}
$file_phids = PhabricatorMarkupEngine::extractFilePHIDsFromEmbeddedFiles(
$creator,
array($message));
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setViewer($creator)
->withPHIDs($file_phids)
->execute();
}
if (!$errors) {
$xactions = array();
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_PARTICIPANTS)
->setNewValue(array('+' => $participant_phids));
if ($files) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_FILES)
->setNewValue(array('+' => mpull($files, 'getPHID')));
}
if ($title) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_TITLE)
@ -88,27 +72,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
ConpherenceThread $conpherence,
$text) {
$files = array();
$file_phids = PhabricatorMarkupEngine::extractFilePHIDsFromEmbeddedFiles(
$viewer,
array($text));
// Since these are extracted from text, we might be re-including the
// same file -- e.g. a mock under discussion. Filter files we
// already have.
$existing_file_phids = $conpherence->getFilePHIDs();
$file_phids = array_diff($file_phids, $existing_file_phids);
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setViewer($this->getActor())
->withPHIDs($file_phids)
->execute();
}
$xactions = array();
if ($files) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_FILES)
->setNewValue(array('+' => mpull($files, 'getPHID')));
}
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment(
@ -126,7 +90,6 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
$types[] = ConpherenceTransaction::TYPE_TITLE;
$types[] = ConpherenceTransaction::TYPE_TOPIC;
$types[] = ConpherenceTransaction::TYPE_PARTICIPANTS;
$types[] = ConpherenceTransaction::TYPE_FILES;
$types[] = ConpherenceTransaction::TYPE_PICTURE;
$types[] = ConpherenceTransaction::TYPE_PICTURE_CROP;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
@ -154,8 +117,6 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
return array();
}
return $object->getParticipantPHIDs();
case ConpherenceTransaction::TYPE_FILES:
return $object->getFilePHIDs();
}
}
@ -172,7 +133,6 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
$file = $xaction->getNewValue();
return $file->getPHID();
case ConpherenceTransaction::TYPE_PARTICIPANTS:
case ConpherenceTransaction::TYPE_FILES:
return $this->getPHIDTransactionNewValue($xaction);
}
}
@ -335,27 +295,6 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case ConpherenceTransaction::TYPE_FILES:
$editor = new PhabricatorEdgeEditor();
$edge_type = PhabricatorObjectHasFileEdgeType::EDGECONST;
$old = array_fill_keys($xaction->getOldValue(), true);
$new = array_fill_keys($xaction->getNewValue(), true);
$add_edges = array_keys(array_diff_key($new, $old));
$remove_edges = array_keys(array_diff_key($old, $new));
foreach ($add_edges as $file_phid) {
$editor->addEdge(
$object->getPHID(),
$edge_type,
$file_phid);
}
foreach ($remove_edges as $file_phid) {
$editor->removeEdge(
$object->getPHID(),
$edge_type,
$file_phid);
}
$editor->save();
break;
case ConpherenceTransaction::TYPE_PARTICIPANTS:
if ($this->getIsNewObject()) {
continue;
@ -488,14 +427,6 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
PhabricatorPolicyCapability::CAN_EDIT);
}
break;
// This is similar to PhabricatorTransactions::TYPE_COMMENT so
// use CAN_VIEW
case ConpherenceTransaction::TYPE_FILES:
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,
PhabricatorPolicyCapability::CAN_VIEW);
break;
case ConpherenceTransaction::TYPE_TITLE:
case ConpherenceTransaction::TYPE_TOPIC:
PhabricatorPolicyFilter::requireCapability(
@ -514,7 +445,6 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
switch ($type) {
case ConpherenceTransaction::TYPE_TITLE:
return $v;
case ConpherenceTransaction::TYPE_FILES:
case ConpherenceTransaction::TYPE_PARTICIPANTS:
return $this->mergePHIDOrEdgeTransactions($u, $v);
}

View file

@ -13,17 +13,11 @@ final class ConpherenceThreadQuery
private $needOrigPics;
private $needTransactions;
private $needParticipantCache;
private $needFilePHIDs;
private $afterTransactionID;
private $beforeTransactionID;
private $transactionLimit;
private $fulltext;
public function needFilePHIDs($need_file_phids) {
$this->needFilePHIDs = $need_file_phids;
return $this;
}
public function needParticipantCache($participant_cache) {
$this->needParticipantCache = $participant_cache;
return $this;
@ -116,9 +110,6 @@ final class ConpherenceThreadQuery
if ($this->needTransactions) {
$this->loadTransactionsAndHandles($conpherences);
}
if ($this->needFilePHIDs) {
$this->loadFilePHIDs($conpherences);
}
if ($this->needOrigPics || $this->needCropPics) {
$this->initImages($conpherences);
}
@ -275,19 +266,6 @@ final class ConpherenceThreadQuery
return $this;
}
private function loadFilePHIDs(array $conpherences) {
$edge_type = PhabricatorObjectHasFileEdgeType::EDGECONST;
$file_edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array_keys($conpherences))
->withEdgeTypes(array($edge_type))
->execute();
foreach ($file_edges as $conpherence_phid => $data) {
$conpherence = $conpherences[$conpherence_phid];
$conpherence->attachFilePHIDs(array_keys($data[$edge_type]));
}
return $this;
}
private function loadOrigPics(array $conpherences) {
return $this->loadPics(
$conpherences,

View file

@ -20,7 +20,6 @@ final class ConpherenceThread extends ConpherenceDAO
private $participants = self::ATTACHABLE;
private $transactions = self::ATTACHABLE;
private $handles = self::ATTACHABLE;
private $filePHIDs = self::ATTACHABLE;
private $images = self::ATTACHABLE;
public static function initializeNewRoom(PhabricatorUser $sender) {
@ -31,7 +30,6 @@ final class ConpherenceThread extends ConpherenceDAO
->setTitle('')
->setTopic('')
->attachParticipants(array())
->attachFilePHIDs(array())
->attachImages(array())
->setViewPolicy($default_policy)
->setEditPolicy($default_policy)
@ -158,14 +156,6 @@ final class ConpherenceThread extends ConpherenceDAO
$amount);
}
public function attachFilePHIDs(array $file_phids) {
$this->filePHIDs = $file_phids;
return $this;
}
public function getFilePHIDs() {
return $this->assertAttached($this->filePHIDs);
}
public function loadImageURI($size) {
$file = $this->getImage($size);

View file

@ -2,7 +2,6 @@
final class ConpherenceTransaction extends PhabricatorApplicationTransaction {
const TYPE_FILES = 'files';
const TYPE_TITLE = 'title';
const TYPE_TOPIC = 'topic';
const TYPE_PARTICIPANTS = 'participants';
@ -44,8 +43,6 @@ final class ConpherenceTransaction extends PhabricatorApplicationTransaction {
case self::TYPE_PICTURE:
case self::TYPE_DATE_MARKER:
return false;
case self::TYPE_FILES:
return true;
case self::TYPE_PICTURE_CROP:
return true;
}
@ -68,29 +65,6 @@ final class ConpherenceTransaction extends PhabricatorApplicationTransaction {
case self::TYPE_PICTURE:
return $this->getRoomTitle();
break;
case self::TYPE_FILES:
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
if ($add && $rem) {
$title = pht(
'%s edited files(s), added %d and removed %d.',
$this->renderHandleLink($author_phid),
count($add),
count($rem));
} else if ($add) {
$title = pht(
'%s added %s files(s).',
$this->renderHandleLink($author_phid),
phutil_count($add));
} else {
$title = pht(
'%s removed %s file(s).',
$this->renderHandleLink($author_phid),
phutil_count($rem));
}
return $title;
break;
case self::TYPE_PARTICIPANTS:
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
@ -252,7 +226,6 @@ final class ConpherenceTransaction extends PhabricatorApplicationTransaction {
switch ($this->getTransactionType()) {
case self::TYPE_TITLE:
case self::TYPE_PICTURE:
case self::TYPE_FILES:
case self::TYPE_DATE_MARKER:
break;
case self::TYPE_PARTICIPANTS:

View file

@ -227,9 +227,6 @@ final class ConpherenceTransactionView extends AphrontView {
$content = null;
$handles = $this->getHandles();
switch ($transaction->getTransactionType()) {
case ConpherenceTransaction::TYPE_FILES:
$content = $transaction->getTitle();
break;
case ConpherenceTransaction::TYPE_TITLE:
case ConpherenceTransaction::TYPE_TOPIC:
case ConpherenceTransaction::TYPE_PICTURE:

View file

@ -2,8 +2,6 @@
final class DarkConsoleDataController extends PhabricatorController {
private $key;
public function shouldRequireLogin() {
return !PhabricatorEnv::getEnvConfig('darkconsole.always-on');
}
@ -16,19 +14,15 @@ final class DarkConsoleDataController extends PhabricatorController {
return true;
}
public function willProcessRequest(array $data) {
$this->key = $data['key'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$key = $request->getURIData('key');
$cache = new PhabricatorKeyValueDatabaseCache();
$cache = new PhutilKeyValueCacheProfiler($cache);
$cache->setProfiler(PhutilServiceProfiler::getInstance());
$result = $cache->getKey('darkconsole:'.$this->key);
$result = $cache->getKey('darkconsole:'.$key);
if (!$result) {
return new Aphront400Response();
}
@ -43,7 +37,7 @@ final class DarkConsoleDataController extends PhabricatorController {
return new Aphront400Response();
}
if ($result['user'] != $user->getPHID()) {
if ($result['user'] != $viewer->getPHID()) {
return new Aphront400Response();
}

View file

@ -2,19 +2,12 @@
final class DifferentialRevisionLandController extends DifferentialController {
private $revisionID;
private $strategyClass;
private $pushStrategy;
public function willProcessRequest(array $data) {
$this->revisionID = $data['id'];
$this->strategyClass = $data['strategy'];
}
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$revision_id = $this->revisionID;
$revision_id = $request->getURIData('id');
$strategy_class = $request->getURIData('strategy');
$revision = id(new DifferentialRevisionQuery())
->withIDs(array($revision_id))
@ -24,15 +17,15 @@ final class DifferentialRevisionLandController extends DifferentialController {
return new Aphront404Response();
}
if (is_subclass_of($this->strategyClass, 'DifferentialLandingStrategy')) {
$this->pushStrategy = newv($this->strategyClass, array());
if (is_subclass_of($strategy_class, 'DifferentialLandingStrategy')) {
$this->pushStrategy = newv($strategy_class, array());
} else {
throw new Exception(
pht(
"Strategy type must be a valid class name and must subclass ".
"%s. '%s' is not a subclass of %s",
'DifferentialLandingStrategy',
$this->strategyClass,
$strategy_class,
'DifferentialLandingStrategy'));
}

View file

@ -78,7 +78,7 @@ final class PhabricatorFilesApplication extends PhabricatorApplication {
'delete/(?P<id>[1-9]\d*)/' => 'PhabricatorFileDeleteController',
'edit/(?P<id>[1-9]\d*)/' => 'PhabricatorFileEditController',
'info/(?P<phid>[^/]+)/' => 'PhabricatorFileInfoController',
'proxy/' => 'PhabricatorFileProxyController',
'imageproxy/' => 'PhabricatorFileImageProxyController',
'transforms/(?P<id>[1-9]\d*)/' =>
'PhabricatorFileTransformListController',
'uploaddialog/(?P<single>single/)?'

View file

@ -0,0 +1,118 @@
<?php
final class PhabricatorFileImageProxyController
extends PhabricatorFileController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$show_prototypes = PhabricatorEnv::getEnvConfig(
'phabricator.show-prototypes');
if (!$show_prototypes) {
throw new Exception(
pht('Show prototypes is disabled.
Set `phabricator.show-prototypes` to `true` to use the image proxy'));
}
$viewer = $request->getViewer();
$img_uri = $request->getStr('uri');
// Validate the URI before doing anything
PhabricatorEnv::requireValidRemoteURIForLink($img_uri);
$uri = new PhutilURI($img_uri);
$proto = $uri->getProtocol();
if (!in_array($proto, array('http', 'https'))) {
throw new Exception(
pht('The provided image URI must be either http or https'));
}
// Check if we already have the specified image URI downloaded
$cached_request = id(new PhabricatorFileExternalRequest())->loadOneWhere(
'uriIndex = %s',
PhabricatorHash::digestForIndex($img_uri));
if ($cached_request) {
return $this->getExternalResponse($cached_request);
}
$ttl = PhabricatorTime::getNow() + phutil_units('7 days in seconds');
$external_request = id(new PhabricatorFileExternalRequest())
->setURI($img_uri)
->setTTL($ttl);
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
// Cache missed so we'll need to validate and download the image
try {
// Rate limit outbound fetches to make this mechanism less useful for
// scanning networks and ports.
PhabricatorSystemActionEngine::willTakeAction(
array($viewer->getPHID()),
new PhabricatorFilesOutboundRequestAction(),
1);
$file = PhabricatorFile::newFromFileDownload(
$uri,
array(
'viewPolicy' => PhabricatorPolicies::POLICY_NOONE,
'canCDN' => true,
));
if (!$file->isViewableImage()) {
$mime_type = $file->getMimeType();
$engine = new PhabricatorDestructionEngine();
$engine->destroyObject($file);
$file = null;
throw new Exception(
pht(
'The URI "%s" does not correspond to a valid image file, got '.
'a file with MIME type "%s". You must specify the URI of a '.
'valid image file.',
$uri,
$mime_type));
} else {
$file->save();
}
$external_request->setIsSuccessful(true)
->setFilePHID($file->getPHID())
->save();
unset($unguarded);
return $this->getExternalResponse($external_request);
} catch (HTTPFutureHTTPResponseStatus $status) {
$external_request->setIsSuccessful(false)
->setResponseMessage($status->getMessage())
->save();
return $this->getExternalResponse($external_request);
} catch (Exception $ex) {
// Not actually saving the request in this case
$external_request->setResponseMessage($ex->getMessage());
return $this->getExternalResponse($external_request);
}
}
private function getExternalResponse(
PhabricatorFileExternalRequest $request) {
if ($request->getIsSuccessful()) {
$file = id(new PhabricatorFileQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs(array($request->getFilePHID()))
->executeOne();
if (!file) {
throw new Exception(pht(
'The underlying file does not exist, but the cached request was '.
'successful. This likely means the file record was manually deleted '.
'by an administrator.'));
}
return id(new AphrontRedirectResponse())
->setIsExternal(true)
->setURI($file->getViewURI());
} else {
throw new Exception(pht(
"The request to get the external file from '%s' was unsuccessful:\n %s",
$request->getURI(),
$request->getResponseMessage()));
}
}
}

View file

@ -0,0 +1,28 @@
<?php
final class PhabricatorFileExternalRequestGarbageCollector
extends PhabricatorGarbageCollector {
const COLLECTORCONST = 'files.externalttl';
public function getCollectorName() {
return pht('External Requests (TTL)');
}
public function hasAutomaticPolicy() {
return true;
}
protected function collectGarbage() {
$file_requests = id(new PhabricatorFileExternalRequest())->loadAllWhere(
'ttl < %d LIMIT 100',
PhabricatorTime::getNow());
$engine = new PhabricatorDestructionEngine();
foreach ($file_requests as $request) {
$engine->destroyObject($request);
}
return (count($file_requests) == 100);
}
}

View file

@ -0,0 +1,63 @@
<?php
final class PhabricatorFileExternalRequest extends PhabricatorFileDAO
implements
PhabricatorDestructibleInterface {
protected $uri;
protected $uriIndex;
protected $ttl;
protected $filePHID;
protected $isSuccessful;
protected $responseMessage;
protected function getConfiguration() {
return array(
self::CONFIG_COLUMN_SCHEMA => array(
'uri' => 'text',
'uriIndex' => 'bytes12',
'ttl' => 'epoch',
'filePHID' => 'phid?',
'isSuccessful' => 'bool',
'responseMessage' => 'text?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_uriindex' => array(
'columns' => array('uriIndex'),
'unique' => true,
),
'key_ttl' => array(
'columns' => array('ttl'),
),
'key_file' => array(
'columns' => array('filePHID'),
),
),
) + parent::getConfiguration();
}
public function save() {
$hash = PhabricatorHash::digestForIndex($this->getURI());
$this->setURIIndex($hash);
return parent::save();
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$file_phid = $this->getFilePHID();
if ($file_phid) {
$file = id(new PhabricatorFileQuery())
->setViewer($engine->getViewer())
->withPHIDs(array($file_phid))
->executeOne();
if ($file) {
$engine->destroyObject($file);
}
}
$this->delete();
}
}

View file

@ -420,6 +420,10 @@ final class HarbormasterBuild extends HarbormasterDAO
->setKey('initiatorPHID')
->setType('phid')
->setDescription(pht('The person (or thing) that started this build.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('name')
->setType('string')
->setDescription(pht('The name of this build.')),
);
}
@ -433,6 +437,7 @@ final class HarbormasterBuild extends HarbormasterDAO
'name' => HarbormasterBuildStatus::getBuildStatusName($status),
),
'initiatorPHID' => nonempty($this->getInitiatorPHID(), null),
'name' => $this->getName(),
);
}

View file

@ -38,7 +38,6 @@ final class PhabricatorPasteApplication extends PhabricatorApplication {
=> 'PhabricatorPasteViewController',
'/paste/' => array(
'(query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorPasteListController',
'create/' => 'PhabricatorPasteEditController',
$this->getEditRoutePattern('edit/') => 'PhabricatorPasteEditController',
'raw/(?P<id>[1-9]\d*)/' => 'PhabricatorPasteRawController',
'archive/(?P<id>[1-9]\d*)/' => 'PhabricatorPasteArchiveController',

View file

@ -361,7 +361,7 @@ final class PhameBlog extends PhameDAO
public function isAutomaticallySubscribed($phid) {
return ($this->creatorPHID == $phid);
return false;
}

View file

@ -19,7 +19,7 @@ final class PhabricatorPhragmentApplication extends PhabricatorApplication {
}
public function getTitleGlyph() {
return "\xE2\x26\xB6";
return "\xE2\x96\x9B";
}
public function getApplicationGroup() {

View file

@ -46,9 +46,7 @@ final class PhabricatorPhurlApplication extends PhabricatorApplication {
'(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhabricatorPhurlURLListController',
'url/' => array(
'create/'
=> 'PhabricatorPhurlURLEditController',
'edit/(?P<id>[1-9]\d*)/'
$this->getEditRoutePattern('edit/')
=> 'PhabricatorPhurlURLEditController',
'comment/(?P<id>[1-9]\d*)/'
=> 'PhabricatorPhurlURLCommentController',

View file

@ -3,17 +3,10 @@
abstract class PhabricatorPhurlController extends PhabricatorController {
protected function buildApplicationCrumbs() {
$can_create = $this->hasApplicationCapability(
PhabricatorPhurlURLCreateCapability::CAPABILITY);
$crumbs = parent::buildApplicationCrumbs();
$crumbs->addAction(
id(new PHUIListItemView())
->setName(pht('Shorten URL'))
->setHref($this->getApplicationURI().'url/create/')
->setIcon('fa-plus-square')
->setDisabled(!$can_create)
->setWorkflow(!$can_create));
id(new PhabricatorPhurlURLEditEngine())
->setViewer($this->getViewer())
->addActionToCrumbs($crumbs);
return $crumbs;
}

View file

@ -4,263 +4,8 @@ final class PhabricatorPhurlURLEditController
extends PhabricatorPhurlController {
public function handleRequest(AphrontRequest $request) {
$id = $request->getURIData('id');
$is_create = !$id;
$viewer = $this->getViewer();
$user_phid = $viewer->getPHID();
$error_long_url = true;
$error_alias = null;
$validation_exception = null;
$next_workflow = $request->getStr('next');
$uri_query = $request->getStr('query');
if ($is_create) {
$this->requireApplicationCapability(
PhabricatorPhurlURLCreateCapability::CAPABILITY);
$url = PhabricatorPhurlURL::initializeNewPhurlURL(
$viewer);
$submit_label = pht('Create');
$page_title = pht('Shorten URL');
$header_icon = 'fa-plus-square';
$subscribers = array();
$cancel_uri = $this->getApplicationURI();
} else {
$url = id(new PhabricatorPhurlURLQuery())
->setViewer($viewer)
->withIDs(array($id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$url) {
return new Aphront404Response();
}
$submit_label = pht('Update');
$page_title = pht('Edit URL: %s', $url->getName());
$header_icon = 'fa-pencil';
$subscribers = PhabricatorSubscribersQuery::loadSubscribersForPHID(
$url->getPHID());
$cancel_uri = '/U'.$url->getID();
}
if ($is_create) {
$projects = array();
} else {
$projects = PhabricatorEdgeQuery::loadDestinationPHIDs(
$url->getPHID(),
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
$projects = array_reverse($projects);
}
$name = $url->getName();
$long_url = $url->getLongURL();
$alias = $url->getAlias();
$description = $url->getDescription();
$edit_policy = $url->getEditPolicy();
$view_policy = $url->getViewPolicy();
$space = $url->getSpacePHID();
if ($request->isFormPost()) {
$xactions = array();
$name = $request->getStr('name');
$long_url = $request->getStr('longURL');
$alias = $request->getStr('alias');
$projects = $request->getArr('projects');
$description = $request->getStr('description');
$subscribers = $request->getArr('subscribers');
$edit_policy = $request->getStr('editPolicy');
$view_policy = $request->getStr('viewPolicy');
$space = $request->getStr('spacePHID');
$xactions[] = id(new PhabricatorPhurlURLTransaction())
->setTransactionType(
PhabricatorPhurlURLTransaction::TYPE_NAME)
->setNewValue($name);
$xactions[] = id(new PhabricatorPhurlURLTransaction())
->setTransactionType(
PhabricatorPhurlURLTransaction::TYPE_URL)
->setNewValue($long_url);
$xactions[] = id(new PhabricatorPhurlURLTransaction())
->setTransactionType(
PhabricatorPhurlURLTransaction::TYPE_ALIAS)
->setNewValue($alias);
$xactions[] = id(new PhabricatorPhurlURLTransaction())
->setTransactionType(
PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setNewValue(array('=' => array_fuse($subscribers)));
$xactions[] = id(new PhabricatorPhurlURLTransaction())
->setTransactionType(
PhabricatorPhurlURLTransaction::TYPE_DESCRIPTION)
->setNewValue($description);
$xactions[] = id(new PhabricatorPhurlURLTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($view_policy);
$xactions[] = id(new PhabricatorPhurlURLTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
->setNewValue($edit_policy);
$xactions[] = id(new PhabricatorPhurlURLTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_SPACE)
->setNewValue($space);
$editor = id(new PhabricatorPhurlURLEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true);
try {
$proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$xactions[] = id(new PhabricatorPhurlURLTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $proj_edge_type)
->setNewValue(array('=' => array_fuse($projects)));
$xactions = $editor->applyTransactions($url, $xactions);
return id(new AphrontRedirectResponse())
->setURI($url->getURI());
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$error_long_url = $ex->getShortMessage(
PhabricatorPhurlURLTransaction::TYPE_URL);
$error_alias = $ex->getShortMessage(
PhabricatorPhurlURLTransaction::TYPE_ALIAS);
}
}
$current_policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($url)
->execute();
$name = id(new AphrontFormTextControl())
->setLabel(pht('Name'))
->setName('name')
->setValue($name);
$long_url = id(new AphrontFormTextControl())
->setLabel(pht('URL'))
->setName('longURL')
->setValue($long_url)
->setError($error_long_url);
$alias = id(new AphrontFormTextControl())
->setLabel(pht('Alias'))
->setName('alias')
->setValue($alias)
->setError($error_alias);
$projects = id(new AphrontFormTokenizerControl())
->setLabel(pht('Tags'))
->setName('projects')
->setValue($projects)
->setUser($viewer)
->setDatasource(new PhabricatorProjectDatasource());
$description = id(new PhabricatorRemarkupControl())
->setLabel(pht('Description'))
->setName('description')
->setValue($description)
->setUser($viewer);
$view_policies = id(new AphrontFormPolicyControl())
->setUser($viewer)
->setValue($view_policy)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicyObject($url)
->setPolicies($current_policies)
->setSpacePHID($space)
->setName('viewPolicy');
$edit_policies = id(new AphrontFormPolicyControl())
->setUser($viewer)
->setValue($edit_policy)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicyObject($url)
->setPolicies($current_policies)
->setName('editPolicy');
$subscribers = id(new AphrontFormTokenizerControl())
->setLabel(pht('Subscribers'))
->setName('subscribers')
->setValue($subscribers)
->setUser($viewer)
->setDatasource(new PhabricatorMetaMTAMailableDatasource());
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild($name)
->appendChild($long_url)
->appendChild($alias)
->appendControl($view_policies)
->appendControl($edit_policies)
->appendControl($subscribers)
->appendChild($projects)
->appendChild($description);
if ($request->isAjax()) {
return $this->newDialog()
->setTitle($page_title)
->setWidth(AphrontDialogView::WIDTH_FULL)
->appendForm($form)
->addCancelButton($cancel_uri)
->addSubmitButton($submit_label);
}
$submit = id(new AphrontFormSubmitControl())
->addCancelButton($cancel_uri)
->setValue($submit_label);
$form->appendChild($submit);
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($page_title)
->setForm($form);
$crumbs = $this->buildApplicationCrumbs();
if (!$is_create) {
$crumbs->addTextCrumb($url->getMonogram(), $url->getURI());
} else {
$crumbs->addTextCrumb(pht('Create URL'));
}
$crumbs->addTextCrumb($page_title);
$crumbs->setBorder(true);
$object_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('URL'))
->setValidationException($validation_exception)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($form);
$header = id(new PHUIHeaderView())
->setHeader($page_title)
->setHeaderIcon($header_icon);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter(array(
$object_box,
));
return $this->newPage()
->setTitle($page_title)
->setCrumbs($crumbs)
->appendChild($view);
return id(new PhabricatorPhurlURLEditEngine())
->setController($this)
->buildResponse();
}
}

View file

@ -0,0 +1,104 @@
<?php
final class PhabricatorPhurlURLEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'phurl.url';
public function getEngineName() {
return pht('Phurl');
}
public function getEngineApplicationClass() {
return 'PhabricatorPhurlApplication';
}
public function getSummaryHeader() {
return pht('Configure Phurl Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms in Phurl.');
}
protected function newEditableObject() {
return PhabricatorPhurlURL::initializeNewPhurlURL($this->getViewer());
}
protected function newObjectQuery() {
return new PhabricatorPhurlURLQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New URL');
}
protected function getObjectEditTitleText($object) {
return pht('Edit URL: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getName();
}
protected function getObjectCreateShortText() {
return pht('Create URL');
}
protected function getObjectName() {
return pht('URL');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('url/edit/');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
PhabricatorPhurlURLCreateCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('URL name.'))
->setConduitTypeDescription(pht('New URL name.'))
->setTransactionType(PhabricatorPhurlURLTransaction::TYPE_NAME)
->setValue($object->getName()),
id(new PhabricatorTextEditField())
->setKey('url')
->setLabel(pht('URL'))
->setDescription(pht('The URL to shorten.'))
->setConduitTypeDescription(pht('New URL.'))
->setValue($object->getLongURL())
->setIsRequired(true)
->setTransactionType(PhabricatorPhurlURLTransaction::TYPE_URL),
id(new PhabricatorTextEditField())
->setKey('alias')
->setLabel(pht('Alias'))
->setTransactionType(PhabricatorPhurlURLTransaction::TYPE_ALIAS)
->setDescription(pht('The alias to give the URL.'))
->setConduitTypeDescription(pht('New alias.'))
->setValue($object->getAlias()),
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setDescription(pht('URL long description.'))
->setConduitTypeDescription(pht('New URL description.'))
->setTransactionType(PhabricatorPhurlURLTransaction::TYPE_DESCRIPTION)
->setValue($object->getDescription()),
);
}
}

View file

@ -99,10 +99,13 @@ final class PhabricatorPhurlURLSearchEngine
}
protected function getNewUserBody() {
$create_uri = id(new PhabricatorPhurlURLEditEngine())
->getEditURI();
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Shorten a URL'))
->setHref('/phurl/url/create/')
->setHref($create_uri)
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();

View file

@ -682,7 +682,32 @@ final class PhabricatorRepositoryDiscoveryEngine
$data['commitID'] = $commit->getID();
PhabricatorWorker::scheduleTask($class, $data);
// If the repository is importing for the first time, we schedule tasks
// at IMPORT priority, which is very low. Making progress on importing a
// new repository for the first time is less important than any other
// daemon task.
// If the repostitory has finished importing and we're just catching up
// on recent commits, we schedule discovery at COMMIT priority, which is
// slightly below the default priority.
// Note that followup tasks and triggered tasks (like those generated by
// Herald or Harbormaster) will queue at DEFAULT priority, so that each
// commit tends to fully import before we start the next one. This tends
// to give imports fairly predictable progress. See T11677 for some
// discussion.
if ($repository->isImporting()) {
$task_priority = PhabricatorWorker::PRIORITY_IMPORT;
} else {
$task_priority = PhabricatorWorker::PRIORITY_COMMIT;
}
$options = array(
'priority' => $task_priority,
);
PhabricatorWorker::scheduleTask($class, $data, $options);
}
private function isInitialImport(array $refs) {

View file

@ -47,6 +47,14 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker
$this->getFollowupTaskClass(),
array(
'commitID' => $commit->getID(),
),
array(
// We queue followup tasks at default priority so that the queue
// finishes work it has started before starting more work. If
// followups are queued at the same priority level, we do all
// message parses first, then all change parses, etc. This makes
// progress uneven. See T11677 for discussion.
'priority' => PhabricatorWorker::PRIORITY_DEFAULT,
));
}
}

View file

@ -72,10 +72,6 @@ final class PhabricatorStandardCustomFieldText
return new AphrontStringHTTPParameterType();
}
public function shouldAppearInApplicationSearch() {
return false;
}
public function getConduitEditParameterType() {
return new ConduitStringParameterType();
}

View file

@ -16,6 +16,7 @@ abstract class PhabricatorWorker extends Phobject {
const PRIORITY_ALERTS = 1000;
const PRIORITY_DEFAULT = 2000;
const PRIORITY_COMMIT = 2500;
const PRIORITY_BULK = 3000;
const PRIORITY_IMPORT = 4000;

View file

@ -51,12 +51,19 @@ final class ManiphestTaskGraph
$assigned = phutil_tag('em', array(), pht('None'));
}
$full_title = $object->getTitle();
$title = id(new PhutilUTF8StringTruncator())
->setMaximumGlyphs(80)
->truncateString($full_title);
$link = phutil_tag(
'a',
array(
'href' => $object->getURI(),
'title' => $full_title,
),
$object->getTitle());
$title);
$link = array(
phutil_tag(
@ -95,8 +102,6 @@ final class ManiphestTaskGraph
));
}
$link = AphrontTableView::renderSingleDisplayLine($link);
return array(
$marker,
$trace,

View file

@ -75,10 +75,19 @@ abstract class PhabricatorLiskDAO extends LiskDAO {
$connection->setReadOnly(true);
}
// Unless this is a script running from the CLI, prevent any query from
// running for more than 30 seconds. See T10849 for discussion.
// Unless this is a script running from the CLI:
// - (T10849) Prevent any query from running for more than 30 seconds.
// - (T11672) Use persistent connections.
if (php_sapi_name() != 'cli') {
$connection->setQueryTimeout(30);
// TODO: For now, disable this until after T11044: it's better at high
// load, but causes us to use slightly more connections at low load and
// is pushing users over limits like MySQL "max_connections".
$use_persistent = false;
$connection
->setQueryTimeout(30)
->setPersistent($use_persistent);
}
return $connection;

View file

@ -228,6 +228,10 @@ span.single-display-line-content {
position: static;
}
.aphront-table-view td.object-link {
white-space: nowrap;
}
.aphront-table-view tr.closed td.object-link .object-name,
.aphront-table-view tr.alt-closed td.object-link .object-name {
text-decoration: line-through;

View file

@ -56,14 +56,6 @@ body.white-background {
color: {$greytext};
}
.keyboard-shortcut-help kbd {
background: #222222;
padding: 6px;
color: #ffffff;
font-weight: bold;
border: 1px solid #555555;
}
.keyboard-focus-focus-reticle {
background: #ffffd3;
position: absolute;