Important adjustments for VirtueMart 3.6

Written by Max Milbers on .

VM 3.6 breaking backwards compatibility with some payment methods

There is a good reason for this backward compatibility problem. The old cart just displayed the default values of userfields, but the defaults were not set in the address arrays like $cart->BT. The new cart directly loads the defaults from the userfields into the arrays of the cart holding the addresses. The core provides now a lot more restrictions for payment/shipment methods than before and so it became important, that shipment/payments (and other) works directly with the set default. But the stupid side effect is, that the prior empty values are now most time filled with some defaults. The set defaults are stored in array (for example byDefaultBT) within the cart, so we even know if we just use a default value or a set value.

There is a new cart function getST with the fallback parameter. The function considers the variable STsameAsBT. The ST is only used, when STsameAsBT is empty, else the getST returns the BT.

Now to the code. The old address array of the cart

[ST] => 0

looks now for example like this

[ST] => Array
    (
    [address_type_name] => Address Nickname
    )

So we get with this widely used line in function checkConditions

$address = (($cart->ST == 0) ? $cart->BT : $cart->ST);

always the ST, but the ST is mainly empty and so payments do not show up or even throw errors. To prevent this, just replace the line above by

$address = $cart->getST();

BUT, we really recommend just to use the new core restrictions. In a lot cases it is just adding 2 lines and removing the whole checkConditions function, because it is just overriding the one of the core. Tutorial for adding the core restrictions

In case you want to write a backward compatible plugin, use

if(method_exists($cart,'getST')){
  $address = $cart->getST();
} else {
  $address = (($cart->ST == 0) ? $cart->BT : $cart->ST);
}

But check the Tutorial for adding the core restrictions we use the if case above to directly call the parent function.

Problems due old legacy code

The handling of "automaticSelectedShipment", "automaticSelectedPayment" changed. Since vm3.5+ it is only set to true, when there is only one method.

The functions plgVmOnCheckAutomaticSelectedPayment respectivly plgVmOnCheckAutomaticSelectedShipment should not use anylonger

$return = $this->onCheckAutomaticSelected($cart, $cart_prices);
if (isset($return)) {
return 0;
} else {
return NULL;
}

Just use 

function plgVmOnCheckAutomaticSelectedPayment(VirtueMartCart $cart, array $cart_prices = array(), &$paymentCounter) {
return $this->onCheckAutomaticSelected($cart, $cart_prices, $paymentCounter);
}

or with fallback to old cores

$return = $this->onCheckAutomaticSelected($cart, $cart_prices);
if(method_exists($cart,'getST')){
return $return;
} else if (isset($return)) {
return 0;
} else {
return NULL;
}

 

In the function plgVmDisplayListFEPayment, the $htmlIn variable can create a doubled output, when called twice. The old method just added the output without key to the array, now you should use within the foreach 

if(!isset($htmlIn[$this->_psType][$method->$idN])) {

and then per method

$idN = 'virtuemart_'.$this->_psType.'method_id';
$htmlIn[$this->_psType][$method->$idN] = $html;

Most plugins use the function displayListFE provided by the core anyway and dont need to think about. The price display in getPluginHtml is now a sublayout and overridable