Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions content/dev/moduleSupport/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: Modules Infrastructure
description: New modules infrastructure
weight: 100
layout: docs
---

{{% wip %}}

In order to make it easier and quicker to write modules(Payment/Shipping/Order Totals) a new infrastructure for these modules has been created.

This new infrastructure will reduce the amount of boilerplate code required, minimize copy/paste coding and adds helpers for common coding requirements.

{{% alert title="Note" color="primary" %}}
Previous Payment/Shipping/Order total modules will continue to work without modification.
{{% /alert %}}
113 changes: 113 additions & 0 deletions content/dev/moduleSupport/base/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
title: Base Module Support
description:
weight: 10
layout: docs
---

{{% wip %}}

# Introduction

The base module support classes contain common code that is used across all module types e.g Payments, Shipping and Order Total modules.

It also provides some common helper methods that you can use in your modules.

## Accessing Define Values

All module types store information about themselves in the database `configuration` table.

The `keys` for this table will look something like

- MODULE_PAYMENT_COD_STATUS
- MODULE_SHIPPING_FLAT_COST
- MODULE_ORDERTOTAL_TOTAL_SORT_ORDER

The structure of these defines is

MODULE_[module type]\_[module name]\_[define name]

where module type is one of `PAYMENT` or `SHIPPING` or `ORDERTOTAL`

The module name is taken from the $code class variable of the module, and the define name describes the purpose of the define.

In previous versions of Zen Cart,these configuration values were accessed directly using the key that was stored in the database, however using
the new module support classes we access them through a helper method.

e.g. In legacy code we might have done

`$this->sort_order = defined('MODULE_PAYMENT_COD_SORT_ORDER') ? MODULE_PAYMENT_COD_SORT_ORDER : null;`

With the new infrastructure we can simply do

`$this->sort_order = $this->getDefine('SORT_ORDER);`

The `getDefine` method is context aware, so knows which type of module you are using(PAYMENT/SHIPPING/ORDERTOTAL) and the current define name (e.g. COD) for
the module you are using.

Furthermore, you can also set a value that will be returned from the method if the configuration value does not exist.

In the example above, the method will return `null` if the `MODULE_PAYMENT_COD_SORT_ORDER` does not exist.

However you could also do `$this->sort_order = $this->getDefine('SORT_ORDER, 0);`

and the method will return `0`, if the configuration value does not exist.

There are also a number of helper methods to get some of the most common module configuration keys.

### getTitle

This gets the title for the Module.

It looks for defines with suffixes in an array of ['TITLE', 'TEXT_TITLE', 'CATALOG_TITLE']

If your module uses a different define for the title then you should override the getTitle method.

### getAdminTitle

This returns a title to display on the Admin interface. In general this would be the same as the getTitle as above, but sometimes you may want it to be different.
It expects to be passed a default title, which would normally be what the getTitle function returns, and will use this if it does not find a define related to the admin title.

This function looks for defines with a suffix in an array ['TITLE_ADMIN', 'TEXT_TITLE_ADMIN', 'ADMIN_TITLE']

If your admin title is defined through other means, then you will need to override this method in your module.

### getDescription

returns a module define with the suffix `DESCRIPTION`

### getSortOrder

returns a module define with the suffix `SORT_ORDER`

### getZone

returns a module define with the suffix `ZONE`

### getDebugMode

returns a module define with the suffix `DEBUG_MODE`

### isEnabled

This function checks to see if the module is enabled.

it first checks to see if the module has any missing configurations and then check the module define suffix `STATUS`

### moduleAutoloadSupportClasses

This function is only called if it exists.

It allows a module to add autoload classes using the psr4autoload Aura autoload.

e.g.

``` php
protected function moduleAutoloadSupportClasses(Loader $psr4Autoloader): Loader
{
$psr4Autoloader->addPrefix('Stripe', DIR_FS_CATALOG . DIR_WS_MODULES . 'payment/stripe_pay/stripe-php-13.15.0/lib/');
$psr4Autoloader->addPrefix('Monolog', DIR_FS_CATALOG . DIR_WS_MODULES . 'payment/stripe_pay/monolog/src/Monolog/');
$psr4Autoloader->addPrefix('Zencart\Logger', DIR_FS_CATALOG . DIR_WS_MODULES . 'payment/stripe_pay/Logger/');
return $psr4Autoloader;
}
```
38 changes: 38 additions & 0 deletions content/dev/moduleSupport/base/classVariables/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Class Variables
description:
weight: 140
layout: docs
---

{{% wip %}}

The base module provides the following class variables for all other module types.

## public int $_check

## public string $description

## public bool $enabled

## public ?int $sort_order

## public string $code = ''

## protected string $defineName = ''

## protected string $version = ''

## public string $title = ''

## protected array $configurationKeys

## protected int $zone

## protected array $configureErrors = []

## protected Logger $logger

## protected $storeLanguageSuffixes = ['TITLE', 'TEXT_TITLE', 'CATALOG_TITLE']

## protected $adminLanguageSuffixes = ['TITLE_ADMIN', 'TEXT_TITLE_ADMIN', 'ADMIN_TITLE']
80 changes: 80 additions & 0 deletions content/dev/moduleSupport/base/configurationSettings/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
title: Configuration Settings
description:
weight: 80
layout: docs
---

{{% wip %}}

In Zen Cart modules written before this module infrastructure code, configuration settings used SQL statements for those settings.

This was usually done in a module method called `install` and would look something like.

``` php
function install() {
global $db, $messageStack;
if (defined('MODULE_PAYMENT_FREECHARGER_STATUS')) {
$messageStack->add_session('FreeCharger module already installed.', 'error');
zen_redirect(zen_href_link(FILENAME_MODULES, 'set=payment&module=freecharger', 'SSL'));
return 'failed';
}
$db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Enable Free Charge Module', 'MODULE_PAYMENT_FREECHARGER_STATUS', 'True', 'Do you want to accept Free Charge payments?', '6', '1', 'zen_cfg_select_option(array(\'True\', \'False\'), ', now());");
$db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Sort order of display.', 'MODULE_PAYMENT_FREECHARGER_SORT_ORDER', '0', 'Sort order of display. Lowest is displayed first.', '6', '0', now())");
$db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Payment Zone', 'MODULE_PAYMENT_FREECHARGER_ZONE', '0', 'If a zone is selected, only enable this payment method for that zone.', '6', '2', 'zen_get_zone_class_title', 'zen_cfg_pull_down_zone_classes(', now())");
$db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, use_function, date_added) values ('Set Order Status', 'MODULE_PAYMENT_FREECHARGER_ORDER_STATUS_ID', '0', 'Set the status of orders made with this payment module to this value', '6', '0', 'zen_cfg_pull_down_order_statuses(', 'zen_get_order_status_name', now())");
}

```

With the new module infrastructure code this is simplified.

The base module classes define a default set of configurations settings for payment/shipping/order total classes, and 3rd party modules can add to those settings.

Rather than use SQL statements, we now use an array based method of defining the settings.

If a module needs to add extra settings, it should define a method called `addCustomConfigurationKeys`

An example, taken from a rewritten moneyorder payment module.

```php
protected function addCustomConfigurationKeys(): array
{
$configKeys = [];
$key = $this->buildDefine('PAYTO');
$configKeys[$key] = [
'configuration_value' => 'the Store Owner/Website Name',
'configuration_title' => 'Make Payable to:',
'configuration_description' => 'Who should payments be made payable to?',
'configuration_group_id' => 6,
'sort_order' => 1,
];
return $configKeys;
}
```

## Module Settings Keys

The following is a list of module settings keys and their usage as per the `configuration` database table.

### configuration_title

### configuration_key

### configuration_value

### configuration_description

### sort_order

### last_modified

### date_added

### use_function

### set_function

### val_function


53 changes: 53 additions & 0 deletions content/dev/moduleSupport/base/configurationerrors/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
title: Configuration Errors
description:
weight: 100
layout: docs
---

{{% wip %}}

# Introduction

The new module support infrastructure allows you to define methods to capture errors in the configuration of a module
and display these errors in the admin title for the module.

If the errors are considered `fatal` the system will also ensure that the module cannot be enabled until the errors are fixed.

Two methods are used which you can add to your module.

`checkNonFatalConfigureStatus` and `checkFatalConfigureStatus`

some examples.

The moneyorder payment module defines a `checkNonFatalConfigureStatus` method

``` php
protected function checkNonFatalConfigureStatus(): void
{
if ($this->getDefine('PAYTO') == 'the Store Owner/Website Name' || $this->getDefine('PAYTO') == '') {
$this->configureErrors[] = '(not configured - needs pay-to)';
}
}
```

The Stripe Pay module defines a `checkFatalConfigureStatus` method


```php
protected function checkFatalConfigureStatus(): bool
{
$configureStatus = true;
$toCheck = 'LIVE';
if ($this->getDefine('MODE') == 'Test') {
$toCheck = 'TEST';
}
if ($this->getDefine($toCheck . 'PUB_KEY') == '' || $this->getDefine($toCheck . '_SECRET_KEY') == '') {
$this->configureErrors[] = sprintf('(not configured - needs %s publishable and secret key)', $toCheck);
$configureStatus = false;
}
return $configureStatus;
}
```


52 changes: 52 additions & 0 deletions content/dev/moduleSupport/base/languagedefines/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: Language defines
description:
weight: 120
layout: docs
---

{{% wip %}}

Language define files for modules follow the same format as normal array based language defines.

They are stored in `includes/languages/{language}/modules/` and at the very least should have an english translation.

e.g.

`includes/languages/english/modules/payment/lang.cod.php`

`includes/languages/english/modules/shipping/lang.flat.php`

`includes/languages/english/modules/order_total/lang.ot_subtotal.php`


Like module configuration keys, naming of module language defines are the same
e.g.

`MODULE_[module type]\_[module name]\_[define name]`

There are some other rules.

language define names should be unique and not match any other module configuration defines.

At a minimum you should provide the following

`'TEXT_TITLE' => 'Stripe Checkout',`

`'TEXT_DESCRIPTION' => '<strong>Stripe Pay</strong>',`


e.g

``` php
$define = [
'MODULE_PAYMENT_STRIPE_PAY_TEXT_TITLE' => 'Stripe Checkout',
'MODULE_PAYMENT_STRIPE_PAY_TEXT_DESCRIPTION' => '<strong>Stripe Pay</strong>',
];
return $define;
```

Note: also if you want to provide a different title in the admin interface you can add something like

`MODULE_PAYMENT_STRIPE_PAY_TEXT_TITLE_ADMIN' => 'Stripe Checkout(ADMIN)`

Loading