oliverdavies.uk/source/_posts/debugging-drupal-commerce-illuminate-collections.md

141 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Debugging Drupal Commerce Promotions and Adjustments using Illuminate Collections (Drupal 8)
date: 2018-10-24
excerpt: Using Laravels Illuminate Collections to debug an issue with a Drupal Commerce promotion.
tags:
- drupal
- drupal-8
- drupal-commerce
- drupal-planet
- illuminate-collections
- laravel-collections
- php
promoted: true
---
Today I found another instance where I decided to use [Illuminate
Collections][0] within my Drupal 8 code; whilst I was debugging an issue where a
[Drupal Commerce][1] promotion was incorrectly being applied to an order.
No adjustments were showing in the Drupal UI for that order, so after some
initial investigation and finding that `$order->getAdjustments()` was empty, I
determined that I would need to get the adjustments from each order item within
the order.
If the order were an array, this is how it would be structured in this
situation:
```php
$order = [
'id' => 1,
'items' => [
[
'id' => 1,
'adjustments' => [
['name' => 'Adjustment 1'],
['name' => 'Adjustment 2'],
['name' => 'Adjustment 3'],
]
],
[
'id' => 2,
'adjustments' => [
['name' => 'Adjustment 4'],
]
],
[
'id' => 3,
'adjustments' => [
['name' => 'Adjustment 5'],
['name' => 'Adjustment 6'],
]
],
],
];
```
## Getting the order items
I started by using `$order->getItems()` to load the orders items, converted
them into a Collection, and used the Collections `pipe()` method and the
`dump()` function provided by the [Devel module][2] to output the order items.
```php
collect($order->getItems())
->pipe(function (Collection $collection) {
dump($collection);
});
```
## Get the order item adjustments
Now we have a Collection of order items, for each item we need to get its
adjustments. We can do this with `map()`, then call `getAdjustments()` on the
order item.
This would return a Collection of arrays, with each array containing its own
adjustments, so we can use `flatten()` to collapse all the adjustments into one
single-dimensional array.
```php
collect($order->getItems())
->map(function (OrderItem $order_item) {
return $order_item->getAdjustments();
})
->flatten(1);
```
There are a couple of refactors that we can do here though:
- Use `flatMap()` to combine the `flatten()` and `map()` methods.
- Use [higher order messages][3] to delegate straight to the `getAdjustments()`
method on the order, rather than having to create a closure and call the
method within it.
```php
collect($order->getItems())
->flatMap->getAdjustments();
```
## Filtering
In this scenario, each order item had three adjustments - the correct promotion,
the incorrect one and the standard VAT addition. I wasnt concerned about the
VAT adjustment for debugging, so I used `filter()` to remove it based on the
result of the adjustments `getSourceId()` method.
```php
collect($order->getItems())
->flatMap->getAdjustments()
->filter(function (Adjustment $adjustment) {
return $adjustment->getSourceId() != 'vat';
});
```
## Conclusion
Now I have just the relevant adjustments, I want to be able to load each one to
load it and check its conditions. To do this, I need just the source IDs.
Again, I can use a higher order message to directly call `getSourceId()` on the
adjustment and return its value to `map()`.
```php
collect($order->getItems())
->flatMap->getAdjustments()
->filter(function (Adjustment $adjustment) {
return $adjustment->getSourceId() != 'vat';
})
->map->getSourceId();
```
This returns a Collection containing just the relevant promotion IDs being
applied to the order that I can use for debugging.
Now just to find out why the incorrect promotion was applying!
[0]: https://laravel.com/docs/collections
[1]: https://drupalcommerce.org
[2]: https://www.drupal.org/project/devel
[3]: https://laravel-news.com/higher-order-messaging