From f191a66490b194785fae28c062b71be99bb14584 Mon Sep 17 00:00:00 2001 From: Austin McKinley Date: Fri, 4 May 2018 20:05:41 -0700 Subject: [PATCH] Add controllers/search/edit engine functionality to RepositoryIdentity Summary: Depends on D19423. Ref T12164. Adds controllers capable of listing and editing `PhabricatorRepositoryIdentity` objects. Starts creating those objects when commits are parsed. Test Plan: Reparsed some revisions, observed objects getting created in the database. Altered some `Identity` objects using the controllers and observed effects in the database. No attempts made to validate behavior under "challenging" author/committer strings. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin, PHID-OPKG-gm6ozazyms6q6i22gyam Maniphest Tasks: T12164 Differential Revision: https://secure.phabricator.com/D19429 --- .../20180504.repo_identity.author.sql | 2 + .../20180504.repo_identity.xaction.sql | 19 +++ src/__phutil_library_map__.php | 28 +++- .../PhabricatorDiffusionApplication.php | 9 ++ .../DiffusionIdentityEditController.php | 12 ++ .../DiffusionIdentityListController.php | 22 ++++ .../DiffusionIdentityViewController.php | 123 ++++++++++++++++++ .../DiffusionRepositoryIdentityEditor.php | 26 ++++ ...iffusionRepositoryIdentitySearchEngine.php | 92 +++++++++++++ ...habricatorRepositoryIdentityEditEngine.php | 91 +++++++++++++ .../PhabricatorRepositoryIdentityQuery.php | 29 ++++- ...atorRepositoryIdentityTransactionQuery.php | 10 ++ ...bricatorRepositoryIdentityFerretEngine.php | 18 +++ .../storage/PhabricatorRepositoryIdentity.php | 82 +++++++++++- ...abricatorRepositoryIdentityTransaction.php | 18 +++ ...torRepositoryCommitMessageParserWorker.php | 28 ++++ ...torRepositoryIdentityAssignTransaction.php | 67 ++++++++++ ...catorRepositoryIdentityTransactionType.php | 4 + 18 files changed, 674 insertions(+), 6 deletions(-) create mode 100644 resources/sql/autopatches/20180504.repo_identity.author.sql create mode 100644 resources/sql/autopatches/20180504.repo_identity.xaction.sql create mode 100644 src/applications/diffusion/controller/DiffusionIdentityEditController.php create mode 100644 src/applications/diffusion/controller/DiffusionIdentityListController.php create mode 100644 src/applications/diffusion/controller/DiffusionIdentityViewController.php create mode 100644 src/applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php create mode 100644 src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php create mode 100644 src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php create mode 100644 src/applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php create mode 100644 src/applications/repository/search/PhabricatorRepositoryIdentityFerretEngine.php create mode 100644 src/applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php create mode 100644 src/applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php create mode 100644 src/applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php diff --git a/resources/sql/autopatches/20180504.repo_identity.author.sql b/resources/sql/autopatches/20180504.repo_identity.author.sql new file mode 100644 index 0000000000..95859a6203 --- /dev/null +++ b/resources/sql/autopatches/20180504.repo_identity.author.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_repository.repository_identity + ADD COLUMN authorPHID VARBINARY(64) NOT NULL; diff --git a/resources/sql/autopatches/20180504.repo_identity.xaction.sql b/resources/sql/autopatches/20180504.repo_identity.xaction.sql new file mode 100644 index 0000000000..4b4e1f2a23 --- /dev/null +++ b/resources/sql/autopatches/20180504.repo_identity.xaction.sql @@ -0,0 +1,19 @@ +CREATE TABLE {$NAMESPACE}_repository.repository_identitytransaction ( + 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) NOT NULL, + oldValue LONGTEXT NOT NULL, + newValue LONGTEXT NOT NULL, + contentSource LONGTEXT NOT NULL, + metadata LONGTEXT NOT NULL, + dateCreated INT UNSIGNED NOT NULL, + dateModified INT UNSIGNED NOT NULL, + UNIQUE KEY `key_phid` (`phid`), + KEY `key_object` (`objectPHID`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE {$COLLATE_TEXT}; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 5c7dd9649c..600ee32cb5 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -815,6 +815,9 @@ phutil_register_library_map(array( 'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php', 'DiffusionHistoryView' => 'applications/diffusion/view/DiffusionHistoryView.php', 'DiffusionHovercardEngineExtension' => 'applications/diffusion/engineextension/DiffusionHovercardEngineExtension.php', + 'DiffusionIdentityEditController' => 'applications/diffusion/controller/DiffusionIdentityEditController.php', + 'DiffusionIdentityListController' => 'applications/diffusion/controller/DiffusionIdentityListController.php', + 'DiffusionIdentityViewController' => 'applications/diffusion/controller/DiffusionIdentityViewController.php', 'DiffusionInlineCommentController' => 'applications/diffusion/controller/DiffusionInlineCommentController.php', 'DiffusionInlineCommentPreviewController' => 'applications/diffusion/controller/DiffusionInlineCommentPreviewController.php', 'DiffusionInternalAncestorsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionInternalAncestorsConduitAPIMethod.php', @@ -937,6 +940,8 @@ phutil_register_library_map(array( 'DiffusionRepositoryEditUpdateController' => 'applications/diffusion/controller/DiffusionRepositoryEditUpdateController.php', 'DiffusionRepositoryFunctionDatasource' => 'applications/diffusion/typeahead/DiffusionRepositoryFunctionDatasource.php', 'DiffusionRepositoryHistoryManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryHistoryManagementPanel.php', + 'DiffusionRepositoryIdentityEditor' => 'applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php', + 'DiffusionRepositoryIdentitySearchEngine' => 'applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php', 'DiffusionRepositoryListController' => 'applications/diffusion/controller/DiffusionRepositoryListController.php', 'DiffusionRepositoryManageController' => 'applications/diffusion/controller/DiffusionRepositoryManageController.php', 'DiffusionRepositoryManagePanelsController' => 'applications/diffusion/controller/DiffusionRepositoryManagePanelsController.php', @@ -4086,8 +4091,14 @@ phutil_register_library_map(array( 'PhabricatorRepositoryGraphCache' => 'applications/repository/graphcache/PhabricatorRepositoryGraphCache.php', 'PhabricatorRepositoryGraphStream' => 'applications/repository/daemon/PhabricatorRepositoryGraphStream.php', 'PhabricatorRepositoryIdentity' => 'applications/repository/storage/PhabricatorRepositoryIdentity.php', + 'PhabricatorRepositoryIdentityAssignTransaction' => 'applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php', + 'PhabricatorRepositoryIdentityEditEngine' => 'applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php', + 'PhabricatorRepositoryIdentityFerretEngine' => 'applications/repository/search/PhabricatorRepositoryIdentityFerretEngine.php', 'PhabricatorRepositoryIdentityPHIDType' => 'applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php', 'PhabricatorRepositoryIdentityQuery' => 'applications/repository/query/PhabricatorRepositoryIdentityQuery.php', + 'PhabricatorRepositoryIdentityTransaction' => 'applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php', + 'PhabricatorRepositoryIdentityTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php', + 'PhabricatorRepositoryIdentityTransactionType' => 'applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php', 'PhabricatorRepositoryManagementCacheWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementCacheWorkflow.php', 'PhabricatorRepositoryManagementClusterizeWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementClusterizeWorkflow.php', 'PhabricatorRepositoryManagementDiscoverWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDiscoverWorkflow.php', @@ -6155,6 +6166,9 @@ phutil_register_library_map(array( 'DiffusionHistoryTableView' => 'DiffusionHistoryView', 'DiffusionHistoryView' => 'DiffusionView', 'DiffusionHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', + 'DiffusionIdentityEditController' => 'DiffusionController', + 'DiffusionIdentityListController' => 'DiffusionController', + 'DiffusionIdentityViewController' => 'DiffusionController', 'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController', 'DiffusionInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController', 'DiffusionInternalAncestorsConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', @@ -6276,6 +6290,8 @@ phutil_register_library_map(array( 'DiffusionRepositoryEditUpdateController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DiffusionRepositoryHistoryManagementPanel' => 'DiffusionRepositoryManagementPanel', + 'DiffusionRepositoryIdentityEditor' => 'PhabricatorApplicationTransactionEditor', + 'DiffusionRepositoryIdentitySearchEngine' => 'PhabricatorApplicationSearchEngine', 'DiffusionRepositoryListController' => 'DiffusionController', 'DiffusionRepositoryManageController' => 'DiffusionController', 'DiffusionRepositoryManagePanelsController' => 'DiffusionRepositoryManageController', @@ -9978,9 +9994,19 @@ phutil_register_library_map(array( 'PhabricatorRepositoryGitLFSRefQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryGraphCache' => 'Phobject', 'PhabricatorRepositoryGraphStream' => 'Phobject', - 'PhabricatorRepositoryIdentity' => 'PhabricatorRepositoryDAO', + 'PhabricatorRepositoryIdentity' => array( + 'PhabricatorRepositoryDAO', + 'PhabricatorPolicyInterface', + 'PhabricatorApplicationTransactionInterface', + ), + 'PhabricatorRepositoryIdentityAssignTransaction' => 'PhabricatorRepositoryIdentityTransactionType', + 'PhabricatorRepositoryIdentityEditEngine' => 'PhabricatorEditEngine', + 'PhabricatorRepositoryIdentityFerretEngine' => 'PhabricatorFerretEngine', 'PhabricatorRepositoryIdentityPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryIdentityQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorRepositoryIdentityTransaction' => 'PhabricatorModularTransaction', + 'PhabricatorRepositoryIdentityTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'PhabricatorRepositoryIdentityTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorRepositoryManagementCacheWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementClusterizeWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow', diff --git a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php index 70990bfe3c..a7baea1968 100644 --- a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php +++ b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php @@ -124,6 +124,15 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication { '(?P[A-Z]+)' => $repository_routes, '(?P[1-9]\d*)' => $repository_routes, + 'identity/' => array( + $this->getQueryRoutePattern() => + 'DiffusionIdentityListController', + $this->getEditRoutePattern('edit/') => + 'DiffusionIdentityEditController', + 'view/(?P[^/]+)/' => + 'DiffusionIdentityViewController', + ), + 'inline/' => array( 'edit/(?P[^/]+)/' => 'DiffusionInlineCommentController', 'preview/(?P[^/]+)/' diff --git a/src/applications/diffusion/controller/DiffusionIdentityEditController.php b/src/applications/diffusion/controller/DiffusionIdentityEditController.php new file mode 100644 index 0000000000..624a67285e --- /dev/null +++ b/src/applications/diffusion/controller/DiffusionIdentityEditController.php @@ -0,0 +1,12 @@ +setController($this) + ->buildResponse(); + } + +} diff --git a/src/applications/diffusion/controller/DiffusionIdentityListController.php b/src/applications/diffusion/controller/DiffusionIdentityListController.php new file mode 100644 index 0000000000..a6db3039c3 --- /dev/null +++ b/src/applications/diffusion/controller/DiffusionIdentityListController.php @@ -0,0 +1,22 @@ +setController($this) + ->buildResponse(); + } + + protected function buildApplicationCrumbs() { + $crumbs = parent::buildApplicationCrumbs(); + + id(new PhabricatorRepositoryIdentityEditEngine()) + ->setViewer($this->getViewer()) + ->addActionToCrumbs($crumbs); + + return $crumbs; + } + +} diff --git a/src/applications/diffusion/controller/DiffusionIdentityViewController.php b/src/applications/diffusion/controller/DiffusionIdentityViewController.php new file mode 100644 index 0000000000..0b22756a51 --- /dev/null +++ b/src/applications/diffusion/controller/DiffusionIdentityViewController.php @@ -0,0 +1,123 @@ +getViewer(); + + $id = $request->getURIData('id'); + $identity = id(new PhabricatorRepositoryIdentityQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->executeOne(); + if (!$identity) { + return new Aphront404Response(); + } + + $title = pht('Identity %d', $identity->getID()); + + $curtain = $this->buildCurtain($identity); + + $header = id(new PHUIHeaderView()) + ->setUser($viewer) + ->setHeader($identity->getIdentityShortName()) + ->setHeaderIcon('fa-globe') + ->setPolicyObject($identity); + + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb($identity->getID()); + $crumbs->setBorder(true); + + $timeline = $this->buildTransactionTimeline( + $identity, + new PhabricatorRepositoryIdentityTransactionQuery()); + $timeline->setShouldTerminate(true); + + $properties = $this->buildPropertyList($identity); + + $view = id(new PHUITwoColumnView()) + ->setHeader($header) + ->setCurtain($curtain) + ->setMainColumn(array( + $properties, + $timeline, + )); + + return $this->newPage() + ->setTitle($title) + ->setCrumbs($crumbs) + ->appendChild( + array( + $view, + )); + } + + private function buildCurtain(PhabricatorRepositoryIdentity $identity) { + $viewer = $this->getViewer(); + + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $identity, + PhabricatorPolicyCapability::CAN_EDIT); + + $id = $identity->getID(); + $edit_uri = $this->getApplicationURI("identity/edit/{$id}/"); + + $curtain = $this->newCurtainView($identity); + + $curtain->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-pencil') + ->setName(pht('Edit Identity')) + ->setHref($edit_uri) + ->setWorkflow(!$can_edit) + ->setDisabled(!$can_edit)); + + return $curtain; + } + + private function buildPropertyList( + PhabricatorRepositoryIdentity $identity) { + + $viewer = $this->getViewer(); + + $properties = id(new PHUIPropertyListView()) + ->setUser($viewer); + + $effective_phid = $identity->getCurrentEffectiveUserPHID(); + $automatic_phid = $identity->getAutomaticGuessedUserPHID(); + $manual_phid = $identity->getManuallySetUserPHID(); + + if ($effective_phid) { + $tag = id(new PHUITagView()) + ->setType(PHUITagView::TYPE_SHADE) + ->setColor('green') + ->setIcon('fa-check') + ->setName('Assigned'); + } else { + $tag = id(new PHUITagView()) + ->setType(PHUITagView::TYPE_SHADE) + ->setColor('indigo') + ->setIcon('fa-bomb') + ->setName('Unassigned'); + } + $properties->addProperty( + pht('Effective User'), + $viewer->renderHandle($effective_phid)); + $properties->addProperty( + pht('Automatically Detected User'), + $viewer->renderHandle($automatic_phid)); + $properties->addProperty( + pht('Manually Set User'), + $viewer->renderHandle($manual_phid)); + + $header = id(new PHUIHeaderView()) + ->setHeader(array(pht('Identity Assignments'), $tag)); + + return id(new PHUIObjectBoxView()) + ->setHeader($header) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) + ->addPropertyList($properties); + } +} diff --git a/src/applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php b/src/applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php new file mode 100644 index 0000000000..8e964e3e71 --- /dev/null +++ b/src/applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php @@ -0,0 +1,26 @@ +setLabel(pht('Is Assigned')) + ->setKey('hasEffectivePHID') + ->setOptions( + pht('(Show All)'), + pht('Show Only Assigned Identities'), + pht('Show Only Unassigned Identities')), + ); + } + + protected function buildQueryFromParameters(array $map) { + $query = $this->newQuery(); + + if ($map['hasEffectivePHID'] !== null) { + $query->withHasEffectivePHID($map['hasEffectivePHID']); + } + + return $query; + } + + protected function getURI($path) { + return '/diffusion/identity/'.$path; + } + + protected function getBuiltinQueryNames() { + $names = array( + 'all' => pht('All Identities'), + ); + + return $names; + } + + public function buildSavedQueryFromBuiltin($query_key) { + + $query = $this->newSavedQuery(); + $query->setQueryKey($query_key); + + switch ($query_key) { + case 'all': + return $query; + } + + return parent::buildSavedQueryFromBuiltin($query_key); + } + + protected function renderResultList( + array $identities, + PhabricatorSavedQuery $query, + array $handles) { + assert_instances_of($identities, 'PhabricatorRepositoryIdentity'); + + $viewer = $this->requireViewer(); + + $list = new PHUIObjectItemListView(); + $list->setUser($viewer); + foreach ($identities as $identity) { + $item = id(new PHUIObjectItemView()) + ->setObjectName(pht('Identity %d', $identity->getID())) + ->setHeader($identity->getIdentityShortName()) + ->setHref($identity->getURI()) + ->setObject($identity); + + $list->addItem($item); + } + + $result = new PhabricatorApplicationSearchResultView(); + $result->setObjectList($list); + $result->setNoDataString(pht('No Identities found.')); + + return $result; + } + +} diff --git a/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php b/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php new file mode 100644 index 0000000000..9b3bc51c36 --- /dev/null +++ b/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php @@ -0,0 +1,91 @@ +getIdentityShortName()); + } + + protected function getObjectEditShortText($object) { + return pht('Edit Identity'); + } + + protected function getObjectCreateShortText() { + return pht('Create Identity'); + } + + protected function getObjectName() { + return pht('Identity'); + } + + protected function getEditorURI() { + return '/diffusion/identity/edit/'; + } + + protected function getObjectCreateCancelURI($object) { + return '/diffusion/identity/'; + } + + protected function getObjectViewURI($object) { + return $object->getURI(); + } + + protected function getCreateNewObjectPolicy() { + return PhabricatorPolicies::POLICY_USER; + } + + protected function buildCustomEditFields($object) { + return array( + id(new PhabricatorUsersEditField()) + ->setKey('manuallySetUserPHID') + ->setLabel(pht('Assigned To')) + ->setDescription(pht('Override this identity\'s assignment.')) + ->setTransactionType( + PhabricatorRepositoryIdentityAssignTransaction::TRANSACTIONTYPE) + ->setIsCopyable(true) + ->setIsNullable(true) + ->setSingleValue($object->getManuallySetUserPHID()), + + ); + } + +} diff --git a/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php b/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php index d14fc9b365..072392f228 100644 --- a/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php +++ b/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php @@ -6,6 +6,7 @@ final class PhabricatorRepositoryIdentityQuery private $ids; private $phids; private $identityNames; + private $hasEffectivePHID; public function withIDs(array $ids) { $this->ids = $ids; @@ -22,10 +23,19 @@ final class PhabricatorRepositoryIdentityQuery return $this; } + public function withHasEffectivePHID($has_effective_phid) { + $this->hasEffectivePHID = $has_effective_phid; + return $this; + } + public function newResultObject() { return new PhabricatorRepositoryIdentity(); } + protected function getPrimaryTableAlias() { + return 'repository_identity'; + } + protected function loadPage() { return $this->loadStandardPage($this->newResultObject()); } @@ -36,17 +46,30 @@ final class PhabricatorRepositoryIdentityQuery if ($this->ids !== null) { $where[] = qsprintf( $conn, - 'id IN (%Ld)', + 'repository_identity.id IN (%Ld)', $this->ids); } if ($this->phids !== null) { $where[] = qsprintf( $conn, - 'phid IN (%Ls)', + 'repository_identity.phid IN (%Ls)', $this->phids); } + if ($this->hasEffectivePHID !== null) { + + if ($this->hasEffectivePHID) { + $where[] = qsprintf( + $conn, + 'repository_identity.currentEffectiveUserPHID IS NOT NULL'); + } else { + $where[] = qsprintf( + $conn, + 'repository_identity.currentEffectiveUserPHID IS NULL'); + } + } + if ($this->identityNames !== null) { $name_hashes = array(); foreach ($this->identityNames as $name) { @@ -55,7 +78,7 @@ final class PhabricatorRepositoryIdentityQuery $where[] = qsprintf( $conn, - 'identityNameHash IN (%Ls)', + 'repository_identity.identityNameHash IN (%Ls)', $name_hashes); } diff --git a/src/applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php b/src/applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php new file mode 100644 index 0000000000..f62a8610ff --- /dev/null +++ b/src/applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php @@ -0,0 +1,10 @@ +setIdentityNameRaw($name_raw); + $this->setIdentityNameHash(PhabricatorHash::digestForIndex($name_raw)); + $this->setIdentityNameEncoding($this->detectEncodingForStorage($name_raw)); + + return $this; + } + + public function getIdentityName() { + return $this->getUTF8StringFromStorage( + $this->getIdentityNameRaw(), + $this->getIdentityNameEncoding()); + } + + public function getIdentityShortName() { + // TODO + return $this->getIdentityName(); + } + + public function getURI() { + return '/diffusion/identity/view/'.$this->getID().'/'; + } + + public function save() { + if ($this->manuallySetUserPHID) { + $this->currentEffectiveUserPHID = $this->manuallySetUserPHID; + } else { + $this->currentEffectiveUserPHID = $this->automaticGuessedUserPHID; + } + + return parent::save(); + } + + +/* -( PhabricatorPolicyInterface )----------------------------------------- */ + + + public function getCapabilities() { + return array( + PhabricatorPolicyCapability::CAN_VIEW, + ); + } + + public function getPolicy($capability) { + return PhabricatorPolicies::getMostOpenPolicy(); + } + + public function hasAutomaticCapability( + $capability, PhabricatorUser $viewer) { + return false; + } + + +/* -( PhabricatorApplicationTransactionInterface )------------------------- */ + + + public function getApplicationTransactionEditor() { + return new DiffusionRepositoryIdentityEditor(); + } + + public function getApplicationTransactionObject() { + return $this; + } + + public function getApplicationTransactionTemplate() { + return new PhabricatorRepositoryIdentityTransaction(); + } + + public function willRenderTimeline( + PhabricatorApplicationTransactionView $timeline, + AphrontRequest $request) { + + return $timeline; + } + } diff --git a/src/applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php b/src/applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php new file mode 100644 index 0000000000..5f25346b64 --- /dev/null +++ b/src/applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php @@ -0,0 +1,18 @@ +getCommitter(); $hashes = $ref->getHashes(); + $author_identity = id(new PhabricatorRepositoryIdentityQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withIdentityNames(array($author)) + ->executeOne(); + + if (!$author_identity) { + $author_identity = id(new PhabricatorRepositoryIdentity()) + ->setAuthorPHID($commit->getPHID()) + ->setIdentityName($author) + ->setAutomaticGuessedUserPHID( + $this->resolveUserPHID($commit, $author)) + ->save(); + } + + $committer_identity = id(new PhabricatorRepositoryIdentityQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withIdentityNames(array($committer)) + ->executeOne(); + + if (!$committer_identity) { + $committer_identity = id(new PhabricatorRepositoryIdentity()) + ->setAuthorPHID($commit->getPHID()) + ->setIdentityName($committer) + ->setAutomaticGuessedUserPHID( + $this->resolveUserPHID($commit, $committer)) + ->save(); + } + $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere( 'commitID = %d', $commit->getID()); diff --git a/src/applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php b/src/applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php new file mode 100644 index 0000000000..da8611f20c --- /dev/null +++ b/src/applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php @@ -0,0 +1,67 @@ +getManuallySetUserPHID(), null); + } + + public function applyInternalEffects($object, $value) { + $object->setManuallySetUserPHID($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + if (!$old) { + return pht( + '%s assigned this identity to %s.', + $this->renderAuthor(), + $this->renderHandle($new)); + } else if (!$new) { + return pht( + '%s removed %s as the assignee of this identity.', + $this->renderAuthor(), + $this->renderHandle($old)); + } else { + return pht( + '%s changed the assigned user for this identity from %s to %s.', + $this->renderAuthor(), + $this->renderHandle($old), + $this->renderHandle($new)); + } + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + foreach ($xactions as $xaction) { + $old = $xaction->getOldValue(); + $new = $xaction->getNewValue(); + if (!strlen($new)) { + continue; + } + + if ($new === $old) { + continue; + } + + $assignee_list = id(new PhabricatorPeopleQuery()) + ->setViewer($this->getActor()) + ->withPHIDs(array($new)) + ->execute(); + + if (!$assignee_list) { + $errors[] = $this->newInvalidError( + pht('User "%s" is not a valid user.', + $new)); + } + } + return $errors; + } + +} diff --git a/src/applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php b/src/applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php new file mode 100644 index 0000000000..54feb6c522 --- /dev/null +++ b/src/applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php @@ -0,0 +1,4 @@ +