Commit 8153697d authored by mglaman's avatar mglaman Committed by bojanz

Issue #2839060: Create an API for entity logs

parent f04be4d0
commerce_cart:
label: Cart
entity_type: commerce_order
commerce_order:
label: Order
entity_type: commerce_order
cart_entity_added:
category: commerce_cart
label: 'Added to cart'
template: '<p><em>{{ purchased_entity_label }}</em> added to the cart.</p>'
cart_item_removed:
category: commerce_cart
label: 'Removed from cart'
template: '<p><em>{{ purchased_entity_label }}</em> removed from the cart.</p>'
order_placed:
category: commerce_order
label: 'Order placed'
template: '<p>The order was placed.</p>'
name: Commerce Log
type: module
description: 'Provides activity logs for Commerce entities.'
package: Commerce
core: 8.x
dependencies:
- user
<?php
/**
* @file
* Provides activity logs for Commerce entities.
*/
/**
* Implements hook_preprocess_commerce_order().
*/
function commerce_log_preprocess_commerce_order(&$variables) {
/** @var \Drupal\commerce_order\Entity\OrderInterface $order */
$order = $variables['elements']['#commerce_order'];
$variables['order']['activity'] = [
'#type' => 'view',
'#name' => 'commerce_activity',
'#display_id' => 'default',
'#arguments' => [$order->id(), 'commerce_order'],
'#embed' => TRUE,
'#title' => t('Order activity'),
];
}
services:
plugin.manager.commerce_log_template:
class: Drupal\commerce_log\LogTemplateManager
arguments: ['@module_handler', '@cache.discovery', '@plugin.manager.commerce_log_category']
plugin.manager.commerce_log_category:
class: Drupal\commerce_log\LogCategoryManager
arguments: ['@module_handler', '@cache.discovery']
commerce_log.cart_event_subscriber:
class: Drupal\commerce_log\EventSubscriber\CartEventSubscriber
arguments: ['@entity_type.manager']
tags:
- { name: event_subscriber }
commerce_log.order_event_subscriber:
class: Drupal\commerce_log\EventSubscriber\OrderEventSubscriber
arguments: ['@entity_type.manager']
tags:
- { name: event_subscriber }
This diff is collapsed.
<?php
namespace Drupal\commerce_log\Entity;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
/**
* Defines the log entity class.
*
* @ContentEntityType(
* id = "commerce_log",
* label = @Translation("Log"),
* label_singular = @Translation("log"),
* label_plural = @Translation("logs"),
* label_count = @PluralTranslation(
* singular = "@count log",
* plural = "@count logs",
* ),
* handlers = {
* "access" = "Drupal\commerce\EntityAccessControlHandler",
* "list_builder" = "Drupal\commerce_log\LogListBuilder",
* "storage" = "Drupal\commerce_log\LogStorage",
* "view_builder" = "Drupal\commerce_log\LogViewBuilder",
* "views_data" = "Drupal\views\EntityViewsData",
* },
* base_table = "commerce_log",
* entity_keys = {
* "id" = "log_id",
* "uuid" = "uuid",
* },
* )
*/
class Log extends ContentEntityBase implements LogInterface {
/**
* {@inheritdoc}
*/
public function getUserId() {
return $this->get('uid')->target_id;
}
/**
* {@inheritdoc}
*/
public function getUser() {
return $this->get('uid')->entity;
}
/**
* {@inheritdoc}
*/
public function label() {
return $this->getCategory()->getLabel() . ': ' . $this->getTemplate()->getLabel();
}
/**
* {@inheritdoc}
*/
public function getCategoryId() {
return $this->get('category_id')->value;
}
/**
* {@inheritdoc}
*/
public function getCategory() {
$log_category_manager = \Drupal::service('plugin.manager.commerce_log_category');
return $log_category_manager->createInstance($this->getCategoryId());
}
/**
* {@inheritdoc}
*/
public function getTemplateId() {
return $this->get('template_id')->value;
}
/**
* {@inheritdoc}
*/
public function getTemplate() {
$log_template_manager = \Drupal::service('plugin.manager.commerce_log_template');
return $log_template_manager->createInstance($this->getTemplateId());
}
/**
* {@inheritdoc}
*/
public function getSourceEntityId() {
return $this->get('source_entity_id')->value;
}
/**
* {@inheritdoc}
*/
public function getSourceEntityTypeId() {
return $this->get('source_entity_type')->value;
}
/**
* {@inheritdoc}
*/
public function getSourceEntity() {
return \Drupal::entityTypeManager()
->getStorage($this->getSourceEntityTypeId())
->load($this->getSourceEntityId());
}
/**
* {@inheritdoc}
*/
public function getParams() {
return $this->get('params')->first()->getValue();
}
/**
* {@inheritdoc}
*/
public function setParams(array $params) {
$this->set('params', $params);
return $this;
}
/**
* {@inheritdoc}
*/
public function getCreatedTime() {
return $this->get('created')->value;
}
/**
* {@inheritdoc}
*/
public function setCreatedTime($timestamp) {
$this->set('created', $timestamp);
return $this;
}
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields = parent::baseFieldDefinitions($entity_type);
$fields['uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('User'))
->setDescription(t('The user for the log.'))
->setSetting('target_type', 'user')
->setSetting('handler', 'default')
->setDefaultValueCallback('Drupal\commerce_log\Entity\Log::getCurrentUserId');
$fields['template_id'] = BaseFieldDefinition::create('string')
->setLabel(t('Log template ID'))
->setDescription(t('The log template plugin ID'));
$fields['category_id'] = BaseFieldDefinition::create('string')
->setLabel(t('Log category ID'))
->setDescription(t('The log category plugin ID'));
$fields['source_entity_id'] = BaseFieldDefinition::create('integer')
->setLabel(t('Source entity ID'))
->setDescription(t('The source entity ID'));
$fields['source_entity_type'] = BaseFieldDefinition::create('string')
->setLabel(t('Source entity type'))
->setDescription(t('The source entity type'));
$fields['params'] = BaseFieldDefinition::create('map')
->setLabel(t('Params'))
->setDescription(t('A serialized array of parameters for the log template.'));
$fields['created'] = BaseFieldDefinition::create('created')
->setLabel(t('Created'))
->setDescription(t('The time when the log was created.'));
return $fields;
}
/**
* Default value callback for 'uid' base field definition.
*
* @see ::baseFieldDefinitions()
*
* @return array
* An array of default values.
*/
public static function getCurrentUserId() {
return [\Drupal::currentUser()->id()];
}
}
<?php
namespace Drupal\commerce_log\Entity;
use Drupal\Core\Entity\ContentEntityInterface;
interface LogInterface extends ContentEntityInterface {
/**
* Gets the user ID.
*
* @return int|null
* The user ID.
*/
public function getUserId();
/**
* Gets the user.
*
* @return \Drupal\user\UserInterface|null
* The user entity.
*/
public function getUser();
/**
* Gets the category ID.
*
* @return string
* The log category ID.
*/
public function getCategoryId();
/**
* Gets the category.
*
* @return \Drupal\commerce_log\Plugin\LogCategory\LogCategoryInterface
* The category.
*/
public function getCategory();
/**
* Gets the template ID.
*
* @return string
* The template ID.
*/
public function getTemplateId();
/**
* Gets the template.
*
* @return \Drupal\commerce_log\Plugin\LogTemplate\LogTemplateInterface
* The template.
*/
public function getTemplate();
/**
* Gets the source entity ID.
*
* @return mixed
* The entity ID.
*/
public function getSourceEntityId();
/**
* Gets the source entity type ID.
*
* @return string
* The entity type ID.
*/
public function getSourceEntityTypeId();
/**
* Gets the source entity.
*
* @return \Drupal\Core\Entity\ContentEntityInterface
* The source entity.
*/
public function getSourceEntity();
/**
* Gets the template parameters.
*
* @return array
* The parameters.
*/
public function getParams();
/**
* Sets the template parameters.
*
* @param array $params
* The parameters.
*
* @return $this
*/
public function setParams(array $params);
/**
* Gets the log creation timestamp.
*
* @return int
* Creation timestamp of the log.
*/
public function getCreatedTime();
/**
* Sets the log creation timestamp.
*
* @param int $timestamp
* The log creation timestamp.
*
* @return $this
*/
public function setCreatedTime($timestamp);
}
<?php
namespace Drupal\commerce_log\EventSubscriber;
use Drupal\commerce_cart\Event\CartEntityAddEvent;
use Drupal\commerce_cart\Event\CartEvents;
use Drupal\commerce_cart\Event\CartOrderItemRemoveEvent;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class CartEventSubscriber implements EventSubscriberInterface {
/**
* The log storage.
*
* @var \Drupal\commerce_log\LogStorageInterface
*/
protected $logStorage;
/**
* Constructs a new CartEventSubscriber object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->logStorage = $entity_type_manager->getStorage('commerce_log');
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events = [
CartEvents::CART_ENTITY_ADD => ['onCartEntityAdd', -100],
CartEvents::CART_ORDER_ITEM_REMOVE => ['onCartOrderItemRemove', -100],
];
return $events;
}
/**
* Creates a log when an entity has been added to the cart.
*
* @param \Drupal\commerce_cart\Event\CartEntityAddEvent $event
* The cart event.
*/
public function onCartEntityAdd(CartEntityAddEvent $event) {
$cart = $event->getCart();
$purchased_entity = $event->getOrderItem()->getPurchasedEntity();
$this->logStorage->generate($cart, 'cart_entity_added', [
'purchased_entity_label' => $purchased_entity->label(),
])->save();
}
/**
* Creates a log when an order item has been removed from the cart.
*
* @param \Drupal\commerce_cart\Event\CartOrderItemRemoveEvent $event
* The cart event.
*/
public function onCartOrderItemRemove(CartOrderItemRemoveEvent $event) {
$cart = $event->getCart();
$order_item = $event->getOrderItem();
$this->logStorage->generate($cart, 'cart_item_removed', [
'purchased_entity_label' => $order_item->getPurchasedEntity()->label(),
])->save();
}
}
<?php
namespace Drupal\commerce_log\EventSubscriber;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\state_machine\Event\WorkflowTransitionEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class OrderEventSubscriber implements EventSubscriberInterface {
/**
* The log storage.
*
* @var \Drupal\commerce_log\LogStorageInterface
*/
protected $logStorage;
/**
* Constructs a new OrderEventSubscriber object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->logStorage = $entity_type_manager->getStorage('commerce_log');
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events = [
'commerce_order.place.pre_transition' => ['onPlaceTransition', -100],
];
return $events;
}
/**
* Creates a log when an order is placed.
*
* @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
* The transition event.
*/
public function onPlaceTransition(WorkflowTransitionEvent $event) {
/** @var \Drupal\commerce_order\Entity\OrderInterface $order */
$order = $event->getEntity();
$this->logStorage->generate($order, 'order_placed')->save();
}
}
<?php
namespace Drupal\commerce_log;
use Drupal\commerce_log\Plugin\LogCategory\LogCategory;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
use Drupal\Core\Plugin\Discovery\YamlDiscovery;
/**
* Manages discovery and instantiation of commerce_log_category plugins.
*
* @see plugin_api
*/
class LogCategoryManager extends DefaultPluginManager implements LogCategoryManagerInterface {
/**
* Default values for each commerce_log_category plugin.
*
* @var array
*/
protected $defaults = [
'id' => '',
'label' => '',
'entity_type' => '',
'class' => LogCategory::class,
];
/**
* Constructs a new LogCategoryManager object.
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* The cache backend.
*/
public function __construct(ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend) {
$this->moduleHandler = $module_handler;
$this->setCacheBackend($cache_backend, 'commerce_log_category', ['commerce_log_category']);
}
/**
* {@inheritdoc}
*/
protected function getDiscovery() {
if (!isset($this->discovery)) {
$this->discovery = new YamlDiscovery('commerce_log_categories', $this->moduleHandler->getModuleDirectories());
$this->discovery->addTranslatableProperty('label', 'label_context');
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
}
return $this->discovery;
}
/**
* {@inheritdoc}
*/
public function processDefinition(&$definition, $plugin_id) {
parent::processDefinition($definition, $plugin_id);
$definition['id'] = $plugin_id;
foreach (['label', 'entity_type'] as $required_property) {
if (empty($definition[$required_property])) {
throw new PluginException(sprintf('The commerce_log_category %s must define the %s property.', $plugin_id, $required_property));
}
}
}
/**
* {@inheritdoc}
*/
public function getDefinitionsByEntityType($entity_type_id = NULL) {
$definitions = $this->getDefinitions();
if ($entity_type_id) {
$definitions = array_filter($definitions, function ($definition) use ($entity_type_id) {
return $definition['entity_type'] == $entity_type_id;
});
}
return $definitions;
}
}
<?php
namespace Drupal\commerce_log;
use Drupal\Component\Plugin\PluginManagerInterface;
/**
* Defines the interface for commerce_log_category plugin managers.
*/
interface LogCategoryManagerInterface extends PluginManagerInterface {
/**
* Gets the definitions filtered by entity type.
*
* @param string $entity_type_id
* The entity type ID.
*
* @return array
* The definitions.
*/
public function getDefinitionsByEntityType($entity_type_id = NULL);
}
<?php
namespace Drupal\commerce_log;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityListBuilder;
class LogListBuilder extends EntityListBuilder {
/**
* {@inheritdoc}
*/
public function buildHeader() {
$header['type'] = t('Type');
$header['time'] = t('Time');
$header['log'] = t('Log');
return $header + parent::buildHeader();
}
/**
* {@inheritdoc}
*/
public function buildRow(EntityInterface $entity) {
/** @var \Drupal\commerce_log\Entity\LogInterface $entity */
$row['type'] = $entity->getCategory()->getLabel();
$row['time'] = $entity->getCreatedTime();
$row['log'] = \Drupal::entityTypeManager()->getViewBuilder($entity->getEntityTypeId())->view($entity);
return $row + parent::buildRow($entity);
}
}
<?php
namespace Drupal\commerce_log;
use Drupal\commerce\CommerceContentEntityStorage;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class LogStorage extends CommerceContentEntityStorage implements LogStorageInterface {
/**
* The log template manager.
*
* @var \Drupal\commerce_log\LogTemplateManagerInterface
*/
protected $logTemplateManager;
/**
* Constructs a new CommerceContentEntityStorage object.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type definition.
* @param \Drupal\Core\Database\Connection $database
* The database connection to be used.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
* The cache backend to be used.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
* The event dispatcher.
* @param \Drupal\commerce_log\LogTemplateManagerInterface $log_template_manager
* The log template manager.
*/
public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, EventDispatcherInterface $event_dispatcher, LogTemplateManagerInterface $log_template_manager) {
parent::__construct($entity_type, $database, $entity_manager, $cache, $language_manager, $event_dispatcher);
$this->logTemplateManager = $log_template_manager;
}
/**
* {@inheritdoc}
*/
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
return new static(
$entity_type,
$container->get('database'),
$container->get('entity.manager'),
$container->get('cache.entity'),
$container->get('language_manager'),
$container->get('event_dispatcher'),