├── .github └── workflows │ ├── check-semantic.yml │ ├── release.yml │ ├── run-test-harness.yml │ └── test.yml ├── .gitignore ├── .openapi-generator-ignore ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── docs ├── Api │ └── DevCycleClient.md └── Model │ ├── DevCycleEvent.md │ ├── DevCycleUser.md │ ├── ErrorResponse.md │ ├── Feature.md │ ├── InlineResponse201.md │ ├── UserDataAndEventsBody.md │ └── Variable.md ├── examples ├── hello-world-http-proxy │ ├── Dockerfile │ ├── README.md │ ├── app.php │ ├── composer.json │ ├── composer.lock │ ├── docker-compose.yml │ ├── dvc-proxy-config.json │ ├── event.php │ ├── features.php │ ├── nginx.conf │ ├── supervisord.conf │ ├── variable.php │ └── variableAsync.php ├── hello-world-udp-proxy │ ├── Dockerfile │ ├── README.md │ ├── app.php │ ├── composer.json │ ├── composer.lock │ ├── docker-compose.yml │ ├── dvc-proxy-config.json │ ├── event.php │ ├── features.php │ ├── nginx.conf │ ├── supervisord.conf │ ├── variable.php │ └── variableAsync.php └── hello-world │ ├── .gitignore │ ├── README.md │ ├── app.php │ ├── composer.json │ ├── composer.lock │ ├── event.php │ ├── features.php │ ├── variable.php │ └── variableAsync.php ├── git_push.sh ├── lib ├── Api │ └── DevCycleClient.php ├── ApiException.php ├── HTTPConfiguration.php ├── HeaderSelector.php ├── Model │ ├── DevCycleEvent.php │ ├── DevCycleOptions.php │ ├── DevCycleUser.php │ ├── DevCycleUserAndEventsBody.php │ ├── ErrorResponse.php │ ├── Feature.php │ ├── InlineResponse201.php │ ├── ModelInterface.php │ └── Variable.php ├── ObjectSerializer.php ├── OpenFeature │ └── DevCycleProvider.php └── Version.php ├── phpunit.xml └── test └── Api ├── DevCycleClientTest.php └── OpenFeatureTest.php /.github/workflows/check-semantic.yml: -------------------------------------------------------------------------------- 1 | name: 'Semantic PR' 2 | on: 3 | pull_request_target: 4 | types: 5 | - opened 6 | - edited 7 | - synchronize 8 | permissions: 9 | pull-requests: read 10 | jobs: 11 | main: 12 | name: Semantic PR title 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: amannn/action-semantic-pull-request@v5 16 | env: 17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | prerelease: 7 | description: "Prerelease" 8 | required: true 9 | default: false 10 | type: boolean 11 | draft: 12 | description: "Draft" 13 | required: true 14 | default: false 15 | type: boolean 16 | version-increment-type: 17 | description: 'Which part of the version to increment:' 18 | required: true 19 | type: choice 20 | options: 21 | - major 22 | - minor 23 | - patch 24 | default: 'patch' 25 | 26 | permissions: 27 | contents: write 28 | 29 | jobs: 30 | release: 31 | name: Version Bump and Release 32 | runs-on: ubuntu-latest 33 | 34 | steps: 35 | - uses: actions/checkout@v4 36 | with: 37 | token: ${{ secrets.AUTOMATION_USER_TOKEN }} 38 | fetch-depth: 0 39 | 40 | - uses: DevCycleHQ/release-action/prepare-release@v2.3.0 41 | id: prepare-release 42 | with: 43 | github-token: ${{ secrets.AUTOMATION_USER_TOKEN }} 44 | prerelease: ${{ github.event.inputs.prerelease }} 45 | draft: ${{ github.event.inputs.draft }} 46 | version-increment-type: ${{ github.event.inputs.version-increment-type }} 47 | 48 | - name: Update Version in code 49 | run: | 50 | sed -i "s/VERSION = '.*'/VERSION = '${{steps.prepare-release.outputs.next-release-tag}}'/g" lib/Version.php 51 | sed -i "s/\"version\": \".*\"/\"version\": \"${{steps.prepare-release.outputs.next-release-tag}}\"/g" composer.json 52 | 53 | - name: Commit version change 54 | run: | 55 | git config --global user.email "github-tracker-bot@taplytics.com" 56 | git config --global user.name "DevCycle Automation" 57 | git add ./lib/Version.php 58 | git add ./composer.json 59 | git commit -m "Release ${{steps.prepare-release.outputs.next-release-tag}}" 60 | 61 | - name: Push version change 62 | run: | 63 | git push origin HEAD:main 64 | if: inputs.draft != true 65 | 66 | - uses: DevCycleHQ/release-action/create-release@v2.3.0 67 | id: create-release 68 | with: 69 | github-token: ${{ secrets.GITHUB_TOKEN }} 70 | tag: ${{ steps.prepare-release.outputs.next-release-tag }} 71 | target: main 72 | prerelease: ${{ github.event.inputs.prerelease }} 73 | draft: ${{ github.event.inputs.draft }} 74 | changelog: ${{ steps.prepare-release.outputs.changelog }} 75 | 76 | - name: Display link to release 77 | run: | 78 | echo "::notice title=Release ID::${{ steps.create-release.outputs.release-id }}" 79 | echo "::notice title=Release URL::${{ steps.create-release.outputs.release-url }}" 80 | -------------------------------------------------------------------------------- /.github/workflows/run-test-harness.yml: -------------------------------------------------------------------------------- 1 | name: Run Test Harness 2 | 3 | on: 4 | pull_request: 5 | branches: [main] 6 | 7 | jobs: 8 | harness-tests: 9 | name: Harness Tests 10 | runs-on: 11 | labels: ubuntu-latest-4-core 12 | steps: 13 | - uses: DevCycleHQ/test-harness@main 14 | with: 15 | sdks-to-test: php 16 | sdk-github-sha: ${{github.event.pull_request.head.sha}} 17 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Unit Tests 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | test: 9 | name: Test 10 | runs-on: ubuntu-latest 11 | env: 12 | DEVCYCLE_SERVER_SDK_KEY: 'dvc_server_token_hash' 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: php-actions/composer@v6 16 | - name: PHPUnit tests 17 | uses: php-actions/phpunit@v3 18 | with: 19 | configuration: "phpunit.xml" 20 | memory_limit: "256M" 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ref: https://github.com/github/gitignore/blob/master/Composer.gitignore 2 | 3 | composer.phar 4 | **/vendor/ 5 | 6 | # Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control 7 | # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file 8 | # composer.lock 9 | 10 | # php-cs-fixer cache 11 | .php_cs.cache 12 | .php-cs-fixer.cache 13 | 14 | # PHPUnit cache 15 | .phpunit.result.cache 16 | .vscode/launch.json 17 | 18 | .idea/* 19 | 20 | -------------------------------------------------------------------------------- /.openapi-generator-ignore: -------------------------------------------------------------------------------- 1 | # OpenAPI Generator Ignore 2 | # Generated by openapi-generator https://github.com/openapitools/openapi-generator 3 | 4 | # Use this file to prevent files from being overwritten by the generator. 5 | # The patterns follow closely to .gitignore or .dockerignore. 6 | 7 | # As an example, the C# client generator defines ApiClient.cs. 8 | # You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: 9 | #ApiClient.cs 10 | 11 | # You can match any string of characters against a directory, file or extension with a single asterisk (*): 12 | #foo/*/qux 13 | # The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux 14 | 15 | # You can recursively match patterns against a directory, file or extension with a double asterisk (**): 16 | #foo/**/qux 17 | # This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux 18 | 19 | # You can also negate patterns with an exclamation (!). 20 | # For example, you can ignore all files in a docs folder with the file extension .md: 21 | #docs/*.md 22 | # Then explicitly reverse the ignore rule for a single file: 23 | #!docs/README.md 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | # Bionic environment has preinstalled PHP from 7.1 to 7.4 3 | # https://docs.travis-ci.com/user/reference/bionic/#php-support 4 | dist: bionic 5 | php: 6 | - 7.3 7 | - 7.4 8 | - 8.0 9 | before_install: "composer install" 10 | script: "vendor/bin/phpunit" 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Taplytics Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DevCycle PHP Server SDK 2 | 3 | Welcome to the DevCycle PHP SDK, initially generated via the [DevCycle Bucketing API](https://docs.devcycle.com/bucketing-api/#tag/devcycle). 4 | 5 | ## Requirements 6 | 7 | PHP 8.0 and later. 8 | 9 | ## Installation 10 | 11 | ### Composer Installation 12 | 13 | To install the bindings via [Composer](https://getcomposer.org/), add the following to `composer.json`: 14 | 15 | ```json 16 | { 17 | "require": { 18 | "devcycle/php-server-sdk": "*" 19 | } 20 | } 21 | ``` 22 | 23 | Then run `composer install` 24 | 25 | ## Getting Started 26 | 27 | Please follow the [installation procedure](#installation--usage) and then run the following: 28 | 29 | ```php 30 | "my-user" 50 | )); 51 | 52 | try { 53 | $result = $apiInstance->allFeatures($user_data); 54 | print_r($result); 55 | } catch (Exception $e) { 56 | echo 'Exception when calling DevCycleClient->allFeatures: ', $e->getMessage(), PHP_EOL; 57 | } 58 | 59 | ``` 60 | 61 | 62 | 63 | ## Usage 64 | 65 | To find usage documentation, visit our [docs](https://docs.devcycle.com/docs/sdk/server-side-sdks/php#usage). 66 | 67 | # OpenFeature Support 68 | 69 | This SDK provides an implementation of the [OpenFeature](https://openfeature.dev/) Provider interface. Use the `getOpenFeatureProvider()` method on the DevCycle SDK client to obtain a provider for OpenFeature. 70 | 71 | ```php 72 | $devCycleClient = new DevCycleClient( 73 | sdkKey: getenv("DEVCYCLE_SERVER_SDK_KEY"), 74 | dvcOptions: $options 75 | ); 76 | $api->setProvider($devCycleClient->getOpenFeatureProvider()); 77 | ``` 78 | 79 | - [The DevCycle PHP OpenFeature Provider](https://docs.devcycle.com/sdk/server-side-sdks/php/php-openfeature) 80 | - [The OpenFeature documentation](https://openfeature.dev/docs/reference/intro) 81 | 82 | ## Advanced Options (Local Bucketing) 83 | 84 | Because of the nature of PHP - we can't directly support local bucketing within PHP - but we have created a supporting worker that 85 | can be used to emulate the local bucketing function of low latency and high throughput. 86 | This proxy can be found here: https://github.com/devcyclehq/local-bucketing-proxy 87 | 88 | The proxy has two modes - HTTP, and Unix sockets. The PHP SDK supports both modes, but the HTTP mode should be used for most cases. 89 | 90 | The configuration for this proxy (in HTTP mode) is as follows (replacing the URL with the URL of the proxy): 91 | 92 | ``` 93 | use DevCycle\Model\DevCycleOptions; 94 | 95 | $options = new DevCycleOptions( 96 | enableEdgeDB: false, 97 | bucketingApiHostname = "hostname for sdk proxy here" 98 | ); 99 | ``` 100 | 101 | The configuration for this proxy (in Unix socket mode) is as follows (replacing the UDS path with the path to the socket): 102 | ``` 103 | use DevCycle\Model\DevCycleOptions; 104 | 105 | $options = new DevCycleOptions( 106 | enableEdgeDB: false, 107 | bucketingApiHostname: "http:/localhost", 108 | unixSocketPath: "/path/to/unix/socket" 109 | ); 110 | ``` -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.1.0", 3 | "description": "DevCycle PHP Server SDK", 4 | "keywords": [ 5 | "openapitools", 6 | "openapi-generator", 7 | "openapi", 8 | "php", 9 | "sdk", 10 | "rest", 11 | "api" 12 | ], 13 | "homepage": "https://devcycle.com", 14 | "license": "MIT", 15 | "name": "devcycle/php-server-sdk", 16 | "authors": [ 17 | { 18 | "name": "DevCycle", 19 | "homepage": "https://devcycle.com" 20 | } 21 | ], 22 | "require": { 23 | "php": ">=8.0", 24 | "ext-curl": "*", 25 | "ext-json": "*", 26 | "ext-mbstring": "*", 27 | "guzzlehttp/guzzle": "^7.9.2", 28 | "guzzlehttp/psr7": "^2.7.0", 29 | "open-feature/sdk": "^2.0.10" 30 | }, 31 | "require-dev": { 32 | "phpunit/phpunit": "^10.5.45", 33 | "friendsofphp/php-cs-fixer": "^v3.71.0" 34 | }, 35 | "autoload": { 36 | "psr-4": { "DevCycle\\" : "lib/" } 37 | }, 38 | "autoload-dev": { 39 | "psr-4": { "DevCycle\\Test\\" : "test/" } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /docs/Api/DevCycleClient.md: -------------------------------------------------------------------------------- 1 | # DevCycleClient 2 | 3 | All URIs are relative to https://bucketing-api.devcycle.com. 4 | 5 | Method | HTTP request | Description 6 | ------------- | ------------- | ------------- 7 | [**getFeatures()**](DevCycleClient.md#getFeatures) | **POST** /v1/features | Get all features by key for user data 8 | [**getVariableByKey()**](DevCycleClient.md#getVariableByKey) | **POST** /v1/variables/{key} | Get variable by key for user data 9 | [**getVariables()**](DevCycleClient.md#getVariables) | **POST** /v1/variables | Get all variables by key for user data 10 | [**track()**](DevCycleClient.md#track) | **POST** /v1/track | Post events to DevCycle for user 11 | 12 | 13 | ## `getFeatures()` 14 | 15 | ```php 16 | getFeatures($user_data): array 17 | ``` 18 | 19 | Get all features by key for user data 20 | 21 | ### Example 22 | 23 | ```php 24 | setApiKey('Authorization', 'DEVCYCLE_SERVER_SDK_KEY'); 33 | // Uncomment below to setup prefix (e.g. Bearer) for API key, if needed 34 | // $config = DevCycleConfiguration::getDefaultConfiguration()->setApiKeyPrefix('Authorization', 'Bearer'); 35 | 36 | 37 | $apiInstance = new DevCycleClient( 38 | // If you want use custom http client, pass your client which implements `GuzzleHttp\ClientInterface`. 39 | // This is optional, `GuzzleHttp\Client` will be used as default. 40 | new GuzzleHttp\Client(), 41 | $config 42 | ); 43 | $user_data = new DevCycleUser(); 44 | 45 | try { 46 | $result = $apiInstance->getFeatures($user_data); 47 | print_r($result); 48 | } catch (Exception $e) { 49 | echo 'Exception when calling DevCycleClient->getFeatures: ', $e->getMessage(), PHP_EOL; 50 | } 51 | ``` 52 | 53 | ### Parameters 54 | 55 | Name | Type | Description | Notes 56 | ------------- | ------------- | ------------- | ------------- 57 | **user_data** | [**\DevCycle\Model\DevCycleUser**](../Model/DevCycleUser.md)| | 58 | 59 | ### Return type 60 | 61 | [**array**](../Model/Feature.md) 62 | 63 | ### Authorization 64 | 65 | [bearerAuth](../../README.md#bearerAuth) 66 | 67 | ### HTTP request headers 68 | 69 | - **Content-Type**: `application/json` 70 | - **Accept**: `application/json` 71 | 72 | [[Back to top]](#) [[Back to API list]](../../README.md#endpoints) 73 | [[Back to Model list]](../../README.md#models) 74 | [[Back to README]](../../README.md) 75 | 76 | ## `getVariableByKey()` 77 | 78 | ```php 79 | getVariableByKey($key, $user_data): \DevCycle\Model\Variable 80 | ``` 81 | 82 | Get variable by key for user data 83 | 84 | ### Example 85 | 86 | ```php 87 | setApiKey('Authorization', 'DEVCYCLE_SERVER_SDK_KEY'); 96 | // Uncomment below to setup prefix (e.g. Bearer) for API key, if needed 97 | // $config = DevCycleConfiguration::getDefaultConfiguration()->setApiKeyPrefix('Authorization', 'Bearer'); 98 | 99 | $apiInstance = new DevCycleClient( 100 | // If you want use custom http client, pass your client which implements `GuzzleHttp\ClientInterface`. 101 | // This is optional, `GuzzleHttp\Client` will be used as default. 102 | new GuzzleHttp\Client(), 103 | $config 104 | ); 105 | $key = 'key_example'; // string | Variable key 106 | $user_data = new DevCycleUser(); 107 | 108 | try { 109 | $result = $apiInstance->getVariableByKey($key, $user_data); 110 | print_r($result); 111 | } catch (Exception $e) { 112 | echo 'Exception when calling DevCycleClient->getVariableByKey: ', $e->getMessage(), PHP_EOL; 113 | } 114 | ``` 115 | 116 | ### Parameters 117 | 118 | Name | Type | Description | Notes 119 | ------------- | ------------- | ------------- | ------------- 120 | **key** | **string**| Variable key | 121 | **user_data** | [**\DevCycle\Model\DevCycleUser**](../Model/DevCycleUser.md)| | 122 | 123 | ### Return type 124 | 125 | [**\DevCycle\Model\Variable**](../Model/Variable.md) 126 | 127 | ### Authorization 128 | 129 | [bearerAuth](../../README.md#bearerAuth) 130 | 131 | ### HTTP request headers 132 | 133 | - **Content-Type**: `application/json` 134 | - **Accept**: `application/json` 135 | 136 | [[Back to top]](#) [[Back to API list]](../../README.md#endpoints) 137 | [[Back to Model list]](../../README.md#models) 138 | [[Back to README]](../../README.md) 139 | 140 | ## `getVariables()` 141 | 142 | ```php 143 | getVariables($user_data): array 144 | ``` 145 | 146 | Get all variables by key for user data 147 | 148 | ### Example 149 | 150 | ```php 151 | setApiKey('Authorization', 'DEVCYCLE_SERVER_SDK_KEY'); 160 | // Uncomment below to setup prefix (e.g. Bearer) for API key, if needed 161 | // $config = DevCycleConfiguration::getDefaultConfiguration()->setApiKeyPrefix('Authorization', 'Bearer'); 162 | 163 | 164 | $apiInstance = new DevCycleClient( 165 | // If you want use custom http client, pass your client which implements `GuzzleHttp\ClientInterface`. 166 | // This is optional, `GuzzleHttp\Client` will be used as default. 167 | new GuzzleHttp\Client(), 168 | $config 169 | ); 170 | $user_data = new DevCycleUser(); 171 | 172 | try { 173 | $result = $apiInstance->getVariables($user_data); 174 | print_r($result); 175 | } catch (Exception $e) { 176 | echo 'Exception when calling DevCycleClient->getVariables: ', $e->getMessage(), PHP_EOL; 177 | } 178 | ``` 179 | 180 | ### Parameters 181 | 182 | Name | Type | Description | Notes 183 | ------------- | ------------- | ------------- | ------------- 184 | **user_data** | [**\DevCycle\Model\DevCycleUser**](../Model/DevCycleUser.md)| | 185 | 186 | ### Return type 187 | 188 | [**array**](../Model/Variable.md) 189 | 190 | ### Authorization 191 | 192 | [bearerAuth](../../README.md#bearerAuth) 193 | 194 | ### HTTP request headers 195 | 196 | - **Content-Type**: `application/json` 197 | - **Accept**: `application/json` 198 | 199 | [[Back to top]](#) [[Back to API list]](../../README.md#endpoints) 200 | [[Back to Model list]](../../README.md#models) 201 | [[Back to README]](../../README.md) 202 | 203 | ## `track()` 204 | 205 | ```php 206 | track($user_data, $event_data): \DevCycle\Model\InlineResponse201 207 | ``` 208 | 209 | Post events to DevCycle for user 210 | 211 | ### Example 212 | 213 | ```php 214 | setApiKey('Authorization', 'DEVCYCLE_SERVER_SDK_KEY'); 224 | // Uncomment below to setup prefix (e.g. Bearer) for API key, if needed 225 | // $config = DevCycleConfiguration::getDefaultConfiguration()->setApiKeyPrefix('Authorization', 'Bearer'); 226 | 227 | 228 | $apiInstance = new DevCycleClient( 229 | // If you want use custom http client, pass your client which implements `GuzzleHttp\ClientInterface`. 230 | // This is optional, `GuzzleHttp\Client` will be used as default. 231 | new GuzzleHttp\Client(), 232 | $config 233 | ); 234 | $user_data = new DevCycleUser(); 235 | $event_data = new DevCycleEvent(array( 236 | "type"=>"my-event" 237 | )); 238 | 239 | try { 240 | $result = $apiInstance->track($user_data, $event_data); 241 | print_r($result); 242 | } catch (Exception $e) { 243 | echo 'Exception when calling DevCycleClient->track: ', $e->getMessage(), PHP_EOL; 244 | } 245 | ``` 246 | 247 | ### Parameters 248 | 249 | Name | Type | Description | Notes 250 | ------------- | ------------- | ------------- | ------------- 251 | **user_data_and_events_body** | [**\DevCycle\Model\DevCycleUserAndEventsBody**](../Model/UserDataAndEventsBody.md)| | 252 | 253 | ### Return type 254 | 255 | [**\DevCycle\Model\InlineResponse201**](../Model/InlineResponse201.md) 256 | 257 | ### Authorization 258 | 259 | [bearerAuth](../../README.md#bearerAuth) 260 | 261 | ### HTTP request headers 262 | 263 | - **Content-Type**: `application/json` 264 | - **Accept**: `application/json` 265 | 266 | [[Back to top]](#) [[Back to API list]](../../README.md#endpoints) 267 | [[Back to Model list]](../../README.md#models) 268 | [[Back to README]](../../README.md) 269 | -------------------------------------------------------------------------------- /docs/Model/DevCycleEvent.md: -------------------------------------------------------------------------------- 1 | # # Event 2 | 3 | ## Properties 4 | 5 | Name | Type | Description | Notes 6 | ------------ | ------------- | ------------- | ------------- 7 | **type** | **string** | Custom event type | 8 | **target** | **string** | Custom event target / subject of event. Contextual to event type | [optional] 9 | **date** | **float** | Unix epoch time the event occurred according to client | [optional] 10 | **value** | **float** | Value for numerical events. Contextual to event type | [optional] 11 | **meta_data** | **object** | Extra JSON metadata for event. Contextual to event type | [optional] 12 | 13 | [[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) 14 | -------------------------------------------------------------------------------- /docs/Model/DevCycleUser.md: -------------------------------------------------------------------------------- 1 | # # DevCycleUser 2 | 3 | ## Properties 4 | 5 | Name | Type | Description | Notes 6 | ------------ | ------------- | ------------- | ------------- 7 | **user_id** | **string** | Unique id to identify the user | 8 | **email** | **string** | User's email used to identify the user on the dashboard / target audiences | [optional] 9 | **name** | **string** | User's name used to identify the user on the dashboard / target audiences | [optional] 10 | **language** | **string** | User's language in ISO 639-1 format | [optional] 11 | **country** | **string** | User's country in ISO 3166 alpha-2 format | [optional] 12 | **app_version** | **string** | App Version of the running application | [optional] 13 | **app_build** | **string** | App Build number of the running application | [optional] 14 | **custom_data** | **object** | User's custom data to target the user with, data will be logged to DevCycle for use in dashboard. | [optional] 15 | **private_custom_data** | **object** | User's custom data to target the user with, data will not be logged to DevCycle only used for feature bucketing. | [optional] 16 | **created_date** | **float** | Date the user was created, Unix epoch timestamp format | [optional] 17 | **last_seen_date** | **float** | Date the user was created, Unix epoch timestamp format | [optional] 18 | **platform** | **string** | Platform the Client SDK is running on | [optional] 19 | **platform_version** | **string** | Version of the platform the Client SDK is running on | [optional] 20 | **device_model** | **string** | User's device model | [optional] 21 | **sdk_type** | **string** | DevCycle SDK type | [optional] 22 | **sdk_version** | **string** | DevCycle SDK Version | [optional] 23 | 24 | [[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) 25 | -------------------------------------------------------------------------------- /docs/Model/ErrorResponse.md: -------------------------------------------------------------------------------- 1 | # # ErrorResponse 2 | 3 | ## Properties 4 | 5 | Name | Type | Description | Notes 6 | ------------ | ------------- | ------------- | ------------- 7 | **message** | **string** | Error message | 8 | **data** | **object** | Additional error information detailing the error reasoning | [optional] 9 | 10 | [[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) 11 | -------------------------------------------------------------------------------- /docs/Model/Feature.md: -------------------------------------------------------------------------------- 1 | # # Feature 2 | 3 | ## Properties 4 | 5 | Name | Type | Description | Notes 6 | ------------ | ------------- | ------------- | ------------- 7 | **_id** | **string** | unique database id | 8 | **key** | **string** | Unique key by Project, can be used in the SDK / API to reference by 'key' rather than _id. | 9 | **type** | **string** | Feature type | 10 | **_variation** | **string** | Bucketed feature variation | 11 | **variationKey** | **string** | Bucketed feature variation key | 12 | **variationName** | **string** | Bucketed feature variation name | 13 | **eval_reason** | **string** | Evaluation reasoning | [optional] 14 | 15 | [[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) 16 | -------------------------------------------------------------------------------- /docs/Model/InlineResponse201.md: -------------------------------------------------------------------------------- 1 | # # InlineResponse201 2 | 3 | ## Properties 4 | 5 | Name | Type | Description | Notes 6 | ------------ | ------------- | ------------- | ------------- 7 | **message** | **string** | | [optional] 8 | 9 | [[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) 10 | -------------------------------------------------------------------------------- /docs/Model/UserDataAndEventsBody.md: -------------------------------------------------------------------------------- 1 | # # UserDataAndEventsBody 2 | 3 | ## Properties 4 | 5 | Name | Type | Description | Notes 6 | ------------ |-----------------------------------------------------| ------------- | ------------- 7 | **events** | [**\DevCycle\Model\DevCycleEvent[]**](DevCycleEvent.md) | | [optional] 8 | **user** | [**\DevCycle\Model\DevCycleUser**](DevCycleUser.md) | | [optional] 9 | 10 | [[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) 11 | -------------------------------------------------------------------------------- /docs/Model/Variable.md: -------------------------------------------------------------------------------- 1 | # # Variable 2 | 3 | ## Properties 4 | 5 | Name | Type | Description | Notes 6 | ------------ | ------------- | ------------- | ------------- 7 | **_id** | **string** | unique database id | 8 | **key** | **string** | Unique key by Project, can be used in the SDK / API to reference by 'key' rather than _id. | 9 | **type** | **string** | Variable type | 10 | **value** | **object** | Variable value can be a string, number, boolean, or JSON | 11 | 12 | [[Back to Model list]](../../README.md#models) [[Back to API list]](../../README.md#endpoints) [[Back to README]](../../README.md) 13 | -------------------------------------------------------------------------------- /examples/hello-world-http-proxy/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:8.2-fpm 2 | 3 | ARG DEVCYCLE_SDK_KEY 4 | ENV DEVCYCLE_SDK_KEY=${DEVCYCLE_SDK_KEY} 5 | 6 | ENV DVC_LBP_VERSION="1.1.1" 7 | ENV DVC_LBP_OS_PLATFORM="amd64" 8 | ENV DVC_LBP_PACKAGE_BUILD="deb" 9 | 10 | WORKDIR /var/www/html 11 | 12 | RUN apt-get update && apt-get install -y supervisor nginx 13 | 14 | COPY ./nginx.conf /etc/nginx/sites-available/default 15 | COPY ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf 16 | 17 | COPY ./dvc-proxy-config.json /etc/devcycle-sdk-proxy/dvc-proxy-config.json 18 | RUN sed -i "s/\${DEVCYCLE_SDK_KEY}/${DEVCYCLE_SDK_KEY}/" /etc/devcycle-sdk-proxy/dvc-proxy-config.json 19 | 20 | RUN export url="https://github.com/DevCycleHQ/sdk-proxy/releases/download/v${DVC_LBP_VERSION}/devcycle-sdk-proxy_${DVC_LBP_VERSION}+git_${DVC_LBP_OS_PLATFORM}.${DVC_LBP_PACKAGE_BUILD}" \ 21 | && echo $url && curl -L -o /tmp/dvc $url \ 22 | && dpkg -i /tmp/dvc \ 23 | && apt-get install -f 24 | 25 | EXPOSE 80 26 | 27 | CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] 28 | -------------------------------------------------------------------------------- /examples/hello-world-http-proxy/README.md: -------------------------------------------------------------------------------- 1 | # PHP SDK Example App 2 | ## Setup 3 | Install dependencies with composer: 4 | `composer update` 5 | 6 | ## Run 7 | Run the PHP Debug server in this directory: 8 | `php 127.0.0.1:8000` 9 | 10 | On MacOS run the PHP Debug server with: 11 | `php -S 127.0.0.1:8000` 12 | 13 | ## Usage 14 | Navigate in a browser to the various pages within this folder to test different SDK functionality, eg: 15 | `http://127.0.0.1:8000/features.php` 16 | 17 | -------------------------------------------------------------------------------- /examples/hello-world-http-proxy/app.php: -------------------------------------------------------------------------------- 1 | 'integration-test', 21 | 'email' => 'email@example.com', 22 | 'country' => 'US', 23 | )); 24 | -------------------------------------------------------------------------------- /examples/hello-world-http-proxy/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "DevCycle PHP Example App", 3 | "require": { 4 | "php": "^8.0", 5 | "devcycle/php-server-sdk": "2.*" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/hello-world-http-proxy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | app: 4 | container_name: "DevCycleHTTPProxyWithNginxAndPhp82" 5 | build: 6 | context: . 7 | args: 8 | DEVCYCLE_SDK_KEY: "replace_with_your_sdk_key" 9 | ports: 10 | - "80:80" 11 | volumes: 12 | - ./:/var/www/html 13 | -------------------------------------------------------------------------------- /examples/hello-world-http-proxy/dvc-proxy-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "instances": [ 3 | { 4 | "sdkKey": "${DEVCYCLE_SDK_KEY}", 5 | "httpEnabled": true, 6 | "httpPort": 8099 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /examples/hello-world-http-proxy/event.php: -------------------------------------------------------------------------------- 1 | "some_event" 6 | )); 7 | 8 | try { 9 | $result = $apiInstance->track($user_data, $event_data); 10 | print_r($result); 11 | } catch (Exception $e) { 12 | echo 'Exception when calling DevCycleClient->track: ', $e->getMessage(), PHP_EOL; 13 | } -------------------------------------------------------------------------------- /examples/hello-world-http-proxy/features.php: -------------------------------------------------------------------------------- 1 | allFeatures($user_data); 6 | print_r($result); 7 | } catch (Exception $e) { 8 | echo 'Exception when calling DVCClient->allFeatures: ', $e->getMessage(), PHP_EOL; 9 | } -------------------------------------------------------------------------------- /examples/hello-world-http-proxy/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | root /var/www/html; 6 | index app.php app.html; 7 | 8 | location / { 9 | try_files $uri $uri/ /app.php$is_args$args; 10 | } 11 | 12 | location ~ \.php$ { 13 | fastcgi_pass localhost:9000; 14 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 15 | include fastcgi_params; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/hello-world-http-proxy/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | 4 | [supervisorctl] 5 | 6 | [program:nginx] 7 | command=/usr/sbin/nginx -g 'daemon off;' 8 | 9 | [program:php-fpm] 10 | command=/usr/local/sbin/php-fpm -F 11 | 12 | [program:dvc-lb-proxy] 13 | command=/usr/bin/devcycle-sdk-proxy -config /etc/devcycle-sdk-proxy/dvc-proxy-config.json 14 | -------------------------------------------------------------------------------- /examples/hello-world-http-proxy/variable.php: -------------------------------------------------------------------------------- 1 | variable($user_data, 'test-feature', null); 6 | echo "Variable result is: "; 7 | print_r($result['value'] ? "true" : "false"); 8 | } catch (Exception $e) { 9 | echo 'Exception when calling DVCClient->variable: ', $e->getMessage(), PHP_EOL; 10 | } 11 | -------------------------------------------------------------------------------- /examples/hello-world-http-proxy/variableAsync.php: -------------------------------------------------------------------------------- 1 | variableAsync($user, 'test-feature', false) 9 | ->then( 10 | function ($response) { 11 | echo "Variable result is: "; 12 | print_r($response['value'] ? "true" : "false"); 13 | }, 14 | function ($e) { 15 | echo 'Exception when calling DVCClient->variableAsync: ', $e->getMessage(), PHP_EOL; 16 | } 17 | )->wait(); 18 | 19 | echo PHP_EOL, "Ending async"; 20 | -------------------------------------------------------------------------------- /examples/hello-world-udp-proxy/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:8.2-fpm 2 | 3 | ARG DEVCYCLE_SDK_KEY 4 | ENV DEVCYCLE_SDK_KEY=${DEVCYCLE_SDK_KEY} 5 | 6 | ENV DVC_LBP_VERSION="1.1.1" 7 | ENV DVC_LBP_OS_PLATFORM="amd64" 8 | ENV DVC_LBP_PACKAGE_BUILD="deb" 9 | 10 | WORKDIR /var/www/html 11 | 12 | RUN apt-get update && apt-get install -y supervisor nginx 13 | 14 | COPY ./nginx.conf /etc/nginx/sites-available/default 15 | COPY ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf 16 | 17 | COPY ./dvc-proxy-config.json /etc/devcycle-sdk-proxy/dvc-proxy-config.json 18 | RUN sed -i "s/\${DEVCYCLE_SDK_KEY}/${DEVCYCLE_SDK_KEY}/" /etc/devcycle-sdk-proxy/dvc-proxy-config.json 19 | 20 | RUN export url="https://github.com/DevCycleHQ/sdk-proxy/releases/download/v${DVC_LBP_VERSION}/devcycle-sdk-proxy_${DVC_LBP_VERSION}+git_${DVC_LBP_OS_PLATFORM}.${DVC_LBP_PACKAGE_BUILD}" \ 21 | && echo $url && curl -L -o /tmp/dvc $url \ 22 | && dpkg -i /tmp/dvc \ 23 | && apt-get install -f 24 | 25 | EXPOSE 80 26 | 27 | CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] 28 | -------------------------------------------------------------------------------- /examples/hello-world-udp-proxy/README.md: -------------------------------------------------------------------------------- 1 | # PHP SDK Example App 2 | ## Setup 3 | Install dependencies with composer: 4 | `composer update` 5 | 6 | ## Run 7 | Run the PHP Debug server in this directory: 8 | `php 127.0.0.1:8000` 9 | 10 | On MacOS run the PHP Debug server with: 11 | `php -S 127.0.0.1:8000` 12 | 13 | ## Usage 14 | Navigate in a browser to the various pages within this folder to test different SDK functionality, eg: 15 | `http://127.0.0.1:8000/features.php` 16 | 17 | -------------------------------------------------------------------------------- /examples/hello-world-udp-proxy/app.php: -------------------------------------------------------------------------------- 1 | 'integration-test', 22 | 'email' => 'email@example.com', 23 | 'country' => 'US', 24 | )); 25 | -------------------------------------------------------------------------------- /examples/hello-world-udp-proxy/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "DevCycle PHP Example App", 3 | "require": { 4 | "php": "^8.0", 5 | "devcycle/php-server-sdk": "2.*" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/hello-world-udp-proxy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | app: 4 | container_name: "DevCycleUDPProxyWithNginxAndPhp82" 5 | build: 6 | context: . 7 | args: 8 | DEVCYCLE_SDK_KEY: "replace_with_your_sdk_key" 9 | ports: 10 | - "80:80" 11 | volumes: 12 | - ./:/var/www/html 13 | -------------------------------------------------------------------------------- /examples/hello-world-udp-proxy/dvc-proxy-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "instances": [ 3 | { 4 | "sdkKey": "${DEVCYCLE_SDK_KEY}", 5 | "unixSocketPath": "/tmp/dvc_lb_proxy.sock", 6 | "unixSocketEnabled": true, 7 | "unixSocketPermissions": "0777", 8 | "httpEnabled": false 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /examples/hello-world-udp-proxy/event.php: -------------------------------------------------------------------------------- 1 | "some_event" 6 | )); 7 | 8 | try { 9 | $result = $apiInstance->track($user_data, $event_data); 10 | print_r($result); 11 | } catch (Exception $e) { 12 | echo 'Exception when calling DevCycleClient->track: ', $e->getMessage(), PHP_EOL; 13 | } -------------------------------------------------------------------------------- /examples/hello-world-udp-proxy/features.php: -------------------------------------------------------------------------------- 1 | allFeatures($user_data); 6 | print_r($result); 7 | } catch (Exception $e) { 8 | echo 'Exception when calling DVCClient->allFeatures: ', $e->getMessage(), PHP_EOL; 9 | } -------------------------------------------------------------------------------- /examples/hello-world-udp-proxy/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | root /var/www/html; 6 | index app.php app.html; 7 | 8 | location / { 9 | try_files $uri $uri/ /app.php$is_args$args; 10 | } 11 | 12 | location ~ \.php$ { 13 | fastcgi_pass localhost:9000; 14 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 15 | include fastcgi_params; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/hello-world-udp-proxy/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | 4 | [supervisorctl] 5 | 6 | [program:nginx] 7 | command=/usr/sbin/nginx -g 'daemon off;' 8 | 9 | [program:php-fpm] 10 | command=/usr/local/sbin/php-fpm -F 11 | 12 | [program:dvc-lb-proxy] 13 | command=/usr/bin/devcycle-sdk-proxy -config /etc/devcycle-sdk-proxy/dvc-proxy-config.json 14 | -------------------------------------------------------------------------------- /examples/hello-world-udp-proxy/variable.php: -------------------------------------------------------------------------------- 1 | variable($user_data, 'test-feature', null); 6 | echo "Variable result is: "; 7 | print_r($result['value'] ? "true" : "false"); 8 | } catch (Exception $e) { 9 | echo 'Exception when calling DVCClient->variable: ', $e->getMessage(), PHP_EOL; 10 | } 11 | -------------------------------------------------------------------------------- /examples/hello-world-udp-proxy/variableAsync.php: -------------------------------------------------------------------------------- 1 | variableAsync($user, 'test-feature', false) 9 | ->then( 10 | function ($response) { 11 | echo "Variable result is: "; 12 | print_r($response['value'] ? "true" : "false"); 13 | }, 14 | function ($e) { 15 | echo 'Exception when calling DVCClient->variableAsync: ', $e->getMessage(), PHP_EOL; 16 | } 17 | )->wait(); 18 | 19 | echo PHP_EOL, "Ending async"; 20 | -------------------------------------------------------------------------------- /examples/hello-world/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ -------------------------------------------------------------------------------- /examples/hello-world/README.md: -------------------------------------------------------------------------------- 1 | # PHP SDK Example App 2 | ## Setup 3 | Install dependencies with composer: 4 | `composer update` 5 | 6 | Set the following environment variables in your shell session before running the PHP example app in the same session. 7 | ``` 8 | export DEVCYCLE_SERVER_SDK_KEY=`` 9 | ``` 10 | 11 | ## Run 12 | Run the PHP Debug server in this directory: 13 | `php 127.0.0.1:8000` 14 | 15 | On MacOS run the PHP Debug server with: 16 | `php -S 127.0.0.1:8000` 17 | 18 | ## Usage 19 | Navigate in a browser to the various pages within this folder to test different SDK functionality, eg: 20 | `http://127.0.0.1:8000/features.php` 21 | 22 | -------------------------------------------------------------------------------- /examples/hello-world/app.php: -------------------------------------------------------------------------------- 1 | "test" 28 | )); 29 | 30 | echo $user->__toString(); 31 | 32 | echo $devCycleClient->variable($user, "test", false); 33 | -------------------------------------------------------------------------------- /examples/hello-world/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "DevCycle PHP Example App", 3 | "require": { 4 | "php": "^8.0", 5 | "devcycle/php-server-sdk": "*" 6 | }, 7 | "repositories": [{ 8 | "type": "path", 9 | "url": "../../", 10 | "only": ["devcycle/php-server-sdk"] 11 | } 12 | ], 13 | "autoload": { 14 | "psr-4": { "DevCycle\\" : "../../lib/" } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/hello-world/composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "eff358b5dc941a33021db127836971be", 8 | "packages": [ 9 | { 10 | "name": "devcycle/php-server-sdk", 11 | "version": "2.0.0", 12 | "dist": { 13 | "type": "path", 14 | "url": "../..", 15 | "reference": "42b3af1d9edcdd8436eac245e946d804f55f956e" 16 | }, 17 | "require": { 18 | "ext-curl": "*", 19 | "ext-json": "*", 20 | "ext-mbstring": "*", 21 | "guzzlehttp/guzzle": "^7.3", 22 | "guzzlehttp/psr7": "^2.0", 23 | "open-feature/sdk": "^2.0", 24 | "php": ">=8.0" 25 | }, 26 | "require-dev": { 27 | "friendsofphp/php-cs-fixer": "^v3.16.0", 28 | "phpunit/phpunit": "^8.0 || ^9.0" 29 | }, 30 | "type": "library", 31 | "autoload": { 32 | "psr-4": { 33 | "DevCycle\\": "lib/" 34 | } 35 | }, 36 | "autoload-dev": { 37 | "psr-4": { 38 | "DevCycle\\Test\\": "test/" 39 | } 40 | }, 41 | "license": [ 42 | "MIT" 43 | ], 44 | "authors": [ 45 | { 46 | "name": "DevCycle", 47 | "homepage": "https://devcycle.com" 48 | } 49 | ], 50 | "description": "Documents the DevCycle Bucketing API which provides and API interface to User Bucketing and for generated SDKs.", 51 | "homepage": "https://openapi-generator.tech", 52 | "keywords": [ 53 | "api", 54 | "openapi", 55 | "openapi-generator", 56 | "openapitools", 57 | "php", 58 | "rest", 59 | "sdk" 60 | ], 61 | "transport-options": { 62 | "relative": true 63 | } 64 | }, 65 | { 66 | "name": "guzzlehttp/guzzle", 67 | "version": "7.8.1", 68 | "source": { 69 | "type": "git", 70 | "url": "https://github.com/guzzle/guzzle.git", 71 | "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" 72 | }, 73 | "dist": { 74 | "type": "zip", 75 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", 76 | "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", 77 | "shasum": "" 78 | }, 79 | "require": { 80 | "ext-json": "*", 81 | "guzzlehttp/promises": "^1.5.3 || ^2.0.1", 82 | "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", 83 | "php": "^7.2.5 || ^8.0", 84 | "psr/http-client": "^1.0", 85 | "symfony/deprecation-contracts": "^2.2 || ^3.0" 86 | }, 87 | "provide": { 88 | "psr/http-client-implementation": "1.0" 89 | }, 90 | "require-dev": { 91 | "bamarni/composer-bin-plugin": "^1.8.2", 92 | "ext-curl": "*", 93 | "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", 94 | "php-http/message-factory": "^1.1", 95 | "phpunit/phpunit": "^8.5.36 || ^9.6.15", 96 | "psr/log": "^1.1 || ^2.0 || ^3.0" 97 | }, 98 | "suggest": { 99 | "ext-curl": "Required for CURL handler support", 100 | "ext-intl": "Required for Internationalized Domain Name (IDN) support", 101 | "psr/log": "Required for using the Log middleware" 102 | }, 103 | "type": "library", 104 | "extra": { 105 | "bamarni-bin": { 106 | "bin-links": true, 107 | "forward-command": false 108 | } 109 | }, 110 | "autoload": { 111 | "files": [ 112 | "src/functions_include.php" 113 | ], 114 | "psr-4": { 115 | "GuzzleHttp\\": "src/" 116 | } 117 | }, 118 | "notification-url": "https://packagist.org/downloads/", 119 | "license": [ 120 | "MIT" 121 | ], 122 | "authors": [ 123 | { 124 | "name": "Graham Campbell", 125 | "email": "hello@gjcampbell.co.uk", 126 | "homepage": "https://github.com/GrahamCampbell" 127 | }, 128 | { 129 | "name": "Michael Dowling", 130 | "email": "mtdowling@gmail.com", 131 | "homepage": "https://github.com/mtdowling" 132 | }, 133 | { 134 | "name": "Jeremy Lindblom", 135 | "email": "jeremeamia@gmail.com", 136 | "homepage": "https://github.com/jeremeamia" 137 | }, 138 | { 139 | "name": "George Mponos", 140 | "email": "gmponos@gmail.com", 141 | "homepage": "https://github.com/gmponos" 142 | }, 143 | { 144 | "name": "Tobias Nyholm", 145 | "email": "tobias.nyholm@gmail.com", 146 | "homepage": "https://github.com/Nyholm" 147 | }, 148 | { 149 | "name": "Márk Sági-Kazár", 150 | "email": "mark.sagikazar@gmail.com", 151 | "homepage": "https://github.com/sagikazarmark" 152 | }, 153 | { 154 | "name": "Tobias Schultze", 155 | "email": "webmaster@tubo-world.de", 156 | "homepage": "https://github.com/Tobion" 157 | } 158 | ], 159 | "description": "Guzzle is a PHP HTTP client library", 160 | "keywords": [ 161 | "client", 162 | "curl", 163 | "framework", 164 | "http", 165 | "http client", 166 | "psr-18", 167 | "psr-7", 168 | "rest", 169 | "web service" 170 | ], 171 | "support": { 172 | "issues": "https://github.com/guzzle/guzzle/issues", 173 | "source": "https://github.com/guzzle/guzzle/tree/7.8.1" 174 | }, 175 | "funding": [ 176 | { 177 | "url": "https://github.com/GrahamCampbell", 178 | "type": "github" 179 | }, 180 | { 181 | "url": "https://github.com/Nyholm", 182 | "type": "github" 183 | }, 184 | { 185 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", 186 | "type": "tidelift" 187 | } 188 | ], 189 | "time": "2023-12-03T20:35:24+00:00" 190 | }, 191 | { 192 | "name": "guzzlehttp/promises", 193 | "version": "2.0.2", 194 | "source": { 195 | "type": "git", 196 | "url": "https://github.com/guzzle/promises.git", 197 | "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" 198 | }, 199 | "dist": { 200 | "type": "zip", 201 | "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", 202 | "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", 203 | "shasum": "" 204 | }, 205 | "require": { 206 | "php": "^7.2.5 || ^8.0" 207 | }, 208 | "require-dev": { 209 | "bamarni/composer-bin-plugin": "^1.8.2", 210 | "phpunit/phpunit": "^8.5.36 || ^9.6.15" 211 | }, 212 | "type": "library", 213 | "extra": { 214 | "bamarni-bin": { 215 | "bin-links": true, 216 | "forward-command": false 217 | } 218 | }, 219 | "autoload": { 220 | "psr-4": { 221 | "GuzzleHttp\\Promise\\": "src/" 222 | } 223 | }, 224 | "notification-url": "https://packagist.org/downloads/", 225 | "license": [ 226 | "MIT" 227 | ], 228 | "authors": [ 229 | { 230 | "name": "Graham Campbell", 231 | "email": "hello@gjcampbell.co.uk", 232 | "homepage": "https://github.com/GrahamCampbell" 233 | }, 234 | { 235 | "name": "Michael Dowling", 236 | "email": "mtdowling@gmail.com", 237 | "homepage": "https://github.com/mtdowling" 238 | }, 239 | { 240 | "name": "Tobias Nyholm", 241 | "email": "tobias.nyholm@gmail.com", 242 | "homepage": "https://github.com/Nyholm" 243 | }, 244 | { 245 | "name": "Tobias Schultze", 246 | "email": "webmaster@tubo-world.de", 247 | "homepage": "https://github.com/Tobion" 248 | } 249 | ], 250 | "description": "Guzzle promises library", 251 | "keywords": [ 252 | "promise" 253 | ], 254 | "support": { 255 | "issues": "https://github.com/guzzle/promises/issues", 256 | "source": "https://github.com/guzzle/promises/tree/2.0.2" 257 | }, 258 | "funding": [ 259 | { 260 | "url": "https://github.com/GrahamCampbell", 261 | "type": "github" 262 | }, 263 | { 264 | "url": "https://github.com/Nyholm", 265 | "type": "github" 266 | }, 267 | { 268 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", 269 | "type": "tidelift" 270 | } 271 | ], 272 | "time": "2023-12-03T20:19:20+00:00" 273 | }, 274 | { 275 | "name": "guzzlehttp/psr7", 276 | "version": "2.6.2", 277 | "source": { 278 | "type": "git", 279 | "url": "https://github.com/guzzle/psr7.git", 280 | "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" 281 | }, 282 | "dist": { 283 | "type": "zip", 284 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", 285 | "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", 286 | "shasum": "" 287 | }, 288 | "require": { 289 | "php": "^7.2.5 || ^8.0", 290 | "psr/http-factory": "^1.0", 291 | "psr/http-message": "^1.1 || ^2.0", 292 | "ralouphie/getallheaders": "^3.0" 293 | }, 294 | "provide": { 295 | "psr/http-factory-implementation": "1.0", 296 | "psr/http-message-implementation": "1.0" 297 | }, 298 | "require-dev": { 299 | "bamarni/composer-bin-plugin": "^1.8.2", 300 | "http-interop/http-factory-tests": "^0.9", 301 | "phpunit/phpunit": "^8.5.36 || ^9.6.15" 302 | }, 303 | "suggest": { 304 | "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" 305 | }, 306 | "type": "library", 307 | "extra": { 308 | "bamarni-bin": { 309 | "bin-links": true, 310 | "forward-command": false 311 | } 312 | }, 313 | "autoload": { 314 | "psr-4": { 315 | "GuzzleHttp\\Psr7\\": "src/" 316 | } 317 | }, 318 | "notification-url": "https://packagist.org/downloads/", 319 | "license": [ 320 | "MIT" 321 | ], 322 | "authors": [ 323 | { 324 | "name": "Graham Campbell", 325 | "email": "hello@gjcampbell.co.uk", 326 | "homepage": "https://github.com/GrahamCampbell" 327 | }, 328 | { 329 | "name": "Michael Dowling", 330 | "email": "mtdowling@gmail.com", 331 | "homepage": "https://github.com/mtdowling" 332 | }, 333 | { 334 | "name": "George Mponos", 335 | "email": "gmponos@gmail.com", 336 | "homepage": "https://github.com/gmponos" 337 | }, 338 | { 339 | "name": "Tobias Nyholm", 340 | "email": "tobias.nyholm@gmail.com", 341 | "homepage": "https://github.com/Nyholm" 342 | }, 343 | { 344 | "name": "Márk Sági-Kazár", 345 | "email": "mark.sagikazar@gmail.com", 346 | "homepage": "https://github.com/sagikazarmark" 347 | }, 348 | { 349 | "name": "Tobias Schultze", 350 | "email": "webmaster@tubo-world.de", 351 | "homepage": "https://github.com/Tobion" 352 | }, 353 | { 354 | "name": "Márk Sági-Kazár", 355 | "email": "mark.sagikazar@gmail.com", 356 | "homepage": "https://sagikazarmark.hu" 357 | } 358 | ], 359 | "description": "PSR-7 message implementation that also provides common utility methods", 360 | "keywords": [ 361 | "http", 362 | "message", 363 | "psr-7", 364 | "request", 365 | "response", 366 | "stream", 367 | "uri", 368 | "url" 369 | ], 370 | "support": { 371 | "issues": "https://github.com/guzzle/psr7/issues", 372 | "source": "https://github.com/guzzle/psr7/tree/2.6.2" 373 | }, 374 | "funding": [ 375 | { 376 | "url": "https://github.com/GrahamCampbell", 377 | "type": "github" 378 | }, 379 | { 380 | "url": "https://github.com/Nyholm", 381 | "type": "github" 382 | }, 383 | { 384 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", 385 | "type": "tidelift" 386 | } 387 | ], 388 | "time": "2023-12-03T20:05:35+00:00" 389 | }, 390 | { 391 | "name": "myclabs/php-enum", 392 | "version": "1.8.4", 393 | "source": { 394 | "type": "git", 395 | "url": "https://github.com/myclabs/php-enum.git", 396 | "reference": "a867478eae49c9f59ece437ae7f9506bfaa27483" 397 | }, 398 | "dist": { 399 | "type": "zip", 400 | "url": "https://api.github.com/repos/myclabs/php-enum/zipball/a867478eae49c9f59ece437ae7f9506bfaa27483", 401 | "reference": "a867478eae49c9f59ece437ae7f9506bfaa27483", 402 | "shasum": "" 403 | }, 404 | "require": { 405 | "ext-json": "*", 406 | "php": "^7.3 || ^8.0" 407 | }, 408 | "require-dev": { 409 | "phpunit/phpunit": "^9.5", 410 | "squizlabs/php_codesniffer": "1.*", 411 | "vimeo/psalm": "^4.6.2" 412 | }, 413 | "type": "library", 414 | "autoload": { 415 | "psr-4": { 416 | "MyCLabs\\Enum\\": "src/" 417 | }, 418 | "classmap": [ 419 | "stubs/Stringable.php" 420 | ] 421 | }, 422 | "notification-url": "https://packagist.org/downloads/", 423 | "license": [ 424 | "MIT" 425 | ], 426 | "authors": [ 427 | { 428 | "name": "PHP Enum contributors", 429 | "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" 430 | } 431 | ], 432 | "description": "PHP Enum implementation", 433 | "homepage": "http://github.com/myclabs/php-enum", 434 | "keywords": [ 435 | "enum" 436 | ], 437 | "support": { 438 | "issues": "https://github.com/myclabs/php-enum/issues", 439 | "source": "https://github.com/myclabs/php-enum/tree/1.8.4" 440 | }, 441 | "funding": [ 442 | { 443 | "url": "https://github.com/mnapoli", 444 | "type": "github" 445 | }, 446 | { 447 | "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum", 448 | "type": "tidelift" 449 | } 450 | ], 451 | "time": "2022-08-04T09:53:51+00:00" 452 | }, 453 | { 454 | "name": "open-feature/sdk", 455 | "version": "2.0.4", 456 | "source": { 457 | "type": "git", 458 | "url": "https://github.com/open-feature/php-sdk.git", 459 | "reference": "a2de465332441b6511c6953cb12e6387be3db442" 460 | }, 461 | "dist": { 462 | "type": "zip", 463 | "url": "https://api.github.com/repos/open-feature/php-sdk/zipball/a2de465332441b6511c6953cb12e6387be3db442", 464 | "reference": "a2de465332441b6511c6953cb12e6387be3db442", 465 | "shasum": "" 466 | }, 467 | "require": { 468 | "myclabs/php-enum": "^1.8", 469 | "php": "^8", 470 | "psr/log": "^2.0 || ^3.0" 471 | }, 472 | "require-dev": { 473 | "behat/behat": "^3.11", 474 | "captainhook/captainhook": "^5.10", 475 | "captainhook/plugin-composer": "^5.3", 476 | "ergebnis/composer-normalize": "^2.25", 477 | "hamcrest/hamcrest-php": "^2.0", 478 | "mdwheele/zalgo": "^0.3.1", 479 | "mockery/mockery": "^1.5", 480 | "php-parallel-lint/php-console-highlighter": "^1.0", 481 | "php-parallel-lint/php-parallel-lint": "^1.3", 482 | "phpstan/extension-installer": "^1.1", 483 | "phpstan/phpstan": "~1.10.0", 484 | "phpstan/phpstan-mockery": "^1.0", 485 | "phpstan/phpstan-phpunit": "^1.1", 486 | "psalm/plugin-mockery": "^1.0.0", 487 | "psalm/plugin-phpunit": "^0.18.0", 488 | "ramsey/coding-standard": "^2.0.3", 489 | "ramsey/composer-repl": "^1.4", 490 | "ramsey/conventional-commits": "^1.3", 491 | "roave/security-advisories": "dev-latest", 492 | "spatie/phpunit-snapshot-assertions": "^4.2", 493 | "vimeo/psalm": "~5.17.0" 494 | }, 495 | "type": "library", 496 | "extra": { 497 | "captainhook": { 498 | "force-install": true 499 | }, 500 | "ramsey/conventional-commits": { 501 | "configFile": "conventional-commits.json" 502 | } 503 | }, 504 | "autoload": { 505 | "psr-4": { 506 | "OpenFeature\\": "src/" 507 | } 508 | }, 509 | "notification-url": "https://packagist.org/downloads/", 510 | "license": [ 511 | "Apache-2.0" 512 | ], 513 | "authors": [ 514 | { 515 | "name": "Tom Carrio", 516 | "email": "tom@carrio.dev" 517 | } 518 | ], 519 | "description": "PHP implementation of the OpenFeature SDK", 520 | "keywords": [ 521 | "featureflagging", 522 | "featureflags", 523 | "openfeature" 524 | ], 525 | "support": { 526 | "issues": "https://github.com/open-feature/php-sdk/issues", 527 | "source": "https://github.com/open-feature/php-sdk/tree/2.0.4" 528 | }, 529 | "time": "2023-12-17T13:48:28+00:00" 530 | }, 531 | { 532 | "name": "psr/http-client", 533 | "version": "1.0.3", 534 | "source": { 535 | "type": "git", 536 | "url": "https://github.com/php-fig/http-client.git", 537 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" 538 | }, 539 | "dist": { 540 | "type": "zip", 541 | "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", 542 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", 543 | "shasum": "" 544 | }, 545 | "require": { 546 | "php": "^7.0 || ^8.0", 547 | "psr/http-message": "^1.0 || ^2.0" 548 | }, 549 | "type": "library", 550 | "extra": { 551 | "branch-alias": { 552 | "dev-master": "1.0.x-dev" 553 | } 554 | }, 555 | "autoload": { 556 | "psr-4": { 557 | "Psr\\Http\\Client\\": "src/" 558 | } 559 | }, 560 | "notification-url": "https://packagist.org/downloads/", 561 | "license": [ 562 | "MIT" 563 | ], 564 | "authors": [ 565 | { 566 | "name": "PHP-FIG", 567 | "homepage": "https://www.php-fig.org/" 568 | } 569 | ], 570 | "description": "Common interface for HTTP clients", 571 | "homepage": "https://github.com/php-fig/http-client", 572 | "keywords": [ 573 | "http", 574 | "http-client", 575 | "psr", 576 | "psr-18" 577 | ], 578 | "support": { 579 | "source": "https://github.com/php-fig/http-client" 580 | }, 581 | "time": "2023-09-23T14:17:50+00:00" 582 | }, 583 | { 584 | "name": "psr/http-factory", 585 | "version": "1.0.2", 586 | "source": { 587 | "type": "git", 588 | "url": "https://github.com/php-fig/http-factory.git", 589 | "reference": "e616d01114759c4c489f93b099585439f795fe35" 590 | }, 591 | "dist": { 592 | "type": "zip", 593 | "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", 594 | "reference": "e616d01114759c4c489f93b099585439f795fe35", 595 | "shasum": "" 596 | }, 597 | "require": { 598 | "php": ">=7.0.0", 599 | "psr/http-message": "^1.0 || ^2.0" 600 | }, 601 | "type": "library", 602 | "extra": { 603 | "branch-alias": { 604 | "dev-master": "1.0.x-dev" 605 | } 606 | }, 607 | "autoload": { 608 | "psr-4": { 609 | "Psr\\Http\\Message\\": "src/" 610 | } 611 | }, 612 | "notification-url": "https://packagist.org/downloads/", 613 | "license": [ 614 | "MIT" 615 | ], 616 | "authors": [ 617 | { 618 | "name": "PHP-FIG", 619 | "homepage": "https://www.php-fig.org/" 620 | } 621 | ], 622 | "description": "Common interfaces for PSR-7 HTTP message factories", 623 | "keywords": [ 624 | "factory", 625 | "http", 626 | "message", 627 | "psr", 628 | "psr-17", 629 | "psr-7", 630 | "request", 631 | "response" 632 | ], 633 | "support": { 634 | "source": "https://github.com/php-fig/http-factory/tree/1.0.2" 635 | }, 636 | "time": "2023-04-10T20:10:41+00:00" 637 | }, 638 | { 639 | "name": "psr/http-message", 640 | "version": "2.0", 641 | "source": { 642 | "type": "git", 643 | "url": "https://github.com/php-fig/http-message.git", 644 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" 645 | }, 646 | "dist": { 647 | "type": "zip", 648 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", 649 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", 650 | "shasum": "" 651 | }, 652 | "require": { 653 | "php": "^7.2 || ^8.0" 654 | }, 655 | "type": "library", 656 | "extra": { 657 | "branch-alias": { 658 | "dev-master": "2.0.x-dev" 659 | } 660 | }, 661 | "autoload": { 662 | "psr-4": { 663 | "Psr\\Http\\Message\\": "src/" 664 | } 665 | }, 666 | "notification-url": "https://packagist.org/downloads/", 667 | "license": [ 668 | "MIT" 669 | ], 670 | "authors": [ 671 | { 672 | "name": "PHP-FIG", 673 | "homepage": "https://www.php-fig.org/" 674 | } 675 | ], 676 | "description": "Common interface for HTTP messages", 677 | "homepage": "https://github.com/php-fig/http-message", 678 | "keywords": [ 679 | "http", 680 | "http-message", 681 | "psr", 682 | "psr-7", 683 | "request", 684 | "response" 685 | ], 686 | "support": { 687 | "source": "https://github.com/php-fig/http-message/tree/2.0" 688 | }, 689 | "time": "2023-04-04T09:54:51+00:00" 690 | }, 691 | { 692 | "name": "psr/log", 693 | "version": "3.0.0", 694 | "source": { 695 | "type": "git", 696 | "url": "https://github.com/php-fig/log.git", 697 | "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" 698 | }, 699 | "dist": { 700 | "type": "zip", 701 | "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", 702 | "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", 703 | "shasum": "" 704 | }, 705 | "require": { 706 | "php": ">=8.0.0" 707 | }, 708 | "type": "library", 709 | "extra": { 710 | "branch-alias": { 711 | "dev-master": "3.x-dev" 712 | } 713 | }, 714 | "autoload": { 715 | "psr-4": { 716 | "Psr\\Log\\": "src" 717 | } 718 | }, 719 | "notification-url": "https://packagist.org/downloads/", 720 | "license": [ 721 | "MIT" 722 | ], 723 | "authors": [ 724 | { 725 | "name": "PHP-FIG", 726 | "homepage": "https://www.php-fig.org/" 727 | } 728 | ], 729 | "description": "Common interface for logging libraries", 730 | "homepage": "https://github.com/php-fig/log", 731 | "keywords": [ 732 | "log", 733 | "psr", 734 | "psr-3" 735 | ], 736 | "support": { 737 | "source": "https://github.com/php-fig/log/tree/3.0.0" 738 | }, 739 | "time": "2021-07-14T16:46:02+00:00" 740 | }, 741 | { 742 | "name": "ralouphie/getallheaders", 743 | "version": "3.0.3", 744 | "source": { 745 | "type": "git", 746 | "url": "https://github.com/ralouphie/getallheaders.git", 747 | "reference": "120b605dfeb996808c31b6477290a714d356e822" 748 | }, 749 | "dist": { 750 | "type": "zip", 751 | "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", 752 | "reference": "120b605dfeb996808c31b6477290a714d356e822", 753 | "shasum": "" 754 | }, 755 | "require": { 756 | "php": ">=5.6" 757 | }, 758 | "require-dev": { 759 | "php-coveralls/php-coveralls": "^2.1", 760 | "phpunit/phpunit": "^5 || ^6.5" 761 | }, 762 | "type": "library", 763 | "autoload": { 764 | "files": [ 765 | "src/getallheaders.php" 766 | ] 767 | }, 768 | "notification-url": "https://packagist.org/downloads/", 769 | "license": [ 770 | "MIT" 771 | ], 772 | "authors": [ 773 | { 774 | "name": "Ralph Khattar", 775 | "email": "ralph.khattar@gmail.com" 776 | } 777 | ], 778 | "description": "A polyfill for getallheaders.", 779 | "support": { 780 | "issues": "https://github.com/ralouphie/getallheaders/issues", 781 | "source": "https://github.com/ralouphie/getallheaders/tree/develop" 782 | }, 783 | "time": "2019-03-08T08:55:37+00:00" 784 | }, 785 | { 786 | "name": "symfony/deprecation-contracts", 787 | "version": "v3.4.0", 788 | "source": { 789 | "type": "git", 790 | "url": "https://github.com/symfony/deprecation-contracts.git", 791 | "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" 792 | }, 793 | "dist": { 794 | "type": "zip", 795 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", 796 | "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", 797 | "shasum": "" 798 | }, 799 | "require": { 800 | "php": ">=8.1" 801 | }, 802 | "type": "library", 803 | "extra": { 804 | "branch-alias": { 805 | "dev-main": "3.4-dev" 806 | }, 807 | "thanks": { 808 | "name": "symfony/contracts", 809 | "url": "https://github.com/symfony/contracts" 810 | } 811 | }, 812 | "autoload": { 813 | "files": [ 814 | "function.php" 815 | ] 816 | }, 817 | "notification-url": "https://packagist.org/downloads/", 818 | "license": [ 819 | "MIT" 820 | ], 821 | "authors": [ 822 | { 823 | "name": "Nicolas Grekas", 824 | "email": "p@tchwork.com" 825 | }, 826 | { 827 | "name": "Symfony Community", 828 | "homepage": "https://symfony.com/contributors" 829 | } 830 | ], 831 | "description": "A generic function and convention to trigger deprecation notices", 832 | "homepage": "https://symfony.com", 833 | "support": { 834 | "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" 835 | }, 836 | "funding": [ 837 | { 838 | "url": "https://symfony.com/sponsor", 839 | "type": "custom" 840 | }, 841 | { 842 | "url": "https://github.com/fabpot", 843 | "type": "github" 844 | }, 845 | { 846 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 847 | "type": "tidelift" 848 | } 849 | ], 850 | "time": "2023-05-23T14:45:45+00:00" 851 | } 852 | ], 853 | "packages-dev": [], 854 | "aliases": [], 855 | "minimum-stability": "stable", 856 | "stability-flags": [], 857 | "prefer-stable": false, 858 | "prefer-lowest": false, 859 | "platform": { 860 | "php": "^8.0" 861 | }, 862 | "platform-dev": [], 863 | "plugin-api-version": "2.6.0" 864 | } 865 | -------------------------------------------------------------------------------- /examples/hello-world/event.php: -------------------------------------------------------------------------------- 1 | "some_event" 11 | )); 12 | 13 | try { 14 | $result = $devCycleClient->track($user, $event_data); 15 | print_r($result); 16 | } catch (Exception $e) { 17 | echo 'Exception when calling DevCycleClient->track: ', $e->getMessage(), PHP_EOL; 18 | } -------------------------------------------------------------------------------- /examples/hello-world/features.php: -------------------------------------------------------------------------------- 1 | allFeatures($user); 7 | print_r($result); 8 | } catch (Exception $e) { 9 | echo 'Exception when calling DVCClient->allFeatures: ', $e->getMessage(), PHP_EOL; 10 | } -------------------------------------------------------------------------------- /examples/hello-world/variable.php: -------------------------------------------------------------------------------- 1 | variable($user, 'test-feature', true); 7 | echo "Variable result is: "; 8 | print_r($result['value'] ? "true" : "false"); 9 | } catch (Exception $e) { 10 | echo 'Exception when calling DVCClient->variable: ', $e->getMessage(), PHP_EOL; 11 | } -------------------------------------------------------------------------------- /examples/hello-world/variableAsync.php: -------------------------------------------------------------------------------- 1 | variableAsync($user, 'test-feature', false) 9 | ->then( 10 | function ($response) { 11 | echo "Variable result is: "; 12 | print_r($response['value'] ? "true" : "false"); 13 | }, 14 | function ($e) { 15 | echo 'Exception when calling DVCClient->variableAsync: ', $e->getMessage(), PHP_EOL; 16 | } 17 | )->wait(); 18 | 19 | echo PHP_EOL, "Ending async"; 20 | -------------------------------------------------------------------------------- /git_push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ 3 | # 4 | # Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com" 5 | 6 | git_user_id=$1 7 | git_repo_id=$2 8 | release_note=$3 9 | git_host=$4 10 | 11 | if [ "$git_host" = "" ]; then 12 | git_host="github.com" 13 | echo "[INFO] No command line input provided. Set \$git_host to $git_host" 14 | fi 15 | 16 | if [ "$git_user_id" = "" ]; then 17 | git_user_id="GIT_USER_ID" 18 | echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" 19 | fi 20 | 21 | if [ "$git_repo_id" = "" ]; then 22 | git_repo_id="GIT_REPO_ID" 23 | echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" 24 | fi 25 | 26 | if [ "$release_note" = "" ]; then 27 | release_note="Minor update" 28 | echo "[INFO] No command line input provided. Set \$release_note to $release_note" 29 | fi 30 | 31 | # Initialize the local directory as a Git repository 32 | git init 33 | 34 | # Adds the files in the local repository and stages them for commit. 35 | git add . 36 | 37 | # Commits the tracked changes and prepares them to be pushed to a remote repository. 38 | git commit -m "$release_note" 39 | 40 | # Sets the new remote 41 | git_remote=$(git remote) 42 | if [ "$git_remote" = "" ]; then # git remote not defined 43 | 44 | if [ "$GIT_TOKEN" = "" ]; then 45 | echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." 46 | git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git 47 | else 48 | git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git 49 | fi 50 | 51 | fi 52 | 53 | git pull origin master 54 | 55 | # Pushes (Forces) the changes in the local repository up to the remote repository 56 | echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" 57 | git push origin master 2>&1 | grep -v 'To https' 58 | -------------------------------------------------------------------------------- /lib/ApiException.php: -------------------------------------------------------------------------------- 1 | responseHeaders = $responseHeaders; 47 | $this->responseBody = $responseBody; 48 | } 49 | 50 | /** 51 | * Gets the HTTP response header 52 | * 53 | * @return string[]|null HTTP response header 54 | */ 55 | public function getResponseHeaders(): ?array 56 | { 57 | return $this->responseHeaders; 58 | } 59 | 60 | /** 61 | * Gets the HTTP body of the server response either as Json or string 62 | * 63 | * @return stdClass|string|null HTTP body of the server response either as \stdClass or string 64 | */ 65 | public function getResponseBody(): stdClass|string|null 66 | { 67 | return $this->responseBody; 68 | } 69 | 70 | /** 71 | * Sets the deserialized response object (during deserialization) 72 | * 73 | * @param mixed $obj Deserialized response object 74 | * 75 | * @return void 76 | */ 77 | public function setResponseObject(mixed $obj): void 78 | { 79 | $this->responseObject = $obj; 80 | } 81 | 82 | /** 83 | * Gets the deserialized response object (during deserialization) 84 | * 85 | * @return stdClass|string|null the deserialized response object 86 | */ 87 | public function getResponseObject(): stdClass|string|null 88 | { 89 | return $this->responseObject; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /lib/HTTPConfiguration.php: -------------------------------------------------------------------------------- 1 | userAgent .= Version::$VERSION . '/' . PHP_VERSION; 55 | } 56 | 57 | /** 58 | * Sets API key 59 | * 60 | * @param string $apiKeyIdentifier API key identifier (authentication scheme) 61 | * @param string $key API key or token 62 | * 63 | * @return $this 64 | */ 65 | public function setApiKey(string $apiKeyIdentifier, string $key): self 66 | { 67 | $this->apiKeys[$apiKeyIdentifier] = $key; 68 | return $this; 69 | } 70 | 71 | /** 72 | * Gets API key 73 | * 74 | * @param string $apiKeyIdentifier API key identifier (authentication scheme) 75 | * 76 | * @return null|string API key or token 77 | */ 78 | public function getApiKey(string $apiKeyIdentifier): ?string 79 | { 80 | return $this->apiKeys[$apiKeyIdentifier] ?? null; 81 | } 82 | 83 | /** 84 | * Sets the prefix for API key (e.g. Bearer) 85 | * 86 | * @param string $apiKeyIdentifier API key identifier (authentication scheme) 87 | * @param string $prefix API key prefix, e.g. Bearer 88 | * 89 | * @return $this 90 | */ 91 | public function setApiKeyPrefix(string $apiKeyIdentifier, string $prefix): self 92 | { 93 | $this->apiKeyPrefixes[$apiKeyIdentifier] = $prefix; 94 | return $this; 95 | } 96 | 97 | /** 98 | * Gets API key prefix 99 | * 100 | * @param string $apiKeyIdentifier API key identifier (authentication scheme) 101 | * 102 | * @return null|string 103 | */ 104 | public function getApiKeyPrefix(string $apiKeyIdentifier): ?string 105 | { 106 | return $this->apiKeyPrefixes[$apiKeyIdentifier] ?? null; 107 | } 108 | 109 | /** 110 | * Sets the user agent of the api client 111 | * 112 | * @param string $userAgent the user agent of the api client 113 | * 114 | * @return $this 115 | * @throws \InvalidArgumentException 116 | */ 117 | public function setUserAgent(string $userAgent): self 118 | { 119 | $this->userAgent = $userAgent; 120 | return $this; 121 | } 122 | 123 | /** 124 | * Gets the user agent of the api client 125 | * 126 | * @return string user agent 127 | */ 128 | public function getUserAgent(): string 129 | { 130 | return $this->userAgent; 131 | } 132 | 133 | /** 134 | * Sets debug flag 135 | * 136 | * @param bool $debug Debug flag 137 | * 138 | * @return $this 139 | */ 140 | public function setDebug(bool $debug): static 141 | { 142 | $this->debug = $debug; 143 | return $this; 144 | } 145 | 146 | /** 147 | * Gets the debug flag 148 | * 149 | * @return bool 150 | */ 151 | public function getDebug(): bool 152 | { 153 | return $this->debug; 154 | } 155 | 156 | /** 157 | * Sets the debug file 158 | * 159 | * @param string $debugFile Debug file 160 | * 161 | * @return $this 162 | */ 163 | public function setDebugFile(string $debugFile): static 164 | { 165 | $this->debugFile = $debugFile; 166 | return $this; 167 | } 168 | 169 | /** 170 | * Gets the debug file 171 | * 172 | * @return string 173 | */ 174 | public function getDebugFile(): string 175 | { 176 | return $this->debugFile; 177 | } 178 | 179 | /** 180 | * Gets the default configuration instance 181 | * 182 | * @return HTTPConfiguration 183 | */ 184 | public static function getDefaultConfiguration(): HTTPConfiguration 185 | { 186 | if (self::$defaultConfiguration === null) { 187 | self::$defaultConfiguration = new HTTPConfiguration(); 188 | } 189 | 190 | return self::$defaultConfiguration; 191 | } 192 | 193 | /** 194 | * Sets the default configuration instance 195 | * 196 | * @param HTTPConfiguration $config An instance of the DevCycleConfiguration Object 197 | * 198 | * @return void 199 | */ 200 | public static function setDefaultConfiguration(HTTPConfiguration $config): void 201 | { 202 | self::$defaultConfiguration = $config; 203 | } 204 | 205 | /** 206 | * Gets the essential information for debugging 207 | * 208 | * @return string The report for debugging 209 | */ 210 | public static function toDebugReport(): string 211 | { 212 | $report = 'PHP SDK (DevCycle) Debug Report:' . PHP_EOL; 213 | $report .= ' OS: ' . php_uname() . PHP_EOL; 214 | $report .= ' PHP Version: ' . PHP_VERSION . PHP_EOL; 215 | $report .= ' SDK Version' . Version::$VERSION. PHP_EOL; 216 | 217 | return $report; 218 | } 219 | 220 | /** 221 | * Get API key (with prefix if set) 222 | * 223 | * @param string $apiKeyIdentifier name of apikey 224 | * 225 | * @return null|string API key with the prefix 226 | */ 227 | public function getApiKeyWithPrefix(string $apiKeyIdentifier): ?string 228 | { 229 | $prefix = $this->getApiKeyPrefix($apiKeyIdentifier); 230 | $apiKey = $this->getApiKey($apiKeyIdentifier); 231 | 232 | if ($apiKey === null) { 233 | return null; 234 | } 235 | 236 | if ($prefix === null) { 237 | $keyWithPrefix = $apiKey; 238 | } else { 239 | $keyWithPrefix = $prefix . ' ' . $apiKey; 240 | } 241 | 242 | return $keyWithPrefix; 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /lib/HeaderSelector.php: -------------------------------------------------------------------------------- 1 | selectAcceptHeader($accept); 25 | if ($accept !== null) { 26 | $headers['Accept'] = $accept; 27 | } 28 | 29 | $headers['Content-Type'] = $this->selectContentTypeHeader($contentTypes); 30 | return $headers; 31 | } 32 | 33 | /** 34 | * Return the header 'Accept' based on an array of Accept provided 35 | * 36 | * @param string[] $accept Array of header 37 | * 38 | * @return null|string Accept (e.g. application/json) 39 | */ 40 | private function selectAcceptHeader(array $accept): ?string 41 | { 42 | if (count($accept) === 0 || (count($accept) === 1 && $accept[0] === '')) { 43 | return null; 44 | } elseif ($jsonAccept = preg_grep('~(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$~', $accept)) { 45 | return implode(',', $jsonAccept); 46 | } else { 47 | return implode(',', $accept); 48 | } 49 | } 50 | 51 | /** 52 | * Return the content type based on an array of content-type provided 53 | * 54 | * @param string[] $contentType Array fo content-type 55 | * 56 | * @return string Content-Type (e.g. application/json) 57 | */ 58 | private function selectContentTypeHeader(array $contentType): string 59 | { 60 | if (count($contentType) === 0 || (count($contentType) === 1 && $contentType[0] === '')) { 61 | return 'application/json'; 62 | } elseif (preg_grep("/application\/json/i", $contentType)) { 63 | return 'application/json'; 64 | } else { 65 | return implode(',', $contentType); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lib/Model/DevCycleEvent.php: -------------------------------------------------------------------------------- 1 | 15 | * @template TKey int|null 16 | * @template TValue mixed|null 17 | */ 18 | class DevCycleEvent implements ModelInterface, ArrayAccess, \JsonSerializable 19 | { 20 | 21 | /** 22 | * The original name of the model. 23 | * 24 | * @var string 25 | */ 26 | protected static string $openAPIModelName = 'Event'; 27 | 28 | /** 29 | * Array of property to type mappings. Used for (de)serialization 30 | * 31 | * @var string[] 32 | */ 33 | protected static array $openAPITypes = [ 34 | 'type' => 'string', 35 | 'target' => 'string', 36 | 'date' => 'float', 37 | 'value' => 'float', 38 | 'meta_data' => 'object' 39 | ]; 40 | 41 | /** 42 | * Array of property to format mappings. Used for (de)serialization 43 | * 44 | * @var string[] 45 | * @phpstan-var array 46 | * @psalm-var array 47 | */ 48 | protected static array $openAPIFormats = [ 49 | 'type' => null, 50 | 'target' => null, 51 | 'date' => null, 52 | 'value' => null, 53 | 'meta_data' => null 54 | ]; 55 | 56 | /** 57 | * Array of property to type mappings. Used for (de)serialization 58 | * 59 | * @return array 60 | */ 61 | public static function openAPITypes(): array 62 | { 63 | return self::$openAPITypes; 64 | } 65 | 66 | /** 67 | * Array of property to format mappings. Used for (de)serialization 68 | * 69 | * @return array 70 | */ 71 | public static function openAPIFormats(): array 72 | { 73 | return self::$openAPIFormats; 74 | } 75 | 76 | /** 77 | * Array of attributes where the key is the local name, 78 | * and the value is the original name 79 | * 80 | * @var string[] 81 | */ 82 | protected static array $attributeMap = [ 83 | 'type' => 'type', 84 | 'target' => 'target', 85 | 'date' => 'date', 86 | 'value' => 'value', 87 | 'meta_data' => 'metaData' 88 | ]; 89 | 90 | /** 91 | * Array of attributes to setter functions (for deserialization of responses) 92 | * 93 | * @var string[] 94 | */ 95 | protected static array $setters = [ 96 | 'type' => 'setType', 97 | 'target' => 'setTarget', 98 | 'date' => 'setDate', 99 | 'value' => 'setValue', 100 | 'meta_data' => 'setMetaData' 101 | ]; 102 | 103 | /** 104 | * Array of attributes to getter functions (for serialization of requests) 105 | * 106 | * @var string[] 107 | */ 108 | protected static array $getters = [ 109 | 'type' => 'getType', 110 | 'target' => 'getTarget', 111 | 'date' => 'getDate', 112 | 'value' => 'getValue', 113 | 'meta_data' => 'getMetaData' 114 | ]; 115 | 116 | /** 117 | * Array of attributes where the key is the local name, 118 | * and the value is the original name 119 | * 120 | * @return array 121 | */ 122 | public static function attributeMap(): array 123 | { 124 | return self::$attributeMap; 125 | } 126 | 127 | /** 128 | * Array of attributes to setter functions (for deserialization of responses) 129 | * 130 | * @return array 131 | */ 132 | public static function setters(): array 133 | { 134 | return self::$setters; 135 | } 136 | 137 | /** 138 | * Array of attributes to getter functions (for serialization of requests) 139 | * 140 | * @return array 141 | */ 142 | public static function getters(): array 143 | { 144 | return self::$getters; 145 | } 146 | 147 | /** 148 | * The original name of the model. 149 | * 150 | * @return string 151 | */ 152 | public function getModelName(): string 153 | { 154 | return self::$openAPIModelName; 155 | } 156 | 157 | 158 | /** 159 | * Associative array for storing property values 160 | * 161 | * @var mixed[] 162 | */ 163 | protected array $container = []; 164 | 165 | /** 166 | * Constructor 167 | * 168 | * @param mixed[]|null $data Associated array of property values 169 | * initializing the model 170 | */ 171 | public function __construct(?array $data = null) 172 | { 173 | $this->container['type'] = $data['type'] ?? null; 174 | $this->container['target'] = $data['target'] ?? null; 175 | $this->container['date'] = $data['date'] ?? null; 176 | $this->container['value'] = $data['value'] ?? null; 177 | $this->container['meta_data'] = $data['meta_data'] ?? null; 178 | } 179 | 180 | /** 181 | * Show all the invalid properties with reasons. 182 | * 183 | * @return array invalid properties with reasons 184 | */ 185 | public function listInvalidProperties(): array 186 | { 187 | $invalidProperties = []; 188 | 189 | if ($this->container['type'] === null || $this->container['type'] === '') { 190 | $invalidProperties[] = "'type' can't be null or empty"; 191 | } 192 | return $invalidProperties; 193 | } 194 | 195 | /** 196 | * Validate all the properties in the model 197 | * return true if all passed 198 | * 199 | * @return bool True if all properties are valid 200 | */ 201 | public function valid(): bool 202 | { 203 | return count($this->listInvalidProperties()) === 0; 204 | } 205 | 206 | 207 | /** 208 | * Gets type 209 | * 210 | * @return string 211 | */ 212 | public function getType(): string 213 | { 214 | return $this->container['type']; 215 | } 216 | 217 | /** 218 | * Sets type 219 | * 220 | * @param string $type Custom event type 221 | * 222 | * @return self 223 | */ 224 | public function setType(string $type): self 225 | { 226 | $this->container['type'] = $type; 227 | 228 | return $this; 229 | } 230 | 231 | /** 232 | * Gets target 233 | * 234 | * @return string|null 235 | */ 236 | public function getTarget(): ?string 237 | { 238 | return $this->container['target']; 239 | } 240 | 241 | /** 242 | * Sets target 243 | * 244 | * @param string|null $target Custom event target / subject of event. Contextual to event type 245 | * 246 | * @return self 247 | */ 248 | public function setTarget(?string $target): self 249 | { 250 | $this->container['target'] = $target; 251 | 252 | return $this; 253 | } 254 | 255 | /** 256 | * Gets date 257 | * 258 | * @return float|null 259 | */ 260 | public function getDate(): ?float 261 | { 262 | return $this->container['date']; 263 | } 264 | 265 | /** 266 | * Sets date 267 | * 268 | * @param float|null $date Unix epoch time the event occurred according to client 269 | * 270 | * @return self 271 | */ 272 | public function setDate(?float $date): self 273 | { 274 | $this->container['date'] = $date; 275 | 276 | return $this; 277 | } 278 | 279 | /** 280 | * Gets value 281 | * 282 | * @return float|null 283 | */ 284 | public function getValue(): ?float 285 | { 286 | return $this->container['value']; 287 | } 288 | 289 | /** 290 | * Sets value 291 | * 292 | * @param float|null $value Value for numerical events. Contextual to event type 293 | * 294 | * @return self 295 | */ 296 | public function setValue(?float $value): self 297 | { 298 | $this->container['value'] = $value; 299 | 300 | return $this; 301 | } 302 | 303 | /** 304 | * Gets meta_data 305 | * 306 | * @return object|null 307 | */ 308 | public function getMetaData(): ?array 309 | { 310 | return $this->container['meta_data']; 311 | } 312 | 313 | /** 314 | * Sets meta_data 315 | * 316 | * @param object|null $meta_data Extra JSON metadata for event. Contextual to event type 317 | * 318 | * @return self 319 | */ 320 | public function setMetaData(?array $meta_data): self 321 | { 322 | $this->container['meta_data'] = $meta_data; 323 | 324 | return $this; 325 | } 326 | 327 | /** 328 | * Returns true if offset exists. False otherwise. 329 | * 330 | * @param integer $offset Offset 331 | * 332 | * @return boolean 333 | */ 334 | public function offsetExists($offset): bool 335 | { 336 | return isset($this->container[$offset]); 337 | } 338 | 339 | /** 340 | * Gets offset. 341 | * 342 | * @param integer $offset Offset 343 | * 344 | * @return mixed|null 345 | */ 346 | public function offsetGet($offset): mixed 347 | { 348 | return $this->container[$offset] ?? null; 349 | } 350 | 351 | /** 352 | * Sets value based on offset. 353 | * 354 | * @param int|null $offset Offset 355 | * @param mixed $value Value to be set 356 | * 357 | * @return void 358 | */ 359 | public function offsetSet($offset, mixed $value): void 360 | { 361 | if (is_null($offset)) { 362 | $this->container[] = $value; 363 | } else { 364 | $this->container[$offset] = $value; 365 | } 366 | } 367 | 368 | /** 369 | * Unsets offset. 370 | * 371 | * @param integer $offset Offset 372 | * 373 | * @return void 374 | */ 375 | public function offsetUnset($offset): void 376 | { 377 | unset($this->container[$offset]); 378 | } 379 | 380 | /** 381 | * Serializes the object to a value that can be serialized natively by json_encode(). 382 | * @link https://www.php.net/manual/en/jsonserializable.jsonserialize.php 383 | * 384 | * @return mixed Returns data which can be serialized by json_encode(), which is a value 385 | * of any type other than a resource. 386 | */ 387 | public function jsonSerialize(): mixed 388 | { 389 | return ObjectSerializer::sanitizeForSerialization($this); 390 | } 391 | 392 | /** 393 | * Gets the string presentation of the object 394 | * 395 | * @return string 396 | */ 397 | public function __toString() 398 | { 399 | return json_encode( 400 | ObjectSerializer::sanitizeForSerialization($this), 401 | JSON_PRETTY_PRINT 402 | ); 403 | } 404 | 405 | /** 406 | * Gets a header-safe presentation of the object 407 | * 408 | * @return string 409 | */ 410 | public function toHeaderValue(): string 411 | { 412 | return json_encode(ObjectSerializer::sanitizeForSerialization($this)); 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /lib/Model/DevCycleOptions.php: -------------------------------------------------------------------------------- 1 | enableEdgeDB = $enableEdgeDB; 31 | if ($bucketingApiHostname !== null) { 32 | $this->bucketingApiHostname = $bucketingApiHostname; 33 | } 34 | $this->unixSocketPath = $unixSocketPath; 35 | $this->httpOptions = $httpOptions; 36 | } 37 | 38 | /** 39 | * Gets the enableEdgeDB flag 40 | * 41 | * @return boolean enable EdgeDB flag 42 | */ 43 | public function isEdgeDBEnabled(): bool 44 | { 45 | return $this->enableEdgeDB; 46 | } 47 | 48 | /** 49 | * Gets the bucketing API hostname 50 | * @return string bucketing API hostname 51 | */ 52 | public function getBucketingApiHostname(): string 53 | { 54 | return $this->bucketingApiHostname; 55 | } 56 | 57 | /** 58 | * Gets the unix socket path 59 | * @return string unix socket path 60 | */ 61 | public function getUnixSocketPath(): ?string 62 | { 63 | return $this->unixSocketPath; 64 | } 65 | 66 | public function getHttpOptions(): array 67 | { 68 | return $this->httpOptions; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lib/Model/DevCycleUser.php: -------------------------------------------------------------------------------- 1 | 18 | * @template TKey int|null 19 | * @template TValue mixed|null 20 | */ 21 | class DevCycleUser implements ModelInterface, ArrayAccess, \JsonSerializable 22 | { 23 | 24 | /** 25 | * The original name of the model. 26 | * 27 | * @var string 28 | */ 29 | protected static string $openAPIModelName = 'User'; 30 | 31 | /** 32 | * Array of property to type mappings. Used for (de)serialization 33 | * 34 | * @var string[] 35 | */ 36 | protected static array $openAPITypes = [ 37 | 'user_id' => 'string', 38 | 'email' => 'string', 39 | 'name' => 'string', 40 | 'language' => 'string', 41 | 'country' => 'string', 42 | 'app_version' => 'string', 43 | 'app_build' => 'string', 44 | 'custom_data' => 'object', 45 | 'private_custom_data' => 'object', 46 | 'created_date' => 'float', 47 | 'last_seen_date' => 'float', 48 | 'platform' => 'string', 49 | 'platform_version' => 'string', 50 | 'sdk_type' => 'string', 51 | 'sdk_version' => 'string' 52 | ]; 53 | 54 | /** 55 | * Array of property to format mappings. Used for (de)serialization 56 | * 57 | * @var string[] 58 | * @phpstan-var array 59 | * @psalm-var array 60 | */ 61 | protected static array $openAPIFormats = [ 62 | 'user_id' => null, 63 | 'email' => null, 64 | 'name' => null, 65 | 'language' => null, 66 | 'country' => null, 67 | 'app_version' => null, 68 | 'app_build' => null, 69 | 'custom_data' => null, 70 | 'private_custom_data' => null, 71 | 'created_date' => null, 72 | 'last_seen_date' => null, 73 | 'platform' => null, 74 | 'platform_version' => null, 75 | 'sdk_type' => null, 76 | 'sdk_version' => null 77 | ]; 78 | 79 | /** 80 | * Array of property to type mappings. Used for (de)serialization 81 | * 82 | * @return array 83 | */ 84 | public static function openAPITypes(): array 85 | { 86 | return self::$openAPITypes; 87 | } 88 | 89 | /** 90 | * Array of property to format mappings. Used for (de)serialization 91 | * 92 | * @return array 93 | */ 94 | public static function openAPIFormats(): array 95 | { 96 | return self::$openAPIFormats; 97 | } 98 | 99 | /** 100 | * Array of attributes where the key is the local name, 101 | * and the value is the original name 102 | * 103 | * @var string[] 104 | */ 105 | protected static array $attributeMap = [ 106 | 'user_id' => 'user_id', 107 | 'email' => 'email', 108 | 'name' => 'name', 109 | 'language' => 'language', 110 | 'country' => 'country', 111 | 'app_version' => 'appVersion', 112 | 'app_build' => 'appBuild', 113 | 'custom_data' => 'customData', 114 | 'private_custom_data' => 'privateCustomData', 115 | 'created_date' => 'createdDate', 116 | 'last_seen_date' => 'lastSeenDate', 117 | 'platform' => 'platform', 118 | 'platform_version' => 'platformVersion', 119 | 'sdk_type' => 'sdkType', 120 | 'sdk_version' => 'sdkVersion' 121 | ]; 122 | 123 | /** 124 | * Array of attributes to setter functions (for deserialization of responses) 125 | * 126 | * @var string[] 127 | */ 128 | protected static array $setters = [ 129 | 'user_id' => 'setUserId', 130 | 'email' => 'setEmail', 131 | 'name' => 'setName', 132 | 'language' => 'setLanguage', 133 | 'country' => 'setCountry', 134 | 'app_version' => 'setAppVersion', 135 | 'app_build' => 'setAppBuild', 136 | 'custom_data' => 'setCustomData', 137 | 'private_custom_data' => 'setPrivateCustomData', 138 | 'created_date' => 'setCreatedDate', 139 | 'last_seen_date' => 'setLastSeenDate' 140 | ]; 141 | 142 | /** 143 | * Array of attributes to getter functions (for serialization of requests) 144 | * 145 | * @var string[] 146 | */ 147 | protected static array $getters = [ 148 | 'user_id' => 'getUserId', 149 | 'email' => 'getEmail', 150 | 'name' => 'getName', 151 | 'language' => 'getLanguage', 152 | 'country' => 'getCountry', 153 | 'app_version' => 'getAppVersion', 154 | 'app_build' => 'getAppBuild', 155 | 'custom_data' => 'getCustomData', 156 | 'private_custom_data' => 'getPrivateCustomData', 157 | 'created_date' => 'getCreatedDate', 158 | 'last_seen_date' => 'getLastSeenDate', 159 | 'platform' => 'getPlatform', 160 | 'platform_version' => 'getPlatformVersion', 161 | 'sdk_type' => 'getSdkType', 162 | 'sdk_version' => 'getSdkVersion' 163 | ]; 164 | 165 | /** 166 | * Array of attributes where the key is the local name, 167 | * and the value is the original name 168 | * 169 | * @return array 170 | */ 171 | public static function attributeMap(): array 172 | { 173 | return self::$attributeMap; 174 | } 175 | 176 | /** 177 | * Array of attributes to setter functions (for deserialization of responses) 178 | * 179 | * @return array 180 | */ 181 | public static function setters(): array 182 | { 183 | return self::$setters; 184 | } 185 | 186 | /** 187 | * Array of attributes to getter functions (for serialization of requests) 188 | * 189 | * @return array 190 | */ 191 | public static function getters(): array 192 | { 193 | return self::$getters; 194 | } 195 | 196 | /** 197 | * The original name of the model. 198 | * 199 | * @return string 200 | */ 201 | public function getModelName(): string 202 | { 203 | return self::$openAPIModelName; 204 | } 205 | 206 | const SDK_TYPE_API = 'api'; 207 | const SDK_TYPE_SERVER = 'server'; 208 | 209 | /** 210 | * Gets allowable values of the enum 211 | * 212 | * @return string[] 213 | */ 214 | public function getSdkTypeAllowableValues(): array 215 | { 216 | return [ 217 | self::SDK_TYPE_API, 218 | self::SDK_TYPE_SERVER, 219 | ]; 220 | } 221 | 222 | /** 223 | * Associative array for storing property values 224 | * 225 | * @var array[] 226 | */ 227 | protected mixed $container = []; 228 | 229 | /** 230 | * Constructor 231 | * 232 | * @param mixed[]|null $data Associated array of property values 233 | * initializing the model 234 | */ 235 | public function __construct(?array $data = null) 236 | { 237 | $this->container['user_id'] = $data['user_id'] ?? null; 238 | $this->container['email'] = $data['email'] ?? null; 239 | $this->container['name'] = $data['name'] ?? null; 240 | $this->container['language'] = $data['language'] ?? null; 241 | $this->container['country'] = $data['country'] ?? null; 242 | $this->container['app_version'] = $data['app_version'] ?? null; 243 | $this->container['app_build'] = $data['app_build'] ?? null; 244 | $this->container['custom_data'] = $data['custom_data'] ?? null; 245 | $this->container['private_custom_data'] = $data['private_custom_data'] ?? null; 246 | $this->container['created_date'] = $data['created_date'] ?? null; 247 | $this->container['last_seen_date'] = $data['last_seen_date'] ?? null; 248 | $this->container['platform'] = 'PHP'; 249 | $this->container['platform_version'] = PHP_VERSION; 250 | $this->container['sdk_type'] = 'server'; 251 | $this->container['sdk_version'] = Version::$VERSION; 252 | } 253 | 254 | /** 255 | * Show all the invalid properties with reasons. 256 | * 257 | * @return array invalid properties with reasons 258 | */ 259 | public function listInvalidProperties(): array 260 | { 261 | $invalidProperties = []; 262 | 263 | if ($this->container['user_id'] === null) { 264 | $invalidProperties[] = "'user_id' can't be null"; 265 | } 266 | if (!is_null($this->container['language']) && (mb_strlen($this->container['language']) > 2)) { 267 | $invalidProperties[] = "invalid value for 'language', the character length must be smaller than or equal to 2."; 268 | } 269 | 270 | if (!is_null($this->container['country']) && (mb_strlen($this->container['country']) > 2)) { 271 | $invalidProperties[] = "invalid value for 'country', the character length must be smaller than or equal to 2."; 272 | } 273 | 274 | $allowedValues = $this->getSdkTypeAllowableValues(); 275 | if (!is_null($this->container['sdk_type']) && !in_array($this->container['sdk_type'], $allowedValues, true)) { 276 | $invalidProperties[] = sprintf( 277 | "invalid value '%s' for 'sdk_type', must be one of '%s'", 278 | $this->container['sdk_type'], 279 | implode("', '", $allowedValues) 280 | ); 281 | } 282 | 283 | return $invalidProperties; 284 | } 285 | 286 | /** 287 | * Validate all the properties in the model 288 | * return true if all passed 289 | * 290 | * @return bool True if all properties are valid 291 | */ 292 | public function valid(): bool 293 | { 294 | return count($this->listInvalidProperties()) === 0; 295 | } 296 | 297 | 298 | /** 299 | * Gets user_id 300 | * 301 | * @return string 302 | */ 303 | public function getUserId(): string 304 | { 305 | return $this->container['user_id']; 306 | } 307 | 308 | /** 309 | * Sets user_id 310 | * 311 | * @param string $user_id Unique id to identify the user 312 | * 313 | * @return self 314 | */ 315 | public function setUserId(string $user_id): self 316 | { 317 | $this->container['user_id'] = $user_id; 318 | 319 | return $this; 320 | } 321 | 322 | /** 323 | * Gets email 324 | * 325 | * @return string|null 326 | */ 327 | public function getEmail(): ?string 328 | { 329 | return $this->container['email']; 330 | } 331 | 332 | /** 333 | * Sets email 334 | * 335 | * @param string|null $email User's email used to identify the user on the dashboard / target audiences 336 | * 337 | * @return self 338 | */ 339 | public function setEmail(?string $email): self 340 | { 341 | $this->container['email'] = $email; 342 | 343 | return $this; 344 | } 345 | 346 | /** 347 | * Gets name 348 | * 349 | * @return string|null 350 | */ 351 | public function getName(): ?string 352 | { 353 | return $this->container['name']; 354 | } 355 | 356 | /** 357 | * Sets name 358 | * 359 | * @param string|null $name User's name used to identify the user on the dashboard / target audiences 360 | * 361 | * @return self 362 | */ 363 | public function setName(?string $name): self 364 | { 365 | $this->container['name'] = $name; 366 | 367 | return $this; 368 | } 369 | 370 | /** 371 | * Gets language 372 | * 373 | * @return string|null 374 | */ 375 | public function getLanguage(): ?string 376 | { 377 | return $this->container['language']; 378 | } 379 | 380 | /** 381 | * Sets language 382 | * 383 | * @param string|null $language User's language in ISO 639-1 format 384 | * 385 | * @return self 386 | */ 387 | public function setLanguage(?string $language): self 388 | { 389 | if (!is_null($language) && (mb_strlen($language) > 2)) { 390 | throw new \InvalidArgumentException('invalid length for $language when calling setLanguage, must be smaller than or equal to 2.'); 391 | } 392 | 393 | $this->container['language'] = $language; 394 | 395 | return $this; 396 | } 397 | 398 | /** 399 | * Gets country 400 | * 401 | * @return string|null 402 | */ 403 | public function getCountry(): ?string 404 | { 405 | return $this->container['country']; 406 | } 407 | 408 | /** 409 | * Sets country 410 | * 411 | * @param string|null $country User's country in ISO 3166 alpha-2 format 412 | * 413 | * @return self 414 | */ 415 | public function setCountry(?string $country): self 416 | { 417 | if (!is_null($country) && (mb_strlen($country) > 2)) { 418 | throw new \InvalidArgumentException('invalid length for $country when calling setCountry., must be smaller than or equal to 2.'); 419 | } 420 | 421 | $this->container['country'] = $country; 422 | 423 | return $this; 424 | } 425 | 426 | /** 427 | * Gets app_version 428 | * 429 | * @return string|null 430 | */ 431 | public function getAppVersion(): ?string 432 | { 433 | return $this->container['app_version']; 434 | } 435 | 436 | /** 437 | * Sets app_version 438 | * 439 | * @param string|null $app_version App Version of the running application 440 | * 441 | * @return self 442 | */ 443 | public function setAppVersion(?string $app_version): self 444 | { 445 | $this->container['app_version'] = $app_version; 446 | 447 | return $this; 448 | } 449 | 450 | /** 451 | * Gets app_build 452 | * 453 | * @return string|null 454 | */ 455 | public function getAppBuild(): ?string 456 | { 457 | return $this->container['app_build']; 458 | } 459 | 460 | /** 461 | * Sets app_build 462 | * 463 | * @param string|null $app_build App Build number of the running application 464 | * 465 | * @return self 466 | */ 467 | public function setAppBuild(?string $app_build): self 468 | { 469 | $this->container['app_build'] = $app_build; 470 | 471 | return $this; 472 | } 473 | 474 | /** 475 | * Gets custom_data 476 | * 477 | * @return object|null 478 | */ 479 | public function getCustomData(): ?array 480 | { 481 | return $this->container['custom_data']; 482 | } 483 | 484 | /** 485 | * Sets custom_data 486 | * 487 | * @param array|null $custom_data User's custom data to target the user with, data will be logged to DevCycle for use in dashboard. 488 | * 489 | * @return self 490 | */ 491 | public function setCustomData(?array $custom_data): self 492 | { 493 | $this->container['custom_data'] = $custom_data; 494 | 495 | return $this; 496 | } 497 | 498 | public function addCustomData(string $key, $value): self 499 | { 500 | if($this->container['custom_data'] === null) { 501 | $this->container['custom_data'] = []; 502 | } 503 | $this->container['custom_data'][$key] = $value; 504 | return $this; 505 | } 506 | 507 | /** 508 | * Gets private_custom_data 509 | * 510 | * @return array|null 511 | */ 512 | public function getPrivateCustomData(): ?array 513 | { 514 | return $this->container['private_custom_data']; 515 | } 516 | 517 | /** 518 | * Sets private_custom_data 519 | * 520 | * @param array|null $private_custom_data User's custom data to target the user with, data will not be logged to DevCycle only used for feature bucketing. 521 | * 522 | * @return self 523 | */ 524 | public function setPrivateCustomData(?array $private_custom_data): self 525 | { 526 | $this->container['private_custom_data'] = $private_custom_data; 527 | 528 | return $this; 529 | } 530 | 531 | public function addPrivateCustomData(string $key, $value): self 532 | { 533 | $this->container['private_custom_data'][$key] = $value; 534 | return $this; 535 | } 536 | 537 | /** 538 | * Gets created_date 539 | * 540 | * @return float|null 541 | */ 542 | public function getCreatedDate(): ?float 543 | { 544 | return $this->container['created_date']; 545 | } 546 | 547 | /** 548 | * Sets created_date 549 | * 550 | * @param float|null $created_date Date the user was created, Unix epoch timestamp format 551 | * 552 | * @return self 553 | */ 554 | public function setCreatedDate(?float $created_date): self 555 | { 556 | $this->container['created_date'] = $created_date; 557 | 558 | return $this; 559 | } 560 | 561 | /** 562 | * Gets last_seen_date 563 | * 564 | * @return float|null 565 | */ 566 | public function getLastSeenDate(): ?float 567 | { 568 | return $this->container['last_seen_date']; 569 | } 570 | 571 | /** 572 | * Sets last_seen_date 573 | * 574 | * @param float|null $last_seen_date Date the user was created, Unix epoch timestamp format 575 | * 576 | * @return self 577 | */ 578 | public function setLastSeenDate(?float $last_seen_date): self 579 | { 580 | $this->container['last_seen_date'] = $last_seen_date; 581 | 582 | return $this; 583 | } 584 | 585 | /** 586 | * Gets platform 587 | * 588 | * @return string 589 | */ 590 | public function getPlatform(): string 591 | { 592 | return $this->container['platform']; 593 | } 594 | 595 | /** 596 | * Gets platform_version 597 | * 598 | * @return string 599 | */ 600 | public function getPlatformVersion(): string 601 | { 602 | return $this->container['platform_version']; 603 | } 604 | 605 | /** 606 | * Gets sdk_type 607 | * 608 | * @return string 609 | */ 610 | public function getSdkType(): string 611 | { 612 | return $this->container['sdk_type']; 613 | } 614 | 615 | /** 616 | * Gets sdk_version 617 | * 618 | * @return string 619 | */ 620 | public function getSdkVersion(): string 621 | { 622 | return $this->container['sdk_version']; 623 | } 624 | 625 | /** 626 | * Returns true if offset exists. False otherwise. 627 | * 628 | * @param integer $offset Offset 629 | * 630 | * @return boolean 631 | */ 632 | public function offsetExists($offset): bool 633 | { 634 | return isset($this->container[$offset]); 635 | } 636 | 637 | /** 638 | * Gets offset. 639 | * 640 | * @param integer $offset Offset 641 | * 642 | * @return mixed|null 643 | */ 644 | public function offsetGet($offset): mixed 645 | { 646 | return $this->container[$offset] ?? null; 647 | } 648 | 649 | /** 650 | * Sets value based on offset. 651 | * 652 | * @param int|null $offset Offset 653 | * @param mixed $value Value to be set 654 | * 655 | * @return void 656 | */ 657 | public function offsetSet($offset, mixed $value): void 658 | { 659 | if (is_null($offset)) { 660 | $this->container[] = $value; 661 | } else { 662 | $this->container[$offset] = $value; 663 | } 664 | } 665 | 666 | /** 667 | * Unsets offset. 668 | * 669 | * @param integer $offset Offset 670 | * 671 | * @return void 672 | */ 673 | public function offsetUnset($offset): void 674 | { 675 | unset($this->container[$offset]); 676 | } 677 | 678 | /** 679 | * Serializes the object to a value that can be serialized natively by json_encode(). 680 | * @link https://www.php.net/manual/en/jsonserializable.jsonserialize.php 681 | * 682 | * @return mixed Returns data which can be serialized by json_encode(), which is a value 683 | * of any type other than a resource. 684 | */ 685 | public function jsonSerialize(): mixed 686 | { 687 | return ObjectSerializer::sanitizeForSerialization($this); 688 | } 689 | 690 | /** 691 | * Gets the string presentation of the object 692 | * 693 | * @return string 694 | */ 695 | public function __toString(): string 696 | { 697 | return json_encode( 698 | ObjectSerializer::sanitizeForSerialization($this), 699 | JSON_PRETTY_PRINT 700 | ); 701 | } 702 | 703 | /** 704 | * Gets a header-safe presentation of the object 705 | * 706 | * @return string 707 | */ 708 | public function toHeaderValue(): string 709 | { 710 | return json_encode(ObjectSerializer::sanitizeForSerialization($this)); 711 | } 712 | 713 | public static function FromEvaluationContext(EvaluationContext $context): DevCycleUser 714 | { 715 | $user = new DevCycleUser(); 716 | if ($context->getTargetingKey() === null && $context->getAttributes()->get("user_id") === null) { 717 | throw new \InvalidArgumentException('targetingKey or user_id is missing from EvaluationContext'); 718 | } 719 | if ($context->getAttributes()->get("user_id") !== null) { 720 | $userId = $context->getAttributes()->get("user_id"); 721 | } else { 722 | $userId = $context->getTargetingKey(); 723 | } 724 | $user->setUserId($userId); 725 | 726 | foreach ($context->getAttributes()->toArray() as $key => $value) { 727 | if ($key === 'user_id' || $key === 'targetingKey') { 728 | continue; 729 | } 730 | switch ($key) { 731 | case "email": 732 | if (!ValueTypeValidator::isString($value)) { 733 | continue 2; 734 | } 735 | $user->setEmail($value); 736 | break; 737 | case "name": 738 | if (!ValueTypeValidator::isString($value)) { 739 | continue 2; 740 | } 741 | $user->setName($value); 742 | break; 743 | case "language": 744 | if (!ValueTypeValidator::isString($value)) { 745 | continue 2; 746 | } 747 | $user->setLanguage($value); 748 | break; 749 | case "country": 750 | if (!ValueTypeValidator::isString($value)) { 751 | continue 2; 752 | } 753 | $user->setCountry($value); 754 | break; 755 | case "appVersion": 756 | if (!ValueTypeValidator::isString($value)) { 757 | continue 2; 758 | } 759 | $user->setAppVersion($value); 760 | break; 761 | case "appBuild": 762 | if (!ValueTypeValidator::isInteger($value) && !ValueTypeValidator::isFloat($value)) { 763 | continue 2; 764 | } 765 | $user->setAppBuild($value); 766 | break; 767 | case "customData": 768 | case "privateCustomData": 769 | if (ValueTypeValidator::isStructure($value)) { 770 | foreach ($value as $subkey => $subvalue) { 771 | if (ValueTypeValidator::isStructure($subvalue)) { 772 | throw new \InvalidArgumentException('DevCycleUser only supports flat customData properties of type string / number / boolean / null'); 773 | } 774 | switch ($key) { 775 | case "privateCustomData": 776 | $user->addPrivateCustomData($subkey, $subvalue); 777 | break; 778 | case "customData": 779 | $user->addCustomData($subkey, $subvalue); 780 | break; 781 | } 782 | } 783 | } 784 | break; 785 | default: 786 | if (gettype($value) !== 'string' && gettype($value) !== 'integer' && gettype($value) !== 'boolean' && gettype($value) !== 'NULL') { 787 | throw new \InvalidArgumentException('DevCycleUser only supports flat customData properties of type string / number / boolean / null'); 788 | } 789 | $user->addCustomData($key, $value); 790 | break; 791 | } 792 | } 793 | return $user; 794 | } 795 | } 796 | -------------------------------------------------------------------------------- /lib/Model/DevCycleUserAndEventsBody.php: -------------------------------------------------------------------------------- 1 | 15 | * @template TKey int|null 16 | * @template TValue mixed|null 17 | */ 18 | class DevCycleUserAndEventsBody implements ModelInterface, ArrayAccess, \JsonSerializable 19 | { 20 | 21 | /** 22 | * The original name of the model. 23 | * 24 | * @var string 25 | */ 26 | protected static string $openAPIModelName = 'UserAndEventsBody'; 27 | 28 | /** 29 | * Array of property to type mappings. Used for (de)serialization 30 | * 31 | * @var string[] 32 | */ 33 | protected static array $openAPITypes = [ 34 | 'events' => '\DevCycle\Model\DevCycleEvent[]', 35 | 'user' => '\DevCycle\Model\DevCycleUser' 36 | ]; 37 | 38 | /** 39 | * Array of property to format mappings. Used for (de)serialization 40 | * 41 | * @var string[] 42 | * @phpstan-var array 43 | * @psalm-var array 44 | */ 45 | protected static array $openAPIFormats = [ 46 | 'events' => null, 47 | 'user' => null 48 | ]; 49 | 50 | /** 51 | * Array of property to type mappings. Used for (de)serialization 52 | * 53 | * @return array 54 | */ 55 | public static function openAPITypes(): array 56 | { 57 | return self::$openAPITypes; 58 | } 59 | 60 | /** 61 | * Array of property to format mappings. Used for (de)serialization 62 | * 63 | * @return array 64 | */ 65 | public static function openAPIFormats(): array 66 | { 67 | return self::$openAPIFormats; 68 | } 69 | 70 | /** 71 | * Array of attributes where the key is the local name, 72 | * and the value is the original name 73 | * 74 | * @var string[] 75 | */ 76 | protected static $attributeMap = [ 77 | 'events' => 'events', 78 | 'user' => 'user' 79 | ]; 80 | 81 | /** 82 | * Array of attributes to setter functions (for deserialization of responses) 83 | * 84 | * @var string[] 85 | */ 86 | protected static array $setters = [ 87 | 'events' => 'setEvents', 88 | 'user' => 'setUser' 89 | ]; 90 | 91 | /** 92 | * Array of attributes to getter functions (for serialization of requests) 93 | * 94 | * @var string[] 95 | */ 96 | protected static array $getters = [ 97 | 'events' => 'getEvents', 98 | 'user' => 'getUser' 99 | ]; 100 | 101 | /** 102 | * Array of attributes where the key is the local name, 103 | * and the value is the original name 104 | * 105 | * @return array 106 | */ 107 | public static function attributeMap(): array 108 | { 109 | return self::$attributeMap; 110 | } 111 | 112 | /** 113 | * Array of attributes to setter functions (for deserialization of responses) 114 | * 115 | * @return array 116 | */ 117 | public static function setters(): array 118 | { 119 | return self::$setters; 120 | } 121 | 122 | /** 123 | * Array of attributes to getter functions (for serialization of requests) 124 | * 125 | * @return array 126 | */ 127 | public static function getters(): array 128 | { 129 | return self::$getters; 130 | } 131 | 132 | /** 133 | * The original name of the model. 134 | * 135 | * @return string 136 | */ 137 | public function getModelName(): string 138 | { 139 | return self::$openAPIModelName; 140 | } 141 | 142 | 143 | /** 144 | * Associative array for storing property values 145 | * 146 | * @var mixed[] 147 | */ 148 | protected array $container = []; 149 | 150 | /** 151 | * Constructor 152 | * 153 | * @param mixed[]|null $data Associated array of property values 154 | * initializing the model 155 | */ 156 | public function __construct(?array $data = null) 157 | { 158 | $this->container['events'] = $data['events'] ?? null; 159 | $this->container['user'] = $data['user'] ?? null; 160 | } 161 | 162 | /** 163 | * Show all the invalid properties with reasons. 164 | * 165 | * @return array invalid properties with reasons 166 | */ 167 | public function listInvalidProperties(): array 168 | { 169 | return []; 170 | } 171 | 172 | /** 173 | * Validate all the properties in the model 174 | * return true if all passed 175 | * 176 | * @return bool True if all properties are valid 177 | */ 178 | public function valid(): bool 179 | { 180 | return true; 181 | } 182 | 183 | 184 | /** 185 | * Gets events 186 | * 187 | * @return \DevCycle\Model\DevCycleEvent[]|null 188 | */ 189 | public function getEvents(): ?array 190 | { 191 | return $this->container['events']; 192 | } 193 | 194 | /** 195 | * Sets events 196 | * 197 | * @param \DevCycle\Model\DevCycleEvent[]|null $events events 198 | * 199 | * @return self 200 | */ 201 | public function setEvents(?array $events): self 202 | { 203 | $this->container['events'] = $events; 204 | 205 | return $this; 206 | } 207 | 208 | /** 209 | * Gets user 210 | * 211 | * @return \DevCycle\Model\DevCycleUser|null 212 | */ 213 | public function getUser() 214 | { 215 | return $this->container['user']; 216 | } 217 | 218 | /** 219 | * Sets user 220 | * 221 | * @param \DevCycle\Model\DevCycleUser|null $user user 222 | * 223 | * @return self 224 | */ 225 | public function setUser($user) 226 | { 227 | $this->container['user'] = $user; 228 | 229 | return $this; 230 | } 231 | /** 232 | * Returns true if offset exists. False otherwise. 233 | * 234 | * @param integer $offset Offset 235 | * 236 | * @return boolean 237 | */ 238 | public function offsetExists($offset):bool 239 | { 240 | return isset($this->container[$offset]); 241 | } 242 | 243 | /** 244 | * Gets offset. 245 | * 246 | * @param integer $offset Offset 247 | * 248 | * @return mixed|null 249 | */ 250 | public function offsetGet($offset):mixed 251 | { 252 | return $this->container[$offset] ?? null; 253 | } 254 | 255 | /** 256 | * Sets value based on offset. 257 | * 258 | * @param int|null $offset Offset 259 | * @param mixed $value Value to be set 260 | * 261 | * @return void 262 | */ 263 | public function offsetSet($offset, $value):void 264 | { 265 | if (is_null($offset)) { 266 | $this->container[] = $value; 267 | } else { 268 | $this->container[$offset] = $value; 269 | } 270 | } 271 | 272 | /** 273 | * Unsets offset. 274 | * 275 | * @param integer $offset Offset 276 | * 277 | * @return void 278 | */ 279 | public function offsetUnset($offset):void 280 | { 281 | unset($this->container[$offset]); 282 | } 283 | 284 | /** 285 | * Serializes the object to a value that can be serialized natively by json_encode(). 286 | * @link https://www.php.net/manual/en/jsonserializable.jsonserialize.php 287 | * 288 | * @return mixed Returns data which can be serialized by json_encode(), which is a value 289 | * of any type other than a resource. 290 | */ 291 | public function jsonSerialize():mixed 292 | { 293 | return ObjectSerializer::sanitizeForSerialization($this); 294 | } 295 | 296 | /** 297 | * Gets the string presentation of the object 298 | * 299 | * @return string 300 | */ 301 | public function __toString() 302 | { 303 | return json_encode( 304 | ObjectSerializer::sanitizeForSerialization($this), 305 | JSON_PRETTY_PRINT 306 | ); 307 | } 308 | 309 | /** 310 | * Gets a header-safe presentation of the object 311 | * 312 | * @return string 313 | */ 314 | public function toHeaderValue() 315 | { 316 | return json_encode(ObjectSerializer::sanitizeForSerialization($this)); 317 | } 318 | } 319 | 320 | 321 | -------------------------------------------------------------------------------- /lib/Model/ErrorResponse.php: -------------------------------------------------------------------------------- 1 | 19 | * @template TKey int|null 20 | * @template TValue mixed|null 21 | */ 22 | class ErrorResponse implements ModelInterface, ArrayAccess, \JsonSerializable 23 | { 24 | public const DISCRIMINATOR = null; 25 | 26 | /** 27 | * The original name of the model. 28 | * 29 | * @var string 30 | */ 31 | protected static string $openAPIModelName = 'ErrorResponse'; 32 | 33 | /** 34 | * Array of property to type mappings. Used for (de)serialization 35 | * 36 | * @var string[] 37 | */ 38 | protected static array $openAPITypes = [ 39 | 'message' => 'string', 40 | 'data' => 'object' 41 | ]; 42 | 43 | /** 44 | * Array of property to format mappings. Used for (de)serialization 45 | * 46 | * @var string[] 47 | * @phpstan-var array 48 | * @psalm-var array 49 | */ 50 | protected static array $openAPIFormats = [ 51 | 'message' => null, 52 | 'data' => null 53 | ]; 54 | 55 | /** 56 | * Array of property to type mappings. Used for (de)serialization 57 | * 58 | * @return array 59 | */ 60 | public static function openAPITypes(): array 61 | { 62 | return self::$openAPITypes; 63 | } 64 | 65 | /** 66 | * Array of property to format mappings. Used for (de)serialization 67 | * 68 | * @return array 69 | */ 70 | public static function openAPIFormats(): array 71 | { 72 | return self::$openAPIFormats; 73 | } 74 | 75 | /** 76 | * Array of attributes where the key is the local name, 77 | * and the value is the original name 78 | * 79 | * @var string[] 80 | */ 81 | protected static array $attributeMap = [ 82 | 'message' => 'message', 83 | 'data' => 'data' 84 | ]; 85 | 86 | /** 87 | * Array of attributes to setter functions (for deserialization of responses) 88 | * 89 | * @var string[] 90 | */ 91 | protected static array $setters = [ 92 | 'message' => 'setMessage', 93 | 'data' => 'setData' 94 | ]; 95 | 96 | /** 97 | * Array of attributes to getter functions (for serialization of requests) 98 | * 99 | * @var string[] 100 | */ 101 | protected static array $getters = [ 102 | 'message' => 'getMessage', 103 | 'data' => 'getData' 104 | ]; 105 | 106 | /** 107 | * Array of attributes where the key is the local name, 108 | * and the value is the original name 109 | * 110 | * @return array 111 | */ 112 | public static function attributeMap(): array 113 | { 114 | return self::$attributeMap; 115 | } 116 | 117 | /** 118 | * Array of attributes to setter functions (for deserialization of responses) 119 | * 120 | * @return array 121 | */ 122 | public static function setters(): array 123 | { 124 | return self::$setters; 125 | } 126 | 127 | /** 128 | * Array of attributes to getter functions (for serialization of requests) 129 | * 130 | * @return array 131 | */ 132 | public static function getters(): array 133 | { 134 | return self::$getters; 135 | } 136 | 137 | /** 138 | * The original name of the model. 139 | * 140 | * @return string 141 | */ 142 | public function getModelName(): string 143 | { 144 | return self::$openAPIModelName; 145 | } 146 | 147 | 148 | /** 149 | * Associative array for storing property values 150 | * 151 | * @var mixed[] 152 | */ 153 | protected array $container = []; 154 | 155 | /** 156 | * Constructor 157 | * 158 | * @param mixed[]|null $data Associated array of property values 159 | * initializing the model 160 | */ 161 | public function __construct(?array $data = null) 162 | { 163 | $this->container['message'] = $data['message'] ?? null; 164 | $this->container['data'] = $data['data'] ?? null; 165 | } 166 | 167 | /** 168 | * Show all the invalid properties with reasons. 169 | * 170 | * @return array invalid properties with reasons 171 | */ 172 | public function listInvalidProperties(): array 173 | { 174 | $invalidProperties = []; 175 | 176 | if ($this->container['message'] === null) { 177 | $invalidProperties[] = "'message' can't be null"; 178 | } 179 | return $invalidProperties; 180 | } 181 | 182 | /** 183 | * Validate all the properties in the model 184 | * return true if all passed 185 | * 186 | * @return bool True if all properties are valid 187 | */ 188 | public function valid(): bool 189 | { 190 | return count($this->listInvalidProperties()) === 0; 191 | } 192 | 193 | 194 | /** 195 | * Gets message 196 | * 197 | * @return string 198 | */ 199 | public function getMessage(): string 200 | { 201 | return $this->container['message']; 202 | } 203 | 204 | /** 205 | * Sets message 206 | * 207 | * @param string $message Error message 208 | * 209 | * @return self 210 | */ 211 | public function setMessage(string $message): static 212 | { 213 | $this->container['message'] = $message; 214 | 215 | return $this; 216 | } 217 | 218 | /** 219 | * Gets data 220 | * 221 | * @return object|null 222 | */ 223 | public function getData(): ?object 224 | { 225 | return $this->container['data']; 226 | } 227 | 228 | /** 229 | * Sets data 230 | * 231 | * @param object|null $data Additional error information detailing the error reasoning 232 | * 233 | * @return self 234 | */ 235 | public function setData(?object $data): static 236 | { 237 | $this->container['data'] = $data; 238 | 239 | return $this; 240 | } 241 | /** 242 | * Returns true if offset exists. False otherwise. 243 | * 244 | * @param integer $offset Offset 245 | * 246 | * @return boolean 247 | */ 248 | public function offsetExists($offset):bool 249 | { 250 | return isset($this->container[$offset]); 251 | } 252 | 253 | /** 254 | * Gets offset. 255 | * 256 | * @param integer $offset Offset 257 | * 258 | * @return mixed|null 259 | */ 260 | public function offsetGet($offset):mixed 261 | { 262 | return $this->container[$offset] ?? null; 263 | } 264 | 265 | /** 266 | * Sets value based on offset. 267 | * 268 | * @param int|null $offset Offset 269 | * @param mixed $value Value to be set 270 | * 271 | * @return void 272 | */ 273 | public function offsetSet($offset, mixed $value):void 274 | { 275 | if (is_null($offset)) { 276 | $this->container[] = $value; 277 | } else { 278 | $this->container[$offset] = $value; 279 | } 280 | } 281 | 282 | /** 283 | * Unsets offset. 284 | * 285 | * @param integer $offset Offset 286 | * 287 | * @return void 288 | */ 289 | public function offsetUnset($offset):void 290 | { 291 | unset($this->container[$offset]); 292 | } 293 | 294 | /** 295 | * Serializes the object to a value that can be serialized natively by json_encode(). 296 | * @link https://www.php.net/manual/en/jsonserializable.jsonserialize.php 297 | * 298 | * @return mixed Returns data which can be serialized by json_encode(), which is a value 299 | * of any type other than a resource. 300 | */ 301 | public function jsonSerialize():mixed 302 | { 303 | return ObjectSerializer::sanitizeForSerialization($this); 304 | } 305 | 306 | /** 307 | * Gets the string presentation of the object 308 | * 309 | * @return string 310 | */ 311 | public function __toString() 312 | { 313 | return json_encode( 314 | ObjectSerializer::sanitizeForSerialization($this), 315 | JSON_PRETTY_PRINT 316 | ); 317 | } 318 | 319 | /** 320 | * Gets a header-safe presentation of the object 321 | * 322 | * @return string 323 | */ 324 | public function toHeaderValue() 325 | { 326 | return json_encode(ObjectSerializer::sanitizeForSerialization($this)); 327 | } 328 | } 329 | 330 | 331 | -------------------------------------------------------------------------------- /lib/Model/Feature.php: -------------------------------------------------------------------------------- 1 | 15 | * @template TKey int|null 16 | * @template TValue mixed|null 17 | */ 18 | class Feature implements ModelInterface, ArrayAccess, \JsonSerializable 19 | { 20 | 21 | /** 22 | * The original name of the model. 23 | * 24 | * @var string 25 | */ 26 | protected static string $openAPIModelName = 'Feature'; 27 | 28 | /** 29 | * Array of property to type mappings. Used for (de)serialization 30 | * 31 | * @var string[] 32 | */ 33 | protected static array $openAPITypes = [ 34 | '_id' => 'string', 35 | 'key' => 'string', 36 | 'type' => 'string', 37 | '_variation' => 'string', 38 | 'variationKey' => 'string', 39 | 'variationName' => 'string', 40 | 'eval_reason' => 'string' 41 | ]; 42 | 43 | /** 44 | * Array of property to format mappings. Used for (de)serialization 45 | * 46 | * @var string[] 47 | * @phpstan-var array 48 | * @psalm-var array 49 | */ 50 | protected static array $openAPIFormats = [ 51 | '_id' => null, 52 | 'key' => null, 53 | 'type' => null, 54 | '_variation' => null, 55 | 'variationKey' => null, 56 | 'variationName' => null, 57 | 'eval_reason' => null 58 | ]; 59 | 60 | /** 61 | * Array of property to type mappings. Used for (de)serialization 62 | * 63 | * @return array 64 | */ 65 | public static function openAPITypes(): array 66 | { 67 | return self::$openAPITypes; 68 | } 69 | 70 | /** 71 | * Array of property to format mappings. Used for (de)serialization 72 | * 73 | * @return array 74 | */ 75 | public static function openAPIFormats(): array 76 | { 77 | return self::$openAPIFormats; 78 | } 79 | 80 | /** 81 | * Array of attributes where the key is the local name, 82 | * and the value is the original name 83 | * 84 | * @var string[] 85 | */ 86 | protected static array $attributeMap = [ 87 | '_id' => '_id', 88 | 'key' => 'key', 89 | 'type' => 'type', 90 | '_variation' => '_variation', 91 | 'variationKey' => 'variationKey', 92 | 'variationName' => 'variationName', 93 | 'eval_reason' => 'evalReason' 94 | ]; 95 | 96 | /** 97 | * Array of attributes to setter functions (for deserialization of responses) 98 | * 99 | * @var string[] 100 | */ 101 | protected static array $setters = [ 102 | '_id' => 'setId', 103 | 'key' => 'setKey', 104 | 'type' => 'setType', 105 | '_variation' => 'setVariation', 106 | 'variationKey' => 'setVariationKey', 107 | 'variationName' => 'setVariationName', 108 | 'eval_reason' => 'setEvalReason' 109 | ]; 110 | 111 | /** 112 | * Array of attributes to getter functions (for serialization of requests) 113 | * 114 | * @var string[] 115 | */ 116 | protected static array $getters = [ 117 | '_id' => 'getId', 118 | 'key' => 'getKey', 119 | 'type' => 'getType', 120 | '_variation' => 'getVariation', 121 | 'variationKey' => 'getVariationKey', 122 | 'variationName' => 'getVariationName', 123 | 'eval_reason' => 'getEvalReason' 124 | ]; 125 | 126 | /** 127 | * Array of attributes where the key is the local name, 128 | * and the value is the original name 129 | * 130 | * @return array 131 | */ 132 | public static function attributeMap(): array 133 | { 134 | return self::$attributeMap; 135 | } 136 | 137 | /** 138 | * Array of attributes to setter functions (for deserialization of responses) 139 | * 140 | * @return array 141 | */ 142 | public static function setters(): array 143 | { 144 | return self::$setters; 145 | } 146 | 147 | /** 148 | * Array of attributes to getter functions (for serialization of requests) 149 | * 150 | * @return array 151 | */ 152 | public static function getters(): array 153 | { 154 | return self::$getters; 155 | } 156 | 157 | /** 158 | * The original name of the model. 159 | * 160 | * @return string 161 | */ 162 | public function getModelName(): string 163 | { 164 | return self::$openAPIModelName; 165 | } 166 | 167 | const TYPE_RELEASE = 'release'; 168 | const TYPE_EXPERIMENT = 'experiment'; 169 | const TYPE_PERMISSION = 'permission'; 170 | const TYPE_OPS = 'ops'; 171 | 172 | /** 173 | * Gets allowable values of the enum 174 | * 175 | * @return string[] 176 | */ 177 | public function getTypeAllowableValues(): array 178 | { 179 | return [ 180 | self::TYPE_RELEASE, 181 | self::TYPE_EXPERIMENT, 182 | self::TYPE_PERMISSION, 183 | self::TYPE_OPS, 184 | ]; 185 | } 186 | 187 | /** 188 | * Associative array for storing property values 189 | * 190 | * @var array 191 | */ 192 | protected array $container = []; 193 | 194 | /** 195 | * Constructor 196 | * 197 | * @param array[]|null $data Associated array of property values 198 | * initializing the model 199 | */ 200 | public function __construct(?array $data = null) 201 | { 202 | $this->container['_id'] = $data['_id'] ?? null; 203 | $this->container['key'] = $data['key'] ?? null; 204 | $this->container['type'] = $data['type'] ?? null; 205 | $this->container['_variation'] = $data['_variation'] ?? null; 206 | $this->container['variationKey'] = $data['variationKey'] ?? null; 207 | $this->container['variationName'] = $data['variationName'] ?? null; 208 | $this->container['eval_reason'] = $data['eval_reason'] ?? null; 209 | } 210 | 211 | /** 212 | * Show all the invalid properties with reasons. 213 | * 214 | * @return array invalid properties with reasons 215 | */ 216 | public function listInvalidProperties(): array 217 | { 218 | $invalidProperties = []; 219 | 220 | if ($this->container['_id'] === null) { 221 | $invalidProperties[] = "'_id' can't be null"; 222 | } 223 | if ($this->container['key'] === null) { 224 | $invalidProperties[] = "'key' can't be null"; 225 | } 226 | if ($this->container['type'] === null) { 227 | $invalidProperties[] = "'type' can't be null"; 228 | } 229 | $allowedValues = $this->getTypeAllowableValues(); 230 | if (!is_null($this->container['type']) && !in_array($this->container['type'], $allowedValues, true)) { 231 | $invalidProperties[] = sprintf( 232 | "invalid value '%s' for 'type', must be one of '%s'", 233 | $this->container['type'], 234 | implode("', '", $allowedValues) 235 | ); 236 | } 237 | 238 | if ($this->container['_variation'] === null) { 239 | $invalidProperties[] = "'_variation' can't be null"; 240 | } 241 | if ($this->container['variationKey'] === null) { 242 | $invalidProperties[] = "'variationKey' can't be null"; 243 | } 244 | if ($this->container['variationName'] === null) { 245 | $invalidProperties[] = "'variationName' can't be null"; 246 | } 247 | return $invalidProperties; 248 | } 249 | 250 | /** 251 | * Validate all the properties in the model 252 | * return true if all passed 253 | * 254 | * @return bool True if all properties are valid 255 | */ 256 | public function valid(): bool 257 | { 258 | return count($this->listInvalidProperties()) === 0; 259 | } 260 | 261 | 262 | /** 263 | * Gets _id 264 | * 265 | * @return string 266 | */ 267 | public function getId(): string 268 | { 269 | return $this->container['_id']; 270 | } 271 | 272 | /** 273 | * Sets _id 274 | * 275 | * @param string $_id unique database id 276 | * 277 | * @return self 278 | */ 279 | public function setId($_id): self 280 | { 281 | $this->container['_id'] = $_id; 282 | 283 | return $this; 284 | } 285 | 286 | /** 287 | * Gets key 288 | * 289 | * @return string 290 | */ 291 | public function getKey(): string 292 | { 293 | return $this->container['key']; 294 | } 295 | 296 | /** 297 | * Sets key 298 | * 299 | * @param string $key Unique key by Project, can be used in the SDK / API to reference by 'key' rather than _id. 300 | * 301 | * @return self 302 | */ 303 | public function setKey($key): self 304 | { 305 | $this->container['key'] = $key; 306 | 307 | return $this; 308 | } 309 | 310 | /** 311 | * Gets type 312 | * 313 | * @return string 314 | */ 315 | public function getType(): string 316 | { 317 | return $this->container['type']; 318 | } 319 | 320 | /** 321 | * Sets type 322 | * 323 | * @param string $type Feature type 324 | * 325 | * @return self 326 | */ 327 | public function setType($type): self 328 | { 329 | $allowedValues = $this->getTypeAllowableValues(); 330 | if (!in_array($type, $allowedValues, true)) { 331 | throw new \InvalidArgumentException( 332 | sprintf( 333 | "Invalid value '%s' for 'type', must be one of '%s'", 334 | $type, 335 | implode("', '", $allowedValues) 336 | ) 337 | ); 338 | } 339 | $this->container['type'] = $type; 340 | 341 | return $this; 342 | } 343 | 344 | /** 345 | * Gets _variation 346 | * 347 | * @return string 348 | */ 349 | public function getVariation(): string 350 | { 351 | return $this->container['_variation']; 352 | } 353 | 354 | /** 355 | * Sets _variation 356 | * 357 | * @param string $_variation Bucketed feature variation 358 | * 359 | * @return self 360 | */ 361 | public function setVariation($_variation): self 362 | { 363 | $this->container['_variation'] = $_variation; 364 | 365 | return $this; 366 | } 367 | 368 | /** 369 | * Gets variationKey 370 | * 371 | * @return string 372 | */ 373 | public function getVariationKey(): string 374 | { 375 | return $this->container['variationKey']; 376 | } 377 | 378 | /** 379 | * Sets variationKey 380 | * 381 | * @param string $variationKey Bucketed feature variation key 382 | * 383 | * @return self 384 | */ 385 | public function setVariationKey(string $variationKey): self 386 | { 387 | $this->container['variationKey'] = $variationKey; 388 | 389 | return $this; 390 | } 391 | 392 | /** 393 | * Gets variationName 394 | * 395 | * @return string 396 | */ 397 | public function getVariationName(): string 398 | { 399 | return $this->container['variationName']; 400 | } 401 | 402 | /** 403 | * Sets variationName 404 | * 405 | * @param string $variationName Bucketed feature variation name 406 | * 407 | * @return self 408 | */ 409 | public function setVariationName(string $variationName): self 410 | { 411 | $this->container['variationName'] = $variationName; 412 | 413 | return $this; 414 | } 415 | 416 | /** 417 | * Gets eval_reason 418 | * 419 | * @return string|null 420 | */ 421 | public function getEvalReason(): ?string 422 | { 423 | return $this->container['eval_reason']; 424 | } 425 | 426 | /** 427 | * Sets eval_reason 428 | * 429 | * @param string|null $eval_reason Evaluation reasoning 430 | * 431 | * @return self 432 | */ 433 | public function setEvalReason(?string $eval_reason): self 434 | { 435 | $this->container['eval_reason'] = $eval_reason; 436 | 437 | return $this; 438 | } 439 | 440 | /** 441 | * Returns true if offset exists. False otherwise. 442 | * 443 | * @param integer $offset Offset 444 | * 445 | * @return boolean 446 | */ 447 | public function offsetExists($offset): bool 448 | { 449 | return isset($this->container[$offset]); 450 | } 451 | 452 | /** 453 | * Gets offset. 454 | * 455 | * @param integer $offset Offset 456 | * 457 | * @return mixed 458 | */ 459 | public function offsetGet($offset): mixed 460 | { 461 | return $this->container[$offset] ?? null; 462 | } 463 | 464 | /** 465 | * Sets value based on offset. 466 | * 467 | * @param int|null $offset Offset 468 | * @param mixed $value Value to be set 469 | * 470 | * @return void 471 | */ 472 | public function offsetSet($offset, mixed $value): void 473 | { 474 | if (is_null($offset)) { 475 | $this->container[] = $value; 476 | } else { 477 | $this->container[$offset] = $value; 478 | } 479 | } 480 | 481 | /** 482 | * Unsets offset. 483 | * 484 | * @param integer $offset Offset 485 | * 486 | * @return void 487 | */ 488 | public function offsetUnset($offset): void 489 | { 490 | unset($this->container[$offset]); 491 | } 492 | 493 | /** 494 | * Serializes the object to a value that can be serialized natively by json_encode(). 495 | * @link https://www.php.net/manual/en/jsonserializable.jsonserialize.php 496 | * 497 | * @return mixed Returns data which can be serialized by json_encode(), which is a value 498 | * of any type other than a resource. 499 | */ 500 | public function jsonSerialize(): mixed 501 | { 502 | return ObjectSerializer::sanitizeForSerialization($this); 503 | } 504 | 505 | /** 506 | * Gets the string presentation of the object 507 | * 508 | * @return string 509 | */ 510 | public function __toString() 511 | { 512 | return json_encode( 513 | ObjectSerializer::sanitizeForSerialization($this), 514 | JSON_PRETTY_PRINT 515 | ); 516 | } 517 | 518 | /** 519 | * Gets a header-safe presentation of the object 520 | * 521 | * @return string 522 | */ 523 | public function toHeaderValue(): string 524 | { 525 | return json_encode(ObjectSerializer::sanitizeForSerialization($this)); 526 | } 527 | } 528 | -------------------------------------------------------------------------------- /lib/Model/InlineResponse201.php: -------------------------------------------------------------------------------- 1 | 17 | * @template TKey int|null 18 | * @template TValue mixed|null 19 | */ 20 | class InlineResponse201 implements ModelInterface, ArrayAccess, \JsonSerializable 21 | { 22 | 23 | /** 24 | * The original name of the model. 25 | * 26 | * @var string 27 | */ 28 | protected static string $openAPIModelName = 'inline_response_201'; 29 | 30 | /** 31 | * Array of property to type mappings. Used for (de)serialization 32 | * 33 | * @var string[] 34 | */ 35 | protected static array $openAPITypes = [ 36 | 'message' => 'string' 37 | ]; 38 | 39 | /** 40 | * Array of property to format mappings. Used for (de)serialization 41 | * 42 | * @var string[] 43 | * @phpstan-var array 44 | * @psalm-var array 45 | */ 46 | protected static array $openAPIFormats = [ 47 | 'message' => null 48 | ]; 49 | 50 | /** 51 | * Array of property to type mappings. Used for (de)serialization 52 | * 53 | * @return array 54 | */ 55 | public static function openAPITypes(): array 56 | { 57 | return self::$openAPITypes; 58 | } 59 | 60 | /** 61 | * Array of property to format mappings. Used for (de)serialization 62 | * 63 | * @return array 64 | */ 65 | public static function openAPIFormats(): array 66 | { 67 | return self::$openAPIFormats; 68 | } 69 | 70 | /** 71 | * Array of attributes where the key is the local name, 72 | * and the value is the original name 73 | * 74 | * @var string[] 75 | */ 76 | protected static array $attributeMap = [ 77 | 'message' => 'message' 78 | ]; 79 | 80 | /** 81 | * Array of attributes to setter functions (for deserialization of responses) 82 | * 83 | * @var string[] 84 | */ 85 | protected static array $setters = [ 86 | 'message' => 'setMessage' 87 | ]; 88 | 89 | /** 90 | * Array of attributes to getter functions (for serialization of requests) 91 | * 92 | * @var string[] 93 | */ 94 | protected static array $getters = [ 95 | 'message' => 'getMessage' 96 | ]; 97 | 98 | /** 99 | * Array of attributes where the key is the local name, 100 | * and the value is the original name 101 | * 102 | * @return array 103 | */ 104 | public static function attributeMap(): array 105 | { 106 | return self::$attributeMap; 107 | } 108 | 109 | /** 110 | * Array of attributes to setter functions (for deserialization of responses) 111 | * 112 | * @return array 113 | */ 114 | public static function setters(): array 115 | { 116 | return self::$setters; 117 | } 118 | 119 | /** 120 | * Array of attributes to getter functions (for serialization of requests) 121 | * 122 | * @return array 123 | */ 124 | public static function getters(): array 125 | { 126 | return self::$getters; 127 | } 128 | 129 | /** 130 | * The original name of the model. 131 | * 132 | * @return string 133 | */ 134 | public function getModelName(): string 135 | { 136 | return self::$openAPIModelName; 137 | } 138 | 139 | 140 | /** 141 | * Associative array for storing property values 142 | * 143 | * @var mixed[] 144 | */ 145 | protected array $container = []; 146 | 147 | /** 148 | * Constructor 149 | * 150 | * @param mixed[]|null $data Associated array of property values 151 | * initializing the model 152 | */ 153 | public function __construct(?array $data = null) 154 | { 155 | $this->container['message'] = $data['message'] ?? null; 156 | } 157 | 158 | /** 159 | * Show all the invalid properties with reasons. 160 | * 161 | * @return array invalid properties with reasons 162 | */ 163 | public function listInvalidProperties(): array 164 | { 165 | return []; 166 | } 167 | 168 | /** 169 | * Validate all the properties in the model 170 | * return true if all passed 171 | * 172 | * @return bool True if all properties are valid 173 | */ 174 | public function valid(): bool 175 | { 176 | return count($this->listInvalidProperties()) === 0; 177 | } 178 | 179 | 180 | /** 181 | * Gets message 182 | * 183 | * @return string|null 184 | */ 185 | public function getMessage(): ?string 186 | { 187 | return $this->container['message']; 188 | } 189 | 190 | /** 191 | * Sets message 192 | * 193 | * @param string|null $message message 194 | * 195 | * @return self 196 | */ 197 | public function setMessage(?string $message): static 198 | { 199 | $this->container['message'] = $message; 200 | 201 | return $this; 202 | } 203 | 204 | /** 205 | * Returns true if offset exists. False otherwise. 206 | * 207 | * @param integer $offset Offset 208 | * 209 | * @return boolean 210 | */ 211 | public function offsetExists($offset): bool 212 | { 213 | return isset($this->container[$offset]); 214 | } 215 | 216 | /** 217 | * Gets offset. 218 | * 219 | * @param integer $offset Offset 220 | * 221 | * @return mixed|null 222 | */ 223 | public function offsetGet($offset): mixed 224 | { 225 | return $this->container[$offset] ?? null; 226 | } 227 | 228 | /** 229 | * Sets value based on offset. 230 | * 231 | * @param int|null $offset Offset 232 | * @param mixed $value Value to be set 233 | * 234 | * @return void 235 | */ 236 | public function offsetSet($offset, mixed $value): void 237 | { 238 | if (is_null($offset)) { 239 | $this->container[] = $value; 240 | } else { 241 | $this->container[$offset] = $value; 242 | } 243 | } 244 | 245 | /** 246 | * Unsets offset. 247 | * 248 | * @param integer $offset Offset 249 | * 250 | * @return void 251 | */ 252 | public function offsetUnset($offset): void 253 | { 254 | unset($this->container[$offset]); 255 | } 256 | 257 | /** 258 | * Serializes the object to a value that can be serialized natively by json_encode(). 259 | * @link https://www.php.net/manual/en/jsonserializable.jsonserialize.php 260 | * 261 | * @return mixed Returns data which can be serialized by json_encode(), which is a value 262 | * of any type other than a resource. 263 | */ 264 | public function jsonSerialize(): mixed 265 | { 266 | return ObjectSerializer::sanitizeForSerialization($this); 267 | } 268 | 269 | /** 270 | * Gets the string presentation of the object 271 | * 272 | * @return string 273 | */ 274 | public function __toString() 275 | { 276 | return json_encode( 277 | ObjectSerializer::sanitizeForSerialization($this), 278 | JSON_PRETTY_PRINT 279 | ); 280 | } 281 | 282 | /** 283 | * Gets a header-safe presentation of the object 284 | * 285 | * @return string 286 | */ 287 | public function toHeaderValue() 288 | { 289 | return json_encode(ObjectSerializer::sanitizeForSerialization($this)); 290 | } 291 | } 292 | 293 | 294 | -------------------------------------------------------------------------------- /lib/Model/ModelInterface.php: -------------------------------------------------------------------------------- 1 | 22 | * @template TKey int|null 23 | * @template TValue mixed|null 24 | */ 25 | class Variable implements ModelInterface, ArrayAccess, \JsonSerializable 26 | { 27 | 28 | /** 29 | * The original name of the model. 30 | * 31 | * @var string 32 | */ 33 | protected static string $openAPIModelName = 'Variable'; 34 | 35 | /** 36 | * Array of property to type mappings. Used for (de)serialization 37 | * 38 | * @var string[] 39 | */ 40 | protected static array $openAPITypes = [ 41 | '_id' => 'string', 42 | 'key' => 'string', 43 | 'type' => 'string', 44 | 'value' => 'object' 45 | ]; 46 | 47 | /** 48 | * Array of property to format mappings. Used for (de)serialization 49 | * 50 | * @var string[] 51 | * @phpstan-var array 52 | * @psalm-var array 53 | */ 54 | protected static $openAPIFormats = [ 55 | '_id' => null, 56 | 'key' => null, 57 | 'type' => null, 58 | 'value' => null 59 | ]; 60 | 61 | /** 62 | * Array of property to type mappings. Used for (de)serialization 63 | * 64 | * @return array 65 | */ 66 | public static function openAPITypes(): array 67 | { 68 | return self::$openAPITypes; 69 | } 70 | 71 | /** 72 | * Array of property to format mappings. Used for (de)serialization 73 | * 74 | * @return array 75 | */ 76 | public static function openAPIFormats(): array 77 | { 78 | return self::$openAPIFormats; 79 | } 80 | 81 | /** 82 | * Array of attributes where the key is the local name, 83 | * and the value is the original name 84 | * 85 | * @var string[] 86 | */ 87 | protected static $attributeMap = [ 88 | '_id' => '_id', 89 | 'key' => 'key', 90 | 'type' => 'type', 91 | 'value' => 'value', 92 | 'isDefaulted' => 'isDefaulted' 93 | ]; 94 | 95 | /** 96 | * Array of attributes to setter functions (for deserialization of responses) 97 | * 98 | * @var string[] 99 | */ 100 | protected static array $setters = [ 101 | '_id' => 'setId', 102 | 'key' => 'setKey', 103 | 'type' => 'setType', 104 | 'value' => 'setValue', 105 | 'isDefaulted' => 'setIsDefaulted' 106 | ]; 107 | 108 | /** 109 | * Array of attributes to getter functions (for serialization of requests) 110 | * 111 | * @var string[] 112 | */ 113 | protected static array $getters = [ 114 | '_id' => 'getId', 115 | 'key' => 'getKey', 116 | 'type' => 'getType', 117 | 'value' => 'getValue', 118 | 'isDefaulted' => 'getIsDefaulted' 119 | ]; 120 | 121 | /** 122 | * Array of attributes where the key is the local name, 123 | * and the value is the original name 124 | * 125 | * @return array 126 | */ 127 | public static function attributeMap(): array 128 | { 129 | return self::$attributeMap; 130 | } 131 | 132 | /** 133 | * Array of attributes to setter functions (for deserialization of responses) 134 | * 135 | * @return array 136 | */ 137 | public static function setters(): array 138 | { 139 | return self::$setters; 140 | } 141 | 142 | /** 143 | * Array of attributes to getter functions (for serialization of requests) 144 | * 145 | * @return array 146 | */ 147 | public static function getters(): array 148 | { 149 | return self::$getters; 150 | } 151 | 152 | /** 153 | * The original name of the model. 154 | * 155 | * @return string 156 | */ 157 | public function getModelName(): string 158 | { 159 | return self::$openAPIModelName; 160 | } 161 | 162 | const TYPE_STRING = 'String'; 163 | const TYPE_BOOLEAN = 'Boolean'; 164 | const TYPE_NUMBER = 'Number'; 165 | const TYPE_JSON = 'JSON'; 166 | 167 | /** 168 | * Gets allowable values of the enum 169 | * 170 | * @return string[] 171 | */ 172 | public function getTypeAllowableValues(): array 173 | { 174 | return [ 175 | self::TYPE_STRING, 176 | self::TYPE_BOOLEAN, 177 | self::TYPE_NUMBER, 178 | self::TYPE_JSON, 179 | ]; 180 | } 181 | 182 | /** 183 | * Associative array for storing property values 184 | * 185 | * @var mixed[] 186 | */ 187 | protected array $container = []; 188 | 189 | /** 190 | * Constructor 191 | * 192 | * @param mixed[]|null $data Associated array of property values 193 | * initializing the model 194 | */ 195 | public function __construct(?array $data = null) 196 | { 197 | $this->container['_id'] = $data['_id'] ?? null; 198 | $this->container['key'] = $data['key'] ?? null; 199 | $this->container['type'] = $data['type'] ?? null; 200 | $this->container['value'] = $data['value'] ?? null; 201 | $this->container['isDefaulted'] = $data['isDefaulted'] ?? false; 202 | } 203 | 204 | /** 205 | * Show all the invalid properties with reasons. 206 | * 207 | * @return array invalid properties with reasons 208 | */ 209 | public function listInvalidProperties(): array 210 | { 211 | $invalidProperties = []; 212 | 213 | if ($this->container['_id'] === null) { 214 | $invalidProperties[] = "'_id' can't be null"; 215 | } 216 | if ($this->container['key'] === null) { 217 | $invalidProperties[] = "'key' can't be null"; 218 | } 219 | if ($this->container['type'] === null) { 220 | $invalidProperties[] = "'type' can't be null"; 221 | } 222 | $allowedValues = $this->getTypeAllowableValues(); 223 | if (!is_null($this->container['type']) && !in_array($this->container['type'], $allowedValues, true)) { 224 | $invalidProperties[] = sprintf( 225 | "invalid value '%s' for 'type', must be one of '%s'", 226 | $this->container['type'], 227 | implode("', '", $allowedValues) 228 | ); 229 | } 230 | 231 | if ($this->container['value'] === null) { 232 | $invalidProperties[] = "'value' can't be null"; 233 | } 234 | return $invalidProperties; 235 | } 236 | 237 | /** 238 | * Validate all the properties in the model 239 | * return true if all passed 240 | * 241 | * @return bool True if all properties are valid 242 | */ 243 | public function valid(): bool 244 | { 245 | return count($this->listInvalidProperties()) === 0; 246 | } 247 | 248 | 249 | /** 250 | * Gets _id 251 | * 252 | * @return string 253 | */ 254 | public function getId(): ?string 255 | { 256 | return $this->container['_id']; 257 | } 258 | 259 | /** 260 | * Sets _id 261 | * 262 | * @param string|null $_id unique database id 263 | * 264 | * @return self 265 | */ 266 | public function setId(?string $_id): self 267 | { 268 | $this->container['_id'] = $_id; 269 | 270 | return $this; 271 | } 272 | 273 | /** 274 | * Gets key 275 | * 276 | * @return string 277 | */ 278 | public function getKey(): string 279 | { 280 | return $this->container['key']; 281 | } 282 | 283 | /** 284 | * Sets key 285 | * 286 | * @param string $key Unique key by Project, can be used in the SDK / API to reference by 'key' rather than _id. 287 | * 288 | * @return self 289 | */ 290 | public function setKey($key): static 291 | { 292 | $this->container['key'] = $key; 293 | 294 | return $this; 295 | } 296 | 297 | /** 298 | * Gets type 299 | * 300 | * @return string 301 | */ 302 | public function getType(): string 303 | { 304 | return $this->container['type']; 305 | } 306 | 307 | /** 308 | * Sets type 309 | * 310 | * @param string $type Variable type 311 | * 312 | * @return self 313 | */ 314 | public function setType(string $type): static 315 | { 316 | $allowedValues = $this->getTypeAllowableValues(); 317 | if (!in_array($type, $allowedValues, true)) { 318 | throw new \InvalidArgumentException( 319 | sprintf( 320 | "Invalid value '%s' for 'type', must be one of '%s'", 321 | $type, 322 | implode("', '", $allowedValues) 323 | ) 324 | ); 325 | } 326 | $this->container['type'] = $type; 327 | 328 | return $this; 329 | } 330 | 331 | /** 332 | * Gets value 333 | * 334 | * @return mixed object 335 | */ 336 | public function getValue(): mixed 337 | { 338 | return $this->container['value']; 339 | } 340 | 341 | /** 342 | * Sets value 343 | * 344 | * @param object $value Variable value can be a string, number, boolean, or JSON 345 | * 346 | * @return self 347 | */ 348 | public function setValue(mixed $value): self 349 | { 350 | $this->container['value'] = $value; 351 | 352 | return $this; 353 | } 354 | 355 | /** 356 | * Gets isDefaulted 357 | * 358 | * @return bool 359 | */ 360 | public function isDefaulted(): bool 361 | { 362 | return $this->container['isDefaulted']; 363 | } 364 | 365 | /** 366 | * Sets isDefaulted 367 | * 368 | * @param bool $isDefaulted Variable set to true if the Variable could not be fetched 369 | * 370 | * @return self 371 | */ 372 | public function setIsDefaulted(bool $isDefaulted): static 373 | { 374 | $this->container['isDefaulted'] = $isDefaulted; 375 | 376 | return $this; 377 | } 378 | 379 | /** 380 | * Returns true if offset exists. False otherwise. 381 | * 382 | * @param integer $offset Offset 383 | * 384 | * @return boolean 385 | */ 386 | public function offsetExists($offset):bool 387 | { 388 | return isset($this->container[$offset]); 389 | } 390 | 391 | /** 392 | * Gets offset. 393 | * 394 | * @param integer $offset Offset 395 | * 396 | * @return mixed|null 397 | */ 398 | public function offsetGet($offset):mixed 399 | { 400 | return $this->container[$offset] ?? null; 401 | } 402 | 403 | /** 404 | * Sets value based on offset. 405 | * 406 | * @param int|null $offset Offset 407 | * @param mixed $value Value to be set 408 | * 409 | * @return void 410 | */ 411 | public function offsetSet($offset, mixed $value):void 412 | { 413 | if (is_null($offset)) { 414 | $this->container[] = $value; 415 | } else { 416 | $this->container[$offset] = $value; 417 | } 418 | } 419 | 420 | /** 421 | * Unsets offset. 422 | * 423 | * @param integer $offset Offset 424 | * 425 | * @return void 426 | */ 427 | public function offsetUnset($offset):void 428 | { 429 | unset($this->container[$offset]); 430 | } 431 | 432 | /** 433 | * Serializes the object to a value that can be serialized natively by json_encode(). 434 | * @link https://www.php.net/manual/en/jsonserializable.jsonserialize.php 435 | * 436 | * @return mixed Returns data which can be serialized by json_encode(), which is a value 437 | * of any type other than a resource. 438 | */ 439 | public function jsonSerialize():mixed 440 | { 441 | return ObjectSerializer::sanitizeForSerialization($this); 442 | } 443 | 444 | /** 445 | * Gets the string presentation of the object 446 | * 447 | * @return string 448 | */ 449 | public function __toString() 450 | { 451 | return json_encode( 452 | ObjectSerializer::sanitizeForSerialization($this), 453 | JSON_PRETTY_PRINT 454 | ); 455 | } 456 | 457 | /** 458 | * Gets a header-safe presentation of the object 459 | * 460 | * @return string 461 | */ 462 | public function toHeaderValue() 463 | { 464 | return json_encode(ObjectSerializer::sanitizeForSerialization($this)); 465 | } 466 | 467 | public function asResolutionDetails(): ResolutionDetails 468 | { 469 | $resolution = new ResolutionDetails(); 470 | $resolution->setValue($this->getValue()); 471 | $resolution->setReason(Reason::TARGETING_MATCH); 472 | if ($this->isDefaulted()) { 473 | $resolution->setError(new ResolutionError(ErrorCode::FLAG_NOT_FOUND(), "Defaulted")); 474 | $resolution->setReason(Reason::DEFAULT); 475 | } 476 | return $resolution; 477 | } 478 | } 479 | -------------------------------------------------------------------------------- /lib/ObjectSerializer.php: -------------------------------------------------------------------------------- 1 | format('Y-m-d') : $data->format(self::$dateTimeFormat); 29 | } 30 | 31 | if (is_array($data)) { 32 | foreach ($data as $property => $value) { 33 | $data[$property] = self::sanitizeForSerialization($value); 34 | } 35 | return $data; 36 | } 37 | 38 | if (is_object($data)) { 39 | $values = []; 40 | if ($data instanceof ModelInterface) { 41 | $formats = $data::openAPIFormats(); 42 | foreach ($data::openAPITypes() as $property => $openAPIType) { 43 | $getter = $data::getters()[$property]; 44 | $value = $data->$getter(); 45 | if ($value !== null && !in_array($openAPIType, ['\DateTime', '\SplFileObject', 'array', 'bool', 'boolean', 'byte', 'double', 'float', 'int', 'integer', 'mixed', 'number', 'object', 'string', 'void'], true)) { 46 | $callable = [$openAPIType, 'getAllowableEnumValues']; 47 | if (is_callable($callable)) { 48 | /** array $callable */ 49 | $allowedEnumTypes = $callable(); 50 | if (!in_array($value, $allowedEnumTypes, true)) { 51 | $imploded = implode("', '", $allowedEnumTypes); 52 | throw new \InvalidArgumentException("Invalid value for enum '$openAPIType', must be one of: '$imploded'"); 53 | } 54 | } 55 | } 56 | if ($value !== null) { 57 | $values[$data::attributeMap()[$property]] = self::sanitizeForSerialization($value, $openAPIType, $formats[$property]); 58 | } 59 | } 60 | } else { 61 | foreach ($data as $property => $value) { 62 | $values[$property] = self::sanitizeForSerialization($value); 63 | } 64 | } 65 | return (object)$values; 66 | } else { 67 | return (string)$data; 68 | } 69 | } 70 | 71 | 72 | /** 73 | * Take value and turn it into a string suitable for inclusion in 74 | * the path, by url-encoding. 75 | * 76 | * @param string $value a string which will be part of the path 77 | * 78 | * @return string the serialized object 79 | */ 80 | public static function toPathValue(string $value): string 81 | { 82 | return rawurlencode(self::toString($value)); 83 | } 84 | 85 | /** 86 | * Take value and turn it into a string suitable for inclusion in 87 | * the query, by imploding comma-separated if it's an object. 88 | * If it's a string, pass through unchanged. It will be url-encoded 89 | * later. 90 | * 91 | * @param string[]|string|\DateTime $object an object to be serialized to a string 92 | * 93 | * @return string the serialized object 94 | */ 95 | public static function toQueryValue($object) 96 | { 97 | if (is_array($object)) { 98 | return implode(',', $object); 99 | } else { 100 | return self::toString($object); 101 | } 102 | } 103 | 104 | /** 105 | * Take value and turn it into a string suitable for inclusion in 106 | * the header. If it's a string, pass through unchanged 107 | * If it's a datetime object, format it in ISO8601 108 | * 109 | * @param string $value a string which will be part of the header 110 | * 111 | * @return string the header string 112 | */ 113 | public static function toHeaderValue(string $value): \DateTime|string 114 | { 115 | $callable = [$value, 'toHeaderValue']; 116 | if (is_callable($callable)) { 117 | return $callable(); 118 | } 119 | 120 | return self::toString($value); 121 | } 122 | 123 | /** 124 | * Take value and turn it into a string suitable for inclusion in 125 | * the parameter. If it's a string, pass through unchanged 126 | * If it's a datetime object, format it in ISO8601 127 | * If it's a boolean, convert it to "true" or "false". 128 | * 129 | * @param string|bool|\DateTime $value the value of the parameter 130 | * 131 | * @return string the header string 132 | */ 133 | public static function toString($value): \DateTime|string 134 | { 135 | if ($value instanceof \DateTime) { // datetime in ISO8601 format 136 | return $value->format(self::$dateTimeFormat); 137 | } elseif (is_bool($value)) { 138 | return $value ? 'true' : 'false'; 139 | } else { 140 | return $value; 141 | } 142 | } 143 | 144 | /** 145 | * Serialize an array to a string. 146 | * 147 | * @param array $collection collection to serialize to a string 148 | * @param string $style the format use for serialization (csv, 149 | * ssv, tsv, pipes, multi) 150 | * @param bool $allowCollectionFormatMulti allow collection format to be a multidimensional array 151 | * 152 | * @return string 153 | */ 154 | public static function serializeCollection(array $collection, string $style, bool $allowCollectionFormatMulti = false): string 155 | { 156 | if ($allowCollectionFormatMulti && ('multi' === $style)) { 157 | // http_build_query() almost does the job for us. We just 158 | // need to fix the result of multidimensional arrays. 159 | return preg_replace('/%5B[0-9]+%5D=/', '=', http_build_query($collection, '', '&')); 160 | } 161 | switch ($style) { 162 | case 'pipeDelimited': 163 | case 'pipes': 164 | return implode('|', $collection); 165 | 166 | case 'tsv': 167 | return implode("\t", $collection); 168 | 169 | case 'spaceDelimited': 170 | case 'ssv': 171 | return implode(' ', $collection); 172 | 173 | case 'simple': 174 | case 'csv': 175 | // Deliberate fall through. CSV is default format. 176 | default: 177 | return implode(',', $collection); 178 | } 179 | } 180 | 181 | /** 182 | * Deserialize a JSON string into an object 183 | * 184 | * @param mixed $data object or primitive to be deserialized 185 | * @param string $class class name is passed as a string 186 | * @param null $httpHeaders HTTP headers 187 | * @return object|array|null a single or an array of $class instances 188 | */ 189 | public static function deserialize(mixed $data, string $class, mixed $httpHeaders = null) 190 | { 191 | if (null === $data) { 192 | return null; 193 | } 194 | 195 | if (strcasecmp(substr($class, -2), '[]') === 0) { 196 | $data = is_string($data) ? json_decode($data) : $data; 197 | 198 | if (!is_array($data)) { 199 | throw new \InvalidArgumentException("Invalid array '$class'"); 200 | } 201 | 202 | $subClass = substr($class, 0, -2); 203 | $values = []; 204 | foreach ($data as $key => $value) { 205 | $values[] = self::deserialize($value, $subClass, null); 206 | } 207 | return $values; 208 | } 209 | 210 | if (preg_match('/^(array<|map\[)/', $class)) { // for associative array e.g. array 211 | $data = is_string($data) ? json_decode($data) : $data; 212 | settype($data, 'array'); 213 | $inner = substr($class, 4, -1); 214 | $deserialized = []; 215 | if (strrpos($inner, ",") !== false) { 216 | $subClass_array = explode(',', $inner, 2); 217 | $subClass = $subClass_array[1]; 218 | foreach ($data as $key => $value) { 219 | $deserialized[$key] = self::deserialize($value, $subClass, null); 220 | } 221 | } 222 | return $deserialized; 223 | } 224 | 225 | if ($class === 'object') { 226 | settype($data, 'array'); 227 | return $data; 228 | } elseif ($class === 'mixed') { 229 | settype($data, gettype($data)); 230 | return $data; 231 | } 232 | 233 | if ($class === '\DateTime') { 234 | // Some API's return an invalid, empty string as a 235 | // date-time property. DateTime::__construct() will return 236 | // the current time for empty input which is probably not 237 | // what is meant. The invalid empty string is probably to 238 | // be interpreted as a missing field/value. Let's handle 239 | // this graceful. 240 | if (!empty($data)) { 241 | try { 242 | return new \DateTime($data); 243 | } catch (\Exception $exception) { 244 | // Some API's return a date-time with too high nanosecond 245 | // precision for php's DateTime to handle. This conversion 246 | // (string -> unix timestamp -> DateTime) is a workaround 247 | // for the problem. 248 | return (new \DateTime())->setTimestamp(strtotime($data)); 249 | } 250 | } else { 251 | return null; 252 | } 253 | } 254 | 255 | /** @psalm-suppress ParadoxicalCondition */ 256 | if (in_array($class, ['\DateTime', 'array', 'bool', 'boolean', 'byte', 'double', 'float', 'int', 'integer', 'mixed', 'number', 'object', 'string', 'void'], true)) { 257 | settype($data, $class); 258 | return $data; 259 | } 260 | 261 | if (method_exists($class, 'getAllowableEnumValues')) { 262 | if (!in_array($data, $class::getAllowableEnumValues(), true)) { 263 | $imploded = implode("', '", $class::getAllowableEnumValues()); 264 | throw new \InvalidArgumentException("Invalid value for enum '$class', must be one of: '$imploded'"); 265 | } 266 | return $data; 267 | } else { 268 | $data = is_string($data) ? json_decode($data) : $data; 269 | 270 | 271 | /** @var ModelInterface $instance */ 272 | $instance = new $class(); 273 | foreach ($instance::openAPITypes() as $property => $type) { 274 | $propertySetter = $instance::setters()[$property]; 275 | 276 | if (!isset($propertySetter) || !isset($data->{$instance::attributeMap()[$property]})) { 277 | continue; 278 | } 279 | 280 | $propertyValue = $data->{$instance::attributeMap()[$property]}; 281 | $instance->$propertySetter(self::deserialize($propertyValue, $type, null)); 282 | } 283 | return $instance; 284 | } 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /lib/OpenFeature/DevCycleProvider.php: -------------------------------------------------------------------------------- 1 | apiClient = $apiClient; 25 | $this->metadata = new Metadata("DevCycle-PHP"); 26 | $this->hooks = []; 27 | } 28 | 29 | /** 30 | * @return Hook[] 31 | */ 32 | public function getHooks(): array 33 | { 34 | return $this->hooks; 35 | } 36 | 37 | public function setHooks(array $hooks): void 38 | { 39 | $this->hooks = $hooks; 40 | } 41 | 42 | /** 43 | * @param LoggerInterface $logger 44 | * @return void 45 | */ 46 | public function setLogger(LoggerInterface $logger): void 47 | { 48 | // TODO: Implement setLogger() method. 49 | } 50 | 51 | /** 52 | * @return Metadata 53 | */ 54 | public function getMetadata(): IMetadata 55 | { 56 | return $this->metadata; 57 | } 58 | 59 | /** 60 | * @param string $flagKey 61 | * @param bool $defaultValue 62 | * @param EvaluationContext|null $context 63 | * @return ResolutionDetails 64 | */ 65 | public function resolveBooleanValue(string $flagKey, bool $defaultValue, ?EvaluationContext $context = null): ResolutionDetails 66 | { 67 | if ($context == null) { 68 | throw new \InvalidArgumentException("Context cannot be null"); 69 | } 70 | $user = DevCycleUser::FromEvaluationContext($context); 71 | 72 | return $this->apiClient->variable($user, $flagKey, $defaultValue)->asResolutionDetails(); 73 | } 74 | 75 | /** 76 | * @param string $flagKey 77 | * @param string $defaultValue 78 | * @param EvaluationContext|null $context 79 | * @return ResolutionDetails 80 | */ 81 | public function resolveStringValue(string $flagKey, string $defaultValue, ?EvaluationContext $context = null): ResolutionDetails 82 | { 83 | if ($context == null) { 84 | throw new \InvalidArgumentException("Context cannot be null"); 85 | } 86 | $user = DevCycleUser::FromEvaluationContext($context); 87 | 88 | return $this->apiClient->variable($user, $flagKey, $defaultValue)->asResolutionDetails(); 89 | } 90 | 91 | /** 92 | * @param string $flagKey 93 | * @param int $defaultValue 94 | * @param EvaluationContext|null $context 95 | * @return ResolutionDetails 96 | */ 97 | public function resolveIntegerValue(string $flagKey, int $defaultValue, ?EvaluationContext $context = null): ResolutionDetails 98 | { 99 | if ($context == null) { 100 | throw new \InvalidArgumentException("Context cannot be null"); 101 | } 102 | $user = DevCycleUser::FromEvaluationContext($context); 103 | 104 | return $this->apiClient->variable($user, $flagKey, $defaultValue)->asResolutionDetails(); 105 | } 106 | 107 | /** 108 | * @param string $flagKey 109 | * @param float $defaultValue 110 | * @param EvaluationContext|null $context 111 | * @return ResolutionDetails 112 | */ 113 | public function resolveFloatValue(string $flagKey, float $defaultValue, ?EvaluationContext $context = null): ResolutionDetails 114 | { 115 | if ($context == null) { 116 | throw new \InvalidArgumentException("Context cannot be null"); 117 | } 118 | $user = DevCycleUser::FromEvaluationContext($context); 119 | 120 | return $this->apiClient->variable($user, $flagKey, $defaultValue)->asResolutionDetails(); 121 | } 122 | 123 | /** 124 | * @param string $flagKey 125 | * @param array $defaultValue 126 | * @param EvaluationContext|null $context 127 | * @return ResolutionDetails 128 | */ 129 | public function resolveObjectValue(string $flagKey, array $defaultValue, ?EvaluationContext $context = null): ResolutionDetails 130 | { 131 | if ($context == null) { 132 | throw new \InvalidArgumentException("Context cannot be null"); 133 | } 134 | $user = DevCycleUser::FromEvaluationContext($context); 135 | 136 | return $this->apiClient->variable($user, $flagKey, $defaultValue)->asResolutionDetails(); 137 | } 138 | } -------------------------------------------------------------------------------- /lib/Version.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./test/Api 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ./lib/Api 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/Api/DevCycleClientTest.php: -------------------------------------------------------------------------------- 1 | "test" 73 | )); 74 | self::$api->setProvider(self::$client->getOpenFeatureProvider()); 75 | self::$openFeatureClient = self::$api->getClient(); 76 | self::$context = new EvaluationContext('test'); 77 | 78 | } 79 | 80 | /** 81 | * Clean up after running each test case 82 | */ 83 | public function tearDown(): void 84 | { 85 | } 86 | 87 | /** 88 | * Clean up after running all test cases 89 | */ 90 | public static function tearDownAfterClass(): void 91 | { 92 | } 93 | 94 | /** 95 | * Test case for getFeatures 96 | * 97 | * Get all features by key for user data. 98 | * 99 | */ 100 | public function testGetFeatures() 101 | { 102 | $result = self::$client->allVariables(self::$user); 103 | 104 | self::assertGreaterThan(0, count($result)); 105 | } 106 | 107 | /** 108 | * Test case for getVariableByKey 109 | * 110 | * Get variable by key for user data. 111 | * 112 | */ 113 | public function testGetVariableByKey() 114 | { 115 | $result = self::$client->variable(self::$user, 'test', false); 116 | self::assertFalse($result->isDefaulted()); 117 | 118 | // add a value to the invocation context 119 | $boolValue = self::$openFeatureClient->getBooleanValue('test', false, self::$context); 120 | self::assertTrue($boolValue); 121 | $resultValue = self::$client->variableValue(self::$user, 'test', false); 122 | self::assertTrue((bool)$resultValue); 123 | 124 | $result = self::$client->variable(self::$user, 'php-sdk-default-invalid', true); 125 | self::assertTrue($result->isDefaulted()); 126 | self::assertTrue((bool)$result->getValue()); 127 | } 128 | 129 | /** 130 | * Test case for getVariableByKey 131 | * 132 | * Get variable by key for user data. 133 | * 134 | */ 135 | public function testVariable_invalidSDKKey_isDefaultedTrue() 136 | { 137 | $localApiInstance = new DevCycleClient( 138 | "dvc_server_invalid-sdk-key", 139 | new DevCycleOptions(false) 140 | ); 141 | $result = $localApiInstance->variable(self::$user, 'test-feature', true); 142 | $openFeatureResult = self::$openFeatureClient->getBooleanDetails('test-feature', true, self::$context); 143 | $resultValue = (bool)$localApiInstance->variableValue(self::$user, 'test-feature', true); 144 | $openFeatureValue = self::$openFeatureClient->getBooleanValue('test-feature', true, self::$context); 145 | 146 | self::assertTrue($result->isDefaulted()); 147 | self::assertEquals(Reason::DEFAULT, $openFeatureResult->getReason()); 148 | self::assertTrue($resultValue); 149 | self::assertTrue($openFeatureValue); 150 | } 151 | 152 | public function testVariableDefaultedDoesNotThrow() 153 | { 154 | $result = self::$client->variable(self::$user, 'variable-does-not-exist', true); 155 | self::assertTrue($result->isDefaulted()); 156 | self::assertTrue((bool)$result->getValue()); 157 | } 158 | 159 | /** 160 | * Test case for getVariables 161 | * 162 | * Get all variables by key for user data. 163 | * 164 | */ 165 | public function testGetVariables() 166 | { 167 | $result = self::$client->allVariables(self::$user); 168 | 169 | self::assertGreaterThan(0, $result); 170 | } 171 | 172 | /** 173 | * Test case for postEvents 174 | * 175 | * Post events to DevCycle for user. 176 | * 177 | */ 178 | public function testPostEvents() 179 | { 180 | $event_data = new DevCycleEvent(array( 181 | "type" => "some_event" 182 | )); 183 | 184 | $result = self::$client->track(self::$user, $event_data); 185 | 186 | self::assertEquals("Successfully received 1 events.", $result["message"]); 187 | } 188 | 189 | public function testTrackNoType() 190 | { 191 | $event_data = new DevCycleEvent(array( 192 | "type" => "" 193 | )); 194 | 195 | $result = self::$client->track(self::$user, $event_data); 196 | self::assertTrue($result instanceof ErrorResponse); 197 | self::assertEquals("Event data is invalid: 'type' can't be null or empty", $result->getMessage()); 198 | } 199 | 200 | public function testOpenFeature() 201 | { 202 | $boolResult = self::$openFeatureClient->getBooleanValue('test', false, self::$context); 203 | self::assertTrue($boolResult); 204 | 205 | $numberResult = self::$openFeatureClient->getIntegerValue('test-number-variable', -1, self::$context); 206 | self::assertNotEquals(-1, $numberResult); 207 | 208 | $stringResult = self::$openFeatureClient->getStringValue('test-string-variable', 'default', self::$context); 209 | self::assertNotEquals('default', $stringResult); 210 | 211 | $structResult = self::$openFeatureClient->getObjectValue('test-json-variable', array(), self::$context); 212 | self::assertNotEquals(array(), $structResult); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /test/Api/OpenFeatureTest.php: -------------------------------------------------------------------------------- 1 | getUserId(), 'User ID not properly passed through/set'); 34 | 35 | $attributes = new Attributes(array("user_id" => "test")); 36 | $evaluationContext = new EvaluationContext(attributes: $attributes); 37 | $user = DevCycleUser::FromEvaluationContext($evaluationContext); 38 | self::assertEquals("test", $user->getUserId(), 'User ID not properly passed through/set'); 39 | 40 | $attributes = new Attributes(array("user_id" => "test")); 41 | $evaluationContext = new EvaluationContext(targetingKey: "test2", attributes: $attributes); 42 | $user = DevCycleUser::FromEvaluationContext($evaluationContext); 43 | self::assertEquals("test", $user->getUserId(), 'User ID not properly passed through/set'); 44 | 45 | } 46 | public function testEvaluationContext() 47 | { 48 | $attributes = new Attributes(array( 49 | "user_id" => "test", 50 | "customData" => array( 51 | "customKey" => "customValue" 52 | ), 53 | "privateCustomData" => array( 54 | "privateKey" => "privateValue" 55 | ), 56 | "email" => "email@email.com", 57 | "name" => "Name Name", 58 | "language" => "EN", 59 | "country" => "CA", 60 | "appVersion" => "0.0.1", 61 | "appBuild" => 1, 62 | "nonSetValueBubbledCustomData" => true, 63 | "nonSetValueBubbledCustomData2" => "true", 64 | "nonSetValueBubbledCustomData3" => 1, 65 | "nonSetValueBubbledCustomData4" => null 66 | )); 67 | $evaluationContext = new EvaluationContext(attributes: $attributes); 68 | $user = DevCycleUser::FromEvaluationContext($evaluationContext); 69 | self::assertEquals("test", $user->getUserId(), 'User ID not properly passed through/set'); 70 | self::assertEquals("customValue", $user->getCustomData()["customKey"], 'Custom Data not properly passed through/set'); 71 | self::assertEquals("privateValue", $user->getPrivateCustomData()["privateKey"], 'Private Custom Data not properly passed through/set'); 72 | self::assertEquals("email@email.com", $user->getEmail(), 'Email not properly passed through/set'); 73 | self::assertEquals("Name Name", $user->getName(), 'Name not properly passed through/set'); 74 | self::assertEquals("EN", $user->getLanguage(), 'Language not properly passed through/set'); 75 | self::assertEquals("CA", $user->getCountry(), 'Country not properly passed through/set'); 76 | self::assertEquals("0.0.1", $user->getAppVersion(), 'App Version not properly passed through/set'); 77 | self::assertEquals(1, $user->getAppBuild(), 'App Build not properly passed through/set'); 78 | self::assertEquals(true, $user->getCustomData()['nonSetValueBubbledCustomData'], 'Non Set Value Bubbled Custom Data not properly passed through/set'); 79 | self::assertEquals("true", $user->getCustomData()['nonSetValueBubbledCustomData2'], 'Non Set Value Bubbled Custom Data 2 not properly passed through/set'); 80 | self::assertEquals(1, $user->getCustomData()['nonSetValueBubbledCustomData3'], 'Non Set Value Bubbled Custom Data 3 not properly passed through/set'); 81 | self::assertEquals(null, $user->getCustomData()['nonSetValueBubbledCustomData4'], 'Non Set Value Bubbled Custom Data 4 not properly passed through/set'); 82 | } 83 | } 84 | --------------------------------------------------------------------------------