This repository has been archived on 2025-01-19. You can view files and clone it, but cannot push or open issues or pull requests.
oliverdavies.uk-old-sculpin/source/_posts/debugging-drupal-commerce-promotions-illiminate-collections.md

145 lines
3.9 KiB
Markdown
Raw Normal View History

2018-10-26 12:04:46 +00:00
---
title:
Debugging Drupal Commerce Promotions and Adjustments using Illuminate
Collections (Drupal 8)
2020-03-08 14:32:13 +00:00
date: 2018-10-24
excerpt:
Using Laravels Illuminate Collections to debug an issue with a Drupal
Commerce promotion.
2018-10-26 12:04:46 +00:00
tags:
- drupal
- drupal-8
- drupal-commerce
- drupal-planet
- illuminate-collections
- laravel-collections
- php
2019-01-15 21:45:34 +00:00
promoted: true
2018-10-26 12:04:46 +00:00
---
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.
2018-10-26 12:04:46 +00:00
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:
2018-10-26 12:04:46 +00:00
```php
$order = [
'id' => 1,
'items' => [
[
'id' => 1,
'adjustments' => [
['name' => 'Adjustment 1'],
['name' => 'Adjustment 2'],
2018-10-26 12:04:46 +00:00
['name' => 'Adjustment 3'],
]
],
[
'id' => 2,
'adjustments' => [
['name' => 'Adjustment 4'],
]
],
[
'id' => 3,
'adjustments' => [
['name' => 'Adjustment 5'],
2018-10-26 12:04:46 +00:00
['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.
2018-10-26 12:04:46 +00:00
```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.
2018-10-26 12:04:46 +00:00
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.
2018-10-26 12:04:46 +00:00
```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:
2020-01-05 20:15:35 +00:00
- 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.
2018-10-26 12:04:46 +00:00
```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.
2018-10-26 12:04:46 +00:00
```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.
2018-10-26 12:04:46 +00:00
Again, I can use a higher order message to directly call `getSourceId()` on the
adjustment and return its value to `map()`.
2018-10-26 12:04:46 +00:00
```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.
2018-10-26 12:04:46 +00:00
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