diff --git a/.gitattributes b/.gitattributes
index 4e30f2f..4b607e7 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -7,5 +7,6 @@
/.sonarcloud.properties export-ignore
/CONTRIBUTING.md export-ignore
/DEPLOY.md export-ignore
-/phpcs.xml export-ignore
/phpunit.xml export-ignore
+/.php-cs-fixer.php export-ignore
+/phpstan.neon export-ignore
diff --git a/.github/workflows/php-ci.yml b/.github/workflows/php-ci.yml
index 01f5704..390c632 100644
--- a/.github/workflows/php-ci.yml
+++ b/.github/workflows/php-ci.yml
@@ -4,7 +4,7 @@ on:
schedule:
- cron: '0 0 * * *'
push:
- branches: [ master ]
+ branches: [ '*' ]
pull_request:
branches: [ master ]
@@ -43,12 +43,14 @@ jobs:
- name: Execute tests
run: vendor/bin/phpunit
-
+
coverage:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
- name: Setup PHP
uses: shivammathur/setup-php@v2
@@ -76,5 +78,68 @@ jobs:
- name: Execute coverage
run: vendor/bin/phpunit --coverage-clover clover.xml
- - name: Upload coverage report
- run: bash <(curl -s https://codecov.io/bash)
+ - name: Upload coverage
+ uses: codecov/codecov-action@v3
+ with:
+ fail_ci_if_error: true
+ files: ./clover.xml
+
+ php-cs-fixer:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.1'
+ ini-values: 'memory_limit=-1'
+
+ - name: Validate composer.json and composer.lock
+ run: composer validate --strict
+
+ - name: Cache Composer packages
+ id: composer-cache
+ uses: actions/cache@v3
+ with:
+ path: vendor
+ key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-php-
+
+ - name: Install dependencies
+ run: |
+ composer self-update
+ composer install --prefer-dist --no-progress --no-suggest --no-plugins
+
+ - run: vendor/bin/php-cs-fixer fix --ansi --diff --dry-run
+
+ phpstan:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.1'
+ ini-values: 'memory_limit=-1'
+
+ - name: Validate composer.json and composer.lock
+ run: composer validate --strict
+
+ - name: Cache Composer packages
+ id: composer-cache
+ uses: actions/cache@v3
+ with:
+ path: vendor
+ key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-php-
+
+ - name: Install dependencies
+ run: |
+ composer self-update
+ composer install --prefer-dist --no-progress --no-suggest --no-plugins
+
+ - run: vendor/bin/phpstan analyse --ansi
diff --git a/.gitignore b/.gitignore
index f9582fe..af20d34 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,7 @@
/vendor
composer.lock
.idea/
-
.DS_Store
-
.phpunit.result.cache
-
+.php-cs-fixer.cache
/samples/consolesample/vendor
\ No newline at end of file
diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php
new file mode 100644
index 0000000..abd507c
--- /dev/null
+++ b/.php-cs-fixer.php
@@ -0,0 +1,24 @@
+in(__DIR__.'/src')
+ ->in(__DIR__.'/tests')
+;
+
+$config = (new PhpCsFixer\Config())
+ ->setRules([
+ '@PhpCsFixer' => true,
+ '@PSR2' => true,
+ 'php_unit_internal_class' => false,
+ 'php_unit_test_class_requires_covers' => false,
+ 'global_namespace_import' => [
+ 'import_classes' => true,
+ 'import_constants' => true,
+ 'import_functions' => false,
+ ],
+ ])
+ ->setUsingCache(true)
+ ->setFinder($finder)
+;
+
+return $config;
diff --git a/DEPLOY.md b/DEPLOY.md
index c4f3104..6b2ec56 100644
--- a/DEPLOY.md
+++ b/DEPLOY.md
@@ -6,15 +6,19 @@
```
2. Make sure the code is properly formatted.
```bash
- ./vendor/bin/phpcs
+ vendor/bin/php-cs-fixer fix --ansi --diff --dry-run
```
- > If it shows formatting errors, then you can fix them with the `./vendor/bin/phpcbf` command
-3. Run tests
+ > If it shows formatting errors, then you can fix them with the `vendor/bin/php-cs-fixer fix --ansi` command
+3. Make sure the static analyzer doesn't show errors.
+ ```bash
+ vendor/bin/phpstan analyse --ansi
+ ```
+4. Run tests
```bash
vendor/bin/phpunit tests
```
-4. Set `SDK_VERSION` constant in `ConfigCatClient.php`
-5. Commit & Push
+5. Set `SDK_VERSION` constant in `ConfigCatClient.php`
+6. Commit & Push
## Publish
- Via git tag
1. Create a new version tag.
diff --git a/composer.json b/composer.json
index d01139f..76451c4 100644
--- a/composer.json
+++ b/composer.json
@@ -17,15 +17,16 @@
"guzzlehttp/guzzle": "^6.3|^7.0",
"psr/log": "^2.0|^3.0",
"ext-json": "*",
- "monolog/monolog": "^2.0|^3.0",
- "z4kn4fein/php-semver": "^2.0"
+ "z4kn4fein/php-semver": "^2.0",
+ "psr/http-client": "^1.0"
},
"require-dev": {
- "phpunit/phpunit": "~7.0|^8",
+ "phpunit/phpunit": "^9",
"illuminate/cache": "^9.0",
"psr/simple-cache": "^3.0",
"psr/cache": "^1.0",
- "squizlabs/php_codesniffer": "^3.7"
+ "phpstan/phpstan": "^1.0",
+ "friendsofphp/php-cs-fixer": "^3.0"
},
"autoload": {
"psr-4": {
diff --git a/phpcs.xml b/phpcs.xml
deleted file mode 100644
index 9b158ae..0000000
--- a/phpcs.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
- The coding standard for ConfigCat.
-
- src
- tests
-
- */samples/*
- */vendor/*
- */tests/*
- */src/Hash/*
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..099fec6
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,9 @@
+parameters:
+ level: 8
+ paths:
+ - src
+ ignoreErrors:
+ -
+ message: '#PHPDoc tag \@throws with type Psr\\Cache\\InvalidArgumentException is not subtype of Throwable#'
+ path: src/Cache/Psr6Cache.php
+ count: 2
\ No newline at end of file
diff --git a/phpunit.xml b/phpunit.xml
index ed5ec68..59b4b59 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -1,23 +1,13 @@
-
-
-
- tests
-
-
-
-
- src
-
-
-
\ No newline at end of file
+
+
+
+
+ src
+
+
+
+
+ tests
+
+
+
diff --git a/src/Attributes/Config.php b/src/Attributes/Config.php
index 752cf9b..fc6c4c1 100644
--- a/src/Attributes/Config.php
+++ b/src/Attributes/Config.php
@@ -1,13 +1,14 @@
+ */
private static array $arrayCache = [];
/**
* Reads the value identified by the given $key from the underlying cache.
*
- * @param string $key Identifier for the cached value.
- * @return ?string Cached value for the given key, or null if it's missing.
+ * @param string $key identifier for the cached value
+ *
+ * @return ?string cached value for the given key, or null if it's missing
*/
protected function get(string $key): ?string
{
@@ -24,8 +29,8 @@ protected function get(string $key): ?string
/**
* Writes the value identified by the given $key into the underlying cache.
*
- * @param string $key Identifier for the cached value.
- * @param string $value The value to cache.
+ * @param string $key identifier for the cached value
+ * @param string $value the value to cache
*/
protected function set(string $key, string $value): void
{
diff --git a/src/Cache/ConfigCache.php b/src/Cache/ConfigCache.php
index be56612..91a79e3 100644
--- a/src/Cache/ConfigCache.php
+++ b/src/Cache/ConfigCache.php
@@ -1,5 +1,7 @@
set($key, $value->serialize());
} catch (Exception $exception) {
- $this->logger->error("Error occurred while writing the cache.", [
- 'event_id' => 2201, 'exception' => $exception
+ $this->logger->error('Error occurred while writing the cache.', [
+ 'event_id' => 2201, 'exception' => $exception,
]);
}
}
@@ -58,16 +43,17 @@ public function store(string $key, ConfigEntry $value): void
/**
* Reads the value identified by the given $key from the underlying cache.
*
- * @param string $key Identifier for the cached value.
- * @return ConfigEntry Cached value for the given key, or null if it's missing.
+ * @param string $key identifier for the cached value
+ *
+ * @return ConfigEntry cached value for the given key, or null if it's missing
*
* @throws InvalidArgumentException
- * If the $key is not a legal value.
+ * If the $key is not a legal value
*/
public function load(string $key): ConfigEntry
{
if (empty($key)) {
- throw new InvalidArgumentException("key cannot be empty.");
+ throw new InvalidArgumentException('key cannot be empty.');
}
try {
@@ -75,11 +61,11 @@ public function load(string $key): ConfigEntry
if (empty($cached)) {
return ConfigEntry::empty();
}
-
+
return ConfigEntry::fromCached($cached);
} catch (Exception $exception) {
- $this->logger->error("Error occurred while reading the cache.", [
- 'event_id' => 2200, 'exception' => $exception
+ $this->logger->error('Error occurred while reading the cache.', [
+ 'event_id' => 2200, 'exception' => $exception,
]);
}
@@ -88,11 +74,26 @@ public function load(string $key): ConfigEntry
/**
* Sets a logger instance on the object.
- *
- * @param LoggerInterface $logger
*/
public function setLogger(LoggerInterface $logger): void
{
$this->logger = $logger;
}
+
+ /**
+ * Reads the value identified by the given $key from the underlying cache.
+ *
+ * @param string $key identifier for the cached value
+ *
+ * @return null|string cached value for the given key, or null if it's missing
+ */
+ abstract protected function get(string $key): ?string;
+
+ /**
+ * Writes the value identified by the given $key into the underlying cache.
+ *
+ * @param string $key identifier for the cached value
+ * @param string $value the value to cache
+ */
+ abstract protected function set(string $key, string $value): void;
}
diff --git a/src/Cache/ConfigEntry.php b/src/Cache/ConfigEntry.php
index d35b019..539274a 100644
--- a/src/Cache/ConfigEntry.php
+++ b/src/Cache/ConfigEntry.php
@@ -1,40 +1,58 @@
configJson;
}
+ /**
+ * @return mixed[] the deserialized config
+ */
public function getConfig(): array
{
return $this->config;
}
+ /**
+ * @return string the ETag related to the current config
+ */
public function getEtag(): string
{
return $this->etag;
}
+ /**
+ * @return float the time when the current config was fetched
+ */
public function getFetchTime(): float
{
return $this->fetchTime;
@@ -42,7 +60,7 @@ public function getFetchTime(): float
public function serialize(): string
{
- return $this->fetchTime . "\n" . $this->etag . "\n" . $this->configJson;
+ return $this->fetchTime."\n".$this->etag."\n".$this->configJson;
}
public function withTime(float $time): ConfigEntry
@@ -52,8 +70,8 @@ public function withTime(float $time): ConfigEntry
public static function empty(): ConfigEntry
{
- if (self::$empty == null) {
- self::$empty = new ConfigEntry("", [], "", 0);
+ if (null == self::$empty) {
+ self::$empty = new ConfigEntry('', [], '', 0);
}
return self::$empty;
@@ -62,7 +80,7 @@ public static function empty(): ConfigEntry
public static function fromConfigJson(string $configJson, string $etag, float $fetchTime): ConfigEntry
{
$deserialized = json_decode($configJson, true);
- if ($deserialized == null) {
+ if (null == $deserialized) {
return self::empty();
}
@@ -74,15 +92,15 @@ public static function fromCached(string $cached): ConfigEntry
$timePos = strpos($cached, "\n");
$etagPos = strpos($cached, "\n", $timePos + 1);
- if ($timePos === false || $etagPos === false) {
- throw new UnexpectedValueException("Number of values is fewer than expected.");
+ if (false === $timePos || false === $etagPos) {
+ throw new UnexpectedValueException('Number of values is fewer than expected.');
}
$fetchTimeString = substr($cached, 0, $timePos);
$fetchTime = floatval($fetchTimeString);
- if ($fetchTime == 0) {
- throw new UnexpectedValueException("Invalid fetch time: " . $fetchTimeString);
+ if (0 == $fetchTime) {
+ throw new UnexpectedValueException('Invalid fetch time: '.$fetchTimeString);
}
$etag = substr($cached, $timePos + 1, $etagPos - $timePos - 1);
diff --git a/src/Cache/LaravelCache.php b/src/Cache/LaravelCache.php
index e9223ea..829e06d 100644
--- a/src/Cache/LaravelCache.php
+++ b/src/Cache/LaravelCache.php
@@ -1,5 +1,7 @@
cachePool->getItem($key);
+
return $item->get();
}
/**
* Writes the value identified by the given $key into the underlying cache.
*
- * @param string $key Identifier for the cached value.
- * @param string $value The value to cache.
+ * @param string $key identifier for the cached value
+ * @param string $value the value to cache
*
- * @throws InvalidArgumentException If the $key is not a legal value.
+ * @throws InvalidArgumentException if the $key is not a legal value
*/
protected function set(string $key, string $value): void
{
diff --git a/src/ClientInterface.php b/src/ClientInterface.php
index 7d3ec97..97fe576 100644
--- a/src/ClientInterface.php
+++ b/src/ClientInterface.php
@@ -1,61 +1,67 @@
new \ConfigCat\Cache\LaravelCache(Cache::store()),
+ * \ConfigCat\ClientOptions::CACHE_REFRESH_INTERVAL => 5
+ * ]);
+ *
+ * The configuration options include the following:
+ *
+ * - base-url: The base ConfigCat CDN url.
+ * - logger: A \Psr\Log\LoggerInterface implementation used for logging.
+ * - cache: A \ConfigCat\ConfigCache implementation used for caching the latest feature flag and setting values.
+ * - cache-refresh-interval: Sets how frequent the cached configuration should be refreshed in seconds.
+ * - request-options: Additional options for Guzzle http requests.
+ * https://docs.guzzlephp.org/en/stable/request-options.html
+ * - custom-handler: A custom callable Guzzle http handler.
+ * - fetch-client: A \ConfigCat\Http\FetchClientInterface implementation that wraps an actual HTTP client used
+ * to make HTTP requests towards ConfigCat.
+ * When it's not set, \ConfigCat\Http\FetchClient::Guzzle() is used by default.
+ * - data-governance: Default: Global. Set this parameter to be in sync with the Data Governance
+ * preference on the Dashboard: https://app.configcat.com/organization/data-governance
+ * (Only Organization Admins can access)
+ * - exceptions-to-ignore: Array of exception classes that should be ignored from logs.
+ * - flag-overrides: A \ConfigCat\Override\FlagOverrides instance used to override
+ * feature flags & settings.
+ * - log-level: Default: Warning. Sets the internal log level.
+ * - default-user: A \ConfigCat\User as default user.
+ * - offline: Default: false. Indicates whether the SDK should be initialized in offline mode or not.
+ *
+ * @param string $sdkKey the SDK Key used to communicate with the ConfigCat services
+ * @param mixed[] $options the configuration options
*
- * @throws InvalidArgumentException
- * When the $sdkKey is not valid.
+ * @throws InvalidArgumentException if the $sdkKey is not valid
+ *
+ * @see ClientOptions for the list of all available options.
*/
public function __construct(string $sdkKey, array $options = [])
{
@@ -73,32 +85,32 @@ public function __construct(string $sdkKey, array $options = [])
}
$this->hooks = new Hooks();
- $this->cacheKey = sha1(sprintf("%s_" . ConfigFetcher::CONFIG_JSON_NAME . "_" . self::CONFIG_JSON_CACHE_VERSION, $sdkKey));
+ $this->cacheKey = sha1(sprintf('%s_'.ConfigFetcher::CONFIG_JSON_NAME.'_'.self::CONFIG_JSON_CACHE_VERSION, $sdkKey));
- $externalLogger = (isset($options[ClientOptions::LOGGER]) &&
- $options[ClientOptions::LOGGER] instanceof LoggerInterface)
+ $externalLogger = (isset($options[ClientOptions::LOGGER])
+ && $options[ClientOptions::LOGGER] instanceof LoggerInterface)
? $options[ClientOptions::LOGGER]
- : $this->getMonolog();
+ : new DefaultLogger();
- $logLevel = (isset($options[ClientOptions::LOG_LEVEL]) &&
- LogLevel::isValid($options[ClientOptions::LOG_LEVEL]))
+ $logLevel = (isset($options[ClientOptions::LOG_LEVEL])
+ && LogLevel::isValid($options[ClientOptions::LOG_LEVEL]))
? $options[ClientOptions::LOG_LEVEL]
: LogLevel::WARNING;
- $exceptionsToIgnore = (isset($options[ClientOptions::EXCEPTIONS_TO_IGNORE]) &&
- is_array($options[ClientOptions::EXCEPTIONS_TO_IGNORE]))
+ $exceptionsToIgnore = (isset($options[ClientOptions::EXCEPTIONS_TO_IGNORE])
+ && is_array($options[ClientOptions::EXCEPTIONS_TO_IGNORE]))
? $options[ClientOptions::EXCEPTIONS_TO_IGNORE]
: [];
$this->logger = new InternalLogger($externalLogger, $logLevel, $exceptionsToIgnore, $this->hooks);
- $this->overrides = (isset($options[ClientOptions::FLAG_OVERRIDES]) &&
- $options[ClientOptions::FLAG_OVERRIDES] instanceof FlagOverrides)
+ $this->overrides = (isset($options[ClientOptions::FLAG_OVERRIDES])
+ && $options[ClientOptions::FLAG_OVERRIDES] instanceof FlagOverrides)
? $options[ClientOptions::FLAG_OVERRIDES]
: null;
- $this->defaultUser = (isset($options[ClientOptions::DEFAULT_USER]) &&
- $options[ClientOptions::DEFAULT_USER] instanceof User)
+ $this->defaultUser = (isset($options[ClientOptions::DEFAULT_USER])
+ && $options[ClientOptions::DEFAULT_USER] instanceof User)
? $options[ClientOptions::DEFAULT_USER]
: null;
@@ -106,15 +118,14 @@ public function __construct(string $sdkKey, array $options = [])
? $options[ClientOptions::CACHE]
: new ArrayCache();
-
- if (isset($options[ClientOptions::CACHE_REFRESH_INTERVAL]) &&
- is_int($options[ClientOptions::CACHE_REFRESH_INTERVAL])) {
+ if (isset($options[ClientOptions::CACHE_REFRESH_INTERVAL])
+ && is_int($options[ClientOptions::CACHE_REFRESH_INTERVAL])) {
$this->cacheRefreshInterval = $options[ClientOptions::CACHE_REFRESH_INTERVAL];
}
$this->overrides?->setLogger($this->logger);
- if (isset($options[ClientOptions::OFFLINE]) && $options[ClientOptions::OFFLINE] === true) {
+ if (isset($options[ClientOptions::OFFLINE]) && true === $options[ClientOptions::OFFLINE]) {
$this->offline = true;
}
@@ -126,23 +137,25 @@ public function __construct(string $sdkKey, array $options = [])
/**
* Gets a value of a feature flag or setting identified by the given key.
*
- * @param string $key The identifier of the configuration value.
- * @param mixed $defaultValue In case of any failure, this value will be returned.
- * @param ?User $user The user object to identify the caller.
- * @return mixed The configuration value identified by the given key.
+ * @param string $key the identifier of the configuration value
+ * @param mixed $defaultValue in case of any failure, this value will be returned
+ * @param ?User $user the user object to identify the caller
+ *
+ * @return mixed the configuration value identified by the given key
*/
public function getValue(string $key, mixed $defaultValue, ?User $user = null): mixed
{
try {
$settingsResult = $this->getSettingsResult();
- $errorMessage = $this->checkSettingAvailable($settingsResult, $key, '$defaultValue', $defaultValue);
- if ($errorMessage !== null) {
+ $errorMessage = $this->checkSettingAvailable($settingsResult, $key, $defaultValue);
+ if (null !== $errorMessage) {
$this->hooks->fireOnFlagEvaluated(EvaluationDetails::fromError(
$key,
$defaultValue,
$user,
$errorMessage
));
+
return $defaultValue;
}
@@ -153,12 +166,11 @@ public function getValue(string $key, mixed $defaultValue, ?User $user = null):
$settingsResult->fetchTime
)->getValue();
} catch (Exception $exception) {
- $message = "Error occurred in the `{METHOD_NAME}` method while evaluating setting '{KEY}'. " .
- "Returning the `{DEFAULT_PARAM_NAME}` parameter that you specified in your application: '{DEFAULT_PARAM_VALUE}'.";
+ $message = "Error occurred in the `getValue` method while evaluating setting '".$key."'. ".
+ 'Returning the `defaultValue` parameter that you specified '.
+ "in your application: '".Utils::getStringRepresentation($defaultValue)."'.";
$messageCtx = [
'event_id' => 1002, 'exception' => $exception,
- 'METHOD_NAME' => 'getValue', 'KEY' => $key,
- 'DEFAULT_PARAM_NAME' => '$defaultValue', 'DEFAULT_PARAM_VALUE' => Utils::getStringRepresentation($defaultValue)
];
$this->logger->error($message, $messageCtx);
$this->hooks->fireOnFlagEvaluated(EvaluationDetails::fromError(
@@ -167,6 +179,7 @@ public function getValue(string $key, mixed $defaultValue, ?User $user = null):
$user,
InternalLogger::format($message, $messageCtx)
));
+
return $defaultValue;
}
}
@@ -174,17 +187,18 @@ public function getValue(string $key, mixed $defaultValue, ?User $user = null):
/**
* Gets the value and evaluation details of a feature flag or setting identified by the given key.
*
- * @param string $key The identifier of the configuration value.
- * @param mixed $defaultValue In case of any failure, this value will be returned.
- * @param ?User $user The user object to identify the caller.
- * @return mixed The configuration value identified by the given key.
+ * @param string $key the identifier of the configuration value
+ * @param mixed $defaultValue in case of any failure, this value will be returned
+ * @param ?User $user the user object to identify the caller
+ *
+ * @return EvaluationDetails the configuration value identified by the given key
*/
public function getValueDetails(string $key, mixed $defaultValue, ?User $user = null): EvaluationDetails
{
try {
$settingsResult = $this->getSettingsResult();
- $errorMessage = $this->checkSettingAvailable($settingsResult, $key, '$defaultValue', $defaultValue);
- if ($errorMessage !== null) {
+ $errorMessage = $this->checkSettingAvailable($settingsResult, $key, $defaultValue);
+ if (null !== $errorMessage) {
$details = EvaluationDetails::fromError(
$key,
$defaultValue,
@@ -192,21 +206,22 @@ public function getValueDetails(string $key, mixed $defaultValue, ?User $user =
$errorMessage
);
$this->hooks->fireOnFlagEvaluated($details);
+
return $details;
}
return $this->evaluate($key, $settingsResult->settings[$key], $user, $settingsResult->fetchTime);
} catch (Exception $exception) {
- $message = "Error occurred in the `{METHOD_NAME}` method while evaluating setting '{KEY}'. " .
- "Returning the `{DEFAULT_PARAM_NAME}` parameter that you specified in your application: '{DEFAULT_PARAM_VALUE}'.";
+ $message = "Error occurred in the `getValueDetails` method while evaluating setting '".$key."'. ".
+ 'Returning the `defaultValue` parameter that you specified in '.
+ "your application: '".Utils::getStringRepresentation($defaultValue)."'.";
$messageCtx = [
'event_id' => 1002, 'exception' => $exception,
- 'METHOD_NAME' => 'getValueDetails', 'KEY' => $key,
- 'DEFAULT_PARAM_NAME' => '$defaultValue', 'DEFAULT_PARAM_VALUE' => Utils::getStringRepresentation($defaultValue)
];
$this->logger->error($message, $messageCtx);
$details = EvaluationDetails::fromError($key, $defaultValue, $user, InternalLogger::format($message, $messageCtx));
$this->hooks->fireOnFlagEvaluated($details);
+
return $details;
}
}
@@ -214,26 +229,26 @@ public function getValueDetails(string $key, mixed $defaultValue, ?User $user =
/**
* Gets the key of a setting and its value identified by the given Variation ID (analytics).
*
- * @param string $variationId The Variation ID.
- * @return ?Pair of the key and value of a setting.
+ * @param string $variationId the Variation ID
+ *
+ * @return ?Pair of the key and value of a setting
*/
public function getKeyAndValue(string $variationId): ?Pair
{
try {
$settingsResult = $this->getSettingsResult();
- if (!$this->checkSettingsAvailable($settingsResult, "null")) {
+ if (!$this->checkSettingsAvailable($settingsResult, 'null')) {
return null;
}
- return $settingsResult->settings === null
+ return empty($settingsResult->settings)
? null
: $this->parseKeyAndValue($settingsResult->settings, $variationId);
} catch (Exception $exception) {
- $this->logger->error("Error occurred in the `{METHOD_NAME}` method. Returning {DEFAULT_RETURN_VALUE}.", [
+ $this->logger->error('Error occurred in the `getKeyAndValue` method. Returning null.', [
'event_id' => 1002, 'exception' => $exception,
- 'METHOD_NAME' => 'getKeyAndValue',
- 'DEFAULT_RETURN_VALUE' => "null"
]);
+
return null;
}
}
@@ -241,23 +256,22 @@ public function getKeyAndValue(string $variationId): ?Pair
/**
* Gets a collection of all setting keys.
*
- * @return array of keys.
+ * @return string[] of keys
*/
public function getAllKeys(): array
{
try {
$settingsResult = $this->getSettingsResult();
- if (!$this->checkSettingsAvailable($settingsResult, "empty array")) {
+ if (!$this->checkSettingsAvailable($settingsResult, 'empty array')) {
return [];
}
- return $settingsResult->settings === null ? [] : array_keys($settingsResult->settings);
+ return empty($settingsResult->settings) ? [] : array_keys($settingsResult->settings);
} catch (Exception $exception) {
- $this->logger->error("Error occurred in the `{METHOD_NAME}` method. Returning {DEFAULT_RETURN_VALUE}.", [
+ $this->logger->error('Error occurred in the `getAllKeys` method. Returning empty array.', [
'event_id' => 1002, 'exception' => $exception,
- 'METHOD_NAME' => 'getAllKeys',
- 'DEFAULT_RETURN_VALUE' => "empty array"
]);
+
return [];
}
}
@@ -265,24 +279,24 @@ public function getAllKeys(): array
/**
* Gets the values of all feature flags or settings.
*
- * @param ?User $user The user object to identify the caller.
- * @return array of values.
+ * @param ?User $user the user object to identify the caller
+ *
+ * @return mixed[] of values
*/
public function getAllValues(?User $user = null): array
{
try {
$settingsResult = $this->getSettingsResult();
- if (!$this->checkSettingsAvailable($settingsResult, "empty array")) {
+ if (!$this->checkSettingsAvailable($settingsResult, 'empty array')) {
return [];
}
-
- return $settingsResult->settings === null ? [] : $this->parseValues($settingsResult, $user);
+
+ return empty($settingsResult->settings) ? [] : $this->parseValues($settingsResult, $user);
} catch (Exception $exception) {
- $this->logger->error("Error occurred in the `{METHOD_NAME}` method. Returning {DEFAULT_RETURN_VALUE}.", [
+ $this->logger->error('Error occurred in the `getAllValues` method. Returning empty array.', [
'event_id' => 1002, 'exception' => $exception,
- 'METHOD_NAME' => 'getAllValues',
- 'DEFAULT_RETURN_VALUE' => "empty array"
]);
+
return [];
}
}
@@ -290,14 +304,15 @@ public function getAllValues(?User $user = null): array
/**
* Gets the values along with evaluation details of all feature flags and settings.
*
- * @param ?User $user The user object to identify the caller.
- * @return EvaluationDetails[] of evaluation details of all feature flags and settings.
+ * @param ?User $user the user object to identify the caller
+ *
+ * @return EvaluationDetails[] of evaluation details of all feature flags and settings
*/
public function getAllValueDetails(?User $user = null): array
{
try {
$settingsResult = $this->getSettingsResult();
- if (!$this->checkSettingsAvailable($settingsResult, "empty array")) {
+ if (!$this->checkSettingsAvailable($settingsResult, 'empty array')) {
return [];
}
@@ -311,13 +326,13 @@ public function getAllValueDetails(?User $user = null): array
$settingsResult->fetchTime
);
}
+
return $result;
} catch (Exception $exception) {
- $this->logger->error("Error occurred in the `{METHOD_NAME}` method. Returning {DEFAULT_RETURN_VALUE}.", [
+ $this->logger->error('Error occurred in the `getAllValueDetails` method. Returning empty array.', [
'event_id' => 1002, 'exception' => $exception,
- 'METHOD_NAME' => 'getAllValueDetails',
- 'DEFAULT_RETURN_VALUE' => "empty array"
]);
+
return [];
}
}
@@ -327,22 +342,22 @@ public function getAllValueDetails(?User $user = null): array
*/
public function forceRefresh(): RefreshResult
{
- if ($this->overrides !== null && OverrideBehaviour::LOCAL_ONLY == $this->overrides->getBehaviour()) {
- $message = "Client is configured to use the `{OVERRIDE_BEHAVIOR}` override behavior, thus `{METHOD_NAME}()` has no effect.";
+ if (null !== $this->overrides && OverrideBehaviour::LOCAL_ONLY == $this->overrides->getBehaviour()) {
+ $message = 'Client is configured to use the `LOCAL_ONLY` override behavior, thus `forceRefresh()` has no effect.';
$messageCtx = [
'event_id' => 3202,
- 'OVERRIDE_BEHAVIOR' => 'LOCAL_ONLY',
- 'METHOD_NAME' => 'forceRefresh'
];
$this->logger->warning($message, $messageCtx);
+
return new RefreshResult(false, InternalLogger::format($message, $messageCtx));
}
if ($this->offline) {
- $message = "Client is in offline mode, it cannot initiate HTTP calls.";
+ $message = 'Client is in offline mode, it cannot initiate HTTP calls.';
$this->logger->warning($message, [
- 'event_id' => 3200
+ 'event_id' => 3200,
]);
+
return new RefreshResult(false, $message);
}
@@ -372,7 +387,7 @@ public function clearDefaultUser(): void
/**
* Gets the Hooks object for subscribing to SDK events.
*
- * @return Hooks for subscribing to SDK events.
+ * @return Hooks for subscribing to SDK events
*/
public function hooks(): Hooks
{
@@ -405,50 +420,56 @@ public function isOffline(): bool
private function checkSettingsAvailable(SettingsResult $settingsResult, string $defaultReturnValue): bool
{
- if ($settingsResult->settings === null) {
- $this->logger->error("Config JSON is not present. Returning {DEFAULT_RETURN_VALUE}.", [
+ if (empty($settingsResult->settings)) {
+ $this->logger->error('Config JSON is not present. Returning '.$defaultReturnValue.'.', [
'event_id' => 1000,
- 'DEFAULT_RETURN_VALUE' => $defaultReturnValue
]);
+
return false;
}
return true;
}
- private function checkSettingAvailable(SettingsResult $settingsResult, string $key, string $defaultValueParam, mixed $defaultValue): ?string
+ private function checkSettingAvailable(SettingsResult $settingsResult, string $key, mixed $defaultValue): ?string
{
- if ($settingsResult->settings === null) {
- $message = "Config JSON is not present when evaluating setting '{KEY}'. " .
- "Returning the `{DEFAULT_PARAM_NAME}` parameter that you specified in your application: '{DEFAULT_PARAM_VALUE}'.";
+ if (!$settingsResult->hasConfigJson) {
+ $message = "Config JSON is not present when evaluating setting '".$key."'. ".
+ 'Returning the `defaultValue` parameter that you specified in '.
+ "your application: '".Utils::getStringRepresentation($defaultValue)."'.";
$messageCtx = [
'event_id' => 1000,
- 'KEY' => $key,
- 'DEFAULT_PARAM_NAME' => $defaultValueParam, 'DEFAULT_PARAM_VALUE' => Utils::getStringRepresentation($defaultValue)
];
$this->logger->error($message, $messageCtx);
+
return InternalLogger::format($message, $messageCtx);
}
if (!array_key_exists($key, $settingsResult->settings)) {
- $message = "Failed to evaluate setting '{KEY}' (the key was not found in config JSON). " .
- "Returning the `{DEFAULT_PARAM_NAME}` parameter that you specified in your application: '{DEFAULT_PARAM_VALUE}'. " .
- "Available keys: [{AVAILABLE_KEYS}].";
+ $message = "Failed to evaluate setting '".$key."' (the key was not found in config JSON). ".
+ 'Returning the `defaultValue` parameter that you specified in your '.
+ "application: '".Utils::getStringRepresentation($defaultValue)."'. ".
+ 'Available keys: ['.(!empty($settingsResult->settings) ? "'".implode("', '", array_keys($settingsResult->settings))."'" : '').'].';
$messageCtx = [
'event_id' => 1001,
- 'KEY' => $key,
- 'DEFAULT_PARAM_NAME' => $defaultValueParam, 'DEFAULT_PARAM_VALUE' => Utils::getStringRepresentation($defaultValue),
- 'AVAILABLE_KEYS' => !empty($settingsResult->settings) ? "'".implode("', '", array_keys($settingsResult->settings))."'" : ""
];
$this->logger->error($message, $messageCtx);
+
return InternalLogger::format($message, $messageCtx);
}
return null;
}
+ /**
+ * @return mixed[]
+ */
private function parseValues(SettingsResult $settingsResult, User $user = null): array
{
+ if (empty($settingsResult->settings)) {
+ return [];
+ }
+
$keys = array_keys($settingsResult->settings);
$result = [];
foreach ($keys as $key) {
@@ -463,15 +484,17 @@ private function parseValues(SettingsResult $settingsResult, User $user = null):
return $result;
}
+ /**
+ * @param mixed[] $setting
+ */
private function evaluate(string $key, array $setting, ?User $user, float $fetchTime): EvaluationDetails
{
- $actualUser = $user === null ? $this->defaultUser : $user;
+ $actualUser = null === $user ? $this->defaultUser : $user;
$collector = new EvaluationLogCollector();
- $collector->add("Evaluating " . $key . ".");
+ $collector->add('Evaluating '.$key.'.');
$result = $this->evaluator->evaluate($key, $setting, $collector, $actualUser);
- $this->logger->info("{EVALUATE_LOG}", [
+ $this->logger->info((string) $collector, [
'event_id' => 5000,
- 'EVALUATE_LOG' => $collector
]);
$details = new EvaluationDetails(
$key,
@@ -485,10 +508,14 @@ private function evaluate(string $key, array $setting, ?User $user, float $fetch
$result->percentageRule
);
$this->hooks->fireOnFlagEvaluated($details);
+
return $details;
}
- private function parseKeyAndValue(array $json, $variationId): ?Pair
+ /**
+ * @param array $json
+ */
+ private function parseKeyAndValue(array $json, string $variationId): ?Pair
{
foreach ($json as $key => $value) {
if ($variationId == $value[SettingAttributes::VARIATION_ID]) {
@@ -511,27 +538,31 @@ private function parseKeyAndValue(array $json, $variationId): ?Pair
}
}
- $this->logger->error("Could not find the setting for the specified variation ID: '{VARIATION_ID}'.", [
+ $this->logger->error("Could not find the setting for the specified variation ID: '".$variationId."'.", [
'event_id' => 2011,
- 'VARIATION_ID' => $variationId
]);
+
return null;
}
private function getSettingsResult(): SettingsResult
{
- if ($this->overrides !== null) {
+ if (null !== $this->overrides) {
switch ($this->overrides->getBehaviour()) {
case OverrideBehaviour::LOCAL_ONLY:
- return new SettingsResult($this->overrides->getDataSource()->getOverrides(), 0);
+ return new SettingsResult($this->overrides->getDataSource()->getOverrides(), 0, true);
+
case OverrideBehaviour::LOCAL_OVER_REMOTE:
$local = $this->overrides->getDataSource()->getOverrides();
$remote = $this->getRemoteSettingsResult();
- return new SettingsResult(array_merge($remote->settings ?? [], $local), $remote->fetchTime);
+
+ return new SettingsResult(array_merge($remote->settings, $local), $remote->fetchTime, $remote->hasConfigJson);
+
default: // remote over local
$local = $this->overrides->getDataSource()->getOverrides();
$remote = $this->getRemoteSettingsResult();
- return new SettingsResult(array_merge($local, $remote->settings ?? []), $remote->fetchTime);
+
+ return new SettingsResult(array_merge($local, $remote->settings), $remote->fetchTime, $remote->hasConfigJson);
}
}
@@ -547,10 +578,10 @@ private function getRemoteSettingsResult(): SettingsResult
}
if (empty($cacheEntry->getConfig())) {
- return new SettingsResult(null, 0);
+ return new SettingsResult([], 0, false);
}
- return new SettingsResult($cacheEntry->getConfig()[Config::ENTRIES], $cacheEntry->getFetchTime());
+ return new SettingsResult($cacheEntry->getConfig()[Config::ENTRIES], $cacheEntry->getFetchTime(), true);
}
private function handleResponse(FetchResponse $response, ConfigEntry $cacheEntry): ConfigEntry
@@ -558,32 +589,16 @@ private function handleResponse(FetchResponse $response, ConfigEntry $cacheEntry
if ($response->isFetched()) {
$this->hooks->fireOnConfigChanged($response->getConfigEntry()->getConfig()[Config::ENTRIES]);
$this->cache->store($this->cacheKey, $response->getConfigEntry());
+
return $response->getConfigEntry();
- } elseif ($response->isNotModified()) {
+ }
+ if ($response->isNotModified()) {
$newEntry = $cacheEntry->withTime(Utils::getUnixMilliseconds());
$this->cache->store($this->cacheKey, $newEntry);
+
return $newEntry;
}
- return $cacheEntry;
- }
- private function getMonolog(): Logger
- {
- $handler = new ErrorLogHandler();
- // This is a slightly modified version of the default log message format used by LineFormatter
- // (see https://github.com/Seldaek/monolog/blob/3.3.1/src/Monolog/Formatter/LineFormatter.php#L28),
- // we just add the event ID.
- $formatter = new LineFormatter(
- "[%datetime%] %channel%.%level_name%: [%context.event_id%] %message% %context% %extra%\n",
- null,
- true,
- true
- );
- $handler->setFormatter($formatter);
- // We use placeholders for message arguments as defined by the PSR-3 standard
- // (see https://www.php-fig.org/psr/psr-3/#12-message). Since `true` is passed
- // as the 2nd argument, placeholder values will be removed from the context array.
- $psrProcessor = new PsrLogMessageProcessor(null, true);
- return new Logger("ConfigCat", [$handler], [$psrProcessor]);
+ return $cacheEntry;
}
}
diff --git a/src/ConfigCatClientException.php b/src/ConfigCatClientException.php
index 8ff0ab1..d81555d 100644
--- a/src/ConfigCatClientException.php
+++ b/src/ConfigCatClientException.php
@@ -1,7 +1,9 @@
urlPath = sprintf("configuration-files/%s/" . self::CONFIG_JSON_NAME, $sdkKey);
+ $this->urlPath = sprintf('configuration-files/%s/'.self::CONFIG_JSON_NAME, $sdkKey);
if (isset($options[ClientOptions::BASE_URL]) && !empty($options[ClientOptions::BASE_URL])) {
$this->baseUrl = $options[ClientOptions::BASE_URL];
$this->urlIsCustom = true;
- } elseif (isset($options[ClientOptions::DATA_GOVERNANCE]) &&
- DataGovernance::isValid($options[ClientOptions::DATA_GOVERNANCE])) {
+ } elseif (isset($options[ClientOptions::DATA_GOVERNANCE])
+ && DataGovernance::isValid($options[ClientOptions::DATA_GOVERNANCE])) {
$this->baseUrl = DataGovernance::isEuOnly($options[ClientOptions::DATA_GOVERNANCE])
? self::EU_ONLY_URL
: self::GLOBAL_URL;
@@ -73,51 +66,28 @@ public function __construct(string $sdkKey, InternalLogger $logger, array $optio
$this->baseUrl = self::GLOBAL_URL;
}
- $additionalOptions = isset($options[ClientOptions::REQUEST_OPTIONS])
- && is_array($options[ClientOptions::REQUEST_OPTIONS])
- && !empty($options[ClientOptions::REQUEST_OPTIONS])
- ? $options[ClientOptions::REQUEST_OPTIONS]
- : [];
-
- if (!isset($additionalOptions[RequestOptions::CONNECT_TIMEOUT])) {
- $additionalOptions[RequestOptions::CONNECT_TIMEOUT] = 10;
- }
-
- if (!isset($additionalOptions[RequestOptions::TIMEOUT])) {
- $additionalOptions[RequestOptions::TIMEOUT] = 30;
- }
+ $this->userAgentHeader = 'ConfigCat-PHP/'.ConfigCatClient::SDK_VERSION;
$this->logger = $logger;
- $this->requestOptions = array_merge([
- 'headers' => [
- 'X-ConfigCat-UserAgent' => "ConfigCat-PHP/" . ConfigCatClient::SDK_VERSION
- ],
- ], $additionalOptions);
-
- $this->clientOptions = isset($options[ClientOptions::CUSTOM_HANDLER])
- ? ['handler' => $options[ClientOptions::CUSTOM_HANDLER]]
- : [];
- $this->client = new Client($this->clientOptions);
+ $this->client = (isset($options[ClientOptions::FETCH_CLIENT])
+ && $options[ClientOptions::FETCH_CLIENT] instanceof FetchClientInterface)
+ ? $options[ClientOptions::FETCH_CLIENT]
+ : GuzzleFetchClient::create($options);
}
/**
* Gets the latest configuration from the network.
*
- * @param ?string $etag The ETag.
+ * @param ?string $etag the ETag
*
- * @return FetchResponse An object describing the result of the fetch.
+ * @return FetchResponse an object describing the result of the fetch
*/
public function fetch(?string $etag): FetchResponse
{
return $this->executeFetch($etag, $this->baseUrl, 2);
}
- public function getRequestOptions(): array
- {
- return $this->requestOptions;
- }
-
private function executeFetch(?string $etag, string $url, int $executionCount): FetchResponse
{
$response = $this->sendConfigFetchRequest($etag, $url);
@@ -126,7 +96,7 @@ private function executeFetch(?string $etag, string $url, int $executionCount):
return $response;
}
- $newUrl = "";
+ $newUrl = '';
if (isset($response->getConfigEntry()->getConfig()[Config::PREFERENCES][Preferences::BASE_URL])) {
$newUrl = $response->getConfigEntry()->getConfig()[Config::PREFERENCES][Preferences::BASE_URL];
}
@@ -136,21 +106,21 @@ private function executeFetch(?string $etag, string $url, int $executionCount):
$preferences = $response->getConfigEntry()->getConfig()[Config::PREFERENCES];
$redirect = $preferences[Preferences::REDIRECT];
- if ($this->urlIsCustom && $redirect != self::FORCE_REDIRECT) {
+ if ($this->urlIsCustom && self::FORCE_REDIRECT != $redirect) {
return $response;
}
- if ($redirect == self::NO_REDIRECT) {
+ if (self::NO_REDIRECT == $redirect) {
return $response;
}
- if ($redirect == self::SHOULD_REDIRECT) {
+ if (self::SHOULD_REDIRECT == $redirect) {
$this->logger->warning(
- "The `dataGovernance` parameter specified at the client initialization is ".
- "not in sync with the preferences on the ConfigCat Dashboard. " .
- "Read more: https://configcat.com/docs/advanced/data-governance/",
+ 'The `dataGovernance` parameter specified at the client initialization is '.
+ 'not in sync with the preferences on the ConfigCat Dashboard. '.
+ 'Read more: https://configcat.com/docs/advanced/data-governance/',
[
- 'event_id' => 3002
+ 'event_id' => 3002,
]
);
}
@@ -159,21 +129,27 @@ private function executeFetch(?string $etag, string $url, int $executionCount):
return $this->executeFetch($etag, $newUrl, $executionCount - 1);
}
- $this->logger->error("Redirection loop encountered while trying to fetch config JSON. Please contact us at https://configcat.com/support/", [
- 'event_id' => 1104
+ $this->logger->error('Redirection loop encountered while trying to fetch config JSON. Please contact us at https://configcat.com/support/', [
+ 'event_id' => 1104,
]);
+
return $response;
}
private function sendConfigFetchRequest(?string $etag, string $url): FetchResponse
{
+ $configJsonUrl = sprintf('%s/%s', $url, $this->urlPath);
+ $request = $this->client->createRequest('GET', $configJsonUrl)
+ ->withHeader('X-ConfigCat-UserAgent', $this->userAgentHeader)
+ ;
+
if (!empty($etag)) {
- $this->requestOptions['headers']['If-None-Match'] = $etag;
+ $request = $request->withHeader('If-None-Match', $etag);
}
try {
- $configJsonUrl = sprintf("%s/%s", $url, $this->urlPath);
- $response = $this->client->get($configJsonUrl, $this->requestOptions);
+ $fetchClient = $this->client->getClient();
+ $response = $fetchClient->sendRequest($request);
$statusCode = $response->getStatusCode();
if ($response->hasHeader(self::ETAG_HEADER)) {
@@ -181,52 +157,40 @@ private function sendConfigFetchRequest(?string $etag, string $url): FetchRespon
}
if ($statusCode >= 200 && $statusCode < 300) {
- $this->logger->debug("Fetch was successful: new config fetched.");
+ $this->logger->debug('Fetch was successful: new config fetched.');
- $entry = ConfigEntry::fromConfigJson($response->getBody(), $etag, Utils::getUnixMilliseconds());
- if (json_last_error() !== JSON_ERROR_NONE) {
- $message = "Fetching config JSON was successful but the HTTP response content was invalid. JSON error: {JSON_ERROR}";
+ $entry = ConfigEntry::fromConfigJson((string) $response->getBody(), $etag ?? '', Utils::getUnixMilliseconds());
+ if (JSON_ERROR_NONE !== json_last_error()) {
+ $message = 'Fetching config JSON was successful but the HTTP response content was invalid. JSON error: '.json_last_error_msg();
$messageCtx = [
'event_id' => 1105,
- 'JSON_ERROR' => json_last_error_msg()
];
$this->logger->error($message, $messageCtx);
+
return FetchResponse::failure(InternalLogger::format($message, $messageCtx));
}
return FetchResponse::success($entry);
- } elseif ($statusCode === 304) {
- $this->logger->debug("Fetch was successful: config not modified.");
+ }
+ if (304 === $statusCode) {
+ $this->logger->debug('Fetch was successful: config not modified.');
+
return FetchResponse::notModified();
}
- $message = "Your SDK Key seems to be wrong. You can find the valid SDK Key at https://app.configcat.com/sdkkey. " .
- "Received unexpected response: {STATUS_CODE}";
+ $message = 'Your SDK Key seems to be wrong. You can find the valid SDK Key at https://app.configcat.com/sdkkey. '.
+ "Received unexpected response: {$statusCode}";
$messageCtx = [
'event_id' => 1100,
- 'STATUS_CODE' => $statusCode
- ];
- $this->logger->error($message, $messageCtx);
- return FetchResponse::failure(InternalLogger::format($message, $messageCtx));
- } catch (ConnectException $exception) {
- $connTimeout = $this->requestOptions[RequestOptions::CONNECT_TIMEOUT];
- $timeout = $this->requestOptions[RequestOptions::TIMEOUT];
- $message = "Request timed out while trying to fetch config JSON. Timeout values: [connect: {CONN_TIMEOUT}s, timeout: {TIMEOUT}s]";
- $messageCtx = [
- 'event_id' => 1102, 'exception' => $exception,
- 'CONN_TIMEOUT' => $connTimeout, 'TIMEOUT' => $timeout,
];
$this->logger->error($message, $messageCtx);
+
return FetchResponse::failure(InternalLogger::format($message, $messageCtx));
- } catch (GuzzleException $exception) {
- $message = "Unexpected HTTP response was received while trying to fetch config JSON.";
- $messageCtx = ['event_id' => 1101, 'exception' => $exception];
- $this->logger->error($message, $messageCtx);
- return FetchResponse::failure($message);
- } catch (Exception $exception) {
- $message = "Unexpected error occurred while trying to fetch config JSON.";
+ } catch (ClientExceptionInterface $exception) {
+ $message = 'Unexpected error occurred while trying to fetch config JSON.';
$messageCtx = ['event_id' => 1103, 'exception' => $exception];
$this->logger->error($message, $messageCtx);
+
return FetchResponse::failure($message);
}
}
diff --git a/src/DataGovernance.php b/src/DataGovernance.php
index 0a8e832..add5452 100644
--- a/src/DataGovernance.php
+++ b/src/DataGovernance.php
@@ -1,30 +1,32 @@
entries[] = $entry;
+ return implode(PHP_EOL, $this->entries);
}
- public function __toString(): string
+ public function add(string $entry): void
{
- return implode(PHP_EOL, $this->entries);
+ $this->entries[] = $entry;
}
}
diff --git a/src/EvaluationResult.php b/src/EvaluationResult.php
index b7994c2..08c3cb4 100644
--- a/src/EvaluationResult.php
+++ b/src/EvaluationResult.php
@@ -1,5 +1,7 @@
status === self::FETCHED;
+ return self::FETCHED === $this->status;
}
/**
* Returns true when the response is in not modified state.
*
- * @return bool True if the fetched configurations was not modified, otherwise false.
+ * @return bool true if the fetched configurations was not modified, otherwise false
*/
public function isNotModified(): bool
{
- return $this->status === self::NOT_MODIFIED;
+ return self::NOT_MODIFIED === $this->status;
}
/**
* Returns true when the response is in failed state.
*
- * @return bool True if the fetch failed, otherwise false.
+ * @return bool true if the fetch failed, otherwise false
*/
public function isFailed(): bool
{
- return $this->status === self::FAILED;
+ return self::FAILED === $this->status;
}
/**
* Returns the produced config entry.
*
- * @return ConfigEntry The produced config entry.
+ * @return ConfigEntry the produced config entry
*/
public function getConfigEntry(): ConfigEntry
{
@@ -100,7 +105,7 @@ public function getConfigEntry(): ConfigEntry
/**
* Returns the error if the fetch failed.
*
- * @return ?string The error.
+ * @return ?string the error
*/
public function getError(): ?string
{
diff --git a/src/Hooks.php b/src/Hooks.php
index 0f46524..ded72af 100644
--- a/src/Hooks.php
+++ b/src/Hooks.php
@@ -1,15 +1,27 @@
$settings
+ *
* @internal
*/
public function fireOnConfigChanged(array $settings): void
diff --git a/src/Http/FetchClientInterface.php b/src/Http/FetchClientInterface.php
new file mode 100644
index 0000000..c319aa5
--- /dev/null
+++ b/src/Http/FetchClientInterface.php
@@ -0,0 +1,28 @@
+ $options
+ */
+ private function __construct(array $options = [])
+ {
+ if (!isset($options[RequestOptions::CONNECT_TIMEOUT])) {
+ $options[RequestOptions::CONNECT_TIMEOUT] = 10;
+ }
+
+ if (!isset($options[RequestOptions::TIMEOUT])) {
+ $options[RequestOptions::TIMEOUT] = 30;
+ }
+
+ if (isset($options[ClientOptions::CUSTOM_HANDLER])) {
+ $options['handler'] = $options[ClientOptions::CUSTOM_HANDLER];
+ }
+
+ $requestOptions = isset($options[ClientOptions::REQUEST_OPTIONS])
+ && is_array($options[ClientOptions::REQUEST_OPTIONS])
+ && !empty($options[ClientOptions::REQUEST_OPTIONS])
+ ? $options[ClientOptions::REQUEST_OPTIONS]
+ : [];
+
+ $this->client = new Client(array_merge($options, $requestOptions));
+ }
+
+ public function getClient(): ClientInterface
+ {
+ return $this->client;
+ }
+
+ public function createRequest(string $method, string $uri): RequestInterface
+ {
+ return new Request($method, $uri);
+ }
+
+ /**
+ * Constructs a \GuzzleHttp\Client to handle the HTTP requests initiated by the SDK.
+ *
+ * @param array $options options for the underlying \GuzzleHttp\Client
+ *
+ * @return FetchClientInterface the constructed fetch client that works with \GuzzleHttp\Client
+ */
+ public static function create(array $options = []): FetchClientInterface
+ {
+ return new GuzzleFetchClient($options);
+ }
+}
diff --git a/src/Log/DefaultLogger.php b/src/Log/DefaultLogger.php
new file mode 100644
index 0000000..facc05c
--- /dev/null
+++ b/src/Log/DefaultLogger.php
@@ -0,0 +1,86 @@
+format('Y-m-d\\TH:i:sP');
+ $context['level'] = LogLevel::asString($level);
+
+ $final = '[{timestamp}] ConfigCat.{level}: '.$message;
+
+ error_log(self::interpolate($final, $context));
+ }
+
+ /**
+ * @param mixed[] $context
+ */
+ private static function interpolate(string|Stringable $message, array $context = []): string
+ {
+ $replace = [];
+ foreach ($context as $key => $val) {
+ if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
+ $replace['{'.$key.'}'] = $val;
+ }
+ }
+
+ return strtr((string) $message, $replace);
+ }
+}
diff --git a/src/Log/InternalLogger.php b/src/Log/InternalLogger.php
index 5d7e772..c391ca1 100644
--- a/src/Log/InternalLogger.php
+++ b/src/Log/InternalLogger.php
@@ -1,36 +1,37 @@
hooks->fireOnError(self::format($message, $context));
if ($this->shouldLog(LogLevel::EMERGENCY, $context)) {
- $this->ensureEventId($context);
- $this->logger->emergency($message, $context);
+ $enriched = $this->enrichMessage($message, $context);
+ $this->logger->emergency($enriched, $context);
}
}
@@ -38,8 +39,8 @@ public function alert($message, array $context = []): void
{
$this->hooks->fireOnError(self::format($message, $context));
if ($this->shouldLog(LogLevel::ALERT, $context)) {
- $this->ensureEventId($context);
- $this->logger->alert($message, $context);
+ $enriched = $this->enrichMessage($message, $context);
+ $this->logger->alert($enriched, $context);
}
}
@@ -47,8 +48,8 @@ public function critical($message, array $context = []): void
{
$this->hooks->fireOnError(self::format($message, $context));
if ($this->shouldLog(LogLevel::CRITICAL, $context)) {
- $this->ensureEventId($context);
- $this->logger->critical($message, $context);
+ $enriched = $this->enrichMessage($message, $context);
+ $this->logger->critical($enriched, $context);
}
}
@@ -56,40 +57,40 @@ public function error($message, array $context = []): void
{
$this->hooks->fireOnError(self::format($message, $context));
if ($this->shouldLog(LogLevel::ERROR, $context)) {
- $this->ensureEventId($context);
- $this->logger->error($message, $context);
+ $enriched = $this->enrichMessage($message, $context);
+ $this->logger->error($enriched, $context);
}
}
public function warning($message, array $context = []): void
{
if ($this->shouldLog(LogLevel::WARNING, $context)) {
- $this->ensureEventId($context);
- $this->logger->warning($message, $context);
+ $enriched = $this->enrichMessage($message, $context);
+ $this->logger->warning($enriched, $context);
}
}
public function notice($message, array $context = []): void
{
if ($this->shouldLog(LogLevel::NOTICE, $context)) {
- $this->ensureEventId($context);
- $this->logger->notice($message, $context);
+ $enriched = $this->enrichMessage($message, $context);
+ $this->logger->notice($enriched, $context);
}
}
public function info($message, array $context = []): void
{
if ($this->shouldLog(LogLevel::INFO, $context)) {
- $this->ensureEventId($context);
- $this->logger->info($message, $context);
+ $enriched = $this->enrichMessage($message, $context);
+ $this->logger->info($enriched, $context);
}
}
public function debug($message, array $context = []): void
{
if ($this->shouldLog(LogLevel::DEBUG, $context)) {
- $this->ensureEventId($context);
- $this->logger->debug($message, $context);
+ $enriched = $this->enrichMessage($message, $context);
+ $this->logger->debug($enriched, $context);
}
}
@@ -98,51 +99,49 @@ public function log($level, $message, array $context = []): void
// Do nothing, only the leveled methods should be used.
}
- private function shouldLog($currentLevel, array $context): bool
+ /**
+ * @param mixed[] $context
+ */
+ public static function format(string|Stringable $message, array $context = []): string
+ {
+ if (array_key_exists('exception', $context)) {
+ $message = $message.PHP_EOL.$context['exception']->getMessage();
+ }
+
+ return (string) $message;
+ }
+
+ /**
+ * @param mixed[] $context
+ */
+ private function shouldLog(int $currentLevel, array $context): bool
{
return $currentLevel >= $this->globalLevel && !$this->hasAnythingToIgnore($context);
}
+ /**
+ * @param mixed[] $context
+ */
private function hasAnythingToIgnore(array $context): bool
{
- if (empty($this->exceptionsToIgnore) ||
- empty($context) ||
- !isset($context['exception'])) {
+ if (empty($this->exceptionsToIgnore)
+ || empty($context)
+ || !isset($context['exception'])) {
return false;
}
return in_array(get_class($context['exception']), $this->exceptionsToIgnore);
}
- private function ensureEventId(array &$context): void
+ /**
+ * @param mixed[] $context
+ */
+ private function enrichMessage(string|Stringable $message, array &$context): string
{
if (!array_key_exists('event_id', $context)) {
$context['event_id'] = 0;
}
- }
-
- public static function format(string $message, array $context): string
- {
- // Format PSR-3 log message by reusing PsrLogMessageProcessor's logic
- // (see https://www.php-fig.org/psr/psr-3/#12-message).
- static $psrProcessor = null;
- if (is_null($psrProcessor)) {
- $psrProcessor = new PsrLogMessageProcessor();
- }
-
- // Before v3.0, Monolog didn't have the LogRecord class but used a simple array.
- if (class_exists('\Monolog\LogRecord')) {
- $rec = new LogRecord(new DateTimeImmutable('@0'), "", Level::Notice, $message, $context);
- $message = $psrProcessor->__invoke($rec)->message;
- } else {
- $rec = ['message' => $message, 'context' => $context];
- $message = $psrProcessor->__invoke($rec)['message'];
- }
-
- if (array_key_exists('exception', $context)) {
- $message = $message . PHP_EOL . $context['exception']->getMessage();
- }
- return $message;
+ return self::format('[{event_id}] '.$message);
}
}
diff --git a/src/Log/LogLevel.php b/src/Log/LogLevel.php
index c4a1b38..bb93275 100644
--- a/src/Log/LogLevel.php
+++ b/src/Log/LogLevel.php
@@ -1,10 +1,11 @@
'DEBUG',
+ self::INFO => 'INFO',
+ self::NOTICE => 'NOTICE',
+ self::WARNING => 'WARNING',
+ self::ERROR => 'ERROR',
+ self::CRITICAL => 'CRITICAL',
+ self::ALERT => 'ALERT',
+ self::EMERGENCY => 'EMERGENCY',
+ self::NO_LOG => 'NO_LOG',
+ default => '',
+ };
}
}
diff --git a/src/Override/ArrayDataSource.php b/src/Override/ArrayDataSource.php
index f542219..edcb831 100644
--- a/src/Override/ArrayDataSource.php
+++ b/src/Override/ArrayDataSource.php
@@ -1,36 +1,37 @@
$overrides the array that contains the overrides
*/
- public function __construct(private readonly array $overrides)
- {
- }
+ public function __construct(private readonly array $overrides) {}
/**
* Gets the overrides.
- * @return array The overrides.
+ *
+ * @return mixed[] the overrides
*/
public function getOverrides(): array
{
$result = [];
foreach ($this->overrides as $key => $value) {
$result[$key] = [
- SettingAttributes::VALUE => $value
+ SettingAttributes::VALUE => $value,
];
}
+
return $result;
}
}
diff --git a/src/Override/FlagOverrides.php b/src/Override/FlagOverrides.php
index 9c8a7ab..7bbf5f5 100644
--- a/src/Override/FlagOverrides.php
+++ b/src/Override/FlagOverrides.php
@@ -1,5 +1,7 @@
filePath);
- if ($content === false) {
- $this->logger->error("Cannot find the local config file '{FILE_PATH}'. ' .
- 'This is a path that your application provided to the ConfigCat SDK by passing it to the `FlagOverrides.LocalFile()` method. ' .
+ if (false === $content) {
+ $this->logger->error("Cannot find the local config file '".$this->filePath."'. ' .
+ 'This is a path that your application provided to the ConfigCat SDK by passing it to the `FlagOverrides.LocalFile()` method. ' .
'Read more: https://configcat.com/docs/sdk-reference/php/#json-file", [
- 'event_id' => 1300,
- 'FILE_PATH' => $this->filePath
- ]);
- return null;
+ 'event_id' => 1300,
+ ]);
+
+ return [];
}
$json = json_decode($content, true);
- if ($json == null) {
- $this->logger->error("Failed to decode JSON from the local config file '{FILE_PATH}'. JSON error: {JSON_ERROR}", [
+ if (null == $json) {
+ $this->logger->error("Failed to decode JSON from the local config file '".$this->filePath."'. JSON error: ".json_last_error_msg(), [
'event_id' => 2302,
- 'FILE_PATH' => $this->filePath, 'JSON_ERROR' => json_last_error_msg()
]);
- return null;
+
+ return [];
}
if (isset($json['flags'])) {
$result = [];
foreach ($json['flags'] as $key => $value) {
$result[$key] = [
- SettingAttributes::VALUE => $value
+ SettingAttributes::VALUE => $value,
];
}
+
return $result;
}
+
return $json[Config::ENTRIES];
}
}
diff --git a/src/Override/OverrideBehaviour.php b/src/Override/OverrideBehaviour.php
index a3d6ec7..a94e094 100644
--- a/src/Override/OverrideBehaviour.php
+++ b/src/Override/OverrideBehaviour.php
@@ -1,10 +1,11 @@
$overrides the array that contains the overrides
+ *
+ * @return OverrideDataSource the constructed data source
*/
public static function localArray(array $overrides): OverrideDataSource
{
diff --git a/src/Pair.php b/src/Pair.php
index 2da39ec..7adb225 100644
--- a/src/Pair.php
+++ b/src/Pair.php
@@ -1,27 +1,24 @@
(SemVer)",
- ">= (SemVer)",
- "= (Number)",
- "<> (Number)",
- "< (Number)",
- "<= (Number)",
- "> (Number)",
- ">= (Number)",
- "IS ONE OF (Sensitive)",
- "IS NOT ONE OF (Sensitive)"
+ 'IS ONE OF',
+ 'IS NOT ONE OF',
+ 'CONTAINS',
+ 'DOES NOT CONTAIN',
+ 'IS ONE OF (SemVer)',
+ 'IS NOT ONE OF (SemVer)',
+ '< (SemVer)',
+ '<= (SemVer)',
+ '> (SemVer)',
+ '>= (SemVer)',
+ '= (Number)',
+ '<> (Number)',
+ '< (Number)',
+ '<= (Number)',
+ '> (Number)',
+ '>= (Number)',
+ 'IS ONE OF (Sensitive)',
+ 'IS NOT ONE OF (Sensitive)',
];
/**
* RolloutEvaluator constructor.
*
- * @param InternalLogger $logger The logger instance.
+ * @param InternalLogger $logger the logger instance
*/
- public function __construct(private readonly InternalLogger $logger)
- {
- }
+ public function __construct(private readonly InternalLogger $logger) {}
/**
* Evaluates a requested value from the configuration by the specified roll-out rules.
*
- * @param string $key The key of the desired value.
- * @param array $json The decoded JSON configuration.
- * @param EvaluationLogCollector $logCollector The evaluation log collector.
- * @param ?User $user Optional. The user to identify the caller.
- * @return EvaluationResult The evaluation result.
+ * @param string $key the key of the desired value
+ * @param array $json the decoded JSON configuration
+ * @param EvaluationLogCollector $logCollector the evaluation log collector
+ * @param ?User $user Optional. The user to identify the caller.
+ *
+ * @return EvaluationResult the evaluation result
*/
public function evaluate(
string $key,
@@ -62,33 +66,33 @@ public function evaluate(
EvaluationLogCollector $logCollector,
?User $user = null
): EvaluationResult {
- if ($user === null) {
- if (isset($json[SettingAttributes::ROLLOUT_RULES]) &&
- !empty($json[SettingAttributes::ROLLOUT_RULES]) ||
- isset($json[SettingAttributes::ROLLOUT_PERCENTAGE_ITEMS]) &&
- !empty($json[SettingAttributes::ROLLOUT_PERCENTAGE_ITEMS])) {
- $this->logger->warning("Cannot evaluate targeting rules and % options for setting '{KEY}' (User Object is missing). " .
- "You should pass a User Object to the evaluation methods like `getValue()` in order to make targeting work properly. " .
- "Read more: https://configcat.com/docs/advanced/user-object/", [
+ if (null === $user) {
+ if (isset($json[SettingAttributes::ROLLOUT_RULES])
+ && !empty($json[SettingAttributes::ROLLOUT_RULES])
+ || isset($json[SettingAttributes::ROLLOUT_PERCENTAGE_ITEMS])
+ && !empty($json[SettingAttributes::ROLLOUT_PERCENTAGE_ITEMS])) {
+ $this->logger->warning("Cannot evaluate targeting rules and % options for setting '".$key."' (User Object is missing). ".
+ 'You should pass a User Object to the evaluation methods like `getValue()` in order to make targeting work properly. '.
+ 'Read more: https://configcat.com/docs/advanced/user-object/', [
'event_id' => 3001,
- 'KEY' => $key
]);
}
$result = $json[SettingAttributes::VALUE];
- $variationId = $json[SettingAttributes::VARIATION_ID] ?? "";
- $logCollector->add("Returning " . Utils::getStringRepresentation($result) . ".");
+ $variationId = $json[SettingAttributes::VARIATION_ID] ?? '';
+ $logCollector->add('Returning '.Utils::getStringRepresentation($result).'.');
+
return new EvaluationResult($result, $variationId, null, null);
}
- $logCollector->add("User object: " . $user);
+ $logCollector->add('User object: '.$user);
if (isset($json[SettingAttributes::ROLLOUT_RULES]) && !empty($json[SettingAttributes::ROLLOUT_RULES])) {
foreach ($json[SettingAttributes::ROLLOUT_RULES] as $rule) {
$comparisonAttribute = $rule[RolloutAttributes::COMPARISON_ATTRIBUTE];
$comparisonValue = $rule[RolloutAttributes::COMPARISON_VALUE];
$comparator = $rule[RolloutAttributes::COMPARATOR];
$value = $rule[RolloutAttributes::VALUE];
- $variationId = $rule[RolloutAttributes::VARIATION_ID] ?? "";
+ $variationId = $rule[RolloutAttributes::VARIATION_ID] ?? '';
$userValue = $user->getAttribute($comparisonAttribute);
if (empty($comparisonValue) || (!is_numeric($userValue) && empty($userValue))) {
@@ -98,11 +102,12 @@ public function evaluate(
$comparator,
$comparisonValue
));
+
continue;
}
switch ($comparator) {
- //IS ONE OF
+ // IS ONE OF
case 0:
$split = array_filter(Utils::splitTrim($comparisonValue));
if (in_array($userValue, $split, true)) {
@@ -113,10 +118,13 @@ public function evaluate(
$comparisonValue,
$value
));
+
return new EvaluationResult($value, $variationId, $rule, null);
}
+
break;
- //IS NOT ONE OF
+
+ // IS NOT ONE OF
case 1:
$split = array_filter(Utils::splitTrim($comparisonValue));
if (!in_array($userValue, $split, true)) {
@@ -127,10 +135,13 @@ public function evaluate(
$comparisonValue,
$value
));
+
return new EvaluationResult($value, $variationId, $rule, null);
}
+
break;
- //CONTAINS
+
+ // CONTAINS
case 2:
if (Utils::strContains($userValue, $comparisonValue)) {
$logCollector->add($this->logMatch(
@@ -140,10 +151,13 @@ public function evaluate(
$comparisonValue,
$value
));
+
return new EvaluationResult($value, $variationId, $rule, null);
}
+
break;
- //DOES NOT CONTAIN
+
+ // DOES NOT CONTAIN
case 3:
if (!Utils::strContains($userValue, $comparisonValue)) {
$logCollector->add($this->logMatch(
@@ -153,20 +167,24 @@ public function evaluate(
$comparisonValue,
$value
));
+
return new EvaluationResult($value, $variationId, $rule, null);
}
+
break;
- //IS ONE OF, IS NOT ONE OF (SemVer)
+
+ // IS ONE OF, IS NOT ONE OF (SemVer)
case 4:
case 5:
$split = array_filter(Utils::splitTrim($comparisonValue));
+
try {
$matched = false;
foreach ($split as $semVer) {
$matched = Version::equal($userValue, $semVer) || $matched;
}
- if (($matched && $comparator == 4) || (!$matched && $comparator == 5)) {
+ if (($matched && 4 == $comparator) || (!$matched && 5 == $comparator)) {
$logCollector->add($this->logMatch(
$comparisonAttribute,
$userValue,
@@ -174,6 +192,7 @@ public function evaluate(
$comparisonValue,
$value
));
+
return new EvaluationResult($value, $variationId, $rule, null);
}
} catch (SemverException) {
@@ -184,24 +203,26 @@ public function evaluate(
$comparisonValue,
$value
));
+
break;
}
break;
- //LESS THAN, LESS THAN OR EQUALS TO, GREATER THAN, GREATER THAN OR EQUALS TO (SemVer)
+
+ // LESS THAN, LESS THAN OR EQUALS TO, GREATER THAN, GREATER THAN OR EQUALS TO (SemVer)
case 6:
case 7:
case 8:
case 9:
try {
- if (($comparator == 6 &&
- Version::lessThan($userValue, $comparisonValue)) ||
- ($comparator == 7 &&
- Version::lessThanOrEqual($userValue, $comparisonValue)) ||
- ($comparator == 8 &&
- Version::greaterThan($userValue, $comparisonValue)) ||
- ($comparator == 9 &&
- Version::greaterThanOrEqual($userValue, $comparisonValue))) {
+ if ((6 == $comparator
+ && Version::lessThan($userValue, $comparisonValue))
+ || (7 == $comparator
+ && Version::lessThanOrEqual($userValue, $comparisonValue))
+ || (8 == $comparator
+ && Version::greaterThan($userValue, $comparisonValue))
+ || (9 == $comparator
+ && Version::greaterThanOrEqual($userValue, $comparisonValue))) {
$logCollector->add($this->logMatch(
$comparisonAttribute,
$userValue,
@@ -209,6 +230,7 @@ public function evaluate(
$comparisonValue,
$value
));
+
return new EvaluationResult($value, $variationId, $rule, null);
}
} catch (SemverException $exception) {
@@ -219,26 +241,30 @@ public function evaluate(
$comparisonValue,
$exception
));
+
break;
}
+
break;
- //LESS THAN, LESS THAN OR EQUALS TO, GREATER THAN, GREATER THAN OR EQUALS TO (Number)
+
+ // LESS THAN, LESS THAN OR EQUALS TO, GREATER THAN, GREATER THAN OR EQUALS TO (Number)
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
- $userDouble = str_replace(",", ".", $userValue);
- $comparisonDouble = str_replace(",", ".", $comparisonValue);
+ $userDouble = str_replace(',', '.', $userValue);
+ $comparisonDouble = str_replace(',', '.', $comparisonValue);
if (!is_numeric($userDouble)) {
$logCollector->add($this->logFormatErrorWithMessage(
$comparisonAttribute,
$userValue,
$comparator,
$comparisonValue,
- $userDouble . "is not a valid number."
+ $userDouble.'is not a valid number.'
));
+
break;
}
@@ -248,20 +274,21 @@ public function evaluate(
$userValue,
$comparator,
$comparisonValue,
- $comparisonDouble . "is not a valid number."
+ $comparisonDouble.'is not a valid number.'
));
+
break;
}
$userDoubleValue = floatval($userDouble);
$comparisonDoubleValue = floatval($comparisonDouble);
- if (($comparator == 10 && $userDoubleValue == $comparisonDoubleValue) ||
- ($comparator == 11 && $userDoubleValue != $comparisonDoubleValue) ||
- ($comparator == 12 && $userDoubleValue < $comparisonDoubleValue) ||
- ($comparator == 13 && $userDoubleValue <= $comparisonDoubleValue) ||
- ($comparator == 14 && $userDoubleValue > $comparisonDoubleValue) ||
- ($comparator == 15 && $userDoubleValue >= $comparisonDoubleValue)) {
+ if ((10 == $comparator && $userDoubleValue == $comparisonDoubleValue)
+ || (11 == $comparator && $userDoubleValue != $comparisonDoubleValue)
+ || (12 == $comparator && $userDoubleValue < $comparisonDoubleValue)
+ || (13 == $comparator && $userDoubleValue <= $comparisonDoubleValue)
+ || (14 == $comparator && $userDoubleValue > $comparisonDoubleValue)
+ || (15 == $comparator && $userDoubleValue >= $comparisonDoubleValue)) {
$logCollector->add($this->logMatch(
$comparisonAttribute,
$userValue,
@@ -269,10 +296,13 @@ public function evaluate(
$comparisonValue,
$value
));
+
return new EvaluationResult($value, $variationId, $rule, null);
}
+
break;
- //IS ONE OF (Sensitive)
+
+ // IS ONE OF (Sensitive)
case 16:
$split = array_filter(Utils::splitTrim($comparisonValue));
if (in_array(sha1($userValue), $split, true)) {
@@ -283,10 +313,13 @@ public function evaluate(
$comparisonValue,
$value
));
+
return new EvaluationResult($value, $variationId, $rule, null);
}
+
break;
- //IS NOT ONE OF (Sensitive)
+
+ // IS NOT ONE OF (Sensitive)
case 17:
$split = array_filter(Utils::splitTrim($comparisonValue));
if (!in_array(sha1($userValue), $split, true)) {
@@ -297,17 +330,19 @@ public function evaluate(
$comparisonValue,
$value
));
+
return new EvaluationResult($value, $variationId, $rule, null);
}
+
break;
}
$logCollector->add($this->logNoMatch($comparisonAttribute, $userValue, $comparator, $comparisonValue));
}
}
- if (isset($json[SettingAttributes::ROLLOUT_PERCENTAGE_ITEMS]) &&
- !empty($json[SettingAttributes::ROLLOUT_PERCENTAGE_ITEMS])) {
- $hashCandidate = $key . $user->getIdentifier();
+ if (isset($json[SettingAttributes::ROLLOUT_PERCENTAGE_ITEMS])
+ && !empty($json[SettingAttributes::ROLLOUT_PERCENTAGE_ITEMS])) {
+ $hashCandidate = $key.$user->getIdentifier();
$stringHash = substr(sha1($hashCandidate), 0, 7);
$intHash = intval($stringHash, 16);
$scale = $intHash % 100;
@@ -319,58 +354,71 @@ public function evaluate(
$result = $rule[PercentageAttributes::VALUE];
$variationId = $rule[PercentageAttributes::VARIATION_ID];
$logCollector->add(
- "Evaluating % options. Returning " . Utils::getStringRepresentation($result) . "."
+ 'Evaluating % options. Returning '.Utils::getStringRepresentation($result).'.'
);
+
return new EvaluationResult($result, $variationId, null, $rule);
}
}
}
$result = $json[SettingAttributes::VALUE];
- $variationId = $json[SettingAttributes::VARIATION_ID] ?? "";
- $logCollector->add("Returning " . Utils::getStringRepresentation($result) . ".");
+ $variationId = $json[SettingAttributes::VARIATION_ID] ?? '';
+ $logCollector->add('Returning '.Utils::getStringRepresentation($result).'.');
+
return new EvaluationResult($result, $variationId, null, null);
}
- private function logMatch($comparisonAttribute, $userValue, $comparator, $comparisonValue, $value): string
- {
- return "Evaluating rule: [" . $comparisonAttribute . ":" . $userValue . "] " .
- "[" . $this->comparatorTexts[$comparator] . "] " .
- "[" . $comparisonValue . "] => match, returning: " . Utils::getStringRepresentation($value) . ".";
+ private function logMatch(
+ string $comparisonAttribute,
+ string $userValue,
+ int $comparator,
+ string $comparisonValue,
+ mixed $value
+ ): string {
+ return 'Evaluating rule: ['.$comparisonAttribute.':'.$userValue.'] '.
+ '['.$this->comparatorTexts[$comparator].'] '.
+ '['.$comparisonValue.'] => match, returning: '.Utils::getStringRepresentation($value).'.';
}
- private function logNoMatch($comparisonAttribute, $userValue, $comparator, $comparisonValue): string
- {
- return "Evaluating rule: [" . $comparisonAttribute . ":" . $userValue . "] " .
- "[" . $this->comparatorTexts[$comparator] . "] " .
- "[" . $comparisonValue . "] => no match.";
+ private function logNoMatch(
+ string $comparisonAttribute,
+ ?string $userValue,
+ int $comparator,
+ string $comparisonValue
+ ): string {
+ return 'Evaluating rule: ['.$comparisonAttribute.':'.$userValue.'] '.
+ '['.$this->comparatorTexts[$comparator].'] '.
+ '['.$comparisonValue.'] => no match.';
}
private function logFormatError(
- $comparisonAttribute,
- $userValue,
- $comparator,
- $comparisonValue,
+ string $comparisonAttribute,
+ string $userValue,
+ int $comparator,
+ string $comparisonValue,
Exception $exception
): string {
- $message = "Evaluating rule: [" . $comparisonAttribute . ":" . $userValue . "] " .
- "[" . $this->comparatorTexts[$comparator] . "] " .
- "[" . $comparisonValue . "] => SKIP rule. Validation error: " . $exception->getMessage() . ".";
+ $message = 'Evaluating rule: ['.$comparisonAttribute.':'.$userValue.'] '.
+ '['.$this->comparatorTexts[$comparator].'] '.
+ '['.$comparisonValue.'] => SKIP rule. Validation error: '.$exception->getMessage().'.';
$this->logger->warning($message, ['exception' => $exception]);
+
return $message;
}
private function logFormatErrorWithMessage(
- $comparisonAttribute,
- $userValue,
- $comparator,
- $comparisonValue,
- $message
+ string $comparisonAttribute,
+ string $userValue,
+ int $comparator,
+ string $comparisonValue,
+ string $message
): string {
- $message = "Evaluating rule: [" . $comparisonAttribute . ":" . $userValue . "] " .
- "[" . $this->comparatorTexts[$comparator] . "] " .
- "[" . $comparisonValue . "] => SKIP rule. Validation error: " . $message . ".";
+ $message = 'Evaluating rule: ['.$comparisonAttribute.':'.$userValue.'] '.
+ '['.$this->comparatorTexts[$comparator].'] '.
+ '['.$comparisonValue.'] => SKIP rule. Validation error: '.$message.'.';
$this->logger->warning($message);
+
return $message;
}
}
diff --git a/src/SettingsResult.php b/src/SettingsResult.php
index daece65..f3cc273 100644
--- a/src/SettingsResult.php
+++ b/src/SettingsResult.php
@@ -1,5 +1,7 @@
+ */
private array $attributes = [];
/**
* User constructor.
*
- * @param string $identifier The identifier of the user.
- * @param string $email Optional. The email of the user.
- * @param string $country Optional. The country attribute of the user.
- * @param array $custom Custom user attributes.
+ * @param string $identifier the identifier of the user
+ * @param string $email Optional. The email of the user.
+ * @param string $country Optional. The country attribute of the user.
+ * @param array $custom custom user attributes
*/
public function __construct(
string $identifier,
- string $email = "",
- string $country = "",
+ string $email = '',
+ string $country = '',
array $custom = []
) {
$this->identifier = $this->attributes['Identifier'] = $identifier;
@@ -40,10 +45,23 @@ public function __construct(
}
}
+ /**
+ * @return string the string representation of the user
+ */
+ public function __toString(): string
+ {
+ $result = json_encode($this->attributes);
+ if (!$result) {
+ return '';
+ }
+
+ return $result;
+ }
+
/**
* Gets the identifier of the user.
*
- * @return string The identifier of the user.
+ * @return string the identifier of the user
*/
public function getIdentifier(): string
{
@@ -53,19 +71,12 @@ public function getIdentifier(): string
/**
* Gets a user attribute identified by the given key.
*
- * @param string $key The key of the user attribute.
- * @return string|null The user attribute, or null if it doesn't exist.
+ * @param string $key the key of the user attribute
+ *
+ * @return null|string the user attribute, or null if it doesn't exist
*/
public function getAttribute(string $key): ?string
{
return array_key_exists($key, $this->attributes) ? $this->attributes[$key] : null;
}
-
- /**
- * @return string The string representation of the user.
- */
- public function __toString(): string
- {
- return json_encode($this->attributes);
- }
}
diff --git a/src/Utils.php b/src/Utils.php
index 4be70ea..c508854 100644
--- a/src/Utils.php
+++ b/src/Utils.php
@@ -1,10 +1,12 @@
format('Uv');
- $etag = "test-etag";
+ $time = (float) $dateTime->format('Uv');
+ $etag = 'test-etag';
- $expectedPayload = "1686756435844\ntest-etag\n" . $testJson;
+ $expectedPayload = "1686756435844\ntest-etag\n".$testJson;
$entry = ConfigEntry::fromConfigJson($testJson, $etag, $time);
@@ -41,26 +42,33 @@ public function testCachePayload()
/**
* @dataProvider cacheKeyTestData
+ *
+ * @param mixed $sdkKey
+ * @param mixed $cacheKey
*/
public function testCacheKeyGeneration($sdkKey, $cacheKey)
{
$cache = $this->getMockBuilder(ConfigCache::class)->getMock();
$client = new ConfigCatClient($sdkKey, [
- ClientOptions::CACHE => $cache,
- ClientOptions::CUSTOM_HANDLER => new MockHandler(
+ ClientOptions::CACHE => $cache,
+ ClientOptions::FETCH_CLIENT => GuzzleFetchClient::create([
+ 'handler' => new MockHandler(
[new Response(200, [], self::TEST_JSON)]
),
- ]);
+ ]),
+ ]);
$cache
->expects($this->once())
->method('store')
- ->with($this->equalTo($cacheKey));
+ ->with($this->equalTo($cacheKey))
+ ;
$cache
->expects($this->once())
->method('load')
- ->with($this->equalTo($cacheKey));
+ ->with($this->equalTo($cacheKey))
+ ;
$client->forceRefresh();
}
@@ -68,8 +76,8 @@ public function testCacheKeyGeneration($sdkKey, $cacheKey)
public function cacheKeyTestData(): array
{
return [
- ["test1", "147c5b4c2b2d7c77e1605b1a4309f0ea6684a0c6"],
- ["test2", "c09513b1756de9e4bc48815ec7a142b2441ed4d5"],
+ ['test1', '147c5b4c2b2d7c77e1605b1a4309f0ea6684a0c6'],
+ ['test2', 'c09513b1756de9e4bc48815ec7a142b2441ed4d5'],
];
}
}
diff --git a/tests/ConfigCatClientTest.php b/tests/ConfigCatClientTest.php
index d79626b..a1207d8 100644
--- a/tests/ConfigCatClientTest.php
+++ b/tests/ConfigCatClientTest.php
@@ -8,6 +8,7 @@
use ConfigCat\ClientOptions;
use ConfigCat\ConfigCatClient;
use ConfigCat\EvaluationDetails;
+use ConfigCat\Http\GuzzleFetchClient;
use ConfigCat\Log\InternalLogger;
use ConfigCat\Log\LogLevel;
use ConfigCat\User;
@@ -19,16 +20,17 @@
use GuzzleHttp\Psr7\Response;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
+use ReflectionClass;
use ReflectionException;
class ConfigCatClientTest extends TestCase
{
- private const TEST_JSON = "{ \"f\" : { \"first\": { \"v\": false, \"p\": [], \"r\": [], \"i\":\"fakeIdFirst\" }, \"second\": { \"v\": true, \"p\": [], \"r\": [], \"i\":\"fakeIdSecond\" }}}";
+ private const TEST_JSON = '{ "f" : { "first": { "v": false, "p": [], "r": [], "i":"fakeIdFirst" }, "second": { "v": true, "p": [], "r": [], "i":"fakeIdSecond" }}}';
public function testConstructEmptySdkKey()
{
$this->expectException(InvalidArgumentException::class);
- new ConfigCatClient("");
+ new ConfigCatClient('');
}
/**
@@ -36,15 +38,15 @@ public function testConstructEmptySdkKey()
*/
public function testConstructDefaults()
{
- $client = new ConfigCatClient("testConstructDefaults");
+ $client = new ConfigCatClient('testConstructDefaults');
- $logger = $this->getReflectedValue($client, "logger");
+ $logger = $this->getReflectedValue($client, 'logger');
$this->assertInstanceOf(InternalLogger::class, $logger);
- $cache = $this->getReflectedValue($client, "cache");
+ $cache = $this->getReflectedValue($client, 'cache');
$this->assertInstanceOf(ArrayCache::class, $cache);
- $cacheRefreshInterval = $this->getReflectedValue($client, "cacheRefreshInterval");
+ $cacheRefreshInterval = $this->getReflectedValue($client, 'cacheRefreshInterval');
$this->assertEquals(60, $cacheRefreshInterval);
}
@@ -54,49 +56,61 @@ public function testConstructDefaults()
public function testConstructLoggerOption()
{
$logger = Utils::getNullLogger();
- $client = new ConfigCatClient("testConstructLoggerOption", [
+ $client = new ConfigCatClient('testConstructLoggerOption', [
ClientOptions::LOGGER => $logger,
ClientOptions::LOG_LEVEL => LogLevel::ERROR,
- ClientOptions::EXCEPTIONS_TO_IGNORE => [InvalidArgumentException::class]
+ ClientOptions::EXCEPTIONS_TO_IGNORE => [InvalidArgumentException::class],
]);
- $internalLogger = $this->getReflectedValue($client, "logger");
+ $internalLogger = $this->getReflectedValue($client, 'logger');
- $externalLogger = $this->getReflectedValue($internalLogger, "logger");
- $globalLevel = $this->getReflectedValue($internalLogger, "globalLevel");
- $exceptions = $this->getReflectedValue($internalLogger, "exceptionsToIgnore");
+ $externalLogger = $this->getReflectedValue($internalLogger, 'logger');
+ $globalLevel = $this->getReflectedValue($internalLogger, 'globalLevel');
+ $exceptions = $this->getReflectedValue($internalLogger, 'exceptionsToIgnore');
$this->assertSame($logger, $externalLogger);
$this->assertSame(LogLevel::ERROR, $globalLevel);
- $this->assertArraySubset([InvalidArgumentException::class], $exceptions);
+ $this->assertTrue(in_array(InvalidArgumentException::class, $exceptions));
}
+ /**
+ * @throws ReflectionException
+ */
public function testConstructCacheOption()
{
$cache = new ArrayCache();
- $client = new ConfigCatClient("testConstructCacheOption", [ClientOptions::CACHE => $cache]);
- $this->assertAttributeSame($cache, "cache", $client);
+ $client = new ConfigCatClient('testConstructCacheOption', [ClientOptions::CACHE => $cache]);
+ $propCache = $this->getReflectedValue($client, 'cache');
+ $this->assertSame($cache, $propCache);
}
+ /**
+ * @throws ReflectionException
+ */
public function testConstructCacheRefreshIntervalOption()
{
- $client = new ConfigCatClient("testConstructCacheRefreshIntervalOption", [ClientOptions::CACHE_REFRESH_INTERVAL => 20]);
- $this->assertAttributeSame(20, "cacheRefreshInterval", $client);
+ $client = new ConfigCatClient('testConstructCacheRefreshIntervalOption', [ClientOptions::CACHE_REFRESH_INTERVAL => 20]);
+ $propInterval = $this->getReflectedValue($client, 'cacheRefreshInterval');
+ $this->assertSame(20, $propInterval);
}
public function testGetValueFailedFetch()
{
- $client = new ConfigCatClient("testGetValueFailedFetch", [ClientOptions::CUSTOM_HANDLER => new MockHandler([
- new Response(400)
+ $client = new ConfigCatClient('testGetValueFailedFetch', [ClientOptions::FETCH_CLIENT => GuzzleFetchClient::create([
+ 'handler' => new MockHandler(
+ [new Response(400)]
+ ),
])]);
- $value = $client->getValue("key", false);
+ $value = $client->getValue('key', false);
$this->assertFalse($value);
}
public function testGetAllKeysFailedFetch()
{
- $client = new ConfigCatClient("testGetAllKeysFailedFetch", [ClientOptions::CUSTOM_HANDLER => new MockHandler([
- new Response(400)
+ $client = new ConfigCatClient('testGetAllKeysFailedFetch', [ClientOptions::FETCH_CLIENT => GuzzleFetchClient::create([
+ 'handler' => new MockHandler(
+ [new Response(400)]
+ ),
])]);
$keys = $client->getAllKeys();
@@ -106,20 +120,23 @@ public function testGetAllKeysFailedFetch()
public function testForceRefresh()
{
$cache = $this->getMockBuilder(ConfigCache::class)->getMock();
- $client = new ConfigCatClient("PKDVCLf-Hq-h-kCzMp-L7Q/PaDVCFk9EpmD6sLpGLltTA",
- [ClientOptions::CACHE => $cache]);
+ $client = new ConfigCatClient(
+ 'PKDVCLf-Hq-h-kCzMp-L7Q/PaDVCFk9EpmD6sLpGLltTA',
+ [ClientOptions::CACHE => $cache]
+ );
$cache
->expects(self::once())
- ->method("store");
+ ->method('store')
+ ;
$client->forceRefresh();
}
public function testKeyNotExist()
{
- $client = new ConfigCatClient("PKDVCLf-Hq-h-kCzMp-L7Q/PaDVCFk9EpmD6sLpGLltTA");
- $value = $client->getValue("nonExistingKey", false);
+ $client = new ConfigCatClient('PKDVCLf-Hq-h-kCzMp-L7Q/PaDVCFk9EpmD6sLpGLltTA');
+ $value = $client->getValue('nonExistingKey', false);
$this->assertFalse($value);
}
@@ -130,24 +147,27 @@ public function testCacheExpiration()
$mockHandler = new MockHandler(
[new Response(200, [], self::TEST_JSON)]
);
- $client = new ConfigCatClient("testCacheExpiration", [
+ $client = new ConfigCatClient('testCacheExpiration', [
ClientOptions::CACHE => $cache,
- ClientOptions::CUSTOM_HANDLER => $mockHandler,
- ClientOptions::CACHE_REFRESH_INTERVAL => 1
+ ClientOptions::FETCH_CLIENT => GuzzleFetchClient::create([
+ 'handler' => $mockHandler,
+ ]),
+ ClientOptions::CACHE_REFRESH_INTERVAL => 1,
]);
$cache
->method('load')
- ->willReturn(ConfigEntry::fromConfigJson(self::TEST_JSON, "", \ConfigCat\Utils::getUnixMilliseconds() - 500));
+ ->willReturn(ConfigEntry::fromConfigJson(self::TEST_JSON, '', \ConfigCat\Utils::getUnixMilliseconds() - 500))
+ ;
- $value = $client->getValue("second", false);
+ $value = $client->getValue('second', false);
$this->assertTrue($value);
$this->assertNull($mockHandler->getLastRequest());
sleep(1);
- $value = $client->getValue("second", false);
+ $value = $client->getValue('second', false);
$this->assertTrue($value);
$this->assertNotNull($mockHandler->getLastRequest());
@@ -155,32 +175,32 @@ public function testCacheExpiration()
public function testGetVariationId()
{
- $client = new ConfigCatClient("testGetVariationId", [
- ClientOptions::CUSTOM_HANDLER => new MockHandler(
- [new Response(200, [], self::TEST_JSON)]
- ),
+ $client = new ConfigCatClient('testGetVariationId', [
+ ClientOptions::FETCH_CLIENT => GuzzleFetchClient::create([
+ 'handler' => new MockHandler([new Response(200, [], self::TEST_JSON)]),
+ ]),
]);
- $details = $client->getValueDetails("second", false);
+ $details = $client->getValueDetails('second', false);
- $this->assertEquals("fakeIdSecond", $details->getVariationId());
+ $this->assertEquals('fakeIdSecond', $details->getVariationId());
}
public function testGetAllVariationIds()
{
- $client = new ConfigCatClient("testGetAllVariationIds", [
- ClientOptions::CUSTOM_HANDLER => new MockHandler(
- [new Response(200, [], self::TEST_JSON)]
- ),
+ $client = new ConfigCatClient('testGetAllVariationIds', [
+ ClientOptions::FETCH_CLIENT => GuzzleFetchClient::create([
+ 'handler' => new MockHandler([new Response(200, [], self::TEST_JSON)]),
+ ]),
]);
$value = $client->getAllValueDetails();
- $this->assertEquals(2, count($value));
+ $this->assertCount(2, $value);
}
public function testGetAllVariationIdsEmpty()
{
- $client = new ConfigCatClient("testGetAllVariationIdsEmpty", [ClientOptions::CUSTOM_HANDLER => new MockHandler([
- new Response(400)
+ $client = new ConfigCatClient('testGetAllVariationIdsEmpty', [ClientOptions::CUSTOM_HANDLER => new MockHandler([
+ new Response(400),
])]);
$value = $client->getAllValueDetails();
@@ -189,121 +209,122 @@ public function testGetAllVariationIdsEmpty()
public function testGetKeyAndValue()
{
- $client = new ConfigCatClient("testGetKeyAndValue", [
- ClientOptions::CUSTOM_HANDLER => new MockHandler(
- [new Response(200, [], self::TEST_JSON)]
- ),
+ $client = new ConfigCatClient('testGetKeyAndValue', [
+ ClientOptions::FETCH_CLIENT => GuzzleFetchClient::create([
+ 'handler' => new MockHandler([new Response(200, [], self::TEST_JSON)]),
+ ]),
]);
- $value = $client->getKeyAndValue("fakeIdSecond");
+ $value = $client->getKeyAndValue('fakeIdSecond');
- $this->assertEquals("second", $value->getKey());
+ $this->assertEquals('second', $value->getKey());
$this->assertTrue($value->getValue());
}
public function testGetKeyAndValueNull()
{
- $client = new ConfigCatClient("testGetKeyAndValueNull", [
- ClientOptions::CUSTOM_HANDLER => new MockHandler(
- [new Response(200, [], self::TEST_JSON)]
- ),
+ $client = new ConfigCatClient('testGetKeyAndValueNull', [
+ ClientOptions::FETCH_CLIENT => GuzzleFetchClient::create([
+ 'handler' => new MockHandler([new Response(200, [], self::TEST_JSON)]),
+ ]),
]);
- $value = $client->getKeyAndValue("nonexisting");
+ $value = $client->getKeyAndValue('nonexisting');
$this->assertNull($value);
}
public function testGetAllValues()
{
- $client = new ConfigCatClient("testGetAllValues", [
- ClientOptions::CUSTOM_HANDLER => new MockHandler(
- [new Response(200, [], self::TEST_JSON)]
- ),
+ $client = new ConfigCatClient('testGetAllValues', [
+ ClientOptions::FETCH_CLIENT => GuzzleFetchClient::create([
+ 'handler' => new MockHandler([new Response(200, [], self::TEST_JSON)]),
+ ]),
]);
$value = $client->getAllValues();
- $this->assertEquals(["first" => false, "second" => true], $value);
+ $this->assertEquals(['first' => false, 'second' => true], $value);
}
public function testGetAllValueDetails()
{
- $client = new ConfigCatClient("testGetAllValueDetails", [
- ClientOptions::CUSTOM_HANDLER => new MockHandler(
- [new Response(200, [], self::TEST_JSON)]
- ),
+ $client = new ConfigCatClient('testGetAllValueDetails', [
+ ClientOptions::FETCH_CLIENT => GuzzleFetchClient::create([
+ 'handler' => new MockHandler([new Response(200, [], self::TEST_JSON)]),
+ ]),
]);
$value = $client->getAllValueDetails();
- $this->assertFalse($value["first"]->getValue());
- $this->assertTrue($value["second"]->getValue());
+ $this->assertFalse($value['first']->getValue());
+ $this->assertTrue($value['second']->getValue());
}
public function testDefaultUser()
{
- $client = new ConfigCatClient("testDefaultUser", [ClientOptions::CUSTOM_HANDLER => new MockHandler([
- new Response(200, [], Utils::formatConfigWithRules())
+ $client = new ConfigCatClient('testDefaultUser', [ClientOptions::CUSTOM_HANDLER => new MockHandler([
+ new Response(200, [], Utils::formatConfigWithRules()),
])]);
- $user1 = new User("test@test1.com");
- $user2 = new User("test@test2.com");
+ $user1 = new User('test@test1.com');
+ $user2 = new User('test@test2.com');
$client->setDefaultUser($user1);
- $value = $client->getValue("key", "");
- $this->assertEquals("fake1", $value);
+ $value = $client->getValue('key', '');
+ $this->assertEquals('fake1', $value);
- $value = $client->getValue("key", "", $user2);
- $this->assertEquals("fake2", $value);
+ $value = $client->getValue('key', '', $user2);
+ $this->assertEquals('fake2', $value);
$client->clearDefaultUser();
- $value = $client->getValue("key", "");
- $this->assertEquals("def", $value);
+ $value = $client->getValue('key', '');
+ $this->assertEquals('def', $value);
}
public function testInitDefaultUser()
{
- $client = new ConfigCatClient("testInitDefaultUser",
+ $client = new ConfigCatClient(
+ 'testInitDefaultUser',
[
ClientOptions::CUSTOM_HANDLER => new MockHandler([new Response(200, [], Utils::formatConfigWithRules())]),
- ClientOptions::DEFAULT_USER => new User("test@test1.com")
+ ClientOptions::DEFAULT_USER => new User('test@test1.com'),
]
);
- $user2 = new User("test@test2.com");
+ $user2 = new User('test@test2.com');
- $value = $client->getValue("key", "");
- $this->assertEquals("fake1", $value);
+ $value = $client->getValue('key', '');
+ $this->assertEquals('fake1', $value);
- $value = $client->getValue("key", "", $user2);
- $this->assertEquals("fake2", $value);
+ $value = $client->getValue('key', '', $user2);
+ $this->assertEquals('fake2', $value);
$client->clearDefaultUser();
- $value = $client->getValue("key", "");
- $this->assertEquals("def", $value);
+ $value = $client->getValue('key', '');
+ $this->assertEquals('def', $value);
}
public function testDefaultUserVariationId()
{
- $client = new ConfigCatClient("testDefaultUserVariationId", [ClientOptions::CUSTOM_HANDLER => new MockHandler([
- new Response(200, [], Utils::formatConfigWithRules())
+ $client = new ConfigCatClient('testDefaultUserVariationId', [ClientOptions::CUSTOM_HANDLER => new MockHandler([
+ new Response(200, [], Utils::formatConfigWithRules()),
])]);
- $user1 = new User("test@test1.com");
- $user2 = new User("test@test2.com");
+ $user1 = new User('test@test1.com');
+ $user2 = new User('test@test2.com');
$client->setDefaultUser($user1);
- $value = $client->getValueDetails("key", "");
- $this->assertEquals("id1", $value->getVariationId());
+ $value = $client->getValueDetails('key', '');
+ $this->assertEquals('id1', $value->getVariationId());
- $value = $client->getValueDetails("key", "", $user2);
- $this->assertEquals("id2", $value->getVariationId());
+ $value = $client->getValueDetails('key', '', $user2);
+ $this->assertEquals('id2', $value->getVariationId());
$client->clearDefaultUser();
- $value = $client->getValueDetails("key", "");
- $this->assertEquals("defVar", $value->getVariationId());
+ $value = $client->getValueDetails('key', '');
+ $this->assertEquals('defVar', $value->getVariationId());
}
public function testOfflineOnline()
@@ -316,7 +337,7 @@ public function testOfflineOnline()
]
);
- $client = new ConfigCatClient("testOfflineOnline", [
+ $client = new ConfigCatClient('testOfflineOnline', [
ClientOptions::CUSTOM_HANDLER => $handler,
]);
@@ -349,9 +370,9 @@ public function testInitOfflineOnline()
]
);
- $client = new ConfigCatClient("testInitOfflineOnline", [
+ $client = new ConfigCatClient('testInitOfflineOnline', [
ClientOptions::CUSTOM_HANDLER => $handler,
- ClientOptions::OFFLINE => true
+ ClientOptions::OFFLINE => true,
]);
$this->assertTrue($client->isOffline());
@@ -370,11 +391,11 @@ public function testInitOfflineOnline()
public function testHooks()
{
- $client = new ConfigCatClient("getTestClientWithError", [
+ $client = new ConfigCatClient('getTestClientWithError', [
ClientOptions::CUSTOM_HANDLER => new MockHandler(
[
new Response(200, [], self::TEST_JSON),
- new Response(400, [], "")
+ new Response(400, [], ''),
]
),
]);
@@ -382,65 +403,64 @@ public function testHooks()
$evaluated = false;
$error = false;
$changed = false;
- $message = "";
- $client->hooks()->addOnFlagEvaluated(function($details) use (&$evaluated) {
+ $message = '';
+ $client->hooks()->addOnFlagEvaluated(function ($details) use (&$evaluated) {
$evaluated = true;
});
- $client->hooks()->addOnConfigChanged(function($settings) use (&$changed) {
+ $client->hooks()->addOnConfigChanged(function ($settings) use (&$changed) {
$changed = true;
});
- $client->hooks()->addOnError(function($err) use (&$error, &$message) {
+ $client->hooks()->addOnError(function ($err) use (&$error, &$message) {
$error = true;
$message = $err;
});
- $client->getValue("first", false);
+ $client->getValue('first', false);
$result = $client->forceRefresh();
-
$this->assertTrue($evaluated);
$this->assertTrue($error);
- $this->assertEquals("Your SDK Key seems to be wrong. You can find the valid SDK Key at https://app.configcat.com/sdkkey. Received unexpected response: 400", $message);
+ $this->assertEquals('Your SDK Key seems to be wrong. You can find the valid SDK Key at https://app.configcat.com/sdkkey. Received unexpected response: 400', $message);
$this->assertTrue($changed);
$this->assertFalse($result->isSuccess());
- $this->assertEquals("Your SDK Key seems to be wrong. You can find the valid SDK Key at https://app.configcat.com/sdkkey. Received unexpected response: 400", $result->getError());
+ $this->assertEquals('Your SDK Key seems to be wrong. You can find the valid SDK Key at https://app.configcat.com/sdkkey. Received unexpected response: 400', $result->getError());
}
public function testEvalDetails()
{
- $client = new ConfigCatClient("testEvalDetails", [ClientOptions::CUSTOM_HANDLER => new MockHandler([
- new Response(200, [], Utils::formatConfigWithRules())
+ $client = new ConfigCatClient('testEvalDetails', [ClientOptions::CUSTOM_HANDLER => new MockHandler([
+ new Response(200, [], Utils::formatConfigWithRules()),
])]);
- $details = $client->getValueDetails("key", "", new User("test@test1.com"));
+ $details = $client->getValueDetails('key', '', new User('test@test1.com'));
- $this->assertEquals("fake1", $details->getValue());
- $this->assertEquals("id1", $details->getVariationId());
+ $this->assertEquals('fake1', $details->getValue());
+ $this->assertEquals('id1', $details->getVariationId());
$this->assertNull($details->getError());
- $this->assertEquals("key", $details->getKey());
- $this->assertEquals("test@test1.com", $details->getUser()->getIdentifier());
- $this->assertEquals("Identifier", $details->getMatchedEvaluationRule()["a"]);
- $this->assertEquals("@test1.com", $details->getMatchedEvaluationRule()["c"]);
- $this->assertEquals(2, $details->getMatchedEvaluationRule()["t"]);
+ $this->assertEquals('key', $details->getKey());
+ $this->assertEquals('test@test1.com', $details->getUser()->getIdentifier());
+ $this->assertEquals('Identifier', $details->getMatchedEvaluationRule()['a']);
+ $this->assertEquals('@test1.com', $details->getMatchedEvaluationRule()['c']);
+ $this->assertEquals(2, $details->getMatchedEvaluationRule()['t']);
$this->assertNull($details->getMatchedEvaluationPercentageRule());
$this->assertTrue($details->getFetchTimeUnixMilliseconds() > 0);
$this->assertFalse($details->isDefaultValue());
}
- public function testEvalDetails_Non_Existent_Flag()
+ public function testEvalDetailsNonExistentFlag()
{
- $client = new ConfigCatClient("testEvalDetails", [ClientOptions::CUSTOM_HANDLER => new MockHandler([
- new Response(200, [], Utils::formatConfigWithRules())
+ $client = new ConfigCatClient('testEvalDetails', [ClientOptions::CUSTOM_HANDLER => new MockHandler([
+ new Response(200, [], Utils::formatConfigWithRules()),
])]);
- $details = $client->getValueDetails("non-existent", "", new User("test@test1.com"));
+ $details = $client->getValueDetails('non-existent', '', new User('test@test1.com'));
- $this->assertEquals("", $details->getValue());
- $this->assertEquals("", $details->getVariationId());
+ $this->assertEquals('', $details->getValue());
+ $this->assertEquals('', $details->getVariationId());
$this->assertNotNull($details->getError());
- $this->assertEquals("non-existent", $details->getKey());
- $this->assertEquals("test@test1.com", $details->getUser()->getIdentifier());
+ $this->assertEquals('non-existent', $details->getKey());
+ $this->assertEquals('test@test1.com', $details->getUser()->getIdentifier());
$this->assertNull($details->getMatchedEvaluationRule());
$this->assertNull($details->getMatchedEvaluationPercentageRule());
$this->assertTrue($details->isDefaultValue());
@@ -448,75 +468,79 @@ public function testEvalDetails_Non_Existent_Flag()
public function testEvalDetailsHook()
{
- $client = new ConfigCatClient("testEvalDetailsHook", [ClientOptions::CUSTOM_HANDLER => new MockHandler([
- new Response(200, [], Utils::formatConfigWithRules())
+ $client = new ConfigCatClient('testEvalDetailsHook', [ClientOptions::CUSTOM_HANDLER => new MockHandler([
+ new Response(200, [], Utils::formatConfigWithRules()),
])]);
$called = false;
$client->hooks()->addOnFlagEvaluated(function (EvaluationDetails $details) use (&$called) {
- $this->assertEquals("fake1", $details->getValue());
- $this->assertEquals("id1", $details->getVariationId());
+ $this->assertEquals('fake1', $details->getValue());
+ $this->assertEquals('id1', $details->getVariationId());
$this->assertNull($details->getError());
- $this->assertEquals("key", $details->getKey());
- $this->assertEquals("test@test1.com", $details->getUser()->getIdentifier());
- $this->assertEquals("Identifier", $details->getMatchedEvaluationRule()["a"]);
- $this->assertEquals("@test1.com", $details->getMatchedEvaluationRule()["c"]);
- $this->assertEquals(2, $details->getMatchedEvaluationRule()["t"]);
+ $this->assertEquals('key', $details->getKey());
+ $this->assertEquals('test@test1.com', $details->getUser()->getIdentifier());
+ $this->assertEquals('Identifier', $details->getMatchedEvaluationRule()['a']);
+ $this->assertEquals('@test1.com', $details->getMatchedEvaluationRule()['c']);
+ $this->assertEquals(2, $details->getMatchedEvaluationRule()['t']);
$this->assertNull($details->getMatchedEvaluationPercentageRule());
$this->assertFalse($details->isDefaultValue());
$this->assertTrue($details->getFetchTimeUnixMilliseconds() > 0);
$called = true;
});
- $client->getValue("key", "", new User("test@test1.com"));
+ $client->getValue('key', '', new User('test@test1.com'));
$this->assertTrue($called);
}
public function testTimeout()
{
- $client = new ConfigCatClient("testTimout", [
+ $client = new ConfigCatClient('testTimout', [
ClientOptions::CUSTOM_HANDLER => new MockHandler([
- new ConnectException("timeout", new Request("GET", "test"))
+ new ConnectException('timeout', new Request('GET', 'test')),
]),
]);
- $value = $client->getValue("test", "def");
+ $value = $client->getValue('test', 'def');
- $this->assertEquals("def", $value);
+ $this->assertEquals('def', $value);
}
public function testHttpException()
{
- $client = new ConfigCatClient("testHttpException", [
+ $client = new ConfigCatClient('testHttpException', [
ClientOptions::CUSTOM_HANDLER => new MockHandler([
- new RequestException("failed", new Request("GET", "test"))
+ new RequestException('failed', new Request('GET', 'test')),
]),
]);
- $value = $client->getValue("test", "def");
+ $value = $client->getValue('test', 'def');
- $this->assertEquals("def", $value);
+ $this->assertEquals('def', $value);
}
public function testGeneralException()
{
- $client = new ConfigCatClient("testGeneralException", [
+ $client = new ConfigCatClient('testGeneralException', [
ClientOptions::CUSTOM_HANDLER => new MockHandler([
- new Exception("failed")
+ new Exception('failed'),
]),
]);
- $value = $client->getValue("test", "def");
+ $value = $client->getValue('test', 'def');
- $this->assertEquals("def", $value);
+ $this->assertEquals('def', $value);
}
/**
+ * @param mixed $object
+ * @param mixed $propertyName
+ *
* @throws ReflectionException
*/
private function getReflectedValue($object, $propertyName)
{
- $reflection = new \ReflectionClass($object);
+ $reflection = new ReflectionClass($object);
$property = $reflection->getProperty($propertyName);
$property->setAccessible(true);
+
return $property->getValue($object);
}
}
diff --git a/tests/ConfigFetcherTest.php b/tests/ConfigFetcherTest.php
index 9f5346e..835fd29 100644
--- a/tests/ConfigFetcherTest.php
+++ b/tests/ConfigFetcherTest.php
@@ -9,36 +9,37 @@
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
-use GuzzleHttp\RequestOptions;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
class ConfigFetcherTest extends TestCase
{
- private string $mockSdkKey = "testSdkKey";
- private string $mockEtag = "testEtag";
- private string $mockBody = "{\"key\": \"value\"}";
+ private string $mockSdkKey = 'testSdkKey';
+ private string $mockEtag = 'testEtag';
+ private string $mockBody = '{"key": "value"}';
public function testFetchOk()
{
- $fetcher = new ConfigFetcher($this->mockSdkKey, Utils::getTestLogger(), [ClientOptions::CUSTOM_HANDLER => HandlerStack::create(new MockHandler([
- new Response(200, [ConfigFetcher::ETAG_HEADER => $this->mockEtag], $this->mockBody)
- ]))]);
+ $mockHandler = new MockHandler([
+ new Response(200, [ConfigFetcher::ETAG_HEADER => $this->mockEtag], $this->mockBody), ]);
+ $fetcher = new ConfigFetcher($this->mockSdkKey, Utils::getTestLogger(), [
+ ClientOptions::CUSTOM_HANDLER => HandlerStack::create($mockHandler), ]);
- $response = $fetcher->fetch("old_etag");
+ $response = $fetcher->fetch('old_etag');
$this->assertTrue($response->isFetched());
$this->assertEquals($this->mockEtag, $response->getConfigEntry()->getEtag());
- $this->assertEquals("value", $response->getConfigEntry()->getConfig()['key']);
+ $this->assertEquals('value', $response->getConfigEntry()->getConfig()['key']);
+ $this->assertNotEmpty($mockHandler->getLastRequest()->getHeader('X-ConfigCat-UserAgent'));
}
public function testFetchNotModified()
{
- $fetcher = new ConfigFetcher($this->mockSdkKey, Utils::getTestLogger(), [ClientOptions::CUSTOM_HANDLER => HandlerStack::create(new MockHandler([
- new Response(304, [ConfigFetcher::ETAG_HEADER => $this->mockEtag])
- ]))]);
+ $fetcher = new ConfigFetcher($this->mockSdkKey, Utils::getTestLogger(), [
+ ClientOptions::CUSTOM_HANDLER => HandlerStack::create(new MockHandler([
+ new Response(304, [ConfigFetcher::ETAG_HEADER => $this->mockEtag]), ])), ]);
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
$this->assertTrue($response->isNotModified());
$this->assertEmpty($response->getConfigEntry()->getETag());
@@ -47,11 +48,10 @@ public function testFetchNotModified()
public function testFetchFailed()
{
- $fetcher = new ConfigFetcher($this->mockSdkKey, Utils::getTestLogger(), [ClientOptions::CUSTOM_HANDLER => HandlerStack::create(new MockHandler([
- new Response(400)
- ]))]);
+ $fetcher = new ConfigFetcher($this->mockSdkKey, Utils::getTestLogger(), [
+ ClientOptions::CUSTOM_HANDLER => HandlerStack::create(new MockHandler([new Response(400)])), ]);
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
$this->assertTrue($response->isFailed());
$this->assertEmpty($response->getConfigEntry()->getETag());
@@ -60,64 +60,37 @@ public function testFetchFailed()
public function testFetchInvalidJson()
{
- $fetcher = new ConfigFetcher($this->mockSdkKey, Utils::getTestLogger(), [ClientOptions::CUSTOM_HANDLER => HandlerStack::create(new MockHandler([
- new Response(200, [], "{\"key\": value}")
- ]))]);
+ $mockHandler = new MockHandler([new Response(200, [], '{"key": value}')]);
+ $fetcher = new ConfigFetcher($this->mockSdkKey, Utils::getTestLogger(), [
+ ClientOptions::CUSTOM_HANDLER => HandlerStack::create($mockHandler), ]);
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
$this->assertTrue($response->isFailed());
$this->assertEmpty($response->getConfigEntry()->getETag());
$this->assertEmpty($response->getConfigEntry()->getConfig());
+ $this->assertNotEmpty($mockHandler->getLastRequest()->getHeader('X-ConfigCat-UserAgent'));
}
public function testConstructEmptySdkKey()
{
$this->expectException(InvalidArgumentException::class);
- new ConfigFetcher("", Utils::getNullLogger());
- }
-
- public function testConstructDefaults()
- {
- $fetcher = new ConfigFetcher("api", Utils::getTestLogger());
- $options = $fetcher->getRequestOptions();
-
- $this->assertEquals(10, $options[RequestOptions::CONNECT_TIMEOUT]);
- $this->assertEquals(30, $options[RequestOptions::TIMEOUT]);
- $this->assertArrayHasKey("headers", $options);
- }
-
- public function testConstructConnectTimeoutOption()
- {
- $fetcher = new ConfigFetcher("api", Utils::getTestLogger(), [ClientOptions::REQUEST_OPTIONS => [
- RequestOptions::CONNECT_TIMEOUT => 5
- ]]);
- $options = $fetcher->getRequestOptions();
- $this->assertEquals(5, $options[RequestOptions::CONNECT_TIMEOUT]);
- }
-
- public function testConstructRequestTimeoutOption()
- {
- $fetcher = new ConfigFetcher("api", Utils::getTestLogger(), [ClientOptions::REQUEST_OPTIONS => [
- RequestOptions::TIMEOUT => 5
- ]]);
- $options = $fetcher->getRequestOptions();
- $this->assertEquals(5, $options[RequestOptions::TIMEOUT]);
+ new ConfigFetcher('', Utils::getNullLogger());
}
public function testTimeoutException()
{
- $fetcher = new ConfigFetcher("api", Utils::getTestLogger(), [ClientOptions::CUSTOM_HANDLER => HandlerStack::create(new MockHandler([
- new ConnectException("timeout", new Request("GET", "test"))
+ $fetcher = new ConfigFetcher('api', Utils::getTestLogger(), [ClientOptions::CUSTOM_HANDLER => HandlerStack::create(new MockHandler([
+ new ConnectException('timeout', new Request('GET', 'test')),
]))]);
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
$this->assertTrue($response->isFailed());
}
public function testIntegration()
{
- $fetcher = new ConfigFetcher("PKDVCLf-Hq-h-kCzMp-L7Q/PaDVCFk9EpmD6sLpGLltTA", Utils::getTestLogger());
- $response = $fetcher->fetch("");
+ $fetcher = new ConfigFetcher('PKDVCLf-Hq-h-kCzMp-L7Q/PaDVCFk9EpmD6sLpGLltTA', Utils::getTestLogger());
+ $response = $fetcher->fetch('');
$this->assertTrue($response->isFetched());
diff --git a/tests/DataGovernanceTest.php b/tests/DataGovernanceTest.php
index d94f38b..f6b3635 100644
--- a/tests/DataGovernanceTest.php
+++ b/tests/DataGovernanceTest.php
@@ -12,70 +12,74 @@
class DataGovernanceTest extends TestCase
{
- const JSON_TEMPLATE = "{ \"p\": { \"u\": \"%s\", \"r\": %d }, \"f\": {} }";
- const CUSTOM_CDN_URL = "https://custom-cdn.configcat.com";
+ const JSON_TEMPLATE = '{ "p": { "u": "%s", "r": %d }, "f": {} }';
+ const CUSTOM_CDN_URL = 'https://custom-cdn.configcat.com';
- public function testShouldStayOnServer() {
+ public function testShouldStayOnServer()
+ {
// Arrange
$requests = [];
- $body = sprintf(self::JSON_TEMPLATE, "https://fakeUrl", 0);
+ $body = sprintf(self::JSON_TEMPLATE, 'https://fakeUrl', 0);
$responses = [
- new Response(200, [], $body)
+ new Response(200, [], $body),
];
$handler = $this->getHandlerStack($responses, $requests);
$fetcher = $this->getFetcher($handler);
// Act
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
// Assert
$this->assertEquals(1, count($requests));
- $this->assertContains($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
+ $this->assertStringContainsString($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
$this->assertEquals(json_decode($body, true), $response->getConfigEntry()->getConfig());
}
- public function testShouldStayOnSameUrlWithRedirect() {
+ public function testShouldStayOnSameUrlWithRedirect()
+ {
// Arrange
$requests = [];
$body = sprintf(self::JSON_TEMPLATE, ConfigFetcher::GLOBAL_URL, 1);
$responses = [
- new Response(200, [], $body)
+ new Response(200, [], $body),
];
$handler = $this->getHandlerStack($responses, $requests);
$fetcher = $this->getFetcher($handler);
// Act
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
// Assert
$this->assertEquals(1, count($requests));
- $this->assertContains($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
+ $this->assertStringContainsString($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
$this->assertEquals(json_decode($body, true), $response->getConfigEntry()->getConfig());
}
- public function testShouldStayOnSameUrlEvenWhenForced() {
+ public function testShouldStayOnSameUrlEvenWhenForced()
+ {
// Arrange
$requests = [];
$body = sprintf(self::JSON_TEMPLATE, ConfigFetcher::GLOBAL_URL, 2);
$responses = [
- new Response(200, [], $body)
+ new Response(200, [], $body),
];
$handler = $this->getHandlerStack($responses, $requests);
$fetcher = $this->getFetcher($handler);
// Act
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
// Assert
$this->assertEquals(1, count($requests));
- $this->assertContains($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
+ $this->assertStringContainsString($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
$this->assertEquals(json_decode($body, true), $response->getConfigEntry()->getConfig());
}
- public function testShouldRedirectToAnotherServer() {
+ public function testShouldRedirectToAnotherServer()
+ {
// Arrange
$requests = [];
$firstBody = sprintf(self::JSON_TEMPLATE, ConfigFetcher::EU_ONLY_URL, 1);
@@ -89,16 +93,17 @@ public function testShouldRedirectToAnotherServer() {
$fetcher = $this->getFetcher($handler);
// Act
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
// Assert
$this->assertEquals(2, count($requests));
- $this->assertContains($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
- $this->assertContains($requests[1]['request']->getUri()->getHost(), ConfigFetcher::EU_ONLY_URL);
+ $this->assertStringContainsString($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
+ $this->assertStringContainsString($requests[1]['request']->getUri()->getHost(), ConfigFetcher::EU_ONLY_URL);
$this->assertEquals(json_decode($secondBody, true), $response->getConfigEntry()->getConfig());
}
- public function testShouldRedirectToAnotherServerWhenForced() {
+ public function testShouldRedirectToAnotherServerWhenForced()
+ {
// Arrange
$requests = [];
$firstBody = sprintf(self::JSON_TEMPLATE, ConfigFetcher::EU_ONLY_URL, 2);
@@ -112,16 +117,17 @@ public function testShouldRedirectToAnotherServerWhenForced() {
$fetcher = $this->getFetcher($handler);
// Act
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
// Assert
$this->assertEquals(2, count($requests));
- $this->assertContains($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
- $this->assertContains($requests[1]['request']->getUri()->getHost(), ConfigFetcher::EU_ONLY_URL);
+ $this->assertStringContainsString($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
+ $this->assertStringContainsString($requests[1]['request']->getUri()->getHost(), ConfigFetcher::EU_ONLY_URL);
$this->assertEquals(json_decode($secondBody, true), $response->getConfigEntry()->getConfig());
}
- public function testShouldBreakRedirectLoop() {
+ public function testShouldBreakRedirectLoop()
+ {
// Arrange
$requests = [];
$firstBody = sprintf(self::JSON_TEMPLATE, ConfigFetcher::EU_ONLY_URL, 1);
@@ -136,17 +142,18 @@ public function testShouldBreakRedirectLoop() {
$fetcher = $this->getFetcher($handler);
// Act
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
// Assert
$this->assertEquals(3, count($requests));
- $this->assertContains($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
- $this->assertContains($requests[1]['request']->getUri()->getHost(), ConfigFetcher::EU_ONLY_URL);
- $this->assertContains($requests[2]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
+ $this->assertStringContainsString($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
+ $this->assertStringContainsString($requests[1]['request']->getUri()->getHost(), ConfigFetcher::EU_ONLY_URL);
+ $this->assertStringContainsString($requests[2]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
$this->assertEquals(json_decode($firstBody, true), $response->getConfigEntry()->getConfig());
}
- public function testShouldBreakRedirectLoopWhenForced() {
+ public function testShouldBreakRedirectLoopWhenForced()
+ {
// Arrange
$requests = [];
$firstBody = sprintf(self::JSON_TEMPLATE, ConfigFetcher::EU_ONLY_URL, 2);
@@ -161,69 +168,72 @@ public function testShouldBreakRedirectLoopWhenForced() {
$fetcher = $this->getFetcher($handler);
// Act
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
// Assert
$this->assertEquals(3, count($requests));
- $this->assertContains($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
- $this->assertContains($requests[1]['request']->getUri()->getHost(), ConfigFetcher::EU_ONLY_URL);
- $this->assertContains($requests[2]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
+ $this->assertStringContainsString($requests[0]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
+ $this->assertStringContainsString($requests[1]['request']->getUri()->getHost(), ConfigFetcher::EU_ONLY_URL);
+ $this->assertStringContainsString($requests[2]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
$this->assertEquals(json_decode($firstBody, true), $response->getConfigEntry()->getConfig());
}
- public function testShouldRespectCustomUrlWhenNotForced() {
+ public function testShouldRespectCustomUrlWhenNotForced()
+ {
// Arrange
$requests = [];
$firstBody = sprintf(self::JSON_TEMPLATE, ConfigFetcher::GLOBAL_URL, 1);
$responses = [
new Response(200, [], $firstBody),
- new Response(200, [], $firstBody)
+ new Response(200, [], $firstBody),
];
$handler = $this->getHandlerStack($responses, $requests);
$fetcher = $this->getFetcher($handler, self::CUSTOM_CDN_URL);
// Act
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
// Assert
$this->assertEquals(1, count($requests));
- $this->assertContains($requests[0]['request']->getUri()->getHost(), self::CUSTOM_CDN_URL);
+ $this->assertStringContainsString($requests[0]['request']->getUri()->getHost(), self::CUSTOM_CDN_URL);
$this->assertEquals(json_decode($firstBody, true), $response->getConfigEntry()->getConfig());
// Act
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
// Assert
$this->assertEquals(2, count($requests));
- $this->assertContains($requests[1]['request']->getUri()->getHost(), self::CUSTOM_CDN_URL);
+ $this->assertStringContainsString($requests[1]['request']->getUri()->getHost(), self::CUSTOM_CDN_URL);
$this->assertEquals(json_decode($firstBody, true), $response->getConfigEntry()->getConfig());
}
- public function testShouldNotRespectCustomUrlWhenForced() {
+ public function testShouldNotRespectCustomUrlWhenForced()
+ {
// Arrange
$requests = [];
$firstBody = sprintf(self::JSON_TEMPLATE, ConfigFetcher::GLOBAL_URL, 2);
$secondBody = sprintf(self::JSON_TEMPLATE, ConfigFetcher::GLOBAL_URL, 0);
$responses = [
new Response(200, [], $firstBody),
- new Response(200, [], $secondBody)
+ new Response(200, [], $secondBody),
];
$handler = $this->getHandlerStack($responses, $requests);
$fetcher = $this->getFetcher($handler, self::CUSTOM_CDN_URL);
// Act
- $response = $fetcher->fetch("");
+ $response = $fetcher->fetch('');
// Assert
$this->assertEquals(2, count($requests));
- $this->assertContains($requests[0]['request']->getUri()->getHost(), self::CUSTOM_CDN_URL);
- $this->assertContains($requests[1]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
+ $this->assertStringContainsString($requests[0]['request']->getUri()->getHost(), self::CUSTOM_CDN_URL);
+ $this->assertStringContainsString($requests[1]['request']->getUri()->getHost(), ConfigFetcher::GLOBAL_URL);
$this->assertEquals(json_decode($secondBody, true), $response->getConfigEntry()->getConfig());
}
- private function getHandlerStack(array $responses, array &$container = []) {
+ private function getHandlerStack(array $responses, array &$container = [])
+ {
$history = Middleware::history($container);
$stack = HandlerStack::create(new MockHandler($responses));
$stack->push($history);
@@ -231,10 +241,11 @@ private function getHandlerStack(array $responses, array &$container = []) {
return $stack;
}
- private function getFetcher($handler, $customUrl = "") {
- return new ConfigFetcher("fakeKey", Utils::getTestLogger(), [
+ private function getFetcher($handler, $customUrl = '')
+ {
+ return new ConfigFetcher('fakeKey', Utils::getTestLogger(), [
ClientOptions::CUSTOM_HANDLER => $handler,
- ClientOptions::BASE_URL => $customUrl
+ ClientOptions::BASE_URL => $customUrl,
]);
}
-}
\ No newline at end of file
+}
diff --git a/tests/LocalSourceTest.php b/tests/LocalSourceTest.php
index 6efdf5b..d1efd03 100644
--- a/tests/LocalSourceTest.php
+++ b/tests/LocalSourceTest.php
@@ -10,86 +10,93 @@
use ConfigCat\User;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\Psr7\Response;
-use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
+use PHPUnit\Framework\TestCase;
class LocalSourceTest extends TestCase
{
- const TEST_JSON_BODY = "{ \"f\" : { \"disabled\": { \"v\": false, \"p\": [], \"r\": [], \"i\":\"fakeIdFirst\" }, \"enabled\": { \"v\": true, \"p\": [], \"r\": [], \"i\":\"fakeIdSecond\" }}}";
+ const TEST_JSON_BODY = '{ "f" : { "disabled": { "v": false, "p": [], "r": [], "i":"fakeIdFirst" }, "enabled": { "v": true, "p": [], "r": [], "i":"fakeIdSecond" }}}';
- public function testWithNonExistingFile() {
+ public function testWithNonExistingFile()
+ {
$this->expectException(InvalidArgumentException::class);
- new ConfigCatClient("testWithNonExistingFile", [
- ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localFile("non-existing"), OverrideBehaviour::LOCAL_ONLY),
+ new ConfigCatClient('testWithNonExistingFile', [
+ ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localFile('non-existing'), OverrideBehaviour::LOCAL_ONLY),
]);
}
- public function testWithInvalidBehavior() {
+ public function testWithInvalidBehavior()
+ {
$this->expectException(InvalidArgumentException::class);
- new ConfigCatClient("testWithInvalidBehavior", [
+ new ConfigCatClient('testWithInvalidBehavior', [
ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localArray([]), 50),
]);
}
- public function testWithFile() {
- $client = new ConfigCatClient("testWithFile", [
- ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localFile("tests/test.json"), OverrideBehaviour::LOCAL_ONLY),
+ public function testWithFile()
+ {
+ $client = new ConfigCatClient('testWithFile', [
+ ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localFile('tests/test.json'), OverrideBehaviour::LOCAL_ONLY),
]);
- $this->assertTrue($client->getValue("enabledFeature", false));
- $this->assertFalse($client->getValue("disabledFeature", true));
- $this->assertEquals(5, $client->getValue("intSetting", 0));
- $this->assertEquals(3.14, $client->getValue("doubleSetting", 0.0));
- $this->assertEquals("test", $client->getValue("stringSetting", 0));
+ $this->assertTrue($client->getValue('enabledFeature', false));
+ $this->assertFalse($client->getValue('disabledFeature', true));
+ $this->assertEquals(5, $client->getValue('intSetting', 0));
+ $this->assertEquals(3.14, $client->getValue('doubleSetting', 0.0));
+ $this->assertEquals('test', $client->getValue('stringSetting', 0));
}
- public function testWithFile_Rules() {
- $client = new ConfigCatClient("testWithFile_Rules", [
- ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localFile("tests/test-rules.json"), OverrideBehaviour::LOCAL_ONLY),
+ public function testWithFileRules()
+ {
+ $client = new ConfigCatClient('testWithFile_Rules', [
+ ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localFile('tests/test-rules.json'), OverrideBehaviour::LOCAL_ONLY),
]);
// without user
- $this->assertFalse($client->getValue("rolloutFeature", true));
+ $this->assertFalse($client->getValue('rolloutFeature', true));
// not in rule
- $this->assertFalse($client->getValue("rolloutFeature", true, new User("test@test.com")));
+ $this->assertFalse($client->getValue('rolloutFeature', true, new User('test@test.com')));
// in rule
- $this->assertTrue($client->getValue("rolloutFeature", false, new User("test@example.com")));
+ $this->assertTrue($client->getValue('rolloutFeature', false, new User('test@example.com')));
}
- public function testWithSimpleFile() {
- $client = new ConfigCatClient("testWithSimpleFile", [
- ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localFile("tests/test-simple.json"), OverrideBehaviour::LOCAL_ONLY),
+ public function testWithSimpleFile()
+ {
+ $client = new ConfigCatClient('testWithSimpleFile', [
+ ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localFile('tests/test-simple.json'), OverrideBehaviour::LOCAL_ONLY),
]);
- $this->assertTrue($client->getValue("enabledFeature", false));
- $this->assertFalse($client->getValue("disabledFeature", true));
- $this->assertEquals(5, $client->getValue("intSetting", 0));
- $this->assertEquals(3.14, $client->getValue("doubleSetting", 0.0));
- $this->assertEquals("test", $client->getValue("stringSetting", 0));
+ $this->assertTrue($client->getValue('enabledFeature', false));
+ $this->assertFalse($client->getValue('disabledFeature', true));
+ $this->assertEquals(5, $client->getValue('intSetting', 0));
+ $this->assertEquals(3.14, $client->getValue('doubleSetting', 0.0));
+ $this->assertEquals('test', $client->getValue('stringSetting', 0));
}
- public function testWithArraySource() {
- $client = new ConfigCatClient("testWithArraySource", [
+ public function testWithArraySource()
+ {
+ $client = new ConfigCatClient('testWithArraySource', [
ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localArray([
'enabledFeature' => true,
'disabledFeature' => false,
'intSetting' => 5,
'doubleSetting' => 3.14,
- 'stringSetting' => "test",
+ 'stringSetting' => 'test',
]), OverrideBehaviour::LOCAL_ONLY),
]);
- $this->assertTrue($client->getValue("enabledFeature", false));
- $this->assertFalse($client->getValue("disabledFeature", true));
- $this->assertEquals(5, $client->getValue("intSetting", 0));
- $this->assertEquals(3.14, $client->getValue("doubleSetting", 0.0));
- $this->assertEquals("test", $client->getValue("stringSetting", 0));
+ $this->assertTrue($client->getValue('enabledFeature', false));
+ $this->assertFalse($client->getValue('disabledFeature', true));
+ $this->assertEquals(5, $client->getValue('intSetting', 0));
+ $this->assertEquals(3.14, $client->getValue('doubleSetting', 0.0));
+ $this->assertEquals('test', $client->getValue('stringSetting', 0));
}
- public function testLocalOverRemote() {
- $client = new ConfigCatClient("testLocalOverRemote", [
+ public function testLocalOverRemote()
+ {
+ $client = new ConfigCatClient('testLocalOverRemote', [
ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localArray([
'enabled' => false,
'nonexisting' => true,
@@ -99,12 +106,13 @@ public function testLocalOverRemote() {
),
]);
- $this->assertTrue($client->getValue("nonexisting", false));
- $this->assertFalse($client->getValue("enabled", true));
+ $this->assertTrue($client->getValue('nonexisting', false));
+ $this->assertFalse($client->getValue('enabled', true));
}
- public function testRemoteOverLocal() {
- $client = new ConfigCatClient("testRemoteOverLocal", [
+ public function testRemoteOverLocal()
+ {
+ $client = new ConfigCatClient('testRemoteOverLocal', [
ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localArray([
'enabled' => false,
'nonexisting' => true,
@@ -114,22 +122,23 @@ public function testRemoteOverLocal() {
),
]);
- $this->assertTrue($client->getValue("nonexisting", false));
- $this->assertTrue($client->getValue("enabled", false));
+ $this->assertTrue($client->getValue('nonexisting', false));
+ $this->assertTrue($client->getValue('enabled', false));
}
- public function testLocalOnlyIgnoresFetched() {
+ public function testLocalOnlyIgnoresFetched()
+ {
$handler = new MockHandler(
[new Response(200, [], self::TEST_JSON_BODY)]
);
- $client = new ConfigCatClient("testLocalOnlyIgnoresFetched", [
+ $client = new ConfigCatClient('testLocalOnlyIgnoresFetched', [
ClientOptions::FLAG_OVERRIDES => new FlagOverrides(OverrideDataSource::localArray([
'nonexisting' => true,
]), OverrideBehaviour::LOCAL_ONLY),
ClientOptions::CUSTOM_HANDLER => $handler,
]);
- $this->assertFalse($client->getValue("enabled", false));
+ $this->assertFalse($client->getValue('enabled', false));
$this->assertEquals(1, $handler->count());
}
-}
\ No newline at end of file
+}
diff --git a/tests/LoggerTest.php b/tests/LoggerTest.php
index 6d7d7b4..693cbe1 100644
--- a/tests/LoggerTest.php
+++ b/tests/LoggerTest.php
@@ -21,44 +21,52 @@ public function testLoggerBypassesInternalLogicWhenGlobalLevelIsZero()
$mockLogger
->expects(self::once())
- ->method("emergency");
+ ->method('emergency')
+ ;
$mockLogger
->expects(self::once())
- ->method("alert");
+ ->method('alert')
+ ;
$mockLogger
->expects(self::once())
- ->method("critical");
+ ->method('critical')
+ ;
$mockLogger
->expects(self::once())
- ->method("error");
+ ->method('error')
+ ;
$mockLogger
->expects(self::once())
- ->method("warning");
+ ->method('warning')
+ ;
$mockLogger
->expects(self::once())
- ->method("notice");
+ ->method('notice')
+ ;
$mockLogger
->expects(self::once())
- ->method("info");
+ ->method('info')
+ ;
$mockLogger
->expects(self::once())
- ->method("debug");
+ ->method('debug')
+ ;
- $logger->emergency("");
- $logger->alert("");
- $logger->critical("");
- $logger->error("");
- $logger->notice("");
- $logger->info("");
- $logger->debug("");
- $logger->warning("");
+ $logger->emergency('');
+ $logger->alert('');
+ $logger->critical('');
+ $logger->error('');
+ $logger->notice('');
+ $logger->info('');
+ $logger->debug('');
+ $logger->warning('');
}
public function testLoggerLogOnlyHigherLevelThanDebug()
@@ -69,44 +77,52 @@ public function testLoggerLogOnlyHigherLevelThanDebug()
$mockLogger
->expects(self::once())
- ->method("emergency");
+ ->method('emergency')
+ ;
$mockLogger
->expects(self::once())
- ->method("alert");
+ ->method('alert')
+ ;
$mockLogger
->expects(self::once())
- ->method("critical");
+ ->method('critical')
+ ;
$mockLogger
->expects(self::once())
- ->method("error");
+ ->method('error')
+ ;
$mockLogger
->expects(self::once())
- ->method("warning");
+ ->method('warning')
+ ;
$mockLogger
->expects(self::once())
- ->method("notice");
+ ->method('notice')
+ ;
$mockLogger
->expects(self::once())
- ->method("info");
+ ->method('info')
+ ;
$mockLogger
->expects(self::never())
- ->method("debug");
+ ->method('debug')
+ ;
- $logger->emergency("");
- $logger->alert("");
- $logger->critical("");
- $logger->error("");
- $logger->notice("");
- $logger->info("");
- $logger->debug("");
- $logger->warning("");
+ $logger->emergency('');
+ $logger->alert('');
+ $logger->critical('');
+ $logger->error('');
+ $logger->notice('');
+ $logger->info('');
+ $logger->debug('');
+ $logger->warning('');
}
public function testLoggerLogOnlyHigherLevelThanInfo()
@@ -117,44 +133,52 @@ public function testLoggerLogOnlyHigherLevelThanInfo()
$mockLogger
->expects(self::once())
- ->method("emergency");
+ ->method('emergency')
+ ;
$mockLogger
->expects(self::once())
- ->method("alert");
+ ->method('alert')
+ ;
$mockLogger
->expects(self::once())
- ->method("critical");
+ ->method('critical')
+ ;
$mockLogger
->expects(self::once())
- ->method("error");
+ ->method('error')
+ ;
$mockLogger
->expects(self::once())
- ->method("warning");
+ ->method('warning')
+ ;
$mockLogger
->expects(self::once())
- ->method("notice");
+ ->method('notice')
+ ;
$mockLogger
->expects(self::never())
- ->method("info");
+ ->method('info')
+ ;
$mockLogger
->expects(self::never())
- ->method("debug");
+ ->method('debug')
+ ;
- $logger->emergency("");
- $logger->alert("");
- $logger->critical("");
- $logger->error("");
- $logger->notice("");
- $logger->info("");
- $logger->debug("");
- $logger->warning("");
+ $logger->emergency('');
+ $logger->alert('');
+ $logger->critical('');
+ $logger->error('');
+ $logger->notice('');
+ $logger->info('');
+ $logger->debug('');
+ $logger->warning('');
}
public function testLoggerLogOnlyHigherLevelThanNotice()
@@ -165,44 +189,52 @@ public function testLoggerLogOnlyHigherLevelThanNotice()
$mockLogger
->expects(self::once())
- ->method("emergency");
+ ->method('emergency')
+ ;
$mockLogger
->expects(self::once())
- ->method("alert");
+ ->method('alert')
+ ;
$mockLogger
->expects(self::once())
- ->method("critical");
+ ->method('critical')
+ ;
$mockLogger
->expects(self::once())
- ->method("error");
+ ->method('error')
+ ;
$mockLogger
->expects(self::once())
- ->method("warning");
+ ->method('warning')
+ ;
$mockLogger
->expects(self::never())
- ->method("notice");
+ ->method('notice')
+ ;
$mockLogger
->expects(self::never())
- ->method("info");
+ ->method('info')
+ ;
$mockLogger
->expects(self::never())
- ->method("debug");
+ ->method('debug')
+ ;
- $logger->emergency("");
- $logger->alert("");
- $logger->critical("");
- $logger->error("");
- $logger->notice("");
- $logger->info("");
- $logger->debug("");
- $logger->warning("");
+ $logger->emergency('');
+ $logger->alert('');
+ $logger->critical('');
+ $logger->error('');
+ $logger->notice('');
+ $logger->info('');
+ $logger->debug('');
+ $logger->warning('');
}
public function testLoggerLogOnlyHigherLevelThanWarning()
@@ -213,44 +245,52 @@ public function testLoggerLogOnlyHigherLevelThanWarning()
$mockLogger
->expects(self::once())
- ->method("emergency");
+ ->method('emergency')
+ ;
$mockLogger
->expects(self::once())
- ->method("alert");
+ ->method('alert')
+ ;
$mockLogger
->expects(self::once())
- ->method("critical");
+ ->method('critical')
+ ;
$mockLogger
->expects(self::once())
- ->method("error");
+ ->method('error')
+ ;
$mockLogger
->expects(self::never())
- ->method("warning");
+ ->method('warning')
+ ;
$mockLogger
->expects(self::never())
- ->method("notice");
+ ->method('notice')
+ ;
$mockLogger
->expects(self::never())
- ->method("info");
+ ->method('info')
+ ;
$mockLogger
->expects(self::never())
- ->method("debug");
+ ->method('debug')
+ ;
- $logger->emergency("");
- $logger->alert("");
- $logger->critical("");
- $logger->error("");
- $logger->notice("");
- $logger->info("");
- $logger->debug("");
- $logger->warning("");
+ $logger->emergency('');
+ $logger->alert('');
+ $logger->critical('');
+ $logger->error('');
+ $logger->notice('');
+ $logger->info('');
+ $logger->debug('');
+ $logger->warning('');
}
public function testLoggerLogOnlyHigherLevelThanError()
@@ -261,44 +301,52 @@ public function testLoggerLogOnlyHigherLevelThanError()
$mockLogger
->expects(self::once())
- ->method("emergency");
+ ->method('emergency')
+ ;
$mockLogger
->expects(self::once())
- ->method("alert");
+ ->method('alert')
+ ;
$mockLogger
->expects(self::once())
- ->method("critical");
+ ->method('critical')
+ ;
$mockLogger
->expects(self::never())
- ->method("error");
+ ->method('error')
+ ;
$mockLogger
->expects(self::never())
- ->method("warning");
+ ->method('warning')
+ ;
$mockLogger
->expects(self::never())
- ->method("notice");
+ ->method('notice')
+ ;
$mockLogger
->expects(self::never())
- ->method("info");
+ ->method('info')
+ ;
$mockLogger
->expects(self::never())
- ->method("debug");
+ ->method('debug')
+ ;
- $logger->emergency("");
- $logger->alert("");
- $logger->critical("");
- $logger->error("");
- $logger->notice("");
- $logger->info("");
- $logger->debug("");
- $logger->warning("");
+ $logger->emergency('');
+ $logger->alert('');
+ $logger->critical('');
+ $logger->error('');
+ $logger->notice('');
+ $logger->info('');
+ $logger->debug('');
+ $logger->warning('');
}
public function testLoggerLogOnlyHigherLevelThanCritical()
@@ -309,44 +357,52 @@ public function testLoggerLogOnlyHigherLevelThanCritical()
$mockLogger
->expects(self::once())
- ->method("emergency");
+ ->method('emergency')
+ ;
$mockLogger
->expects(self::once())
- ->method("alert");
+ ->method('alert')
+ ;
$mockLogger
->expects(self::never())
- ->method("critical");
+ ->method('critical')
+ ;
$mockLogger
->expects(self::never())
- ->method("error");
+ ->method('error')
+ ;
$mockLogger
->expects(self::never())
- ->method("warning");
+ ->method('warning')
+ ;
$mockLogger
->expects(self::never())
- ->method("notice");
+ ->method('notice')
+ ;
$mockLogger
->expects(self::never())
- ->method("info");
+ ->method('info')
+ ;
$mockLogger
->expects(self::never())
- ->method("debug");
+ ->method('debug')
+ ;
- $logger->emergency("");
- $logger->alert("");
- $logger->critical("");
- $logger->error("");
- $logger->notice("");
- $logger->info("");
- $logger->debug("");
- $logger->warning("");
+ $logger->emergency('');
+ $logger->alert('');
+ $logger->critical('');
+ $logger->error('');
+ $logger->notice('');
+ $logger->info('');
+ $logger->debug('');
+ $logger->warning('');
}
public function testLoggerLogOnlyHigherLevelThanAlert()
@@ -357,44 +413,52 @@ public function testLoggerLogOnlyHigherLevelThanAlert()
$mockLogger
->expects(self::once())
- ->method("emergency");
+ ->method('emergency')
+ ;
$mockLogger
->expects(self::never())
- ->method("alert");
+ ->method('alert')
+ ;
$mockLogger
->expects(self::never())
- ->method("critical");
+ ->method('critical')
+ ;
$mockLogger
->expects(self::never())
- ->method("error");
+ ->method('error')
+ ;
$mockLogger
->expects(self::never())
- ->method("warning");
+ ->method('warning')
+ ;
$mockLogger
->expects(self::never())
- ->method("notice");
+ ->method('notice')
+ ;
$mockLogger
->expects(self::never())
- ->method("info");
+ ->method('info')
+ ;
$mockLogger
->expects(self::never())
- ->method("debug");
+ ->method('debug')
+ ;
- $logger->emergency("");
- $logger->alert("");
- $logger->critical("");
- $logger->error("");
- $logger->notice("");
- $logger->info("");
- $logger->debug("");
- $logger->warning("");
+ $logger->emergency('');
+ $logger->alert('');
+ $logger->critical('');
+ $logger->error('');
+ $logger->notice('');
+ $logger->info('');
+ $logger->debug('');
+ $logger->warning('');
}
public function testLoggerNoLog()
@@ -405,88 +469,104 @@ public function testLoggerNoLog()
$mockLogger
->expects(self::never())
- ->method("emergency");
+ ->method('emergency')
+ ;
$mockLogger
->expects(self::never())
- ->method("alert");
+ ->method('alert')
+ ;
$mockLogger
->expects(self::never())
- ->method("critical");
+ ->method('critical')
+ ;
$mockLogger
->expects(self::never())
- ->method("error");
+ ->method('error')
+ ;
$mockLogger
->expects(self::never())
- ->method("warning");
+ ->method('warning')
+ ;
$mockLogger
->expects(self::never())
- ->method("notice");
+ ->method('notice')
+ ;
$mockLogger
->expects(self::never())
- ->method("info");
+ ->method('info')
+ ;
$mockLogger
->expects(self::never())
- ->method("debug");
+ ->method('debug')
+ ;
- $logger->emergency("");
- $logger->alert("");
- $logger->critical("");
- $logger->error("");
- $logger->notice("");
- $logger->info("");
- $logger->debug("");
- $logger->warning("");
+ $logger->emergency('');
+ $logger->alert('');
+ $logger->critical('');
+ $logger->error('');
+ $logger->notice('');
+ $logger->info('');
+ $logger->debug('');
+ $logger->warning('');
}
public function testClientNoLog()
{
$mockLogger = $this->getMockBuilder(LoggerInterface::class)->getMock();
- $client = new ConfigCatClient("not-existing", [
- ClientOptions::LOGGER => $mockLogger,
- ClientOptions::LOG_LEVEL => LogLevel::NO_LOG
+ $client = new ConfigCatClient('not-existing', [
+ ClientOptions::LOGGER => $mockLogger,
+ ClientOptions::LOG_LEVEL => LogLevel::NO_LOG,
]);
$mockLogger
->expects(self::never())
- ->method("emergency");
+ ->method('emergency')
+ ;
$mockLogger
->expects(self::never())
- ->method("alert");
+ ->method('alert')
+ ;
$mockLogger
->expects(self::never())
- ->method("critical");
+ ->method('critical')
+ ;
$mockLogger
->expects(self::never())
- ->method("error");
+ ->method('error')
+ ;
$mockLogger
->expects(self::never())
- ->method("warning");
+ ->method('warning')
+ ;
$mockLogger
->expects(self::never())
- ->method("notice");
+ ->method('notice')
+ ;
$mockLogger
->expects(self::never())
- ->method("info");
+ ->method('info')
+ ;
$mockLogger
->expects(self::never())
- ->method("debug");
+ ->method('debug')
+ ;
- $client->getValue("fake", false);
+ $client->getValue('fake', false);
}
public function testLoggerBypassesLogWhenExceptionIsIgnored()
@@ -497,43 +577,51 @@ public function testLoggerBypassesLogWhenExceptionIsIgnored()
$mockLogger
->expects(self::never())
- ->method("emergency");
+ ->method('emergency')
+ ;
$mockLogger
->expects(self::never())
- ->method("alert");
+ ->method('alert')
+ ;
$mockLogger
->expects(self::never())
- ->method("critical");
+ ->method('critical')
+ ;
$mockLogger
->expects(self::never())
- ->method("error");
+ ->method('error')
+ ;
$mockLogger
->expects(self::never())
- ->method("warning");
+ ->method('warning')
+ ;
$mockLogger
->expects(self::never())
- ->method("notice");
+ ->method('notice')
+ ;
$mockLogger
->expects(self::never())
- ->method("info");
+ ->method('info')
+ ;
$mockLogger
->expects(self::never())
- ->method("debug");
+ ->method('debug')
+ ;
- $logger->emergency("", ['exception' => new InvalidArgumentException()]);
- $logger->alert("", ['exception' => new InvalidArgumentException()]);
- $logger->critical("", ['exception' => new InvalidArgumentException()]);
- $logger->error("", ['exception' => new InvalidArgumentException()]);
- $logger->notice("", ['exception' => new InvalidArgumentException()]);
- $logger->info("", ['exception' => new InvalidArgumentException()]);
- $logger->debug("", ['exception' => new InvalidArgumentException()]);
- $logger->warning("", ['exception' => new InvalidArgumentException()]);
+ $logger->emergency('', ['exception' => new InvalidArgumentException()]);
+ $logger->alert('', ['exception' => new InvalidArgumentException()]);
+ $logger->critical('', ['exception' => new InvalidArgumentException()]);
+ $logger->error('', ['exception' => new InvalidArgumentException()]);
+ $logger->notice('', ['exception' => new InvalidArgumentException()]);
+ $logger->info('', ['exception' => new InvalidArgumentException()]);
+ $logger->debug('', ['exception' => new InvalidArgumentException()]);
+ $logger->warning('', ['exception' => new InvalidArgumentException()]);
}
-}
\ No newline at end of file
+}
diff --git a/tests/RolloutIntegrationsTest.php b/tests/RolloutIntegrationsTest.php
index 6d1c522..56ed21d 100644
--- a/tests/RolloutIntegrationsTest.php
+++ b/tests/RolloutIntegrationsTest.php
@@ -14,19 +14,19 @@ class RolloutIntegrationsTest extends TestCase
const variationKind = 1;
/**
- * @param $file
- * @param $sdkKey
- * @param $kind
- *
* @dataProvider rolloutTestData
+ *
+ * @param mixed $file
+ * @param mixed $sdkKey
+ * @param mixed $kind
*/
public function testRolloutIntegration($file, $sdkKey, $kind)
{
- $rows = self::readCsv("tests/" . $file);
+ $rows = self::readCsv('tests/'.$file);
$settingKeys = array_slice($rows[0], 4);
$customKey = $rows[0][3];
$client = new ConfigCatClient($sdkKey, [
- ClientOptions::LOG_LEVEL => LogLevel::WARNING
+ ClientOptions::LOG_LEVEL => LogLevel::WARNING,
]);
$errors = [];
@@ -34,32 +34,34 @@ public function testRolloutIntegration($file, $sdkKey, $kind)
$keys = $client->getAllKeys();
$diff = array_diff($settingKeys, $keys);
if (!empty($diff)) {
- $errors[] = sprintf("Not all keys are found, Expected: %s, Result: %s, Diff: %s",
+ $errors[] = sprintf(
+ 'Not all keys are found, Expected: %s, Result: %s, Diff: %s',
print_r($settingKeys, true),
print_r($keys, true),
- print_r($diff, true));
+ print_r($diff, true)
+ );
}
foreach (range(1, count($rows) - 1) as $i) {
$testObjects = $rows[$i];
$user = null;
- if ($testObjects[0] !== "##null##") {
+ if ('##null##' !== $testObjects[0]) {
$identifier = $testObjects[0];
- $email = "";
- $country = "";
+ $email = '';
+ $country = '';
- if (!empty($testObjects[1]) && $testObjects[1] !== "##null##") {
+ if (!empty($testObjects[1]) && '##null##' !== $testObjects[1]) {
$email = $testObjects[1];
}
- if (!empty($testObjects[2]) && $testObjects[2] !== "##null##") {
+ if (!empty($testObjects[2]) && '##null##' !== $testObjects[2]) {
$country = $testObjects[2];
}
$custom = [];
- if (!empty($testObjects[3]) && $testObjects[3] !== "##null##") {
+ if (!empty($testObjects[3]) && '##null##' !== $testObjects[3]) {
$custom[$customKey] = $testObjects[3];
} elseif (is_numeric($testObjects[3])) {
$custom[$customKey] = $testObjects[3];
@@ -71,12 +73,12 @@ public function testRolloutIntegration($file, $sdkKey, $kind)
$count = 0;
foreach ($settingKeys as $key) {
$expected = $testObjects[$count + 4];
- $actual = $kind == self::valueKind
+ $actual = self::valueKind == $kind
? $client->getValue($key, null, $user)
: $client->getValueDetails($key, null, $user)->getVariationId();
if (is_bool($actual)) {
- $actual = $actual ? "True" : "False";
+ $actual = $actual ? 'True' : 'False';
}
if (is_int($actual)) {
@@ -88,19 +90,31 @@ public function testRolloutIntegration($file, $sdkKey, $kind)
}
if ($expected !== $actual) {
- $errors[] = sprintf("Identifier: %s, SettingKey: %s, UV: %s, Expected: %s, Result: %s", $testObjects[0], $key, $testObjects[3], $expected, $actual);
+ $errors[] = sprintf('Identifier: %s, SettingKey: %s, UV: %s, Expected: %s, Result: %s', $testObjects[0], $key, $testObjects[3], $expected, $actual);
}
- $count++;
+ ++$count;
}
}
$this->assertEquals(0, count($errors));
}
+ public function rolloutTestData(): array
+ {
+ return [
+ ['testmatrix.csv', 'PKDVCLf-Hq-h-kCzMp-L7Q/psuH7BGHoUmdONrzzUOY7A', self::valueKind],
+ ['testmatrix_semantic.csv', 'PKDVCLf-Hq-h-kCzMp-L7Q/BAr3KgLTP0ObzKnBTo5nhA', self::valueKind],
+ ['testmatrix_number.csv', 'PKDVCLf-Hq-h-kCzMp-L7Q/uGyK3q9_ckmdxRyI7vjwCw', self::valueKind],
+ ['testmatrix_semantic_2.csv', 'PKDVCLf-Hq-h-kCzMp-L7Q/q6jMCFIp-EmuAfnmZhPY7w', self::valueKind],
+ ['testmatrix_sensitive.csv', 'PKDVCLf-Hq-h-kCzMp-L7Q/qX3TP2dTj06ZpCCT1h_SPA', self::valueKind],
+ ['testmatrix_variationId.csv', 'PKDVCLf-Hq-h-kCzMp-L7Q/nQ5qkhRAUEa6beEyyrVLBA', self::variationKind],
+ ];
+ }
+
private static function readCsv($file): array
{
$rows = [];
- if (($handle = fopen($file, "r")) !== false) {
+ if (($handle = fopen($file, 'r')) !== false) {
while (($data = fgetcsv($handle, 1200, ';')) !== false) {
$rows[] = $data;
}
@@ -109,16 +123,4 @@ private static function readCsv($file): array
return $rows;
}
-
- public function rolloutTestData(): array
- {
- return [
- ["testmatrix.csv", "PKDVCLf-Hq-h-kCzMp-L7Q/psuH7BGHoUmdONrzzUOY7A", self::valueKind],
- ["testmatrix_semantic.csv", "PKDVCLf-Hq-h-kCzMp-L7Q/BAr3KgLTP0ObzKnBTo5nhA", self::valueKind],
- ["testmatrix_number.csv", "PKDVCLf-Hq-h-kCzMp-L7Q/uGyK3q9_ckmdxRyI7vjwCw", self::valueKind],
- ["testmatrix_semantic_2.csv", "PKDVCLf-Hq-h-kCzMp-L7Q/q6jMCFIp-EmuAfnmZhPY7w", self::valueKind],
- ["testmatrix_sensitive.csv", "PKDVCLf-Hq-h-kCzMp-L7Q/qX3TP2dTj06ZpCCT1h_SPA", self::valueKind],
- ["testmatrix_variationId.csv", "PKDVCLf-Hq-h-kCzMp-L7Q/nQ5qkhRAUEa6beEyyrVLBA", self::variationKind],
- ];
- }
}
diff --git a/tests/UserTest.php b/tests/UserTest.php
index ac76263..5fe8d6a 100644
--- a/tests/UserTest.php
+++ b/tests/UserTest.php
@@ -3,20 +3,19 @@
namespace ConfigCat\Tests;
use ConfigCat\User;
-use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
class UserTest extends TestCase
{
public function testConstructEmptyIdentifier()
{
- $user = new User("");
- $this->assertEquals("", $user->getIdentifier());
+ $user = new User('');
+ $this->assertEquals('', $user->getIdentifier());
}
public function testGetAttributeEmptyKey()
{
- $user = new User("id");
- $this->assertEquals("", $user->getAttribute(""));
+ $user = new User('id');
+ $this->assertEquals('', $user->getAttribute(''));
}
}
diff --git a/tests/Utils.php b/tests/Utils.php
index eea5a0b..a35a464 100644
--- a/tests/Utils.php
+++ b/tests/Utils.php
@@ -3,48 +3,40 @@
namespace ConfigCat\Tests;
use ConfigCat\Hooks;
+use ConfigCat\Log\DefaultLogger;
use ConfigCat\Log\InternalLogger;
use ConfigCat\Log\LogLevel;
-use Monolog\Formatter\LineFormatter;
-use Monolog\Handler\ErrorLogHandler;
-use Monolog\Logger;
-use Monolog\Processor\PsrLogMessageProcessor;
use Psr\Log\NullLogger;
class Utils
{
public static function getTestLogger(): InternalLogger
{
- $handler = new ErrorLogHandler();
- $formatter = new LineFormatter(
- "[%datetime%] %channel%.%level_name%: [%context.event_id%] %message% %context% %extra%\n",
- null, true, true);
- $handler->setFormatter($formatter);
- $psrProcessor = new PsrLogMessageProcessor(null, true);
- return new InternalLogger(new Logger("ConfigCat", [$handler], [$psrProcessor]), LogLevel::WARNING, [], new Hooks());
+ return new InternalLogger(new DefaultLogger(), LogLevel::WARNING, [], new Hooks());
}
- public static function getNullLogger(): InternalLogger {
+ public static function getNullLogger(): InternalLogger
+ {
return new InternalLogger(new NullLogger(), LogLevel::DEBUG, [], new Hooks());
}
public static function formatConfigWithRules(): string
{
- return "{ \"f\": { \"key\": { \"v\": \"def\", \"i\": \"defVar\", \"p\": [], \"r\": [
- {
- \"v\": \"fake1\",
- \"i\": \"id1\",
- \"t\": 2,
- \"a\": \"Identifier\",
- \"c\": \"@test1.com\"
- },
- {
- \"v\": \"fake2\",
- \"i\": \"id2\",
- \"t\": 2,
- \"a\": \"Identifier\",
- \"c\": \"@test2.com\"
- }
- ] }}}";
+ return '{ "f": { "key": { "v": "def", "i": "defVar", "p": [], "r": [
+ {
+ "v": "fake1",
+ "i": "id1",
+ "t": 2,
+ "a": "Identifier",
+ "c": "@test1.com"
+ },
+ {
+ "v": "fake2",
+ "i": "id2",
+ "t": 2,
+ "a": "Identifier",
+ "c": "@test2.com"
+ }
+ ] }}}';
}
-}
\ No newline at end of file
+}