diff --git a/CHANGELOG.md b/CHANGELOG.md index 15a6a2d..7e3ff39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +2.2.7 +=== +

released on 2020-08-14

+ + +2.2.6 +=== +

released on 2020-03-06

+ + +2.2.5 +=== +

released on 2019-04-04

+ + 2.2.4 ===

released on 2018-11-12

diff --git a/class/PaylinePaymentGateway.php b/class/PaylinePaymentGateway.php index e873e67..1ba9c71 100644 --- a/class/PaylinePaymentGateway.php +++ b/class/PaylinePaymentGateway.php @@ -866,6 +866,9 @@ public static function captureTransaction($transactionId, $paymentMode = 'CPT', // Do re-autorization $params['payment']['action'] = 101; $params['order'] = $transaction['order']; + // Format Order Date for Payline dd/mm/YYYY h:m + $dt = new DateTime($params['order']['date']); + $params['order']['date'] = $dt->format('d/m/Y h:m'); $result = $instance->doReAuthorization($params); } else { // Do capture diff --git a/lib/composer/ClassLoader.php b/lib/composer/ClassLoader.php index 2c72175..fce8549 100644 --- a/lib/composer/ClassLoader.php +++ b/lib/composer/ClassLoader.php @@ -279,7 +279,7 @@ public function isClassMapAuthoritative() */ public function setApcuPrefix($apcuPrefix) { - $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; } /** @@ -377,11 +377,11 @@ private function findFileWithExtension($class, $ext) $subPath = $class; while (false !== $lastPos = strrpos($subPath, '\\')) { $subPath = substr($subPath, 0, $lastPos); - $search = $subPath.'\\'; + $search = $subPath . '\\'; if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); foreach ($this->prefixDirsPsr4[$search] as $dir) { - $length = $this->prefixLengthsPsr4[$first][$search]; - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + if (file_exists($file = $dir . $pathEnd)) { return $file; } } diff --git a/lib/composer/installed.json b/lib/composer/installed.json index de9fa2c..4ae7e9d 100644 --- a/lib/composer/installed.json +++ b/lib/composer/installed.json @@ -1,66 +1,65 @@ [ { - "name": "psr/log", - "version": "1.0.2", - "version_normalized": "1.0.2.0", + "name": "monext/payline-sdk", + "version": "4.59.5", + "version_normalized": "4.59.5.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "url": "https://github.com/PaylineByMonext/payline-php-sdk.git", + "reference": "f73fc72b63547e42b00de7fc27432c5b7aff0285" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/PaylineByMonext/payline-php-sdk/zipball/f73fc72b63547e42b00de7fc27432c5b7aff0285", + "reference": "f73fc72b63547e42b00de7fc27432c5b7aff0285", "shasum": "" }, "require": { + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-soap": "*", + "monolog/monolog": "1.* || ~2.0", "php": ">=5.3.0" }, - "time": "2016-10-10T12:19:37+00:00", + "time": "2020-01-03T12:41:19+00:00", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "installation-source": "dist", "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Payline\\": "src/Payline" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "LGPL-3.0" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Fabien SUAREZ", + "email": "fabien.suarez@payline.com", + "homepage": "http://www.payline.com" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Payline library for PHP", "keywords": [ - "log", - "psr", - "psr-3" + "Monext", + "Payline", + "payment" ] }, { "name": "monolog/monolog", - "version": "1.23.0", - "version_normalized": "1.23.0.0", + "version": "1.25.3", + "version_normalized": "1.25.3.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4" + "reference": "fa82921994db851a8becaf3787a9e73c5976b6f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fd8c787753b3a2ad11bc60c063cff1358a32a3b4", - "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fa82921994db851a8becaf3787a9e73c5976b6f1", + "reference": "fa82921994db851a8becaf3787a9e73c5976b6f1", "shasum": "" }, "require": { @@ -96,7 +95,7 @@ "ruflin/elastica": "Allow sending log messages to an Elastic Search server", "sentry/sentry": "Allow sending log messages to a Sentry server" }, - "time": "2017-06-19T01:22:40+00:00", + "time": "2019-12-20T14:15:16+00:00", "type": "library", "extra": { "branch-alias": { @@ -129,48 +128,52 @@ ] }, { - "name": "monext/payline-sdk", - "version": "4.52.1", - "version_normalized": "4.52.1.0", + "name": "psr/log", + "version": "1.1.2", + "version_normalized": "1.1.2.0", "source": { "type": "git", - "url": "https://github.com/PaylineByMonext/payline-php-sdk.git", - "reference": "25a04234f2a826c572e104834f6f851606137ff9" + "url": "https://github.com/php-fig/log.git", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PaylineByMonext/payline-php-sdk/zipball/25a04234f2a826c572e104834f6f851606137ff9", - "reference": "25a04234f2a826c572e104834f6f851606137ff9", + "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", "shasum": "" }, "require": { - "monolog/monolog": "1.*", "php": ">=5.3.0" }, - "time": "2017-10-24T09:55:59+00:00", + "time": "2019-11-01T11:05:21+00:00", "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, "installation-source": "dist", "autoload": { "psr-4": { - "Payline\\": "src/Payline" + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0" + "MIT" ], "authors": [ { - "name": "Fabien SUAREZ", - "email": "fabien.suarez@payline.com", - "homepage": "http://www.payline.com" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Payline library for PHP", + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ - "Monext", - "Payline", - "payment" + "log", + "psr", + "psr-3" ] } ] diff --git a/lib/monext/payline-sdk/CHANGELOG.md b/lib/monext/payline-sdk/CHANGELOG.md index e4d073e..2c310a0 100644 --- a/lib/monext/payline-sdk/CHANGELOG.md +++ b/lib/monext/payline-sdk/CHANGELOG.md @@ -1,4 +1,30 @@ -* 4.52 (2017-10-16) +* 4.59 (2019-07-28) + * wsdl upgrade + * new threeDSInfo parameter for manageWebWallet and doWebPayment + * new browser in threeDSInfo + * new sdk in threeDSInfo + * new streetNumber, addressCreateDate and email in address + * new resultContainer and authenticationResult in Authentication3DSecure + * new buyerExtended, merchantAuthentication and loyaltyMemberType in buyer + * new discountAmount, otaPackageType, otaDestinationCountry, bookingReference, orderDetail, orderExtended and orderOTA in order + * new seller and sellerType in OrderDetail + * new cumulatedAmount in payment + * new billingBank in recurring + +* 4.54 & 4.55 (2018-06-27) + * new asynchronousRetryTimeout parameter for doAuthorization and doWebPayment (4.55) + * new miscData parameter for isRegistered (4.54) + +* 4.53 (2018-01-10) + * new deliveryCharge attribute in order object + * new registrationToken attribute in payment object + * new object subMerchant + * new method isRegistered + * new subMerchant parameter for doAuthorization, doWebPayment, doCredit, doDebit, doImmediateWalletPayment, doScheduledWalletPayment + * new miscData parameter for doWebPayment + * new returnUrl parameter for verifyEnrollment + + * 4.52 (2017-10-16) * new avs child node in transaction object * 4.51 (2017-08-11) diff --git a/lib/monext/payline-sdk/README.md b/lib/monext/payline-sdk/README.md index 007376b..7b57ba0 100644 --- a/lib/monext/payline-sdk/README.md +++ b/lib/monext/payline-sdk/README.md @@ -58,7 +58,7 @@ Requires monolog/monolog, just let Composer do the job Author ------ -Fabien SUAREZ - +Payline support - License ------- diff --git a/lib/monext/payline-sdk/composer.json b/lib/monext/payline-sdk/composer.json index 7d83560..7285b86 100644 --- a/lib/monext/payline-sdk/composer.json +++ b/lib/monext/payline-sdk/composer.json @@ -16,7 +16,10 @@ ], "require" : { "php" : ">=5.3.0", - "monolog/monolog" : "1.*" + "ext-soap": "*", + "monolog/monolog" : "1.* || ~2.0", + "ext-openssl": "*", + "ext-mbstring": "*" }, "support" : { "email" : "support@payline.com", @@ -26,6 +29,6 @@ "psr-4" : { "Payline\\" : "src/Payline" } - + } } diff --git a/lib/monext/payline-sdk/src/Payline/Address.php b/lib/monext/payline-sdk/src/Payline/Address.php index 15eae93..a73588d 100644 --- a/lib/monext/payline-sdk/src/Payline/Address.php +++ b/lib/monext/payline-sdk/src/Payline/Address.php @@ -37,4 +37,10 @@ class Address public $phoneType; public $phone; -} \ No newline at end of file + + public $streetNumber; + + public $addressCreateDate; + + public $email; +} diff --git a/lib/monext/payline-sdk/src/Payline/Authentication3DSecure.php b/lib/monext/payline-sdk/src/Payline/Authentication3DSecure.php index 901bbac..6828964 100644 --- a/lib/monext/payline-sdk/src/Payline/Authentication3DSecure.php +++ b/lib/monext/payline-sdk/src/Payline/Authentication3DSecure.php @@ -31,4 +31,8 @@ class Authentication3DSecure public $PaResStatus; public $VeResStatus; -} \ No newline at end of file + + public $resultContainer; + + public $authenticationResult; +} diff --git a/lib/monext/payline-sdk/src/Payline/Browser.php b/lib/monext/payline-sdk/src/Payline/Browser.php new file mode 100644 index 0000000..041a945 --- /dev/null +++ b/lib/monext/payline-sdk/src/Payline/Browser.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Payline; +class Browser { + public $acceptHeader; + + public $javaEnabled; + + public $javascriptEnabled; + + public $language; + + public $colorDepth; + + public $screenHeight; + + public $screenWidth; + + public $timeZoneOffset; + + public $userAgent; +} diff --git a/lib/monext/payline-sdk/src/Payline/Buyer.php b/lib/monext/payline-sdk/src/Payline/Buyer.php index d7eafb1..c740f55 100644 --- a/lib/monext/payline-sdk/src/Payline/Buyer.php +++ b/lib/monext/payline-sdk/src/Payline/Buyer.php @@ -67,4 +67,10 @@ class Buyer public $isRooted; public $hasTimezoneMismatch; -} \ No newline at end of file + + public $buyerExtended; + + public $merchantAuthentication; + + public $loyaltyMemberType; +} diff --git a/lib/monext/payline-sdk/src/Payline/MerchantAuthentication.php b/lib/monext/payline-sdk/src/Payline/MerchantAuthentication.php new file mode 100644 index 0000000..2d30500 --- /dev/null +++ b/lib/monext/payline-sdk/src/Payline/MerchantAuthentication.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Payline; +class MerchantAuthentication { + public $method; + + public $date; +} diff --git a/lib/monext/payline-sdk/src/Payline/Order.php b/lib/monext/payline-sdk/src/Payline/Order.php index 05c2dc0..3e28cd3 100644 --- a/lib/monext/payline-sdk/src/Payline/Order.php +++ b/lib/monext/payline-sdk/src/Payline/Order.php @@ -39,4 +39,20 @@ class Order public $deliveryExpectedDate; public $deliveryExpectedDelay; -} \ No newline at end of file + + public $deliveryCharge; + + public $discountAmount; + + public $otaPackageType; + + public $otaDestinationCountry; + + public $bookingReference; + + public $orderDetail; + + public $orderExtended; + + public $orderOTA; +} diff --git a/lib/monext/payline-sdk/src/Payline/OrderDetail.php b/lib/monext/payline-sdk/src/Payline/OrderDetail.php index bfaccf2..554eaf2 100644 --- a/lib/monext/payline-sdk/src/Payline/OrderDetail.php +++ b/lib/monext/payline-sdk/src/Payline/OrderDetail.php @@ -31,4 +31,8 @@ class OrderDetail public $additionalData; public $taxRate; -} \ No newline at end of file + + public $seller; + + public $sellerType; +} diff --git a/lib/monext/payline-sdk/src/Payline/PaylineSDK.php b/lib/monext/payline-sdk/src/Payline/PaylineSDK.php index beb8e50..394e814 100644 --- a/lib/monext/payline-sdk/src/Payline/PaylineSDK.php +++ b/lib/monext/payline-sdk/src/Payline/PaylineSDK.php @@ -9,8 +9,10 @@ */ namespace Payline; +use Payline\MerchantAuthentication; use Monolog\Logger; use Monolog\Handler\StreamHandler; +use Payline\Browser; use SoapClient; use SoapVar; use Payline\Payment; @@ -29,6 +31,8 @@ use Payline\Creditor; use Payline\Cheque; use Payline\Recurring; +use Payline\ThreeDSInfo; +use Payline\Sdk; class PaylineSDK { @@ -36,18 +40,18 @@ class PaylineSDK /** * Payline release corresponding to this version of the package */ - const SDK_RELEASE = 'PHP SDK 4.52.1'; + const SDK_RELEASE = 'PHP SDK 4.59'; /** * WSDL file name */ - const WSDL = 'v4.52.wsdl'; + const WSDL = 'v4.59.wsdl'; /** * development environment flag */ const ENV_DEV = "DEV"; - + /** * integration environment flag */ @@ -57,7 +61,7 @@ class PaylineSDK * homologation environment flag */ const ENV_HOMO = "HOMO"; - + /** * homologation environment flag - uses certificate-based authentication */ @@ -117,7 +121,7 @@ class PaylineSDK * SOAP name of payment object */ const SOAP_PAYMENT = 'payment'; - + /** * SOAP name of paymentData object */ @@ -178,6 +182,36 @@ class PaylineSDK */ const SOAP_RECURRING = 'recurring'; + /** + * SOAP name of subMerchant object + */ + const SOAP_SUBMERCHANT = 'subMerchant'; + + /** + * SOAP name of threeDSInfo object + */ + const SOAP_THREEDSINFO = 'threeDSInfo'; + + /** + * SOAP name of browser object + */ + const SOAP_BROWSER = 'browser'; + + /** + * SOAP name of sdk object + */ + const SOAP_SDK = 'sdk'; + + /** + * SOAP name of merchantAuthentication object + */ + const SOAP_MERCHANT_AUTHENTICATION = 'merchantAuthentication'; + + /** + * SOAP name of wallet object + */ + const SOAP_WALLET = 'wallet'; + /** * web services endpoint in development environment */ @@ -207,12 +241,12 @@ class PaylineSDK * certificate-based authentication web services endpoint in production environment */ const PROD_CC_ENDPOINT = 'https://services-cc.payline.com/V4/services/'; - + /** * URL of getToken servlet, used by AJAX API, in development environment */ const DEV_GET_TOKEN_SERVLET = "https://webpayment.dev.payline.com/webpayment/getToken"; - + /** * URL of getToken servlet, used by AJAX API, in integration environment */ @@ -227,44 +261,44 @@ class PaylineSDK * URL of getToken servlet, used by AJAX API, in production environment */ const PROD_GET_TOKEN_SERVLET = "https://webpayment.payline.com/webpayment/getToken"; - + /** * Widget JavaScript in development environment */ const DEV_WDGT_JS = "https://webpayment.dev.payline.com/payline-widget/scripts/widget-min.js"; - + /** * Widget JavaScript in homologation environment */ const HOMO_WDGT_JS = "https://homologation-payment.payline.com/scripts/widget-min.js"; - + /** * Widget JavaScript in production environment */ const PROD_WDGT_JS = "https://payment.payline.com/scripts/widget-min.js"; - + /** * Widget css in development environment */ - const DEV_WDGT_CSS = "https://webpayment.dev.payline.com/payline-widget/styles/widget-min.css"; - + const DEV_WDGT_CSS = "https://webpayment.dev.payline.com/payline-widget/styles/widget-min.css"; + /** * Widget css in homologation environment */ - const HOMO_WDGT_CSS = "https://homologation-payment.payline.com/styles/widget-min.css"; - + const HOMO_WDGT_CSS = "https://homologation-payment.payline.com/styles/widget-min.css"; + /** * Widget css in production environment */ const PROD_WDGT_CSS = "https://payment.payline.com/styles/widget-min.css"; - + /** * homologation administration center URL */ const HOMO_CA = 'https://homologation-admin.payline.com'; /** - * administration center URL + * administration center URL */ const PROD_CA = 'https://admin.payline.com'; @@ -293,7 +327,7 @@ class PaylineSDK * array containing private data */ private $privateData; - + /** * array containing parent-child nodes associations */ @@ -315,7 +349,7 @@ class PaylineSDK 'PaymentMeansTrans' => 'PaymentMeansTransHist', 'AlertsTrans' => 'AlertsTransHist' ); - + /** * PaylineSDK class constructor * @@ -338,7 +372,7 @@ class PaylineSDK * @param int $logLevel * Monolog\Logger log level. Default : Logger::INFO * @param Monolog\Logger $externalLogger - * Monolog\Logger instance, used by PaylineSDK but external to it + * Monolog\Logger instance, used by PaylineSDK but external to it */ public function __construct($merchant_id, $access_key, $proxy_host, $proxy_port, $proxy_login, $proxy_password, $environment, $pathLog = null, $logLevel = Logger::INFO, $externalLogger = null, $defaultTimezone = "Europe/Paris") { @@ -346,19 +380,20 @@ public function __construct($merchant_id, $access_key, $proxy_host, $proxy_port, $merchant_id = (string) $merchant_id; } - date_default_timezone_set($defaultTimezone); if ($externalLogger) { $this->logger = $externalLogger; } else { $this->logger = new Logger('PaylineSDK'); } + + $logfileDate = (new \DateTime('now', new \DateTimeZone($defaultTimezone)))->format('Y-m-d'); if (is_null($pathLog)) { - $this->logger->pushHandler(new StreamHandler(realpath(dirname(dirname(dirname(__FILE__)))) . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . date('Y-m-d') . '.log', $logLevel)); // set default log folder + $this->logger->pushHandler(new StreamHandler(realpath(dirname(dirname(__DIR__))) . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . $logfileDate . '.log', $logLevel)); // set default log folder } elseif (strlen($pathLog) > 0) { - $this->logger->pushHandler(new StreamHandler($pathLog . date('Y-m-d') . '.log', $logLevel)); // set custom log folder + $this->logger->pushHandler(new StreamHandler($pathLog . $logfileDate . '.log', $logLevel)); // set custom log folder } - $this->logger->addInfo('__construct', array( + $this->logger->info('__construct', array( 'merchant_id' => $this->hideChars($merchant_id, 6, 1), 'access_key' => $this->hideChars($access_key, 1, 3), 'proxy_host' => $proxy_host, @@ -377,19 +412,19 @@ public function __construct($merchant_id, $access_key, $proxy_host, $proxy_port, $this->soapclient_options['proxy_password'] = $proxy_password; } $plnInternal = false; - if (strcmp($environment, PaylineSDK::ENV_HOMO) == 0) { - $this->webServicesEndpoint = PaylineSDK::HOMO_ENDPOINT; - } elseif (strcmp($environment, PaylineSDK::ENV_HOMO_CC) == 0) { - $this->webServicesEndpoint = PaylineSDK::HOMO_CC_ENDPOINT; - } elseif (strcmp($environment, PaylineSDK::ENV_PROD) == 0) { - $this->webServicesEndpoint = PaylineSDK::PROD_ENDPOINT; - } elseif (strcmp($environment, PaylineSDK::ENV_PROD_CC) == 0) { - $this->webServicesEndpoint = PaylineSDK::PROD_CC_ENDPOINT; - } elseif (strcmp($environment, PaylineSDK::ENV_DEV) == 0) { - $this->webServicesEndpoint = PaylineSDK::DEV_ENDPOINT; + if (strcmp($environment, self::ENV_HOMO) == 0) { + $this->webServicesEndpoint = self::HOMO_ENDPOINT; + } elseif (strcmp($environment, self::ENV_HOMO_CC) == 0) { + $this->webServicesEndpoint = self::HOMO_CC_ENDPOINT; + } elseif (strcmp($environment, self::ENV_PROD) == 0) { + $this->webServicesEndpoint = self::PROD_ENDPOINT; + } elseif (strcmp($environment, self::ENV_PROD_CC) == 0) { + $this->webServicesEndpoint = self::PROD_CC_ENDPOINT; + } elseif (strcmp($environment, self::ENV_DEV) == 0) { + $this->webServicesEndpoint = self::DEV_ENDPOINT; $plnInternal = true; - } elseif (strcmp($environment, PaylineSDK::ENV_INT) == 0) { - $this->webServicesEndpoint = PaylineSDK::INT_ENDPOINT; + } elseif (strcmp($environment, self::ENV_INT) == 0) { + $this->webServicesEndpoint = self::INT_ENDPOINT; $plnInternal = true; } else { $this->webServicesEndpoint = false; // Exception is raised in PaylineSDK::webServiceRequest @@ -397,6 +432,8 @@ public function __construct($merchant_id, $access_key, $proxy_host, $proxy_port, $this->soapclient_options['style'] = defined('SOAP_DOCUMENT') ? SOAP_DOCUMENT : 2; $this->soapclient_options['use'] = defined('SOAP_LITERAL') ? SOAP_LITERAL : 2; $this->soapclient_options['connection_timeout'] = 5; + $this->soapclient_options['trace'] = false; + $this->soapclient_options['soap_client'] = false; if($plnInternal){ $this->soapclient_options['stream_context'] = stream_context_create( array( @@ -409,8 +446,26 @@ public function __construct($merchant_id, $access_key, $proxy_host, $proxy_port, } $this->orderDetails = array(); $this->privateData = array(); - - ini_set('user_agent', "PHP\r\nversion: " . PaylineSDK::SDK_RELEASE); + + ini_set('user_agent', "PHP\r\nversion: " . self::SDK_RELEASE); + } + + + /** + * reset OrderDetails + */ + public function resetOrderDetails() + { + $this->orderDetails = array(); + } + + + /** + * reset Private Data + */ + public function resetPrivateData() + { + $this->privateData = array(); } /** @@ -422,17 +477,9 @@ public function __construct($merchant_id, $access_key, $proxy_host, $proxy_port, */ protected function payment(array $array) { - $payment = new Payment(); - if ($array) { - foreach ($array as $k => $v) { - if (array_key_exists($k, $payment) && (strlen($v))) { - $payment->$k = $v; - } - } - } - return new \SoapVar($payment, SOAP_ENC_OBJECT, PaylineSDK::SOAP_PAYMENT, PaylineSDK::PAYLINE_NAMESPACE); + return $this->buildSoapObject($array, new Payment(), self::SOAP_PAYMENT); } - + /** * build PaymentData instance from $array and make SoapVar object for payment * @@ -442,15 +489,7 @@ protected function payment(array $array) */ protected function paymentData(array $array) { - $paymentData = new PaymentData(); - if ($array) { - foreach ($array as $k => $v) { - if (array_key_exists($k, $paymentData) && (strlen($v))) { - $paymentData->$k = $v; - } - } - } - return new \SoapVar($paymentData, SOAP_ENC_OBJECT, PaylineSDK::SOAP_PAYMENT_DATA, PaylineSDK::PAYLINE_NAMESPACE); + return $this->buildSoapObject($array, new PaymentData(), self::SOAP_PAYMENT_DATA); } /** @@ -472,7 +511,7 @@ protected function order(array $array) } // insert orderDetails $order->details = $this->orderDetails; - return new \SoapVar($order, SOAP_ENC_OBJECT, PaylineSDK::SOAP_ORDER, PaylineSDK::PAYLINE_NAMESPACE); + return new \SoapVar($order, SOAP_ENC_OBJECT, self::SOAP_ORDER, self::PAYLINE_NAMESPACE); } /** @@ -496,7 +535,7 @@ protected function card(array $array) if (isset($array['paymentData'])) { $card->paymentData = $this->paymentData($array['paymentData']); } - return new \SoapVar($card, SOAP_ENC_OBJECT, PaylineSDK::SOAP_CARD, PaylineSDK::PAYLINE_NAMESPACE); + return new \SoapVar($card, SOAP_ENC_OBJECT, self::SOAP_CARD, self::PAYLINE_NAMESPACE); } /** @@ -508,9 +547,11 @@ protected function card(array $array) * the array keys are listed in Address CLASS. * @param array $billingAddress * the array keys are listed in Address CLASS. + * @param array $merchantAuthentication + * the array keys are listed in MerchantAuthentication CLASS. * @return SoapVar representation of Buyer instance */ - protected function buyer(array $array,array $shippingAdress,array $billingAddress) + protected function buyer(array $array, array $shippingAdress, array $billingAddress, array $merchantAuthentication) { $buyer = new Buyer(); if ($array) { @@ -522,7 +563,8 @@ protected function buyer(array $array,array $shippingAdress,array $billingAddres } $buyer->shippingAdress = $this->address($shippingAdress); $buyer->billingAddress = $this->address($billingAddress); - return new \SoapVar($buyer, SOAP_ENC_OBJECT, PaylineSDK::SOAP_BUYER, PaylineSDK::PAYLINE_NAMESPACE); + $buyer->merchantAuthentication = $this->merchantAuthentication($merchantAuthentication); + return new \SoapVar($buyer, SOAP_ENC_OBJECT, self::SOAP_BUYER, self::PAYLINE_NAMESPACE); } /** @@ -534,15 +576,7 @@ protected function buyer(array $array,array $shippingAdress,array $billingAddres */ protected function address(array $array) { - $address = new Address(); - if ($array) { - foreach ($array as $k => $v) { - if (array_key_exists($k, $address) && (strlen($v))) { - $address->$k = $v; - } - } - } - return new \SoapVar($address, SOAP_ENC_OBJECT, PaylineSDK::SOAP_ADDRESS, PaylineSDK::PAYLINE_NAMESPACE); + return $this->buildSoapObject($array, new Address(), self::SOAP_ADDRESS); } /** @@ -554,15 +588,7 @@ protected function address(array $array) */ protected function addressOwner(array $array) { - $addressOwner = new AddressOwner(); - if ($array) { - foreach ($array as $k => $v) { - if (array_key_exists($k, $addressOwner) && (strlen($v))) { - $addressOwner->$k = $v; - } - } - } - return new \SoapVar($addressOwner, SOAP_ENC_OBJECT, PaylineSDK::SOAP_ADDRESS_OWNER, PaylineSDK::PAYLINE_NAMESPACE); + return $this->buildSoapObject($array, new AddressOwner(), self::SOAP_ADDRESS_OWNER); } /** @@ -573,7 +599,7 @@ protected function addressOwner(array $array) * @param array $addressOwner * the array keys are listed in AddressOwner CLASS. * @return SoapVar representation of Owner instance - * + * */ protected function owner(array $array, array $addressOwner) { @@ -587,7 +613,7 @@ protected function owner(array $array, array $addressOwner) } } $owner->billingAddress = $this->addressOwner($addressOwner); - return new \SoapVar($owner, SOAP_ENC_OBJECT, PaylineSDK::SOAP_OWNER, PaylineSDK::PAYLINE_NAMESPACE); + return new \SoapVar($owner, SOAP_ENC_OBJECT, self::SOAP_OWNER, self::PAYLINE_NAMESPACE); } else { return null; } @@ -602,15 +628,7 @@ protected function owner(array $array, array $addressOwner) */ protected function authentication3DSecure(array $array) { - $authentication3DSecure = new Authentication3DSecure(); - if ($array) { - foreach ($array as $k => $v) { - if (array_key_exists($k, $authentication3DSecure) && (strlen($v))) { - $authentication3DSecure->$k = $v; - } - } - } - return new \SoapVar($authentication3DSecure, SOAP_ENC_OBJECT, PaylineSDK::SOAP_AUTHENTICATION_3DSECURE, PaylineSDK::PAYLINE_NAMESPACE); + return $this->buildSoapObject($array, new Authentication3DSecure(), self::SOAP_AUTHENTICATION_3DSECURE); } /** @@ -622,15 +640,7 @@ protected function authentication3DSecure(array $array) */ protected function bankAccountData(array $array) { - $bankAccountData = new BankAccountData($array); - if ($array) { - foreach ($array as $k => $v) { - if (array_key_exists($k, $bankAccountData) && (strlen($v))) { - $bankAccountData->$k = $v; - } - } - } - return new \SoapVar($bankAccountData, SOAP_ENC_OBJECT, PaylineSDK::SOAP_BANK_ACCOUNT_DATA, PaylineSDK::PAYLINE_NAMESPACE); + return $this->buildSoapObject($array, new BankAccountData(), self::SOAP_BANK_ACCOUNT_DATA); } /** @@ -642,15 +652,7 @@ protected function bankAccountData(array $array) */ protected function billingRecordForUpdate(array $array) { - $billingRecordForUpdate = new BillingRecordForUpdate(); - if ($array) { - foreach ($array as $k => $v) { - if (array_key_exists($k, $billingRecordForUpdate) && (strlen($v))) { - $billingRecordForUpdate->$k = $v; - } - } - } - return new \SoapVar($billingRecordForUpdate, SOAP_ENC_OBJECT, PaylineSDK::SOAP_BILLING_RECORD_FOR_UPDATE, PaylineSDK::PAYLINE_NAMESPACE); + return $this->buildSoapObject($array, new BillingRecordForUpdate(), self::SOAP_BILLING_RECORD_FOR_UPDATE); } /** @@ -674,11 +676,10 @@ protected function wallet(array $inWallet, array $address, array $card) } } } - + $wallet->shippingAddress = $this->address($address); $wallet->card = $this->card($card); - - return $wallet; + return new \SoapVar($wallet, SOAP_ENC_OBJECT, self::SOAP_WALLET, self::PAYLINE_NAMESPACE); } /** @@ -687,19 +688,12 @@ protected function wallet(array $inWallet, array $address, array $card) * @param array $array * the array keys are listed in Authorization CLASS. * @return SoapVar representation of Authorization instance - * + * */ protected function authorization(array $array) { - $authorization = new Authorization($array); - if ($array) { - foreach ($array as $k => $v) { - if (array_key_exists($k, $authorization) && (strlen($v))) { - $authorization->$k = $v; - } - } - } - return new \SoapVar($authorization, SOAP_ENC_OBJECT, PaylineSDK::SOAP_AUTHORIZATION, PaylineSDK::PAYLINE_NAMESPACE); + return $this->buildSoapObject($array, new Authorization(), self::SOAP_AUTHORIZATION); + } /** @@ -711,15 +705,7 @@ protected function authorization(array $array) */ protected function creditor(array $array) { - $creditor = new Creditor(); - if ($array) { - foreach ($array as $k => $v) { - if (array_key_exists($k, $creditor) && (strlen($v))) { - $creditor->$k = $v; - } - } - } - return new \SoapVar($creditor, SOAP_ENC_OBJECT, PaylineSDK::SOAP_CREDITOR, PaylineSDK::PAYLINE_NAMESPACE); + return $this->buildSoapObject($array, new Creditor(), self::SOAP_CREDITOR); } /** @@ -731,17 +717,9 @@ protected function creditor(array $array) */ protected function cheque(array $array) { - $cheque = new Cheque($array); - if ($array) { - foreach ($array as $k => $v) { - if (array_key_exists($k, $cheque) && (strlen($v))) { - $cheque->$k = $v; - } - } - } - return new \SoapVar($cheque, SOAP_ENC_OBJECT, PaylineSDK::SOAP_CHEQUE, PaylineSDK::PAYLINE_NAMESPACE); + return $this->buildSoapObject($array, new Cheque(), self::SOAP_CHEQUE); } - + /** * build Recurring instance from $array and make SoapVar object for recurring * @@ -751,15 +729,77 @@ protected function cheque(array $array) */ protected function recurring(array $array) { - $recurring = new Recurring(); + return $this->buildSoapObject($array, new Recurring(), self::SOAP_RECURRING); + } + + /** + * build SubMerchant instance from $array and make SoapVar object for subMerchant + * + * @param array $array + * the array keys are listed in SubMerchant CLASS. + * @return SoapVar representation of SubMerchant instance + */ + protected function subMerchant(array $array) + { + return $this->buildSoapObject($array, new SubMerchant(), self::SOAP_SUBMERCHANT); + } + + /** + * build ThreeDSInfo instance froù $array and make SoapVar object for threeDSInfo + * + * @param array $array + * the array keys liste in ThreeDSInfo CLASS. + * @param array $arrayBrowser + * the array keys liste in Browser CLASS. + * @param array $arraySdk + * the array keys liste in Sdk CLASS. + * @return SoapVar representation of ThreeDSInfo instance + */ + protected function threeDSInfo(array $array, array $arrayBrowser, array $arraySdk) { + $threeDSInfo = new ThreeDSInfo(); if ($array) { foreach ($array as $k => $v) { - if (array_key_exists($k, $recurring) && (strlen($v))) { - $recurring->$k = $v; + if (array_key_exists($k, $array) && (strlen($v))) { + $threeDSInfo->$k = $v; } } } - return new \SoapVar($recurring, SOAP_ENC_OBJECT, PaylineSDK::SOAP_RECURRING, PaylineSDK::PAYLINE_NAMESPACE); + $threeDSInfo->sdk = $this->sdk($arraySdk); + $threeDSInfo->browser = $this->browser($arrayBrowser); + return new \SoapVar($threeDSInfo, SOAP_ENC_OBJECT, self::SOAP_THREEDSINFO, self::PAYLINE_NAMESPACE); + } + + /** + * build Browser instance from $array and make SoapVar object for browser + * + * @param array $array + * the array keys list in Browser CLASS. + * @return SoapVar representation of Browser instance + */ + protected function browser(array $array) { + return $this->buildSoapObject($array, new Browser(), self::SOAP_BROWSER); + } + + /** + * build MerchantAuthentication instance from $array and make SoapVar object for merchantAuthentication + * + * @param array $array + * the array keys list in MerchantAuthentication CLASS. + * @return SoapVar representation of MerchantAuthentication instance + */ + protected function merchantAuthentication(array $array) { + return $this->buildSoapObject($array, new MerchantAuthentication(), self::SOAP_MERCHANT_AUTHENTICATION); + } + + /** + * build Sdk instance from $array and make SoapVar object for sdk + * + * @param array $array + * the array keys list in Sdk CLASS. + * @return SoapVar representation of Sdk instance + */ + protected function sdk(array $array) { + return $this->buildSoapObject($array, new Sdk(), self::SOAP_SDK); } /** @@ -783,7 +823,7 @@ protected function hideChars($inString, $n1, $n2) $outString .= substr($inString, - ($n2)); return $outString; } - + /** * * @param String $nodeName name of a node in a web service response @@ -798,7 +838,7 @@ protected function isChildFromList($nodeName,$parentName){ } return false; } - + /** * make an array from a payline server response object. * @@ -813,7 +853,7 @@ protected function responseToArray($node, $parent = null) $array = array(); foreach ($node as $k => $v) { if ($this->isChildFromList($k, $parent)) { // current value is a list - if (count($v) == 1 && $k != '0') { // a list with 1 element. It's returned with a 0-index + if (!($v instanceof \Countable) && count($v) == 1 && $k != '0') { // a list with 1 element. It's returned with a 0-index $array[$k][0] = PaylineSDK::responseToArray($v, $k); } elseif (is_object($v) || is_array($v)) { // a list with more than 1 element $array[$k] = PaylineSDK::responseToArray($v, $k); @@ -830,7 +870,7 @@ protected function responseToArray($node, $parent = null) } return $array; } - + /** * Adds indexes with empty values to the web services request array, in order to prevent SOAP format exception * @@ -905,8 +945,29 @@ private static function formatRequest(&$array) if (!isset($array['merchantName'])) { $array['merchantName'] = null; } + if (!isset($array['miscData'])) { + $array['miscData'] = null; + } + if (!isset($array['subMerchant'])) { + $array['subMerchant'] = array(); + } + if (!isset($array['asynchronousRetryTimeout'])) { + $array['asynchronousRetryTimeout'] = null; + } + if (!isset($array['merchantAuthentication'])) { + $array['merchantAuthentication'] = array(); + } + if (!isset($array['browser'])) { + $array['browser'] = array(); + } + if (!isset($array['sdk'])) { + $array['sdk'] = array(); + } + if (!isset($array['threeDSInfo'])) { + $array['threeDSInfo'] = array(); + } } - + /** * Create the SoapClient instance and make the web service call * @@ -929,15 +990,19 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI if(!$this->webServicesEndpoint){ throw new \Exception('Endpoint error (check `environment` parameter of PaylineSDK constructor)'); } - $client = new SoapClient(dirname(__FILE__) . '/' . PaylineSDK::WSDL, $this->soapclient_options); + if ($this->soapclient_options['soap_client'] instanceof \SoapClient) { + $client = $this->soapclient_options['soap_client']; + } else { + $client = new SoapClient(__DIR__ . '/' . self::WSDL, $this->soapclient_options); + } $client->__setLocation($this->webServicesEndpoint . $PaylineAPI); - + $WSRequest['version'] = isset($array['version']) && strlen($array['version']) ? $array['version'] : ''; $WSRequest['media'] = isset($array['media']) && strlen($array['media']) ? $array['media'] : ''; - + switch ($Method) { case 'createMerchant': - $response = PaylineSDK::responseToArray($client->createMerchant($WSRequest)); + $response = self::responseToArray($client->createMerchant($WSRequest)); break; case 'createWallet': $logRequest = array( @@ -945,14 +1010,14 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'walletId' => $array['wallet']['walletId'], 'card.number' => $this->hideChars($array['card']['number'], 4, 4) ); - $response = PaylineSDK::responseToArray($client->createWallet($WSRequest)); + $response = self::responseToArray($client->createWallet($WSRequest)); break; case 'createWebWallet': $logRequest = array( 'contractNumber' => $array['contractNumber'], 'walletId' => $array['buyer']['walletId'] ); - $response = PaylineSDK::responseToArray($client->createWebWallet($WSRequest)); + $response = self::responseToArray($client->createWebWallet($WSRequest)); if ($response['result']['code'] == '00000') { $logResponse['token'] = $response['token']; } @@ -970,7 +1035,7 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'paymentRecordId' => $array['paymentRecordId'], 'billingRecordId' => $array['billingRecordId'] ); - $response = PaylineSDK::responseToArray($client->getBillingRecord($WSRequest)); + $response = self::responseToArray($client->getBillingRecord($WSRequest)); break; case 'updateBillingRecord': $logRequest = array( @@ -978,21 +1043,21 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'paymentRecordId' => $array['paymentRecordId'], 'billingRecordId' => $array['billingRecordId'] ); - $response = PaylineSDK::responseToArray($client->updateBillingRecord($WSRequest)); + $response = self::responseToArray($client->updateBillingRecord($WSRequest)); break; case 'disablePaymentRecord': $logRequest = array( 'contractNumber' => $array['contractNumber'], 'paymentRecordId' => $array['paymentRecordId'] ); - $response = PaylineSDK::responseToArray($client->disablePaymentRecord($WSRequest)); + $response = self::responseToArray($client->disablePaymentRecord($WSRequest)); break; case 'disableWallet': $logRequest = array( 'contractNumber' => $array['contractNumber'], 'walletIdList' => implode(';', $array['walletIds']) ); - $response = PaylineSDK::responseToArray($client->disableWallet($WSRequest)); + $response = self::responseToArray($client->disableWallet($WSRequest)); break; case 'doAuthorization': $logRequest = array( @@ -1000,7 +1065,7 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'payment.contractNumber' => $array['payment']['contractNumber'], 'payment.amount' => $array['payment']['amount'] ); - $response = PaylineSDK::responseToArray($client->doAuthorization($WSRequest)); + $response = self::responseToArray($client->doAuthorization($WSRequest)); $logResponse['transaction.id'] = $response['transaction']['id']; break; case 'doCapture': @@ -1008,7 +1073,7 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'transactionID' => $array['transactionID'], 'payment.amount' => $array['payment']['amount'] ); - $response = PaylineSDK::responseToArray($client->doCapture($WSRequest)); + $response = self::responseToArray($client->doCapture($WSRequest)); $logResponse['transaction.id'] = $response['transaction']['id']; break; case 'doCredit': @@ -1017,7 +1082,7 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'order.ref' => $array['order']['ref'], 'card.number' => $this->hideChars($array['card']['number'], 4, 4) ); - $response = PaylineSDK::responseToArray($client->doCredit($WSRequest)); + $response = self::responseToArray($client->doCredit($WSRequest)); $logResponse['transaction.id'] = $response['transaction']['id']; break; case 'doDebit': @@ -1026,7 +1091,7 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'order.ref' => $array['order']['ref'], 'card.number' => $this->hideChars($array['card']['number'], 4, 4) ); - $response = PaylineSDK::responseToArray($client->doDebit($WSRequest)); + $response = self::responseToArray($client->doDebit($WSRequest)); $logResponse['transaction.id'] = $response['transaction']['id']; break; case 'doImmediateWalletPayment': @@ -1035,7 +1100,7 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'walletId' => $array['walletId'], 'order.ref' => $array['order']['ref'] ); - $response = PaylineSDK::responseToArray($client->doImmediateWalletPayment($WSRequest)); + $response = self::responseToArray($client->doImmediateWalletPayment($WSRequest)); $logResponse['transaction.id'] = $response['transaction']['id']; break; case 'doReAuthorization': @@ -1043,7 +1108,7 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'transactionID' => $array['transactionID'], 'amount' => $array['payment']['amount'] ); - $response = PaylineSDK::responseToArray($client->doReAuthorization($WSRequest)); + $response = self::responseToArray($client->doReAuthorization($WSRequest)); $logResponse['transaction.id'] = $response['transaction']['id']; break; case 'doRecurrentWalletPayment': @@ -1052,7 +1117,7 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'walletId' => $array['walletId'], 'order.ref' => $array['order']['ref'] ); - $response = PaylineSDK::responseToArray($client->doRecurrentWalletPayment($WSRequest)); + $response = self::responseToArray($client->doRecurrentWalletPayment($WSRequest)); if ($response['result']['code'] == '02500') { $logResponse['paymentRecordId'] = $response['paymentRecordId']; } @@ -1062,14 +1127,14 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'transactionID' => $array['transactionID'], 'payment.amount' => $array['payment']['amount'] ); - $response = PaylineSDK::responseToArray($client->doRefund($WSRequest)); + $response = self::responseToArray($client->doRefund($WSRequest)); $logResponse['transaction.id'] = $response['transaction']['id']; break; case 'doReset': $logRequest = array( 'transactionID' => $array['transactionID'] ); - $response = PaylineSDK::responseToArray($client->doReset($WSRequest)); + $response = self::responseToArray($client->doReset($WSRequest)); $logResponse['transaction.id'] = $response['transaction']['id']; break; case 'doScheduledWalletPayment': @@ -1078,19 +1143,19 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'walletId' => $array['walletId'], 'order.ref' => $array['order']['ref'] ); - $response = PaylineSDK::responseToArray($client->doScheduledWalletPayment($WSRequest)); + $response = self::responseToArray($client->doScheduledWalletPayment($WSRequest)); if ($response['result']['code'] == '02500') { $logResponse['paymentRecordId'] = $response['paymentRecordId']; } break; case 'doScoringCheque': - $response = PaylineSDK::responseToArray($client->doScoringCheque($WSRequest)); + $response = self::responseToArray($client->doScoringCheque($WSRequest)); break; case 'doWebPayment': $logRequest = array( 'order.ref' => $array['order']['ref'] ); - $response = PaylineSDK::responseToArray($client->doWebPayment($WSRequest)); + $response = self::responseToArray($client->doWebPayment($WSRequest)); if ($response['result']['code'] == '00000') { $logResponse['token'] = $response['token']; } @@ -1099,21 +1164,21 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI $logRequest = array( 'walletId' => $array['walletId'] ); - $response = PaylineSDK::responseToArray($client->enableWallet($WSRequest)); + $response = self::responseToArray($client->enableWallet($WSRequest)); break; case 'getAlertDetails': $logRequest = array( 'alertId' => $array['AlertId'], 'transactionId' => $array['TransactionId'] ); - $response = PaylineSDK::responseToArray($client->getAlertDetails($WSRequest)); + $response = self::responseToArray($client->getAlertDetails($WSRequest)); break; case 'getBalance': $logRequest = array( 'contractNumber' => $array['contractNumber'], 'cardID' => $this->hideChars($array['cardID'], 4, 4) ); - $response = PaylineSDK::responseToArray($client->getBalance($WSRequest)); + $response = self::responseToArray($client->getBalance($WSRequest)); break; case 'getCards': $logRequest = array( @@ -1121,27 +1186,27 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'walletId' => $array['walletId'], 'cardInd' => $array['cardInd'] ); - $response = PaylineSDK::responseToArray($client->getCards($WSRequest)); + $response = self::responseToArray($client->getCards($WSRequest)); break; case 'getEncryptionKey': - $response = PaylineSDK::responseToArray($client->getEncryptionKey($WSRequest)); + $response = self::responseToArray($client->getEncryptionKey($WSRequest)); break; case 'getMerchantSettings': - $response = PaylineSDK::responseToArray($client->getMerchantSettings($WSRequest)); + $response = self::responseToArray($client->getMerchantSettings($WSRequest)); break; case 'getPaymentRecord': $logRequest = array( 'contractNumber' => $array['contractNumber'], 'paymentRecordId' => $array['paymentRecordId'] ); - $response = PaylineSDK::responseToArray($client->getPaymentRecord($WSRequest)); + $response = self::responseToArray($client->getPaymentRecord($WSRequest)); break; case 'getToken': $logRequest = array( 'contractNumber' => $array['contractNumber'], 'cardNumber' => $this->hideChars($array['cardNumber'], 4, 4) ); - $response = PaylineSDK::responseToArray($client->getToken($WSRequest)); + $response = self::responseToArray($client->getToken($WSRequest)); if ($response['result']['code'] == '02500') { $logResponse['token'] = $response['token']; } @@ -1150,7 +1215,7 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI $logRequest = array( 'transactionId' => $array['transactionId'] ); - $response = PaylineSDK::responseToArray($client->getTransactionDetails($WSRequest)); + $response = self::responseToArray($client->getTransactionDetails($WSRequest)); break; case 'getWallet': $logRequest = array( @@ -1158,13 +1223,13 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'walletId' => $array['walletId'], 'cardInd' => $array['cardInd'] ); - $response = PaylineSDK::responseToArray($client->getWallet($WSRequest)); + $response = self::responseToArray($client->getWallet($WSRequest)); break; case 'getWebPaymentDetails': $logRequest = array( 'token' => $array['token'] ); - $response = PaylineSDK::responseToArray($client->getWebPaymentDetails($WSRequest)); + $response = self::responseToArray($client->getWebPaymentDetails($WSRequest)); if (isset($response['transaction']['id'])) { $logResponse['transaction.id'] = $response['transaction']['id']; } @@ -1173,7 +1238,7 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI $logRequest = array( 'token' => $array['token'] ); - $response = PaylineSDK::responseToArray($client->getWebWallet($WSRequest)); + $response = self::responseToArray($client->getWebWallet($WSRequest)); if (isset($response['wallet']['card'])) { $logResponse['wallet.card.number'] = $this->hideChars($response['wallet']['card']['number'], 4, 4); } @@ -1183,7 +1248,7 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'contractNumber' => $array['contractNumber'], 'buyer.walletId' => $array['buyer']['walletId'] ); - $response = PaylineSDK::responseToArray($client->manageWebWallet($WSRequest)); + $response = self::responseToArray($client->manageWebWallet($WSRequest)); if ($response['result']['code'] == '00000') { $logResponse['token'] = $response['token']; } @@ -1195,25 +1260,25 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI $logRequest[$key] = $value; } } - $response = PaylineSDK::responseToArray($client->transactionsSearch($WSRequest)); + $response = self::responseToArray($client->transactionsSearch($WSRequest)); break; case 'unBlock': $logRequest = array( 'transactionID' => $array['transactionID'] ); - $response = PaylineSDK::responseToArray($client->unBlock($WSRequest)); + $response = self::responseToArray($client->unBlock($WSRequest)); break; case 'updateWallet': $logRequest = array( 'walletId' => $array['wallet']['walletId'] ); - $response = PaylineSDK::responseToArray($client->updateWallet($WSRequest)); + $response = self::responseToArray($client->updateWallet($WSRequest)); break; case 'updateWebWallet': $logRequest = array( 'walletId' => $array['walletId'] ); - $response = PaylineSDK::responseToArray($client->updateWebWallet($WSRequest)); + $response = self::responseToArray($client->updateWebWallet($WSRequest)); if ($response['result']['code'] == '00000') { $logResponse['token'] = $response['token']; } @@ -1223,14 +1288,14 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'contractNumber' => $array['contractNumber'], 'card.number' => $this->hideChars($array['card']['number'], 4, 4) ); - $response = PaylineSDK::responseToArray($client->verifyAuthentication($WSRequest)); + $response = self::responseToArray($client->verifyAuthentication($WSRequest)); break; case 'verifyEnrollment': $logRequest = array( 'payment.contractNumber' => $array['payment']['contractNumber'], 'card.number' => $this->hideChars($array['card']['number'], 4, 4) ); - $response = PaylineSDK::responseToArray($client->verifyEnrollment($WSRequest)); + $response = self::responseToArray($client->verifyEnrollment($WSRequest)); break; case 'doBankTransfer': $logRequest = array( @@ -1238,25 +1303,39 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI 'creditor.bic' => $this->hideChars($array['creditor']['bic'], 4, 1), 'creditor.iban' => $this->hideChars($array['creditor']['iban'], 8, 1) ); - $response = PaylineSDK::responseToArray($client->doBankTransfer($WSRequest)); + $response = self::responseToArray($client->doBankTransfer($WSRequest)); $logResponse['transaction.id'] = $response['transaction']['id']; break; + case 'isRegistered': + $logRequest = array( + 'order.ref' => $array['order']['ref'], + 'payment.contractNumber' => $array['payment']['contractNumber'] + ); + $response = self::responseToArray($client->isRegistered($WSRequest)); + $logResponse['token'] = $response['token']; + break; } $logResponse['result.code'] = $response['result']['code']; - $this->logger->addInfo($Method . 'Request', $logRequest); - $this->logger->addInfo($Method . 'Response', $logResponse); + $this->logger->info($Method . 'Request', $logRequest); + $this->logger->info($Method . 'Response', $logResponse); + if ($this->soapclient_options['trace'] === true) { + $this->logger->debug($Method . ' Last Request ' . $client->__getLastRequest()); + $this->logger->debug($Method . ' Last Request Headers ' . $client->__getLastRequestHeaders()); + $this->logger->debug($Method . ' Last Response ' . $client->__getLastResponse()); + $this->logger->debug($Method . ' Last Response Headers ' . $client->__getLastResponseHeaders()); + } return $response; } catch (\Exception $e) { - $this->logger->addInfo($Method . 'Request', $logRequest); - $this->logger->addError('Exception occured at ' . $Method . ' call', array( + $this->logger->info($Method . 'Request', $logRequest); + $this->logger->error('Exception occured at ' . $Method . ' call', array( 'code' => $e->getCode(), 'message' => $e->getMessage(), 'endpoint' => $this->webServicesEndpoint . $PaylineAPI )); $ERROR = array(); - $ERROR['result']['code'] = PaylineSDK::ERR_CODE; + $ERROR['result']['code'] = self::ERR_CODE; $ERROR['result']['longMessage'] = $e->getMessage(); - $ERROR['result']['shortMessage'] = PaylineSDK::ERR_SHORT_MESSAGE; + $ERROR['result']['shortMessage'] = self::ERR_SHORT_MESSAGE; $ERROR['result']['partnerCode'] = null; $ERROR['result']['partnerCodeLabel'] = null; return $ERROR; @@ -1273,7 +1352,7 @@ protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI public function usedBy($toolName) { $this->usedBy = $toolName; - ini_set('user_agent', "PHP\r\nversion: " . $toolName . ' - ' . PaylineSDK::SDK_RELEASE); + ini_set('user_agent', "PHP\r\nversion: " . $toolName . ' - ' . self::SDK_RELEASE); } /** @@ -1300,7 +1379,7 @@ public function addOrderDetail(array $newOrderDetail) } } } - $this->orderDetails[] = new \SoapVar($orderDetail, SOAP_ENC_OBJECT, PaylineSDK::SOAP_ORDERDETAIL, PaylineSDK::PAYLINE_NAMESPACE); + $this->orderDetails[] = new \SoapVar($orderDetail, SOAP_ENC_OBJECT, self::SOAP_ORDERDETAIL, self::PAYLINE_NAMESPACE); } /** @@ -1308,7 +1387,7 @@ public function addOrderDetail(array $newOrderDetail) * * @param array $array * an array containing two indexes : key and value - * + * */ public function addPrivateData(array $array) { @@ -1320,7 +1399,7 @@ public function addPrivateData(array $array) } } } - $this->privateData[] = new \SoapVar($private, SOAP_ENC_OBJECT, PaylineSDK::SOAP_PRIVATE_DATA, PaylineSDK::PAYLINE_NAMESPACE); + $this->privateData[] = new \SoapVar($private, SOAP_ENC_OBJECT, self::SOAP_PRIVATE_DATA, self::PAYLINE_NAMESPACE); } /* @@ -1330,7 +1409,7 @@ public function addPrivateData(array $array) * * ************************************************************************* */ - + /** * calls doAuthorization web service * @@ -1341,16 +1420,25 @@ public function doAuthorization(array $array) { $this->formatRequest($array); $WSRequest = array( - 'payment' => $this->payment($array['payment']), - 'card' => $this->card($array['card']), - 'order' => $this->order($array['order']), - 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress']), - 'owner' => $this->owner($array['owner'], $array['ownerAddress']), - 'privateDataList' => $this->privateData, - 'authentication3DSecure' => $this->authentication3DSecure($array['3DSecure']), - 'bankAccountData' => $this->bankAccountData($array['bankAccountData']) + 'payment' => $this->payment($array['payment']), + 'card' => $this->card($array['card']), + 'order' => $this->order($array['order']), + 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']), + 'owner' => $this->owner($array['owner'], $array['ownerAddress']), + 'privateDataList' => $this->privateData, + 'authentication3DSecure' => $this->authentication3DSecure($array['3DSecure']), + 'bankAccountData' => $this->bankAccountData($array['bankAccountData']), + 'subMerchant' => $this->subMerchant($array['subMerchant']), + 'asynchronousRetryTimeout' => $array['asynchronousRetryTimeout'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'doAuthorization'); + + if (isset($array['payment']['mode'])) { + if (($array['payment']['mode'] == "REC") || ($array['payment']['mode'] == "NX")) { + $WSRequest['recurring'] = $this->recurring($array['recurring']); + } + } + + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doAuthorization'); } /** @@ -1367,7 +1455,7 @@ public function doCapture(array $array) 'privateDataList' => $this->privateData, 'sequenceNumber' => $array['sequenceNumber'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'doCapture'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doCapture'); } /** @@ -1384,7 +1472,7 @@ public function doReAuthorization(array $array) 'order' => $this->order($array['order']), 'privateDataList' => $this->privateData ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'doReAuthorization'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doReAuthorization'); } /** @@ -1401,11 +1489,12 @@ public function doDebit(array $array) 'card' => $this->card($array['card']), 'order' => $this->order($array['order']), 'privateDataList' => $this->privateData, - 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress']), + 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']), 'authentication3DSecure' => $this->authentication3DSecure($array['3DSecure']), - 'authorization' => $this->authorization($array['authorization']) + 'authorization' => $this->authorization($array['authorization']), + 'subMerchant' => $this->subMerchant($array['subMerchant']) ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'doDebit'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doDebit'); } /** @@ -1424,7 +1513,7 @@ public function doRefund($array) 'details' => $this->orderDetails, 'sequenceNumber' => $array['sequenceNumber'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'doRefund'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doRefund'); } /** @@ -1439,7 +1528,7 @@ public function doReset(array $array) 'transactionID' => $array['transactionID'], 'comment' => $array['comment'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'doReset'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doReset'); } /** @@ -1454,12 +1543,13 @@ public function doCredit(array $array) $WSRequest = array( 'payment' => $this->payment($array['payment']), 'card' => $this->card($array['card']), - 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress']), + 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']), 'privateDataList' => $this->privateData, 'order' => $this->order($array['order']), - 'comment' => $array['comment'] + 'comment' => $array['comment'], + 'subMerchant' => $this->subMerchant($array['subMerchant']) ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'doCredit'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doCredit'); } /** @@ -1474,13 +1564,13 @@ public function createWallet(array $array) $WSRequest = array( 'contractNumber' => $array['contractNumber'], 'wallet' => $this->wallet($array['wallet'], $array['address'], $array['card']), - 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress']), + 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']), 'owner' => $this->owner($array['owner'], $array['ownerAddress']), 'privateDataList' => $this->privateData, 'authentication3DSecure' => $this->authentication3DSecure($array['3DSecure']), 'contractNumberWalletList' => $array['walletContracts'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'createWallet'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'createWallet'); } /** @@ -1495,13 +1585,13 @@ public function updateWallet(array $array) 'contractNumber' => $array['contractNumber'], 'cardInd' => $array['cardInd'], 'wallet' => $this->wallet($array['wallet'], $array['address'], $array['card']), - 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress']), + 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']), 'owner' => $this->owner($array['owner'], $array['ownerAddress']), 'privateDataList' => $this->privateData, 'authentication3DSecure' => $this->authentication3DSecure($array['3DSecure']), 'contractNumberWalletList' => $array['walletContracts'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'updateWallet'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'updateWallet'); } /** @@ -1517,7 +1607,7 @@ public function getWallet(array $array) 'walletId' => $array['walletId'], 'cardInd' => $array['cardInd'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'getWallet'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getWallet'); } /** @@ -1533,7 +1623,7 @@ public function getCards(array $array) 'walletId' => $array['walletId'], 'cardInd' => $array['cardInd'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'getCards'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getCards'); } /** @@ -1549,7 +1639,7 @@ public function disableWallet(array $array) 'walletIdList' => $array['walletIds'], 'cardInd' => $array['cardInd'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'disableWallet'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'disableWallet'); } /** @@ -1565,7 +1655,7 @@ public function enableWallet(array $array) 'walletId' => $array['walletId'], 'cardInd' => $array['cardInd'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'enableWallet'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'enableWallet'); } /** @@ -1580,14 +1670,15 @@ public function doImmediateWalletPayment(array $array) $WSRequest = array( 'payment' => $this->payment($array['payment']), 'order' => $this->order($array['order']), - 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress']), + 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']), 'walletId' => $array['walletId'], 'cardInd' => $array['cardInd'], 'cvx' => $array['walletCvx'], 'privateDataList' => $this->privateData, - 'authentication3DSecure' => $this->authentication3DSecure($array['3DSecure']) + 'authentication3DSecure' => $this->authentication3DSecure($array['3DSecure']), + 'subMerchant' => $this->subMerchant($array['subMerchant']) ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'doImmediateWalletPayment'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doImmediateWalletPayment'); } /** @@ -1607,9 +1698,10 @@ public function doScheduledWalletPayment(array $array) 'walletId' => $array['walletId'], 'cardInd' => $array['cardInd'], 'order' => $this->order($array['order']), - 'privateDataList' => $this->privateData + 'privateDataList' => $this->privateData, + 'subMerchant' => $this->subMerchant($array['subMerchant']) ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'doScheduledWalletPayment'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doScheduledWalletPayment'); } /** @@ -1632,7 +1724,7 @@ public function doRecurrentWalletPayment(array $array) 'privateDataList' => $this->privateData, 'order' => $this->order($array['order']) ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'doRecurrentWalletPayment'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doRecurrentWalletPayment'); } /** @@ -1647,7 +1739,7 @@ public function getPaymentRecord(array $array) 'contractNumber' => $array['contractNumber'], 'paymentRecordId' => $array['paymentRecordId'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'getPaymentRecord'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getPaymentRecord'); } /** @@ -1662,7 +1754,7 @@ public function disablePaymentRecord(array $array) 'contractNumber' => $array['contractNumber'], 'paymentRecordId' => $array['paymentRecordId'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'disablePaymentRecord'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'disablePaymentRecord'); } /** @@ -1674,20 +1766,37 @@ public function disablePaymentRecord(array $array) public function verifyEnrollment(array $array) { $this->formatRequest($array); + $order = array_key_exists('order', $array) ? $this->order($array['order']) : null; + $buyer = array_key_exists('buyer', $array) ? $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']) : null; + $subMerchant = array_key_exists('subMerchant', $array) ? $this->subMerchant($array['subMerchant']) : null; + $threeDSInfo = array_key_exists('threeDSInfo', $array) ? $this->threeDSInfo($array['threeDSInfo'], $array['browser'], $array['sdk']) : null; + $merchantScore = array_key_exists('merchantScore', $array) ? $array['merchantScore'] : null; $WSRequest = array( - 'payment' => $this->payment($array['payment']), - 'card' => $this->card($array['card']), - 'orderRef' => $array['orderRef'], - 'userAgent' => $array['userAgent'], - 'mdFieldValue' => $array['mdFieldValue'], - 'walletId' => $array['walletId'], - 'walletCardInd' => $array['walletCardInd'], - 'merchantName' => $array['merchantName'] + 'payment' => $this->payment($array['payment']), + 'card' => $this->card($array['card']), + 'orderRef' => $array['orderRef'], + 'userAgent' => $array['userAgent'], + 'mdFieldValue' => $array['mdFieldValue'], + 'walletId' => $array['walletId'], + 'walletCardInd' => $array['walletCardInd'], + 'merchantName' => $array['merchantName'], + 'returnURL' => $array['returnURL'], + 'order' => $order, + 'buyer' => $buyer, + 'subMerchant' => $subMerchant, + 'privateDataList' => $this->privateData, + 'merchantScore' => $merchantScore, + 'threeDSInfo' => $threeDSInfo ); if (isset($array['generateVirtualCvx'])) { $WSRequest['generateVirtualCvx'] = $array['generateVirtualCvx']; } - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'verifyEnrollment'); + if (isset($array['payment']['mode'])) { + if (($array['payment']['mode'] == "REC") || ($array['payment']['mode'] == "NX")) { + $WSRequest['recurring'] = $this->recurring($array['recurring']); + } + } + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'verifyEnrollment'); } /** @@ -1699,12 +1808,13 @@ public function verifyEnrollment(array $array) public function verifyAuthentication(array $array) { $WSRequest = array( - 'contractNumber' => $array['contractNumber'], - 'pares' => $array['pares'], - 'md' => $array['md'], - 'card' => $this->card($array['card']) + 'contractNumber' => $array['contractNumber'], + 'pares' => $array['pares'], + 'md' => $array['md'], + 'card' => $this->card($array['card']), + 'privateDataList' => $this->privateData ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'verifyAuthentication'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'verifyAuthentication'); } /** @@ -1721,7 +1831,7 @@ public function doScoringCheque(array $array) 'order' => $this->order($array['order']), 'privateDataList' => $this->privateData ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'doScoringCheque'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doScoringCheque'); } /** @@ -1733,7 +1843,7 @@ public function doScoringCheque(array $array) public function getEncryptionKey(array $array) { $WSRequest = array(); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'getEncryptionKey'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getEncryptionKey'); } /** @@ -1745,7 +1855,7 @@ public function getEncryptionKey(array $array) public function getMerchantSettings(array $array) { $WSRequest = array(); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'getMerchantSettings'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getMerchantSettings'); } /** @@ -1760,7 +1870,7 @@ public function getBalance(array $array) 'contractNumber' => $array['contractNumber'], 'cardID' => $array['cardID'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'getBalance'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getBalance'); } /** @@ -1776,7 +1886,7 @@ public function getToken(array $array) 'expirationDate' => $array['expirationDate'], 'contractNumber' => $array['contractNumber'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'getToken'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getToken'); } /** @@ -1791,7 +1901,7 @@ public function unBlock(array $array) 'transactionID' => $array['transactionID'], 'transactionDate' => $array['transactionDate'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'unBlock'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'unBlock'); } /** @@ -1807,7 +1917,7 @@ public function updatePaymentRecord(array $array) 'paymentRecordId' => $array['paymentRecordId'], 'recurring' => $this->recurring($array['recurring']) ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'updatePaymentRecord'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'updatePaymentRecord'); } /** @@ -1823,7 +1933,7 @@ public function getBillingRecord(array $array) 'paymentRecordId' => $array['paymentRecordId'], 'billingRecordId' => $array['billingRecordId'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'getBillingRecord'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getBillingRecord'); } /** @@ -1840,7 +1950,7 @@ public function updateBillingRecord(array $array) 'billingRecordId' => $array['billingRecordId'], 'billingRecordForUpdate' => $this->billingRecordForUpdate($array['billingRecordForUpdate']) ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'updateBillingRecord'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'updateBillingRecord'); } /** @@ -1849,7 +1959,7 @@ public function updateBillingRecord(array $array) * @param array $array * associative array containing doBankTransfer parameters */ - public function doBankTransfer(array $array) + public function doBankTransfer(array $array) { $this->formatRequest($array); $WSRequest = array( @@ -1859,7 +1969,26 @@ public function doBankTransfer(array $array) 'transactionID' => $array['transactionID'], 'orderID' => $array['orderID'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::DIRECT_API, 'doBankTransfer'); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doBankTransfer'); + } + + /** + * calls isRegistered web service + * + * @param array $array + * associative array containing isRegistered parameters + */ + public function isRegistered(array $array) + { + $this->formatRequest($array); + $WSRequest = array( + 'payment' => $this->payment($array['payment']), + 'order' => $this->order($array['order']), + 'privateDataList' => $this->privateData, + 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']), + 'miscData' => $array['miscData'] + ); + return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'isRegistered'); } /* @@ -1869,14 +1998,14 @@ public function doBankTransfer(array $array) * * ************************************************************************* */ - + /** * calls doWebPayment web service * * @param array $array * associative array containing doWebPayment parameters */ - public function doWebPayment(array $array) + public function doWebPayment(array $array) { $this->formatRequest($array); $WSRequest = array( @@ -1891,11 +2020,15 @@ public function doWebPayment(array $array) 'privateDataList' => $this->privateData, 'languageCode' => $array['languageCode'], 'customPaymentPageCode' => $array['customPaymentPageCode'], - 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress']), + 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']), 'owner' => $this->owner($array['owner'], $array['ownerAddress']), 'securityMode' => $array['securityMode'], 'contractNumberWalletList' => $array['walletContracts'], - 'merchantName' => $array['merchantName'] + 'merchantName' => $array['merchantName'], + 'subMerchant' => $this->subMerchant($array['subMerchant']), + 'miscData' => $array['miscData'], + 'asynchronousRetryTimeout' => $array['asynchronousRetryTimeout'], + 'threeDSInfo' => $this->threeDSInfo($array['threeDSInfo'], $array['browser'], $array['sdk']) ); if (isset($array['payment']['mode'])) { @@ -1903,7 +2036,41 @@ public function doWebPayment(array $array) $WSRequest['recurring'] = $this->recurring($array['recurring']); } } - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::WEB_API, 'doWebPayment'); + return $this->webServiceRequest($array, $WSRequest, self::WEB_API, 'doWebPayment'); + } + + /** + * calls doAuthorizationRedirectRequest web service + * + * @param array $array + * associative array containing doAuthorizationRedirectRequest parameters + */ + public function doAuthorizationRedirectRequest(array $array) + { + $this->formatRequest($array); + $WSRequest = array( + 'payment' => $this->payment($array['payment']), + 'returnURL' => $array['returnURL'], + 'cancelURL' => $array['cancelURL'], + 'order' => $this->order($array['order']), + 'notificationURL' => $array['notificationURL'], + 'privateDataList' => $this->privateData, + 'languageCode' => $array['languageCode'], + 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']), + 'owner' => $this->owner($array['owner'], $array['ownerAddress']), + 'securityMode' => $array['securityMode'], + 'merchantName' => $array['merchantName'], + 'subMerchant' => $this->subMerchant($array['subMerchant']), + 'miscData' => $array['miscData'], + 'asynchronousRetryTimeout' => $array['asynchronousRetryTimeout'] + ); + + if (isset($array['payment']['mode'])) { + if (($array['payment']['mode'] == "REC") || ($array['payment']['mode'] == "NX")) { + $WSRequest['recurring'] = $this->recurring($array['recurring']); + } + } + return $this->webServiceRequest($array, $WSRequest, self::WEB_API, 'doWebPayment'); } /** @@ -1914,7 +2081,7 @@ public function doWebPayment(array $array) */ public function getWebPaymentDetails(array $array) { - return $this->webServiceRequest($array, $array, PaylineSDK::WEB_API, 'getWebPaymentDetails'); + return $this->webServiceRequest($array, $array, self::WEB_API, 'getWebPaymentDetails'); } /** @@ -1923,14 +2090,14 @@ public function getWebPaymentDetails(array $array) * @param array $array * associative array containing manageWebWallet parameters */ - public function manageWebWallet(array $array) + public function manageWebWallet(array $array) { $this->formatRequest($array); $WSRequest = array( 'contractNumber' => $array['contractNumber'], 'selectedContractList' => $array['contracts'], 'updatePersonalDetails' => $array['updatePersonalDetails'], - 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress']), + 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']), 'owner' => $this->owner($array['owner'], $array['ownerAddress']), 'languageCode' => $array['languageCode'], 'customPaymentPageCode' => $array['customPaymentPageCode'], @@ -1941,9 +2108,10 @@ public function manageWebWallet(array $array) 'privateDataList' => $this->privateData, 'customPaymentTemplateURL' => $array['customPaymentTemplateURL'], 'contractNumberWalletList' => $array['walletContracts'], - 'merchantName' => $array['merchantName'] + 'merchantName' => $array['merchantName'], + 'threeDSInfo' => $this->threeDSInfo($array['threeDSInfo'], $array['browser'], $array['sdk']) ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::WEB_API, 'manageWebWallet'); + return $this->webServiceRequest($array, $WSRequest, self::WEB_API, 'manageWebWallet'); } /** @@ -1959,7 +2127,7 @@ public function createWebWallet(array $array) 'contractNumber' => $array['contractNumber'], 'selectedContractList' => $array['contracts'], 'updatePersonalDetails' => $array['updatePersonalDetails'], - 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress']), + 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']), 'languageCode' => $array['languageCode'], 'customPaymentPageCode' => $array['customPaymentPageCode'], 'securityMode' => $array['securityMode'], @@ -1970,7 +2138,7 @@ public function createWebWallet(array $array) 'customPaymentTemplateURL' => $array['customPaymentTemplateURL'], 'contractNumberWalletList' => $array['walletContracts'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::WEB_API, 'createWebWallet'); + return $this->webServiceRequest($array, $WSRequest, self::WEB_API, 'createWebWallet'); } /** @@ -1979,7 +2147,7 @@ public function createWebWallet(array $array) * @param array $array * associative array containing updateWebWallet parameters */ - public function updateWebWallet(array $array) + public function updateWebWallet(array $array) { $this->formatRequest($array); $WSRequest = array( @@ -1989,7 +2157,7 @@ public function updateWebWallet(array $array) 'updatePersonalDetails' => $array['updatePersonalDetails'], 'updateOwnerDetails' => $array['updateOwnerDetails'], 'updatePaymentDetails' => $array['updatePaymentDetails'], - 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress']), + 'buyer' => $this->buyer($array['buyer'], $array['shippingAddress'], $array['billingAddress'], $array['merchantAuthentication']), 'languageCode' => $array['languageCode'], 'customPaymentPageCode' => $array['customPaymentPageCode'], 'securityMode' => $array['securityMode'], @@ -2000,7 +2168,7 @@ public function updateWebWallet(array $array) 'customPaymentTemplateURL' => $array['customPaymentTemplateURL'], 'contractNumberWalletList' => $array['walletContracts'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::WEB_API, 'updateWebWallet'); + return $this->webServiceRequest($array, $WSRequest, self::WEB_API, 'updateWebWallet'); } /** @@ -2011,7 +2179,7 @@ public function updateWebWallet(array $array) */ public function getWebWallet(array $array) { - return $this->webServiceRequest($array, $array, PaylineSDK::WEB_API, 'getWebWallet'); + return $this->webServiceRequest($array, $array, self::WEB_API, 'getWebWallet'); } /* @@ -2021,14 +2189,14 @@ public function getWebWallet(array $array) * * ************************************************************************* */ - + /** * calls getTransactionDetails web service * * @param array $array * associative array containing getWebWallet parameters */ - public function getTransactionDetails(array $array) + public function getTransactionDetails(array $array) { $this->formatRequest($array); $WSRequest = array( @@ -2039,7 +2207,7 @@ public function getTransactionDetails(array $array) 'transactionHistory' => $array['transactionHistory'], 'archiveSearch' => $array['archiveSearch'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::EXTENDED_API, 'getTransactionDetails'); + return $this->webServiceRequest($array, $WSRequest, self::EXTENDED_API, 'getTransactionDetails'); } /** @@ -2048,7 +2216,7 @@ public function getTransactionDetails(array $array) * @param array $array * associative array containing getWebWallet parameters */ - public function transactionsSearch(array $array) + public function transactionsSearch(array $array) { $WSRequest = array( 'transactionId' => $array['transactionId'], @@ -2071,7 +2239,7 @@ public function transactionsSearch(array $array) 'sequenceNumber' => $array['sequenceNumber'], 'token' => $array['token'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::EXTENDED_API, 'transactionsSearch'); + return $this->webServiceRequest($array, $WSRequest, self::EXTENDED_API, 'transactionsSearch'); } /** @@ -2086,7 +2254,7 @@ public function getAlertDetails(array $array) { 'TransactionId' => $array['TransactionId'], 'TransactionDate' => $array['TransactionDate'] ); - return $this->webServiceRequest($array, $WSRequest, PaylineSDK::EXTENDED_API, 'getAlertDetails'); + return $this->webServiceRequest($array, $WSRequest, self::EXTENDED_API, 'getAlertDetails'); } /* @@ -2096,7 +2264,7 @@ public function getAlertDetails(array $array) { * * ************************************************************************ */ - + /** * Custom base64 url encoding. * Replace unsafe url chars @@ -2134,12 +2302,24 @@ public function base64_url_decode($input) * merchant access key (SHA256 encrypted) * @return string encrypted message */ - public function getEncrypt($message, $accessKey) + public function getEncrypt($message, $accessKey) { - $block = mcrypt_get_block_size('rijndael_128', 'ecb'); - $pad = $block - (strlen($message) % $block); - $message .= str_repeat(chr($pad), $pad); - return $this->base64_url_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $accessKey, $message, MCRYPT_MODE_ECB)); + $cipher = "AES-256-ECB"; + $opts = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING; + + $pad = 16; + $len = strlen($message); + + $padlen = $len + $pad - $len % $pad; + $message = str_pad( + $message, + $padlen, + chr($padlen - $len) + ); + + $encrypted = openssl_encrypt($message, $cipher, $accessKey, $opts); + + return $this->base64_url_encode($encrypted); } /** @@ -2152,13 +2332,15 @@ public function getEncrypt($message, $accessKey) */ public function getDecrypt($message, $accessKey) { + $cipher = "AES-256-ECB"; + $opts = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING; + $message = $this->base64_url_decode($message); - $message = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $accessKey, $message, MCRYPT_MODE_ECB); - $pad = ord($message[($len = strlen($message)) - 1]); - $len = strlen($message); - $pad = ord($message[$len - 1]); - $return = substr($message, 0, strlen($message) - $pad); - return $return; + $decrypted = openssl_decrypt($message, $cipher, $accessKey, $opts); + $len = strlen($decrypted); + $pad = ord($decrypted[$len - 1]); + + return substr($decrypted, 0, strlen($decrypted) - $pad); } /** @@ -2166,9 +2348,9 @@ public function getDecrypt($message, $accessKey) * * @param string $data * decrypted message sent by getToken servlet - * @param string $filename - * @param string $error - * @param unknown $maxlength + * @param string $filename + * @param string $error + * @param unknown $maxlength * @return NULL|boolean|string */ public function gzdecode($data, &$filename = '', &$error = '', $maxlength = null) @@ -2276,4 +2458,22 @@ public function gzdecode($data, &$filename = '', &$error = '', $maxlength = null } return $data; } + + /** + * @param array $array + * @param $object + * @param $typeName + * @return SoapVar + */ + protected function buildSoapObject(array $array, $object, $typeName) + { + if ($array) { + foreach ($array as $k => $v) { + if (array_key_exists($k, $object) && (strlen($v))) { + $object->$k = $v; + } + } + } + return new \SoapVar($object, SOAP_ENC_OBJECT, $typeName, self::PAYLINE_NAMESPACE); + } } diff --git a/lib/monext/payline-sdk/src/Payline/Payment.php b/lib/monext/payline-sdk/src/Payline/Payment.php index b5b6cdc..d123fa9 100644 --- a/lib/monext/payline-sdk/src/Payline/Payment.php +++ b/lib/monext/payline-sdk/src/Payline/Payment.php @@ -29,4 +29,8 @@ class Payment public $softDescriptor; public $cardBrand; -} \ No newline at end of file + + public $registrationToken; + + public $cumulatedAmount; +} diff --git a/lib/monext/payline-sdk/src/Payline/Recurring.php b/lib/monext/payline-sdk/src/Payline/Recurring.php index 03c75b3..47b1708 100644 --- a/lib/monext/payline-sdk/src/Payline/Recurring.php +++ b/lib/monext/payline-sdk/src/Payline/Recurring.php @@ -25,4 +25,10 @@ class Recurring public $startDate; public $endDate; -} \ No newline at end of file + + public $newAmount; + + public $amountModificationDate; + + public $billingRank; +} diff --git a/lib/monext/payline-sdk/src/Payline/Sdk.php b/lib/monext/payline-sdk/src/Payline/Sdk.php new file mode 100644 index 0000000..f310c13 --- /dev/null +++ b/lib/monext/payline-sdk/src/Payline/Sdk.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Payline; +class Sdk { + public $deviceRenderingOptionsIF; + + public $deviceRenderOptionsUI; + + public $appID; + + public $ephemPubKey; + + public $maxTimeout; + + public $referenceNumber; + + public $transID; +} diff --git a/lib/monext/payline-sdk/src/Payline/SubMerchant.php b/lib/monext/payline-sdk/src/Payline/SubMerchant.php new file mode 100644 index 0000000..8e591b9 --- /dev/null +++ b/lib/monext/payline-sdk/src/Payline/SubMerchant.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Payline; + +class SubMerchant +{ + + public $subMerchantId; + + public $subMerchantName; + + public $subMerchantMCC; + + public $subMerchantSIRET; + + public $subMerchantTaxCode; + + public $subMerchantStreet; + + public $subMerchantCity; + + public $subMerchantZipCode; + + public $subMerchantCountry; + + public $subMerchantState; + + public $subMerchantEmailAddress; + + public $subMerchantPhoneNumber; +} \ No newline at end of file diff --git a/lib/monext/payline-sdk/src/Payline/ThreeDSInfo.php b/lib/monext/payline-sdk/src/Payline/ThreeDSInfo.php new file mode 100644 index 0000000..2fe9518 --- /dev/null +++ b/lib/monext/payline-sdk/src/Payline/ThreeDSInfo.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Payline; + +class ThreeDSInfo { + public $challengeInd; + + public $threeDSReqPriorAuthData; + + public $threeDSReqPriorAuthMethod; + + public $threeDSReqPriorAuthTimestamp; + + public $browser; + + public $sdk; + + public $threeDSMethodNotificationURL; + + public $threeDSMethodResult; +} + diff --git a/lib/monext/payline-sdk/src/Payline/v4.52.wsdl b/lib/monext/payline-sdk/src/Payline/v4.52.wsdl deleted file mode 100644 index 7c8a69f..0000000 --- a/lib/monext/payline-sdk/src/Payline/v4.52.wsdl +++ /dev/null @@ -1,3408 +0,0 @@ - - - - - - - - - - This element is the request for the - doWebPayment - method - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This element is the reponse from the - doWebPayment - method - - - - - - - - - - - - - - - - - This element is the reponse from the - getWebPayment - method - - - - - - - - - - - - - This element is the reponse from the - doWebPayment - method - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This element is the request for the - doAuthorization - method - - - - - - - - - - - - - - - - - - - - - This element is the reponse from the - doAuthorization method - - - - - - - - - - - - - - - - - - This element is the request for the - doCapture method - - - - - - - - - - - - - - - - - This element is the reponse from the - doCapture - method - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This element is the request for the doRefund - method - - - - - - - - - - - - - - - - - - - This element is the reponse from the - doRefund method - - - - - - - - - - - - - This element is the request for the doReset - method - - - - - - - - - - - - - - - This element is the reponse from the doReset - method - - - - - - - - - - - - - This element is the request for the doCredit - method - - - - - - - - - - - - - - - - - - - - This element is the reponse from the - doCredit method - - - - - - - - - - - - - - - This element is the request for the - createWallet - method - - - - - - - - - - - - - - - - - - - - This element is the reponse from the - createWallet - method - - - - - - - - - - - - - - - - This element is the request for the - updateWallet - method - - - - - - - - - - - - - - - - - - - - - This element is the reponse from the - updateWallet - method - - - - - - - - - - - - - - - This element is the request for the - getWallet method - - - - - - - - - - - - - - - - This element is the reponse from the - getWallet - method - - - - - - - - - - - - - - - - - - - - This element is the request for the - getCards method - - - - - - - - - - - - - - - This element is the reponse from the - getCards method - - - - - - - - - - - - - - - This element is the request for the - disableWallet - method - - - - - - - - - - - - - - This element is the reponse from the - disableWallet - method - - - - - - - - - - - - - This element is the request for the - enableWallet - method - - - - - - - - - - - - - - This element is the reponse from the - enableWallet - method - - - - - - - - - - - - This element is the request for the - doImmediateWalletPayment method - - - - - - - - - - - - - - - - - - - - - This element is the reponse from the - doImmediateWalletPayment method - - - - - - - - - - - - - - This element is the request for the - doScheduledWalletPayment method - - - - - - - - - - - - - - - - - - - - - This element is the reponse from the - doScheduledWalletPayment method - - - - - - - - - - - - - This element is the request for the - doRecurrentWalletPayment method - - - - - - - - - - - - - - - - - - - - - - This element is the reponse from the - doRecurrentWalletPayment method - - - - - - - - - - - - - - This element is the request for the - getPaymentRecord method - - - - - - - - - - - - - - This element is the reponse from the - getPaymentRecord method - - - - - - - - - - - - - - - - - - - This element is the request for the - disablePaymentRecord method - - - - - - - - - - - - - This element is the reponse from the - disablePaymentRecord method - - - - - - - - - - - - This element is the request for the - manageWebWallet - method - - - - - - - - - - - - - - - - - - - - - - - - - - - This element is the reponse from the - manageWebWallet method - - - - - - - - - - - - - - This element is the request for the - createWebWallet - method - - - - - - - - - - - - - - - - - - - - - - - - - - This element is the reponse from the - createWebWallet method - - - - - - - - - - - - - - This element is the request for the - updateWebWallet - method - - - - - - - - - - - - - - - - - - - - - - - - - - - - This element is the reponse from the - updateWebWallet method - - - - - - - - - - - - - - This element is the request for the - getWebWallet - method - - - - - - - - - - - - - This element is the reponse from the - getWebWallet - method - - - - - - - - - - - - - - - - - - - This element is the request for the - getTransactionDetails method - - - - - - - - - - - - - - - - - - This element is the response for the - getTransactionDetails method - - - - - - - - - - - - - - - - - - - - - - - - - - This element is the request for the - transactionsSearch method - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This element is the response for the - transactionsSearch method - - - - - - - - - - - - - This element is the request for the - verifyEnrollment method - - - - - - - - - - - - - - - - - - - - - This element is the reponse from the - verifyEnrollment method - - - - - - - - - - - - - - - - - - - - - - - - This element is the request for the - doAuthentication method - - - - - - - - - - - - - - - - This element is the reponse from the - doAuthentication method - - - - - - - - - - - - - - This element is the request for the - doScoringCheque - method - - - - - - - - - - - - - - - - - This element is the reponse from the - doScoringCheque method - - - - - - - - - - - - - - This element is the request for the - getEncryptionKeyRequest method - - - - - - - - - This element is the reponse from the - getEncryptionKeyResponse method - - - - - - - - - - - - - This element is the request for the - doReAuthorization method - - - - - - - - - - - - - - - - - This element is the reponse from the - doReAuthorization method - - - - - - - - - - - - - - - This element is the request for the - getMerchantSettings method - - - - - - - - - - - - This element is the response from the - getMerchantSettings method - - - - - - - - - - - - - - - - - - - This element is the request for the - getBalance - method - - - - - - - - - - - - - - This element is the reponse from the - getBalance - method - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This element is the request for the doBankTransfer - method - - - - - - - - - - - - - - - - - This element is the reponse from the - doBankTransfer method - - - - - - - - - - - - - - - - This element contains information about the - process - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This element contains information about the - order - - - - - - - - - - - - - - - - - - - - - This element contains information about the - encryptionKey - - - - - - - - - - - - - This element contains an array of orderDetail - - - - - - - - - - - This element contains information about the - order - product - - - - - - - - - - - - - - - - - - - This element contains information about the - merchant - private data - - - - - - - - - - - This element contains information about the - transaction - - - - - - - - - - - - - - - - - - - - - - - This element contains information about the - fraud - result details - - - - - - - - - - - - This element contains information about the - payment - - - - - - - - - - - - - - - - - - This element contains information about the - authorization - - - - - - - - - - - This element contains information about the paymentData - - - - - - - - - - - - This element contains information about the card - - - - - - - - - - - - - - - - - - - - - This element contains information about the - buyer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This element contains information about the - owner - - - - - - - - - - - - - This element contains information about the - address - - - - - - - - - - - - - - - - - - - - - - This element contains information about the - address - - - - - - - - - - - - - - This element contains information about the - capture - - - - - - - - - - - This element contains information about the - refund - - - - - - - - - - - This element contains the list of selected card - - - - - - - - - - An array of private data - - - - - - - - - - This element contains the result of the address verification service - - - - - - - - - - - An array of contract number of a wallet - - - - - - - - - - An array of cards - - - - - - - - - - This element contains element for recurring - operation - - - - - - - - - - - - - - - - - - This element contains element for update a recurring - operation - - - - - - - - - - - - - - This element contains element for a billing - record - - - - - - - - - - - - - - - - - An array of billing record - - - - - - - - - - - This element contains element for update a recurring - operation - - - - - - - - - - - - - - This element contains element for a wallet - - - - - - - - - - - - - - - - - - - This element contains element for a wallet - - - - - - - - - - - - - - - - - - - - - This element contains the list of selected card - - - - - - - - - - This element contains the list of selected card - - - - - - - - - - This element contains element for a 3DSecure - transaction - - - - - - - - - - - - - - - - - - - This element contains the merchant connection - parameters - - - - - - - - - - - - - - This element contains the scoring cheque parameters - - - - - - - - - - - - - This element contains information about Interlocutor - address - - - - - - - - - - - - - - - This element contains information about Interlocutor - - - - - - - - - - - - - - - - This element contains IBAN information - - - - - - - - - - - - - This element contains RIB information - - - - - - - - - - - - This element contains bankAccount information - - - - - - - - - - - - - This element contains bank Account information - - - - - - - - - - - - - This element contains technical data used to define - acquirer service - - - - - - - - - - - - This element contains all information about contract - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This element contains all information about - customPaymentPageCode - - - - - - - - - - - - This element contains information e-ticket - - - - - - - - - - - This element contains all information about point of - sell - - - - - - - Merchant Category Code - - - - - - - - - - - - - - - - - - - - list of contract - - - - - - - - - - - list of custom payment page code - - - - - - - - - - - - virtualTerminal - - - - - - http session timeout delay - - - - - path to logo - - - - - list of functions - - - - - - - - - - - - functions availbe in virtual terminal - - - - - - Please refer to Payline documentation - - - - - - - - - - - - - - - Value of parameter - - - - - Parameter ID. Refer to payline documentation - - - - - - - - - - - - This element contains information about the - cheque - - - - - - - - - - This element contains all information about - contrinution - - - - - - - - - - - - - - - This element contains information about the - associated transactions - - - - - - - - - - - - - - - - An array of associatedTransactions - - - - - - - - - - - This element contains information about the - status - History - - - - - - - - - - - - - - - - An array of statusHistory - - - - - - - - - - This element contains information about the - paymentAdditional - - - - - - - - - - - - - - - - An array of paymentAdditionalList - - - - - - - - - - - An array of CustomerTrans - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An array of PaymentMeansTrans - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An array of AlertsTrans - - - - - - - - - - - - - - - - - - - - - - - - - - - - This element contains information about the - creditor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/monext/payline-sdk/src/Payline/v4.59.wsdl b/lib/monext/payline-sdk/src/Payline/v4.59.wsdl new file mode 100644 index 0000000..8a6c1f2 --- /dev/null +++ b/lib/monext/payline-sdk/src/Payline/v4.59.wsdl @@ -0,0 +1,4036 @@ + + + + + + + + + + This element is the request for the + doWebPayment + method + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + doWebPayment + method + + + + + + + + + + + + + + + + + This element is the reponse from the + getWebPayment + method + + + + + + + + + + + + + This element is the reponse from the + doWebPayment + method + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the request for the + doAuthorization + method + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + doAuthorization method + + + + + + + + + + + + + + + + + + + + + This element is the request for the + doCapture method + + + + + + + + + + + + + + + + + This element is the reponse from the + doCapture + method + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the request for the doRefund + method + + + + + + + + + + + + + + + + + + + This element is the reponse from the + doRefund method + + + + + + + + + + + + + This element is the request for the doReset + method + + + + + + + + + + + + + + + This element is the reponse from the doReset + method + + + + + + + + + + + + + This element is the request for the doCredit + method + + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + doCredit method + + + + + + + + + + + + + + + + This element is the request for the + createWallet + method + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + createWallet + method + + + + + + + + + + + + + + + + This element is the request for the + updateWallet + method + + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + updateWallet + method + + + + + + + + + + + + + + + This element is the request for the + getWallet method + + + + + + + + + + + + + + + + This element is the reponse from the + getWallet + method + + + + + + + + + + + + + + + + + + + + This element is the request for the + getCards method + + + + + + + + + + + + + + + This element is the reponse from the + getCards method + + + + + + + + + + + + + + + This element is the request for the + disableWallet + method + + + + + + + + + + + + + + This element is the reponse from the + disableWallet + method + + + + + + + + + + + + + This element is the request for the + enableWallet + method + + + + + + + + + + + + + + This element is the reponse from the + enableWallet + method + + + + + + + + + + + + This element is the request for the + doImmediateWalletPayment method + + + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + doImmediateWalletPayment method + + + + + + + + + + + + + + This element is the request for the + doScheduledWalletPayment method + + + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + doScheduledWalletPayment method + + + + + + + + + + + + + This element is the request for the + doRecurrentWalletPayment method + + + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + doRecurrentWalletPayment method + + + + + + + + + + + + + + This element is the request for the + getPaymentRecord method + + + + + + + + + + + + + + This element is the reponse from the + getPaymentRecord method + + + + + + + + + + + + + + + + + + + This element is the request for the + disablePaymentRecord method + + + + + + + + + + + + + This element is the reponse from the + disablePaymentRecord method + + + + + + + + + + + + This element is the request for the + manageWebWallet + method + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + manageWebWallet method + + + + + + + + + + + + + + This element is the request for the + createWebWallet + method + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + createWebWallet method + + + + + + + + + + + + + + This element is the request for the + updateWebWallet + method + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + updateWebWallet method + + + + + + + + + + + + + + This element is the request for the + getWebWallet + method + + + + + + + + + + + + + This element is the reponse from the + getWebWallet + method + + + + + + + + + + + + + + + + + + + This element is the request for the + doAuthorizationRedirect + method + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + doAuthorizationRedirect + method + + + + + + + + + + + + + This element is the request for the + getTransactionDetails method + + + + + + + + + + + + + + + + + + This element is the response for the + getTransactionDetails method + + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the request for the + transactionsSearch method + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the response for the + transactionsSearch method + + + + + + + + + + + + + This element is the request for the + verifyEnrollment method + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the reponse from the + verifyEnrollment method + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the request for the + doAuthentication method + + + + + + + + + + + + + + + + + + This element is the reponse from the + doAuthentication method + + + + + + + + + + + + + + + + This element is the request for the + createMerchant + method + + + + + + + + currency in ISO 4217 numeric format + + + + + + + + + + + unique national merchant ID + + + + + + Systeme d identification du Repertoire des + ENtreprises + + + + + + + + + + + to use if country is not France + + + + + + + + + Payline Distributor ID + + + + + + + + + list of point of sell + + + + + + + + + + Billing partner. 1:monext, 2:cetib, 3:payline.com + + + + + + + + + + + This element is the reponse from the + createMerchant + method + + + + + + + + + + + + + This element is the request for the + doScoringCheque + method + + + + + + + + + + + + + + + + + This element is the reponse from the + doScoringCheque method + + + + + + + + + + + + + + This element is the request for the + getEncryptionKeyRequest method + + + + + + + + + + + + This element is the reponse from the + getEncryptionKeyResponse method + + + + + + + + + + + + + This element is the request for the + doReAuthorization method + + + + + + + + + + + + + + + + + This element is the reponse from the + doReAuthorization method + + + + + + + + + + + + + + + This element is the request for the + getMerchantSettings method + + + + + + + + + + + + This element is the response from the + getMerchantSettings method + + + + + + + + + + + + + + + + + + + This element is the request for the + getBalance + method + + + + + + + + + + + + + + This element is the reponse from the + getBalance + method + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element is the request for the doBankTransfer + method + + + + + + + + + + + + + + + + + This element is the reponse from the + doBankTransfer method + + + + + + + + + + + + + + This element is the request for the + isRegistered method + + + + + + + + + + + + + + + + + This element is the reponse from the + isRegistered method + + + + + + + + + + + + + + + + This element contains information about the + process + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element contains information about the + order + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element contains information about the + encryptionKey + + + + + + + + + + + + + + + + + This element contains an array of orderDetail + + + + + + + + + + + This element contains information about the + order + product + + + + + + + + + + + + + + + + + + + + + This element contains information about the + merchant + private data + + + + + + + + + + + This element contains information about the + transaction + + + + + + + + + + + + + + + + + + + + + + + + This element contains information about the + scoring + + + + + + + + + + + + + + This element contains information about the + fraud + result details + + + + + + + + + + + + This element contains information about the + payment + + + + + + + + + + + + + + + + + + + + This element contains information about the + authorization + + + + + + + + + + + This element contains information about the paymentData + + + + + + + + + + + + This element contains information about the card + + + + + + + + + + + + + + + + + + + + + This element contains information about the + buyer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element contains information about the + owner + + + + + + + + + + + + + This element contains information about the + address + + + + + + + + + + + + + + + + + + + + + + + + + This element contains information about the + address + + + + + + + + + + + + + + This element contains information about the + capture + + + + + + + + + + + This element contains information about the + refund + + + + + + + + + + + This element contains the list of selected card + + + + + + + + + + An array of private data + + + + + + + + + + + This element contains the result of the address verification service + + + + + + + + + + + + An array of contract number of a wallet + + + + + + + + + + An array of cards + + + + + + + + + + An array of authorization to capture + + + + + + + + + + An array of authorization to refund + + + + + + + + + + An array of authorization to reset + + + + + + + + + + An array of mass element failed + + + + + + + + + + This element contains failedObject + + + + + + + + + + + This element contains element for recurring + operation + + + + + + + + + + + + + + + + + + + This element contains element for update a recurring + operation + + + + + + + + + + + + + + This element contains element for a billing + record + + + + + + + + + + + + + + + + + An array of billing record + + + + + + + + + + + This element contains element for update a recurring + operation + + + + + + + + + + + + + + This element contains element for a wallet + + + + + + + + + + + + + + + + + + + This element contains element for a wallet + + + + + + + + + + + + + + + + + + + + + This element contains the list of selected card + + + + + + + + + + This element contains the list of selected card + + + + + + + + + + This element contains element for a 3DSecure + transaction + + + + + + + + + + + + + + + + + + + + + This element contains the merchant connection + parameters + + + + + + + + + + + + + + This element contains the scoring cheque parameters + + + + + + + + + + + + + This element contains information about Interlocutor + address + + + + + + + + + + + + + + + This element contains information about Interlocutor + + + + + + + + + + + + + + + + An array of subscribed options + + + + + + + + + + + + This element contains information about the payline + package subscribed by the merchant + + + + + + + + + + + This element contains IBAN information + + + + + + + + + + + + + This element contains RIB information + + + + + + + + + + + + This element contains bankAccount information + + + + + + + + + + + + + This element contains bank Account information + + + + + + + + + + + + + This element contains technical data used to define + acquirer service + + + + + + + + + + + + This element contains all information about contract + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element contains all information about + customPaymentPageCode + + + + + + + + + + + + This element contains information e-ticket + + + + + + + + + + + This element contains all information about point of + sell + + + + + + + Merchant Category Code + + + + + + + + + + + + + + + + + + + + list of contract + + + + + + + + + + + list of custom payment page code + + + + + + + + + + + + virtualTerminal + + + + + + http session timeout delay + + + + + path to logo + + + + + list of functions + + + + + + + + + + + + functions availbe in virtual terminal + + + + + + Please refer to Payline documentation + + + + + + + + + + + + + + + Value of parameter + + + + + Parameter ID. Refer to payline documentation + + + + + + + + + + + + This element contains information about the + cheque + + + + + + + + + + This element contains all information about + contrinution + + + + + + + + + + + + + + + This element contains information about the + associated transactions + + + + + + + + + + + + + + + + An array of associatedTransactions + + + + + + + + + + + This element contains information about the + status + History + + + + + + + + + + + + + + + + An array of statusHistory + + + + + + + + + + This element contains information about the + paymentAdditional + + + + + + + + + + + + + + + + An array of paymentAdditionalList + + + + + + + + + + + An array of CustomerTrans + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + An array of PaymentMeansTrans + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + An array of AlertsTrans + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element contains information about the + creditor + + + + + + + + + + + + + This element contains information about a subMerchant associated with a Payment Facilitator + + + + + + + + + + + + + + + + + + + + + This element contains information about 3DS. + + + + + + + + + + + + + + + + + This element contains information about Browser. + + + + + + + + + + + + + + + + + + This element contains information about SDK. + + + + + + + + + + + + + + + + This element contains information about SDK. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/monolog/monolog/CHANGELOG.md b/lib/monolog/monolog/CHANGELOG.md index cd1142d..255297c 100644 --- a/lib/monolog/monolog/CHANGELOG.md +++ b/lib/monolog/monolog/CHANGELOG.md @@ -1,3 +1,65 @@ +### 1.25.3 (2019-12-20) + + * Fixed formatting of resources in JsonFormatter + * Fixed RedisHandler failing to use MULTI properly when passed a proxied Redis instance (e.g. in Symfony with lazy services) + * Fixed FilterHandler triggering a notice when handleBatch was filtering all records passed to it + * Fixed Turkish locale messing up the conversion of level names to their constant values + +### 1.25.2 (2019-11-13) + + * Fixed normalization of Traversables to avoid traversing them as not all of them are rewindable + * Fixed setFormatter/getFormatter to forward to the nested handler in FilterHandler, FingersCrossedHandler, BufferHandler and SamplingHandler + * Fixed BrowserConsoleHandler formatting when using multiple styles + * Fixed normalization of exception codes to be always integers even for PDOException which have them as numeric strings + * Fixed normalization of SoapFault objects containing non-strings as "detail" + * Fixed json encoding across all handlers to always attempt recovery of non-UTF-8 strings instead of failing the whole encoding + +### 1.25.1 (2019-09-06) + + * Fixed forward-compatible interfaces to be compatible with Monolog 1.x too. + +### 1.25.0 (2019-09-06) + + * Deprecated SlackbotHandler, use SlackWebhookHandler or SlackHandler instead + * Deprecated RavenHandler, use sentry/sentry 2.x and their Sentry\Monolog\Handler instead + * Deprecated HipChatHandler, migrate to Slack and use SlackWebhookHandler or SlackHandler instead + * Added forward-compatible interfaces and traits FormattableHandlerInterface, FormattableHandlerTrait, ProcessableHandlerInterface, ProcessableHandlerTrait. If you use modern PHP and want to make code compatible with Monolog 1 and 2 this can help. You will have to require at least Monolog 1.25 though. + * Added support for RFC3164 (outdated BSD syslog protocol) to SyslogUdpHandler + * Fixed issue in GroupHandler and WhatFailureGroupHandler where setting multiple processors would duplicate records + * Fixed issue in SignalHandler restarting syscalls functionality + * Fixed normalizers handling of exception backtraces to avoid serializing arguments in some cases + * Fixed ZendMonitorHandler to work with the latest Zend Server versions + * Fixed ChromePHPHandler to avoid sending more data than latest Chrome versions allow in headers (4KB down from 256KB). + +### 1.24.0 (2018-11-05) + + * BC Notice: If you are extending any of the Monolog's Formatters' `normalize` method, make sure you add the new `$depth = 0` argument to your function signature to avoid strict PHP warnings. + * Added a `ResettableInterface` in order to reset/reset/clear/flush handlers and processors + * Added a `ProcessorInterface` as an optional way to label a class as being a processor (mostly useful for autowiring dependency containers) + * Added a way to log signals being received using Monolog\SignalHandler + * Added ability to customize error handling at the Logger level using Logger::setExceptionHandler + * Added InsightOpsHandler to migrate users of the LogEntriesHandler + * Added protection to NormalizerHandler against circular and very deep structures, it now stops normalizing at a depth of 9 + * Added capture of stack traces to ErrorHandler when logging PHP errors + * Added RavenHandler support for a `contexts` context or extra key to forward that to Sentry's contexts + * Added forwarding of context info to FluentdFormatter + * Added SocketHandler::setChunkSize to override the default chunk size in case you must send large log lines to rsyslog for example + * Added ability to extend/override BrowserConsoleHandler + * Added SlackWebhookHandler::getWebhookUrl and SlackHandler::getToken to enable class extensibility + * Added SwiftMailerHandler::getSubjectFormatter to enable class extensibility + * Dropped official support for HHVM in test builds + * Fixed normalization of exception traces when call_user_func is used to avoid serializing objects and the data they contain + * Fixed naming of fields in Slack handler, all field names are now capitalized in all cases + * Fixed HipChatHandler bug where slack dropped messages randomly + * Fixed normalization of objects in Slack handlers + * Fixed support for PHP7's Throwable in NewRelicHandler + * Fixed race bug when StreamHandler sometimes incorrectly reported it failed to create a directory + * Fixed table row styling issues in HtmlFormatter + * Fixed RavenHandler dropping the message when logging exception + * Fixed WhatFailureGroupHandler skipping processors when using handleBatch + and implement it where possible + * Fixed display of anonymous class names + ### 1.23.0 (2017-06-19) * Improved SyslogUdpHandler's support for RFC5424 and added optional `$ident` argument diff --git a/lib/monolog/monolog/README.md b/lib/monolog/monolog/README.md index 7d8ade5..a578eb2 100644 --- a/lib/monolog/monolog/README.md +++ b/lib/monolog/monolog/README.md @@ -2,7 +2,6 @@ [![Total Downloads](https://img.shields.io/packagist/dt/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog) [![Latest Stable Version](https://img.shields.io/packagist/v/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog) -[![Reference Status](https://www.versioneye.com/php/monolog:monolog/reference_badge.svg)](https://www.versioneye.com/php/monolog:monolog/references) Monolog sends your logs to files, sockets, inboxes, databases and various @@ -91,5 +90,5 @@ Monolog is licensed under the MIT License - see the `LICENSE` file for details ### Acknowledgements -This library is heavily inspired by Python's [Logbook](http://packages.python.org/Logbook/) +This library is heavily inspired by Python's [Logbook](https://logbook.readthedocs.io/en/stable/) library, although most concepts have been adjusted to fit to the PHP world. diff --git a/lib/monolog/monolog/composer.json b/lib/monolog/monolog/composer.json index 3b0c880..097df87 100644 --- a/lib/monolog/monolog/composer.json +++ b/lib/monolog/monolog/composer.json @@ -59,7 +59,7 @@ }, "scripts": { "test": [ - "parallel-lint . --exclude vendor", + "parallel-lint . --exclude vendor --exclude src/Monolog/Handler/FormattableHandlerInterface.php --exclude src/Monolog/Handler/FormattableHandlerTrait.php --exclude src/Monolog/Handler/ProcessableHandlerInterface.php --exclude src/Monolog/Handler/ProcessableHandlerTrait.php", "phpunit" ] } diff --git a/lib/monolog/monolog/src/Monolog/ErrorHandler.php b/lib/monolog/monolog/src/Monolog/ErrorHandler.php index 7bfcd83..adc55bd 100644 --- a/lib/monolog/monolog/src/Monolog/ErrorHandler.php +++ b/lib/monolog/monolog/src/Monolog/ErrorHandler.php @@ -14,6 +14,7 @@ use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use Monolog\Handler\AbstractHandler; +use Monolog\Registry; /** * Monolog error handler @@ -38,6 +39,7 @@ class ErrorHandler private $hasFatalErrorHandler; private $fatalLevel; private $reservedMemory; + private $lastFatalTrace; private static $fatalErrors = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR); public function __construct(LoggerInterface $logger) @@ -132,7 +134,7 @@ public function handleException($e) { $this->logger->log( $this->uncaughtExceptionLevel === null ? LogLevel::ERROR : $this->uncaughtExceptionLevel, - sprintf('Uncaught Exception %s: "%s" at %s line %s', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()), + sprintf('Uncaught Exception %s: "%s" at %s line %s', Utils::getClass($e), $e->getMessage(), $e->getFile(), $e->getLine()), array('exception' => $e) ); @@ -156,6 +158,13 @@ public function handleError($code, $message, $file = '', $line = 0, $context = a if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) { $level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : LogLevel::CRITICAL; $this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line)); + } else { + // http://php.net/manual/en/function.debug-backtrace.php + // As of 5.3.6, DEBUG_BACKTRACE_IGNORE_ARGS option was added. + // Any version less than 5.3.6 must use the DEBUG_BACKTRACE_IGNORE_ARGS constant value '2'. + $trace = debug_backtrace((PHP_VERSION_ID < 50306) ? 2 : DEBUG_BACKTRACE_IGNORE_ARGS); + array_shift($trace); // Exclude handleError from trace + $this->lastFatalTrace = $trace; } if ($this->previousErrorHandler === true) { @@ -177,7 +186,7 @@ public function handleFatalError() $this->logger->log( $this->fatalLevel === null ? LogLevel::ALERT : $this->fatalLevel, 'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'], - array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line']) + array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $this->lastFatalTrace) ); if ($this->logger instanceof Logger) { diff --git a/lib/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php b/lib/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php index 02632bb..f8ead47 100644 --- a/lib/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php +++ b/lib/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php @@ -11,6 +11,8 @@ namespace Monolog\Formatter; +use Monolog\Utils; + /** * Class FluentdFormatter * @@ -62,6 +64,7 @@ public function format(array $record) $message = array( 'message' => $record['message'], + 'context' => $record['context'], 'extra' => $record['extra'], ); @@ -70,7 +73,7 @@ public function format(array $record) $message['level_name'] = $record['level_name']; } - return json_encode(array($tag, $record['datetime']->getTimestamp(), $message)); + return Utils::jsonEncode(array($tag, $record['datetime']->getTimestamp(), $message)); } public function formatBatch(array $records) diff --git a/lib/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php b/lib/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php index 3eec95f..9e8d2d0 100644 --- a/lib/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php +++ b/lib/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php @@ -11,6 +11,7 @@ namespace Monolog\Formatter; use Monolog\Logger; +use Monolog\Utils; /** * Formats incoming records into an HTML table @@ -58,7 +59,7 @@ protected function addRow($th, $td = ' ', $escapeTd = true) $td = '
'.htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8').'
'; } - return "\n$th:\n".$td."\n"; + return "\n$th:\n".$td."\n"; } /** @@ -133,9 +134,9 @@ protected function convertToString($data) $data = $this->normalize($data); if (version_compare(PHP_VERSION, '5.4.0', '>=')) { - return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + return Utils::jsonEncode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE, true); } - return str_replace('\\/', '/', json_encode($data)); + return str_replace('\\/', '/', Utils::jsonEncode($data, null, true)); } } diff --git a/lib/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php b/lib/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php index 0782f14..86966b0 100644 --- a/lib/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php +++ b/lib/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php @@ -12,6 +12,7 @@ namespace Monolog\Formatter; use Exception; +use Monolog\Utils; use Throwable; /** @@ -138,18 +139,23 @@ protected function formatBatchNewlines(array $records) * * @return mixed */ - protected function normalize($data) + protected function normalize($data, $depth = 0) { - if (is_array($data) || $data instanceof \Traversable) { + if ($depth > 9) { + return 'Over 9 levels deep, aborting normalization'; + } + + if (is_array($data)) { $normalized = array(); $count = 1; foreach ($data as $key => $value) { - if ($count++ >= 1000) { - $normalized['...'] = 'Over 1000 items, aborting normalization'; + if ($count++ > 1000) { + $normalized['...'] = 'Over 1000 items ('.count($data).' total), aborting normalization'; break; } - $normalized[$key] = $this->normalize($value); + + $normalized[$key] = $this->normalize($value, $depth+1); } return $normalized; @@ -159,6 +165,10 @@ protected function normalize($data) return $this->normalizeException($data); } + if (is_resource($data)) { + return parent::normalize($data); + } + return $data; } @@ -174,13 +184,13 @@ protected function normalizeException($e) { // TODO 2.0 only check for Throwable if (!$e instanceof Exception && !$e instanceof Throwable) { - throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e)); + throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.Utils::getClass($e)); } $data = array( - 'class' => get_class($e), + 'class' => Utils::getClass($e), 'message' => $e->getMessage(), - 'code' => $e->getCode(), + 'code' => (int) $e->getCode(), 'file' => $e->getFile().':'.$e->getLine(), ); @@ -189,12 +199,6 @@ protected function normalizeException($e) foreach ($trace as $frame) { if (isset($frame['file'])) { $data['trace'][] = $frame['file'].':'.$frame['line']; - } elseif (isset($frame['function']) && $frame['function'] === '{closure}') { - // We should again normalize the frames, because it might contain invalid items - $data['trace'][] = $frame['function']; - } else { - // We should again normalize the frames, because it might contain invalid items - $data['trace'][] = $this->normalize($frame); } } } diff --git a/lib/monolog/monolog/src/Monolog/Formatter/LineFormatter.php b/lib/monolog/monolog/src/Monolog/Formatter/LineFormatter.php index d3e209e..acc1fd3 100644 --- a/lib/monolog/monolog/src/Monolog/Formatter/LineFormatter.php +++ b/lib/monolog/monolog/src/Monolog/Formatter/LineFormatter.php @@ -11,6 +11,8 @@ namespace Monolog\Formatter; +use Monolog\Utils; + /** * Formats incoming records into a one-line string * @@ -129,17 +131,17 @@ protected function normalizeException($e) { // TODO 2.0 only check for Throwable if (!$e instanceof \Exception && !$e instanceof \Throwable) { - throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e)); + throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.Utils::getClass($e)); } $previousText = ''; if ($previous = $e->getPrevious()) { do { - $previousText .= ', '.get_class($previous).'(code: '.$previous->getCode().'): '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine(); + $previousText .= ', '.Utils::getClass($previous).'(code: '.$previous->getCode().'): '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine(); } while ($previous = $previous->getPrevious()); } - $str = '[object] ('.get_class($e).'(code: '.$e->getCode().'): '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')'; + $str = '[object] ('.Utils::getClass($e).'(code: '.$e->getCode().'): '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')'; if ($this->includeStacktraces) { $str .= "\n[stacktrace]\n".$e->getTraceAsString()."\n"; } @@ -161,7 +163,7 @@ protected function convertToString($data) return $this->toJson($data, true); } - return str_replace('\\/', '/', @json_encode($data)); + return str_replace('\\/', '/', $this->toJson($data, true)); } protected function replaceNewlines($str) diff --git a/lib/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php b/lib/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php index eb067bb..bd9e4c0 100644 --- a/lib/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php +++ b/lib/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php @@ -11,6 +11,8 @@ namespace Monolog\Formatter; +use Monolog\Utils; + /** * Formats a record for use with the MongoDBHandler. * @@ -75,7 +77,7 @@ protected function formatArray(array $record, $nestingLevel = 0) protected function formatObject($value, $nestingLevel) { $objectVars = get_object_vars($value); - $objectVars['class'] = get_class($value); + $objectVars['class'] = Utils::getClass($value); return $this->formatArray($objectVars, $nestingLevel); } @@ -83,9 +85,9 @@ protected function formatObject($value, $nestingLevel) protected function formatException(\Exception $exception, $nestingLevel) { $formattedException = array( - 'class' => get_class($exception), + 'class' => Utils::getClass($exception), 'message' => $exception->getMessage(), - 'code' => $exception->getCode(), + 'code' => (int) $exception->getCode(), 'file' => $exception->getFile() . ':' . $exception->getLine(), ); diff --git a/lib/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php b/lib/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php index d441488..61861c8 100644 --- a/lib/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php +++ b/lib/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php @@ -12,6 +12,7 @@ namespace Monolog\Formatter; use Exception; +use Monolog\Utils; /** * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets @@ -55,8 +56,12 @@ public function formatBatch(array $records) return $records; } - protected function normalize($data) + protected function normalize($data, $depth = 0) { + if ($depth > 9) { + return 'Over 9 levels deep, aborting normalization'; + } + if (null === $data || is_scalar($data)) { if (is_float($data)) { if (is_infinite($data)) { @@ -75,11 +80,12 @@ protected function normalize($data) $count = 1; foreach ($data as $key => $value) { - if ($count++ >= 1000) { + if ($count++ > 1000) { $normalized['...'] = 'Over 1000 items ('.count($data).' total), aborting normalization'; break; } - $normalized[$key] = $this->normalize($value); + + $normalized[$key] = $this->normalize($value, $depth+1); } return $normalized; @@ -103,7 +109,7 @@ protected function normalize($data) $value = $this->toJson($data, true); } - return sprintf("[object] (%s: %s)", get_class($data), $value); + return sprintf("[object] (%s: %s)", Utils::getClass($data), $value); } if (is_resource($data)) { @@ -117,13 +123,13 @@ protected function normalizeException($e) { // TODO 2.0 only check for Throwable if (!$e instanceof Exception && !$e instanceof \Throwable) { - throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e)); + throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.Utils::getClass($e)); } $data = array( - 'class' => get_class($e), + 'class' => Utils::getClass($e), 'message' => $e->getMessage(), - 'code' => $e->getCode(), + 'code' => (int) $e->getCode(), 'file' => $e->getFile().':'.$e->getLine(), ); @@ -136,8 +142,8 @@ protected function normalizeException($e) $data['faultactor'] = $e->faultactor; } - if (isset($e->detail)) { - $data['detail'] = $e->detail; + if (isset($e->detail) && (is_string($e->detail) || is_object($e->detail) || is_array($e->detail))) { + $data['detail'] = is_string($e->detail) ? $e->detail : reset($e->detail); } } @@ -145,12 +151,6 @@ protected function normalizeException($e) foreach ($trace as $frame) { if (isset($frame['file'])) { $data['trace'][] = $frame['file'].':'.$frame['line']; - } elseif (isset($frame['function']) && $frame['function'] === '{closure}') { - // We should again normalize the frames, because it might contain invalid items - $data['trace'][] = $frame['function']; - } else { - // We should again normalize the frames, because it might contain invalid items - $data['trace'][] = $this->toJson($this->normalize($frame), true); } } @@ -171,127 +171,6 @@ protected function normalizeException($e) */ protected function toJson($data, $ignoreErrors = false) { - // suppress json_encode errors since it's twitchy with some inputs - if ($ignoreErrors) { - return @$this->jsonEncode($data); - } - - $json = $this->jsonEncode($data); - - if ($json === false) { - $json = $this->handleJsonError(json_last_error(), $data); - } - - return $json; - } - - /** - * @param mixed $data - * @return string JSON encoded data or null on failure - */ - private function jsonEncode($data) - { - if (version_compare(PHP_VERSION, '5.4.0', '>=')) { - return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); - } - - return json_encode($data); - } - - /** - * Handle a json_encode failure. - * - * If the failure is due to invalid string encoding, try to clean the - * input and encode again. If the second encoding attempt fails, the - * inital error is not encoding related or the input can't be cleaned then - * raise a descriptive exception. - * - * @param int $code return code of json_last_error function - * @param mixed $data data that was meant to be encoded - * @throws \RuntimeException if failure can't be corrected - * @return string JSON encoded data after error correction - */ - private function handleJsonError($code, $data) - { - if ($code !== JSON_ERROR_UTF8) { - $this->throwEncodeError($code, $data); - } - - if (is_string($data)) { - $this->detectAndCleanUtf8($data); - } elseif (is_array($data)) { - array_walk_recursive($data, array($this, 'detectAndCleanUtf8')); - } else { - $this->throwEncodeError($code, $data); - } - - $json = $this->jsonEncode($data); - - if ($json === false) { - $this->throwEncodeError(json_last_error(), $data); - } - - return $json; - } - - /** - * Throws an exception according to a given code with a customized message - * - * @param int $code return code of json_last_error function - * @param mixed $data data that was meant to be encoded - * @throws \RuntimeException - */ - private function throwEncodeError($code, $data) - { - switch ($code) { - case JSON_ERROR_DEPTH: - $msg = 'Maximum stack depth exceeded'; - break; - case JSON_ERROR_STATE_MISMATCH: - $msg = 'Underflow or the modes mismatch'; - break; - case JSON_ERROR_CTRL_CHAR: - $msg = 'Unexpected control character found'; - break; - case JSON_ERROR_UTF8: - $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded'; - break; - default: - $msg = 'Unknown error'; - } - - throw new \RuntimeException('JSON encoding failed: '.$msg.'. Encoding: '.var_export($data, true)); - } - - /** - * Detect invalid UTF-8 string characters and convert to valid UTF-8. - * - * Valid UTF-8 input will be left unmodified, but strings containing - * invalid UTF-8 codepoints will be reencoded as UTF-8 with an assumed - * original encoding of ISO-8859-15. This conversion may result in - * incorrect output if the actual encoding was not ISO-8859-15, but it - * will be clean UTF-8 output and will not rely on expensive and fragile - * detection algorithms. - * - * Function converts the input in place in the passed variable so that it - * can be used as a callback for array_walk_recursive. - * - * @param mixed &$data Input to check and convert if needed - * @private - */ - public function detectAndCleanUtf8(&$data) - { - if (is_string($data) && !preg_match('//u', $data)) { - $data = preg_replace_callback( - '/[\x80-\xFF]+/', - function ($m) { return utf8_encode($m[0]); }, - $data - ); - $data = str_replace( - array('¤', '¦', '¨', '´', '¸', '¼', '½', '¾'), - array('€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'), - $data - ); - } + return Utils::jsonEncode($data, null, $ignoreErrors); } } diff --git a/lib/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php b/lib/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php index 654710a..65dba99 100644 --- a/lib/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php +++ b/lib/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php @@ -102,12 +102,12 @@ public function formatBatch(array $records) throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter'); } - protected function normalize($data) + protected function normalize($data, $depth = 0) { if (is_object($data) && !$data instanceof \DateTime) { return $data; } - return parent::normalize($data); + return parent::normalize($data, $depth); } } diff --git a/lib/monolog/monolog/src/Monolog/Handler/AbstractHandler.php b/lib/monolog/monolog/src/Monolog/Handler/AbstractHandler.php index 758a425..92b9d45 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/AbstractHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/AbstractHandler.php @@ -11,16 +11,17 @@ namespace Monolog\Handler; -use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; +use Monolog\Logger; +use Monolog\ResettableInterface; /** * Base Handler class providing the Handler structure * * @author Jordi Boggiano */ -abstract class AbstractHandler implements HandlerInterface +abstract class AbstractHandler implements HandlerInterface, ResettableInterface { protected $level = Logger::DEBUG; protected $bubble = true; @@ -32,8 +33,8 @@ abstract class AbstractHandler implements HandlerInterface protected $processors = array(); /** - * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($level = Logger::DEBUG, $bubble = true) { @@ -141,8 +142,8 @@ public function getLevel() /** * Sets the bubbling behavior. * - * @param Boolean $bubble true means that this handler allows bubbling. - * false means that bubbling is not permitted. + * @param bool $bubble true means that this handler allows bubbling. + * false means that bubbling is not permitted. * @return self */ public function setBubble($bubble) @@ -155,8 +156,8 @@ public function setBubble($bubble) /** * Gets the bubbling behavior. * - * @return Boolean true means that this handler allows bubbling. - * false means that bubbling is not permitted. + * @return bool true means that this handler allows bubbling. + * false means that bubbling is not permitted. */ public function getBubble() { @@ -174,6 +175,15 @@ public function __destruct() } } + public function reset() + { + foreach ($this->processors as $processor) { + if ($processor instanceof ResettableInterface) { + $processor->reset(); + } + } + } + /** * Gets the default formatter. * diff --git a/lib/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php b/lib/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php index 6f18f72..e1e8953 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php @@ -11,6 +11,8 @@ namespace Monolog\Handler; +use Monolog\ResettableInterface; + /** * Base Handler class providing the Handler structure * diff --git a/lib/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php b/lib/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php index e2b2832..8c76aca 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php @@ -53,9 +53,9 @@ abstract class AbstractSyslogHandler extends AbstractProcessingHandler ); /** - * @param mixed $facility - * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param mixed $facility + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($facility = LOG_USER, $level = Logger::DEBUG, $bubble = true) { diff --git a/lib/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php b/lib/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php index b3a21bd..68feb48 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php @@ -43,11 +43,11 @@ protected function getDefaultFormatter() protected function write(array $record) { // Accumulate records - self::$records[] = $record; + static::$records[] = $record; // Register shutdown handler if not already done - if (!self::$initialized) { - self::$initialized = true; + if (!static::$initialized) { + static::$initialized = true; $this->registerShutdownFunction(); } } @@ -58,27 +58,37 @@ protected function write(array $record) */ public static function send() { - $format = self::getResponseFormat(); + $format = static::getResponseFormat(); if ($format === 'unknown') { return; } - if (count(self::$records)) { + if (count(static::$records)) { if ($format === 'html') { - self::writeOutput(''); + static::writeOutput(''); } elseif ($format === 'js') { - self::writeOutput(self::generateScript()); + static::writeOutput(static::generateScript()); } - self::reset(); + static::resetStatic(); } } + public function close() + { + self::resetStatic(); + } + + public function reset() + { + self::resetStatic(); + } + /** * Forget all logged records */ - public static function reset() + public static function resetStatic() { - self::$records = array(); + static::$records = array(); } /** @@ -133,18 +143,18 @@ protected static function getResponseFormat() private static function generateScript() { $script = array(); - foreach (self::$records as $record) { - $context = self::dump('Context', $record['context']); - $extra = self::dump('Extra', $record['extra']); + foreach (static::$records as $record) { + $context = static::dump('Context', $record['context']); + $extra = static::dump('Extra', $record['extra']); if (empty($context) && empty($extra)) { - $script[] = self::call_array('log', self::handleStyles($record['formatted'])); + $script[] = static::call_array('log', static::handleStyles($record['formatted'])); } else { $script = array_merge($script, - array(self::call_array('groupCollapsed', self::handleStyles($record['formatted']))), + array(static::call_array('groupCollapsed', static::handleStyles($record['formatted']))), $context, $extra, - array(self::call('groupEnd')) + array(static::call('groupEnd')) ); } } @@ -154,21 +164,22 @@ private static function generateScript() private static function handleStyles($formatted) { - $args = array(self::quote('font-weight: normal')); + $args = array(); $format = '%c' . $formatted; preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); foreach (array_reverse($matches) as $match) { - $args[] = self::quote(self::handleCustomStyles($match[2][0], $match[1][0])); $args[] = '"font-weight: normal"'; + $args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0])); $pos = $match[0][1]; $format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0])); } - array_unshift($args, self::quote($format)); + $args[] = static::quote('font-weight: normal'); + $args[] = static::quote($format); - return $args; + return array_reverse($args); } private static function handleCustomStyles($style, $string) @@ -198,13 +209,13 @@ private static function dump($title, array $dict) if (empty($dict)) { return $script; } - $script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title)); + $script[] = static::call('log', static::quote('%c%s'), static::quote('font-weight: bold'), static::quote($title)); foreach ($dict as $key => $value) { $value = json_encode($value); if (empty($value)) { - $value = self::quote(''); + $value = static::quote(''); } - $script[] = self::call('log', self::quote('%s: %o'), self::quote($key), $value); + $script[] = static::call('log', static::quote('%s: %o'), static::quote($key), $value); } return $script; @@ -220,7 +231,7 @@ private static function call() $args = func_get_args(); $method = array_shift($args); - return self::call_array($method, $args); + return static::call_array($method, $args); } private static function call_array($method, array $args) diff --git a/lib/monolog/monolog/src/Monolog/Handler/BufferHandler.php b/lib/monolog/monolog/src/Monolog/Handler/BufferHandler.php index 72f8953..0957e55 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/BufferHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/BufferHandler.php @@ -12,6 +12,8 @@ namespace Monolog\Handler; use Monolog\Logger; +use Monolog\ResettableInterface; +use Monolog\Formatter\FormatterInterface; /** * Buffers all records until closing the handler and then pass them as batch. @@ -34,8 +36,8 @@ class BufferHandler extends AbstractHandler * @param HandlerInterface $handler Handler. * @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not - * @param Boolean $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded */ public function __construct(HandlerInterface $handler, $bufferLimit = 0, $level = Logger::DEBUG, $bubble = true, $flushOnOverflow = false) { @@ -114,4 +116,33 @@ public function clear() $this->bufferSize = 0; $this->buffer = array(); } + + public function reset() + { + $this->flush(); + + parent::reset(); + + if ($this->handler instanceof ResettableInterface) { + $this->handler->reset(); + } + } + + /** + * {@inheritdoc} + */ + public function setFormatter(FormatterInterface $formatter) + { + $this->handler->setFormatter($formatter); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getFormatter() + { + return $this->handler->getFormatter(); + } } diff --git a/lib/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php b/lib/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php index 785cb0c..47120e5 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php @@ -13,6 +13,7 @@ use Monolog\Formatter\ChromePHPFormatter; use Monolog\Logger; +use Monolog\Utils; /** * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/) @@ -32,7 +33,7 @@ class ChromePHPHandler extends AbstractProcessingHandler * Header name */ const HEADER_NAME = 'X-ChromeLogger-Data'; - + /** * Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+) */ @@ -43,9 +44,9 @@ class ChromePHPHandler extends AbstractProcessingHandler /** * Tracks whether we sent too much data * - * Chrome limits the headers to 256KB, so when we sent 240KB we stop sending + * Chrome limits the headers to 4KB, so when we sent 3KB we stop sending * - * @var Boolean + * @var bool */ protected static $overflowed = false; @@ -58,8 +59,8 @@ class ChromePHPHandler extends AbstractProcessingHandler protected static $sendHeaders = true; /** - * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($level = Logger::DEBUG, $bubble = true) { @@ -134,9 +135,9 @@ protected function send() self::$json['request_uri'] = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; } - $json = @json_encode(self::$json); + $json = Utils::jsonEncode(self::$json, null, true); $data = base64_encode(utf8_encode($json)); - if (strlen($data) > 240 * 1024) { + if (strlen($data) > 3 * 1024) { self::$overflowed = true; $record = array( @@ -149,7 +150,7 @@ protected function send() 'extra' => array(), ); self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record); - $json = @json_encode(self::$json); + $json = Utils::jsonEncode(self::$json, null, true); $data = base64_encode(utf8_encode($json)); } @@ -174,7 +175,7 @@ protected function sendHeader($header, $content) /** * Verifies if the headers are accepted by the current user agent * - * @return Boolean + * @return bool */ protected function headersAccepted() { diff --git a/lib/monolog/monolog/src/Monolog/Handler/CubeHandler.php b/lib/monolog/monolog/src/Monolog/Handler/CubeHandler.php index 96b3ca0..44928ef 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/CubeHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/CubeHandler.php @@ -12,6 +12,7 @@ namespace Monolog\Handler; use Monolog\Logger; +use Monolog\Utils; /** * Logs to Cube. @@ -119,9 +120,9 @@ protected function write(array $record) $data['data']['level'] = $record['level']; if ($this->scheme === 'http') { - $this->writeHttp(json_encode($data)); + $this->writeHttp(Utils::jsonEncode($data)); } else { - $this->writeUdp(json_encode($data)); + $this->writeUdp(Utils::jsonEncode($data)); } } diff --git a/lib/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php b/lib/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php index 7778c22..35b55cb 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php @@ -60,7 +60,7 @@ class DeduplicationHandler extends BufferHandler * @param string $deduplicationStore The file/path where the deduplication log should be kept * @param int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes * @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(HandlerInterface $handler, $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, $time = 60, $bubble = true) { diff --git a/lib/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php b/lib/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php index 8196740..bb0f83e 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php @@ -46,10 +46,10 @@ class ElasticSearchHandler extends AbstractProcessingHandler protected $options = array(); /** - * @param Client $client Elastica Client object - * @param array $options Handler configuration - * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param Client $client Elastica Client object + * @param array $options Handler configuration + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(Client $client, array $options = array(), $level = Logger::DEBUG, $bubble = true) { diff --git a/lib/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php b/lib/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php index 1447a58..b2986b0 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php @@ -28,10 +28,10 @@ class ErrorLogHandler extends AbstractProcessingHandler protected $expandNewlines; /** - * @param int $messageType Says where the error should go. - * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not - * @param Boolean $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries + * @param int $messageType Says where the error should go. + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries */ public function __construct($messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, $bubble = true, $expandNewlines = false) { diff --git a/lib/monolog/monolog/src/Monolog/Handler/FilterHandler.php b/lib/monolog/monolog/src/Monolog/Handler/FilterHandler.php index 2a0f7fd..949f227 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/FilterHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/FilterHandler.php @@ -12,6 +12,7 @@ namespace Monolog\Handler; use Monolog\Logger; +use Monolog\Formatter\FormatterInterface; /** * Simple handler wrapper that filters records based on a list of levels @@ -40,15 +41,15 @@ class FilterHandler extends AbstractHandler /** * Whether the messages that are handled can bubble up the stack or not * - * @var Boolean + * @var bool */ protected $bubble; /** - * @param callable|HandlerInterface $handler Handler or factory callable($record, $this). + * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $filterHandler). * @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided * @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, $bubble = true) { @@ -104,21 +105,13 @@ public function handle(array $record) return false; } - // The same logic as in FingersCrossedHandler - if (!$this->handler instanceof HandlerInterface) { - $this->handler = call_user_func($this->handler, $record, $this); - if (!$this->handler instanceof HandlerInterface) { - throw new \RuntimeException("The factory callable should return a HandlerInterface"); - } - } - if ($this->processors) { foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } } - $this->handler->handle($record); + $this->getHandler($record)->handle($record); return false === $this->bubble; } @@ -135,6 +128,45 @@ public function handleBatch(array $records) } } - $this->handler->handleBatch($filtered); + if (count($filtered) > 0) { + $this->getHandler($filtered[count($filtered) - 1])->handleBatch($filtered); + } + } + + /** + * Return the nested handler + * + * If the handler was provided as a factory callable, this will trigger the handler's instantiation. + * + * @return HandlerInterface + */ + public function getHandler(array $record = null) + { + if (!$this->handler instanceof HandlerInterface) { + $this->handler = call_user_func($this->handler, $record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); + } + } + + return $this->handler; + } + + /** + * {@inheritdoc} + */ + public function setFormatter(FormatterInterface $formatter) + { + $this->getHandler()->setFormatter($formatter); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getFormatter() + { + return $this->getHandler()->getFormatter(); } } diff --git a/lib/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php b/lib/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php index c3e42ef..aaca12c 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php +++ b/lib/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php @@ -22,7 +22,7 @@ interface ActivationStrategyInterface * Returns whether the given record activates the handler. * * @param array $record - * @return Boolean + * @return bool */ public function isHandlerActivated(array $record); } diff --git a/lib/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php b/lib/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php index d1dcaac..cdabc44 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php @@ -14,6 +14,8 @@ use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; use Monolog\Handler\FingersCrossed\ActivationStrategyInterface; use Monolog\Logger; +use Monolog\ResettableInterface; +use Monolog\Formatter\FormatterInterface; /** * Buffers all records until a certain level is reached @@ -38,11 +40,11 @@ class FingersCrossedHandler extends AbstractHandler protected $passthruLevel; /** - * @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler). + * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $fingersCrossedHandler). * @param int|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not - * @param Boolean $stopBuffering Whether the handler should stop buffering after being triggered (default true) + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true) * @param int $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered */ public function __construct($handler, $activationStrategy = null, $bufferSize = 0, $bubble = true, $stopBuffering = true, $passthruLevel = null) @@ -87,15 +89,7 @@ public function activate() if ($this->stopBuffering) { $this->buffering = false; } - if (!$this->handler instanceof HandlerInterface) { - $record = end($this->buffer) ?: null; - - $this->handler = call_user_func($this->handler, $record, $this); - if (!$this->handler instanceof HandlerInterface) { - throw new \RuntimeException("The factory callable should return a HandlerInterface"); - } - } - $this->handler->handleBatch($this->buffer); + $this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer); $this->buffer = array(); } @@ -119,7 +113,7 @@ public function handle(array $record) $this->activate(); } } else { - $this->handler->handle($record); + $this->getHandler($record)->handle($record); } return false === $this->bubble; @@ -129,6 +123,36 @@ public function handle(array $record) * {@inheritdoc} */ public function close() + { + $this->flushBuffer(); + } + + public function reset() + { + $this->flushBuffer(); + + parent::reset(); + + if ($this->getHandler() instanceof ResettableInterface) { + $this->getHandler()->reset(); + } + } + + /** + * Clears the buffer without flushing any messages down to the wrapped handler. + * + * It also resets the handler to its initial buffering state. + */ + public function clear() + { + $this->buffer = array(); + $this->reset(); + } + + /** + * Resets the state of the handler. Stops forwarding records to the wrapped handler. + */ + private function flushBuffer() { if (null !== $this->passthruLevel) { $level = $this->passthruLevel; @@ -136,28 +160,48 @@ public function close() return $record['level'] >= $level; }); if (count($this->buffer) > 0) { - $this->handler->handleBatch($this->buffer); - $this->buffer = array(); + $this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer); } } + + $this->buffer = array(); + $this->buffering = true; } /** - * Resets the state of the handler. Stops forwarding records to the wrapped handler. + * Return the nested handler + * + * If the handler was provided as a factory callable, this will trigger the handler's instantiation. + * + * @return HandlerInterface */ - public function reset() + public function getHandler(array $record = null) { - $this->buffering = true; + if (!$this->handler instanceof HandlerInterface) { + $this->handler = call_user_func($this->handler, $record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); + } + } + + return $this->handler; } /** - * Clears the buffer without flushing any messages down to the wrapped handler. - * - * It also resets the handler to its initial buffering state. + * {@inheritdoc} */ - public function clear() + public function setFormatter(FormatterInterface $formatter) { - $this->buffer = array(); - $this->reset(); + $this->getHandler()->setFormatter($formatter); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getFormatter() + { + return $this->getHandler()->getFormatter(); } } diff --git a/lib/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php b/lib/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php index fee4795..c30b184 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php @@ -158,7 +158,7 @@ protected function write(array $record) /** * Verifies if the headers are accepted by the current user agent * - * @return Boolean + * @return bool */ protected function headersAccepted() { diff --git a/lib/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php b/lib/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php index dd9a361..f0f010c 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php @@ -12,6 +12,7 @@ namespace Monolog\Handler; use Monolog\Logger; +use Monolog\Utils; use Monolog\Formatter\FlowdockFormatter; use Monolog\Formatter\FormatterInterface; @@ -105,7 +106,7 @@ protected function generateDataStream($record) */ private function buildContent($record) { - return json_encode($record['formatted']['flowdock']); + return Utils::jsonEncode($record['formatted']['flowdock']); } /** diff --git a/lib/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php b/lib/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php new file mode 100644 index 0000000..3e2f1b2 --- /dev/null +++ b/lib/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; + +/** + * Interface to describe loggers that have a formatter + * + * This interface is present in monolog 1.x to ease forward compatibility. + * + * @author Jordi Boggiano + */ +interface FormattableHandlerInterface +{ + /** + * Sets the formatter. + * + * @param FormatterInterface $formatter + * @return HandlerInterface self + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface; + + /** + * Gets the formatter. + * + * @return FormatterInterface + */ + public function getFormatter(): FormatterInterface; +} diff --git a/lib/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php b/lib/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php new file mode 100644 index 0000000..e9ec5e7 --- /dev/null +++ b/lib/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\LineFormatter; + +/** + * Helper trait for implementing FormattableInterface + * + * This trait is present in monolog 1.x to ease forward compatibility. + * + * @author Jordi Boggiano + */ +trait FormattableHandlerTrait +{ + /** + * @var FormatterInterface + */ + protected $formatter; + + /** + * {@inheritdoc} + * @suppress PhanTypeMismatchReturn + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + $this->formatter = $formatter; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getFormatter(): FormatterInterface + { + if (!$this->formatter) { + $this->formatter = $this->getDefaultFormatter(); + } + + return $this->formatter; + } + + /** + * Gets the default formatter. + * + * Overwrite this if the LineFormatter is not a good default for your handler. + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new LineFormatter(); + } +} diff --git a/lib/monolog/monolog/src/Monolog/Handler/GelfHandler.php b/lib/monolog/monolog/src/Monolog/Handler/GelfHandler.php index d3847d8..71e4669 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/GelfHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/GelfHandler.php @@ -47,14 +47,6 @@ public function __construct($publisher, $level = Logger::DEBUG, $bubble = true) $this->publisher = $publisher; } - /** - * {@inheritdoc} - */ - public function close() - { - $this->publisher = null; - } - /** * {@inheritdoc} */ diff --git a/lib/monolog/monolog/src/Monolog/Handler/GroupHandler.php b/lib/monolog/monolog/src/Monolog/Handler/GroupHandler.php index 663f5a9..0d461f9 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/GroupHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/GroupHandler.php @@ -12,6 +12,7 @@ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; +use Monolog\ResettableInterface; /** * Forwards records to multiple handlers @@ -23,8 +24,8 @@ class GroupHandler extends AbstractHandler protected $handlers; /** - * @param array $handlers Array of Handlers. - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param array $handlers Array of Handlers. + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(array $handlers, $bubble = true) { @@ -79,8 +80,9 @@ public function handleBatch(array $records) $processed = array(); foreach ($records as $record) { foreach ($this->processors as $processor) { - $processed[] = call_user_func($processor, $record); + $record = call_user_func($processor, $record); } + $processed[] = $record; } $records = $processed; } @@ -90,6 +92,17 @@ public function handleBatch(array $records) } } + public function reset() + { + parent::reset(); + + foreach ($this->handlers as $handler) { + if ($handler instanceof ResettableInterface) { + $handler->reset(); + } + } + } + /** * {@inheritdoc} */ diff --git a/lib/monolog/monolog/src/Monolog/Handler/HandlerInterface.php b/lib/monolog/monolog/src/Monolog/Handler/HandlerInterface.php index d920c4b..8d5a4a0 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/HandlerInterface.php +++ b/lib/monolog/monolog/src/Monolog/Handler/HandlerInterface.php @@ -31,7 +31,7 @@ interface HandlerInterface * * @param array $record Partial log record containing only a level key * - * @return Boolean + * @return bool */ public function isHandling(array $record); @@ -46,7 +46,7 @@ public function isHandling(array $record); * calling further handlers in the stack with a given log record. * * @param array $record The record to handle - * @return Boolean true means that this handler handled the record, and that bubbling is not permitted. + * @return bool true means that this handler handled the record, and that bubbling is not permitted. * false means the record was either not processed or that this handler allows bubbling. */ public function handle(array $record); diff --git a/lib/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php b/lib/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php index e540d80..55e6498 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php +++ b/lib/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php @@ -11,6 +11,7 @@ namespace Monolog\Handler; +use Monolog\ResettableInterface; use Monolog\Formatter\FormatterInterface; /** @@ -30,7 +31,7 @@ * * @author Alexey Karapetov */ -class HandlerWrapper implements HandlerInterface +class HandlerWrapper implements HandlerInterface, ResettableInterface { /** * @var HandlerInterface @@ -105,4 +106,11 @@ public function getFormatter() { return $this->handler->getFormatter(); } + + public function reset() + { + if ($this->handler instanceof ResettableInterface) { + return $this->handler->reset(); + } + } } diff --git a/lib/monolog/monolog/src/Monolog/Handler/HipChatHandler.php b/lib/monolog/monolog/src/Monolog/Handler/HipChatHandler.php index 73049f3..179d626 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/HipChatHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/HipChatHandler.php @@ -97,6 +97,8 @@ class HipChatHandler extends SocketHandler */ public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text', $host = 'api.hipchat.com', $version = self::API_V1) { + @trigger_error('The Monolog\Handler\HipChatHandler class is deprecated. You should migrate to Slack and the SlackWebhookHandler / SlackbotHandler, see https://www.atlassian.com/partnerships/slack', E_USER_DEPRECATED); + if ($version == self::API_V1 && !$this->validateStringLength($name, static::MAXIMUM_NAME_LENGTH)) { throw new \InvalidArgumentException('The supplied name is too long. HipChat\'s v1 API supports names up to 15 UTF-8 characters.'); } @@ -219,6 +221,21 @@ protected function getAlertColor($level) protected function write(array $record) { parent::write($record); + $this->finalizeWrite(); + } + + /** + * Finalizes the request by reading some bytes and then closing the socket + * + * If we do not read some but close the socket too early, hipchat sometimes + * drops the request entirely. + */ + protected function finalizeWrite() + { + $res = $this->getResource(); + if (is_resource($res)) { + @fread($res, 2048); + } $this->closeSocket(); } diff --git a/lib/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php b/lib/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php index d60a3c8..f4d3b97 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php @@ -12,6 +12,7 @@ namespace Monolog\Handler; use Monolog\Logger; +use Monolog\Utils; /** * IFTTTHandler uses cURL to trigger IFTTT Maker actions @@ -30,10 +31,10 @@ class IFTTTHandler extends AbstractProcessingHandler private $secretKey; /** - * @param string $eventName The name of the IFTTT Maker event that should be triggered - * @param string $secretKey A valid IFTTT secret key - * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param string $eventName The name of the IFTTT Maker event that should be triggered + * @param string $secretKey A valid IFTTT secret key + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($eventName, $secretKey, $level = Logger::ERROR, $bubble = true) { @@ -53,7 +54,7 @@ public function write(array $record) "value2" => $record["level_name"], "value3" => $record["message"], ); - $postString = json_encode($postData); + $postString = Utils::jsonEncode($postData); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey); diff --git a/lib/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php b/lib/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php new file mode 100644 index 0000000..8f683dc --- /dev/null +++ b/lib/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + + namespace Monolog\Handler; + + use Monolog\Logger; + +/** + * Inspired on LogEntriesHandler. + * + * @author Robert Kaufmann III + * @author Gabriel Machado + */ +class InsightOpsHandler extends SocketHandler +{ + /** + * @var string + */ + protected $logToken; + + /** + * @param string $token Log token supplied by InsightOps + * @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'. + * @param bool $useSSL Whether or not SSL encryption should be used + * @param int $level The minimum logging level to trigger this handler + * @param bool $bubble Whether or not messages that are handled should bubble up the stack. + * + * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing + */ + public function __construct($token, $region = 'us', $useSSL = true, $level = Logger::DEBUG, $bubble = true) + { + if ($useSSL && !extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for InsightOpsHandler'); + } + + $endpoint = $useSSL + ? 'ssl://' . $region . '.data.logs.insight.rapid7.com:443' + : $region . '.data.logs.insight.rapid7.com:80'; + + parent::__construct($endpoint, $level, $bubble); + $this->logToken = $token; + } + + /** + * {@inheritdoc} + * + * @param array $record + * @return string + */ + protected function generateDataStream($record) + { + return $this->logToken . ' ' . $record['formatted']; + } +} diff --git a/lib/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php b/lib/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php index 494c605..ea89fb3 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php @@ -31,13 +31,13 @@ class LogEntriesHandler extends SocketHandler * * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing */ - public function __construct($token, $useSSL = true, $level = Logger::DEBUG, $bubble = true) + public function __construct($token, $useSSL = true, $level = Logger::DEBUG, $bubble = true, $host = 'data.logentries.com') { if ($useSSL && !extension_loaded('openssl')) { throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler'); } - $endpoint = $useSSL ? 'ssl://data.logentries.com:443' : 'data.logentries.com:80'; + $endpoint = $useSSL ? 'ssl://' . $host . ':443' : $host . ':80'; parent::__construct($endpoint, $level, $bubble); $this->logToken = $token; } diff --git a/lib/monolog/monolog/src/Monolog/Handler/MandrillHandler.php b/lib/monolog/monolog/src/Monolog/Handler/MandrillHandler.php index ab95924..3f0956a 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/MandrillHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/MandrillHandler.php @@ -27,7 +27,7 @@ class MandrillHandler extends MailHandler * @param string $apiKey A valid Mandrill API key * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($apiKey, $message, $level = Logger::ERROR, $bubble = true) { diff --git a/lib/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php b/lib/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php index 6718e9e..64dc138 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php @@ -12,12 +12,15 @@ namespace Monolog\Handler; use Monolog\Logger; +use Monolog\Utils; use Monolog\Formatter\NormalizerFormatter; /** * Class to record a log on a NewRelic application. * Enabling New Relic High Security mode may prevent capture of useful information. * + * This handler requires a NormalizerFormatter to function and expects an array in $record['formatted'] + * * @see https://docs.newrelic.com/docs/agents/php-agent * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security */ @@ -84,7 +87,7 @@ protected function write(array $record) unset($record['formatted']['context']['transaction_name']); } - if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) { + if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) { newrelic_notice_error($record['message'], $record['context']['exception']); unset($record['formatted']['context']['exception']); } else { @@ -188,7 +191,7 @@ protected function setNewRelicParameter($key, $value) if (null === $value || is_scalar($value)) { newrelic_add_custom_parameter($key, $value); } else { - newrelic_add_custom_parameter($key, @json_encode($value)); + newrelic_add_custom_parameter($key, Utils::jsonEncode($value, null, true)); } } diff --git a/lib/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php b/lib/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php index 1f2076a..d0a8b43 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php @@ -14,6 +14,7 @@ use Exception; use Monolog\Formatter\LineFormatter; use Monolog\Logger; +use Monolog\Utils; use PhpConsole\Connector; use PhpConsole\Handler; use PhpConsole\Helper; @@ -188,7 +189,7 @@ private function handleDebugRecord(array $record) $tags = $this->getRecordTags($record); $message = $record['message']; if ($record['context']) { - $message .= ' ' . json_encode($this->connector->getDumper()->dump(array_filter($record['context']))); + $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($record['context'])), null, true); } $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']); } diff --git a/lib/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php b/lib/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php new file mode 100644 index 0000000..66a3d83 --- /dev/null +++ b/lib/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Processor\ProcessorInterface; + +/** + * Interface to describe loggers that have processors + * + * This interface is present in monolog 1.x to ease forward compatibility. + * + * @author Jordi Boggiano + */ +interface ProcessableHandlerInterface +{ + /** + * Adds a processor in the stack. + * + * @param ProcessorInterface|callable $callback + * @return HandlerInterface self + */ + public function pushProcessor($callback): HandlerInterface; + + /** + * Removes the processor on top of the stack and returns it. + * + * @throws \LogicException In case the processor stack is empty + * @return callable + */ + public function popProcessor(): callable; +} diff --git a/lib/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php b/lib/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php new file mode 100644 index 0000000..09f32a1 --- /dev/null +++ b/lib/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\ResettableInterface; + +/** + * Helper trait for implementing ProcessableInterface + * + * This trait is present in monolog 1.x to ease forward compatibility. + * + * @author Jordi Boggiano + */ +trait ProcessableHandlerTrait +{ + /** + * @var callable[] + */ + protected $processors = []; + + /** + * {@inheritdoc} + * @suppress PhanTypeMismatchReturn + */ + public function pushProcessor($callback): HandlerInterface + { + array_unshift($this->processors, $callback); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function popProcessor(): callable + { + if (!$this->processors) { + throw new \LogicException('You tried to pop from an empty processor stack.'); + } + + return array_shift($this->processors); + } + + /** + * Processes a record. + */ + protected function processRecord(array $record): array + { + foreach ($this->processors as $processor) { + $record = $processor($record); + } + + return $record; + } + + protected function resetProcessors(): void + { + foreach ($this->processors as $processor) { + if ($processor instanceof ResettableInterface) { + $processor->reset(); + } + } + } +} diff --git a/lib/monolog/monolog/src/Monolog/Handler/PsrHandler.php b/lib/monolog/monolog/src/Monolog/Handler/PsrHandler.php index 1ae8584..a99e6ab 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/PsrHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/PsrHandler.php @@ -31,7 +31,7 @@ class PsrHandler extends AbstractHandler /** * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, $bubble = true) { diff --git a/lib/monolog/monolog/src/Monolog/Handler/PushoverHandler.php b/lib/monolog/monolog/src/Monolog/Handler/PushoverHandler.php index bba7200..f27bb3d 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/PushoverHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/PushoverHandler.php @@ -69,8 +69,8 @@ class PushoverHandler extends SocketHandler * @param string|array $users Pushover user id or array of ids the message will be sent to * @param string $title Title sent to the Pushover API * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not - * @param Boolean $useSSL Whether to connect via SSL. Required when pushing messages to users that are not + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not * the pushover.net app owner. OpenSSL is required for this option. * @param int $highPriorityLevel The minimum logging level at which this handler will start * sending "high priority" requests to the Pushover API @@ -180,6 +180,6 @@ public function setEmergencyLevel($value) */ public function useFormattedMessage($value) { - $this->useFormattedMessage = (boolean) $value; + $this->useFormattedMessage = (bool) $value; } } diff --git a/lib/monolog/monolog/src/Monolog/Handler/RavenHandler.php b/lib/monolog/monolog/src/Monolog/Handler/RavenHandler.php index 53a8b39..1929f25 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/RavenHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/RavenHandler.php @@ -18,7 +18,7 @@ /** * Handler to send messages to a Sentry (https://github.com/getsentry/sentry) server - * using raven-php (https://github.com/getsentry/raven-php) + * using sentry-php (https://github.com/getsentry/sentry-php) * * @author Marc Abramowitz */ @@ -27,7 +27,7 @@ class RavenHandler extends AbstractProcessingHandler /** * Translates Monolog log levels to Raven log levels. */ - private $logLevels = array( + protected $logLevels = array( Logger::DEBUG => Raven_Client::DEBUG, Logger::INFO => Raven_Client::INFO, Logger::NOTICE => Raven_Client::INFO, @@ -42,7 +42,7 @@ class RavenHandler extends AbstractProcessingHandler * @var string should represent the current version of the calling * software. Can be any string (git commit, version number) */ - private $release; + protected $release; /** * @var Raven_Client the client object that sends the message to the server @@ -57,10 +57,12 @@ class RavenHandler extends AbstractProcessingHandler /** * @param Raven_Client $ravenClient * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true) { + @trigger_error('The Monolog\Handler\RavenHandler class is deprecated. You should rather upgrade to the sentry/sentry 2.x and use Sentry\Monolog\Handler, see https://github.com/getsentry/sentry-php/blob/master/src/Monolog/Handler.php', E_USER_DEPRECATED); + parent::__construct($level, $bubble); $this->ravenClient = $ravenClient; @@ -180,7 +182,7 @@ protected function write(array $record) } if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) { - $options['extra']['message'] = $record['formatted']; + $options['message'] = $record['formatted']; $this->ravenClient->captureException($record['context']['exception'], $options); } else { $this->ravenClient->captureMessage($record['formatted'], array(), $options); @@ -216,7 +218,7 @@ protected function getDefaultBatchFormatter() */ protected function getExtraParameters() { - return array('checksum', 'release', 'event_id'); + return array('contexts', 'checksum', 'release', 'event_id'); } /** diff --git a/lib/monolog/monolog/src/Monolog/Handler/RedisHandler.php b/lib/monolog/monolog/src/Monolog/Handler/RedisHandler.php index 590f996..bb00db5 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/RedisHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/RedisHandler.php @@ -73,7 +73,8 @@ protected function write(array $record) protected function writeCapped(array $record) { if ($this->redisClient instanceof \Redis) { - $this->redisClient->multi() + $mode = defined('\Redis::MULTI') ? \Redis::MULTI : 1; + $this->redisClient->multi($mode) ->rpush($this->redisKey, $record["formatted"]) ->ltrim($this->redisKey, -$this->capSize, -1) ->exec(); diff --git a/lib/monolog/monolog/src/Monolog/Handler/RollbarHandler.php b/lib/monolog/monolog/src/Monolog/Handler/RollbarHandler.php index 6c8a3e3..65073ff 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/RollbarHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/RollbarHandler.php @@ -129,4 +129,16 @@ public function close() { $this->flush(); } + + /** + * {@inheritdoc} + */ + public function reset() + { + $this->flush(); + + parent::reset(); + } + + } diff --git a/lib/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php b/lib/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php index 3b60b3d..ae2309f 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php @@ -39,9 +39,9 @@ class RotatingFileHandler extends StreamHandler * @param string $filename * @param int $maxFiles The maximal amount of files to keep (0 means unlimited) * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) - * @param Boolean $useLocking Try to lock log file before doing any writes + * @param bool $useLocking Try to lock log file before doing any writes */ public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) { @@ -66,6 +66,18 @@ public function close() } } + /** + * {@inheritdoc} + */ + public function reset() + { + parent::reset(); + + if (true === $this->mustRotate) { + $this->rotate(); + } + } + public function setFilenameFormat($filenameFormat, $dateFormat) { if (!preg_match('{^Y(([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) { @@ -166,7 +178,7 @@ protected function getGlobPattern() $fileInfo = pathinfo($this->filename); $glob = str_replace( array('{filename}', '{date}'), - array($fileInfo['filename'], '*'), + array($fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'), $fileInfo['dirname'] . '/' . $this->filenameFormat ); if (!empty($fileInfo['extension'])) { diff --git a/lib/monolog/monolog/src/Monolog/Handler/SamplingHandler.php b/lib/monolog/monolog/src/Monolog/Handler/SamplingHandler.php index 9509ae3..b547ed7 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/SamplingHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/SamplingHandler.php @@ -11,6 +11,8 @@ namespace Monolog\Handler; +use Monolog\Formatter\FormatterInterface; + /** * Sampling handler * @@ -38,7 +40,7 @@ class SamplingHandler extends AbstractHandler protected $factor; /** - * @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler). + * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $samplingHandler). * @param int $factor Sample factor */ public function __construct($handler, $factor) @@ -54,29 +56,58 @@ public function __construct($handler, $factor) public function isHandling(array $record) { - return $this->handler->isHandling($record); + return $this->getHandler($record)->isHandling($record); } public function handle(array $record) { if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) { - // The same logic as in FingersCrossedHandler - if (!$this->handler instanceof HandlerInterface) { - $this->handler = call_user_func($this->handler, $record, $this); - if (!$this->handler instanceof HandlerInterface) { - throw new \RuntimeException("The factory callable should return a HandlerInterface"); - } - } - if ($this->processors) { foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } } - $this->handler->handle($record); + $this->getHandler($record)->handle($record); } return false === $this->bubble; } + + /** + * Return the nested handler + * + * If the handler was provided as a factory callable, this will trigger the handler's instantiation. + * + * @return HandlerInterface + */ + public function getHandler(array $record = null) + { + if (!$this->handler instanceof HandlerInterface) { + $this->handler = call_user_func($this->handler, $record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); + } + } + + return $this->handler; + } + + /** + * {@inheritdoc} + */ + public function setFormatter(FormatterInterface $formatter) + { + $this->getHandler()->setFormatter($formatter); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getFormatter() + { + return $this->getHandler()->getFormatter(); + } } diff --git a/lib/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php b/lib/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php index 38bc838..3945550 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php +++ b/lib/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php @@ -12,6 +12,7 @@ namespace Monolog\Handler\Slack; use Monolog\Logger; +use Monolog\Utils; use Monolog\Formatter\NormalizerFormatter; use Monolog\Formatter\FormatterInterface; @@ -146,7 +147,7 @@ public function getSlackData(array $record) if ($this->useShortAttachment) { $attachment['fields'][] = $this->generateAttachmentField( - ucfirst($key), + $key, $record[$key] ); } else { @@ -207,13 +208,17 @@ public function stringify($fields) { $normalized = $this->normalizerFormatter->format($fields); $prettyPrintFlag = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 128; + $flags = 0; + if (PHP_VERSION_ID >= 50400) { + $flags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE; + } $hasSecondDimension = count(array_filter($normalized, 'is_array')); $hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric')); return $hasSecondDimension || $hasNonNumericKeys - ? json_encode($normalized, $prettyPrintFlag) - : json_encode($normalized); + ? Utils::jsonEncode($normalized, $prettyPrintFlag | $flags) + : Utils::jsonEncode($normalized, $flags); } /** @@ -229,8 +234,8 @@ public function setFormatter(FormatterInterface $formatter) /** * Generates attachment field * - * @param string $title - * @param string|array $value\ + * @param string $title + * @param string|array $value * * @return array */ @@ -241,7 +246,7 @@ private function generateAttachmentField($title, $value) : $value; return array( - 'title' => $title, + 'title' => ucfirst($title), 'value' => $value, 'short' => false ); @@ -257,7 +262,7 @@ private function generateAttachmentField($title, $value) private function generateAttachmentFields(array $data) { $fields = array(); - foreach ($data as $key => $value) { + foreach ($this->normalizerFormatter->format($data) as $key => $value) { $fields[] = $this->generateAttachmentField($key, $value); } diff --git a/lib/monolog/monolog/src/Monolog/Handler/SlackHandler.php b/lib/monolog/monolog/src/Monolog/Handler/SlackHandler.php index 3ac4d83..88c4c4d 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/SlackHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/SlackHandler.php @@ -13,6 +13,7 @@ use Monolog\Formatter\FormatterInterface; use Monolog\Logger; +use Monolog\Utils; use Monolog\Handler\Slack\SlackRecord; /** @@ -75,6 +76,11 @@ public function getSlackRecord() return $this->slackRecord; } + public function getToken() + { + return $this->token; + } + /** * {@inheritdoc} * @@ -113,7 +119,7 @@ protected function prepareContentData($record) $dataArray['token'] = $this->token; if (!empty($dataArray['attachments'])) { - $dataArray['attachments'] = json_encode($dataArray['attachments']); + $dataArray['attachments'] = Utils::jsonEncode($dataArray['attachments']); } return $dataArray; diff --git a/lib/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php b/lib/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php index 9a1bbb4..b87be99 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php @@ -13,6 +13,7 @@ use Monolog\Formatter\FormatterInterface; use Monolog\Logger; +use Monolog\Utils; use Monolog\Handler\Slack\SlackRecord; /** @@ -70,6 +71,11 @@ public function getSlackRecord() return $this->slackRecord; } + public function getWebhookUrl() + { + return $this->webhookUrl; + } + /** * {@inheritdoc} * @@ -78,7 +84,7 @@ public function getSlackRecord() protected function write(array $record) { $postData = $this->slackRecord->getSlackData($record); - $postString = json_encode($postData); + $postString = Utils::jsonEncode($postData); $ch = curl_init(); $options = array( diff --git a/lib/monolog/monolog/src/Monolog/Handler/SlackbotHandler.php b/lib/monolog/monolog/src/Monolog/Handler/SlackbotHandler.php index baead52..d3352ea 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/SlackbotHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/SlackbotHandler.php @@ -16,8 +16,11 @@ /** * Sends notifications through Slack's Slackbot * - * @author Haralan Dobrev - * @see https://slack.com/apps/A0F81R8ET-slackbot + * @author Haralan Dobrev + * @see https://slack.com/apps/A0F81R8ET-slackbot + * @deprecated According to Slack the API used on this handler it is deprecated. + * Therefore this handler will be removed on 2.x + * Slack suggests to use webhooks instead. Please contact slack for more information. */ class SlackbotHandler extends AbstractProcessingHandler { @@ -48,6 +51,7 @@ class SlackbotHandler extends AbstractProcessingHandler */ public function __construct($slackTeam, $token, $channel, $level = Logger::CRITICAL, $bubble = true) { + @trigger_error('SlackbotHandler is deprecated and will be removed on 2.x', E_USER_DEPRECATED); parent::__construct($level, $bubble); $this->slackTeam = $slackTeam; diff --git a/lib/monolog/monolog/src/Monolog/Handler/SocketHandler.php b/lib/monolog/monolog/src/Monolog/Handler/SocketHandler.php index 7a61bf4..db50d97 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/SocketHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/SocketHandler.php @@ -27,15 +27,16 @@ class SocketHandler extends AbstractProcessingHandler private $timeout = 0; private $writingTimeout = 10; private $lastSentBytes = null; + private $chunkSize = null; private $persistent = false; private $errno; private $errstr; private $lastWritingAt; /** - * @param string $connectionString Socket connection string - * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param string $connectionString Socket connection string + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true) { @@ -87,7 +88,7 @@ public function closeSocket() */ public function setPersistent($persistent) { - $this->persistent = (boolean) $persistent; + $this->persistent = (bool) $persistent; } /** @@ -127,6 +128,16 @@ public function setWritingTimeout($seconds) $this->writingTimeout = (float) $seconds; } + /** + * Set chunk size. Only has effect during connection in the writing cycle. + * + * @param float $bytes + */ + public function setChunkSize($bytes) + { + $this->chunkSize = $bytes; + } + /** * Get current connection string * @@ -177,6 +188,16 @@ public function getWritingTimeout() return $this->writingTimeout; } + /** + * Get current chunk size + * + * @return float + */ + public function getChunkSize() + { + return $this->chunkSize; + } + /** * Check to see if the socket is currently available. * @@ -219,6 +240,16 @@ protected function streamSetTimeout() return stream_set_timeout($this->resource, $seconds, $microseconds); } + /** + * Wrapper to allow mocking + * + * @see http://php.net/manual/en/function.stream-set-chunk-size.php + */ + protected function streamSetChunkSize() + { + return stream_set_chunk_size($this->resource, $this->chunkSize); + } + /** * Wrapper to allow mocking */ @@ -268,6 +299,7 @@ private function connect() { $this->createSocketResource(); $this->setSocketTimeout(); + $this->setStreamChunkSize(); } private function createSocketResource() @@ -290,6 +322,13 @@ private function setSocketTimeout() } } + private function setStreamChunkSize() + { + if ($this->chunkSize && !$this->streamSetChunkSize()) { + throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()"); + } + } + private function writeToSocket($data) { $length = strlen($data); diff --git a/lib/monolog/monolog/src/Monolog/Handler/StreamHandler.php b/lib/monolog/monolog/src/Monolog/Handler/StreamHandler.php index 09a1573..27d90e0 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/StreamHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/StreamHandler.php @@ -32,9 +32,9 @@ class StreamHandler extends AbstractProcessingHandler /** * @param resource|string $stream * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) - * @param Boolean $useLocking Try to lock log file before doing any writes + * @param bool $useLocking Try to lock log file before doing any writes * * @throws \Exception If a missing directory is not buildable * @throws \InvalidArgumentException If stream is not a resource or string @@ -63,6 +63,7 @@ public function close() fclose($this->stream); } $this->stream = null; + $this->dirCreated = null; } /** @@ -167,7 +168,7 @@ private function createDir() set_error_handler(array($this, 'customErrorHandler')); $status = mkdir($dir, 0777, true); restore_error_handler(); - if (false === $status) { + if (false === $status && !is_dir($dir)) { throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and its not buildable: '.$this->errorMessage, $dir)); } } diff --git a/lib/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php b/lib/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php index 72f44a5..ac7b16f 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php @@ -12,6 +12,7 @@ namespace Monolog\Handler; use Monolog\Logger; +use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; use Swift; @@ -29,7 +30,7 @@ class SwiftMailerHandler extends MailHandler * @param \Swift_Mailer $mailer The mailer to use * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, $bubble = true) { @@ -47,6 +48,17 @@ protected function send($content, array $records) $this->mailer->send($this->buildMessage($content, $records)); } + /** + * Gets the formatter for the Swift_Message subject. + * + * @param string $format The format of the subject + * @return FormatterInterface + */ + protected function getSubjectFormatter($format) + { + return new LineFormatter($format); + } + /** * Creates instance of Swift_Message to be sent * @@ -69,7 +81,7 @@ protected function buildMessage($content, array $records) } if ($records) { - $subjectFormatter = new LineFormatter($message->getSubject()); + $subjectFormatter = $this->getSubjectFormatter($message->getSubject()); $message->setSubject($subjectFormatter->format($this->getHighestRecord($records))); } diff --git a/lib/monolog/monolog/src/Monolog/Handler/SyslogHandler.php b/lib/monolog/monolog/src/Monolog/Handler/SyslogHandler.php index 376bc3b..f770c80 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/SyslogHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/SyslogHandler.php @@ -32,11 +32,11 @@ class SyslogHandler extends AbstractSyslogHandler protected $logopts; /** - * @param string $ident - * @param mixed $facility - * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not - * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID + * @param string $ident + * @param mixed $facility + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID */ public function __construct($ident, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $logopts = LOG_PID) { diff --git a/lib/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php b/lib/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php index 4718711..4dfd5f5 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php @@ -18,25 +18,37 @@ * A Handler for logging to a remote syslogd server. * * @author Jesper Skovgaard Nielsen + * @author Dominik Kukacka */ class SyslogUdpHandler extends AbstractSyslogHandler { + const RFC3164 = 0; + const RFC5424 = 1; + + private $dateFormats = array( + self::RFC3164 => 'M d H:i:s', + self::RFC5424 => \DateTime::RFC3339, + ); + protected $socket; protected $ident; + protected $rfc; /** - * @param string $host - * @param int $port - * @param mixed $facility - * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not - * @param string $ident Program name or tag for each log message. + * @param string $host + * @param int $port + * @param mixed $facility + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param string $ident Program name or tag for each log message. + * @param int $rfc RFC to format the message for. */ - public function __construct($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $ident = 'php') + public function __construct($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $ident = 'php', $rfc = self::RFC5424) { parent::__construct($facility, $level, $bubble); $this->ident = $ident; + $this->rfc = $rfc; $this->socket = new UdpSocket($host, $port ?: 514); } @@ -67,7 +79,7 @@ private function splitMessageIntoLines($message) } /** - * Make common syslog header (see rfc5424) + * Make common syslog header (see rfc5424 or rfc3164) */ protected function makeCommonSyslogHeader($severity) { @@ -81,16 +93,25 @@ protected function makeCommonSyslogHeader($severity) $hostname = '-'; } - return "<$priority>1 " . - $this->getDateTime() . " " . - $hostname . " " . - $this->ident . " " . - $pid . " - - "; + $date = $this->getDateTime(); + + if ($this->rfc === self::RFC3164) { + return "<$priority>" . + $date . " " . + $hostname . " " . + $this->ident . "[" . $pid . "]: "; + } else { + return "<$priority>1 " . + $date . " " . + $hostname . " " . + $this->ident . " " . + $pid . " - - "; + } } protected function getDateTime() { - return date(\DateTime::RFC3339); + return date($this->dateFormats[$this->rfc]); } /** diff --git a/lib/monolog/monolog/src/Monolog/Handler/TestHandler.php b/lib/monolog/monolog/src/Monolog/Handler/TestHandler.php index e39cfc6..478db0a 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/TestHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/TestHandler.php @@ -67,6 +67,7 @@ class TestHandler extends AbstractProcessingHandler { protected $records = array(); protected $recordsByLevel = array(); + private $skipReset = false; public function getRecords() { @@ -79,19 +80,41 @@ public function clear() $this->recordsByLevel = array(); } + public function reset() + { + if (!$this->skipReset) { + $this->clear(); + } + } + + public function setSkipReset($skipReset) + { + $this->skipReset = $skipReset; + } + public function hasRecords($level) { return isset($this->recordsByLevel[$level]); } + /** + * @param string|array $record Either a message string or an array containing message and optionally context keys that will be checked against all records + * @param int $level Logger::LEVEL constant value + */ public function hasRecord($record, $level) { - if (is_array($record)) { - $record = $record['message']; + if (is_string($record)) { + $record = array('message' => $record); } return $this->hasRecordThatPasses(function ($rec) use ($record) { - return $rec['message'] === $record; + if ($rec['message'] !== $record['message']) { + return false; + } + if (isset($record['context']) && $rec['context'] !== $record['context']) { + return false; + } + return true; }, $level); } diff --git a/lib/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php b/lib/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php index 2732ba3..7d7622a 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php @@ -48,6 +48,17 @@ public function handle(array $record) */ public function handleBatch(array $records) { + if ($this->processors) { + $processed = array(); + foreach ($records as $record) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + $processed[] = $record; + } + $records = $processed; + } + foreach ($this->handlers as $handler) { try { $handler->handleBatch($records); diff --git a/lib/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php b/lib/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php index f22cf21..a20aeae 100644 --- a/lib/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php +++ b/lib/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php @@ -17,6 +17,7 @@ * Handler sending logs to Zend Monitor * * @author Christian Bergau + * @author Jason Davis */ class ZendMonitorHandler extends AbstractProcessingHandler { @@ -25,16 +26,7 @@ class ZendMonitorHandler extends AbstractProcessingHandler * * @var array */ - protected $levelMap = array( - Logger::DEBUG => 1, - Logger::INFO => 2, - Logger::NOTICE => 3, - Logger::WARNING => 4, - Logger::ERROR => 5, - Logger::CRITICAL => 6, - Logger::ALERT => 7, - Logger::EMERGENCY => 0, - ); + protected $levelMap = array(); /** * Construct @@ -46,8 +38,21 @@ class ZendMonitorHandler extends AbstractProcessingHandler public function __construct($level = Logger::DEBUG, $bubble = true) { if (!function_exists('zend_monitor_custom_event')) { - throw new MissingExtensionException('You must have Zend Server installed in order to use this handler'); + throw new MissingExtensionException( + 'You must have Zend Server installed with Zend Monitor enabled in order to use this handler' + ); } + //zend monitor constants are not defined if zend monitor is not enabled. + $this->levelMap = array( + Logger::DEBUG => \ZEND_MONITOR_EVENT_SEVERITY_INFO, + Logger::INFO => \ZEND_MONITOR_EVENT_SEVERITY_INFO, + Logger::NOTICE => \ZEND_MONITOR_EVENT_SEVERITY_INFO, + Logger::WARNING => \ZEND_MONITOR_EVENT_SEVERITY_WARNING, + Logger::ERROR => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, + Logger::CRITICAL => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, + Logger::ALERT => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, + Logger::EMERGENCY => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, + ); parent::__construct($level, $bubble); } @@ -57,22 +62,23 @@ public function __construct($level = Logger::DEBUG, $bubble = true) protected function write(array $record) { $this->writeZendMonitorCustomEvent( - $this->levelMap[$record['level']], + Logger::getLevelName($record['level']), $record['message'], - $record['formatted'] + $record['formatted'], + $this->levelMap[$record['level']] ); } /** - * Write a record to Zend Monitor - * - * @param int $level - * @param string $message - * @param array $formatted + * Write to Zend Monitor Events + * @param string $type Text displayed in "Class Name (custom)" field + * @param string $message Text displayed in "Error String" + * @param mixed $formatted Displayed in Custom Variables tab + * @param int $severity Set the event severity level (-1,0,1) */ - protected function writeZendMonitorCustomEvent($level, $message, $formatted) + protected function writeZendMonitorCustomEvent($type, $message, $formatted, $severity) { - zend_monitor_custom_event($level, $message, $formatted); + zend_monitor_custom_event($type, $message, $formatted, $severity); } /** diff --git a/lib/monolog/monolog/src/Monolog/Logger.php b/lib/monolog/monolog/src/Monolog/Logger.php index 49d00af..e649af5 100644 --- a/lib/monolog/monolog/src/Monolog/Logger.php +++ b/lib/monolog/monolog/src/Monolog/Logger.php @@ -15,6 +15,7 @@ use Monolog\Handler\StreamHandler; use Psr\Log\LoggerInterface; use Psr\Log\InvalidArgumentException; +use Exception; /** * Monolog log channel @@ -24,7 +25,7 @@ * * @author Jordi Boggiano */ -class Logger implements LoggerInterface +class Logger implements LoggerInterface, ResettableInterface { /** * Detailed debug information @@ -133,6 +134,11 @@ class Logger implements LoggerInterface */ protected $microsecondTimestamps = true; + /** + * @var callable + */ + protected $exceptionHandler; + /** * @param string $name The logging channel * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc. @@ -141,7 +147,7 @@ class Logger implements LoggerInterface public function __construct($name, array $handlers = array(), array $processors = array()) { $this->name = $name; - $this->handlers = $handlers; + $this->setHandlers($handlers); $this->processors = $processors; } @@ -281,7 +287,7 @@ public function useMicrosecondTimestamps($micro) * @param int $level The logging level * @param string $message The log message * @param array $context The log context - * @return Boolean Whether the record has been processed + * @return bool Whether the record has been processed */ public function addRecord($level, $message, array $context = array()) { @@ -329,27 +335,75 @@ public function addRecord($level, $message, array $context = array()) 'extra' => array(), ); - foreach ($this->processors as $processor) { - $record = call_user_func($processor, $record); + try { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + + while ($handler = current($this->handlers)) { + if (true === $handler->handle($record)) { + break; + } + + next($this->handlers); + } + } catch (Exception $e) { + $this->handleException($e, $record); } - while ($handler = current($this->handlers)) { - if (true === $handler->handle($record)) { - break; + return true; + } + + /** + * Ends a log cycle and frees all resources used by handlers. + * + * Closing a Handler means flushing all buffers and freeing any open resources/handles. + * Handlers that have been closed should be able to accept log records again and re-open + * themselves on demand, but this may not always be possible depending on implementation. + * + * This is useful at the end of a request and will be called automatically on every handler + * when they get destructed. + */ + public function close() + { + foreach ($this->handlers as $handler) { + if (method_exists($handler, 'close')) { + $handler->close(); } + } + } - next($this->handlers); + /** + * Ends a log cycle and resets all handlers and processors to their initial state. + * + * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal + * state, and getting it back to a state in which it can receive log records again. + * + * This is useful in case you want to avoid logs leaking between two requests or jobs when you + * have a long running process like a worker or an application server serving multiple requests + * in one process. + */ + public function reset() + { + foreach ($this->handlers as $handler) { + if ($handler instanceof ResettableInterface) { + $handler->reset(); + } } - return true; + foreach ($this->processors as $processor) { + if ($processor instanceof ResettableInterface) { + $processor->reset(); + } + } } /** * Adds a log record at the DEBUG level. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function addDebug($message, array $context = array()) { @@ -359,9 +413,9 @@ public function addDebug($message, array $context = array()) /** * Adds a log record at the INFO level. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function addInfo($message, array $context = array()) { @@ -371,9 +425,9 @@ public function addInfo($message, array $context = array()) /** * Adds a log record at the NOTICE level. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function addNotice($message, array $context = array()) { @@ -383,9 +437,9 @@ public function addNotice($message, array $context = array()) /** * Adds a log record at the WARNING level. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function addWarning($message, array $context = array()) { @@ -395,9 +449,9 @@ public function addWarning($message, array $context = array()) /** * Adds a log record at the ERROR level. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function addError($message, array $context = array()) { @@ -407,9 +461,9 @@ public function addError($message, array $context = array()) /** * Adds a log record at the CRITICAL level. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function addCritical($message, array $context = array()) { @@ -419,9 +473,9 @@ public function addCritical($message, array $context = array()) /** * Adds a log record at the ALERT level. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function addAlert($message, array $context = array()) { @@ -431,9 +485,9 @@ public function addAlert($message, array $context = array()) /** * Adds a log record at the EMERGENCY level. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function addEmergency($message, array $context = array()) { @@ -473,8 +527,13 @@ public static function getLevelName($level) */ public static function toMonologLevel($level) { - if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) { - return constant(__CLASS__.'::'.strtoupper($level)); + if (is_string($level)) { + // Contains chars of all log levels and avoids using strtoupper() which may have + // strange results depending on locale (for example, "i" will become "İ") + $upper = strtr($level, 'abcdefgilmnortuwy', 'ABCDEFGILMNORTUWY'); + if (defined(__CLASS__.'::'.$upper)) { + return constant(__CLASS__ . '::' . $upper); + } } return $level; @@ -484,7 +543,7 @@ public static function toMonologLevel($level) * Checks whether the Logger has a handler that listens on the given level * * @param int $level - * @return Boolean + * @return bool */ public function isHandling($level) { @@ -501,15 +560,52 @@ public function isHandling($level) return false; } + /** + * Set a custom exception handler + * + * @param callable $callback + * @return $this + */ + public function setExceptionHandler($callback) + { + if (!is_callable($callback)) { + throw new \InvalidArgumentException('Exception handler must be valid callable (callback or object with an __invoke method), '.var_export($callback, true).' given'); + } + $this->exceptionHandler = $callback; + + return $this; + } + + /** + * @return callable + */ + public function getExceptionHandler() + { + return $this->exceptionHandler; + } + + /** + * Delegates exception management to the custom exception handler, + * or throws the exception if no custom handler is set. + */ + protected function handleException(Exception $e, array $record) + { + if (!$this->exceptionHandler) { + throw $e; + } + + call_user_func($this->exceptionHandler, $e, $record); + } + /** * Adds a log record at an arbitrary level. * * This method allows for compatibility with common interfaces. * * @param mixed $level The log level - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function log($level, $message, array $context = array()) { @@ -523,9 +619,9 @@ public function log($level, $message, array $context = array()) * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function debug($message, array $context = array()) { @@ -537,9 +633,9 @@ public function debug($message, array $context = array()) * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function info($message, array $context = array()) { @@ -551,9 +647,9 @@ public function info($message, array $context = array()) * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function notice($message, array $context = array()) { @@ -565,9 +661,9 @@ public function notice($message, array $context = array()) * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function warn($message, array $context = array()) { @@ -579,9 +675,9 @@ public function warn($message, array $context = array()) * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function warning($message, array $context = array()) { @@ -593,9 +689,9 @@ public function warning($message, array $context = array()) * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function err($message, array $context = array()) { @@ -607,9 +703,9 @@ public function err($message, array $context = array()) * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function error($message, array $context = array()) { @@ -621,9 +717,9 @@ public function error($message, array $context = array()) * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function crit($message, array $context = array()) { @@ -635,9 +731,9 @@ public function crit($message, array $context = array()) * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function critical($message, array $context = array()) { @@ -649,9 +745,9 @@ public function critical($message, array $context = array()) * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function alert($message, array $context = array()) { @@ -663,9 +759,9 @@ public function alert($message, array $context = array()) * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function emerg($message, array $context = array()) { @@ -677,9 +773,9 @@ public function emerg($message, array $context = array()) * * This method allows for compatibility with common interfaces. * - * @param string $message The log message - * @param array $context The log context - * @return Boolean Whether the record has been processed + * @param string $message The log message + * @param array $context The log context + * @return bool Whether the record has been processed */ public function emergency($message, array $context = array()) { diff --git a/lib/monolog/monolog/src/Monolog/Processor/GitProcessor.php b/lib/monolog/monolog/src/Monolog/Processor/GitProcessor.php index 1899400..9fc3f50 100644 --- a/lib/monolog/monolog/src/Monolog/Processor/GitProcessor.php +++ b/lib/monolog/monolog/src/Monolog/Processor/GitProcessor.php @@ -19,7 +19,7 @@ * @author Nick Otter * @author Jordi Boggiano */ -class GitProcessor +class GitProcessor implements ProcessorInterface { private $level; private static $cache; diff --git a/lib/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php b/lib/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php index 2c07cae..6ae192a 100644 --- a/lib/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php +++ b/lib/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php @@ -24,7 +24,7 @@ * * @author Jordi Boggiano */ -class IntrospectionProcessor +class IntrospectionProcessor implements ProcessorInterface { private $level; diff --git a/lib/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php b/lib/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php index 85f9dc5..2a379a3 100644 --- a/lib/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php +++ b/lib/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php @@ -16,7 +16,7 @@ * * @author Rob Jensen */ -abstract class MemoryProcessor +abstract class MemoryProcessor implements ProcessorInterface { /** * @var bool If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported. @@ -34,8 +34,8 @@ abstract class MemoryProcessor */ public function __construct($realUsage = true, $useFormatting = true) { - $this->realUsage = (boolean) $realUsage; - $this->useFormatting = (boolean) $useFormatting; + $this->realUsage = (bool) $realUsage; + $this->useFormatting = (bool) $useFormatting; } /** diff --git a/lib/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php b/lib/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php index 7c07a7e..2f5b326 100644 --- a/lib/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php +++ b/lib/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php @@ -18,7 +18,7 @@ * * @author Jonathan A. Schweder */ -class MercurialProcessor +class MercurialProcessor implements ProcessorInterface { private $level; private static $cache; diff --git a/lib/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php b/lib/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php index 9d3f559..66b80fb 100644 --- a/lib/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php +++ b/lib/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php @@ -16,7 +16,7 @@ * * @author Andreas Hörnicke */ -class ProcessIdProcessor +class ProcessIdProcessor implements ProcessorInterface { /** * @param array $record diff --git a/lib/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php b/lib/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php new file mode 100644 index 0000000..7e64d4d --- /dev/null +++ b/lib/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +/** + * An optional interface to allow labelling Monolog processors. + * + * @author Nicolas Grekas + */ +interface ProcessorInterface +{ + /** + * @return array The processed records + */ + public function __invoke(array $records); +} diff --git a/lib/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php b/lib/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php index c2686ce..0088505 100644 --- a/lib/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php +++ b/lib/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php @@ -11,6 +11,8 @@ namespace Monolog\Processor; +use Monolog\Utils; + /** * Processes a record's message according to PSR-3 rules * @@ -18,7 +20,7 @@ * * @author Jordi Boggiano */ -class PsrLogMessageProcessor +class PsrLogMessageProcessor implements ProcessorInterface { /** * @param array $record @@ -35,7 +37,7 @@ public function __invoke(array $record) if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) { $replacements['{'.$key.'}'] = $val; } elseif (is_object($val)) { - $replacements['{'.$key.'}'] = '[object '.get_class($val).']'; + $replacements['{'.$key.'}'] = '[object '.Utils::getClass($val).']'; } else { $replacements['{'.$key.'}'] = '['.gettype($val).']'; } diff --git a/lib/monolog/monolog/src/Monolog/Processor/TagProcessor.php b/lib/monolog/monolog/src/Monolog/Processor/TagProcessor.php index 7e2df2a..615a4d9 100644 --- a/lib/monolog/monolog/src/Monolog/Processor/TagProcessor.php +++ b/lib/monolog/monolog/src/Monolog/Processor/TagProcessor.php @@ -16,7 +16,7 @@ * * @author Martijn Riemers */ -class TagProcessor +class TagProcessor implements ProcessorInterface { private $tags; diff --git a/lib/monolog/monolog/src/Monolog/Processor/UidProcessor.php b/lib/monolog/monolog/src/Monolog/Processor/UidProcessor.php index 812707c..d1f708c 100644 --- a/lib/monolog/monolog/src/Monolog/Processor/UidProcessor.php +++ b/lib/monolog/monolog/src/Monolog/Processor/UidProcessor.php @@ -11,12 +11,14 @@ namespace Monolog\Processor; +use Monolog\ResettableInterface; + /** * Adds a unique identifier into records * * @author Simon Mönch */ -class UidProcessor +class UidProcessor implements ProcessorInterface, ResettableInterface { private $uid; @@ -26,7 +28,8 @@ public function __construct($length = 7) throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32'); } - $this->uid = substr(hash('md5', uniqid('', true)), 0, $length); + + $this->uid = $this->generateUid($length); } public function __invoke(array $record) @@ -43,4 +46,14 @@ public function getUid() { return $this->uid; } + + public function reset() + { + $this->uid = $this->generateUid(strlen($this->uid)); + } + + private function generateUid($length) + { + return substr(hash('md5', uniqid('', true)), 0, $length); + } } diff --git a/lib/monolog/monolog/src/Monolog/Processor/WebProcessor.php b/lib/monolog/monolog/src/Monolog/Processor/WebProcessor.php index ea1d897..684188f 100644 --- a/lib/monolog/monolog/src/Monolog/Processor/WebProcessor.php +++ b/lib/monolog/monolog/src/Monolog/Processor/WebProcessor.php @@ -16,7 +16,7 @@ * * @author Jordi Boggiano */ -class WebProcessor +class WebProcessor implements ProcessorInterface { /** * @var array|\ArrayAccess diff --git a/lib/monolog/monolog/src/Monolog/ResettableInterface.php b/lib/monolog/monolog/src/Monolog/ResettableInterface.php new file mode 100644 index 0000000..635bc77 --- /dev/null +++ b/lib/monolog/monolog/src/Monolog/ResettableInterface.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +/** + * Handler or Processor implementing this interface will be reset when Logger::reset() is called. + * + * Resetting ends a log cycle gets them back to their initial state. + * + * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal + * state, and getting it back to a state in which it can receive log records again. + * + * This is useful in case you want to avoid logs leaking between two requests or jobs when you + * have a long running process like a worker or an application server serving multiple requests + * in one process. + * + * @author Grégoire Pineau + */ +interface ResettableInterface +{ + public function reset(); +} diff --git a/lib/monolog/monolog/src/Monolog/SignalHandler.php b/lib/monolog/monolog/src/Monolog/SignalHandler.php new file mode 100644 index 0000000..d87018f --- /dev/null +++ b/lib/monolog/monolog/src/Monolog/SignalHandler.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; +use ReflectionExtension; + +/** + * Monolog POSIX signal handler + * + * @author Robert Gust-Bardon + */ +class SignalHandler +{ + private $logger; + + private $previousSignalHandler = array(); + private $signalLevelMap = array(); + private $signalRestartSyscalls = array(); + + public function __construct(LoggerInterface $logger) + { + $this->logger = $logger; + } + + public function registerSignalHandler($signo, $level = LogLevel::CRITICAL, $callPrevious = true, $restartSyscalls = true, $async = true) + { + if (!extension_loaded('pcntl') || !function_exists('pcntl_signal')) { + return $this; + } + + if ($callPrevious) { + if (function_exists('pcntl_signal_get_handler')) { + $handler = pcntl_signal_get_handler($signo); + if ($handler === false) { + return $this; + } + $this->previousSignalHandler[$signo] = $handler; + } else { + $this->previousSignalHandler[$signo] = true; + } + } else { + unset($this->previousSignalHandler[$signo]); + } + $this->signalLevelMap[$signo] = $level; + $this->signalRestartSyscalls[$signo] = $restartSyscalls; + + if (function_exists('pcntl_async_signals') && $async !== null) { + pcntl_async_signals($async); + } + + pcntl_signal($signo, array($this, 'handleSignal'), $restartSyscalls); + + return $this; + } + + public function handleSignal($signo, array $siginfo = null) + { + static $signals = array(); + + if (!$signals && extension_loaded('pcntl')) { + $pcntl = new ReflectionExtension('pcntl'); + $constants = $pcntl->getConstants(); + if (!$constants) { + // HHVM 3.24.2 returns an empty array. + $constants = get_defined_constants(true); + $constants = $constants['Core']; + } + foreach ($constants as $name => $value) { + if (substr($name, 0, 3) === 'SIG' && $name[3] !== '_' && is_int($value)) { + $signals[$value] = $name; + } + } + unset($constants); + } + + $level = isset($this->signalLevelMap[$signo]) ? $this->signalLevelMap[$signo] : LogLevel::CRITICAL; + $signal = isset($signals[$signo]) ? $signals[$signo] : $signo; + $context = isset($siginfo) ? $siginfo : array(); + $this->logger->log($level, sprintf('Program received signal %s', $signal), $context); + + if (!isset($this->previousSignalHandler[$signo])) { + return; + } + + if ($this->previousSignalHandler[$signo] === true || $this->previousSignalHandler[$signo] === SIG_DFL) { + if (extension_loaded('pcntl') && function_exists('pcntl_signal') && function_exists('pcntl_sigprocmask') && function_exists('pcntl_signal_dispatch') + && extension_loaded('posix') && function_exists('posix_getpid') && function_exists('posix_kill')) { + $restartSyscalls = isset($this->signalRestartSyscalls[$signo]) ? $this->signalRestartSyscalls[$signo] : true; + pcntl_signal($signo, SIG_DFL, $restartSyscalls); + pcntl_sigprocmask(SIG_UNBLOCK, array($signo), $oldset); + posix_kill(posix_getpid(), $signo); + pcntl_signal_dispatch(); + pcntl_sigprocmask(SIG_SETMASK, $oldset); + pcntl_signal($signo, array($this, 'handleSignal'), $restartSyscalls); + } + } elseif (is_callable($this->previousSignalHandler[$signo])) { + if (PHP_VERSION_ID >= 70100) { + $this->previousSignalHandler[$signo]($signo, $siginfo); + } else { + $this->previousSignalHandler[$signo]($signo); + } + } + } +} diff --git a/lib/monolog/monolog/src/Monolog/Utils.php b/lib/monolog/monolog/src/Monolog/Utils.php new file mode 100644 index 0000000..180a159 --- /dev/null +++ b/lib/monolog/monolog/src/Monolog/Utils.php @@ -0,0 +1,159 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +class Utils +{ + /** + * @internal + */ + public static function getClass($object) + { + $class = \get_class($object); + + return 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; + } + + /** + * Return the JSON representation of a value + * + * @param mixed $data + * @param int $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE + * @param bool $ignoreErrors whether to ignore encoding errors or to throw on error, when ignored and the encoding fails, "null" is returned which is valid json for null + * @throws \RuntimeException if encoding fails and errors are not ignored + * @return string + */ + public static function jsonEncode($data, $encodeFlags = null, $ignoreErrors = false) + { + if (null === $encodeFlags && version_compare(PHP_VERSION, '5.4.0', '>=')) { + $encodeFlags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE; + } + + if ($ignoreErrors) { + $json = @json_encode($data, $encodeFlags); + if (false === $json) { + return 'null'; + } + + return $json; + } + + $json = json_encode($data, $encodeFlags); + if (false === $json) { + $json = self::handleJsonError(json_last_error(), $data); + } + + return $json; + } + + /** + * Handle a json_encode failure. + * + * If the failure is due to invalid string encoding, try to clean the + * input and encode again. If the second encoding attempt fails, the + * inital error is not encoding related or the input can't be cleaned then + * raise a descriptive exception. + * + * @param int $code return code of json_last_error function + * @param mixed $data data that was meant to be encoded + * @param int $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE + * @throws \RuntimeException if failure can't be corrected + * @return string JSON encoded data after error correction + */ + public static function handleJsonError($code, $data, $encodeFlags = null) + { + if ($code !== JSON_ERROR_UTF8) { + self::throwEncodeError($code, $data); + } + + if (is_string($data)) { + self::detectAndCleanUtf8($data); + } elseif (is_array($data)) { + array_walk_recursive($data, array('Monolog\Utils', 'detectAndCleanUtf8')); + } else { + self::throwEncodeError($code, $data); + } + + if (null === $encodeFlags && version_compare(PHP_VERSION, '5.4.0', '>=')) { + $encodeFlags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE; + } + + $json = json_encode($data, $encodeFlags); + + if ($json === false) { + self::throwEncodeError(json_last_error(), $data); + } + + return $json; + } + + /** + * Throws an exception according to a given code with a customized message + * + * @param int $code return code of json_last_error function + * @param mixed $data data that was meant to be encoded + * @throws \RuntimeException + */ + private static function throwEncodeError($code, $data) + { + switch ($code) { + case JSON_ERROR_DEPTH: + $msg = 'Maximum stack depth exceeded'; + break; + case JSON_ERROR_STATE_MISMATCH: + $msg = 'Underflow or the modes mismatch'; + break; + case JSON_ERROR_CTRL_CHAR: + $msg = 'Unexpected control character found'; + break; + case JSON_ERROR_UTF8: + $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded'; + break; + default: + $msg = 'Unknown error'; + } + + throw new \RuntimeException('JSON encoding failed: '.$msg.'. Encoding: '.var_export($data, true)); + } + + /** + * Detect invalid UTF-8 string characters and convert to valid UTF-8. + * + * Valid UTF-8 input will be left unmodified, but strings containing + * invalid UTF-8 codepoints will be reencoded as UTF-8 with an assumed + * original encoding of ISO-8859-15. This conversion may result in + * incorrect output if the actual encoding was not ISO-8859-15, but it + * will be clean UTF-8 output and will not rely on expensive and fragile + * detection algorithms. + * + * Function converts the input in place in the passed variable so that it + * can be used as a callback for array_walk_recursive. + * + * @param mixed &$data Input to check and convert if needed + * @private + */ + public static function detectAndCleanUtf8(&$data) + { + if (is_string($data) && !preg_match('//u', $data)) { + $data = preg_replace_callback( + '/[\x80-\xFF]+/', + function ($m) { return utf8_encode($m[0]); }, + $data + ); + $data = str_replace( + array('¤', '¦', '¨', '´', '¸', '¼', '½', '¾'), + array('€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'), + $data + ); + } + } +} diff --git a/lib/psr/log/Psr/Log/LoggerInterface.php b/lib/psr/log/Psr/Log/LoggerInterface.php index 5ea7243..e695046 100644 --- a/lib/psr/log/Psr/Log/LoggerInterface.php +++ b/lib/psr/log/Psr/Log/LoggerInterface.php @@ -118,6 +118,8 @@ public function debug($message, array $context = array()); * @param array $context * * @return void + * + * @throws \Psr\Log\InvalidArgumentException */ public function log($level, $message, array $context = array()); } diff --git a/lib/psr/log/Psr/Log/LoggerTrait.php b/lib/psr/log/Psr/Log/LoggerTrait.php index 867225d..e392fef 100644 --- a/lib/psr/log/Psr/Log/LoggerTrait.php +++ b/lib/psr/log/Psr/Log/LoggerTrait.php @@ -135,6 +135,8 @@ public function debug($message, array $context = array()) * @param array $context * * @return void + * + * @throws \Psr\Log\InvalidArgumentException */ abstract public function log($level, $message, array $context = array()); } diff --git a/lib/psr/log/Psr/Log/NullLogger.php b/lib/psr/log/Psr/Log/NullLogger.php index d8cd682..c8f7293 100644 --- a/lib/psr/log/Psr/Log/NullLogger.php +++ b/lib/psr/log/Psr/Log/NullLogger.php @@ -20,6 +20,8 @@ class NullLogger extends AbstractLogger * @param array $context * * @return void + * + * @throws \Psr\Log\InvalidArgumentException */ public function log($level, $message, array $context = array()) { diff --git a/lib/psr/log/Psr/Log/Test/LoggerInterfaceTest.php b/lib/psr/log/Psr/Log/Test/LoggerInterfaceTest.php index a0391a5..9ecb6c4 100644 --- a/lib/psr/log/Psr/Log/Test/LoggerInterfaceTest.php +++ b/lib/psr/log/Psr/Log/Test/LoggerInterfaceTest.php @@ -4,6 +4,7 @@ use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; +use PHPUnit\Framework\TestCase; /** * Provides a base test class for ensuring compliance with the LoggerInterface. @@ -11,7 +12,7 @@ * Implementors can extend the class and implement abstract methods to run this * as part of their test suite. */ -abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase +abstract class LoggerInterfaceTest extends TestCase { /** * @return LoggerInterface @@ -101,6 +102,9 @@ public function testObjectCastToString() public function testContextCanContainAnything() { + $closed = fopen('php://memory', 'r'); + fclose($closed); + $context = array( 'bool' => true, 'null' => null, @@ -110,6 +114,7 @@ public function testContextCanContainAnything() 'nested' => array('with object' => new DummyTest), 'object' => new \DateTime, 'resource' => fopen('php://memory', 'r'), + 'closed' => $closed, ); $this->getLogger()->warning('Crazy context data', $context); @@ -136,5 +141,6 @@ class DummyTest { public function __toString() { + return 'DummyTest'; } } diff --git a/lib/psr/log/Psr/Log/Test/TestLogger.php b/lib/psr/log/Psr/Log/Test/TestLogger.php new file mode 100644 index 0000000..1be3230 --- /dev/null +++ b/lib/psr/log/Psr/Log/Test/TestLogger.php @@ -0,0 +1,147 @@ + $level, + 'message' => $message, + 'context' => $context, + ]; + + $this->recordsByLevel[$record['level']][] = $record; + $this->records[] = $record; + } + + public function hasRecords($level) + { + return isset($this->recordsByLevel[$level]); + } + + public function hasRecord($record, $level) + { + if (is_string($record)) { + $record = ['message' => $record]; + } + return $this->hasRecordThatPasses(function ($rec) use ($record) { + if ($rec['message'] !== $record['message']) { + return false; + } + if (isset($record['context']) && $rec['context'] !== $record['context']) { + return false; + } + return true; + }, $level); + } + + public function hasRecordThatContains($message, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($message) { + return strpos($rec['message'], $message) !== false; + }, $level); + } + + public function hasRecordThatMatches($regex, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($regex) { + return preg_match($regex, $rec['message']) > 0; + }, $level); + } + + public function hasRecordThatPasses(callable $predicate, $level) + { + if (!isset($this->recordsByLevel[$level])) { + return false; + } + foreach ($this->recordsByLevel[$level] as $i => $rec) { + if (call_user_func($predicate, $rec, $i)) { + return true; + } + } + return false; + } + + public function __call($method, $args) + { + if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { + $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; + $level = strtolower($matches[2]); + if (method_exists($this, $genericMethod)) { + $args[] = $level; + return call_user_func_array([$this, $genericMethod], $args); + } + } + throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); + } + + public function reset() + { + $this->records = []; + $this->recordsByLevel = []; + } +} diff --git a/lib/psr/log/README.md b/lib/psr/log/README.md index 574bc1c..a9f20c4 100644 --- a/lib/psr/log/README.md +++ b/lib/psr/log/README.md @@ -7,6 +7,13 @@ This repository holds all interfaces/classes/traits related to Note that this is not a logger of its own. It is merely an interface that describes a logger. See the specification for more details. +Installation +------------ + +```bash +composer require psr/log +``` + Usage ----- @@ -31,6 +38,12 @@ class Foo if ($this->logger) { $this->logger->info('Doing work'); } + + try { + $this->doSomethingElse(); + } catch (Exception $exception) { + $this->logger->error('Oh no!', array('exception' => $exception)); + } // do something useful } diff --git a/lib/psr/log/composer.json b/lib/psr/log/composer.json index 87934d7..3f6d4ee 100644 --- a/lib/psr/log/composer.json +++ b/lib/psr/log/composer.json @@ -20,7 +20,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } } } diff --git a/payline.php b/payline.php index b4652d3..fd7df24 100644 --- a/payline.php +++ b/payline.php @@ -4,7 +4,7 @@ * * @author Monext * @copyright Monext - http://www.payline.com - * @version 2.1.0 + * @version 2.2.7 */ if (!defined('_PS_VERSION_')) { @@ -90,7 +90,7 @@ public function __construct() $this->name = 'payline'; $this->tab = 'payments_gateways'; $this->module_key = ''; - $this->version = '2.2.4'; + $this->version = '2.2.7'; $this->author = 'Monext'; $this->need_instance = true; @@ -360,19 +360,7 @@ protected function processFullOrderRefund(Order $order) $orderSlipDetailsList = array(); // Amount for refund - $amountToRefund = 0.00; - foreach ($order->getProducts() as $idOrderDetail => $product) { - if (($product['product_quantity'] - $product['product_quantity_refunded']) > 0) { - $orderSlipDetailsList[(int)$idOrderDetail] = array( - 'id_order_detail' => $idOrderDetail, - 'quantity' => ($product['product_quantity'] - $product['product_quantity_refunded']), - 'unit_price' => (float)$product['unit_price_tax_excl'], - 'amount' => $product['unit_price_tax_incl'] * ($product['product_quantity'] - $product['product_quantity_refunded']), - ); - } - $amountToRefund += round(($product['product_price_wt'] * $product['product_quantity']), 2); - } - $amountToRefund += (float)($order->total_shipping); + $amountToRefund = $transaction['payment']['amount'] / 100; // Create order slip (available since PS 1.6.0.11) if (method_exists('OrderSlip', 'create')) { @@ -413,16 +401,15 @@ protected function processTransactionCapture(Order $order, $idTransaction, $doRe $capture = PaylinePaymentGateway::captureTransaction($idTransaction, 'CPT', $this->l('Manual capture from PrestaShop BackOffice')); if (PaylinePaymentGateway::isValidResponse($capture)) { // Capture OK - // Change order state - $history = new OrderHistory(); - $history->id_order = (int)$order->id; - $history->changeIdOrderState(_PS_OS_PAYMENT_, (int)$order->id); - $history->addWithemail(); + if (Configuration::get('PAYLINE_WEB_CASH_VALIDATION') != _PS_OS_PAYMENT_) { + // Change order state + $history = new OrderHistory(); + $history->id_order = (int)$order->id; + $history->changeIdOrderState(_PS_OS_PAYMENT_, (int)$order->id); + $history->addWithemail(); + } if ($doRedirect) { - // Wait 1s because Payline API may take some time to be updated after a capture - sleep(1); - Tools::redirectAdmin($this->context->link->getAdminLink('AdminOrders') . '&id_order=' . $order->id . '&vieworder&paylineCaptureOK=1'); } } else { @@ -3029,7 +3016,7 @@ public function processRecNotification($idTransaction, $paymentRecordId) } /** - * Clone of Order::addOrderPayment() - We force total_paid_real to be = 0 instead of a negative value, so we can update without warning + * Clone of Order::addOrderPayment() * @since 2.0.0 * @return bool */ @@ -3046,8 +3033,7 @@ protected function addOrderPaymentAfterRefund(Order $order, $amount_paid, $payme $order_payment->amount = $amount_paid; $order_payment->date_add = ($date ? $date : null); - // Force total_paid_real to 0 - $order->total_paid_real = 0; + $order->total_paid_real = max(0, $order->total_paid_real - abs($amount_paid)); // We put autodate parameter of add method to true if date_add field is null $res = $order_payment->add(is_null($order_payment->date_add)) && $order->update(); diff --git a/translations/fr.php b/translations/fr.php index 1f108ef..4a04f19 100644 --- a/translations/fr.php +++ b/translations/fr.php @@ -102,7 +102,7 @@ $_MODULE['<{payline}prestashop>payline_2715d06f9a029a951c5c8b66903badd5'] = 'Configuration des contrats'; $_MODULE['<{payline}prestashop>payline_1c6ddba6ebafc01b08f21aefd7993899'] = 'Sélectionnez et triez les contrats que vous souhaitez rendre disponibles à vos clients'; $_MODULE['<{payline}prestashop>payline_cc0ca8cd23cacc40345b234594a3df42'] = 'Vous pouvez trier les contrats en utilisant la méthode glisser & déposer'; -$_MODULE['<{payline}prestashop>payline_7dbab2bc66cba2aeb56aec68973b3c53'] = 'Sélectionnez et triez les contrats alternatfis que vous souhaitez rendre disponibles à vos clients'; +$_MODULE['<{payline}prestashop>payline_7dbab2bc66cba2aeb56aec68973b3c53'] = 'Sélectionnez et triez les contrats alternatifs que vous souhaitez rendre disponibles à vos clients'; $_MODULE['<{payline}prestashop>payline_558b49eb972c3c62a1a4e5b6d91420ae'] = 'Configuration enregistrée.'; $_MODULE['<{payline}prestashop>payline_3cd289dd8822372e7348bb7fda88de1b'] = 'La commande ne peut pas être créée car le montant payé est différent du total de votre panier.'; $_MODULE['<{payline}prestashop>payline_a8823d45d4a0c43caa6f5eb36e200381'] = 'La commande ne peut pas être créée car le panier n\'existe pas.'; diff --git a/views/templates/admin/landing.tpl b/views/templates/admin/landing.tpl index e7524a4..f8d9dbe 100644 --- a/views/templates/admin/landing.tpl +++ b/views/templates/admin/landing.tpl @@ -20,11 +20,5 @@

{l s='More information on www.payline.com.' mod='payline'}

-
-
-

{l s='Need help ?' mod='payline'}

-

{l s='Find our documentation or contact our team through support.payline.com.' mod='payline'}

-
-
\ No newline at end of file