Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2bcd42f4a5 | |||
| 05b33ac157 | |||
| fd5477269b | |||
| afb11a6797 |
@@ -26,6 +26,7 @@
|
|||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^9",
|
"phpunit/phpunit": "^9",
|
||||||
"gullevek/dotenv": "dev-master"
|
"gullevek/dotenv": "dev-master",
|
||||||
|
"dg/bypass-finals": "dev-master"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
59
composer.lock
generated
59
composer.lock
generated
@@ -4,9 +4,63 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "412ca7fe7d62707c222169f4a7deeaec",
|
"content-hash": "717f24a1578a5d25a0522cfb908b13cc",
|
||||||
"packages": [],
|
"packages": [],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
{
|
||||||
|
"name": "dg/bypass-finals",
|
||||||
|
"version": "dev-master",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dg/bypass-finals.git",
|
||||||
|
"reference": "fb62dc6ab1a097e234fa1567943d8e87ea4d0842"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/dg/bypass-finals/zipball/fb62dc6ab1a097e234fa1567943d8e87ea4d0842",
|
||||||
|
"reference": "fb62dc6ab1a097e234fa1567943d8e87ea4d0842",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"nette/tester": "^2.3",
|
||||||
|
"phpstan/phpstan": "^0.12"
|
||||||
|
},
|
||||||
|
"default-branch": true,
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"classmap": [
|
||||||
|
"src/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-3-Clause",
|
||||||
|
"GPL-2.0",
|
||||||
|
"GPL-3.0"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "David Grudl",
|
||||||
|
"homepage": "https://davidgrudl.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Removes final keyword from source code on-the-fly and allows mocking of final methods and classes",
|
||||||
|
"keywords": [
|
||||||
|
"finals",
|
||||||
|
"mocking",
|
||||||
|
"phpunit",
|
||||||
|
"testing",
|
||||||
|
"unit"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/dg/bypass-finals/issues",
|
||||||
|
"source": "https://github.com/dg/bypass-finals/tree/master"
|
||||||
|
},
|
||||||
|
"time": "2022-04-14T12:24:34+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/instantiator",
|
"name": "doctrine/instantiator",
|
||||||
"version": "1.5.x-dev",
|
"version": "1.5.x-dev",
|
||||||
@@ -2090,7 +2144,8 @@
|
|||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"stability-flags": {
|
"stability-flags": {
|
||||||
"gullevek/dotenv": 20
|
"gullevek/dotenv": 20,
|
||||||
|
"dg/bypass-finals": 20
|
||||||
},
|
},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
|
|||||||
@@ -2,4 +2,8 @@
|
|||||||
colors="true"
|
colors="true"
|
||||||
verbose="true"
|
verbose="true"
|
||||||
>
|
>
|
||||||
|
<!-- Below removes final from classes for mock tests -->
|
||||||
|
<extensions>
|
||||||
|
<extension class="test\phpUnit\Hook\BypassFinalHook" file="test/phpUnit/Hook/BypassFinalHook.php" />
|
||||||
|
</extensions>
|
||||||
</phpunit>
|
</phpunit>
|
||||||
|
|||||||
@@ -129,6 +129,16 @@ class AWS
|
|||||||
return new CreateBalanceResponse($result);
|
return new CreateBalanceResponse($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return a new curl connection client class
|
||||||
|
*
|
||||||
|
* @return Client Curl connection Client
|
||||||
|
*/
|
||||||
|
public function newClient(): Client
|
||||||
|
{
|
||||||
|
return new Client();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General request method for all actions
|
* General request method for all actions
|
||||||
* Calls the Client class that actually runs the json request
|
* Calls the Client class that actually runs the json request
|
||||||
@@ -190,7 +200,7 @@ class AWS
|
|||||||
$date_time_string,
|
$date_time_string,
|
||||||
$service_target
|
$service_target
|
||||||
);
|
);
|
||||||
return (new Client())->request($url, $headers, $payload);
|
return ($this->newClient())->request($url, $headers, $payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ final class AmazonIncentives
|
|||||||
*/
|
*/
|
||||||
public function buyGiftCard(float $value, string $creation_request_id = null): Response\CreateResponse
|
public function buyGiftCard(float $value, string $creation_request_id = null): Response\CreateResponse
|
||||||
{
|
{
|
||||||
return (new AWS($this->config))->getCode($value, $creation_request_id);
|
return ($this->newAWS())->getCode($value, $creation_request_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ final class AmazonIncentives
|
|||||||
*/
|
*/
|
||||||
public function cancelGiftCard(string $creation_request_id, string $gift_card_id): Response\CancelResponse
|
public function cancelGiftCard(string $creation_request_id, string $gift_card_id): Response\CancelResponse
|
||||||
{
|
{
|
||||||
return (new AWS($this->config))->cancelCode($creation_request_id, $gift_card_id);
|
return ($this->newAWS())->cancelCode($creation_request_id, $gift_card_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,7 +94,7 @@ final class AmazonIncentives
|
|||||||
*/
|
*/
|
||||||
public function getAvailableFunds(): Response\CreateBalanceResponse
|
public function getAvailableFunds(): Response\CreateBalanceResponse
|
||||||
{
|
{
|
||||||
return (new AWS($this->config))->getBalance();
|
return ($this->newAWS())->getBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,6 +119,17 @@ final class AmazonIncentives
|
|||||||
return new static($key, $secret, $partner, $endpoint, $currency, $debug);
|
return new static($key, $secret, $partner, $endpoint, $currency, $debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wrapper to create new AWS class.
|
||||||
|
* used in all buy/cancel/get calss
|
||||||
|
*
|
||||||
|
* @return AWS Main AWS worker class
|
||||||
|
*/
|
||||||
|
public function newAWS(): AWS
|
||||||
|
{
|
||||||
|
return new AWS($this->config);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes the Exception message body
|
* Decodes the Exception message body
|
||||||
* Returns an array with code (Amazon error codes), type (Amazon error info)
|
* Returns an array with code (Amazon error codes), type (Amazon error info)
|
||||||
@@ -126,22 +137,12 @@ final class AmazonIncentives
|
|||||||
*
|
*
|
||||||
* @param string $message Exception message json string
|
* @param string $message Exception message json string
|
||||||
* @return array<mixed> Decoded with code, type, message fields
|
* @return array<mixed> Decoded with code, type, message fields
|
||||||
|
*
|
||||||
|
* @deprecated use \gullevek\AmazonIncentives\Exceptions\AmazonErrors::decodeExceptionMessage()
|
||||||
*/
|
*/
|
||||||
public static function decodeExceptionMessage(string $message): array
|
public static function decodeExceptionMessage(string $message): array
|
||||||
{
|
{
|
||||||
$message_ar = json_decode($message, true);
|
return AmazonErrors::decodeExceptionMessage($message);
|
||||||
// if we have an error, build empty block and only fill message
|
|
||||||
if (json_last_error()) {
|
|
||||||
$message_ar = [
|
|
||||||
'status' => '',
|
|
||||||
'code' => '',
|
|
||||||
'type' => '',
|
|
||||||
'message' => $message,
|
|
||||||
'log_id' => '',
|
|
||||||
'log' => []
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return $message_ar;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
|
|||||||
@@ -39,6 +39,31 @@ final class AmazonErrors extends RuntimeException
|
|||||||
$_error_code
|
$_error_code
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the Exception message body
|
||||||
|
* Returns an array with code (Amazon error codes), type (Amazon error info)
|
||||||
|
* message (Amazon returned error message string)
|
||||||
|
*
|
||||||
|
* @param string $message Exception message json string
|
||||||
|
* @return array<mixed> Decoded with code, type, message fields
|
||||||
|
*/
|
||||||
|
public static function decodeExceptionMessage(string $message): array
|
||||||
|
{
|
||||||
|
$message_ar = json_decode($message, true);
|
||||||
|
// if we have an error, build empty block and only fill message
|
||||||
|
if (json_last_error()) {
|
||||||
|
$message_ar = [
|
||||||
|
'status' => '',
|
||||||
|
'code' => '',
|
||||||
|
'type' => '',
|
||||||
|
'message' => $message,
|
||||||
|
'log_id' => '',
|
||||||
|
'log' => []
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $message_ar;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// __END__
|
// __END__
|
||||||
|
|||||||
140
test/agcod_http_return_samples.md
Normal file
140
test/agcod_http_return_samples.md
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
# Return data from AWS as json string
|
||||||
|
|
||||||
|
## Mock tests self
|
||||||
|
|
||||||
|
Tests run in local mock tests without connection to AWS
|
||||||
|
|
||||||
|
### funds
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"availableFunds":{"amount":0.0,"currencyCode":"JPY"},"status":"SUCCESS","timestamp":"20220610T085450Z"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### buy
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"cardInfo":{"cardNumber":null,"cardStatus":"Fulfilled","expirationDate":null,"value":{"amount":1000.0,"currencyCode":"JPY"}},"creationRequestId":"PartnerId_62a309167e7a4","gcClaimCode":"LJ49-AKDUV6-UYCP","gcExpirationDate":"Thu Jun 10 14:59:59 UTC 2032","gcId":"5535125272070255","status":"SUCCESS"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### cancel
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"creationRequestId":"EG3bd_62a309167e7a4","gcId":"5535125272070255","status":"SUCCESS"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### buy other 1
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"cardInfo":{"cardNumber":null,"cardStatus":"RefundedToPurchaser","expirationDate":null,"value":{"amount":1000.0,"currencyCode":"JPY"}},"creationRequestId":"PartnerId_62a309167e7a4","gcClaimCode":"LJ49-AKDUV6-UYCP","gcExpirationDate":"Thu Jun 10 14:59:59 UTC 2032","gcId":"5535125272070255","status":"SUCCESS"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### buy aother 2
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"cardInfo":{"cardNumber":null,"cardStatus":"Fulfilled","expirationDate":null,"value":{"amount":1000.0,"currencyCode":"JPY"}},"creationRequestId":"PartnerId_62a30923e9705","gcClaimCode":"UM97-FD5QKK-WKCT","gcExpirationDate":"Thu Jun 10 14:59:59 UTC 2032","gcId":"5540334324324221","status":"SUCCESS"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### buy other 2 (same create request id)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"cardInfo":{"cardNumber":null,"cardStatus":"Fulfilled","expirationDate":null,"value":{"amount":1000.0,"currencyCode":"JPY"}},"creationRequestId":"PartnerId_62a30923e9705","gcClaimCode":"UM97-FD5QKK-WKCT","gcExpirationDate":"Thu Jun 10 14:59:59 UTC 2032","gcId":"5540334324324221","status":"SUCCESS"}
|
||||||
|
```
|
||||||
|
|
||||||
|
## AWS GCOD Mocks
|
||||||
|
|
||||||
|
Mocking on AWS side, these will be returned if given request ID codes are sent.
|
||||||
|
A working test account must exist for this
|
||||||
|
|
||||||
|
## success
|
||||||
|
|
||||||
|
### buy gift card F0000
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"cardInfo":{"cardNumber":null,"cardStatus":"Fulfilled","expirationDate":null,"value":{"amount":500.0,"currencyCode":"JPY"}},"creationRequestId":"F0000","gcClaimCode":"ZYXW-VUTS-RQPO","gcExpirationDate":null,"gcId":"ABC123ZYX987","status":"SUCCESS"}
|
||||||
|
```
|
||||||
|
|
||||||
|
## errors
|
||||||
|
|
||||||
|
### F1000 -> F100
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F100","errorType":"GeneralError","message":"General Error"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F2003 -> F200
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"InvalidAmountInput","message":"Amount can't be null"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F2004 -> F200
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"InvalidAmountValue","message":"Amount must be larger than 0"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F2005 -> F200
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"InvalidCurrencyCodeInput","message":"Currency Code can't be null or empty"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F2010 -> F200
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"CardAlreadyActivatedWithDifferentRequestId","message":"The card was already activated with a different request id"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F2015 -> F200
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"MaxAmountExceeded","message":"Max Amount Exceeded"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F2016 -> F200
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"CurrencyCodeMismatch","message":"Currency Code Mismatch"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F2017 -> F200
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"FractionalAmountNotAllowed","message":"Fractional Amount Not Allowed"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F2047 -> F200
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"CancelRequestArrivedAfterTimeLimit","message":"Cancellation cannot be processed as too much time has elapsed since creation"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F3003 -> F300
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F300","errorType":"InsufficientFunds","message":"Insufficient Funds"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F3005 -> F300
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F300","errorType":"GeneralError","message":"General Error"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F3010 -> F300
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F300","errorType":"CustomerSurpassedDailyVelocityLimit","message":"Customer has exceeded daily velocity limit"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F4000 -> F400
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"RESEND"},"errorCode":"F400","errorType":"SystemTemporarilyUnavailable","message":"System Temporarily Unavailable"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### F5000 -> F500
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F500","errorType":"GeneralError","message":"General Error"}
|
||||||
|
```
|
||||||
@@ -59,6 +59,7 @@ $loader->addPsr4('gullevek\\', __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_
|
|||||||
// print "LOADER: <pre>" . print_r($loader, true) . "</pre>";
|
// print "LOADER: <pre>" . print_r($loader, true) . "</pre>";
|
||||||
|
|
||||||
use gullevek\AmazonIncentives\AmazonIncentives;
|
use gullevek\AmazonIncentives\AmazonIncentives;
|
||||||
|
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
|
||||||
use gullevek\dotEnv\DotEnv;
|
use gullevek\dotEnv\DotEnv;
|
||||||
|
|
||||||
// load env data with dotenv
|
// load env data with dotenv
|
||||||
@@ -75,30 +76,34 @@ print "<h1>Amazon Gift Card Incentives</h1><br>";
|
|||||||
// optional
|
// optional
|
||||||
// debug: AWS_DEBUG (if not set: off)
|
// debug: AWS_DEBUG (if not set: off)
|
||||||
|
|
||||||
|
// run info test (prints ENV vars)
|
||||||
|
$run_info_test = !empty($_GET['info']) ? true : false;
|
||||||
|
// run test to get funds info
|
||||||
|
$run_fund_test = !empty($_GET['fund']) ? true : false;
|
||||||
|
// run the normal get/cancel gift card tests
|
||||||
|
$run_gift_tests = !empty($_GET['gift']) ? true : false;
|
||||||
|
// run mock error check tests
|
||||||
|
$run_mocks = !empty($_GET['mocks']) ? true : false;
|
||||||
|
|
||||||
|
// should we print debug info
|
||||||
|
$debug_print = !empty($_GET['debug']) ? true : false;
|
||||||
|
// how long to wait between each call
|
||||||
|
$debug_wait = 2;
|
||||||
|
// if set to true will print all the debug logs too
|
||||||
|
$mock_debug = !empty($_GET['debug_mock']) ? true : false;
|
||||||
|
// wait in seconds between mock tests
|
||||||
|
$mock_wait = 2;
|
||||||
|
|
||||||
|
if (empty($_GET)) {
|
||||||
|
print "<b>Use _GET parameters to start tests</b>";
|
||||||
|
}
|
||||||
|
|
||||||
// open debug file output
|
// open debug file output
|
||||||
$fp = fopen('log/debug.' . date('YmdHis') . '.log', 'w');
|
$fp = fopen('log/debug.' . date('YmdHis') . '.log', 'w');
|
||||||
if (!is_resource($fp)) {
|
if (!is_resource($fp)) {
|
||||||
die("Cannot open log debug file");
|
die("Cannot open log debug file");
|
||||||
}
|
}
|
||||||
|
|
||||||
// run info test (prints ENV vars)
|
|
||||||
$run_info_test = false;
|
|
||||||
// run test to get funds info
|
|
||||||
$run_fund_test = true;
|
|
||||||
// run the normal get/cancel gift card tests
|
|
||||||
$run_gift_tests = true;
|
|
||||||
// run mock error check tests
|
|
||||||
$run_mocks = false;
|
|
||||||
|
|
||||||
// should we print debug info
|
|
||||||
$debug_print = false;
|
|
||||||
// how long to wait between each call
|
|
||||||
$debug_wait = 2;
|
|
||||||
// if set to true will print all the debug logs too
|
|
||||||
$mock_debug = false;
|
|
||||||
// wait in seconds between mock tests
|
|
||||||
$mock_wait = 2;
|
|
||||||
|
|
||||||
if ($run_info_test === true) {
|
if ($run_info_test === true) {
|
||||||
$aws = new AmazonIncentives();
|
$aws = new AmazonIncentives();
|
||||||
$aws_check_me = $aws->checkMe();
|
$aws_check_me = $aws->checkMe();
|
||||||
@@ -120,7 +125,7 @@ if ($run_fund_test === true) {
|
|||||||
}
|
}
|
||||||
fwrite($fp, writeLog((array)$aws_test));
|
fwrite($fp, writeLog((array)$aws_test));
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
|
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
|
||||||
printException('getAvailableFunds', $e->getCode(), $error, $debug_print);
|
printException('getAvailableFunds', $e->getCode(), $error, $debug_print);
|
||||||
fwrite($fp, writeLog($error));
|
fwrite($fp, writeLog($error));
|
||||||
};
|
};
|
||||||
@@ -152,7 +157,7 @@ if ($run_gift_tests === true) {
|
|||||||
}
|
}
|
||||||
fwrite($fp, writeLog((array)$aws_test));
|
fwrite($fp, writeLog((array)$aws_test));
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
|
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
|
||||||
printException('buyGiftCard', $e->getCode(), $error, $debug_print);
|
printException('buyGiftCard', $e->getCode(), $error, $debug_print);
|
||||||
fwrite($fp, writeLog($error));
|
fwrite($fp, writeLog($error));
|
||||||
}
|
}
|
||||||
@@ -169,7 +174,7 @@ if ($run_gift_tests === true) {
|
|||||||
}
|
}
|
||||||
fwrite($fp, writeLog((array)$aws_test));
|
fwrite($fp, writeLog((array)$aws_test));
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
|
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
|
||||||
print "AWS: cancelGiftCard: " . $error['status']
|
print "AWS: cancelGiftCard: " . $error['status']
|
||||||
. " [" . $e->getCode() . "]: "
|
. " [" . $e->getCode() . "]: "
|
||||||
. $error['code'] . " | " . $error['type']
|
. $error['code'] . " | " . $error['type']
|
||||||
@@ -197,7 +202,7 @@ if ($run_gift_tests === true) {
|
|||||||
}
|
}
|
||||||
fwrite($fp, writeLog((array)$aws_test));
|
fwrite($fp, writeLog((array)$aws_test));
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
|
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
|
||||||
printException('buyGiftCard', $e->getCode(), $error, $debug_print);
|
printException('buyGiftCard', $e->getCode(), $error, $debug_print);
|
||||||
fwrite($fp, writeLog($error));
|
fwrite($fp, writeLog($error));
|
||||||
}
|
}
|
||||||
@@ -221,7 +226,7 @@ if ($run_gift_tests === true) {
|
|||||||
}
|
}
|
||||||
fwrite($fp, writeLog((array)$aws_test));
|
fwrite($fp, writeLog((array)$aws_test));
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
|
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
|
||||||
printException('cancelGiftCard', $e->getCode(), $error, $debug_print);
|
printException('cancelGiftCard', $e->getCode(), $error, $debug_print);
|
||||||
fwrite($fp, writeLog($error));
|
fwrite($fp, writeLog($error));
|
||||||
}
|
}
|
||||||
@@ -242,7 +247,7 @@ if ($run_gift_tests === true) {
|
|||||||
}
|
}
|
||||||
fwrite($fp, writeLog((array)$aws_test));
|
fwrite($fp, writeLog((array)$aws_test));
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
|
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
|
||||||
printException('buyGiftCard', $e->getCode(), $error, $debug_print);
|
printException('buyGiftCard', $e->getCode(), $error, $debug_print);
|
||||||
fwrite($fp, writeLog($error));
|
fwrite($fp, writeLog($error));
|
||||||
}
|
}
|
||||||
@@ -295,7 +300,7 @@ if ($run_mocks === true) {
|
|||||||
}
|
}
|
||||||
fwrite($fp, writeLog((array)$aws_test));
|
fwrite($fp, writeLog((array)$aws_test));
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
|
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
|
||||||
print "AWS: MOCK: " . $creation_id . ": buyGiftCard: " . $error['status']
|
print "AWS: MOCK: " . $creation_id . ": buyGiftCard: " . $error['status']
|
||||||
. " [" . $e->getCode() . "]: "
|
. " [" . $e->getCode() . "]: "
|
||||||
. $error['code'] . " | " . $error['type']
|
. $error['code'] . " | " . $error['type']
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace tests;
|
namespace test\phpUnit;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use gullevek\AmazonIncentives\AmazonIncentives;
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
use gullevek\AmazonIncentives;
|
||||||
use gullevek\dotEnv\DotEnv;
|
use gullevek\dotEnv\DotEnv;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,71 +16,932 @@ use gullevek\dotEnv\DotEnv;
|
|||||||
*/
|
*/
|
||||||
final class AmazonIncentivesTest extends TestCase
|
final class AmazonIncentivesTest extends TestCase
|
||||||
{
|
{
|
||||||
public function amazonIncentivesProvider(): array
|
/** @var int wait tme in seconds between AWS side mock calls */
|
||||||
|
private $mock_wait = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client curl exception testing
|
||||||
|
*
|
||||||
|
* @testdox AWS Incentives curl exception handling
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testAwsIncentivesCurlException(): void
|
||||||
{
|
{
|
||||||
|
// this is the exceptio we want
|
||||||
|
$this->expectException(AmazonIncentives\Exceptions\AmazonErrors::class);
|
||||||
|
// we don't need a class here, we just need client
|
||||||
|
$client = new AmazonIncentives\Client\Client();
|
||||||
|
// produce any error
|
||||||
|
$client->request('invalid', [], '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* curl/connection error checks
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function amazonIncentivesProviderErrors(): array
|
||||||
|
{
|
||||||
|
// parameter data only for this
|
||||||
|
// 0: url
|
||||||
|
// 1: expected status
|
||||||
|
// 2: expected code
|
||||||
|
// 3: expected type
|
||||||
return [
|
return [
|
||||||
'empty' => [
|
// C001
|
||||||
|
'C002 error' => [
|
||||||
|
'url' => 'invalid',
|
||||||
|
'expected_status' => 'FAILURE',
|
||||||
|
'expected_error' => 'C002',
|
||||||
|
'expected_type' => 'CurlError'
|
||||||
|
],
|
||||||
|
// T001 timeout
|
||||||
|
// 'T001 error' => [
|
||||||
|
// 'url' => 'https://timeout.teq.jp',
|
||||||
|
// 'expected_status' => 'RESEND',
|
||||||
|
// 'expected_error' => 'T001',
|
||||||
|
// 'expected_type' => 'RateExceeded'
|
||||||
|
// ],
|
||||||
|
// other error
|
||||||
|
'E999 error' => [
|
||||||
|
'url' => 'https://www.yahoo.co.jp',
|
||||||
|
'expected_status' => 'FAILURE',
|
||||||
|
'expected_error' => 'E999',
|
||||||
|
'expected_type' => 'OtherUnknownError'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test errors thrown in Client class
|
||||||
|
*
|
||||||
|
* @dataProvider amazonIncentivesProviderErrors
|
||||||
|
* @testdox AWS Incentives error handling [$_dataName]
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testAwsIncentivesCurlErrors(
|
||||||
|
string $url,
|
||||||
|
string $expected_status,
|
||||||
|
string $expected_error,
|
||||||
|
string $expected_type
|
||||||
|
): void {
|
||||||
|
// HANDLE:
|
||||||
|
// * Init error
|
||||||
|
// - C001/Curl init error
|
||||||
|
// * Client errors (C002)/false:
|
||||||
|
// - CURLE_COULDNT_CONNECT
|
||||||
|
// - CURLE_COULDNT_RESOLVE_HOST
|
||||||
|
// - CURLE_OPERATION_TIMEOUTED
|
||||||
|
// - CURLE_SSL_PEER_CERTIFICATE
|
||||||
|
// - 0/OTHER
|
||||||
|
// * Client errors other
|
||||||
|
// - T001/Rate exceeded
|
||||||
|
// - E999/Other error
|
||||||
|
|
||||||
|
// try/catch
|
||||||
|
// -decodeExceptionMessage (static)
|
||||||
|
|
||||||
|
// we don't need the full interface here, we just need client class
|
||||||
|
$client = new AmazonIncentives\Client\Client();
|
||||||
|
try {
|
||||||
|
// set expected throw error
|
||||||
|
$result = $client->request($url, [], '');
|
||||||
|
print "R: " . $result . "\n";
|
||||||
|
} catch (AmazonIncentives\Exceptions\AmazonErrors $e) {
|
||||||
|
$curl_error = AmazonIncentives\Exceptions\AmazonErrors::decodeExceptionMessage($e->getMessage());
|
||||||
|
// print "E-B: " . print_r($curl_error, true) . "\n";
|
||||||
|
$this->assertEquals(
|
||||||
|
$expected_status,
|
||||||
|
$curl_error['status'],
|
||||||
|
'Assert error status'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$expected_error,
|
||||||
|
$curl_error['code'],
|
||||||
|
'Assert error code'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$expected_type,
|
||||||
|
$curl_error['type'],
|
||||||
|
'Assert error type'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* init amazon incentive interface
|
||||||
|
*
|
||||||
|
* @param array $connect
|
||||||
|
* @param bool $mock
|
||||||
|
* @param array|null $mock_response
|
||||||
|
* @return AmazonIncentives\AmazonIncentives
|
||||||
|
*/
|
||||||
|
private function awsIncentivesStartUp(
|
||||||
|
array $connect,
|
||||||
|
bool $mock,
|
||||||
|
?array $mock_response,
|
||||||
|
): AmazonIncentives\AmazonIncentives {
|
||||||
|
$env_folder = $connect['env_folder'] ?? '';
|
||||||
|
$env_file = $connect['env_file'] ?? '';
|
||||||
|
$parameters = $connect['parameters'] ?? [];
|
||||||
|
// reset _ENV always
|
||||||
|
$_ENV = [];
|
||||||
|
// env file read status
|
||||||
|
$status = null;
|
||||||
|
if (!empty($env_folder)) {
|
||||||
|
if (!empty($env_file)) {
|
||||||
|
$status = DotEnv::readEnvFile($env_folder, $env_file);
|
||||||
|
} else {
|
||||||
|
$status = DotEnv::readEnvFile($env_folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ENV must match _ENV vars if set
|
||||||
|
if (!empty($env_folder) && $status != 0) {
|
||||||
|
// abort with error
|
||||||
|
$this->markTestSkipped(
|
||||||
|
'Cannot read .env file needed for AWS tests: ' . $status
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MOCK:
|
||||||
|
// - for all buyGiftCard|cancelGiftCard|getAvailableFunds
|
||||||
|
// WHAT:
|
||||||
|
// \AWS->getCode|cancelCode|getBalance
|
||||||
|
// -> \AWS->makeReqeust
|
||||||
|
// -> NEW Client->request <= MOCK this
|
||||||
|
// NOT MOCK:
|
||||||
|
// any error calls in Client->request or exceptions
|
||||||
|
|
||||||
|
if ($mock === true) {
|
||||||
|
// create a new config with or without parameters
|
||||||
|
$agcod_config = new AmazonIncentives\Config\Config(
|
||||||
|
$parameters['key'] ?? null,
|
||||||
|
$parameters['secret'] ?? null,
|
||||||
|
$parameters['partner'] ?? null,
|
||||||
|
$parameters['endpoint'] ?? null,
|
||||||
|
$parameters['currency'] ?? null,
|
||||||
|
$parameters['debug'] ?? null
|
||||||
|
);
|
||||||
|
|
||||||
|
// MOCK CLIENT
|
||||||
|
// Master mock the Client class for request call
|
||||||
|
// If we wan't to get errors thrown
|
||||||
|
/** @var AmazonIncentives\Client\Client&MockObject */
|
||||||
|
$client_mock = $this->createPartialMock(AmazonIncentives\Client\Client::class, ['request']);
|
||||||
|
// set the needed return here
|
||||||
|
$client_mock->method('request')->willReturn(json_encode($mock_response));
|
||||||
|
|
||||||
|
// MOCK AWS and attache above class in client return
|
||||||
|
/** @var AmazonIncentives\AWS\AWS&MockObject */
|
||||||
|
$aws_mock = $this->getMockBuilder(AmazonIncentives\AWS\AWS::class)
|
||||||
|
->setConstructorArgs([$agcod_config])
|
||||||
|
->onlyMethods(['newClient'])
|
||||||
|
->getMock();
|
||||||
|
// attach mocked client
|
||||||
|
$aws_mock->method('newClient')->willReturn($client_mock);
|
||||||
|
|
||||||
|
// MOCK AMAZONINCENTIVES
|
||||||
|
/** @var AmazonIncentives\AmazonIncentives&MockObject */
|
||||||
|
$agcod = $this->getMockBuilder(AmazonIncentives\AmazonIncentives::class)
|
||||||
|
->setConstructorArgs([
|
||||||
|
$parameters['key'] ?? null,
|
||||||
|
$parameters['secret'] ?? null,
|
||||||
|
$parameters['partner'] ?? null,
|
||||||
|
$parameters['endpoint'] ?? null,
|
||||||
|
$parameters['currency'] ?? null,
|
||||||
|
$parameters['debug'] ?? null
|
||||||
|
])
|
||||||
|
->onlyMethods(['newAWS'])
|
||||||
|
->getMock();
|
||||||
|
// attach mocked AWS class
|
||||||
|
$agcod->method('newAWS')->willReturn($aws_mock);
|
||||||
|
} else {
|
||||||
|
// if we mock, we mock the Client->request
|
||||||
|
$agcod = new AmazonIncentives\AmazonIncentives(
|
||||||
|
$parameters['key'] ?? null,
|
||||||
|
$parameters['secret'] ?? null,
|
||||||
|
$parameters['partner'] ?? null,
|
||||||
|
$parameters['endpoint'] ?? null,
|
||||||
|
$parameters['currency'] ?? null,
|
||||||
|
$parameters['debug'] ?? null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $agcod;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the configs for loading data from .env for parameter
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function awsIncentivesProvider(): array
|
||||||
|
{
|
||||||
|
// 0: .env file folder
|
||||||
|
// 1: .env file name (if not set use .env)
|
||||||
|
// 2: parameters that override _ENV variables
|
||||||
|
return [
|
||||||
|
// this is with real test account data
|
||||||
|
'env_test' => [
|
||||||
|
'env_folder' => __DIR__ . DIRECTORY_SEPARATOR . '..',
|
||||||
|
'env_file' => null,
|
||||||
|
'parameters' => null
|
||||||
|
],
|
||||||
|
// this is for mocking only
|
||||||
|
'parameter_dummy' => [
|
||||||
'env_folder' => null,
|
'env_folder' => null,
|
||||||
'env_file' => null,
|
'env_file' => null,
|
||||||
|
'parameters' => [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
'http://i.dont.exist.at.all',
|
||||||
|
'JPY'
|
||||||
]
|
]
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undocumented function
|
* Undocumented function
|
||||||
*
|
*
|
||||||
* @dataProvider amazonIncentivesProvider
|
* @return array
|
||||||
* @testdox AmazonIncentives tests [$_dataName]
|
*/
|
||||||
|
public function amazonIncentivesProviderGetFunds(): array
|
||||||
|
{
|
||||||
|
// remove final keyword
|
||||||
|
// BypassFinals::enable();
|
||||||
|
// get connectors
|
||||||
|
$connectors = $this->awsIncentivesProvider();
|
||||||
|
// 0: connect array (env file, env folder, parameters array)
|
||||||
|
// 1: mock or normal call
|
||||||
|
// 2: if mock connect response must be defined here
|
||||||
|
// 3: exepcted response array
|
||||||
|
return [
|
||||||
|
'non mock test data' => [
|
||||||
|
'connect' => $connectors['env_test'],
|
||||||
|
'mock' => false,
|
||||||
|
'mock_response' => null,
|
||||||
|
'expected' => [
|
||||||
|
//
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'mock data test' => [
|
||||||
|
'connect' => $connectors['parameter_dummy'],
|
||||||
|
'mock' => true,
|
||||||
|
'mock_response' => [
|
||||||
|
'availableFunds' => [
|
||||||
|
'amount' => 0.0,
|
||||||
|
'currencyCode' => 'JPY',
|
||||||
|
],
|
||||||
|
'status' => 'SUCCESS',
|
||||||
|
'timestamp' => '20220610T085450Z',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undocumented function
|
||||||
*
|
*
|
||||||
|
* @dataProvider amazonIncentivesProviderGetFunds
|
||||||
|
* @testdox AWS Incentives get available funds [$_dataName]
|
||||||
|
*
|
||||||
|
* @param array $connect
|
||||||
|
* @param bool $mock
|
||||||
|
* @param array|null $mock_response
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function testAmazonIncentives(?string $env_folder, ?string $env_file): void
|
public function testAwsIncentivesGetAvailableFunds(
|
||||||
|
array $connect,
|
||||||
|
bool $mock,
|
||||||
|
?array $mock_response
|
||||||
|
): void {
|
||||||
|
// load class
|
||||||
|
$agcod = $this->awsIncentivesStartUp(
|
||||||
|
$connect,
|
||||||
|
$mock,
|
||||||
|
$mock_response,
|
||||||
|
);
|
||||||
|
|
||||||
|
// - getAvailableFunds: get available fund
|
||||||
|
// - getStatus
|
||||||
|
// - getAmount
|
||||||
|
// - getCurrency
|
||||||
|
// - getTimestamp
|
||||||
|
$funds = $agcod->getAvailableFunds();
|
||||||
|
// if not mock do type check
|
||||||
|
// if mock do matching check from mcok
|
||||||
|
if ($mock === false) {
|
||||||
|
$this->assertEquals(
|
||||||
|
'SUCCESS',
|
||||||
|
$funds->getStatus(),
|
||||||
|
'Assert status is success'
|
||||||
|
);
|
||||||
|
// numeric number
|
||||||
|
$this->assertIsNumeric(
|
||||||
|
$funds->getAmount(),
|
||||||
|
'Assert amoount is numerc'
|
||||||
|
);
|
||||||
|
// USD, JPY, etc
|
||||||
|
$this->assertIsString(
|
||||||
|
$funds->getCurrency(),
|
||||||
|
'Assert currency is string'
|
||||||
|
);
|
||||||
|
// 20220610T085450Z
|
||||||
|
$this->assertMatchesRegularExpression(
|
||||||
|
"/^\d{8}T\d{6}Z$/",
|
||||||
|
$funds->getTimestamp(),
|
||||||
|
'Assert timestamp matches regex'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->assertEquals(
|
||||||
|
$mock_response['status'],
|
||||||
|
$funds->getStatus(),
|
||||||
|
'Assert mock status'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$mock_response['availableFunds']['amount'],
|
||||||
|
$funds->getAmount(),
|
||||||
|
'Assert mock amount'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$mock_response['availableFunds']['currencyCode'],
|
||||||
|
$funds->getCurrency(),
|
||||||
|
'Assert mock currency code'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$mock_response['timestamp'],
|
||||||
|
$funds->getTimestamp(),
|
||||||
|
'Assert mock timestamp'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undocumented function
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function amazonIncentivesProviderBuy(): array
|
||||||
{
|
{
|
||||||
|
// get connectors
|
||||||
|
$connectors = $this->awsIncentivesProvider();
|
||||||
|
// 0: connect array (env file, env folder, parameters array)
|
||||||
|
// 1: mock or normal call
|
||||||
|
// 2: if mock connect response must be defined here
|
||||||
|
// 3: exepcted response array
|
||||||
|
// 4: value in float
|
||||||
|
return [
|
||||||
|
'non mock test data' => [
|
||||||
|
'connect' => $connectors['env_test'],
|
||||||
|
'mock' => false,
|
||||||
|
'mock_response' => null,
|
||||||
|
'amount' => 500.0,
|
||||||
|
],
|
||||||
|
'mock data test' => [
|
||||||
|
'connect' => $connectors['parameter_dummy'],
|
||||||
|
'mock' => true,
|
||||||
|
'mock_response' => [
|
||||||
|
'cardInfo' => [
|
||||||
|
'cardNumber' => null,
|
||||||
|
'cardStatus' => 'Fulfilled',
|
||||||
|
'expirationDate' => null,
|
||||||
|
'value' => [
|
||||||
|
'amount' => 1000.0,
|
||||||
|
'currencyCode' => 'JPY',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'creationRequestId' => 'PartnerId_62a309167e7a4',
|
||||||
|
'gcClaimCode' => 'LJ49-AKDUV6-UYCP',
|
||||||
|
'gcExpirationDate' => 'Thu Jun 10 14:59:59 UTC 2032',
|
||||||
|
'gcId' => '5535125272070255',
|
||||||
|
'status' => 'SUCCESS',
|
||||||
|
],
|
||||||
|
'amount' => 1000.0,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undocumented function
|
||||||
|
*
|
||||||
|
* @dataProvider amazonIncentivesProviderBuy
|
||||||
|
* @testdox AWS Incentives buy gift card [$_dataName]
|
||||||
|
*
|
||||||
|
* @param array $connect
|
||||||
|
* @param bool $mock
|
||||||
|
* @param array|null $mock_response
|
||||||
|
* @param float $amount
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testAwsIncentivesBuyGiftCard(
|
||||||
|
array $connect,
|
||||||
|
bool $mock,
|
||||||
|
?array $mock_response,
|
||||||
|
float $amount
|
||||||
|
): void {
|
||||||
// - init plain
|
// - init plain
|
||||||
// * via ::make()
|
// * via ::make()
|
||||||
|
|
||||||
// - buyGiftCard: buy gift card
|
// - buyGiftCard: buy gift card
|
||||||
// - getCreationRequestId
|
// - getCreationRequestId
|
||||||
// - getId
|
// - getId
|
||||||
// - getClaimCode
|
// - getClaimCode
|
||||||
// - getExpirationDate
|
// - getExpirationDate
|
||||||
// - getStatus
|
// - getStatus
|
||||||
// - cancelGiftCard: cancel gift card
|
|
||||||
// - getAvailableFunds: get available fund
|
|
||||||
// - getAmount
|
|
||||||
// - getCurrency
|
|
||||||
// - getTimestamp
|
|
||||||
|
|
||||||
// try/catch
|
// load class
|
||||||
// -decodeExceptionMessage (static)
|
$agcod = $this->awsIncentivesStartUp(
|
||||||
$this->markTestSkipped('Not yet implemented: AmazonIncentives');
|
$connect,
|
||||||
|
$mock,
|
||||||
|
$mock_response,
|
||||||
|
);
|
||||||
|
|
||||||
|
$response = $agcod->buyGiftCard($amount);
|
||||||
|
|
||||||
|
if ($mock === false) {
|
||||||
|
// type check
|
||||||
|
$this->assertEquals(
|
||||||
|
'SUCCESS',
|
||||||
|
$response->getStatus(),
|
||||||
|
'Assert status'
|
||||||
|
);
|
||||||
|
// creation request id must start with partner id
|
||||||
|
$this->assertStringStartsWith(
|
||||||
|
$agcod->checkMe()['CONFIG']->getPartner(),
|
||||||
|
$response->getCreationRequestId(),
|
||||||
|
'Assert creation request id starts with partner id'
|
||||||
|
);
|
||||||
|
// gift card id is number
|
||||||
|
$this->assertIsNumeric(
|
||||||
|
$response->getId(),
|
||||||
|
'Assert gift card id is numeric'
|
||||||
|
);
|
||||||
|
// claim code is 4-6-4 alphanumeric
|
||||||
|
$this->assertIsString(
|
||||||
|
$response->getClaimCode(),
|
||||||
|
'Assert claim code is string'
|
||||||
|
);
|
||||||
|
// only for requests outside US/Australia cards
|
||||||
|
// expiration date: Thu Jun 10 14:59:59 UTC 2032
|
||||||
|
} else {
|
||||||
|
// value match to mock response
|
||||||
|
$this->assertEquals(
|
||||||
|
$mock_response['status'],
|
||||||
|
$response->getStatus(),
|
||||||
|
'Assert mock status'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$mock_response['creationRequestId'],
|
||||||
|
$response->getCreationRequestId(),
|
||||||
|
'Assert mock creation request id'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$mock_response['gcId'],
|
||||||
|
$response->getId(),
|
||||||
|
'Assert mock gift card id'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$mock_response['gcClaimCode'],
|
||||||
|
$response->getClaimCode(),
|
||||||
|
'Assert mock claim code'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$mock_response['gcExpirationDate'],
|
||||||
|
$response->getExpirationDate(),
|
||||||
|
'Assert mock expiration date'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkMeProvider(): array
|
/**
|
||||||
|
* Buy a gift card and use same creation request id to get another gift card
|
||||||
|
* has to return same data ggain
|
||||||
|
*
|
||||||
|
* @dataProvider amazonIncentivesProviderBuy
|
||||||
|
* @testdox AWS Incentives buy gift card and again with same creation request id [$_dataName]
|
||||||
|
*
|
||||||
|
* @param array $connect
|
||||||
|
* @param bool $mock
|
||||||
|
* @param array|null $mock_response
|
||||||
|
* @param float $amount
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testAwsIncentivesSameBuyGiftCard(
|
||||||
|
array $connect,
|
||||||
|
bool $mock,
|
||||||
|
?array $mock_response,
|
||||||
|
float $amount
|
||||||
|
): void {
|
||||||
|
// load class
|
||||||
|
$agcod = $this->awsIncentivesStartUp(
|
||||||
|
$connect,
|
||||||
|
$mock,
|
||||||
|
$mock_response,
|
||||||
|
);
|
||||||
|
// get one
|
||||||
|
$response_a = $agcod->buyGiftCard($amount);
|
||||||
|
// get one again with same code
|
||||||
|
$response_b = $agcod->buyGiftCard($amount, $response_a->getCreationRequestId());
|
||||||
|
|
||||||
|
// a and b must be equalt
|
||||||
|
$this->assertEquals(
|
||||||
|
$response_a->getStatus(),
|
||||||
|
$response_b->getStatus(),
|
||||||
|
'Assert status'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$response_a->getCreationRequestId(),
|
||||||
|
$response_b->getCreationRequestId(),
|
||||||
|
'Assert creation request id'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$response_a->getId(),
|
||||||
|
$response_b->getId(),
|
||||||
|
'Assert gift card id'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$response_a->getClaimCode(),
|
||||||
|
$response_b->getClaimCode(),
|
||||||
|
'Assert claim code'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$response_a->getExpirationDate(),
|
||||||
|
$response_b->getExpirationDate(),
|
||||||
|
'Assert expiration date'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undocumented function
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function amazonIncentivesProviderCancel(): array
|
||||||
{
|
{
|
||||||
|
// get connectors
|
||||||
|
$connectors = $this->awsIncentivesProvider();
|
||||||
|
// 0: connect array (env file, env folder, parameters array)
|
||||||
|
// 1: mock or normal call
|
||||||
|
// 2: if mock connect response must be defined here
|
||||||
|
// 3: exepcted response array
|
||||||
return [
|
return [
|
||||||
'default' => [
|
'non mock test data' => [
|
||||||
'env_folder' => null,
|
'connect' => $connectors['env_test'],
|
||||||
'env_file' => null,
|
'mock' => false,
|
||||||
'expected' => [],
|
'mock_response' => null,
|
||||||
]
|
],
|
||||||
|
'mock data test' => [
|
||||||
|
'connect' => $connectors['parameter_dummy'],
|
||||||
|
'mock' => true,
|
||||||
|
'mock_response' => [
|
||||||
|
'creationRequestId' => 'PartnerId_62a309167e7a4',
|
||||||
|
'gcId' => '5535125272070255',
|
||||||
|
'status' => 'SUCCESS',
|
||||||
|
],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undocumented function
|
* Undocumented function
|
||||||
*
|
*
|
||||||
|
* @dataProvider amazonIncentivesProviderCancel
|
||||||
|
* @testdox AWS Incentives cancel gift card [$_dataName]
|
||||||
|
*
|
||||||
|
* @param array $connect
|
||||||
|
* @param bool $mock
|
||||||
|
* @param array|null $mock_response
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testAwsIncentivesCancelGiftCard(
|
||||||
|
array $connect,
|
||||||
|
bool $mock,
|
||||||
|
?array $mock_response
|
||||||
|
): void {
|
||||||
|
// - cancelGiftCard: cancel gift card
|
||||||
|
// load class
|
||||||
|
$agcod = $this->awsIncentivesStartUp(
|
||||||
|
$connect,
|
||||||
|
$mock,
|
||||||
|
$mock_response,
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($mock === false) {
|
||||||
|
// get a gift card, then cancel it
|
||||||
|
$purchase = $agcod->buyGiftCard(500.0);
|
||||||
|
$response = $agcod->cancelGiftCard(
|
||||||
|
$purchase->getCreationRequestId(),
|
||||||
|
$purchase->getId()
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
'SUCCESS',
|
||||||
|
$response->getStatus(),
|
||||||
|
'Assert mock status'
|
||||||
|
);
|
||||||
|
// creation request id must start with partner id
|
||||||
|
$this->assertStringStartsWith(
|
||||||
|
$agcod->checkMe()['CONFIG']->getPartner(),
|
||||||
|
$response->getCreationRequestId(),
|
||||||
|
'Assert creation request id starts with partner id'
|
||||||
|
);
|
||||||
|
// gift card id is number
|
||||||
|
$this->assertIsNumeric(
|
||||||
|
$response->getId(),
|
||||||
|
'Assert gift card id is numeric'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$response = $agcod->cancelGiftCard(
|
||||||
|
$mock_response['creationRequestId'],
|
||||||
|
$mock_response['gcId']
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$mock_response['status'],
|
||||||
|
$response->getStatus(),
|
||||||
|
'Assert mock status'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$mock_response['creationRequestId'],
|
||||||
|
$response->getCreationRequestId(),
|
||||||
|
'Assert mock creation request id'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$mock_response['gcId'],
|
||||||
|
$response->getId(),
|
||||||
|
'Assert mock gift card id'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list of AWS mock codes for AWS side mock testing
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function awsIncentivesMockProvider(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'successMock' => [
|
||||||
|
'creation_request_id' => 'F0000',
|
||||||
|
'return_code' => '',
|
||||||
|
'status' => 'SUCCESS'
|
||||||
|
],
|
||||||
|
'SimpleAmountIsNull' => [
|
||||||
|
'creation_request_id' => 'F1000',
|
||||||
|
'return_code' => 'F100',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
'InvalidAmountInput' => [
|
||||||
|
'creation_request_id' => 'F2003',
|
||||||
|
'return_code' => 'F200',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
'InvalidAmountValue' => [
|
||||||
|
'creation_request_id' => 'F2004',
|
||||||
|
'return_code' => 'F200',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
'InvalidCurrencyCodeInput' => [
|
||||||
|
'creation_request_id' => 'F2005',
|
||||||
|
'return_code' => 'F200',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
'CardActivatedWithDifferentRequestId' => [
|
||||||
|
'creation_request_id' => 'F2010',
|
||||||
|
'return_code' => 'F200',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
'MaxAmountExceeded' => [
|
||||||
|
'creation_request_id' => 'F2015',
|
||||||
|
'return_code' => 'F200',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
'CurrencyCodeMismatch' => [
|
||||||
|
'creation_request_id' => 'F2016',
|
||||||
|
'return_code' => 'F200',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
'FractionalAmountNotAllowed' => [
|
||||||
|
'creation_request_id' => 'F2017',
|
||||||
|
'return_code' => 'F200',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
'CancelRequestArrivedAfterTimeLimit' => [
|
||||||
|
'creation_request_id' => 'F2047',
|
||||||
|
'return_code' => 'F200',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
'InsufficientFunds' => [
|
||||||
|
'creation_request_id' => 'F3003',
|
||||||
|
'return_code' => 'F300',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
'AccountHasProblems' => [
|
||||||
|
'creation_request_id' => 'F3005',
|
||||||
|
'return_code' => 'F300',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
'CustomerSurpassedDailyVelocityLimit' => [
|
||||||
|
'creation_request_id' => 'F3010',
|
||||||
|
'return_code' => 'F300',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
'SystemTemporarilyUnavailable' => [
|
||||||
|
'creation_request_id' => 'F4000',
|
||||||
|
'return_code' => 'F400',
|
||||||
|
'status' => 'RESEND'
|
||||||
|
],
|
||||||
|
'UnknownError' => [
|
||||||
|
'creation_request_id' => 'F5000',
|
||||||
|
'return_code' => 'F500',
|
||||||
|
'status' => 'FAILURE'
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE: Must have a valid test user connection setup
|
||||||
|
* This only works with a valid server connection.
|
||||||
|
* Runs through AWS Incentives mock values and checks the return code and status
|
||||||
|
*
|
||||||
|
* @dataProvider awsIncentivesMockProvider
|
||||||
|
* @testdox AWS Incentives Mock $creation_request_id will be $expected_status with $expected_code [$_dataName]
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testAwsIncentivesWithMocks(
|
||||||
|
string $creation_request_id,
|
||||||
|
string $expected_code,
|
||||||
|
string $expected_status,
|
||||||
|
): void {
|
||||||
|
// reset _ENV for reading
|
||||||
|
$_ENV = [];
|
||||||
|
// read the .env file
|
||||||
|
$status = DotEnv::readEnvFile(__DIR__ . DIRECTORY_SEPARATOR . '..');
|
||||||
|
// if loading failed, abort
|
||||||
|
if ($status != 0) {
|
||||||
|
// abort with error
|
||||||
|
$this->markTestSkipped(
|
||||||
|
'Cannot read .env file needed for AWS mock tests: ' . $status
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// if no value set, set to 500
|
||||||
|
$value = $_ENV['AWS_MOCK_VALUE'] ?? 500;
|
||||||
|
// run tests
|
||||||
|
try {
|
||||||
|
$aws_gcod = AmazonIncentives\AmazonIncentives::make()->buyGiftCard(
|
||||||
|
(float)$value,
|
||||||
|
$creation_request_id
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$expected_status,
|
||||||
|
$aws_gcod->getStatus(),
|
||||||
|
'Assert status ok in AWS GCOD mocks'
|
||||||
|
);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$error = AmazonIncentives\Exceptions\AmazonErrors::decodeExceptionMessage($e->getMessage());
|
||||||
|
$this->assertEquals(
|
||||||
|
[
|
||||||
|
'code' => $expected_code,
|
||||||
|
'status' => $expected_status,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => $error['code'],
|
||||||
|
'status' => $error['status'],
|
||||||
|
],
|
||||||
|
'Assert status failed in AWS GCOD mocks'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// wait a moment between tests
|
||||||
|
sleep($this->mock_wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undocumented function
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function checkMeProvider(): array
|
||||||
|
{
|
||||||
|
// 0: .env file folder
|
||||||
|
// 1: .env file name (if not set use .env)
|
||||||
|
// 2: parameters that override _ENV variables
|
||||||
|
return [
|
||||||
|
'default all empty' => [
|
||||||
|
'use_env' => null,
|
||||||
|
'env_file' => null,
|
||||||
|
'parameters' => null,
|
||||||
|
],
|
||||||
|
'set parameters' => [
|
||||||
|
'env_folder' => null,
|
||||||
|
'env_file' => null,
|
||||||
|
'parameters' => [
|
||||||
|
'key' => 'key',
|
||||||
|
'secret' => 'secret',
|
||||||
|
'partner' => 'partner id',
|
||||||
|
'endpoint' => 'https://endpoint.test.com',
|
||||||
|
'currency' => 'currency',
|
||||||
|
'debug' => true,
|
||||||
|
],
|
||||||
|
'expected' => [],
|
||||||
|
],
|
||||||
|
'load from env' => [
|
||||||
|
'env_folder' => __DIR__ . DIRECTORY_SEPARATOR . '..',
|
||||||
|
'env_file' => null,
|
||||||
|
'parameters' => null,
|
||||||
|
],
|
||||||
|
'load from env, but override parameter' => [
|
||||||
|
'env_folder' => __DIR__ . DIRECTORY_SEPARATOR . '..',
|
||||||
|
'env_file' => null,
|
||||||
|
'parameters' => [
|
||||||
|
'key' => 'key',
|
||||||
|
'secret' => 'secret',
|
||||||
|
'partner' => 'partner id',
|
||||||
|
'endpoint' => 'https://endpoint.test.com',
|
||||||
|
'currency' => 'currency',
|
||||||
|
]
|
||||||
|
]
|
||||||
|
// test missing parameter, set vie _ENV
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the checkMe function that will work with or without any settings
|
||||||
|
* passed on.
|
||||||
|
* This also tests basic loading
|
||||||
|
* - parseing for endoint as url
|
||||||
|
* - override check for _ENV vs parameter
|
||||||
|
*
|
||||||
* @cover ::checkMe
|
* @cover ::checkMe
|
||||||
* @dataProvider checkMeProvider
|
* @dataProvider checkMeProvider
|
||||||
* @testdox AmazonIncentives tests [$_dataName]
|
* @testdox AmazonIncentives tests [$_dataName]
|
||||||
*
|
*
|
||||||
|
* @param string|null $env_folder
|
||||||
|
* @param string|null $env_file
|
||||||
|
* @param array|null $parameters
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function testCheckMe(?string $env_folder, ?string $env_file, array $expected): void
|
public function testCheckMe(?string $env_folder, ?string $env_file, ?array $parameters): void
|
||||||
{
|
{
|
||||||
$aws = new AmazonIncentives();
|
// reset _ENV before each run to avoid nothing to load errors
|
||||||
|
$_ENV = [];
|
||||||
|
// env load status
|
||||||
|
$status = null;
|
||||||
|
if (!empty($env_folder)) {
|
||||||
|
if (!empty($env_file)) {
|
||||||
|
$status = DotEnv::readEnvFile($env_folder, $env_file);
|
||||||
|
} else {
|
||||||
|
$status = DotEnv::readEnvFile($env_folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($parameters)) {
|
||||||
|
$aws = new AmazonIncentives\AmazonIncentives(
|
||||||
|
$parameters['key'],
|
||||||
|
$parameters['secret'],
|
||||||
|
$parameters['partner'],
|
||||||
|
$parameters['endpoint'],
|
||||||
|
$parameters['currency'],
|
||||||
|
$parameters['debug'] ?? null,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$aws = new AmazonIncentives\AmazonIncentives();
|
||||||
|
}
|
||||||
$aws_check_me = $aws->checkMe();
|
$aws_check_me = $aws->checkMe();
|
||||||
|
// ENV must match _ENV vars if set
|
||||||
|
if (!empty($env_folder) && $status != 0) {
|
||||||
|
// abort with error
|
||||||
|
$this->markTestSkipped(
|
||||||
|
'Cannot read .env file needed: ' . $status
|
||||||
|
);
|
||||||
|
} elseif (!empty($env_folder)) {
|
||||||
|
$this->assertEquals(
|
||||||
|
$_ENV,
|
||||||
|
$aws_check_me['ENV'],
|
||||||
|
'Assert _ENV set equal'
|
||||||
|
);
|
||||||
|
}
|
||||||
// compare that data matches
|
// compare that data matches
|
||||||
print "CM: " . print_r($aws_check_me, true) . "\n";
|
// print "CM: " . print_r($aws_check_me, true) . "\n";
|
||||||
|
// CONFIG must match to parameters or ENV, parsed host name check
|
||||||
|
$this->assertEquals(
|
||||||
|
// parameter > _ENV -> empty
|
||||||
|
!empty($parameters['partner']) ?
|
||||||
|
$parameters['partner'] :
|
||||||
|
$_ENV['AWS_GIFT_CARD_PARTNER_ID'] ?? '',
|
||||||
|
$aws_check_me['CONFIG']->getPartner(),
|
||||||
|
'Assert config matching input'
|
||||||
|
);
|
||||||
|
// KEY must match access_key/AWS_GIFT_CARD_KEY
|
||||||
|
$this->assertEquals(
|
||||||
|
$aws_check_me['CONFIG']->getAccessKey(),
|
||||||
|
$aws_check_me['KEY'],
|
||||||
|
'Assert access key m'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
21
test/phpUnit/Hook/BypassFinalHook.php
Normal file
21
test/phpUnit/Hook/BypassFinalHook.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// strip the final name from a to be mocked class
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace test\phpUnit\Hook;
|
||||||
|
|
||||||
|
use DG\BypassFinals;
|
||||||
|
use PHPUnit\Runner\BeforeFirstTestHook;
|
||||||
|
|
||||||
|
// only works if it is the FIRST load and not before EACH test
|
||||||
|
final class BypassFinalHook implements BeforeFirstTestHook
|
||||||
|
{
|
||||||
|
public function executeBeforeFirstTest(): void
|
||||||
|
{
|
||||||
|
BypassFinals::enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// __END__
|
||||||
1
vendor/composer/autoload_classmap.php
vendored
1
vendor/composer/autoload_classmap.php
vendored
@@ -7,6 +7,7 @@ $baseDir = dirname($vendorDir);
|
|||||||
|
|
||||||
return array(
|
return array(
|
||||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||||
|
'DG\\BypassFinals' => $vendorDir . '/dg/bypass-finals/src/BypassFinals.php',
|
||||||
'PHPUnit\\Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php',
|
'PHPUnit\\Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php',
|
||||||
'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php',
|
'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php',
|
||||||
'PHPUnit\\Framework\\Assert' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert.php',
|
'PHPUnit\\Framework\\Assert' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert.php',
|
||||||
|
|||||||
1
vendor/composer/autoload_static.php
vendored
1
vendor/composer/autoload_static.php
vendored
@@ -76,6 +76,7 @@ class ComposerStaticInit0c8f6bec90a6d60040a922f19a1f0e64
|
|||||||
|
|
||||||
public static $classMap = array (
|
public static $classMap = array (
|
||||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||||
|
'DG\\BypassFinals' => __DIR__ . '/..' . '/dg/bypass-finals/src/BypassFinals.php',
|
||||||
'PHPUnit\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Exception.php',
|
'PHPUnit\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Exception.php',
|
||||||
'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php',
|
'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php',
|
||||||
'PHPUnit\\Framework\\Assert' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert.php',
|
'PHPUnit\\Framework\\Assert' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert.php',
|
||||||
|
|||||||
58
vendor/composer/installed.json
vendored
58
vendor/composer/installed.json
vendored
@@ -1,5 +1,62 @@
|
|||||||
{
|
{
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "dg/bypass-finals",
|
||||||
|
"version": "dev-master",
|
||||||
|
"version_normalized": "dev-master",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dg/bypass-finals.git",
|
||||||
|
"reference": "fb62dc6ab1a097e234fa1567943d8e87ea4d0842"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/dg/bypass-finals/zipball/fb62dc6ab1a097e234fa1567943d8e87ea4d0842",
|
||||||
|
"reference": "fb62dc6ab1a097e234fa1567943d8e87ea4d0842",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"nette/tester": "^2.3",
|
||||||
|
"phpstan/phpstan": "^0.12"
|
||||||
|
},
|
||||||
|
"time": "2022-04-14T12:24:34+00:00",
|
||||||
|
"default-branch": true,
|
||||||
|
"type": "library",
|
||||||
|
"installation-source": "dist",
|
||||||
|
"autoload": {
|
||||||
|
"classmap": [
|
||||||
|
"src/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-3-Clause",
|
||||||
|
"GPL-2.0",
|
||||||
|
"GPL-3.0"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "David Grudl",
|
||||||
|
"homepage": "https://davidgrudl.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Removes final keyword from source code on-the-fly and allows mocking of final methods and classes",
|
||||||
|
"keywords": [
|
||||||
|
"finals",
|
||||||
|
"mocking",
|
||||||
|
"phpunit",
|
||||||
|
"testing",
|
||||||
|
"unit"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/dg/bypass-finals/issues",
|
||||||
|
"source": "https://github.com/dg/bypass-finals/tree/master"
|
||||||
|
},
|
||||||
|
"install-path": "../dg/bypass-finals"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/instantiator",
|
"name": "doctrine/instantiator",
|
||||||
"version": "1.5.x-dev",
|
"version": "1.5.x-dev",
|
||||||
@@ -2184,6 +2241,7 @@
|
|||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dev-package-names": [
|
"dev-package-names": [
|
||||||
|
"dg/bypass-finals",
|
||||||
"doctrine/instantiator",
|
"doctrine/instantiator",
|
||||||
"gullevek/dotenv",
|
"gullevek/dotenv",
|
||||||
"myclabs/deep-copy",
|
"myclabs/deep-copy",
|
||||||
|
|||||||
15
vendor/composer/installed.php
vendored
15
vendor/composer/installed.php
vendored
@@ -5,11 +5,22 @@
|
|||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'reference' => '1e836e9a2bd6e41c4555cf917fe645b453cb5b79',
|
'reference' => 'fd5477269b9a133448cecb5854b784033d6c6c62',
|
||||||
'name' => 'gullevek/amazon-incentives',
|
'name' => 'gullevek/amazon-incentives',
|
||||||
'dev' => true,
|
'dev' => true,
|
||||||
),
|
),
|
||||||
'versions' => array(
|
'versions' => array(
|
||||||
|
'dg/bypass-finals' => array(
|
||||||
|
'pretty_version' => 'dev-master',
|
||||||
|
'version' => 'dev-master',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../dg/bypass-finals',
|
||||||
|
'aliases' => array(
|
||||||
|
0 => '9999999-dev',
|
||||||
|
),
|
||||||
|
'reference' => 'fb62dc6ab1a097e234fa1567943d8e87ea4d0842',
|
||||||
|
'dev_requirement' => true,
|
||||||
|
),
|
||||||
'doctrine/instantiator' => array(
|
'doctrine/instantiator' => array(
|
||||||
'pretty_version' => '1.5.x-dev',
|
'pretty_version' => '1.5.x-dev',
|
||||||
'version' => '1.5.9999999.9999999-dev',
|
'version' => '1.5.9999999.9999999-dev',
|
||||||
@@ -25,7 +36,7 @@
|
|||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'reference' => '1e836e9a2bd6e41c4555cf917fe645b453cb5b79',
|
'reference' => 'fd5477269b9a133448cecb5854b784033d6c6c62',
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'gullevek/dotenv' => array(
|
'gullevek/dotenv' => array(
|
||||||
|
|||||||
26
vendor/dg/bypass-finals/composer.json
vendored
Normal file
26
vendor/dg/bypass-finals/composer.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "dg/bypass-finals",
|
||||||
|
"description": "Removes final keyword from source code on-the-fly and allows mocking of final methods and classes",
|
||||||
|
"keywords": ["testing", "unit", "phpunit", "mocking", "finals"],
|
||||||
|
"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "David Grudl",
|
||||||
|
"homepage": "https://davidgrudl.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"nette/tester": "^2.3",
|
||||||
|
"phpstan/phpstan": "^0.12"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"classmap": ["src/"]
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"phpstan": "phpstan analyse",
|
||||||
|
"tester": "tester tests -s"
|
||||||
|
}
|
||||||
|
}
|
||||||
49
vendor/dg/bypass-finals/license.md
vendored
Normal file
49
vendor/dg/bypass-finals/license.md
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
Licenses
|
||||||
|
========
|
||||||
|
|
||||||
|
Good news! You may use Nette Tester under the terms of either
|
||||||
|
the New BSD License or the GNU General Public License (GPL) version 2 or 3.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
New BSD License
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Copyright (c) 2004, 2013 David Grudl (https://davidgrudl.com)
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of "Nette Tester" nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
This software is provided by the copyright holders and contributors "as is" and
|
||||||
|
any express or implied warranties, including, but not limited to, the implied
|
||||||
|
warranties of merchantability and fitness for a particular purpose are
|
||||||
|
disclaimed. In no event shall the copyright owner or contributors be liable for
|
||||||
|
any direct, indirect, incidental, special, exemplary, or consequential damages
|
||||||
|
(including, but not limited to, procurement of substitute goods or services;
|
||||||
|
loss of use, data, or profits; or business interruption) however caused and on
|
||||||
|
any theory of liability, whether in contract, strict liability, or tort
|
||||||
|
(including negligence or otherwise) arising in any way out of the use of this
|
||||||
|
software, even if advised of the possibility of such damage.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GNU General Public License
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
GPL licenses are very very long, so instead of including them here we offer
|
||||||
|
you URLs with full text:
|
||||||
|
|
||||||
|
- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
|
||||||
|
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
64
vendor/dg/bypass-finals/readme.md
vendored
Normal file
64
vendor/dg/bypass-finals/readme.md
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
Bypass Finals
|
||||||
|
=============
|
||||||
|
|
||||||
|
[](https://packagist.org/packages/dg/bypass-finals)
|
||||||
|
[](https://github.com/dg/bypass-finals/actions)
|
||||||
|
[](https://github.com/dg/bypass-finals/releases)
|
||||||
|
[](https://github.com/dg/bypass-finals/blob/master/license.md)
|
||||||
|
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
Removes final keywords from source code on-the-fly and allows mocking of final methods and classes.
|
||||||
|
It can be used together with any test tool such as PHPUnit, Mockery or [Nette Tester](https://tester.nette.org).
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
The recommended way to install is through Composer:
|
||||||
|
|
||||||
|
```
|
||||||
|
composer require dg/bypass-finals --dev
|
||||||
|
```
|
||||||
|
|
||||||
|
It requires PHP version 7.1 (or 5.6 in case of release 1.1) and supports PHP up to 8.1.
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
Simply call this:
|
||||||
|
|
||||||
|
```php
|
||||||
|
DG\BypassFinals::enable();
|
||||||
|
```
|
||||||
|
|
||||||
|
You need to enable it before the classes you want to remove the final are loaded. So call it as soon as possible,
|
||||||
|
preferably right after `vendor/autoload.php` is loaded.
|
||||||
|
|
||||||
|
Note that final internal PHP classes like `Closure` cannot be mocked.
|
||||||
|
|
||||||
|
You can choose to only bypass finals in specific files or directories:
|
||||||
|
|
||||||
|
```php
|
||||||
|
DG\BypassFinals::setWhitelist([
|
||||||
|
'*/Nette/*',
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
This gives you finer control and can solve issues with certain frameworks and libraries.
|
||||||
|
|
||||||
|
You can try to increase performance by using the cache (the directory must exist):
|
||||||
|
|
||||||
|
```php
|
||||||
|
DG\BypassFinals::$cacheDir = __DIR__ . '/tmp';
|
||||||
|
```
|
||||||
|
|
||||||
|
Support Project
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Do you like BypassFinals?
|
||||||
|
|
||||||
|
[](https://nette.org/make-donation?to=bypass-finals)
|
||||||
312
vendor/dg/bypass-finals/src/BypassFinals.php
vendored
Normal file
312
vendor/dg/bypass-finals/src/BypassFinals.php
vendored
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DG;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes keyword final from source codes.
|
||||||
|
*/
|
||||||
|
class BypassFinals
|
||||||
|
{
|
||||||
|
private const PROTOCOL = 'file';
|
||||||
|
|
||||||
|
/** @var resource|null */
|
||||||
|
public $context;
|
||||||
|
|
||||||
|
/** @var ?string */
|
||||||
|
public static $cacheDir;
|
||||||
|
|
||||||
|
/** @var resource|null */
|
||||||
|
private $handle;
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
private static $pathWhitelist = ['*'];
|
||||||
|
|
||||||
|
/** @var ?object */
|
||||||
|
private static $prevWrapper;
|
||||||
|
|
||||||
|
|
||||||
|
public static function enable(): void
|
||||||
|
{
|
||||||
|
$meta = stream_get_meta_data(fopen(__FILE__, 'r'));
|
||||||
|
self::$prevWrapper = $meta['wrapper_data'] ?? null;
|
||||||
|
stream_wrapper_unregister(self::PROTOCOL);
|
||||||
|
stream_wrapper_register(self::PROTOCOL, self::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function setWhitelist(array $whitelist): void
|
||||||
|
{
|
||||||
|
foreach ($whitelist as &$mask) {
|
||||||
|
$mask = strtr($mask, '\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$pathWhitelist = $whitelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function dir_closedir(): void
|
||||||
|
{
|
||||||
|
closedir($this->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function dir_opendir(string $path, int $options): bool
|
||||||
|
{
|
||||||
|
$this->handle = $this->context
|
||||||
|
? $this->native('opendir', $path, $this->context)
|
||||||
|
: $this->native('opendir', $path);
|
||||||
|
return (bool) $this->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function dir_readdir()
|
||||||
|
{
|
||||||
|
return readdir($this->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function dir_rewinddir(): bool
|
||||||
|
{
|
||||||
|
return (bool) rewinddir($this->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function mkdir(string $path, int $mode, int $options): bool
|
||||||
|
{
|
||||||
|
$recursive = (bool) ($options & STREAM_MKDIR_RECURSIVE);
|
||||||
|
return $this->context
|
||||||
|
? $this->native('mkdir', $path, $mode, $recursive, $this->context)
|
||||||
|
: $this->native('mkdir', $path, $mode, $recursive);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function rename(string $pathFrom, string $pathTo): bool
|
||||||
|
{
|
||||||
|
return $this->context
|
||||||
|
? $this->native('rename', $pathFrom, $pathTo, $this->context)
|
||||||
|
: $this->native('rename', $pathFrom, $pathTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function rmdir(string $path, int $options): bool
|
||||||
|
{
|
||||||
|
return $this->context
|
||||||
|
? $this->native('rmdir', $path, $this->context)
|
||||||
|
: $this->native('rmdir', $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_cast(int $castAs)
|
||||||
|
{
|
||||||
|
return $this->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_close(): void
|
||||||
|
{
|
||||||
|
fclose($this->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_eof(): bool
|
||||||
|
{
|
||||||
|
return feof($this->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_flush(): bool
|
||||||
|
{
|
||||||
|
return fflush($this->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_lock(int $operation): bool
|
||||||
|
{
|
||||||
|
return $operation
|
||||||
|
? flock($this->handle, $operation)
|
||||||
|
: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_metadata(string $path, int $option, $value): bool
|
||||||
|
{
|
||||||
|
switch ($option) {
|
||||||
|
case STREAM_META_TOUCH:
|
||||||
|
return $this->native('touch', $path, $value[0] ?? time(), $value[1] ?? time());
|
||||||
|
case STREAM_META_OWNER_NAME:
|
||||||
|
case STREAM_META_OWNER:
|
||||||
|
return $this->native('chown', $path, $value);
|
||||||
|
case STREAM_META_GROUP_NAME:
|
||||||
|
case STREAM_META_GROUP:
|
||||||
|
return $this->native('chgrp', $path, $value);
|
||||||
|
case STREAM_META_ACCESS:
|
||||||
|
return $this->native('chmod', $path, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_open(string $path, string $mode, int $options, ?string &$openedPath): bool
|
||||||
|
{
|
||||||
|
$usePath = (bool) ($options & STREAM_USE_PATH);
|
||||||
|
if ($mode === 'rb' && pathinfo($path, PATHINFO_EXTENSION) === 'php' && self::isPathInWhiteList($path)) {
|
||||||
|
if (self::$prevWrapper) {
|
||||||
|
$content = null;
|
||||||
|
self::$prevWrapper->stream_open($path, $mode, $options, $openedPath);
|
||||||
|
while (!self::$prevWrapper->stream_eof()) {
|
||||||
|
$content .= self::$prevWrapper->stream_read(8192);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$prevWrapper->stream_close();
|
||||||
|
} else {
|
||||||
|
$content = $this->native('file_get_contents', $path, $usePath, $this->context);
|
||||||
|
}
|
||||||
|
if (!is_string($content)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$modified = self::cachedRemoveFinals($content);
|
||||||
|
if ($modified !== $content) {
|
||||||
|
$this->handle = tmpfile();
|
||||||
|
$this->native('fwrite', $this->handle, $modified);
|
||||||
|
$this->native('fseek', $this->handle, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->handle = $this->context
|
||||||
|
? $this->native('fopen', $path, $mode, $usePath, $this->context)
|
||||||
|
: $this->native('fopen', $path, $mode, $usePath);
|
||||||
|
return (bool) $this->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_read(int $count)
|
||||||
|
{
|
||||||
|
return fread($this->handle, $count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_seek(int $offset, int $whence = SEEK_SET): bool
|
||||||
|
{
|
||||||
|
return fseek($this->handle, $offset, $whence) === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_set_option(int $option, int $arg1, ?int $arg2): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_stat()
|
||||||
|
{
|
||||||
|
return fstat($this->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_tell()
|
||||||
|
{
|
||||||
|
return ftell($this->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_truncate(int $newSize): bool
|
||||||
|
{
|
||||||
|
return ftruncate($this->handle, $newSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function stream_write(string $data)
|
||||||
|
{
|
||||||
|
return fwrite($this->handle, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function unlink(string $path): bool
|
||||||
|
{
|
||||||
|
return $this->native('unlink', $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function url_stat(string $path, int $flags)
|
||||||
|
{
|
||||||
|
$func = $flags & STREAM_URL_STAT_LINK ? 'lstat' : 'stat';
|
||||||
|
return $flags & STREAM_URL_STAT_QUIET
|
||||||
|
? @$this->native($func, $path)
|
||||||
|
: $this->native($func, $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function native(string $func)
|
||||||
|
{
|
||||||
|
stream_wrapper_restore(self::PROTOCOL);
|
||||||
|
try {
|
||||||
|
return $func(...array_slice(func_get_args(), 1));
|
||||||
|
} finally {
|
||||||
|
stream_wrapper_unregister(self::PROTOCOL);
|
||||||
|
stream_wrapper_register(self::PROTOCOL, self::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function cachedRemoveFinals(string $code): string
|
||||||
|
{
|
||||||
|
if (stripos($code, 'final') === false) {
|
||||||
|
// do nothing
|
||||||
|
|
||||||
|
} elseif (self::$cacheDir) {
|
||||||
|
$hash = sha1($code);
|
||||||
|
if ($file = @fopen(self::$cacheDir . '/' . $hash, 'r')) { // @ may not exist
|
||||||
|
flock($file, LOCK_SH);
|
||||||
|
if ($res = stream_get_contents($file)) {
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$code = self::removeFinals($code);
|
||||||
|
if ($file = @fopen(self::$cacheDir . '/' . $hash, 'x')) { // @ may exist
|
||||||
|
flock($file, LOCK_EX);
|
||||||
|
fwrite($file, $code);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$code = self::removeFinals($code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function removeFinals(string $code): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$tokens = token_get_all($code, TOKEN_PARSE);
|
||||||
|
} catch (\ParseError $e) {
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
$code = '';
|
||||||
|
foreach ($tokens as $token) {
|
||||||
|
$code .= is_array($token)
|
||||||
|
? ($token[0] === T_FINAL ? '' : $token[1])
|
||||||
|
: $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static function isPathInWhiteList(string $path): bool
|
||||||
|
{
|
||||||
|
$path = strtr($path, '\\', '/');
|
||||||
|
foreach (self::$pathWhitelist as $mask) {
|
||||||
|
if (fnmatch($mask, $path)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user