Permalink
Browse files

Add owners.query method

Summary:
Allow callers to find all packages/paths owned by a given
user/project.

Test Plan:
Used conduit api page with --
user owner: PHID-USER-6ce1c976b86e5f3c34f6 (tried both loadPackagesFromProjects
true/false)

proj owner: PHID-PROJ-r5wnmmaawqsn4tvjmqm4

repo/path: E, /tfb/trunk/www/flib/privacy. Checked both path.getowners
and owners.query

(all of these are defined internally at fb)

Reviewers: epriestley, btrahan, nh

Reviewed By: btrahan

CC: aran, Koolvin

Differential Revision: https://secure.phabricator.com/D2482
  • Loading branch information...
1 parent a009c93 commit 787c95abd8586d9f5aba114da54b7ba3c24ea7cf mkedia committed May 22, 2012
@@ -165,6 +165,7 @@
'ConduitAPI_maniphest_gettasktransactions_Method' => 'applications/conduit/method/maniphest/gettasktransactions',
'ConduitAPI_maniphest_info_Method' => 'applications/conduit/method/maniphest/info',
'ConduitAPI_maniphest_update_Method' => 'applications/conduit/method/maniphest/update',
+ 'ConduitAPI_owners_query_Method' => 'applications/conduit/method/owners/query',
'ConduitAPI_paste_Method' => 'applications/conduit/method/paste/base',
'ConduitAPI_paste_create_Method' => 'applications/conduit/method/paste/create',
'ConduitAPI_paste_info_Method' => 'applications/conduit/method/paste/info',
@@ -1201,6 +1202,7 @@
'ConduitAPI_maniphest_gettasktransactions_Method' => 'ConduitAPI_maniphest_Method',
'ConduitAPI_maniphest_info_Method' => 'ConduitAPI_maniphest_Method',
'ConduitAPI_maniphest_update_Method' => 'ConduitAPI_maniphest_Method',
+ 'ConduitAPI_owners_query_Method' => 'ConduitAPIMethod',
'ConduitAPI_paste_Method' => 'ConduitAPIMethod',
'ConduitAPI_paste_create_Method' => 'ConduitAPI_paste_Method',
'ConduitAPI_paste_info_Method' => 'ConduitAPI_paste_Method',
@@ -0,0 +1,177 @@
+<?php
+
+/*
+ * Copyright 2012 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @group conduit
+ */
+final class ConduitAPI_owners_query_Method
+ extends ConduitAPIMethod {
+
+ public function getMethodDescription() {
+ return 'Query for packages by one of the following: repository/path, ' .
+ 'packages with a given user or project owner, or packages affiliated ' .
+ 'with a user (owned by either the user or a project they are a member ' .
+ 'of.) You should only provide at most one search query.';
+ }
+
+ public function defineParamTypes() {
+ return array(
+ 'userOwner' => 'optional string',
+ 'projectOwner' => 'optional string',
+ 'userAffiliated' => 'optional string',
+ 'repositoryCallsign' => 'optional string',
+ 'path' => 'optional string',
+ );
+
+ }
+
+ public function defineReturnType() {
+ return 'dict<phid -> dict of package info>';
+ }
+
+ public function defineErrorTypes() {
+ return array(
+ 'ERR-INVALID-USAGE' =>
+ 'Provide one of a single owner phid (user/project), a single ' .
+ 'affiliated user phid (user), or a repository/path.',
+ 'ERR-INVALID-PARAMETER' => 'parameter should be a phid',
+ 'ERR_REP_NOT_FOUND' => 'The repository callsign is not recognized',
+ );
+ }
+
+ protected static function queryByOwner($owner) {
+ $is_valid_phid =
+ phid_get_type($owner) == PhabricatorPHIDConstants::PHID_TYPE_USER ||
+ phid_get_type($owner) == PhabricatorPHIDConstants::PHID_TYPE_PROJ;
+
+ if (!$is_valid_phid) {
+ throw id(new ConduitException('ERR-INVALID-PARAMETER'))
+ ->setErrorDescription(
+ 'Expected user/project PHID for owner, got '.$owner);
+ }
+
+ $owners = id(new PhabricatorOwnersOwner())->loadAllWhere(
+ 'userPHID = %s',
+ $owner);
+
+ $package_ids = mpull($owners, 'getPackageID');
+ $packages = array();
+ foreach ($package_ids as $id) {
+ $packages[] = id(new PhabricatorOwnersPackage())->load($id);
+ }
+ return $packages;
+ }
+
+ protected static function queryByAffiliatedUser($owner) {
+ $is_valid_phid =
+ phid_get_type($owner) == PhabricatorPHIDConstants::PHID_TYPE_USER;
+
+ if (!$is_valid_phid) {
+ throw id(new ConduitException('ERR-INVALID-PARAMETER'))
+ ->setErrorDescription(
+ 'Expected user PHID for affiliation, got '.$owner);
+ }
+
+ $owners = PhabricatorOwnersOwner::loadAffiliatedPackages($owner);
+
+ $package_ids = mpull($owners, 'getPackageID');
+ $packages = array();
+ foreach ($package_ids as $id) {
+ $packages[] = id(new PhabricatorOwnersPackage())->load($id);
+ }
+ return $packages;
+ }
+
+ public static function queryByPath($repo_callsign, $path) {
+ // note: we call this from the deprecated path.getowners conduit call.
+
+ $repository = id(new PhabricatorRepository())->loadOneWhere('callsign = %s',
+ $repo_callsign);
+
+ if (empty($repository)) {
+ throw id(new ConduitException('ERR_REP_NOT_FOUND'))
+ ->setErrorDescription(
+ 'Repository callsign '.$repo_callsign.' not recognized');
+ }
+
+ return PhabricatorOwnersPackage::loadOwningPackages(
+ $repository, $path);
+ }
+
+ public static function buildPackageInformationDictionaries($packages) {
+ assert_instances_of($packages, 'PhabricatorOwnersPackage');
+
+ $result = array();
+ foreach ($packages as $package) {
+ $p_owners = $package->loadOwners();
+ $p_paths = $package->loadPaths();
+
+ $owners = array_values(mpull($p_owners, 'getUserPHID'));
+ $paths = array();
+ foreach ($p_paths as $p) {
+ $paths[] = array($p->getRepositoryPHID(), $p->getPath());
+ }
+
+ $result[$package->getPHID()] = array(
+ 'phid' => $package->getPHID(),
+ 'name' => $package->getName(),
+ 'description' => $package->getDescription(),
+ 'primaryOwner' => $package->getPrimaryOwnerPHID(),
+ 'owners' => $owners,
+ 'paths' => $paths
+ );
+ }
+ return $result;
+ }
+
+ protected function execute(ConduitAPIRequest $request) {
+ $is_owner_query =
+ ($request->getValue('userOwner') ||
+ $request->getValue('projectOwner')) ?
+ 1 : 0;
+
+ $is_affiliated_query = $request->getValue('userAffiliated') ?
+ 1 : 0;
+
+ $repo = $request->getValue('repositoryCallsign');
+ $path = $request->getValue('path');
+ $is_path_query = ($repo && $path) ? 1 : 0;
+
+ // exactly one of these should be provided
+ if ($is_owner_query + $is_path_query + $is_affiliated_query !== 1) {
+ throw new ConduitException('ERR-INVALID-USAGE');
+ }
+
+ if ($is_affiliated_query) {
+ $packages = self::queryByAffiliatedUser(
+ $request->getValue('userAffiliated'));
+
+ } else if ($is_owner_query) {
+ $owner = nonempty(
+ $request->getValue('userOwner'),
+ $request->getValue('projectOwner'));
+
+ $packages = self::queryByOwner($owner);
+
+ } else {
+ $packages = self::queryByPath($repo, $path);
+ }
+
+ return self::buildPackageInformationDictionaries($packages);
+ }
+}
@@ -0,0 +1,20 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'applications/conduit/method/base');
+phutil_require_module('phabricator', 'applications/conduit/protocol/exception');
+phutil_require_module('phabricator', 'applications/owners/storage/owner');
+phutil_require_module('phabricator', 'applications/owners/storage/package');
+phutil_require_module('phabricator', 'applications/phid/constants');
+phutil_require_module('phabricator', 'applications/phid/utils');
+phutil_require_module('phabricator', 'applications/repository/storage/repository');
+
+phutil_require_module('phutil', 'utils');
+
+
+phutil_require_source('ConduitAPI_owners_query_Method.php');
@@ -21,6 +21,15 @@
*/
final class ConduitAPI_path_getowners_Method extends ConduitAPIMethod {
+ // This conduit call is deprecated
+ public function getMethodStatus() {
+ return self::METHOD_STATUS_DEPRECATED;
+ }
+
+ public function getMethodStatusDescription() {
+ return "Replaced by 'owners.query'.";
+ }
+
public function getMethodDescription() {
return "Find the Owners package that contains a given path.";
}
@@ -50,16 +59,11 @@ public function defineErrorTypes() {
}
protected function execute(ConduitAPIRequest $request) {
+ $packages = ConduitAPI_owners_query_Method::queryByPath(
+ $request->getValue('repositoryCallsign'),
+ $request->getValue('path')
+ );
- $repository = id(new PhabricatorRepository())->loadOneWhere('callsign = %s',
- $request->getValue('repositoryCallsign'));
-
- if (empty($repository)) {
- throw new ConduitException('ERR_REP_NOT_FOUND');
- }
-
- $packages = PhabricatorOwnersPackage::loadOwningPackages(
- $repository, $request->getValue('path'));
if (empty($packages)) {
throw new ConduitException('ERR_PATH_NOT_FOUND');
}
@@ -79,5 +83,4 @@ protected function execute(ConduitAPIRequest $request) {
return $result;
}
-
}
@@ -7,10 +7,9 @@
phutil_require_module('phabricator', 'applications/conduit/method/base');
+phutil_require_module('phabricator', 'applications/conduit/method/owners/query');
phutil_require_module('phabricator', 'applications/conduit/protocol/exception');
phutil_require_module('phabricator', 'applications/owners/storage/owner');
-phutil_require_module('phabricator', 'applications/owners/storage/package');
-phutil_require_module('phabricator', 'applications/repository/storage/repository');
phutil_require_module('phutil', 'utils');

0 comments on commit 787c95a

Please sign in to comment.