1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-30 02:32:42 +01:00

Allow projects to own packages

Summary:
- The UI is pretty straightforward, since Handle just works (tm)
- Added two methods to the owners object to handle the new layer of
  indirection. Then ran git grep PhabricatorOwnersOwner and changed
  callsites as appropriate.

Sending this to get a round of feedback before I test the non-trivial
changes in this diff.

Test Plan:
- owners tool: edit, view, list for basic functionality.
- phlog for the two new methods I added

Reviewers: epriestley, blair, jungejason

CC: aran

Differential Revision: https://secure.phabricator.com/D2079
This commit is contained in:
mkedia 2012-03-30 15:46:32 -07:00
parent 8813c7be0e
commit 591d50008f
10 changed files with 66 additions and 11 deletions

View file

@ -929,6 +929,7 @@ phutil_register_library_map(array(
), ),
'function' => 'function' =>
array( array(
'__phabricator_date_format' => 'view/utils',
'__phabricator_format_local_time' => 'view/utils', '__phabricator_format_local_time' => 'view/utils',
'_qsprintf_check_scalar_type' => 'storage/qsprintf', '_qsprintf_check_scalar_type' => 'storage/qsprintf',
'_qsprintf_check_type' => 'storage/qsprintf', '_qsprintf_check_type' => 'storage/qsprintf',
@ -939,8 +940,12 @@ phutil_register_library_map(array(
'phabricator_datetime' => 'view/utils', 'phabricator_datetime' => 'view/utils',
'phabricator_format_relative_time' => 'view/utils', 'phabricator_format_relative_time' => 'view/utils',
'phabricator_format_units_generic' => 'view/utils', 'phabricator_format_units_generic' => 'view/utils',
'phabricator_on_relative_date' => 'view/utils',
'phabricator_relative_date' => 'view/utils',
'phabricator_render_form' => 'infrastructure/javelin/markup', 'phabricator_render_form' => 'infrastructure/javelin/markup',
'phabricator_time' => 'view/utils', 'phabricator_time' => 'view/utils',
'phid_get_type' => 'applications/phid/utils',
'phid_group_by_type' => 'applications/phid/utils',
'qsprintf' => 'storage/qsprintf', 'qsprintf' => 'storage/qsprintf',
'queryfx' => 'storage/queryfx', 'queryfx' => 'storage/queryfx',
'queryfx_all' => 'storage/queryfx', 'queryfx_all' => 'storage/queryfx',

View file

@ -202,9 +202,9 @@ final class PhabricatorAuditCommentEditor {
$phids[$user->getPHID()] = true; $phids[$user->getPHID()] = true;
// The user can audit on behalf of all packages they own. // The user can audit on behalf of all packages they own.
$owned_packages = id(new PhabricatorOwnersOwner())->loadAllWhere( $owned_packages = PhabricatorOwnersOwner::loadAffiliatedPackages(
'userPHID = %s',
$user->getPHID()); $user->getPHID());
if ($owned_packages) { if ($owned_packages) {
$packages = id(new PhabricatorOwnersPackage())->loadAllWhere( $packages = id(new PhabricatorOwnersPackage())->loadAllWhere(
'id IN (%Ld)', 'id IN (%Ld)',

View file

@ -217,8 +217,8 @@ final class HeraldDifferentialRevisionAdapter extends HeraldObjectAdapter {
return mpull($packages, 'getPHID'); return mpull($packages, 'getPHID');
case HeraldFieldConfig::FIELD_AFFECTED_PACKAGE_OWNER: case HeraldFieldConfig::FIELD_AFFECTED_PACKAGE_OWNER:
$packages = $this->loadAffectedPackages(); $packages = $this->loadAffectedPackages();
$owners = PhabricatorOwnersOwner::loadAllForPackages($packages); return PhabricatorOwnersOwner::loadAffiliatedUserPHIDs(
return mpull($owners, 'getUserPHID'); mpull($packages, 'getID'));
default: default:
throw new Exception("Invalid field '{$field}'."); throw new Exception("Invalid field '{$field}'.");
} }

View file

@ -203,7 +203,7 @@ final class PhabricatorOwnersEditController
->setError($e_name)) ->setError($e_name))
->appendChild( ->appendChild(
id(new AphrontFormTokenizerControl()) id(new AphrontFormTokenizerControl())
->setDatasource('/typeahead/common/users/') ->setDatasource('/typeahead/common/usersorprojects/')
->setLabel('Primary Owner') ->setLabel('Primary Owner')
->setName('primary') ->setName('primary')
->setLimit(1) ->setLimit(1)
@ -211,7 +211,7 @@ final class PhabricatorOwnersEditController
->setError($e_primary)) ->setError($e_primary))
->appendChild( ->appendChild(
id(new AphrontFormTokenizerControl()) id(new AphrontFormTokenizerControl())
->setDatasource('/typeahead/common/users/') ->setDatasource('/typeahead/common/usersorprojects/')
->setLabel('Owners') ->setLabel('Owners')
->setName('owners') ->setName('owners')
->setValue($token_all_owners) ->setValue($token_all_owners)

View file

@ -171,7 +171,7 @@ final class PhabricatorOwnersListController
->setValue($request->getStr('name'))) ->setValue($request->getStr('name')))
->appendChild( ->appendChild(
id(new AphrontFormTokenizerControl()) id(new AphrontFormTokenizerControl())
->setDatasource('/typeahead/common/users/') ->setDatasource('/typeahead/common/usersorprojects/')
->setLimit(1) ->setLimit(1)
->setName('owner') ->setName('owner')
->setLabel('Owner') ->setLabel('Owner')

View file

@ -19,6 +19,10 @@
final class PhabricatorOwnersOwner extends PhabricatorOwnersDAO { final class PhabricatorOwnersOwner extends PhabricatorOwnersDAO {
protected $packageID; protected $packageID;
// this can be a project or a user. We assume that all members of a project
// owner also own the package; use the loadAffiliatedUserPHIDs method if
// you want to recursively grab all user ids that own a package
protected $userPHID; protected $userPHID;
public function getConfiguration() { public function getConfiguration() {
@ -37,4 +41,43 @@ final class PhabricatorOwnersOwner extends PhabricatorOwnersDAO {
mpull($packages, 'getID')); mpull($packages, 'getID'));
} }
// Loads all user phids affiliated with a set of packages. This includes both
// user owners and all members of any project owners
public static function loadAffiliatedUserPHIDs(array $package_ids) {
$owners = id(new PhabricatorOwnersOwner())->loadAllWhere(
'packageID IN (%Ls)',
$package_ids);
$all_phids = phid_group_by_type(mpull($owners, 'getUserPHID'));
$user_phids = idx($all_phids,
PhabricatorPHIDConstants::PHID_TYPE_USER,
array());
$users_in_project_phids = array();
if (idx($all_phids, PhabricatorPHIDConstants::PHID_TYPE_PROJ)) {
$users_in_project_phids = mpull(
id(new PhabricatorProjectAffiliation())->loadAllWhere(
'projectPHID IN (%Ls)',
idx($all_phids, PhabricatorPHIDConstants::PHID_TYPE_PROJ, array())),
'getUserPHID');
}
return array_unique(array_merge($users_in_project_phids, $user_phids));
}
// Loads all affiliated packages for a user. This includes packages owned by
// any project the user is a member of.
public static function loadAffiliatedPackages($user_phid) {
$query = new PhabricatorProjectQuery();
$query->setMembers(array($user_phid));
$query->withStatus(PhabricatorProjectQuery::STATUS_ACTIVE);
$projects = $query->execute();
$phids = mpull($projects, 'getPHID') + array($user_phid);
return
id(new PhabricatorOwnersOwner())->loadAllWhere(
'userPHID in (%Ls)',
$phids);
}
} }

View file

@ -7,6 +7,10 @@
phutil_require_module('phabricator', 'applications/owners/storage/base'); phutil_require_module('phabricator', 'applications/owners/storage/base');
phutil_require_module('phabricator', 'applications/phid/constants');
phutil_require_module('phabricator', 'applications/phid/utils');
phutil_require_module('phabricator', 'applications/project/query/project');
phutil_require_module('phabricator', 'applications/project/storage/affiliation');
phutil_require_module('phutil', 'utils'); phutil_require_module('phutil', 'utils');

View file

@ -126,10 +126,8 @@ final class PhabricatorRepositoryCommitOwnersWorker
$reasons[] = "No Revision Specified"; $reasons[] = "No Revision Specified";
} }
$owners = id(new PhabricatorOwnersOwner())->loadAllWhere( $owners_phids = PhabricatorOwnersOwner::loadAffiliatedUserPHIDs(
'packageID = %d', array($package->getID()));
$package->getID());
$owners_phids = mpull($owners, 'getUserPHID');
if (!($commit_author_phid && in_array($commit_author_phid, $owners_phids) || if (!($commit_author_phid && in_array($commit_author_phid, $owners_phids) ||
$commit_reviewedby_phid && in_array($commit_reviewedby_phid, $commit_reviewedby_phid && in_array($commit_reviewedby_phid,

View file

@ -61,6 +61,10 @@ final class PhabricatorTypeaheadCommonDatasourceController
case 'projects': case 'projects':
$need_projs = true; $need_projs = true;
break; break;
case 'usersorprojects':
$need_users = true;
$need_projs = true;
break;
case 'repositories': case 'repositories':
$need_repos = true; $need_repos = true;
break; break;

View file

@ -105,6 +105,7 @@ final class AphrontFormTokenizerControl extends AphrontFormControl {
$map = array( $map = array(
'users' => 'Type a user name...', 'users' => 'Type a user name...',
'usersorprojects' => 'Type a user or project name...',
'searchowner' => 'Type a user name...', 'searchowner' => 'Type a user name...',
'accounts' => 'Type a user name...', 'accounts' => 'Type a user name...',
'mailable' => 'Type a user or mailing list...', 'mailable' => 'Type a user or mailing list...',