How to build a Gahela Cart module from an X-Cart module
This tutorial is going to show how to build a Gahela Cart module from an X-Cart module. I'm going to use the Product Page Downloads module for this example. Even if you are not going to be converting any modules, this is still a good tutorial to explain some of the basic operations of the Gahela framework running cart software.
The Gahela Cart module system is based on code hooks. Using hooks you can create an entire module without changing any of the existing source code. Like all aspects of the Gahela Cart code, it is first and foremost designed to be a next generation cart that is accessible to all. You will not be dealing with advanced OOP principles, or rebuilding templates, all of the magic happens automatically in the code. You just setup the basic parameters, tick a few checkboxes, and write some code.
1. To create a new module go to Admin -> Modules -> Manage and click the Create New Module button.
This will bring up the module creation window where you can enter the module name and details.
Fill in the fields:
Name: Create a unique module name. (This should have your business as a prefix to prevent collision with other modules).
Module Name: This will be automatically generated based on the input. This is the unique module name used in the Classes and file system
Description: A short description displayed on the module page explaining what the module does
Menu: (Optional). When a menu is selected a link to the module manage page will be displayed in the Navigation section. For example, if you select products, the Product Page Downloads link will be shown in the Products navigation section
Manufacturer: The person or business who created the module
URL: A link to the manufacturer's site.
When Create Module is pressed the module will be entered into the database and displayed in the list on the Admin -> Modules -> Manage page.
There are four main controls:
- Toggle switch to enable/disable the module.
- Download a distribution (for moving the module to a different site, or creating a sellable distribution file, and simplifying the module creation).
- Links to the hook page.
- Link to completely uninstall the module from the database.
2. The module is now entered in the database. Next, we will assign the basic hooks (this can be done at any time). Click the hooks link [#3 in the graphic above] to go to the hook assign page. The hooks page displays the main file the hook is in, what type of hook it is, and finally, a basic description of what it does. There are three types of hooks:
- Insert: This type of hook simply inserts the HTML from a template into the file.
- Filter: This type of hooks filters a block of HTML generated from a template
- Process (PHP). These are code inserts at the hook point in the file. Anything you can do in PHP can be done with these hooks.
As you use the module system more, you will get more familiar with the hooks. The Product Page Downloads module in X-Cart added a section to the product modify page, and to the product page for downloads. Instead of inserting this code, we will just select the hooks. For the Product Page Downloads we will enable:
- edit_product_tab to create a tab on the product modify page to add the downloads.
- product_page to load the downloads on the product page
3. Now that our module is created, and our hooks are added we can start coding. Navigate back to the Admin -> Modules -> Manage page and click the download distribution icon [#2 in the graphic above] to create all of the needed hook files, directories, templates and PHP class files. One of the benefits of adding your hooks before downloading the distribution, is all of the required hook event files will be created.
If you are working on a development cart it is easier to see errors in real time as changes are made, so you can do the following:
- Extract the module file locally.
- Upload this to the store, or copy these to your local working directory.
- Enable the module you just created in the Admin -> Modules page.
- Open the core/config/config.php file and change define('GFW_DEBUG_MODE', false); to define('GFW_DEBUG_MODE', true);
4. Let's start with the SQL tables. You will want all of your tables to begin with: gfw_<module_name>_
In our X-Cart module the Product Page Downloads has two tables, let's rename these:
xcart_product_downloads to gfw_product_page_downloads
xcart_product_downloads_log to gfw_product_page_downloads_log
The tables can be created by going to Admin -> Tools -> SQL Patch and entering your CREATE TABLE... statements. Note, when the distribution is built all tables with your module name prefix will be included automatically.
5. Convert the code. Since Gahela uses Smarty 3 + PHP + MySQLi converting the modules is very easy. Without going through every file, here are some examples, and explanation of the basic hook and file structure. We will start with the new code for the product edit section.
We created an edit_product_tab hook. This created an empty modules/product_page_downloads/events/edit_product_tab.php file in our distribution. This code in this file will be executed when the admin side product edit page is opened. We will want to add our tab data, and load the assigned product page downloads in this file (it is included in the completed distribution found at the end of this article).
We created a product_page hook. This created an empty modules/product_page_downloads/events/product_page.php file in our distribution. This code in this file will be executed on the customer side product page. We will want to add our tab data, and load the active product page downloads in this file (it is included in the completed distribution found at the end of this article).
A couple of notes about this new code. First, there are new text variables that need to be created. For this to display we will want to go to Admin -> Settings -> Text & Languages and insert this new variable:
Secondly, we referenced a new file: modules/product_page_downloads/edit-product-tab.tpl. It will need to be created: skin/default/modules/product_page_downloads/edit-product-tab.tpl
In our new skin/default/modules/product_page_downloads/edit-product-tab.tpl we can insert the admin code to assign, edit, and delete downloads for individual products. In the X-Cart module this was in the skin/common_files/modules/Product_Page_Downloads/ppd_product_details_display.tpl. Since Gahela Cart uses Smarty, we just copy the code directly from this file and edit the parts that need to be changed. This will vary based on the module, but the Product Page Downloads code needed the following changes:
- It referenced a main/subheader.tpl file used in X-Cart that is not in Gahela Cart. This is used as a title, so lets just change this to a <h3> header tag (a lot cleaner code).
- The text variables need to be converted. Gahela cart uses a {$text.<text_variable>} format. For example: {$lng.lbl_download} will be changed to: {$text.txt_download}. You can test for excising variables in the Admin -> Settings -> Text & Languages section, and create any new variables needed.
- Remove the X-Cart {$geid} multiple product edit code.
- Remove the X-Cart specific CSS classes and tables and replace them with Gahela classes.
The next thing we need to do is add the add download file selector. Gahela Cart has a lot of built in widgets for product selection, files, dates, attributes etc, (there are many examples of these other widgets in the source code and other modules). In the bottom of the src="edit-product-tab.tpl file insert the file explorer widget.
{include file='sections/editor/insert-file.tpl' explorer_name='ppd' hide_limits=1 auto_copy=1}
Note, when coding, if you need a description of the parameters when a file is included (for example, what does auto_copy=1 do?) you can open the included file to view a description of the parameters. At the top of the sections/editor/insert-file.tpl there are descriptive comments about the accepted parameters.
We need to add some JavaScript to this template to use with the insert file widget. To do this first we will create a new .js file here: skin/default/modules/product_page_downloads/js/product_page_downloads.edit-product.js, and then we will include this in on the page with this code in the src="edit-product-tab.tpl file:
{include_source file='modules/product_page_downloads/js/product_page_downloads.edit-product.js'}
The Smarty {include_source} module will copy the contents of the file parameter to the Gahela Cart CSS and JS files. For speed, all of the CSS and JS files are reduced to a single file to be sent to the customer.
The new .js we wrote for the editor has an AJAX file assign. This sends a request to the server to add the file. The next thing we are going to discuss is the server side code. There are three main parameters sent to the server for a request;
- Section
- Action
- View
Every request will have a section, this directs the request to the code to run on the server. For this module, the section will always be 'product_page_downloads'. A view is used to display a page, and an action is used to send a request to the server to perform an operation. An action will always redirect back to a view page. It will never display a page.
The Product Page Downloads file selector widget will send the following request to the server to add a file:
- Section = product_page_downloads
- Action = add_file
- files = filepath(s) to add
This will execute the modules/product_page_downloads/action/Add_file.product_page_downloads.class.php file. All requests always map to a specific file, this makes it very easy to find the .php and .tpl files being used on each request. They will always match the parameters. You don't need to use webmaster mode to figure out which templates are loading (Gahela Cart still has a really great webmaster mode for easy editing).
Every request made to your cart will have a permissions check. You wouldn't want a customer to be able to make an 'add_file' request. Each section of the cart has a XML permissions file. For the product page downloads it can be found at modules/product_page_downloads/xml/product_page_downloads.permissions.xml. In the files you can add permissions for various actions and views. We will add permission for the add_file action:
For this action we set the request permissions level at 3. This means only an admin can perform this action. The permissions are:
- 0 = Everyone
- 1 = Logged in customers
- 2 = Vendors or admins
- 3 = Only admin
Once we have the file created and permissions set we can copy our existing file assign code to this file. Just a note, in X-Cart procedural code you would have a lot of if/else statements in a single file to handle the server side logic. In the OOP setup each action should have a separate class file and permissions. In the procedural code of X-Cart you would normally have a func.php file to load the required functions. In Gahela Cart, each section and module has an auto loaded static class file to contain your modules programming logic. In this case it is modules/product_page_downloads/Product_page_downloads.core.class.php (These files were all created with our module).
The logic of the module was copied to the new files for each required action (adding, deleting, downloading, and updating files)
- modules/product_page_downloads/actions/Add_file.product_page_downloads.action.class.php
- modules/product_page_downloads/actions/Delete_file.product_page_downloads.action.class.php
- modules/product_page_downloads/actions/Download.product_page_downloads.action.class.php
- modules/product_page_downloads/actions/Update_files.product_page_downloads.action.class.php
7. MySQLi
Gahela Cart uses MySQLi prepared statements. This is a far more secure method to interact with a database. All of the variables are separated from the statement to prevent SQL injection. This is done by replacing the variables in a SQL statement with question marks (?), and then including the variables in an array as a separate parameter. Your existing database statements will need to be changed to this format.
For example, the query:
$db->query("SELECT * FROM gfw_product_page_downloads WHERE productid=".$productid);
would become:
$db->query("SELECT * FROM gfw_product_page_downloads WHERE productid=?", array($productid));
At this point when all of the db tables, templates, and php files are converted we have the Product Page Downloads running on Gahela Cart. Below are the full source downloads for both modules and files. One note, I did make a number of enhancements to the module like restricting downloads, and using the built in widgets of Gahela cart, so it isn't an exact comparison, but hopefully this walk through the code will better explain the design principles of the cart. As you become more comfortable with the code you will see how quickly modules can be developed for this system.
Any questions, let me know.