When FormIt 4.2.0 was released two weeks ago, its internals changed a bit. The change is subtle, and would not normally affect other extras that rely on FormIt, but unfortunately, it causes a flurry of errors in SimpleCart and a fatal error when checking out.
This issue was reported today, and after a bit of debugging, I’ve immediately made a SimpleCart 2.6.1 hotfix available to correct it.
If you have updated FormIt to 4.2 in the past two weeks, your checkout is likely broken, and you need to immediately upgrade SimpleCart to 2.6.1. This affects SimpleCart v2.4 and up.
I can’t upgrade to 2.6.1. How do I patch?
In the scCreateOrder
snippet, change the following line (on line 9):
$sc = $modx->getService('simplecart','SimpleCart',$modx->getOption('simplecart.core_path',null,$modx->getOption('core_path').'components/simplecart/').'model/simplecart/', $scriptProperties);
to this:
$sc = $modx->getService('simplecart','SimpleCart',$modx->getOption('simplecart.core_path',null,$modx->getOption('core_path').'components/simplecart/').'model/simplecart/');
Note the removal of $scriptProperties
as the fourth parameter. This same fix can be applied to the scCreateComment
snippet which is also affected (but has a lower impact).
What happened? (Technical details ahead.)
SimpleCart relies on FormIt for handling of the checkout form, and creating an order when the customer chose their payment method is implemented as a FormIt hook, scCreateOrder
.
In that snippet (hook), the SimpleCart service class is initialized, like so:
$sc = $modx->getService(
'simplecart',
'SimpleCart',
$modx->getOption('simplecart.core_path',null,$modx->getOption('core_path').'components/simplecart/').'model/simplecart/',
$scriptProperties
);
This is pretty standard code that anyone that has built an extra for MODX has likely written at some point.
The problem that 4th parameter, $scriptProperties
. It allows passing in additional properties into the SimpleCart class (which arrive in the 2nd $config
parameter in the constructor), which allows overriding the standard configuration.
$scriptProperties
in a FormIt hook contains a lot of variables, varying from the useful $formit
and $hook
, to various configuration options and properties that were passed to the FormIt snippet call. Before FormIt 4.2, the $scriptProperties
included configuration options in camelCase
, like corePath
and modelPath
. In 4.2+, FormIt’s configuration changed to snake_case
, like core_path
and model_path
.
SimpleCart also uses snake_case
configuration keys (as of v2.4), and this change in FormIt 4.2 causes internal SimpleCart configuration to be overridden by FormIt configuration values. Most notably, the model_path
changed from core/components/simplecart/model/
to core/components/formit/model/
, and as a result of that, trying to load the xPDO model for SimpleCart no longer worked in the hook.
This leads to a whole bunch of errors like these:
[2019-02-27 19:25:03] (ERROR @core/xpdo/xpdo.class.php : 644) Could not load class: simpleCartCurrency from mysql.simplecartcurrency.
[2019-02-27 19:25:03] (ERROR @ core/xpdo/xpdo.class.php : 1655) Could not load class simpleCartCurrency!
[2019-02-27 19:25:03] (ERROR @ core/xpdo/xpdo.class.php : 644) Could not load class: simpleCartCurrency from mysql.simplecartcurrency.
[2019-02-27 19:25:03] (ERROR @ core/xpdo/xpdo.class.php : 762) simpleCartCurrency::load() is not a valid static method.
[2019-02-27 19:25:03] (ERROR @ core/xpdo/xpdo.class.php : 644) Could not load class: simpleCartMethod from mysql.simplecartmethod.
[2019-02-27 19:25:03] (ERROR @ core/xpdo/xpdo.class.php : 1655) Could not load class simpleCartMethod!
[2019-02-27 19:25:03] (ERROR @ core/xpdo/xpdo.class.php : 644) Could not load class: simpleCartMethod from mysql.simplecartmethod.
[2019-02-27 19:25:03] (ERROR @ core/xpdo/xpdo.class.php : 762) simpleCartMethod::load() is not a valid static method.
But, more importantly, the following fatal error (or a variation on it) would be triggered when trying to checkout and customers cannot pay for their order:
PHP Fatal error: Uncaught Error: Call to a member function set() on null in core/components/simplecart/controllers/web/Order.class.php:216
The fix is simple; removing $scriptProperties
from the 4th parameter on getService in scCreateOrder. That prevents the configuration from being overridden, and allows models to be loaded to make sure everything works as expected.