This commit is contained in:
David Remer 2020-04-06 11:16:18 +03:00
parent 7fd57b9393
commit 005a55c213
62 changed files with 905 additions and 751 deletions

View file

@ -1,7 +1,6 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient; namespace Inpsyde\PayPalCommerce\ApiClient;
use Dhii\Modular\Module\ModuleInterface; use Dhii\Modular\Module\ModuleInterface;

View file

@ -20,23 +20,23 @@ use Inpsyde\PayPalCommerce\ApiClient\Repository\CartRepository;
return [ return [
'api.host' => function(ContainerInterface $container) : string { 'api.host' => function (ContainerInterface $container) : string {
return 'https://api.sandbox.paypal.com'; return 'https://api.sandbox.paypal.com';
}, },
'api.key' => function(ContainerInterface $container) : string { 'api.key' => function (ContainerInterface $container) : string {
return 'AQB97CzMsd58-It1vxbcDAGvMuXNCXRD9le_XUaMlHB_U7XsU9IiItBwGQOtZv9sEeD6xs2vlIrL4NiD'; return 'AQB97CzMsd58-It1vxbcDAGvMuXNCXRD9le_XUaMlHB_U7XsU9IiItBwGQOtZv9sEeD6xs2vlIrL4NiD';
}, },
'api.secret' => function(ContainerInterface $container) : string { 'api.secret' => function (ContainerInterface $container) : string {
return 'EILGMYK_0iiSbja8hT-nCBGl0BvKxEB4riHgyEO7QWDeUzCJ5r42JUEvrI7gpGyw0Qww8AIXxSdCIAny'; return 'EILGMYK_0iiSbja8hT-nCBGl0BvKxEB4riHgyEO7QWDeUzCJ5r42JUEvrI7gpGyw0Qww8AIXxSdCIAny';
}, },
'api.bearer' => function(ContainerInterface $container) : Bearer { 'api.bearer' => function (ContainerInterface $container) : Bearer {
return new Bearer( return new Bearer(
$container->get('api.host'), $container->get('api.host'),
$container->get('api.key'), $container->get('api.key'),
$container->get('api.secret') $container->get('api.secret')
); );
}, },
'api.endpoint.order' => function(ContainerInterface $container) : OrderEndpoint { 'api.endpoint.order' => function (ContainerInterface $container) : OrderEndpoint {
$sessionHandler = $container->get('session.handler'); $sessionHandler = $container->get('session.handler');
$orderFactory = $container->get('api.factory.order'); $orderFactory = $container->get('api.factory.order');
$patchCollectionFactory = $container->get('api.factory.patch-collection-factory'); $patchCollectionFactory = $container->get('api.factory.patch-collection-factory');
@ -48,20 +48,24 @@ return [
$patchCollectionFactory $patchCollectionFactory
); );
}, },
'api.cart-repository' => function(ContainerInterface $container) : CartRepository { 'api.cart-repository' => function (ContainerInterface $container) : CartRepository {
/* /*
* ToDo: We need to watch out and see, if we can load the Cart Repository only on specific situations. * ToDo: We need to watch out and see, if we can load the Cart Repository
* Current problem can be seen here: http://ppc-dev-website.localhost/wp-admin/admin.php?page=wc-settings&tab=tax * only on specific situations.
* @see http://ppc-dev-website.localhost/wp-admin/admin.php?page=wc-settings&tab=tax
*/ */
$cart = WC()->cart; $cart = WC()->cart;
if (! $cart) { if (! $cart) {
// ToDo: The cart repository gets pulled in the wp-admin, where there is no WC Cart loaded. Rethink. /**
* ToDo: The cart repository gets pulled in the wp-admin,
* where there is no WC Cart loaded. Rethink.
**/
$cart = new \WC_Cart(); $cart = new \WC_Cart();
} }
$factory = $container->get('api.factory.purchase-unit'); $factory = $container->get('api.factory.purchase-unit');
return new CartRepository($cart, $factory); return new CartRepository($cart, $factory);
}, },
'api.factory.purchase-unit' => function(ContainerInterface $container) : PurchaseUnitFactory { 'api.factory.purchase-unit' => function (ContainerInterface $container) : PurchaseUnitFactory {
$amountFactory = $container->get('api.factory.amount'); $amountFactory = $container->get('api.factory.amount');
$payeeFactory = $container->get('api.factory.payee'); $payeeFactory = $container->get('api.factory.payee');
@ -74,30 +78,31 @@ return [
$shippingFactory $shippingFactory
); );
}, },
'api.factory.patch-collection-factory' => function(ContainerInterface $container) : PatchCollectionFactory { 'api.factory.patch-collection-factory' => function (ContainerInterface $container)
: PatchCollectionFactory {
return new PatchCollectionFactory(); return new PatchCollectionFactory();
}, },
'api.factory.payee' => function(ContainerInterface $container) : PayeeFactory { 'api.factory.payee' => function (ContainerInterface $container) : PayeeFactory {
return new PayeeFactory(); return new PayeeFactory();
}, },
'api.factory.item' => function(ContainerInterface $container) : ItemFactory { 'api.factory.item' => function (ContainerInterface $container) : ItemFactory {
return new ItemFactory(); return new ItemFactory();
}, },
'api.factory.shipping' => function(ContainerInterface $container) : ShippingFactory { 'api.factory.shipping' => function (ContainerInterface $container) : ShippingFactory {
$addressFactory = $container->get('api.factory.address'); $addressFactory = $container->get('api.factory.address');
return new ShippingFactory($addressFactory); return new ShippingFactory($addressFactory);
}, },
'api.factory.amount' => function(ContainerInterface $container) : AmountFactory { 'api.factory.amount' => function (ContainerInterface $container) : AmountFactory {
return new AmountFactory(); return new AmountFactory();
}, },
'api.factory.payer' => function(ContainerInterface $container) : PayerFactory { 'api.factory.payer' => function (ContainerInterface $container) : PayerFactory {
$addressFactory = $container->get('api.factory.address'); $addressFactory = $container->get('api.factory.address');
return new PayerFactory($addressFactory); return new PayerFactory($addressFactory);
}, },
'api.factory.address' => function(ContainerInterface $container) : AddressFactory { 'api.factory.address' => function (ContainerInterface $container) : AddressFactory {
return new AddressFactory(); return new AddressFactory();
}, },
'api.factory.order' => function(ContainerInterface $container) : OrderFactory { 'api.factory.order' => function (ContainerInterface $container) : OrderFactory {
$purchaseUnitFactory = $container->get('api.factory.purchase-unit'); $purchaseUnitFactory = $container->get('api.factory.purchase-unit');
$payerFactory = $container->get('api.factory.payer'); $payerFactory = $container->get('api.factory.payer');
return new OrderFactory($purchaseUnitFactory, $payerFactory); return new OrderFactory($purchaseUnitFactory, $payerFactory);

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient; namespace Inpsyde\PayPalCommerce\ApiClient;
use Dhii\Container\ServiceProvider; use Dhii\Container\ServiceProvider;
use Dhii\Modular\Module\Exception\ModuleExceptionInterface; use Dhii\Modular\Module\Exception\ModuleExceptionInterface;
use Dhii\Modular\Module\ModuleInterface; use Dhii\Modular\Module\ModuleInterface;
@ -21,7 +20,7 @@ class ApiModule implements ModuleInterface
); );
} }
public function run(ContainerInterface $c) public function run(ContainerInterface $container)
{ {
// TODO: Implement run() method. // TODO: Implement run() method.
} }

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Authentication; namespace Inpsyde\PayPalCommerce\ApiClient\Authentication;
use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException; use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException;
class Bearer class Bearer
@ -23,7 +22,7 @@ class Bearer
{ {
//ToDo: Do not store with wp_cache_get but as transient. //ToDo: Do not store with wp_cache_get but as transient.
$bearer = wp_cache_get(self::CACHE_KEY); $bearer = wp_cache_get(self::CACHE_KEY);
if ( ! $bearer) { if (! $bearer) {
return $this->newBearer(); return $this->newBearer();
} }
return (string) $bearer; return (string) $bearer;

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Endpoint; namespace Inpsyde\PayPalCommerce\ApiClient\Endpoint;
use Inpsyde\PayPalCommerce\ApiClient\Authentication\Bearer; use Inpsyde\PayPalCommerce\ApiClient\Authentication\Bearer;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Order; use Inpsyde\PayPalCommerce\ApiClient\Entity\Order;
use Inpsyde\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use Inpsyde\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
@ -35,14 +34,14 @@ class OrderEndpoint
$this->patchCollectionFactory = $patchCollectionFactory; $this->patchCollectionFactory = $patchCollectionFactory;
} }
public function createForPurchaseUnits(PurchaseUnit ...$items) : Order { public function createForPurchaseUnits(PurchaseUnit ...$items) : Order
{
$bearer = $this->bearer->bearer(); $bearer = $this->bearer->bearer();
$data = [ $data = [
'intent' => 'CAPTURE', 'intent' => 'CAPTURE',
'purchase_units' => array_map( 'purchase_units' => array_map(
function(PurchaseUnit $item) : array { function (PurchaseUnit $item) : array {
return $item->toArray(); return $item->toArray();
}, },
$items $items
@ -63,13 +62,12 @@ class OrderEndpoint
} }
$json = json_decode($response['body']); $json = json_decode($response['body']);
$order = $this->orderFactory->fromPayPalResponse($json); $order = $this->orderFactory->fromPayPalResponse($json);
$this->sessionHandler->setOrder($order); $this->sessionHandler->replaceOrder($order);
return $order; return $order;
} }
public function capture(Order $order) : Order public function capture(Order $order) : Order
{ {
$bearer = $this->bearer->bearer(); $bearer = $this->bearer->bearer();
$url = trailingslashit($this->host) . 'v2/checkout/orders/' . $order->id() . '/capture'; $url = trailingslashit($this->host) . 'v2/checkout/orders/' . $order->id() . '/capture';
$args = [ $args = [
@ -77,7 +75,7 @@ class OrderEndpoint
'Authorization' => 'Bearer ' . $bearer, 'Authorization' => 'Bearer ' . $bearer,
'Content-Type' => 'application/json', 'Content-Type' => 'application/json',
'Prefer' => 'return=representation', 'Prefer' => 'return=representation',
] ],
]; ];
$response = wp_remote_post($url, $args); $response = wp_remote_post($url, $args);
/** /**
@ -92,12 +90,12 @@ class OrderEndpoint
} }
$json = json_decode($response['body']); $json = json_decode($response['body']);
$order = $this->orderFactory->fromPayPalResponse($json); $order = $this->orderFactory->fromPayPalResponse($json);
$this->sessionHandler->setOrder($order); $this->sessionHandler->replaceOrder($order);
return $order; return $order;
} }
public function order(string $id) : Order { public function order(string $id) : Order
{
$bearer = $this->bearer->bearer(); $bearer = $this->bearer->bearer();
$url = trailingslashit($this->host) . 'v2/checkout/orders/' . $id; $url = trailingslashit($this->host) . 'v2/checkout/orders/' . $id;
$args = [ $args = [
@ -114,13 +112,13 @@ class OrderEndpoint
return $this->orderFactory->fromPayPalResponse($json); return $this->orderFactory->fromPayPalResponse($json);
} }
public function patchOrderWith(Order $orderToUpdate, Order $orderToCompare) : Order { public function patchOrderWith(Order $orderToUpdate, Order $orderToCompare) : Order
{
$patches = $this->patchCollectionFactory->fromOrders($orderToCompare, $orderToCompare); $patches = $this->patchCollectionFactory->fromOrders($orderToCompare, $orderToCompare);
if (! count($patches->patches())) { if (! count($patches->patches())) {
return $orderToUpdate; return $orderToUpdate;
} }
$bearer = $this->bearer->bearer(); $bearer = $this->bearer->bearer();
$url = trailingslashit($this->host) . 'v2/checkout/orders/' . $orderToUpdate->id(); $url = trailingslashit($this->host) . 'v2/checkout/orders/' . $orderToUpdate->id();
$args = [ $args = [
@ -138,7 +136,7 @@ class OrderEndpoint
} }
$newOrder = $this->order($orderToUpdate->id()); $newOrder = $this->order($orderToUpdate->id());
$this->sessionHandler->setOrder($newOrder); $this->sessionHandler->replaceOrder($newOrder);
return $newOrder; return $newOrder;
} }
} }

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class Address class Address
{ {
private $countryCode; private $countryCode;
@ -19,8 +18,8 @@ class Address
string $adminArea1 = '', string $adminArea1 = '',
string $adminArea2 = '', string $adminArea2 = '',
string $postalCode = '' string $postalCode = ''
) ) {
{
$this->countryCode = $countryCode; $this->countryCode = $countryCode;
$this->addressLine1 = $addressLine1; $this->addressLine1 = $addressLine1;
$this->addressLine2 = $addressLine2; $this->addressLine2 = $addressLine2;
@ -29,22 +28,33 @@ class Address
$this->postalCode = $postalCode; $this->postalCode = $postalCode;
} }
public function countryCode() : string { public function countryCode() : string
{
return $this->countryCode; return $this->countryCode;
} }
public function addressLine1() : string {
public function addressLine1() : string
{
return $this->addressLine1; return $this->addressLine1;
} }
public function addressLine2() : string {
public function addressLine2() : string
{
return $this->addressLine2; return $this->addressLine2;
} }
public function adminArea1() : string {
public function adminArea1() : string
{
return $this->adminArea1; return $this->adminArea1;
} }
public function adminArea2() : string {
public function adminArea2() : string
{
return $this->adminArea2; return $this->adminArea2;
} }
public function postalCode() : string {
public function postalCode() : string
{
return $this->postalCode; return $this->postalCode;
} }

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class Amount class Amount
{ {

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class AmountBreakdown class AmountBreakdown
{ {

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class Item class Item
{ {
@ -30,6 +29,7 @@ class Item
string $sku = '', string $sku = '',
string $category = 'PHYSICAL_GOODS' string $category = 'PHYSICAL_GOODS'
) { ) {
$this->name = $name; $this->name = $name;
$this->unitAmount = $unitAmount; $this->unitAmount = $unitAmount;
$this->quantity = $quantity; $this->quantity = $quantity;
@ -39,35 +39,43 @@ class Item
$this->category = ($category === self::DIGITAL_GOODS) ? self::DIGITAL_GOODS : self::PHYSICAL_GOODS; $this->category = ($category === self::DIGITAL_GOODS) ? self::DIGITAL_GOODS : self::PHYSICAL_GOODS;
} }
public function name() : string { public function name() : string
{
return $this->name; return $this->name;
} }
public function unitAmount() : Money { public function unitAmount() : Money
{
return $this->unitAmount; return $this->unitAmount;
} }
public function quantity() : int { public function quantity() : int
{
return $this->quantity; return $this->quantity;
} }
public function description() : string { public function description() : string
{
return $this->description; return $this->description;
} }
public function tax() : ?Money { public function tax() : ?Money
{
return $this->tax; return $this->tax;
} }
public function sku() : string { public function sku() : string
{
return $this->sku; return $this->sku;
} }
public function category() : string { public function category() : string
{
return $this->category; return $this->category;
} }
public function toArray() : array { public function toArray() : array
{
$item = [ $item = [
'name' => $this->name(), 'name' => $this->name(),
'unit_amount' => $this->unitAmount()->toArray(), 'unit_amount' => $this->unitAmount()->toArray(),

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class Money class Money
{ {
@ -25,7 +24,8 @@ class Money
return $this->currencyCode; return $this->currencyCode;
} }
public function toArray() : array { public function toArray() : array
{
return [ return [
'currency_code' => $this->currencyCode(), 'currency_code' => $this->currencyCode(),
'value' => $this->value(), 'value' => $this->value(),

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class Order class Order
{ {
@ -29,14 +28,17 @@ class Order
string $intent = 'CAPTURE', string $intent = 'CAPTURE',
\DateTime $updateTime = null \DateTime $updateTime = null
) { ) {
$this->id = $id; $this->id = $id;
$this->createTime = $createTime; $this->createTime = $createTime;
//phpcs:disable Inpsyde.CodeQuality.ArgumentTypeDeclaration.NoArgumentType
$this->purchaseUnits = array_values(array_filter( $this->purchaseUnits = array_values(array_filter(
$purchaseUnits, $purchaseUnits,
function($unit) : bool { function ($unit) : bool {
return is_a($unit, PurchaseUnit::class); return is_a($unit, PurchaseUnit::class);
} }
)); ));
//phpcs:enable Inpsyde.CodeQuality.ArgumentTypeDeclaration.NoArgumentType
$this->payer = $payer; $this->payer = $payer;
$this->orderStatus = $orderStatus; $this->orderStatus = $orderStatus;
$this->intent = ($intent === 'CAPTURE') ? 'CAPTURE' : 'AUTHORIZE'; $this->intent = ($intent === 'CAPTURE') ? 'CAPTURE' : 'AUTHORIZE';
@ -44,30 +46,36 @@ class Order
$this->updateTime = $updateTime; $this->updateTime = $updateTime;
} }
public function id() : string { public function id() : string
{
return $this->id; return $this->id;
} }
public function createTime() : \DateTime { public function createTime() : \DateTime
{
return $this->createTime; return $this->createTime;
} }
public function updateTime() : ?\DateTime { public function updateTime() : ?\DateTime
{
return $this->updateTime; return $this->updateTime;
} }
public function intent() : string { public function intent() : string
{
return $this->intent; return $this->intent;
} }
public function payer() : ?Payer { public function payer() : ?Payer
{
return $this->payer; return $this->payer;
} }
/** /**
* @return PurchaseUnit[] * @return PurchaseUnit[]
*/ */
public function purchaseUnits() : array { public function purchaseUnits() : array
{
return $this->purchaseUnits; return $this->purchaseUnits;
} }
@ -76,13 +84,14 @@ class Order
return $this->orderStatus; return $this->orderStatus;
} }
public function toArray() : array { public function toArray() : array
{
$order = [ $order = [
'id' => $this->id(), 'id' => $this->id(),
'intent' => $this->intent(), 'intent' => $this->intent(),
'status' => $this->status()->name(), 'status' => $this->status()->name(),
'purchase_units' => array_map( 'purchase_units' => array_map(
function(PurchaseUnit $unit) : array { function (PurchaseUnit $unit) : array {
return $unit->toArray(); return $unit->toArray();
}, },
$this->purchaseUnits() $this->purchaseUnits()

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException; use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException;
class OrderStatus class OrderStatus
@ -25,9 +24,11 @@ class OrderStatus
]; ];
private $status; private $status;
public function __construct(string $status) { public function __construct(string $status)
{
if (! in_array($status, self::VALID_STATI, true)) { if (! in_array($status, self::VALID_STATI, true)) {
throw new RuntimeException(sprintf( throw new RuntimeException(sprintf(
// translators: %s is the current status.
__("%s is not a valid status", "woocmmerce-paypal-commerce-gateway"), __("%s is not a valid status", "woocmmerce-paypal-commerce-gateway"),
$status $status
)); ));

View file

@ -3,7 +3,7 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
//phpcs:disable Inpsyde.CodeQuality.ElementNameMinimalLength.TooShort
class Patch class Patch
{ {
@ -17,19 +17,25 @@ class Patch
$this->value = $value; $this->value = $value;
} }
public function op() : string { public function op() : string
{
return $this->op; return $this->op;
} }
public function path() : string { public function path() : string
{
return $this->path; return $this->path;
} }
public function value() { // phpcs:disable Inpsyde.CodeQuality.ReturnTypeDeclaration.NoReturnType
public function value()
{
return $this->value; return $this->value;
} }
// phpcs:enable Inpsyde.CodeQuality.ReturnTypeDeclaration.NoReturnType
public function toArray() : array { public function toArray() : array
{
return [ return [
'op' => $this->op(), 'op' => $this->op(),
'value' => $this->value(), 'value' => $this->value(),
@ -43,7 +49,8 @@ class Patch
* *
* @return string * @return string
*/ */
public function from() : string { public function from() : string
{
return ''; return '';
} }
} }

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class PatchCollection class PatchCollection
{ {
@ -24,7 +23,7 @@ class PatchCollection
public function toArray() : array public function toArray() : array
{ {
return array_map( return array_map(
function(Patch $patch) : array { function (Patch $patch) : array {
return $patch->toArray(); return $patch->toArray();
}, },
$this->patches() $this->patches()

View file

@ -19,19 +19,23 @@ class Payee
string $email, string $email,
string $merchantId string $merchantId
) { ) {
$this->email = $email; $this->email = $email;
$this->merchantId = $merchantId; $this->merchantId = $merchantId;
} }
public function email() : string { public function email() : string
{
return $this->email; return $this->email;
} }
public function merchantId() : string { public function merchantId() : string
{
return $this->merchantId; return $this->merchantId;
} }
public function toArray() : array { public function toArray() : array
{
return [ return [
'email_address' => $this->email(), 'email_address' => $this->email(),
'merchant_id' => $this->merchantId(), 'merchant_id' => $this->merchantId(),

View file

@ -29,6 +29,7 @@ class Payer
PhoneWithType $phone = null, PhoneWithType $phone = null,
PayerTaxInfo $taxInfo = null PayerTaxInfo $taxInfo = null
) { ) {
$this->name = $name; $this->name = $name;
$this->emailAddress = $emailAddress; $this->emailAddress = $emailAddress;
$this->payerId = $payerId; $this->payerId = $payerId;
@ -38,35 +39,43 @@ class Payer
$this->taxInfo = $taxInfo; $this->taxInfo = $taxInfo;
} }
public function name() : PayerName { public function name() : PayerName
{
return $this->name; return $this->name;
} }
public function emailAddress() : string { public function emailAddress() : string
$this->emailAddress; {
return $this->emailAddress;
} }
public function payerId() : string { public function payerId() : string
{
return $this->payerId; return $this->payerId;
} }
public function birthDate() : \DateTime { public function birthDate() : \DateTime
{
return $this->birthDate; return $this->birthDate;
} }
public function address() : Address { public function address() : Address
{
return $this->address; return $this->address;
} }
public function phone() : ?PhoneWithType { public function phone() : ?PhoneWithType
{
return $this->phone; return $this->phone;
} }
public function taxInfo() : ?PayerTaxInfo { public function taxInfo() : ?PayerTaxInfo
{
return $this->taxInfo; return $this->taxInfo;
} }
public function toArray() : array { public function toArray() : array
{
$payer = [ $payer = [
'name' => $this->name()->toArray(), 'name' => $this->name()->toArray(),
'email_address' => $this->emailAddress(), 'email_address' => $this->emailAddress(),

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class PayerName class PayerName
{ {
@ -13,13 +12,12 @@ class PayerName
public function __construct( public function __construct(
string $givenName, string $givenName,
string $surname string $surname
) ) {
{
$this->givenName = $givenName; $this->givenName = $givenName;
$this->surname = $surname; $this->surname = $surname;
} }
public function givenName() : string public function givenName() : string
{ {
return $this->givenName; return $this->givenName;

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException; use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException;
class PayerTaxInfo class PayerTaxInfo
@ -18,10 +17,11 @@ class PayerTaxInfo
public function __construct( public function __construct(
string $taxId, string $taxId,
string $type string $type
) ) {
{
if (! in_array($type, self::VALID_TYPES, true)) { if (! in_array($type, self::VALID_TYPES, true)) {
throw new RuntimeException(sprintf( throw new RuntimeException(sprintf(
// translators: %s is the current type.
__("%s is not a valid tax type.", "woocommerce-paypal-commerce-gateway"), __("%s is not a valid tax type.", "woocommerce-paypal-commerce-gateway"),
$type $type
)); ));
@ -30,14 +30,18 @@ class PayerTaxInfo
$this->type = $type; $this->type = $type;
} }
public function type() : string { public function type() : string
{
return $this->type; return $this->type;
} }
public function taxId() : string {
public function taxId() : string
{
return $this->taxId; return $this->taxId;
} }
public function toArray() : array { public function toArray() : array
{
return [ return [
'tax_id' => $this->taxId(), 'tax_id' => $this->taxId(),
'tax_id_type' => $this->type(), 'tax_id_type' => $this->type(),

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class Phone class Phone
{ {

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class PhoneWithType class PhoneWithType
{ {
const VALLID_TYPES = [ const VALLID_TYPES = [
@ -18,7 +17,6 @@ class PhoneWithType
private $phone; private $phone;
public function __construct(string $type, Phone $phone) public function __construct(string $type, Phone $phone)
{ {
$this->type = in_array($type, self::VALLID_TYPES, true) ? $type : 'OTHER'; $this->type = in_array($type, self::VALLID_TYPES, true) ? $type : 'OTHER';
$this->phone = $phone; $this->phone = $phone;
} }
@ -28,15 +26,16 @@ class PhoneWithType
return $this->type; return $this->type;
} }
public function phone() : Phone { public function phone() : Phone
{
return $this->phone; return $this->phone;
} }
public function toArray() : array { public function toArray() : array
{
return [ return [
'phone_type' => $this->type(), 'phone_type' => $this->type(),
'phone_number' => $this->phone()->toArray(), 'phone_number' => $this->phone()->toArray(),
]; ];
} }
} }

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class PurchaseUnit class PurchaseUnit
{ {
@ -32,25 +31,29 @@ class PurchaseUnit
$this->shipping = $shipping; $this->shipping = $shipping;
$this->referenceId = $referenceId; $this->referenceId = $referenceId;
$this->description = $description; $this->description = $description;
//phpcs:disable Inpsyde.CodeQuality.ArgumentTypeDeclaration.NoArgumentType
$this->items = array_values( $this->items = array_values(
array_filter( array_filter(
$items, $items,
function($item) : bool { function ($item) : bool {
return is_a($item, Item::class); return is_a($item, Item::class);
} }
) )
); );
//phpcs:enable Inpsyde.CodeQuality.ArgumentTypeDeclaration.NoArgumentType
$this->payee = $payee; $this->payee = $payee;
$this->customId = $customId; $this->customId = $customId;
$this->invoiceId = $invoiceId; $this->invoiceId = $invoiceId;
$this->softDescriptor = $softDescriptor; $this->softDescriptor = $softDescriptor;
} }
public function amount() : Amount { public function amount() : Amount
{
return $this->amount; return $this->amount;
} }
public function shipping() : ?Shipping { public function shipping() : ?Shipping
{
return $this->shipping; return $this->shipping;
} }
@ -63,13 +66,19 @@ class PurchaseUnit
{ {
return $this->description; return $this->description;
} }
public function customId() : string {
public function customId() : string
{
return $this->customId; return $this->customId;
} }
public function invoiceId() : string {
public function invoiceId() : string
{
return $this->invoiceId; return $this->invoiceId;
} }
public function softDescriptor() : string {
public function softDescriptor() : string
{
return $this->softDescriptor; return $this->softDescriptor;
} }
@ -86,13 +95,16 @@ class PurchaseUnit
return $this->items; return $this->items;
} }
public function toArray() : array { public function toArray() : array
{
$purchaseUnit = [ $purchaseUnit = [
'reference_id' => $this->referenceId(), 'reference_id' => $this->referenceId(),
'amount' => $this->amount()->toArray(), 'amount' => $this->amount()->toArray(),
'description' => $this->description(), 'description' => $this->description(),
'items' => array_map( 'items' => array_map(
function(Item $item) : array { return $item->toArray(); }, function (Item $item) : array {
return $item->toArray();
},
$this->items() $this->items()
), ),
]; ];

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity; namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class Shipping class Shipping
{ {
@ -15,15 +14,18 @@ class Shipping
$this->address = $address; $this->address = $address;
} }
public function name() : string { public function name() : string
{
return $this->name; return $this->name;
} }
public function address() : Address { public function address() : Address
{
return $this->address; return $this->address;
} }
public function toArray() : array { public function toArray() : array
{
return [ return [
'name' => [ 'name' => [
'full_name' => $this->name(), 'full_name' => $this->name(),

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Exception; namespace Inpsyde\PayPalCommerce\ApiClient\Exception;
class RuntimeException extends \RuntimeException class RuntimeException extends \RuntimeException
{ {

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Factory; namespace Inpsyde\PayPalCommerce\ApiClient\Factory;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Address; use Inpsyde\PayPalCommerce\ApiClient\Entity\Address;
use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException; use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException;
@ -14,8 +13,8 @@ class AddressFactory
{ {
} }
public function fromPayPalRequest(\stdClass $data) : Address { public function fromPayPalRequest(\stdClass $data) : Address
{
if (! isset($data->country_code)) { if (! isset($data->country_code)) {
new RuntimeException(__('No country given for address.', 'woocommerce-paypal-commerce-gateway')); new RuntimeException(__('No country given for address.', 'woocommerce-paypal-commerce-gateway'));
} }

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Factory; namespace Inpsyde\PayPalCommerce\ApiClient\Factory;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Amount; use Inpsyde\PayPalCommerce\ApiClient\Entity\Amount;
use Inpsyde\PayPalCommerce\ApiClient\Entity\AmountBreakdown; use Inpsyde\PayPalCommerce\ApiClient\Entity\AmountBreakdown;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Money; use Inpsyde\PayPalCommerce\ApiClient\Entity\Money;
@ -16,8 +15,8 @@ class AmountFactory
{ {
} }
public function fromPayPalResponse(\stdClass $data) : Amount{ public function fromPayPalResponse(\stdClass $data) : Amount
{
if (! isset($data->value) || ! is_numeric($data->value)) { if (! isset($data->value) || ! is_numeric($data->value)) {
throw new RuntimeException(__("No value given", "woocommerce-paypal-commerce-gateway")); throw new RuntimeException(__("No value given", "woocommerce-paypal-commerce-gateway"));
} }
@ -30,7 +29,8 @@ class AmountFactory
return new Amount($money, $breakdown); return new Amount($money, $breakdown);
} }
private function breakDown(\stdClass $data) : AmountBreakdown { private function breakDown(\stdClass $data) : AmountBreakdown
{
/** /**
* The order of the keys equals the necessary order of the constructor arguments. * The order of the keys equals the necessary order of the constructor arguments.
*/ */
@ -54,12 +54,14 @@ class AmountFactory
if (! isset($item->value) || ! is_numeric($item->value)) { if (! isset($item->value) || ! is_numeric($item->value)) {
throw new RuntimeException(sprintf( throw new RuntimeException(sprintf(
// translators: %s is the current breakdown key.
__("No value given for breakdown %s", "woocommerce-paypal-commerce-gateway"), __("No value given for breakdown %s", "woocommerce-paypal-commerce-gateway"),
$key $key
)); ));
} }
if (! isset($item->currency_code)) { if (! isset($item->currency_code)) {
throw new RuntimeException(sprintf( throw new RuntimeException(sprintf(
// translators: %s is the current breakdown key.
__("No currency given for breakdown %s", "woocommerce-paypal-commerce-gateway"), __("No currency given for breakdown %s", "woocommerce-paypal-commerce-gateway"),
$key $key
)); ));

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Factory; namespace Inpsyde\PayPalCommerce\ApiClient\Factory;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Item; use Inpsyde\PayPalCommerce\ApiClient\Entity\Item;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Money; use Inpsyde\PayPalCommerce\ApiClient\Entity\Money;
use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException; use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException;
@ -21,15 +20,21 @@ class ItemFactory
throw new RuntimeException(__("No name for item given", "woocommerce-paypal-commerce-gateway")); throw new RuntimeException(__("No name for item given", "woocommerce-paypal-commerce-gateway"));
} }
if (! isset($data->quantity) || ! is_numeric($data->quantity)) { if (! isset($data->quantity) || ! is_numeric($data->quantity)) {
throw new RuntimeException(__("No quantity for item given", "woocommerce-paypal-commerce-gateway")); throw new RuntimeException(
__("No quantity for item given", "woocommerce-paypal-commerce-gateway")
);
} }
if (! isset($data->unit_amount->value) || ! isset($data->unit_amount->currency_code)) { if (! isset($data->unit_amount->value) || ! isset($data->unit_amount->currency_code)) {
throw new RuntimeException(__("No money values for item given", "woocommerce-paypal-commerce-gateway")); throw new RuntimeException(
__("No money values for item given", "woocommerce-paypal-commerce-gateway")
);
} }
$unitAmount = new Money((float) $data->unit_amount->value, $data->unit_amount->currency_code); $unitAmount = new Money((float) $data->unit_amount->value, $data->unit_amount->currency_code);
$description = (isset($data->description)) ? $data->description : ''; $description = (isset($data->description)) ? $data->description : '';
$tax = (isset($data->tax)) ? new Money((float) $data->tax->value, $data->tax->currency_code) : null; $tax = (isset($data->tax)) ?
new Money((float) $data->tax->value, $data->tax->currency_code)
: null;
$sku = (isset($data->sku)) ? $data->sku : ''; $sku = (isset($data->sku)) ? $data->sku : '';
$category = (isset($data->category)) ? $data->category : 'PHYSICAL_GOODS'; $category = (isset($data->category)) ? $data->category : 'PHYSICAL_GOODS';

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Factory; namespace Inpsyde\PayPalCommerce\ApiClient\Factory;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Order; use Inpsyde\PayPalCommerce\ApiClient\Entity\Order;
use Inpsyde\PayPalCommerce\ApiClient\Entity\OrderStatus; use Inpsyde\PayPalCommerce\ApiClient\Entity\OrderStatus;
use Inpsyde\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use Inpsyde\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
@ -18,12 +17,13 @@ class OrderFactory
PurchaseUnitFactory $purchaseUnitFactory, PurchaseUnitFactory $purchaseUnitFactory,
PayerFactory $payerFactory PayerFactory $payerFactory
) { ) {
$this->purchaseUnitFactory = $purchaseUnitFactory; $this->purchaseUnitFactory = $purchaseUnitFactory;
$this->payerFactory = $payerFactory; $this->payerFactory = $payerFactory;
} }
public function fromWcOrder(\WC_Order $wcOrder, Order $order) : Order { public function fromWcOrder(\WC_Order $wcOrder, Order $order) : Order
{
$purchaseUnits = [$this->purchaseUnitFactory->fromWcOrder($wcOrder)]; $purchaseUnits = [$this->purchaseUnitFactory->fromWcOrder($wcOrder)];
return new Order( return new Order(
@ -40,30 +40,44 @@ class OrderFactory
public function fromPayPalResponse(\stdClass $orderData) : Order public function fromPayPalResponse(\stdClass $orderData) : Order
{ {
if (! isset($orderData->id)) { if (! isset($orderData->id)) {
throw new RuntimeException(__('Order does not contain an id.', 'woocommerce-paypal-commerce-gateway')); throw new RuntimeException(
__('Order does not contain an id.', 'woocommerce-paypal-commerce-gateway')
);
} }
if (! isset($orderData->create_time)) { if (! isset($orderData->create_time)) {
throw new RuntimeException(__('Order does not contain a create time.', 'woocommerce-paypal-commerce-gateway')); throw new RuntimeException(
__('Order does not contain a create time.', 'woocommerce-paypal-commerce-gateway')
);
} }
if (! isset($orderData->purchase_units) || !is_array($orderData->purchase_units)) { if (! isset($orderData->purchase_units) || !is_array($orderData->purchase_units)) {
throw new RuntimeException(__('Order does not contain items.', 'woocommerce-paypal-commerce-gateway')); throw new RuntimeException(
__('Order does not contain items.', 'woocommerce-paypal-commerce-gateway')
);
} }
if (! isset($orderData->status)) { if (! isset($orderData->status)) {
throw new RuntimeException(__('Order does not contain status.', 'woocommerce-paypal-commerce-gateway')); throw new RuntimeException(
__('Order does not contain status.', 'woocommerce-paypal-commerce-gateway')
);
} }
if (! isset($orderData->intent)) { if (! isset($orderData->intent)) {
throw new RuntimeException(__('Order does not contain intent.', 'woocommerce-paypal-commerce-gateway')); throw new RuntimeException(
__('Order does not contain intent.', 'woocommerce-paypal-commerce-gateway')
);
} }
$purchaseUnits = array_map( $purchaseUnits = array_map(
function($data) : PurchaseUnit { function (\stdClass $data) : PurchaseUnit {
return $this->purchaseUnitFactory->fromPayPalResponse($data); return $this->purchaseUnitFactory->fromPayPalResponse($data);
}, },
$orderData->purchase_units $orderData->purchase_units
); );
$updateTime = (isset($orderData->update_time)) ? \DateTime::createFromFormat(\DateTime::ISO8601, $orderData->update_time) : null; $updateTime = (isset($orderData->update_time)) ?
$payer = (isset($orderData->payer)) ? $this->payerFactory->fromPayPalResponse($orderData->payer) : null; \DateTime::createFromFormat(\DateTime::ISO8601, $orderData->update_time)
: null;
$payer = (isset($orderData->payer)) ?
$this->payerFactory->fromPayPalResponse($orderData->payer)
: null;
return new Order( return new Order(
$orderData->id, $orderData->id,

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Factory; namespace Inpsyde\PayPalCommerce\ApiClient\Factory;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Order; use Inpsyde\PayPalCommerce\ApiClient\Entity\Order;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Patch; use Inpsyde\PayPalCommerce\ApiClient\Entity\Patch;
use Inpsyde\PayPalCommerce\ApiClient\Entity\PatchCollection; use Inpsyde\PayPalCommerce\ApiClient\Entity\PatchCollection;
@ -12,7 +11,8 @@ use Inpsyde\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
class PatchCollectionFactory class PatchCollectionFactory
{ {
public function fromOrders(Order $from, Order $to) : PatchCollection { public function fromOrders(Order $from, Order $to) : PatchCollection
{
$allPatches = []; $allPatches = [];
$allPatches += $this->purchaseUnits($from->purchaseUnits(), $to->purchaseUnits()); $allPatches += $this->purchaseUnits($from->purchaseUnits(), $to->purchaseUnits());
@ -20,14 +20,12 @@ class PatchCollectionFactory
} }
/** /**
* ToDo: This patches the purchaseUnits. The way we do it right now, we simply always patch. This simplifies the
* process but the drawback is, we always have to send a patch request.
*
* @param PurchaseUnit[] $from * @param PurchaseUnit[] $from
* @param PurchaseUnit[] $to * @param PurchaseUnit[] $to
* @return Patch[] * @return Patch[]
*/ */
private function purchaseUnits(array $from, array $to) : array { private function purchaseUnits(array $from, array $to) : array
{
$patches = []; $patches = [];
$path = '/purchase_units'; $path = '/purchase_units';
@ -35,8 +33,11 @@ class PatchCollectionFactory
$needsUpdate = ! count( $needsUpdate = ! count(
array_filter( array_filter(
$from, $from,
function(PurchaseUnit $unit) use ($purchaseUnitTo) : bool { function (PurchaseUnit $unit) use ($purchaseUnitTo) : bool {
//phpcs:disable WordPress.PHP.StrictComparisons.LooseComparison
// Loose comparison needed to compare two objects.
return $unit == $purchaseUnitTo; return $unit == $purchaseUnitTo;
//phpcs:enable WordPress.PHP.StrictComparisons.LooseComparison
} }
) )
); );
@ -45,8 +46,7 @@ class PatchCollectionFactory
} }
$purchaseUnitFrom = current(array_filter( $purchaseUnitFrom = current(array_filter(
$from, $from,
function(PurchaseUnit $unit) use ($purchaseUnitTo) : bool function (PurchaseUnit $unit) use ($purchaseUnitTo) : bool {
{
return $purchaseUnitTo->referenceId() === $unit->referenceId(); return $purchaseUnitTo->referenceId() === $unit->referenceId();
} }
)); ));

View file

@ -3,15 +3,14 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Factory; namespace Inpsyde\PayPalCommerce\ApiClient\Factory;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Payee; use Inpsyde\PayPalCommerce\ApiClient\Entity\Payee;
use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException; use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException;
class PayeeFactory class PayeeFactory
{ {
public function fromPayPalResponse($data) : ?Payee { public function fromPayPalResponse(\stdClass $data) : ?Payee
{
if (! isset($data->email_address)) { if (! isset($data->email_address)) {
throw new RuntimeException(__("No email for payee given.", "woocommerce-paypal-commerce-gateway")); throw new RuntimeException(__("No email for payee given.", "woocommerce-paypal-commerce-gateway"));
} }

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Factory; namespace Inpsyde\PayPalCommerce\ApiClient\Factory;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Payer; use Inpsyde\PayPalCommerce\ApiClient\Entity\Payer;
use Inpsyde\PayPalCommerce\ApiClient\Entity\PayerName; use Inpsyde\PayPalCommerce\ApiClient\Entity\PayerName;
use Inpsyde\PayPalCommerce\ApiClient\Entity\PayerTaxInfo; use Inpsyde\PayPalCommerce\ApiClient\Entity\PayerTaxInfo;
@ -21,7 +20,6 @@ class PayerFactory
public function fromPayPalResponse(\stdClass $data) : Payer public function fromPayPalResponse(\stdClass $data) : Payer
{ {
$address = $this->addressFactory->fromPayPalRequest($data->address); $address = $this->addressFactory->fromPayPalRequest($data->address);
$payerName = new PayerName( $payerName = new PayerName(
$data->name->given_name, $data->name->given_name,
@ -33,8 +31,12 @@ class PayerFactory
$data->phone->phone_number->national_number $data->phone->phone_number->national_number
) )
) : null; ) : null;
$taxInfo = (isset($data->tax_info)) ? new PayerTaxInfo($data->tax_info->tax_id,$data->tax_info->tax_id_type) : null; $taxInfo = (isset($data->tax_info)) ?
$birthDate = (isset($data->birth_date)) ? \DateTime::createFromFormat('Y-m-d', $data->birth_date) : null; new PayerTaxInfo($data->tax_info->tax_id, $data->tax_info->tax_id_type)
: null;
$birthDate = (isset($data->birth_date)) ?
\DateTime::createFromFormat('Y-m-d', $data->birth_date)
: null;
return new Payer( return new Payer(
$payerName, $payerName,
$data->email_address, $data->email_address,

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Factory; namespace Inpsyde\PayPalCommerce\ApiClient\Factory;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Amount; use Inpsyde\PayPalCommerce\ApiClient\Entity\Amount;
use Inpsyde\PayPalCommerce\ApiClient\Entity\AmountBreakdown; use Inpsyde\PayPalCommerce\ApiClient\Entity\AmountBreakdown;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Item; use Inpsyde\PayPalCommerce\ApiClient\Entity\Item;
@ -24,17 +23,19 @@ class PurchaseUnitFactory
ItemFactory $itemFactory, ItemFactory $itemFactory,
ShippingFactory $shippingFactory ShippingFactory $shippingFactory
) { ) {
$this->amountFactory = $amountFactory; $this->amountFactory = $amountFactory;
$this->payeeFactory = $payeeFactory; $this->payeeFactory = $payeeFactory;
$this->itemFactory = $itemFactory; $this->itemFactory = $itemFactory;
$this->shippingFactory = $shippingFactory; $this->shippingFactory = $shippingFactory;
} }
public function fromWcOrder(\WC_Order $order) : PurchaseUnit { public function fromWcOrder(\WC_Order $order) : PurchaseUnit
{
$currency = get_woocommerce_currency(); $currency = get_woocommerce_currency();
$items = array_map( $items = array_map(
function(\WC_Order_Item_Product $item) use ($currency, $order): Item { function (\WC_Order_Item_Product $item) use ($currency, $order): Item {
$product = $item->get_product(); $product = $item->get_product();
/** /**
@ -56,7 +57,6 @@ class PurchaseUnitFactory
$product->get_sku(), $product->get_sku(),
($product->is_downloadable()) ? Item::DIGITAL_GOODS : Item::PHYSICAL_GOODS ($product->is_downloadable()) ? Item::DIGITAL_GOODS : Item::PHYSICAL_GOODS
); );
}, },
$order->get_items('line_item') $order->get_items('line_item')
); );
@ -64,15 +64,18 @@ class PurchaseUnitFactory
$total = new Money((float) $order->get_total(), $currency); $total = new Money((float) $order->get_total(), $currency);
$itemsTotal = new Money(array_reduce( $itemsTotal = new Money(array_reduce(
$items, $items,
function(float $total, Item $item) : float { function (float $total, Item $item) : float {
return $total + $item->quantity() * $item->unitAmount()->value(); return $total + $item->quantity() * $item->unitAmount()->value();
}, },
0 0
), $currency); ), $currency);
$shipping = new Money((float) $order->get_shipping_total() + (float) $order->get_shipping_tax(), $currency); $shipping = new Money(
(float) $order->get_shipping_total() + (float) $order->get_shipping_tax(),
$currency
);
$taxes = new Money(array_reduce( $taxes = new Money(array_reduce(
$items, $items,
function(float $total, Item $item) : float { function (float $total, Item $item) : float {
return $total + $item->quantity() * $item->tax()->value(); return $total + $item->quantity() * $item->tax()->value();
}, },
0 0
@ -119,13 +122,16 @@ class PurchaseUnitFactory
return $purchaseUnit; return $purchaseUnit;
} }
public function fromWcCart(\WC_Cart $cart) : PurchaseUnit { public function fromWcCart(\WC_Cart $cart) : PurchaseUnit
{
$currency = get_woocommerce_currency(); $currency = get_woocommerce_currency();
$total = new Money((float) $cart->get_total('numeric'), $currency); $total = new Money((float) $cart->get_total('numeric'), $currency);
$itemsTotal = $cart->get_cart_contents_total(); $itemsTotal = $cart->get_cart_contents_total();
$itemsTotal = new Money((float) $itemsTotal, $currency); $itemsTotal = new Money((float) $itemsTotal, $currency);
$shipping = new Money((float) $cart->get_shipping_total() + $cart->get_shipping_tax(), $currency); $shipping = new Money(
(float) $cart->get_shipping_total() + $cart->get_shipping_tax(),
$currency
);
$taxes = new Money((float) $cart->get_cart_contents_tax(), $currency); $taxes = new Money((float) $cart->get_cart_contents_tax(), $currency);
@ -144,7 +150,7 @@ class PurchaseUnitFactory
$breakdown $breakdown
); );
$items = array_map( $items = array_map(
function(array $item) use ($currency): Item { function (array $item) use ($currency): Item {
$product = $item['data']; $product = $item['data'];
/** /**
* @var \WC_Product $product * @var \WC_Product $product
@ -165,7 +171,6 @@ class PurchaseUnitFactory
$product->get_sku(), $product->get_sku(),
($product->is_downloadable()) ? Item::DIGITAL_GOODS : Item::PHYSICAL_GOODS ($product->is_downloadable()) ? Item::DIGITAL_GOODS : Item::PHYSICAL_GOODS
); );
}, },
$cart->get_cart_contents() $cart->get_cart_contents()
); );
@ -197,8 +202,8 @@ class PurchaseUnitFactory
return $purchaseUnit; return $purchaseUnit;
} }
public function fromPayPalResponse(\stdClass $data) : PurchaseUnit { public function fromPayPalResponse(\stdClass $data) : PurchaseUnit
{
if (! isset($data->reference_id) || ! is_string($data->reference_id)) { if (! isset($data->reference_id) || ! is_string($data->reference_id)) {
throw new RuntimeException(__("No reference ID given.", "woocommercepaypal-commerce-gateway")); throw new RuntimeException(__("No reference ID given.", "woocommercepaypal-commerce-gateway"));
} }
@ -211,14 +216,16 @@ class PurchaseUnitFactory
$items = []; $items = [];
if (isset($data->items) && is_array($data->items)) { if (isset($data->items) && is_array($data->items)) {
$items = array_map( $items = array_map(
function($item) : Item { function (\stdClass $item) : Item {
return $this->itemFactory->fromPayPalRequest($item); return $this->itemFactory->fromPayPalRequest($item);
}, },
$data->items $data->items
); );
} }
$payee = isset($data->payee) ? $this->payeeFactory->fromPayPalResponse($data->payee) : null; $payee = isset($data->payee) ? $this->payeeFactory->fromPayPalResponse($data->payee) : null;
$shipping = isset($data->shipping) ? $this->shippingFactory->fromPayPalResponse($data->shipping) : null; $shipping = isset($data->shipping) ?
$this->shippingFactory->fromPayPalResponse($data->shipping)
: null;
return new PurchaseUnit( return new PurchaseUnit(
$amount, $amount,
$items, $items,

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Factory; namespace Inpsyde\PayPalCommerce\ApiClient\Factory;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Shipping; use Inpsyde\PayPalCommerce\ApiClient\Entity\Shipping;
use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException; use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException;
@ -16,8 +15,8 @@ class ShippingFactory
$this->addressFactory = $addressFactory; $this->addressFactory = $addressFactory;
} }
public function fromPayPalResponse(\stdClass $data) : Shipping { public function fromPayPalResponse(\stdClass $data) : Shipping
{
if (! isset($data->name->full_name)) { if (! isset($data->name->full_name)) {
throw new RuntimeException( throw new RuntimeException(
__("No name was given for shipping.", "woocommerce-paypal-commerce-gateway") __("No name was given for shipping.", "woocommerce-paypal-commerce-gateway")

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Repository; namespace Inpsyde\PayPalCommerce\ApiClient\Repository;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Item; use Inpsyde\PayPalCommerce\ApiClient\Entity\Item;
use Inpsyde\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use Inpsyde\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
use Inpsyde\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use Inpsyde\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
@ -23,8 +22,8 @@ class CartRepository implements PurchaseUnitRepositoryInterface
* *
* @return PurchaseUnit[] * @return PurchaseUnit[]
*/ */
public function all() : array { public function all() : array
{
return [$this->factory->fromWcCart($this->cart)]; return [$this->factory->fromWcCart($this->cart)];
} }
} }

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Repository; namespace Inpsyde\PayPalCommerce\ApiClient\Repository;
use Inpsyde\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use Inpsyde\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
interface PurchaseUnitRepositoryInterface interface PurchaseUnitRepositoryInterface

View file

@ -1,12 +1,14 @@
/******/ (function(modules) { // webpackBootstrap /******/ (function (modules) {
// webpackBootstrap
/******/ // The module cache /******/ // The module cache
/******/ var installedModules = {}; /******/ var installedModules = {};
/******/ /******/
/******/ // The require function /******/ // The require function
/******/ function __webpack_require__(moduleId) { /******/ function __webpack_require__(moduleId)
{
/******/ /******/
/******/ // Check if module is in cache /******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) { /******/ if (installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports; /******/ return installedModules[moduleId].exports;
/******/ } /******/ }
/******/ // Create a new module (and put it into the cache) /******/ // Create a new module (and put it into the cache)
@ -34,15 +36,15 @@
/******/ __webpack_require__.c = installedModules; /******/ __webpack_require__.c = installedModules;
/******/ /******/
/******/ // define getter function for harmony exports /******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) { /******/ __webpack_require__.d = function (exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) { /******/ if (!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ } /******/ }
/******/ }; /******/ };
/******/ /******/
/******/ // define __esModule on exports /******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) { /******/ __webpack_require__.r = function (exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ } /******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ Object.defineProperty(exports, '__esModule', { value: true });
@ -53,28 +55,44 @@
/******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object /******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require /******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) { /******/ __webpack_require__.t = function (value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value); /******/ if (mode & 1) {
/******/ if(mode & 8) return value; value = __webpack_require__(value);
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; }
/******/ if (mode & 8) {
return value;
}
/******/ if ((mode & 4) && typeof value === 'object' && value && value.__esModule) {
return value;
}
/******/ var ns = Object.create(null); /******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns); /******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ if (mode & 2 && typeof value != 'string') {
for (var key in value) {
__webpack_require__.d(ns, key, function (key) {
return value[key]; }.bind(null, key));
}
}
/******/ return ns; /******/ return ns;
/******/ }; /******/ };
/******/ /******/
/******/ // getDefaultExport function for compatibility with non-harmony modules /******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) { /******/ __webpack_require__.n = function (module) {
/******/ var getter = module && module.__esModule ? /******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } : /******/ function getDefault()
/******/ function getModuleExports() { return module; }; {
return module['default']; } :
/******/ function getModuleExports()
{
return module; };
/******/ __webpack_require__.d(getter, 'a', getter); /******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter; /******/ return getter;
/******/ }; /******/ };
/******/ /******/
/******/ // Object.prototype.hasOwnProperty.call /******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ __webpack_require__.o = function (object, property) {
return Object.prototype.hasOwnProperty.call(object, property); };
/******/ /******/
/******/ // __webpack_public_path__ /******/ // __webpack_public_path__
/******/ __webpack_require__.p = ""; /******/ __webpack_require__.p = "";
@ -82,29 +100,27 @@
/******/ /******/
/******/ // Load entry module and return exports /******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./resources/js/button.js"); /******/ return __webpack_require__(__webpack_require__.s = "./resources/js/button.js");
/******/ }) /******/ })({
/************************************************************************/
/******/ ({
/***/ "./resources/js/button.js": /***/ "./resources/js/button.js":
/*!********************************!*\ /*!********************************!*\
!*** ./resources/js/button.js ***! !*** ./resources/js/button.js ***!
\********************************/ \********************************/
/*! no exports provided */ /*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function (module, __webpack_exports__, __webpack_require__) {
"use strict"; "use strict";
__webpack_require__.r(__webpack_exports__); __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _modules_Renderer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modules/Renderer */ "./resources/js/modules/Renderer.js"); /* harmony import */ var _modules_Renderer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modules/Renderer */ "./resources/js/modules/Renderer.js");
/* harmony import */ var _modules_SingleProductConfig__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./modules/SingleProductConfig */ "./resources/js/modules/SingleProductConfig.js"); /* harmony import */ var _modules_SingleProductConfig__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./modules/SingleProductConfig */ "./resources/js/modules/SingleProductConfig.js");
/* harmony import */ var _modules_UpdateCart__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./modules/UpdateCart */ "./resources/js/modules/UpdateCart.js"); /* harmony import */ var _modules_UpdateCart__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./modules/UpdateCart */ "./resources/js/modules/UpdateCart.js");
/* harmony import */ var _modules_ErrorHandler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./modules/ErrorHandler */ "./resources/js/modules/ErrorHandler.js"); /* harmony import */ var _modules_ErrorHandler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./modules/ErrorHandler */ "./resources/js/modules/ErrorHandler.js");
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
if (!typeof PayPalCommerceGateway) { if (!typeof PayPalCommerceGateway) {
console.error('PayPal button could not be configured.'); console.error('PayPal button could not be configured.');
return; return;
@ -134,33 +150,35 @@ document.addEventListener('DOMContentLoaded', () => {
return; return;
} }
renderer.render(configurator.configuration()); renderer.render(configurator.configuration());
}); });
/***/ }), /***/ }),
/***/ "./resources/js/modules/ButtonsToggleListener.js": /***/ "./resources/js/modules/ButtonsToggleListener.js":
/*!*******************************************************!*\ /*!*******************************************************!*\
!*** ./resources/js/modules/ButtonsToggleListener.js ***! !*** ./resources/js/modules/ButtonsToggleListener.js ***!
\*******************************************************/ \*******************************************************/
/*! exports provided: default */ /*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function (module, __webpack_exports__, __webpack_require__) {
"use strict"; "use strict";
__webpack_require__.r(__webpack_exports__); __webpack_require__.r(__webpack_exports__);
/** /**
* When you can't add something to the cart, the PayPal buttons should not show. * When you can't add something to the cart, the PayPal buttons should not show.
* Therefore we listen for changes on the add to cart button and show/hide the buttons accordingly. * Therefore we listen for changes on the add to cart button and show/hide the buttons accordingly.
*/ */
class ButtonsToggleListener { class ButtonsToggleListener {
constructor(element, showCallback, hideCallback) { constructor(element, showCallback, hideCallback)
{
this.element = element; this.element = element;
this.showCallback = showCallback; this.showCallback = showCallback;
this.hideCallback = hideCallback; this.hideCallback = hideCallback;
this.observer = null; this.observer = null;
} }
init() { init()
{
const config = { attributes: true }; const config = { attributes: true };
const callback = () => { const callback = () => {
if (this.element.classList.contains('disabled')) { if (this.element.classList.contains('disabled')) {
@ -173,70 +191,77 @@ class ButtonsToggleListener {
this.observer.observe(this.element, config); this.observer.observe(this.element, config);
} }
disconnect() { disconnect()
{
this.observer.disconnect(); this.observer.disconnect();
} }
} }
/* harmony default export */ __webpack_exports__["default"] = (ButtonsToggleListener); /* harmony default export */ __webpack_exports__["default"] = (ButtonsToggleListener);
/***/ }), /***/ }),
/***/ "./resources/js/modules/ErrorHandler.js": /***/ "./resources/js/modules/ErrorHandler.js":
/*!**********************************************!*\ /*!**********************************************!*\
!*** ./resources/js/modules/ErrorHandler.js ***! !*** ./resources/js/modules/ErrorHandler.js ***!
\**********************************************/ \**********************************************/
/*! exports provided: default */ /*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function (module, __webpack_exports__, __webpack_require__) {
"use strict"; "use strict";
__webpack_require__.r(__webpack_exports__); __webpack_require__.r(__webpack_exports__);
class ErrorHandler { class ErrorHandler {
constructor() { constructor()
{
this.wrapper = document.querySelector('.woocommerce-notices-wrapper'); this.wrapper = document.querySelector('.woocommerce-notices-wrapper');
} }
message(text) { message(text)
{
this.wrapper.classList.add('woocommerce-error'); this.wrapper.classList.add('woocommerce-error');
this.wrapper.innerText = this.sanitize(text); this.wrapper.innerText = this.sanitize(text);
} }
sanitize(text) { sanitize(text)
{
const textarea = document.createElement('textarea'); const textarea = document.createElement('textarea');
textarea.innerHTML = text; textarea.innerHTML = text;
return textarea.value; return textarea.value;
} }
clear() { clear()
{
if (!this.wrapper.classList.contains('woocommerce-error')) { if (!this.wrapper.classList.contains('woocommerce-error')) {
return; return;
} }
this.wrapper.classList.remove('woocommerce-error'); this.wrapper.classList.remove('woocommerce-error');
this.wrapper.innerText = ''; this.wrapper.innerText = '';
} }
} }
/* harmony default export */ __webpack_exports__["default"] = (ErrorHandler); /* harmony default export */ __webpack_exports__["default"] = (ErrorHandler);
/***/ }), /***/ }),
/***/ "./resources/js/modules/Renderer.js": /***/ "./resources/js/modules/Renderer.js":
/*!******************************************!*\ /*!******************************************!*\
!*** ./resources/js/modules/Renderer.js ***! !*** ./resources/js/modules/Renderer.js ***!
\******************************************/ \******************************************/
/*! exports provided: default */ /*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function (module, __webpack_exports__, __webpack_require__) {
"use strict"; "use strict";
__webpack_require__.r(__webpack_exports__); __webpack_require__.r(__webpack_exports__);
class Renderer { class Renderer {
constructor(config) { constructor(config)
{
this.config = config; this.config = config;
} }
render(buttonConfig) { render(buttonConfig)
{
const script = document.createElement('script'); const script = document.createElement('script');
@ -252,39 +277,43 @@ class Renderer {
this.renderButtons(buttonConfig); this.renderButtons(buttonConfig);
} }
renderButtons(buttonConfig) { renderButtons(buttonConfig)
{
paypal.Buttons(buttonConfig).render(this.config.wrapper); paypal.Buttons(buttonConfig).render(this.config.wrapper);
} }
hideButtons() { hideButtons()
{
document.querySelector(this.config.wrapper).style.display = 'none'; document.querySelector(this.config.wrapper).style.display = 'none';
} }
showButtons() { showButtons()
{
document.querySelector(this.config.wrapper).style.display = 'block'; document.querySelector(this.config.wrapper).style.display = 'block';
} }
} }
/* harmony default export */ __webpack_exports__["default"] = (Renderer); /* harmony default export */ __webpack_exports__["default"] = (Renderer);
/***/ }), /***/ }),
/***/ "./resources/js/modules/SingleProductConfig.js": /***/ "./resources/js/modules/SingleProductConfig.js":
/*!*****************************************************!*\ /*!*****************************************************!*\
!*** ./resources/js/modules/SingleProductConfig.js ***! !*** ./resources/js/modules/SingleProductConfig.js ***!
\*****************************************************/ \*****************************************************/
/*! exports provided: default */ /*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function (module, __webpack_exports__, __webpack_require__) {
"use strict"; "use strict";
__webpack_require__.r(__webpack_exports__); __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _ButtonsToggleListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ButtonsToggleListener */ "./resources/js/modules/ButtonsToggleListener.js"); /* harmony import */ var _ButtonsToggleListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ButtonsToggleListener */ "./resources/js/modules/ButtonsToggleListener.js");
class SingleProductConfig { class SingleProductConfig {
constructor(config, updateCart, showButtonCallback, hideButtonCallback, formElement, errorHandler) { constructor(config, updateCart, showButtonCallback, hideButtonCallback, formElement, errorHandler)
{
this.config = config; this.config = config;
this.updateCart = updateCart; this.updateCart = updateCart;
this.showButtonCallback = showButtonCallback; this.showButtonCallback = showButtonCallback;
@ -293,7 +322,8 @@ class SingleProductConfig {
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
} }
configuration() { configuration()
{
if (this.hasVariations()) { if (this.hasVariations()) {
const observer = new _ButtonsToggleListener__WEBPACK_IMPORTED_MODULE_0__["default"](this.formElement.querySelector('.single_add_to_cart_button'), this.showButtonCallback, this.hideButtonCallback); const observer = new _ButtonsToggleListener__WEBPACK_IMPORTED_MODULE_0__["default"](this.formElement.querySelector('.single_add_to_cart_button'), this.showButtonCallback, this.hideButtonCallback);
@ -311,7 +341,8 @@ class SingleProductConfig {
}; };
} }
createOrder() { createOrder()
{
const createOrder = (data, actions) => { const createOrder = (data, actions) => {
this.errorHandler.clear(); this.errorHandler.clear();
const product = document.querySelector('[name="add-to-cart"]').value; const product = document.querySelector('[name="add-to-cart"]').value;
@ -342,7 +373,8 @@ class SingleProductConfig {
return createOrder; return createOrder;
} }
variations() { variations()
{
if (!this.hasVariations()) { if (!this.hasVariations()) {
return null; return null;
@ -356,32 +388,35 @@ class SingleProductConfig {
return attributes; return attributes;
} }
hasVariations() { hasVariations()
{
return this.formElement.classList.contains('variations_form'); return this.formElement.classList.contains('variations_form');
} }
} }
/* harmony default export */ __webpack_exports__["default"] = (SingleProductConfig); /* harmony default export */ __webpack_exports__["default"] = (SingleProductConfig);
/***/ }), /***/ }),
/***/ "./resources/js/modules/UpdateCart.js": /***/ "./resources/js/modules/UpdateCart.js":
/*!********************************************!*\ /*!********************************************!*\
!*** ./resources/js/modules/UpdateCart.js ***! !*** ./resources/js/modules/UpdateCart.js ***!
\********************************************/ \********************************************/
/*! exports provided: default */ /*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function (module, __webpack_exports__, __webpack_require__) {
"use strict"; "use strict";
__webpack_require__.r(__webpack_exports__); __webpack_require__.r(__webpack_exports__);
class UpdateCart { class UpdateCart {
constructor(endpoint, nonce) { constructor(endpoint, nonce)
{
this.endpoint = endpoint; this.endpoint = endpoint;
this.nonce = nonce; this.nonce = nonce;
} }
update(onResolve, product, qty, variations) { update(onResolve, product, qty, variations)
{
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fetch(this.endpoint, { fetch(this.endpoint, {
method: 'POST', method: 'POST',
@ -404,11 +439,11 @@ class UpdateCart {
}); });
}); });
} }
} }
/* harmony default export */ __webpack_exports__["default"] = (UpdateCart); /* harmony default export */ __webpack_exports__["default"] = (UpdateCart);
/***/ }) /***/ })
/******/ }); /******/ });
//# sourceMappingURL=button.js.map //# sourceMappingURL=button.js.map

View file

@ -18,14 +18,11 @@ document.addEventListener(
if (context === 'product' && ! document.querySelector('form.cart') ) { if (context === 'product' && ! document.querySelector('form.cart') ) {
return; return;
} }
const errorHandler = new ErrorHandler(); const errorHandler = new ErrorHandler();
const renderer = new Renderer({ const renderer = new Renderer({
url: PayPalCommerceGateway.button.url, url: PayPalCommerceGateway.button.url,
wrapper:PayPalCommerceGateway.button.wrapper wrapper:PayPalCommerceGateway.button.wrapper
}); });
const updateCart = new UpdateCart( const updateCart = new UpdateCart(
PayPalCommerceGateway.ajax.change_cart.endpoint, PayPalCommerceGateway.ajax.change_cart.endpoint,
PayPalCommerceGateway.ajax.change_cart.nonce PayPalCommerceGateway.ajax.change_cart.nonce
@ -46,6 +43,5 @@ document.addEventListener(
return; return;
} }
renderer.render(configurator.configuration()); renderer.render(configurator.configuration());
} }
); );

View file

@ -4,14 +4,16 @@
*/ */
class ButtonsToggleListener { class ButtonsToggleListener {
constructor(element, showCallback, hideCallback) { constructor(element, showCallback, hideCallback)
{
this.element = element; this.element = element;
this.showCallback = showCallback; this.showCallback = showCallback;
this.hideCallback = hideCallback; this.hideCallback = hideCallback;
this.observer = null; this.observer = null;
} }
init() { init()
{
const config = { attributes : true }; const config = { attributes : true };
const callback = () => { const callback = () => {
if (this.element.classList.contains('disabled')) { if (this.element.classList.contains('disabled')) {
@ -24,7 +26,8 @@ class ButtonsToggleListener {
this.observer.observe(this.element, config); this.observer.observe(this.element, config);
} }
disconnect() { disconnect()
{
this.observer.disconnect(); this.observer.disconnect();
} }
} }

View file

@ -1,21 +1,25 @@
class ErrorHandler { class ErrorHandler {
constructor() { constructor()
{
this.wrapper = document.querySelector('.woocommerce-notices-wrapper'); this.wrapper = document.querySelector('.woocommerce-notices-wrapper');
} }
message(text) { message(text)
{
this.wrapper.classList.add('woocommerce-error'); this.wrapper.classList.add('woocommerce-error');
this.wrapper.innerText = this.sanitize(text); this.wrapper.innerText = this.sanitize(text);
} }
sanitize(text) { sanitize(text)
{
const textarea = document.createElement('textarea'); const textarea = document.createElement('textarea');
textarea.innerHTML = text; textarea.innerHTML = text;
return textarea.value; return textarea.value;
} }
clear() { clear()
{
if (! this.wrapper.classList.contains('woocommerce-error')) { if (! this.wrapper.classList.contains('woocommerce-error')) {
return; return;
} }

View file

@ -1,10 +1,12 @@
class Renderer { class Renderer {
constructor(config) { constructor(config)
{
this.config = config; this.config = config;
} }
render(buttonConfig) { render(buttonConfig)
{
const script = document.createElement('script'); const script = document.createElement('script');
@ -20,18 +22,21 @@ class Renderer {
this.renderButtons(buttonConfig); this.renderButtons(buttonConfig);
} }
renderButtons(buttonConfig) { renderButtons(buttonConfig)
{
paypal.Buttons( paypal.Buttons(
buttonConfig buttonConfig
).render(this.config.wrapper); ).render(this.config.wrapper);
} }
hideButtons() { hideButtons()
{
document.querySelector(this.config.wrapper).style.display = 'none'; document.querySelector(this.config.wrapper).style.display = 'none';
} }
showButtons() { showButtons()
{
document.querySelector(this.config.wrapper).style.display = 'block'; document.querySelector(this.config.wrapper).style.display = 'block';
} }
} }

View file

@ -18,7 +18,8 @@ class SingleProductConfig {
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
} }
configuration() { configuration()
{
if ( this.hasVariations() ) { if ( this.hasVariations() ) {
const observer = new ButtonsToggleListener( const observer = new ButtonsToggleListener(
@ -40,7 +41,8 @@ class SingleProductConfig {
} }
} }
createOrder() { createOrder()
{
const createOrder = (data, actions) => { const createOrder = (data, actions) => {
this.errorHandler.clear(); this.errorHandler.clear();
const product = document.querySelector('[name="add-to-cart"]').value; const product = document.querySelector('[name="add-to-cart"]').value;
@ -54,9 +56,9 @@ class SingleProductConfig {
nonce:this.config.ajax.create_order.nonce, nonce:this.config.ajax.create_order.nonce,
purchase_units purchase_units
}) })
}).then(function(res) { }).then(function (res) {
return res.json(); return res.json();
}).then(function(data) { }).then(function (data) {
if (! data.success) { if (! data.success) {
//Todo: Error handling //Todo: Error handling
return; return;
@ -71,7 +73,8 @@ class SingleProductConfig {
return createOrder; return createOrder;
} }
variations() { variations()
{
if (! this.hasVariations()) { if (! this.hasVariations()) {
return null; return null;
@ -87,7 +90,8 @@ class SingleProductConfig {
return attributes; return attributes;
} }
hasVariations() { hasVariations()
{
return this.formElement.classList.contains('variations_form'); return this.formElement.classList.contains('variations_form');
} }
} }

View file

@ -1,12 +1,14 @@
class UpdateCart { class UpdateCart {
constructor(endpoint, nonce) { constructor(endpoint, nonce)
{
this.endpoint = endpoint; this.endpoint = endpoint;
this.nonce = nonce; this.nonce = nonce;
} }
update(onResolve, product, qty, variations) { update(onResolve, product, qty, variations)
return new Promise( (resolve, reject) => { {
return new Promise((resolve, reject) => {
fetch( fetch(
this.endpoint, this.endpoint,
{ {
@ -22,7 +24,7 @@ class UpdateCart {
(result) => { (result) => {
return result.json(); return result.json();
} }
).then( (result) => { ).then((result) => {
if (! result.success) { if (! result.success) {
reject(result.data); reject(result.data);
return; return;
@ -30,8 +32,7 @@ class UpdateCart {
const resolved = onResolve(result.data); const resolved = onResolve(result.data);
resolve(resolved); resolve(resolved);
} })
)
}); });
} }
} }

View file

@ -11,17 +11,20 @@ use Inpsyde\PayPalCommerce\Button\Endpoint\RequestData;
use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException; use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException;
return [ return [
'button.smart-button' => function(ContainerInterface $container) { 'button.smart-button' => function (ContainerInterface $container) : SmartButton {
$isSandbox = true; $isSandbox = true;
return new SmartButton($container->get('button.url'), $isSandbox); return new SmartButton($container->get('button.url'), $isSandbox);
}, },
'button.url' => function(ContainerInterface $container) : string { 'button.url' => function (ContainerInterface $container) : string {
return plugins_url('/modules/ppcp-button/', dirname(__FILE__, 3) . '/woocommerce-paypal-commerce-gateway.php'); return plugins_url(
'/modules/ppcp-button/',
dirname(__FILE__, 3) . '/woocommerce-paypal-commerce-gateway.php'
);
}, },
'button.request-data' => function(ContainerInterface $container) : RequestData { 'button.request-data' => function (ContainerInterface $container) : RequestData {
return new RequestData(); return new RequestData();
}, },
'button.endpoint.change-cart' => function(ContainerInterface $container) : ChangeCartEndpoint { 'button.endpoint.change-cart' => function (ContainerInterface $container) : ChangeCartEndpoint {
if (! \WC()->cart) { if (! \WC()->cart) {
throw new RuntimeException('cant initialize endpoint at this moment'); throw new RuntimeException('cant initialize endpoint at this moment');
} }
@ -31,10 +34,10 @@ return [
$repository = $container->get('api.cart-repository'); $repository = $container->get('api.cart-repository');
return new ChangeCartEndpoint($cart, $shipping, $requestData, $repository); return new ChangeCartEndpoint($cart, $shipping, $requestData, $repository);
}, },
'button.endpoint.create-order' => function(ContainerInterface $container) : CreateOrderEndpoint { 'button.endpoint.create-order' => function (ContainerInterface $container) : CreateOrderEndpoint {
$requestData = $container->get('button.request-data'); $requestData = $container->get('button.request-data');
$repository = $container->get('api.cart-repository'); $repository = $container->get('api.cart-repository');
$apiClient = $container->get('api.endpoint.order'); $apiClient = $container->get('api.endpoint.order');
return new CreateOrderEndpoint($requestData, $repository, $apiClient); return new CreateOrderEndpoint($requestData, $repository, $apiClient);
} },
]; ];

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Button\Assets; namespace Inpsyde\PayPalCommerce\Button\Assets;
use Inpsyde\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint; use Inpsyde\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
use Inpsyde\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint; use Inpsyde\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
@ -16,13 +15,14 @@ class SmartButton
string $moduleUrl, string $moduleUrl,
bool $isSandbox bool $isSandbox
) { ) {
$this->moduleUrl = $moduleUrl; $this->moduleUrl = $moduleUrl;
$this->isSandbox = $isSandbox; $this->isSandbox = $isSandbox;
} }
public function renderWrapper() : bool public function renderWrapper() : bool
{ {
$renderer = function() { $renderer = function () {
echo '<div id="ppc-button"></div>'; echo '<div id="ppc-button"></div>';
}; };
if (is_product()) { if (is_product()) {
@ -51,7 +51,6 @@ class SmartButton
$this->moduleUrl . '/assets/js/button.js' $this->moduleUrl . '/assets/js/button.js'
); );
$params = [ $params = [
'client-id' => 'AcVzowpNCpTxFzLG7onQI4JD0sVcA0BkZv-D42qRZPv_gZ8cNfX9zGL_8bXmSu7cbJ5B2DH7sot8vDpw', 'client-id' => 'AcVzowpNCpTxFzLG7onQI4JD0sVcA0BkZv-D42qRZPv_gZ8cNfX9zGL_8bXmSu7cbJ5B2DH7sot8vDpw',
'currency' => get_woocommerce_currency(), 'currency' => get_woocommerce_currency(),
@ -63,18 +62,18 @@ class SmartButton
'context' => $this->context(), 'context' => $this->context(),
'ajax' => [ 'ajax' => [
'change_cart' => [ 'change_cart' => [
'endpoint' => home_url(\WC_AJAX::get_endpoint( ChangeCartEndpoint::ENDPOINT )), 'endpoint' => home_url(\WC_AJAX::get_endpoint(ChangeCartEndpoint::ENDPOINT)),
'nonce' => wp_create_nonce(ChangeCartEndpoint::nonce()), 'nonce' => wp_create_nonce(ChangeCartEndpoint::nonce()),
], ],
'create_order' => [ 'create_order' => [
'endpoint' => home_url(\WC_AJAX::get_endpoint( CreateOrderEndpoint::ENDPOINT )), 'endpoint' => home_url(\WC_AJAX::get_endpoint(CreateOrderEndpoint::ENDPOINT)),
'nonce' => wp_create_nonce(CreateOrderEndpoint::nonce()), 'nonce' => wp_create_nonce(CreateOrderEndpoint::nonce()),
], ],
], ],
'button' => [ 'button' => [
'wrapper' => '#ppc-button', 'wrapper' => '#ppc-button',
'url' =>$smartButtonUrl, 'url' =>$smartButtonUrl,
] ],
]; ];
wp_localize_script( wp_localize_script(
'paypal-smart-button', 'paypal-smart-button',
@ -84,7 +83,8 @@ class SmartButton
return true; return true;
} }
private function context() : string { private function context() : string
{
$context = 'mini-cart'; $context = 'mini-cart';
if (is_product()) { if (is_product()) {
$context = 'product'; $context = 'product';

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Button; namespace Inpsyde\PayPalCommerce\Button;
use Dhii\Container\ServiceProvider; use Dhii\Container\ServiceProvider;
use Dhii\Modular\Module\ModuleInterface; use Dhii\Modular\Module\ModuleInterface;
use Inpsyde\PayPalCommerce\Button\Assets\SmartButton; use Inpsyde\PayPalCommerce\Button\Assets\SmartButton;
@ -35,20 +34,20 @@ class ButtonModule implements ModuleInterface
*/ */
add_action( add_action(
'wp', 'wp',
function() use ($smartButton) { function () use ($smartButton) {
if (is_admin()) { if (is_admin()) {
return; return;
} }
$smartButton->renderWrapper(); $smartButton->renderWrapper();
} }
); );
add_action('wp_enqueue_scripts', function() use ($smartButton) { add_action('wp_enqueue_scripts', function () use ($smartButton) {
$smartButton->enqueue(); $smartButton->enqueue();
}); });
add_action( add_action(
'wc_ajax_' . ChangeCartEndpoint::ENDPOINT, 'wc_ajax_' . ChangeCartEndpoint::ENDPOINT,
function() use ($container) { function () use ($container) {
$endpoint = $container->get('button.endpoint.change-cart'); $endpoint = $container->get('button.endpoint.change-cart');
/** /**
* @var ChangeCartEndpoint $endpoint * @var ChangeCartEndpoint $endpoint
@ -59,7 +58,7 @@ class ButtonModule implements ModuleInterface
add_action( add_action(
'wc_ajax_' . CreateOrderEndpoint::ENDPOINT, 'wc_ajax_' . CreateOrderEndpoint::ENDPOINT,
function() use ($container) { function () use ($container) {
$endpoint = $container->get('button.endpoint.create-order'); $endpoint = $container->get('button.endpoint.create-order');
/** /**
* @var ChangeCartEndpoint $endpoint * @var ChangeCartEndpoint $endpoint

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Button\Endpoint; namespace Inpsyde\PayPalCommerce\Button\Endpoint;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Item; use Inpsyde\PayPalCommerce\ApiClient\Entity\Item;
use Inpsyde\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use Inpsyde\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
use Inpsyde\PayPalCommerce\ApiClient\Repository\CartRepository; use Inpsyde\PayPalCommerce\ApiClient\Repository\CartRepository;
@ -24,6 +23,7 @@ class ChangeCartEndpoint implements EndpointInterface
RequestData $requestData, RequestData $requestData,
CartRepository $repository CartRepository $repository
) { ) {
$this->cart = $cart; $this->cart = $cart;
$this->shipping = $shipping; $this->shipping = $shipping;
$this->requestData = $requestData; $this->requestData = $requestData;
@ -40,16 +40,25 @@ class ChangeCartEndpoint implements EndpointInterface
try { try {
$data = $this->requestData->readRequest($this->nonce()); $data = $this->requestData->readRequest($this->nonce());
if ( if (! isset($data['product'])
! isset($data['product'])
|| ! isset($data['qty']) || ! isset($data['qty'])
) { ) {
wp_send_json_error(__('Necessary fields not defined. Action aborted.', 'woocommerce-paypal-commerce-gateway')); wp_send_json_error(
__(
'Necessary fields not defined. Action aborted.',
'woocommerce-paypal-commerce-gateway'
)
);
return false; return false;
} }
$product = wc_get_product((int) $data['product']); $product = wc_get_product((int) $data['product']);
if (! $product) { if (! $product) {
wp_send_json_error(__('No product defined. Action aborted.', 'woocommerce-paypal-commerce-gateway')); wp_send_json_error(
__(
'No product defined. Action aborted.',
'woocommerce-paypal-commerce-gateway'
)
);
return false; return false;
} }
@ -60,13 +69,12 @@ class ChangeCartEndpoint implements EndpointInterface
$success = $this->addProduct($product, $quantity) $success = $this->addProduct($product, $quantity)
: $this->addVariableProduct($product, $quantity, $data['variations']); : $this->addVariableProduct($product, $quantity, $data['variations']);
if (! $success) { if (! $success) {
$message = __('Something went wrong. Action aborted', 'woocommerce-paypal-commerce-gateway'); $message = __('Something went wrong. Action aborted', 'woocommerce-paypal-commerce-gateway');
$errors = wc_get_notices('error'); $errors = wc_get_notices('error');
if (count($errors)) { if (count($errors)) {
$message = array_reduce( $message = array_reduce(
$errors, $errors,
function(string $add, $error) : string { function (string $add, array $error) : string {
return $add . $error['notice'] . ' '; return $add . $error['notice'] . ' ';
}, },
'' ''
@ -85,27 +93,32 @@ class ChangeCartEndpoint implements EndpointInterface
} }
} }
private function addProduct(\WC_Product $product, int $quantity) : bool { private function addProduct(\WC_Product $product, int $quantity) : bool
{
return false !== $this->cart->add_to_cart($product->get_id(), $quantity); return false !== $this->cart->add_to_cart($product->get_id(), $quantity);
} }
private function addVariableProduct(\WC_Product $product, int $quantity, array $postVariations) : bool {
private function addVariableProduct(
\WC_Product $product,
int $quantity,
array $postVariations
) : bool {
foreach ($postVariations as $key => $value) { foreach ($postVariations as $key => $value) {
$variations[$value['name']] = $value['value']; $variations[$value['name']] = $value['value'];
} }
$dataStore = \WC_Data_Store::load( 'product' ); $dataStore = \WC_Data_Store::load('product');
$variationId = $dataStore->find_matching_product_variation( $product, $variations ); $variationId = $dataStore->find_matching_product_variation($product, $variations);
//ToDo: Check stock status for variation. //ToDo: Check stock status for variation.
return false !== WC()->cart->add_to_cart( $product->get_id(), $quantity, $variationId, $variations ); return false !== WC()->cart->add_to_cart($product->get_id(), $quantity, $variationId, $variations);
} }
private function generatePurchaseUnits() : array { private function generatePurchaseUnits() : array
{
return array_map( return array_map(
function(PurchaseUnit $lineItem) : array { function (PurchaseUnit $lineItem) : array {
return $lineItem->toArray(); return $lineItem->toArray();
}, },
$this->repository->all() $this->repository->all()

View file

@ -20,6 +20,7 @@ class CreateOrderEndpoint implements EndpointInterface
CartRepository $repository, CartRepository $repository,
OrderEndpoint $apiEndpoint OrderEndpoint $apiEndpoint
) { ) {
$this->requestData = $requestData; $this->requestData = $requestData;
$this->repository = $repository; $this->repository = $repository;
$this->apiEndpoint = $apiEndpoint; $this->apiEndpoint = $apiEndpoint;
@ -32,7 +33,6 @@ class CreateOrderEndpoint implements EndpointInterface
public function handleRequest() : bool public function handleRequest() : bool
{ {
try { try {
$this->requestData->readRequest($this->nonce()); $this->requestData->readRequest($this->nonce());
$purchaseUnits = $this->repository->all(); $purchaseUnits = $this->repository->all();
@ -41,10 +41,9 @@ class CreateOrderEndpoint implements EndpointInterface
); );
wp_send_json_success($order->toArray()); wp_send_json_success($order->toArray());
return false; return false;
} catch (\RuntimeException $error ) { } catch (\RuntimeException $error) {
wp_send_json_error($error->getMessage()); wp_send_json_error($error->getMessage());
return false; return false;
} }
} }
} }

View file

@ -3,12 +3,10 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Button\Endpoint; namespace Inpsyde\PayPalCommerce\Button\Endpoint;
interface EndpointInterface interface EndpointInterface
{ {
public static function nonce() : string; public static function nonce() : string;
public function handleRequest() : bool; public function handleRequest() : bool;
} }

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Button\Endpoint; namespace Inpsyde\PayPalCommerce\Button\Endpoint;
use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException; use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException;
class RequestData class RequestData
@ -11,11 +10,9 @@ class RequestData
public function readRequest(string $nonce) : array public function readRequest(string $nonce) : array
{ {
$stream = file_get_contents('php://input'); $stream = file_get_contents('php://input');
$json = json_decode($stream, true); $json = json_decode($stream, true);
if ( if (! isset($json['nonce'])
! isset($json['nonce'])
|| !wp_verify_nonce($json['nonce'], $nonce) || !wp_verify_nonce($json['nonce'], $nonce)
) { ) {
throw new RuntimeException( throw new RuntimeException(
@ -26,8 +23,8 @@ class RequestData
return $this->sanitize($json); return $this->sanitize($json);
} }
private function sanitize(array $assocArray) : array { private function sanitize(array $assocArray) : array
{
$data = []; $data = [];
foreach ((array) $assocArray as $rawKey => $rawValue) { foreach ((array) $assocArray as $rawKey => $rawValue) {
if (! is_array($rawValue)) { if (! is_array($rawValue)) {

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Button\Exception; namespace Inpsyde\PayPalCommerce\Button\Exception;
class RuntimeException extends \RuntimeException class RuntimeException extends \RuntimeException
{ {

View file

@ -1,4 +1,4 @@
const path = require( 'path' ); const path = require('path');
const isProduction = process.env.NODE_ENV === 'production'; const isProduction = process.env.NODE_ENV === 'production';
module.exports = { module.exports = {
@ -6,10 +6,10 @@ module.exports = {
mode: isProduction ? 'production' : 'development', mode: isProduction ? 'production' : 'development',
target: 'web', target: 'web',
entry: { entry: {
button: path.resolve( './resources/js/button.js' ), button: path.resolve('./resources/js/button.js'),
}, },
output: { output: {
path: path.resolve( __dirname, 'assets/' ), path: path.resolve(__dirname, 'assets/'),
filename: 'js/[name].js', filename: 'js/[name].js',
}, },
module: { module: {

View file

@ -6,7 +6,7 @@ namespace Inpsyde\PayPalCommerce\Session;
use Dhii\Data\Container\ContainerInterface; use Dhii\Data\Container\ContainerInterface;
return [ return [
'session.handler' => function(ContainerInterface $container) : SessionHandler { 'session.handler' => function (ContainerInterface $container) : SessionHandler {
if (is_admin()) { if (is_admin()) {
return new SessionHandler(); return new SessionHandler();
@ -18,5 +18,5 @@ return [
$sessionHandler = new SessionHandler(); $sessionHandler = new SessionHandler();
WC()->session->set(SessionHandler::ID, $sessionHandler); WC()->session->set(SessionHandler::ID, $sessionHandler);
return $sessionHandler; return $sessionHandler;
} },
]; ];

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Session; namespace Inpsyde\PayPalCommerce\Session;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Order; use Inpsyde\PayPalCommerce\ApiClient\Entity\Order;
class SessionHandler class SessionHandler
@ -11,17 +10,20 @@ class SessionHandler
const ID = 'ppcp'; const ID = 'ppcp';
private $order; private $order;
public function order() : ?Order { public function order() : ?Order
{
return $this->order; return $this->order;
} }
public function setOrder(Order $order) : SessionHandler { public function replaceOrder(Order $order) : SessionHandler
{
$this->order = $order; $this->order = $order;
$this->storeSession(); $this->storeSession();
return $this; return $this;
} }
private function storeSession() { private function storeSession()
{
WC()->session->set(self::ID, $this); WC()->session->set(self::ID, $this);
} }
} }

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Session; namespace Inpsyde\PayPalCommerce\Session;
use Dhii\Container\ServiceProvider; use Dhii\Container\ServiceProvider;
use Dhii\Modular\Module\ModuleInterface; use Dhii\Modular\Module\ModuleInterface;
use Interop\Container\ServiceProviderInterface; use Interop\Container\ServiceProviderInterface;
@ -20,12 +19,12 @@ class SessionModule implements ModuleInterface
); );
} }
public function run(ContainerInterface $c) public function run(ContainerInterface $container)
{ {
add_action( add_action(
'woocommerce_init', 'woocommerce_init',
function() use ($c) { function () use ($container) {
$c->get('session.handler'); $container->get('session.handler');
} }
); );
} }

View file

@ -8,15 +8,15 @@ use Inpsyde\PayPalCommerce\WcGateway\Checkout\DisableGateways;
use Inpsyde\PayPalCommerce\WcGateway\Gateway\WcGateway; use Inpsyde\PayPalCommerce\WcGateway\Gateway\WcGateway;
return [ return [
'wcgateway.gateway' => function(ContainerInterface $container) : WcGateway { 'wcgateway.gateway' => function (ContainerInterface $container) : WcGateway {
$sessionHandler = $container->get('session.handler'); $sessionHandler = $container->get('session.handler');
$cartRepository = $container->get('api.cart-repository'); $cartRepository = $container->get('api.cart-repository');
$endpoint = $container->get('api.endpoint.order'); $endpoint = $container->get('api.endpoint.order');
$orderFactory = $container->get('api.factory.order'); $orderFactory = $container->get('api.factory.order');
return new WcGateway($sessionHandler, $cartRepository, $endpoint, $orderFactory); return new WcGateway($sessionHandler, $cartRepository, $endpoint, $orderFactory);
}, },
'wcgateway.disabler' => function(ContainerInterface $container) : DisableGateways { 'wcgateway.disabler' => function (ContainerInterface $container) : DisableGateways {
$sessionHandler = $container->get('session.handler'); $sessionHandler = $container->get('session.handler');
return new DisableGateways($sessionHandler); return new DisableGateways($sessionHandler);
} },
]; ];

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\WcGateway\Checkout; namespace Inpsyde\PayPalCommerce\WcGateway\Checkout;
use Inpsyde\PayPalCommerce\Session\SessionHandler; use Inpsyde\PayPalCommerce\Session\SessionHandler;
use Inpsyde\PayPalCommerce\WcGateway\Gateway\WcGateway; use Inpsyde\PayPalCommerce\WcGateway\Gateway\WcGateway;

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\WcGateway\Gateway; namespace Inpsyde\PayPalCommerce\WcGateway\Gateway;
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use Inpsyde\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Order; use Inpsyde\PayPalCommerce\ApiClient\Entity\Order;
use Inpsyde\PayPalCommerce\ApiClient\Entity\OrderStatus; use Inpsyde\PayPalCommerce\ApiClient\Entity\OrderStatus;
@ -11,6 +10,8 @@ use Inpsyde\PayPalCommerce\ApiClient\Factory\OrderFactory;
use Inpsyde\PayPalCommerce\ApiClient\Repository\CartRepository; use Inpsyde\PayPalCommerce\ApiClient\Repository\CartRepository;
use Inpsyde\PayPalCommerce\Session\SessionHandler; use Inpsyde\PayPalCommerce\Session\SessionHandler;
//phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
//phpcs:disable Inpsyde.CodeQuality.ArgumentTypeDeclaration.NoArgumentType
class WcGateway extends \WC_Payment_Gateway class WcGateway extends \WC_Payment_Gateway
{ {
@ -35,68 +36,79 @@ class WcGateway extends \WC_Payment_Gateway
$this->orderFactory = $orderFactory; $this->orderFactory = $orderFactory;
$this->id = self::ID; $this->id = self::ID;
$this->method_title = __('PayPal Payments', 'woocommerce-paypal-gateway'); $this->method_title = __('PayPal Payments', 'woocommerce-paypal-gateway');
$this->method_description = __('Provide your customers with the PayPal payment system', 'woocommerce-paypal-gateway'); $this->method_description = __(
'Provide your customers with the PayPal payment system',
'woocommerce-paypal-gateway'
);
$this->init_form_fields(); $this->init_form_fields();
$this->init_settings(); $this->init_settings();
$this->isSandbox = $this->get_option( 'sandbox_on', 'yes' ) === 'yes'; $this->isSandbox = $this->get_option('sandbox_on', 'yes') === 'yes';
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); add_action(
'woocommerce_update_options_payment_gateways_' . $this->id,
[
$this,
'process_admin_options',
]
);
} }
public function init_form_fields() public function init_form_fields()
{ {
$this->form_fields = [ $this->form_fields = [
'enabled' => array( 'enabled' => [
'title' => __( 'Enable/Disable', 'woocommerce-paypal-gateway' ), 'title' => __('Enable/Disable', 'woocommerce-paypal-gateway'),
'type' => 'checkbox', 'type' => 'checkbox',
'label' => __( 'Enable PayPal Payments', 'woocommerce-paypal-gateway' ), 'label' => __('Enable PayPal Payments', 'woocommerce-paypal-gateway'),
'default' => 'yes' 'default' => 'yes',
), ],
'sandbox_on' => array( 'sandbox_on' => [
'title' => __( 'Enable Sandbox', 'woocommerce-paypal-gateway' ), 'title' => __('Enable Sandbox', 'woocommerce-paypal-gateway'),
'type' => 'checkbox', 'type' => 'checkbox',
'label' => __( 'For testing your integration, you can enable the sandbox.', 'woocommerce-paypal-gateway' ), 'label' => __(
'default' => 'yes' 'For testing your integration, you can enable the sandbox.',
'woocommerce-paypal-gateway'
), ),
'default' => 'yes',
],
]; ];
} }
function process_payment($orderId) : ?array public function process_payment($orderId) : ?array
{ {
global $woocommerce; global $woocommerce;
$wcOrder = new \WC_Order( $orderId ); $wcOrder = new \WC_Order($orderId);
//ToDo: We need to fetch the order from paypal again to get it with the new status. //ToDo: We need to fetch the order from paypal again to get it with the new status.
$order = $this->sessionHandler->order(); $order = $this->sessionHandler->order();
$errorMessage = null; $errorMessage = null;
if (! $order || ! $order->status()->is(OrderStatus::APPROVED)) { if (! $order || ! $order->status()->is(OrderStatus::APPROVED)) {
$errorMessage = 'not approve yet'; $errorMessage = 'not approve yet';
} }
$errorMessage = null; $errorMessage = null;
if ($errorMessage) { if ($errorMessage) {
wc_add_notice( __('Payment error:', 'woocommerce-paypal-gateway') . $errorMessage, 'error' ); wc_add_notice(__('Payment error:', 'woocommerce-paypal-gateway') . $errorMessage, 'error');
return null; return null;
} }
$order = $this->patchOrder($wcOrder, $order); $order = $this->patchOrder($wcOrder, $order);
$order = $this->endpoint->capture($order); $order = $this->endpoint->capture($order);
$wcOrder->update_status('on-hold', __( 'Awaiting payment.', 'woocommerce-paypal-gateway' )); $wcOrder->update_status('on-hold', __('Awaiting payment.', 'woocommerce-paypal-gateway'));
if ($order->status()->is(OrderStatus::COMPLETED)) { if ($order->status()->is(OrderStatus::COMPLETED)) {
$wcOrder->update_status('processing', __( 'Payment received.', 'woocommerce-paypal-gateway' )); $wcOrder->update_status('processing', __('Payment received.', 'woocommerce-paypal-gateway'));
} }
$woocommerce->cart->empty_cart(); $woocommerce->cart->empty_cart();
return array( return [
'result' => 'success', 'result' => 'success',
'redirect' => $this->get_return_url( $wcOrder ) 'redirect' => $this->get_return_url($wcOrder),
); ];
} }
private function patchOrder(\WC_Order $wcOrder, Order $order) : Order { private function patchOrder(\WC_Order $wcOrder, Order $order) : Order
{
$updatedOrder = $this->orderFactory->fromWcOrder($wcOrder, $order); $updatedOrder = $this->orderFactory->fromWcOrder($wcOrder, $order);
$order = $this->endpoint->patchOrderWith($order, $updatedOrder); $order = $this->endpoint->patchOrderWith($order, $updatedOrder);
return $order; return $order;

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\WcGateway; namespace Inpsyde\PayPalCommerce\WcGateway;
use Dhii\Container\ServiceProvider; use Dhii\Container\ServiceProvider;
use Dhii\Modular\Module\Exception\ModuleExceptionInterface; use Dhii\Modular\Module\Exception\ModuleExceptionInterface;
use Dhii\Modular\Module\ModuleInterface; use Dhii\Modular\Module\ModuleInterface;
@ -22,21 +21,21 @@ class WcGatewayModule implements ModuleInterface
); );
} }
public function run(ContainerInterface $c) public function run(ContainerInterface $container)
{ {
add_filter( add_filter(
'woocommerce_payment_gateways', 'woocommerce_payment_gateways',
function($methods) use ($c) : array { function ($methods) use ($container) : array {
$methods[] = $c->get('wcgateway.gateway'); $methods[] = $container->get('wcgateway.gateway');
return (array) $methods; return (array) $methods;
} }
); );
add_filter( add_filter(
'woocommerce_available_payment_gateways', 'woocommerce_available_payment_gateways',
function($methods) use ($c) : array { function ($methods) use ($container) : array {
$disabler = $c->get('wcgateway.disabler'); $disabler = $container->get('wcgateway.disabler');
/** /**
* @var DisableGateways $disabler * @var DisableGateways $disabler
*/ */

View file

@ -2,4 +2,9 @@
<ruleset name="Inpsyde Coding Standard"> <ruleset name="Inpsyde Coding Standard">
<rule ref="Inpsyde"/> <rule ref="Inpsyde"/>
<file>./src</file> <file>./src</file>
<file>./modules.local</file>
<exclude-pattern>*\.(inc|css|js)$</exclude-pattern>
<exclude-pattern>*\.(inc|css|js)$</exclude-pattern>
</ruleset> </ruleset>

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce; namespace Inpsyde\PayPalCommerce;
use Dhii\Container\ServiceProvider; use Dhii\Container\ServiceProvider;
use Dhii\Modular\Module\Exception\ModuleExceptionInterface; use Dhii\Modular\Module\Exception\ModuleExceptionInterface;
use Dhii\Modular\Module\ModuleInterface; use Dhii\Modular\Module\ModuleInterface;
@ -18,7 +17,7 @@ class PluginModule implements ModuleInterface
return new ServiceProvider([], []); return new ServiceProvider([], []);
} }
public function run(ContainerInterface $c) public function run(ContainerInterface $container)
{ {
// TODO: Implement run() method. // TODO: Implement run() method.
} }