Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/herald/adapter/HeraldCommitAdapter.php b/src/applications/herald/adapter/HeraldCommitAdapter.php
index 35cb0e0ddf..754912d6e0 100644
--- a/src/applications/herald/adapter/HeraldCommitAdapter.php
+++ b/src/applications/herald/adapter/HeraldCommitAdapter.php
@@ -1,241 +1,241 @@
<?php
final class HeraldCommitAdapter extends HeraldObjectAdapter {
protected $diff;
protected $revision;
protected $repository;
protected $commit;
protected $commitData;
protected $emailPHIDs = array();
protected $auditMap = array();
protected $affectedPaths;
protected $affectedRevision;
protected $affectedPackages;
protected $auditNeededPackages;
public function __construct(
PhabricatorRepository $repository,
PhabricatorRepositoryCommit $commit,
PhabricatorRepositoryCommitData $commit_data) {
$this->repository = $repository;
$this->commit = $commit;
$this->commitData = $commit_data;
}
public function getPHID() {
return $this->commit->getPHID();
}
public function getEmailPHIDs() {
return array_keys($this->emailPHIDs);
}
public function getAuditMap() {
return $this->auditMap;
}
public function getHeraldName() {
return
'r'.
$this->repository->getCallsign().
$this->commit->getCommitIdentifier();
}
public function getHeraldTypeName() {
return HeraldContentTypeConfig::CONTENT_TYPE_COMMIT;
}
public function loadAffectedPaths() {
if ($this->affectedPaths === null) {
$result = PhabricatorOwnerPathQuery::loadAffectedPaths(
$this->repository,
$this->commit,
PhabricatorUser::getOmnipotentUser());
$this->affectedPaths = $result;
}
return $this->affectedPaths;
}
public function loadAffectedPackages() {
if ($this->affectedPackages === null) {
$packages = PhabricatorOwnersPackage::loadAffectedPackages(
$this->repository,
$this->loadAffectedPaths());
$this->affectedPackages = $packages;
}
return $this->affectedPackages;
}
public function loadAuditNeededPackage() {
if ($this->auditNeededPackages === null) {
$status_arr = array(
PhabricatorAuditStatusConstants::AUDIT_REQUIRED,
PhabricatorAuditStatusConstants::CONCERNED,
);
$requests = id(new PhabricatorRepositoryAuditRequest())
->loadAllWhere(
"commitPHID = %s AND auditStatus IN (%Ls)",
$this->commit->getPHID(),
$status_arr);
$packages = mpull($requests, 'getAuditorPHID');
$this->auditNeededPackages = $packages;
}
return $this->auditNeededPackages;
}
public function loadDifferentialRevision() {
if ($this->affectedRevision === null) {
$this->affectedRevision = false;
$data = $this->commitData;
$revision_id = $data->getCommitDetail('differential.revisionID');
if ($revision_id) {
$revision = id(new DifferentialRevision())->load($revision_id);
if ($revision) {
$revision->loadRelationships();
$this->affectedRevision = $revision;
}
}
}
return $this->affectedRevision;
}
private function loadCommitDiff() {
$drequest = DiffusionRequest::newFromDictionary(
array(
'user' => PhabricatorUser::getOmnipotentUser(),
'repository' => $this->repository,
'commit' => $this->commit->getCommitIdentifier(),
));
$raw = DiffusionQuery::callConduitWithDiffusionRequest(
$drequest,
PhabricatorUser::getOmnipotentUser(),
'diffusion.rawdiffquery',
array(
'commit' => $this->commit->getCommitIdentifier(),
'timeout' => 60 * 60 * 15,
'linesOfContext' => 0));
$parser = new ArcanistDiffParser();
$changes = $parser->parseDiff($raw);
$diff = DifferentialDiff::newFromRawChanges($changes);
return $diff;
}
public function getHeraldField($field) {
$data = $this->commitData;
switch ($field) {
case HeraldFieldConfig::FIELD_BODY:
return $data->getCommitMessage();
case HeraldFieldConfig::FIELD_AUTHOR:
return $data->getCommitDetail('authorPHID');
case HeraldFieldConfig::FIELD_REVIEWER:
return $data->getCommitDetail('reviewerPHID');
case HeraldFieldConfig::FIELD_DIFF_FILE:
return $this->loadAffectedPaths();
case HeraldFieldConfig::FIELD_REPOSITORY:
return $this->repository->getPHID();
case HeraldFieldConfig::FIELD_DIFF_CONTENT:
try {
$diff = $this->loadCommitDiff();
} catch (Exception $ex) {
return array(
'<<< Failed to load diff, this may mean the change was '.
'unimaginably enormous. >>>');
}
$dict = array();
$lines = array();
$changes = $diff->getChangesets();
foreach ($changes as $change) {
$lines = array();
foreach ($change->getHunks() as $hunk) {
$lines[] = $hunk->makeChanges();
}
$dict[$change->getFilename()] = implode("\n", $lines);
}
return $dict;
case HeraldFieldConfig::FIELD_AFFECTED_PACKAGE:
$packages = $this->loadAffectedPackages();
return mpull($packages, 'getPHID');
case HeraldFieldConfig::FIELD_AFFECTED_PACKAGE_OWNER:
$packages = $this->loadAffectedPackages();
$owners = PhabricatorOwnersOwner::loadAllForPackages($packages);
return mpull($owners, 'getUserPHID');
case HeraldFieldConfig::FIELD_NEED_AUDIT_FOR_PACKAGE:
return $this->loadAuditNeededPackage();
case HeraldFieldConfig::FIELD_DIFFERENTIAL_REVISION:
$revision = $this->loadDifferentialRevision();
if (!$revision) {
return null;
}
return $revision->getID();
case HeraldFieldConfig::FIELD_DIFFERENTIAL_REVIEWERS:
$revision = $this->loadDifferentialRevision();
if (!$revision) {
return array();
}
return $revision->getReviewers();
case HeraldFieldConfig::FIELD_DIFFERENTIAL_CCS:
$revision = $this->loadDifferentialRevision();
if (!$revision) {
return array();
}
return $revision->getCCPHIDs();
default:
throw new Exception("Invalid field '{$field}'.");
}
}
public function applyHeraldEffects(array $effects) {
assert_instances_of($effects, 'HeraldEffect');
$result = array();
foreach ($effects as $effect) {
$action = $effect->getAction();
switch ($action) {
case HeraldActionConfig::ACTION_NOTHING:
$result[] = new HeraldApplyTranscript(
$effect,
true,
- 'Great success at doing nothing.');
+ pht('Great success at doing nothing.'));
break;
case HeraldActionConfig::ACTION_EMAIL:
foreach ($effect->getTarget() as $phid) {
$this->emailPHIDs[$phid] = true;
}
$result[] = new HeraldApplyTranscript(
$effect,
true,
- 'Added address to email targets.');
+ pht('Added address to email targets.'));
break;
case HeraldActionConfig::ACTION_AUDIT:
foreach ($effect->getTarget() as $phid) {
if (empty($this->auditMap[$phid])) {
$this->auditMap[$phid] = array();
}
$this->auditMap[$phid][] = $effect->getRuleID();
}
$result[] = new HeraldApplyTranscript(
$effect,
true,
- 'Triggered an audit.');
+ pht('Triggered an audit.'));
break;
case HeraldActionConfig::ACTION_FLAG:
$result[] = parent::applyFlagEffect(
$effect,
$this->commit->getPHID());
break;
default:
throw new Exception("No rules to handle action '{$action}'.");
}
}
return $result;
}
}
diff --git a/src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php b/src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php
index a4be15d361..d17b560b52 100644
--- a/src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php
+++ b/src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php
@@ -1,301 +1,301 @@
<?php
final class HeraldDifferentialRevisionAdapter extends HeraldObjectAdapter {
protected $revision;
protected $diff;
protected $explicitCCs;
protected $explicitReviewers;
protected $forbiddenCCs;
protected $newCCs = array();
protected $remCCs = array();
protected $emailPHIDs = array();
protected $repository;
protected $affectedPackages;
protected $changesets;
public function __construct(
DifferentialRevision $revision,
DifferentialDiff $diff) {
$revision->loadRelationships();
$this->revision = $revision;
$this->diff = $diff;
}
public function setExplicitCCs($explicit_ccs) {
$this->explicitCCs = $explicit_ccs;
return $this;
}
public function setExplicitReviewers($explicit_reviewers) {
$this->explicitReviewers = $explicit_reviewers;
return $this;
}
public function setForbiddenCCs($forbidden_ccs) {
$this->forbiddenCCs = $forbidden_ccs;
return $this;
}
public function getCCsAddedByHerald() {
return array_diff_key($this->newCCs, $this->remCCs);
}
public function getCCsRemovedByHerald() {
return $this->remCCs;
}
public function getEmailPHIDsAddedByHerald() {
return $this->emailPHIDs;
}
public function getPHID() {
return $this->revision->getPHID();
}
public function getHeraldName() {
return $this->revision->getTitle();
}
public function getHeraldTypeName() {
return HeraldContentTypeConfig::CONTENT_TYPE_DIFFERENTIAL;
}
public function loadRepository() {
if ($this->repository === null) {
$diff = $this->diff;
$repository = false;
if ($diff->getRepositoryUUID()) {
$repository = id(new PhabricatorRepository())->loadOneWhere(
'uuid = %s',
$diff->getRepositoryUUID());
}
if (!$repository && $diff->getArcanistProjectPHID()) {
$project = id(new PhabricatorRepositoryArcanistProject())->loadOneWhere(
'phid = %s',
$diff->getArcanistProjectPHID());
if ($project && $project->getRepositoryID()) {
$repository = id(new PhabricatorRepository())->load(
$project->getRepositoryID());
}
}
$this->repository = $repository;
}
return $this->repository;
}
protected function loadChangesets() {
if ($this->changesets === null) {
$this->changesets = $this->diff->loadChangesets();
}
return $this->changesets;
}
protected function loadAffectedPaths() {
$changesets = $this->loadChangesets();
$paths = array();
foreach ($changesets as $changeset) {
$paths[] = $this->getAbsoluteRepositoryPathForChangeset($changeset);
}
return $paths;
}
protected function getAbsoluteRepositoryPathForChangeset(
DifferentialChangeset $changeset) {
$repository = $this->loadRepository();
if (!$repository) {
return '/'.ltrim($changeset->getFilename(), '/');
}
$diff = $this->diff;
return $changeset->getAbsoluteRepositoryPath($repository, $diff);
}
protected function loadContentDictionary() {
$changesets = $this->loadChangesets();
$hunks = array();
if ($changesets) {
$hunks = id(new DifferentialHunk())->loadAllWhere(
'changesetID in (%Ld)',
mpull($changesets, 'getID'));
}
$dict = array();
$hunks = mgroup($hunks, 'getChangesetID');
$changesets = mpull($changesets, null, 'getID');
foreach ($changesets as $id => $changeset) {
$path = $this->getAbsoluteRepositoryPathForChangeset($changeset);
$content = array();
foreach (idx($hunks, $id, array()) as $hunk) {
$content[] = $hunk->makeChanges();
}
$dict[$path] = implode("\n", $content);
}
return $dict;
}
public function loadAffectedPackages() {
if ($this->affectedPackages === null) {
$this->affectedPackages = array();
$repository = $this->loadRepository();
if ($repository) {
$packages = PhabricatorOwnersPackage::loadAffectedPackages(
$repository,
$this->loadAffectedPaths());
$this->affectedPackages = $packages;
}
}
return $this->affectedPackages;
}
public function getHeraldField($field) {
switch ($field) {
case HeraldFieldConfig::FIELD_TITLE:
return $this->revision->getTitle();
break;
case HeraldFieldConfig::FIELD_BODY:
return $this->revision->getSummary()."\n".
$this->revision->getTestPlan();
break;
case HeraldFieldConfig::FIELD_AUTHOR:
return $this->revision->getAuthorPHID();
break;
case HeraldFieldConfig::FIELD_DIFF_FILE:
return $this->loadAffectedPaths();
case HeraldFieldConfig::FIELD_CC:
if (isset($this->explicitCCs)) {
return array_keys($this->explicitCCs);
} else {
return $this->revision->getCCPHIDs();
}
case HeraldFieldConfig::FIELD_REVIEWERS:
if (isset($this->explicitReviewers)) {
return array_keys($this->explicitReviewers);
} else {
return $this->revision->getReviewers();
}
case HeraldFieldConfig::FIELD_REPOSITORY:
$repository = $this->loadRepository();
if (!$repository) {
return null;
}
return $repository->getPHID();
case HeraldFieldConfig::FIELD_DIFF_CONTENT:
return $this->loadContentDictionary();
case HeraldFieldConfig::FIELD_AFFECTED_PACKAGE:
$packages = $this->loadAffectedPackages();
return mpull($packages, 'getPHID');
case HeraldFieldConfig::FIELD_AFFECTED_PACKAGE_OWNER:
$packages = $this->loadAffectedPackages();
return PhabricatorOwnersOwner::loadAffiliatedUserPHIDs(
mpull($packages, 'getID'));
default:
throw new Exception("Invalid field '{$field}'.");
}
}
public function applyHeraldEffects(array $effects) {
assert_instances_of($effects, 'HeraldEffect');
$result = array();
if ($this->explicitCCs) {
$effect = new HeraldEffect();
$effect->setAction(HeraldActionConfig::ACTION_ADD_CC);
$effect->setTarget(array_keys($this->explicitCCs));
$effect->setReason(
- 'CCs provided explicitly by revision author or carried over from a '.
- 'previous version of the revision.');
+ pht('CCs provided explicitly by revision author or carried over '.
+ 'from a previous version of the revision.'));
$result[] = new HeraldApplyTranscript(
$effect,
true,
- 'Added addresses to CC list.');
+ pht('Added addresses to CC list.'));
}
$forbidden_ccs = array_fill_keys(
nonempty($this->forbiddenCCs, array()),
true);
foreach ($effects as $effect) {
$action = $effect->getAction();
switch ($action) {
case HeraldActionConfig::ACTION_NOTHING:
$result[] = new HeraldApplyTranscript(
$effect,
true,
- 'OK, did nothing.');
+ pht('OK, did nothing.'));
break;
case HeraldActionConfig::ACTION_FLAG:
$result[] = parent::applyFlagEffect(
$effect,
$this->revision->getPHID());
break;
case HeraldActionConfig::ACTION_EMAIL:
case HeraldActionConfig::ACTION_ADD_CC:
$op = ($action == HeraldActionConfig::ACTION_EMAIL) ? 'email' : 'CC';
$base_target = $effect->getTarget();
$forbidden = array();
foreach ($base_target as $key => $fbid) {
if (isset($forbidden_ccs[$fbid])) {
$forbidden[] = $fbid;
unset($base_target[$key]);
} else {
if ($action == HeraldActionConfig::ACTION_EMAIL) {
$this->emailPHIDs[$fbid] = true;
} else {
$this->newCCs[$fbid] = true;
}
}
}
if ($forbidden) {
$failed = clone $effect;
$failed->setTarget($forbidden);
if ($base_target) {
$effect->setTarget($base_target);
$result[] = new HeraldApplyTranscript(
$effect,
true,
- 'Added these addresses to '.$op.' list. '.
- 'Others could not be added.');
+ pht('Added these addresses to %s list. '.
+ 'Others could not be added.', $op));
}
$result[] = new HeraldApplyTranscript(
$failed,
false,
- $op.' forbidden, these addresses have unsubscribed.');
+ pht('%s forbidden, these addresses have unsubscribed.', $op));
} else {
$result[] = new HeraldApplyTranscript(
$effect,
true,
- 'Added addresses to '.$op.' list.');
+ pht('Added addresses to %s list.', $op));
}
break;
case HeraldActionConfig::ACTION_REMOVE_CC:
foreach ($effect->getTarget() as $fbid) {
$this->remCCs[$fbid] = true;
}
$result[] = new HeraldApplyTranscript(
$effect,
true,
- 'Removed addresses from CC list.');
+ pht('Removed addresses from CC list.'));
break;
default:
throw new Exception("No rules to handle action '{$action}'.");
}
}
return $result;
}
}
diff --git a/src/applications/herald/adapter/HeraldDryRunAdapter.php b/src/applications/herald/adapter/HeraldDryRunAdapter.php
index 4c58374578..8d82e0da64 100644
--- a/src/applications/herald/adapter/HeraldDryRunAdapter.php
+++ b/src/applications/herald/adapter/HeraldDryRunAdapter.php
@@ -1,32 +1,32 @@
<?php
final class HeraldDryRunAdapter extends HeraldObjectAdapter {
public function getPHID() {
return 0;
}
public function getHeraldName() {
return 'Dry Run';
}
public function getHeraldTypeName() {
return null;
}
public function getHeraldField($field) {
return null;
}
public function applyHeraldEffects(array $effects) {
assert_instances_of($effects, 'HeraldEffect');
$results = array();
foreach ($effects as $effect) {
$results[] = new HeraldApplyTranscript(
$effect,
false,
- 'This was a dry run, so no actions were actually taken.');
+ pht('This was a dry run, so no actions were actually taken.'));
}
return $results;
}
}
diff --git a/src/applications/herald/adapter/HeraldObjectAdapter.php b/src/applications/herald/adapter/HeraldObjectAdapter.php
index 0a1d2c7b43..7b2949ed8d 100644
--- a/src/applications/herald/adapter/HeraldObjectAdapter.php
+++ b/src/applications/herald/adapter/HeraldObjectAdapter.php
@@ -1,51 +1,52 @@
<?php
abstract class HeraldObjectAdapter {
abstract public function getPHID();
abstract public function getHeraldName();
abstract public function getHeraldTypeName();
abstract public function getHeraldField($field_name);
abstract public function applyHeraldEffects(array $effects);
public static function applyFlagEffect(HeraldEffect $effect, $phid) {
$color = $effect->getTarget();
// TODO: Silly that we need to load this again here.
$rule = id(new HeraldRule())->load($effect->getRuleID());
$user = id(new PhabricatorUser())->loadOneWhere(
'phid = %s',
$rule->getAuthorPHID());
$flag = PhabricatorFlagQuery::loadUserFlag($user, $phid);
if ($flag) {
return new HeraldApplyTranscript(
$effect,
false,
- 'Object already flagged.');
+ pht('Object already flagged.'));
}
$handle = PhabricatorObjectHandleData::loadOneHandle(
$phid,
$user);
$flag = new PhabricatorFlag();
$flag->setOwnerPHID($user->getPHID());
$flag->setType($handle->getType());
$flag->setObjectPHID($handle->getPHID());
// TOOD: Should really be transcript PHID, but it doesn't exist yet.
$flag->setReasonPHID($user->getPHID());
$flag->setColor($color);
- $flag->setNote('Flagged by Herald Rule "'.$rule->getName().'".');
+ $flag->setNote(
+ pht('Flagged by Herald Rule "%s".', $rule->getName()));
$flag->save();
return new HeraldApplyTranscript(
$effect,
true,
- 'Added flag.');
+ pht('Added flag.'));
}
}
diff --git a/src/applications/herald/application/PhabricatorApplicationHerald.php b/src/applications/herald/application/PhabricatorApplicationHerald.php
index 7687a906ea..f751971093 100644
--- a/src/applications/herald/application/PhabricatorApplicationHerald.php
+++ b/src/applications/herald/application/PhabricatorApplicationHerald.php
@@ -1,52 +1,52 @@
<?php
final class PhabricatorApplicationHerald extends PhabricatorApplication {
public function getBaseURI() {
return '/herald/';
}
public function getIconName() {
return 'herald';
}
public function getShortDescription() {
- return 'Create Notification Rules';
+ return pht('Create Notification Rules');
}
public function getTitleGlyph() {
return "\xE2\x98\xBF";
}
public function getHelpURI() {
return PhabricatorEnv::getDoclink('article/Herald_User_Guide.html');
}
public function getFlavorText() {
return pht('Watch for danger!');
}
public function getApplicationGroup() {
return self::GROUP_ORGANIZATION;
}
public function getRoutes() {
return array(
'/herald/' => array(
'' => 'HeraldHomeController',
'view/(?P<content_type>[^/]+)/(?:(?P<rule_type>[^/]+)/)?'
=> 'HeraldHomeController',
'new/(?:(?P<type>[^/]+)/(?:(?P<rule_type>[^/]+)/)?)?'
=> 'HeraldNewController',
'rule/(?:(?P<id>[1-9]\d*)/)?' => 'HeraldRuleController',
'history/(?:(?P<id>[1-9]\d*)/)?' => 'HeraldRuleEditHistoryController',
'delete/(?P<id>[1-9]\d*)/' => 'HeraldDeleteController',
'test/' => 'HeraldTestConsoleController',
'transcript/' => 'HeraldTranscriptListController',
'transcript/(?P<id>[1-9]\d*)/(?:(?P<filter>\w+)/)?'
=> 'HeraldTranscriptController',
),
);
}
}
diff --git a/src/applications/herald/config/HeraldActionConfig.php b/src/applications/herald/config/HeraldActionConfig.php
index ea7a8d3cb4..1194fdfcec 100644
--- a/src/applications/herald/config/HeraldActionConfig.php
+++ b/src/applications/herald/config/HeraldActionConfig.php
@@ -1,136 +1,136 @@
<?php
final class HeraldActionConfig {
const ACTION_ADD_CC = 'addcc';
const ACTION_REMOVE_CC = 'remcc';
const ACTION_EMAIL = 'email';
const ACTION_NOTHING = 'nothing';
const ACTION_AUDIT = 'audit';
const ACTION_FLAG = 'flag';
public static function getActionMessageMapForRuleType($rule_type) {
$generic_mappings = array(
- self::ACTION_NOTHING => 'Do nothing',
- self::ACTION_ADD_CC => 'Add emails to CC',
- self::ACTION_REMOVE_CC => 'Remove emails from CC',
- self::ACTION_EMAIL => 'Send an email to',
- self::ACTION_AUDIT => 'Trigger an Audit',
- self::ACTION_FLAG => 'Mark with flag',
+ self::ACTION_NOTHING => pht('Do nothing'),
+ self::ACTION_ADD_CC => pht('Add emails to CC'),
+ self::ACTION_REMOVE_CC => pht('Remove emails from CC'),
+ self::ACTION_EMAIL => pht('Send an email to'),
+ self::ACTION_AUDIT => pht('Trigger an Audit'),
+ self::ACTION_FLAG => pht('Mark with flag'),
);
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
$specific_mappings = array(
- self::ACTION_AUDIT => 'Trigger an Audit for project',
+ self::ACTION_AUDIT => pht('Trigger an Audit for project'),
);
break;
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
$specific_mappings = array(
- self::ACTION_ADD_CC => 'CC me',
- self::ACTION_REMOVE_CC => 'Remove me from CC',
- self::ACTION_EMAIL => 'Email me',
- self::ACTION_AUDIT => 'Trigger an Audit by me',
+ self::ACTION_ADD_CC => pht('CC me'),
+ self::ACTION_REMOVE_CC => pht('Remove me from CC'),
+ self::ACTION_EMAIL => pht('Email me'),
+ self::ACTION_AUDIT => pht('Trigger an Audit by me'),
);
break;
case null:
$specific_mappings = array();
// Use generic mappings, used on transcript.
break;
default:
throw new Exception("Unknown rule type '${rule_type}'");
}
return $specific_mappings + $generic_mappings;
}
public static function getActionMessageMap($content_type,
$rule_type) {
$map = self::getActionMessageMapForRuleType($rule_type);
switch ($content_type) {
case HeraldContentTypeConfig::CONTENT_TYPE_DIFFERENTIAL:
return array_select_keys(
$map,
array(
self::ACTION_ADD_CC,
self::ACTION_REMOVE_CC,
self::ACTION_EMAIL,
self::ACTION_FLAG,
self::ACTION_NOTHING,
));
case HeraldContentTypeConfig::CONTENT_TYPE_COMMIT:
return array_select_keys(
$map,
array(
self::ACTION_EMAIL,
self::ACTION_AUDIT,
self::ACTION_FLAG,
self::ACTION_NOTHING,
));
case HeraldContentTypeConfig::CONTENT_TYPE_MERGE:
return array_select_keys(
$map,
array(
self::ACTION_EMAIL,
self::ACTION_NOTHING,
));
case HeraldContentTypeConfig::CONTENT_TYPE_OWNERS:
return array_select_keys(
$map,
array(
self::ACTION_EMAIL,
self::ACTION_NOTHING,
));
default:
throw new Exception("Unknown content type '{$content_type}'.");
}
}
/**
* Create a HeraldAction to save from data.
*
* $data is of the form:
* array(
* 0 => <action type>
* 1 => array(<targets>)
* )
*/
public static function willSaveAction($rule_type,
$author_phid,
$data) {
$obj = new HeraldAction();
$obj->setAction($data[0]);
// for personal rule types, set the target to be the owner of the rule
if ($rule_type == HeraldRuleTypeConfig::RULE_TYPE_PERSONAL) {
switch ($obj->getAction()) {
case HeraldActionConfig::ACTION_EMAIL:
case HeraldActionConfig::ACTION_ADD_CC:
case HeraldActionConfig::ACTION_REMOVE_CC:
case HeraldActionConfig::ACTION_AUDIT:
$data[1] = array($author_phid => $author_phid);
break;
case HeraldActionConfig::ACTION_FLAG:
// Make sure flag color is valid; set to blue if not.
$color_map = PhabricatorFlagColor::getColorNameMap();
if (empty($color_map[$data[1]])) {
$data[1] = PhabricatorFlagColor::COLOR_BLUE;
}
break;
case HeraldActionConfig::ACTION_NOTHING:
break;
default:
throw new Exception('Unrecognized action type: ' .
$obj->getAction());
}
}
if (is_array($data[1])) {
$obj->setTarget(array_keys($data[1]));
} else {
$obj->setTarget($data[1]);
}
return $obj;
}
}
diff --git a/src/applications/herald/config/HeraldConditionConfig.php b/src/applications/herald/config/HeraldConditionConfig.php
index 55fc1e9718..b273ebf2ba 100644
--- a/src/applications/herald/config/HeraldConditionConfig.php
+++ b/src/applications/herald/config/HeraldConditionConfig.php
@@ -1,126 +1,126 @@
<?php
final class HeraldConditionConfig {
const CONDITION_CONTAINS = 'contains';
const CONDITION_NOT_CONTAINS = '!contains';
const CONDITION_IS = 'is';
const CONDITION_IS_NOT = '!is';
const CONDITION_IS_ANY = 'isany';
const CONDITION_IS_NOT_ANY = '!isany';
const CONDITION_INCLUDE_ALL = 'all';
const CONDITION_INCLUDE_ANY = 'any';
const CONDITION_INCLUDE_NONE = 'none';
const CONDITION_IS_ME = 'me';
const CONDITION_IS_NOT_ME = '!me';
const CONDITION_REGEXP = 'regexp';
const CONDITION_RULE = 'conditions';
const CONDITION_NOT_RULE = '!conditions';
const CONDITION_EXISTS = 'exists';
const CONDITION_NOT_EXISTS = '!exists';
const CONDITION_REGEXP_PAIR = 'regexp-pair';
public static function getConditionMap() {
- static $map = array(
- self::CONDITION_CONTAINS => 'contains',
- self::CONDITION_NOT_CONTAINS => 'does not contain',
- self::CONDITION_IS => 'is',
- self::CONDITION_IS_NOT => 'is not',
- self::CONDITION_IS_ANY => 'is any of',
- self::CONDITION_IS_NOT_ANY => 'is not any of',
- self::CONDITION_INCLUDE_ALL => 'include all of',
- self::CONDITION_INCLUDE_ANY => 'include any of',
- self::CONDITION_INCLUDE_NONE => 'include none of',
- self::CONDITION_IS_ME => 'is myself',
- self::CONDITION_IS_NOT_ME => 'is not myself',
- self::CONDITION_REGEXP => 'matches regexp',
- self::CONDITION_RULE => 'matches:',
- self::CONDITION_NOT_RULE => 'does not match:',
- self::CONDITION_EXISTS => 'exists',
- self::CONDITION_NOT_EXISTS => 'does not exist',
- self::CONDITION_REGEXP_PAIR => 'matches regexp pair',
+ $map = array(
+ self::CONDITION_CONTAINS => pht('contains'),
+ self::CONDITION_NOT_CONTAINS => pht('does not contain'),
+ self::CONDITION_IS => pht('is'),
+ self::CONDITION_IS_NOT => pht('is not'),
+ self::CONDITION_IS_ANY => pht('is any of'),
+ self::CONDITION_IS_NOT_ANY => pht('is not any of'),
+ self::CONDITION_INCLUDE_ALL => pht('include all of'),
+ self::CONDITION_INCLUDE_ANY => pht('include any of'),
+ self::CONDITION_INCLUDE_NONE => pht('include none of'),
+ self::CONDITION_IS_ME => pht('is myself'),
+ self::CONDITION_IS_NOT_ME => pht('is not myself'),
+ self::CONDITION_REGEXP => pht('matches regexp'),
+ self::CONDITION_RULE => pht('matches:'),
+ self::CONDITION_NOT_RULE => pht('does not match:'),
+ self::CONDITION_EXISTS => pht('exists'),
+ self::CONDITION_NOT_EXISTS => pht('does not exist'),
+ self::CONDITION_REGEXP_PAIR => pht('matches regexp pair'),
);
return $map;
}
public static function getConditionMapForField($field) {
$map = self::getConditionMap();
switch ($field) {
case HeraldFieldConfig::FIELD_TITLE:
case HeraldFieldConfig::FIELD_BODY:
return array_select_keys(
$map,
array(
self::CONDITION_CONTAINS,
self::CONDITION_NOT_CONTAINS,
self::CONDITION_IS,
self::CONDITION_IS_NOT,
self::CONDITION_REGEXP,
));
case HeraldFieldConfig::FIELD_AUTHOR:
case HeraldFieldConfig::FIELD_REPOSITORY:
case HeraldFieldConfig::FIELD_REVIEWER:
case HeraldFieldConfig::FIELD_MERGE_REQUESTER:
return array_select_keys(
$map,
array(
self::CONDITION_IS_ANY,
self::CONDITION_IS_NOT_ANY,
));
case HeraldFieldConfig::FIELD_TAGS:
case HeraldFieldConfig::FIELD_REVIEWERS:
case HeraldFieldConfig::FIELD_CC:
case HeraldFieldConfig::FIELD_DIFFERENTIAL_REVIEWERS:
case HeraldFieldConfig::FIELD_DIFFERENTIAL_CCS:
return array_select_keys(
$map,
array(
self::CONDITION_INCLUDE_ALL,
self::CONDITION_INCLUDE_ANY,
self::CONDITION_INCLUDE_NONE,
));
case HeraldFieldConfig::FIELD_DIFF_FILE:
return array_select_keys(
$map,
array(
self::CONDITION_CONTAINS,
self::CONDITION_REGEXP,
));
case HeraldFieldConfig::FIELD_DIFF_CONTENT:
return array_select_keys(
$map,
array(
self::CONDITION_CONTAINS,
self::CONDITION_REGEXP,
self::CONDITION_REGEXP_PAIR,
));
case HeraldFieldConfig::FIELD_RULE:
return array_select_keys(
$map,
array(
self::CONDITION_RULE,
self::CONDITION_NOT_RULE,
));
case HeraldFieldConfig::FIELD_AFFECTED_PACKAGE:
case HeraldFieldConfig::FIELD_AFFECTED_PACKAGE_OWNER:
case HeraldFieldConfig::FIELD_NEED_AUDIT_FOR_PACKAGE:
return array_select_keys(
$map,
array(
self::CONDITION_INCLUDE_ANY,
self::CONDITION_INCLUDE_NONE,
));
case HeraldFieldConfig::FIELD_DIFFERENTIAL_REVISION:
return array_select_keys(
$map,
array(
self::CONDITION_EXISTS,
self::CONDITION_NOT_EXISTS,
));
default:
throw new Exception("Unknown field type '{$field}'.");
}
}
}
diff --git a/src/applications/herald/config/HeraldContentTypeConfig.php b/src/applications/herald/config/HeraldContentTypeConfig.php
index 364a6f0912..01ea861b67 100644
--- a/src/applications/herald/config/HeraldContentTypeConfig.php
+++ b/src/applications/herald/config/HeraldContentTypeConfig.php
@@ -1,21 +1,21 @@
<?php
final class HeraldContentTypeConfig {
const CONTENT_TYPE_DIFFERENTIAL = 'differential';
const CONTENT_TYPE_COMMIT = 'commit';
const CONTENT_TYPE_MERGE = 'merge';
const CONTENT_TYPE_OWNERS = 'owners';
public static function getContentTypeMap() {
- static $map = array(
- self::CONTENT_TYPE_DIFFERENTIAL => 'Differential Revisions',
- self::CONTENT_TYPE_COMMIT => 'Commits',
+ $map = array(
+ self::CONTENT_TYPE_DIFFERENTIAL => pht('Differential Revisions'),
+ self::CONTENT_TYPE_COMMIT => pht('Commits'),
/* TODO: Deal with this
self::CONTENT_TYPE_MERGE => 'Merge Requests',
self::CONTENT_TYPE_OWNERS => 'Owners Changes',
*/
);
return $map;
}
}
diff --git a/src/applications/herald/config/HeraldFieldConfig.php b/src/applications/herald/config/HeraldFieldConfig.php
index d2273e27ac..8942815102 100644
--- a/src/applications/herald/config/HeraldFieldConfig.php
+++ b/src/applications/herald/config/HeraldFieldConfig.php
@@ -1,118 +1,119 @@
<?php
final class HeraldFieldConfig {
const FIELD_TITLE = 'title';
const FIELD_BODY = 'body';
const FIELD_AUTHOR = 'author';
const FIELD_REVIEWER = 'reviewer';
const FIELD_REVIEWERS = 'reviewers';
const FIELD_CC = 'cc';
const FIELD_TAGS = 'tags';
const FIELD_DIFF_FILE = 'diff-file';
const FIELD_DIFF_CONTENT = 'diff-content';
const FIELD_REPOSITORY = 'repository';
const FIELD_RULE = 'rule';
const FIELD_AFFECTED_PACKAGE = 'affected-package';
const FIELD_AFFECTED_PACKAGE_OWNER = 'affected-package-owner';
const FIELD_NEED_AUDIT_FOR_PACKAGE = 'need-audit-for-package';
const FIELD_DIFFERENTIAL_REVISION = 'differential-revision';
const FIELD_DIFFERENTIAL_REVIEWERS = 'differential-reviewers';
const FIELD_DIFFERENTIAL_CCS = 'differential-ccs';
const FIELD_MERGE_REQUESTER = 'merge-requester';
public static function getFieldMap() {
- static $map = array(
- self::FIELD_TITLE => 'Title',
- self::FIELD_BODY => 'Body',
- self::FIELD_AUTHOR => 'Author',
- self::FIELD_REVIEWER => 'Reviewer',
- self::FIELD_REVIEWERS => 'Reviewers',
- self::FIELD_CC => 'CCs',
- self::FIELD_TAGS => 'Tags',
- self::FIELD_DIFF_FILE => 'Any changed filename',
- self::FIELD_DIFF_CONTENT => 'Any changed file content',
- self::FIELD_REPOSITORY => 'Repository',
- self::FIELD_RULE => 'Another Herald rule',
- self::FIELD_AFFECTED_PACKAGE => 'Any affected package',
- self::FIELD_AFFECTED_PACKAGE_OWNER => "Any affected package's owner",
+ $map = array(
+ self::FIELD_TITLE => pht('Title'),
+ self::FIELD_BODY => pht('Body'),
+ self::FIELD_AUTHOR => pht('Author'),
+ self::FIELD_REVIEWER => pht('Reviewer'),
+ self::FIELD_REVIEWERS => pht('Reviewers'),
+ self::FIELD_CC => pht('CCs'),
+ self::FIELD_TAGS => pht('Tags'),
+ self::FIELD_DIFF_FILE => pht('Any changed filename'),
+ self::FIELD_DIFF_CONTENT => pht('Any changed file content'),
+ self::FIELD_REPOSITORY => pht('Repository'),
+ self::FIELD_RULE => pht('Another Herald rule'),
+ self::FIELD_AFFECTED_PACKAGE => pht('Any affected package'),
+ self::FIELD_AFFECTED_PACKAGE_OWNER =>
+ pht("Any affected package's owner"),
self::FIELD_NEED_AUDIT_FOR_PACKAGE =>
- 'Affected packages that need audit',
- self::FIELD_DIFFERENTIAL_REVISION => 'Differential revision',
- self::FIELD_DIFFERENTIAL_REVIEWERS => 'Differential reviewers',
- self::FIELD_DIFFERENTIAL_CCS => 'Differential CCs',
- self::FIELD_MERGE_REQUESTER => 'Merge requester'
+ pht('Affected packages that need audit'),
+ self::FIELD_DIFFERENTIAL_REVISION => pht('Differential revision'),
+ self::FIELD_DIFFERENTIAL_REVIEWERS => pht('Differential reviewers'),
+ self::FIELD_DIFFERENTIAL_CCS => pht('Differential CCs'),
+ self::FIELD_MERGE_REQUESTER => pht('Merge requester')
);
return $map;
}
public static function getFieldMapForContentType($type) {
$map = self::getFieldMap();
switch ($type) {
case HeraldContentTypeConfig::CONTENT_TYPE_DIFFERENTIAL:
return array_select_keys(
$map,
array(
self::FIELD_TITLE,
self::FIELD_BODY,
self::FIELD_AUTHOR,
self::FIELD_REVIEWERS,
self::FIELD_CC,
self::FIELD_REPOSITORY,
self::FIELD_DIFF_FILE,
self::FIELD_DIFF_CONTENT,
self::FIELD_RULE,
self::FIELD_AFFECTED_PACKAGE,
self::FIELD_AFFECTED_PACKAGE_OWNER,
));
case HeraldContentTypeConfig::CONTENT_TYPE_COMMIT:
return array_select_keys(
$map,
array(
self::FIELD_BODY,
self::FIELD_AUTHOR,
self::FIELD_REVIEWER,
self::FIELD_REPOSITORY,
self::FIELD_DIFF_FILE,
self::FIELD_DIFF_CONTENT,
self::FIELD_RULE,
self::FIELD_AFFECTED_PACKAGE,
self::FIELD_AFFECTED_PACKAGE_OWNER,
self::FIELD_NEED_AUDIT_FOR_PACKAGE,
self::FIELD_DIFFERENTIAL_REVISION,
self::FIELD_DIFFERENTIAL_REVIEWERS,
self::FIELD_DIFFERENTIAL_CCS,
));
case HeraldContentTypeConfig::CONTENT_TYPE_MERGE:
return array_select_keys(
$map,
array(
self::FIELD_BODY,
self::FIELD_AUTHOR,
self::FIELD_REVIEWER,
self::FIELD_REPOSITORY,
self::FIELD_DIFF_FILE,
self::FIELD_DIFF_CONTENT,
self::FIELD_RULE,
self::FIELD_AFFECTED_PACKAGE,
self::FIELD_AFFECTED_PACKAGE_OWNER,
self::FIELD_DIFFERENTIAL_REVISION,
self::FIELD_DIFFERENTIAL_REVIEWERS,
self::FIELD_DIFFERENTIAL_CCS,
self::FIELD_MERGE_REQUESTER,
));
case HeraldContentTypeConfig::CONTENT_TYPE_OWNERS:
return array_select_keys(
$map,
array(
self::FIELD_AFFECTED_PACKAGE,
self::FIELD_AFFECTED_PACKAGE_OWNER,
));
default:
throw new Exception("Unknown content type.");
}
}
}
diff --git a/src/applications/herald/config/HeraldRuleTypeConfig.php b/src/applications/herald/config/HeraldRuleTypeConfig.php
index 7d9e4812f8..6d9712134a 100644
--- a/src/applications/herald/config/HeraldRuleTypeConfig.php
+++ b/src/applications/herald/config/HeraldRuleTypeConfig.php
@@ -1,15 +1,15 @@
<?php
final class HeraldRuleTypeConfig {
const RULE_TYPE_GLOBAL = 'global';
const RULE_TYPE_PERSONAL = 'personal';
public static function getRuleTypeMap() {
- static $map = array(
- self::RULE_TYPE_GLOBAL => 'Global',
- self::RULE_TYPE_PERSONAL => 'Personal',
+ $map = array(
+ self::RULE_TYPE_GLOBAL => pht('Global'),
+ self::RULE_TYPE_PERSONAL => pht('Personal'),
);
return $map;
}
}
diff --git a/src/applications/herald/controller/HeraldController.php b/src/applications/herald/controller/HeraldController.php
index 7ad03c5fd2..9242792316 100644
--- a/src/applications/herald/controller/HeraldController.php
+++ b/src/applications/herald/controller/HeraldController.php
@@ -1,52 +1,68 @@
<?php
abstract class HeraldController extends PhabricatorController {
public function buildStandardPageResponse($view, array $data) {
$page = $this->buildStandardPageView();
- $page->setApplicationName('Herald');
+ $page->setApplicationName(pht('Herald'));
$page->setBaseURI('/herald/');
$page->setTitle(idx($data, 'title'));
$page->setGlyph("\xE2\x98\xBF");
$page->appendChild($view);
$response = new AphrontWebpageResponse();
return $response->setContent($page->render());
}
+ public function buildApplicationMenu() {
+ return $this->renderNav()->getMenu();
+ }
+
+ public function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ $crumbs->addAction(
+ id(new PhabricatorMenuItemView())
+ ->setName(pht('Create Herald Rule'))
+ ->setHref($this->getApplicationURI('new/'))
+ ->setIcon('create'));
+
+ return $crumbs;
+ }
+
protected function renderNav() {
$nav = id(new AphrontSideNavFilterView())
->setBaseURI(new PhutilURI('/herald/'))
- ->addLabel('My Rules')
- ->addFilter('new', 'Create Rule');
+ ->addLabel(pht('My Rules'))
+ ->addFilter('new', pht('Create Rule'));
$rules_map = HeraldContentTypeConfig::getContentTypeMap();
foreach ($rules_map as $key => $value) {
$nav->addFilter("view/{$key}/personal", $value);
}
- $nav->addLabel('Global Rules');
+ $nav->addLabel(pht('Global Rules'));
foreach ($rules_map as $key => $value) {
$nav->addFilter("view/{$key}/global", $value);
}
$nav
- ->addLabel('Utilities')
- ->addFilter('test', 'Test Console')
- ->addFilter('transcript', 'Transcripts')
- ->addFilter('history', 'Edit Log');
+ ->addLabel(pht('Utilities'))
+ ->addFilter('test', pht('Test Console'))
+ ->addFilter('transcript', pht('Transcripts'))
+ ->addFilter('history', pht('Edit Log'));
if ($this->getRequest()->getUser()->getIsAdmin()) {
- $nav->addLabel('Admin');
+ $nav->addLabel(pht('Admin'));
foreach ($rules_map as $key => $value) {
$nav->addFilter("view/{$key}/all", $value);
}
}
return $nav;
}
}
diff --git a/src/applications/herald/controller/HeraldDeleteController.php b/src/applications/herald/controller/HeraldDeleteController.php
index 8649f63993..47fb857849 100644
--- a/src/applications/herald/controller/HeraldDeleteController.php
+++ b/src/applications/herald/controller/HeraldDeleteController.php
@@ -1,57 +1,58 @@
<?php
final class HeraldDeleteController extends HeraldController {
private $id;
public function getFilter() {
// note this controller is only used from a dialog-context at the moment
// and there is actually no "delete" filter
return 'delete';
}
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$rule = id(new HeraldRule())->load($this->id);
if (!$rule) {
return new Aphront404Response();
}
$request = $this->getRequest();
$user = $request->getUser();
// Anyone can delete a global rule, but only the rule owner can delete a
// personal one.
if ($rule->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_PERSONAL) {
if ($user->getPHID() != $rule->getAuthorPHID()) {
return new Aphront400Response();
}
}
if ($request->isFormPost()) {
$rule->openTransaction();
$rule->logEdit($user->getPHID(), 'delete');
$rule->delete();
$rule->saveTransaction();
return id(new AphrontReloadResponse())->setURI('/herald/');
}
$dialog = new AphrontDialogView();
$dialog->setUser($request->getUser());
- $dialog->setTitle('Really delete this rule?');
- $dialog->appendChild(hsprintf(
- "Are you sure you want to delete the rule '<strong>%s</strong>'?",
+ $dialog->setTitle(pht('Really delete this rule?'));
+ $dialog->setHeaderColor(PhabricatorActionHeaderView::HEADER_RED);
+ $dialog->appendChild(pht(
+ "Are you sure you want to delete the rule: %s?",
$rule->getName()));
- $dialog->addSubmitButton('Delete');
+ $dialog->addSubmitButton(pht('Delete'));
$dialog->addCancelButton('/herald/');
$dialog->setSubmitURI($request->getPath());
return id(new AphrontDialogResponse())->setDialog($dialog);
}
}
diff --git a/src/applications/herald/controller/HeraldHomeController.php b/src/applications/herald/controller/HeraldHomeController.php
index 66d95c3956..223d70998f 100644
--- a/src/applications/herald/controller/HeraldHomeController.php
+++ b/src/applications/herald/controller/HeraldHomeController.php
@@ -1,160 +1,155 @@
<?php
final class HeraldHomeController extends HeraldController {
private $contentType;
private $ruleType;
public function willProcessRequest(array $data) {
$this->contentType = idx($data, 'content_type');
$this->ruleType = idx($data, 'rule_type');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
if ($request->isFormPost()) {
$phids = $request->getArr('set_phid');
$phid = head($phids);
$uri = $request->getRequestURI();
if ($phid) {
$uri = $uri->alter('phid', nonempty($phid, null));
}
return id(new AphrontRedirectResponse())->setURI($uri);
}
$query = new HeraldRuleQuery();
$content_type_map = HeraldContentTypeConfig::getContentTypeMap();
if (empty($content_type_map[$this->contentType])) {
$this->contentType = head_key($content_type_map);
}
$content_desc = $content_type_map[$this->contentType];
$query->withContentTypes(array($this->contentType));
- $is_admin_page = false;
$show_author = false;
$show_rule_type = false;
- $can_create = false;
$has_author_filter = false;
$author_filter_phid = null;
switch ($this->ruleType) {
case 'all':
if (!$user->getIsAdmin()) {
return new Aphront400Response();
}
- $is_admin_page = true;
$show_rule_type = true;
$show_author = true;
$has_author_filter = true;
$author_filter_phid = $request->getStr('phid');
if ($author_filter_phid) {
$query->withAuthorPHIDs(array($author_filter_phid));
}
- $rule_desc = 'All';
+ $rule_desc = pht('All');
break;
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
$query->withRuleTypes(array(HeraldRuleTypeConfig::RULE_TYPE_GLOBAL));
- $can_create = true;
- $rule_desc = 'Global';
+ $rule_desc = pht('Global');
break;
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
default:
$this->ruleType = HeraldRuleTypeConfig::RULE_TYPE_PERSONAL;
$query->withRuleTypes(array(HeraldRuleTypeConfig::RULE_TYPE_PERSONAL));
$query->withAuthorPHIDs(array($user->getPHID()));
- $can_create = true;
- $rule_desc = 'Personal';
+ $rule_desc = pht('Personal');
break;
}
$pager = new AphrontPagerView();
$pager->setURI($request->getRequestURI(), 'offset');
$pager->setOffset($request->getStr('offset'));
$rules = $query->executeWithOffsetPager($pager);
$need_phids = mpull($rules, 'getAuthorPHID');
$handles = $this->loadViewerHandles($need_phids);
$list_view = id(new HeraldRuleListView())
->setRules($rules)
->setShowAuthor($show_author)
->setShowRuleType($show_rule_type)
->setHandles($handles)
->setUser($user);
$panel = new AphrontPanelView();
$panel->appendChild($list_view);
$panel->appendChild($pager);
$panel->setNoBackground();
- $panel->setHeader("Herald: {$rule_desc} Rules for {$content_desc}");
-
- if ($can_create) {
- $panel->addButton(
- phutil_tag(
- 'a',
- array(
- 'href' => '/herald/new/'.$this->contentType.'/'.$this->ruleType.'/',
- 'class' => 'green button',
- ),
- 'Create New Herald Rule'));
- }
+ $panel->setHeader(
+ pht("Herald: %s Rules for %s", $rule_desc, $content_desc));
+ $crumbs = $this
+ ->buildApplicationCrumbs()
+ ->addCrumb(
+ id(new PhabricatorCrumbView())
+ ->setName(pht('Herald Rules'))
+ ->setHref($this->getApplicationURI(
+ 'view/'.$this->contentType.'/'.$this->ruleType)));
$nav = $this->renderNav();
$nav->selectFilter('view/'.$this->contentType.'/'.$this->ruleType);
if ($has_author_filter) {
$nav->appendChild($this->renderAuthorFilter($author_filter_phid));
}
$nav->appendChild($panel);
+ $nav->setCrumbs($crumbs);
- return $this->buildStandardPageResponse(
+ return $this->buildApplicationPage(
$nav,
array(
- 'title' => 'Herald',
- 'admin' => $is_admin_page,
+ 'title' => pht('Herald'),
+ 'dust' => true,
+ 'device' => true,
));
}
private function renderAuthorFilter($phid) {
$user = $this->getRequest()->getUser();
if ($phid) {
$handle = PhabricatorObjectHandleData::loadOneHandle(
$phid,
$user);
$tokens = array(
$phid => $handle->getFullName(),
);
} else {
$tokens = array();
}
$form = id(new AphrontFormView())
->setUser($user)
+ ->setNoShading(true)
->appendChild(
id(new AphrontFormTokenizerControl())
->setName('set_phid')
->setValue($tokens)
->setLimit(1)
- ->setLabel('Filter Author')
+ ->setLabel(pht('Filter Author'))
->setDataSource('/typeahead/common/accounts/'))
->appendChild(
id(new AphrontFormSubmitControl())
- ->setValue('Apply Filter'));
+ ->setValue(pht('Apply Filter')));
$filter = new AphrontListFilterView();
$filter->appendChild($form);
return $filter;
}
}
diff --git a/src/applications/herald/controller/HeraldNewController.php b/src/applications/herald/controller/HeraldNewController.php
index 327379b517..15e0f52cba 100644
--- a/src/applications/herald/controller/HeraldNewController.php
+++ b/src/applications/herald/controller/HeraldNewController.php
@@ -1,90 +1,95 @@
<?php
final class HeraldNewController extends HeraldController {
private $contentType;
private $ruleType;
public function willProcessRequest(array $data) {
$this->contentType = idx($data, 'type');
$this->ruleType = idx($data, 'rule_type');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$content_type_map = HeraldContentTypeConfig::getContentTypeMap();
if (empty($content_type_map[$this->contentType])) {
$this->contentType = head_key($content_type_map);
}
$rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();
if (empty($rule_type_map[$this->ruleType])) {
$this->ruleType = HeraldRuleTypeConfig::RULE_TYPE_PERSONAL;
}
// Reorder array to put "personal" first.
$rule_type_map = array_select_keys(
$rule_type_map,
array(
HeraldRuleTypeConfig::RULE_TYPE_PERSONAL,
)) + $rule_type_map;
$captions = array(
HeraldRuleTypeConfig::RULE_TYPE_PERSONAL =>
- 'Personal rules notify you about events. You own them, but they can '.
- 'only affect you.',
+ pht('Personal rules notify you about events. You own them, but '.
+ 'they can only affect you.'),
HeraldRuleTypeConfig::RULE_TYPE_GLOBAL =>
- 'Global rules notify anyone about events. No one owns them, and '.
+ pht('Global rules notify anyone about events. No one owns them, and '.
'anyone can edit them. Usually, Global rules are used to notify '.
- 'mailing lists.',
+ 'mailing lists.'),
);
$radio = id(new AphrontFormRadioButtonControl())
- ->setLabel('Type')
+ ->setLabel(pht('Type'))
->setName('rule_type')
->setValue($this->ruleType);
foreach ($rule_type_map as $value => $name) {
$radio->addButton(
$value,
$name,
idx($captions, $value));
}
$form = id(new AphrontFormView())
->setUser($user)
->setAction('/herald/rule/')
->setFlexible(true)
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('New rule for'))
->setName('content_type')
->setValue($this->contentType)
->setOptions($content_type_map))
->appendChild($radio)
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Create Rule'))
->addCancelButton('/herald/view/'.$this->contentType.'/'));
- $header = new PhabricatorHeaderView();
- $header->setHeader(pht('Create New Herald Rule'));
+ $crumbs = $this
+ ->buildApplicationCrumbs()
+ ->addCrumb(
+ id(new PhabricatorCrumbView())
+ ->setName(pht('Create Herald Rule'))
+ ->setHref($this->getApplicationURI(
+ 'view/'.$this->contentType.'/'.$this->ruleType)));
$nav = $this->renderNav();
$nav->selectFilter('new');
- $nav->appendChild($header);
$nav->appendChild($form);
+ $nav->setCrumbs($crumbs);
return $this->buildApplicationPage(
$nav,
array(
'title' => pht('Create Herald Rule'),
'device' => true,
'dust' => true,
));
}
}
diff --git a/src/applications/herald/controller/HeraldRuleController.php b/src/applications/herald/controller/HeraldRuleController.php
index fa61e4f946..44d25a29af 100644
--- a/src/applications/herald/controller/HeraldRuleController.php
+++ b/src/applications/herald/controller/HeraldRuleController.php
@@ -1,557 +1,565 @@
<?php
final class HeraldRuleController extends HeraldController {
private $id;
private $filter;
public function willProcessRequest(array $data) {
$this->id = (int)idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$content_type_map = HeraldContentTypeConfig::getContentTypeMap();
$rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();
if ($this->id) {
$rule = id(new HeraldRule())->load($this->id);
if (!$rule) {
return new Aphront404Response();
}
if (!$this->canEditRule($rule, $user)) {
throw new Exception("You don't own this rule and can't edit it.");
}
} else {
$rule = new HeraldRule();
$rule->setAuthorPHID($user->getPHID());
$rule->setMustMatchAll(true);
$content_type = $request->getStr('content_type');
if (!isset($content_type_map[$content_type])) {
$content_type = HeraldContentTypeConfig::CONTENT_TYPE_DIFFERENTIAL;
}
$rule->setContentType($content_type);
$rule_type = $request->getStr('rule_type');
if (!isset($rule_type_map[$rule_type])) {
$rule_type = HeraldRuleTypeConfig::RULE_TYPE_GLOBAL;
}
$rule->setRuleType($rule_type);
}
$local_version = id(new HeraldRule())->getConfigVersion();
if ($rule->getConfigVersion() > $local_version) {
throw new Exception(
"This rule was created with a newer version of Herald. You can not ".
"view or edit it in this older version. Upgrade your Phabricator ".
"deployment.");
}
// Upgrade rule version to our version, since we might add newly-defined
// conditions, etc.
$rule->setConfigVersion($local_version);
$rule_conditions = $rule->loadConditions();
$rule_actions = $rule->loadActions();
$rule->attachConditions($rule_conditions);
$rule->attachActions($rule_actions);
$e_name = true;
$errors = array();
if ($request->isFormPost() && $request->getStr('save')) {
list($e_name, $errors) = $this->saveRule($rule, $request);
if (!$errors) {
$uri = '/herald/view/'.
$rule->getContentType().'/'.
$rule->getRuleType().'/';
return id(new AphrontRedirectResponse())->setURI($uri);
}
}
if ($errors) {
$error_view = new AphrontErrorView();
- $error_view->setTitle('Form Errors');
+ $error_view->setTitle(pht('Form Errors'));
$error_view->setErrors($errors);
} else {
$error_view = null;
}
$must_match_selector = $this->renderMustMatchSelector($rule);
$repetition_selector = $this->renderRepetitionSelector($rule);
$handles = $this->loadHandlesForRule($rule);
require_celerity_resource('herald-css');
$content_type_name = $content_type_map[$rule->getContentType()];
$rule_type_name = $rule_type_map[$rule->getRuleType()];
$form = id(new AphrontFormView())
->setUser($user)
->setID('herald-rule-edit-form')
->addHiddenInput('content_type', $rule->getContentType())
->addHiddenInput('rule_type', $rule->getRuleType())
->addHiddenInput('save', 1)
->appendChild(
// Build this explicitly (instead of using addHiddenInput())
// so we can add a sigil to it.
javelin_tag(
'input',
array(
'type' => 'hidden',
'name' => 'rule',
'sigil' => 'rule',
)))
->appendChild(
id(new AphrontFormTextControl())
- ->setLabel('Rule Name')
+ ->setLabel(pht('Rule Name'))
->setName('name')
->setError($e_name)
->setValue($rule->getName()));
$form
->appendChild(
id(new AphrontFormMarkupControl())
- ->setValue(hsprintf(
- "This <strong>%s</strong> rule triggers for <strong>%s</strong>.",
- $rule_type_name,
- $content_type_name)))
+ ->setValue(pht(
+ "This %s rule triggers for %s.",
+ phutil_tag('strong', array(), $rule_type_name),
+ phutil_tag('strong', array(), $content_type_name))))
->appendChild(
id(new AphrontFormInsetView())
- ->setTitle('Conditions')
+ ->setTitle(pht('Conditions'))
->setRightButton(javelin_tag(
'a',
array(
'href' => '#',
'class' => 'button green',
'sigil' => 'create-condition',
'mustcapture' => true
),
- 'Create New Condition'))
+ pht('New Condition')))
->setDescription(
- hsprintf('When %s these conditions are met:', $must_match_selector))
+ pht('When %s these conditions are met:', $must_match_selector))
->setContent(javelin_tag(
'table',
array(
'sigil' => 'rule-conditions',
'class' => 'herald-condition-table'
),
'')))
->appendChild(
id(new AphrontFormInsetView())
- ->setTitle('Action')
+ ->setTitle(pht('Action'))
->setRightButton(javelin_tag(
'a',
array(
'href' => '#',
'class' => 'button green',
'sigil' => 'create-action',
'mustcapture' => true,
),
- 'Create New Action'))
- ->setDescription(hsprintf(
+ pht('New Action')))
+ ->setDescription(pht(
'Take these actions %s this rule matches:',
$repetition_selector))
->setContent(javelin_tag(
'table',
array(
'sigil' => 'rule-actions',
'class' => 'herald-action-table',
),
'')))
->appendChild(
id(new AphrontFormSubmitControl())
- ->setValue('Save Rule')
+ ->setValue(pht('Save Rule'))
->addCancelButton('/herald/view/'.$rule->getContentType().'/'));
$this->setupEditorBehavior($rule, $handles);
- $header = new PhabricatorHeaderView();
- $header->setHeader(
- $rule->getID()
+ $title = $rule->getID()
? pht('Edit Herald Rule')
- : pht('Create Herald Rule'));
+ : pht('Create Herald Rule');
+
+ $crumbs = $this
+ ->buildApplicationCrumbs()
+ ->addCrumb(
+ id(new PhabricatorCrumbView())
+ ->setName($title)
+ ->setHref('#'));
$nav = $this->renderNav();
+ $nav->setCrumbs($crumbs);
$nav->selectFilter(
'view/'.$rule->getContentType().'/'.$rule->getRuleType());
$nav->appendChild(
array(
$error_view,
- $header,
$form,
));
return $this->buildApplicationPage(
$nav,
array(
'title' => pht('Edit Rule'),
+ 'dust' => true,
+ 'device' => true,
));
}
private function canEditRule($rule, $user) {
return
($user->getIsAdmin()) ||
($rule->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL) ||
($rule->getAuthorPHID() == $user->getPHID());
}
private function saveRule($rule, $request) {
$rule->setName($request->getStr('name'));
$rule->setMustMatchAll(($request->getStr('must_match') == 'all'));
$repetition_policy_param = $request->getStr('repetition_policy');
$rule->setRepetitionPolicy(
HeraldRepetitionPolicyConfig::toInt($repetition_policy_param));
$e_name = true;
$errors = array();
if (!strlen($rule->getName())) {
- $e_name = "Required";
- $errors[] = "Rule must have a name.";
+ $e_name = pht("Required");
+ $errors[] = pht("Rule must have a name.");
}
$data = json_decode($request->getStr('rule'), true);
if (!is_array($data) ||
!$data['conditions'] ||
!$data['actions']) {
throw new Exception("Failed to decode rule data.");
}
$conditions = array();
foreach ($data['conditions'] as $condition) {
if ($condition === null) {
// We manage this as a sparse array on the client, so may receive
// NULL if conditions have been removed.
continue;
}
$obj = new HeraldCondition();
$obj->setFieldName($condition[0]);
$obj->setFieldCondition($condition[1]);
if (is_array($condition[2])) {
$obj->setValue(array_keys($condition[2]));
} else {
$obj->setValue($condition[2]);
}
$cond_type = $obj->getFieldCondition();
if ($cond_type == HeraldConditionConfig::CONDITION_REGEXP) {
if (@preg_match($obj->getValue(), '') === false) {
$errors[] =
- 'The regular expression "'.$obj->getValue().'" is not valid. '.
+ pht('The regular expression "%s" is not valid. '.
'Regular expressions must have enclosing characters (e.g. '.
'"@/path/to/file@", not "/path/to/file") and be syntactically '.
- 'correct.';
+ 'correct.', $obj->getValue());
}
}
if ($cond_type == HeraldConditionConfig::CONDITION_REGEXP_PAIR) {
$json = json_decode($obj->getValue(), true);
if (!is_array($json)) {
$errors[] =
- 'The regular expression pair "'.$obj->getValue().'" is not '.
- 'valid JSON. Enter a valid JSON array with two elements.';
+ pht('The regular expression pair "%s" is not '.
+ 'valid JSON. Enter a valid JSON array with two elements.',
+ $obj->getValue());
} else {
if (count($json) != 2) {
$errors[] =
- 'The regular expression pair "'.$obj->getValue().'" must have '.
- 'exactly two elements.';
+ pht('The regular expression pair "%s" must have '.
+ 'exactly two elements.', $obj->getValue());
} else {
$key_regexp = array_shift($json);
$val_regexp = array_shift($json);
if (@preg_match($key_regexp, '') === false) {
$errors[] =
- 'The first regexp, "'.$key_regexp.'" in the regexp pair '.
- 'is not a valid regexp.';
+ pht('The first regexp, "%s" in the regexp pair '.
+ 'is not a valid regexp.', $key_regexp);
}
if (@preg_match($val_regexp, '') === false) {
$errors[] =
- 'The second regexp, "'.$val_regexp.'" in the regexp pair '.
- 'is not a valid regexp.';
+ pht('The second regexp, "%s" in the regexp pair '.
+ 'is not a valid regexp.', $val_regexp);
}
}
}
}
$conditions[] = $obj;
}
$actions = array();
foreach ($data['actions'] as $action) {
if ($action === null) {
// Sparse on the client; removals can give us NULLs.
continue;
}
if (!isset($action[1])) {
// Legitimate for any action which doesn't need a target, like
// "Do nothing".
$action[1] = null;
}
$actions[] = HeraldActionConfig::willSaveAction($rule->getRuleType(),
$rule->getAuthorPHID(),
$action);
}
$rule->attachConditions($conditions);
$rule->attachActions($actions);
if (!$errors) {
try {
$edit_action = $rule->getID() ? 'edit' : 'create';
$rule->openTransaction();
$rule->save();
$rule->saveConditions($conditions);
$rule->saveActions($actions);
$rule->logEdit($request->getUser()->getPHID(), $edit_action);
$rule->saveTransaction();
} catch (AphrontQueryDuplicateKeyException $ex) {
- $e_name = "Not Unique";
- $errors[] = "Rule name is not unique. Choose a unique name.";
+ $e_name = pht("Not Unique");
+ $errors[] = pht("Rule name is not unique. Choose a unique name.");
}
}
return array($e_name, $errors);
}
private function setupEditorBehavior($rule, $handles) {
$serial_conditions = array(
array('default', 'default', ''),
);
if ($rule->getConditions()) {
$serial_conditions = array();
foreach ($rule->getConditions() as $condition) {
$value = $condition->getValue();
if (is_array($value)) {
$value_map = array();
foreach ($value as $k => $fbid) {
$value_map[$fbid] = $handles[$fbid]->getName();
}
$value = $value_map;
}
$serial_conditions[] = array(
$condition->getFieldName(),
$condition->getFieldCondition(),
$value,
);
}
}
$serial_actions = array(
array('default', ''),
);
if ($rule->getActions()) {
$serial_actions = array();
foreach ($rule->getActions() as $action) {
switch ($action->getAction()) {
case HeraldActionConfig::ACTION_FLAG:
$current_value = $action->getTarget();
break;
default:
$target_map = array();
foreach ((array)$action->getTarget() as $fbid) {
$target_map[$fbid] = $handles[$fbid]->getName();
}
$current_value = $target_map;
break;
}
$serial_actions[] = array(
$action->getAction(),
$current_value,
);
}
}
$all_rules = $this->loadRulesThisRuleMayDependUpon($rule);
$all_rules = mpull($all_rules, 'getName', 'getID');
asort($all_rules);
$config_info = array();
$config_info['fields']
= HeraldFieldConfig::getFieldMapForContentType($rule->getContentType());
$config_info['conditions'] = HeraldConditionConfig::getConditionMap();
foreach ($config_info['fields'] as $field => $name) {
$config_info['conditionMap'][$field] = array_keys(
HeraldConditionConfig::getConditionMapForField($field));
}
foreach ($config_info['fields'] as $field => $fname) {
foreach ($config_info['conditions'] as $condition => $cname) {
$config_info['values'][$field][$condition] =
HeraldValueTypeConfig::getValueTypeForFieldAndCondition(
$field,
$condition);
}
}
$config_info['actions'] =
HeraldActionConfig::getActionMessageMap($rule->getContentType(),
$rule->getRuleType());
$config_info['rule_type'] = $rule->getRuleType();
foreach ($config_info['actions'] as $action => $name) {
$config_info['targets'][$action] =
HeraldValueTypeConfig::getValueTypeForAction($action,
$rule->getRuleType());
}
Javelin::initBehavior(
'herald-rule-editor',
array(
'root' => 'herald-rule-edit-form',
'conditions' => (object)$serial_conditions,
'actions' => (object)$serial_actions,
'template' => $this->buildTokenizerTemplates() + array(
'rules' => $all_rules,
'colors' => PhabricatorFlagColor::getColorNameMap(),
'defaultColor' => PhabricatorFlagColor::COLOR_BLUE,
),
'author' => array($rule->getAuthorPHID() =>
$handles[$rule->getAuthorPHID()]->getName()),
'info' => $config_info,
));
}
private function loadHandlesForRule($rule) {
$phids = array();
foreach ($rule->getActions() as $action) {
if (!is_array($action->getTarget())) {
continue;
}
foreach ($action->getTarget() as $target) {
$target = (array)$target;
foreach ($target as $phid) {
$phids[] = $phid;
}
}
}
foreach ($rule->getConditions() as $condition) {
$value = $condition->getValue();
if (is_array($value)) {
foreach ($value as $phid) {
$phids[] = $phid;
}
}
}
$phids[] = $rule->getAuthorPHID();
return $this->loadViewerHandles($phids);
}
/**
* Render the selector for the "When (all of | any of) these conditions are
* met:" element.
*/
private function renderMustMatchSelector($rule) {
return AphrontFormSelectControl::renderSelectTag(
$rule->getMustMatchAll() ? 'all' : 'any',
array(
- 'all' => 'all of',
- 'any' => 'any of',
+ 'all' => pht('all of'),
+ 'any' => pht('any of'),
),
array(
'name' => 'must_match',
));
}
/**
* Render the selector for "Take these actions (every time | only the first
* time) this rule matches..." element.
*/
private function renderRepetitionSelector($rule) {
// Make the selector for choosing how often this rule should be repeated
$repetition_policy = HeraldRepetitionPolicyConfig::toString(
$rule->getRepetitionPolicy());
$repetition_options = HeraldRepetitionPolicyConfig::getMapForContentType(
$rule->getContentType());
if (empty($repetition_options)) {
// default option is 'every time'
$repetition_selector = idx(
HeraldRepetitionPolicyConfig::getMap(),
HeraldRepetitionPolicyConfig::EVERY);
return $repetition_selector;
} else if (count($repetition_options) == 1) {
// if there's only 1 option, just pick it for the user
$repetition_selector = reset($repetition_options);
return $repetition_selector;
} else {
return AphrontFormSelectControl::renderSelectTag(
$repetition_policy,
$repetition_options,
array(
'name' => 'repetition_policy',
));
}
}
protected function buildTokenizerTemplates() {
$template = new AphrontTokenizerTemplateView();
$template = $template->render();
return array(
'source' => array(
'email' => '/typeahead/common/mailable/',
'user' => '/typeahead/common/users/',
'repository' => '/typeahead/common/repositories/',
'package' => '/typeahead/common/packages/',
'project' => '/typeahead/common/projects/',
),
'markup' => $template,
);
}
/**
* Load rules for the "Another Herald rule..." condition dropdown, which
* allows one rule to depend upon the success or failure of another rule.
*/
private function loadRulesThisRuleMayDependUpon(HeraldRule $rule) {
// Any rule can depend on a global rule.
$all_rules = id(new HeraldRuleQuery())
->withRuleTypes(array(HeraldRuleTypeConfig::RULE_TYPE_GLOBAL))
->withContentTypes(array($rule->getContentType()))
->execute();
if ($rule->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_PERSONAL) {
// Personal rules may depend upon your other personal rules.
$all_rules += id(new HeraldRuleQuery())
->withRuleTypes(array(HeraldRuleTypeConfig::RULE_TYPE_PERSONAL))
->withContentTypes(array($rule->getContentType()))
->withAuthorPHIDs(array($rule->getAuthorPHID()))
->execute();
}
// A rule can not depend upon itself.
unset($all_rules[$rule->getID()]);
return $all_rules;
}
}
diff --git a/src/applications/herald/controller/HeraldRuleEditHistoryController.php b/src/applications/herald/controller/HeraldRuleEditHistoryController.php
index 5bfd69c2d1..50887264bf 100644
--- a/src/applications/herald/controller/HeraldRuleEditHistoryController.php
+++ b/src/applications/herald/controller/HeraldRuleEditHistoryController.php
@@ -1,49 +1,59 @@
<?php
final class HeraldRuleEditHistoryController extends HeraldController {
private $id;
public function willProcessRequest(array $data) {
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$edit_query = new HeraldEditLogQuery();
if ($this->id) {
$edit_query->withRuleIDs(array($this->id));
}
$pager = new AphrontPagerView();
$pager->setURI($request->getRequestURI(), 'offset');
$pager->setOffset($request->getStr('offset'));
$edits = $edit_query->executeWithOffsetPager($pager);
$need_phids = mpull($edits, 'getEditorPHID');
$handles = $this->loadViewerHandles($need_phids);
$list_view = id(new HeraldRuleEditHistoryView())
->setEdits($edits)
->setHandles($handles)
->setUser($this->getRequest()->getUser());
$panel = new AphrontPanelView();
$panel->setHeader(pht('Edit History'));
$panel->appendChild($list_view);
$panel->setNoBackground();
+ $crumbs = $this
+ ->buildApplicationCrumbs($can_create = false)
+ ->addCrumb(
+ id(new PhabricatorCrumbView())
+ ->setName(pht('Edit History'))
+ ->setHref($this->getApplicationURI('herald/history')));
+
$nav = $this->renderNav();
$nav->selectFilter('history');
$nav->appendChild($panel);
+ $nav->setCrumbs($crumbs);
- return $this->buildStandardPageResponse(
+ return $this->buildApplicationPage(
$nav,
array(
- 'title' => 'Rule Edit History',
+ 'title' => pht('Rule Edit History'),
+ 'device' => true,
+ 'dust' => true,
));
}
}
diff --git a/src/applications/herald/controller/HeraldTestConsoleController.php b/src/applications/herald/controller/HeraldTestConsoleController.php
index 7d4836c508..e9865a41c7 100644
--- a/src/applications/herald/controller/HeraldTestConsoleController.php
+++ b/src/applications/herald/controller/HeraldTestConsoleController.php
@@ -1,141 +1,143 @@
<?php
final class HeraldTestConsoleController extends HeraldController {
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$request = $this->getRequest();
$object_name = trim($request->getStr('object_name'));
$e_name = true;
$errors = array();
if ($request->isFormPost()) {
if (!$object_name) {
- $e_name = 'Required';
- $errors[] = 'An object name is required.';
+ $e_name = pht('Required');
+ $errors[] = pht('An object name is required.');
}
if (!$errors) {
$matches = null;
$object = null;
if (preg_match('/^D(\d+)$/', $object_name, $matches)) {
$object = id(new DifferentialRevision())->load($matches[1]);
if (!$object) {
- $e_name = 'Invalid';
- $errors[] = 'No Differential Revision with that ID exists.';
+ $e_name = pht('Invalid');
+ $errors[] = pht('No Differential Revision with that ID exists.');
}
} else if (preg_match('/^r([A-Z]+)(\w+)$/', $object_name, $matches)) {
$repo = id(new PhabricatorRepository())->loadOneWhere(
'callsign = %s',
$matches[1]);
if (!$repo) {
- $e_name = 'Invalid';
- $errors[] = 'There is no repository with the callsign '.
- $matches[1].'.';
+ $e_name = pht('Invalid');
+ $errors[] = pht('There is no repository with the callsign: %s.',
+ $matches[1]);
}
$commit = id(new PhabricatorRepositoryCommit())->loadOneWhere(
'repositoryID = %d AND commitIdentifier = %s',
$repo->getID(),
$matches[2]);
if (!$commit) {
- $e_name = 'Invalid';
- $errors[] = 'There is no commit with that identifier.';
+ $e_name = pht('Invalid');
+ $errors[] = pht('There is no commit with that identifier.');
}
$object = $commit;
} else {
- $e_name = 'Invalid';
- $errors[] = 'This object name is not recognized.';
+ $e_name = pht('Invalid');
+ $errors[] = pht('This object name is not recognized.');
}
if (!$errors) {
if ($object instanceof DifferentialRevision) {
$adapter = new HeraldDifferentialRevisionAdapter(
$object,
$object->loadActiveDiff());
} else if ($object instanceof PhabricatorRepositoryCommit) {
$data = id(new PhabricatorRepositoryCommitData())->loadOneWhere(
'commitID = %d',
$object->getID());
$adapter = new HeraldCommitAdapter(
$repo,
$object,
$data);
} else {
throw new Exception("Can not build adapter for object!");
}
$rules = HeraldRule::loadAllByContentTypeWithFullData(
$adapter->getHeraldTypeName(),
$object->getPHID());
$engine = new HeraldEngine();
$effects = $engine->applyRules($rules, $adapter);
$dry_run = new HeraldDryRunAdapter();
$engine->applyEffects($effects, $dry_run, $rules);
$xscript = $engine->getTranscript();
return id(new AphrontRedirectResponse())
->setURI('/herald/transcript/'.$xscript->getID().'/');
}
}
}
if ($errors) {
$error_view = new AphrontErrorView();
- $error_view->setTitle('Form Errors');
+ $error_view->setTitle(pht('Form Errors'));
$error_view->setErrors($errors);
} else {
$error_view = null;
}
+ $text = pht('Enter an object to test rules '.
+ 'for, like a Diffusion commit (e.g., rX123) or a '.
+ 'Differential revision (e.g., D123). You will be shown the '.
+ 'results of a dry run on the object.');
+
$form = id(new AphrontFormView())
->setUser($user)
->appendChild(hsprintf(
- '<p class="aphront-form-instructions">Enter an object to test rules '.
- 'for, like a Diffusion commit (e.g., <tt>rX123</tt>) or a '.
- 'Differential revision (e.g., <tt>D123</tt>). You will be shown the '.
- 'results of a dry run on the object.</p>'))
+ '<p class="aphront-form-instructions">%s</p>', $text))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Object Name'))
->setName('object_name')
->setError($e_name)
->setValue($object_name))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Test Rules')));
$nav = $this->renderNav();
$nav->selectFilter('test');
$nav->appendChild(
array(
$error_view,
$form,
));
$crumbs = id($this->buildApplicationCrumbs())
->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('Transcripts'))
->setHref($this->getApplicationURI('/transcript/')))
->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('Test Console')));
$nav->setCrumbs($crumbs);
return $this->buildApplicationPage(
$nav,
array(
'title' => pht('Test Console'),
'dust' => true,
'device' => true,
));
}
}
diff --git a/src/applications/herald/controller/HeraldTranscriptController.php b/src/applications/herald/controller/HeraldTranscriptController.php
index 870fab3e68..2fb2f76f24 100644
--- a/src/applications/herald/controller/HeraldTranscriptController.php
+++ b/src/applications/herald/controller/HeraldTranscriptController.php
@@ -1,511 +1,523 @@
<?php
final class HeraldTranscriptController extends HeraldController {
const FILTER_AFFECTED = 'affected';
const FILTER_OWNED = 'owned';
const FILTER_ALL = 'all';
private $id;
private $filter;
private $handles;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
$map = $this->getFilterMap();
$this->filter = idx($data, 'filter');
if (empty($map[$this->filter])) {
$this->filter = self::FILTER_AFFECTED;
}
}
public function processRequest() {
$xscript = id(new HeraldTranscript())->load($this->id);
if (!$xscript) {
throw new Exception('Uknown transcript!');
}
require_celerity_resource('herald-test-css');
$nav = $this->buildSideNav();
$object_xscript = $xscript->getObjectTranscript();
if (!$object_xscript) {
$notice = id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
- ->setTitle('Old Transcript')
+ ->setTitle(pht('Old Transcript'))
->appendChild(phutil_tag(
'p',
array(),
- 'Details of this transcript have been garbage collected.'));
+ pht('Details of this transcript have been garbage collected.')));
$nav->appendChild($notice);
} else {
$filter = $this->getFilterPHIDs();
$this->filterTranscript($xscript, $filter);
$phids = array_merge($filter, $this->getTranscriptPHIDs($xscript));
$phids = array_unique($phids);
$phids = array_filter($phids);
$handles = $this->loadViewerHandles($phids);
$this->handles = $handles;
if ($xscript->getDryRun()) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
- $notice->setTitle('Dry Run');
- $notice->appendChild(
- 'This was a dry run to test Herald rules, no actions were executed.');
+ $notice->setTitle(pht('Dry Run'));
+ $notice->appendChild(pht('This was a dry run to test Herald '.
+ 'rules, no actions were executed.'));
$nav->appendChild($notice);
}
$apply_xscript_panel = $this->buildApplyTranscriptPanel(
$xscript);
$nav->appendChild($apply_xscript_panel);
$action_xscript_panel = $this->buildActionTranscriptPanel(
$xscript);
$nav->appendChild($action_xscript_panel);
$object_xscript_panel = $this->buildObjectTranscriptPanel(
$xscript);
$nav->appendChild($object_xscript_panel);
}
$crumbs = id($this->buildApplicationCrumbs())
->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('Transcripts'))
->setHref($this->getApplicationURI('/transcript/')))
->addCrumb(
id(new PhabricatorCrumbView())
->setName($xscript->getID()));
$nav->setCrumbs($crumbs);
- return $this->buildStandardPageResponse(
+ return $this->buildApplicationPage(
$nav,
array(
- 'title' => 'Transcript',
+ 'title' => pht('Transcript'),
+ 'device' => true,
+ 'dust' => true,
));
}
protected function renderConditionTestValue($condition, $handles) {
$value = $condition->getTestValue();
if (!is_scalar($value) && $value !== null) {
foreach ($value as $key => $phid) {
$handle = idx($handles, $phid);
if ($handle) {
$value[$key] = $handle->getName();
} else {
// This shouldn't ever really happen as we are supposed to have
// grabbed handles for everything, but be super liberal in what
// we accept here since we expect all sorts of weird issues as we
// version the system.
$value[$key] = 'Unknown Object #'.$phid;
}
}
sort($value);
$value = implode(', ', $value);
}
return hsprintf('<span class="condition-test-value">%s</span>', $value);
}
private function buildSideNav() {
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI('/herald/transcript/'.$this->id.'/'));
$items = array();
$filters = $this->getFilterMap();
foreach ($filters as $key => $name) {
$nav->addFilter($key, $name);
}
$nav->selectFilter($this->filter, null);
return $nav;
}
protected function getFilterMap() {
return array(
- self::FILTER_AFFECTED => 'Rules that Affected Me',
- self::FILTER_OWNED => 'Rules I Own',
- self::FILTER_ALL => 'All Rules',
+ self::FILTER_AFFECTED => pht('Rules that Affected Me'),
+ self::FILTER_OWNED => pht('Rules I Own'),
+ self::FILTER_ALL => pht('All Rules'),
);
}
protected function getFilterPHIDs() {
return array($this->getRequest()->getUser()->getPHID());
/* TODO
$viewer_id = $this->getRequest()->getUser()->getPHID();
$fbids = array();
if ($this->filter == self::FILTER_AFFECTED) {
$fbids[] = $viewer_id;
require_module_lazy('intern/subscriptions');
$datastore = new SubscriberDatabaseStore();
$lists = $datastore->getUserMailmanLists($viewer_id);
foreach ($lists as $list) {
$fbids[] = $list;
}
}
return $fbids;
*/
}
protected function getTranscriptPHIDs($xscript) {
$phids = array();
$object_xscript = $xscript->getObjectTranscript();
if (!$object_xscript) {
return array();
}
$phids[] = $object_xscript->getPHID();
foreach ($xscript->getApplyTranscripts() as $apply_xscript) {
// TODO: This is total hacks. Add another amazing layer of abstraction.
$target = (array)$apply_xscript->getTarget();
foreach ($target as $phid) {
if ($phid) {
$phids[] = $phid;
}
}
}
foreach ($xscript->getRuleTranscripts() as $rule_xscript) {
$phids[] = $rule_xscript->getRuleOwner();
}
$condition_xscripts = $xscript->getConditionTranscripts();
if ($condition_xscripts) {
$condition_xscripts = call_user_func_array(
'array_merge',
$condition_xscripts);
}
foreach ($condition_xscripts as $condition_xscript) {
$value = $condition_xscript->getTestValue();
// TODO: Also total hacks.
if (is_array($value)) {
foreach ($value as $phid) {
if ($phid) { // TODO: Probably need to make sure this "looks like" a
// PHID or decrease the level of hacks here; this used
// to be an is_numeric() check in Facebook land.
$phids[] = $phid;
}
}
}
}
return $phids;
}
protected function filterTranscript($xscript, $filter_phids) {
$filter_owned = ($this->filter == self::FILTER_OWNED);
$filter_affected = ($this->filter == self::FILTER_AFFECTED);
if (!$filter_owned && !$filter_affected) {
// No filtering to be done.
return;
}
if (!$xscript->getObjectTranscript()) {
return;
}
$user_phid = $this->getRequest()->getUser()->getPHID();
$keep_apply_xscripts = array();
$keep_rule_xscripts = array();
$filter_phids = array_fill_keys($filter_phids, true);
$rule_xscripts = $xscript->getRuleTranscripts();
foreach ($xscript->getApplyTranscripts() as $id => $apply_xscript) {
$rule_id = $apply_xscript->getRuleID();
if ($filter_owned) {
if (empty($rule_xscripts[$rule_id])) {
// No associated rule so you can't own this effect.
continue;
}
if ($rule_xscripts[$rule_id]->getRuleOwner() != $user_phid) {
continue;
}
} else if ($filter_affected) {
$targets = (array)$apply_xscript->getTarget();
if (!array_select_keys($filter_phids, $targets)) {
continue;
}
}
$keep_apply_xscripts[$id] = true;
if ($rule_id) {
$keep_rule_xscripts[$rule_id] = true;
}
}
foreach ($rule_xscripts as $rule_id => $rule_xscript) {
if ($filter_owned && $rule_xscript->getRuleOwner() == $user_phid) {
$keep_rule_xscripts[$rule_id] = true;
}
}
$xscript->setRuleTranscripts(
array_intersect_key(
$xscript->getRuleTranscripts(),
$keep_rule_xscripts));
$xscript->setApplyTranscripts(
array_intersect_key(
$xscript->getApplyTranscripts(),
$keep_apply_xscripts));
$xscript->setConditionTranscripts(
array_intersect_key(
$xscript->getConditionTranscripts(),
$keep_rule_xscripts));
}
private function buildApplyTranscriptPanel($xscript) {
$handles = $this->handles;
$action_names = HeraldActionConfig::getActionMessageMapForRuleType(null);
$rows = array();
foreach ($xscript->getApplyTranscripts() as $apply_xscript) {
$target = $apply_xscript->getTarget();
switch ($apply_xscript->getAction()) {
case HeraldActionConfig::ACTION_NOTHING:
$target = '';
break;
case HeraldActionConfig::ACTION_FLAG:
$target = PhabricatorFlagColor::getColorName($target);
break;
default:
if ($target) {
foreach ($target as $k => $phid) {
$target[$k] = $handles[$phid]->getName();
}
$target = implode("\n", $target);
} else {
$target = '<empty>';
}
break;
}
if ($apply_xscript->getApplied()) {
- $outcome = hsprintf('<span class="outcome-success">SUCCESS</span>');
+ $success = pht('SUCCESS');
+ $outcome =
+ hsprintf('<span class="outcome-success">%s</span>', $success);
} else {
- $outcome = hsprintf('<span class="outcome-failure">FAILURE</span>');
+ $failure = pht('FAILURE');
+ $outcome =
+ hsprintf('<span class="outcome-failure">%s</span>', $failure);
}
$rows[] = array(
$action_names[$apply_xscript->getAction()],
$target,
hsprintf(
'<strong>Taken because:</strong> %s<br />'.
'<strong>Outcome:</strong> %s %s',
$apply_xscript->getReason(),
$outcome,
$apply_xscript->getAppliedReason()),
);
}
$table = new AphrontTableView($rows);
- $table->setNoDataString('No actions were taken.');
+ $table->setNoDataString(pht('No actions were taken.'));
$table->setHeaders(
array(
- 'Action',
- 'Target',
- 'Details',
+ pht('Action'),
+ pht('Target'),
+ pht('Details'),
));
$table->setColumnClasses(
array(
'',
'',
'wide',
));
$panel = new AphrontPanelView();
$panel->setHeader(pht('Actions Taken'));
$panel->appendChild($table);
$panel->setNoBackground();
return $panel;
}
private function buildActionTranscriptPanel($xscript) {
$action_xscript = mgroup($xscript->getApplyTranscripts(), 'getRuleID');
$field_names = HeraldFieldConfig::getFieldMap();
$condition_names = HeraldConditionConfig::getConditionMap();
$handles = $this->handles;
$rule_markup = array();
foreach ($xscript->getRuleTranscripts() as $rule_id => $rule) {
$cond_markup = array();
foreach ($xscript->getConditionTranscriptsForRule($rule_id) as $cond) {
if ($cond->getNote()) {
$note = hsprintf(
'<div class="herald-condition-note">%s</div>',
$cond->getNote());
} else {
$note = null;
}
if ($cond->getResult()) {
$result = hsprintf(
'<span class="herald-outcome condition-pass">'.
"\xE2\x9C\x93".
'</span>');
} else {
$result = hsprintf(
'<span class="herald-outcome condition-fail">'.
"\xE2\x9C\x98".
'</span>');
}
$cond_markup[] = phutil_tag(
'li',
array(),
- hsprintf(
+ pht(
'%s Condition: %s %s %s%s',
$result,
$field_names[$cond->getFieldName()],
$condition_names[$cond->getCondition()],
$this->renderConditionTestValue($cond, $handles),
$note));
}
if ($rule->getResult()) {
+ $pass = pht('PASS');
$result = hsprintf(
- '<span class="herald-outcome rule-pass">PASS</span>');
+ '<span class="herald-outcome rule-pass">%s</span>', $pass);
$class = 'herald-rule-pass';
} else {
+ $fail = pht('FAIL');
$result = hsprintf(
- '<span class="herald-outcome rule-fail">FAIL</span>');
+ '<span class="herald-outcome rule-fail">%s</span>', $fail);
$class = 'herald-rule-fail';
}
$cond_markup[] = hsprintf('<li>%s %s</li>', $result, $rule->getReason());
/*
if ($rule->getResult()) {
$actions = idx($action_xscript, $rule_id, array());
if ($actions) {
$cond_markup[] = <li><div class="action-header">Actions</div></li>;
foreach ($actions as $action) {
$target = $action->getTarget();
if ($target) {
foreach ((array)$target as $k => $phid) {
$target[$k] = $handles[$phid]->getName();
}
$target = <strong>: {implode(', ', $target)}</strong>;
}
$cond_markup[] =
<li>
{$action_names[$action->getAction()]}
{$target}
</li>;
}
}
}
*/
$user_phid = $this->getRequest()->getUser()->getPHID();
$name = $rule->getRuleName();
if ($rule->getRuleOwner() == $user_phid) {
// $name = <a href={"/herald/rule/".$rule->getRuleID()."/"}>{$name}</a>;
}
$rule_markup[] =
phutil_tag(
'li',
array(
'class' => $class,
),
hsprintf(
'<div class="rule-name"><strong>%s</strong> %s</div>%s',
$name,
$handles[$rule->getRuleOwner()]->getName(),
phutil_tag('ul', array(), $cond_markup)));
}
- $panel = new AphrontPanelView();
- $panel->setHeader('Rule Details');
- $panel->appendChild(phutil_tag(
- 'ul',
- array('class' => 'herald-explain-list'),
- $rule_markup));
-
+ $panel = '';
+ if ($rule_markup) {
+ $panel = new AphrontPanelView();
+ $panel->setHeader(pht('Rule Details'));
+ $panel->setNoBackground();
+ $panel->appendChild(phutil_tag(
+ 'ul',
+ array('class' => 'herald-explain-list'),
+ $rule_markup));
+ }
return $panel;
}
private function buildObjectTranscriptPanel($xscript) {
$field_names = HeraldFieldConfig::getFieldMap();
$object_xscript = $xscript->getObjectTranscript();
$data = array();
if ($object_xscript) {
$phid = $object_xscript->getPHID();
$handles = $this->loadViewerHandles(array($phid));
$data += array(
- 'Object Name' => $object_xscript->getName(),
- 'Object Type' => $object_xscript->getType(),
- 'Object PHID' => $phid,
- 'Object Link' => $handles[$phid]->renderLink(),
+ pht('Object Name') => $object_xscript->getName(),
+ pht('Object Type') => $object_xscript->getType(),
+ pht('Object PHID') => $phid,
+ pht('Object Link') => $handles[$phid]->renderLink(),
);
}
$data += $xscript->getMetadataMap();
if ($object_xscript) {
foreach ($object_xscript->getFields() as $field => $value) {
$field = idx($field_names, $field, '['.$field.'?]');
$data['Field: '.$field] = $value;
}
}
$rows = array();
foreach ($data as $name => $value) {
if (!($value instanceof PhutilSafeHTML)) {
if (!is_scalar($value) && !is_null($value)) {
$value = implode("\n", $value);
}
if (strlen($value) > 256) {
$value = phutil_tag(
'textarea',
array(
'class' => 'herald-field-value-transcript',
),
$value);
}
}
$rows[] = array($name, $value);
}
$table = new AphrontTableView($rows);
$table->setColumnClasses(
array(
'header',
'wide',
));
$panel = new AphrontPanelView();
- $panel->setHeader('Object Transcript');
+ $panel->setHeader(pht('Object Transcript'));
+ $panel->setNoBackground();
$panel->appendChild($table);
return $panel;
}
}
diff --git a/src/applications/herald/controller/HeraldTranscriptListController.php b/src/applications/herald/controller/HeraldTranscriptListController.php
index c4d131fb80..5e38f31c45 100644
--- a/src/applications/herald/controller/HeraldTranscriptListController.php
+++ b/src/applications/herald/controller/HeraldTranscriptListController.php
@@ -1,115 +1,117 @@
<?php
final class HeraldTranscriptListController extends HeraldController {
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
// Get one page of data together with the pager.
// Pull these objects manually since the serialized fields are gigantic.
$transcript = new HeraldTranscript();
$conn_r = $transcript->establishConnection('r');
$phid = $request->getStr('phid');
$where_clause = '';
if ($phid) {
$where_clause = qsprintf(
$conn_r,
'WHERE objectPHID = %s',
$phid);
}
$pager = new AphrontPagerView();
$pager->setOffset($request->getInt('offset'));
$pager->setURI($request->getRequestURI(), 'offset');
$limit_clause = qsprintf(
$conn_r,
'LIMIT %d, %d',
$pager->getOffset(),
$pager->getPageSize() + 1);
$data = queryfx_all(
$conn_r,
'SELECT id, objectPHID, time, duration, dryRun FROM %T
%Q
ORDER BY id DESC
%Q',
$transcript->getTableName(),
$where_clause,
$limit_clause);
$data = $pager->sliceResults($data);
// Render the table.
$handles = array();
if ($data) {
$phids = ipull($data, 'objectPHID', 'objectPHID');
$handles = $this->loadViewerHandles($phids);
}
$rows = array();
foreach ($data as $xscript) {
$rows[] = array(
phabricator_date($xscript['time'], $user),
phabricator_time($xscript['time'], $user),
$handles[$xscript['objectPHID']]->renderLink(),
$xscript['dryRun'] ? 'Yes' : '',
number_format((int)(1000 * $xscript['duration'])).' ms',
phutil_tag(
'a',
array(
'href' => '/herald/transcript/'.$xscript['id'].'/',
'class' => 'button small grey',
),
- 'View Transcript'),
+ pht('View Transcript')),
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
- 'Date',
- 'Time',
- 'Object',
- 'Dry Run',
- 'Duration',
- 'View',
+ pht('Date'),
+ pht('Time'),
+ pht('Object'),
+ pht('Dry Run'),
+ pht('Duration'),
+ pht('View'),
));
$table->setColumnClasses(
array(
'',
'right',
'wide wrap',
'',
'',
'action',
));
// Render the whole page.
$panel = new AphrontPanelView();
$panel->setHeader(pht('Herald Transcripts'));
$panel->appendChild($table);
$panel->appendChild($pager);
$panel->setNoBackground();
$nav = $this->renderNav();
$nav->selectFilter('transcript');
$nav->appendChild($panel);
$crumbs = id($this->buildApplicationCrumbs())
->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('Transcripts')));
$nav->setCrumbs($crumbs);
- return $this->buildStandardPageResponse(
+ return $this->buildApplicationPage(
$nav,
array(
- 'title' => 'Herald Transcripts',
+ 'title' => pht('Herald Transcripts'),
+ 'device' => true,
+ 'dust' => true,
));
}
}
diff --git a/src/applications/herald/view/HeraldRuleEditHistoryView.php b/src/applications/herald/view/HeraldRuleEditHistoryView.php
index 7bbfd2342f..58fa440411 100644
--- a/src/applications/herald/view/HeraldRuleEditHistoryView.php
+++ b/src/applications/herald/view/HeraldRuleEditHistoryView.php
@@ -1,73 +1,64 @@
<?php
final class HeraldRuleEditHistoryView extends AphrontView {
private $edits;
private $handles;
public function setEdits(array $edits) {
$this->edits = $edits;
return $this;
}
public function getEdits() {
return $this->edits;
}
public function setHandles(array $handles) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$this->handles = $handles;
return $this;
}
public function render() {
- $rows = array();
+ $list = new PhabricatorObjectItemListView();
+ $list->setFlush(true);
+ $list->setCards(true);
foreach ($this->edits as $edit) {
$name = nonempty($edit->getRuleName(), 'Unknown Rule');
$rule_name = phutil_tag(
'strong',
array(),
$name);
switch ($edit->getAction()) {
case 'create':
$details = pht("Created rule '%s'.", $rule_name);
break;
case 'delete':
$details = pht("Deleted rule '%s'.", $rule_name);
break;
case 'edit':
default:
$details = pht("Edited rule '%s'.", $rule_name);
break;
}
- $rows[] = array(
- $edit->getRuleID(),
- $this->handles[$edit->getEditorPHID()]->renderLink(),
- $details,
- phabricator_datetime($edit->getDateCreated(), $this->user),
- );
+ $editor = $this->handles[$edit->getEditorPHID()]->renderLink();
+ $date = phabricator_datetime($edit->getDateCreated(), $this->user);
+
+ $item = id(new PhabricatorObjectItemView())
+ ->setObjectName(pht('Rule %d', $edit->getRuleID()))
+ ->setSubHead($details)
+ ->addIcon('none', $date)
+ ->addByLine(pht('Editor: %s', $editor));
+
+ $list->addItem($item);
}
- $table = new AphrontTableView($rows);
- $table->setNoDataString("No edits for rule.");
- $table->setHeaders(
- array(
- 'Rule ID',
- 'Editor',
- 'Details',
- 'Edit Date',
- ));
- $table->setColumnClasses(
- array(
- '',
- '',
- 'wide',
- '',
- ));
+ $list->setNoDataString(pht('No edits for rule.'));
- return $table->render();
+ return $list;
}
}
diff --git a/src/applications/herald/view/HeraldRuleListView.php b/src/applications/herald/view/HeraldRuleListView.php
index d95765ecd7..4109af51bf 100644
--- a/src/applications/herald/view/HeraldRuleListView.php
+++ b/src/applications/herald/view/HeraldRuleListView.php
@@ -1,109 +1,83 @@
<?php
final class HeraldRuleListView extends AphrontView {
private $rules;
private $handles;
private $showAuthor;
private $showRuleType;
public function setRules(array $rules) {
assert_instances_of($rules, 'HeraldRule');
$this->rules = $rules;
return $this;
}
public function setHandles(array $handles) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$this->handles = $handles;
return $this;
}
public function setShowAuthor($show_author) {
$this->showAuthor = $show_author;
return $this;
}
public function setShowRuleType($show_rule_type) {
$this->showRuleType = $show_rule_type;
return $this;
}
public function render() {
$type_map = HeraldRuleTypeConfig::getRuleTypeMap();
- $rows = array();
-
+ $list = new PhabricatorObjectItemListView();
+ $list->setFlush(true);
+ $list->setCards(true);
foreach ($this->rules as $rule) {
if ($rule->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL) {
- $author = null;
+ $author = pht('Global Rule');
} else {
$author = $this->handles[$rule->getAuthorPHID()]->renderLink();
+ $author = pht('Editor: %s', $author);
}
- $name = phutil_tag(
- 'a',
- array(
- 'href' => '/herald/rule/'.$rule->getID().'/',
- ),
- $rule->getName());
-
$edit_log = phutil_tag(
'a',
array(
'href' => '/herald/history/'.$rule->getID().'/',
),
- 'View Edit Log');
+ pht('View Edit Log'));
$delete = javelin_tag(
'a',
array(
'href' => '/herald/delete/'.$rule->getID().'/',
'sigil' => 'workflow',
- 'class' => 'button small grey',
),
- 'Delete');
-
- $rows[] = array(
- $type_map[$rule->getRuleType()],
- $author,
- $name,
- $edit_log,
- $delete,
- );
+ pht('Delete'));
+
+ $item = id(new PhabricatorObjectItemView())
+ ->setObjectName($type_map[$rule->getRuleType()])
+ ->setHeader($rule->getName())
+ ->setHref('/herald/rule/'.$rule->getID().'/')
+ ->addAttribute($edit_log)
+ ->addIcon('none', $author)
+ ->addAction(
+ id(new PhabricatorMenuItemView())
+ ->setHref('/herald/delete/'.$rule->getID().'/')
+ ->setIcon('delete')
+ ->setWorkflow(true));
+
+ $list->addItem($item);
}
- $table = new AphrontTableView($rows);
- $table->setNoDataString("No matching rules.");
-
- $table->setHeaders(
- array(
- 'Rule Type',
- 'Author',
- 'Rule Name',
- 'Edit Log',
- '',
- ));
- $table->setColumnClasses(
- array(
- '',
- '',
- 'wide pri',
- '',
- 'action'
- ));
- $table->setColumnVisibility(
- array(
- $this->showRuleType,
- $this->showAuthor,
- true,
- true,
- true,
- ));
-
- return $table->render();
+ $list->setNoDataString(pht("No matching rules."));
+
+ return $list;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jul 27, 2:09 PM (1 w, 5 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
185818
Default Alt Text
(108 KB)

Event Timeline