8 Commits
1.0.0 ... 1.1.1

Author SHA1 Message Date
d0b676f8ce Add phan checks at max level 2021-10-21 13:37:59 +09:00
c2721cb8d4 Add PHPstan and fix all checks for max level 2021-10-21 13:31:18 +09:00
18cf3330df Change license to MIT 2021-10-21 10:31:08 +09:00
3b7f644ae9 Update readme file, Update composer.json file, Exception updates
Alle exceptions thrown in Response are now general AmazonError with json
return string for full compability
2021-10-21 10:22:17 +09:00
6f9bf781f2 Rewrite to composer package
composer require gullevek/amazon-incentives
2021-10-21 09:55:32 +09:00
94ea118731 Documentation update 2021-10-20 16:18:18 +09:00
a56f33c81c Debug log updates, error message updates on curl failure
Config setup works with null data if no data is set.

Debugger is now launched in the AamzonIncentive class at the beginning
Debugger id/debug flag set is now one static call
Debugger methods all have proper PHPdoc documentationn added

Fixed Client/Curl error messages to include the original error message
too. Also made sure that a possible null endpoint is not throwing errors
2021-10-20 09:39:26 +09:00
f3b17bbf4c Update tests script with logging, etc 2021-10-19 11:46:52 +09:00
28 changed files with 1404 additions and 399 deletions

97
.phan/config.php Normal file
View File

@@ -0,0 +1,97 @@
<?php
/**
* This configuration will be read and overlaid on top of the
* default configuration. Command line arguments will be applied
* after this file is read.
*
* @see src/Phan/Config.php
* See Config for all configurable options.
*
* A Note About Paths
* ==================
*
* Files referenced from this file should be defined as
*
* ```
* Config::projectPath('relative_path/to/file')
* ```
*
* where the relative path is relative to the root of the
* project which is defined as either the working directory
* of the phan executable or a path passed in via the CLI
* '-d' flag.
*/
// use Phan\Config;
return [
// If true, missing properties will be created when
// they are first seen. If false, we'll report an
// error message.
"allow_missing_properties" => false,
// Allow null to be cast as any type and for any
// type to be cast to null.
"null_casts_as_any_type" => false,
// Backwards Compatibility Checking
'backward_compatibility_checks' => true,
// Run a quick version of checks that takes less
// time
"quick_mode" => false,
// Only emit critical issues to start with
// (0 is low severity, 5 is normal severity, 10 is critical)
"minimum_severity" => 10,
// default false for include path check
"enable_include_path_checks" => true,
"include_paths" => [
],
'ignore_undeclared_variables_in_global_scope' => true,
"file_list" => [
],
// A list of directories that should be parsed for class and
// method information. After excluding the directories
// defined in exclude_analysis_directory_list, the remaining
// files will be statically analyzed for errors.
//
// Thus, both first-party and third-party code being used by
// your application should be included in this list.
'directory_list' => [
// Change this to include the folders you wish to analyze
// (and the folders of their dependencies)
'.'
// 'www',
// To speed up analysis, we recommend going back later and
// limiting this to only the vendor/ subdirectories your
// project depends on.
// `phan --init` will generate a list of folders for you
//'www/vendor',
],
// A list of directories holding code that we want
// to parse, but not analyze
"exclude_analysis_directory_list" => [
'vendor',
],
'exclude_file_list' => [
],
// what not to show as problem
'suppress_issue_types' => [
// 'PhanUndeclaredMethod',
'PhanEmptyFile',
],
// Override to hardcode existence and types of (non-builtin) globals in the global scope.
// Class names should be prefixed with `\`.
//
// (E.g. `['_FOO' => '\FooClass', 'page' => '\PageClass', 'userId' => 'int']`)
'globals_type_map' => [],
];

View File

@@ -1,11 +1,19 @@
# Amazon Incentives - Gift on Demand standa 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.
Uses .env file to load configuration data
Amazon Gift Codes On Demand (AGCOD). Integration for Amazon Incentive API.
## How to install
`composer request gullevek/amazon-incentives`
## _ENV variables needed
Uses .env file to load configuration data
The below keys are searched in the _ENV file for loading
* AWS_GIFT_CARD_KEY
* AWS_GIFT_CARD_SECRET
* AWS_GIFT_CARD_PARTNER_ID
@@ -15,14 +23,15 @@ Uses .env file to load configuration data
## How to use
The class must be loaded with an autoloader (see test/autoloader.php for example).
The above _ENV variables must be set (Except AWS_DEBUG, defaults to off).
### create gift card
```php
$aws_gc = Amazon\AmazonIncentives::make()->buyGiftCard((float)$value);
use gullevek\AmazonIncentives\AmazonIncentives;
// buy a gift card with a value
$value = 500;
$aws_gc = AmazonIncentives::make()->buyGiftCard((float)$value);
// the two below are need if we want to cancel the card
// get gift card id (gcID)
$aws_gc->getId();
@@ -55,14 +64,14 @@ Recommended to pool requests. Or check when last requests where sent and then pr
```php
// use getCreationRequestId() and getId() from request
$aws_gc = Amazon\AmazonIncentives::make()->cancelGiftCard($creation_request_id, $gift_card_id);
$aws_gc = gullevek\AmazonIncentives\AmazonIncentives::make()->cancelGiftCard($creation_request_id, $gift_card_id);
// return is as above
```
### check balance
```php
$aws_gc = Amazon\AmazonIncentives::make()->getAvailableFunds();
$aws_gc = gullevek\AmazonIncentives\AmazonIncentives::make()->getAvailableFunds();
```
## Exceptions
@@ -71,6 +80,12 @@ If the HTTPS request does not return 220 OK it will throw an exception.
The error code is the curl handler error code.
The error message is json encoded array with the layout
Use
```php
$exception_array = gullevek\AmazonIncentives\AmazonIncentives::decodeExceptionMessage($exception_message);
```
to extract the below array from the thrown exception
```php
[
'status' => 'AWS Status FAILURE or RESEND',
@@ -84,18 +99,40 @@ The error message is json encoded array with the layout
`status`, `code` and `type` must be checked on a failure.
**NOTE**: if code is E999 then this is a request flood error:
## Other Errors from exceptions
### T001
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.
### E9999
if code is E999 some other critical error has happened
### E001
if code is E001 if the return create/cancel/check calls is not an array
### C001
fif code is C001 curl failed to init
### C002
if code is C002 a curl error has happened
### empty error code
any other NON amazon error will have only 'message' set if run through decode
## Debugging
If AWS_DEBUG is set to 1 and internal array will be written with debug info.
The Amazon\Debug\AmazonDebug class handles all this.
The gulleek\AmazonIncentives\Debug\AmazonDebug class handles all this.
In the Amazon\AWS\AWS main class the debugger gets set
* setFlag that turns debugger on/off
* setId (to set unique id for each run)
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)
New entries can be written with

24
composer.json Normal file
View File

@@ -0,0 +1,24 @@
{
"name": "gullevek/amazon-incentives",
"description": "Amazon Gift Codes, Gift on Demand, Incentives",
"keywords": ["AmazonGiftCode", "Amazon", "GiftCard", "AGCOD", "Incentives API", "Amazon Incentives API"],
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {
"gullevek\\AmazonIncentives\\": "src/"
}
},
"authors": [
{
"name": "Clemens Schwaighofer",
"email": "gullevek@gullevek.org",
"homepage": "http://gullevek.org"
}
],
"homepage": "https://github.com/gullevek/AmazonIncentives",
"minimum-stability": "dev",
"require": {
"php": ">=7.4.0"
}
}

15
phpstan.neon Normal file
View File

@@ -0,0 +1,15 @@
# PHP Stan Config
parameters:
tmpDir: /tmp/phpstan-codeblocks-amazon-incentives
level: max
paths:
- %currentWorkingDirectory%
excludes_analyse:
# ignore composer
- vendor
# ignore errores with
ignoreErrors:
-
message: '#Strict comparison using === between false and true will always evaluate to false.#'
path: %currentWorkingDirectory%/test/aws_gift_card_tests.php

View File

@@ -1,14 +1,14 @@
<?php
namespace Amazon\AWS;
namespace gullevek\AmazonIncentives\AWS;
use Amazon\Client\Client;
use Amazon\Config\Config;
use Amazon\Exceptions\AmazonErrors;
use Amazon\Debug\AmazonDebug;
use Amazon\Response\CancelResponse;
use Amazon\Response\CreateBalanceResponse;
use Amazon\Response\CreateResponse;
use gullevek\AmazonIncentives\Client\Client;
use gullevek\AmazonIncentives\Config\Config;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
use gullevek\AmazonIncentives\Debug\AmazonDebug;
use gullevek\AmazonIncentives\Response\CancelResponse;
use gullevek\AmazonIncentives\Response\CreateBalanceResponse;
use gullevek\AmazonIncentives\Response\CreateResponse;
class AWS
{
@@ -26,6 +26,9 @@ class AWS
public const CANCEL_GIFT_CARD_SERVICE = 'CancelGiftCard';
public const GET_AVAILABLE_FUNDS_SERVICE = 'GetAvailableFunds';
/**
* @var Config
*/
private $config;
/**
@@ -34,8 +37,6 @@ class AWS
public function __construct(Config $config)
{
$this->config = $config;
AmazonDebug::setFlag($config->getDebug());
AmazonDebug::setId();
AmazonDebug::writeLog([__METHOD__ => date('Y-m-d H:m:s.u')]);
}
@@ -154,7 +155,7 @@ class AWS
'Service' => $k_service_hexis,
]]);
$url = 'https://' . $endpoint . '/' . $service_operation;
$url = 'https://' . (string)$endpoint . '/' . $service_operation;
$headers = $this->buildHeaders($payload, $authorization_value, $date_time_string, $service_target);
return (new Client())->request($url, $headers, $payload);
}
@@ -164,7 +165,7 @@ class AWS
* @param string $authorization_value
* @param string $date_time_string
* @param string $service_target
* @return array
* @return array<mixed>
*/
public function buildHeaders(
string $payload,
@@ -268,6 +269,30 @@ class AWS
}
/**
* get the region based on endpoint
* list as of 2021/10/20
* WHERE URL REGION
* North America https://agcod-v2-gamma.amazon.com us-east-1
* https://agcod-v2.amazon.com
* (US, CA, MX)
* Europe and Asia https://agcod-v2-eu-gamma.amazon.com eu-west-1
* https://agcod-v2-eu.amazon.com
* (IT, ES, DE, FR, UK, TR, UAE, KSA, PL, NL, SE)
* Far East https://agcod-v2-fe-gamma.amazon.com us-west-2
* https://agcod-v2-fe.amazon.com
* (JP, AU, SG)
*
* CURRENCY
* USD for US
* EUR for EU (IT, ES, DE, FR, PL, NL, SE)
* JPY for JP
* CAD for CA
* AUD for AU
* TRY for TR
* AED for UAE
* MXN for MX
* GBP for UK
*
* @return string
*/
public function getRegion(): string
@@ -296,12 +321,11 @@ class AWS
/**
* @param float $amount
* @param string $creation_id
* @param string|null $creation_id
* @return string
*/
public function getGiftCardPayload(float $amount, ?string $creation_id = null): string
{
$amount = trim($amount);
$payload = [
'creationRequestId' => $creation_id ?: uniqid($this->config->getPartner() . '_'),
'partnerId' => $this->config->getPartner(),
@@ -311,7 +335,7 @@ class AWS
'amount' => (float)$amount
]
];
return json_encode($payload);
return (json_encode($payload)) ?: '';
}
/**
@@ -321,13 +345,12 @@ class AWS
*/
public function getCancelGiftCardPayload(string $creation_request_id, string $gift_card_id): string
{
$gift_card_response_id = trim($gift_card_id);
$payload = [
'creationRequestId' => $creation_request_id,
'partnerId' => $this->config->getPartner(),
'gcId' => $gift_card_response_id
'gcId' => $gift_card_id
];
return json_encode($payload);
return (json_encode($payload)) ?: '';
}
/**
@@ -338,7 +361,7 @@ class AWS
$payload = [
'partnerId' => $this->config->getPartner(),
];
return json_encode($payload);
return (json_encode($payload)) ?: '';
}
/**
@@ -372,7 +395,7 @@ class AWS
}
/**
* @return false|string
* @return string
*/
public function getTimestamp()
{
@@ -391,7 +414,7 @@ class AWS
}
/**
* @return bool|string
* @return string
*/
public function getDateString()
{

View File

@@ -1,18 +0,0 @@
<?php
namespace Amazon\Client;
interface ClientInterface
{
/**
* @param string $url The URL being requested, including domain and protocol
* @param array $headers Headers to be used in the request
* @param array|string $params Can be nested for arrays and hashes
*
* @return String
*/
public function request(string $url, array $headers, $params): string;
}
// __END__

View File

@@ -1,56 +0,0 @@
<?php
// simple write all into an array that we can poll in the return group
namespace Amazon\Debug;
class AmazonDebug
{
private static $log = [];
private static $debug = false;
private static $id = null;
public function __construct()
{
}
public static function setId(?string $id = null): void
{
if (self::$debug === false) {
return;
}
if ($id === null) {
$id = uniqid();
}
self::$id = $id;
}
public static function getId(): string
{
return self::$id;
}
public static function setFlag(bool $debug): void
{
self::$debug = $debug;
}
public static function writeLog(array $data): void
{
if (self::$debug === false) {
return;
}
self::$log[self::$id][] = $data;
}
public static function getLog(?string $id = null): array
{
if ($id === null) {
return self::$log;
} else {
return self::$log[$id] ?? [];
}
}
}
// __END__

View File

@@ -2,46 +2,21 @@
/*
* Amazon Incentive Code
*
* # settings:
* aws endpoint (also sets region)
* aws key
* aws secret
* aws partner id
* money type (set as default, override in call)
* money value (set as default, override in call)
*
* # checks
* endpoint + region must match
*
* # calls:
* create gift card: CreateGiftCard
* cancel gift card: CancelGiftCard
*
* activate gift card: ActivateGiftCard
* deactivate gift card: DeactivateGiftCard
*
* gift card status: ActivationStatusCheck
*
* check available funds: GetAvailablefunds
*
* api server health check
*
* # sub classes
* config reader/checker
* API v4 encrypter
* submitter/data getter
* error handler/retry
* Amazon Gift Code on Demand
*/
namespace Amazon;
namespace gullevek\AmazonIncentives;
use Amazon\AWS\AWS;
use Amazon\Config\Config;
use Amazon\Exceptions\AmazonErrors;
use gullevek\AmazonIncentives\AWS\AWS;
use gullevek\AmazonIncentives\Config\Config;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
use gullevek\AmazonIncentives\Debug\AmazonDebug;
class AmazonIncentives
final class AmazonIncentives
{
/**
* @var Config
*/
private $config;
/**
@@ -65,25 +40,21 @@ class AmazonIncentives
// load AWS settings
// fail here if settings missing
$this->config = new Config($key, $secret, $partner, $endpoint, $currency, $debug);
// init debug
AmazonDebug::setDebug($this->config->getDebug());
}
// *********************************************************************
// PRIVATE HELPER METHODS
// *********************************************************************
// *********************************************************************
// PUBLIC DEBUG METHODS
// *********************************************************************
// like log collector (array) and returner
// *********************************************************************
// PUBLIC METHODS
// *********************************************************************
/**
* @param float $value
* @param string $creation_request_id AWS creationRequestId
* @param string|null $creation_request_id AWS creationRequestId
* @return Response\CreateResponse
*
* @throws AmazonErrors
@@ -115,7 +86,7 @@ class AmazonIncentives
}
/**
* AmazonGiftCode make own client.
* AmazonIncentives make own client.
*
* @param string|null $key
* @param string|null $secret
@@ -123,7 +94,7 @@ class AmazonIncentives
* @param string|null $endpoint
* @param string|null $currency
* @param bool|null $debug
* @return AmazonGiftCode
* @return AmazonIncentives
*/
public static function make(
string $key = null,
@@ -142,7 +113,7 @@ class AmazonIncentives
* message (Amazon returned error message string)
*
* @param string $message Exception message json string
* @return array Decoded with code, type, message fields
* @return array<mixed> Decoded with code, type, message fields
*/
public static function decodeExceptionMessage(string $message): array
{
@@ -165,6 +136,9 @@ class AmazonIncentives
// PUBLIC TEST METHODS
// *********************************************************************
/**
* @return array<mixed>
*/
public function checkMe(): array
{
$data = [];

View File

@@ -1,9 +1,9 @@
<?php
namespace Amazon\Client;
namespace gullevek\AmazonIncentives\Client;
use Amazon\Exceptions\AmazonErrors;
use Amazon\Debug\AmazonDebug;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
use gullevek\AmazonIncentives\Debug\AmazonDebug;
class Client implements ClientInterface
{
@@ -13,15 +13,25 @@ class Client implements ClientInterface
/**
*
* @param string $url The URL being requested, including domain and protocol
* @param array $headers Headers to be used in the request
* @param array|string $params Can be nested for arrays and hashes
* @param array<mixed> $headers Headers to be used in the request
* @param array<mixed>|string $params Can be nested for arrays and hashes
*
*
* @return String
* @return string
*/
public function request(string $url, array $headers, $params): string
{
$handle = curl_init($url);
if ($handle === false) {
// throw Error here with all codes
throw AmazonErrors::getError(
'FAILURE',
'C001',
'CurlInitError',
'Failed to init curl with url: ' . $url,
0
);
}
curl_setopt($handle, CURLOPT_POST, true);
curl_setopt($handle, CURLOPT_HTTPHEADER, $headers);
// curl_setopt($handle, CURLOPT_FAILONERROR, true);
@@ -39,13 +49,13 @@ class Client implements ClientInterface
$err = curl_errno($handle);
AmazonDebug::writeLog(['CURL_REQUEST_RESULT' => $result]);
// extract all the error codes from Amazon
$result_ar = json_decode($result, true);
$result_ar = json_decode((string)$result, true);
// if message is 'Rate exceeded', set different error
if (($result_ar['message'] ?? '') == 'Rate exceeded') {
$error_status = 'RESEND';
$error_code = 'T001';
$error_type = 'RateExceeded';
$message = $result_ar['message'];
$message = $result_ar['message'] ?? 'Rate exceeded';
} else {
// for all other error messages
$error_status = $result_ar['agcodResponse']['status'] ?? 'FAILURE';
@@ -62,14 +72,14 @@ class Client implements ClientInterface
$err
);
}
return $result;
return (string)$result;
}
/**
* Undocumented function
*
* @param string $url
* @param string $errno
* @param int $errno
* @param string $message
* @return void
*/
@@ -79,25 +89,25 @@ class Client implements ClientInterface
case CURLE_COULDNT_CONNECT:
case CURLE_COULDNT_RESOLVE_HOST:
case CURLE_OPERATION_TIMEOUTED:
$msg = 'Could not connect to AWS (' . $url . '). Please check your '
. 'internet connection and try again.';
$message = 'Could not connect to AWS (' . $url . '). Please check your '
. 'internet connection and try again. [' . $message . ']';
break;
case CURLE_SSL_CACERT:
case CURLE_SSL_PEER_CERTIFICATE:
$msg = '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. '
. '(Try going to ' . $url . 'in your browser.) '
. 'If this problem persists,';
. '[' . $message . ']';
break;
case 0:
default:
$msg = 'Unexpected error communicating with AWS. ' . $message;
$message = 'Unexpected error communicating with AWS: ' . $message;
}
// throw an error like in the normal reqeust, but set to CURL error
throw AmazonErrors::getError(
'FAILURE',
'C001',
'C002',
'CurlError',
$message,
$errno

View File

@@ -0,0 +1,19 @@
<?php
namespace gullevek\AmazonIncentives\Client;
interface ClientInterface
{
/**
* @param string $url The URL being requested,
* including domain and protocol
* @param array<mixed> $headers Headers to be used in the request
* @param array<mixed>|string $params Can be nested for arrays and hashes
*
* @return String
*/
public function request(string $url, array $headers, $params): string;
}
// __END__

View File

@@ -1,6 +1,6 @@
<?php
namespace Amazon\Config;
namespace gullevek\AmazonIncentives\Config;
class Config implements ConfigInterface
{
@@ -44,12 +44,12 @@ class Config implements ConfigInterface
?string $currency,
?bool $debug,
) {
$this->setAccessKey($key ?: $this->parseEnv('AWS_GIFT_CARD_KEY'));
$this->setSecret($secret ?: $this->parseEnv('AWS_GIFT_CARD_SECRET'));
$this->setPartner($partner ?: $this->parseEnv('AWS_GIFT_CARD_PARTNER_ID'));
$this->setEndpoint($endpoint ?: $this->parseEnv('AWS_GIFT_CARD_ENDPOINT'));
$this->setCurrency($currency ?: $this->parseEnv('AWS_GIFT_CARD_CURRENCY'));
$this->setDebug($debug ?: $this->parseEnv('AWS_DEBUG'));
$this->setAccessKey(($key) ?: $this->parseEnv('AWS_GIFT_CARD_KEY')); /** @phpstan-ignore-line */
$this->setSecret(($secret) ?: $this->parseEnv('AWS_GIFT_CARD_SECRET')); /** @phpstan-ignore-line */
$this->setPartner(($partner) ?: $this->parseEnv('AWS_GIFT_CARD_PARTNER_ID')); /** @phpstan-ignore-line */
$this->setEndpoint(($endpoint) ?: $this->parseEnv('AWS_GIFT_CARD_ENDPOINT')); /** @phpstan-ignore-line */
$this->setCurrency(($currency) ?: $this->parseEnv('AWS_GIFT_CARD_CURRENCY')); /** @phpstan-ignore-line */
$this->setDebug(($debug) ?: $this->parseEnv('AWS_DEBUG')); /** @phpstan-ignore-line */
}
/**
@@ -80,9 +80,9 @@ class Config implements ConfigInterface
}
/**
* @return string
* @return string|null
*/
public function getEndpoint(): string
public function getEndpoint(): ?string
{
return $this->endpoint;
}
@@ -94,15 +94,15 @@ class Config implements ConfigInterface
public function setEndpoint(string $endpoint): ConfigInterface
{
// TODO: check valid endpoint + set region
$this->endpoint = parse_url($endpoint, PHP_URL_HOST);
$this->endpoint = (parse_url($endpoint, PHP_URL_HOST)) ?: '';
return $this;
}
/**
* @return string
* @return string|null
*/
public function getAccessKey(): string
public function getAccessKey(): ?string
{
return $this->access_key;
}
@@ -119,9 +119,9 @@ class Config implements ConfigInterface
}
/**
* @return string
* @return string|null
*/
public function getSecret(): string
public function getSecret(): ?string
{
return $this->secret_key;
}
@@ -138,9 +138,9 @@ class Config implements ConfigInterface
}
/**
* @return string
* @return string|null
*/
public function getCurrency(): string
public function getCurrency(): ?string
{
return $this->currency;
}
@@ -158,9 +158,9 @@ class Config implements ConfigInterface
}
/**
* @return string
* @return string|null
*/
public function getPartner(): string
public function getPartner(): ?string
{
return $this->partner_id;
}

View File

@@ -1,13 +1,13 @@
<?php
namespace Amazon\Config;
namespace gullevek\AmazonIncentives\Config;
interface ConfigInterface
{
/**
* @return String
* @return string|null
*/
public function getEndpoint(): string;
public function getEndpoint(): ?string;
/**
* @param string $endpoint
@@ -16,9 +16,9 @@ interface ConfigInterface
public function setEndpoint(string $endpoint): ConfigInterface;
/**
* @return String
* @return string|null
*/
public function getAccessKey(): string;
public function getAccessKey(): ?string;
/**
* @param string $key
@@ -27,9 +27,9 @@ interface ConfigInterface
public function setAccessKey(string $key): ConfigInterface;
/**
* @return String
* @return string|null
*/
public function getSecret(): string;
public function getSecret(): ?string;
/**
* @param string $secret
@@ -38,9 +38,9 @@ interface ConfigInterface
public function setSecret(string $secret): ConfigInterface;
/**
* @return String
* @return string|null
*/
public function getCurrency(): string;
public function getCurrency(): ?string;
/**
* @param string $currency
@@ -49,9 +49,9 @@ interface ConfigInterface
public function setCurrency(string $currency): ConfigInterface;
/**
* @return String
* @return string|null
*/
public function getPartner(): string;
public function getPartner(): ?string;
/**
* @param string $partner
@@ -60,9 +60,9 @@ interface ConfigInterface
public function setPartner(string $partner): ConfigInterface;
/**
* @return bool
* @return bool|null
*/
public function getDebug(): bool;
public function getDebug(): ?bool;
/**
* @param bool $debug

115
src/Debug/AmazonDebug.php Normal file
View File

@@ -0,0 +1,115 @@
<?php
// simple write all into an array that we can poll in the return group
// to activate AmazonDebug::setDebug(true) must be called once
namespace gullevek\AmazonIncentives\Debug;
class AmazonDebug
{
/**
* @var array<mixed>
*/
private static $log = [];
/**
* @var bool
*/
private static $debug = false;
/**
* @var string|null
*/
private static $id = null;
/**
* set the ID for current run
* if debug is off, nothing will be set and id is null
* This is run on setFlag, if debug is true
*
* @param string|null $id If not set, will default to uniqid() call
* @return void
*/
private static function setId(?string $id = null): void
{
if (self::$debug === false) {
return;
}
if ($id === null) {
$id = uniqid();
}
self::$id = $id;
}
/**
* set the debug flag.
* This is automatically run in gullevek\AmazonIncentives\AmazonIncentives::__construct
* No need to run manuall
*
* @param boolean $debug Can only be True or False
* @param string|null $id If not set, will default to uniqid() call
* @return void
*/
public static function setDebug(bool $debug, ?string $id = null): void
{
self::$debug = $debug;
if (self::$debug === false) {
return;
}
self::setId($id);
}
/**
* returns current debug flag status
*
* @return boolean True if debug is on, False if debug is off
*/
public static function getDebug(): bool
{
return self::$debug;
}
/**
* get the current set ID, can return null if debug is off
*
* @return string|null Current set ID for this log run
*/
public static function getId(): ?string
{
return self::$id;
}
/**
* write a log entry
* Data is as array key -> value
* Will be pushed as new array entry int log
* Main key is the set Id for this run
*
* @param array<mixed> $data Any array data to store in the log
* @return void
*/
public static function writeLog(array $data): void
{
if (self::$debug === false) {
return;
}
self::$log[self::getId() ?? ''][] = $data;
}
/**
* get all logs written since first class run
* or get all log entries for given ID
*
* @param string|null $id If set returns only this id logs
* or empty array if not found
* @return array<mixed> Always array, empty if not data or not found
*/
public static function getLog(?string $id = null): array
{
if ($id === null) {
return self::$log;
} else {
return self::$log[$id] ?? [];
}
}
}
// __END__

View File

@@ -1,17 +1,18 @@
<?php
namespace Amazon\Exceptions;
namespace gullevek\AmazonIncentives\Exceptions;
use RuntimeException;
use gullevek\AmazonIncentives\Debug\AmazonDebug;
class AmazonErrors extends RuntimeException
final class AmazonErrors extends RuntimeException
{
/**
* @param string $error_status agcodResponse->status from Amazon
* @param string $error_code errorCode from Amazon
* @param string $error_type errorType from Amazon
* @param string $message
* @param string $_error_code
* @param int $_error_code
* @return AmazonErrors
*/
public static function getError(
@@ -19,19 +20,19 @@ class AmazonErrors extends RuntimeException
string $error_code,
string $error_type,
string $message,
string $_error_code
int $_error_code
): self {
// NOTE: if xdebug.show_exception_trace is set to 1 this will print ERRORS
return new static(
json_encode([
(json_encode([
'status' => $error_status,
'code' => $error_code,
'type' => $error_type,
'message' => $message,
// atach log data if exists
'log_id' => \Amazon\Debug\AmazonDebug::getId(),
'log' => \Amazon\Debug\AmazonDebug::getLog(),
]),
'log_id' => AmazonDebug::getId(),
'log' => AmazonDebug::getLog(),
])) ?: 'AmazonErrors: json encode problem: ' . $message,
$_error_code
);
}

View File

@@ -1,6 +1,9 @@
<?php
namespace Amazon\Response;
namespace gullevek\AmazonIncentives\Response;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
use gullevek\AmazonIncentives\Debug\AmazonDebug;
class CancelResponse
{
@@ -25,31 +28,26 @@ class CancelResponse
/**
* Amazon Gift Card Raw JSON
*
* @var string
* @var array<mixed>
*/
protected $raw_json;
/**
* @var array
*/
protected $log;
/**
* Response constructor.
* @param array $json_response
* @param array<mixed> $json_response
*/
public function __construct(array $json_response)
{
$this->raw_json = $json_response;
$this->log = \Amazon\Debug\AmazonDebug::getLog(\Amazon\Debug\AmazonDebug::getId());
$this->parseJsonResponse($json_response);
}
/**
* @return array
* @return array<mixed>
*/
public function getLog(): array
{
return $this->log;
return AmazonDebug::getLog(AmazonDebug::getId());
}
/**
@@ -81,17 +79,23 @@ class CancelResponse
*/
public function getRawJson(): string
{
return json_encode($this->raw_json);
return (json_encode($this->raw_json)) ?: '';
}
/**
* @param array $json_response
* @param array<mixed> $json_response
* @return CancelResponse
*/
public function parseJsonResponse(array $json_response): self
{
if (!is_array($json_response)) {
throw new \RuntimeException('Response must be a scalar value');
throw AmazonErrors::getError(
'FAILURE',
'E001',
'NonScalarValue',
'Response must be a scalar value',
0
);
}
if (array_key_exists('gcId', $json_response)) {
$this->id = $json_response['gcId'];

View File

@@ -1,6 +1,9 @@
<?php
namespace Amazon\Response;
namespace gullevek\AmazonIncentives\Response;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
use gullevek\AmazonIncentives\Debug\AmazonDebug;
class CreateBalanceResponse
{
@@ -31,32 +34,27 @@ class CreateBalanceResponse
/**
* Amazon Gift Card Raw JSON
*
* @var string
* @var array<mixed>
*/
protected $raw_json;
/**
* @var array
*/
protected $log;
/**
* Response constructor.
*
* @param array $json_response
* @param array<mixed> $json_response
*/
public function __construct(array $json_response)
{
$this->raw_json = $json_response;
$this->log = \Amazon\Debug\AmazonDebug::getLog(\Amazon\Debug\AmazonDebug::getId());
$this->parseJsonResponse($json_response);
}
/**
* @return array
* @return array<mixed>
*/
public function getLog(): array
{
return $this->log;
return AmazonDebug::getLog(AmazonDebug::getId());
}
/**
@@ -96,19 +94,25 @@ class CreateBalanceResponse
*/
public function getRawJson(): string
{
return json_encode($this->raw_json);
return (json_encode($this->raw_json)) ?: '';
}
/**
* Undocumented function
*
* @param array $json_response
* @param array<mixed> $json_response
* @return CreateBalanceResponse
*/
public function parseJsonResponse(array $json_response): self
{
if (!is_array($json_response)) {
throw new \RuntimeException('Response must be a scalar value');
throw AmazonErrors::getError(
'FAILURE',
'E001',
'NonScalarValue',
'Response must be a scalar value',
0
);
}
if (array_key_exists('amount', $json_response['availableFunds'])) {
$this->amount = $json_response['availableFunds']['amount'];

View File

@@ -1,6 +1,9 @@
<?php
namespace Amazon\Response;
namespace gullevek\AmazonIncentives\Response;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
use gullevek\AmazonIncentives\Debug\AmazonDebug;
class CreateResponse
{
@@ -59,31 +62,26 @@ class CreateResponse
/**
* Amazon Gift Card Raw JSON
*
* @var string
* @var array<mixed>
*/
protected $raw_json;
/**
* @var array
*/
protected $log;
/**
* Response constructor.
* @param array $json_response
* @param array<mixed> $json_response
*/
public function __construct(array $json_response)
{
$this->raw_json = $json_response;
$this->log = \Amazon\Debug\AmazonDebug::getLog(\Amazon\Debug\AmazonDebug::getId());
$this->parseJsonResponse($json_response);
}
/**
* @return array
* @return array<mixed>
*/
public function getLog(): array
{
return $this->log;
return AmazonDebug::getLog(AmazonDebug::getId());
}
/**
@@ -111,9 +109,9 @@ class CreateResponse
}
/**
* @return string
* @return float
*/
public function getValue(): string
public function getValue(): float
{
return $this->value;
}
@@ -156,17 +154,23 @@ class CreateResponse
*/
public function getRawJson(): string
{
return json_encode($this->raw_json);
return (json_encode($this->raw_json)) ?: '';
}
/**
* @param array $json_response
* @param array<mixed> $json_response
* @return CreateResponse
*/
public function parseJsonResponse(array $json_response): self
{
if (!is_array($json_response)) {
throw new \RuntimeException('Response must be a scalar value');
throw AmazonErrors::getError(
'FAILURE',
'E001',
'NonScalarValue',
'Response must be a scalar value',
0
);
}
if (array_key_exists('gcId', $json_response)) {
$this->id = $json_response['gcId'];

View File

@@ -1,63 +0,0 @@
<?php // phpcs:ignore PSR1.Files.SideEffects
declare(strict_types=1);
namespace Autoloader;
// shall implement an auto loader
if (class_exists('Autoload', false) === false) {
// define the auto loader class
class Autoload
{
// we do it simple here
// passes on the class to load and we search here in namespace
// to load that class
public static function load($class)
{
// print "(1) Class: $class / DIR: " . __DIR__ . "<br>";
// set directory seperator (we need to replace from namespace)
$DS = DIRECTORY_SEPARATOR;
// base lib
$LIB = defined('LIB') ? LIB : '../src' . $DS;
// if lib is in path at the end, do not add lib again
// note that $LIB can have a directory seperator at the end
// strip that out before we do a match
$_LIB = rtrim($LIB, $DS);
if (!preg_match("|$_LIB$|", __DIR__)) {
$LIB .= $DS;
} else {
$LIB = '';
}
// default path is unset
$path = false;
// set path on full dir
// if we have the namespace in the class, strip it out
$len = 0;
if (strpos($class, __NAMESPACE__) !== false) {
$len = strlen(__NAMESPACE__);
}
// set default extension
$extension = '.php';
// set full include path
$path = __DIR__ . $DS . $LIB . substr($class, $len);
// replace namespace \ with dir sepeator
$path = str_replace('\\', $DS, $path) . $extension;
// print "(2) Class clean: $path<br>";
// if path is set and a valid file
if ($path !== false && is_file($path)) {
// print "<b>(3)</b> Load Path: $path<br>";
// we should sub that
// self::loadFile($path);
include $path;
return true;
}
return false;
}
// end class define
}
spl_autoload_register('Autoloader\Autoload::load', true, true);
} // end check for already defined
// __END__

View File

@@ -1,12 +1,67 @@
<?php // phpcs:ignore PSR1.Files.SideEffects
// test for Amazon Gift Card Incentives
// Tests for Amazon Gift Card Incentives
// general auto loader
require 'autoloader.php';
// env file loader
/**
* write log as string from array data
* includes timestamp
*
* @param array<mixed> $data Debug log array data to add to the json string
* @return string
*/
function writeLog(array $data): string
{
return json_encode([
'date' => date('Y-m-d H:i:s'),
'log' => $data
]) . "\n";
}
/**
* translate the UTC amazon date string to Y-m-d H:i:s standard
*
* @param string $date A UTC string date from Amazon
* @return string
*/
function dateTr(string $date): string
{
return date('Y-m-d H:i:s', (strtotime($date)) ?: null);
}
/**
* print exception string
*
* @param string $call_request Call request, eg buyGiftCard
* @param integer $error_code $e Exception error code
* @param array<mixed> $error Array from the Exception message json string
* @param boolean $debug_print If we should show the debug log
* @return void
*/
function printException(
string $call_request,
int $error_code,
array $error,
bool $debug_print
): void {
print "AWS: " . $call_request . ": " . $error['status']
. " [" . $error_code . "]: "
. $error['code'] . " | " . $error['type']
. " | " . $error['message'];
if ($debug_print === true) {
print "<pre>" . print_r($error['log'][$error['log_id'] ?? ''] ?? [], true) . "</pre>";
}
}
// composer auto loader
$loader = require '../vendor/autoload.php';
// need to add this or it will not load here
$loader->addPsr4('gullevek\\', __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'src');
// print "LOADER: <pre>" . print_r($loader, true) . "</pre>";
// env file loader (simple)
require 'read_env_file.php';
use gullevek\AmazonIncentives\AmazonIncentives;
// load env data with dotenv
readEnvFile(__DIR__);
@@ -17,8 +72,9 @@ print "<h1>Amazon Gift Card Incentives</h1><br>";
// aws key: AWS_GIFT_CARD_KEY
// aws secret: AWS_GIFT_CARD_SECRET
// partner id: AWS_GIFT_CARD_PARTNER_ID
// optional
// currency: AWS_ICENTIVE_CURRENCY
// optional
// debug: AWS_DEBUG (if not set: off)
// as in .env
// AWS_GIFT_CARD_ENDPOINT.TEST
@@ -35,34 +91,16 @@ foreach (
$_ENV[$key] = $_ENV[$key . '.' . strtoupper((LOCATION))] ?? $_ENV[$key] ?? '';
}
/*
ENDPOINTS:
- remove '-gamma' for non sandox
WHERE URL REGION
North America https://agcod-v2-gamma.amazon.com us-east-1
https://agcod-v2.amazon.com
(US, CA, MX)
Europe and Asia https://agcod-v2-eu-gamma.amazon.com eu-west-1
https://agcod-v2-eu.amazon.com
(IT, ES, DE, FR, UK, TR, UAE, KSA, PL, NL, SE)
Far East https://agcod-v2-fe-gamma.amazon.com us-west-2
https://agcod-v2-fe.amazon.com
(JP, AU, SG)
CURRENCY
USD for US
EUR for EU
JPY for JP
CAD for CA
AUD for AU
TRY for TR
AED for UAE
*/
// open debug file output
$fp = fopen('log/debug.' . date('YmdHis') . '.log', 'w');
if (!is_resource($fp)) {
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 = false;
$run_fund_test = true;
// run the normal get/cancel gift card tests
$run_gift_tests = true;
// run mock error check tests
@@ -77,29 +115,31 @@ $mock_debug = false;
// wait in seconds between mock tests
$mock_wait = 2;
$aws = new Amazon\AmazonIncentives();
// $aws->createGiftCard(100);
if ($run_info_test === true) {
$aws = new AmazonIncentives();
print "checkMe: <pre>" . print_r($aws->checkMe(), true) . "</pre>";
fwrite($fp, writeLog($aws->checkMe()));
print "<hr>";
// we should open log file to collect all creationRequestId/gcId
// so we can test and cancel
}
// check balance
if ($run_fund_test === true) {
try {
$aws_test = Amazon\AmazonIncentives::make()->getAvailableFunds();
print "AWS: getAvailableFunds: <pre>" . print_r($aws_test, true) . "</pre><br>";
} catch (Exception $e) {
print "AWS: getAvailableFunds: " . $error['status']
. " [" . $e->getCode() . "]: "
. $error['code'] . " | " . $error['type']
. " | " . $error['message'] . ": ";
$aws_test = AmazonIncentives::make()->getAvailableFunds();
print "AWS: getAvailableFunds: " . $aws_test->getStatus() . ": "
. "Amount: " . $aws_test->getAmount() . ", "
. "Currency: " . $aws_test->getCurrency() . ", "
. "Timestamp: " . $aws_test->getTimestamp();
if ($debug_print === true) {
print "/<pre>" . print_r($error['log'][$error['log_id'] ?? ''] ?? [], true) . "</pre>";
print "<pre>" . print_r($aws_test, true) . "</pre>";
}
fwrite($fp, writeLog((array)$aws_test));
} catch (Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
printException('getAvailableFunds', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error));
};
print "<br>";
sleep($debug_wait);
// print "LOG: <pre>" . print_r($aws_test->getLog(), true) . "</pre><br>";
print "<hr>";
@@ -108,62 +148,111 @@ if ($run_fund_test === true) {
if ($run_gift_tests === true) {
// create card
$value = 1000;
$creation_request_id = '';
$gift_card_id = '';
try {
// we must be sure we pass FLOAT there
$aws_test = Amazon\AmazonIncentives::make()->buyGiftCard((float)$value);
$aws_test = AmazonIncentives::make()->buyGiftCard((float)$value);
$creation_request_id = $aws_test->getCreationRequestId();
$gift_card_id = $aws_test->getId();
$claim_code = $aws_test->getClaimCode();
$expiration_date = $aws_test->getExpirationDate();
$request_status = $aws_test->getStatus();
print "AWS: buyGiftCard: " . $request_status . ": "
. "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", "
. "CLAIM CODE: <b>" . $claim_code . "</b><br>";
. "EXPIRE DATE: <b>" . dateTr($expiration_date) . "</b>, "
. "CLAIM CODE: <b>" . $claim_code . "</b>";
if ($debug_print === true) {
print "<pre>" . print_r($aws_test, true) . "</pre><br>";
print "<pre>" . print_r($aws_test, true) . "</pre>";
}
fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
printException('buyGiftCard', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error));
}
print "<br>";
sleep($debug_wait);
try {
// cancel above created card card
$aws_test = Amazon\AmazonIncentives::make()->cancelGiftCard($creation_request_id, $gift_card_id);
$aws_test = AmazonIncentives::make()->cancelGiftCard($creation_request_id, $gift_card_id);
$request_status = $aws_test->getStatus();
print "AWS: cancelGiftCard: " . $request_status . ": "
. "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id
. "<br>";
. "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id;
if ($debug_print === true) {
print "<pre>" . print_r($aws_test, true) . "</pre><br>";
print "<pre>" . print_r($aws_test, true) . "</pre>";
}
fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
print "AWS: cancelGiftCard: " . $error['status']
. " [" . $e->getCode() . "]: "
. $error['code'] . " | " . $error['type']
. " | " . $error['message'];
if ($debug_print === true) {
print "<pre>" . print_r($error['log'][$error['log_id'] ?? ''] ?? [], true) . "</pre>";
}
fwrite($fp, writeLog($error));
}
print "<br>";
sleep($debug_wait);
// set same request ID twice to get same response test
$aws_test = Amazon\AmazonIncentives::make()->buyGiftCard((float)$value);
try {
$aws_test = AmazonIncentives::make()->buyGiftCard((float)$value);
$creation_request_id = $aws_test->getCreationRequestId();
$gift_card_id = $aws_test->getId();
$claim_code = $aws_test->getClaimCode();
$expiration_date = $aws_test->getExpirationDate();
$request_status = $aws_test->getStatus();
print "AWS: buyGiftCard: CODE A: " . $request_status . ": "
. "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", "
. "CLAIM CODE: <b>" . $claim_code . "</b><br>";
. "EXPIRE DATE: <b>" . dateTr($expiration_date) . "</b>, "
. "CLAIM CODE: <b>" . $claim_code . "</b>";
if ($debug_print === true) {
print "<pre>" . print_r($aws_test, true) . "</pre><br>";
print "<pre>" . print_r($aws_test, true) . "</pre>";
}
fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
printException('cancelGiftCard', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error));
}
print "<br>";
sleep($debug_wait);
$aws_test = Amazon\AmazonIncentives::make()->buyGiftCard((float)$value, $creation_request_id);
try {
$aws_test = AmazonIncentives::make()->buyGiftCard((float)$value, $creation_request_id);
$request_status = $aws_test->getStatus();
// same?
$claim_code = $aws_test->getClaimCode();
$expiration_date = $aws_test->getExpirationDate();
print "AWS: buyGiftCard: SAME CODE A AGAIN: " . $request_status . ": "
. "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", "
. "CLAIM CODE: <b>" . $claim_code . "</b><br>";
. "EXPIRE DATE: <b>" . dateTr($expiration_date) . "</b>, "
. "CLAIM CODE: <b>" . $claim_code . "</b>";
if ($debug_print === true) {
print "<pre>" . print_r($aws_test, true) . "</pre><br>";
print "<pre>" . print_r($aws_test, true) . "</pre>";
}
fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
printException('buyGiftCard', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error));
}
print "<br>";
print "<hr>";
sleep($debug_wait);
}
// MOCK TEST
if ($mock_debug === true) {
if ($run_mocks === true) {
$mock_ok = '<span style="color:green;">MOCK OK</span>';
$mock_failure = '<span style="color:red;">MOCK FAILURE</span>';
$mock_value = 500;
$mock = [];
$mock['F0000'] = [ 'ret' => '', 'st' => 'SUCCESS']; // success mock
$mock['F1000'] = [ 'ret' => 'F100', 'st' => 'FAILURE']; // SimpleAmountIsNull, etc
$mock['F2003'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // InvalidAmountInput
$mock['F2004'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // InvalidAmountValue
$mock['F2005'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // InvalidCurrencyCodeInput
@@ -181,12 +270,12 @@ if ($mock_debug === true) {
foreach ($mock as $creation_id => $mock_return) {
print "<b>TS: " . microtime() . "</b>: ";
try {
$aws_test = Amazon\AmazonIncentives::make()->buyGiftCard((float)$mock_value, $creation_id);
$aws_test = AmazonIncentives::make()->buyGiftCard((float)$mock_value, $creation_id);
$creation_request_id = $aws_test->getCreationRequestId();
$gift_card_id = $aws_test->getId();
$claim_code = $aws_test->getClaimCode();
$request_status = $aws_test->getStatus();
print "AWS: MOCK: " . $creation_id . ": buyGiftCard: " . $request_status . ": "
print "AWS: MOCK: " . $creation_id . ": buyGiftCard: <b>" . $request_status . "</b>: "
. "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", "
. "CLAIM CODE: <b>" . $claim_code . "</b>: ";
if ($mock_return['st'] == $request_status) {
@@ -197,8 +286,9 @@ if ($mock_debug === true) {
if ($mock_debug === true) {
print "<pre>" . print_r($aws_test, true) . "</pre>";
}
fwrite($fp, writeLog((array)$aws_test));
} catch (Exception $e) {
$error = Amazon\AmazonIncentives::decodeExceptionMessage($e->getMessage());
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
print "AWS: MOCK: " . $creation_id . ": buyGiftCard: " . $error['status']
. " [" . $e->getCode() . "]: "
. $error['code'] . " | " . $error['type']
@@ -212,8 +302,9 @@ if ($mock_debug === true) {
print $mock_failure;
}
if ($mock_debug === true) {
print "/<pre>" . print_r($error['log'][$error['log_id'] ?? ''] ?? [], true) . "</pre>";
print "<pre>" . print_r($error['log'][$error['log_id'] ?? ''] ?? [], true) . "</pre>";
}
fwrite($fp, writeLog($error));
}
print "<br>";
// Waiting a moment, so we don't flood
@@ -222,4 +313,6 @@ if ($mock_debug === true) {
print "<hr>";
}
fclose($fp);
// __END__

2
test/log/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

7
vendor/autoload.php vendored Normal file
View File

@@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit0c8f6bec90a6d60040a922f19a1f0e64::getLoader();

572
vendor/composer/ClassLoader.php vendored Normal file
View File

@@ -0,0 +1,572 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
/** @var ?string */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
private $apcuPrefix;
/**
* @var self[]
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
/**
* @return string[]
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return string[] Array of classname => path
* @psalm-var array<string, string>
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
*
* @return void
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
* @private
*/
function includeFile($file)
{
include $file;
}

21
vendor/composer/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

10
vendor/composer/autoload_classmap.php vendored Normal file
View File

@@ -0,0 +1,10 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
);

View File

@@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

10
vendor/composer/autoload_psr4.php vendored Normal file
View File

@@ -0,0 +1,10 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'gullevek\\AmazonIncentives\\' => array($baseDir . '/src'),
);

55
vendor/composer/autoload_real.php vendored Normal file
View File

@@ -0,0 +1,55 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit0c8f6bec90a6d60040a922f19a1f0e64
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit0c8f6bec90a6d60040a922f19a1f0e64', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit0c8f6bec90a6d60040a922f19a1f0e64', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit0c8f6bec90a6d60040a922f19a1f0e64::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
return $loader;
}
}

36
vendor/composer/autoload_static.php vendored Normal file
View File

@@ -0,0 +1,36 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit0c8f6bec90a6d60040a922f19a1f0e64
{
public static $prefixLengthsPsr4 = array (
'G' =>
array (
'gullevek\\AmazonIncentives\\' => 26,
),
);
public static $prefixDirsPsr4 = array (
'gullevek\\AmazonIncentives\\' =>
array (
0 => __DIR__ . '/../..' . '/src',
),
);
public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit0c8f6bec90a6d60040a922f19a1f0e64::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit0c8f6bec90a6d60040a922f19a1f0e64::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit0c8f6bec90a6d60040a922f19a1f0e64::$classMap;
}, null, ClassLoader::class);
}
}