From da9a61fb70dbee432cc42e97ac8a7e69421cbc3f Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 27 May 2015 10:30:08 -0700 Subject: [PATCH] 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 --- .../autopatches/20150526.owners.mailkey.1.sql | 2 + .../autopatches/20150526.owners.mailkey.2.php | 18 ++ .../autopatches/20150526.owners.xaction.sql | 19 ++ src/__phutil_library_map__.php | 7 + .../PhabricatorOwnersDetailController.php | 6 + .../PhabricatorOwnersEditController.php | 148 +++++------ ...bricatorOwnersPackageTransactionEditor.php | 240 ++++++++++++++++++ ...abricatorOwnersPackageTransactionQuery.php | 10 + .../storage/PhabricatorOwnersPackage.php | 46 +++- .../PhabricatorOwnersPackageTransaction.php | 152 +++++++++++ .../PhabricatorUSEnglishTranslation.php | 18 ++ 11 files changed, 593 insertions(+), 73 deletions(-) create mode 100644 resources/sql/autopatches/20150526.owners.mailkey.1.sql create mode 100644 resources/sql/autopatches/20150526.owners.mailkey.2.php create mode 100644 resources/sql/autopatches/20150526.owners.xaction.sql create mode 100644 src/applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php create mode 100644 src/applications/owners/query/PhabricatorOwnersPackageTransactionQuery.php create mode 100644 src/applications/owners/storage/PhabricatorOwnersPackageTransaction.php diff --git a/resources/sql/autopatches/20150526.owners.mailkey.1.sql b/resources/sql/autopatches/20150526.owners.mailkey.1.sql new file mode 100644 index 0000000000..6e83129ec3 --- /dev/null +++ b/resources/sql/autopatches/20150526.owners.mailkey.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_owners.owners_package + ADD mailKey binary(20) NOT NULL; diff --git a/resources/sql/autopatches/20150526.owners.mailkey.2.php b/resources/sql/autopatches/20150526.owners.mailkey.2.php new file mode 100644 index 0000000000..c6bb5f8266 --- /dev/null +++ b/resources/sql/autopatches/20150526.owners.mailkey.2.php @@ -0,0 +1,18 @@ +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); +} diff --git a/resources/sql/autopatches/20150526.owners.xaction.sql b/resources/sql/autopatches/20150526.owners.xaction.sql new file mode 100644 index 0000000000..f25b3dfdb6 --- /dev/null +++ b/resources/sql/autopatches/20150526.owners.xaction.sql @@ -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}; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 5631ebdacc..822667a1ec 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -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', diff --git a/src/applications/owners/controller/PhabricatorOwnersDetailController.php b/src/applications/owners/controller/PhabricatorOwnersDetailController.php index 51f8b1d4e0..b14835c122 100644 --- a/src/applications/owners/controller/PhabricatorOwnersDetailController.php +++ b/src/applications/owners/controller/PhabricatorOwnersDetailController.php @@ -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(), diff --git a/src/applications/owners/controller/PhabricatorOwnersEditController.php b/src/applications/owners/controller/PhabricatorOwnersEditController.php index 8bf4ea5595..9f1987814d 100644 --- a/src/applications/owners/controller/PhabricatorOwnersEditController.php +++ b/src/applications/owners/controller/PhabricatorOwnersEditController.php @@ -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) diff --git a/src/applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php b/src/applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php new file mode 100644 index 0000000000..4f4c131c8c --- /dev/null +++ b/src/applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php @@ -0,0 +1,240 @@ +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; + } + +} diff --git a/src/applications/owners/query/PhabricatorOwnersPackageTransactionQuery.php b/src/applications/owners/query/PhabricatorOwnersPackageTransactionQuery.php new file mode 100644 index 0000000000..e0e7c2792f --- /dev/null +++ b/src/applications/owners/query/PhabricatorOwnersPackageTransactionQuery.php @@ -0,0 +1,10 @@ +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; + } + } diff --git a/src/applications/owners/storage/PhabricatorOwnersPackageTransaction.php b/src/applications/owners/storage/PhabricatorOwnersPackageTransaction.php new file mode 100644 index 0000000000..741bbddf37 --- /dev/null +++ b/src/applications/owners/storage/PhabricatorOwnersPackageTransaction.php @@ -0,0 +1,152 @@ +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); + } + +} diff --git a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php index 61dd34fbe2..111e38857f 100644 --- a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php +++ b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php @@ -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.', + ), + ); }