Skip to content

Commit cc4d46b

Browse files
authored
Add Organization Feature Flags & Vault Support (#299)
* Added Organization Feature Flags functionality in Organizations by introducing the `listOrganizationFeatureFlags` method. Added tests to validate organization feature flags. Resolved a deprecated notice in the OrganizationsTest to ensure compatibility with newer PHP versions. Implemented support for reading Vault items. Expanded the test suite to encompass Vault-related functionalities. * Added patch with pagination and other changes from @nicknisi This brings it into alignment with the Node SDK
1 parent ed4dd61 commit cc4d46b

File tree

6 files changed

+411
-0
lines changed

6 files changed

+411
-0
lines changed

lib/Organizations.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,4 +250,49 @@ public function listOrganizationRoles($organizationId)
250250

251251
return [$roles];
252252
}
253+
254+
/**
255+
* List feature flags for an organization.
256+
*
257+
* @param string $organizationId WorkOS organization ID to fetch feature flags for
258+
* @param int $limit Maximum number of records to return
259+
* @param null|string $before FeatureFlag ID to look before
260+
* @param null|string $after FeatureFlag ID to look after
261+
* @param Resource\Order $order The Order in which to paginate records
262+
*
263+
* @throws Exception\WorkOSException
264+
*
265+
* @return array{?string, ?string, Resource\FeatureFlag[]} An array containing the FeatureFlag ID to use as before and after cursor, and an array of FeatureFlag instances
266+
*/
267+
public function listOrganizationFeatureFlags(
268+
$organizationId,
269+
$limit = self::DEFAULT_PAGE_SIZE,
270+
$before = null,
271+
$after = null,
272+
$order = null
273+
) {
274+
$featureFlagsPath = "organizations/{$organizationId}/feature-flags";
275+
$params = [
276+
"limit" => $limit,
277+
"before" => $before,
278+
"after" => $after,
279+
"order" => $order
280+
];
281+
282+
$response = Client::request(
283+
Client::METHOD_GET,
284+
$featureFlagsPath,
285+
null,
286+
$params,
287+
true
288+
);
289+
290+
$featureFlags = [];
291+
list($before, $after) = Util\Request::parsePaginationArgs($response);
292+
foreach ($response["data"] as $responseData) {
293+
\array_push($featureFlags, Resource\FeatureFlag::constructFromResponse($responseData));
294+
}
295+
296+
return [$before, $after, $featureFlags];
297+
}
253298
}

lib/Resource/FeatureFlag.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace WorkOS\Resource;
4+
5+
/**
6+
* Class FeatureFlag.
7+
*
8+
* @property string $id
9+
* @property string $slug
10+
* @property string $name
11+
* @property string $description
12+
* @property string $createdAt
13+
* @property string $updatedAt
14+
*/
15+
16+
class FeatureFlag extends BaseWorkOSResource
17+
{
18+
public const RESOURCE_TYPE = "feature_flag";
19+
20+
public const RESOURCE_ATTRIBUTES = [
21+
"id",
22+
"slug",
23+
"name",
24+
"description",
25+
"createdAt",
26+
"updatedAt"
27+
];
28+
29+
public const RESPONSE_TO_RESOURCE_KEY = [
30+
"id" => "id",
31+
"slug" => "slug",
32+
"name" => "name",
33+
"description" => "description",
34+
"created_at" => "createdAt",
35+
"updated_at" => "updatedAt"
36+
];
37+
}

lib/Resource/VaultObject.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace WorkOS\Resource;
4+
5+
/**
6+
* Class VaultObject.
7+
*/
8+
class VaultObject extends BaseWorkOSResource
9+
{
10+
public const RESOURCE_TYPE = "vault_object";
11+
12+
public const RESOURCE_ATTRIBUTES = [
13+
"id",
14+
"name",
15+
"updatedAt",
16+
"value",
17+
"metadata"
18+
];
19+
20+
public const RESPONSE_TO_RESOURCE_KEY = [
21+
"id" => "id",
22+
"name" => "name",
23+
"updated_at" => "updatedAt",
24+
"value" => "value",
25+
"metadata" => "metadata"
26+
];
27+
}

lib/Vault.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
namespace WorkOS;
4+
5+
/**
6+
* Class Vault.
7+
*
8+
* This class facilitates the use of WorkOS Vault operations.
9+
*/
10+
class Vault
11+
{
12+
public const DEFAULT_PAGE_SIZE = 10;
13+
14+
/**
15+
* Get a Vault Object.
16+
*
17+
* @param string $vaultObjectId The unique identifier for the vault object.
18+
*
19+
* @throws Exception\WorkOSException
20+
*
21+
* @return Resource\VaultObject
22+
*/
23+
public function getVaultObject($vaultObjectId)
24+
{
25+
$vaultObjectPath = "vault/v1/kv/{$vaultObjectId}";
26+
27+
$response = Client::request(Client::METHOD_GET, $vaultObjectPath, null, null, true);
28+
29+
return Resource\VaultObject::constructFromResponse($response);
30+
}
31+
32+
/**
33+
* List Vault Objects.
34+
*
35+
* @param int $limit Maximum number of records to return
36+
* @param null|string $before Vault Object ID to look before
37+
* @param null|string $after Vault Object ID to look after
38+
* @param Resource\Order $order The Order in which to paginate records
39+
*
40+
* @return array{?string, ?string, Resource\VaultObject[]} An array containing the Vault Object ID to use as before and after cursor, and an array of VaultObject instances
41+
*
42+
* @throws Exception\WorkOSException
43+
*/
44+
public function listVaultObjects(
45+
$limit = self::DEFAULT_PAGE_SIZE,
46+
$before = null,
47+
$after = null,
48+
$order = null
49+
) {
50+
$vaultObjectsPath = "vault/v1/kv";
51+
$params = [
52+
"limit" => $limit,
53+
"before" => $before,
54+
"after" => $after,
55+
"order" => $order
56+
];
57+
58+
$response = Client::request(
59+
Client::METHOD_GET,
60+
$vaultObjectsPath,
61+
null,
62+
$params,
63+
true
64+
);
65+
66+
$vaultObjects = [];
67+
list($before, $after) = Util\Request::parsePaginationArgs($response);
68+
foreach ($response["data"] as $responseData) {
69+
\array_push($vaultObjects, Resource\VaultObject::constructFromResponse($responseData));
70+
}
71+
72+
return [$before, $after, $vaultObjects];
73+
}
74+
75+
76+
77+
78+
}

tests/WorkOS/OrganizationsTest.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ class OrganizationsTest extends TestCase
1010
setUp as protected traitSetUp;
1111
}
1212

13+
/**
14+
* @var Organizations
15+
*/
16+
protected $organizations;
17+
1318
protected function setUp(): void
1419
{
1520
$this->traitSetUp();
@@ -190,6 +195,34 @@ public function testListOrganizationRoles()
190195
$this->assertSame($role, $roles[0]->toArray());
191196
}
192197

198+
public function testListOrganizationFeatureFlags()
199+
{
200+
$featureFlagsPath = "organizations/org_01EHQMYV6MBK39QC5PZXHY59C3/feature-flags";
201+
202+
$result = $this->featureFlagsResponseFixture();
203+
204+
$params = [
205+
"limit" => 10,
206+
"before" => null,
207+
"after" => null,
208+
"order" => null
209+
];
210+
211+
$this->mockRequest(
212+
Client::METHOD_GET,
213+
$featureFlagsPath,
214+
null,
215+
$params,
216+
true,
217+
$result
218+
);
219+
220+
$featureFlag = $this->featureFlagFixture();
221+
222+
list($before, $after, $featureFlags) = $this->organizations->listOrganizationFeatureFlags("org_01EHQMYV6MBK39QC5PZXHY59C3");
223+
$this->assertSame($featureFlag, $featureFlags[0]->toArray());
224+
}
225+
193226
// Fixtures
194227

195228
private function createOrganizationResponseFixture()
@@ -342,4 +375,56 @@ private function roleFixture()
342375
"updated_at" => "2024-01-01T00:00:00.000Z"
343376
];
344377
}
378+
379+
private function featureFlagFixture()
380+
{
381+
return [
382+
"id" => "flag_01K2QR5YSWRB8J7GGAG05Y24HQ",
383+
"slug" => "flag3",
384+
"name" => "Flag3",
385+
"description" => "",
386+
"createdAt" => "2025-08-15T20:54:13.561Z",
387+
"updatedAt" => "2025-08-15T20:54:13.561Z"
388+
];
389+
}
390+
391+
private function featureFlagsResponseFixture()
392+
{
393+
return json_encode([
394+
"object" => "list",
395+
"data" => [
396+
[
397+
"object" => "feature_flag",
398+
"id" => "flag_01K2QR5YSWRB8J7GGAG05Y24HQ",
399+
"slug" => "flag3",
400+
"name" => "Flag3",
401+
"description" => "",
402+
"created_at" => "2025-08-15T20:54:13.561Z",
403+
"updated_at" => "2025-08-15T20:54:13.561Z"
404+
],
405+
[
406+
"object" => "feature_flag",
407+
"id" => "flag_01K2QR5HGK2HQVFDZ4T60GWGVD",
408+
"slug" => "flag2",
409+
"name" => "Flag2",
410+
"description" => "",
411+
"created_at" => "2025-08-15T20:53:59.952Z",
412+
"updated_at" => "2025-08-15T20:53:59.952Z"
413+
],
414+
[
415+
"object" => "feature_flag",
416+
"id" => "flag_01K2QKSH38RF4P9FV917PE24R3",
417+
"slug" => "flag1",
418+
"name" => "Flag1",
419+
"description" => "",
420+
"created_at" => "2025-08-15T19:37:32.005Z",
421+
"updated_at" => "2025-08-15T19:37:32.005Z"
422+
],
423+
],
424+
"list_metadata" => [
425+
"before" => "",
426+
"after" => ""
427+
]
428+
]);
429+
}
345430
}

0 commit comments

Comments
 (0)