diff --git a/src/Api/Projects.php b/src/Api/Projects.php index ee755bc..9b279db 100644 --- a/src/Api/Projects.php +++ b/src/Api/Projects.php @@ -10,7 +10,7 @@ namespace PrivatePackagist\ApiClient\Api; /** - * @deprecated Use the Subrepositories API instead + * @deprecated Use the Suborganizations API instead */ class Projects extends Subrepositories { diff --git a/src/Api/Projects/MirroredRepositories.php b/src/Api/Projects/MirroredRepositories.php index f455efd..fc95024 100644 --- a/src/Api/Projects/MirroredRepositories.php +++ b/src/Api/Projects/MirroredRepositories.php @@ -10,7 +10,7 @@ namespace PrivatePackagist\ApiClient\Api\Projects; /** - * @deprecated Use Subrepositories\MirroredRepositories instead + * @deprecated Use \PrivatePackagist\ApiClient\Api\Suborganizations\MirroredRepositories instead */ class MirroredRepositories extends \PrivatePackagist\ApiClient\Api\Subrepositories\MirroredRepositories { diff --git a/src/Api/Projects/Packages.php b/src/Api/Projects/Packages.php index 70aeaf3..cae72fc 100644 --- a/src/Api/Projects/Packages.php +++ b/src/Api/Projects/Packages.php @@ -10,7 +10,7 @@ namespace PrivatePackagist\ApiClient\Api\Projects; /** - * @deprecated Use Subrepositories\Packages instead + * @deprecated Use \PrivatePackagist\ApiClient\Api\Suborganizations\Packages instead */ class Packages extends \PrivatePackagist\ApiClient\Api\Subrepositories\Packages { diff --git a/src/Api/Suborganizations.php b/src/Api/Suborganizations.php new file mode 100644 index 0000000..614ad9a --- /dev/null +++ b/src/Api/Suborganizations.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PrivatePackagist\ApiClient\Api; + +use PrivatePackagist\ApiClient\Exception\InvalidArgumentException; + +class Suborganizations extends AbstractApi +{ + public function all() + { + return $this->get('/suborganizations/'); + } + + public function show($suborganizationName) + { + return $this->get(sprintf('/suborganizations/%s/', $suborganizationName)); + } + + public function create($name) + { + return $this->post('/suborganizations/', ['name' => $name]); + } + + public function remove($suborganizationName) + { + return $this->delete(sprintf('/suborganizations/%s/', $suborganizationName)); + } + + public function listTeams($suborganizationName) + { + return $this->get(sprintf('/suborganizations/%s/teams/', $suborganizationName)); + } + + public function addOrEditTeams($suborganizationName, array $teams) + { + foreach ($teams as $team) { + if (!isset($team['id'])) { + throw new InvalidArgumentException('Parameter "id" is required.'); + } + + if (!isset($team['permission'])) { + throw new InvalidArgumentException('Parameter "permission" is required.'); + } + } + + return $this->post(sprintf('/suborganizations/%s/teams/', $suborganizationName), $teams); + } + + public function removeTeam($suborganizationName, $teamId) + { + return $this->delete(sprintf('/suborganizations/%s/teams/%s/', $suborganizationName, $teamId)); + } + + public function listTokens($suborganizationName) + { + return $this->get(sprintf('/suborganizations/%s/tokens/', $suborganizationName)); + } + + public function createToken($suborganizationName, array $tokenData) + { + return $this->post(sprintf('/suborganizations/%s/tokens/', $suborganizationName), $tokenData); + } + + public function removeToken($suborganizationName, $tokenId) + { + return $this->delete(sprintf('/suborganizations/%s/tokens/%s/', $suborganizationName, $tokenId)); + } + + public function regenerateToken($suborganizationName, $tokenId, array $confirmation) + { + if (!isset($confirmation['IConfirmOldTokenWillStopWorkingImmediately'])) { + throw new InvalidArgumentException('Confirmation is required to regenerate the Composer repository token.'); + } + + return $this->post(sprintf('/suborganizations/%s/tokens/%s/regenerate', $suborganizationName, $tokenId), $confirmation); + } + + public function packages() + { + return new Suborganizations\Packages($this->client); + } + + public function mirroredRepositories() + { + return new Suborganizations\MirroredRepositories($this->client); + } +} diff --git a/src/Api/Suborganizations/MirroredRepositories.php b/src/Api/Suborganizations/MirroredRepositories.php new file mode 100644 index 0000000..6230369 --- /dev/null +++ b/src/Api/Suborganizations/MirroredRepositories.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PrivatePackagist\ApiClient\Api\Suborganizations; + +use PrivatePackagist\ApiClient\Api\AbstractApi; +use PrivatePackagist\ApiClient\Exception\InvalidArgumentException; + +class MirroredRepositories extends AbstractApi +{ + public function all($suborganizationName) + { + return $this->get(sprintf('/suborganizations/%s/mirrored-repositories/', $suborganizationName)); + } + + public function add($suborganizationName, array $mirroredRepositories) + { + foreach ($mirroredRepositories as $mirroredRepository) { + if (!isset($mirroredRepository['id'], $mirroredRepository['mirroringBehavior'])) { + throw new InvalidArgumentException('The "id" and the "mirroringBehavior" are required to add a mirrored repository to a project'); + } + } + + return $this->post(sprintf('/suborganizations/%s/mirrored-repositories/', $suborganizationName), $mirroredRepositories); + } + + public function show($suborganizationName, $mirroredRepositoryId) + { + return $this->get(sprintf('/suborganizations/%s/mirrored-repositories/%s/', $suborganizationName, $mirroredRepositoryId)); + } + + public function edit($suborganizationName, $mirroredRepositoryId, $mirroringBehavior) + { + return $this->put(sprintf('/suborganizations/%s/mirrored-repositories/%s/', $suborganizationName, $mirroredRepositoryId), [ + 'mirroringBehavior' => $mirroringBehavior, + ]); + } + + public function remove($suborganizationName, $mirroredRepositoryId) + { + return $this->delete(sprintf('/suborganizations/%s/mirrored-repositories/%s/', $suborganizationName, $mirroredRepositoryId)); + } + + public function listPackages($suborganizationName, $mirroredRepositoryId) + { + return $this->get(sprintf('/suborganizations/%s/mirrored-repositories/%s/packages/', $suborganizationName, $mirroredRepositoryId)); + } + + public function addPackages($suborganizationName, $mirroredRepositoryId, array $packages) + { + return $this->post(sprintf('/suborganizations/%s/mirrored-repositories/%s/packages/', $suborganizationName, $mirroredRepositoryId), $packages); + } + + public function removePackages($suborganizationName, $mirroredRepositoryId) + { + return $this->delete(sprintf('/suborganizations/%s/mirrored-repositories/%s/packages/', $suborganizationName, $mirroredRepositoryId)); + } +} diff --git a/src/Api/Suborganizations/Packages.php b/src/Api/Suborganizations/Packages.php new file mode 100644 index 0000000..0289130 --- /dev/null +++ b/src/Api/Suborganizations/Packages.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PrivatePackagist\ApiClient\Api\Suborganizations; + +use PrivatePackagist\ApiClient\Api\AbstractApi; +use PrivatePackagist\ApiClient\Exception\InvalidArgumentException; +use PrivatePackagist\ApiClient\Payload\CustomPackageConfig; +use PrivatePackagist\ApiClient\Payload\VcsPackageConfig; + +class Packages extends AbstractApi +{ + public function all($suborganizationName, array $filters = []) + { + if (isset($filters['origin']) && !in_array($filters['origin'], \PrivatePackagist\ApiClient\Api\Packages::AVAILABLE_ORIGINS, true)) { + throw new InvalidArgumentException('Filter "origin" has to be one of: "' . implode('", "', \PrivatePackagist\ApiClient\Api\Packages::AVAILABLE_ORIGINS) . '".'); + } + + return $this->get(sprintf('/suborganizations/%s/packages/', $suborganizationName), $filters); + } + + public function show($suborganizationName, $packageIdOrName) + { + return $this->get(sprintf('/suborganizations/%s/packages/%s', $suborganizationName, $packageIdOrName)); + } + + public function createVcsPackage($suborganizationName, $url, $credentialId = null, $type = 'vcs', $defaultSuborganizationAccess = null) + { + $data = new VcsPackageConfig($url, $credentialId, $type, $defaultSuborganizationAccess); + + return $this->post(sprintf('/suborganizations/%s/packages/', $suborganizationName), $data->toParameters()); + } + + public function createCustomPackage($suborganizationName, $customJson, $credentialId = null, $defaultSuborganizationAccess = null) + { + $data = new CustomPackageConfig($customJson, $credentialId, $defaultSuborganizationAccess); + + return $this->post(sprintf('/suborganizations/%s/packages/', $suborganizationName), $data->toParameters()); + } + + public function editVcsPackage($suborganizationName, $packageIdOrName, $url, $credentialId = null, $type = 'vcs', $defaultSuborganizationAccess = null) + { + $data = new VcsPackageConfig($url, $credentialId, $type, $defaultSuborganizationAccess); + + return $this->put(sprintf('/suborganizations/%s/packages/%s/', $suborganizationName, $packageIdOrName), $data->toParameters()); + } + + public function editCustomPackage($suborganizationName, $packageIdOrName, $customJson, $credentialId = null, $defaultSuborganizationAccess = null) + { + $data = new CustomPackageConfig($customJson, $credentialId, $defaultSuborganizationAccess); + + return $this->put(sprintf('/suborganizations/%s/packages/%s/', $suborganizationName, $packageIdOrName), $data->toParameters()); + } + + public function remove($suborganizationName, $packageIdOrName) + { + return $this->delete(sprintf('/suborganizations/%s/packages/%s/', $suborganizationName, $packageIdOrName)); + } + + public function listDependents($suborganizationName, $packageIdOrName) + { + return $this->get(sprintf('/suborganizations/%s/packages/%s/dependents/', $suborganizationName, $packageIdOrName)); + } +} diff --git a/src/Api/Subrepositories.php b/src/Api/Subrepositories.php index 075825b..1e3d108 100644 --- a/src/Api/Subrepositories.php +++ b/src/Api/Subrepositories.php @@ -11,6 +11,9 @@ use PrivatePackagist\ApiClient\Exception\InvalidArgumentException; +/** + * @deprecated Use the Suborganizations API instead + */ class Subrepositories extends AbstractApi { public function all() diff --git a/src/Api/Subrepositories/MirroredRepositories.php b/src/Api/Subrepositories/MirroredRepositories.php index 8670cae..3875f8a 100644 --- a/src/Api/Subrepositories/MirroredRepositories.php +++ b/src/Api/Subrepositories/MirroredRepositories.php @@ -12,6 +12,9 @@ use PrivatePackagist\ApiClient\Api\AbstractApi; use PrivatePackagist\ApiClient\Exception\InvalidArgumentException; +/** + * @deprecated Use \PrivatePackagist\ApiClient\Api\Suborganizations\MirroredRepositories instead + */ class MirroredRepositories extends AbstractApi { public function all($subrepositoryName) diff --git a/src/Api/Subrepositories/Packages.php b/src/Api/Subrepositories/Packages.php index 9df4ae9..7f0a0b1 100644 --- a/src/Api/Subrepositories/Packages.php +++ b/src/Api/Subrepositories/Packages.php @@ -14,6 +14,9 @@ use PrivatePackagist\ApiClient\Payload\CustomPackageConfig; use PrivatePackagist\ApiClient\Payload\VcsPackageConfig; +/** + * @deprecated Use \PrivatePackagist\ApiClient\Api\Suborganizations\Packages instead + */ class Packages extends AbstractApi { public function all($subrepositoryName, array $filters = []) diff --git a/src/Api/Teams.php b/src/Api/Teams.php index 714bd71..c0aeebb 100644 --- a/src/Api/Teams.php +++ b/src/Api/Teams.php @@ -25,7 +25,7 @@ public function create(string $name, TeamPermissions $permissions): array 'permissions' => [ 'canEditTeamPackages' => (bool) $permissions->canEditTeamPackages, 'canAddPackages' => (bool) $permissions->canAddPackages, - 'canCreateSubrepositories' => (bool) $permissions->canCreateSubrepositories, + 'canCreateSuborganizations' => $permissions->canCreateSuborganizations || $permissions->canCreateSubrepositories, 'canViewVendorCustomers' => (bool) $permissions->canViewVendorCustomers, 'canManageVendorCustomers' => (bool) $permissions->canManageVendorCustomers, ], @@ -46,7 +46,7 @@ public function edit($teamId, string $name, TeamPermissions $permissions): array 'permissions' => [ 'canEditTeamPackages' => (bool) $permissions->canEditTeamPackages, 'canAddPackages' => (bool) $permissions->canAddPackages, - 'canCreateSubrepositories' => (bool) $permissions->canCreateSubrepositories, + 'canCreateSuborganizations' => $permissions->canCreateSuborganizations || $permissions->canCreateSubrepositories, 'canViewVendorCustomers' => (bool) $permissions->canViewVendorCustomers, 'canManageVendorCustomers' => (bool) $permissions->canManageVendorCustomers, ], diff --git a/src/Client.php b/src/Client.php index 381423a..19638cc 100644 --- a/src/Client.php +++ b/src/Client.php @@ -74,19 +74,28 @@ public function customers() } /** - * @deprecated Use Client::subrepositories instead + * @deprecated Use Client::suborganizations instead */ - #[\Deprecated('Use Client::subrepositories instead', '1.16.1')] + #[\Deprecated('Use Client::suborganizations instead', '1.16.1')] public function projects() { return new Api\Subrepositories($this, $this->responseMediator); } + /** + * @deprecated Use Client::suborganizations instead + */ + #[\Deprecated('Use Client::suborganizations instead', '1.38.0')] public function subrepositories() { return new Api\Subrepositories($this, $this->responseMediator); } + public function suborganizations() + { + return new Api\Suborganizations($this, $this->responseMediator); + } + public function organization() { return new Api\Organization($this, $this->responseMediator); diff --git a/src/TeamPermissions.php b/src/TeamPermissions.php index 8024424..0e64f09 100644 --- a/src/TeamPermissions.php +++ b/src/TeamPermissions.php @@ -13,7 +13,10 @@ final class TeamPermissions { public const PERMISSION_CAN_EDIT_TEAM_PACKAGES = 1 << 0; public const PERMISSION_CAN_ADD_PACKAGES = 1 << 1; + /** @deprecated Use PERMISSION_CAN_CREATE_SUBORGANIZATIONS instead */ + #[\Deprecated('Use TeamPermissions::PERMISSION_CAN_CREATE_SUBORGANIZATIONS instead', '1.38.0')] public const PERMISSION_CAN_CREATE_SUBREPOSITORIES = 1 << 2; + public const PERMISSION_CAN_CREATE_SUBORGANIZATIONS = 1 << 2; public const PERMISSION_CAN_VIEW_VENDOR_CUSTOMERS = 1 << 3; public const PERMISSION_CAN_MANAGE_VENDOR_CUSTOMERS = 1 << 4; @@ -21,8 +24,12 @@ final class TeamPermissions public $canEditTeamPackages = false; /** @var bool */ public $canAddPackages = false; - /** @var bool */ + /** + * @var bool + * @deprecated Use $canCreateSuborganizations instead + */ public $canCreateSubrepositories = false; + public $canCreateSuborganizations = false; /** @var bool */ public $canViewVendorCustomers = false; /** @var bool */ @@ -33,7 +40,8 @@ public static function fromFlags(int $flags): self $permissions = new self; $permissions->canEditTeamPackages = ($flags & self::PERMISSION_CAN_EDIT_TEAM_PACKAGES) > 0; $permissions->canAddPackages = ($flags & self::PERMISSION_CAN_ADD_PACKAGES) > 0; - $permissions->canCreateSubrepositories = ($flags & self::PERMISSION_CAN_CREATE_SUBREPOSITORIES) > 0; + $permissions->canCreateSubrepositories = ($flags & self::PERMISSION_CAN_CREATE_SUBORGANIZATIONS) > 0; + $permissions->canCreateSuborganizations = ($flags & self::PERMISSION_CAN_CREATE_SUBORGANIZATIONS) > 0; $permissions->canViewVendorCustomers = ($flags & self::PERMISSION_CAN_VIEW_VENDOR_CUSTOMERS) > 0; $permissions->canManageVendorCustomers = ($flags & self::PERMISSION_CAN_MANAGE_VENDOR_CUSTOMERS) > 0; return $permissions; @@ -41,10 +49,13 @@ public static function fromFlags(int $flags): self public static function fromTeamResponse(array $team): self { + $canCreateSuborganizations = isset($team['permissions']['canCreateSuborganizations']) && $team['permissions']['canCreateSuborganizations'] || isset($team['permissions']['canCreateSubrepositories']) && $team['permissions']['canCreateSubrepositories']; + $permissions = new self; $permissions->canEditTeamPackages = isset($team['permissions']['canEditTeamPackages']) && $team['permissions']['canEditTeamPackages']; $permissions->canAddPackages = isset($team['permissions']['canAddPackages']) && $team['permissions']['canAddPackages']; - $permissions->canCreateSubrepositories = isset($team['permissions']['canCreateSubrepositories']) && $team['permissions']['canCreateSubrepositories']; + $permissions->canCreateSubrepositories = $canCreateSuborganizations; + $permissions->canCreateSuborganizations = $canCreateSuborganizations; $permissions->canViewVendorCustomers = isset($team['permissions']['canViewVendorCustomers']) && $team['permissions']['canViewVendorCustomers']; $permissions->canManageVendorCustomers = isset($team['permissions']['canManageVendorCustomers']) && $team['permissions']['canManageVendorCustomers']; return $permissions; diff --git a/tests/Api/Suborganizations/MirroredRepositoriesTest.php b/tests/Api/Suborganizations/MirroredRepositoriesTest.php new file mode 100644 index 0000000..1421d44 --- /dev/null +++ b/tests/Api/Suborganizations/MirroredRepositoriesTest.php @@ -0,0 +1,170 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PrivatePackagist\ApiClient\Api\Suborganizations; + +use PHPUnit\Framework\MockObject\MockObject; +use PrivatePackagist\ApiClient\Api\ApiTestCase; + +class MirroredRepositoriesTest extends ApiTestCase +{ + public function testAll() + { + $suborganizationName = 'suborganization'; + $expected = [ + $this->getProjectMirroredRepositoryDefinition(), + ]; + + /** @var MirroredRepositories&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($this->equalTo('/suborganizations/suborganization/mirrored-repositories/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->all($suborganizationName)); + } + + public function testShow() + { + $suborganizationName = 'suborganization'; + $expected = $this->getProjectMirroredRepositoryDefinition(); + + /** @var MirroredRepositories&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($this->equalTo('/suborganizations/suborganization/mirrored-repositories/1/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->show($suborganizationName, 1)); + } + + public function testAdd() + { + $suborganizationName = 'suborganization'; + $expected = $this->getProjectMirroredRepositoryDefinition(); + $data = [ + 'id' => $expected['mirroredRepository']['id'], + 'mirroringBehavior' => $expected['mirroringBehavior'], + ]; + + /** @var MirroredRepositories&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with($this->equalTo('/suborganizations/suborganization/mirrored-repositories/'), $this->equalTo([$data])) + ->willReturn([$expected]); + + $this->assertSame([$expected], $api->add($suborganizationName, [$data])); + } + + public function testEdit() + { + $suborganizationName = 'suborganization'; + $expected = $this->getProjectMirroredRepositoryDefinition(); + $mirroredRepositoryId = $expected['mirroredRepository']['id']; + $data = [ + 'mirroringBehavior' => $mirroringBehaviour = $expected['mirroringBehavior'], + ]; + + /** @var MirroredRepositories&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with($this->equalTo('/suborganizations/suborganization/mirrored-repositories/1/'), $this->equalTo($data)) + ->willReturn($expected); + + $this->assertSame($expected, $api->edit($suborganizationName, $mirroredRepositoryId, $mirroringBehaviour)); + } + public function testRemove() + { + $suborganizationName = 'suborganization'; + /** @var MirroredRepositories&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with($this->equalTo('/suborganizations/suborganization/mirrored-repositories/1/')) + ->willReturn([]); + + $this->assertSame([], $api->remove($suborganizationName, 1)); + } + + public function testListPackages() + { + $suborganizationName = 'suborganization'; + $expected = [[ + 'name' => 'acme/cool-lib', + 'origin' => 'public-mirror', + 'credentials' => null, + ]]; + /** @var MirroredRepositories&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($this->equalTo('/suborganizations/suborganization/mirrored-repositories/1/packages/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->listPackages($suborganizationName, 1)); + } + + public function testAddPackages() + { + $suborganizationName = 'suborganization'; + $expected = [[ + 'id' => 'job-id', + 'status' => 'queued', + ]]; + + $packages = [ + 'acme/cool-lib', + ]; + + /** @var MirroredRepositories&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with($this->equalTo('/suborganizations/suborganization/mirrored-repositories/1/packages/'), $this->equalTo($packages)) + ->willReturn($expected); + + $this->assertSame($expected, $api->addPackages($suborganizationName, 1, $packages)); + } + + public function testRemovePackages() + { + $suborganizationName = 'suborganization'; + /** @var MirroredRepositories&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with($this->equalTo('/suborganizations/suborganization/mirrored-repositories/1/packages/')) + ->willReturn([]); + + $this->assertSame([], $api->removePackages($suborganizationName, 1)); + } + + protected function getApiClass() + { + return MirroredRepositories::class; + } + + private function getProjectMirroredRepositoryDefinition() + { + return [ + 'mirroringBehavior' => 'add_on_use', + 'mirroredRepository' => [ + 'id' => 1, + 'name' => 'Packagist.org', + 'url' => 'https://packagist.org', + 'mirroringBehavior' => 'add_on_use', + 'credentials' => null, + ] + ]; + } +} diff --git a/tests/Api/Suborganizations/PackagesTest.php b/tests/Api/Suborganizations/PackagesTest.php new file mode 100644 index 0000000..0753df0 --- /dev/null +++ b/tests/Api/Suborganizations/PackagesTest.php @@ -0,0 +1,220 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PrivatePackagist\ApiClient\Api\Suborganizations; + +use PHPUnit\Framework\MockObject\MockObject; +use PrivatePackagist\ApiClient\Api\ApiTestCase; +use PrivatePackagist\ApiClient\Exception\InvalidArgumentException; + +class PackagesTest extends ApiTestCase +{ + public function testAll() + { + $suborganizationName = 'suborganization'; + $expected = [ + [ + 'id' => 1, + 'name' => 'acme-website/package', + ], + ]; + + /** @var Packages&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($this->equalTo('/suborganizations/suborganization/packages/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->all($suborganizationName)); + } + + public function testAllWithFilters() + { + $suborganizationName = 'suborganization'; + $expected = [ + [ + 'id' => 1, + 'name' => 'acme-website/package', + ], + ]; + + $filters = [ + 'origin' => \PrivatePackagist\ApiClient\Api\Packages::ORIGIN_PRIVATE, + ]; + + /** @var Packages&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($this->equalTo('/suborganizations/suborganization/packages/'), $this->equalTo($filters)) + ->willReturn($expected); + + $this->assertSame($expected, $api->all($suborganizationName, $filters)); + } + + public function testAllWithInvalidFilters() + { + $this->expectException(InvalidArgumentException::class); + + $suborganizationName = 'suborganization'; + $filters = [ + 'origin' => 'invalid' + ]; + + /** @var Packages&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->never()) + ->method('get'); + + $api->all($suborganizationName, $filters); + } + + public function testShow() + { + $suborganizationName = 'suborganization'; + $expected = [ + 'id' => 1, + 'name' => 'acme-website/package', + ]; + + /** @var Packages&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($this->equalTo('/suborganizations/suborganization/packages/acme-website/package')) + ->willReturn($expected); + + $this->assertSame($expected, $api->show($suborganizationName, 'acme-website/package')); + } + + public function testCreateVcsPackage() + { + $suborganizationName = 'suborganization'; + $expected = [ + 'id' => 'job-id', + 'status' => 'queued', + ]; + + /** @var Packages&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with($this->equalTo('/suborganizations/suborganization/packages/'), $this->equalTo(['repoType' => 'vcs', 'repoUrl' => 'localhost', 'credentials' => null])) + ->willReturn($expected); + + $this->assertSame($expected, $api->createVcsPackage($suborganizationName, 'localhost')); + } + + /** + * @dataProvider customProvider + */ + public function testCreateCustomPackage($customJson) + { + $suborganizationName = 'suborganization'; + $expected = [ + 'id' => 'job-id', + 'status' => 'queued', + ]; + + /** @var Packages&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with($this->equalTo('/suborganizations/suborganization/packages/'), $this->equalTo(['repoType' => 'package', 'repoConfig' => '{}', 'credentials' => null])) + ->willReturn($expected); + + $this->assertSame($expected, $api->createCustomPackage($suborganizationName, $customJson)); + } + + public function customProvider() + { + return [ + ['{}'], + [new \stdClass()], + ]; + } + + public function testEditVcsPackage() + { + $suborganizationName = 'suborganization'; + $expected = [ + 'id' => 'job-id', + 'status' => 'queued', + ]; + + /** @var Packages&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with($this->equalTo('/suborganizations/suborganization/packages/acme-website/package/'), $this->equalTo(['repoType' => 'vcs', 'repoUrl' => 'localhost', 'credentials' => null])) + ->willReturn($expected); + + $this->assertSame($expected, $api->editVcsPackage($suborganizationName, 'acme-website/package', 'localhost')); + } + + public function testEditCustomPackage() + { + $suborganizationName = 'suborganization'; + $expected = [ + 'id' => 'job-id', + 'status' => 'queued', + ]; + + /** @var Packages&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with($this->equalTo('/suborganizations/suborganization/packages/acme-website/package/'), $this->equalTo(['repoType' => 'package', 'repoConfig' => '{}', 'credentials' => null])) + ->willReturn($expected); + + $this->assertSame($expected, $api->editCustomPackage($suborganizationName, 'acme-website/package', '{}')); + } + + public function testRemove() + { + $suborganizationName = 'suborganization'; + $expected = []; + + /** @var Packages&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with($this->equalTo('/suborganizations/suborganization/packages/acme-website/package/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->remove($suborganizationName, 'acme-website/package')); + } + + public function testListDependents() + { + $suborganizationName = 'suborganization'; + $packageName = 'acme-website/core-package'; + $expected = [ + [ + 'id' => 1, + 'name' => 'acme-website/package', + ], + ]; + + /** @var Packages&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($this->equalTo('/suborganizations/suborganization/packages/acme-website/core-package/dependents/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->listDependents($suborganizationName, $packageName)); + } + + protected function getApiClass() + { + return Packages::class; + } +} diff --git a/tests/Api/SuborganizationsTest.php b/tests/Api/SuborganizationsTest.php new file mode 100644 index 0000000..9b28bda --- /dev/null +++ b/tests/Api/SuborganizationsTest.php @@ -0,0 +1,243 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PrivatePackagist\ApiClient\Api; + +use PHPUnit\Framework\MockObject\MockObject; + +class SuborganizationsTest extends ApiTestCase +{ + public function testAll() + { + $expected = [ + $this->getSuborganizationDefinition(), + ]; + + /** @var Suborganizations&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($this->equalTo('/suborganizations/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->all()); + } + + public function testShow() + { + $expected = $this->getSuborganizationDefinition(); + + $suborganizationName = 'suborganization'; + + /** @var Suborganizations&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($this->equalTo('/suborganizations/suborganization/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->show($suborganizationName)); + } + + public function testCreate() + { + $expected = $this->getSuborganizationDefinition(); + + /** @var Suborganizations&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with($this->equalTo('/suborganizations/'), $this->equalTo(['name' => 'ACME Websites'])) + ->willReturn($expected); + + $this->assertSame($expected, $api->create('ACME Websites')); + } + + public function testRemove() + { + $expected = ''; + + /** @var Suborganizations&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with($this->equalTo('/suborganizations/suborganization/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->remove('suborganization')); + } + + public function testListTeams() + { + $expected = [ + [ + 'id' => 42, + 'name' => 'Owners', + 'permission' => 'owner', + 'members' => [], + 'suborganizations' => [], + ], + ]; + + /** @var Suborganizations&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($this->equalTo('/suborganizations/suborganization/teams/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->listTeams('suborganization')); + } + + public function testAddOrEditTeam() + { + $expected = [ + [ + 'id' => 42, + 'name' => 'Owners', + 'permission' => 'owner', + 'members' => [], + 'suborganizations' => [], + ], + ]; + + $teams = [['id' => 42, 'permission' => 'owner']]; + + /** @var Suborganizations&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with($this->equalTo('/suborganizations/suborganization/teams/'), $this->equalTo($teams)) + ->willReturn($expected); + + $this->assertSame($expected, $api->addOrEditTeams('suborganization', $teams)); + } + + public function testRemoveTeam() + { + $expected = ''; + + /** @var Suborganizations&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with($this->equalTo('/suborganizations/suborganization/teams/42/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->removeTeam('suborganization', 42)); + } + + public function testListTokens() + { + $expected = [ + [ + 'description' => 'Generated Client Token', + 'access' => 'read', + 'url' => 'https://vendor-org.repo.packagist.com/acme-websites/', + 'user' => 'token', + 'token' => 'password', + 'lastUsed' => '2018-03-14T11:36:00+00:00' + ], + ]; + + /** @var Suborganizations&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($this->equalTo('/suborganizations/suborganization/tokens/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->listTokens('suborganization')); + } + + public function testCreateToken() + { + $expected = [ + 'description' => 'Suborganization Token', + 'access' => 'read', + 'url' => 'https://vendor-org.repo.packagist.com/acme-websites/', + 'user' => 'token', + 'token' => 'password', + 'lastUsed' => '2018-03-14T11:36:00+00:00' + ]; + + /** @var Suborganizations&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with($this->equalTo('/suborganizations/suborganization/tokens/'), $this->equalTo([ + 'description' => 'Suborganization Token', + 'access' => 'read', + ])) + ->willReturn($expected); + + $this->assertSame($expected, $api->createToken('suborganization', [ + 'description' => 'Suborganization Token', + 'access' => 'read', + ])); + } + + public function testRemoveToken() + { + $expected = []; + + /** @var Suborganizations&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with($this->equalTo('/suborganizations/suborganization/tokens/1/')) + ->willReturn($expected); + + $this->assertSame($expected, $api->removeToken('suborganization', 1)); + } + + public function testRegenerateToken() + { + $expected = []; + + /** @var Suborganizations&MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with($this->equalTo('/suborganizations/suborganization/tokens/1/regenerate'), $this->equalTo(['IConfirmOldTokenWillStopWorkingImmediately' => true])) + ->willReturn($expected); + + $this->assertSame($expected, $api->regenerateToken('suborganization', 1, ['IConfirmOldTokenWillStopWorkingImmediately' => true])); + } + + private function getSuborganizationDefinition() + { + return [ + 'id' => 1, + 'name' => 'ACME Websites', + 'urlName' => 'acme-websites', + 'teams' => [ + [ + 'id' => 1, + 'name' => 'Owners', + 'permission' => 'owner', + 'members' => [ + [ + 'id' => 12, + 'username' => 'username' + ] + ], + ] + ] + ]; + } + + /** + * @return string + */ + protected function getApiClass() + { + return Suborganizations::class; + } +} diff --git a/tests/Api/TeamsTest.php b/tests/Api/TeamsTest.php index 3d51384..4d2a143 100644 --- a/tests/Api/TeamsTest.php +++ b/tests/Api/TeamsTest.php @@ -102,7 +102,7 @@ public function testCreateTeam(): void 'permissions' => [ 'canEditTeamPackages' => true, 'canAddPackages' => false, - 'canCreateSubrepositories' => false, + 'canCreateSuborganizations' => false, 'canViewVendorCustomers' => true, 'canManageVendorCustomers' => false, ], @@ -117,7 +117,7 @@ public function testCreateTeam(): void 'permissions' => [ 'canEditTeamPackages' => true, 'canAddPackages' => false, - 'canCreateSubrepositories' => false, + 'canCreateSuborganizations' => false, 'canViewVendorCustomers' => true, 'canManageVendorCustomers' => false, ], @@ -138,7 +138,7 @@ public function testShowTeam(): void 'permissions' => [ 'canEditTeamPackages' => true, 'canAddPackages' => false, - 'canCreateSubrepositories' => false, + 'canCreateSuborganizations' => false, 'canViewVendorCustomers' => true, 'canManageVendorCustomers' => false, ], @@ -165,7 +165,7 @@ public function testEditTeam(): void 'permissions' => [ 'canEditTeamPackages' => true, 'canAddPackages' => false, - 'canCreateSubrepositories' => false, + 'canCreateSuborganizations' => false, 'canViewVendorCustomers' => true, 'canManageVendorCustomers' => false, ], @@ -180,7 +180,7 @@ public function testEditTeam(): void 'permissions' => [ 'canEditTeamPackages' => true, 'canAddPackages' => false, - 'canCreateSubrepositories' => false, + 'canCreateSuborganizations' => false, 'canViewVendorCustomers' => true, 'canManageVendorCustomers' => false, ], @@ -201,7 +201,7 @@ public function testTeamGrant(): void 'permissions' => [ 'canEditTeamPackages' => true, 'canAddPackages' => false, - 'canCreateSubrepositories' => false, + 'canCreateSuborganizations' => false, 'canViewVendorCustomers' => true, 'canManageVendorCustomers' => false, ], @@ -225,7 +225,7 @@ public function testTeamRevoke(): void 'permissions' => [ 'canEditTeamPackages' => true, 'canAddPackages' => false, - 'canCreateSubrepositories' => false, + 'canCreateSuborganizations' => false, 'canViewVendorCustomers' => true, 'canManageVendorCustomers' => false, ],