Copyright (c) 2005 Holbi Group LTD

Basic Provisions:
1. All extensions must be placed in separate folder.
2. The class file name must be the same as the folder name.
3. Places for:
   Templates - folder 'views'.
   Model - folder 'models'
   Helpers - folder 'helpers'
   Classes - folder 'classes'
   Frontend controllers - folder 'frontend/controllers'
   Frontend views - folder 'frontend/views'
   Backend controllers - folder 'backend/controllers'
   Backend views - folder 'backend/views'
   Hooks - folder 'hooks'
   Images - extension images folder


Extension Generator
===================

Use this link to generate a new extension by Extension Generator:

https://generator.tllab.co.uk/

You will get a Zip file with extension as result.


SVN
===

All extension will be moved here:

https://svn.holbi.co.uk/tlnew/extensions


Controllers
===========

*** Bootstrap ***
if you want to use personal controllers
1) Create class in file named Bootstrap.php and place in root directory of your extension

use yii\base\Application;
use yii\base\BootstrapInterface;
class Bootstrap implements BootstrapInterface {
    public function bootstrap($app) {
        \Yii::setAlias('@your-extension-alias', dirname(__FILE__));
        if ($app instanceof \yii\web\Application) {
            if ($app->id == 'app-frontend') {
                $app->controllerMap = array_merge($app->controllerMap, [
                    'frontend-controller' => ['class' => 'common\extensions\your-extension\frontend\controllers\your-controller'],
                ]);
            } elseif ($app->id == 'app-backend') {
                $app->controllerMap = array_merge($app->controllerMap, [
                    'backend-controller' => ['class' => 'common\extensions\your-extension\backend\controllers\your-controller'],
                ]);
            }
        }
    }
}

2) enable your extension and try run index action https://yoursite/frontend-controller


Install/Uninstall
=================

To manage install/uninstall process create Setup.php file with class:

	class Setup extends \common\classes\modules\SetupExtensions {
	...
	}

It will be automatically used for:
- get extension description and version
- install/uninstall extention
- install/uninstall extention migrations
- install/uninstall/init translation
- install/uninstall/check extension acl
- install/uninstall widgets
- check if extention requred other extentions

Its required and optional methods you can see in \common\classes\modules\SetupExtensions.php
Below is additional info by install/uninstall topics:

*** Widgets ***
if you want to use widgets in extensions
1. Add method getWidgets with $type parameter and describe widgets in array
example:
return [
            [
                'name' => 'CustomerLoyalty\ShoppingCart', 'title' => 'Customer Loyalty Info Box', 'description' => '', 'type' => 'cart',
            ],
        ];
in this case ShoppingCart (in subfolder \ShoppingCart) is widget ( ShoppingCart.php) can be used in customizing Themes
We recoomend to place widgets in "widgets" subdirectory of your extension
2. to show additional settings for widget use method showSettings
example:
    public static function showSettings($settings){
        return self::begin()->render('settings.tpl', ['settings' => $settings]);
    }


*** Admin menu ***
if you want to use menu in extensions
1. Add method getAdminMenu

*** Hooks ***
if you want to use hooks in extensions
getAdminHooks
We recommend to place all hook files in separate extention folder with name "hooks"

naming rules:
------------
second hook parameter 'page_area' is used only for .tpl files and means visual place

the first hook parameter must be named depending on its location:
- for frontend controllers: frontend/controller/action[/place-in-action]
- for backend controllers: controller/action/[/place-in-action]
- for common files: file-name/function[/place-in-function]
- for widgets: 'box/widget-class'
- for extensions: 'ext/extension-class/unique-name' - such names are not checked, so you may not add them to this file

In addition a list of available values page_name and page_area:
<HOOKS>

### BACKEND CONTROLLERS ###
'index/index', ''
'adminmembers/before-save', ''
'adminmembers/adminedit', 'form-top'
'adminmembers/adminedit', 'form-middle'
'adminmembers/adminedit', 'form-bottom'
'customers/customerlist', ''
'customers/customeredit', ''
'customers/customeredit/before-render', ''
'customers/customeredit', 'btn-bar-right'
'customers/customeredit', 'personal-block'
'customers/customeredit', 'left-column'
'customers/customeredit', 'right-column'
'customers/customeredit', 'address-form-bottom'
'customers/customeractions', ''
'customergroups/groupedit/before-save', ''
'customergroups/groupedit/before-render', ''
'customergroups/groupedit', 'right-column'
'categories/index', 'right-buttons-bottom'
'categories/brandedit', ''
'categories/brandedit', 'tab-navs'
'categories/brandedit', 'tab-content'
'categories/brandedit', 'main-tab'
'categories/brandedit', 'desc-tab'
'categories/brandedit', 'seo-tab'
'categories/productedit-beforesave', ''
'categories/productedit', ''
'categories/productedit/before-render', ''
'categories/productedit', 'prices-left-top'
'categories/productedit', 'prices-priceblock-bottom'
'categories/productedit', 'details-left-column'
'categories/productedit', 'details-left-column-subproduct'
'categories/productedit', 'details-right-column'
'categories/productedit', 'details-right-column-subproduct'
'categories/productedit', 'details-before-actions'
'categories/productedit', 'details-actions'
'categories/productedit', 'details-actions-subproduct'
'categories/productedit', 'details-after-actions'
'categories/productedit', 'details-after-actions-subproduct'
'categories/productedit', 'product-identifiers'
'categories/productedit', 'seo-tab'
'categories/productedit', 'marketing/tab-navs'
'categories/productedit', 'marketing/tab-content'
'categories/productedit', 'size/bottom'
'categories/productedit', 'tab-navs-middle'
'categories/productedit', 'tab-content-middle'
'categories/categoryedit', ''
'categories/categoryedit/before-render', ''
'categories/categoryedit', 'tab-navs'
'categories/categoryedit', 'tab-content'
'categories/categoryedit', 'main-tab'
'categories/categoryedit', 'desc-tab'
'categories/categoryedit', 'seo-tab'
'categories/categoryedit', 'seo-tab-without-lang' // after languages tabs
'categories/categoryedit', 'breadcrumb-buttons'
'categories/supplier-price', ''
'categories/auto-supplier-price', ''
'filters/orders', 'filter-1-column'
'orders/orderlist', '',
'orders/process-order', ''
'orders/process-order/before-next-prev-query', ''
'orders/process-order/check-query', ''
'orders/process-order', 'totals-block'
'orders/process-order', 'btn-bar-top'
'orders/process-order', 'btn-bar-bottom'
'orders/process-order', 'btn-bar-right'
'orders/process-order', 'product-name'
'orders/process-order', 'customer-block'
'tmp-orders/process-order', 'btn-bar-top'
'tmp-orders/process-order', 'btn-bar-bottom'
'tmp-orders/process-order', 'btn-bar-right'
'shopping-cart/index', ''
'platforms/edit', 'left-column'
'platforms/edit', 'right-column'
'platforms/after-save', ''
'platforms/after-delete', ''
'platforms-settings/after-save', ''
'banner_manager/banneredit', ''
'banner_manager/banneredit', 'platform-table-heading-cell'
'banner_manager/banneredit', 'platform-table-cell'
'banner_manager/switch-status-platform', ''
'banner_manager/submit', ''
'coupon_admin/voucher-submit', ''
'coupon_admin/voucheredit', 'tab-content/main-detail/bottom'
'reviews/after-status-change', ''
'editor/checkout/after', ''
'sceleton/before-action', ''

### BACKEND OTHERS ###
'components/breadcrumbs/before-render', ''

### FRONTEND CONTROLLERS ###
'frontend/index/index', ''
'frontend/account/edit', ''
'frontend/account/create-success', ''
'frontend/account/login-success', ''
'frontend/account/password-forgotten', ''
'frontend/checkout/index', ''
'frontend/checkout/index/before-render', ''
'frontend/checkout/process/cart-loaded', ''
'frontend/checkout/process/before-process', ''
'frontend/checkout/process/after-save', ''
'frontend/checkout/process/end', ''
'frontend/checkout/success', ''
'frontend/checkout/login/before-render', ''
'frontend/checkout/confirmation/before-render', ''
'frontend/cart-decorator/decorate-products/products', ''
'frontend/catalog/product', ''
'frontend/catalog/search-suggest', ''
'frontend/sceleton/construct', ''
'frontend/sceleton/bindactionparams', ''
'frontend/sceleton/set-meta', ''
'frontend/sceleton/register-href-lang', ''
'frontend/socials/login-success', ''

### WIDGETS ###
'box/cart/products', ''
'box/cart/products', 'bottom'
'box/product', 'button-buy-attribute'
'box/product-listing', ''
'box/product-listing', 'button-buy-attribute'
'box/login/register', 'after-main-fields'
'box/account/account-edit', 'after-main-fields'
'box/account/order-products', 'order-product' // was account/order_history_info, order-product
'box/banner', ''
'box/block/hide-widget', ''
'box/invoice/products', 'product-name'
'box/heading', ''

### EXTENSIONS ###
// names like 'ext/*' are not checked
'departments/after-create', ''
'departments/after-update', ''
'departments/after-delete', ''
'PlainProductsDescription/extra-product-details-same', '' // same for all lang
'PlainProductsDescription/extra-lang-product-details', ''
'PlainProductsDescription/extra-product-details', '' // dirty hack

### FRONTEND OTHERS ###
'frontend/layouts-main', 'before-body-close'
'frontend/layouts-ajax', 'before-body-close'
'frontend/jsonld-organization', ''
'frontend/jsonld-product', ''

### OTHERS ###
'customers/register', ''                        // common/components/Customer.php
'customers/login-customer', ''                  // common/components/Customer.php
'customers/login-customer/after-validate', ''   // common/components/Customer.php
'customers/logoff', ''                          // common/components/Customer.php
'customers/after-auth', ''                      // common/components/Customer.php
'customers/update-address/before', '' // return true if extension did work and no need standard way
'customers/after-trunk', ''     // helpers/customer.php
'customers/after-delete', ''    // helpers/customer.php
'customers/order-anonymize', '' // helpers/customer.php

'categories/after-delete', '' // helpers/categories
'categories/after-trunk', ''  // helpers/categories

'product/after-delete', ''    //helpers/products.php
'product/after-trunk', ''     //helpers/products.php
'product/get-products-discount-table', ''
'products-query/add-keywords', '' // return true if extension did work and no need standard way
'products-query/add-order-by', '' // return true if extension did work and no need standard way
'products-search/alter-keywords', '' //alternate search keywords
'products-search/alter-force-search', '' //alternate products_id by keywords: $f = ['or',$f, ['in', 'p.products_id', [NNNN]]] NNNNNNNN by $params (only valid keywords) or $this
'product_props/init_workers', ''
'attributes/get-options-values-price', ''
'stock-indication/product-info', ''

'base-price/get-product-price', ''
'base-price/get-inventory-group-price', ''
'base-price/get-inventory-special-price', ''
'base-price/get-product-special-price', ''
'tax/get-tax-rate', ''
'tax/get-tax-values', ''
'tax/get-product-tax-class-id', ''

'orders/after-delete', ''   // helpers/order.php
'orders/after-trunk', ''    // helpers/order.php
'orders/order-anonymize', '' // helpers/order.php
'orders/after-setstatus', '' // helpers/order.php
'order/before-save', ''
'order/after-save', ''
'order/notify_customer', ''
'order/cart/after', ''
'order/query/each-product', ''
'order/query/after', ''
'order/before-save-product', ''
'order/after-save-product', ''
'order/prepare-products/before-loop', ''
'order/prepare-products/after-loop', ''
'order-manager/check-free-shipping', ''
'order-manager/reset-delivery-address', ''
'order-manager/total-process', ''
'order-manager/change-customer-address-selection/after', ''
'order-manager/collect-data', ''
'order-manager/clear-after-process', ''
'order-manager/validate-additional-fields', ''

'init-factory/init', ''
'cart-factory/add-product', ''  // return true if extension did work and no need standard way
'cart-factory/work', ''
'cart-factory/work/end', ''
'shopping-cart/reset', ''
'shopping-cart/add-cart', ''     // for simple products only
'shopping-cart/add-cart-cfg', '' // for configurable products only
'shopping-cart/remove', ''
'shopping-cart/restore-content-products/products-basket', ''
'shopping-cart/cleanup/before', ''
'shopping-cart/cleanup', ''
'shopping-cart/cleanup/after', ''
'shopping-cart/cleanup/delete-product', ''
'shopping-cart/count_contents/after', ''
'shopping-cart/get-products', ''
'shopping-cart/get-products/product', ''
'shopping-cart/save-contents', ''
'shopping-cart/update-quantity', ''

'module-payment/force-pre-authorize-method', '' // return true if extension wants to force pre-authorize transaction method
'module-payment/process-notification', ''
'payment/check-ignored', ''
'shipping/check-ignored', ''  // return true if extension wants to ignore current shipping module
'shipping/after-quote', ''
'ot-shipping/process', ''
'ot-coupon/get-coupon-by-id', ''
'ot-coupon/process/calculate_credit/after', ''

'comment-template/visibility-variants', ''
'email/template-keys', ''
'email/after-sending', ''

'design/export-block', ''
'design/import-block', ''
'design/file-manager', ''
'design/box-edit', 'hide-widget'

'meta-cannonical/set-cannonical', ''
'url-rule/parse-request/before', ''    // return url array
'url-rule/parse-request', ''    // return url array
'socials/get-defined-modules', ''
'console-tools/logs-cleanup', ''

'catalog/products-list-info', ''
'billing/billing-points', ''

'opc/remove-temp-customer', ''

///brands restrictions
'products-query/init', ''
'product/check-product', ''
'frontend/brands', ''
'boxes/menu', ''
'menu-helper/get-brands-list', ''

</HOOKS>