mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-23 12:09:12 +01:00
(stable) Promote 2021 Week 11
This commit is contained in:
commit
e7d3bae2cc
44 changed files with 549 additions and 287 deletions
|
@ -11,12 +11,20 @@ $chunk_size = 4096;
|
|||
|
||||
$temporary_table = 'tmp_20210215_changeset_id_map';
|
||||
|
||||
queryfx(
|
||||
$conn,
|
||||
'CREATE TEMPORARY TABLE %T (
|
||||
changeset_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
changeset_phid VARBINARY(64) NOT NULL)',
|
||||
$temporary_table);
|
||||
try {
|
||||
queryfx(
|
||||
$conn,
|
||||
'CREATE TEMPORARY TABLE %T (
|
||||
changeset_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
changeset_phid VARBINARY(64) NOT NULL)',
|
||||
$temporary_table);
|
||||
} catch (AphrontAccessDeniedQueryException $ex) {
|
||||
throw new PhutilProxyException(
|
||||
pht(
|
||||
'Failed to "CREATE TEMPORARY TABLE". You may need to "GRANT" the '.
|
||||
'current MySQL user this permission.'),
|
||||
$ex);
|
||||
}
|
||||
|
||||
$table_iterator = id(new LiskRawMigrationIterator($conn, $table_name))
|
||||
->setPageSize($chunk_size);
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
UPDATE {$NAMESPACE}_repository.repository_auditrequest
|
||||
SET auditStatus = 'accepted' WHERE auditStatus = 'closed';
|
||||
|
||||
DELETE FROM {$NAMESPACE}_repository.repository_auditrequest
|
||||
WHERE auditStatus IN ('', 'cc', 'audit-not-required');
|
|
@ -724,6 +724,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionAuditorsAddAuditorsHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsAddAuditorsHeraldAction.php',
|
||||
'DiffusionAuditorsAddSelfHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsAddSelfHeraldAction.php',
|
||||
'DiffusionAuditorsHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsHeraldAction.php',
|
||||
'DiffusionAuditorsSearchEngineAttachment' => 'applications/diffusion/engineextension/DiffusionAuditorsSearchEngineAttachment.php',
|
||||
'DiffusionBlameConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionBlameConduitAPIMethod.php',
|
||||
'DiffusionBlameController' => 'applications/diffusion/controller/DiffusionBlameController.php',
|
||||
'DiffusionBlameQuery' => 'applications/diffusion/query/blame/DiffusionBlameQuery.php',
|
||||
|
@ -2304,7 +2305,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuditManagementDeleteWorkflow' => 'applications/audit/management/PhabricatorAuditManagementDeleteWorkflow.php',
|
||||
'PhabricatorAuditManagementWorkflow' => 'applications/audit/management/PhabricatorAuditManagementWorkflow.php',
|
||||
'PhabricatorAuditReplyHandler' => 'applications/audit/mail/PhabricatorAuditReplyHandler.php',
|
||||
'PhabricatorAuditStatusConstants' => 'applications/audit/constants/PhabricatorAuditStatusConstants.php',
|
||||
'PhabricatorAuditRequestStatus' => 'applications/audit/constants/PhabricatorAuditRequestStatus.php',
|
||||
'PhabricatorAuditSynchronizeManagementWorkflow' => 'applications/audit/management/PhabricatorAuditSynchronizeManagementWorkflow.php',
|
||||
'PhabricatorAuditTransaction' => 'applications/audit/storage/PhabricatorAuditTransaction.php',
|
||||
'PhabricatorAuditTransactionComment' => 'applications/audit/storage/PhabricatorAuditTransactionComment.php',
|
||||
|
@ -3208,6 +3209,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorDocumentEngineBlock' => 'applications/files/diff/PhabricatorDocumentEngineBlock.php',
|
||||
'PhabricatorDocumentEngineBlockDiff' => 'applications/files/diff/PhabricatorDocumentEngineBlockDiff.php',
|
||||
'PhabricatorDocumentEngineBlocks' => 'applications/files/diff/PhabricatorDocumentEngineBlocks.php',
|
||||
'PhabricatorDocumentEngineParserException' => 'applications/files/document/exception/PhabricatorDocumentEngineParserException.php',
|
||||
'PhabricatorDocumentRef' => 'applications/files/document/PhabricatorDocumentRef.php',
|
||||
'PhabricatorDocumentRenderingEngine' => 'applications/files/document/render/PhabricatorDocumentRenderingEngine.php',
|
||||
'PhabricatorDoorkeeperApplication' => 'applications/doorkeeper/application/PhabricatorDoorkeeperApplication.php',
|
||||
|
@ -4251,6 +4253,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPhurlURLViewController' => 'applications/phurl/controller/PhabricatorPhurlURLViewController.php',
|
||||
'PhabricatorPinnedApplicationsSetting' => 'applications/settings/setting/PhabricatorPinnedApplicationsSetting.php',
|
||||
'PhabricatorPirateEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorPirateEnglishTranslation.php',
|
||||
'PhabricatorPlatform404Controller' => 'applications/base/controller/PhabricatorPlatform404Controller.php',
|
||||
'PhabricatorPlatformSite' => 'aphront/site/PhabricatorPlatformSite.php',
|
||||
'PhabricatorPointsEditField' => 'applications/transactions/editfield/PhabricatorPointsEditField.php',
|
||||
'PhabricatorPointsFact' => 'applications/fact/fact/PhabricatorPointsFact.php',
|
||||
|
@ -4686,7 +4689,11 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRequestExceptionHandler' => 'aphront/handler/PhabricatorRequestExceptionHandler.php',
|
||||
'PhabricatorResetPasswordUserLogType' => 'applications/people/userlog/PhabricatorResetPasswordUserLogType.php',
|
||||
'PhabricatorResourceSite' => 'aphront/site/PhabricatorResourceSite.php',
|
||||
'PhabricatorRobotsController' => 'applications/system/controller/PhabricatorRobotsController.php',
|
||||
'PhabricatorRobotsBlogController' => 'applications/system/controller/robots/PhabricatorRobotsBlogController.php',
|
||||
'PhabricatorRobotsController' => 'applications/system/controller/robots/PhabricatorRobotsController.php',
|
||||
'PhabricatorRobotsPlatformController' => 'applications/system/controller/robots/PhabricatorRobotsPlatformController.php',
|
||||
'PhabricatorRobotsResourceController' => 'applications/system/controller/robots/PhabricatorRobotsResourceController.php',
|
||||
'PhabricatorRobotsShortController' => 'applications/system/controller/robots/PhabricatorRobotsShortController.php',
|
||||
'PhabricatorS3FileStorageEngine' => 'applications/files/engine/PhabricatorS3FileStorageEngine.php',
|
||||
'PhabricatorSMSAuthFactor' => 'applications/auth/factor/PhabricatorSMSAuthFactor.php',
|
||||
'PhabricatorSQLPatchList' => 'infrastructure/storage/patch/PhabricatorSQLPatchList.php',
|
||||
|
@ -6843,6 +6850,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionAuditorsAddAuditorsHeraldAction' => 'DiffusionAuditorsHeraldAction',
|
||||
'DiffusionAuditorsAddSelfHeraldAction' => 'DiffusionAuditorsHeraldAction',
|
||||
'DiffusionAuditorsHeraldAction' => 'HeraldAction',
|
||||
'DiffusionAuditorsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
|
||||
'DiffusionBlameConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
|
||||
'DiffusionBlameController' => 'DiffusionController',
|
||||
'DiffusionBlameQuery' => 'DiffusionQuery',
|
||||
|
@ -8649,7 +8657,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuditManagementDeleteWorkflow' => 'PhabricatorAuditManagementWorkflow',
|
||||
'PhabricatorAuditManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||
'PhabricatorAuditReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
|
||||
'PhabricatorAuditStatusConstants' => 'Phobject',
|
||||
'PhabricatorAuditRequestStatus' => 'Phobject',
|
||||
'PhabricatorAuditSynchronizeManagementWorkflow' => 'PhabricatorAuditManagementWorkflow',
|
||||
'PhabricatorAuditTransaction' => 'PhabricatorModularTransaction',
|
||||
'PhabricatorAuditTransactionComment' => array(
|
||||
|
@ -9705,6 +9713,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorDocumentEngineBlock' => 'Phobject',
|
||||
'PhabricatorDocumentEngineBlockDiff' => 'Phobject',
|
||||
'PhabricatorDocumentEngineBlocks' => 'Phobject',
|
||||
'PhabricatorDocumentEngineParserException' => 'Exception',
|
||||
'PhabricatorDocumentRef' => 'Phobject',
|
||||
'PhabricatorDocumentRenderingEngine' => 'Phobject',
|
||||
'PhabricatorDoorkeeperApplication' => 'PhabricatorApplication',
|
||||
|
@ -10910,6 +10919,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPhurlURLViewController' => 'PhabricatorPhurlController',
|
||||
'PhabricatorPinnedApplicationsSetting' => 'PhabricatorInternalSetting',
|
||||
'PhabricatorPirateEnglishTranslation' => 'PhutilTranslation',
|
||||
'PhabricatorPlatform404Controller' => 'PhabricatorController',
|
||||
'PhabricatorPlatformSite' => 'PhabricatorSite',
|
||||
'PhabricatorPointsEditField' => 'PhabricatorEditField',
|
||||
'PhabricatorPointsFact' => 'PhabricatorFact',
|
||||
|
@ -11466,7 +11476,11 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRequestExceptionHandler' => 'AphrontRequestExceptionHandler',
|
||||
'PhabricatorResetPasswordUserLogType' => 'PhabricatorUserLogType',
|
||||
'PhabricatorResourceSite' => 'PhabricatorSite',
|
||||
'PhabricatorRobotsBlogController' => 'PhabricatorRobotsController',
|
||||
'PhabricatorRobotsController' => 'PhabricatorController',
|
||||
'PhabricatorRobotsPlatformController' => 'PhabricatorRobotsController',
|
||||
'PhabricatorRobotsResourceController' => 'PhabricatorRobotsController',
|
||||
'PhabricatorRobotsShortController' => 'PhabricatorRobotsController',
|
||||
'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine',
|
||||
'PhabricatorSMSAuthFactor' => 'PhabricatorAuthFactor',
|
||||
'PhabricatorSQLPatchList' => 'Phobject',
|
||||
|
|
|
@ -32,10 +32,6 @@ final class AphrontApplicationConfiguration
|
|||
return $request;
|
||||
}
|
||||
|
||||
public function build404Controller() {
|
||||
return array(new Phabricator404Controller(), array());
|
||||
}
|
||||
|
||||
public function buildRedirectController($uri, $external) {
|
||||
return array(
|
||||
new PhabricatorRedirectController(),
|
||||
|
@ -504,7 +500,10 @@ final class AphrontApplicationConfiguration
|
|||
return array($result, array());
|
||||
}
|
||||
|
||||
return $this->build404Controller();
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Aphront site ("%s") failed to build a 404 controller.',
|
||||
get_class($site)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,10 +10,17 @@ final class Aphront404Response extends AphrontHTMLResponse {
|
|||
$request = $this->getRequest();
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
// See T13636. Note that this response may be served from a Site other than
|
||||
// the primary PlatformSite. For now, always link to the PlatformSite.
|
||||
|
||||
// (This may not be the best possible place to send users who are currently
|
||||
// on "real" sites, like the BlogSite.)
|
||||
$return_uri = PhabricatorEnv::getURI('/');
|
||||
|
||||
$dialog = id(new AphrontDialogView())
|
||||
->setViewer($viewer)
|
||||
->setTitle(pht('404 Not Found'))
|
||||
->addCancelButton('/', pht('Return to Charted Waters'))
|
||||
->addCancelButton($return_uri, pht('Return to Charted Waters'))
|
||||
->appendParagraph(
|
||||
pht(
|
||||
'You arrive at your destination, but there is nothing here.'))
|
||||
|
|
|
@ -10,7 +10,7 @@ abstract class AphrontSite extends Phobject {
|
|||
abstract public function getRoutingMaps();
|
||||
|
||||
public function new404Controller(AphrontRequest $request) {
|
||||
return null;
|
||||
return new Phabricator404Controller();
|
||||
}
|
||||
|
||||
protected function isHostMatch($host, array $uris) {
|
||||
|
|
|
@ -50,4 +50,8 @@ final class PhabricatorPlatformSite extends PhabricatorSite {
|
|||
return $maps;
|
||||
}
|
||||
|
||||
public function new404Controller(AphrontRequest $request) {
|
||||
return new PhabricatorPlatform404Controller();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuditRequestStatus extends Phobject {
|
||||
|
||||
const AUDIT_REQUIRED = 'audit-required';
|
||||
const CONCERNED = 'concerned';
|
||||
const ACCEPTED = 'accepted';
|
||||
const AUDIT_REQUESTED = 'requested';
|
||||
const RESIGNED = 'resigned';
|
||||
|
||||
private $key;
|
||||
|
||||
public static function newForStatus($status) {
|
||||
$result = new self();
|
||||
$result->key = $status;
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getIconIcon() {
|
||||
return $this->getMapProperty('icon');
|
||||
}
|
||||
|
||||
public function getIconColor() {
|
||||
return $this->getMapProperty('icon.color');
|
||||
}
|
||||
|
||||
public function getStatusName() {
|
||||
$name = $this->getMapProperty('name');
|
||||
if ($name !== null) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
return pht('Unknown Audit Request Status ("%s")', $this->key);
|
||||
}
|
||||
|
||||
public function getStatusValue() {
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public function getStatusValueForConduit() {
|
||||
return $this->getMapProperty('value.conduit');
|
||||
}
|
||||
|
||||
public function isResigned() {
|
||||
return ($this->key === self::RESIGNED);
|
||||
}
|
||||
|
||||
private function getMapProperty($key, $default = null) {
|
||||
$map = self::newStatusMap();
|
||||
$spec = idx($map, $this->key, array());
|
||||
return idx($spec, $key, $default);
|
||||
}
|
||||
|
||||
private static function newStatusMap() {
|
||||
return array(
|
||||
self::AUDIT_REQUIRED => array(
|
||||
'name' => pht('Audit Required'),
|
||||
'icon' => 'fa-exclamation-circle',
|
||||
'icon.color' => 'orange',
|
||||
'value.conduit' => 'audit-required',
|
||||
),
|
||||
self::AUDIT_REQUESTED => array(
|
||||
'name' => pht('Audit Requested'),
|
||||
'icon' => 'fa-exclamation-circle',
|
||||
'icon.color' => 'orange',
|
||||
'value.conduit' => 'audit-requested',
|
||||
),
|
||||
self::CONCERNED => array(
|
||||
'name' => pht('Concern Raised'),
|
||||
'icon' => 'fa-times-circle',
|
||||
'icon.color' => 'red',
|
||||
'value.conduit' => 'concern-raised',
|
||||
),
|
||||
self::ACCEPTED => array(
|
||||
'name' => pht('Accepted'),
|
||||
'icon' => 'fa-check-circle',
|
||||
'icon.color' => 'green',
|
||||
'value.conduit' => 'accepted',
|
||||
),
|
||||
self::RESIGNED => array(
|
||||
'name' => pht('Resigned'),
|
||||
'icon' => 'fa-times',
|
||||
'icon.color' => 'grey',
|
||||
'value.conduit' => 'resigned',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuditStatusConstants extends Phobject {
|
||||
|
||||
const NONE = '';
|
||||
const AUDIT_NOT_REQUIRED = 'audit-not-required';
|
||||
const AUDIT_REQUIRED = 'audit-required';
|
||||
const CONCERNED = 'concerned';
|
||||
const ACCEPTED = 'accepted';
|
||||
const AUDIT_REQUESTED = 'requested';
|
||||
const RESIGNED = 'resigned';
|
||||
const CLOSED = 'closed';
|
||||
const CC = 'cc';
|
||||
|
||||
public static function getStatusNameMap() {
|
||||
$map = array(
|
||||
self::NONE => pht('Not Applicable'),
|
||||
self::AUDIT_NOT_REQUIRED => pht('Audit Not Required'),
|
||||
self::AUDIT_REQUIRED => pht('Audit Required'),
|
||||
self::CONCERNED => pht('Concern Raised'),
|
||||
self::ACCEPTED => pht('Accepted'),
|
||||
self::AUDIT_REQUESTED => pht('Audit Requested'),
|
||||
self::RESIGNED => pht('Resigned'),
|
||||
self::CLOSED => pht('Closed'),
|
||||
self::CC => pht("Was CC'd"),
|
||||
);
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
public static function getActionRequiredStatusConstants() {
|
||||
return array(
|
||||
self::AUDIT_REQUIRED,
|
||||
self::AUDIT_REQUESTED,
|
||||
);
|
||||
}
|
||||
|
||||
public static function getStatusName($code) {
|
||||
return idx(self::getStatusNameMap(), $code, pht('Unknown'));
|
||||
}
|
||||
|
||||
public static function getStatusColor($code) {
|
||||
switch ($code) {
|
||||
case self::CONCERNED:
|
||||
$color = 'red';
|
||||
break;
|
||||
case self::AUDIT_REQUIRED:
|
||||
case self::AUDIT_REQUESTED:
|
||||
$color = 'orange';
|
||||
break;
|
||||
case self::ACCEPTED:
|
||||
$color = 'green';
|
||||
break;
|
||||
case self::AUDIT_NOT_REQUIRED:
|
||||
$color = 'blue';
|
||||
break;
|
||||
case self::CLOSED:
|
||||
$color = 'dark';
|
||||
break;
|
||||
case self::RESIGNED:
|
||||
$color = 'grey';
|
||||
break;
|
||||
default:
|
||||
$color = 'bluegrey';
|
||||
break;
|
||||
}
|
||||
return $color;
|
||||
}
|
||||
|
||||
public static function getStatusIcon($code) {
|
||||
switch ($code) {
|
||||
case self::AUDIT_NOT_REQUIRED:
|
||||
$icon = PHUIStatusItemView::ICON_OPEN;
|
||||
break;
|
||||
case self::AUDIT_REQUIRED:
|
||||
case self::AUDIT_REQUESTED:
|
||||
$icon = PHUIStatusItemView::ICON_WARNING;
|
||||
break;
|
||||
case self::CONCERNED:
|
||||
$icon = PHUIStatusItemView::ICON_REJECT;
|
||||
break;
|
||||
case self::ACCEPTED:
|
||||
case self::CLOSED:
|
||||
$icon = PHUIStatusItemView::ICON_ACCEPT;
|
||||
break;
|
||||
case self::RESIGNED:
|
||||
$icon = 'fa-times';
|
||||
break;
|
||||
default:
|
||||
$icon = PHUIStatusItemView::ICON_QUESTION;
|
||||
break;
|
||||
}
|
||||
return $icon;
|
||||
}
|
||||
|
||||
public static function getOpenStatusConstants() {
|
||||
return array(
|
||||
self::AUDIT_REQUIRED,
|
||||
self::AUDIT_REQUESTED,
|
||||
self::CONCERNED,
|
||||
);
|
||||
}
|
||||
|
||||
public static function isOpenStatus($status) {
|
||||
return in_array($status, self::getOpenStatusConstants());
|
||||
}
|
||||
|
||||
}
|
|
@ -178,12 +178,6 @@ final class PhabricatorAuditEditor
|
|||
}
|
||||
$object->attachAudits($commit->getAudits());
|
||||
|
||||
$status_concerned = PhabricatorAuditStatusConstants::CONCERNED;
|
||||
$status_closed = PhabricatorAuditStatusConstants::CLOSED;
|
||||
$status_resigned = PhabricatorAuditStatusConstants::RESIGNED;
|
||||
$status_accepted = PhabricatorAuditStatusConstants::ACCEPTED;
|
||||
$status_concerned = PhabricatorAuditStatusConstants::CONCERNED;
|
||||
|
||||
$actor_phid = $this->getActingAsPHID();
|
||||
$actor_is_author = ($object->getAuthorPHID()) &&
|
||||
($actor_phid == $object->getAuthorPHID());
|
||||
|
@ -491,12 +485,6 @@ final class PhabricatorAuditEditor
|
|||
}
|
||||
|
||||
foreach ($object->getAudits() as $audit) {
|
||||
if (!$audit->isInteresting()) {
|
||||
// Don't send mail to uninteresting auditors, like packages which
|
||||
// own this code but which audits have not triggered for.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$audit->isResigned()) {
|
||||
$phids[] = $audit->getAuditorPHID();
|
||||
}
|
||||
|
|
|
@ -153,13 +153,13 @@ final class PhabricatorAuditManagementDeleteWorkflow
|
|||
|
||||
foreach ($commit_audits as $audit) {
|
||||
$audit_id = $audit->getID();
|
||||
$status = $audit->getAuditRequestStatusObject();
|
||||
|
||||
$description = sprintf(
|
||||
'%10d %-16s %-16s %s: %s',
|
||||
$audit_id,
|
||||
$handles[$audit->getAuditorPHID()]->getName(),
|
||||
PhabricatorAuditStatusConstants::getStatusName(
|
||||
$audit->getAuditStatus()),
|
||||
$status->getStatusName(),
|
||||
$commit->getRepository()->formatCommitName(
|
||||
$commit->getCommitIdentifier()),
|
||||
trim($commit->getSummary()));
|
||||
|
|
|
@ -39,7 +39,13 @@ final class PhabricatorAuthMainMenuBarExtension
|
|||
private function buildLoginMenu() {
|
||||
$controller = $this->getController();
|
||||
|
||||
$uri = new PhutilURI('/auth/start/');
|
||||
// See T13636. This button may be rendered by the 404 controller on sites
|
||||
// other than the primary PlatformSite. Link the button to the primary
|
||||
// site.
|
||||
|
||||
$uri = '/auth/start/';
|
||||
$uri = PhabricatorEnv::getURI($uri);
|
||||
$uri = new PhutilURI($uri);
|
||||
if ($controller) {
|
||||
$path = $controller->getRequest()->getPath();
|
||||
$uri->replaceQueryParam('next', $path);
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
<?php
|
||||
|
||||
final class Phabricator404Controller extends PhabricatorController {
|
||||
final class Phabricator404Controller
|
||||
extends PhabricatorController {
|
||||
|
||||
public function shouldRequireLogin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
return new Aphront404Response();
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPlatform404Controller
|
||||
extends PhabricatorController {
|
||||
|
||||
public function processRequest() {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
}
|
|
@ -61,16 +61,22 @@ final class PhabricatorDiffusionConfigOptions
|
|||
->setDescription(pht('Hard byte limit on including patches in email.')),
|
||||
$this->newOption('metamta.diffusion.time-limit', 'int', 60)
|
||||
->setDescription(pht('Hard time limit on generating patches.')),
|
||||
|
||||
$this->newOption(
|
||||
'audit.can-author-close-audit',
|
||||
'bool',
|
||||
false)
|
||||
->setBoolOptions(
|
||||
array(
|
||||
pht('Enable Closing Audits'),
|
||||
pht('Disable Closing Audits'),
|
||||
pht('Enable Self-Accept'),
|
||||
pht('Disable Self-Accept'),
|
||||
))
|
||||
->setDescription(pht('Controls whether Author can Close Audits.')),
|
||||
->setDescription(
|
||||
pht(
|
||||
'Allows the author of a commit to be an auditor and accept their '.
|
||||
'own commits. Note that this behavior is different from the '.
|
||||
'behavior implied by the name of the option: long ago, it did '.
|
||||
'something else.')),
|
||||
|
||||
$this->newOption('bugtraq.url', 'string', null)
|
||||
->addExample('https://bugs.php.net/%BUGID%', pht('PHP bugs'))
|
||||
|
|
|
@ -598,10 +598,6 @@ final class DiffusionCommitController extends DiffusionController {
|
|||
$other_requests = array();
|
||||
|
||||
foreach ($audit_requests as $audit_request) {
|
||||
if (!$audit_request->isInteresting()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($audit_request->isUser()) {
|
||||
$user_requests[] = $audit_request;
|
||||
} else {
|
||||
|
@ -902,12 +898,13 @@ final class DiffusionCommitController extends DiffusionController {
|
|||
|
||||
$view = new PHUIStatusListView();
|
||||
foreach ($audit_requests as $request) {
|
||||
$code = $request->getAuditStatus();
|
||||
$status = $request->getAuditRequestStatusObject();
|
||||
|
||||
$item = new PHUIStatusItemView();
|
||||
$item->setIcon(
|
||||
PhabricatorAuditStatusConstants::getStatusIcon($code),
|
||||
PhabricatorAuditStatusConstants::getStatusColor($code),
|
||||
PhabricatorAuditStatusConstants::getStatusName($code));
|
||||
$status->getIconIcon(),
|
||||
$status->getIconColor(),
|
||||
$status->getStatusName());
|
||||
|
||||
$auditor_phid = $request->getAuditorPHID();
|
||||
$target = $viewer->renderHandle($auditor_phid);
|
||||
|
|
|
@ -98,9 +98,9 @@ final class DiffusionDoorkeeperCommitFeedStoryPublisher
|
|||
}
|
||||
|
||||
switch ($status) {
|
||||
case PhabricatorAuditStatusConstants::AUDIT_REQUIRED:
|
||||
case PhabricatorAuditStatusConstants::AUDIT_REQUESTED:
|
||||
case PhabricatorAuditStatusConstants::CONCERNED:
|
||||
case PhabricatorAuditRequestStatus::AUDIT_REQUIRED:
|
||||
case PhabricatorAuditRequestStatus::AUDIT_REQUESTED:
|
||||
case PhabricatorAuditRequestStatus::CONCERNED:
|
||||
$active += array_fuse($request_phids);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionAuditorsSearchEngineAttachment
|
||||
extends PhabricatorSearchEngineAttachment {
|
||||
|
||||
public function getAttachmentName() {
|
||||
return pht('Diffusion Auditors');
|
||||
}
|
||||
|
||||
public function getAttachmentDescription() {
|
||||
return pht('Get the auditors for each commit.');
|
||||
}
|
||||
|
||||
public function willLoadAttachmentData($query, $spec) {
|
||||
$query->needAuditRequests(true);
|
||||
}
|
||||
|
||||
public function getAttachmentForObject($object, $data, $spec) {
|
||||
$auditors = $object->getAudits();
|
||||
|
||||
$list = array();
|
||||
foreach ($auditors as $auditor) {
|
||||
$status = $auditor->getAuditRequestStatusObject();
|
||||
|
||||
$list[] = array(
|
||||
'auditorPHID' => $auditor->getAuditorPHID(),
|
||||
'status' => $status->getStatusValueForConduit(),
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'auditors' => $list,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -38,9 +38,7 @@ abstract class DiffusionAuditorsHeraldAction
|
|||
|
||||
$current = array();
|
||||
foreach ($auditors as $auditor) {
|
||||
if ($auditor->isInteresting()) {
|
||||
$current[] = $auditor->getAuditorPHID();
|
||||
}
|
||||
$current[] = $auditor->getAuditorPHID();
|
||||
}
|
||||
|
||||
$allowed_types = array(
|
||||
|
|
|
@ -22,9 +22,11 @@ final class DiffusionCommitAuditorsHeraldField
|
|||
|
||||
$phids = array();
|
||||
foreach ($audits as $audit) {
|
||||
if ($audit->isActiveAudit()) {
|
||||
$phids[] = $audit->getAuditorPHID();
|
||||
if ($audit->isResigned()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$phids[] = $audit->getAuditorPHID();
|
||||
}
|
||||
|
||||
return $phids;
|
||||
|
|
|
@ -166,8 +166,8 @@ final class HeraldCommitAdapter
|
|||
public function loadAuditNeededPackages() {
|
||||
if ($this->auditNeededPackages === null) {
|
||||
$status_arr = array(
|
||||
PhabricatorAuditStatusConstants::AUDIT_REQUIRED,
|
||||
PhabricatorAuditStatusConstants::CONCERNED,
|
||||
PhabricatorAuditRequestStatus::AUDIT_REQUIRED,
|
||||
PhabricatorAuditRequestStatus::CONCERNED,
|
||||
);
|
||||
$requests = id(new PhabricatorRepositoryAuditRequest())
|
||||
->loadAllWhere(
|
||||
|
|
|
@ -90,7 +90,7 @@ final class DiffusionCommitRequiredActionResultBucket
|
|||
$objects = $this->objects;
|
||||
|
||||
$has_concern = array(
|
||||
PhabricatorAuditStatusConstants::CONCERNED,
|
||||
PhabricatorAuditRequestStatus::CONCERNED,
|
||||
);
|
||||
$has_concern = array_fuse($has_concern);
|
||||
|
||||
|
@ -119,8 +119,8 @@ final class DiffusionCommitRequiredActionResultBucket
|
|||
$objects = $this->objects;
|
||||
|
||||
$should_audit = array(
|
||||
PhabricatorAuditStatusConstants::AUDIT_REQUIRED,
|
||||
PhabricatorAuditStatusConstants::AUDIT_REQUESTED,
|
||||
PhabricatorAuditRequestStatus::AUDIT_REQUIRED,
|
||||
PhabricatorAuditRequestStatus::AUDIT_REQUESTED,
|
||||
);
|
||||
$should_audit = array_fuse($should_audit);
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ final class DiffusionCommitAcceptTransaction
|
|||
}
|
||||
|
||||
public function applyExternalEffects($object, $value) {
|
||||
$status = PhabricatorAuditStatusConstants::ACCEPTED;
|
||||
$status = PhabricatorAuditRequestStatus::ACCEPTED;
|
||||
$actor = $this->getActor();
|
||||
$this->applyAuditorEffect($object, $actor, $value, $status);
|
||||
}
|
||||
|
|
|
@ -21,12 +21,12 @@ abstract class DiffusionCommitAuditTransaction
|
|||
PhabricatorRepositoryCommit $commit,
|
||||
PhabricatorUser $viewer) {
|
||||
|
||||
// This omits various inactive states like "Resigned" and "Not Required".
|
||||
// This omits inactive states; currently just "Resigned".
|
||||
$active = array(
|
||||
PhabricatorAuditStatusConstants::AUDIT_REQUIRED,
|
||||
PhabricatorAuditStatusConstants::CONCERNED,
|
||||
PhabricatorAuditStatusConstants::ACCEPTED,
|
||||
PhabricatorAuditStatusConstants::AUDIT_REQUESTED,
|
||||
PhabricatorAuditRequestStatus::AUDIT_REQUIRED,
|
||||
PhabricatorAuditRequestStatus::CONCERNED,
|
||||
PhabricatorAuditRequestStatus::ACCEPTED,
|
||||
PhabricatorAuditRequestStatus::AUDIT_REQUESTED,
|
||||
);
|
||||
$active = array_fuse($active);
|
||||
|
||||
|
@ -42,7 +42,7 @@ abstract class DiffusionCommitAuditTransaction
|
|||
$commit,
|
||||
$viewer,
|
||||
array(
|
||||
PhabricatorAuditStatusConstants::ACCEPTED,
|
||||
PhabricatorAuditRequestStatus::ACCEPTED,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ abstract class DiffusionCommitAuditTransaction
|
|||
$commit,
|
||||
$viewer,
|
||||
array(
|
||||
PhabricatorAuditStatusConstants::CONCERNED,
|
||||
PhabricatorAuditRequestStatus::CONCERNED,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ abstract class DiffusionCommitAuditTransaction
|
|||
|
||||
$map = array();
|
||||
|
||||
$with_authority = ($status != PhabricatorAuditStatusConstants::RESIGNED);
|
||||
$with_authority = ($status != PhabricatorAuditRequestStatus::RESIGNED);
|
||||
if ($with_authority) {
|
||||
foreach ($audits as $audit) {
|
||||
if ($commit->hasAuditAuthority($actor, $audit, $acting_phid)) {
|
||||
|
|
|
@ -16,7 +16,7 @@ final class DiffusionCommitAuditorsTransaction
|
|||
$auditors = $this->generateOldValue($object);
|
||||
$old_auditors = $auditors;
|
||||
|
||||
$request_status = PhabricatorAuditStatusConstants::AUDIT_REQUESTED;
|
||||
$request_status = PhabricatorAuditRequestStatus::AUDIT_REQUESTED;
|
||||
|
||||
$rem = idx($value, '-', array());
|
||||
foreach ($rem as $phid) {
|
||||
|
|
|
@ -37,7 +37,7 @@ final class DiffusionCommitConcernTransaction
|
|||
}
|
||||
|
||||
public function applyExternalEffects($object, $value) {
|
||||
$status = PhabricatorAuditStatusConstants::CONCERNED;
|
||||
$status = PhabricatorAuditRequestStatus::CONCERNED;
|
||||
$actor = $this->getActor();
|
||||
$this->applyAuditorEffect($object, $actor, $value, $status);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ final class DiffusionCommitResignTransaction
|
|||
}
|
||||
|
||||
public function applyExternalEffects($object, $value) {
|
||||
$status = PhabricatorAuditStatusConstants::RESIGNED;
|
||||
$status = PhabricatorAuditRequestStatus::RESIGNED;
|
||||
$actor = $this->getActor();
|
||||
$this->applyAuditorEffect($object, $actor, $value, $status);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,17 @@ final class PhabricatorJSONDocumentEngine
|
|||
try {
|
||||
$data = phutil_json_decode($raw_data);
|
||||
|
||||
// See T13635. "phutil_json_decode()" always turns JSON into a PHP array,
|
||||
// and we lose the distinction between "{}" and "[]". This distinction is
|
||||
// important when rendering a document.
|
||||
$data = json_decode($raw_data, false);
|
||||
if (!$data) {
|
||||
throw new PhabricatorDocumentEngineParserException(
|
||||
pht(
|
||||
'Failed to "json_decode(...)" JSON document after successfully '.
|
||||
'decoding it with "phutil_json_decode(...).'));
|
||||
}
|
||||
|
||||
if (preg_match('/^\s*\[/', $raw_data)) {
|
||||
$content = id(new PhutilJSON())->encodeAsList($data);
|
||||
} else {
|
||||
|
@ -47,6 +58,13 @@ final class PhabricatorJSONDocumentEngine
|
|||
'This document is not valid JSON: %s',
|
||||
$ex->getMessage()));
|
||||
|
||||
$content = $raw_data;
|
||||
} catch (PhabricatorDocumentEngineParserException $ex) {
|
||||
$message = $this->newMessage(
|
||||
pht(
|
||||
'Unable to parse this document as JSON: %s',
|
||||
$ex->getMessage()));
|
||||
|
||||
$content = $raw_data;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorDocumentEngineParserException
|
||||
extends Exception {}
|
|
@ -63,25 +63,7 @@ final class PhabricatorNotificationQuery
|
|||
$this->buildWhereClause($conn),
|
||||
$this->buildLimitClause($conn));
|
||||
|
||||
// See T13623. Although most queries for notifications return unique
|
||||
// stories, this isn't a guarantee.
|
||||
$story_map = ipull($data, null, 'chronologicalKey');
|
||||
|
||||
$stories = PhabricatorFeedStory::loadAllFromRows(
|
||||
$story_map,
|
||||
$this->getViewer());
|
||||
$stories = mpull($stories, null, 'getChronologicalKey');
|
||||
|
||||
$results = array();
|
||||
foreach ($data as $row) {
|
||||
$story_key = $row['chronologicalKey'];
|
||||
$has_viewed = $row['hasViewed'];
|
||||
|
||||
$results[] = id(clone $stories[$story_key])
|
||||
->setHasViewed($has_viewed);
|
||||
}
|
||||
|
||||
return $results;
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
|
@ -111,14 +93,47 @@ final class PhabricatorNotificationQuery
|
|||
return $where;
|
||||
}
|
||||
|
||||
protected function willFilterPage(array $stories) {
|
||||
foreach ($stories as $key => $story) {
|
||||
if (!$story->isVisibleInNotifications()) {
|
||||
unset($stories[$key]);
|
||||
protected function willFilterPage(array $rows) {
|
||||
// See T13623. The policy model here is outdated and awkward.
|
||||
|
||||
// Users may have notifications about objects they can no longer see.
|
||||
// Two ways this can arise: destroy an object; or change an object's
|
||||
// view policy to exclude a user.
|
||||
|
||||
// "PhabricatorFeedStory::loadAllFromRows()" does its own policy filtering.
|
||||
// This doesn't align well with modern query sequencing, but we should be
|
||||
// able to get away with it by loading here.
|
||||
|
||||
// See T13623. Although most queries for notifications return unique
|
||||
// stories, this isn't a guarantee.
|
||||
$story_map = ipull($rows, null, 'chronologicalKey');
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
$stories = PhabricatorFeedStory::loadAllFromRows($story_map, $viewer);
|
||||
$stories = mpull($stories, null, 'getChronologicalKey');
|
||||
|
||||
$results = array();
|
||||
foreach ($rows as $row) {
|
||||
$story_key = $row['chronologicalKey'];
|
||||
$has_viewed = $row['hasViewed'];
|
||||
|
||||
if (!isset($stories[$story_key])) {
|
||||
// NOTE: We can't call "didRejectResult()" here because we don't have
|
||||
// a policy object to pass.
|
||||
continue;
|
||||
}
|
||||
|
||||
$story = id(clone $stories[$story_key])
|
||||
->setHasViewed($has_viewed);
|
||||
|
||||
if (!$story->isVisibleInNotifications()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$results[] = $story;
|
||||
}
|
||||
|
||||
return $stories;
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function getDefaultOrderVector() {
|
||||
|
@ -166,7 +181,7 @@ final class PhabricatorNotificationQuery
|
|||
|
||||
protected function newPagingMapFromPartialObject($object) {
|
||||
return array(
|
||||
'key' => $object->getChronologicalKey(),
|
||||
'key' => $object['chronologicalKey'],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,11 @@ final class PhabricatorPhameApplication extends PhabricatorApplication {
|
|||
}
|
||||
|
||||
public function getBlogRoutes() {
|
||||
return $this->getLiveRoutes();
|
||||
return $this->getLiveRoutes() + array(
|
||||
'/status/' => 'PhabricatorStatusController',
|
||||
'/favicon.ico' => 'PhabricatorFaviconController',
|
||||
'/robots.txt' => 'PhabricatorRobotsBlogController',
|
||||
);
|
||||
}
|
||||
|
||||
private function getLiveRoutes() {
|
||||
|
|
|
@ -55,6 +55,10 @@ final class PhabricatorPhurlApplication extends PhabricatorApplication {
|
|||
|
||||
public function getShortRoutes() {
|
||||
return array(
|
||||
'/status/' => 'PhabricatorStatusController',
|
||||
'/favicon.ico' => 'PhabricatorFaviconController',
|
||||
'/robots.txt' => 'PhabricatorRobotsShortController',
|
||||
|
||||
'/u/(?P<append>[^/]+)' => 'PhabricatorPhurlShortURLController',
|
||||
'.*' => 'PhabricatorPhurlShortURLDefaultController',
|
||||
);
|
||||
|
|
|
@ -49,38 +49,14 @@ final class PhabricatorRepositoryAuditRequest
|
|||
return $this->assertAttached($this->commit);
|
||||
}
|
||||
|
||||
public function isActiveAudit() {
|
||||
switch ($this->getAuditStatus()) {
|
||||
case PhabricatorAuditStatusConstants::NONE:
|
||||
case PhabricatorAuditStatusConstants::AUDIT_NOT_REQUIRED:
|
||||
case PhabricatorAuditStatusConstants::RESIGNED:
|
||||
case PhabricatorAuditStatusConstants::CLOSED:
|
||||
case PhabricatorAuditStatusConstants::CC:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isInteresting() {
|
||||
switch ($this->getAuditStatus()) {
|
||||
case PhabricatorAuditStatusConstants::NONE:
|
||||
case PhabricatorAuditStatusConstants::AUDIT_NOT_REQUIRED:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isResigned() {
|
||||
switch ($this->getAuditStatus()) {
|
||||
case PhabricatorAuditStatusConstants::RESIGNED:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return $this->getAuditRequestStatusObject()->isResigned();
|
||||
}
|
||||
|
||||
public function getAuditRequestStatusObject() {
|
||||
$status = $this->getAuditStatus();
|
||||
return PhabricatorAuditRequestStatus::newForStatus($status);
|
||||
}
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -312,14 +312,14 @@ final class PhabricatorRepositoryCommit
|
|||
|
||||
foreach ($requests as $request) {
|
||||
switch ($request->getAuditStatus()) {
|
||||
case PhabricatorAuditStatusConstants::AUDIT_REQUIRED:
|
||||
case PhabricatorAuditStatusConstants::AUDIT_REQUESTED:
|
||||
case PhabricatorAuditRequestStatus::AUDIT_REQUIRED:
|
||||
case PhabricatorAuditRequestStatus::AUDIT_REQUESTED:
|
||||
$any_need = true;
|
||||
break;
|
||||
case PhabricatorAuditStatusConstants::ACCEPTED:
|
||||
case PhabricatorAuditRequestStatus::ACCEPTED:
|
||||
$any_accept = true;
|
||||
break;
|
||||
case PhabricatorAuditStatusConstants::CONCERNED:
|
||||
case PhabricatorAuditRequestStatus::CONCERNED:
|
||||
$any_concern = true;
|
||||
break;
|
||||
}
|
||||
|
@ -945,7 +945,10 @@ final class PhabricatorRepositoryCommit
|
|||
}
|
||||
|
||||
public function getConduitSearchAttachments() {
|
||||
return array();
|
||||
return array(
|
||||
id(new DiffusionAuditorsSearchEngineAttachment())
|
||||
->setAttachmentKey('auditors'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -284,11 +284,24 @@ final class PhutilSearchQueryCompiler
|
|||
$operator = self::OPERATOR_AND;
|
||||
break;
|
||||
case '':
|
||||
// See T12995. If this query term contains Chinese, Japanese or
|
||||
// Korean characters, treat the term as a substring term by default.
|
||||
// These languages do not separate words with spaces, so the term
|
||||
// search mode is normally useless.
|
||||
if ($enable_functions && !$is_quoted && phutil_utf8_is_cjk($value)) {
|
||||
$use_substring = false;
|
||||
|
||||
if ($enable_functions && !$is_quoted) {
|
||||
// See T12995. If this query term contains Chinese, Japanese or
|
||||
// Korean characters, treat the term as a substring term by default.
|
||||
// These languages do not separate words with spaces, so the term
|
||||
// search mode is normally useless.
|
||||
if (phutil_utf8_is_cjk($value)) {
|
||||
$use_substring = true;
|
||||
} else if (phutil_preg_match('/^_/', $value)) {
|
||||
// See T13632. Assume users searching for any term that begins
|
||||
// with an undescore intend to perform substring search if they
|
||||
// don't provide an explicit search function.
|
||||
$use_substring = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($use_substring) {
|
||||
$operator = self::OPERATOR_SUBSTRING;
|
||||
} else {
|
||||
$operator = self::OPERATOR_AND;
|
||||
|
|
|
@ -205,6 +205,20 @@ final class PhutilSearchQueryCompilerTestCase
|
|||
'xyz',
|
||||
),
|
||||
),
|
||||
|
||||
// See T12995. Interpret CJK tokens as substring queries since these
|
||||
// languages do not use spaces as word separators.
|
||||
"\xE7\x8C\xAB" => array(
|
||||
array(null, $op_sub, "\xE7\x8C\xAB"),
|
||||
),
|
||||
|
||||
// See T13632. Interpret tokens that begin with "_" as substring tokens
|
||||
// if no function is specified.
|
||||
'_x _y_ "_z_"' => array(
|
||||
array(null, $op_sub, '_x'),
|
||||
array(null, $op_sub, '_y_'),
|
||||
array(null, $op_and, '_z_'),
|
||||
),
|
||||
);
|
||||
|
||||
$this->assertCompileFunctionQueries($function_tests);
|
||||
|
|
|
@ -25,7 +25,7 @@ final class PhabricatorSystemApplication extends PhabricatorApplication {
|
|||
'/status/' => 'PhabricatorStatusController',
|
||||
'/debug/' => 'PhabricatorDebugController',
|
||||
'/favicon.ico' => 'PhabricatorFaviconController',
|
||||
'/robots.txt' => 'PhabricatorRobotsController',
|
||||
'/robots.txt' => 'PhabricatorRobotsPlatformController',
|
||||
'/services/' => array(
|
||||
'encoding/' => 'PhabricatorSystemSelectEncodingController',
|
||||
'highlight/' => 'PhabricatorSystemSelectHighlightController',
|
||||
|
@ -38,4 +38,12 @@ final class PhabricatorSystemApplication extends PhabricatorApplication {
|
|||
);
|
||||
}
|
||||
|
||||
public function getResourceRoutes() {
|
||||
return array(
|
||||
'/status/' => 'PhabricatorStatusController',
|
||||
'/favicon.ico' => 'PhabricatorFaviconController',
|
||||
'/robots.txt' => 'PhabricatorRobotsResourceController',
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRobotsBlogController
|
||||
extends PhabricatorRobotsController {
|
||||
|
||||
protected function newRobotsRules() {
|
||||
$out = array();
|
||||
|
||||
// Allow everything on blog domains to be indexed.
|
||||
|
||||
$out[] = 'User-Agent: *';
|
||||
$out[] = 'Crawl-delay: 1';
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorRobotsController extends PhabricatorController {
|
||||
|
||||
public function shouldRequireLogin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
final public function processRequest() {
|
||||
$out = $this->newRobotsRules();
|
||||
|
||||
$content = implode("\n", $out)."\n";
|
||||
|
||||
return id(new AphrontPlainTextResponse())
|
||||
->setContent($content)
|
||||
->setCacheDurationInSeconds(phutil_units('2 hours in seconds'))
|
||||
->setCanCDN(true);
|
||||
}
|
||||
|
||||
abstract protected function newRobotsRules();
|
||||
|
||||
}
|
|
@ -1,12 +1,9 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRobotsController extends PhabricatorController {
|
||||
final class PhabricatorRobotsPlatformController
|
||||
extends PhabricatorRobotsController {
|
||||
|
||||
public function shouldRequireLogin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
protected function newRobotsRules() {
|
||||
$out = array();
|
||||
|
||||
// Prevent indexing of '/diffusion/', since the content is not generally
|
||||
|
@ -29,11 +26,7 @@ final class PhabricatorRobotsController extends PhabricatorController {
|
|||
// probably not hugely concerned about cutting-edge SEO.
|
||||
$out[] = 'Crawl-delay: 1';
|
||||
|
||||
$content = implode("\n", $out)."\n";
|
||||
|
||||
return id(new AphrontPlainTextResponse())
|
||||
->setContent($content)
|
||||
->setCacheDurationInSeconds(phutil_units('2 hours in seconds'))
|
||||
->setCanCDN(true);
|
||||
return $out;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRobotsResourceController
|
||||
extends PhabricatorRobotsController {
|
||||
|
||||
protected function newRobotsRules() {
|
||||
$out = array();
|
||||
|
||||
// See T13636. Prevent indexing of any content on resource domains.
|
||||
|
||||
$out[] = 'User-Agent: *';
|
||||
$out[] = 'Disallow: /';
|
||||
$out[] = 'Crawl-delay: 1';
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRobotsShortController
|
||||
extends PhabricatorRobotsController {
|
||||
|
||||
protected function newRobotsRules() {
|
||||
$out = array();
|
||||
|
||||
// See T13636. Prevent indexing of any content on short domains.
|
||||
|
||||
$out[] = 'User-Agent: *';
|
||||
$out[] = 'Disallow: /';
|
||||
$out[] = 'Crawl-delay: 1';
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
}
|
|
@ -8,7 +8,9 @@ final class TransactionSearchConduitAPIMethod
|
|||
}
|
||||
|
||||
public function getMethodDescription() {
|
||||
return pht('Read transactions and comments for an object.');
|
||||
return pht(
|
||||
'Read transactions and comments for a particular object '.
|
||||
'or an entire object type.');
|
||||
}
|
||||
|
||||
public function getMethodDocumentation() {
|
||||
|
@ -23,6 +25,26 @@ One common reason to call this method is that you're implmenting a webhook and
|
|||
just received a notification that an object has changed. See the Webhooks
|
||||
documentation for more detailed discussion of this use case.
|
||||
|
||||
One Object Type at a Time
|
||||
=========================
|
||||
|
||||
This API method can query transactions for any type of object which supports
|
||||
transactions, but only one type of object can be queried per call. For example:
|
||||
you can retrieve transactions affecting Tasks, or you can retrieve transactions
|
||||
affecting Revisions, but a single call can not retrieve both.
|
||||
|
||||
This is a technical limitation arising because (among other reasons) there is
|
||||
no global ordering on transactions.
|
||||
|
||||
To find transactions for a specific object (like a particular task), pass the
|
||||
object PHID or an appropriate object identifier (like `T123`) as an
|
||||
`objectIdentifier`.
|
||||
|
||||
To find all transactions for an object type, pass the object type constant as
|
||||
an `objectType`. For example, the correct identifier for tasks is `TASK`. (You
|
||||
can quickly find an unknown type constant by looking at the PHID of an object
|
||||
of that type.)
|
||||
|
||||
Constraints
|
||||
===========
|
||||
|
||||
|
@ -64,8 +86,9 @@ EOREMARKUP
|
|||
|
||||
protected function defineParamTypes() {
|
||||
return array(
|
||||
'objectIdentifier' => 'phid|string',
|
||||
'constraints' => 'map<string, wild>',
|
||||
'objectIdentifier' => 'optional phid|string',
|
||||
'objectType' => 'optional string',
|
||||
'constraints' => 'optional map<string, wild>',
|
||||
) + $this->getPagerParamTypes();
|
||||
}
|
||||
|
||||
|
@ -81,43 +104,19 @@ EOREMARKUP
|
|||
$viewer = $request->getUser();
|
||||
$pager = $this->newPager($request);
|
||||
|
||||
$object_name = $request->getValue('objectIdentifier', null);
|
||||
if (!strlen($object_name)) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'When calling "transaction.search", you must provide an object to '.
|
||||
'retrieve transactions for.'));
|
||||
}
|
||||
|
||||
$object = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withNames(array($object_name))
|
||||
->executeOne();
|
||||
if (!$object) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'No object "%s" exists.',
|
||||
$object_name));
|
||||
}
|
||||
|
||||
if (!($object instanceof PhabricatorApplicationTransactionInterface)) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Object "%s" (of type "%s") does not implement "%s", so '.
|
||||
'transactions can not be loaded for it.',
|
||||
$object_name,
|
||||
get_class($object),
|
||||
'PhabricatorApplicationTransactionInterface'));
|
||||
}
|
||||
$object = $this->loadTemplateObject($request);
|
||||
|
||||
$xaction_query = PhabricatorApplicationTransactionQuery::newQueryForObject(
|
||||
$object);
|
||||
|
||||
$xaction_query
|
||||
->needHandles(false)
|
||||
->withObjectPHIDs(array($object->getPHID()))
|
||||
->setViewer($viewer);
|
||||
|
||||
if ($object->getPHID()) {
|
||||
$xaction_query->withObjectPHIDs(array($object->getPHID()));
|
||||
}
|
||||
|
||||
$constraints = $request->getValue('constraints', array());
|
||||
|
||||
$xaction_query = $this->applyConstraints($constraints, $xaction_query);
|
||||
|
@ -355,4 +354,65 @@ EOREMARKUP
|
|||
);
|
||||
}
|
||||
|
||||
private function loadTemplateObject(ConduitAPIRequest $request) {
|
||||
$viewer = $request->getUser();
|
||||
|
||||
$object_identifier = $request->getValue('objectIdentifier');
|
||||
$object_type = $request->getValue('objectType');
|
||||
|
||||
$has_identifier = ($object_identifier !== null);
|
||||
$has_type = ($object_type !== null);
|
||||
|
||||
if (!$has_type && !$has_identifier) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Calls to "transaction.search" must specify either an "objectType" '.
|
||||
'or an "objectIdentifier"'));
|
||||
} else if ($has_type && $has_identifier) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Calls to "transaction.search" must not specify both an '.
|
||||
'"objectType" and an "objectIdentifier".'));
|
||||
}
|
||||
|
||||
if ($has_type) {
|
||||
$all_types = PhabricatorPHIDType::getAllTypes();
|
||||
|
||||
if (!isset($all_types[$object_type])) {
|
||||
ksort($all_types);
|
||||
throw new Exception(
|
||||
pht(
|
||||
'In call to "transaction.search", specified "objectType" ("%s") '.
|
||||
'is unknown. Valid object types are: %s.',
|
||||
$object_type,
|
||||
implode(', ', array_keys($all_types))));
|
||||
}
|
||||
|
||||
$object = $all_types[$object_type]->newObject();
|
||||
} else {
|
||||
$object = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withNames(array($object_identifier))
|
||||
->executeOne();
|
||||
if (!$object) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'In call to "transaction.search", specified "objectIdentifier" '.
|
||||
'("%s") does not exist.',
|
||||
$object_identifier));
|
||||
}
|
||||
}
|
||||
|
||||
if (!($object instanceof PhabricatorApplicationTransactionInterface)) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'In call to "transaction.search", selected object (of type "%s") '.
|
||||
'does not implement "%s", so transactions can not be loaded for it.',
|
||||
get_class($object),
|
||||
'PhabricatorApplicationTransactionInterface'));
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -347,7 +347,16 @@ abstract class AphrontBaseMySQLDatabaseConnection
|
|||
case 1142: // Access denied to table
|
||||
case 1143: // Access denied to column
|
||||
case 1227: // Access denied (e.g., no SUPER for SHOW SLAVE STATUS).
|
||||
throw new AphrontAccessDeniedQueryException($message);
|
||||
|
||||
// See T13622. Try to help users figure out that this is a GRANT
|
||||
// problem.
|
||||
|
||||
$more = pht(
|
||||
'This error usually indicates that you need to "GRANT" the '.
|
||||
'MySQL user additional permissions. See "GRANT" in the MySQL '.
|
||||
'manual for help.');
|
||||
|
||||
throw new AphrontAccessDeniedQueryException("{$message}\n\n{$more}");
|
||||
case 1045: // Access denied (auth)
|
||||
throw new AphrontInvalidCredentialsQueryException($message);
|
||||
case 1146: // No such table
|
||||
|
|
Loading…
Add table
Reference in a new issue