@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+674 -6
+2
resources/sql/autopatches/20180504.repo_identity.author.sql
··· 1 + ALTER TABLE {$NAMESPACE}_repository.repository_identity 2 + ADD COLUMN authorPHID VARBINARY(64) NOT NULL;
+19
resources/sql/autopatches/20180504.repo_identity.xaction.sql
··· 1 + CREATE TABLE {$NAMESPACE}_repository.repository_identitytransaction ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + phid VARBINARY(64) NOT NULL, 4 + authorPHID VARBINARY(64) NOT NULL, 5 + objectPHID VARBINARY(64) NOT NULL, 6 + viewPolicy VARBINARY(64) NOT NULL, 7 + editPolicy VARBINARY(64) NOT NULL, 8 + commentPHID VARBINARY(64) DEFAULT NULL, 9 + commentVersion INT UNSIGNED NOT NULL, 10 + transactionType VARCHAR(32) NOT NULL, 11 + oldValue LONGTEXT NOT NULL, 12 + newValue LONGTEXT NOT NULL, 13 + contentSource LONGTEXT NOT NULL, 14 + metadata LONGTEXT NOT NULL, 15 + dateCreated INT UNSIGNED NOT NULL, 16 + dateModified INT UNSIGNED NOT NULL, 17 + UNIQUE KEY `key_phid` (`phid`), 18 + KEY `key_object` (`objectPHID`) 19 + ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE {$COLLATE_TEXT};
+27 -1
src/__phutil_library_map__.php
··· 815 815 'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php', 816 816 'DiffusionHistoryView' => 'applications/diffusion/view/DiffusionHistoryView.php', 817 817 'DiffusionHovercardEngineExtension' => 'applications/diffusion/engineextension/DiffusionHovercardEngineExtension.php', 818 + 'DiffusionIdentityEditController' => 'applications/diffusion/controller/DiffusionIdentityEditController.php', 819 + 'DiffusionIdentityListController' => 'applications/diffusion/controller/DiffusionIdentityListController.php', 820 + 'DiffusionIdentityViewController' => 'applications/diffusion/controller/DiffusionIdentityViewController.php', 818 821 'DiffusionInlineCommentController' => 'applications/diffusion/controller/DiffusionInlineCommentController.php', 819 822 'DiffusionInlineCommentPreviewController' => 'applications/diffusion/controller/DiffusionInlineCommentPreviewController.php', 820 823 'DiffusionInternalAncestorsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionInternalAncestorsConduitAPIMethod.php', ··· 937 940 'DiffusionRepositoryEditUpdateController' => 'applications/diffusion/controller/DiffusionRepositoryEditUpdateController.php', 938 941 'DiffusionRepositoryFunctionDatasource' => 'applications/diffusion/typeahead/DiffusionRepositoryFunctionDatasource.php', 939 942 'DiffusionRepositoryHistoryManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryHistoryManagementPanel.php', 943 + 'DiffusionRepositoryIdentityEditor' => 'applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php', 944 + 'DiffusionRepositoryIdentitySearchEngine' => 'applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php', 940 945 'DiffusionRepositoryListController' => 'applications/diffusion/controller/DiffusionRepositoryListController.php', 941 946 'DiffusionRepositoryManageController' => 'applications/diffusion/controller/DiffusionRepositoryManageController.php', 942 947 'DiffusionRepositoryManagePanelsController' => 'applications/diffusion/controller/DiffusionRepositoryManagePanelsController.php', ··· 4086 4091 'PhabricatorRepositoryGraphCache' => 'applications/repository/graphcache/PhabricatorRepositoryGraphCache.php', 4087 4092 'PhabricatorRepositoryGraphStream' => 'applications/repository/daemon/PhabricatorRepositoryGraphStream.php', 4088 4093 'PhabricatorRepositoryIdentity' => 'applications/repository/storage/PhabricatorRepositoryIdentity.php', 4094 + 'PhabricatorRepositoryIdentityAssignTransaction' => 'applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php', 4095 + 'PhabricatorRepositoryIdentityEditEngine' => 'applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php', 4096 + 'PhabricatorRepositoryIdentityFerretEngine' => 'applications/repository/search/PhabricatorRepositoryIdentityFerretEngine.php', 4089 4097 'PhabricatorRepositoryIdentityPHIDType' => 'applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php', 4090 4098 'PhabricatorRepositoryIdentityQuery' => 'applications/repository/query/PhabricatorRepositoryIdentityQuery.php', 4099 + 'PhabricatorRepositoryIdentityTransaction' => 'applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php', 4100 + 'PhabricatorRepositoryIdentityTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php', 4101 + 'PhabricatorRepositoryIdentityTransactionType' => 'applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php', 4091 4102 'PhabricatorRepositoryManagementCacheWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementCacheWorkflow.php', 4092 4103 'PhabricatorRepositoryManagementClusterizeWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementClusterizeWorkflow.php', 4093 4104 'PhabricatorRepositoryManagementDiscoverWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDiscoverWorkflow.php', ··· 6155 6166 'DiffusionHistoryTableView' => 'DiffusionHistoryView', 6156 6167 'DiffusionHistoryView' => 'DiffusionView', 6157 6168 'DiffusionHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 6169 + 'DiffusionIdentityEditController' => 'DiffusionController', 6170 + 'DiffusionIdentityListController' => 'DiffusionController', 6171 + 'DiffusionIdentityViewController' => 'DiffusionController', 6158 6172 'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController', 6159 6173 'DiffusionInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController', 6160 6174 'DiffusionInternalAncestorsConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', ··· 6276 6290 'DiffusionRepositoryEditUpdateController' => 'DiffusionRepositoryManageController', 6277 6291 'DiffusionRepositoryFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 6278 6292 'DiffusionRepositoryHistoryManagementPanel' => 'DiffusionRepositoryManagementPanel', 6293 + 'DiffusionRepositoryIdentityEditor' => 'PhabricatorApplicationTransactionEditor', 6294 + 'DiffusionRepositoryIdentitySearchEngine' => 'PhabricatorApplicationSearchEngine', 6279 6295 'DiffusionRepositoryListController' => 'DiffusionController', 6280 6296 'DiffusionRepositoryManageController' => 'DiffusionController', 6281 6297 'DiffusionRepositoryManagePanelsController' => 'DiffusionRepositoryManageController', ··· 9978 9994 'PhabricatorRepositoryGitLFSRefQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 9979 9995 'PhabricatorRepositoryGraphCache' => 'Phobject', 9980 9996 'PhabricatorRepositoryGraphStream' => 'Phobject', 9981 - 'PhabricatorRepositoryIdentity' => 'PhabricatorRepositoryDAO', 9997 + 'PhabricatorRepositoryIdentity' => array( 9998 + 'PhabricatorRepositoryDAO', 9999 + 'PhabricatorPolicyInterface', 10000 + 'PhabricatorApplicationTransactionInterface', 10001 + ), 10002 + 'PhabricatorRepositoryIdentityAssignTransaction' => 'PhabricatorRepositoryIdentityTransactionType', 10003 + 'PhabricatorRepositoryIdentityEditEngine' => 'PhabricatorEditEngine', 10004 + 'PhabricatorRepositoryIdentityFerretEngine' => 'PhabricatorFerretEngine', 9982 10005 'PhabricatorRepositoryIdentityPHIDType' => 'PhabricatorPHIDType', 9983 10006 'PhabricatorRepositoryIdentityQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 10007 + 'PhabricatorRepositoryIdentityTransaction' => 'PhabricatorModularTransaction', 10008 + 'PhabricatorRepositoryIdentityTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 10009 + 'PhabricatorRepositoryIdentityTransactionType' => 'PhabricatorModularTransactionType', 9984 10010 'PhabricatorRepositoryManagementCacheWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 9985 10011 'PhabricatorRepositoryManagementClusterizeWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 9986 10012 'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
+9
src/applications/diffusion/application/PhabricatorDiffusionApplication.php
··· 124 124 '(?P<repositoryCallsign>[A-Z]+)' => $repository_routes, 125 125 '(?P<repositoryID>[1-9]\d*)' => $repository_routes, 126 126 127 + 'identity/' => array( 128 + $this->getQueryRoutePattern() => 129 + 'DiffusionIdentityListController', 130 + $this->getEditRoutePattern('edit/') => 131 + 'DiffusionIdentityEditController', 132 + 'view/(?P<id>[^/]+)/' => 133 + 'DiffusionIdentityViewController', 134 + ), 135 + 127 136 'inline/' => array( 128 137 'edit/(?P<phid>[^/]+)/' => 'DiffusionInlineCommentController', 129 138 'preview/(?P<phid>[^/]+)/'
+12
src/applications/diffusion/controller/DiffusionIdentityEditController.php
··· 1 + <?php 2 + 3 + final class DiffusionIdentityEditController 4 + extends DiffusionController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + return id(new PhabricatorRepositoryIdentityEditEngine()) 8 + ->setController($this) 9 + ->buildResponse(); 10 + } 11 + 12 + }
+22
src/applications/diffusion/controller/DiffusionIdentityListController.php
··· 1 + <?php 2 + 3 + final class DiffusionIdentityListController 4 + extends DiffusionController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + return id(new DiffusionRepositoryIdentitySearchEngine()) 8 + ->setController($this) 9 + ->buildResponse(); 10 + } 11 + 12 + protected function buildApplicationCrumbs() { 13 + $crumbs = parent::buildApplicationCrumbs(); 14 + 15 + id(new PhabricatorRepositoryIdentityEditEngine()) 16 + ->setViewer($this->getViewer()) 17 + ->addActionToCrumbs($crumbs); 18 + 19 + return $crumbs; 20 + } 21 + 22 + }
+123
src/applications/diffusion/controller/DiffusionIdentityViewController.php
··· 1 + <?php 2 + 3 + final class DiffusionIdentityViewController 4 + extends DiffusionController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + $viewer = $request->getViewer(); 8 + 9 + $id = $request->getURIData('id'); 10 + $identity = id(new PhabricatorRepositoryIdentityQuery()) 11 + ->setViewer($viewer) 12 + ->withIDs(array($id)) 13 + ->executeOne(); 14 + if (!$identity) { 15 + return new Aphront404Response(); 16 + } 17 + 18 + $title = pht('Identity %d', $identity->getID()); 19 + 20 + $curtain = $this->buildCurtain($identity); 21 + 22 + $header = id(new PHUIHeaderView()) 23 + ->setUser($viewer) 24 + ->setHeader($identity->getIdentityShortName()) 25 + ->setHeaderIcon('fa-globe') 26 + ->setPolicyObject($identity); 27 + 28 + $crumbs = $this->buildApplicationCrumbs(); 29 + $crumbs->addTextCrumb($identity->getID()); 30 + $crumbs->setBorder(true); 31 + 32 + $timeline = $this->buildTransactionTimeline( 33 + $identity, 34 + new PhabricatorRepositoryIdentityTransactionQuery()); 35 + $timeline->setShouldTerminate(true); 36 + 37 + $properties = $this->buildPropertyList($identity); 38 + 39 + $view = id(new PHUITwoColumnView()) 40 + ->setHeader($header) 41 + ->setCurtain($curtain) 42 + ->setMainColumn(array( 43 + $properties, 44 + $timeline, 45 + )); 46 + 47 + return $this->newPage() 48 + ->setTitle($title) 49 + ->setCrumbs($crumbs) 50 + ->appendChild( 51 + array( 52 + $view, 53 + )); 54 + } 55 + 56 + private function buildCurtain(PhabricatorRepositoryIdentity $identity) { 57 + $viewer = $this->getViewer(); 58 + 59 + $can_edit = PhabricatorPolicyFilter::hasCapability( 60 + $viewer, 61 + $identity, 62 + PhabricatorPolicyCapability::CAN_EDIT); 63 + 64 + $id = $identity->getID(); 65 + $edit_uri = $this->getApplicationURI("identity/edit/{$id}/"); 66 + 67 + $curtain = $this->newCurtainView($identity); 68 + 69 + $curtain->addAction( 70 + id(new PhabricatorActionView()) 71 + ->setIcon('fa-pencil') 72 + ->setName(pht('Edit Identity')) 73 + ->setHref($edit_uri) 74 + ->setWorkflow(!$can_edit) 75 + ->setDisabled(!$can_edit)); 76 + 77 + return $curtain; 78 + } 79 + 80 + private function buildPropertyList( 81 + PhabricatorRepositoryIdentity $identity) { 82 + 83 + $viewer = $this->getViewer(); 84 + 85 + $properties = id(new PHUIPropertyListView()) 86 + ->setUser($viewer); 87 + 88 + $effective_phid = $identity->getCurrentEffectiveUserPHID(); 89 + $automatic_phid = $identity->getAutomaticGuessedUserPHID(); 90 + $manual_phid = $identity->getManuallySetUserPHID(); 91 + 92 + if ($effective_phid) { 93 + $tag = id(new PHUITagView()) 94 + ->setType(PHUITagView::TYPE_SHADE) 95 + ->setColor('green') 96 + ->setIcon('fa-check') 97 + ->setName('Assigned'); 98 + } else { 99 + $tag = id(new PHUITagView()) 100 + ->setType(PHUITagView::TYPE_SHADE) 101 + ->setColor('indigo') 102 + ->setIcon('fa-bomb') 103 + ->setName('Unassigned'); 104 + } 105 + $properties->addProperty( 106 + pht('Effective User'), 107 + $viewer->renderHandle($effective_phid)); 108 + $properties->addProperty( 109 + pht('Automatically Detected User'), 110 + $viewer->renderHandle($automatic_phid)); 111 + $properties->addProperty( 112 + pht('Manually Set User'), 113 + $viewer->renderHandle($manual_phid)); 114 + 115 + $header = id(new PHUIHeaderView()) 116 + ->setHeader(array(pht('Identity Assignments'), $tag)); 117 + 118 + return id(new PHUIObjectBoxView()) 119 + ->setHeader($header) 120 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 121 + ->addPropertyList($properties); 122 + } 123 + }
+26
src/applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php
··· 1 + <?php 2 + 3 + final class DiffusionRepositoryIdentityEditor 4 + extends PhabricatorApplicationTransactionEditor { 5 + 6 + public function getEditorObjectsDescription() { 7 + return pht('Repository Identity'); 8 + } 9 + 10 + public function getCreateObjectTitle($author, $object) { 11 + return pht('%s created this identity.', $author); 12 + } 13 + 14 + public function getCreateObjectTitleForFeed($author, $object) { 15 + return pht('%s created %s.', $author, $object); 16 + } 17 + 18 + protected function supportsSearch() { 19 + return true; 20 + } 21 + 22 + public function getEditorApplicationClass() { 23 + return 'PhabricatorDiffusionApplication'; 24 + } 25 + 26 + }
+92
src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php
··· 1 + <?php 2 + 3 + final class DiffusionRepositoryIdentitySearchEngine 4 + extends PhabricatorApplicationSearchEngine { 5 + 6 + public function getResultTypeDescription() { 7 + return pht('Repository Identities'); 8 + } 9 + 10 + public function getApplicationClassName() { 11 + return 'PhabricatorDiffusionApplication'; 12 + } 13 + 14 + public function newQuery() { 15 + return new PhabricatorRepositoryIdentityQuery(); 16 + } 17 + 18 + protected function buildCustomSearchFields() { 19 + return array( 20 + id(new PhabricatorSearchThreeStateField()) 21 + ->setLabel(pht('Is Assigned')) 22 + ->setKey('hasEffectivePHID') 23 + ->setOptions( 24 + pht('(Show All)'), 25 + pht('Show Only Assigned Identities'), 26 + pht('Show Only Unassigned Identities')), 27 + ); 28 + } 29 + 30 + protected function buildQueryFromParameters(array $map) { 31 + $query = $this->newQuery(); 32 + 33 + if ($map['hasEffectivePHID'] !== null) { 34 + $query->withHasEffectivePHID($map['hasEffectivePHID']); 35 + } 36 + 37 + return $query; 38 + } 39 + 40 + protected function getURI($path) { 41 + return '/diffusion/identity/'.$path; 42 + } 43 + 44 + protected function getBuiltinQueryNames() { 45 + $names = array( 46 + 'all' => pht('All Identities'), 47 + ); 48 + 49 + return $names; 50 + } 51 + 52 + public function buildSavedQueryFromBuiltin($query_key) { 53 + 54 + $query = $this->newSavedQuery(); 55 + $query->setQueryKey($query_key); 56 + 57 + switch ($query_key) { 58 + case 'all': 59 + return $query; 60 + } 61 + 62 + return parent::buildSavedQueryFromBuiltin($query_key); 63 + } 64 + 65 + protected function renderResultList( 66 + array $identities, 67 + PhabricatorSavedQuery $query, 68 + array $handles) { 69 + assert_instances_of($identities, 'PhabricatorRepositoryIdentity'); 70 + 71 + $viewer = $this->requireViewer(); 72 + 73 + $list = new PHUIObjectItemListView(); 74 + $list->setUser($viewer); 75 + foreach ($identities as $identity) { 76 + $item = id(new PHUIObjectItemView()) 77 + ->setObjectName(pht('Identity %d', $identity->getID())) 78 + ->setHeader($identity->getIdentityShortName()) 79 + ->setHref($identity->getURI()) 80 + ->setObject($identity); 81 + 82 + $list->addItem($item); 83 + } 84 + 85 + $result = new PhabricatorApplicationSearchResultView(); 86 + $result->setObjectList($list); 87 + $result->setNoDataString(pht('No Identities found.')); 88 + 89 + return $result; 90 + } 91 + 92 + }
+91
src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorRepositoryIdentityEditEngine 4 + extends PhabricatorEditEngine { 5 + 6 + const ENGINECONST = 'repository.identity'; 7 + 8 + public function isEngineConfigurable() { 9 + return false; 10 + } 11 + 12 + public function getEngineName() { 13 + return pht('Repository Identities'); 14 + } 15 + 16 + public function getSummaryHeader() { 17 + return pht('Edit Repository Identity Configurations'); 18 + } 19 + 20 + public function getSummaryText() { 21 + return pht('This engine is used to edit Repository identities.'); 22 + } 23 + 24 + public function getEngineApplicationClass() { 25 + return 'PhabricatorDiffusionApplication'; 26 + } 27 + 28 + protected function newEditableObject() { 29 + return new PhabricatorRepositoryIdentity(); 30 + } 31 + 32 + protected function newObjectQuery() { 33 + return new PhabricatorRepositoryIdentityQuery(); 34 + } 35 + 36 + protected function getObjectCreateTitleText($object) { 37 + return pht('Create Identity'); 38 + } 39 + 40 + protected function getObjectCreateButtonText($object) { 41 + return pht('Create Identity'); 42 + } 43 + 44 + protected function getObjectEditTitleText($object) { 45 + return pht('Edit Identity: %s', $object->getIdentityShortName()); 46 + } 47 + 48 + protected function getObjectEditShortText($object) { 49 + return pht('Edit Identity'); 50 + } 51 + 52 + protected function getObjectCreateShortText() { 53 + return pht('Create Identity'); 54 + } 55 + 56 + protected function getObjectName() { 57 + return pht('Identity'); 58 + } 59 + 60 + protected function getEditorURI() { 61 + return '/diffusion/identity/edit/'; 62 + } 63 + 64 + protected function getObjectCreateCancelURI($object) { 65 + return '/diffusion/identity/'; 66 + } 67 + 68 + protected function getObjectViewURI($object) { 69 + return $object->getURI(); 70 + } 71 + 72 + protected function getCreateNewObjectPolicy() { 73 + return PhabricatorPolicies::POLICY_USER; 74 + } 75 + 76 + protected function buildCustomEditFields($object) { 77 + return array( 78 + id(new PhabricatorUsersEditField()) 79 + ->setKey('manuallySetUserPHID') 80 + ->setLabel(pht('Assigned To')) 81 + ->setDescription(pht('Override this identity\'s assignment.')) 82 + ->setTransactionType( 83 + PhabricatorRepositoryIdentityAssignTransaction::TRANSACTIONTYPE) 84 + ->setIsCopyable(true) 85 + ->setIsNullable(true) 86 + ->setSingleValue($object->getManuallySetUserPHID()), 87 + 88 + ); 89 + } 90 + 91 + }
+26 -3
src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php
··· 6 6 private $ids; 7 7 private $phids; 8 8 private $identityNames; 9 + private $hasEffectivePHID; 9 10 10 11 public function withIDs(array $ids) { 11 12 $this->ids = $ids; ··· 22 23 return $this; 23 24 } 24 25 26 + public function withHasEffectivePHID($has_effective_phid) { 27 + $this->hasEffectivePHID = $has_effective_phid; 28 + return $this; 29 + } 30 + 25 31 public function newResultObject() { 26 32 return new PhabricatorRepositoryIdentity(); 27 33 } 28 34 35 + protected function getPrimaryTableAlias() { 36 + return 'repository_identity'; 37 + } 38 + 29 39 protected function loadPage() { 30 40 return $this->loadStandardPage($this->newResultObject()); 31 41 } ··· 36 46 if ($this->ids !== null) { 37 47 $where[] = qsprintf( 38 48 $conn, 39 - 'id IN (%Ld)', 49 + 'repository_identity.id IN (%Ld)', 40 50 $this->ids); 41 51 } 42 52 43 53 if ($this->phids !== null) { 44 54 $where[] = qsprintf( 45 55 $conn, 46 - 'phid IN (%Ls)', 56 + 'repository_identity.phid IN (%Ls)', 47 57 $this->phids); 48 58 } 49 59 60 + if ($this->hasEffectivePHID !== null) { 61 + 62 + if ($this->hasEffectivePHID) { 63 + $where[] = qsprintf( 64 + $conn, 65 + 'repository_identity.currentEffectiveUserPHID IS NOT NULL'); 66 + } else { 67 + $where[] = qsprintf( 68 + $conn, 69 + 'repository_identity.currentEffectiveUserPHID IS NULL'); 70 + } 71 + } 72 + 50 73 if ($this->identityNames !== null) { 51 74 $name_hashes = array(); 52 75 foreach ($this->identityNames as $name) { ··· 55 78 56 79 $where[] = qsprintf( 57 80 $conn, 58 - 'identityNameHash IN (%Ls)', 81 + 'repository_identity.identityNameHash IN (%Ls)', 59 82 $name_hashes); 60 83 } 61 84
+10
src/applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php
··· 1 + <?php 2 + 3 + final class PhabricatorRepositoryIdentityTransactionQuery 4 + extends PhabricatorApplicationTransactionQuery { 5 + 6 + public function getTemplateApplicationTransaction() { 7 + return new PhabricatorRepositoryIdentityTransaction(); 8 + } 9 + 10 + }
+18
src/applications/repository/search/PhabricatorRepositoryIdentityFerretEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorRepositoryIdentityFerretEngine 4 + extends PhabricatorFerretEngine { 5 + 6 + public function getApplicationName() { 7 + return 'repository'; 8 + } 9 + 10 + public function getScopeName() { 11 + return 'identity'; 12 + } 13 + 14 + public function newSearchEngine() { 15 + return new DiffusionRepositoryIdentitySearchEngine(); 16 + } 17 + 18 + }
+80 -2
src/applications/repository/storage/PhabricatorRepositoryIdentity.php
··· 1 1 <?php 2 2 3 3 final class PhabricatorRepositoryIdentity 4 - extends PhabricatorRepositoryDAO { 4 + extends PhabricatorRepositoryDAO 5 + implements 6 + PhabricatorPolicyInterface, 7 + PhabricatorApplicationTransactionInterface { 5 8 9 + protected $authorPHID; 6 10 protected $identityNameHash; 7 11 protected $identityNameRaw; 8 12 protected $identityNameEncoding; 9 - 10 13 protected $automaticGuessedUserPHID; 11 14 protected $manuallySetUserPHID; 12 15 protected $currentEffectiveUserPHID; ··· 35 38 36 39 public function getPHIDType() { 37 40 return PhabricatorRepositoryIdentityPHIDType::TYPECONST; 41 + } 42 + 43 + public function setIdentityName($name_raw) { 44 + $this->setIdentityNameRaw($name_raw); 45 + $this->setIdentityNameHash(PhabricatorHash::digestForIndex($name_raw)); 46 + $this->setIdentityNameEncoding($this->detectEncodingForStorage($name_raw)); 47 + 48 + return $this; 49 + } 50 + 51 + public function getIdentityName() { 52 + return $this->getUTF8StringFromStorage( 53 + $this->getIdentityNameRaw(), 54 + $this->getIdentityNameEncoding()); 55 + } 56 + 57 + public function getIdentityShortName() { 58 + // TODO 59 + return $this->getIdentityName(); 60 + } 61 + 62 + public function getURI() { 63 + return '/diffusion/identity/view/'.$this->getID().'/'; 64 + } 65 + 66 + public function save() { 67 + if ($this->manuallySetUserPHID) { 68 + $this->currentEffectiveUserPHID = $this->manuallySetUserPHID; 69 + } else { 70 + $this->currentEffectiveUserPHID = $this->automaticGuessedUserPHID; 71 + } 72 + 73 + return parent::save(); 74 + } 75 + 76 + 77 + /* -( PhabricatorPolicyInterface )----------------------------------------- */ 78 + 79 + 80 + public function getCapabilities() { 81 + return array( 82 + PhabricatorPolicyCapability::CAN_VIEW, 83 + ); 84 + } 85 + 86 + public function getPolicy($capability) { 87 + return PhabricatorPolicies::getMostOpenPolicy(); 88 + } 89 + 90 + public function hasAutomaticCapability( 91 + $capability, PhabricatorUser $viewer) { 92 + return false; 93 + } 94 + 95 + 96 + /* -( PhabricatorApplicationTransactionInterface )------------------------- */ 97 + 98 + 99 + public function getApplicationTransactionEditor() { 100 + return new DiffusionRepositoryIdentityEditor(); 101 + } 102 + 103 + public function getApplicationTransactionObject() { 104 + return $this; 105 + } 106 + 107 + public function getApplicationTransactionTemplate() { 108 + return new PhabricatorRepositoryIdentityTransaction(); 109 + } 110 + 111 + public function willRenderTimeline( 112 + PhabricatorApplicationTransactionView $timeline, 113 + AphrontRequest $request) { 114 + 115 + return $timeline; 38 116 } 39 117 40 118 }
+18
src/applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorRepositoryIdentityTransaction 4 + extends PhabricatorModularTransaction { 5 + 6 + public function getApplicationTransactionType() { 7 + return PhabricatorRepositoryIdentityPHIDType::TYPECONST; 8 + } 9 + 10 + public function getBaseTransactionClass() { 11 + return 'PhabricatorRepositoryIdentityTransactionType'; 12 + } 13 + 14 + public function getApplicationName() { 15 + return 'repository'; 16 + } 17 + 18 + }
+28
src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php
··· 66 66 $committer = $ref->getCommitter(); 67 67 $hashes = $ref->getHashes(); 68 68 69 + $author_identity = id(new PhabricatorRepositoryIdentityQuery()) 70 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 71 + ->withIdentityNames(array($author)) 72 + ->executeOne(); 73 + 74 + if (!$author_identity) { 75 + $author_identity = id(new PhabricatorRepositoryIdentity()) 76 + ->setAuthorPHID($commit->getPHID()) 77 + ->setIdentityName($author) 78 + ->setAutomaticGuessedUserPHID( 79 + $this->resolveUserPHID($commit, $author)) 80 + ->save(); 81 + } 82 + 83 + $committer_identity = id(new PhabricatorRepositoryIdentityQuery()) 84 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 85 + ->withIdentityNames(array($committer)) 86 + ->executeOne(); 87 + 88 + if (!$committer_identity) { 89 + $committer_identity = id(new PhabricatorRepositoryIdentity()) 90 + ->setAuthorPHID($commit->getPHID()) 91 + ->setIdentityName($committer) 92 + ->setAutomaticGuessedUserPHID( 93 + $this->resolveUserPHID($commit, $committer)) 94 + ->save(); 95 + } 96 + 69 97 $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere( 70 98 'commitID = %d', 71 99 $commit->getID());
+67
src/applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorRepositoryIdentityAssignTransaction 4 + extends PhabricatorRepositoryIdentityTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'repository:identity:assign'; 7 + 8 + public function generateOldValue($object) { 9 + return nonempty($object->getManuallySetUserPHID(), null); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setManuallySetUserPHID($value); 14 + } 15 + 16 + public function getTitle() { 17 + $old = $this->getOldValue(); 18 + $new = $this->getNewValue(); 19 + 20 + if (!$old) { 21 + return pht( 22 + '%s assigned this identity to %s.', 23 + $this->renderAuthor(), 24 + $this->renderHandle($new)); 25 + } else if (!$new) { 26 + return pht( 27 + '%s removed %s as the assignee of this identity.', 28 + $this->renderAuthor(), 29 + $this->renderHandle($old)); 30 + } else { 31 + return pht( 32 + '%s changed the assigned user for this identity from %s to %s.', 33 + $this->renderAuthor(), 34 + $this->renderHandle($old), 35 + $this->renderHandle($new)); 36 + } 37 + } 38 + 39 + public function validateTransactions($object, array $xactions) { 40 + $errors = array(); 41 + 42 + foreach ($xactions as $xaction) { 43 + $old = $xaction->getOldValue(); 44 + $new = $xaction->getNewValue(); 45 + if (!strlen($new)) { 46 + continue; 47 + } 48 + 49 + if ($new === $old) { 50 + continue; 51 + } 52 + 53 + $assignee_list = id(new PhabricatorPeopleQuery()) 54 + ->setViewer($this->getActor()) 55 + ->withPHIDs(array($new)) 56 + ->execute(); 57 + 58 + if (!$assignee_list) { 59 + $errors[] = $this->newInvalidError( 60 + pht('User "%s" is not a valid user.', 61 + $new)); 62 + } 63 + } 64 + return $errors; 65 + } 66 + 67 + }
+4
src/applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorRepositoryIdentityTransactionType 4 + extends PhabricatorModularTransactionType {}