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

(stable) Promote 2016 Week 35

This commit is contained in:
epriestley 2016-08-26 17:30:23 -07:00
commit be84c051e5
79 changed files with 1180 additions and 616 deletions

View file

@ -42,7 +42,7 @@ return array(
'rsrc/css/application/config/config-options.css' => '0ede4c9b',
'rsrc/css/application/config/config-template.css' => '8e6c6fcd',
'rsrc/css/application/config/config-welcome.css' => '035aa483',
'rsrc/css/application/config/setup-issue.css' => 'db7e9c40',
'rsrc/css/application/config/setup-issue.css' => 'f794cfc3',
'rsrc/css/application/config/unhandled-exception.css' => '4c96257a',
'rsrc/css/application/conpherence/durable-column.css' => '86396117',
'rsrc/css/application/conpherence/menu.css' => 'f99fee4c',
@ -891,7 +891,7 @@ return array(
'releeph-preview-branch' => 'b7a6f4a5',
'releeph-request-differential-create-dialog' => '8d8b92cd',
'releeph-request-typeahead-css' => '667a48ae',
'setup-issue-css' => 'db7e9c40',
'setup-issue-css' => 'f794cfc3',
'sprite-login-css' => '60e8560e',
'sprite-tokens-css' => '9cdfd599',
'syntax-default-css' => '9923583c',

View file

@ -15,8 +15,7 @@
],
"conduit.uri" : null,
"conduit.user" : null,
"conduit.cert" : null,
"conduit.token" : null,
"macro.size" : 48,
"macro.aspect" : 0.66,

View file

@ -0,0 +1 @@
DROP TABLE {$NAMESPACE}_conduit.conduit_connectionlog;

View file

@ -0,0 +1,8 @@
CREATE TABLE {$NAMESPACE}_repository.repository_commithint (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
repositoryPHID VARBINARY(64) NOT NULL,
oldCommitIdentifier VARCHAR(40) NOT NULL COLLATE {$COLLATE_TEXT},
newCommitIdentifier VARCHAR(40) COLLATE {$COLLATE_TEXT},
hintType VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
UNIQUE KEY `key_old` (repositoryPHID, oldCommitIdentifier)
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,39 @@
<?php
$table = new PhabricatorRepositoryCommit();
$conn = $table->establishConnection('w');
$rows = queryfx_all(
$conn,
'SELECT fullCommitName FROM repository_badcommit');
$viewer = PhabricatorUser::getOmnipotentUser();
foreach ($rows as $row) {
$identifier = $row['fullCommitName'];
$commit = id(new DiffusionCommitQuery())
->setViewer($viewer)
->withIdentifiers(array($identifier))
->executeOne();
if (!$commit) {
echo tsprintf(
"%s\n",
pht(
'Skipped hint for "%s", this is not a valid commit.',
$identifier));
} else {
PhabricatorRepositoryCommitHint::updateHint(
$commit->getRepository()->getPHID(),
$commit->getCommitIdentifier(),
null,
PhabricatorRepositoryCommitHint::HINT_UNREADABLE);
echo tsprintf(
"%s\n",
pht(
'Updated commit hint for "%s".',
$identifier));
}
}

View file

@ -0,0 +1 @@
DROP TABLE {$NAMESPACE}_repository.repository_badcommit;

View file

@ -0,0 +1,7 @@
/* Removes Ponder vote data. */
DELETE FROM {$NAMESPACE}_ponder.edge
WHERE type IN (17, 18, 19, 20);
DELETE FROM {$NAMESPACE}_user.edge
WHERE type IN (17, 18, 19, 20);

View file

@ -612,6 +612,7 @@ phutil_register_library_map(array(
'DiffusionCommitHash' => 'applications/diffusion/data/DiffusionCommitHash.php',
'DiffusionCommitHeraldField' => 'applications/diffusion/herald/DiffusionCommitHeraldField.php',
'DiffusionCommitHeraldFieldGroup' => 'applications/diffusion/herald/DiffusionCommitHeraldFieldGroup.php',
'DiffusionCommitHintQuery' => 'applications/diffusion/query/DiffusionCommitHintQuery.php',
'DiffusionCommitHookEngine' => 'applications/diffusion/engine/DiffusionCommitHookEngine.php',
'DiffusionCommitHookRejectException' => 'applications/diffusion/exception/DiffusionCommitHookRejectException.php',
'DiffusionCommitMergeHeraldField' => 'applications/diffusion/herald/DiffusionCommitMergeHeraldField.php',
@ -2114,7 +2115,6 @@ phutil_register_library_map(array(
'PhabricatorConduitAPIController' => 'applications/conduit/controller/PhabricatorConduitAPIController.php',
'PhabricatorConduitApplication' => 'applications/conduit/application/PhabricatorConduitApplication.php',
'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/PhabricatorConduitCertificateToken.php',
'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/PhabricatorConduitConnectionLog.php',
'PhabricatorConduitConsoleController' => 'applications/conduit/controller/PhabricatorConduitConsoleController.php',
'PhabricatorConduitContentSource' => 'infrastructure/contentsource/PhabricatorConduitContentSource.php',
'PhabricatorConduitController' => 'applications/conduit/controller/PhabricatorConduitController.php',
@ -2140,6 +2140,7 @@ phutil_register_library_map(array(
'PhabricatorConduitTokensSettingsPanel' => 'applications/conduit/settings/PhabricatorConduitTokensSettingsPanel.php',
'PhabricatorConfigAllController' => 'applications/config/controller/PhabricatorConfigAllController.php',
'PhabricatorConfigApplication' => 'applications/config/application/PhabricatorConfigApplication.php',
'PhabricatorConfigApplicationController' => 'applications/config/controller/PhabricatorConfigApplicationController.php',
'PhabricatorConfigCacheController' => 'applications/config/controller/PhabricatorConfigCacheController.php',
'PhabricatorConfigClusterDatabasesController' => 'applications/config/controller/PhabricatorConfigClusterDatabasesController.php',
'PhabricatorConfigClusterNotificationsController' => 'applications/config/controller/PhabricatorConfigClusterNotificationsController.php',
@ -2201,7 +2202,7 @@ phutil_register_library_map(array(
'PhabricatorConfigTransaction' => 'applications/config/storage/PhabricatorConfigTransaction.php',
'PhabricatorConfigTransactionQuery' => 'applications/config/query/PhabricatorConfigTransactionQuery.php',
'PhabricatorConfigValidationException' => 'applications/config/exception/PhabricatorConfigValidationException.php',
'PhabricatorConfigVersionsModule' => 'applications/config/module/PhabricatorConfigVersionsModule.php',
'PhabricatorConfigVersionController' => 'applications/config/controller/PhabricatorConfigVersionController.php',
'PhabricatorConfigWelcomeController' => 'applications/config/controller/PhabricatorConfigWelcomeController.php',
'PhabricatorConpherenceApplication' => 'applications/conpherence/application/PhabricatorConpherenceApplication.php',
'PhabricatorConpherenceColumnVisibleSetting' => 'applications/settings/setting/PhabricatorConpherenceColumnVisibleSetting.php',
@ -3383,6 +3384,7 @@ phutil_register_library_map(array(
'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php',
'PhabricatorRepositoryCommitData' => 'applications/repository/storage/PhabricatorRepositoryCommitData.php',
'PhabricatorRepositoryCommitHeraldWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitHeraldWorker.php',
'PhabricatorRepositoryCommitHint' => 'applications/repository/storage/PhabricatorRepositoryCommitHint.php',
'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php',
'PhabricatorRepositoryCommitOwnersWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitOwnersWorker.php',
'PhabricatorRepositoryCommitPHIDType' => 'applications/repository/phid/PhabricatorRepositoryCommitPHIDType.php',
@ -3403,6 +3405,7 @@ phutil_register_library_map(array(
'PhabricatorRepositoryManagementCacheWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementCacheWorkflow.php',
'PhabricatorRepositoryManagementClusterizeWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementClusterizeWorkflow.php',
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDiscoverWorkflow.php',
'PhabricatorRepositoryManagementHintWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementHintWorkflow.php',
'PhabricatorRepositoryManagementImportingWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementImportingWorkflow.php',
'PhabricatorRepositoryManagementListPathsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListPathsWorkflow.php',
'PhabricatorRepositoryManagementListWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListWorkflow.php',
@ -5104,6 +5107,7 @@ phutil_register_library_map(array(
'DiffusionCommitHash' => 'Phobject',
'DiffusionCommitHeraldField' => 'HeraldField',
'DiffusionCommitHeraldFieldGroup' => 'HeraldFieldGroup',
'DiffusionCommitHintQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'DiffusionCommitHookEngine' => 'Phobject',
'DiffusionCommitHookRejectException' => 'Exception',
'DiffusionCommitMergeHeraldField' => 'DiffusionCommitHeraldField',
@ -6845,7 +6849,6 @@ phutil_register_library_map(array(
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
'PhabricatorConduitApplication' => 'PhabricatorApplication',
'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO',
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
'PhabricatorConduitContentSource' => 'PhabricatorContentSource',
'PhabricatorConduitController' => 'PhabricatorController',
@ -6877,6 +6880,7 @@ phutil_register_library_map(array(
'PhabricatorConduitTokensSettingsPanel' => 'PhabricatorSettingsPanel',
'PhabricatorConfigAllController' => 'PhabricatorConfigController',
'PhabricatorConfigApplication' => 'PhabricatorApplication',
'PhabricatorConfigApplicationController' => 'PhabricatorConfigController',
'PhabricatorConfigCacheController' => 'PhabricatorConfigController',
'PhabricatorConfigClusterDatabasesController' => 'PhabricatorConfigController',
'PhabricatorConfigClusterNotificationsController' => 'PhabricatorConfigController',
@ -6945,7 +6949,7 @@ phutil_register_library_map(array(
'PhabricatorConfigTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorConfigValidationException' => 'Exception',
'PhabricatorConfigVersionsModule' => 'PhabricatorConfigModule',
'PhabricatorConfigVersionController' => 'PhabricatorConfigController',
'PhabricatorConfigWelcomeController' => 'PhabricatorConfigController',
'PhabricatorConpherenceApplication' => 'PhabricatorApplication',
'PhabricatorConpherenceColumnVisibleSetting' => 'PhabricatorInternalSetting',
@ -8348,6 +8352,10 @@ phutil_register_library_map(array(
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitHint' => array(
'PhabricatorRepositoryDAO',
'PhabricatorPolicyInterface',
),
'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitOwnersWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitPHIDType' => 'PhabricatorPHIDType',
@ -8372,6 +8380,7 @@ phutil_register_library_map(array(
'PhabricatorRepositoryManagementCacheWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementClusterizeWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementHintWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementImportingWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementListPathsWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementListWorkflow' => 'PhabricatorRepositoryManagementWorkflow',

View file

@ -162,7 +162,7 @@ abstract class AphrontResponse extends Phobject {
$object,
array(__CLASS__, 'processValueForJSONEncoding'));
$response = json_encode($object);
$response = phutil_json_encode($object);
// Prevent content sniffing attacks by encoding "<" and ">", so browsers
// won't try to execute the document as HTML even if they ignore

View file

@ -43,6 +43,7 @@ final class PhabricatorAuthSessionEngineExtensionModule
return id(new PHUIObjectBoxView())
->setHeaderText(pht('SessionEngine Extensions'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -41,6 +41,7 @@ final class PhabricatorAuthTemporaryTokenTypeModule
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Temporary Token Types'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -575,44 +575,4 @@ abstract class PhabricatorController extends AphrontController {
return $page->produceAphrontResponse();
}
/**
* DEPRECATED. Use @{method:newPage}.
*/
public function buildApplicationPage($view, array $options) {
$page = $this->newPage();
$title = PhabricatorEnv::getEnvConfig('phabricator.serious-business') ?
'Phabricator' :
pht('Bacon Ice Cream for Breakfast');
$page->setTitle(idx($options, 'title', $title));
if (idx($options, 'class')) {
$page->addClass($options['class']);
}
if (!($view instanceof AphrontSideNavFilterView)) {
$nav = new AphrontSideNavFilterView();
$nav->appendChild($view);
$view = $nav;
}
$page->appendChild($view);
$object_phids = idx($options, 'pageObjects', array());
if ($object_phids) {
$page->setPageObjectPHIDs($object_phids);
}
if (!idx($options, 'device', true)) {
$page->setDeviceReady(false);
}
$page->setShowFooter(idx($options, 'showFooter', true));
$page->setShowChrome(idx($options, 'chrome', true));
return $page->produceAphrontResponse();
}
}

View file

@ -232,11 +232,8 @@ EOFILE;
list($description, $metadata) = $parser->parse($matches[0]);
$provides = preg_split('/\s+/', trim(idx($metadata, 'provides')));
$requires = preg_split('/\s+/', trim(idx($metadata, 'requires')));
$provides = array_filter($provides);
$requires = array_filter($requires);
$provides = $this->parseResourceSymbolList(idx($metadata, 'provides'));
$requires = $this->parseResourceSymbolList(idx($metadata, 'requires'));
if (!$provides) {
// Tests and documentation-only JS is permitted to @provide no targets.
return array(null, null);
@ -364,4 +361,37 @@ EOFILE;
return $result;
}
private function parseResourceSymbolList($list) {
if (!$list) {
return array();
}
// This is valid:
//
// @requires x y
//
// But so is this:
//
// @requires x
// @requires y
//
// Accept either form and produce a list of symbols.
$list = (array)$list;
// We can get `true` values if there was a bare `@requires` in the input.
foreach ($list as $key => $item) {
if ($item === true) {
unset($list[$key]);
}
}
$list = implode(' ', $list);
$list = trim($list);
$list = preg_split('/\s+/', $list);
$list = array_filter($list);
return $list;
}
}

View file

@ -1,26 +0,0 @@
<?php
final class PhabricatorConduitConnectionLog extends PhabricatorConduitDAO {
protected $client;
protected $clientVersion;
protected $clientDescription;
protected $username;
protected function getConfiguration() {
return array(
self::CONFIG_COLUMN_SCHEMA => array(
'client' => 'text255?',
'clientVersion' => 'text255?',
'clientDescription' => 'text255?',
'username' => 'text255?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_created' => array(
'columns' => array('dateCreated'),
),
),
) + parent::getConfiguration();
}
}

View file

@ -38,10 +38,12 @@ final class PhabricatorConfigApplication extends PhabricatorApplication {
return array(
'/config/' => array(
'' => 'PhabricatorConfigListController',
'application/' => 'PhabricatorConfigApplicationController',
'all/' => 'PhabricatorConfigAllController',
'history/' => 'PhabricatorConfigHistoryController',
'edit/(?P<key>[\w\.\-]+)/' => 'PhabricatorConfigEditController',
'group/(?P<key>[^/]+)/' => 'PhabricatorConfigGroupController',
'version/' => 'PhabricatorConfigVersionController',
'welcome/' => 'PhabricatorConfigWelcomeController',
'database/'.
'(?:(?P<database>[^/]+)/'.

View file

@ -143,6 +143,9 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
'phabricator.auth-permanent',
'phabricator.application-id',
'phabricator.application-secret',
'maniphest.priorities.unbreak-now',
'maniphest.priorities.needs-triage',
'welcome.html',
);
$ancient_config = array_fill_keys($auth_config, $reason_auth);
@ -332,6 +335,19 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
'ui.custom-header' => pht(
'This option has been replaced with `ui.logo`, which provides more '.
'flexible configuration options.'),
'welcome.html' => pht(
'This option has been removed, you can use Dashboards to provide '.
'homepage customization. See T11533 for more details.'),
'maniphest.priorities.unbreak-now' => pht(
'This option has been removed, you can use Dashboards to provide '.
'homepage customization. See T11533 for more details.'),
'maniphest.priorities.needs-triage' => pht(
'This option has been removed, you can use Dashboards to provide '.
'homepage customization. See T11533 for more details.'),
);
return $ancient_config;

View file

@ -197,5 +197,53 @@ final class PhabricatorPHPConfigSetupCheck extends PhabricatorSetupCheck {
->setMessage($message);
}
}
if (empty($_SERVER['REMOTE_ADDR'])) {
$doc_href = PhabricatorEnv::getDocLink('Configuring a Preamble Script');
$summary = pht(
'You likely need to fix your preamble script so '.
'REMOTE_ADDR is no longer empty.');
$message = pht(
'No REMOTE_ADDR is available, so Phabricator cannot determine the '.
'origin address for requests. This will prevent Phabricator from '.
'performing important security checks. This most often means you '.
'have a mistake in your preamble script. Consult the documentation '.
'(%s) and double-check that the script is written correctly.',
phutil_tag(
'a',
array(
'href' => $doc_href,
'target' => '_blank',
),
pht('Configuring a Preamble Script')));
$this->newIssue('php.remote_addr')
->setName(pht('No REMOTE_ADDR available'))
->setSummary($summary)
->setMessage($message);
}
$raw_post_data = (int)ini_get('always_populate_raw_post_data');
if ($raw_post_data != -1) {
$summary = pht(
'PHP setting "%s" should be set to "-1" to avoid deprecation '.
'warnings.',
'always_populate_raw_post_data');
$message = pht(
'The "%s" key is set to some value other than "-1" in your PHP '.
'configuration. This can cause PHP to raise deprecation warnings '.
'during process startup. Set this option to "-1" to prevent these '.
'warnings from appearing.',
'always_populate_raw_post_data');
$this->newIssue('php.always_populate_raw_post_data')
->setName(pht('Disable PHP %s', 'always_populate_raw_post_data'))
->setSummary($summary)
->setMessage($message)
->addPHPConfig('always_populate_raw_post_data');
}
}
}

View file

@ -52,11 +52,13 @@ final class PhabricatorConfigAllController
$crumbs = $this
->buildApplicationCrumbs()
->addTextCrumb(pht('Configuration'), $this->getApplicationURI())
->addTextCrumb($title);
$panel = new PHUIObjectBoxView();
$panel->setHeaderText(pht('Current Settings'));
$panel->setTable($table);
$panel = id(new PHUIObjectBoxView())
->setHeaderText(pht('Current Settings'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
$nav = $this->buildSideNavView();
$nav->selectFilter('all/');

View file

@ -0,0 +1,58 @@
<?php
final class PhabricatorConfigApplicationController
extends PhabricatorConfigController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$nav = $this->buildSideNavView();
$nav->selectFilter('application/');
$groups = PhabricatorApplicationConfigOptions::loadAll();
$apps_list = $this->buildConfigOptionsList($groups, 'apps');
$title = pht('Application Configuration');
$apps = id(new PHUIObjectBoxView())
->setHeaderText($title)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($apps_list);
$crumbs = $this
->buildApplicationCrumbs()
->addTextCrumb(pht('Configuration'), $this->getApplicationURI())
->addTextCrumb(pht('Applications'));
$view = id(new PHUITwoColumnView())
->setNavigation($nav)
->setMainColumn(array(
$apps,
));
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
private function buildConfigOptionsList(array $groups, $type) {
assert_instances_of($groups, 'PhabricatorApplicationConfigOptions');
$list = new PHUIObjectItemListView();
$groups = msort($groups, 'getName');
foreach ($groups as $group) {
if ($group->getGroup() == $type) {
$item = id(new PHUIObjectItemView())
->setHeader($group->getName())
->setHref('/config/group/'.$group->getKey().'/')
->addAttribute($group->getDescription())
->setImageIcon($group->getIcon());
$list->addItem($item);
}
}
return $list;
}
}

View file

@ -51,6 +51,7 @@ final class PhabricatorConfigCacheController
return id(new PHUIObjectBoxView())
->setHeader($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->addPropertyList($properties);
}
@ -102,6 +103,7 @@ final class PhabricatorConfigCacheController
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Data Cache'))
->addPropertyList($properties)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -207,6 +207,7 @@ final class PhabricatorConfigClusterDatabasesController
return id(new PHUIObjectBoxView())
->setHeader($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -157,6 +157,7 @@ final class PhabricatorConfigClusterNotificationsController
return id(new PHUIObjectBoxView())
->setHeader($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -253,6 +253,7 @@ final class PhabricatorConfigClusterRepositoriesController
return id(new PHUIObjectBoxView())
->setHeader($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -12,11 +12,14 @@ abstract class PhabricatorConfigController extends PhabricatorController {
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
$nav->addLabel(pht('Configuration'));
$nav->addFilter('/', pht('Browse Settings'));
$nav->addFilter('all/', pht('All Settings'));
$nav->addFilter('/', pht('Core Settings'));
$nav->addFilter('application/', pht('Application Settings'));
$nav->addFilter('history/', pht('Settings History'));
$nav->addFilter('version/', pht('Version Information'));
$nav->addFilter('all/', pht('All Settings'));
$nav->addLabel(pht('Setup'));
$nav->addFilter('issue/', pht('Setup Issues'));
$nav->addFilter('welcome/', pht('Installation Guide'));
$nav->addLabel(pht('Database'));
$nav->addFilter('database/', pht('Database Status'));
$nav->addFilter('dbissue/', pht('Database Issues'));
@ -26,8 +29,6 @@ abstract class PhabricatorConfigController extends PhabricatorController {
$nav->addFilter('cluster/databases/', pht('Database Servers'));
$nav->addFilter('cluster/notifications/', pht('Notification Servers'));
$nav->addFilter('cluster/repositories/', pht('Repository Servers'));
$nav->addLabel(pht('Welcome'));
$nav->addFilter('welcome/', pht('Welcome Screen'));
$nav->addLabel(pht('Modules'));
$modules = PhabricatorConfigModule::getAllModules();

View file

@ -149,6 +149,7 @@ final class PhabricatorConfigDatabaseIssueController
$table_box = id(new PHUIObjectBoxView())
->setHeader($this->buildHeaderWithDocumentationLink($title))
->setFormErrors($errors)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
$nav = $this->buildSideNavView();

View file

@ -165,10 +165,12 @@ final class PhabricatorConfigDatabaseStatusController
$prop_box = id(new PHUIObjectBoxView())
->setHeader($this->buildHeaderWithDocumentationLink($title))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->addPropertyList($properties);
$table_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Databases'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
return $this->buildResponse($title, array($prop_box, $table_box));
@ -263,10 +265,12 @@ final class PhabricatorConfigDatabaseStatusController
$prop_box = id(new PHUIObjectBoxView())
->setHeader($this->buildHeaderWithDocumentationLink($title))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->addPropertyList($properties);
$table_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Database Status'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
return $this->buildResponse($title, array($prop_box, $table_box));
@ -476,14 +480,17 @@ final class PhabricatorConfigDatabaseStatusController
$prop_box = id(new PHUIObjectBoxView())
->setHeader($this->buildHeaderWithDocumentationLink($title))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->addPropertyList($properties);
$table_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Database'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table_view);
$key_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Keys'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($keys_view);
return $this->buildResponse($title, array($prop_box, $table_box, $key_box));
@ -620,6 +627,7 @@ final class PhabricatorConfigDatabaseStatusController
$box = id(new PHUIObjectBoxView())
->setHeader($this->buildHeaderWithDocumentationLink($title))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->addPropertyList($properties);
return $this->buildResponse($title, $box);
@ -713,6 +721,7 @@ final class PhabricatorConfigDatabaseStatusController
$box = id(new PHUIObjectBoxView())
->setHeader($this->buildHeaderWithDocumentationLink($title))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->addPropertyList($properties);
return $this->buildResponse($title, $box);

View file

@ -17,6 +17,7 @@ final class PhabricatorConfigGroupController
$list = $this->buildOptionList($options->getOptions());
$box = id(new PHUIObjectBoxView())
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($list);
$crumbs = $this

View file

@ -31,7 +31,7 @@ final class PhabricatorConfigHistoryController
$title = pht('Settings History');
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb('Config', $this->getApplicationURI());
$crumbs->addTextCrumb('Configuration', $this->getApplicationURI());
$crumbs->addTextCrumb($title, '/config/history/');
$nav = $this->buildSideNavView();

View file

@ -27,25 +27,28 @@ final class PhabricatorConfigIssueListController
if ($important) {
$setup_issues[] = id(new PHUIObjectBoxView())
->setHeaderText(pht('Important Setup Issues'))
->setColor(PHUIObjectBoxView::COLOR_RED)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($important);
}
if ($php) {
$setup_issues[] = id(new PHUIObjectBoxView())
->setHeaderText(pht('PHP Setup Issues'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($php);
}
if ($mysql) {
$setup_issues[] = id(new PHUIObjectBoxView())
->setHeaderText(pht('MySQL Setup Issues'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($mysql);
}
if ($other) {
$setup_issues[] = id(new PHUIObjectBoxView())
->setHeaderText(pht('Other Setup Issues'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($other);
}

View file

@ -11,27 +11,23 @@ final class PhabricatorConfigListController
$groups = PhabricatorApplicationConfigOptions::loadAll();
$core_list = $this->buildConfigOptionsList($groups, 'core');
$apps_list = $this->buildConfigOptionsList($groups, 'apps');
$title = pht('Phabricator Configuration');
$title = pht('Core Configuration');
$core = id(new PHUIObjectBoxView())
->setHeaderText($title)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($core_list);
$apps = id(new PHUIObjectBoxView())
->setHeaderText(pht('Applications Configuration'))
->setObjectList($apps_list);
$crumbs = $this
->buildApplicationCrumbs()
->addTextCrumb(pht('Config'), $this->getApplicationURI());
->addTextCrumb(pht('Configuration'), $this->getApplicationURI())
->addTextCrumb($title);
$view = id(new PHUITwoColumnView())
->setNavigation($nav)
->setMainColumn(array(
$core,
$apps,
));
return $this->newPage()

View file

@ -1,19 +1,37 @@
<?php
final class PhabricatorConfigVersionsModule
extends PhabricatorConfigModule {
final class PhabricatorConfigVersionController
extends PhabricatorConfigController {
public function getModuleKey() {
return 'versions';
}
public function getModuleName() {
return pht('Versions');
}
public function renderModuleStatus(AphrontRequest $request) {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$title = pht('Version Information');
$crumbs = $this
->buildApplicationCrumbs()
->addTextCrumb(pht('Configuration'), $this->getApplicationURI())
->addTextCrumb($title);
$versions = $this->renderModuleStatus($viewer);
$nav = $this->buildSideNavView();
$nav->selectFilter('version/');
$view = id(new PHUITwoColumnView())
->setNavigation($nav)
->setMainColumn(array(
$versions,
));
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
public function renderModuleStatus($viewer) {
$versions = $this->loadVersions($viewer);
$version_property_list = id(new PHUIPropertyListView());
@ -22,7 +40,8 @@ final class PhabricatorConfigVersionsModule
}
$object_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Current Versions'))
->setHeaderText(pht('Version Information'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->addPropertyList($version_property_list);
$phabricator_root = dirname(phutil_get_library_root('phabricator'));

View file

@ -9,11 +9,11 @@ final class PhabricatorConfigWelcomeController
$nav = $this->buildSideNavView();
$nav->selectFilter('welcome/');
$title = pht('Welcome');
$title = pht('Installation Guide');
$crumbs = $this
->buildApplicationCrumbs()
->addTextCrumb(pht('Welcome'));
->addTextCrumb($title);
$view = id(new PHUITwoColumnView())
->setNavigation($nav)

View file

@ -73,6 +73,7 @@ final class PhabricatorConfigCollectorsModule extends PhabricatorConfigModule {
return id(new PHUIObjectBoxView())
->setHeader($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -41,6 +41,7 @@ final class PhabricatorConfigEdgeModule extends PhabricatorConfigModule {
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Edge Types'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -21,6 +21,7 @@ final class PhabricatorConfigHTTPParameterTypesModule
return id(new PHUIObjectBoxView())
->setHeaderText(pht('HTTP Parameter Types'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -73,6 +73,7 @@ final class PhabricatorConfigPHIDModule extends PhabricatorConfigModule {
return id(new PHUIObjectBoxView())
->setHeaderText(pht('PHID Types'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -41,6 +41,7 @@ final class PhabricatorConfigRequestExceptionHandlerModule
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Exception Handlers'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -40,6 +40,7 @@ final class PhabricatorConfigSiteModule extends PhabricatorConfigModule {
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Sites'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -213,10 +213,6 @@ final class PhabricatorCoreConfigOptions
->setLocked(true)
->setDescription(
pht('Customized settings for Phabricator applications.')),
$this->newOption('welcome.html', 'string', null)
->setLocked(true)
->setDescription(
pht('Custom HTML to show on the main Phabricator dashboard.')),
$this->newOption('phabricator.cache-namespace', 'string', 'phabricator')
->setLocked(true)
->setDescription(pht('Cache namespace.')),

View file

@ -7,7 +7,6 @@ final class DifferentialRevisionListView extends AphrontView {
private $revisions;
private $handles;
private $highlightAge;
private $header;
private $noDataString;
private $noBox;
@ -39,11 +38,6 @@ final class DifferentialRevisionListView extends AphrontView {
return $this;
}
public function setHighlightAge($bool) {
$this->highlightAge = $bool;
return $this;
}
public function setNoBox($box) {
$this->noBox = $box;
return $this;

View file

@ -73,6 +73,38 @@ final class DiffusionCommitController extends DiffusionController {
$commit_data = $commit->getCommitData();
$is_foreign = $commit_data->getCommitDetail('foreign-svn-stub');
$error_panel = null;
$hard_limit = 1000;
if ($commit->isImported()) {
$change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
$drequest);
$change_query->setLimit($hard_limit + 1);
$changes = $change_query->loadChanges();
} else {
$changes = array();
}
$was_limited = (count($changes) > $hard_limit);
if ($was_limited) {
$changes = array_slice($changes, 0, $hard_limit);
}
$count = count($changes);
$is_unreadable = false;
$hint = null;
if (!$count || $commit->isUnreachable()) {
$hint = id(new DiffusionCommitHintQuery())
->setViewer($viewer)
->withRepositoryPHIDs(array($repository->getPHID()))
->withOldCommitIdentifiers(array($commit->getCommitIdentifier()))
->executeOne();
if ($hint) {
$is_unreadable = $hint->isUnreadable();
}
}
if ($is_foreign) {
$subpath = $commit_data->getCommitDetail('svn-subpath');
@ -130,9 +162,41 @@ final class DiffusionCommitController extends DiffusionController {
$message));
if ($commit->isUnreachable()) {
$this->commitErrors[] = pht(
'This commit has been deleted in the repository: it is no longer '.
'reachable from any branch, tag, or ref.');
$did_rewrite = false;
if ($hint) {
if ($hint->isRewritten()) {
$rewritten = id(new DiffusionCommitQuery())
->setViewer($viewer)
->withRepository($repository)
->withIdentifiers(array($hint->getNewCommitIdentifier()))
->executeOne();
if ($rewritten) {
$did_rewrite = true;
$rewritten_uri = $rewritten->getURI();
$rewritten_name = $rewritten->getLocalName();
$rewritten_link = phutil_tag(
'a',
array(
'href' => $rewritten_uri,
),
$rewritten_name);
$this->commitErrors[] = pht(
'This commit was rewritten after it was published, which '.
'changed the commit hash. This old version of the commit is '.
'no longer reachable from any branch, tag or ref. The new '.
'version of this commit is %s.',
$rewritten_link);
}
}
}
if (!$did_rewrite) {
$this->commitErrors[] = pht(
'This commit has been deleted in the repository: it is no longer '.
'reachable from any branch, tag, or ref.');
}
}
if ($this->getCommitErrors()) {
@ -143,47 +207,23 @@ final class DiffusionCommitController extends DiffusionController {
}
$timeline = $this->buildComments($commit);
$hard_limit = 1000;
if ($commit->isImported()) {
$change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
$drequest);
$change_query->setLimit($hard_limit + 1);
$changes = $change_query->loadChanges();
} else {
$changes = array();
}
$was_limited = (count($changes) > $hard_limit);
if ($was_limited) {
$changes = array_slice($changes, 0, $hard_limit);
}
$merge_table = $this->buildMergesTable($commit);
$highlighted_audits = $commit->getAuthorityAudits(
$viewer,
$this->auditAuthorityPHIDs);
$count = count($changes);
$bad_commit = null;
if ($count == 0) {
$bad_commit = queryfx_one(
id(new PhabricatorRepository())->establishConnection('r'),
'SELECT * FROM %T WHERE fullCommitName = %s',
PhabricatorRepository::TABLE_BADCOMMIT,
$commit->getMonogram());
}
$show_changesets = false;
$info_panel = null;
$change_list = null;
$change_table = null;
if ($bad_commit) {
if ($is_unreadable) {
$info_panel = $this->renderStatusMessage(
pht('Bad Commit'),
$bad_commit['description']);
pht('Unreadable Commit'),
pht(
'This commit has been marked as unreadable by an administrator. '.
'It may have been corrupted or created improperly by an external '.
'tool.'));
} else if ($is_foreign) {
// Don't render anything else.
} else if (!$commit->isImported()) {

View file

@ -0,0 +1,116 @@
<?php
final class DiffusionCommitHintQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $repositoryPHIDs;
private $oldCommitIdentifiers;
private $commits;
private $commitMap;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withRepositoryPHIDs(array $phids) {
$this->repositoryPHIDs = $phids;
return $this;
}
public function withOldCommitIdentifiers(array $identifiers) {
$this->oldCommitIdentifiers = $identifiers;
return $this;
}
public function withCommits(array $commits) {
assert_instances_of($commits, 'PhabricatorRepositoryCommit');
$repository_phids = array();
foreach ($commits as $commit) {
$repository_phids[] = $commit->getRepository()->getPHID();
}
$this->repositoryPHIDs = $repository_phids;
$this->oldCommitIdentifiers = mpull($commits, 'getCommitIdentifier');
$this->commits = $commits;
return $this;
}
public function getCommitMap() {
if ($this->commitMap === null) {
throw new PhutilInvalidStateException('execute');
}
return $this->commitMap;
}
public function newResultObject() {
return new PhabricatorRepositoryCommitHint();
}
protected function willExecute() {
$this->commitMap = array();
}
protected function loadPage() {
return $this->loadStandardPage($this->newResultObject());
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->oldCommitIdentifiers !== null) {
$where[] = qsprintf(
$conn,
'oldCommitIdentifier IN (%Ls)',
$this->oldCommitIdentifiers);
}
return $where;
}
protected function didFilterPage(array $hints) {
if ($this->commits) {
$map = array();
foreach ($this->commits as $commit) {
$repository_phid = $commit->getRepository()->getPHID();
$identifier = $commit->getCommitIdentifier();
$map[$repository_phid][$identifier] = $commit->getPHID();
}
foreach ($hints as $hint) {
$repository_phid = $hint->getRepositoryPHID();
$identifier = $hint->getOldCommitIdentifier();
if (isset($map[$repository_phid][$identifier])) {
$commit_phid = $map[$repository_phid][$identifier];
$this->commitMap[$commit_phid] = $hint;
}
}
}
return $hints;
}
public function getQueryApplicationClass() {
return 'PhabricatorDiffusionApplication';
}
}

View file

@ -14,6 +14,25 @@ final class DiffusionCommitRemarkupRule extends PhabricatorObjectRemarkupRule {
return PhabricatorRepositoryCommitPHIDType::getCommitObjectNamePattern();
}
protected function getObjectNameText(
$object,
PhabricatorObjectHandle $handle,
$id) {
// If this commit is unreachable, return the handle name instead of the
// normal text because it may be able to tell the user that the commit
// was rewritten and where to find the new one.
// By default, we try to preserve what the user actually typed as
// faithfully as possible, but if they're referencing a deleted commit
// it's more valuable to try to pick up any rewrite. See T11522.
if ($object->isUnreachable()) {
return $handle->getName();
}
return parent::getObjectNameText($object, $handle, $id);
}
protected function loadObjects(array $ids) {
$viewer = $this->getEngine()->getConfig('viewer');

View file

@ -2,8 +2,6 @@
final class PhabricatorHomeMainController extends PhabricatorHomeController {
private $minipanels = array();
public function shouldAllowPublic() {
return true;
}
@ -13,32 +11,27 @@ final class PhabricatorHomeMainController extends PhabricatorHomeController {
}
public function handleRequest(AphrontRequest $request) {
$user = $request->getUser();
$viewer = $request->getViewer();
$dashboard = PhabricatorDashboardInstall::getDashboard(
$user,
$user->getPHID(),
$viewer,
$viewer->getPHID(),
get_class($this->getCurrentApplication()));
if (!$dashboard) {
$dashboard = PhabricatorDashboardInstall::getDashboard(
$user,
$viewer,
PhabricatorHomeApplication::DASHBOARD_DEFAULT,
get_class($this->getCurrentApplication()));
}
if ($dashboard) {
$content = id(new PhabricatorDashboardRenderingEngine())
->setViewer($user)
->setViewer($viewer)
->setDashboard($dashboard)
->renderDashboard();
} else {
$project_query = new PhabricatorProjectQuery();
$project_query->setViewer($user);
$project_query->withMemberPHIDs(array($user->getPHID()));
$projects = $project_query->execute();
$content = $this->buildMainResponse($projects);
$content = $this->buildMainResponse();
}
if (!$request->getURIData('only')) {
@ -46,7 +39,7 @@ final class PhabricatorHomeMainController extends PhabricatorHomeController {
$nav->appendChild(
array(
$content,
id(new PhabricatorGlobalUploadTargetView())->setUser($user),
id(new PhabricatorGlobalUploadTargetView())->setUser($viewer),
));
$content = $nav;
}
@ -58,354 +51,180 @@ final class PhabricatorHomeMainController extends PhabricatorHomeController {
}
private function buildMainResponse(array $projects) {
assert_instances_of($projects, 'PhabricatorProject');
$viewer = $this->getRequest()->getUser();
private function buildMainResponse() {
require_celerity_resource('phabricator-dashboard-css');
$viewer = $this->getViewer();
$has_maniphest = PhabricatorApplication::isClassInstalledForViewer(
'PhabricatorManiphestApplication',
$viewer);
$has_audit = PhabricatorApplication::isClassInstalledForViewer(
'PhabricatorAuditApplication',
$has_diffusion = PhabricatorApplication::isClassInstalledForViewer(
'PhabricatorDiffusionApplication',
$viewer);
$has_differential = PhabricatorApplication::isClassInstalledForViewer(
'PhabricatorDifferentialApplication',
$viewer);
if ($has_maniphest) {
$unbreak_panel = $this->buildUnbreakNowPanel();
$triage_panel = $this->buildNeedsTriagePanel($projects);
$tasks_panel = $this->buildTasksPanel();
} else {
$unbreak_panel = null;
$triage_panel = null;
$tasks_panel = null;
}
if ($has_audit) {
$audit_panel = $this->buildAuditPanel();
$commit_panel = $this->buildCommitPanel();
} else {
$audit_panel = null;
$commit_panel = null;
}
if (PhabricatorEnv::getEnvConfig('welcome.html') !== null) {
$welcome_panel = $this->buildWelcomePanel();
} else {
$welcome_panel = null;
}
$revision_panel = null;
if ($has_differential) {
$revision_panel = $this->buildRevisionPanel();
} else {
$revision_panel = null;
}
$home = phutil_tag(
$tasks_panel = null;
if ($has_maniphest) {
$tasks_panel = $this->buildTasksPanel();
}
$repository_panel = null;
if ($has_diffusion) {
$repository_panel = $this->buildRepositoryPanel();
}
$feed_panel = $this->buildFeedPanel();
$dashboard = id(new AphrontMultiColumnView())
->setFluidlayout(true)
->setGutter(AphrontMultiColumnView::GUTTER_LARGE);
$main_panel = phutil_tag(
'div',
array(
'class' => 'homepage-panel',
),
array(
$welcome_panel,
$unbreak_panel,
$triage_panel,
$revision_panel,
$tasks_panel,
$audit_panel,
$commit_panel,
$this->minipanels,
$repository_panel,
));
return $home;
$dashboard->addColumn($main_panel, 'thirds');
$side_panel = phutil_tag(
'div',
array(
'class' => 'homepage-side-panel',
),
array(
$feed_panel,
));
$dashboard->addColumn($side_panel, 'third');
$view = id(new PHUIBoxView())
->addClass('dashboard-view')
->appendChild($dashboard);
return $view;
}
private function buildUnbreakNowPanel() {
$unbreak_now = PhabricatorEnv::getEnvConfig(
'maniphest.priorities.unbreak-now');
if (!$unbreak_now) {
return null;
}
$user = $this->getRequest()->getUser();
$task_query = id(new ManiphestTaskQuery())
->setViewer($user)
->withStatuses(ManiphestTaskStatus::getOpenStatusConstants())
->withPriorities(array($unbreak_now))
->needProjectPHIDs(true)
->setLimit(10);
$tasks = $task_query->execute();
if (!$tasks) {
return $this->renderMiniPanel(
pht('No "Unbreak Now!" Tasks'),
pht('Nothing appears to be critically broken right now.'));
}
$href = urisprintf(
'/maniphest/?statuses=open()&priorities=%s#R',
$unbreak_now);
$title = pht('Unbreak Now!');
$panel = new PHUIObjectBoxView();
$panel->setHeader($this->renderSectionHeader($title, $href));
$panel->setObjectList($this->buildTaskListView($tasks));
return $panel;
}
private function buildNeedsTriagePanel(array $projects) {
assert_instances_of($projects, 'PhabricatorProject');
$needs_triage = PhabricatorEnv::getEnvConfig(
'maniphest.priorities.needs-triage');
if (!$needs_triage) {
return null;
}
$user = $this->getRequest()->getUser();
if (!$user->isLoggedIn()) {
return null;
}
if ($projects) {
$task_query = id(new ManiphestTaskQuery())
->setViewer($user)
->withStatuses(ManiphestTaskStatus::getOpenStatusConstants())
->withPriorities(array($needs_triage))
->withEdgeLogicPHIDs(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
PhabricatorQueryConstraint::OPERATOR_OR,
mpull($projects, 'getPHID'))
->needProjectPHIDs(true)
->setLimit(10);
$tasks = $task_query->execute();
} else {
$tasks = array();
}
if (!$tasks) {
return $this->renderMiniPanel(
pht('No "Needs Triage" Tasks'),
pht('No tasks tagged with projects you are a member of need triage.'));
}
$title = pht('Needs Triage');
$href = urisprintf(
'/maniphest/?statuses=open()&priorities=%s&projects=projects(%s)#R',
$needs_triage,
$user->getPHID());
$panel = new PHUIObjectBoxView();
$panel->setHeader($this->renderSectionHeader($title, $href));
$panel->setObjectList($this->buildTaskListView($tasks));
return $panel;
}
private function buildRevisionPanel() {
$viewer = $this->getViewer();
$revisions = PhabricatorDifferentialApplication::loadNeedAttentionRevisions(
$viewer);
if (!$revisions) {
return $this->renderMiniPanel(
pht('No Waiting Revisions'),
pht('No revisions are waiting on you.'));
}
$title = pht('Revisions Waiting on You');
$href = '/differential/';
$panel = new PHUIObjectBoxView();
$panel->setHeader($this->renderSectionHeader($title, $href));
$revision_view = id(new DifferentialRevisionListView())
->setHighlightAge(true)
->setRevisions($revisions)
->setUser($viewer);
$phids = array_merge(
array($viewer->getPHID()),
$revision_view->getRequiredHandlePHIDs());
$handles = $this->loadViewerHandles($phids);
$revision_view->setHandles($handles);
$list_view = $revision_view->render();
$panel->setObjectList($list_view);
return $panel;
}
private function buildWelcomePanel() {
$panel = new PHUIObjectBoxView();
$panel->setHeaderText(pht('Welcome'));
$panel->appendChild(
phutil_safe_html(
PhabricatorEnv::getEnvConfig('welcome.html')));
return $panel;
}
private function buildTasksPanel() {
$user = $this->getRequest()->getUser();
$user_phid = $user->getPHID();
$task_query = id(new ManiphestTaskQuery())
->setViewer($user)
->withStatuses(ManiphestTaskStatus::getOpenStatusConstants())
->setGroupBy(ManiphestTaskQuery::GROUP_PRIORITY)
->withOwners(array($user_phid))
->needProjectPHIDs(true)
->setLimit(10);
$tasks = $task_query->execute();
if (!$tasks) {
return $this->renderMiniPanel(
pht('No Assigned Tasks'),
pht('You have no assigned tasks.'));
}
$title = pht('Assigned Tasks');
$href = '/maniphest/query/assigned/';
$panel = new PHUIObjectBoxView();
$panel->setHeader($this->renderSectionHeader($title, $href));
$panel->setObjectList($this->buildTaskListView($tasks));
return $panel;
}
private function buildTaskListView(array $tasks) {
assert_instances_of($tasks, 'ManiphestTask');
$user = $this->getRequest()->getUser();
$phids = array_merge(
array_filter(mpull($tasks, 'getOwnerPHID')),
array_mergev(mpull($tasks, 'getProjectPHIDs')));
$handles = $this->loadViewerHandles($phids);
$view = new ManiphestTaskListView();
$view->setTasks($tasks);
$view->setUser($user);
$view->setHandles($handles);
return $view;
}
private function renderSectionHeader($title, $href) {
private function buildHomepagePanel($title, $href, $view) {
$title = phutil_tag(
'a',
array(
'href' => $href,
),
$title);
$icon = id(new PHUIIconView())
->setIcon('fa-search')
->setHref($href);
$header = id(new PHUIHeaderView())
->setHeader($title)
->addActionItem($icon);
return $header;
}
private function renderMiniPanel($title, $body) {
$panel = new PHUIInfoView();
$panel->setSeverity(PHUIInfoView::SEVERITY_NODATA);
$panel->appendChild(
phutil_tag(
'p',
array(
),
array(
phutil_tag('strong', array(), $title.': '),
$body,
)));
$this->minipanels[] = $panel;
}
$box = id(new PHUIObjectBoxView())
->setHeader($header);
public function buildAuditPanel() {
$request = $this->getRequest();
$user = $request->getUser();
$phids = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
$query = id(new DiffusionCommitQuery())
->setViewer($user)
->withNeedsAuditByPHIDs($phids)
->withAuditStatus(DiffusionCommitQuery::AUDIT_STATUS_OPEN)
->needAuditRequests(true)
->needCommitData(true)
->setLimit(10);
$commits = $query->execute();
if (!$commits) {
return $this->renderMinipanel(
pht('No Audits'),
pht('No commits are waiting for you to audit them.'));
if ($view->getObjectList()) {
$box->setObjectList($view->getObjectList());
}
if ($view->getContent()) {
$box->appendChild($view->getContent());
}
$view = id(new PhabricatorAuditListView())
->setCommits($commits)
->setUser($user);
$phids = $view->getRequiredHandlePHIDs();
$handles = $this->loadViewerHandles($phids);
$view->setHandles($handles);
$title = pht('Audits');
$href = '/audit/';
$panel = new PHUIObjectBoxView();
$panel->setHeader($this->renderSectionHeader($title, $href));
$panel->setObjectList($view);
return $panel;
return $box;
}
public function buildCommitPanel() {
$request = $this->getRequest();
$user = $request->getUser();
$phids = array($user->getPHID());
$query = id(new DiffusionCommitQuery())
->setViewer($user)
->withAuthorPHIDs($phids)
->withAuditStatus(DiffusionCommitQuery::AUDIT_STATUS_CONCERN)
->needCommitData(true)
->needAuditRequests(true)
->setLimit(10);
$commits = $query->execute();
if (!$commits) {
return $this->renderMinipanel(
pht('No Problem Commits'),
pht('No one has raised concerns with your commits.'));
private function buildRevisionPanel() {
$viewer = $this->getViewer();
if (!$viewer->isLoggedIn()) {
return null;
}
$view = id(new PhabricatorAuditListView())
->setCommits($commits)
->setUser($user);
$engine = new DifferentialRevisionSearchEngine();
$engine->setViewer($viewer);
$saved = $engine->buildSavedQueryFromBuiltin('active');
$query = $engine->buildQueryFromSavedQuery($saved);
$pager = $engine->newPagerForSavedQuery($saved);
$pager->setPageSize(15);
$results = $engine->executeQuery($query, $pager);
$view = $engine->renderResults($results, $saved);
$phids = $view->getRequiredHandlePHIDs();
$handles = $this->loadViewerHandles($phids);
$view->setHandles($handles);
$title = pht('Active Revisions');
$href = '/differential/query/active/';
$title = pht('Problem Commits');
$href = '/audit/';
$panel = new PHUIObjectBoxView();
$panel->setHeader($this->renderSectionHeader($title, $href));
$panel->setObjectList($view);
return $this->buildHomepagePanel($title, $href, $view);
}
return $panel;
private function buildTasksPanel() {
$viewer = $this->getViewer();
$query = 'assigned';
$title = pht('Assigned Tasks');
$href = '/maniphest/query/assigned/';
if (!$viewer->isLoggedIn()) {
$query = 'open';
$title = pht('Open Tasks');
$href = '/maniphest/query/open/';
}
$engine = new ManiphestTaskSearchEngine();
$engine->setViewer($viewer);
$saved = $engine->buildSavedQueryFromBuiltin($query);
$query = $engine->buildQueryFromSavedQuery($saved);
$pager = $engine->newPagerForSavedQuery($saved);
$pager->setPageSize(15);
$results = $engine->executeQuery($query, $pager);
$view = $engine->renderResults($results, $saved);
return $this->buildHomepagePanel($title, $href, $view);
}
public function buildFeedPanel() {
$viewer = $this->getViewer();
$engine = new PhabricatorFeedSearchEngine();
$engine->setViewer($viewer);
$saved = $engine->buildSavedQueryFromBuiltin('all');
$query = $engine->buildQueryFromSavedQuery($saved);
$pager = $engine->newPagerForSavedQuery($saved);
$pager->setPageSize(40);
$results = $engine->executeQuery($query, $pager);
$view = $engine->renderResults($results, $saved);
$title = pht('Recent Activity');
$href = '/feed/';
return $this->buildHomepagePanel($title, $href, $view);
}
public function buildRepositoryPanel() {
$viewer = $this->getViewer();
$engine = new PhabricatorRepositorySearchEngine();
$engine->setViewer($viewer);
$saved = $engine->buildSavedQueryFromBuiltin('active');
$query = $engine->buildQueryFromSavedQuery($saved);
$pager = $engine->newPagerForSavedQuery($saved);
$pager->setPageSize(5);
$results = $engine->executeQuery($query, $pager);
$view = $engine->renderResults($results, $saved);
$title = pht('Active Repositories');
$href = '/diffusion/';
return $this->buildHomepagePanel($title, $href, $view);
}
}

View file

@ -356,28 +356,6 @@ EOTEXT
'string',
'[Maniphest]')
->setDescription(pht('Subject prefix for Maniphest mail.')),
$this->newOption(
'maniphest.priorities.unbreak-now',
'int',
100)
->setSummary(pht('Priority used to populate "Unbreak Now" on home.'))
->setDescription(
pht(
'Temporary setting. If set, this priority is used to populate the '.
'"Unbreak Now" panel on the home page. You should adjust this if '.
'you adjust priorities using `%s`.',
'maniphest.priorities')),
$this->newOption(
'maniphest.priorities.needs-triage',
'int',
90)
->setSummary(pht('Priority used to populate "Needs Triage" on home.'))
->setDescription(
pht(
'Temporary setting. If set, this priority is used to populate the '.
'"Needs Triage" panel on the home page. You should adjust this if '.
'you adjust priorities using `%s`.',
'maniphest.priorities')),
$this->newOption('maniphest.points', $points_type, array())
->setSummary(pht('Configure point values for tasks.'))
->setDescription($points_description)

View file

@ -41,7 +41,8 @@ final class ManiphestTaskResultListView extends ManiphestView {
// If we didn't match anything, just pick up the default empty state.
if (!$tasks) {
return id(new PHUIObjectItemListView())
->setUser($viewer);
->setUser($viewer)
->setNoDataString(pht('No tasks found.'));
}
$group_parameter = nonempty($query->getParameter('group'), 'priority');

View file

@ -38,7 +38,9 @@ final class PhabricatorApplicationDatasource
->setDisplayType($application->getShortDescription())
->setImageuRI($application->getIconURI())
->setPriorityType('apps')
->setImageSprite('phabricator-search-icon '.$img);
->setImageSprite('phabricator-search-icon '.$img)
->setIcon($application->getIcon())
->addAttribute($application->getShortDescription());
}
return $this->filterResultsAgainstTokens($results);

View file

@ -3,20 +3,12 @@
final class PhabricatorPeopleApproveController
extends PhabricatorPeopleController {
private $id;
public function willProcessRequest(array $data) {
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$admin = $request->getUser();
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$user = id(new PhabricatorPeopleQuery())
->setViewer($admin)
->withIDs(array($this->id))
->setViewer($viewer)
->withIDs(array($request->getURIData('id')))
->executeOne();
if (!$user) {
return new Aphront404Response();
@ -26,7 +18,7 @@ final class PhabricatorPeopleApproveController
if ($request->isFormPost()) {
id(new PhabricatorUserEditor())
->setActor($admin)
->setActor($viewer)
->approveUser($user, true);
$title = pht(
@ -39,12 +31,12 @@ final class PhabricatorPeopleApproveController
'Your Phabricator account (%s) has been approved by %s. You can '.
'login here:',
$user->getUsername(),
$admin->getUsername()),
$viewer->getUsername()),
PhabricatorEnv::getProductionURI('/'));
$mail = id(new PhabricatorMetaMTAMail())
->addTos(array($user->getPHID()))
->addCCs(array($admin->getPHID()))
->addCCs(array($viewer->getPHID()))
->setSubject('[Phabricator] '.$title)
->setForceDelivery(true)
->setBody($body)

View file

@ -3,8 +3,6 @@
final class PhabricatorPeopleListController
extends PhabricatorPeopleController {
private $key;
public function shouldAllowPublic() {
return true;
}
@ -13,16 +11,12 @@ final class PhabricatorPeopleListController
return false;
}
public function willProcessRequest(array $data) {
$this->key = idx($data, 'key');
}
public function processRequest() {
public function handleRequest(AphrontRequest $request) {
$this->requireApplicationCapability(
PeopleBrowseUserDirectoryCapability::CAPABILITY);
$controller = id(new PhabricatorApplicationSearchController())
->setQueryKey($this->key)
->setQueryKey($request->getURIData('key'))
->setSearchEngine(new PhabricatorPeopleSearchEngine())
->setNavigation($this->buildSideNavView());

View file

@ -3,15 +3,9 @@
final class PhabricatorPeopleLogsController
extends PhabricatorPeopleController {
private $queryKey;
public function willProcessRequest(array $data) {
$this->queryKey = idx($data, 'queryKey');
}
public function processRequest() {
$controller = id(new PhabricatorApplicationSearchController())
->setQueryKey($this->queryKey)
public function handleRequest(AphrontRequest $request) {
$controller = id(new PhabricatorApplicationSearchController())
->setQueryKey($request->getURIData('queryKey'))
->setSearchEngine(new PhabricatorPeopleLogSearchEngine())
->setNavigation($this->buildSideNavView());

View file

@ -108,7 +108,7 @@ final class PhabricatorUserLog extends PhabricatorUserDAO
$log->setUserPHID((string)$object_phid);
$log->setAction($action);
$log->remoteAddr = idx($_SERVER, 'REMOTE_ADDR', '');
$log->remoteAddr = (string)idx($_SERVER, 'REMOTE_ADDR', '');
return $log;
}

View file

@ -406,9 +406,17 @@ final class PhabricatorRepositoryDiscoveryEngine
$refs = array();
foreach ($commits as $commit) {
$epoch = $stream->getCommitDate($commit);
// If the epoch doesn't fit into a uint32, treat it as though it stores
// the current time. For discussion, see T11537.
if ($epoch > 0xFFFFFFFF) {
$epoch = PhabricatorTime::getNow();
}
$refs[] = id(new PhabricatorRepositoryCommitRef())
->setIdentifier($commit)
->setEpoch($stream->getCommitDate($commit))
->setEpoch($epoch)
->setCanCloseImmediately($close_immediately)
->setParents($stream->getParents($commit));
}

View file

@ -0,0 +1,97 @@
<?php
final class PhabricatorRepositoryManagementHintWorkflow
extends PhabricatorRepositoryManagementWorkflow {
protected function didConstruct() {
$this
->setName('hint')
->setExamples('**hint** [options] ...')
->setSynopsis(
pht(
'Write hints about unusual (rewritten or unreadable) commits.'))
->setArguments(array());
}
public function execute(PhutilArgumentParser $args) {
$viewer = $this->getViewer();
echo tsprintf(
"%s\n",
pht('Reading list of hints from stdin...'));
$hints = file_get_contents('php://stdin');
if ($hints === false) {
throw new PhutilArgumentUsageException(pht('Failed to read stdin.'));
}
try {
$hints = phutil_json_decode($hints);
} catch (Exception $ex) {
throw new PhutilArgumentUsageException(
pht(
'Expected a list of hints in JSON format: %s',
$ex->getMessage()));
}
$repositories = array();
foreach ($hints as $idx => $hint) {
if (!is_array($hint)) {
throw new PhutilArgumentUsageException(
pht(
'Each item in the list of hints should be a JSON object, but '.
'the item at index "%s" is not.',
$idx));
}
try {
PhutilTypeSpec::checkMap(
$hint,
array(
'repository' => 'string|int',
'old' => 'string',
'new' => 'optional string|null',
'hint' => 'string',
));
} catch (Exception $ex) {
throw new PhutilArgumentUsageException(
pht(
'Unexpected hint format at index "%s": %s',
$idx,
$ex->getMessage()));
}
$repository_identifier = $hint['repository'];
$repository = idx($repositories, $repository_identifier);
if (!$repository) {
$repository = id(new PhabricatorRepositoryQuery())
->setViewer($viewer)
->withIdentifiers(array($repository_identifier))
->executeOne();
if (!$repository) {
throw new PhutilArgumentUsageException(
pht(
'Repository identifier "%s" (in hint at index "%s") does not '.
'identify a valid repository.',
$repository_identifier,
$idx));
}
$repositories[$repository_identifier] = $repository;
}
PhabricatorRepositoryCommitHint::updateHint(
$repository->getPHID(),
$hint['old'],
idx($hint, 'new'),
$hint['hint']);
echo tsprintf(
"%s\n",
pht(
'Updated hint for "%s".',
$hint['old']));
}
}
}

View file

@ -29,12 +29,47 @@ final class PhabricatorRepositoryCommitPHIDType extends PhabricatorPHIDType {
array $handles,
array $objects) {
$unreachable = array();
foreach ($handles as $phid => $handle) {
$commit = $objects[$phid];
if ($commit->isUnreachable()) {
$unreachable[$phid] = $commit;
}
}
if ($unreachable) {
$query = id(new DiffusionCommitHintQuery())
->setViewer($query->getViewer())
->withCommits($unreachable);
$query->execute();
$hints = $query->getCommitMap();
} else {
$hints = array();
}
foreach ($handles as $phid => $handle) {
$commit = $objects[$phid];
$repository = $commit->getRepository();
$commit_identifier = $commit->getCommitIdentifier();
$name = $repository->formatCommitName($commit_identifier);
if ($commit->isUnreachable()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
// If we have a hint about this commit being rewritten, add the
// rewrite target to the handle name. This reduces the chance users
// will be caught offguard by the rewrite.
$hint = idx($hints, $phid);
if ($hint && $hint->isRewritten()) {
$new_name = $hint->getNewCommitIdentifier();
$new_name = $repository->formatCommitName($new_name);
$name = pht("%s \xE2\x99\xBB %s", $name, $new_name);
}
}
$summary = $commit->getSummary();
if (strlen($summary)) {
$full_name = $name.': '.$summary;
@ -46,10 +81,6 @@ final class PhabricatorRepositoryCommitPHIDType extends PhabricatorPHIDType {
$handle->setFullName($full_name);
$handle->setURI($commit->getURI());
$handle->setTimestamp($commit->getEpoch());
if ($commit->isUnreachable()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}

View file

@ -35,7 +35,6 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
const TABLE_PATHCHANGE = 'repository_pathchange';
const TABLE_FILESYSTEM = 'repository_filesystem';
const TABLE_SUMMARY = 'repository_summary';
const TABLE_BADCOMMIT = 'repository_badcommit';
const TABLE_LINTMESSAGE = 'repository_lintmessage';
const TABLE_PARENTS = 'repository_parents';
const TABLE_COVERAGE = 'repository_coverage';

View file

@ -0,0 +1,137 @@
<?php
final class PhabricatorRepositoryCommitHint
extends PhabricatorRepositoryDAO
implements PhabricatorPolicyInterface {
protected $repositoryPHID;
protected $oldCommitIdentifier;
protected $newCommitIdentifier;
protected $hintType;
const HINT_NONE = 'none';
const HINT_REWRITTEN = 'rewritten';
const HINT_UNREADABLE = 'unreadable';
protected function getConfiguration() {
return array(
self::CONFIG_TIMESTAMPS => false,
self::CONFIG_COLUMN_SCHEMA => array(
'oldCommitIdentifier' => 'text40',
'newCommitIdentifier' => 'text40?',
'hintType' => 'text32',
),
self::CONFIG_KEY_SCHEMA => array(
'key_old' => array(
'columns' => array('repositoryPHID', 'oldCommitIdentifier'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public static function getAllHintTypes() {
return array(
self::HINT_NONE,
self::HINT_REWRITTEN,
self::HINT_UNREADABLE,
);
}
public static function updateHint($repository_phid, $old, $new, $type) {
switch ($type) {
case self::HINT_NONE:
break;
case self::HINT_REWRITTEN:
if (!$new) {
throw new Exception(
pht(
'When hinting a commit ("%s") as rewritten, you must provide '.
'the commit it was rewritten into.',
$old));
}
break;
case self::HINT_UNREADABLE:
if ($new) {
throw new Exception(
pht(
'When hinting a commit ("%s") as unreadable, you must not '.
'provide a new commit ("%s").',
$old,
$new));
}
break;
default:
$all_types = self::getAllHintTypes();
throw new Exception(
pht(
'Hint type ("%s") for commit ("%s") is not valid. Valid hints '.
'are: %s.',
$type,
$old,
implode(', ', $all_types)));
}
$table = new self();
$table_name = $table->getTableName();
$conn = $table->establishConnection('w');
if ($type == self::HINT_NONE) {
queryfx(
$conn,
'DELETE FROM %T WHERE repositoryPHID = %s AND oldCommitIdentifier = %s',
$table_name,
$repository_phid,
$old);
} else {
queryfx(
$conn,
'INSERT INTO %T
(repositoryPHID, oldCommitIdentifier, newCommitIdentifier, hintType)
VALUES (%s, %s, %ns, %s)
ON DUPLICATE KEY UPDATE
newCommitIdentifier = VALUES(newCommitIdentifier),
hintType = VALUES(hintType)',
$table_name,
$repository_phid,
$old,
$new,
$type);
}
}
public function isUnreadable() {
return ($this->getHintType() == self::HINT_UNREADABLE);
}
public function isRewritten() {
return ($this->getHintType() == self::HINT_REWRITTEN);
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return PhabricatorPolicies::getMostOpenPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
public function describeAutomaticCapability($capability) {
return null;
}
}

View file

@ -6,20 +6,6 @@ final class PhabricatorRepositorySchemaSpec
public function buildSchemata() {
$this->buildEdgeSchemata(new PhabricatorRepository());
$this->buildRawSchema(
id(new PhabricatorRepository())->getApplicationName(),
PhabricatorRepository::TABLE_BADCOMMIT,
array(
'fullCommitName' => 'text64',
'description' => 'text',
),
array(
'PRIMARY' => array(
'columns' => array('fullCommitName'),
'unique' => true,
),
));
$this->buildRawSchema(
id(new PhabricatorRepository())->getApplicationName(),
PhabricatorRepository::TABLE_COVERAGE,

View file

@ -95,16 +95,16 @@ abstract class PhabricatorRepositoryCommitParserWorker
PhabricatorRepository $repository,
PhabricatorRepositoryCommit $commit);
protected function isBadCommit(PhabricatorRepositoryCommit $commit) {
$repository = new PhabricatorRepository();
protected function loadCommitHint(PhabricatorRepositoryCommit $commit) {
$viewer = PhabricatorUser::getOmnipotentUser();
$bad_commit = queryfx_one(
$repository->establishConnection('w'),
'SELECT * FROM %T WHERE fullCommitName = %s',
PhabricatorRepository::TABLE_BADCOMMIT,
$commit->getMonogram());
$repository = $commit->getRepository();
return (bool)$bad_commit;
return id(new DiffusionCommitHintQuery())
->setViewer($viewer)
->withRepositoryPHIDs(array($repository->getPHID()))
->withOldCommitIdentifiers(array($commit->getCommitIdentifier()))
->executeOne();
}
public function renderForDisplay(PhabricatorUser $viewer) {

View file

@ -22,8 +22,13 @@ abstract class PhabricatorRepositoryCommitChangeParserWorker
PhabricatorRepositoryCommit $commit) {
$this->log("%s\n", pht('Parsing "%s"...', $commit->getMonogram()));
if ($this->isBadCommit($commit)) {
$this->log(pht('This commit is marked bad!'));
$hint = $this->loadCommitHint($commit);
if ($hint && $hint->isUnreadable()) {
$this->log(
pht(
'This commit is marked as unreadable, so changes will not be '.
'parsed.'));
return;
}

View file

@ -49,6 +49,7 @@ final class PhabricatorHovercardEngineExtensionModule
return id(new PHUIObjectBoxView())
->setHeaderText(pht('HovercardEngine Extensions'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -49,6 +49,7 @@ final class PhabricatorSearchEngineExtensionModule
return id(new PHUIObjectBoxView())
->setHeaderText(pht('SearchEngine Extensions'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -38,6 +38,7 @@ final class PhabricatorFulltextEngineExtensionModule
return id(new PHUIObjectBoxView())
->setHeaderText(pht('FulltextEngine Extensions'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -38,6 +38,7 @@ final class PhabricatorIndexEngineExtensionModule
return id(new PHUIObjectBoxView())
->setHeaderText(pht('IndexEngine Extensions'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -143,7 +143,8 @@ final class PhabricatorMotivatorProfilePanel
pht(
'Cats will often bring you their prey because they feel sorry '.
'for your inability to hunt.'),
);
pht('Cats spend most of their time plotting to kill their owner.'),
);
}
private function selectFact(array $facts) {

View file

@ -25,20 +25,30 @@ final class PhabricatorSearchDocumentTypeDatasource
}
private function buildResults() {
$viewer = $this->getViewer();
$types =
PhabricatorSearchApplicationSearchEngine::getIndexableDocumentTypes();
PhabricatorSearchApplicationSearchEngine::getIndexableDocumentTypes(
$viewer);
$icons = mpull(
PhabricatorPHIDType::getAllTypes(),
'getTypeIcon',
$phid_types = mpull(PhabricatorPHIDType::getAllTypes(),
null,
'getTypeConstant');
$results = array();
foreach ($types as $type => $name) {
$type_object = idx($phid_types, $type);
if (!$type_object) {
continue;
}
$application_class = $type_object->getPHIDTypeApplicationClass();
$application = PhabricatorApplication::getByClass($application_class);
$application_name = $application->getName();
$results[$type] = id(new PhabricatorTypeaheadResult())
->setPHID($type)
->setName($name)
->setIcon(idx($icons, $type));
->addAttribute($application_name)
->setIcon($type_object->getTypeIcon());
}
return $results;

View file

@ -165,6 +165,11 @@ final class PhabricatorEmailAddressesSettingsPanel
$user = $this->getUser();
$viewer = $this->getViewer();
$token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
$viewer,
$request,
$this->getPanelURI());
$e_email = true;
$email = null;
$errors = array();
@ -276,6 +281,11 @@ final class PhabricatorEmailAddressesSettingsPanel
$user = $this->getUser();
$viewer = $this->getViewer();
$token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
$viewer,
$request,
$this->getPanelURI());
// NOTE: You can only delete your own email addresses, and you can not
// delete your primary address.
$email = id(new PhabricatorUserEmail())->loadOneWhere(

View file

@ -67,7 +67,19 @@ final class PhabricatorHomePreferencesSettingsPanel
unset($options['PhabricatorApplicationsApplication']);
if ($request->isFormPost()) {
$pin = $request->getStr('pin');
$pins = $request->getArr('pin');
$phid = head($pins);
$app = id(new PhabricatorApplicationQuery())
->setViewer($viewer)
->withPHIDs(array($phid))
->executeOne();
if ($app) {
$pin = get_class($app);
} else {
// This likely means the user submitted an empty form
// which will cause nothing to happen.
$pin = '';
}
if (isset($options[$pin]) && !in_array($pin, $pinned)) {
$pinned[] = $pin;
@ -78,18 +90,18 @@ final class PhabricatorHomePreferencesSettingsPanel
}
}
$options_control = id(new AphrontFormSelectControl())
$options_control = id(new AphrontFormTokenizerControl())
->setName('pin')
->setLabel(pht('Application'))
->setOptions($options)
->setDisabledOptions(array_keys($app_list));
->setDatasource(new PhabricatorApplicationDatasource())
->setLimit(1);
$form = id(new AphrontFormView())
->setViewer($viewer)
->addHiddenInput('add', 'true')
->appendRemarkupInstructions(
pht('Choose an application to pin to your home page.'))
->appendChild($options_control);
->appendControl($options_control);
return $this->newDialog()
->setWidth(AphrontDialogView::WIDTH_FORM)
@ -152,20 +164,12 @@ final class PhabricatorHomePreferencesSettingsPanel
$icon = $application->getIcon();
if (!$icon) {
$icon = 'application';
$icon = 'fa-globe';
}
$icon_view = javelin_tag(
'span',
array(
'class' => 'phui-icon-view phui-font-fa '.$icon,
'aural' => false,
),
'');
$item = id(new PHUIObjectItemView())
->setHeader($application->getName())
->setImageIcon($icon_view)
->setImageIcon($icon)
->addAttribute($application->getShortDescription())
->setGrippable(true);

View file

@ -38,6 +38,7 @@ final class PhabricatorDestructionEngineExtensionModule
return id(new PHUIObjectBoxView())
->setHeaderText(pht('DestructionEngine Extensions'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -46,6 +46,7 @@ final class PhabricatorEditEngineExtensionModule
return id(new PHUIObjectBoxView())
->setHeaderText(pht('EditEngine Extensions'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -2,26 +2,4 @@
abstract class PhabricatorXHProfController extends PhabricatorController {
public function buildStandardPageResponse($view, array $data) {
$page = $this->buildStandardPageView();
$page->setApplicationName(pht('XHProf'));
$page->setBaseURI('/xhprof/');
$page->setTitle(idx($data, 'title'));
$page->setGlyph("\xE2\x98\x84");
$page->appendChild($view);
$page->setDeviceReady(true);
$response = new AphrontWebpageResponse();
if (isset($data['frame'])) {
$response->setFrameable(true);
$page->setFrameable(true);
$page->setShowChrome(false);
$page->setDisableConsole(true);
}
return $response->setContent($page->render());
}
}

View file

@ -47,11 +47,14 @@ final class PhabricatorXHProfProfileController
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('%s Profile', $symbol));
return $this->buildStandardPageResponse(
array($crumbs, $view),
array(
'title' => pht('Profile'),
'frame' => $is_framed,
));
$title = pht('Profile');
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->setFrameable(true)
->setShowChrome(false)
->setDisableConsole(true)
->appendChild($view);
}
}

View file

@ -32,7 +32,7 @@ These are the configuration values it reads:
- `join` Array, list of channels to join.
- `handlers` Array, list of handlers to run. These are like plugins for the
bot.
- `conduit.uri`, `conduit.user`, `conduit.cert` Conduit configuration,
- `conduit.uri`, `conduit.token` Conduit configuration,
see below.
- `notification.channels` Notification configuration, see below.
@ -72,10 +72,8 @@ with. To do this, login to Phabricator as an administrator and go to
- `conduit.uri` The URI for your Phabricator install, like
`http://phabricator.example.com/`
- `conduit.user` The username your bot should login to Phabricator with --
whatever you selected above, like `phabot`.
- `conduit.cert` The user's certificate, from the "Conduit Certificate" tab
in the user's administrative view.
- `conduit.token` The user's conduit API token, from the "Conduit API Tokens"
tab in the user's administrative view.
Now the bot should be able to connect to Phabricator via Conduit.

View file

@ -0,0 +1,134 @@
@title Repository Hints and Rewriting Commits
@group fieldmanual
Dealing with rewrites of published repositories and other unusual problems.
Overview
========
Some repositories have unusual commits. You can provide "hints" to Phabricator
about these commits to improve behavior.
Supported hints are:
- **Rewritten Commits**: If you have rewritten the history of a published
repository, you can provide hints about the mapping from old commits to
new commits so it can redirect users who visit old pages to the proper
new pages.
- **Unreadable Commits**: If some commits are not readable (which is rare,
but can happen in some cases if they are generated with an external tool)
you can provide hints so that Phabricator doesn't try to read them.
The remainder of this document explains how to create and remove hints, and how
to specify each type of hint.
Creating Hints
==============
To create hints, pipe a JSON list of hints to `bin/repository hint`:
```
phabricator/ $ cat hints.json | ./bin/repository hint
```
The hints should be a list of objects like this:
```lang=json
[
...
{
"repository": "XYZ",
"hint": "...",
"old": "abcdef1234abcdef1234abcdef1234abcdef1234",
"new": "..."
}
...
]
```
Each hint may have these keys:
- `repository`: A repository identifier (ID, PHID, callsign or short name).
- `hint`: The hint type, see below.
- `old`: The full identifier or commit hash of the commit you want to
provide a hint for.
- `new`: For hints which specify a new commit, the full identifier or commit
hash of the new commit.
See below for exactly how to specify each type of hint.
Removing Hints
==============
To remove a hint, create a hint of type `"none"`. This will remove any existing
hint.
For example, use a hint specification like this:
```lang=json
[
{
"repository": "XYZ",
"hint": "none",
"old": "abcdef1234abcdef1234abcdef1234abcdef1234"
}
]
```
Phabricator won't treat commits without any hint specially.
Hint: Rewritten Commits
=======================
The `"rewritten"` hint allows you to redirect old commits to new commits after
a rewrite of published history. You should normally avoid rewriting published
commits, but sometimes this is necessary: for example, if a repository has
become unwieldy because it contains large binaries, you may strip them from
history.
To provide this kind of hint, pass the `"old"` commit hash (from before the
rewrite) and the `"new"` commit hash (from after the rewrite).
For example, a hint might look like this:
```lang=json
[
{
"repository": "XYZ",
"hint": "rewritten",
"old": "abcdef1234abcdef1234abcdef1234abcdef1234",
"new": "098765ffaabbccdd4680098765ffaabbccdd4680"
}
]
```
Phabricator will show users that the commit was rewritten in the web UI.
Hint: Unreadable Commits
========================
The `"unreadable"` hint allows you to tell Phabricator that it should not
bother trying to read the changes associated with a particular commit. In
some rare cases, repositories can contain commits which aren't readable
(for example, if they were created by external tools during an import or
merge process).
To provide this kind of hint, pass the `"old"` commit which is affected.
For example, a hint might look like this:
```lang=json
[
{
"repository": "XYZ",
"hint": "unreadable",
"old": "abcdef1234abcdef1234abcdef1234abcdef1234"
}
]
```
Phabricator won't try to read, parse, import, or display the changes associated
with this commit.

View file

@ -45,6 +45,7 @@ final class PhabricatorContentSourceModule
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Content Sources'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}

View file

@ -159,11 +159,10 @@ final class PhabricatorBot extends PhabricatorDaemon {
if (empty($this->conduit)) {
throw new Exception(
pht(
"This bot is not configured with a Conduit uplink. Set '%s', ".
"'%s' and '%s' in the configuration to connect.",
"This bot is not configured with a Conduit uplink. Set '%s' and ".
"'%s' in the configuration to connect.",
'conduit.uri',
'conduit.user',
'conduit.cert'));
'conduit.token'));
}
return $this->conduit;
}

View file

@ -50,8 +50,14 @@ final class PhabricatorBotObjectNameHandler extends PhabricatorBotHandler {
'(?:\b|$)'.
'@';
$regex = trim(
PhabricatorEnv::getEnvConfig('remarkup.ignored-object-names'));
if (preg_match_all($pattern, $message, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
if ($regex && preg_match($regex, $match[0])) {
continue;
}
switch ($match[1]) {
case 'P':
$paste_ids[] = $match[2];

View file

@ -25,6 +25,13 @@ abstract class PhabricatorObjectRemarkupRule extends PhutilRemarkupRule {
return true;
}
protected function getObjectNameText(
$object,
PhabricatorObjectHandle $handle,
$id) {
return $this->getObjectNamePrefix().$id;
}
protected function loadHandles(array $objects) {
$phids = mpull($objects, 'getPHID');
@ -60,7 +67,7 @@ abstract class PhabricatorObjectRemarkupRule extends PhutilRemarkupRule {
$id) {
$href = $this->getObjectHref($object, $handle, $id);
$text = $this->getObjectNamePrefix().$id;
$text = $this->getObjectNameText($object, $handle, $id);
if ($anchor) {
$href = $href.'#'.$anchor;
@ -85,7 +92,7 @@ abstract class PhabricatorObjectRemarkupRule extends PhutilRemarkupRule {
$id) {
$href = $this->getObjectHref($object, $handle, $id);
$text = $this->getObjectNamePrefix().$id;
$text = $this->getObjectNameText($object, $handle, $id);
$status_closed = PhabricatorObjectHandle::STATUS_CLOSED;
if ($anchor) {

View file

@ -890,7 +890,8 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView
} else {
$content = $this->render();
$response = id(new AphrontWebpageResponse())
->setContent($content);
->setContent($content)
->setFrameable($this->getFrameable());
}
return $response;

View file

@ -38,6 +38,7 @@
.setup-issue table td {
border: 1px solid #BFCFDA;
padding: 8px;
word-break: break-word;
}
.setup-issue pre {