From 53181d76a2e54e5786db6a03bea363f48bf247b0 Mon Sep 17 00:00:00 2001 From: Divyajose <75604843+divya-intelli@users.noreply.github.com> Date: Tue, 9 Jan 2024 19:31:45 +0530 Subject: [PATCH 1/8] Fix for test failing for symfony 6.4 (#342) --- composer.json | 2 +- .../Denormalizer/ReportCriteriaDenormalizerTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 0b0c819a..f58114e7 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "symfony/options-resolver": "^6.3", "symfony/property-access": "^6.3", "symfony/property-info": "^6.3", - "symfony/serializer": "^6.3" + "symfony/serializer": "^6.3.11" }, "require-dev": { "dms/phpunit-arraysubset-asserts": "^0.4.0", diff --git a/tests/Api/Monetization/Denormalizer/ReportCriteriaDenormalizerTest.php b/tests/Api/Monetization/Denormalizer/ReportCriteriaDenormalizerTest.php index d0b1158b..f471a76e 100644 --- a/tests/Api/Monetization/Denormalizer/ReportCriteriaDenormalizerTest.php +++ b/tests/Api/Monetization/Denormalizer/ReportCriteriaDenormalizerTest.php @@ -31,7 +31,7 @@ class ReportCriteriaDenormalizerTest extends TestCase { - /** @var \Apigee\Edge\Api\Monetization\Denormalizer\ReportCriteriaDenormalizer */ + /** @var Apigee\Edge\Api\Monetization\Denormalizer\ReportCriteriaDenormalizer */ protected static $denormalizer; /** @@ -46,7 +46,7 @@ public static function setUpBeforeClass(): void public function testDenormalizeWithAbtractClassNoContext(): void { - $this->expectException('\Error'); + $this->expectException('\Symfony\Component\Serializer\Exception\NotNormalizableValueException'); static::$denormalizer->denormalize((object) [], AbstractCriteria::class, 'json'); } From 189c2dc5aa6cff686c285e7a92e31b9c5f092288 Mon Sep 17 00:00:00 2001 From: Kedar Khaire Date: Wed, 10 Jan 2024 12:42:37 +0530 Subject: [PATCH 2/8] Fix for Team app credentials listings sorted in ascending order (#337) * Added usort at root level to provide common sort output at all displays * Fixing indentation style * PHP CS fixes * Arrow function used * PHP CS FIX * Chnages to fix PossiblyNullReference error --- src/Api/Management/Entity/App.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Api/Management/Entity/App.php b/src/Api/Management/Entity/App.php index 0b030015..b089189d 100644 --- a/src/Api/Management/Entity/App.php +++ b/src/Api/Management/Entity/App.php @@ -25,6 +25,7 @@ use Apigee\Edge\Entity\Property\ScopesPropertyAwareTrait; use Apigee\Edge\Entity\Property\StatusPropertyAwareTrait; use Apigee\Edge\Structure\AttributesProperty; +use LogicException; /** * Class App. @@ -55,7 +56,7 @@ abstract class App extends Entity implements AppInterface /** @var string Url, used for "three-legged" OAuth grant type flows. */ protected $callbackUrl; - /** @var \Apigee\Edge\Api\Management\Entity\AppCredential[] */ + /** @var AppCredential[] */ protected $credentials = []; /** @var string[] */ @@ -187,6 +188,8 @@ public function setCallbackUrl(string $callbackUrl): void */ public function getCredentials(): array { + usort($this->credentials, static fn (AppCredentialInterface $a, AppCredentialInterface $b) => $b->getIssuedAt() <=> $a->getIssuedAt()); + return $this->credentials; } @@ -195,7 +198,7 @@ public function getCredentials(): array * * Credentials, included in app, can not be changed by modifying them on the entity level. * - * @param \Apigee\Edge\Api\Management\Entity\AppCredentialInterface ...$credentials + * @param AppCredentialInterface ...$credentials * * @internal */ @@ -238,14 +241,14 @@ final public function getApiProducts(): array * * @param array $initialApiProducts * - * @throws \LogicException If used to update existing App. + * @throws LogicException If used to update existing App. */ final public function setInitialApiProducts(array $initialApiProducts): void { if (!$this->appId) { $this->initialApiProducts = $initialApiProducts; } else { - throw new \LogicException('This method is only supported for creating a new app.'); + throw new LogicException('This method is only supported for creating a new app.'); } } } From 14b01a8aafb180be35df8038c16f174f7b5a8ecc Mon Sep 17 00:00:00 2001 From: Shishir <75600200+shishir-intelli@users.noreply.github.com> Date: Wed, 10 Jan 2024 17:30:47 +0530 Subject: [PATCH 3/8] Fix attribute values lost in PUT call while creating AppGroup (#340) --- .../Controller/AppGroupMembersController.php | 24 +++++++++++++++++-- .../AppGroupMembersControllerInterface.php | 6 ++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/Api/ApigeeX/Controller/AppGroupMembersController.php b/src/Api/ApigeeX/Controller/AppGroupMembersController.php index a4fe6b4b..411eaa3d 100644 --- a/src/Api/ApigeeX/Controller/AppGroupMembersController.php +++ b/src/Api/ApigeeX/Controller/AppGroupMembersController.php @@ -20,6 +20,7 @@ use Apigee\Edge\Api\ApigeeX\Serializer\AppGroupMembershipSerializer; use Apigee\Edge\Api\ApigeeX\Structure\AppGroupMembership; +use Apigee\Edge\Api\Management\Serializer\AttributesPropertyAwareEntitySerializer; use Apigee\Edge\ClientInterface; use Apigee\Edge\Controller\AbstractController; use Apigee\Edge\Controller\OrganizationAwareControllerTrait; @@ -47,7 +48,7 @@ class AppGroupMembersController extends AbstractController implements AppGroupMe * * @param string $appGroup * @param string $organization - * @param \Apigee\Edge\ClientInterface $client + * @param ClientInterface $client */ public function __construct(string $appGroup, string $organization, ClientInterface $client) { @@ -73,8 +74,10 @@ public function getMembers(): AppGroupMembership public function setMembers(AppGroupMembership $members): AppGroupMembership { $members = $this->serializer->normalize($members); - $apigeeReservedMembers = new AttributesProperty(); + // We don't have a separate API to get appgroup attributes, + // that is why we are calling getAppGroupAttributes() method. + $apigeeReservedMembers = $this->getAppGroupAttributes(); // Adding the new members into the attribute. $apigeeReservedMembers->add('__apigee_reserved__developer_details', json_encode($members)); $response = $this->client->put( @@ -101,6 +104,23 @@ public function removeMember(string $email): void $this->client->delete($this->getBaseEndpointUri()->withPath("{$this->getBaseEndpointUri()->getPath()}/{$encoded}")); } + /** + * Helper function for getting all attributes in AppGroup. + * + * @return AttributesProperty + */ + public function getAppGroupAttributes(): AttributesProperty + { + $appGroup = $this->responseToArray($this->client->get($this->getBaseEndpointUri())); + $serializer = new AttributesPropertyAwareEntitySerializer(); + $appGroupAttributes = $serializer->denormalize( + $appGroup['attributes'], + AttributesProperty::class + ); + + return $appGroupAttributes; + } + /** * {@inheritdoc} */ diff --git a/src/Api/ApigeeX/Controller/AppGroupMembersControllerInterface.php b/src/Api/ApigeeX/Controller/AppGroupMembersControllerInterface.php index 9f5f67b1..a321d92e 100644 --- a/src/Api/ApigeeX/Controller/AppGroupMembersControllerInterface.php +++ b/src/Api/ApigeeX/Controller/AppGroupMembersControllerInterface.php @@ -28,7 +28,7 @@ interface AppGroupMembersControllerInterface extends AppGroupAwareControllerInte /** * List all developers associated with a appgroup. * - * @return \Apigee\Edge\Api\ApigeeX\Structure\AppGroupMembership + * @return AppGroupMembership * Array of developers with their optional roles in the appgroup. */ public function getMembers(): AppGroupMembership; @@ -39,10 +39,10 @@ public function getMembers(): AppGroupMembership; * WARNING! If you pass en empty membership object you remove all developers * from the appgroup. * - * @param \Apigee\Edge\Api\ApigeeX\Structure\AppGroupMembership $members + * @param AppGroupMembership $members * Membership object with the changes to be applied. * - * @return \Apigee\Edge\Api\ApigeeX\Structure\AppGroupMembership + * @return AppGroupMembership * Membership object with the applied changes, it does not contain all * members. Use getMembers() to retrieve them. */ From 88b3cc2054798bc5fe0829c785b79edd167eddf7 Mon Sep 17 00:00:00 2001 From: Shishir <75600200+shishir-intelli@users.noreply.github.com> Date: Wed, 10 Jan 2024 17:32:17 +0530 Subject: [PATCH 4/8] Fix Invalid payload issue while editing/updating AppGroup/Teams in Apigee X (#344) --- src/Api/ApigeeX/Entity/AppGroup.php | 10 ++- src/Api/ApigeeX/Entity/AppGroupInterface.php | 10 ++- .../AppCredentialControllerTestBase.php | 64 +++++++++---------- .../AppGroupAppCredentialControllerTest.php | 8 +-- .../organizations/phpunit/appgroups/POST.json | 3 +- .../phpunit/appgroups/phpunit/PUT.json | 3 +- 6 files changed, 55 insertions(+), 43 deletions(-) diff --git a/src/Api/ApigeeX/Entity/AppGroup.php b/src/Api/ApigeeX/Entity/AppGroup.php index da1a3706..0c8dead0 100644 --- a/src/Api/ApigeeX/Entity/AppGroup.php +++ b/src/Api/ApigeeX/Entity/AppGroup.php @@ -18,18 +18,24 @@ namespace Apigee\Edge\Api\ApigeeX\Entity; -use Apigee\Edge\Api\Management\Entity\AppOwner; +use Apigee\Edge\Entity\CommonEntityPropertiesAwareTrait; +use Apigee\Edge\Entity\Entity; +use Apigee\Edge\Entity\Property\AttributesPropertyAwareTrait; use Apigee\Edge\Entity\Property\DisplayNamePropertyAwareTrait; use Apigee\Edge\Entity\Property\NamePropertyAwareTrait; +use Apigee\Edge\Entity\Property\StatusPropertyAwareTrait; use Apigee\Edge\Structure\AttributesProperty; /** * Describes an AppGroup entity. */ -class AppGroup extends AppOwner implements AppGroupInterface +class AppGroup extends Entity implements AppGroupInterface { use DisplayNamePropertyAwareTrait; use NamePropertyAwareTrait; + use AttributesPropertyAwareTrait; + use CommonEntityPropertiesAwareTrait; + use StatusPropertyAwareTrait; /** @var string|null */ protected $channelUri; diff --git a/src/Api/ApigeeX/Entity/AppGroupInterface.php b/src/Api/ApigeeX/Entity/AppGroupInterface.php index d422ba79..ecd3959e 100644 --- a/src/Api/ApigeeX/Entity/AppGroupInterface.php +++ b/src/Api/ApigeeX/Entity/AppGroupInterface.php @@ -18,16 +18,20 @@ namespace Apigee\Edge\Api\ApigeeX\Entity; -use Apigee\Edge\Api\Management\Entity\AppOwnerInterface; +use Apigee\Edge\Entity\CommonEntityPropertiesInterface; +use Apigee\Edge\Entity\Property\AttributesPropertyInterface; use Apigee\Edge\Entity\Property\DisplayNamePropertyInterface; use Apigee\Edge\Entity\Property\NamePropertyInterface; +use Apigee\Edge\Entity\Property\StatusPropertyInterface; /** * Interface AppGroupInterface. */ -interface AppGroupInterface extends AppOwnerInterface, +interface AppGroupInterface extends AttributesPropertyInterface, DisplayNamePropertyInterface, - NamePropertyInterface + NamePropertyInterface, + StatusPropertyInterface, + CommonEntityPropertiesInterface { /** * @param string $channelUri diff --git a/tests/Api/ApigeeX/Controller/AppCredentialControllerTestBase.php b/tests/Api/ApigeeX/Controller/AppCredentialControllerTestBase.php index 07f0212a..ca61bab3 100644 --- a/tests/Api/ApigeeX/Controller/AppCredentialControllerTestBase.php +++ b/tests/Api/ApigeeX/Controller/AppCredentialControllerTestBase.php @@ -18,10 +18,10 @@ namespace Apigee\Edge\Tests\Api\ApigeeX\Controller; +use Apigee\Edge\Api\ApigeeX\Entity\AppGroup; use Apigee\Edge\Api\Management\Controller\AppCredentialControllerInterface; use Apigee\Edge\Api\Management\Entity\AppCredentialInterface; use Apigee\Edge\Api\Management\Entity\AppInterface; -use Apigee\Edge\Api\Management\Entity\AppOwnerInterface; use Apigee\Edge\Structure\CredentialProductInterface; use Apigee\Edge\Tests\Api\Management\Entity\ApiProductTestEntityProviderTrait; use Apigee\Edge\Tests\Test\Controller\DefaultAPIClientAwareTrait; @@ -43,13 +43,13 @@ abstract class AppCredentialControllerTestBase extends EntityControllerTestBase // The order of these trait matters. Check @depends in test methods. use AttributesAwareEntityControllerTestTrait; - /** @var \Apigee\Edge\Api\ApigeeX\Entity\ApiProductInterface */ + /** @var ApiProductInterface */ protected static $testApiProduct; - /** @var \Apigee\Edge\Api\Management\Entity\AppOwnerInterface */ + /** @var AppOwnerInterface */ protected static $testAppOwner; - /** @var \Apigee\Edge\Api\Management\Entity\AppInterface */ + /** @var AppInterface */ protected static $testApp; /** @@ -66,12 +66,12 @@ public static function setUpBeforeClass(): void public function testCreatedAppHasAnEmptyCredential(): void { - /** @var \Apigee\Edge\Api\Management\Entity\DeveloperAppInterface $entity */ - /** @var \Apigee\Edge\Api\Management\Controller\AppByOwnerControllerInterface $controller */ + /** @var DeveloperAppInterface $entity */ + /** @var AppByOwnerControllerInterface $controller */ $entity = static::appByOwnerController()->load(static::$testApp->id()); $credentials = $entity->getCredentials(); $this->assertCount(1, $credentials); - /** @var \Apigee\Edge\Api\Management\Entity\AppCredentialInterface $credential */ + /** @var AppCredentialInterface $credential */ $credential = reset($credentials); $this->assertCount(0, $credential->getApiProducts()); $this->assertNotEmpty($credential->getConsumerKey()); @@ -82,7 +82,7 @@ public function testCreatedAppHasAnEmptyCredential(): void /** * @depends testCreatedAppHasAnEmptyCredential * - * @return \Apigee\Edge\Api\Management\Entity\AppCredentialInterface + * @return AppCredentialInterface */ public function testCreate(): AppCredentialInterface { @@ -102,13 +102,13 @@ public function testCreate(): AppCredentialInterface /** * @depends testCreate * - * @param \Apigee\Edge\Api\Management\Entity\AppCredentialInterface $created + * @param AppCredentialInterface $created * * @return string */ public function testLoad(AppCredentialInterface $created) { - /** @var \Apigee\Edge\Api\Management\Entity\AppCredentialInterface $loaded */ + /** @var AppCredentialInterface $loaded */ $loaded = static::entityController()->load($created->id()); $this->assertCount(count($loaded->getApiProducts()), $created->getApiProducts()); $this->assertEquals($created->getConsumerKey(), $loaded->getConsumerKey()); @@ -126,7 +126,7 @@ public function testLoad(AppCredentialInterface $created) */ public function testAddProducts(string $entityId): void { - /** @var \Apigee\Edge\Api\Management\Controller\AppCredentialControllerInterface $controller */ + /** @var AppCredentialControllerInterface $controller */ $controller = $this->entityController(); $credential = $controller->addProducts($entityId, [static::$testApiProduct->id()]); $productNames = $this->getCredentialProducts($credential); @@ -140,9 +140,9 @@ public function testAddProducts(string $entityId): void */ public function testOverrideScopes(string $entityId): void { - /** @var \Apigee\Edge\Api\Management\Controller\AppCredentialControllerInterface $controller */ + /** @var AppCredentialControllerInterface $controller */ $controller = $this->entityController(); - /** @var \Apigee\Edge\Api\Management\Entity\AppCredentialInterface $credential */ + /** @var AppCredentialInterface $credential */ $credential = $controller->load($entityId); $this->assertEmpty($credential->getScopes()); $credential = $controller->overrideScopes($entityId, ['scope 1']); @@ -165,9 +165,9 @@ public function testOverrideScopes(string $entityId): void public function testStatusChange(string $entityId): void { static::markOnlineTestSkipped(__FUNCTION__); - /** @var \Apigee\Edge\Api\Management\Controller\AppCredentialControllerInterface $controller */ + /** @var AppCredentialControllerInterface $controller */ $controller = static::entityController(); - /* @var \Apigee\Edge\Api\Management\Entity\AppCredentialInterface $credential */ + /* @var AppCredentialInterface $credential */ $controller->setStatus($entityId, AppCredentialControllerInterface::STATUS_REVOKE); $credential = $controller->load($entityId); $this->assertEquals($credential->getStatus(), AppCredentialInterface::STATUS_REVOKED); @@ -186,16 +186,16 @@ public function testStatusChange(string $entityId): void public function testApiProductStatusChange(string $entityId): void { static::markOnlineTestSkipped(__FUNCTION__); - /** @var \Apigee\Edge\Api\Management\Controller\AppCredentialControllerInterface $controller */ + /** @var AppCredentialControllerInterface $controller */ $controller = static::entityController(); - /* @var \Apigee\Edge\Api\Management\Entity\AppCredentialInterface $credential */ + /* @var AppCredentialInterface $credential */ $controller->setApiProductStatus( $entityId, static::$testApiProduct->id(), AppCredentialControllerInterface::STATUS_REVOKE ); $credential = $controller->load($entityId); - /** @var \Apigee\Edge\Structure\CredentialProduct $product */ + /** @var CredentialProduct $product */ foreach ($credential->getApiProducts() as $product) { if ($product->getApiproduct() === static::$testApiProduct->id()) { $this->assertEquals($product->getStatus(), CredentialProductInterface::STATUS_REVOKED); @@ -224,11 +224,11 @@ public function testApiProductStatusChange(string $entityId): void public function testGenerate(): string { static::markOnlineTestSkipped(__FUNCTION__); - /** @var \Apigee\Edge\Api\Management\Controller\AppCredentialControllerInterface $controller */ + /** @var AppCredentialControllerInterface $controller */ $controller = $this->entityController(); - /** @var \Apigee\Edge\Api\Management\Entity\AppInterface $app */ + /** @var AppInterface $app */ $app = static::appByOwnerController()->load(static::$testApp->id()); - /** @var \Apigee\Edge\Api\Management\Entity\AppCredentialInterface $credential */ + /** @var AppCredentialInterface $credential */ $credential = $controller->generate( [static::$testApiProduct->id()], $app->getAttributes(), @@ -243,7 +243,7 @@ public function testGenerate(): string // Thanks for the offline tests, we can not expect a concrete value // here. $this->assertNotEquals('-1', $credential->getExpiresAt()); - /** @var \Apigee\Edge\Api\Management\Entity\AppInterface $updatedApp */ + /** @var AppInterface $updatedApp */ $updatedApp = static::appByOwnerController()->load(static::$testApp->id()); // Credential generation should not deleted any previously existing app // credentials. @@ -260,13 +260,13 @@ public function testGenerate(): string public function testDeleteApiProduct(string $entityId): void { static::markOnlineTestSkipped(__FUNCTION__); - /** @var \Apigee\Edge\Api\Management\Controller\AppCredentialControllerInterface $controller */ + /** @var AppCredentialControllerInterface $controller */ $controller = static::entityController(); - /** @var \Apigee\Edge\Api\Management\Entity\AppCredentialInterface $credential */ + /** @var AppCredentialInterface $credential */ $credential = $controller->load($entityId); $productNames = $this->getCredentialProducts($credential); $this->assertContains(static::$testApiProduct->id(), $productNames); - /* @var \Apigee\Edge\Api\Management\Entity\AppCredentialInterface $credential */ + /* @var AppCredentialInterface $credential */ $controller->deleteApiProduct( $entityId, static::$testApiProduct->id() @@ -281,15 +281,15 @@ public function testDeleteApiProduct(string $entityId): void */ public function testAddAttributesToEntity(): string { - /** @var \Apigee\Edge\Api\Management\Entity\AppCredentialInterface $credential */ + /** @var AppCredentialInterface $credential */ $credentials = static::$testApp->getCredentials(); $credential = reset($credentials); - /** @var \Apigee\Edge\Structure\AttributesProperty $attributes */ + /** @var AttributesProperty $attributes */ $attributes = $credential->getAttributes(); $originalAttributes = $attributes->values(); $attributes->add('name1', 'value1'); $attributes->add('name2', 'value2'); - /** @var \Apigee\Edge\Structure\AttributesProperty $attributesProperty */ + /** @var AttributesProperty $attributesProperty */ $attributesProperty = static::entityController()->updateAttributes($credential->id(), $attributes); /** @var array $newAttributes */ $newAttributes = $attributesProperty->values(); @@ -329,19 +329,19 @@ public function testDelete(): void $this->assertFalse($found, 'Credential credential has not been deleted.'); } - abstract protected static function setupTestApp(AppOwnerInterface $appOwner): AppInterface; + abstract protected static function setupTestApp(AppGroup $appOwner): AppInterface; - abstract protected static function setupTestAppOwner(): AppOwnerInterface; + abstract protected static function setupTestAppOwner(): AppGroup; /** - * @return \Apigee\Edge\Tests\Test\Controller\EntityControllerTesterInterface|\Apigee\Edge\Api\Management\Controller\AppByOwnerControllerInterface + * @return EntityControllerTesterInterface|AppByOwnerControllerInterface */ abstract protected static function appByOwnerController(): EntityControllerTesterInterface; private function getCredentialProducts(AppCredentialInterface $credential) { return array_map(function ($product) { - /* @var \Apigee\Edge\Structure\CredentialProduct $product */ + /* @var CredentialProduct $product */ return $product->getApiproduct(); }, $credential->getApiProducts()); } diff --git a/tests/Api/ApigeeX/Controller/AppGroupAppCredentialControllerTest.php b/tests/Api/ApigeeX/Controller/AppGroupAppCredentialControllerTest.php index 85562193..38cc3ac3 100644 --- a/tests/Api/ApigeeX/Controller/AppGroupAppCredentialControllerTest.php +++ b/tests/Api/ApigeeX/Controller/AppGroupAppCredentialControllerTest.php @@ -19,9 +19,9 @@ namespace Apigee\Edge\Tests\Api\ApigeeX\Controller; use Apigee\Edge\Api\ApigeeX\Controller\AppGroupAppCredentialController; +use Apigee\Edge\Api\ApigeeX\Entity\AppGroup; use Apigee\Edge\Api\ApigeeX\Entity\AppGroupInterface; use Apigee\Edge\Api\Management\Entity\AppInterface; -use Apigee\Edge\Api\Management\Entity\AppOwnerInterface; use Apigee\Edge\ClientInterface; use Apigee\Edge\Entity\EntityInterface; use Apigee\Edge\Tests\Api\ApigeeX\Entity\AppGroupAppTestEntityProviderTrait; @@ -47,14 +47,14 @@ class AppGroupAppCredentialControllerTest extends AppCredentialControllerTestBas /** * {@inheritdoc} */ - protected static function entityController(ClientInterface $client = null): EntityControllerTesterInterface + protected static function entityController(?ClientInterface $client = null): EntityControllerTesterInterface { $client = $client ?? static::defaultAPIClient(); return new EntityControllerTester(new AppGroupAppCredentialController(static::defaultTestOrganization($client), static::$testAppOwner->id(), static::$testApp->id(), $client)); } - protected static function setupTestApp(AppOwnerInterface $appOwner): AppInterface + protected static function setupTestApp(AppGroup $appOwner): AppInterface { $app = static::getNewAppGroupApp(); static::appGroupAppController()->create($app); @@ -62,7 +62,7 @@ protected static function setupTestApp(AppOwnerInterface $appOwner): AppInterfac return $app; } - protected static function setupTestAppOwner(): AppOwnerInterface + protected static function setupTestAppOwner(): AppGroup { $appGroup = static::getNewAppGroup(); static::appGroupController()->create($appGroup); diff --git a/tests/offline-test-data/v1/organizations/phpunit/appgroups/POST.json b/tests/offline-test-data/v1/organizations/phpunit/appgroups/POST.json index c01a3e58..253d2117 100644 --- a/tests/offline-test-data/v1/organizations/phpunit/appgroups/POST.json +++ b/tests/offline-test-data/v1/organizations/phpunit/appgroups/POST.json @@ -1,5 +1,6 @@ { - "apps": [], + "channelUri": "http:\/\/example.com", + "channelId": "devportal", "name": "phpunit", "displayName": "A PHPUnit appgroup", "status": "active", diff --git a/tests/offline-test-data/v1/organizations/phpunit/appgroups/phpunit/PUT.json b/tests/offline-test-data/v1/organizations/phpunit/appgroups/phpunit/PUT.json index b35b8b85..c3dc9c68 100644 --- a/tests/offline-test-data/v1/organizations/phpunit/appgroups/phpunit/PUT.json +++ b/tests/offline-test-data/v1/organizations/phpunit/appgroups/phpunit/PUT.json @@ -1,5 +1,6 @@ { - "apps": [], + "channelUri": "http:\/\/example.com", + "channelId": "devportal", "name": "phpunit", "displayName": "(Edited) A PHPUnit appgroup", "status": "active", From b561085fc21531622670a7e1541c6dd89c69578a Mon Sep 17 00:00:00 2001 From: Kedar Khaire Date: Wed, 10 Jan 2024 21:38:20 +0530 Subject: [PATCH 5/8] Bump client version to 3.0.4 and changelog (#345) --- CHANGELOG.md | 7 +++++++ src/ClientInterface.php | 24 ++++++++++++------------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 735bc175..245caff2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,11 @@ # CHANGELOG +## [3.0.4](https://github.com/apigee/apigee-client-php/milestone/28?closed=1) +* [#343] Fix Invalid payload issue while editing/updating AppGroup/Teams in Apigee X. +* [#342] Fix for test failing for symfony 6.4. +* [#340] Fix for attribute values lost in PUT call while creating AppGroup. +* [#337] Fix for Team app credentials listings sorted in ascending order. +* [#334] Fix for \Apigee\Edge\HttpClient\Plugin\Authentication\GceServiceAccount::isAvailable() throws exception when called on non-GCE context. + ## [3.0.3](https://github.com/apigee/apigee-client-php/milestone/26?closed=1) * [#323] Add union type to suppress deprecation warning. * [#325] Fix error when AppGroup list is empty or do not returns appgroups array. diff --git a/src/ClientInterface.php b/src/ClientInterface.php index c42e55cb..5a11a875 100644 --- a/src/ClientInterface.php +++ b/src/ClientInterface.php @@ -63,12 +63,12 @@ interface ClientInterface extends HttpClient */ public const APIGEE_ON_GCP_ENDPOINT = 'https://apigee.googleapis.com/v1'; - public const VERSION = '3.0.3'; + public const VERSION = '3.0.4'; /** * Allows access to the last request, response and exception. * - * @return \Apigee\Edge\HttpClient\Utility\JournalInterface + * @return JournalInterface */ public function getJournal(): JournalInterface; @@ -108,10 +108,10 @@ public function getEndpoint(): string; * @param \Psr\Http\Message\UriInterface|string $uri * @param array $headers * - * @throws \Apigee\Edge\Exception\ApiException + * @throws Exception\ApiException * @throws \Http\Client\Exception * - * @return \Psr\Http\Message\ResponseInterface + * @return ResponseInterface */ public function get($uri, array $headers = []): ResponseInterface; @@ -121,10 +121,10 @@ public function get($uri, array $headers = []): ResponseInterface; * @param \Psr\Http\Message\UriInterface|string $uri * @param array $headers * - * @throws \Apigee\Edge\Exception\ApiException + * @throws Exception\ApiException * @throws \Http\Client\Exception * - * @return \Psr\Http\Message\ResponseInterface + * @return ResponseInterface */ public function head($uri, array $headers = []): ResponseInterface; @@ -135,10 +135,10 @@ public function head($uri, array $headers = []): ResponseInterface; * @param \Psr\Http\Message\StreamInterface|resource|string|null $body * @param array $headers * - * @throws \Apigee\Edge\Exception\ApiException + * @throws Exception\ApiException * @throws \Http\Client\Exception * - * @return \Psr\Http\Message\ResponseInterface + * @return ResponseInterface */ public function post($uri, $body = null, array $headers = []): ResponseInterface; @@ -149,10 +149,10 @@ public function post($uri, $body = null, array $headers = []): ResponseInterface * @param \Psr\Http\Message\StreamInterface|resource|string|null $body * @param array $headers * - * @throws \Apigee\Edge\Exception\ApiException + * @throws Exception\ApiException * @throws \Http\Client\Exception * - * @return \Psr\Http\Message\ResponseInterface + * @return ResponseInterface */ public function put($uri, $body = null, array $headers = []): ResponseInterface; @@ -163,10 +163,10 @@ public function put($uri, $body = null, array $headers = []): ResponseInterface; * @param \Psr\Http\Message\StreamInterface|resource|string|null $body * @param array $headers * - * @throws \Apigee\Edge\Exception\ApiException + * @throws Exception\ApiException * @throws \Http\Client\Exception * - * @return \Psr\Http\Message\ResponseInterface + * @return ResponseInterface */ public function delete($uri, $body = null, array $headers = []): ResponseInterface; } From f0b17907933dc6c72774d4009ba7195ca618814c Mon Sep 17 00:00:00 2001 From: Divyajose <75604843+divya-intelli@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:14:45 +0530 Subject: [PATCH 6/8] Fix for composer analyze failing in github action (#349) --- composer.json | 2 +- psalm.xml.dist | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f58114e7..32c9220f 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,7 @@ "phpunit/phpunit": "^9.6", "sebastian/comparator": "^4.0.5", "symfony/cache": "^6.3", - "vimeo/psalm": "^5.12" + "vimeo/psalm": "^5.20" }, "autoload": { "psr-4": { diff --git a/psalm.xml.dist b/psalm.xml.dist index b0582145..065e811d 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -52,5 +52,8 @@ + + + From d70542ecd3414e13de4d5da23b8649c1bf8a7a7c Mon Sep 17 00:00:00 2001 From: Shishir <75600200+shishir-intelli@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:05:28 +0530 Subject: [PATCH 7/8] Retrieving the next list items based on 'nextpagetoken' flag (#347) --- .../Controller/PaginationHelperTrait.php | 56 ++--- .../phpunit/appgroups/GET_pageSize=1000.json | 69 ++++++ .../phpunit/apps/GET_pageSize=1000.json | 206 ++++++++++++++++++ 3 files changed, 304 insertions(+), 27 deletions(-) create mode 100644 tests/offline-test-data/v1/organizations/phpunit/appgroups/GET_pageSize=1000.json create mode 100644 tests/offline-test-data/v1/organizations/phpunit/appgroups/phpunit/apps/GET_pageSize=1000.json diff --git a/src/Api/ApigeeX/Controller/PaginationHelperTrait.php b/src/Api/ApigeeX/Controller/PaginationHelperTrait.php index 4afe9b09..fcc860a7 100644 --- a/src/Api/ApigeeX/Controller/PaginationHelperTrait.php +++ b/src/Api/ApigeeX/Controller/PaginationHelperTrait.php @@ -25,7 +25,7 @@ /** * Utility methods for those controllers that supports paginated listing. * - * @see \Apigee\Edge\Api\ApigeeX\Controller\PaginatedEntityListingControllerInterface + * @see \PaginatedEntityListingControllerInterface */ trait PaginationHelperTrait { @@ -35,7 +35,7 @@ trait PaginationHelperTrait /** * {@inheritdoc} */ - public function createPager(int $limit = 0, string $pageToken = null): PagerInterface + public function createPager(int $limit = 0, ?string $pageToken = null): PagerInterface { // Create an anonymous class here because this class should not exist and be in use // in those controllers that do not work with entities that belongs to an organization. @@ -90,7 +90,7 @@ public function setLimit(int $limit): int /** * Loads paginated list of entities from Apigee X. * - * @param \Apigee\Edge\Api\ApigeeX\Structure\PagerInterface|null $pager + * @param PagerInterface|null $pager * Pager. * @param array $query_params * Additional query parameters. @@ -103,7 +103,7 @@ public function setLimit(int $limit): int * @psalm-suppress PossiblyNullArrayOffset $tmp->id() is always not null here. * @psalm-suppress PossiblyFalseArgument $tmp not be false. */ - protected function listEntities(PagerInterface $pager = null, array $query_params = [], string $key_provider = 'id'): array + protected function listEntities(?PagerInterface $pager = null, array $query_params = [], string $key_provider = 'id'): array { if ($pager) { $responseArray = $this->getResultsInRange($pager, $query_params); @@ -113,8 +113,14 @@ protected function listEntities(PagerInterface $pager = null, array $query_param return $this->responseArrayToArrayOfEntities($responseArray, $key_provider); } else { + // Default page size set to 1000, because the AppGroupApps endpoint + // does not return nextPageToken unless a pageSize is specified + // in the request parameters. + $pageSize = 1000; // Pass an empty pager to load all entities. - $responseArray = $this->getResultsInRange($this->createPager(), $query_params); + $responseArray = $this->getResultsInRange($this->createPager($pageSize), $query_params); + // Check flag 'nextPageToken' to get next items from the list. + $nextPageToken = array_key_exists('nextPageToken', $responseArray) ? $responseArray['nextPageToken'] : false; // Ignore entity type key from response, ex.: developer, apiproduct, // etc. $responseArray = reset($responseArray); @@ -123,30 +129,26 @@ protected function listEntities(PagerInterface $pager = null, array $query_param return []; } $entities = $this->responseArrayToArrayOfEntities($responseArray, $key_provider); - $lastEntity = end($entities); - $lastId = $lastEntity->{$key_provider}(); - do { - $tmp = $this->getResultsInRange($this->createPager(0, $lastId), $query_params); - // Ignore entity type key from response, ex.: developer, - // apiproduct, etc. - $tmp = reset($tmp); - // Remove the first item from the list because it is the same - // as the last item of $entities at this moment. - // Apigee X response always starts with the requested entity - // (pageToken). - array_shift($tmp); - $tmpEntities = $this->responseArrayToArrayOfEntities($tmp, $key_provider); - - if (count($tmpEntities) > 0) { + + if ($nextPageToken) { + do { + $tmp = $this->getResultsInRange($this->createPager($pageSize, $nextPageToken), $query_params); + // Check the flag 'nextPageToken' to get next items from the list. + $nextPageToken = array_key_exists('nextPageToken', $tmp) ? $tmp['nextPageToken'] : false; + // Ignore entity type key from response, ex.: developer, + // apiproduct, etc. + $tmp = reset($tmp); + // Remove the first item from the list because it is the same + // as the last item of $entities at this moment. + // Apigee X response always starts with the requested entity + // (pageToken). + array_shift($tmp); + $tmpEntities = $this->responseArrayToArrayOfEntities($tmp, $key_provider); // The returned entity array is keyed by entity id which // is unique so we can do this. $entities += $tmpEntities; - $lastEntity = end($tmpEntities); - $lastId = $lastEntity->{$key_provider}(); - } else { - $lastId = false; - } - } while ($lastId); + } while ($nextPageToken); + } return $entities; } @@ -155,7 +157,7 @@ protected function listEntities(PagerInterface $pager = null, array $query_param /** * Gets entities and entity ids in a provided range from Apigee X. * - * @param \Apigee\Edge\Api\ApigeeX\Structure\PagerInterface $pager + * @param PagerInterface $pager * limit object with configured pageToken and limit. * @param array $query_params * Query parameters for the API call. diff --git a/tests/offline-test-data/v1/organizations/phpunit/appgroups/GET_pageSize=1000.json b/tests/offline-test-data/v1/organizations/phpunit/appgroups/GET_pageSize=1000.json new file mode 100644 index 00000000..5085a7b2 --- /dev/null +++ b/tests/offline-test-data/v1/organizations/phpunit/appgroups/GET_pageSize=1000.json @@ -0,0 +1,69 @@ +{ + "appGroups": [ + { + "name": "phpunit", + "displayName": "A PHPUnit appgroup", + "status": "active", + "attributes": [ + { + "name": "foo", + "value": "bar" + } + ], + "createdAt": 1691588699000, + "lastModifiedAt": 1691588699617 + }, + { + "name": "1phpunit", + "displayName": "A PHPUnit appgroup", + "status": "active", + "attributes": [ + { + "name": "foo", + "value": "bar" + } + ], + "createdAt": 1691588699000, + "lastModifiedAt": 1691588699617 + }, + { + "name": "2phpunit", + "displayName": "A PHPUnit appgroup", + "status": "active", + "attributes": [ + { + "name": "foo", + "value": "bar" + } + ], + "createdAt": 1691588699000, + "lastModifiedAt": 1691588699617 + }, + { + "name": "3phpunit", + "displayName": "A PHPUnit appgroup", + "status": "active", + "attributes": [ + { + "name": "foo", + "value": "bar" + } + ], + "createdAt": 1691588699000, + "lastModifiedAt": 1691588699617 + }, + { + "name": "4phpunit", + "displayName": "A PHPUnit appgroup", + "status": "active", + "attributes": [ + { + "name": "foo", + "value": "bar" + } + ], + "createdAt": 1691588699000, + "lastModifiedAt": 1691588699617 + } + ] +} diff --git a/tests/offline-test-data/v1/organizations/phpunit/appgroups/phpunit/apps/GET_pageSize=1000.json b/tests/offline-test-data/v1/organizations/phpunit/appgroups/phpunit/apps/GET_pageSize=1000.json new file mode 100644 index 00000000..e3c1950c --- /dev/null +++ b/tests/offline-test-data/v1/organizations/phpunit/appgroups/phpunit/apps/GET_pageSize=1000.json @@ -0,0 +1,206 @@ +{ + "app": [ + { + "appFamily": "default", + "appId": "a47891c5-ca20-4f2f-975e-0e7588ec81f0", + "attributes": [ + { + "name": "DisplayName", + "value": "PHP Unit: Test app" + }, + { + "name": "Notes", + "value": "This is a test app created by PHP Unit." + }, + { + "name": "foo", + "value": "foo" + }, + { + "name": "bar", + "value": "baz" + } + ], + "callbackUrl": "http://foo.example.com", + "createdAt": 648345600000, + "createdBy": "phpunit@example.com", + "credentials": [ + { + "apiProducts": [], + "attributes": [], + "consumerKey": "Zww6GKaGRxQFGkfE36vgSN0eoac1Ymk3", + "consumerSecret": "LtdYkcmgDYV7kzxz", + "issuedAt": 648345600000, + "scopes": [], + "status": "approved" + } + ], + "appGroup": "phpunit", + "lastModifiedAt": 648345600000, + "lastModifiedBy": "phpunit@example.com", + "name": "phpunit_test_app", + "scopes": [], + "status": "approved" + }, + { + "appFamily": "default", + "appId": "b3e71cbb-7eb5-1111-b384-ac82bca1d9dc", + "attributes": [ + { + "name": "DisplayName", + "value": "PHP Unit: Test app" + }, + { + "name": "Notes", + "value": "This is a test app created by PHP Unit." + }, + { + "name": "foo", + "value": "bar" + } + ], + "callbackUrl": "http://example.com", + "createdAt": 648345600000, + "createdBy": "phpunit@example.com", + "credentials": [ + { + "apiProducts": [], + "attributes": [], + "consumerKey": "Zww6GKaGRxQFGkfE36vgSN0eoac1Ymk3", + "consumerSecret": "LtdYkcmgDYV7kzxz", + "issuedAt": 648345600000, + "scopes": [], + "status": "approved" + } + ], + "appGroup": "phpunit", + "lastModifiedAt": 648345600000, + "lastModifiedBy": "phpunit@example.com", + "name": "1phpunit_test_app", + "scopes": [], + "status": "approved" + }, + { + "appFamily": "default", + "appId": "b3e71cbb-7eb5-2222-b384-ac82bca1d9dc", + "attributes": [ + { + "name": "DisplayName", + "value": "PHP Unit: Test app" + }, + { + "name": "Notes", + "value": "This is a test app created by PHP Unit." + }, + { + "name": "foo", + "value": "foo" + }, + { + "name": "bar", + "value": "baz" + } + ], + "callbackUrl": "http://example.com", + "createdAt": 648345600000, + "createdBy": "phpunit@example.com", + "credentials": [ + { + "apiProducts": [], + "attributes": [], + "consumerKey": "wAXAIiOr2oJOVGqFltnm3Jwr2LE0GEuY", + "consumerSecret": "S8YjnsjmdBqDAegR", + "issuedAt": 648345600000, + "scopes": [], + "status": "approved" + } + ], + "appGroup": "phpunit", + "lastModifiedAt": 648345600000, + "lastModifiedBy": "phpunit@example.com", + "name": "2phpunit_test_app", + "scopes": [], + "status": "approved" + }, + { + "appFamily": "default", + "appId": "b3e71cbb-7eb5-3333-b384-ac82bca1d9dc", + "attributes": [ + { + "name": "DisplayName", + "value": "PHP Unit: Test app" + }, + { + "name": "Notes", + "value": "This is a test app created by PHP Unit." + }, + { + "name": "foo", + "value": "bar" + } + ], + "callbackUrl": "http://example.com", + "createdAt": 648345600000, + "createdBy": "phpunit@example.com", + "credentials": [ + { + "apiProducts": [], + "attributes": [], + "consumerKey": "wAXAIiOr2oJOVGqFltnm3Jwr2LE0GEuY", + "consumerSecret": "S8YjnsjmdBqDAegR", + "issuedAt": 648345600000, + "scopes": [], + "status": "approved" + } + ], + "appGroup": "phpunit", + "lastModifiedAt": 648345600000, + "lastModifiedBy": "phpunit@example.com", + "name": "3phpunit_test_app", + "scopes": [], + "status": "approved" + }, + { + "appFamily": "default", + "appId": "b3e71cbb-7eb5-4444-b384-ac82bca1d9dc", + "attributes": [ + { + "name": "DisplayName", + "value": "PHP Unit: Test app" + }, + { + "name": "Notes", + "value": "This is a test app created by PHP Unit." + }, + { + "name": "foo", + "value": "foo" + }, + { + "name": "bar", + "value": "baz" + } + ], + "callbackUrl": "http://example.com", + "createdAt": 648345600000, + "createdBy": "phpunit@example.com", + "credentials": [ + { + "apiProducts": [], + "attributes": [], + "consumerKey": "wAXAIiOr2oJOVGqFltnm3Jwr2LE0GEuY", + "consumerSecret": "S8YjnsjmdBqDAegR", + "issuedAt": 648345600000, + "scopes": [], + "status": "approved" + } + ], + "appGroup": "phpunit", + "lastModifiedAt": 648345600000, + "lastModifiedBy": "phpunit@example.com", + "name": "4phpunit_test_app", + "scopes": [], + "status": "approved" + } + ] +} From 13761ed9b0e6168f311cb40e7087a3af50f8e7e6 Mon Sep 17 00:00:00 2001 From: Shishir <75600200+shishir-intelli@users.noreply.github.com> Date: Tue, 13 Feb 2024 18:24:05 +0530 Subject: [PATCH 8/8] Bump client version to 3.0.5 and changelog (#355) --- CHANGELOG.md | 4 ++++ src/ClientInterface.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 245caff2..bc641ce6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ # CHANGELOG +## [3.0.5](https://github.com/apigee/apigee-client-php/milestone/29?closed=1) +* [#351] Retrieving the next list items based on 'nextpagetoken' flag in Apigee X. +* [#348] Fix for composer analyze failing in github action. + ## [3.0.4](https://github.com/apigee/apigee-client-php/milestone/28?closed=1) * [#343] Fix Invalid payload issue while editing/updating AppGroup/Teams in Apigee X. * [#342] Fix for test failing for symfony 6.4. diff --git a/src/ClientInterface.php b/src/ClientInterface.php index 5a11a875..a422dab4 100644 --- a/src/ClientInterface.php +++ b/src/ClientInterface.php @@ -63,7 +63,7 @@ interface ClientInterface extends HttpClient */ public const APIGEE_ON_GCP_ENDPOINT = 'https://apigee.googleapis.com/v1'; - public const VERSION = '3.0.4'; + public const VERSION = '3.0.5'; /** * Allows access to the last request, response and exception.