Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 422fc66137 | |||
| 308794488d | |||
| 2bcd42f4a5 | |||
| 05b33ac157 | |||
| fd5477269b | |||
| afb11a6797 |
23
Readme.md
23
Readme.md
@@ -1,9 +1,11 @@
|
|||||||
# Amazon Incentives - Gift Codes on Demand stand alone class
|
# Amazon Incentives - Gift Codes on Demand stand alone class
|
||||||
|
|
||||||
This is a abastract from (https://github.com/kamerk22/AmazonGiftCode) to be not dependend on Laravel base code.
|
This is a abastract from [https://github.com/kamerk22/AmazonGiftCod](https://github.com/kamerk22/AmazonGiftCode) to be not dependend on Laravel base code.
|
||||||
|
|
||||||
Amazon Gift Codes On Demand (AGCOD). Integration for Amazon Incentive API.
|
Amazon Gift Codes On Demand (AGCOD). Integration for Amazon Incentive API.
|
||||||
|
|
||||||
|
[General Amazon Incentives Documentation](https://developer.amazon.com/docs/incentives-api/digital-gift-cards.html)
|
||||||
|
|
||||||
## How to install
|
## How to install
|
||||||
|
|
||||||
`composer require gullevek/amazon-incentives`
|
`composer require gullevek/amazon-incentives`
|
||||||
@@ -82,18 +84,21 @@ The error code is the curl handler error code.
|
|||||||
The error message is json encoded array with the layout
|
The error message is json encoded array with the layout
|
||||||
|
|
||||||
Use
|
Use
|
||||||
|
|
||||||
```php
|
```php
|
||||||
$exception_array = gullevek\AmazonIncentives\AmazonIncentives::decodeExceptionMessage($exception_message);
|
$exception_array = gullevek\AmazonIncentives\AmazonIncentives::decodeExceptionMessage($exception_message);
|
||||||
```
|
```
|
||||||
|
|
||||||
to extract the below array from the thrown exception
|
to extract the below array from the thrown exception
|
||||||
|
|
||||||
```php
|
```php
|
||||||
[
|
[
|
||||||
'status' => 'AWS Status FAILURE or RESEND',
|
'status' => 'AWS Status FAILURE or RESEND',
|
||||||
'code' => 'AWS Error Code Fnnn',
|
'code' => 'AWS Error Code Fnnn',
|
||||||
'type' => 'AWS Error info',
|
'type' => 'AWS Error info',
|
||||||
'message' => 'AWS long error message',
|
'message' => 'AWS long error message',
|
||||||
'log_id' => 'If logging is on the current log id',
|
'log_id' => 'If logging is on the current log id',
|
||||||
'log' => 'The complete log collected over all calls',
|
'log' => 'The complete log collected over all calls',
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -106,7 +111,7 @@ to extract the below array from the thrown exception
|
|||||||
if code is T001 then this is a request flood error:
|
if code is T001 then this is a request flood error:
|
||||||
In this case the request has to be resend after a certain waiting period.
|
In this case the request has to be resend after a certain waiting period.
|
||||||
|
|
||||||
### E9999
|
### E999
|
||||||
|
|
||||||
if code is E999 some other critical error has happened
|
if code is E999 some other critical error has happened
|
||||||
|
|
||||||
@@ -117,6 +122,7 @@ if code is E001 if the return create/cancel/check calls is not an array
|
|||||||
### C001
|
### C001
|
||||||
|
|
||||||
fif code is C001 curl failed to init
|
fif code is C001 curl failed to init
|
||||||
|
|
||||||
### C002
|
### C002
|
||||||
|
|
||||||
if code is C002 a curl error has happened
|
if code is C002 a curl error has happened
|
||||||
@@ -132,6 +138,7 @@ If AWS_DEBUG is set to 1 and internal array will be written with debug info.
|
|||||||
The gulleek\AmazonIncentives\Debug\AmazonDebug class handles all this.
|
The gulleek\AmazonIncentives\Debug\AmazonDebug class handles all this.
|
||||||
|
|
||||||
In the gulleek\AmazonIncentives\AmazonIncentives main class the debugger gets set
|
In the gulleek\AmazonIncentives\AmazonIncentives main class the debugger gets set
|
||||||
|
|
||||||
* setDebug that turns debugger on/off and if on sets unique id (getId to check)
|
* setDebug that turns debugger on/off and if on sets unique id (getId to check)
|
||||||
|
|
||||||
New entries can be written with
|
New entries can be written with
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
|
|||||||
@@ -91,13 +91,13 @@ class Client implements ClientInterface
|
|||||||
case CURLE_COULDNT_CONNECT:
|
case CURLE_COULDNT_CONNECT:
|
||||||
case CURLE_COULDNT_RESOLVE_HOST:
|
case CURLE_COULDNT_RESOLVE_HOST:
|
||||||
case CURLE_OPERATION_TIMEOUTED:
|
case CURLE_OPERATION_TIMEOUTED:
|
||||||
$message = 'Could not connect to AWS (' . $url . '). Please check your '
|
$message = 'Could not connect to AWS (' . $url . '). Please check your '
|
||||||
. 'internet connection and try again. [' . $message . ']';
|
. 'internet connection and try again. [' . $message . ']';
|
||||||
break;
|
break;
|
||||||
case CURLE_SSL_PEER_CERTIFICATE:
|
case CURLE_SSL_PEER_CERTIFICATE:
|
||||||
$message = 'Could not verify AWS SSL certificate. Please make sure '
|
$message = 'Could not verify AWS SSL certificate. Please make sure '
|
||||||
. 'that your network is not intercepting certificates. '
|
. 'that your network is not intercepting certificates. '
|
||||||
. '(Try going to ' . $url . 'in your browser.) '
|
. '(Try going to ' . $url . 'in your browser.) '
|
||||||
. '[' . $message . ']';
|
. '[' . $message . ']';
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
|
|||||||
@@ -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']
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
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