Merx

Upgrade Merx 1 to 2

What changed between Merx 1 and Merx 2, and what you have to rewrite.

Merx 2 renames a lot and moves a few things to a different place entirely. Work through the sections below in order; each one is independent.

Order page model

The abstract model is gone. Extend the class instead.

/site/models/order.php (Merx 1)
class OrderPage extends OrderPageAbstract
{
/site/models/order.php (Merx 2)
class OrderPage extends \Wagnerwagner\Merx\OrderPage
{

Options

Every option moved namespace.

ww.merx.[name] → wagnerwagner.merx.[name]

Three are gone. currency and currencySymbol are replaced by pricing rules, which set the currency per rule instead of once for the whole shop. successPage is replaced by the API — see The success page below.

Everything else is new, including license, which a production shop needs. The config options reference lists them all.

Products

A product carried its tax rate as a percentage. It now names a tax rule, and the rate lives in the config.

/content/products/1_bike/product.txt (Merx 1)
Price: 2000

----

Tax: 19
/content/products/1_bike/product.txt (Merx 2)
Price: 2000

----

Taxrule: default

The rule itself goes into taxRules, with the rate as a decimal: Tax: 19 becomes 'rate' => 0.19. See Taxes.

Merx counts the stock itself. A Stock field keeps working as it is, but delete the hooks that lowered it, or every order lowers it twice. The method returns the number now, not the field:

$page->stock()->toFloat() → $page->stock()

Hooks

initializePayment:before → initializeOrder:before
initializePayment:after → initializeOrder:after
completePayment:before → createOrder:before
completePayment:after → createOrder:after

The single ww.merx.cart hook is gone. It fired whenever a cart was built; there is now one pair of hooks per operation.

cart → cart.add:after, cart.remove:after and cart.updateItem:after

Apart from that, there are many more new hooks.

Merx methods

Merx::initializePayment → Merx::initializeOrder
Merx::completePayment → Merx::createOrder
Merx::formatPrice → Merx::formatCurrency

Merx::calculateNet, Merx::getFieldError, Merx::setMessage and Merx::getMessage are gone without a replacement. Net prices are part of Price now, and field errors come back from the checkout endpoint as JSON.

formatCurrency takes a currency, where formatPrice used the global option. You can wrap it.

/site/config/config.php
<?php
if (!function_exists('formatPrice')) {
  function formatPrice(?float $price) {
    return Merx::formatCurrency($price, 'EUR');
  }
}

Cart and items

$cart->append() → $cart->add()
$cart->update([…]) → $cart->updateItem($key, […]), one item at a time
$cart->getSum() → $cart->total()
$cart->getTax() → $cart->total()->tax
$cart->getTaxRates() → $cart->taxRates()

getFormattedItems() is gone. Items format themselves — see Reading cart items below.

Adding to the cart

add() took an id plus arbitrary keys at the top level. It now accepts the parameters of new ListItem() and nothing else, so any other key fails with Unknown named parameter.

The identifier is key instead of id, the product page is page, and your own attributes belong in data. Leaving out key makes Merx use the page’s UUID.

Merx 1
$cart->add([
  'id' => 'products/nice-shoes',
  'color' => 'red',
]);
Merx 2
$cart->add([
  'key' => 'nice-shoes-red',
  'page' => 'products/nice-shoes',
  'data' => ['color' => 'red'],
]);

Reading cart items

Cart items were arrays. They are ListItem objects now, in the cart as well as in $orderPage->cart().

$cartItem['id'] → $item->page
$cartItem['quantity'] → $item->quantity
$cartItem['price'] → $item->price

Order page

$orderPage->invoiceNumber() → $orderPage->orderNumber()
$orderPage->invoiceDate() → $orderPage->dateCreated()
$orderPage->payedDate() and paidDate() → $orderPage->datePaid()
$orderPage->paymentComplete() → $orderPage->isPaid()
$orderPage->formattedSum() → $orderPage->total()

The order number is stored on the page now. Merx 1 derived it from the page’s sorting number, so it changed when the order was re-sorted. You can replace how it is built with the orderNumber option.

Existing orders

Merx does not migrate the orders you already have. Rename their fields yourself, or leave them as they are if you only keep them for the record.

Invoicedate → Datecreated
Paiddate → Datepaid
Paymentmethod → Paymentgateway

Paymentcomplete is gone. An order is paid once it has a Datepaid.

Every entry in Items needs a type — product for anything you sell. Merx 1 wrote template instead.

And because the order number is a field now, an order without Ordernumber stays untitled.

Blueprints

Kirby 6 replaced sections with fields, and so did Merx.

sections/order → fields/order, a field group
sections/orders → fields/orders, a pagelist field
sections/payment → fields/payment, a field group

Where you extend one of them, change the name and move it from sections: to fields:. Under sections:, Kirby shows an error in its place.

If you replaced one of them with a file of your own, such as /site/blueprints/sections/orders.yml, move it to /site/blueprints/fields/ and turn it into a field: type: fields becomes type: group, type: pages becomes type: pagelist and headline becomes label. A file left in sections/ is ignored without an error.

layouts/order also has a Personal data tab now. It shows fields/personal-data, and that is where your customer fields go — see Validate checkout. Kirby’s Sections become fields covers your other blueprints.

The success page

Merx 1 created a virtual success page and sent the customer there. There is none in Merx 2.

The provider returns the customer to /api/shop/success, which completes the payment, writes the order page and redirects to it. Delete the successPage option and the template that went with it.

Error messages

Three translation keys were renamed along with the methods.

error.merx.initializePayment → error.merx.initializeOrder
error.merx.completePayment → error.merx.createOrder
error.merx.noPaymentMethod → error.merx.noPaymentGateway

If you overrode any of them, the translations reference lists every string Merx ships today.

Payment methods and gateways

Payment methods credit-card-sca, credit-card, sepa-debit, klarna and ideal are removed in favor of stripe-elements. You can still use all payment methods mentioned and many more with Stripe Elements.

The field that selects one is paymentGateway, not paymentMethod.