1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 08:42:41 +01:00

Use ApplicationTransactions for all non-path edits to Owners packages

Summary: Ref T8320.

Test Plan: {F437431}

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T8320

Differential Revision: https://secure.phabricator.com/D13028
This commit is contained in:
epriestley 2015-05-27 10:30:08 -07:00
parent 009598593f
commit da9a61fb70
11 changed files with 593 additions and 73 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_owners.owners_package
ADD mailKey binary(20) NOT NULL;

View file

@ -0,0 +1,18 @@
<?php
$table = new PhabricatorOwnersPackage();
$conn_w = $table->establishConnection('w');
$iterator = new LiskMigrationIterator($table);
foreach ($iterator as $package) {
$id = $package->getID();
echo pht('Adding mail key for package %d...', $id);
echo "\n";
queryfx(
$conn_w,
'UPDATE %T SET mailKey = %s WHERE id = %d',
$table->getTableName(),
Filesystem::readRandomCharacters(20),
$id);
}

View file

@ -0,0 +1,19 @@
CREATE TABLE {$NAMESPACE}_owners.owners_packagetransaction (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
phid VARBINARY(64) NOT NULL,
authorPHID VARBINARY(64) NOT NULL,
objectPHID VARBINARY(64) NOT NULL,
viewPolicy VARBINARY(64) NOT NULL,
editPolicy VARBINARY(64) NOT NULL,
commentPHID VARBINARY(64) DEFAULT NULL,
commentVersion INT UNSIGNED NOT NULL,
transactionType VARCHAR(32) COLLATE {$COLLATE_TEXT} NOT NULL,
oldValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
newValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
contentSource LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
metadata LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
UNIQUE KEY `key_phid` (`phid`),
KEY `key_object` (`objectPHID`)
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};

View file

@ -2180,6 +2180,9 @@ phutil_register_library_map(array(
'PhabricatorOwnersPackageQuery' => 'applications/owners/query/PhabricatorOwnersPackageQuery.php',
'PhabricatorOwnersPackageSearchEngine' => 'applications/owners/query/PhabricatorOwnersPackageSearchEngine.php',
'PhabricatorOwnersPackageTestCase' => 'applications/owners/storage/__tests__/PhabricatorOwnersPackageTestCase.php',
'PhabricatorOwnersPackageTransaction' => 'applications/owners/storage/PhabricatorOwnersPackageTransaction.php',
'PhabricatorOwnersPackageTransactionEditor' => 'applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php',
'PhabricatorOwnersPackageTransactionQuery' => 'applications/owners/query/PhabricatorOwnersPackageTransactionQuery.php',
'PhabricatorOwnersPath' => 'applications/owners/storage/PhabricatorOwnersPath.php',
'PhabricatorOwnersPathsController' => 'applications/owners/controller/PhabricatorOwnersPathsController.php',
'PhabricatorPHDConfigOptions' => 'applications/config/option/PhabricatorPHDConfigOptions.php',
@ -5581,6 +5584,7 @@ phutil_register_library_map(array(
'PhabricatorOwnersPackage' => array(
'PhabricatorOwnersDAO',
'PhabricatorPolicyInterface',
'PhabricatorApplicationTransactionInterface',
),
'PhabricatorOwnersPackageDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorOwnersPackageEditor' => 'PhabricatorEditor',
@ -5588,6 +5592,9 @@ phutil_register_library_map(array(
'PhabricatorOwnersPackageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorOwnersPackageSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorOwnersPackageTestCase' => 'PhabricatorTestCase',
'PhabricatorOwnersPackageTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorOwnersPackageTransactionEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorOwnersPackageTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorOwnersPath' => 'PhabricatorOwnersDAO',
'PhabricatorOwnersPathsController' => 'PhabricatorOwnersController',
'PhabricatorPHDConfigOptions' => 'PhabricatorApplicationConfigOptions',

View file

@ -124,12 +124,18 @@ final class PhabricatorOwnersDetailController
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb($package->getName());
$timeline = $this->buildTransactionTimeline(
$package,
new PhabricatorOwnersPackageTransactionQuery());
$timeline->setShouldTerminate(true);
return $this->buildApplicationPage(
array(
$crumbs,
$panel,
$this->renderPathsTable($paths, $repositories),
$commit_panels,
$timeline,
),
array(
'title' => $package->getName(),

View file

@ -21,86 +21,93 @@ final class PhabricatorOwnersEditController
if (!$package) {
return new Aphront404Response();
}
$is_new = false;
} else {
$package = new PhabricatorOwnersPackage();
$package->setPrimaryOwnerPHID($viewer->getPHID());
$package = PhabricatorOwnersPackage::initializeNewPackage($viewer);
$is_new = true;
}
$e_name = true;
$e_primary = true;
$v_name = $package->getName();
$v_primary = $package->getPrimaryOwnerPHID();
// TODO: Pull these off needOwners() on the Query.
$v_owners = mpull($package->loadOwners(), 'getUserPHID');
$v_auditing = $package->getAuditingEnabled();
$v_description = $package->getDescription();
$errors = array();
if ($request->isFormPost()) {
$package->setName($request->getStr('name'));
$package->setDescription($request->getStr('description'));
$old_auditing_enabled = $package->getAuditingEnabled();
$package->setAuditingEnabled(
($request->getStr('auditing') === 'enabled')
? 1
: 0);
$xactions = array();
$primary = $request->getArr('primary');
$primary = reset($primary);
$old_primary = $package->getPrimaryOwnerPHID();
$package->setPrimaryOwnerPHID($primary);
$v_name = $request->getStr('name');
$v_primary = head($request->getArr('primary'));
$v_owners = $request->getArr('owners');
$v_auditing = ($request->getStr('auditing') == 'enabled');
$v_description = $request->getStr('description');
$owners = $request->getArr('owners');
if ($primary) {
array_unshift($owners, $primary);
}
$owners = array_unique($owners);
if (!strlen($package->getName())) {
$e_name = pht('Required');
$errors[] = pht('Package name is required.');
} else {
$e_name = null;
if ($v_primary) {
$v_owners[] = $v_primary;
$v_owners = array_unique($v_owners);
}
if (!$package->getPrimaryOwnerPHID()) {
$e_primary = pht('Required');
$errors[] = pht('Package must have a primary owner.');
} else {
$e_primary = null;
}
$type_name = PhabricatorOwnersPackageTransaction::TYPE_NAME;
$type_primary = PhabricatorOwnersPackageTransaction::TYPE_PRIMARY;
$type_owners = PhabricatorOwnersPackageTransaction::TYPE_OWNERS;
$type_auditing = PhabricatorOwnersPackageTransaction::TYPE_AUDITING;
$type_description = PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION;
if (!$errors) {
$package->attachUnsavedOwners($owners);
$package->attachUnsavedPaths(array());
$package->attachOldAuditingEnabled($old_auditing_enabled);
$package->attachOldPrimaryOwnerPHID($old_primary);
try {
id(new PhabricatorOwnersPackageEditor())
->setActor($viewer)
->setPackage($package)
->save();
$xactions[] = id(new PhabricatorOwnersPackageTransaction())
->setTransactionType($type_name)
->setNewValue($v_name);
$id = $package->getID();
if ($is_new) {
$next_uri = '/owners/paths/'.$id.'/';
} else {
$next_uri = '/owners/package/'.$id.'/';
}
$xactions[] = id(new PhabricatorOwnersPackageTransaction())
->setTransactionType($type_primary)
->setNewValue($v_primary);
return id(new AphrontRedirectResponse())->setURI($next_uri);
} catch (AphrontDuplicateKeyQueryException $ex) {
$e_name = pht('Duplicate');
$errors[] = pht('Package name must be unique.');
$xactions[] = id(new PhabricatorOwnersPackageTransaction())
->setTransactionType($type_owners)
->setNewValue($v_owners);
$xactions[] = id(new PhabricatorOwnersPackageTransaction())
->setTransactionType($type_auditing)
->setNewValue($v_auditing);
$xactions[] = id(new PhabricatorOwnersPackageTransaction())
->setTransactionType($type_description)
->setNewValue($v_description);
$editor = id(new PhabricatorOwnersPackageTransactionEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true);
try {
$editor->applyTransactions($package, $xactions);
$id = $package->getID();
if ($is_new) {
$next_uri = '/owners/paths/'.$id.'/';
} else {
$next_uri = '/owners/package/'.$id.'/';
}
return id(new AphrontRedirectResponse())->setURI($next_uri);
} catch (AphrontDuplicateKeyQueryException $ex) {
$e_name = pht('Duplicate');
$errors[] = pht('Package name must be unique.');
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$e_name = $ex->getShortMessage($type_name);
$e_primary = $ex->getShortMessage($type_primary);
}
} else {
$owners = $package->loadOwners();
$owners = mpull($owners, 'getUserPHID');
}
$primary = $package->getPrimaryOwnerPHID();
if ($primary) {
$value_primary_owner = array($primary);
if ($v_primary) {
$value_primary_owner = array($v_primary);
} else {
$value_primary_owner = array();
}
@ -121,7 +128,7 @@ final class PhabricatorOwnersEditController
id(new AphrontFormTextControl())
->setLabel(pht('Name'))
->setName('name')
->setValue($package->getName())
->setValue($v_name)
->setError($e_name))
->appendControl(
id(new AphrontFormTokenizerControl())
@ -136,7 +143,7 @@ final class PhabricatorOwnersEditController
->setDatasource(new PhabricatorProjectOrUserDatasource())
->setLabel(pht('Owners'))
->setName('owners')
->setValue($owners))
->setValue($v_owners))
->appendChild(
id(new AphrontFormSelectControl())
->setName('auditing')
@ -147,19 +154,18 @@ final class PhabricatorOwnersEditController
'this package will be reviewed to make sure an owner '.
'of the package is involved and the commit message has '.
'a valid revision, reviewed by, and author.'))
->setOptions(array(
'disabled' => pht('Disabled'),
'enabled' => pht('Enabled'),
))
->setValue(
$package->getAuditingEnabled()
? 'enabled'
: 'disabled'))
->setOptions(
array(
'disabled' => pht('Disabled'),
'enabled' => pht('Enabled'),
))
->setValue(($v_auditing ? 'enabled' : 'disabled')))
->appendChild(
id(new AphrontFormTextAreaControl())
id(new PhabricatorRemarkupControl())
->setUser($viewer)
->setLabel(pht('Description'))
->setName('description')
->setValue($package->getDescription()))
->setValue($v_description))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton($cancel_uri)

View file

@ -0,0 +1,240 @@
<?php
final class PhabricatorOwnersPackageTransactionEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
return 'PhabricatorOwnersApplication';
}
public function getEditorObjectsDescription() {
return pht('Owners Packages');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorOwnersPackageTransaction::TYPE_NAME;
$types[] = PhabricatorOwnersPackageTransaction::TYPE_PRIMARY;
$types[] = PhabricatorOwnersPackageTransaction::TYPE_OWNERS;
$types[] = PhabricatorOwnersPackageTransaction::TYPE_AUDITING;
$types[] = PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorOwnersPackageTransaction::TYPE_NAME:
return $object->getName();
case PhabricatorOwnersPackageTransaction::TYPE_PRIMARY:
return $object->getPrimaryOwnerPHID();
case PhabricatorOwnersPackageTransaction::TYPE_OWNERS:
// TODO: needOwners() this on the Query.
$phids = mpull($object->loadOwners(), 'getUserPHID');
$phids = array_values($phids);
return $phids;
case PhabricatorOwnersPackageTransaction::TYPE_AUDITING:
return (int)$object->getAuditingEnabled();
case PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION:
return $object->getDescription();
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorOwnersPackageTransaction::TYPE_NAME:
case PhabricatorOwnersPackageTransaction::TYPE_PRIMARY:
case PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION:
return $xaction->getNewValue();
case PhabricatorOwnersPackageTransaction::TYPE_AUDITING:
return (int)$xaction->getNewValue();
case PhabricatorOwnersPackageTransaction::TYPE_OWNERS:
$phids = $xaction->getNewValue();
$phids = array_unique($phids);
$phids = array_values($phids);
return $phids;
}
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorOwnersPackageTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
return;
case PhabricatorOwnersPackageTransaction::TYPE_PRIMARY:
$object->setPrimaryOwnerPHID($xaction->getNewValue());
return;
case PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION:
$object->setDescription($xaction->getNewValue());
return;
case PhabricatorOwnersPackageTransaction::TYPE_AUDITING:
$object->setAuditingEnabled($xaction->getNewValue());
return;
case PhabricatorOwnersPackageTransaction::TYPE_OWNERS:
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorOwnersPackageTransaction::TYPE_NAME:
case PhabricatorOwnersPackageTransaction::TYPE_PRIMARY:
case PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION:
case PhabricatorOwnersPackageTransaction::TYPE_AUDITING:
return;
case PhabricatorOwnersPackageTransaction::TYPE_OWNERS:
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
// TODO: needOwners this
$owners = $object->loadOwners();
$owners = mpull($owners, null, 'getUserPHID');
$rem = array_diff($old, $new);
foreach ($rem as $phid) {
if (isset($owners[$phid])) {
$owners[$phid]->delete();
unset($owners[$phid]);
}
}
$add = array_diff($new, $old);
foreach ($add as $phid) {
$owners[$phid] = id(new PhabricatorOwnersOwner())
->setPackageID($object->getID())
->setUserPHID($phid)
->save();
}
// TODO: Attach owners here
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case PhabricatorOwnersPackageTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('Package name is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
break;
case PhabricatorOwnersPackageTransaction::TYPE_PRIMARY:
$missing = $this->validateIsEmptyTextField(
$object->getPrimaryOwnerPHID(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('Packages must have a primary owner.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
break;
}
return $errors;
}
protected function extractFilePHIDsFromCustomTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION:
return array($xaction->getNewValue());
}
return parent::extractFilePHIDsFromCustomTransaction($object, $xaction);
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.package.subject-prefix');
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$object->getPrimaryOwnerPHID(),
$this->requireActor()->getPHID(),
);
}
protected function getMailCC(PhabricatorLiskDAO $object) {
// TODO: needOwners() this
return mpull($object->loadOwners(), 'getUserPHID');
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new OwnersPackageReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$name = $object->getName();
return id(new PhabricatorMetaMTAMail())
->setSubject($name)
->addHeader('Thread-Topic', $object->getPHID());
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$detail_uri = PhabricatorEnv::getProductionURI(
'/owners/package/'.$object->getID().'/');
$body->addLinkSection(
pht('PACKAGE DETAIL'),
$detail_uri);
return $body;
}
}

View file

@ -0,0 +1,10 @@
<?php
final class PhabricatorOwnersPackageTransactionQuery
extends PhabricatorApplicationTransactionQuery {
public function getTemplateApplicationTransaction() {
return new PhabricatorOwnersPackageTransaction();
}
}

View file

@ -1,13 +1,17 @@
<?php
final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO
implements PhabricatorPolicyInterface {
final class PhabricatorOwnersPackage
extends PhabricatorOwnersDAO
implements
PhabricatorPolicyInterface,
PhabricatorApplicationTransactionInterface {
protected $name;
protected $originalName;
protected $auditingEnabled;
protected $description;
protected $primaryOwnerPHID;
protected $mailKey;
private $unsavedOwners = self::ATTACHABLE;
private $unsavedPaths = self::ATTACHABLE;
@ -15,6 +19,12 @@ final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO
private $oldPrimaryOwnerPHID;
private $oldAuditingEnabled;
public static function initializeNewPackage(PhabricatorUser $actor) {
return id(new PhabricatorOwnersPackage())
->setAuditingEnabled(0)
->setPrimaryOwnerPHID($actor->getPHID());
}
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
@ -44,6 +54,7 @@ final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO
'description' => 'text',
'primaryOwnerPHID' => 'phid?',
'auditingEnabled' => 'bool',
'mailKey' => 'bytes20',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
@ -64,6 +75,14 @@ final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO
PhabricatorOwnersPackagePHIDType::TYPECONST);
}
public function save() {
if (!$this->getMailKey()) {
$this->setMailKey(Filesystem::readRandomCharacters(20));
}
return parent::save();
}
public function attachUnsavedOwners(array $owners) {
$this->unsavedOwners = $owners;
return $this;
@ -269,4 +288,27 @@ final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO
}
return $result;
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhabricatorOwnersPackageTransactionEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new PhabricatorOwnersPackageTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
}

View file

@ -0,0 +1,152 @@
<?php
final class PhabricatorOwnersPackageTransaction
extends PhabricatorApplicationTransaction {
const TYPE_NAME = 'owners.name';
const TYPE_PRIMARY = 'owners.primary';
const TYPE_OWNERS = 'owners.owners';
const TYPE_AUDITING = 'owners.auditing';
const TYPE_DESCRIPTION = 'owners.description';
public function getApplicationName() {
return 'owners';
}
public function getApplicationTransactionType() {
return PhabricatorOwnersPackagePHIDType::TYPECONST;
}
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_PRIMARY:
if ($old) {
$phids[] = $old;
}
if ($new) {
$phids[] = $new;
}
break;
case self::TYPE_OWNERS:
$add = array_diff($new, $old);
foreach ($add as $phid) {
$phids[] = $phid;
}
$rem = array_diff($old, $new);
foreach ($rem as $phid) {
$phids[] = $phid;
}
break;
}
return $phids;
}
public function shouldHide() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
return ($old === null);
}
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$author_phid = $this->getAuthorPHID();
switch ($this->getTransactionType()) {
case self::TYPE_NAME:
if ($old === null) {
return pht(
'%s created this package.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s renamed this package from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
case self::TYPE_PRIMARY:
return pht(
'%s changed the primary owner for this package from %s to %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($old),
$this->renderHandleLink($new));
case self::TYPE_OWNERS:
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
if ($add && !$rem) {
return pht(
'%s added %s owner(s): %s.',
$this->renderHandleLink($author_phid),
count($add),
$this->renderHandleList($add));
} else if ($rem && !$add) {
return pht(
'%s removed %s owner(s): %s.',
$this->renderHandleLink($author_phid),
count($rem),
$this->renderHandleList($rem));
} else {
return pht(
'%s changed %s package owner(s), added %s: %s; removed %s: %s.',
$this->renderHandleLink($author_phid),
count($add) + count($rem),
count($add),
$this->renderHandleList($add),
count($rem),
$this->renderHandleList($rem));
}
case self::TYPE_AUDITING:
if ($new) {
return pht(
'%s enabled auditing for this package.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s disabled auditing for this package.',
$this->renderHandleLink($author_phid));
}
case self::TYPE_DESCRIPTION:
return pht(
'%s updated the description for this package.',
$this->renderHandleLink($author_phid));
}
return parent::getTitle();
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
return ($this->getOldValue() !== null);
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
$old = $this->getOldValue();
$new = $this->getNewValue();
return $this->renderTextCorpusChangeDetails(
$viewer,
$old,
$new);
}
return parent::renderChangeDetails($viewer);
}
}

View file

@ -1078,6 +1078,24 @@ final class PhabricatorUSEnglishTranslation
'Are you absolutely certain you want to destroy these objects?',
),
'%s added %s owner(s): %s.' => array(
array(
'%s added an owner: %3$s.',
'%s added owners: %3$s.',
),
),
'%s removed %s owner(s): %s.' => array(
array(
'%s removed an owner: %3$s.',
'%s removed owners: %3$s.',
),
),
'%s changed %s package owner(s), added %s: %s; removed %s: %s.' => array(
'%s changed package owners, added: %4$s; removed: %6$s.',
),
);
}