diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 8ef9f42d..1c8a1e9c 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -31,6 +31,36 @@ jobs: - run: composer test + php8-4: + name: Unit Tests php8.4 (php ${{ matrix.php-version }}) + runs-on: ubuntu-latest + # always run on push events + # only run on pull_request_target event when pull request pulls from fork repository + if: > + github.event_name == 'push' || + github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository + strategy: + fail-fast: false + matrix: + php-version: [ 8.4 ] + + steps: + - uses: actions/checkout@v2 + + - uses: shivammathur/setup-php@2.9.0 + with: + php-version: ${{ matrix.php-version }} + + # Remove php-cs-fixer until compatible with PHP 8 + # This step might be removable if php-cs-fixer is compatible with 8.4 by the time this runs + - run: composer remove --dev --no-update --no-interaction friendsofphp/php-cs-fixer + + - run: composer self-update + + - run: composer install --no-interaction --prefer-source --dev + + - run: composer test + php7-4: name: Unit Tests php7.4 (php ${{ matrix.php-version }}) runs-on: ubuntu-latest @@ -109,4 +139,3 @@ jobs: - run: composer install --no-interaction --prefer-source --dev - run: composer test - diff --git a/.php-cs-fixer.cache b/.php-cs-fixer.cache new file mode 100644 index 00000000..c0dde319 --- /dev/null +++ b/.php-cs-fixer.cache @@ -0,0 +1 @@ +{"php":"8.1.27","version":"3.22.0:v3.22.0#92b019f6c8d79aa26349d0db7671d37440dc0ff3","indent":" ","lineEnding":"\n","rules":{"array_syntax":{"syntax":"short"},"no_unused_imports":true,"ordered_imports":{"imports_order":["const","class","function"]},"php_unit_fqcn_annotation":true,"phpdoc_return_self_reference":true,"phpdoc_scalar":true},"hashes":{"\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder2419\/examples\/digitalidentity\/app\/Http\/Controllers\/IdentityController.php":"369515522c3efd6cd55a8363d4e97c05","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder4308\/src\/Identity\/Policy\/Policy.php":"e1bca74eaafe5271dd1a38769fe1c3b2","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder3692\/src\/Identity\/Policy\/PolicyBuilder.php":"88302b88aba33563661d4b989b5dc429","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder2054\/tests\/Identity\/Policy\/PolicyBuilderTest.php":"a262a261102744a1acf6d5d0b421dc44","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder5221\/src\/Identity\/ReceiptBuilder.php":"2e6ef33d3401f7cbd36145ad66b3b2ef","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder289\/examples\/digitalidentity\/app\/Http\/Controllers\/ReceiptController.php":"e79ec7e1511895c954f77c713d435ad2","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder2348\/tests\/Identity\/ReceiptTest.php":"b602e6828020fef411df597e17fa7c88","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder4139\/examples\/digitalidentity\/routes\/web.php":"dcdc77843f3e59dd61467a324edf0c77","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder5396\/src\/Identity\/Receipt.php":"4744c8887009fd9ffbf084f99021eb1c","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder5193\/src\/Identity\/WrappedReceipt.php":"3a77a22be093a1da75438ea2bb9fcb20","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder4416\/examples\/digitalidentity\/app\/Http\/Controllers\/AdvancedIdentityController.php":"6b5c23f2ce8da246bc41d136d87ecdb6","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder5544\/examples\/digitalidentity\/app\/Http\/Controllers\/AdvancedIdentityController.php":"6b5c23f2ce8da246bc41d136d87ecdb6","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder4533\/src\/Identity\/Policy\/Policy.php":"bea4b7ebb268fca1ad719f933ec82cbd","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder3559\/tests\/Identity\/Policy\/PolicyBuilderTest.php":"f6d7380ae2db4eca426bb39ccfb3a900","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder2922\/examples\/digitalidentity\/routes\/web.php":"fdf260e4dfd18c8ba12078943564875a","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder3947\/src\/Constants.php":"4bb1127c9665c5d0496b90ea3211951d","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder4440\/src\/Constants.php":"99a3224f6e3fcae067362798bbab64f0","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder4745\/src\/Constants.php":"afc40e02bdc3a87ff7a874826447c604","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder1311\/src\/Constants.php":"77a8a39eac3e973495b7719ebd41509e","\/private\/var\/folders\/b6\/tqq9d7y54ll62fjfysz50ry80000gn\/T\/PHP CS Fixertemp_folder1635\/examples\/digitalidentity\/app\/Http\/Controllers\/ReceiptController.php":"10f70ffe111a0030b29762494cc5de7d"}} \ No newline at end of file diff --git a/README.md b/README.md index 6f35b579..e6dadebc 100755 --- a/README.md +++ b/README.md @@ -42,13 +42,13 @@ Add the Yoti SDK dependency: ```json "require": { - "yoti/yoti-php-sdk" : "^4.3.0" + "yoti/yoti-php-sdk" : "^4.4.0" } ``` Or run this Composer command ```console -$ composer require yoti/yoti-php-sdk "^4.3.0" +$ composer require yoti/yoti-php-sdk "^4.4.0" ``` ## Setup diff --git a/composer.json b/composer.json index 95ef8a52..b08dca14 100755 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "yoti/yoti-php-sdk", "description": "Yoti SDK for quickly integrating your PHP backend with Yoti", - "version": "4.3.0", + "version": "4.4.0", "keywords": [ "yoti", "sdk" @@ -9,7 +9,7 @@ "homepage": "https://yoti.com", "license": "MIT", "require": { - "php": "^7.4 || ^8.0 || ^8.1", + "php": "^7.4 || ^8.0 || ^8.1 || ^8.4", "ext-json": "*", "google/protobuf": "^3.10", "phpseclib/phpseclib": "^3.0", diff --git a/examples/digitalidentity/README.md b/examples/digitalidentity/README.md index 3673b72a..9bf2d1b3 100644 --- a/examples/digitalidentity/README.md +++ b/examples/digitalidentity/README.md @@ -24,4 +24,4 @@ This example requires [Docker](https://docs.docker.com/) ## Digital Identity(Advanced) Share Example * Visit [/generate-advanced-identity-share](https://localhost:4002/generate-advanced-identity-share) * ## Digital Identity DBS Example -* Visit [/generate-dbs-share](https://localhost:4002/generate-dbs-share) \ No newline at end of file +* Visit [/generate-dbs-share](https://localhost:4002/generate-dbs-share) diff --git a/examples/digitalidentity/resources/views/dbs.blade.php b/examples/digitalidentity/resources/views/dbs.blade.php index 1359cc7c..9f325177 100644 --- a/examples/digitalidentity/resources/views/dbs.blade.php +++ b/examples/digitalidentity/resources/views/dbs.blade.php @@ -85,5 +85,6 @@ function onErrorListener(...data) { await onReadyToStart() } + diff --git a/examples/digitalidentity/routes/web.php b/examples/digitalidentity/routes/web.php index 3fb377e7..f0e02806 100644 --- a/examples/digitalidentity/routes/web.php +++ b/examples/digitalidentity/routes/web.php @@ -19,4 +19,4 @@ Route::get('/generate-advanced-identity-share', 'AdvancedIdentityController@show'); Route::get('/generate-advanced-identity-session', 'AdvancedIdentityController@generateSession'); Route::get('/generate-dbs-share', 'DbsController@show'); -Route::get('/generate-dbs-session', 'DbsController@generateSession'); \ No newline at end of file +Route::get('/generate-dbs-session', 'DbsController@generateSession'); diff --git a/examples/doc-scan/app/Http/Controllers/HomeController.php b/examples/doc-scan/app/Http/Controllers/HomeController.php index 299fa6b1..f116e776 100644 --- a/examples/doc-scan/app/Http/Controllers/HomeController.php +++ b/examples/doc-scan/app/Http/Controllers/HomeController.php @@ -103,11 +103,12 @@ public function show(Request $request, DocScanClient $client) ->withMaxRetries(3) ->build() ) + /* ->withRequestedCheck( (new RequestedWatchlistAdvancedCaCheckBuilder()) ->withConfig($customConfig) ->build() - ) + )*/ ->withRequestedCheck( (new RequestedFaceMatchCheckBuilder()) ->withManualCheckFallback() @@ -150,6 +151,7 @@ public function show(Request $request, DocScanClient $client) ->withErrorUrl(config('app.url') . '/error') ->withPrivacyPolicyUrl(config('app.url') . '/privacy-policy') ->withBiometricConsentFlow('EARLY') + ->withBrandId('brand_id') ->build() ) ->withRequiredDocument( diff --git a/src/Aml/Profile.php b/src/Aml/Profile.php index b0ee2a10..d03219c3 100644 --- a/src/Aml/Profile.php +++ b/src/Aml/Profile.php @@ -50,7 +50,7 @@ class Profile implements \JsonSerializable * @param \Yoti\Aml\Address $amlAddress * @param null|string $ssn */ - public function __construct($givenNames, $familyName, Address $amlAddress, string $ssn = null) + public function __construct(string $givenNames, string $familyName, Address $amlAddress, ?string $ssn = null) { $this->givenNames = $givenNames; $this->familyName = $familyName; diff --git a/src/Constants.php b/src/Constants.php index b1cb4499..67486d3d 100644 --- a/src/Constants.php +++ b/src/Constants.php @@ -31,7 +31,7 @@ class Constants public const SDK_IDENTIFIER = 'PHP'; /** Default SDK version */ - public const SDK_VERSION = '4.3.0'; + public const SDK_VERSION = '4.4.0'; /** Base url for connect page (user will be redirected to this page eg. baseurl/app-id) */ public const CONNECT_BASE_URL = 'https://www.yoti.com/connect'; diff --git a/src/DocScan/Session/Create/Check/RequestedLivenessConfig.php b/src/DocScan/Session/Create/Check/RequestedLivenessConfig.php index 050655db..07db4fea 100644 --- a/src/DocScan/Session/Create/Check/RequestedLivenessConfig.php +++ b/src/DocScan/Session/Create/Check/RequestedLivenessConfig.php @@ -23,7 +23,7 @@ class RequestedLivenessConfig implements RequestedCheckConfigInterface */ private $manualCheck; - public function __construct(string $livenessType, int $maxRetries, string $manualCheck = null) + public function __construct(string $livenessType, int $maxRetries, ?string $manualCheck = null) { $this->livenessType = $livenessType; $this->maxRetries = $maxRetries; diff --git a/src/DocScan/Session/Create/ImportTokenBuilder.php b/src/DocScan/Session/Create/ImportTokenBuilder.php index 84340213..b40dd9bf 100644 --- a/src/DocScan/Session/Create/ImportTokenBuilder.php +++ b/src/DocScan/Session/Create/ImportTokenBuilder.php @@ -10,7 +10,7 @@ class ImportTokenBuilder private int $ttl; - public function withTtl(int $ttl = null): ImportTokenBuilder + public function withTtl(?int $ttl = null): ImportTokenBuilder { $this->ttl = $ttl ?? self::DEFAULT_TTL; diff --git a/src/DocScan/Session/Create/SdkConfig.php b/src/DocScan/Session/Create/SdkConfig.php index a3c8086d..43c0498d 100644 --- a/src/DocScan/Session/Create/SdkConfig.php +++ b/src/DocScan/Session/Create/SdkConfig.php @@ -68,6 +68,21 @@ class SdkConfig implements \JsonSerializable */ private $biometricConsentFlow; + /** + * @var string|null + */ + private $darkMode; + + /** + * @var string|null + */ + private $primaryColourDarkMode; + + /** + * @var string|null + */ + private $brandId; + /** * @param string|null $allowedCaptureMethods * @param string|null $primaryColour @@ -81,6 +96,9 @@ class SdkConfig implements \JsonSerializable * @param bool|null $allowHandoff * @param array|null $idDocumentTextDataExtractionRetriesConfig * @param string|null $biometricConsentFlow + * @param string|null $darkMode + * @param string|null $primaryColourDarkMode + * @param string|null $brandId */ public function __construct( ?string $allowedCaptureMethods, @@ -94,7 +112,10 @@ public function __construct( ?string $privacyPolicyUrl = null, ?bool $allowHandoff = null, ?array $idDocumentTextDataExtractionRetriesConfig = null, - ?string $biometricConsentFlow = null + ?string $biometricConsentFlow = null, + ?string $darkMode = null, + ?string $primaryColourDarkMode = null, + ?string $brandId = null ) { $this->allowedCaptureMethods = $allowedCaptureMethods; $this->primaryColour = $primaryColour; @@ -110,6 +131,9 @@ public function __construct( $this->attemptsConfiguration = new AttemptsConfiguration($idDocumentTextDataExtractionRetriesConfig); } $this->biometricConsentFlow = $biometricConsentFlow; + $this->darkMode = $darkMode; + $this->primaryColourDarkMode = $primaryColourDarkMode; + $this->brandId = $brandId; } /** @@ -129,7 +153,10 @@ public function jsonSerialize(): \stdClass 'privacy_policy_url' => $this->getPrivacyPolicyUrl(), 'allow_handoff' => $this->getAllowHandoff(), 'attempts_configuration' => $this->getAttemptsConfiguration(), - 'biometric_consent_flow' => $this->getBiometricConsentFlow() + 'biometric_consent_flow' => $this->getBiometricConsentFlow(), + 'dark_mode' => $this->getDarkMode(), + 'primary_colour_dark_mode' => $this->getPrimaryColourDarkMode(), + 'brand_id' => $this->getBrandId() ]); } @@ -228,4 +255,28 @@ public function getBiometricConsentFlow(): ?string { return $this->biometricConsentFlow; } + + /** + * @return string|null + */ + public function getDarkMode(): ?string + { + return $this->darkMode; + } + + /** + * @return string|null + */ + public function getPrimaryColourDarkMode(): ?string + { + return $this->primaryColourDarkMode; + } + + /** + * @return string|null + */ + public function getBrandId(): ?string + { + return $this->brandId; + } } diff --git a/src/DocScan/Session/Create/SdkConfigBuilder.php b/src/DocScan/Session/Create/SdkConfigBuilder.php index acf30fcc..5a4661dd 100644 --- a/src/DocScan/Session/Create/SdkConfigBuilder.php +++ b/src/DocScan/Session/Create/SdkConfigBuilder.php @@ -71,6 +71,21 @@ class SdkConfigBuilder */ private $biometricConsentFlow; + /** + * @var string|null + */ + private $darkMode; + + /** + * @var string|null + */ + private $primaryColourDarkMode; + + /** + * @var string|null + */ + private $brandId; + public function withAllowsCamera(): self { return $this->withAllowedCaptureMethod(self::CAMERA); @@ -146,6 +161,7 @@ public function withBiometricConsentFlow(string $biometricConsentFlow): self $this->biometricConsentFlow = $biometricConsentFlow; return $this; } + /** * Allows configuring the number of attempts permitted for text extraction on an ID document * @@ -199,6 +215,41 @@ public function withIdDocumentTextExtractionGenericAttempts(int $genericRetries) return $this; } + public function withDarkMode(string $darkMode): self + { + $this->darkMode = $darkMode; + return $this; + } + + public function withDarkModeOn(): self + { + $this->darkMode = "ON"; + return $this; + } + + public function withDarkModeOff(): self + { + $this->darkMode = "OFF"; + return $this; + } + + public function withDarkModeAuto(): self + { + $this->darkMode = "AUTO"; + return $this; + } + + public function withPrimaryColourDarkMode(string $primaryColourDarkMode): self + { + $this->primaryColourDarkMode = $primaryColourDarkMode; + return $this; + } + + public function withBrandId(string $brandId): self + { + $this->brandId = $brandId; + return $this; + } public function build(): SdkConfig { @@ -214,7 +265,10 @@ public function build(): SdkConfig $this->privacyPolicyUrl, $this->allowHandoff, $this->idDocumentTextDataExtractionRetriesConfig, - $this->biometricConsentFlow + $this->biometricConsentFlow, + $this->darkMode, + $this->primaryColourDarkMode, + $this->brandId ); } } diff --git a/src/DocScan/Session/Retrieve/CustomAccountWatchlistCaSearchConfigResponse.php b/src/DocScan/Session/Retrieve/CustomAccountWatchlistCaSearchConfigResponse.php index efa7819d..6b95fd6c 100644 --- a/src/DocScan/Session/Retrieve/CustomAccountWatchlistCaSearchConfigResponse.php +++ b/src/DocScan/Session/Retrieve/CustomAccountWatchlistCaSearchConfigResponse.php @@ -35,7 +35,9 @@ public function __construct(array $searchConfig) $this->apiKey = $searchConfig['api_key']; $this->monitoring = $searchConfig['monitoring']; $this->clientRef = $searchConfig['client_ref']; - $this->tags = array_key_exists('tags', $searchConfig) ? json_decode($searchConfig['tags'], true) : []; + $this->tags = array_key_exists('tags', $searchConfig) && is_string($searchConfig['tags']) + ? json_decode($searchConfig['tags'], true) + : (array_key_exists('tags', $searchConfig) && is_array($searchConfig['tags']) ? $searchConfig['tags'] : []); } /** diff --git a/src/Exception/ActivityDetailsException.php b/src/Exception/ActivityDetailsException.php index 1913be81..d01f61ac 100644 --- a/src/Exception/ActivityDetailsException.php +++ b/src/Exception/ActivityDetailsException.php @@ -25,7 +25,7 @@ public function __construct( $message = "", ?ResponseInterface $response = null, ?array $responseBody = null, - \Throwable $previous = null + ?\Throwable $previous = null ) { parent::__construct($message, $response, $previous); diff --git a/src/Exception/base/YotiException.php b/src/Exception/base/YotiException.php index 8dde0005..b6a7d2e6 100644 --- a/src/Exception/base/YotiException.php +++ b/src/Exception/base/YotiException.php @@ -20,7 +20,7 @@ class YotiException extends \Exception * @param ResponseInterface|null $response * @param \Throwable|null $previous */ - public function __construct($message = "", ?ResponseInterface $response = null, \Throwable $previous = null) + public function __construct($message = "", ?ResponseInterface $response = null, ?\Throwable $previous = null) { parent::__construct($this->formatMessage($message, $response), 0, $previous); diff --git a/src/Http/Exception/NetworkException.php b/src/Http/Exception/NetworkException.php index 0879d9f9..814871f7 100644 --- a/src/Http/Exception/NetworkException.php +++ b/src/Http/Exception/NetworkException.php @@ -19,7 +19,7 @@ class NetworkException extends ClientException implements NetworkExceptionInterf public function __construct( string $message, RequestInterface $request, - \Throwable $previous = null + ?\Throwable $previous = null ) { $this->setRequest($request); parent::__construct($message, 0, $previous); diff --git a/src/Http/Exception/RequestException.php b/src/Http/Exception/RequestException.php index 2ce34d5d..6c3a946c 100644 --- a/src/Http/Exception/RequestException.php +++ b/src/Http/Exception/RequestException.php @@ -19,7 +19,7 @@ class RequestException extends ClientException implements RequestExceptionInterf public function __construct( string $message, RequestInterface $request, - \Throwable $previous = null + ?\Throwable $previous = null ) { $this->setRequest($request); parent::__construct($message, 0, $previous); diff --git a/src/Http/RequestBuilder.php b/src/Http/RequestBuilder.php index 8afff19e..e2413181 100644 --- a/src/Http/RequestBuilder.php +++ b/src/Http/RequestBuilder.php @@ -73,9 +73,9 @@ class RequestBuilder private $multipartEntity; /** - * @param \Yoti\Util\Config $config + * @param \Yoti\Util\Config|null $config */ - public function __construct(Config $config = null) + public function __construct(?Config $config = null) { $this->config = $config ?? new Config(); } diff --git a/src/Http/RequestSigner.php b/src/Http/RequestSigner.php index 99bdff79..abf09fe0 100644 --- a/src/Http/RequestSigner.php +++ b/src/Http/RequestSigner.php @@ -26,7 +26,7 @@ public static function sign( PemFile $pemFile, string $endpoint, string $httpMethod, - Payload $payload = null + ?Payload $payload = null ): string { $messageToSign = "{$httpMethod}&$endpoint"; if ($payload instanceof Payload) { diff --git a/src/Identity/Content/ApplicationContent.php b/src/Identity/Content/ApplicationContent.php index 8487fc4a..7c0d267f 100644 --- a/src/Identity/Content/ApplicationContent.php +++ b/src/Identity/Content/ApplicationContent.php @@ -10,7 +10,7 @@ class ApplicationContent private ?ApplicationProfile $profile; private ?ExtraData $extraData; - public function __construct(ApplicationProfile $profile = null, ExtraData $extraData = null) + public function __construct(?ApplicationProfile $profile = null, ?ExtraData $extraData = null) { $this->profile = $profile; $this->extraData = $extraData; diff --git a/src/Identity/Content/Content.php b/src/Identity/Content/Content.php index 9cf61c01..cef3ef37 100644 --- a/src/Identity/Content/Content.php +++ b/src/Identity/Content/Content.php @@ -9,7 +9,7 @@ class Content private ?string $profile; private ?string $extraData; - public function __construct(string $profile = null, string $extraData = null) + public function __construct(?string $profile = null, ?string $extraData = null) { $this->profile = $profile; $this->extraData = $extraData; diff --git a/src/Identity/Content/UserContent.php b/src/Identity/Content/UserContent.php index a32c2dfd..a69e24fd 100644 --- a/src/Identity/Content/UserContent.php +++ b/src/Identity/Content/UserContent.php @@ -10,7 +10,7 @@ class UserContent private ?UserProfile $profile; private ?ExtraData $extraData; - public function __construct(UserProfile $profile = null, ExtraData $extraData = null) + public function __construct(?UserProfile $profile = null, ?ExtraData $extraData = null) { $this->profile = $profile; $this->extraData = $extraData; diff --git a/src/Identity/Policy/PolicyBuilder.php b/src/Identity/Policy/PolicyBuilder.php index a3b8f479..8ad89aaa 100644 --- a/src/Identity/Policy/PolicyBuilder.php +++ b/src/Identity/Policy/PolicyBuilder.php @@ -51,8 +51,8 @@ public function withWantedAttribute(WantedAttribute $wantedAttribute): self */ public function withWantedAttributeByName( string $name, - array $constraints = null, - bool $acceptSelfAsserted = null + ?array $constraints = null, + ?bool $acceptSelfAsserted = null ): self { $wantedAttributeBuilder = (new WantedAttributeBuilder()) ->withName($name); @@ -71,7 +71,7 @@ public function withWantedAttributeByName( /** * @param Constraint[]|null $constraints */ - public function withFamilyName(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withFamilyName(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_FAMILY_NAME, @@ -83,7 +83,7 @@ public function withFamilyName(array $constraints = null, bool $acceptSelfAssert /** * @param Constraint[]|null $constraints */ - public function withGivenNames(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withGivenNames(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_GIVEN_NAMES, @@ -95,7 +95,7 @@ public function withGivenNames(array $constraints = null, bool $acceptSelfAssert /** * @param Constraint[]|null $constraints */ - public function withFullName(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withFullName(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_FULL_NAME, @@ -107,7 +107,7 @@ public function withFullName(array $constraints = null, bool $acceptSelfAsserted /** * @param Constraint[]|null $constraints */ - public function withDateOfBirth(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withDateOfBirth(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_DATE_OF_BIRTH, @@ -119,7 +119,7 @@ public function withDateOfBirth(array $constraints = null, bool $acceptSelfAsser /** * @param Constraint[]|null $constraints */ - public function withAgeOver(int $age, array $constraints = null, bool $acceptSelfAsserted = null): self + public function withAgeOver(int $age, ?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withAgeDerivedAttribute( UserProfile::AGE_OVER . $age, @@ -131,7 +131,7 @@ public function withAgeOver(int $age, array $constraints = null, bool $acceptSel /** * @param Constraint[]|null $constraints */ - public function withAgeUnder(int $age, array $constraints = null, bool $acceptSelfAsserted = null): self + public function withAgeUnder(int $age, ?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withAgeDerivedAttribute( UserProfile::AGE_UNDER . $age, @@ -145,8 +145,8 @@ public function withAgeUnder(int $age, array $constraints = null, bool $acceptSe */ public function withAgeDerivedAttribute( string $derivation, - array $constraints = null, - bool $acceptSelfAsserted = null + ?array $constraints = null, + ?bool $acceptSelfAsserted = null ): self { $wantedAttributeBuilder = (new WantedAttributeBuilder()) ->withName(UserProfile::ATTR_DATE_OF_BIRTH) @@ -166,7 +166,7 @@ public function withAgeDerivedAttribute( /** * @param Constraint[]|null $constraints */ - public function withGender(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withGender(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_GENDER, @@ -178,7 +178,7 @@ public function withGender(array $constraints = null, bool $acceptSelfAsserted = /** * @param Constraint[]|null $constraints */ - public function withPostalAddress(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withPostalAddress(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_POSTAL_ADDRESS, @@ -190,7 +190,7 @@ public function withPostalAddress(array $constraints = null, bool $acceptSelfAss /** * @param Constraint[]|null $constraints */ - public function withStructuredPostalAddress(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withStructuredPostalAddress(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_STRUCTURED_POSTAL_ADDRESS, @@ -202,7 +202,7 @@ public function withStructuredPostalAddress(array $constraints = null, bool $acc /** * @param Constraint[]|null $constraints */ - public function withNationality(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withNationality(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_NATIONALITY, @@ -214,7 +214,7 @@ public function withNationality(array $constraints = null, bool $acceptSelfAsser /** * @param Constraint[]|null $constraints */ - public function withPhoneNumber(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withPhoneNumber(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_PHONE_NUMBER, @@ -226,7 +226,7 @@ public function withPhoneNumber(array $constraints = null, bool $acceptSelfAsser /** * @param Constraint[]|null $constraints */ - public function withSelfie(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withSelfie(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_SELFIE, @@ -238,7 +238,7 @@ public function withSelfie(array $constraints = null, bool $acceptSelfAsserted = /** * @param Constraint[]|null $constraints */ - public function withDocumentDetails(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withDocumentDetails(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_DOCUMENT_DETAILS, @@ -250,7 +250,7 @@ public function withDocumentDetails(array $constraints = null, bool $acceptSelfA /** * @param Constraint[]|null $constraints */ - public function withDocumentImages(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withDocumentImages(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_DOCUMENT_IMAGES, @@ -262,7 +262,7 @@ public function withDocumentImages(array $constraints = null, bool $acceptSelfAs /** * @param Constraint[]|null $constraints */ - public function withEmail(array $constraints = null, bool $acceptSelfAsserted = null): self + public function withEmail(?array $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_EMAIL_ADDRESS, diff --git a/src/Identity/Policy/WantedAttribute.php b/src/Identity/Policy/WantedAttribute.php index dc34da79..47005af1 100644 --- a/src/Identity/Policy/WantedAttribute.php +++ b/src/Identity/Policy/WantedAttribute.php @@ -29,10 +29,10 @@ class WantedAttribute implements \JsonSerializable */ public function __construct( string $name, - string $derivation = null, + ?string $derivation = null, bool $optional = false, - bool $acceptSelfAsserted = null, - array $constraints = null + ?bool $acceptSelfAsserted = null, + ?array $constraints = null ) { Validation::notEmptyString($name, 'name'); $this->name = $name; diff --git a/src/Identity/ReceiptBuilder.php b/src/Identity/ReceiptBuilder.php index 0851a088..1ec378f2 100644 --- a/src/Identity/ReceiptBuilder.php +++ b/src/Identity/ReceiptBuilder.php @@ -42,14 +42,14 @@ public function withSessionId(string $sessionId): self return $this; } - public function withRememberMeId(string $rememberMeId = null): self + public function withRememberMeId(?string $rememberMeId = null): self { $this->rememberMeId = $rememberMeId; return $this; } - public function withParentRememberMeId(string $parentRememberMeId = null): self + public function withParentRememberMeId(?string $parentRememberMeId = null): self { $this->parentRememberMeId = $parentRememberMeId; @@ -63,28 +63,28 @@ public function withTimestamp(\DateTime $timestamp): self return $this; } - public function withApplicationContent(ApplicationProfile $profile, ExtraData $extraData = null): self + public function withApplicationContent(ApplicationProfile $profile, ?ExtraData $extraData = null): self { $this->applicationContent = new ApplicationContent($profile, $extraData); return $this; } - public function withUserContent(UserProfile $profile = null, ExtraData $extraData = null): self + public function withUserContent(?UserProfile $profile = null, ?ExtraData $extraData = null): self { $this->userContent = new UserContent($profile, $extraData); return $this; } - public function withError(string $error = null): self + public function withError(?string $error = null): self { $this->error = $error; return $this; } - public function withErrorReason(ErrorReason $errorReason = null): self + public function withErrorReason(?ErrorReason $errorReason = null): self { $this->errorReason = $errorReason; diff --git a/src/Identity/ReceiptParser.php b/src/Identity/ReceiptParser.php index 904ef7b7..39fae9ee 100644 --- a/src/Identity/ReceiptParser.php +++ b/src/Identity/ReceiptParser.php @@ -21,7 +21,7 @@ class ReceiptParser */ private $logger; - public function __construct(LoggerInterface $logger = null) + public function __construct(?LoggerInterface $logger = null) { $this->logger = $logger ?? new Logger(); } diff --git a/src/Profile/Attribute.php b/src/Profile/Attribute.php index 1117f728..39f1d8b2 100644 --- a/src/Profile/Attribute.php +++ b/src/Profile/Attribute.php @@ -36,7 +36,7 @@ class Attribute * @param Anchor[] $anchors * @param string|null $id */ - public function __construct(string $name, $value, array $anchors, string $id = null) + public function __construct(string $name, $value, array $anchors, ?string $id = null) { $this->name = $name; $this->value = $value; diff --git a/src/Profile/ExtraData/AttributeIssuanceDetails.php b/src/Profile/ExtraData/AttributeIssuanceDetails.php index 019350c6..31d6e9ca 100644 --- a/src/Profile/ExtraData/AttributeIssuanceDetails.php +++ b/src/Profile/ExtraData/AttributeIssuanceDetails.php @@ -25,10 +25,10 @@ class AttributeIssuanceDetails /** * @param string $token - * @param \DateTime $expiryDate + * @param \DateTime|null $expiryDate * @param \Yoti\Profile\ExtraData\AttributeDefinition[] $issuingAttributes */ - public function __construct(string $token, \DateTime $expiryDate = null, array $issuingAttributes = []) + public function __construct(string $token, ?\DateTime $expiryDate = null, array $issuingAttributes = []) { $this->token = $token; diff --git a/src/Profile/Util/Attribute/AnchorConverter.php b/src/Profile/Util/Attribute/AnchorConverter.php index a13d6147..93f9b130 100644 --- a/src/Profile/Util/Attribute/AnchorConverter.php +++ b/src/Profile/Util/Attribute/AnchorConverter.php @@ -60,8 +60,31 @@ private static function decodeAnchorValue(string $extEncodedValue): string { $encodedBER = ASN1::extractBER($extEncodedValue); $decodedValArr = ASN1::decodeBER($encodedBER); + if (isset($decodedValArr[0]['content'][0]['content'])) { - return $decodedValArr[0]['content'][0]['content']; + $value = $decodedValArr[0]['content'][0]['content']; + + if (!is_string($value)) { + return ''; + } + + $detectionOrder = mb_detect_order(); + $encoding = mb_detect_encoding($value, is_array($detectionOrder) ? $detectionOrder : null, true); + + if (is_string($encoding)) { + if ($encoding !== 'UTF-8') { + // PHPStan implies $value is string, $encoding is valid string, so result is string. + return mb_convert_encoding($value, 'UTF-8', $encoding); + } + // It is UTF-8 + return $value; + } else { // $encoding is false (detection failed) + if (!mb_check_encoding($value, 'UTF-8')) { + // PHPStan implies $value is string, so result is string. + return mb_convert_encoding($value, 'UTF-8', 'ISO-8859-1'); + } + return $value; // It's valid UTF-8 despite detection failing + } } return ''; } @@ -108,16 +131,28 @@ private static function convertCertToX509(string $certificate): \stdClass $X509 = new X509(); $X509Data = $X509->loadX509($certificate); - /** We need because of new 3.0 version phpseclib @link https://github.com/phpseclib/phpseclib/issues/1738 */ array_walk_recursive($X509Data, function (&$item): void { - if (is_string($item) && mb_detect_encoding($item) != 'ASCII') { - $item = base64_encode($item); + if (is_string($item)) { + $detectionOrder = mb_detect_order(); + $encoding = mb_detect_encoding($item, is_array($detectionOrder) ? $detectionOrder : null, true); + + if (is_string($encoding)) { + if ($encoding !== 'UTF-8' && $encoding !== 'ASCII') { + // PHPStan implies $item is string, $encoding is valid string, so result is string. + // The 'else' branch for base64_encode was deemed unreachable by PHPStan. + $item = mb_convert_encoding($item, 'UTF-8', $encoding); + } + // If $encoding is 'UTF-8' or 'ASCII', $item is left as is. + } else { // $encoding is false (detection failed) + if (!mb_check_encoding($item, 'UTF-8') && !mb_check_encoding($item, 'ASCII')) { + $item = base64_encode($item); + } + // If it's valid UTF-8/ASCII despite detection failing, $item is left as is. + } } }); $decodedX509Data = Json::decode(Json::encode(Json::convertFromLatin1ToUtf8Recursively($X509Data)), false); - // Ensure serial number is cast to string. - // @see \phpseclib\Math\BigInteger::__toString() $decodedX509Data ->tbsCertificate ->serialNumber diff --git a/src/ShareUrl/Policy/DynamicPolicyBuilder.php b/src/ShareUrl/Policy/DynamicPolicyBuilder.php index 4d3ba083..cf395be2 100644 --- a/src/ShareUrl/Policy/DynamicPolicyBuilder.php +++ b/src/ShareUrl/Policy/DynamicPolicyBuilder.php @@ -77,8 +77,8 @@ public function withWantedAttribute(WantedAttribute $wantedAttribute): self */ public function withWantedAttributeByName( string $name, - Constraints $constraints = null, - bool $acceptSelfAsserted = null + ?Constraints $constraints = null, + ?bool $acceptSelfAsserted = null ): self { $wantedAttributeBuilder = (new WantedAttributeBuilder()) ->withName($name); @@ -100,7 +100,7 @@ public function withWantedAttributeByName( * * @return $this */ - public function withFamilyName(Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withFamilyName(?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_FAMILY_NAME, @@ -115,7 +115,7 @@ public function withFamilyName(Constraints $constraints = null, bool $acceptSelf * * @return self */ - public function withGivenNames(Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withGivenNames(?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_GIVEN_NAMES, @@ -130,7 +130,7 @@ public function withGivenNames(Constraints $constraints = null, bool $acceptSelf * * @return self */ - public function withFullName(Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withFullName(?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_FULL_NAME, @@ -145,7 +145,7 @@ public function withFullName(Constraints $constraints = null, bool $acceptSelfAs * * @return $this */ - public function withDateOfBirth(Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withDateOfBirth(?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_DATE_OF_BIRTH, @@ -161,7 +161,7 @@ public function withDateOfBirth(Constraints $constraints = null, bool $acceptSel * * @return $this */ - public function withAgeOver(int $age, Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withAgeOver(int $age, ?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withAgeDerivedAttribute( UserProfile::AGE_OVER . (string) $age, @@ -177,7 +177,7 @@ public function withAgeOver(int $age, Constraints $constraints = null, bool $acc * * @return $this */ - public function withAgeUnder(int $age, Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withAgeUnder(int $age, ?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withAgeDerivedAttribute( UserProfile::AGE_UNDER . (string) $age, @@ -195,8 +195,8 @@ public function withAgeUnder(int $age, Constraints $constraints = null, bool $ac */ public function withAgeDerivedAttribute( string $derivation, - Constraints $constraints = null, - bool $acceptSelfAsserted = null + ?Constraints $constraints = null, + ?bool $acceptSelfAsserted = null ): self { $wantedAttributeBuilder = (new WantedAttributeBuilder()) ->withName(UserProfile::ATTR_DATE_OF_BIRTH) @@ -216,7 +216,7 @@ public function withAgeDerivedAttribute( * * @return $this */ - public function withGender(Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withGender(?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_GENDER, @@ -231,7 +231,7 @@ public function withGender(Constraints $constraints = null, bool $acceptSelfAsse * * @return $this */ - public function withPostalAddress(Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withPostalAddress(?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_POSTAL_ADDRESS, @@ -246,8 +246,10 @@ public function withPostalAddress(Constraints $constraints = null, bool $acceptS * * @return $this */ - public function withStructuredPostalAddress(Constraints $constraints = null, bool $acceptSelfAsserted = null): self - { + public function withStructuredPostalAddress( + ?Constraints $constraints = null, + ?bool $acceptSelfAsserted = null + ): self { return $this->withWantedAttributeByName( UserProfile::ATTR_STRUCTURED_POSTAL_ADDRESS, $constraints, @@ -261,7 +263,7 @@ public function withStructuredPostalAddress(Constraints $constraints = null, boo * * @return $this */ - public function withNationality(Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withNationality(?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_NATIONALITY, @@ -276,7 +278,7 @@ public function withNationality(Constraints $constraints = null, bool $acceptSel * * @return $this */ - public function withPhoneNumber(Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withPhoneNumber(?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_PHONE_NUMBER, @@ -291,7 +293,7 @@ public function withPhoneNumber(Constraints $constraints = null, bool $acceptSel * * @return $this */ - public function withSelfie(Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withSelfie(?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_SELFIE, @@ -306,7 +308,7 @@ public function withSelfie(Constraints $constraints = null, bool $acceptSelfAsse * * @return $this */ - public function withDocumentDetails(Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withDocumentDetails(?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_DOCUMENT_DETAILS, @@ -321,7 +323,7 @@ public function withDocumentDetails(Constraints $constraints = null, bool $accep * * @return $this */ - public function withDocumentImages(Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withDocumentImages(?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_DOCUMENT_IMAGES, @@ -336,7 +338,7 @@ public function withDocumentImages(Constraints $constraints = null, bool $accept * * @return $this */ - public function withEmail(Constraints $constraints = null, bool $acceptSelfAsserted = null): self + public function withEmail(?Constraints $constraints = null, ?bool $acceptSelfAsserted = null): self { return $this->withWantedAttributeByName( UserProfile::ATTR_EMAIL_ADDRESS, @@ -411,7 +413,7 @@ public function withIdentityProfileRequirements($identityProfileRequirements): s * @param object $advancedIdentityProfileRequirements * @return $this */ - public function withAdvancedIdentityProfileRequirements($advancedIdentityProfileRequirements): self + public function withAdvIdentityProfileReqs($advancedIdentityProfileRequirements): self { $this->advancedIdentityProfileRequirements = $advancedIdentityProfileRequirements; return $this; diff --git a/src/ShareUrl/Policy/WantedAttribute.php b/src/ShareUrl/Policy/WantedAttribute.php index a5b0f2ed..d176070a 100644 --- a/src/ShareUrl/Policy/WantedAttribute.php +++ b/src/ShareUrl/Policy/WantedAttribute.php @@ -32,17 +32,24 @@ class WantedAttribute implements \JsonSerializable */ private $acceptSelfAsserted; + /** + * @var bool|null + */ + private $optional; + /** * @param string $name * @param string $derivation * @param bool $acceptSelfAsserted * @param \Yoti\ShareUrl\Policy\Constraints $constraints + * @param bool $optional */ public function __construct( string $name, - string $derivation = null, - bool $acceptSelfAsserted = null, - Constraints $constraints = null + ?string $derivation = null, + ?bool $acceptSelfAsserted = null, + ?Constraints $constraints = null, + ?bool $optional = null ) { Validation::notEmptyString($name, 'name'); $this->name = $name; @@ -50,6 +57,7 @@ public function __construct( $this->derivation = $derivation; $this->acceptSelfAsserted = $acceptSelfAsserted; $this->constraints = $constraints; + $this->optional = $optional; } /** @@ -97,6 +105,14 @@ public function getAcceptSelfAsserted(): ?bool return $this->acceptSelfAsserted; } + /** + * @return bool|null + */ + public function getOptional(): ?bool + { + return $this->optional; + } + /** * @inheritDoc * @@ -106,7 +122,7 @@ public function jsonSerialize(): array { $json = [ 'name' => $this->getName(), - 'optional' => false, + 'optional' => $this->getOptional(), ]; if ($this->getDerivation() !== null) { @@ -121,6 +137,12 @@ public function jsonSerialize(): array $json['accept_self_asserted'] = $this->getAcceptSelfAsserted(); } + if ($this->getOptional() !== null) { + $json['optional'] = $this->getOptional(); + } + + + return $json; } diff --git a/src/ShareUrl/Policy/WantedAttributeBuilder.php b/src/ShareUrl/Policy/WantedAttributeBuilder.php index 37f381e7..9995cfdb 100644 --- a/src/ShareUrl/Policy/WantedAttributeBuilder.php +++ b/src/ShareUrl/Policy/WantedAttributeBuilder.php @@ -29,6 +29,10 @@ class WantedAttributeBuilder */ private $acceptSelfAsserted; + /** + * @var bool|null + */ + private $optional = false; /** * @param string $name * @@ -73,6 +77,16 @@ public function withAcceptSelfAsserted(?bool $acceptSelfAsserted = true): self return $this; } + /** + * @param bool $optional + * + * @return $this + */ + public function withOptional(?bool $optional = false): self + { + $this->optional = $optional; + return $this; + } /** * @return \Yoti\ShareUrl\Policy\WantedAttribute */ @@ -82,7 +96,8 @@ public function build(): WantedAttribute $this->name, $this->derivation, $this->acceptSelfAsserted, - $this->constraints + $this->constraints, + $this->optional ); } } diff --git a/src/Util/Json.php b/src/Util/Json.php index 8be63f78..81f7bdb7 100644 --- a/src/Util/Json.php +++ b/src/Util/Json.php @@ -65,7 +65,7 @@ private static function validate(): void public static function convertFromLatin1ToUtf8Recursively($dat) { if (is_string($dat)) { - return utf8_encode($dat); + return mb_convert_encoding($dat, 'UTF-8', 'ISO-8859-1'); } elseif (is_array($dat)) { $ret = []; foreach ($dat as $i => $d) { diff --git a/tests/Aml/ResultTest.php b/tests/Aml/ResultTest.php index 76dd42d0..86f83eaf 100644 --- a/tests/Aml/ResultTest.php +++ b/tests/Aml/ResultTest.php @@ -21,6 +21,11 @@ class ResultTest extends TestCase */ public $amlResult; + /** + * @var \PHPUnit\Framework\MockObject\MockObject&\Psr\Http\Message\ResponseInterface + */ + private $responseMock; + public function setup(): void { $this->responseMock = $this->createMock(ResponseInterface::class); diff --git a/tests/DocScan/Session/Create/SdkConfigBuilderTest.php b/tests/DocScan/Session/Create/SdkConfigBuilderTest.php index 3c84f5d2..846f2433 100644 --- a/tests/DocScan/Session/Create/SdkConfigBuilderTest.php +++ b/tests/DocScan/Session/Create/SdkConfigBuilderTest.php @@ -23,7 +23,9 @@ class SdkConfigBuilderTest extends TestCase private const SOME_CATEGORY = 'someCategory'; private const SOME_NUMBER_RETRIES = 5; private const SOME_BIOMETRIC_CONSENT_FLOW = 'someBiometricConsentFlow'; - + private const SOME_DARK_MODE = 'someDarkMode'; + private const SOME_PRIMARY_COLOUR_DARK_MODE = 'somePrimaryColourDarkMode'; + private const SOME_BRAND_ID = 'someBrandId'; /** * @test @@ -38,6 +40,7 @@ class SdkConfigBuilderTest extends TestCase * @covers ::withErrorUrl * @covers ::withPrivacyPolicyUrl * @covers ::withAllowHandoff + * @covers ::withBrandId * @covers \Yoti\DocScan\Session\Create\SdkConfig::__construct * @covers \Yoti\DocScan\Session\Create\SdkConfig::getAllowedCaptureMethods * @covers \Yoti\DocScan\Session\Create\SdkConfig::getPrimaryColour @@ -49,6 +52,9 @@ class SdkConfigBuilderTest extends TestCase * @covers \Yoti\DocScan\Session\Create\SdkConfig::getErrorUrl * @covers \Yoti\DocScan\Session\Create\SdkConfig::getPrivacyPolicyUrl * @covers \Yoti\DocScan\Session\Create\SdkConfig::getAllowHandoff + * @covers \Yoti\DocScan\Session\Create\SdkConfig::getDarkMode + * @covers \Yoti\DocScan\Session\Create\SdkConfig::getPrimaryColourDarkMode + * @covers \Yoti\DocScan\Session\Create\SdkConfig::getBrandId */ public function shouldCorrectlyBuildSdkConfig() { @@ -63,6 +69,10 @@ public function shouldCorrectlyBuildSdkConfig() ->withErrorUrl(self::SOME_ERROR_URL) ->withPrivacyPolicyUrl(self::SOME_PRIVACY_POLICY_URL) ->withAllowHandoff(true) + ->withBiometricConsentFlow(self::SOME_BIOMETRIC_CONSENT_FLOW) + ->withDarkMode(self::SOME_DARK_MODE) + ->withPrimaryColourDarkMode(self::SOME_PRIMARY_COLOUR_DARK_MODE) + ->withBrandId(self::SOME_BRAND_ID) ->build(); $this->assertEquals(self::SOME_CAPTURE_METHOD, $result->getAllowedCaptureMethods()); @@ -74,7 +84,11 @@ public function shouldCorrectlyBuildSdkConfig() $this->assertEquals(self::SOME_SUCCESS_URL, $result->getSuccessUrl()); $this->assertEquals(self::SOME_ERROR_URL, $result->getErrorUrl()); $this->assertEquals(self::SOME_PRIVACY_POLICY_URL, $result->getPrivacyPolicyUrl()); + $this->assertEquals(self::SOME_BIOMETRIC_CONSENT_FLOW, $result->getBiometricConsentFlow()); $this->assertTrue($result->getAllowHandoff()); + $this->assertEquals(self::SOME_DARK_MODE, $result->getDarkMode()); + $this->assertEquals(self::SOME_PRIMARY_COLOUR_DARK_MODE, $result->getPrimaryColourDarkMode()); + $this->assertEquals(self::SOME_BRAND_ID, $result->getBrandId()); } /** @@ -121,6 +135,8 @@ public function shouldProduceTheCorrectJsonString() ->withPrivacyPolicyUrl(self::SOME_PRIVACY_POLICY_URL) ->withAllowHandoff(true) ->withBiometricConsentFlow(self::SOME_BIOMETRIC_CONSENT_FLOW) + ->withPrimaryColourDarkMode(self::SOME_PRIMARY_COLOUR_DARK_MODE) + ->withDarkMode(self::SOME_DARK_MODE) ->build(); $expected = [ @@ -134,7 +150,9 @@ public function shouldProduceTheCorrectJsonString() 'error_url' => self::SOME_ERROR_URL, 'privacy_policy_url' => self::SOME_PRIVACY_POLICY_URL, 'allow_handoff' => true, - 'biometric_consent_flow' => self::SOME_BIOMETRIC_CONSENT_FLOW + 'biometric_consent_flow' => self::SOME_BIOMETRIC_CONSENT_FLOW, + 'dark_mode' => self::SOME_DARK_MODE, + 'primary_colour_dark_mode' => self::SOME_PRIMARY_COLOUR_DARK_MODE ]; $this->assertJsonStringEqualsJsonString(json_encode($expected), json_encode($result)); @@ -291,4 +309,43 @@ public function attemptsConfigurationShouldAllowMultipleCategories(): void ->getIdDocumentTextDataExtraction() ); } + + /** + * @test + * @covers ::withDarkModeAuto + */ + public function shouldSetCorrectValueWithDarkModeAuto() + { + $result = (new SdkConfigBuilder()) + ->withDarkModeAuto() + ->build(); + + $this->assertEquals('AUTO', $result->getDarkMode()); + } + + /** + * @test + * @covers ::withDarkModeOn + */ + public function shouldSetCorrectValueWithDarkModeOn() + { + $result = (new SdkConfigBuilder()) + ->withDarkModeOn() + ->build(); + + $this->assertEquals('ON', $result->getDarkMode()); + } + + /** + * @test + * @covers ::withDarkModeOff + */ + public function shouldSetCorrectValueWithDarkModeOff() + { + $result = (new SdkConfigBuilder()) + ->withDarkModeOff() + ->build(); + + $this->assertEquals('OFF', $result->getDarkMode()); + } } diff --git a/tests/Profile/BaseProfileTest.php b/tests/Profile/BaseProfileTest.php index 71fce4bb..20c7b122 100644 --- a/tests/Profile/BaseProfileTest.php +++ b/tests/Profile/BaseProfileTest.php @@ -138,7 +138,7 @@ public function testGetAttributeById() $givenNamesAttribute = new ProtobufAttribute([ 'name' => self::SOME_ATTRIBUTE, - 'value' => utf8_decode('Alan'), + 'value' => mb_convert_encoding('Alan', 'ISO-8859-1', 'UTF-8'), 'content_type' => self::CONTENT_TYPE_STRING, ]); $newAttribute = AttributeConverter::convertToYotiAttribute($givenNamesAttribute); diff --git a/tests/Profile/Util/EncryptedDataTest.php b/tests/Profile/Util/EncryptedDataTest.php index 1680c9a8..4d1e8741 100644 --- a/tests/Profile/Util/EncryptedDataTest.php +++ b/tests/Profile/Util/EncryptedDataTest.php @@ -28,6 +28,11 @@ class EncrypedDataTest extends TestCase */ private $wrappedKey; + /** + * @var \Yoti\Protobuf\Compubapi\EncryptedData + */ + private $encryptedDataProto; + /** * Setup test data. */ diff --git a/tests/ShareUrl/Policy/DynamicPolicyBuilderTest.php b/tests/ShareUrl/Policy/DynamicPolicyBuilderTest.php index 0980b58e..0c1680a6 100644 --- a/tests/ShareUrl/Policy/DynamicPolicyBuilderTest.php +++ b/tests/ShareUrl/Policy/DynamicPolicyBuilderTest.php @@ -719,7 +719,7 @@ public function testWithAdvancedIdentityProfileRequirements() ]; $dynamicPolicy = (new DynamicPolicyBuilder()) - ->withAdvancedIdentityProfileRequirements($advancedIdentityProfileSample) + ->withAdvIdentityProfileReqs($advancedIdentityProfileSample) ->build(); $this->assertEquals(json_encode($expectedWantedAttributeData), json_encode($dynamicPolicy)); diff --git a/tests/ShareUrl/Policy/WantedAttributeBuilderTest.php b/tests/ShareUrl/Policy/WantedAttributeBuilderTest.php index 5abb542e..2b1c20f3 100644 --- a/tests/ShareUrl/Policy/WantedAttributeBuilderTest.php +++ b/tests/ShareUrl/Policy/WantedAttributeBuilderTest.php @@ -32,6 +32,7 @@ public function testBuild() $wantedAttribute = (new WantedAttributeBuilder()) ->withName($someName) ->withDerivation($someDerivation) + ->withOptional(false) ->build(); $expectedJsonData = [ @@ -91,6 +92,7 @@ public function testAcceptSelfAsserted() $wantedAttributeDefault = (new WantedAttributeBuilder()) ->withName($someName) ->withAcceptSelfAsserted() + ->withOptional(false) ->build(); $this->assertEquals(json_encode($expectedJsonData), json_encode($wantedAttributeDefault)); @@ -124,6 +126,7 @@ public function testWithoutAcceptSelfAsserted() $wantedAttribute = (new WantedAttributeBuilder()) ->withName($someName) ->withAcceptSelfAsserted(false) + ->withOptional(false) ->build(); $this->assertEquals(json_encode($expectedJsonData), json_encode($wantedAttribute)); @@ -149,6 +152,7 @@ public function testWithConstraints() $wantedAttribute = (new WantedAttributeBuilder()) ->withName($someName) + ->withOptional(false) ->withConstraints($constraints) ->build(); diff --git a/tests/Util/JsonTest.php b/tests/Util/JsonTest.php index df232c6e..30a9b29b 100644 --- a/tests/Util/JsonTest.php +++ b/tests/Util/JsonTest.php @@ -81,18 +81,27 @@ public function testWithoutNullValues() */ public function testConvertFromLatin1ToUtf8Recursively() { - $latin1String = utf8_decode('éàê'); - $latin1Array = [utf8_decode('éàê'), utf8_decode('çî')]; - $nestedLatin1Array = [utf8_decode('éàê'), [utf8_decode('çî'), utf8_decode('üñ')]]; + $latin1String = mb_convert_encoding('éàê', 'ISO-8859-1', 'UTF-8'); + $latin1Array = [ + mb_convert_encoding('éàê', 'ISO-8859-1', 'UTF-8'), + mb_convert_encoding('çî', 'ISO-8859-1', 'UTF-8') + ]; + $nestedLatin1Array = [ + mb_convert_encoding('éàê', 'ISO-8859-1', 'UTF-8'), + [ + mb_convert_encoding('çî', 'ISO-8859-1', 'UTF-8'), + mb_convert_encoding('üñ', 'ISO-8859-1', 'UTF-8') + ] + ]; $latin1Object = new \stdClass(); - $latin1Object->property1 = utf8_decode('éàê'); - $latin1Object->property2 = utf8_decode('çî'); + $latin1Object->property1 = mb_convert_encoding('éàê', 'ISO-8859-1', 'UTF-8'); + $latin1Object->property2 = mb_convert_encoding('çî', 'ISO-8859-1', 'UTF-8'); $nestedLatin1Object = new \stdClass(); - $nestedLatin1Object->property = utf8_decode('çî'); + $nestedLatin1Object->property = mb_convert_encoding('çî', 'ISO-8859-1', 'UTF-8'); $latin1ObjectWithNestedObject = new \stdClass(); - $latin1ObjectWithNestedObject->property1 = utf8_decode('éàê'); + $latin1ObjectWithNestedObject->property1 = mb_convert_encoding('éàê', 'ISO-8859-1', 'UTF-8'); $latin1ObjectWithNestedObject->property2 = $nestedLatin1Object; $this->assertSame('éàê', Json::convertFromLatin1ToUtf8Recursively($latin1String));