From e6c0969c828e4d1c2a94485a6f97705766f5ca6b Mon Sep 17 00:00:00 2001 From: heddn Date: Tue, 19 Sep 2017 15:09:55 -0600 Subject: [PATCH 1/3] Initial PoC --- .../commerce_log.commerce_log_categories.yml | 4 + .../commerce_log.commerce_log_templates.yml | 13 ++ modules/log/commerce_log.module | 23 +++- .../log/src/CommerceLogServiceProvider.php | 8 ++ modules/log/src/Event/LogEvents.php | 19 +++ ...oductVariationChangedFieldsFilterEvent.php | 46 +++++++ .../ProductVariationEventSubscriber.php | 128 ++++++++++++++++++ 7 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 modules/log/src/Event/LogEvents.php create mode 100644 modules/log/src/Event/ProductVariationChangedFieldsFilterEvent.php create mode 100644 modules/log/src/EventSubscriber/ProductVariationEventSubscriber.php diff --git a/modules/log/commerce_log.commerce_log_categories.yml b/modules/log/commerce_log.commerce_log_categories.yml index b921707752..7e5acba560 100644 --- a/modules/log/commerce_log.commerce_log_categories.yml +++ b/modules/log/commerce_log.commerce_log_categories.yml @@ -5,3 +5,7 @@ commerce_cart: commerce_order: label: Order entity_type: commerce_order + +commerce_product: + label: Product + entity_type: commerce_product diff --git a/modules/log/commerce_log.commerce_log_templates.yml b/modules/log/commerce_log.commerce_log_templates.yml index a9aee4860d..1a95c8b080 100644 --- a/modules/log/commerce_log.commerce_log_templates.yml +++ b/modules/log/commerce_log.commerce_log_templates.yml @@ -27,3 +27,16 @@ order_assigned: category: commerce_order label: 'Order assigned' template: '

The order was assigned to {{ user }}.

' + +variation_added: + category: commerce_product + label: 'Variation added' + template: '

Variation id {{ id }} with sku {{ sku }} was added.

' +variation_field_changed: + category: commerce_product + label: 'Variation changed' + template: '

Variation id {{ id }} with sku {{ sku }} had the following fields changed: {{ changed_fields }}.

' +variation_deleted: + category: commerce_product + label: 'Variation deleted' + template: '

Variation id {{ id }} with sku {{ sku }} was deleted.

' diff --git a/modules/log/commerce_log.module b/modules/log/commerce_log.module index 9c4927c624..8e0ed5d393 100644 --- a/modules/log/commerce_log.module +++ b/modules/log/commerce_log.module @@ -6,7 +6,7 @@ */ /** - * Implements hook_preprocess_commerce_order(). + * Implements hook_preprocess_HOOK() for commerce_order. */ function commerce_log_preprocess_commerce_order(&$variables) { /** @var \Drupal\commerce_order\Entity\OrderInterface $order */ @@ -20,3 +20,24 @@ function commerce_log_preprocess_commerce_order(&$variables) { '#title' => t('Order activity'), ]; } + +/** + * Implements hook_preprocess_HOOK() for commerce_product_form. + */ +function commerce_log_preprocess_commerce_product_form(&$variables) { + /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ + $product = \Drupal::service('current_route_match')->getParameter('commerce_product'); + $variables['form']['actions']['activity'] = [ + '#weight' => 100, + 'title' => [ + '#markup' => '

' . t('Product activity') . '

', + ], + 'log' => [ + '#type' => 'view', + '#name' => 'commerce_activity', + '#display_id' => 'default', + '#arguments' => [$product->id(), 'commerce_product'], + '#weight' => 100, + ], + ]; +} diff --git a/modules/log/src/CommerceLogServiceProvider.php b/modules/log/src/CommerceLogServiceProvider.php index 769cc5fc21..6d939d9267 100644 --- a/modules/log/src/CommerceLogServiceProvider.php +++ b/modules/log/src/CommerceLogServiceProvider.php @@ -2,6 +2,8 @@ namespace Drupal\commerce_log; +use Drupal\commerce_log\EventSubscriber\ProductVariationEventSubscriber; +use Drupal\commerce_product\Event\ProductVariationEvent; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DependencyInjection\ServiceProviderBase; use Symfony\Component\DependencyInjection\Reference; @@ -29,6 +31,12 @@ public function register(ContainerBuilder $container) { ->addTag('event_subscriber') ->addArgument(new Reference('entity_type.manager')); } + if (isset($modules['commerce_product'])) { + $container->register('commerce_log.product_variation_subscriber', ProductVariationEventSubscriber::class) + ->addTag('event_subscriber') + ->addArgument(new Reference('entity_type.manager')) + ->addArgument(new Reference('event_dispatcher')); + } } } diff --git a/modules/log/src/Event/LogEvents.php b/modules/log/src/Event/LogEvents.php new file mode 100644 index 0000000000..8198cf8e67 --- /dev/null +++ b/modules/log/src/Event/LogEvents.php @@ -0,0 +1,19 @@ +fields = $fields; + } + + /** + * Gets the fields. + * + * @return array + * The fields. + */ + public function getFields() { + return $this->fields; + } + + /** + * Sets the fields. + * + * @return \Drupal\commerce_log\Event\ProductVariationChangedFieldsFilterEvent + * The product variation changed field filter event. + */ + public function setFields(array $fields) { + $this->fields = $fields; + return $this; + } +} diff --git a/modules/log/src/EventSubscriber/ProductVariationEventSubscriber.php b/modules/log/src/EventSubscriber/ProductVariationEventSubscriber.php new file mode 100644 index 0000000000..7f3c2b12a4 --- /dev/null +++ b/modules/log/src/EventSubscriber/ProductVariationEventSubscriber.php @@ -0,0 +1,128 @@ +logStorage = $entityTypeManager->getStorage('commerce_log'); + $this->eventDispatcher = $eventDispatcher; + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events = [ + ProductEvents::PRODUCT_VARIATION_PRESAVE => ['onVariationPresave', -100], + ProductEvents::PRODUCT_VARIATION_PREDELETE => ['onVariationPredelete', -100], + ]; + return $events; + } + + /** + * Creates a log before saving a product variation. + * + * @param \Drupal\commerce_product\Event\ProductVariationEvent $event + * The variation event. + * + * @throws \Drupal\Core\Entity\EntityStorageException + */ + public function onVariationPresave(ProductVariationEvent $event) { + if ($product = $event->getProductVariation()->getProduct()) { + $variation = $event->getProductVariation(); + $original = $variation->original; + // If there isn't a related product yet, then it is a new variation. + if (!$original->getProduct()) { + $this->logStorage->generate($product, 'variation_added', [ + 'id' => $event->getProductVariation()->id(), + 'sku' => $event->getProductVariation()->getSku(), + ])->save(); + } + elseif ($changedValues = $this->getChangedFields($original, $variation)) { + $this->logStorage->generate($product, 'variation_field_changed', [ + 'id' => $event->getProductVariation()->id(), + 'sku' => $event->getProductVariation()->getSku(), + 'changed_fields' => json_encode($changedValues, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT), + ])->save(); + } + } + } + + /** + * Creates a log when a product variation is deleted. + * + * @param \Drupal\commerce_product\Event\ProductVariationEvent $event + * The variation event. + * + * @throws \Drupal\Core\Entity\EntityStorageException + */ + public function onVariationPredelete(ProductVariationEvent $event) { + $this->logStorage->generate($event->getProductVariation()->getProduct(), 'variation_deleted', [ + 'id' => $event->getProductVariation()->id(), + 'sku' => $event->getProductVariation()->getSku(), + ])->save(); + } + + /** + * Determine the changed fields and their values. + * + * @param \Drupal\commerce_product\Entity\ProductVariationInterface $original + * The original product variation. + * @param \Drupal\commerce_product\Entity\ProductVariationInterface $new + * The new product variation. + * + * @return array + * A list of changed values + */ + protected function getChangedFields(ProductVariationInterface $original, ProductVariationInterface $new) { + $changedFields = new ProductVariationChangedFieldsFilterEvent(['price', 'sku', 'status', 'title']); + $this->eventDispatcher->dispatch(LogEvents::PRODUCT_VARIATION_CHANGED_FIELDS_FILTER, $changedFields); + $changedValues = []; + foreach ($changedFields->getFields() as $field) { + $newValue = $new->{$field}->getValue(); + $originalValue = $original->{$field}->getValue(); + if ($newValue != $originalValue) { + $changedValues[$field] = [ + 'Original value' => $originalValue, + 'New value' => $newValue, + ]; + } + } + return $changedValues; + } + +} From c8d02e02b6b31711408a80c180ade5ee4e79f078 Mon Sep 17 00:00:00 2001 From: heddn Date: Tue, 19 Sep 2017 15:25:59 -0600 Subject: [PATCH 2/3] update log template --- modules/log/commerce_log.commerce_log_templates.yml | 6 +++--- .../src/EventSubscriber/ProductVariationEventSubscriber.php | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/log/commerce_log.commerce_log_templates.yml b/modules/log/commerce_log.commerce_log_templates.yml index 1a95c8b080..4ee3b4aaf2 100644 --- a/modules/log/commerce_log.commerce_log_templates.yml +++ b/modules/log/commerce_log.commerce_log_templates.yml @@ -31,12 +31,12 @@ order_assigned: variation_added: category: commerce_product label: 'Variation added' - template: '

Variation id {{ id }} with sku {{ sku }} was added.

' + template: '

Variation added

id: {{ id }}

sku: {{ sku }}

title: {{ label }}

' variation_field_changed: category: commerce_product label: 'Variation changed' - template: '

Variation id {{ id }} with sku {{ sku }} had the following fields changed: {{ changed_fields }}.

' + template: '

Variation changed

id: {{ id }}

sku: {{ sku }}

changed fields: {{ changed_fields }}

' variation_deleted: category: commerce_product label: 'Variation deleted' - template: '

Variation id {{ id }} with sku {{ sku }} was deleted.

' + template: '

Variation deleted

id: {{ id }}

sku: {{ sku }}

' diff --git a/modules/log/src/EventSubscriber/ProductVariationEventSubscriber.php b/modules/log/src/EventSubscriber/ProductVariationEventSubscriber.php index 7f3c2b12a4..a21aab8acb 100644 --- a/modules/log/src/EventSubscriber/ProductVariationEventSubscriber.php +++ b/modules/log/src/EventSubscriber/ProductVariationEventSubscriber.php @@ -70,6 +70,7 @@ public function onVariationPresave(ProductVariationEvent $event) { $this->logStorage->generate($product, 'variation_added', [ 'id' => $event->getProductVariation()->id(), 'sku' => $event->getProductVariation()->getSku(), + 'label' => $event->getProductVariation()->label(), ])->save(); } elseif ($changedValues = $this->getChangedFields($original, $variation)) { From 2e15e8d56d386c0c24489e018b30f0de905ce0be Mon Sep 17 00:00:00 2001 From: heddn Date: Thu, 5 Oct 2017 11:03:25 -0600 Subject: [PATCH 3/3] fix the tests --- .../commerce_log.commerce_log_categories.yml | 4 + .../commerce_log.commerce_log_templates.yml | 13 ++ modules/log/commerce_log.module | 24 +++- .../log/src/CommerceLogServiceProvider.php | 7 + modules/log/src/Event/LogEvents.php | 19 +++ ...oductVariationChangedFieldsFilterEvent.php | 47 +++++++ .../ProductVariationEventSubscriber.php | 129 ++++++++++++++++++ .../tests/src/Kernel/OrderIntegrationTest.php | 4 +- 8 files changed, 244 insertions(+), 3 deletions(-) create mode 100644 modules/log/src/Event/LogEvents.php create mode 100644 modules/log/src/Event/ProductVariationChangedFieldsFilterEvent.php create mode 100644 modules/log/src/EventSubscriber/ProductVariationEventSubscriber.php diff --git a/modules/log/commerce_log.commerce_log_categories.yml b/modules/log/commerce_log.commerce_log_categories.yml index b921707752..7e5acba560 100644 --- a/modules/log/commerce_log.commerce_log_categories.yml +++ b/modules/log/commerce_log.commerce_log_categories.yml @@ -5,3 +5,7 @@ commerce_cart: commerce_order: label: Order entity_type: commerce_order + +commerce_product: + label: Product + entity_type: commerce_product diff --git a/modules/log/commerce_log.commerce_log_templates.yml b/modules/log/commerce_log.commerce_log_templates.yml index a9aee4860d..4ee3b4aaf2 100644 --- a/modules/log/commerce_log.commerce_log_templates.yml +++ b/modules/log/commerce_log.commerce_log_templates.yml @@ -27,3 +27,16 @@ order_assigned: category: commerce_order label: 'Order assigned' template: '

The order was assigned to {{ user }}.

' + +variation_added: + category: commerce_product + label: 'Variation added' + template: '

Variation added

id: {{ id }}

sku: {{ sku }}

title: {{ label }}

' +variation_field_changed: + category: commerce_product + label: 'Variation changed' + template: '

Variation changed

id: {{ id }}

sku: {{ sku }}

changed fields: {{ changed_fields }}

' +variation_deleted: + category: commerce_product + label: 'Variation deleted' + template: '

Variation deleted

id: {{ id }}

sku: {{ sku }}

' diff --git a/modules/log/commerce_log.module b/modules/log/commerce_log.module index 9c4927c624..fa02d01646 100644 --- a/modules/log/commerce_log.module +++ b/modules/log/commerce_log.module @@ -6,7 +6,7 @@ */ /** - * Implements hook_preprocess_commerce_order(). + * Implements hook_preprocess_HOOK() for commerce_order. */ function commerce_log_preprocess_commerce_order(&$variables) { /** @var \Drupal\commerce_order\Entity\OrderInterface $order */ @@ -20,3 +20,25 @@ function commerce_log_preprocess_commerce_order(&$variables) { '#title' => t('Order activity'), ]; } + +/** + * Implements hook_preprocess_HOOK() for commerce_product_form. + */ +function commerce_log_preprocess_commerce_product_form(&$variables) { + /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ + if ($product = \Drupal::service('current_route_match')->getParameter('commerce_product')) { + $variables['form']['actions']['activity'] = [ + '#weight' => 100, + 'title' => [ + '#markup' => '

' . t('Product activity') . '

', + ], + 'log' => [ + '#type' => 'view', + '#name' => 'commerce_activity', + '#display_id' => 'default', + '#arguments' => [$product->id(), 'commerce_product'], + '#weight' => 100, + ], + ]; + } +} diff --git a/modules/log/src/CommerceLogServiceProvider.php b/modules/log/src/CommerceLogServiceProvider.php index 769cc5fc21..547b6f0dd6 100644 --- a/modules/log/src/CommerceLogServiceProvider.php +++ b/modules/log/src/CommerceLogServiceProvider.php @@ -2,6 +2,7 @@ namespace Drupal\commerce_log; +use Drupal\commerce_log\EventSubscriber\ProductVariationEventSubscriber; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DependencyInjection\ServiceProviderBase; use Symfony\Component\DependencyInjection\Reference; @@ -29,6 +30,12 @@ public function register(ContainerBuilder $container) { ->addTag('event_subscriber') ->addArgument(new Reference('entity_type.manager')); } + if (isset($modules['commerce_product'])) { + $container->register('commerce_log.product_variation_subscriber', ProductVariationEventSubscriber::class) + ->addTag('event_subscriber') + ->addArgument(new Reference('entity_type.manager')) + ->addArgument(new Reference('event_dispatcher')); + } } } diff --git a/modules/log/src/Event/LogEvents.php b/modules/log/src/Event/LogEvents.php new file mode 100644 index 0000000000..8198cf8e67 --- /dev/null +++ b/modules/log/src/Event/LogEvents.php @@ -0,0 +1,19 @@ +fields = $fields; + } + + /** + * Gets the fields. + * + * @return array + * The fields. + */ + public function getFields() { + return $this->fields; + } + + /** + * Sets the fields. + * + * @return \Drupal\commerce_log\Event\ProductVariationChangedFieldsFilterEvent + * The product variation changed field filter event. + */ + public function setFields(array $fields) { + $this->fields = $fields; + return $this; + } + +} diff --git a/modules/log/src/EventSubscriber/ProductVariationEventSubscriber.php b/modules/log/src/EventSubscriber/ProductVariationEventSubscriber.php new file mode 100644 index 0000000000..a21aab8acb --- /dev/null +++ b/modules/log/src/EventSubscriber/ProductVariationEventSubscriber.php @@ -0,0 +1,129 @@ +logStorage = $entityTypeManager->getStorage('commerce_log'); + $this->eventDispatcher = $eventDispatcher; + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events = [ + ProductEvents::PRODUCT_VARIATION_PRESAVE => ['onVariationPresave', -100], + ProductEvents::PRODUCT_VARIATION_PREDELETE => ['onVariationPredelete', -100], + ]; + return $events; + } + + /** + * Creates a log before saving a product variation. + * + * @param \Drupal\commerce_product\Event\ProductVariationEvent $event + * The variation event. + * + * @throws \Drupal\Core\Entity\EntityStorageException + */ + public function onVariationPresave(ProductVariationEvent $event) { + if ($product = $event->getProductVariation()->getProduct()) { + $variation = $event->getProductVariation(); + $original = $variation->original; + // If there isn't a related product yet, then it is a new variation. + if (!$original->getProduct()) { + $this->logStorage->generate($product, 'variation_added', [ + 'id' => $event->getProductVariation()->id(), + 'sku' => $event->getProductVariation()->getSku(), + 'label' => $event->getProductVariation()->label(), + ])->save(); + } + elseif ($changedValues = $this->getChangedFields($original, $variation)) { + $this->logStorage->generate($product, 'variation_field_changed', [ + 'id' => $event->getProductVariation()->id(), + 'sku' => $event->getProductVariation()->getSku(), + 'changed_fields' => json_encode($changedValues, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT), + ])->save(); + } + } + } + + /** + * Creates a log when a product variation is deleted. + * + * @param \Drupal\commerce_product\Event\ProductVariationEvent $event + * The variation event. + * + * @throws \Drupal\Core\Entity\EntityStorageException + */ + public function onVariationPredelete(ProductVariationEvent $event) { + $this->logStorage->generate($event->getProductVariation()->getProduct(), 'variation_deleted', [ + 'id' => $event->getProductVariation()->id(), + 'sku' => $event->getProductVariation()->getSku(), + ])->save(); + } + + /** + * Determine the changed fields and their values. + * + * @param \Drupal\commerce_product\Entity\ProductVariationInterface $original + * The original product variation. + * @param \Drupal\commerce_product\Entity\ProductVariationInterface $new + * The new product variation. + * + * @return array + * A list of changed values + */ + protected function getChangedFields(ProductVariationInterface $original, ProductVariationInterface $new) { + $changedFields = new ProductVariationChangedFieldsFilterEvent(['price', 'sku', 'status', 'title']); + $this->eventDispatcher->dispatch(LogEvents::PRODUCT_VARIATION_CHANGED_FIELDS_FILTER, $changedFields); + $changedValues = []; + foreach ($changedFields->getFields() as $field) { + $newValue = $new->{$field}->getValue(); + $originalValue = $original->{$field}->getValue(); + if ($newValue != $originalValue) { + $changedValues[$field] = [ + 'Original value' => $originalValue, + 'New value' => $newValue, + ]; + } + } + return $changedValues; + } + +} diff --git a/modules/log/tests/src/Kernel/OrderIntegrationTest.php b/modules/log/tests/src/Kernel/OrderIntegrationTest.php index 988c3809fa..3dea83bc3f 100644 --- a/modules/log/tests/src/Kernel/OrderIntegrationTest.php +++ b/modules/log/tests/src/Kernel/OrderIntegrationTest.php @@ -167,7 +167,7 @@ public function testPlaceValidateFulfillLogs() { $logs = $this->logStorage->loadMultipleByEntity($this->order); $this->assertEquals(2, count($logs)); - $log = $logs[2]; + $log = array_pop($logs); $build = $this->logViewBuilder->view($log); $this->render($build); @@ -180,7 +180,7 @@ public function testPlaceValidateFulfillLogs() { $logs = $this->logStorage->loadMultipleByEntity($this->order); $this->assertEquals(3, count($logs)); - $log = $logs[3]; + $log = array_pop($logs); $build = $this->logViewBuilder->view($log); $this->render($build);