Extensions
Extensions provides a basic method to develop and distribute integrated customization for Simple Invoices.
What is an "Extension?"
An extension is a way to modify the standard files used by Simple Invoices without changing the standard Simple Invoices code. Note that the best teacher is to look through extensions included with the standard package. The documentation here will help, but the actual use in code is the best teacher of what the documentation is trying to explain.
How do extensions work?
When a user request is made, it is processed by the index.php file. Each user request includes at least two parameters in the URL. For instance, the initial screen displayed by Simple Invoices, once you are logged in, has the following URL:
localhost/<yoursimpleinvoicespath>/index.php?module=invoices&view=manage
This tells Simple Invoices to execute the index.php file passing it the parameters of module set to invoices, and view set to manage.
If no extensions are enabled, index.php will execute the code in the modules/invoices/manage.php file and display the data it collects in the templates/default/invoices/manage.tpl file.
However, before accessing the manage.php file, a check is made of all enabled extensions to see if they have this file. The path used is extensions/<extensionname>/modules/invoices/manage.php. If an extension has this file, it is executed instead of the default file.
Similarly, before accessing the manage.tpl file, a check is made of all enabled extensions to see if they have this file. The path used is extensions/<extensionname>/templates/default/invoices/manage.tpl. If an extension has this file, it is executed instead of the default file.
Notice the pattern here, the path for the file is the extensions directory, the directory for the extension name. followed by the default file path. However, it is a bit more complex than just this. There are a number of default files accessed before the default files (or their extension replacement). In each case, the extensions directory is searched first to see if a user defined file is to be executed in place of or sometimes along with the default file.
What does index.php search extensions for?
First, the include/init.php file is loaded. This initialization file sets up the database accessors, sets library paths, verifies the user session, sets the path to the si_log and error_log files, loads the custom.config.php file, etc. Basically all the stuff necessary for your request to be processed. It also loads the list of enabled extensions and any initialization files specified in those extensions. The following list specifies which files can be specified in an extension, in the order that init.php checks for them:
- extensions/<extensionname>/include/smarty_plugins – Any plugins you made and want to use. These plugins are used in addition to the default plugins.
- extensions/<extensionname>/include/acl.php – Authentication rules used in addition to the default rules. Note this is only accessed if you have enabled Simple Invoices authentication (aka login).
After the init.php logic is completed, the code in the index.php file continues. The following list specifies the enabled extension files searched for by index.php, in the order they are checked for:
- extensions/<extensionname>/include/init.php – Any initialization actions required by the extension. Note that this is after the default include/init.php file logic is executed. These can be very important to your extension and is fully explained in the “Extension init.php file” section.
- extensions/<extensionname>/modules/invoices/template.php – This file is only checked for if the URL is for the invoice template file. If found, the extension template will be used rather than the template in the
- (Special case) – extensions/<extensionname>/modules/<module>/<view>.php – The <module> and <view> come from the URL. BUT, they are only checked if the module contains the string of api, or the view contains the string xml or ajax. If found, the standard <module>/<view> file is NOT used. Regardless of this extension file existing or not, If the module contains api, or the view contains xml or ajax, index.php exits at this point.
- extensions/<extensionname>/include/jquery/<extensionname>.jquery.ext.js – A jquery files found in the extensions will be loaded in the resulting html output.
- extensions/<extensionname>/templates/default/hooks.tpl – “hooks” are explained in the “Extension & Custom hooks.tpl” section. For now note this is where they are loaded and they are loaded in addition to and prior to the standard custom/hooks.tpl file.
- extensions/<extensionname>/templates/default/header.tpl – If a custom header template is to be used for the output html file. If found, the default templates/default/header.tpl file is NOT loaded.
- extensions/<extensionname>/modules/<module>/<view>.php – The <module> and <view> come from the URL. BUT, these are two types of these files and they affect the output html file differently. If the <module> is “system_defaults” and the <view> is “edit” the extension file is treated differently. This is fully explained in the “Extension <module>/<view>.php files” section.
- extensions/<extensionname>/include/jquery/<extensionname>.post_load.jquery.ext.js.tpl – Template file containing jquery related scripts, etc. These files are loaded in addition to the default include/jquery_load.jquery.ext.js.tpl file however, The default file is NOT loaded if the module in the URL is “auth”. That is, it isn’t loaded in authentication mode.
- extensions/<extensionname>/templates/default/main.tpl – If present, this file is loaded in place of the default templates/default/main.tpl file.
- extensions/<extensionname>/templates/default/<module>/<view>.tpl – This is another very special extension file. It behaves differently if the <module> is “reports” and the <view> is “index”, or if the <module> is “system_defaults” and the <view> is “manage”. This is fully explained in the “Extension <module>/<view>.tpl files” section. If the URL does not have these special parameter combinations, the extension file is loaded in place of the default file.
- extensions/<extensionname>/templates/default/footer.tpl – The default templates/default/footer.tpl file is NOT loaded if and extension file is preset. However, the footer.tpl from an extension or default path is only loaded if the <module> and <view> combination is not classified as an Early Exit URL. This is fully explained in the “Early Exit URLs” section.
Extension init.php file
The extension init.php file is a very important component of many extensions. It is used to include any global functions that are considered part of the include/sql_queries.php file, to load any class files that would be like those in the include/class directory, and to execute initialization logic such as a class method that checks for a database table added by this module and creates it if it doesn’t exist. This approach to updating the database structure automates what had been a manual requirement in the past.
Extension and Custom Hooks
There are two types of hooks, The Custom Hook and the Extension Hook. They have similar functionality but Custom Hooks are always applied and Extension Hooks are only applied if they exist in an enabled extension.
Custom Hooks
SI “hooks” allow content to be inserted into or to replace predefined locations in the default header.tpl, menu.tpl and footer.tpl files.
Before you consider using hooks, make sure other options such as tpl file content insertion be used before resorting to hooks (see Custom Flags extension menu.tpl file or Past Due Report extension index.tpl file for examples). The reason for this is that a hook can only be used once since the Smarty {capture name=”hook_name”}{/capture} function is in essence a variable in which values to be inserted are saved. So if the same hook (capture name value) is defined multiple times then only the value of the last one set will be used.
This file contains the list of all defined hooks. Note the name of the hook as it will tell you if its value will be inserted in the code or if it will replace a section of code. If the hook name contains the word, “replace”, defining it will replace the named section of the tpl file it is defined in. All other hooks are insertion points and have names that indicate “start” or “end” of the named location.
All hooks should be defined in this file to document their existence. They should be surrounded by a test to see if they have previously been set; preventing them from being inadvertantly redefined in this file.
Note that this file is loaded after the extension hooks have been loaded. This allows hooks to be conditionally used by extensions that a user has enabled. Hooks in this file should only be used if needed all the time. But consider, if it is needed all the time, it should probably be put in the file where the hook is loaded rather than being here.
Review the content of the custom/hooks.tpl file to see what hooks are available and what template location they impact.
Extension Hooks
Every location where a Custom Hook can be loaded in the template, an Extension Hook can be loaded. The extension hook and custom hooks work the same except that where custom hooks are always applied, the extension hooks are only applied if the extension is enabled.
Extension <module>/<view>.php files
There are two cases for these files. If the module contains the string, api, or the view contains the string xml or ajax, it is an early exit file that stops index.php execution once the php file has been executed. This early exit occurs whether there is an extension file or not. All other module/view URLs are processed later in the index.php file.
In the case of module/view URLs that don’t qualify as early exit are of two types. One type is for the case where the module is “system_defaults” and the view is “edit”. The other is all the remaining settings.
The extensions/<extensionname>/modules/system_defaults/edit.php files contain sections to insert at the end of the standard modules/system_defaults/edit.php file.
All other module/view settings are for files to load in place of the standard non-extension file.
Extension <module>/<view>.tpl files
There are two types of module/view tpl file. If the module is “reports” and the view is “index”, or if the module is “system_defaults” and the view is “manage”, the extension tpl file contains information that is to be inserted into into the standard tpl file. If not one of these special module/view tpl files, it is a tpl file that will be loaded in place of the standard one.
The module/view tpl is the reports/index.tpl, it contains a menu section that is to be inserted into the standard reports menu. If the module/view tpl is the system_defaults/manage.tpl, it contains a section that is to be loaded into the standard system_defaults tpl file.
The standard reports/index.tpl and system_defaults/manage.tpl files contain section values that are used in the extension files to indicate where their data should be loaded.
The insertion logic uses a data-section attribute to determine where the sections are to be inserted. The sections are either inserted before a language element or at the end of a section that is headed by a language element.
An example of the insertion before attribute is:
<h2 data-section="BEFORE {$LANG.other}">{$LANG.expenses}<a name="expenses" href=""></a></h2> <div class="si_toolbar"> <a href="index.php?module=reports&view=report_tax_vs_sales_by_period" class=""> <img src="images/famfam/money_delete.png" alt="" /> Monthly tax summary per year </a> <a href="index.php?module=reports&view=report_expense_account_by_period" class=""> <img src="images/famfam/money_delete.png" alt="" /> Expense accounts summary </a> <a href="index.php?module=reports&view=report_summary" class=""> <img src="images/famfam/money_delete.png" alt="" /> Expense accounts summary </a> </div>
This will cause this section to be inserted before the section with he heading, <h2>[$LANG.others]</h2>.
An example of the add at the end of the section attribute is:
<a href="index.php?module=reports&view=past_due_report" class="">
<img src="images/famfam/report_edit.png" alt="" />
<span data-section="{$LANG.debtors}">Past Due Report</span>
</a>
This will cause this section to be inserted at the end of section with the <h2>[$LANG.debtors]</h2> header.