Skip to content
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

Add events and logging for payments #797

Open
wants to merge 4 commits into
base: 8.x-2.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions modules/log/commerce_log.commerce_log_categories.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ commerce_cart:
commerce_order:
label: Order
entity_type: commerce_order

commerce_payment:
label: Payment
entity_type: commerce_payment
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this read commerce_order?

17 changes: 17 additions & 0 deletions modules/log/commerce_log.commerce_log_templates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,20 @@ order_assigned:
category: commerce_order
label: 'Order assigned'
template: '<p>The order was assigned to {{ user }}.</p>'

payment_insert:
category: commerce_payment
label: 'Payment created'
template: '<p>Payment of {{ amount|commerce_price_format }} was created.</p>'
payment_update:
category: commerce_payment
label: 'Payment updated'
template: '<p>Payment of {{ amount|commerce_price_format }} was updated.</p>'
payment_delete:
category: commerce_payment
label: 'Payment deleted'
template: '<p>Payment of {{ amount|commerce_price_format }} was deleted.</p>'
payment_refunded:
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured that insert, update, delete and refund are the only things of interest.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like we want more details in the messages. Let's add the current state as part of the log too.

category: commerce_payment
label: 'Payment refunded'
template: '<p>Payment of {{ refunded_amount|commerce_price_format }} was refunded.</p>'
7 changes: 7 additions & 0 deletions modules/log/commerce_log.module
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* Provides activity logs for Commerce entities.
*/

use Drupal\commerce_log\PaymentListBuilder;

/**
* Implements hook_preprocess_commerce_order().
*/
Expand All @@ -20,3 +22,8 @@ function commerce_log_preprocess_commerce_order(&$variables) {
'#title' => t('Order activity'),
];
}

function commerce_log_entity_type_alter(array &$entity_types) {
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
$entity_types['commerce_payment']->setListBuilderClass(PaymentListBuilder::class);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't care if the module is enabled, if it isn't this will just get ignored.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the module is disabled there won't be an $entity_types['commerce_payment'] object, causing a crash, no?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's true. I ignored that important item. I was still in d7 array mode.

}
4 changes: 2 additions & 2 deletions modules/log/config/install/views.view.commerce_activity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ display:
entity_type: commerce_log
entity_field: log_id
plugin_id: standard
title: 'Order logs'
title: 'Activity log'
header: { }
footer: { }
empty:
Expand Down Expand Up @@ -337,7 +337,7 @@ display:
type: none
fail: 'not found'
validate_options: { }
break_phrase: false
break_phrase: true
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This let's us pass in multiple entity id arguments to the source id contextual argument.

not: false
entity_type: commerce_log
entity_field: source_entity_id
Expand Down
6 changes: 6 additions & 0 deletions modules/log/src/CommerceLogServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Drupal\commerce_log;

use Drupal\commerce_log\EventSubscriber\PaymentEventSubscriber;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Symfony\Component\DependencyInjection\Reference;
Expand Down Expand Up @@ -29,6 +30,11 @@ public function register(ContainerBuilder $container) {
->addTag('event_subscriber')
->addArgument(new Reference('entity_type.manager'));
}
if (isset($modules['commerce_payment'])) {
$container->register('commerce_log.payment_subscriber', PaymentEventSubscriber::class)
->addTag('event_subscriber')
->addArgument(new Reference('entity_type.manager'));
}
}

}
103 changes: 103 additions & 0 deletions modules/log/src/EventSubscriber/PaymentEventSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

namespace Drupal\commerce_log\EventSubscriber;

use Drupal\commerce_payment\Entity\PaymentInterface;
use Drupal\commerce_payment\Event\PaymentEvent;
use Drupal\commerce_payment\Event\PaymentEvents;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\state_machine\Event\WorkflowTransitionEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class PaymentEventSubscriber implements EventSubscriberInterface {

/**
* The log storage.
*
* @var \Drupal\commerce_log\LogStorageInterface
*/
protected $logStorage;

/**
* Constructs a new PaymentEventSubscriber object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->logStorage = $entity_type_manager->getStorage('commerce_log');
}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events = [
PaymentEvents::PAYMENT_INSERT => ['onPaymentInsert', -100],
PaymentEvents::PAYMENT_UPDATE => ['onPaymentUpdate', -100],
PaymentEvents::PAYMENT_DELETE => ['onPaymentDelete', -100],
];
return $events;
}

/**
* Creates a log when a payment is inserted.
*
* @param \Drupal\commerce_payment\Event\PaymentEvent $event
* The payment event.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function onPaymentInsert(PaymentEvent $event) {
$this->logPayment($event->getPayment(), 'payment_insert');
}

/**
* Creates a log when a payment is updated.
*
* @param \Drupal\commerce_payment\Event\PaymentEvent $event
* The payment event.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function onPaymentUpdate(PaymentEvent $event) {
$payment = $event->getPayment();
$this->logPayment($payment, 'payment_update');
if ($refunded = $payment->getRefundedAmount()) {
$this->logStorage->generate($payment, 'refund', [
'refunded_amount' => $refunded,
])->save();
}
}

/**
* Creates a log when a payment is deleted.
*
* @param \Drupal\commerce_payment\Event\PaymentEvent $event
* The payment event.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function onPaymentDelete(PaymentEvent $event) {
$this->logPayment($event->getPayment(), 'payment_delete');
}

/**
* Creates a log when a payment is changed.
*
* @param \Drupal\commerce_payment\Entity\PaymentInterface $payment
* The payment.
* @param string $templateId
* The log template ID.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
protected function logPayment(PaymentInterface $payment, $templateId) {
$this->logStorage->generate($payment, $templateId, [
'amount' => $payment->getAmount(),
])->save();
}

}
34 changes: 34 additions & 0 deletions modules/log/src/PaymentListBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Drupal\commerce_log;

use Drupal\commerce_payment\PaymentListBuilder as BasePaymentListBuilder;

/**
* Overrides the list builder for payments.
*/
class PaymentListBuilder extends BasePaymentListBuilder {

/**
* {@inheritdoc}
*/
public function render() {
$build = parent::render();
$entityIds = [];
foreach ($this->load() as $entity) {
$entityIds[] = $entity->id();
}
$build['log']['title'] = [
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe some views expert will figure out how to print the title. It didn't want to. So I punted and did this hack.

'#markup' => '<h3>' . $this->t('Payment activity') . '</h3>',
];
$build['log']['activity'] = [
'#type' => 'view',
'#name' => 'commerce_activity',
'#display_id' => 'default',
'#arguments' => [implode('+', $entityIds), 'commerce_payment'],
'#embed' => FALSE,
];
return $build;
}

}
1 change: 1 addition & 0 deletions modules/payment/src/Entity/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* bundle_plugin_type = "commerce_payment_type",
* handlers = {
* "access" = "Drupal\commerce_payment\PaymentAccessControlHandler",
* "event" = "Drupal\commerce_payment\Event\PaymentEvent",
* "list_builder" = "Drupal\commerce_payment\PaymentListBuilder",
* "storage" = "Drupal\commerce_payment\PaymentStorage",
* "form" = {
Expand Down
43 changes: 43 additions & 0 deletions modules/payment/src/Event/PaymentEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Drupal\commerce_payment\Event;

use Drupal\commerce_payment\Entity\PaymentInterface;
use Drupal\commerce_price\Price;
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
* The payment.
*/
public function getPayment() {
return $this->payment;
}

}
67 changes: 67 additions & 0 deletions modules/payment/src/Event/PaymentEvents.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,74 @@ final class PaymentEvents {
* @Event
*
* @see \Drupal\commerce_payment\Event\FilterPaymentGatewaysEvent
*
* @var string
*/
const FILTER_PAYMENT_GATEWAYS = 'commerce_payment.filter_payment_gateways';


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

/**
* Name of the event fired before saving a payment.
*
* @Event
*
* @see \Drupal\commerce_payment\Event\PaymentEvent
*
* @var string
*/
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';
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see an INSERT and a CREATE in product variation events. Do we need to duplicate the same here? The docs between the two aren't very clear about what the difference is.


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

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

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

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: 'Payment 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 }
Loading