1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-15 10:00:55 +01:00

(stable) Promote 2017 Week 7

This commit is contained in:
epriestley 2017-02-17 17:42:05 -08:00
commit d963227c83
170 changed files with 1552 additions and 894 deletions

View file

@ -2027,8 +2027,10 @@ phutil_register_library_map(array(
'PhabricatorBadgesListController' => 'applications/badges/controller/PhabricatorBadgesListController.php',
'PhabricatorBadgesMailReceiver' => 'applications/badges/mail/PhabricatorBadgesMailReceiver.php',
'PhabricatorBadgesPHIDType' => 'applications/badges/phid/PhabricatorBadgesPHIDType.php',
'PhabricatorBadgesProfileController' => 'applications/badges/controller/PhabricatorBadgesProfileController.php',
'PhabricatorBadgesQuality' => 'applications/badges/constants/PhabricatorBadgesQuality.php',
'PhabricatorBadgesQuery' => 'applications/badges/query/PhabricatorBadgesQuery.php',
'PhabricatorBadgesRecipientsController' => 'applications/badges/controller/PhabricatorBadgesRecipientsController.php',
'PhabricatorBadgesRecipientsListView' => 'applications/badges/view/PhabricatorBadgesRecipientsListView.php',
'PhabricatorBadgesRemoveRecipientsController' => 'applications/badges/controller/PhabricatorBadgesRemoveRecipientsController.php',
'PhabricatorBadgesReplyHandler' => 'applications/badges/mail/PhabricatorBadgesReplyHandler.php',
@ -2464,8 +2466,8 @@ phutil_register_library_map(array(
'PhabricatorDashboardAddPanelController' => 'applications/dashboard/controller/PhabricatorDashboardAddPanelController.php',
'PhabricatorDashboardApplication' => 'applications/dashboard/application/PhabricatorDashboardApplication.php',
'PhabricatorDashboardArchiveController' => 'applications/dashboard/controller/PhabricatorDashboardArchiveController.php',
'PhabricatorDashboardArrangeController' => 'applications/dashboard/controller/PhabricatorDashboardArrangeController.php',
'PhabricatorDashboardController' => 'applications/dashboard/controller/PhabricatorDashboardController.php',
'PhabricatorDashboardCopyController' => 'applications/dashboard/controller/PhabricatorDashboardCopyController.php',
'PhabricatorDashboardDAO' => 'applications/dashboard/storage/PhabricatorDashboardDAO.php',
'PhabricatorDashboardDashboardHasPanelEdgeType' => 'applications/dashboard/edge/PhabricatorDashboardDashboardHasPanelEdgeType.php',
'PhabricatorDashboardDashboardPHIDType' => 'applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php',
@ -2503,6 +2505,7 @@ phutil_register_library_map(array(
'PhabricatorDashboardPanelTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelTransactionQuery.php',
'PhabricatorDashboardPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardPanelType.php',
'PhabricatorDashboardPanelViewController' => 'applications/dashboard/controller/PhabricatorDashboardPanelViewController.php',
'PhabricatorDashboardProfileController' => 'applications/dashboard/controller/PhabricatorDashboardProfileController.php',
'PhabricatorDashboardProfileMenuItem' => 'applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php',
'PhabricatorDashboardQuery' => 'applications/dashboard/query/PhabricatorDashboardQuery.php',
'PhabricatorDashboardQueryPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardQueryPanelType.php',
@ -2516,7 +2519,6 @@ phutil_register_library_map(array(
'PhabricatorDashboardTransaction' => 'applications/dashboard/storage/PhabricatorDashboardTransaction.php',
'PhabricatorDashboardTransactionEditor' => 'applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php',
'PhabricatorDashboardTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardTransactionQuery.php',
'PhabricatorDashboardUninstallController' => 'applications/dashboard/controller/PhabricatorDashboardUninstallController.php',
'PhabricatorDashboardViewController' => 'applications/dashboard/controller/PhabricatorDashboardViewController.php',
'PhabricatorDataCacheSpec' => 'applications/cache/spec/PhabricatorDataCacheSpec.php',
'PhabricatorDataNotAttachedException' => 'infrastructure/storage/lisk/PhabricatorDataNotAttachedException.php',
@ -2947,6 +2949,7 @@ phutil_register_library_map(array(
'PhabricatorMailManagementSendTestWorkflow' => 'applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php',
'PhabricatorMailManagementShowInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementShowInboundWorkflow.php',
'PhabricatorMailManagementShowOutboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementShowOutboundWorkflow.php',
'PhabricatorMailManagementUnverifyWorkflow' => 'applications/metamta/management/PhabricatorMailManagementUnverifyWorkflow.php',
'PhabricatorMailManagementVolumeWorkflow' => 'applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php',
'PhabricatorMailManagementWorkflow' => 'applications/metamta/management/PhabricatorMailManagementWorkflow.php',
'PhabricatorMailOutboundMailHeraldAdapter' => 'applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php',
@ -3029,6 +3032,7 @@ phutil_register_library_map(array(
'PhabricatorModularTransactionType' => 'applications/transactions/storage/PhabricatorModularTransactionType.php',
'PhabricatorMonospacedFontSetting' => 'applications/settings/setting/PhabricatorMonospacedFontSetting.php',
'PhabricatorMonospacedTextareasSetting' => 'applications/settings/setting/PhabricatorMonospacedTextareasSetting.php',
'PhabricatorMotivatorProfileMenuItem' => 'applications/search/menuitem/PhabricatorMotivatorProfileMenuItem.php',
'PhabricatorMultiColumnUIExample' => 'applications/uiexample/examples/PhabricatorMultiColumnUIExample.php',
'PhabricatorMultiFactorSettingsPanel' => 'applications/settings/panel/PhabricatorMultiFactorSettingsPanel.php',
'PhabricatorMultimeterApplication' => 'applications/multimeter/application/PhabricatorMultimeterApplication.php',
@ -3368,6 +3372,7 @@ phutil_register_library_map(array(
'PhabricatorPhurlURLAccessController' => 'applications/phurl/controller/PhabricatorPhurlURLAccessController.php',
'PhabricatorPhurlURLCommentController' => 'applications/phurl/controller/PhabricatorPhurlURLCommentController.php',
'PhabricatorPhurlURLCreateCapability' => 'applications/phurl/capability/PhabricatorPhurlURLCreateCapability.php',
'PhabricatorPhurlURLDatasource' => 'applications/phurl/typeahead/PhabricatorPhurlURLDatasource.php',
'PhabricatorPhurlURLEditConduitAPIMethod' => 'applications/phurl/conduit/PhabricatorPhurlURLEditConduitAPIMethod.php',
'PhabricatorPhurlURLEditController' => 'applications/phurl/controller/PhabricatorPhurlURLEditController.php',
'PhabricatorPhurlURLEditEngine' => 'applications/phurl/editor/PhabricatorPhurlURLEditEngine.php',
@ -3770,6 +3775,7 @@ phutil_register_library_map(array(
'PhabricatorSettingsDeveloperPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsDeveloperPanelGroup.php',
'PhabricatorSettingsEditEngine' => 'applications/settings/editor/PhabricatorSettingsEditEngine.php',
'PhabricatorSettingsEmailPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsEmailPanelGroup.php',
'PhabricatorSettingsIssueController' => 'applications/settings/controller/PhabricatorSettingsIssueController.php',
'PhabricatorSettingsListController' => 'applications/settings/controller/PhabricatorSettingsListController.php',
'PhabricatorSettingsLogsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsLogsPanelGroup.php',
'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php',
@ -6938,7 +6944,6 @@ phutil_register_library_map(array(
'PhabricatorPolicyInterface',
'PhabricatorApplicationTransactionInterface',
'PhabricatorSubscribableInterface',
'PhabricatorTokenReceiverInterface',
'PhabricatorFlaggableInterface',
'PhabricatorDestructibleInterface',
'PhabricatorConduitResultInterface',
@ -6960,8 +6965,10 @@ phutil_register_library_map(array(
'PhabricatorBadgesListController' => 'PhabricatorBadgesController',
'PhabricatorBadgesMailReceiver' => 'PhabricatorObjectMailReceiver',
'PhabricatorBadgesPHIDType' => 'PhabricatorPHIDType',
'PhabricatorBadgesProfileController' => 'PhabricatorController',
'PhabricatorBadgesQuality' => 'Phobject',
'PhabricatorBadgesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorBadgesRecipientsController' => 'PhabricatorBadgesProfileController',
'PhabricatorBadgesRecipientsListView' => 'AphrontView',
'PhabricatorBadgesRemoveRecipientsController' => 'PhabricatorBadgesController',
'PhabricatorBadgesReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
@ -6971,7 +6978,7 @@ phutil_register_library_map(array(
'PhabricatorBadgesTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorBadgesTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PhabricatorBadgesTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorBadgesViewController' => 'PhabricatorBadgesController',
'PhabricatorBadgesViewController' => 'PhabricatorBadgesProfileController',
'PhabricatorBarePageUIExample' => 'PhabricatorUIExample',
'PhabricatorBarePageView' => 'AphrontPageView',
'PhabricatorBaseURISetupCheck' => 'PhabricatorSetupCheck',
@ -7470,8 +7477,8 @@ phutil_register_library_map(array(
'PhabricatorDashboardAddPanelController' => 'PhabricatorDashboardController',
'PhabricatorDashboardApplication' => 'PhabricatorApplication',
'PhabricatorDashboardArchiveController' => 'PhabricatorDashboardController',
'PhabricatorDashboardArrangeController' => 'PhabricatorDashboardProfileController',
'PhabricatorDashboardController' => 'PhabricatorController',
'PhabricatorDashboardCopyController' => 'PhabricatorDashboardController',
'PhabricatorDashboardDAO' => 'PhabricatorLiskDAO',
'PhabricatorDashboardDashboardHasPanelEdgeType' => 'PhabricatorEdgeType',
'PhabricatorDashboardDashboardPHIDType' => 'PhabricatorPHIDType',
@ -7481,7 +7488,7 @@ phutil_register_library_map(array(
'PhabricatorDashboardInstall' => 'PhabricatorDashboardDAO',
'PhabricatorDashboardLayoutConfig' => 'Phobject',
'PhabricatorDashboardListController' => 'PhabricatorDashboardController',
'PhabricatorDashboardManageController' => 'PhabricatorDashboardController',
'PhabricatorDashboardManageController' => 'PhabricatorDashboardProfileController',
'PhabricatorDashboardMovePanelController' => 'PhabricatorDashboardController',
'PhabricatorDashboardNgrams' => 'PhabricatorSearchNgrams',
'PhabricatorDashboardPanel' => array(
@ -7520,6 +7527,7 @@ phutil_register_library_map(array(
'PhabricatorDashboardPanelTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorDashboardPanelType' => 'Phobject',
'PhabricatorDashboardPanelViewController' => 'PhabricatorDashboardController',
'PhabricatorDashboardProfileController' => 'PhabricatorController',
'PhabricatorDashboardProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorDashboardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorDashboardQueryPanelType' => 'PhabricatorDashboardPanelType',
@ -7533,8 +7541,7 @@ phutil_register_library_map(array(
'PhabricatorDashboardTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorDashboardTransactionEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorDashboardTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorDashboardUninstallController' => 'PhabricatorDashboardController',
'PhabricatorDashboardViewController' => 'PhabricatorDashboardController',
'PhabricatorDashboardViewController' => 'PhabricatorDashboardProfileController',
'PhabricatorDataCacheSpec' => 'PhabricatorCacheSpec',
'PhabricatorDataNotAttachedException' => 'Exception',
'PhabricatorDatabaseHealthRecord' => 'Phobject',
@ -8007,6 +8014,7 @@ phutil_register_library_map(array(
'PhabricatorMailManagementSendTestWorkflow' => 'PhabricatorMailManagementWorkflow',
'PhabricatorMailManagementShowInboundWorkflow' => 'PhabricatorMailManagementWorkflow',
'PhabricatorMailManagementShowOutboundWorkflow' => 'PhabricatorMailManagementWorkflow',
'PhabricatorMailManagementUnverifyWorkflow' => 'PhabricatorMailManagementWorkflow',
'PhabricatorMailManagementVolumeWorkflow' => 'PhabricatorMailManagementWorkflow',
'PhabricatorMailManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorMailOutboundMailHeraldAdapter' => 'HeraldAdapter',
@ -8099,6 +8107,7 @@ phutil_register_library_map(array(
'PhabricatorModularTransactionType' => 'Phobject',
'PhabricatorMonospacedFontSetting' => 'PhabricatorStringSetting',
'PhabricatorMonospacedTextareasSetting' => 'PhabricatorSelectSetting',
'PhabricatorMotivatorProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorMultiColumnUIExample' => 'PhabricatorUIExample',
'PhabricatorMultiFactorSettingsPanel' => 'PhabricatorSettingsPanel',
'PhabricatorMultimeterApplication' => 'PhabricatorApplication',
@ -8515,6 +8524,7 @@ phutil_register_library_map(array(
'PhabricatorPhurlURLAccessController' => 'PhabricatorPhurlController',
'PhabricatorPhurlURLCommentController' => 'PhabricatorPhurlController',
'PhabricatorPhurlURLCreateCapability' => 'PhabricatorPolicyCapability',
'PhabricatorPhurlURLDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorPhurlURLEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'PhabricatorPhurlURLEditController' => 'PhabricatorPhurlController',
'PhabricatorPhurlURLEditEngine' => 'PhabricatorEditEngine',
@ -9017,6 +9027,7 @@ phutil_register_library_map(array(
'PhabricatorSettingsDeveloperPanelGroup' => 'PhabricatorSettingsPanelGroup',
'PhabricatorSettingsEditEngine' => 'PhabricatorEditEngine',
'PhabricatorSettingsEmailPanelGroup' => 'PhabricatorSettingsPanelGroup',
'PhabricatorSettingsIssueController' => 'PhabricatorController',
'PhabricatorSettingsListController' => 'PhabricatorController',
'PhabricatorSettingsLogsPanelGroup' => 'PhabricatorSettingsPanelGroup',
'PhabricatorSettingsMainController' => 'PhabricatorController',

View file

@ -61,7 +61,7 @@ final class PhabricatorAuthUnlinkController
return id(new AphrontRedirectResponse())->setURI($this->getDoneURI());
}
return $this->renderConfirmDialog($account);
return $this->renderConfirmDialog();
}
private function getDoneURI() {

View file

@ -191,16 +191,18 @@ final class PhabricatorAuthEditController
->setHeader(pht('%s: %s', $title, $provider->getProviderName()))
->setHeaderIcon($header_icon);
if ($config->getIsEnabled()) {
$status_name = pht('Enabled');
$status_color = 'green';
$status_icon = 'fa-check';
$header->setStatus($status_icon, $status_color, $status_name);
} else if (!$is_new) {
$status_name = pht('Disabled');
$status_color = 'indigo';
$status_icon = 'fa-ban';
$header->setStatus($status_icon, $status_color, $status_name);
if (!$is_new) {
if ($config->getIsEnabled()) {
$status_name = pht('Enabled');
$status_color = 'green';
$status_icon = 'fa-check';
$header->setStatus($status_icon, $status_color, $status_name);
} else {
$status_name = pht('Disabled');
$status_color = 'indigo';
$status_icon = 'fa-ban';
$header->setStatus($status_icon, $status_color, $status_name);
}
}
$config_name = 'auth.email-domains';

View file

@ -47,11 +47,14 @@ final class PhabricatorBadgesApplication extends PhabricatorApplication {
=> 'PhabricatorBadgesArchiveController',
'view/(?:(?P<id>\d+)/)?'
=> 'PhabricatorBadgesViewController',
'recipients/(?P<id>[1-9]\d*)/'
=> 'PhabricatorBadgesEditRecipientsController',
'recipients/(?P<id>[1-9]\d*)/remove/'
=> 'PhabricatorBadgesRemoveRecipientsController',
'recipients/' => array(
'(?P<id>[1-9]\d*)/'
=> 'PhabricatorBadgesRecipientsController',
'(?P<id>[1-9]\d*)/add/'
=> 'PhabricatorBadgesEditRecipientsController',
'(?P<id>[1-9]\d*)/remove/'
=> 'PhabricatorBadgesRemoveRecipientsController',
),
),
);
}

View file

@ -40,7 +40,7 @@ final class PhabricatorBadgesAwardController
->setTransactionType(PhabricatorBadgesTransaction::TYPE_AWARD)
->setNewValue($award_phids);
$editor = id(new PhabricatorBadgesEditor($badge))
$editor = id(new PhabricatorBadgesEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)

View file

@ -22,7 +22,7 @@ final class PhabricatorBadgesEditRecipientsController
return new Aphront404Response();
}
$view_uri = $this->getApplicationURI('view/'.$badge->getID().'/');
$view_uri = $this->getApplicationURI('recipients/'.$badge->getID().'/');
$awards = $badge->getAwards();
$recipient_phids = mpull($awards, 'getRecipientPHID');
@ -40,7 +40,7 @@ final class PhabricatorBadgesEditRecipientsController
->setTransactionType(PhabricatorBadgesTransaction::TYPE_AWARD)
->setNewValue($award_phids);
$editor = id(new PhabricatorBadgesEditor($badge))
$editor = id(new PhabricatorBadgesEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
@ -79,13 +79,13 @@ final class PhabricatorBadgesEditRecipientsController
->appendControl(
id(new AphrontFormTokenizerControl())
->setName('phids')
->setLabel(pht('Add Recipients'))
->setLabel(pht('Recipients'))
->setDatasource(new PhabricatorPeopleDatasource()));
}
$dialog = id(new AphrontDialogView())
->setUser($viewer)
->setTitle(pht('Award Badges'))
->setTitle(pht('Add Recipients'))
->appendForm($form)
->addCancelButton($view_uri)
->addSubmitButton(pht('Add Recipients'));

View file

@ -0,0 +1,88 @@
<?php
abstract class PhabricatorBadgesProfileController
extends PhabricatorController {
private $badge;
public function setBadge(PhabricatorBadgesBadge $badge) {
$this->badge = $badge;
return $this;
}
public function getBadge() {
return $this->badge;
}
public function buildApplicationMenu() {
return $this->buildSideNavView()->getMenu();
}
protected function buildHeaderView() {
$viewer = $this->getViewer();
$badge = $this->getBadge();
$id = $badge->getID();
if ($badge->isArchived()) {
$status_icon = 'fa-ban';
$status_color = 'dark';
} else {
$status_icon = 'fa-check';
$status_color = 'bluegrey';
}
$status_name = idx(
PhabricatorBadgesBadge::getStatusNameMap(),
$badge->getStatus());
return id(new PHUIHeaderView())
->setHeader($badge->getName())
->setUser($viewer)
->setPolicyObject($badge)
->setStatus($status_icon, $status_color, $status_name)
->setHeaderIcon('fa-trophy');
}
protected function buildApplicationCrumbs() {
$badge = $this->getBadge();
$id = $badge->getID();
$badge_uri = $this->getApplicationURI("/view/{$id}/");
$crumbs = parent::buildApplicationCrumbs();
$crumbs->addTextCrumb($badge->getName(), $badge_uri);
$crumbs->setBorder(true);
return $crumbs;
}
protected function buildSideNavView($filter = null) {
$viewer = $this->getViewer();
$badge = $this->getBadge();
$id = $badge->getID();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$badge,
PhabricatorPolicyCapability::CAN_EDIT);
$nav = id(new AphrontSideNavFilterView())
->setBaseURI(new PhutilURI($this->getApplicationURI()));
$nav->addLabel(pht('Badge'));
$nav->addFilter(
'view',
pht('View Badge'),
$this->getApplicationURI("/view/{$id}/"),
'fa-trophy');
$nav->addFilter(
'recipients',
pht('View Recipients'),
$this->getApplicationURI("/recipients/{$id}/"),
'fa-group');
$nav->selectFilter($filter);
return $nav;
}
}

View file

@ -0,0 +1,58 @@
<?php
final class PhabricatorBadgesRecipientsController
extends PhabricatorBadgesProfileController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$badge = id(new PhabricatorBadgesQuery())
->setViewer($viewer)
->withIDs(array($id))
->needRecipients(true)
->executeOne();
if (!$badge) {
return new Aphront404Response();
}
$this->setBadge($badge);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Recipients'));
$crumbs->setBorder(true);
$title = $badge->getName();
$header = $this->buildHeaderView();
$awards = $badge->getAwards();
$recipient_phids = mpull($awards, 'getRecipientPHID');
$recipient_phids = array_reverse($recipient_phids);
$handles = $this->loadViewerHandles($recipient_phids);
$recipient_list = id(new PhabricatorBadgesRecipientsListView())
->setBadge($badge)
->setHandles($handles)
->setUser($viewer);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter(array(
$recipient_list,
));
$navigation = $this->buildSideNavView('recipients');
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->setPageObjectPHIDs(array($badge->getPHID()))
->setNavigation($navigation)
->appendChild($view);
}
}

View file

@ -37,7 +37,7 @@ final class PhabricatorBadgesRemoveRecipientsController
->setTransactionType(PhabricatorBadgesTransaction::TYPE_REVOKE)
->setNewValue(array($remove_phid));
$editor = id(new PhabricatorBadgesEditor($badge))
$editor = id(new PhabricatorBadgesEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)

View file

@ -1,7 +1,7 @@
<?php
final class PhabricatorBadgesViewController
extends PhabricatorBadgesController {
extends PhabricatorBadgesProfileController {
public function shouldAllowPublic() {
return true;
@ -14,35 +14,17 @@ final class PhabricatorBadgesViewController
$badge = id(new PhabricatorBadgesQuery())
->setViewer($viewer)
->withIDs(array($id))
->needRecipients(true)
->executeOne();
if (!$badge) {
return new Aphront404Response();
}
$this->setBadge($badge);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb($badge->getName());
$crumbs->setBorder(true);
$title = $badge->getName();
if ($badge->isArchived()) {
$status_icon = 'fa-ban';
$status_color = 'dark';
} else {
$status_icon = 'fa-check';
$status_color = 'bluegrey';
}
$status_name = idx(
PhabricatorBadgesBadge::getStatusNameMap(),
$badge->getStatus());
$header = id(new PHUIHeaderView())
->setHeader($badge->getName())
->setUser($viewer)
->setPolicyObject($badge)
->setStatus($status_icon, $status_color, $status_name)
->setHeaderIcon('fa-trophy');
$header = $this->buildHeaderView();
$curtain = $this->buildCurtain($badge);
$details = $this->buildDetailsView($badge);
@ -50,16 +32,6 @@ final class PhabricatorBadgesViewController
$badge,
new PhabricatorBadgesTransactionQuery());
$awards = $badge->getAwards();
$recipient_phids = mpull($awards, 'getRecipientPHID');
$recipient_phids = array_reverse($recipient_phids);
$handles = $this->loadViewerHandles($recipient_phids);
$recipient_list = id(new PhabricatorBadgesRecipientsListView())
->setBadge($badge)
->setHandles($handles)
->setUser($viewer);
$comment_view = id(new PhabricatorBadgesEditEngine())
->setViewer($viewer)
->buildEditEngineCommentView($badge);
@ -68,16 +40,18 @@ final class PhabricatorBadgesViewController
->setHeader($header)
->setCurtain($curtain)
->setMainColumn(array(
$recipient_list,
$timeline,
$comment_view,
))
->addPropertySection(pht('Description'), $details);
$navigation = $this->buildSideNavView('view');
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->setPageObjectPHIDs(array($badge->getPHID()))
->setNavigation($navigation)
->appendChild($view);
}
@ -116,7 +90,7 @@ final class PhabricatorBadgesViewController
$id = $badge->getID();
$edit_uri = $this->getApplicationURI("/edit/{$id}/");
$archive_uri = $this->getApplicationURI("/archive/{$id}/");
$award_uri = $this->getApplicationURI("/recipients/{$id}/");
$award_uri = $this->getApplicationURI("/recipients/{$id}/add/");
$curtain = $this->newCurtainView($badge);

View file

@ -5,7 +5,6 @@ final class PhabricatorBadgesBadge extends PhabricatorBadgesDAO
PhabricatorPolicyInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorSubscribableInterface,
PhabricatorTokenReceiverInterface,
PhabricatorFlaggableInterface,
PhabricatorDestructibleInterface,
PhabricatorConduitResultInterface,
@ -161,14 +160,6 @@ final class PhabricatorBadgesBadge extends PhabricatorBadgesDAO
}
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
public function getUsersToNotifyOfTokenGiven() {
return array($this->getCreatorPHID());
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */

View file

@ -38,6 +38,10 @@ final class PhabricatorBadgesTransaction
$type = $this->getTransactionType();
switch ($type) {
case PhabricatorTransactions::TYPE_CREATE:
return pht(
'%s created this badge.',
$this->renderHandleLink($author_phid));
case self::TYPE_NAME:
if ($old === null) {
return pht(

View file

@ -27,6 +27,18 @@ final class PhabricatorBadgesRecipientsListView extends AphrontView {
$badge,
PhabricatorPolicyCapability::CAN_EDIT);
$award_button = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-plus')
->setText(pht('Add Recipents'))
->setWorkflow(true)
->setDisabled(!$can_edit)
->setHref('/badges/recipients/'.$badge->getID().'/add/');
$header = id(new PHUIHeaderView())
->setHeader(pht('Recipients'))
->addActionLink($award_button);
$list = id(new PHUIObjectItemListView())
->setNoDataString(pht('This badge does not have any recipients.'))
->setFlush(true);
@ -62,7 +74,7 @@ final class PhabricatorBadgesRecipientsListView extends AphrontView {
}
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Recipients'))
->setHeader($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($list);

View file

@ -251,7 +251,7 @@ abstract class PhabricatorApplication
}
final protected function getInboundEmailSupportLink() {
return PhabricatorEnv::getDocLink('Configuring Inbound Email');
return PhabricatorEnv::getDoclink('Configuring Inbound Email');
}
public function getAppEmailBlurb() {

View file

@ -7,9 +7,7 @@ final class CalendarTimeUtilTestCase extends PhabricatorTestCase {
$u->overrideTimezoneIdentifier('America/Los_Angeles');
$days = $this->getAllDays();
foreach ($days as $day) {
$data = CalendarTimeUtil::getCalendarWidgetTimestamps(
$u,
$day);
$data = CalendarTimeUtil::getTimestamps($u, $day, 1);
$this->assertEqual(
'000000',

View file

@ -70,7 +70,7 @@ final class PhabricatorCalendarExportEditEngine
$current_mode = $object->getPolicyMode();
if (empty($export_modes[$current_mode])) {
array_shift($export_modes, $current_mode);
array_unshift($export_modes, $current_mode);
}
$mode_options = array();

View file

@ -14,7 +14,7 @@ final class PhabricatorCalendarExternalInvitee
PhabricatorUser $actor, $event) {
return id(new PhabricatorCalendarEventInvitee())
->setInviterPHID($actor->getPHID())
->setStatus(self::STATUS_INVITED)
->setStatus(PhabricatorCalendarEventInvitee::STATUS_INVITED)
->setEventPHID($event->getPHID());
}

View file

@ -201,8 +201,8 @@ final class CelerityDefaultPostprocessor
'copy-background' => '#f1c40f',
// Background color for "most" themes.
'page.background' => '#f8f8fb',
'page.sidenav' => '#f0f0f2',
'page.background' => '#f3f5f7',
'page.sidenav' => '#eaedf1',
'menu.profile.text' => 'rgba(255,255,255,.8)',
'menu.profile.text.selected' => 'rgba(255,255,255,1)',

View file

@ -154,7 +154,7 @@ abstract class PhabricatorConduitController extends PhabricatorController {
$parts[] = "\n\n";
$parts[] = 'require_once ';
$parts[] = phutil_var_export($libphutil_path, true);
$parts[] = phutil_var_export($libphutil_path);
$parts[] = ";\n\n";
$parts[] = '$api_token = "';
@ -168,7 +168,7 @@ abstract class PhabricatorConduitController extends PhabricatorController {
$parts[] = ');';
} else {
$params = $this->simplifyParams($params);
$params = phutil_var_export($params, true);
$params = phutil_var_export($params);
$parts[] = phutil_tag('strong', array('class' => 'real'), $params);
$parts[] = ';';
}
@ -178,7 +178,7 @@ abstract class PhabricatorConduitController extends PhabricatorController {
$parts[] = phutil_tag(
'strong',
array('class' => 'real'),
phutil_var_export(PhabricatorEnv::getURI('/'), true));
phutil_var_export(PhabricatorEnv::getURI('/')));
$parts[] = ");\n";
$parts[] = '$client->setConduitToken($api_token);';
@ -188,7 +188,7 @@ abstract class PhabricatorConduitController extends PhabricatorController {
$parts[] = phutil_tag(
'strong',
array('class' => 'real'),
phutil_var_export($method->getAPIMethodName(), true));
phutil_var_export($method->getAPIMethodName()));
$parts[] = ', ';
$parts[] = '$api_parameters';
$parts[] = ");\n";

View file

@ -162,7 +162,7 @@ final class PhabricatorConduitLogSearchEngine
->addSigil('has-tooltip')
->setMetadata(
array(
'tip' => pht('Unknown ("%s")', $status),
'tip' => pht('Unknown ("%s")', $method_status),
));
break;
}

View file

@ -16,7 +16,7 @@ final class PhabricatorDaemonsSetupCheck extends PhabricatorSetupCheck {
->execute();
if (!$task_daemon) {
$doc_href = PhabricatorEnv::getDocLink('Managing Daemons with phd');
$doc_href = PhabricatorEnv::getDoclink('Managing Daemons with phd');
$summary = pht(
'You must start the Phabricator daemons to send email, rebuild '.

View file

@ -14,7 +14,7 @@ final class PhabricatorPHPConfigSetupCheck extends PhabricatorSetupCheck {
protected function executeChecks() {
if (empty($_SERVER['REMOTE_ADDR'])) {
$doc_href = PhabricatorEnv::getDocLink('Configuring a Preamble Script');
$doc_href = PhabricatorEnv::getDoclink('Configuring a Preamble Script');
$summary = pht(
'You likely need to fix your preamble script so '.

View file

@ -52,7 +52,7 @@ final class PhabricatorSecuritySetupCheck extends PhabricatorSetupCheck {
$file_key = 'security.alternate-file-domain';
$file_domain = PhabricatorEnv::getEnvConfig($file_key);
if (!$file_domain) {
$doc_href = PhabricatorEnv::getDocLink('Configuring a File Domain');
$doc_href = PhabricatorEnv::getDoclink('Configuring a File Domain');
$this->newIssue('security.'.$file_key)
->setName(pht('Alternate File Domain Not Configured'))

View file

@ -16,7 +16,7 @@ final class PhabricatorStorageSetupCheck extends PhabricatorSetupCheck {
$this->checkS3();
if (!$chunk_engine_active) {
$doc_href = PhabricatorEnv::getDocLink('Configuring File Storage');
$doc_href = PhabricatorEnv::getDoclink('Configuring File Storage');
$message = pht(
'Large file storage has not been configured, which will limit '.

View file

@ -21,7 +21,7 @@ final class PhabricatorConfigClusterDatabasesController
->setText(pht('Documentation')));
$crumbs = $this
->buildApplicationCrumbs($nav)
->buildApplicationCrumbs()
->addTextCrumb($title)
->setBorder(true);

View file

@ -21,7 +21,7 @@ final class PhabricatorConfigClusterNotificationsController
->setText(pht('Documentation')));
$crumbs = $this
->buildApplicationCrumbs($nav)
->buildApplicationCrumbs()
->addTextCrumb($title)
->setBorder(true);

View file

@ -22,7 +22,7 @@ final class PhabricatorConfigClusterRepositoriesController
->setText(pht('Documentation')));
$crumbs = $this
->buildApplicationCrumbs($nav)
->buildApplicationCrumbs()
->addTextCrumb(pht('Repository Servers'))
->setBorder(true);

View file

@ -49,7 +49,7 @@ final class PhabricatorConfigIssueListController
->setProfileHeader(true);
$crumbs = $this
->buildApplicationCrumbs($nav)
->buildApplicationCrumbs()
->addTextCrumb(pht('Setup Issues'))
->setBorder(true);

View file

@ -84,11 +84,13 @@ final class PhabricatorAuthenticationConfigOptions
'Determines whether or not basic account information is editable.'))
->setDescription(
pht(
'Is basic account information (email, real name, profile '.
'picture) editable? If you set up Phabricator to automatically '.
'synchronize account information from some other authoritative '.
'system, you can disable this to ensure information remains '.
'consistent across both systems.')),
'This option controls whether users can edit account email '.
'addresses and profile real names.'.
"\n\n".
'If you set up Phabricator to automatically synchronize account '.
'information from some other authoritative system, you can '.
'prevent users from making these edits to ensure information '.
'remains consistent across both systems.')),
$this->newOption('account.minimum-password-length', 'int', 8)
->setSummary(pht('Minimum password length.'))
->setDescription(

View file

@ -61,9 +61,10 @@ of each approach are:
a normal recipient and also Cc'd on a mailing list.
- Getting threading to work properly is harder, and probably requires
making mail less useful by turning off options.
- Sometimes people will "Reply All" and everyone will get two mails,
one from the user and one from Phabricator turning their mail into
a comment.
- Sometimes people will "Reply All", which can send mail to too many
recipients. Phabricator will try not to send mail to users who already
received a similar message, but can not prevent all stray email arising
from "Reply All".
- Not supported with a private reply-to address.
- Mails are sent in the server default translation.
- One mail to each user:
@ -73,7 +74,8 @@ of each approach are:
mail.
- Getting threading to work properly is easier, and threading settings
can be customzied by each user.
- "Reply All" no longer spams all other users.
- "Reply All" will never send extra mail to other users involved in the
thread.
- Required if private reply-to addresses are configured.
- Mails are sent in the language of user preference.

View file

@ -20,7 +20,7 @@ final class PhabricatorSyntaxHighlightingConfigOptions
}
public function getOptions() {
$caches_href = PhabricatorEnv::getDocLink('Managing Caches');
$caches_href = PhabricatorEnv::getDoclink('Managing Caches');
return array(
$this->newOption(

View file

@ -9,6 +9,7 @@ final class PhabricatorConfigKeySchema
private $unique;
private $table;
private $indexType;
private $property;
public function setIndexType($index_type) {
$this->indexType = $index_type;

View file

@ -50,9 +50,6 @@ final class ConpherenceCreateThreadConduitAPIMethod
if ($errors) {
foreach ($errors as $error_code) {
switch ($error_code) {
case ConpherenceEditor::ERROR_EMPTY_TITLE:
throw new ConduitException('ERR_EMPTY_TITLE');
break;
case ConpherenceEditor::ERROR_EMPTY_PARTICIPANTS:
throw new ConduitException('ERR_EMPTY_PARTICIPANT_PHIDS');
break;

View file

@ -27,10 +27,9 @@ final class PhabricatorDashboardApplication extends PhabricatorApplication {
'view/(?P<id>\d+)/' => 'PhabricatorDashboardViewController',
'archive/(?P<id>\d+)/' => 'PhabricatorDashboardArchiveController',
'manage/(?P<id>\d+)/' => 'PhabricatorDashboardManageController',
'arrange/(?P<id>\d+)/' => 'PhabricatorDashboardArrangeController',
'create/' => 'PhabricatorDashboardEditController',
'copy/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardCopyController',
'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardEditController',
'uninstall/(?P<id>\d+)/' => 'PhabricatorDashboardUninstallController',
'addpanel/(?P<id>\d+)/' => 'PhabricatorDashboardAddPanelController',
'movepanel/(?P<id>\d+)/' => 'PhabricatorDashboardMovePanelController',
'removepanel/(?P<id>\d+)/'

View file

@ -10,6 +10,7 @@ final class PhabricatorDashboardAddPanelController
$dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withIDs(array($id))
->needPanels(true)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
@ -20,9 +21,10 @@ final class PhabricatorDashboardAddPanelController
return new Aphront404Response();
}
$redirect_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/');
$redirect_uri = $this->getApplicationURI(
'arrange/'.$dashboard->getID().'/');
$v_panel = $request->getStr('panel');
$v_panel = head($request->getArr('panel'));
$e_panel = true;
$errors = array();
if ($request->isFormPost()) {
@ -32,9 +34,18 @@ final class PhabricatorDashboardAddPanelController
->withIDs(array($v_panel))
->executeOne();
if (!$panel) {
$errors[] = pht('No such panel!');
$errors[] = pht('Not a valid panel.');
$e_panel = pht('Invalid');
}
$on_dashboard = $dashboard->getPanels();
$on_ids = mpull($on_dashboard, null, 'getID');
if (array_key_exists($v_panel, $on_ids)) {
$p_name = $panel->getName();
$errors[] = pht('Panel "%s" already exists on dashboard.', $p_name);
$e_panel = pht('Invalid');
}
} else {
$errors[] = pht('Select a panel to add.');
$e_panel = pht('Required');
@ -69,26 +80,18 @@ final class PhabricatorDashboardAddPanelController
->addCancelButton($redirect_uri);
}
$panel_options = array();
foreach ($panels as $panel) {
$panel_options[$panel->getID()] = pht(
'%s %s',
$panel->getMonogram(),
$panel->getName());
}
$form = id(new AphrontFormView())
->setUser($viewer)
->addHiddenInput('column', $request->getInt('column'))
->appendRemarkupInstructions(
pht('Choose a panel to add to this dashboard:'))
->appendChild(
id(new AphrontFormSelectControl())
id(new AphrontFormTokenizerControl())
->setUser($this->getViewer())
->setDatasource(new PhabricatorDashboardPanelDatasource())
->setLimit(1)
->setName('panel')
->setLabel(pht('Panel'))
->setValue($v_panel)
->setError($e_panel)
->setOptions($panel_options));
->setLabel(pht('Panel')));
return $this->newDialog()
->setTitle(pht('Add Panel'))

View file

@ -0,0 +1,71 @@
<?php
final class PhabricatorDashboardArrangeController
extends PhabricatorDashboardProfileController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withIDs(array($id))
->needPanels(true)
->executeOne();
if (!$dashboard) {
return new Aphront404Response();
}
$this->setDashboard($dashboard);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$dashboard,
PhabricatorPolicyCapability::CAN_EDIT);
$title = $dashboard->getName();
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Arrange'));
$header = $this->buildHeaderView();
$info_view = null;
if (!$can_edit) {
$no_edit = pht(
'You do not have permission to edit this dashboard.');
$info_view = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->setErrors(array($no_edit));
}
$rendered_dashboard = id(new PhabricatorDashboardRenderingEngine())
->setViewer($viewer)
->setDashboard($dashboard)
->setArrangeMode($can_edit)
->renderDashboard();
$dashboard_box = id(new PHUIBoxView())
->addClass('dashboard-preview-box')
->appendChild($rendered_dashboard);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter(array(
$info_view,
$dashboard_box,
));
$navigation = $this->buildSideNavView('arrange');
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->setNavigation($navigation)
->appendChild($view);
}
}

View file

@ -1,62 +0,0 @@
<?php
final class PhabricatorDashboardCopyController
extends PhabricatorDashboardController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withIDs(array($id))
->needPanels(true)
->executeOne();
if (!$dashboard) {
return new Aphront404Response();
}
$manage_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/');
if ($request->isFormPost()) {
$copy = PhabricatorDashboard::initializeNewDashboard($viewer);
$copy = PhabricatorDashboard::copyDashboard($copy, $dashboard);
$copy->setName(pht('Copy of %s', $copy->getName()));
// Set up all the edges for the new dashboard.
$xactions = array();
$xactions[] = id(new PhabricatorDashboardTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST)
->setNewValue(
array(
'=' => array_fuse($dashboard->getPanelPHIDs()),
));
$editor = id(new PhabricatorDashboardTransactionEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->applyTransactions($copy, $xactions);
$manage_uri = $this->getApplicationURI('edit/'.$copy->getID().'/');
return id(new AphrontRedirectResponse())->setURI($manage_uri);
}
return $this->newDialog()
->setTitle(pht('Copy Dashboard'))
->appendParagraph(
pht(
'Create a copy of the dashboard "%s"?',
phutil_tag('strong', array(), $dashboard->getName())))
->addCancelButton($manage_uri)
->addSubmitButton(pht('Create Copy'));
}
}

View file

@ -117,7 +117,7 @@ final class PhabricatorDashboardEditController
->setContentSourceFromRequest($request)
->applyTransactions($dashboard, $xactions);
$uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/');
$uri = $this->getApplicationURI('arrange/'.$dashboard->getID().'/');
return id(new AphrontRedirectResponse())->setURI($uri);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
@ -351,7 +351,7 @@ final class PhabricatorDashboardEditController
->setContentSourceFromRequest($request)
->applyTransactions($dashboard, $xactions);
$manage_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/');
$manage_uri = $this->getApplicationURI('arrange/'.$dashboard->getID().'/');
return id(new AphrontRedirectResponse())
->setURI($manage_uri);

View file

@ -1,14 +1,16 @@
<?php
final class PhabricatorDashboardManageController
extends PhabricatorDashboardController {
extends PhabricatorDashboardProfileController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$dashboard_uri = $this->getApplicationURI('view/'.$id.'/');
// TODO: This UI should drop a lot of capabilities if the user can't
// edit the dashboard, but we should still let them in for "Install" and
// "View History".
@ -21,6 +23,7 @@ final class PhabricatorDashboardManageController
if (!$dashboard) {
return new Aphront404Response();
}
$this->setDashboard($dashboard);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
@ -30,41 +33,27 @@ final class PhabricatorDashboardManageController
$title = $dashboard->getName();
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
pht('Dashboard %d', $dashboard->getID()),
$dashboard_uri);
$crumbs->addTextCrumb(pht('Manage'));
$crumbs->setBorder(true);
$header = $this->buildHeaderView($dashboard);
$curtain = $this->buildCurtainview($dashboard);
$header = $this->buildHeaderView();
$curtain = $this->buildCurtainView($dashboard);
$properties = $this->buildPropertyView($dashboard);
$timeline = $this->buildTransactionTimeline(
$dashboard,
new PhabricatorDashboardTransactionQuery());
$timeline->setShouldTerminate(true);
$info_view = null;
if (!$can_edit) {
$no_edit = pht(
'You do not have permission to edit this dashboard. If you want to '.
'make changes, make a copy first.');
'You do not have permission to edit this dashboard.');
$info_view = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->setErrors(array($no_edit));
}
$rendered_dashboard = id(new PhabricatorDashboardRenderingEngine())
->setViewer($viewer)
->setDashboard($dashboard)
->setArrangeMode($can_edit)
->renderDashboard();
$dashboard_box = id(new PHUIBoxView())
->addClass('dashboard-preview-box')
->appendChild($rendered_dashboard);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
@ -72,47 +61,18 @@ final class PhabricatorDashboardManageController
$info_view,
$properties,
$timeline,
))
->setFooter($dashboard_box);
));
$navigation = $this->buildSideNavView('manage');
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->setNavigation($navigation)
->appendChild($view);
}
private function buildHeaderView(PhabricatorDashboard $dashboard) {
$viewer = $this->getViewer();
$id = $dashboard->getID();
if ($dashboard->isArchived()) {
$status_icon = 'fa-ban';
$status_color = 'dark';
} else {
$status_icon = 'fa-check';
$status_color = 'bluegrey';
}
$status_name = idx(
PhabricatorDashboard::getStatusNameMap(),
$dashboard->getStatus());
$button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('View Dashboard'))
->setIcon('fa-columns')
->setHref($this->getApplicationURI("view/{$id}/"));
return id(new PHUIHeaderView())
->setUser($viewer)
->setHeader($dashboard->getName())
->setPolicyObject($dashboard)
->setStatus($status_icon, $status_color, $status_name)
->setHeaderIcon($dashboard->getIcon())
->addActionLink($button);
}
private function buildCurtainView(PhabricatorDashboard $dashboard) {
$viewer = $this->getViewer();
$id = $dashboard->getID();
@ -149,13 +109,6 @@ final class PhabricatorDashboardManageController
->setWorkflow($can_edit));
}
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Copy Dashboard'))
->setIcon('fa-files-o')
->setHref($this->getApplicationURI("copy/{$id}/"))
->setWorkflow(true));
return $curtain;
}

View file

@ -26,7 +26,7 @@ final class PhabricatorDashboardPanelEditController
return new Aphront404Response();
}
$manage_uri = $this->getApplicationURI('manage/'.$dashboard_id.'/');
$manage_uri = $this->getApplicationURI('arrange/'.$dashboard_id.'/');
}
if ($id) {
@ -52,25 +52,6 @@ final class PhabricatorDashboardPanelEditController
return new Aphront404Response();
}
if ($dashboard) {
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$panel,
PhabricatorPolicyCapability::CAN_EDIT);
if (!$can_edit) {
if ($request->isFormPost() && $request->getBool('copy')) {
$panel = $this->copyPanel(
$request,
$dashboard,
$panel);
} else {
return $this->processPanelCloneRequest(
$request,
$dashboard,
$panel);
}
}
}
} else {
$is_create = true;
@ -162,7 +143,7 @@ final class PhabricatorDashboardPanelEditController
->applyTransactions($panel, $xactions);
// If we're creating a panel directly on a dashboard, add it now.
if ($dashboard) {
if ($dashboard && $is_create) {
PhabricatorDashboardTransactionEditor::addPanelToDashboard(
$viewer,
PhabricatorContentSource::newFromRequest($request),
@ -365,79 +346,5 @@ final class PhabricatorDashboardPanelEditController
->appendChild($view);
}
private function processPanelCloneRequest(
AphrontRequest $request,
PhabricatorDashboard $dashboard,
PhabricatorDashboardPanel $panel) {
$viewer = $request->getUser();
$manage_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/');
return $this->newDialog()
->setTitle(pht('Copy Panel?'))
->addHiddenInput('copy', true)
->addHiddenInput('dashboardID', $request->getInt('dashboardID'))
->addHiddenInput('column', $request->getInt('column'))
->appendParagraph(
pht(
'You do not have permission to edit this dashboard panel, but you '.
'can make a copy and edit that instead. If you choose to copy the '.
'panel, the original will be replaced with the new copy on this '.
'dashboard.'))
->appendParagraph(
pht(
'Do you want to make a copy of this panel?'))
->addCancelButton($manage_uri)
->addSubmitButton(pht('Copy Panel'));
}
private function copyPanel(
AphrontRequest $request,
PhabricatorDashboard $dashboard,
PhabricatorDashboardPanel $panel) {
$viewer = $request->getUser();
$copy = PhabricatorDashboardPanel::initializeNewPanel($viewer);
$copy = PhabricatorDashboardPanel::copyPanel($copy, $panel, $viewer);
$copy->openTransaction();
$copy->save();
// TODO: This should record a transaction on the panel copy, too.
$xactions = array();
$xactions[] = id(new PhabricatorDashboardTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST)
->setNewValue(
array(
'+' => array(
$copy->getPHID() => $copy->getPHID(),
),
'-' => array(
$panel->getPHID() => $panel->getPHID(),
),
));
$layout_config = $dashboard->getLayoutConfigObject();
$layout_config->replacePanel($panel->getPHID(), $copy->getPHID());
$dashboard->setLayoutConfigFromObject($layout_config);
$dashboard->save();
$editor = id(new PhabricatorDashboardTransactionEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->applyTransactions($dashboard, $xactions);
$copy->saveTransaction();
return $copy;
}
}

View file

@ -0,0 +1,95 @@
<?php
abstract class PhabricatorDashboardProfileController
extends PhabricatorController {
private $dashboard;
public function setDashboard(PhabricatorDashboard $dashboard) {
$this->dashboard = $dashboard;
return $this;
}
public function getDashboard() {
return $this->dashboard;
}
public function buildApplicationMenu() {
return $this->buildSideNavView()->getMenu();
}
protected function buildHeaderView() {
$viewer = $this->getViewer();
$dashboard = $this->getDashboard();
$id = $dashboard->getID();
if ($dashboard->isArchived()) {
$status_icon = 'fa-ban';
$status_color = 'dark';
} else {
$status_icon = 'fa-check';
$status_color = 'bluegrey';
}
$status_name = idx(
PhabricatorDashboard::getStatusNameMap(),
$dashboard->getStatus());
return id(new PHUIHeaderView())
->setUser($viewer)
->setHeader($dashboard->getName())
->setPolicyObject($dashboard)
->setStatus($status_icon, $status_color, $status_name)
->setHeaderIcon($dashboard->getIcon());
}
protected function buildApplicationCrumbs() {
$dashboard = $this->getDashboard();
$id = $dashboard->getID();
$dashboard_uri = $this->getApplicationURI("/view/{$id}/");
$crumbs = parent::buildApplicationCrumbs();
$crumbs->addTextCrumb($dashboard->getName(), $dashboard_uri);
$crumbs->setBorder(true);
return $crumbs;
}
protected function buildSideNavView($filter = null) {
$viewer = $this->getViewer();
$dashboard = $this->getDashboard();
$id = $dashboard->getID();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$dashboard,
PhabricatorPolicyCapability::CAN_EDIT);
$nav = id(new AphrontSideNavFilterView())
->setBaseURI(new PhutilURI($this->getApplicationURI()));
$nav->addLabel(pht('Dashboard'));
$nav->addFilter(
'view',
pht('View Dashboard'),
$this->getApplicationURI("/view/{$id}/"),
'fa-dashboard');
$nav->addFilter(
'arrange',
pht('Arrange Panels'),
$this->getApplicationURI("/arrange/{$id}/"),
'fa-columns');
$nav->addFilter(
'manage',
pht('Manage Dashboard'),
$this->getApplicationURI("/manage/{$id}/"),
'fa-gears');
$nav->selectFilter($filter);
return $nav;
}
}

View file

@ -43,7 +43,7 @@ final class PhabricatorDashboardRemovePanelController
}
$redirect_uri = $this->getApplicationURI(
'manage/'.$dashboard->getID().'/');
'arrange/'.$dashboard->getID().'/');
$layout_config = $dashboard->getLayoutConfigObject();
if ($request->isFormPost()) {

View file

@ -1,131 +0,0 @@
<?php
final class PhabricatorDashboardUninstallController
extends PhabricatorDashboardController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withIDs(array($id))
->executeOne();
if (!$dashboard) {
return new Aphront404Response();
}
$dashboard_phid = $dashboard->getPHID();
$object_phid = $request->getStr('objectPHID', $viewer->getPHID());
$object = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->withPHIDs(array($object_phid))
->executeOne();
if (!$object) {
return new Aphront404Response();
}
$application_class = $request->getStr(
'applicationClass',
'PhabricatorHomeApplication');
$dashboard_install = id(new PhabricatorDashboardInstall())
->loadOneWhere(
'objectPHID = %s AND applicationClass = %s',
$object_phid,
$application_class);
if (!$dashboard_install) {
return new Aphront404Response();
}
if ($dashboard_install->getDashboardPHID() != $dashboard_phid) {
return new Aphront404Response();
}
$installer_phid = $viewer->getPHID();
if ($request->isFormPost()) {
$dashboard_install->delete();
return id(new AphrontRedirectResponse())
->setURI($this->getRedirectURI($application_class, $object_phid));
}
$body = $this->getBodyContent(
$application_class,
$object_phid,
$installer_phid);
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild($body);
return $this->newDialog()
->setTitle(pht('Uninstall Dashboard'))
->appendChild($form->buildLayoutView())
->addCancelButton($this->getCancelURI(
$application_class, $object_phid, $id))
->addSubmitButton(pht('Uninstall Dashboard'));
}
private function getBodyContent(
$application_class,
$object_phid,
$installer_phid) {
$viewer = $this->getViewer();
$body = array();
switch ($application_class) {
case 'PhabricatorHomeApplication':
if ($installer_phid == $object_phid) {
$body[] = phutil_tag(
'p',
array(),
pht(
'Are you sure you want to uninstall this dashboard as your '.
'home page?'));
$body[] = phutil_tag(
'p',
array(),
pht(
'You will be re-directed to your bland, default home page if '.
'you choose to uninstall this dashboard.'));
} else {
$body[] = phutil_tag(
'p',
array(),
pht(
'Are you sure you want to uninstall this dashboard as the home '.
'page for %s?',
$viewer->renderHandle($object_phid)));
}
break;
}
return $body;
}
private function getCancelURI($application_class, $object_phid, $id) {
$uri = null;
switch ($application_class) {
case 'PhabricatorHomeApplication':
$uri = '/dashboard/view/'.$id.'/';
break;
}
return $uri;
}
private function getRedirectURI($application_class, $object_phid) {
$uri = null;
switch ($application_class) {
case 'PhabricatorHomeApplication':
$uri = '/';
break;
}
return $uri;
}
}

View file

@ -1,9 +1,7 @@
<?php
final class PhabricatorDashboardViewController
extends PhabricatorDashboardController {
private $id;
extends PhabricatorDashboardProfileController {
public function shouldAllowPublic() {
return true;
@ -11,63 +9,51 @@ final class PhabricatorDashboardViewController
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$this->id = $request->getURIData('id');
$id = $request->getURIData('id');
$dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withIDs(array($this->id))
->withIDs(array($id))
->needPanels(true)
->executeOne();
if (!$dashboard) {
return new Aphront404Response();
}
$this->setDashboard($dashboard);
$dashboard_uri = $this->getApplicationURI("view/{$id}/");
$title = $dashboard->getName();
$crumbs = $this->buildApplicationCrumbs();
$crumbs->setBorder(true);
$crumbs->addTextCrumb(pht('Dashboard %d', $dashboard->getID()));
$crumbs->addTextCrumb(pht('View'));
if ($dashboard->getPanelPHIDs()) {
$rendered_dashboard = id(new PhabricatorDashboardRenderingEngine())
->setViewer($viewer)
->setDashboard($dashboard)
->renderDashboard();
$content = id(new PHUIBoxView())
->addClass('dashboard-preview-box')
->appendChild($rendered_dashboard);
} else {
$rendered_dashboard = $this->buildEmptyView();
$content = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->appendChild(pht('This dashboard has no panels yet.'));
}
$navigation = $this->buildSideNavView('view');
$header = $this->buildHeaderView();
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter(array(
$content,
));
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($rendered_dashboard);
}
protected function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$id = $this->id;
$crumbs->addAction(
id(new PHUIListItemView())
->setIcon('fa-th')
->setName(pht('Manage Dashboard'))
->setHref($this->getApplicationURI("manage/{$id}/")));
return $crumbs;
}
public function buildEmptyView() {
$id = $this->id;
$manage_uri = $this->getApplicationURI("manage/{$id}/");
return id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NODATA)
->appendChild(
pht('This dashboard has no panels '.
'yet. Use %s to add panels.',
phutil_tag(
'a',
array('href' => $manage_uri),
pht('Manage Dashboard'))));
->setNavigation($navigation)
->appendChild($view);
}
}

View file

@ -15,7 +15,11 @@ final class PhabricatorDashboardPanelTabsCustomField
$value = array();
$names = $request->getArr($this->getFieldKey().'_name');
$panels = $request->getArr($this->getFieldKey().'_panelID');
$panel_ids = $request->getArr($this->getFieldKey().'_panelID');
$panels = array();
foreach ($panel_ids as $panel_id) {
$panels[] = $panel_id[0];
}
foreach ($names as $idx => $name) {
$panel_id = idx($panels, $idx);
if (strlen($name) && $panel_id) {
@ -29,26 +33,54 @@ final class PhabricatorDashboardPanelTabsCustomField
$this->setFieldValue($value);
}
public function getApplicationTransactionTitle(
PhabricatorApplicationTransaction $xaction) {
$author_phid = $xaction->getAuthorPHID();
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
$new_tabs = array();
if ($new) {
foreach ($new as $new_tab) {
$new_tabs[] = $new_tab['name'];
}
$new_tabs = implode(' | ', $new_tabs);
}
$old_tabs = array();
if ($old) {
foreach ($old as $old_tab) {
$old_tabs[] = $old_tab['name'];
}
$old_tabs = implode(' | ', $old_tabs);
}
if (!$old) {
// In case someone makes a tab panel with no tabs.
if ($new) {
return pht(
'%s set the tabs to "%s".',
$xaction->renderHandleLink($author_phid),
$new_tabs);
}
} else if (!$new) {
return pht(
'%s removed tabs.',
$xaction->renderHandleLink($author_phid));
} else {
return pht(
'%s changed the tabs from "%s" to "%s".',
$xaction->renderHandleLink($author_phid),
$old_tabs,
$new_tabs);
}
}
public function renderEditControl(array $handles) {
// NOTE: This includes archived panels so we don't mutate the tabs
// when saving a tab panel that includes archied panels. This whole UI is
// hopefully temporary anyway.
$panels = id(new PhabricatorDashboardPanelQuery())
->setViewer($this->getViewer())
->execute();
$panel_map = array();
foreach ($panels as $panel) {
$panel_map[$panel->getID()] = pht(
'%s %s',
$panel->getMonogram(),
$panel->getName());
}
$panel_map = array(
'' => pht('(None)'),
) + $panel_map;
$value = $this->getFieldValue();
if (!is_array($value)) {
$value = array();
@ -57,15 +89,22 @@ final class PhabricatorDashboardPanelTabsCustomField
$out = array();
for ($ii = 1; $ii <= 6; $ii++) {
$tab = idx($value, ($ii - 1), array());
$panel = idx($tab, 'panelID', null);
$panel_id = array();
if ($panel) {
$panel_id[] = $panel;
}
$out[] = id(new AphrontFormTextControl())
->setName($this->getFieldKey().'_name[]')
->setValue(idx($tab, 'name'))
->setLabel(pht('Tab %d Name', $ii));
$out[] = id(new AphrontFormSelectControl())
$out[] = id(new AphrontFormTokenizerControl())
->setUser($this->getViewer())
->setDatasource(new PhabricatorDashboardPanelDatasource())
->setName($this->getFieldKey().'_panelID[]')
->setValue(idx($tab, 'panelID'))
->setOptions($panel_map)
->setValue($panel_id)
->setLimit(1)
->setLabel(pht('Tab %d Panel', $ii));
}

View file

@ -13,6 +13,7 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject {
private $parentPanelPHIDs;
private $headerMode = self::HEADER_MODE_NORMAL;
private $dashboardID;
private $movable = true;
public function setDashboardID($id) {
$this->dashboardID = $id;
@ -63,6 +64,15 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject {
return $this;
}
public function setMovable($movable) {
$this->movable = $movable;
return $this;
}
public function getMovable() {
return $this->movable;
}
public function getPanel() {
return $this->panel;
}
@ -78,7 +88,6 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject {
public function renderPanel() {
$panel = $this->getPanel();
$viewer = $this->getViewer();
if (!$panel) {
return $this->renderErrorPanel(
@ -107,7 +116,7 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject {
}
}
return $this->renderNormalPanel($viewer, $panel, $this);
return $this->renderNormalPanel();
} catch (Exception $ex) {
return $this->renderErrorPanel(
$panel->getName(),
@ -221,8 +230,13 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject {
$box
->setHeader($header)
->setID($id)
->addClass('dashboard-box')
->addSigil('dashboard-panel');
if ($this->getMovable()) {
$box->addSigil('panel-movable');
}
if ($panel) {
$box->setMetadata(
array(

View file

@ -81,17 +81,43 @@ final class PhabricatorDashboardRenderingEngine extends Phobject {
}
if ($this->arrangeMode) {
$footer = null;
Javelin::initBehavior(
'dashboard-move-panels',
array(
'dashboardID' => $dashboard_id,
'moveURI' => '/dashboard/movepanel/'.$dashboard->getID().'/',
));
} else {
$name = $dashboard->getName();
$icon = id(new PHUIIconView())
->setIcon($dashboard->getIcon())
->addClass('msr');
$footer_left = phutil_tag(
'a',
array(
'class' => 'dashboard-footer-name',
'href' => '/dashboard/view/'.$dashboard->getID().'/',
),
array(
$icon,
$name,
));
$footer = phutil_tag(
'div',
array(
'class' => 'dashboard-footer-view',
),
array(
$footer_left,
));
}
$view = id(new PHUIBoxView())
->addClass('dashboard-view')
->appendChild($result);
->appendChild($result)
->appendChild($footer);
return $view;
}
@ -123,7 +149,6 @@ final class PhabricatorDashboardRenderingEngine extends Phobject {
->setTag('a')
->setHref($create_uri)
->setWorkflow(true)
->setColor(PHUIButtonView::GREY)
->setText(pht('Create Panel'))
->addClass(PHUI::MARGIN_MEDIUM);
@ -131,7 +156,6 @@ final class PhabricatorDashboardRenderingEngine extends Phobject {
->setTag('a')
->setHref($add_uri)
->setWorkflow(true)
->setColor(PHUIButtonView::GREY)
->setText(pht('Add Existing Panel'))
->addClass(PHUI::MARGIN_MEDIUM);

View file

@ -6,6 +6,7 @@ abstract class PhabricatorDashboardPanelType extends Phobject {
abstract public function getPanelTypeName();
abstract public function getPanelTypeDescription();
abstract public function getFieldSpecifications();
abstract public function getIcon();
abstract public function renderPanelContent(
PhabricatorUser $viewer,

View file

@ -11,6 +11,10 @@ final class PhabricatorDashboardQueryPanelType
return pht('Query Panel');
}
public function getIcon() {
return 'fa-search';
}
public function getPanelTypeDescription() {
return pht(
'Show results of a search query, like the most recently filed tasks or '.

View file

@ -11,6 +11,10 @@ final class PhabricatorDashboardTabsPanelType
return pht('Tab Panel');
}
public function getIcon() {
return 'fa-window-maximize';
}
public function getPanelTypeDescription() {
return pht('Use tabs to switch between several other panels.');
}
@ -93,6 +97,7 @@ final class PhabricatorDashboardTabsPanelType
->setPanel($panel)
->setPanelPHID($panel->getPHID())
->setHeaderMode($no_headers)
->setMovable(false)
->renderPanel();
} else {
$panel_content = pht('(Invalid Panel)');

View file

@ -11,6 +11,10 @@ final class PhabricatorDashboardTextPanelType
return pht('Text Panel');
}
public function getIcon() {
return 'fa-paragraph';
}
public function getPanelTypeDescription() {
return pht(
'Add some static text to the dashboard. This can be used to '.

View file

@ -13,7 +13,7 @@ final class PhabricatorDashboardSearchEngine
public function newQuery() {
return id(new PhabricatorDashboardQuery())
->needProjects(true);
->needPanels(true);
}
protected function buildCustomSearchFields() {
@ -98,100 +98,53 @@ final class PhabricatorDashboardSearchEngine
PhabricatorSavedQuery $query,
array $handles) {
$dashboards = mpull($dashboards, null, 'getPHID');
$viewer = $this->requireViewer();
if ($dashboards) {
$installs = id(new PhabricatorDashboardInstall())
->loadAllWhere(
'objectPHID IN (%Ls) AND dashboardPHID IN (%Ls)',
array(
PhabricatorHomeApplication::DASHBOARD_DEFAULT,
$viewer->getPHID(),
),
array_keys($dashboards));
$installs = mpull($installs, null, 'getDashboardPHID');
} else {
$installs = array();
}
$proj_phids = array();
$phids = array();
foreach ($dashboards as $dashboard) {
foreach ($dashboard->getProjectPHIDs() as $project_phid) {
$proj_phids[] = $project_phid;
$author_phid = $dashboard->getAuthorPHID();
if ($author_phid) {
$phids[] = $author_phid;
}
}
$proj_handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs($proj_phids)
->execute();
$handles = $viewer->loadHandles($phids);
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
$list->initBehavior('phabricator-tooltips', array());
$list->requireResource('aphront-tooltip-css');
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($dashboards as $dashboard_phid => $dashboard) {
foreach ($dashboards as $dashboard) {
$id = $dashboard->getID();
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Dashboard %d', $id))
->setUser($viewer)
->setHeader($dashboard->getName())
->setHref($this->getApplicationURI("view/{$id}/"))
->setObject($dashboard);
if (isset($installs[$dashboard_phid])) {
$install = $installs[$dashboard_phid];
if ($install->getObjectPHID() == $viewer->getPHID()) {
$attrs = array(
'tip' => pht(
'This dashboard is installed to your personal homepage.'),
);
$item->addIcon('fa-user', pht('Installed'), $attrs);
} else {
$attrs = array(
'tip' => pht(
'This dashboard is the default homepage for all users.'),
);
$item->addIcon('fa-globe', pht('Installed'), $attrs);
}
}
$project_handles = array_select_keys(
$proj_handles,
$dashboard->getProjectPHIDs());
$item->addAttribute(
id(new PHUIHandleTagListView())
->setLimit(4)
->setNoDataString(pht('No Projects'))
->setSlim(true)
->setHandles($project_handles));
if ($dashboard->isArchived()) {
$item->setDisabled(true);
}
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$dashboard,
PhabricatorPolicyCapability::CAN_EDIT);
$panels = $dashboard->getPanels();
foreach ($panels as $panel) {
$item->addAttribute($panel->getName());
}
$href_view = $this->getApplicationURI("manage/{$id}/");
$item->addAction(
id(new PHUIListItemView())
->setName(pht('Manage'))
->setIcon('fa-th')
->setHref($href_view));
if (empty($panels)) {
$empty = phutil_tag('em', array(), pht('No panels.'));
$item->addAttribute($empty);
}
$href_edit = $this->getApplicationURI("edit/{$id}/");
$item->addAction(
id(new PHUIListItemView())
->setName(pht('Edit'))
->setIcon('fa-pencil')
->setHref($href_edit)
->setDisabled(!$can_edit));
$icon = id(new PHUIIconView())
->setIcon($dashboard->getIcon())
->setBackground('bg-dark');
$item->setImageIcon($icon);
$item->setEpoch($dashboard->getDateModified());
$author_phid = $dashboard->getAuthorPHID();
$author_name = $handles[$author_phid]->renderLink();
$item->addByline(pht('Author: %s', $author_name));
$list->addItem($item);
}

View file

@ -47,16 +47,6 @@ final class PhabricatorDashboard extends PhabricatorDashboardDAO
);
}
public static function copyDashboard(
PhabricatorDashboard $dst,
PhabricatorDashboard $src) {
$dst->name = $src->name;
$dst->layoutConfig = $src->layoutConfig;
return $dst;
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,

View file

@ -31,19 +31,6 @@ final class PhabricatorDashboardPanel
->setEditPolicy($actor->getPHID());
}
public static function copyPanel(
PhabricatorDashboardPanel $dst,
PhabricatorDashboardPanel $src,
PhabricatorUser $user) {
$dst->name = $src->name;
$dst->panelType = $src->panelType;
$dst->properties = $src->properties;
$dst->authorPHID = $user->getPHID();
return $dst;
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,

View file

@ -56,11 +56,11 @@ final class PhabricatorDashboardTransaction
case self::TYPE_STATUS:
if ($new == PhabricatorDashboard::STATUS_ACTIVE) {
return pht(
'%s activated this dashboard',
'%s activated this dashboard.',
$author_link);
} else {
return pht(
'%s archived this dashboard',
'%s archived this dashboard.',
$author_link);
}
break;

View file

@ -16,9 +16,19 @@ final class PhabricatorDashboardPanelDatasource
}
public function loadResults() {
$query = id(new PhabricatorDashboardPanelQuery());
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
public function buildResults() {
$query = id(new PhabricatorDashboardPanelQuery());
$panels = $this->executeQuery($query);
$results = array();
foreach ($panels as $panel) {
$impl = $panel->getImplementation();
@ -27,20 +37,29 @@ final class PhabricatorDashboardPanelDatasource
} else {
$type_text = nonempty($panel->getPanelType(), pht('Unknown Type'));
}
$id = $panel->getID();
$monogram = $panel->getMonogram();
$properties = $panel->getProperties();
$result = id(new PhabricatorTypeaheadResult())
->setName($panel->getName())
->setPHID($panel->getPHID())
->setDisplayName($monogram.' '.$panel->getName())
->setPHID($id)
->setIcon($impl->getIcon())
->addAttribute($type_text);
if (!empty($properties['class'])) {
$result->addAttribute($properties['class']);
}
if ($panel->getIsArchived()) {
$result->setClosed(pht('Archived'));
}
$results[] = $result;
$results[$id] = $result;
}
return $this->filterResultsAgainstTokens($results);
return $results;
}
}

View file

@ -111,8 +111,8 @@ abstract class DifferentialCustomField
* @task diff
*/
public function renderDiffPropertyViewLabel(DifferentialDiff $diff) {
if ($this->proxy) {
return $this->proxy->renderDiffPropertyViewLabel($diff);
if ($this->getProxy()) {
return $this->getProxy()->renderDiffPropertyViewLabel($diff);
}
return $this->getFieldName();
}
@ -122,8 +122,8 @@ abstract class DifferentialCustomField
* @task diff
*/
public function renderDiffPropertyViewValue(DifferentialDiff $diff) {
if ($this->proxy) {
return $this->proxy->renderDiffPropertyViewValue($diff);
if ($this->getProxy()) {
return $this->getProxy()->renderDiffPropertyViewValue($diff);
}
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}

View file

@ -20,7 +20,7 @@ final class DifferentialRevisionRequiredActionResultBucket
$this->objects = $objects;
$phids = $query->getEvaluatedParameter('responsiblePHIDs', array());
$phids = $query->getEvaluatedParameter('responsiblePHIDs');
if (!$phids) {
throw new Exception(
pht(

View file

@ -201,7 +201,7 @@ final class DiffusionDiffQueryConduitAPIMethod
$effective_commit = $this->getEffectiveCommit($request);
if (!$effective_commit) {
return $this->getEmptyResult(1);
return $this->getEmptyResult();
}
$raw_query = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest)
@ -209,7 +209,7 @@ final class DiffusionDiffQueryConduitAPIMethod
$raw_diff = $raw_query->executeInline();
if (!$raw_diff) {
return $this->getEmptyResult(2);
return $this->getEmptyResult();
}
$parser = $this->getDefaultParser();

View file

@ -44,7 +44,7 @@ final class DiffusionBrowseController extends DiffusionController {
$is_file = ($reason == DiffusionBrowseResultSet::REASON_IS_FILE);
if ($is_file) {
return $this->browseFile($results);
return $this->browseFile();
} else {
$paths = $results->getPaths();
$paths = $pager->sliceResults($paths);

View file

@ -705,7 +705,11 @@ final class DiffusionCommitController extends DiffusionController {
$timeline = $this->buildTransactionTimeline(
$commit,
new PhabricatorAuditTransactionQuery());
$commit->willRenderTimeline($timeline, $this->getRequest());
$timeline->setQuoteRef($commit->getMonogram());
return $timeline;
}

View file

@ -357,7 +357,7 @@ abstract class DiffusionController extends PhabricatorController {
$stable_commit = $drequest->getStableCommit();
$stable_commit_hash = PhabricatorHash::digestForIndex($stable_commit);
$readme_path_hash = PhabricatorHash::digestForindex($readme_path);
$readme_path_hash = PhabricatorHash::digestForIndex($readme_path);
$cache = PhabricatorCaches::getMutableStructureCache();
$cache_key = "diffusion".

View file

@ -59,7 +59,7 @@ final class DiffusionHistoryController extends DiffusionController {
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($history_table);
$header = $this->buildHeader($drequest, $repository);
$header = $this->buildHeader($drequest);
$crumbs = $this->buildCrumbs(
array(

View file

@ -241,7 +241,7 @@ final class DiffusionRepositoryStatusManagementPanel
}
}
$doc_href = PhabricatorEnv::getDocLink('Managing Daemons with phd');
$doc_href = PhabricatorEnv::getDoclink('Managing Daemons with phd');
$daemon_instructions = pht(
'Use %s to start daemons. See %s.',

View file

@ -335,7 +335,8 @@ final class DiffusionRepositoryClusterEngine extends Phobject {
pht(
'Failed to acquire write lock after waiting %s second(s). You '.
'may be able to retry later.',
new PhutilNumber($lock_wait)));
new PhutilNumber($lock_wait)),
$ex);
}
$versions = PhabricatorRepositoryWorkingCopyVersion::loadVersions(

View file

@ -17,7 +17,7 @@ final class DiffusionCommitRequiredActionResultBucket
$this->objects = $objects;
$phids = $query->getEvaluatedParameter('responsiblePHIDs', array());
$phids = $query->getEvaluatedParameter('responsiblePHIDs');
if (!$phids) {
throw new Exception(
pht(

View file

@ -43,7 +43,7 @@ final class DivinerAtom extends Phobject {
$this->getContext(),
$this->getName(),
$this->getFile(),
sprintf('%08', $this->getLine()),
sprintf('%08d', $this->getLine()),
));
}

View file

@ -94,7 +94,7 @@ final class DivinerDefaultRenderer extends DivinerRenderer {
$this->pushAtomStack($atom);
$description = $engine->markupText($text);
$this->popAtomStack($atom);
$this->popAtomStack();
return phutil_tag(
'div',

View file

@ -33,8 +33,8 @@ final class DivinerLiveSymbolFulltextEngine
$document->addRelationship(
$atom->getGraphHash()
? PhabricatorSearchRelationship::RELATIONSHIP_CLOSED
: PhabricatorSearchRelationship::RELATIONSHIP_OPEN,
? PhabricatorSearchRelationship::RELATIONSHIP_OPEN
: PhabricatorSearchRelationship::RELATIONSHIP_CLOSED,
$atom->getBookPHID(),
DivinerBookPHIDType::TYPECONST,
PhabricatorTime::getNow());

View file

@ -61,7 +61,7 @@ abstract class DivinerWorkflow extends PhabricatorManagementWorkflow {
}
foreach (idx($book, 'groups', array()) as $group) {
PhutilTypeSpec::checkmap(
PhutilTypeSpec::checkMap(
$group,
array(
'name' => 'string',

View file

@ -3,6 +3,10 @@
final class PhabricatorFileLightboxController
extends PhabricatorFileController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$phid = $request->getURIData('phid');

View file

@ -3,7 +3,7 @@
abstract class HeraldController extends PhabricatorController {
public function buildApplicationMenu() {
return $this->buildSideNavView(true)->getMenu();
return $this->buildSideNavView()->getMenu();
}
protected function buildApplicationCrumbs() {

View file

@ -40,11 +40,6 @@ final class HeraldRuleQuery extends PhabricatorCursorPagedPolicyAwareQuery {
return $this;
}
public function withExecutableRules($executable) {
$this->executable = $executable;
return $this;
}
public function withDisabled($disabled) {
$this->disabled = $disabled;
return $this;

View file

@ -213,7 +213,7 @@ final class LegalpadDocumentEditController extends LegalpadController {
->setPolicies($policies)
->setName('can_edit'));
$crumbs = $this->buildApplicationCrumbs($this->buildSideNav());
$crumbs = $this->buildApplicationCrumbs();
$submit = new AphrontFormSubmitControl();
if ($is_create) {
$submit->setValue(pht('Create Document'));

View file

@ -54,7 +54,7 @@ final class LegalpadDocumentManageController extends LegalpadController {
$add_comment = $this->buildAddCommentView($document, $comment_form_id);
$crumbs = $this->buildApplicationCrumbs($this->buildSideNav());
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
$document->getMonogram(),
'/'.$document->getMonogram());

View file

@ -52,9 +52,6 @@ final class LegalpadDocumentBody extends LegalpadDAO
case self::MARKUP_FIELD_TEXT:
$text = $this->getText();
break;
case self::MARKUP_FIELD_TITLE:
$text = $this->getTitle();
break;
default:
throw new Exception(pht('Unknown field: %s', $field));
break;

View file

@ -98,8 +98,10 @@ abstract class PhabricatorTestDataGenerator extends Phobject {
->loadOneWhere('1 = 1 ORDER BY RAND() LIMIT 1');
} catch (PhutilMissingSymbolException $ex) {
throw new PhutilMissingSymbolException(
$classname,
pht('class'),
pht(
'Unable to load symbol %s: this class does not exit.',
'Unable to load symbol %s: this class does not exist.',
$classname));
}
}

View file

@ -3,7 +3,7 @@
abstract class ManiphestController extends PhabricatorController {
public function buildApplicationMenu() {
return $this->buildSideNavView(true)->getMenu();
return $this->buildSideNavView()->getMenu();
}
public function buildSideNavView() {

View file

@ -219,7 +219,7 @@ final class ManiphestTaskDetailController extends ManiphestController {
$status = $task->getStatus();
$status_name = ManiphestTaskStatus::renderFullDescription(
$status, $priority_name, $priority_color);
$status, $priority_name);
$view->addProperty(PHUIHeaderView::PROPERTY_STATUS, $status_name);
$view->setHeaderIcon(ManiphestTaskStatus::getStatusIcon(

View file

@ -10,8 +10,7 @@ final class ManiphestConfiguredCustomField
public function createFields($object) {
$config = PhabricatorEnv::getEnvConfig(
'maniphest.custom-field-definitions',
array());
'maniphest.custom-field-definitions');
$fields = PhabricatorStandardCustomField::buildStandardFields(
$this,
$config);

View file

@ -767,7 +767,7 @@ final class ManiphestTransaction
$new_name);
} else {
return pht(
'%s changed the status of %s, a subtasktask of %s, '.
'%s changed the status of %s, a subtask of %s, '.
'from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($blocker_phid),

View file

@ -15,7 +15,7 @@ final class PhabricatorMailImplementationPHPMailerAdapter
$this->mailer = new PHPMailer($use_exceptions = true);
$this->mailer->CharSet = 'utf-8';
$encoding = PhabricatorEnv::getEnvConfig('phpmailer.smtp-encoding', '8bit');
$encoding = PhabricatorEnv::getEnvConfig('phpmailer.smtp-encoding');
$this->mailer->Encoding = $encoding;
// By default, PHPMailer sends one mail per recipient. We handle

View file

@ -18,7 +18,7 @@ class PhabricatorMailImplementationPHPMailerLiteAdapter
$this->mailer = new PHPMailerLite($use_exceptions = true);
$this->mailer->CharSet = 'utf-8';
$encoding = PhabricatorEnv::getEnvConfig('phpmailer.smtp-encoding', '8bit');
$encoding = PhabricatorEnv::getEnvConfig('phpmailer.smtp-encoding');
$this->mailer->Encoding = $encoding;
// By default, PHPMailerLite sends one mail per recipient. We handle

View file

@ -0,0 +1,110 @@
<?php
final class PhabricatorMailManagementUnverifyWorkflow
extends PhabricatorMailManagementWorkflow {
protected function didConstruct() {
$this
->setName('unverify')
->setSynopsis(
pht('Unverify an email address so it no longer receives mail.'))
->setExamples('**unverify** __address__ ...')
->setArguments(
array(
array(
'name' => 'addresses',
'wildcard' => true,
'help' => pht('Address (or addresses) to unverify.'),
),
));
}
public function execute(PhutilArgumentParser $args) {
$console = PhutilConsole::getConsole();
$viewer = $this->getViewer();
$addresses = $args->getArg('addresses');
if (!$addresses) {
throw new PhutilArgumentUsageException(
pht('Specify one or more email addresses to unverify.'));
}
foreach ($addresses as $address) {
$email = id(new PhabricatorUserEmail())->loadOneWhere(
'address = %s',
$address);
if (!$email) {
echo tsprintf(
"%s\n",
pht(
'Address "%s" is unknown.',
$address));
continue;
}
$user_phid = $email->getUserPHID();
$user = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withPHIDs(array($user_phid))
->executeOne();
if (!$user) {
echo tsprintf(
"%s\n",
pht(
'Address "%s" belongs to invalid user "%s".',
$address,
$user_phid));
continue;
}
if (!$email->getIsVerified()) {
echo tsprintf(
"%s\n",
pht(
'Address "%s" (owned by "%s") is already unveriifed.',
$address,
$user->getUsername()));
continue;
}
$email->openTransaction();
$email
->setIsVerified(0)
->save();
if ($email->getIsPrimary()) {
$user
->setIsEmailVerified(0)
->save();
}
$email->saveTransaction();
if ($email->getIsPrimary()) {
echo tsprintf(
"%s\n",
pht(
'Unverified "%s", the primary address for "%s".',
$address,
$user->getUsername()));
} else {
echo tsprintf(
"%s\n",
pht(
'Unverified "%s", an address for "%s".',
$address,
$user->getUsername()));
}
}
echo tsprintf(
"%s\n",
pht('Done.'));
return 0;
}
}

View file

@ -20,12 +20,14 @@ final class PhabricatorMetaMTAActor extends Phobject {
const REASON_FORCE_HERALD = 'force-herald';
const REASON_ROUTE_AS_NOTIFICATION = 'route-as-notification';
const REASON_ROUTE_AS_MAIL = 'route-as-mail';
const REASON_UNVERIFIED = 'unverified';
private $phid;
private $emailAddress;
private $name;
private $status = self::STATUS_DELIVERABLE;
private $reasons = array();
private $isVerified = false;
public function setName($name) {
$this->name = $name;
@ -45,6 +47,15 @@ final class PhabricatorMetaMTAActor extends Phobject {
return $this->emailAddress;
}
public function setIsVerified($is_verified) {
$this->isVerified = $is_verified;
return $this;
}
public function getIsVerified() {
return $this->isVerified;
}
public function setPHID($phid) {
$this->phid = $phid;
return $this;
@ -104,6 +115,7 @@ final class PhabricatorMetaMTAActor extends Phobject {
self::REASON_FORCE_HERALD => pht('Forced by Herald'),
self::REASON_ROUTE_AS_NOTIFICATION => pht('Route as Notification'),
self::REASON_ROUTE_AS_MAIL => pht('Route as Mail'),
self::REASON_UNVERIFIED => pht('Address Not Verified'),
);
return idx($names, $reason, pht('Unknown ("%s")', $reason));
@ -158,6 +170,8 @@ final class PhabricatorMetaMTAActor extends Phobject {
self::REASON_ROUTE_AS_MAIL => pht(
'This message was upgraded to email by outbound mail rules '.
'in Herald.'),
self::REASON_UNVERIFIED => pht(
'This recipient does not have a verified primary email address.'),
);
return idx($descriptions, $reason, pht('Unknown Reason ("%s")', $reason));

View file

@ -89,6 +89,7 @@ final class PhabricatorMetaMTAActorQuery extends PhabricatorQuery {
$actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_NO_ADDRESS);
} else {
$actor->setEmailAddress($email->getAddress());
$actor->setIsVerified($email->getIsVerified());
}
}
}
@ -119,6 +120,13 @@ final class PhabricatorMetaMTAActorQuery extends PhabricatorQuery {
}
$actor->setEmailAddress($xuser->getAccountID());
// NOTE: This effectively drops all outbound mail to unrecognized
// addresses unless "phabricator.allow-email-users" is set. See T12237
// for context.
$allow_key = 'phabricator.allow-email-users';
$allow_value = PhabricatorEnv::getEnvConfig($allow_key);
$actor->setIsVerified((bool)$allow_value);
}
}

View file

@ -153,6 +153,10 @@ abstract class PhabricatorMailReceiver extends Phobject {
->loadOneOrCreate();
return $xuser->getPhabricatorUser();
} else {
// NOTE: Currently, we'll always drop this mail (since it's headed to
// an unverified recipient). See T12237. These details are still useful
// because they'll appear in the mail logs and Mail web UI.
$reasons[] = pht(
'Phabricator is also not configured to allow unknown external users '.
'to send mail to the system using just an email address.');
@ -174,13 +178,13 @@ abstract class PhabricatorMailReceiver extends Phobject {
if ($user) {
return $user;
}
}
$reasons[] = pht(
"Phabricator is misconfigured, the application email ".
"'%s' is set to user '%s' but that user does not exist.",
$application_email->getAddress(),
$default_user_phid);
$reasons[] = pht(
'Phabricator is misconfigured: the application email '.
'"%s" is set to user "%s", but that user does not exist.',
$application_email->getAddress(),
$default_user_phid);
}
}
$reasons = implode("\n\n", $reasons);

View file

@ -41,7 +41,7 @@ final class PhabricatorMetaMTAAttachment extends Phobject {
public function toDictionary() {
return array(
'filename' => $this->getFilename(),
'mimetype' => $this->getMimetype(),
'mimetype' => $this->getMimeType(),
'data' => $this->getData(),
);
}

View file

@ -951,6 +951,16 @@ final class PhabricatorMetaMTAMail
}
}
// Unless delivery was forced earlier (password resets, confirmation mail),
// never send mail to unverified addresses.
foreach ($actors as $phid => $actor) {
if ($actor->getIsVerified()) {
continue;
}
$actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_UNVERIFIED);
}
return $actors;
}

View file

@ -153,6 +153,22 @@ final class PhabricatorMetaMTAMailTestCase extends PhabricatorTestCase {
$this->assertTrue(
in_array($phid, $mail->buildRecipientList()),
'Recipients restored after tag preference removed.');
$email = id(new PhabricatorUserEmail())->loadOneWhere(
'userPHID = %s AND isPrimary = 1',
$phid);
$email->setIsVerified(0)->save();
$this->assertFalse(
in_array($phid, $mail->buildRecipientList()),
pht('Mail not sent to unverified address.'));
$email->setIsVerified(1)->save();
$this->assertTrue(
in_array($phid, $mail->buildRecipientList()),
pht('Mail sent to verified address.'));
}
public function testThreadIDHeaders() {

View file

@ -9,9 +9,7 @@ final class PhabricatorOwnersConfiguredCustomField
}
public function createFields($object) {
$config = PhabricatorEnv::getEnvConfig(
'owners.custom-field-definitions',
array());
$config = PhabricatorEnv::getEnvConfig('owners.custom-field-definitions');
$fields = PhabricatorStandardCustomField::buildStandardFields(
$this,

View file

@ -292,7 +292,7 @@ final class PhabricatorPasteQuery
foreach ($pastes as $paste) {
$key = $this->getSnippetCacheKey($paste);
if (isset($caches[$key])) {
$snippet_data = phutil_json_decode($caches[$key], true);
$snippet_data = phutil_json_decode($caches[$key]);
$snippet = new PhabricatorPasteSnippet(
phutil_safe_html($snippet_data['content']),
$snippet_data['type'],

View file

@ -15,7 +15,7 @@ final class PhabricatorPasteTitleTransaction
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNeWValue();
$new = $this->getNewValue();
if (strlen($old) && strlen($new)) {
return pht(
@ -38,7 +38,7 @@ final class PhabricatorPasteTitleTransaction
public function getTitleForFeed() {
$old = $this->getOldValue();
$new = $this->getNeWValue();
$new = $this->getNewValue();
if (strlen($old) && strlen($new)) {
return pht(

View file

@ -103,6 +103,8 @@ abstract class PhabricatorPeopleProfileController
if ($user->getIsDisabled()) {
$header->setStatus('fa-ban', 'red', pht('Disabled'));
} else if (!$user->getIsEmailVerified()) {
$header->setStatus('fa-envelope', 'red', pht('Email Not Verified'));
} else {
$header->setStatus($profile_icon, 'bluegrey', $profile_title);
}

View file

@ -42,6 +42,7 @@ final class PhabricatorPeopleProfileViewController
$home = id(new PHUITwoColumnView())
->setHeader($header)
->addClass('project-view-home')
->addClass('project-view-people-home')
->setMainColumn(
array(
$properties,
@ -87,8 +88,13 @@ final class PhabricatorPeopleProfileViewController
return null;
}
$header = id(new PHUIHeaderView())
->setHeader(pht('User Details'));
$view = id(new PHUIObjectBoxView())
->appendChild($view)
->setHeader($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->addClass('project-view-properties');
return $view;
@ -143,7 +149,7 @@ final class PhabricatorPeopleProfileViewController
$box = id(new PHUIObjectBoxView())
->setHeader($header)
->appendChild($list)
->setBackground(PHUIObjectBoxView::GREY);
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY);
return $box;
}
@ -217,7 +223,7 @@ final class PhabricatorPeopleProfileViewController
->setHeader($header)
->appendChild($day_view)
->addClass('calendar-profile-box')
->setBackground(PHUIObjectBoxView::GREY);
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY);
return $box;
}
@ -317,7 +323,7 @@ final class PhabricatorPeopleProfileViewController
->setHeader($header)
->addClass('project-view-badges')
->appendChild($flex)
->setBackground(PHUIObjectBoxView::GREY);
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY);
return $box;
}

View file

@ -11,7 +11,7 @@ final class PhabricatorUserConfiguredCustomField
public function createFields($object) {
return PhabricatorStandardCustomField::buildStandardFields(
$this,
PhabricatorEnv::getEnvConfig('user.custom-field-definitions', array()));
PhabricatorEnv::getEnvConfig('user.custom-field-definitions'));
}
public function newStorageObject() {

View file

@ -150,7 +150,7 @@ final class PhabricatorMentionRemarkupRule extends PhutilRemarkupRule {
$tag->addClass('phabricator-remarkup-mention-nopermission');
}
if (!$user->isUserActivated()) {
if (!$user->isResponsive()) {
$tag->setDotColor(PHUITagView::COLOR_GREY);
} else {
if ($user->getAwayUntil()) {

View file

@ -61,7 +61,7 @@ final class PhabricatorPeopleUserPHIDType extends PhabricatorPHIDType {
}
$availability = null;
if (!$user->isUserActivated()) {
if (!$user->isResponsive()) {
$availability = PhabricatorObjectHandle::AVAILABILITY_DISABLED;
} else {
$until = $user->getAwayUntil();

View file

@ -120,6 +120,32 @@ final class PhabricatorUser
return true;
}
/**
* Is this a user who we can reasonably expect to respond to requests?
*
* This is used to provide a grey "disabled/unresponsive" dot cue when
* rendering handles and tags, so it isn't a surprise if you get ignored
* when you ask things of users who will not receive notifications or could
* not respond to them (because they are disabled, unapproved, do not have
* verified email addresses, etc).
*
* @return bool True if this user can receive and respond to requests from
* other humans.
*/
public function isResponsive() {
if (!$this->isUserActivated()) {
return false;
}
if (!$this->getIsEmailVerified()) {
return false;
}
return true;
}
public function canEstablishWebSessions() {
if ($this->getIsMailingList()) {
return false;

View file

@ -52,17 +52,44 @@ final class PhabricatorUserCardView extends AphrontTagView {
require_celerity_resource('project-card-view-css');
$profile_icon = PhabricatorPeopleIconSet::getIconIcon($profile->getIcon());
$profile_title = $profile->getDisplayTitle();
// We don't have a ton of room on the hovercard, so we're trying to show
// the most important tag. Users can click through to the profile to get
// more details.
if ($user->getIsDisabled()) {
$tag_icon = 'fa-ban';
$tag_title = pht('Disabled');
$tag_shade = PHUITagView::COLOR_RED;
} else if (!$user->getIsApproved()) {
$tag_icon = 'fa-ban';
$tag_title = pht('Unapproved Account');
$tag_shade = PHUITagView::COLOR_RED;
} else if (!$user->getIsEmailVerified()) {
$tag_icon = 'fa-envelope';
$tag_title = pht('Email Not Verified');
$tag_shade = PHUITagView::COLOR_RED;
} else if ($user->getIsAdmin()) {
$tag_icon = 'fa-star';
$tag_title = pht('Administrator');
$tag_shade = PHUITagView::COLOR_INDIGO;
} else {
$tag_icon = PhabricatorPeopleIconSet::getIconIcon($profile->getIcon());
$tag_title = $profile->getDisplayTitle();
$tag_shade = null;
}
$tag = id(new PHUITagView())
->setIcon($profile_icon)
->setName($profile_title)
->addClass('project-view-header-tag')
->setIcon($tag_icon)
->setName($tag_title)
->setType(PHUITagView::TYPE_SHADE);
if ($tag_shade !== null) {
$tag->setShade($tag_shade);
}
$header = id(new PHUIHeaderView())
->setHeader(array($user->getFullName(), $tag))
->setHeader($user->getFullName())
->addTag($tag)
->setUser($viewer)
->setImage($picture);
@ -70,7 +97,7 @@ final class PhabricatorUserCardView extends AphrontTagView {
$body[] = $this->addItem(
pht('User Since'),
phabricator_date($profile->getDateCreated(), $viewer));
phabricator_date($user->getDateCreated(), $viewer));
if (PhabricatorApplication::isClassInstalledForViewer(
'PhabricatorCalendarApplication',

Some files were not shown because too many files have changed in this diff Show more