mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-26 14:38:19 +01:00
(stable) Promote 2018 Week 31
This commit is contained in:
commit
b45047f952
32 changed files with 468 additions and 92 deletions
|
@ -9,7 +9,7 @@ return array(
|
||||||
'names' => array(
|
'names' => array(
|
||||||
'conpherence.pkg.css' => 'e68cf1fa',
|
'conpherence.pkg.css' => 'e68cf1fa',
|
||||||
'conpherence.pkg.js' => '15191c65',
|
'conpherence.pkg.js' => '15191c65',
|
||||||
'core.pkg.css' => 'e5233bff',
|
'core.pkg.css' => 'f515619b',
|
||||||
'core.pkg.js' => '2058ec09',
|
'core.pkg.js' => '2058ec09',
|
||||||
'differential.pkg.css' => '06dc617c',
|
'differential.pkg.css' => '06dc617c',
|
||||||
'differential.pkg.js' => 'ef19e026',
|
'differential.pkg.js' => 'ef19e026',
|
||||||
|
@ -154,7 +154,7 @@ return array(
|
||||||
'rsrc/css/phui/phui-form-view.css' => 'ae9f8d16',
|
'rsrc/css/phui/phui-form-view.css' => 'ae9f8d16',
|
||||||
'rsrc/css/phui/phui-form.css' => '7aaa04e3',
|
'rsrc/css/phui/phui-form.css' => '7aaa04e3',
|
||||||
'rsrc/css/phui/phui-head-thing.css' => 'fd311e5f',
|
'rsrc/css/phui/phui-head-thing.css' => 'fd311e5f',
|
||||||
'rsrc/css/phui/phui-header-view.css' => '31dc6c72',
|
'rsrc/css/phui/phui-header-view.css' => 'edeb9252',
|
||||||
'rsrc/css/phui/phui-hovercard.css' => 'f0592bcf',
|
'rsrc/css/phui/phui-hovercard.css' => 'f0592bcf',
|
||||||
'rsrc/css/phui/phui-icon-set-selector.css' => '87db8fee',
|
'rsrc/css/phui/phui-icon-set-selector.css' => '87db8fee',
|
||||||
'rsrc/css/phui/phui-icon.css' => 'cf24ceec',
|
'rsrc/css/phui/phui-icon.css' => 'cf24ceec',
|
||||||
|
@ -821,7 +821,7 @@ return array(
|
||||||
'phui-form-css' => '7aaa04e3',
|
'phui-form-css' => '7aaa04e3',
|
||||||
'phui-form-view-css' => 'ae9f8d16',
|
'phui-form-view-css' => 'ae9f8d16',
|
||||||
'phui-head-thing-view-css' => 'fd311e5f',
|
'phui-head-thing-view-css' => 'fd311e5f',
|
||||||
'phui-header-view-css' => '31dc6c72',
|
'phui-header-view-css' => 'edeb9252',
|
||||||
'phui-hovercard' => '1bd28176',
|
'phui-hovercard' => '1bd28176',
|
||||||
'phui-hovercard-view-css' => 'f0592bcf',
|
'phui-hovercard-view-css' => 'f0592bcf',
|
||||||
'phui-icon-set-selector-css' => '87db8fee',
|
'phui-icon-set-selector-css' => '87db8fee',
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_phriction.phriction_document
|
||||||
|
ADD spacePHID VARBINARY(64) DEFAULT NULL;
|
2
resources/sql/autopatches/20180730.project.01.spaces.sql
Normal file
2
resources/sql/autopatches/20180730.project.01.spaces.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_project.project
|
||||||
|
ADD COLUMN spacePHID VARBINARY(64) DEFAULT NULL;
|
|
@ -27,7 +27,15 @@ $args->parsePartial(
|
||||||
'param' => pht('port'),
|
'param' => pht('port'),
|
||||||
'help' => pht('Port number to connect to.'),
|
'help' => pht('Port number to connect to.'),
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'options',
|
||||||
|
'short' => 'o',
|
||||||
|
'param' => pht('options'),
|
||||||
|
'repeat' => true,
|
||||||
|
'help' => pht('SSH options.'),
|
||||||
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
$unconsumed_argv = $args->getUnconsumedArgumentVector();
|
$unconsumed_argv = $args->getUnconsumedArgumentVector();
|
||||||
|
|
||||||
if (function_exists('pcntl_signal')) {
|
if (function_exists('pcntl_signal')) {
|
||||||
|
@ -113,6 +121,25 @@ if ($port) {
|
||||||
$arguments[] = $port;
|
$arguments[] = $port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$options = $args->getArg('options');
|
||||||
|
$allowed_ssh_options = array('SendEnv=GIT_PROTOCOL');
|
||||||
|
|
||||||
|
if (!empty($options)) {
|
||||||
|
foreach ($options as $option) {
|
||||||
|
if (array_search($option, $allowed_ssh_options) !== false) {
|
||||||
|
$pattern[] = '-o %s';
|
||||||
|
$arguments[] = $option;
|
||||||
|
} else {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Disallowed ssh option "%s" given with "-o". '.
|
||||||
|
'Allowed options are: %s.',
|
||||||
|
$option,
|
||||||
|
implode(', ', $allowed_ssh_options)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$pattern[] = '--';
|
$pattern[] = '--';
|
||||||
|
|
||||||
$pattern[] = '%s';
|
$pattern[] = '%s';
|
||||||
|
|
|
@ -9752,6 +9752,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorFerretInterface',
|
'PhabricatorFerretInterface',
|
||||||
'PhabricatorConduitResultInterface',
|
'PhabricatorConduitResultInterface',
|
||||||
'PhabricatorColumnProxyInterface',
|
'PhabricatorColumnProxyInterface',
|
||||||
|
'PhabricatorSpacesInterface',
|
||||||
),
|
),
|
||||||
'PhabricatorProjectAddHeraldAction' => 'PhabricatorProjectHeraldAction',
|
'PhabricatorProjectAddHeraldAction' => 'PhabricatorProjectHeraldAction',
|
||||||
'PhabricatorProjectApplication' => 'PhabricatorApplication',
|
'PhabricatorProjectApplication' => 'PhabricatorApplication',
|
||||||
|
@ -11128,6 +11129,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorApplicationTransactionInterface',
|
'PhabricatorApplicationTransactionInterface',
|
||||||
'PhabricatorConduitResultInterface',
|
'PhabricatorConduitResultInterface',
|
||||||
'PhabricatorPolicyCodexInterface',
|
'PhabricatorPolicyCodexInterface',
|
||||||
|
'PhabricatorSpacesInterface',
|
||||||
),
|
),
|
||||||
'PhrictionDocumentAuthorHeraldField' => 'PhrictionDocumentHeraldField',
|
'PhrictionDocumentAuthorHeraldField' => 'PhrictionDocumentHeraldField',
|
||||||
'PhrictionDocumentContentHeraldField' => 'PhrictionDocumentHeraldField',
|
'PhrictionDocumentContentHeraldField' => 'PhrictionDocumentHeraldField',
|
||||||
|
|
|
@ -9,6 +9,14 @@ final class DiffusionGetRecentCommitsByPathConduitAPIMethod
|
||||||
return 'diffusion.getrecentcommitsbypath';
|
return 'diffusion.getrecentcommitsbypath';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getMethodStatus() {
|
||||||
|
return self::METHOD_STATUS_DEPRECATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMethodStatusDescription() {
|
||||||
|
return pht('Obsoleted by "diffusion.historyquery".');
|
||||||
|
}
|
||||||
|
|
||||||
public function getMethodDescription() {
|
public function getMethodDescription() {
|
||||||
return pht(
|
return pht(
|
||||||
'Get commit identifiers for recent commits affecting a given path.');
|
'Get commit identifiers for recent commits affecting a given path.');
|
||||||
|
@ -23,6 +31,12 @@ final class DiffusionGetRecentCommitsByPathConduitAPIMethod
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function defineErrorTypes() {
|
||||||
|
return array(
|
||||||
|
'ERR_NOT_FOUND' => pht('Repository was not found.'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
protected function defineReturnType() {
|
protected function defineReturnType() {
|
||||||
return 'nonempty list<string>';
|
return 'nonempty list<string>';
|
||||||
}
|
}
|
||||||
|
@ -36,6 +50,10 @@ final class DiffusionGetRecentCommitsByPathConduitAPIMethod
|
||||||
'branch' => $request->getValue('branch'),
|
'branch' => $request->getValue('branch'),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if ($drequest === null) {
|
||||||
|
throw new ConduitException('ERR_NOT_FOUND');
|
||||||
|
}
|
||||||
|
|
||||||
$limit = nonempty(
|
$limit = nonempty(
|
||||||
$request->getValue('limit'),
|
$request->getValue('limit'),
|
||||||
self::DEFAULT_LIMIT);
|
self::DEFAULT_LIMIT);
|
||||||
|
|
|
@ -14,6 +14,8 @@ final class DiffusionPushLogListView extends AphrontView {
|
||||||
$logs = $this->logs;
|
$logs = $this->logs;
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$reject_herald = PhabricatorRepositoryPushLog::REJECT_HERALD;
|
||||||
|
|
||||||
$handle_phids = array();
|
$handle_phids = array();
|
||||||
foreach ($logs as $log) {
|
foreach ($logs as $log) {
|
||||||
$handle_phids[] = $log->getPusherPHID();
|
$handle_phids[] = $log->getPusherPHID();
|
||||||
|
@ -21,9 +23,13 @@ final class DiffusionPushLogListView extends AphrontView {
|
||||||
if ($device_phid) {
|
if ($device_phid) {
|
||||||
$handle_phids[] = $device_phid;
|
$handle_phids[] = $device_phid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($log->getPushEvent()->getRejectCode() == $reject_herald) {
|
||||||
|
$handle_phids[] = $log->getPushEvent()->getRejectDetails();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$handles = $viewer->loadHandles($handle_phids);
|
$viewer->loadHandles($handle_phids);
|
||||||
|
|
||||||
// Only administrators can view remote addresses.
|
// Only administrators can view remote addresses.
|
||||||
$remotes_visible = $viewer->getIsAdmin();
|
$remotes_visible = $viewer->getIsAdmin();
|
||||||
|
@ -74,10 +80,17 @@ final class DiffusionPushLogListView extends AphrontView {
|
||||||
$flag_names);
|
$flag_names);
|
||||||
|
|
||||||
$reject_code = $log->getPushEvent()->getRejectCode();
|
$reject_code = $log->getPushEvent()->getRejectCode();
|
||||||
$reject_label = idx(
|
|
||||||
$reject_map,
|
if ($reject_code == $reject_herald) {
|
||||||
$reject_code,
|
$rule_phid = $log->getPushEvent()->getRejectDetails();
|
||||||
pht('Unknown ("%s")', $reject_code));
|
$handle = $viewer->renderHandle($rule_phid);
|
||||||
|
$reject_label = pht('Blocked: %s', $handle);
|
||||||
|
} else {
|
||||||
|
$reject_label = idx(
|
||||||
|
$reject_map,
|
||||||
|
$reject_code,
|
||||||
|
pht('Unknown ("%s")', $reject_code));
|
||||||
|
}
|
||||||
|
|
||||||
$rows[] = array(
|
$rows[] = array(
|
||||||
phutil_tag(
|
phutil_tag(
|
||||||
|
|
|
@ -159,10 +159,22 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
||||||
|
|
||||||
public function saveAndIndex() {
|
public function saveAndIndex() {
|
||||||
$this->save();
|
$this->save();
|
||||||
PhabricatorSearchWorker::queueDocumentForIndexing($this->getPHID());
|
|
||||||
|
if ($this->isIndexableFile()) {
|
||||||
|
PhabricatorSearchWorker::queueDocumentForIndexing($this->getPHID());
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function isIndexableFile() {
|
||||||
|
if ($this->getIsChunk()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function getMonogram() {
|
public function getMonogram() {
|
||||||
return 'F'.$this->getID();
|
return 'F'.$this->getID();
|
||||||
}
|
}
|
||||||
|
|
|
@ -643,7 +643,13 @@ final class HarbormasterBuildLog
|
||||||
$pos += $slice_length;
|
$pos += $slice_length;
|
||||||
|
|
||||||
$map_bytes += $slice_length;
|
$map_bytes += $slice_length;
|
||||||
$line_count += count(preg_split("/\r\n|\r|\n/", $slice)) - 1;
|
|
||||||
|
// Count newlines in the slice. This goofy approach is meaningfully
|
||||||
|
// faster than "preg_match_all()" or "preg_split()". See PHI766.
|
||||||
|
$n_rn = substr_count($slice, "\r\n");
|
||||||
|
$n_r = substr_count($slice, "\r");
|
||||||
|
$n_n = substr_count($slice, "\n");
|
||||||
|
$line_count += ($n_rn) + ($n_r - $n_rn) + ($n_n - $n_rn);
|
||||||
|
|
||||||
if ($map_bytes >= ($marker_distance - $max_utf8_width)) {
|
if ($map_bytes >= ($marker_distance - $max_utf8_width)) {
|
||||||
$map[] = array(
|
$map[] = array(
|
||||||
|
|
|
@ -19,10 +19,18 @@ final class HeraldRuleDatasource
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
$raw_query = $this->getRawQuery();
|
$raw_query = $this->getRawQuery();
|
||||||
|
|
||||||
$rules = id(new HeraldRuleQuery())
|
$query = id(new HeraldRuleQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer);
|
||||||
->withDatasourceQuery($raw_query)
|
|
||||||
->execute();
|
if (preg_match('/^[hH]\d+\z/', $raw_query)) {
|
||||||
|
$id = trim($raw_query, 'hH');
|
||||||
|
$id = (int)$id;
|
||||||
|
$query->withIDs(array($id));
|
||||||
|
} else {
|
||||||
|
$query->withDatasourceQuery($raw_query);
|
||||||
|
}
|
||||||
|
|
||||||
|
$rules = $query->execute();
|
||||||
|
|
||||||
$handles = id(new PhabricatorHandleQuery())
|
$handles = id(new PhabricatorHandleQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
|
|
|
@ -6,6 +6,9 @@ abstract class PhabricatorMailImplementationAdapter extends Phobject {
|
||||||
private $priority;
|
private $priority;
|
||||||
private $options = array();
|
private $options = array();
|
||||||
|
|
||||||
|
private $supportsInbound = true;
|
||||||
|
private $supportsOutbound = true;
|
||||||
|
|
||||||
final public function getAdapterType() {
|
final public function getAdapterType() {
|
||||||
return $this->getPhobjectClassConstant('ADAPTERTYPE');
|
return $this->getPhobjectClassConstant('ADAPTERTYPE');
|
||||||
}
|
}
|
||||||
|
@ -67,6 +70,24 @@ abstract class PhabricatorMailImplementationAdapter extends Phobject {
|
||||||
return $this->priority;
|
return $this->priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final public function setSupportsInbound($supports_inbound) {
|
||||||
|
$this->supportsInbound = $supports_inbound;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getSupportsInbound() {
|
||||||
|
return $this->supportsInbound;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function setSupportsOutbound($supports_outbound) {
|
||||||
|
$this->supportsOutbound = $supports_outbound;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getSupportsOutbound() {
|
||||||
|
return $this->supportsOutbound;
|
||||||
|
}
|
||||||
|
|
||||||
final public function getOption($key) {
|
final public function getOption($key) {
|
||||||
if (!array_key_exists($key, $this->options)) {
|
if (!array_key_exists($key, $this->options)) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
|
|
|
@ -17,9 +17,12 @@ final class PhabricatorMetaMTAMailgunReceiveController
|
||||||
// inbound mail from any of them. Test the signature to see if it matches
|
// inbound mail from any of them. Test the signature to see if it matches
|
||||||
// any configured Mailgun mailer.
|
// any configured Mailgun mailer.
|
||||||
|
|
||||||
$mailers = PhabricatorMetaMTAMail::newMailersWithTypes(
|
$mailers = PhabricatorMetaMTAMail::newMailers(
|
||||||
array(
|
array(
|
||||||
PhabricatorMailImplementationMailgunAdapter::ADAPTERTYPE,
|
'inbound' => true,
|
||||||
|
'types' => array(
|
||||||
|
PhabricatorMailImplementationMailgunAdapter::ADAPTERTYPE,
|
||||||
|
),
|
||||||
));
|
));
|
||||||
foreach ($mailers as $mailer) {
|
foreach ($mailers as $mailer) {
|
||||||
$api_key = $mailer->getOption('api-key');
|
$api_key = $mailer->getOption('api-key');
|
||||||
|
|
|
@ -12,9 +12,12 @@ final class PhabricatorMetaMTAPostmarkReceiveController
|
||||||
*/
|
*/
|
||||||
public function handleRequest(AphrontRequest $request) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
// Don't process requests if we don't have a configured Postmark adapter.
|
// Don't process requests if we don't have a configured Postmark adapter.
|
||||||
$mailers = PhabricatorMetaMTAMail::newMailersWithTypes(
|
$mailers = PhabricatorMetaMTAMail::newMailers(
|
||||||
array(
|
array(
|
||||||
PhabricatorMailImplementationPostmarkAdapter::ADAPTERTYPE,
|
'inbound' => true,
|
||||||
|
'types' => array(
|
||||||
|
PhabricatorMailImplementationPostmarkAdapter::ADAPTERTYPE,
|
||||||
|
),
|
||||||
));
|
));
|
||||||
if (!$mailers) {
|
if (!$mailers) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
|
|
|
@ -11,9 +11,12 @@ final class PhabricatorMetaMTASendGridReceiveController
|
||||||
// SendGrid doesn't sign payloads so we can't be sure that SendGrid
|
// SendGrid doesn't sign payloads so we can't be sure that SendGrid
|
||||||
// actually sent this request, but require a configured SendGrid mailer
|
// actually sent this request, but require a configured SendGrid mailer
|
||||||
// before we activate this endpoint.
|
// before we activate this endpoint.
|
||||||
$mailers = PhabricatorMetaMTAMail::newMailersWithTypes(
|
$mailers = PhabricatorMetaMTAMail::newMailers(
|
||||||
array(
|
array(
|
||||||
PhabricatorMailImplementationSendGridAdapter::ADAPTERTYPE,
|
'inbound' => true,
|
||||||
|
'types' => array(
|
||||||
|
PhabricatorMailImplementationSendGridAdapter::ADAPTERTYPE,
|
||||||
|
),
|
||||||
));
|
));
|
||||||
if (!$mailers) {
|
if (!$mailers) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
|
|
|
@ -168,7 +168,8 @@ final class PhabricatorMailManagementSendTestWorkflow
|
||||||
|
|
||||||
$mailer_key = $args->getArg('mailer');
|
$mailer_key = $args->getArg('mailer');
|
||||||
if ($mailer_key !== null) {
|
if ($mailer_key !== null) {
|
||||||
$mailers = PhabricatorMetaMTAMail::newMailers();
|
$mailers = PhabricatorMetaMTAMail::newMailers(array());
|
||||||
|
|
||||||
$mailers = mpull($mailers, null, 'getKey');
|
$mailers = mpull($mailers, null, 'getKey');
|
||||||
if (!isset($mailers[$mailer_key])) {
|
if (!isset($mailers[$mailer_key])) {
|
||||||
throw new PhutilArgumentUsageException(
|
throw new PhutilArgumentUsageException(
|
||||||
|
@ -178,6 +179,13 @@ final class PhabricatorMailManagementSendTestWorkflow
|
||||||
implode(', ', array_keys($mailers))));
|
implode(', ', array_keys($mailers))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$mailers[$mailer_key]->getSupportsOutbound()) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht(
|
||||||
|
'Mailer ("%s") is not configured to support outbound mail.',
|
||||||
|
$mailer_key));
|
||||||
|
}
|
||||||
|
|
||||||
$mail->setTryMailers(array($mailer_key));
|
$mail->setTryMailers(array($mailer_key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -494,7 +494,10 @@ final class PhabricatorMetaMTAMail
|
||||||
throw new Exception(pht('Trying to send an already-sent mail!'));
|
throw new Exception(pht('Trying to send an already-sent mail!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$mailers = self::newMailers();
|
$mailers = self::newMailers(
|
||||||
|
array(
|
||||||
|
'outbound' => true,
|
||||||
|
));
|
||||||
|
|
||||||
$try_mailers = $this->getParam('mailers.try');
|
$try_mailers = $this->getParam('mailers.try');
|
||||||
if ($try_mailers) {
|
if ($try_mailers) {
|
||||||
|
@ -505,21 +508,15 @@ final class PhabricatorMetaMTAMail
|
||||||
return $this->sendWithMailers($mailers);
|
return $this->sendWithMailers($mailers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function newMailersWithTypes(array $types) {
|
public static function newMailers(array $constraints) {
|
||||||
$mailers = self::newMailers();
|
PhutilTypeSpec::checkMap(
|
||||||
$types = array_fuse($types);
|
$constraints,
|
||||||
|
array(
|
||||||
|
'types' => 'optional list<string>',
|
||||||
|
'inbound' => 'optional bool',
|
||||||
|
'outbound' => 'optional bool',
|
||||||
|
));
|
||||||
|
|
||||||
foreach ($mailers as $key => $mailer) {
|
|
||||||
$mailer_type = $mailer->getAdapterType();
|
|
||||||
if (!isset($types[$mailer_type])) {
|
|
||||||
unset($mailers[$key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_values($mailers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function newMailers() {
|
|
||||||
$mailers = array();
|
$mailers = array();
|
||||||
|
|
||||||
$config = PhabricatorEnv::getEnvConfig('cluster.mailers');
|
$config = PhabricatorEnv::getEnvConfig('cluster.mailers');
|
||||||
|
@ -565,10 +562,45 @@ final class PhabricatorMetaMTAMail
|
||||||
$options = idx($spec, 'options', array()) + $defaults;
|
$options = idx($spec, 'options', array()) + $defaults;
|
||||||
$mailer->setOptions($options);
|
$mailer->setOptions($options);
|
||||||
|
|
||||||
|
$mailer->setSupportsInbound(idx($spec, 'inbound', true));
|
||||||
|
$mailer->setSupportsOutbound(idx($spec, 'outbound', true));
|
||||||
|
|
||||||
$mailers[] = $mailer;
|
$mailers[] = $mailer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove mailers with the wrong types.
|
||||||
|
if (isset($constraints['types'])) {
|
||||||
|
$types = $constraints['types'];
|
||||||
|
$types = array_fuse($types);
|
||||||
|
foreach ($mailers as $key => $mailer) {
|
||||||
|
$mailer_type = $mailer->getAdapterType();
|
||||||
|
if (!isset($types[$mailer_type])) {
|
||||||
|
unset($mailers[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're only looking for inbound mailers, remove mailers with inbound
|
||||||
|
// support disabled.
|
||||||
|
if (!empty($constraints['inbound'])) {
|
||||||
|
foreach ($mailers as $key => $mailer) {
|
||||||
|
if (!$mailer->getSupportsInbound()) {
|
||||||
|
unset($mailers[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're only looking for outbound mailers, remove mailers with outbound
|
||||||
|
// support disabled.
|
||||||
|
if (!empty($constraints['outbound'])) {
|
||||||
|
foreach ($mailers as $key => $mailer) {
|
||||||
|
if (!$mailer->getSupportsOutbound()) {
|
||||||
|
unset($mailers[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$sorted = array();
|
$sorted = array();
|
||||||
$groups = mgroup($mailers, 'getPriority');
|
$groups = mgroup($mailers, 'getPriority');
|
||||||
krsort($groups);
|
krsort($groups);
|
||||||
|
@ -589,9 +621,24 @@ final class PhabricatorMetaMTAMail
|
||||||
|
|
||||||
public function sendWithMailers(array $mailers) {
|
public function sendWithMailers(array $mailers) {
|
||||||
if (!$mailers) {
|
if (!$mailers) {
|
||||||
|
$any_mailers = self::newMailers();
|
||||||
|
|
||||||
|
// NOTE: We can end up here with some custom list of "$mailers", like
|
||||||
|
// from a unit test. In that case, this message could be misleading. We
|
||||||
|
// can't really tell if the caller made up the list, so just assume they
|
||||||
|
// aren't tricking us.
|
||||||
|
|
||||||
|
if ($any_mailers) {
|
||||||
|
$void_message = pht(
|
||||||
|
'No configured mailers support sending outbound mail.');
|
||||||
|
} else {
|
||||||
|
$void_message = pht(
|
||||||
|
'No mailers are configured.');
|
||||||
|
}
|
||||||
|
|
||||||
return $this
|
return $this
|
||||||
->setStatus(PhabricatorMailOutboundStatus::STATUS_VOID)
|
->setStatus(PhabricatorMailOutboundStatus::STATUS_VOID)
|
||||||
->setMessage(pht('No mailers are configured.'))
|
->setMessage($void_message)
|
||||||
->save();
|
->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,11 +118,80 @@ final class PhabricatorMailConfigTestCase
|
||||||
$this->assertTrue($saw_a1 && $saw_a2);
|
$this->assertTrue($saw_a1 && $saw_a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function newMailersWithConfig(array $config) {
|
public function testMailerConstraints() {
|
||||||
|
$config = array(
|
||||||
|
array(
|
||||||
|
'key' => 'X1',
|
||||||
|
'type' => 'test',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'key' => 'X1-in',
|
||||||
|
'type' => 'test',
|
||||||
|
'outbound' => false,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'key' => 'X1-out',
|
||||||
|
'type' => 'test',
|
||||||
|
'inbound' => false,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'key' => 'X1-void',
|
||||||
|
'type' => 'test',
|
||||||
|
'inbound' => false,
|
||||||
|
'outbound' => false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$mailers = $this->newMailersWithConfig(
|
||||||
|
$config,
|
||||||
|
array());
|
||||||
|
$this->assertEqual(4, count($mailers));
|
||||||
|
|
||||||
|
$mailers = $this->newMailersWithConfig(
|
||||||
|
$config,
|
||||||
|
array(
|
||||||
|
'inbound' => true,
|
||||||
|
));
|
||||||
|
$this->assertEqual(2, count($mailers));
|
||||||
|
|
||||||
|
$mailers = $this->newMailersWithConfig(
|
||||||
|
$config,
|
||||||
|
array(
|
||||||
|
'outbound' => true,
|
||||||
|
));
|
||||||
|
$this->assertEqual(2, count($mailers));
|
||||||
|
|
||||||
|
$mailers = $this->newMailersWithConfig(
|
||||||
|
$config,
|
||||||
|
array(
|
||||||
|
'inbound' => true,
|
||||||
|
'outbound' => true,
|
||||||
|
));
|
||||||
|
$this->assertEqual(1, count($mailers));
|
||||||
|
|
||||||
|
$mailers = $this->newMailersWithConfig(
|
||||||
|
$config,
|
||||||
|
array(
|
||||||
|
'types' => array('test'),
|
||||||
|
));
|
||||||
|
$this->assertEqual(4, count($mailers));
|
||||||
|
|
||||||
|
$mailers = $this->newMailersWithConfig(
|
||||||
|
$config,
|
||||||
|
array(
|
||||||
|
'types' => array('duck'),
|
||||||
|
));
|
||||||
|
$this->assertEqual(0, count($mailers));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function newMailersWithConfig(
|
||||||
|
array $config,
|
||||||
|
array $constraints = array()) {
|
||||||
|
|
||||||
$env = PhabricatorEnv::beginScopedEnv();
|
$env = PhabricatorEnv::beginScopedEnv();
|
||||||
$env->overrideEnvConfig('cluster.mailers', $config);
|
$env->overrideEnvConfig('cluster.mailers', $config);
|
||||||
|
|
||||||
$mailers = PhabricatorMetaMTAMail::newMailers();
|
$mailers = PhabricatorMetaMTAMail::newMailers($constraints);
|
||||||
|
|
||||||
unset($env);
|
unset($env);
|
||||||
return $mailers;
|
return $mailers;
|
||||||
|
|
|
@ -254,7 +254,8 @@ final class PhrictionDocumentController
|
||||||
PhrictionContent $content,
|
PhrictionContent $content,
|
||||||
$slug) {
|
$slug) {
|
||||||
|
|
||||||
$viewer = $this->getRequest()->getUser();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
$view = id(new PHUIPropertyListView())
|
$view = id(new PHUIPropertyListView())
|
||||||
->setUser($viewer)
|
->setUser($viewer)
|
||||||
->setObject($document);
|
->setObject($document);
|
||||||
|
@ -263,6 +264,10 @@ final class PhrictionDocumentController
|
||||||
pht('Last Author'),
|
pht('Last Author'),
|
||||||
$viewer->renderHandle($content->getAuthorPHID()));
|
$viewer->renderHandle($content->getAuthorPHID()));
|
||||||
|
|
||||||
|
$view->addProperty(
|
||||||
|
pht('Last Edited'),
|
||||||
|
phabricator_datetime($content->getDateCreated(), $viewer));
|
||||||
|
|
||||||
return $view;
|
return $view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,8 @@ final class PhrictionEditController
|
||||||
$v_projects = array_reverse($v_projects);
|
$v_projects = array_reverse($v_projects);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$v_space = $document->getSpacePHID();
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
|
|
||||||
$title = $request->getStr('title');
|
$title = $request->getStr('title');
|
||||||
|
@ -131,6 +133,7 @@ final class PhrictionEditController
|
||||||
$v_edit = $request->getStr('editPolicy');
|
$v_edit = $request->getStr('editPolicy');
|
||||||
$v_cc = $request->getArr('cc');
|
$v_cc = $request->getArr('cc');
|
||||||
$v_projects = $request->getArr('projects');
|
$v_projects = $request->getArr('projects');
|
||||||
|
$v_space = $request->getStr('spacePHID');
|
||||||
|
|
||||||
$xactions = array();
|
$xactions = array();
|
||||||
$xactions[] = id(new PhrictionTransaction())
|
$xactions[] = id(new PhrictionTransaction())
|
||||||
|
@ -146,6 +149,9 @@ final class PhrictionEditController
|
||||||
$xactions[] = id(new PhrictionTransaction())
|
$xactions[] = id(new PhrictionTransaction())
|
||||||
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
|
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
|
||||||
->setNewValue($v_edit);
|
->setNewValue($v_edit);
|
||||||
|
$xactions[] = id(new PhrictionTransaction())
|
||||||
|
->setTransactionType(PhabricatorTransactions::TYPE_SPACE)
|
||||||
|
->setNewValue($v_space);
|
||||||
$xactions[] = id(new PhrictionTransaction())
|
$xactions[] = id(new PhrictionTransaction())
|
||||||
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
|
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
|
||||||
->setNewValue(array('=' => $v_cc));
|
->setNewValue(array('=' => $v_cc));
|
||||||
|
@ -192,6 +198,7 @@ final class PhrictionEditController
|
||||||
|
|
||||||
$document->setViewPolicy($v_view);
|
$document->setViewPolicy($v_view);
|
||||||
$document->setEditPolicy($v_edit);
|
$document->setEditPolicy($v_edit);
|
||||||
|
$document->setSpacePHID($v_space);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +274,9 @@ final class PhrictionEditController
|
||||||
->setDatasource(new PhabricatorMetaMTAMailableDatasource()))
|
->setDatasource(new PhabricatorMetaMTAMailableDatasource()))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormPolicyControl())
|
id(new AphrontFormPolicyControl())
|
||||||
|
->setViewer($viewer)
|
||||||
->setName('viewPolicy')
|
->setName('viewPolicy')
|
||||||
|
->setSpacePHID($v_space)
|
||||||
->setPolicyObject($document)
|
->setPolicyObject($document)
|
||||||
->setCapability($view_capability)
|
->setCapability($view_capability)
|
||||||
->setPolicies($policies)
|
->setPolicies($policies)
|
||||||
|
|
|
@ -131,6 +131,7 @@ final class PhrictionDocumentSearchEngine
|
||||||
|
|
||||||
$item = id(new PHUIObjectItemView())
|
$item = id(new PHUIObjectItemView())
|
||||||
->setHeader($content->getTitle())
|
->setHeader($content->getTitle())
|
||||||
|
->setObject($document)
|
||||||
->setHref($slug_uri)
|
->setHref($slug_uri)
|
||||||
->addByline($byline)
|
->addByline($byline)
|
||||||
->addIcon('none', $updated);
|
->addIcon('none', $updated);
|
||||||
|
|
|
@ -12,7 +12,8 @@ final class PhrictionDocument extends PhrictionDAO
|
||||||
PhabricatorProjectInterface,
|
PhabricatorProjectInterface,
|
||||||
PhabricatorApplicationTransactionInterface,
|
PhabricatorApplicationTransactionInterface,
|
||||||
PhabricatorConduitResultInterface,
|
PhabricatorConduitResultInterface,
|
||||||
PhabricatorPolicyCodexInterface {
|
PhabricatorPolicyCodexInterface,
|
||||||
|
PhabricatorSpacesInterface {
|
||||||
|
|
||||||
protected $slug;
|
protected $slug;
|
||||||
protected $depth;
|
protected $depth;
|
||||||
|
@ -21,6 +22,7 @@ final class PhrictionDocument extends PhrictionDAO
|
||||||
protected $mailKey;
|
protected $mailKey;
|
||||||
protected $viewPolicy;
|
protected $viewPolicy;
|
||||||
protected $editPolicy;
|
protected $editPolicy;
|
||||||
|
protected $spacePHID;
|
||||||
|
|
||||||
private $contentObject = self::ATTACHABLE;
|
private $contentObject = self::ATTACHABLE;
|
||||||
private $ancestors = array();
|
private $ancestors = array();
|
||||||
|
@ -81,12 +83,16 @@ final class PhrictionDocument extends PhrictionDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($parent_doc) {
|
if ($parent_doc) {
|
||||||
$document->setViewPolicy($parent_doc->getViewPolicy());
|
$document
|
||||||
$document->setEditPolicy($parent_doc->getEditPolicy());
|
->setViewPolicy($parent_doc->getViewPolicy())
|
||||||
|
->setEditPolicy($parent_doc->getEditPolicy())
|
||||||
|
->setSpacePHID($parent_doc->getSpacePHID());
|
||||||
} else {
|
} else {
|
||||||
$default_view_policy = PhabricatorPolicies::getMostOpenPolicy();
|
$default_view_policy = PhabricatorPolicies::getMostOpenPolicy();
|
||||||
$document->setViewPolicy($default_view_policy);
|
$document
|
||||||
$document->setEditPolicy(PhabricatorPolicies::POLICY_USER);
|
->setViewPolicy($default_view_policy)
|
||||||
|
->setEditPolicy(PhabricatorPolicies::POLICY_USER)
|
||||||
|
->setSpacePHID($actor->getDefaultSpacePHID());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $document;
|
return $document;
|
||||||
|
@ -202,6 +208,15 @@ final class PhrictionDocument extends PhrictionDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorSpacesInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function getSpacePHID() {
|
||||||
|
return $this->spacePHID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorSubscribableInterface )----------------------------------- */
|
/* -( PhabricatorSubscribableInterface )----------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -106,8 +106,8 @@ final class PhabricatorProjectSubprojectsController
|
||||||
->addClass('project-view-people-home')
|
->addClass('project-view-people-home')
|
||||||
->setMainColumn(array(
|
->setMainColumn(array(
|
||||||
$info_view,
|
$info_view,
|
||||||
$milestone_list,
|
|
||||||
$subproject_list,
|
$subproject_list,
|
||||||
|
$milestone_list,
|
||||||
));
|
));
|
||||||
|
|
||||||
return $this->newPage()
|
return $this->newPage()
|
||||||
|
@ -132,28 +132,11 @@ final class PhabricatorProjectSubprojectsController
|
||||||
$project,
|
$project,
|
||||||
PhabricatorPolicyCapability::CAN_EDIT);
|
PhabricatorPolicyCapability::CAN_EDIT);
|
||||||
|
|
||||||
$allows_milestones = $project->supportsMilestones();
|
|
||||||
$allows_subprojects = $project->supportsSubprojects();
|
$allows_subprojects = $project->supportsSubprojects();
|
||||||
|
$allows_milestones = $project->supportsMilestones();
|
||||||
|
|
||||||
$curtain = $this->newCurtainView();
|
$curtain = $this->newCurtainView();
|
||||||
|
|
||||||
if ($allows_milestones && $milestones) {
|
|
||||||
$milestone_text = pht('Create Next Milestone');
|
|
||||||
} else {
|
|
||||||
$milestone_text = pht('Create Milestone');
|
|
||||||
}
|
|
||||||
|
|
||||||
$can_milestone = ($can_create && $can_edit && $allows_milestones);
|
|
||||||
$milestone_href = "/project/edit/?milestone={$id}";
|
|
||||||
|
|
||||||
$curtain->addAction(
|
|
||||||
id(new PhabricatorActionView())
|
|
||||||
->setName($milestone_text)
|
|
||||||
->setIcon('fa-plus')
|
|
||||||
->setHref($milestone_href)
|
|
||||||
->setDisabled(!$can_milestone)
|
|
||||||
->setWorkflow(!$can_milestone));
|
|
||||||
|
|
||||||
$can_subproject = ($can_create && $can_edit && $allows_subprojects);
|
$can_subproject = ($can_create && $can_edit && $allows_subprojects);
|
||||||
|
|
||||||
// If we're offering to create the first subproject, we're going to warn
|
// If we're offering to create the first subproject, we're going to warn
|
||||||
|
@ -176,22 +159,22 @@ final class PhabricatorProjectSubprojectsController
|
||||||
->setDisabled($subproject_disabled)
|
->setDisabled($subproject_disabled)
|
||||||
->setWorkflow($subproject_workflow));
|
->setWorkflow($subproject_workflow));
|
||||||
|
|
||||||
|
if ($allows_milestones && $milestones) {
|
||||||
if (!$project->supportsMilestones()) {
|
$milestone_text = pht('Create Next Milestone');
|
||||||
$note = pht(
|
|
||||||
'This project is already a milestone, and milestones may not '.
|
|
||||||
'have their own milestones.');
|
|
||||||
} else {
|
} else {
|
||||||
if (!$milestones) {
|
$milestone_text = pht('Create Milestone');
|
||||||
$note = pht('Milestones can be created for this project.');
|
|
||||||
} else {
|
|
||||||
$note = pht('This project has milestones.');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$curtain->newPanel()
|
$can_milestone = ($can_create && $can_edit && $allows_milestones);
|
||||||
->setHeaderText(pht('Milestones'))
|
$milestone_href = "/project/edit/?milestone={$id}";
|
||||||
->appendChild($note);
|
|
||||||
|
$curtain->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setName($milestone_text)
|
||||||
|
->setIcon('fa-plus')
|
||||||
|
->setHref($milestone_href)
|
||||||
|
->setDisabled(!$can_milestone)
|
||||||
|
->setWorkflow(!$can_milestone));
|
||||||
|
|
||||||
if (!$project->supportsSubprojects()) {
|
if (!$project->supportsSubprojects()) {
|
||||||
$note = pht(
|
$note = pht(
|
||||||
|
@ -209,6 +192,22 @@ final class PhabricatorProjectSubprojectsController
|
||||||
->setHeaderText(pht('Subprojects'))
|
->setHeaderText(pht('Subprojects'))
|
||||||
->appendChild($note);
|
->appendChild($note);
|
||||||
|
|
||||||
|
if (!$project->supportsSubprojects()) {
|
||||||
|
$note = pht(
|
||||||
|
'This project is already a milestone, and milestones may not '.
|
||||||
|
'have their own milestones.');
|
||||||
|
} else {
|
||||||
|
if (!$milestones) {
|
||||||
|
$note = pht('Milestones can be created for this project.');
|
||||||
|
} else {
|
||||||
|
$note = pht('This project has milestones.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$curtain->newPanel()
|
||||||
|
->setHeaderText(pht('Milestones'))
|
||||||
|
->appendChild($note);
|
||||||
|
|
||||||
return $curtain;
|
return $curtain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,11 @@ final class PhabricatorProjectEditEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function newEditableObject() {
|
protected function newEditableObject() {
|
||||||
return PhabricatorProject::initializeNewProject($this->getViewer());
|
$parent = nonempty($this->parentProject, $this->milestoneProject);
|
||||||
|
|
||||||
|
return PhabricatorProject::initializeNewProject(
|
||||||
|
$this->getViewer(),
|
||||||
|
$parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function newObjectQuery() {
|
protected function newObjectQuery() {
|
||||||
|
@ -112,6 +116,7 @@ final class PhabricatorProjectEditEngine
|
||||||
PhabricatorTransactions::TYPE_VIEW_POLICY,
|
PhabricatorTransactions::TYPE_VIEW_POLICY,
|
||||||
PhabricatorTransactions::TYPE_EDIT_POLICY,
|
PhabricatorTransactions::TYPE_EDIT_POLICY,
|
||||||
PhabricatorTransactions::TYPE_JOIN_POLICY,
|
PhabricatorTransactions::TYPE_JOIN_POLICY,
|
||||||
|
PhabricatorTransactions::TYPE_SPACE,
|
||||||
PhabricatorProjectIconTransaction::TRANSACTIONTYPE,
|
PhabricatorProjectIconTransaction::TRANSACTIONTYPE,
|
||||||
PhabricatorProjectColorTransaction::TRANSACTIONTYPE,
|
PhabricatorProjectColorTransaction::TRANSACTIONTYPE,
|
||||||
);
|
);
|
||||||
|
|
|
@ -11,7 +11,8 @@ final class PhabricatorProject extends PhabricatorProjectDAO
|
||||||
PhabricatorFulltextInterface,
|
PhabricatorFulltextInterface,
|
||||||
PhabricatorFerretInterface,
|
PhabricatorFerretInterface,
|
||||||
PhabricatorConduitResultInterface,
|
PhabricatorConduitResultInterface,
|
||||||
PhabricatorColumnProxyInterface {
|
PhabricatorColumnProxyInterface,
|
||||||
|
PhabricatorSpacesInterface {
|
||||||
|
|
||||||
protected $name;
|
protected $name;
|
||||||
protected $status = PhabricatorProjectStatus::STATUS_ACTIVE;
|
protected $status = PhabricatorProjectStatus::STATUS_ACTIVE;
|
||||||
|
@ -38,6 +39,7 @@ final class PhabricatorProject extends PhabricatorProjectDAO
|
||||||
protected $projectPathKey;
|
protected $projectPathKey;
|
||||||
|
|
||||||
protected $properties = array();
|
protected $properties = array();
|
||||||
|
protected $spacePHID;
|
||||||
|
|
||||||
private $memberPHIDs = self::ATTACHABLE;
|
private $memberPHIDs = self::ATTACHABLE;
|
||||||
private $watcherPHIDs = self::ATTACHABLE;
|
private $watcherPHIDs = self::ATTACHABLE;
|
||||||
|
@ -59,7 +61,10 @@ final class PhabricatorProject extends PhabricatorProjectDAO
|
||||||
const ITEM_MILESTONES = 'project.milestones';
|
const ITEM_MILESTONES = 'project.milestones';
|
||||||
const ITEM_SUBPROJECTS = 'project.subprojects';
|
const ITEM_SUBPROJECTS = 'project.subprojects';
|
||||||
|
|
||||||
public static function initializeNewProject(PhabricatorUser $actor) {
|
public static function initializeNewProject(
|
||||||
|
PhabricatorUser $actor,
|
||||||
|
PhabricatorProject $parent = null) {
|
||||||
|
|
||||||
$app = id(new PhabricatorApplicationQuery())
|
$app = id(new PhabricatorApplicationQuery())
|
||||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||||
->withClasses(array('PhabricatorProjectApplication'))
|
->withClasses(array('PhabricatorProjectApplication'))
|
||||||
|
@ -72,6 +77,14 @@ final class PhabricatorProject extends PhabricatorProjectDAO
|
||||||
$join_policy = $app->getPolicy(
|
$join_policy = $app->getPolicy(
|
||||||
ProjectDefaultJoinCapability::CAPABILITY);
|
ProjectDefaultJoinCapability::CAPABILITY);
|
||||||
|
|
||||||
|
// If this is the child of some other project, default the Space to the
|
||||||
|
// Space of the parent.
|
||||||
|
if ($parent) {
|
||||||
|
$space_phid = $parent->getSpacePHID();
|
||||||
|
} else {
|
||||||
|
$space_phid = $actor->getDefaultSpacePHID();
|
||||||
|
}
|
||||||
|
|
||||||
$default_icon = PhabricatorProjectIconSet::getDefaultIconKey();
|
$default_icon = PhabricatorProjectIconSet::getDefaultIconKey();
|
||||||
$default_color = PhabricatorProjectIconSet::getDefaultColorKey();
|
$default_color = PhabricatorProjectIconSet::getDefaultColorKey();
|
||||||
|
|
||||||
|
@ -82,6 +95,7 @@ final class PhabricatorProject extends PhabricatorProjectDAO
|
||||||
->setViewPolicy($view_policy)
|
->setViewPolicy($view_policy)
|
||||||
->setEditPolicy($edit_policy)
|
->setEditPolicy($edit_policy)
|
||||||
->setJoinPolicy($join_policy)
|
->setJoinPolicy($join_policy)
|
||||||
|
->setSpacePHID($space_phid)
|
||||||
->setIsMembershipLocked(0)
|
->setIsMembershipLocked(0)
|
||||||
->attachMemberPHIDs(array())
|
->attachMemberPHIDs(array())
|
||||||
->attachSlugs(array())
|
->attachSlugs(array())
|
||||||
|
@ -697,6 +711,17 @@ final class PhabricatorProject extends PhabricatorProjectDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorSpacesInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function getSpacePHID() {
|
||||||
|
if ($this->isMilestone()) {
|
||||||
|
return $this->getParentProject()->getSpacePHID();
|
||||||
|
}
|
||||||
|
return $this->spacePHID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorDestructibleInterface )----------------------------------- */
|
/* -( PhabricatorDestructibleInterface )----------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ final class PhabricatorProjectListView extends AphrontView {
|
||||||
$icon_name = $project->getDisplayIconName();
|
$icon_name = $project->getDisplayIconName();
|
||||||
|
|
||||||
$item = id(new PHUIObjectItemView())
|
$item = id(new PHUIObjectItemView())
|
||||||
|
->setObject($project)
|
||||||
->setHeader($project->getName())
|
->setHeader($project->getName())
|
||||||
->setHref("/project/view/{$id}/")
|
->setHref("/project/view/{$id}/")
|
||||||
->setImageURI($project->getProfileImageURI())
|
->setImageURI($project->getProfileImageURI())
|
||||||
|
|
|
@ -12,6 +12,7 @@ final class PhabricatorRepositoryPushLogQuery
|
||||||
private $pushEventPHIDs;
|
private $pushEventPHIDs;
|
||||||
private $epochMin;
|
private $epochMin;
|
||||||
private $epochMax;
|
private $epochMax;
|
||||||
|
private $blockingHeraldRulePHIDs;
|
||||||
|
|
||||||
public function withIDs(array $ids) {
|
public function withIDs(array $ids) {
|
||||||
$this->ids = $ids;
|
$this->ids = $ids;
|
||||||
|
@ -54,6 +55,11 @@ final class PhabricatorRepositoryPushLogQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withBlockingHeraldRulePHIDs(array $phids) {
|
||||||
|
$this->blockingHeraldRulePHIDs = $phids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function newResultObject() {
|
public function newResultObject() {
|
||||||
return new PhabricatorRepositoryPushLog();
|
return new PhabricatorRepositoryPushLog();
|
||||||
}
|
}
|
||||||
|
@ -89,71 +95,105 @@ final class PhabricatorRepositoryPushLogQuery
|
||||||
if ($this->ids !== null) {
|
if ($this->ids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'id IN (%Ld)',
|
'log.id IN (%Ld)',
|
||||||
$this->ids);
|
$this->ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->phids !== null) {
|
if ($this->phids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'phid IN (%Ls)',
|
'log.phid IN (%Ls)',
|
||||||
$this->phids);
|
$this->phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->repositoryPHIDs !== null) {
|
if ($this->repositoryPHIDs !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'repositoryPHID IN (%Ls)',
|
'log.repositoryPHID IN (%Ls)',
|
||||||
$this->repositoryPHIDs);
|
$this->repositoryPHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->pusherPHIDs !== null) {
|
if ($this->pusherPHIDs !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'pusherPHID in (%Ls)',
|
'log.pusherPHID in (%Ls)',
|
||||||
$this->pusherPHIDs);
|
$this->pusherPHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->pushEventPHIDs !== null) {
|
if ($this->pushEventPHIDs !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'pushEventPHID in (%Ls)',
|
'log.pushEventPHID in (%Ls)',
|
||||||
$this->pushEventPHIDs);
|
$this->pushEventPHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->refTypes !== null) {
|
if ($this->refTypes !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'refType IN (%Ls)',
|
'log.refType IN (%Ls)',
|
||||||
$this->refTypes);
|
$this->refTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->newRefs !== null) {
|
if ($this->newRefs !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'refNew IN (%Ls)',
|
'log.refNew IN (%Ls)',
|
||||||
$this->newRefs);
|
$this->newRefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->epochMin !== null) {
|
if ($this->epochMin !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'epoch >= %d',
|
'log.epoch >= %d',
|
||||||
$this->epochMin);
|
$this->epochMin);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->epochMax !== null) {
|
if ($this->epochMax !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'epoch <= %d',
|
'log.epoch <= %d',
|
||||||
$this->epochMax);
|
$this->epochMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->blockingHeraldRulePHIDs !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'(event.rejectCode = %d AND event.rejectDetails IN (%Ls))',
|
||||||
|
PhabricatorRepositoryPushLog::REJECT_HERALD,
|
||||||
|
$this->blockingHeraldRulePHIDs);
|
||||||
|
}
|
||||||
|
|
||||||
return $where;
|
return $where;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
|
||||||
|
$joins = parent::buildJoinClauseParts($conn);
|
||||||
|
|
||||||
|
if ($this->shouldJoinPushEventTable()) {
|
||||||
|
$joins[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'JOIN %T event ON event.phid = log.pushEventPHID',
|
||||||
|
id(new PhabricatorRepositoryPushEvent())->getTableName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $joins;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function shouldJoinPushEventTable() {
|
||||||
|
if ($this->blockingHeraldRulePHIDs !== null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public function getQueryApplicationClass() {
|
public function getQueryApplicationClass() {
|
||||||
return 'PhabricatorDiffusionApplication';
|
return 'PhabricatorDiffusionApplication';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getPrimaryTableAlias() {
|
||||||
|
return 'log';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,10 @@ final class PhabricatorRepositoryPushLogSearchEngine
|
||||||
$map['createdEnd']);
|
$map['createdEnd']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($map['blockingHeraldRulePHIDs']) {
|
||||||
|
$query->withBlockingHeraldRulePHIDs($map['blockingHeraldRulePHIDs']);
|
||||||
|
}
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,13 +47,19 @@ final class PhabricatorRepositoryPushLogSearchEngine
|
||||||
->setAliases(array('repository', 'repositories', 'repositoryPHID'))
|
->setAliases(array('repository', 'repositories', 'repositoryPHID'))
|
||||||
->setLabel(pht('Repositories'))
|
->setLabel(pht('Repositories'))
|
||||||
->setDescription(
|
->setDescription(
|
||||||
pht('Search for pull logs for specific repositories.')),
|
pht('Search for push logs for specific repositories.')),
|
||||||
id(new PhabricatorUsersSearchField())
|
id(new PhabricatorUsersSearchField())
|
||||||
->setKey('pusherPHIDs')
|
->setKey('pusherPHIDs')
|
||||||
->setAliases(array('pusher', 'pushers', 'pusherPHID'))
|
->setAliases(array('pusher', 'pushers', 'pusherPHID'))
|
||||||
->setLabel(pht('Pushers'))
|
->setLabel(pht('Pushers'))
|
||||||
->setDescription(
|
->setDescription(
|
||||||
pht('Search for pull logs by specific users.')),
|
pht('Search for push logs by specific users.')),
|
||||||
|
id(new PhabricatorSearchDatasourceField())
|
||||||
|
->setDatasource(new HeraldRuleDatasource())
|
||||||
|
->setKey('blockingHeraldRulePHIDs')
|
||||||
|
->setLabel(pht('Blocked By'))
|
||||||
|
->setDescription(
|
||||||
|
pht('Search for pushes blocked by particular Herald rules.')),
|
||||||
id(new PhabricatorSearchDateField())
|
id(new PhabricatorSearchDateField())
|
||||||
->setLabel(pht('Created After'))
|
->setLabel(pht('Created After'))
|
||||||
->setKey('createdStart'),
|
->setKey('createdStart'),
|
||||||
|
@ -149,6 +159,9 @@ final class PhabricatorRepositoryPushLogSearchEngine
|
||||||
id(new PhabricatorStringExportField())
|
id(new PhabricatorStringExportField())
|
||||||
->setKey('resultName')
|
->setKey('resultName')
|
||||||
->setLabel(pht('Result Name')),
|
->setLabel(pht('Result Name')),
|
||||||
|
id(new PhabricatorStringExportField())
|
||||||
|
->setKey('resultDetails')
|
||||||
|
->setLabel(pht('Result Details')),
|
||||||
id(new PhabricatorIntExportField())
|
id(new PhabricatorIntExportField())
|
||||||
->setKey('writeWait')
|
->setKey('writeWait')
|
||||||
->setLabel(pht('Write Wait (us)')),
|
->setLabel(pht('Write Wait (us)')),
|
||||||
|
@ -237,6 +250,7 @@ final class PhabricatorRepositoryPushLogSearchEngine
|
||||||
'flagNames' => $flag_names,
|
'flagNames' => $flag_names,
|
||||||
'result' => $result,
|
'result' => $result,
|
||||||
'resultName' => $result_name,
|
'resultName' => $result_name,
|
||||||
|
'resultDetails' => $event->getRejectDetails(),
|
||||||
'writeWait' => $event->getWriteWait(),
|
'writeWait' => $event->getWriteWait(),
|
||||||
'readWait' => $event->getReadWait(),
|
'readWait' => $event->getReadWait(),
|
||||||
'hostWait' => $event->getHostWait(),
|
'hostWait' => $event->getHostWait(),
|
||||||
|
|
|
@ -49,6 +49,9 @@ final class PhabricatorRepositoryPushEvent
|
||||||
'key_identifier' => array(
|
'key_identifier' => array(
|
||||||
'columns' => array('requestIdentifier'),
|
'columns' => array('requestIdentifier'),
|
||||||
),
|
),
|
||||||
|
'key_reject' => array(
|
||||||
|
'columns' => array('rejectCode', 'rejectDetails'),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
) + parent::getConfiguration();
|
) + parent::getConfiguration();
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,14 @@ final class TransactionSearchConduitAPIMethod
|
||||||
));
|
));
|
||||||
|
|
||||||
$with_phids = idx($constraints, 'phids');
|
$with_phids = idx($constraints, 'phids');
|
||||||
|
|
||||||
|
if ($with_phids === array()) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Constraint "phids" to "transaction.search" requires nonempty list, '.
|
||||||
|
'empty list provided.'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($with_phids) {
|
if ($with_phids) {
|
||||||
$xaction_query->withPHIDs($with_phids);
|
$xaction_query->withPHIDs($with_phids);
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,10 @@ The supported keys for each mailer are:
|
||||||
- `priority`: Optional string. Advanced option which controls load balancing
|
- `priority`: Optional string. Advanced option which controls load balancing
|
||||||
and failover behavior. See below for details.
|
and failover behavior. See below for details.
|
||||||
- `options`: Optional map. Additional options for the mailer type.
|
- `options`: Optional map. Additional options for the mailer type.
|
||||||
|
- `inbound`: Optional bool. Use `false` to prevent this mailer from being
|
||||||
|
used to receive inbound mail.
|
||||||
|
- `outbound`: Optional bool. Use `false` to prevent this mailer from being
|
||||||
|
used to send outbound mail.
|
||||||
|
|
||||||
The `type` field can be used to select these third-party mailers:
|
The `type` field can be used to select these third-party mailers:
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ final class PhabricatorClusterMailersConfigType
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'priority' => 'optional int',
|
'priority' => 'optional int',
|
||||||
'options' => 'optional wild',
|
'options' => 'optional wild',
|
||||||
|
'inbound' => 'optional bool',
|
||||||
|
'outbound' => 'optional bool',
|
||||||
));
|
));
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
throw $this->newException(
|
throw $this->newException(
|
||||||
|
|
|
@ -294,7 +294,8 @@ body .phui-header-shell.phui-bleed-header
|
||||||
}
|
}
|
||||||
|
|
||||||
.spaces-name .phui-handle,
|
.spaces-name .phui-handle,
|
||||||
.spaces-name a.phui-handle {
|
.spaces-name a.phui-handle,
|
||||||
|
.phui-profile-header.phui-header-shell .spaces-name .phui-handle {
|
||||||
color: {$sh-redtext};
|
color: {$sh-redtext};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue