Skip to content

2862339 - Add event listener to payments #791

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
1 change: 1 addition & 0 deletions modules/payment/src/Entity/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* bundle_label = @Translation("Payment type"),
* bundle_plugin_type = "commerce_payment_type",
* handlers = {
* "event" = "Drupal\commerce_payment\Event\PaymentEvent",
* "access" = "Drupal\commerce_payment\PaymentAccessControlHandler",
* "list_builder" = "Drupal\commerce_payment\PaymentListBuilder",
* "storage" = "Drupal\commerce_payment\PaymentStorage",
Expand Down
42 changes: 42 additions & 0 deletions modules/payment/src/Event/PaymentEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Drupal\commerce_payment\Event;

use Drupal\commerce_payment\Entity\PaymentInterface;
use Symfony\Component\EventDispatcher\Event;

/**
* Defines the payment event.
*
* @see \Drupal\commerce_payment\Event\PaymentEvents
*/
class PaymentEvent extends Event {

/**
* The payment.
*
* @var \Drupal\commerce_payment\Entity\PaymentInterface
*/
protected $payment;

/**
* Constructs a new Paymentevent.
*
* @param \Drupal\commerce_payment\Entity\PaymentInterface $payment
* The payment.
*/
public function __construct(PaymentInterface $payment) {
$this->payment = $payment;
}

/**
* Gets the payment.
*
* @return \Drupal\commerce_payment\Entity\PaymentInterface
* Gets the payment.
*/
public function getEntity() {
return $this->payment;
}

}
65 changes: 65 additions & 0 deletions modules/payment/src/Event/PaymentEvents.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,71 @@

final class PaymentEvents {

/**
* Name of the event fired after loading an payment.
*
* @Event
*
* @see \Drupal\commerce_payment\Event\PaymentEvent
*/
const PAYMENT_LOAD = 'commerce_payment.commerce_payment.load';

/**
* Name of the event fired after creating a new payment.
*
* Fired before the payment is saved.
*
* @Event
*
* @see \Drupal\commerce_payment\Event\PaymentEvent
*/
const PAYMENT_CREATE = 'commerce_payment.commerce_payment.create';

/**
* Name of the event fired before saving an payment.
*
* @Event
*
* @see \Drupal\commerce_payment\Event\PaymentEvent
*/
const PAYMENT_PRESAVE = 'commerce_payment.commerce_payment.presave';

/**
* Name of the event fired after saving a new payment.
*
* @Event
*
* @see \Drupal\commerce_payment\Event\PaymentEvent
*/
const PAYMENT_INSERT = 'commerce_payment.commerce_payment.insert';

/**
* Name of the event fired after saving an existing payment.
*
* @Event
*
* @see \Drupal\commerce_payment\Event\PaymentEvent
*/
const PAYMENT_UPDATE = 'commerce_payment.commerce_payment.update';

/**
* Name of the event fired before deleting an payment.
*
* @Event
*
* @see \Drupal\commerce_payment\Event\PaymentEvent
*/
const PAYMENT_PREDELETE = 'commerce_payment.commerce_payment.predelete';

/**
* Name of the event fired after deleting an payment.
*
* @Event
*
* @see \Drupal\commerce_payment\Event\PaymentEvent
*/
const PAYMENT_DELETE = 'commerce_payment.commerce_payment.delete';

/**
* Name of the event fired when payment gateways are loaded for an order.
*
Expand Down
23 changes: 22 additions & 1 deletion modules/payment/src/PaymentStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

use Drupal\commerce\CommerceContentEntityStorage;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_payment\Entity\PaymentInterface;
use Drupal\commerce_payment\Event\PaymentEvent;
use Drupal\commerce_payment\Event\PaymentEvents;
use Drupal\Core\Entity\EntityStorageException;

/**
Expand Down Expand Up @@ -53,7 +56,25 @@ protected function doCreate(array $values) {
$values['type'] = $payment_type->getPluginId();
}

return parent::doCreate($values);
$payment = parent::doCreate($values);

$this->dispatchPaymentEvent($payment, PaymentEvents::PAYMENT_CREATE);

return $payment;
}

/**
* Notifies other modules about payment events.
*
* @param \Drupal\commerce_payment\Entity\PaymentInterface $payment
* The payment.
* @param string $event_id
* The event identifier defined in
* \Drupal\commerce_payment\Event\PaymentEvents.
*/
public function dispatchPaymentEvent(PaymentInterface $payment, $event_id) {
$event = new PaymentEvent($payment);
$this->eventDispatcher->dispatch($event_id, $event);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: 'Configuration events test'
type: module
package: Testing
core: 8.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
services:
payment_events_test.event_subscriber:
class: Drupal\payment_events_test\EventSubscriber
arguments: ['@state']
tags:
- { name: event_subscriber }
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Drupal\payment_events_test;

use Drupal\commerce_payment\Event\PaymentEvent;
use Drupal\commerce_payment\Event\PaymentEvents;
use Drupal\Core\State\StateInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class EventSubscriber implements EventSubscriberInterface {

/**
* The state key value store.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;

/**
* Constructs the Event Subscriber object.
*
* @param \Drupal\Core\State\StateInterface $state
* The state key value store.
*/
public function __construct(StateInterface $state) {
$this->state = $state;
}

/**
* Reacts to payment event.
*
* @param \Drupal\commerce_payment\Event\PaymentEvent $event
* The payment event.
* @param string $name
* The name of the event.
*/
public function paymentEvent(PaymentEvent $event, $name) {
$this->state->set('payment_events_test.event', [
'event_name' => $name,
'event_entity' => $event->getEntity(),
]);
}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[PaymentEvents::PAYMENT_LOAD][] = ['paymentEvent'];
$events[PaymentEvents::PAYMENT_CREATE][] = ['paymentEvent'];
return $events;
}

}
107 changes: 107 additions & 0 deletions modules/payment/tests/src/Kernel/PaymentEventsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace Drupal\Tests\commerce_payment\Kernel;

use Drupal\commerce_order\Entity\OrderItemType;
use Drupal\commerce_payment\Entity\Payment;
use Drupal\commerce_payment\Entity\PaymentGateway;
use Drupal\commerce_payment\Entity\PaymentMethod;
use Drupal\Tests\commerce\Kernel\CommerceKernelTestBase;

/**
* Tests the payment events.
*
* @group commerce
*/
class PaymentEventsTest extends CommerceKernelTestBase {

/**
* Modules to enable.
*
* @var array
*/
public static $modules = [
'address',
'entity_reference_revisions',
'profile',
'state_machine',
'commerce_product',
'commerce_order',
'commerce_payment',
'commerce_payment_example',
'payment_events_test',
];

/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();

$this->installEntitySchema('profile');
$this->installEntitySchema('commerce_order');
$this->installEntitySchema('commerce_order_item');
$this->installEntitySchema('commerce_payment');
$this->installEntitySchema('commerce_payment_method');
$this->installConfig('commerce_order');
$this->installConfig('commerce_payment');

// An order item type that doesn't need a purchasable entity, for simplicity.
OrderItemType::create([
'id' => 'test',
'label' => 'Test',
'orderType' => 'default',
])->save();

$payment_gateway = PaymentGateway::create([
'id' => 'example',
'label' => 'Example',
'plugin' => 'example_onsite',
]);
$payment_gateway->save();

$user = $this->createUser();

/** @var \Drupal\commerce_payment\Entity\PaymentMethodInterface $payment_method */
$payment_method_active = PaymentMethod::create([
'type' => 'credit_card',
'payment_gateway' => 'example',
// Thu, 16 Jan 2020.
'expires' => '1579132800',
'uid' => $user->id(),
]);
$payment_method_active->save();
}

/**
* Tests the basic payment events.
*/
public function testPaymentEvents() {
// Create a dummy payment.
$payment = Payment::create([
'payment_gateway' => 'example',
'payment_method' => 'credit_card',
'remote_id' => '123456',
'amount' => [
'number' => '39.99',
'currency_code' => 'USD',
],
'state' => 'capture_completed',
'test' => TRUE,
]);
$payment->save();

// Check the create event.
$event_recorder = \Drupal::state()->get('payment_events_test.event', FALSE);
$this->assertEquals('commerce_payment.commerce_payment.create', $event_recorder['event_name']);
$this->assertEquals($payment->id(), $event_recorder['event_entity']->id());

// Reload the payment.
$this->reloadEntity($payment);

// Check the load event.
$event_recorder = \Drupal::state()->get('payment_events_test.event', FALSE);
$this->assertEquals('commerce_payment.commerce_payment.load', $event_recorder['event_name']);
}

}