Home Blog Page 20

“What People are Buying right now?” Opencart Module for free

Another free Opencart module for my visitors and subscribers, this extension will show “What People are buying right now?”. It lists out the recently ordered products.

To download the module click below:

Installation

Upload the folders ‘admin’ and ‘catalog’ and their files from the extracted directory to your server OpenCart main directory. Check this installation video if have any issues

OpenCart core files are not changed.

After installation:

You can edit the module and setup following:

Then setup in your preferred layout and you will see like below:

Query implemented is below:

public function getLatestOrderedProducts($limit)
{
	$product_data = "";
	$product_data = $this->cache->get('product.latestordered.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id') . '.' . $this->config->get('config_customer_group_id') . '.' . (int)$limit);

	if (!$product_data) {
		$product_data = array();

		$query = $this->db->query("SELECT op.product_id FROM " . DB_PREFIX . "order_product op LEFT JOIN `" . DB_PREFIX . "order` o ON (op.order_id = o.order_id) LEFT JOIN `" . DB_PREFIX . "product` p ON (op.product_id = p.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE o.order_status_id > '0' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "' ORDER BY o.order_id DESC LIMIT " . (int)$limit);
		foreach ($query->rows as $result) {
			$product_data[$result['product_id']] = $this->getProduct($result['product_id']);
		}
		$this->cache->set('product.latestordered.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id') . '.' . $this->config->get('config_customer_group_id') . '.' . (int)$limit, $product_data);
	}

	return $product_data;
}

Further help and customized versions:

This module has been successfully tested for a standard OpenCart 3.0.3.2.

If you need a customized version of this module and any other Opencart help and support then let me know and I can create one for a charge.

If you get any problem with the module then let me know by commenting.

Youtube video to show with autoplay, Free Opencart module or extensions

Another Opencart module for free by webocreation.com which shows youtube video and autoplay it, download this extension upload and take the youtube video id and show it in module placed and autoplay it.

Download, extract and Upload the files and folder inside the upload/ folder to your respective admin/ and catalog/ folder. If you have a problem then watch this video which will show how to upload, install and configure opencart module

After uploading, go to Extensions >> Choose the Modules >> Then go to the “Youtube AutoPlay youtube module” and click + Install green button and then click the + blue button. After that, you will see the following screenshot where you have to enter the Module Name, Youtube Id and change the status to Enabled.

Youtube Auto Play Opencart module

Click Save.

Then go to Design >> Layouts >> Edit where you want to show the youtube video. For us we are showing it on the home page at the bottom so our setting is like below:

Layout and Position to show for the Youtube Autoplay module

With the above settings we can see the youtube video at the bottom of the home page, like in this demo:

Let us know if you need to improve anything in the module and we will make the adjustments as per your request. Thanks for using these modules and let us know if you have any requirements.

How to upgrade Opencart from version 2.3 to 3.0.3.1 and Journal theme 2 to 3?

Our webocreation.com is still in opencart v2.3 and today we are upgrading to opencart version 3.0.3.1 live. So that it will be pressure for us to complete it. We are able to upgrade in 1hrs and fix problems to go through the normal ordering. Previously we were using Journal version 2 and now we are using journal version 3.

Be prepared with the following:

  • Make a backup of every file and folder and the database.
  • Download the latest version of OpenCart, right now it is 3.0.3.2
  • Download the Journal theme version 3
  • Download the demo data of the Journal theme
  • Login to admin and disable the custom theme and set up the default theme of OpenCart so there are no conflicts.
  • Upload all the latest version Opencart files and folders to your server and go to your store URL, it mostly gives errors unless it is a minor version update.
  • Rename the Vqmod folder to something else as it may contain .xml files which give errors in major version upgrades.
  • Rename the journal-cache folder also if you have.
  • Remove all .xml files except modification.xml inside system/ folder
  • Go to system/storage/cache folder and delete all files and folder except index.html, similarly go to system/storage/modification and delete all files and folder except index.html, likewise, go to system/storage/upload and delete all files and folder except index.html. It means the need to remove all the cache and file modifications that are in the system/storage of Opencart 2.
  • Then run YOURSTOREURL/install in your browser
  • You will see some notice, if you re-run then it will be resolved automatically.
  • Install the Opencart in the subfolder so that it will be easy to copy and paste in the config.php and get the files and folder as needed. This is extra steps but will be helpful to debug if something went wrong.
  • Update your config.php and admin/config.php as required as mostly, it missed the DIR_STORAGE constant.
  • Then go to the directory of DIR_STORAGE and upload files and folders to match the DIR_STORAGE folder of your demo sub-folder installation. Or you can download the following and extract and upload all files and folders to your store DIR_STORAGE path.
    • Download DIR_STORAGE files.
    • Some time upgrade code is not able to create the files and folders for the DIR_STORAGE so we have to upload it manually.
  • If you see errors then it is because of non-upgraded extensions, so find them out and disable them.
  • Then verify all of your extensions if they are enabled as mostly they got disabled when a major version upgrade is done.
  • Check for modules, shipping, payments, and Order totals likewise other Analytics, Captchas, etc
  • Don’t forget to delete Journal2 folders in admin and in catalog likewise in the system folder. Similarly, remove all .tpl files will be a good idea.
  • Happy Upgrading and hope it went smooth on your side.

Read: Learn Journal theme coding by example

Things to consider:

  • SEO URL alias is not transferred properly. So you have to transferred manually or write SQL code to transfer from the oc_url_alias to oc_seo_url, as now in OpenCart 3.0.3.1 the SEO URL is also stored specific and language-specific.
  • None of the Journal settings and configuration are transferred so if you have a unique design then you have entered them manually.
  • Most of the modules get disabled so need to enabled again.
  • Theme will show two default theme so need to disabled both and enable whichever works as this is because there are existing files of Opencart 2

Some of the error we fixed while we upgrade the OpenCart and Journal theme:

SyntaxError: Unexpected token < in JSON at position 0 parsererror Notice: Undefined variable: affiliatee in /public_html/install/model/upgrade/1009.php on line 23{“success”:”Patch 1009 has been applied (10 of 10)”,”next”:”index.php?route=upgrade\/upgrade\/next&step=11″}

-Re-run the install

Warning: fopen(DIR_STORAGElogs/openbay.log): failed to open stream: No such file or directory in /public_html/system/library/log.php on line 22Warning: fopen(DIR_STORAGElogs/error.txt): failed to open stream: No such file or directory in /public_html/system/library/log.php on line 22Warning: Use of undefined constant DIR_STORAGE – assumed ‘DIR_STORAGE’ (this will throw an Error in a future version of PHP) in /public_html/admin/controller/startup/sass.php on line 7Warning: include_once(DIR_STORAGEvendor/scss.inc.php): failed to open stream: No such file or directory in /public_html/admin/controller/startup/sass.phpon line 7Warning: include_once(): Failed opening ‘DIR_STORAGEvendor/scss.inc.php’ for inclusion (include_path=’.:/opt/alt/php72/usr/share/pear’) in /public_html/admin/controller/startup/sass.php on line 7

  • First, remove the cache which is in system/storage of OpenCart 2
  • Define the DIR_STORAGE constant at the config.php and provide the right path.
  • If you are confused which path to provide then install an Opencart in sub-folder and log in which will redirect you to define the storage folder. With this default setup, now you can see its config.php and admin/config.php and do the same for your store config.php and admin/config.php. This is one way.

Warning: fopen(/v3storage/cache/cache.catalog.language.1557105242): failed to open stream: No such file or directory in /public_html/system/library/cache/file.php on line 49Warning: flock() expects parameter 1 to be resource, boolean given in /public_html/system/library/cache/file.php on line 51Warning: fwrite() expects parameter 1 to be resource, boolean given in /public_html/system/library/cache/file.php on line 53Warning: fflush() expects parameter 1 to be resource, boolean given in /public_html/system/library/cache/file.php on line 55Warning: flock() expects parameter 1 to be resource, boolean given in /public_html/system/library/cache/file.php on line 57Warning: fclose() expects parameter 1 to be resource, boolean given in /public_html/system/library/cache/file.php on line 59Warning: fopen(/v3storage/cache/cache.currency.1557105242): failed to open stream

  • Upload the cache folder, download, logs, modification, session, upload, vendor files, and folder.
  • You can download here as well, which is the basic files and folder of the OpenCart installation

Error: A theme has not been assigned to this store!

You can fix the error by referring to this post as it contains some steps to solve it.

Notice: Undefined variable: _SESSION in /public_html/catalog/controller/extension/module/v2pagecache.php on line 13Error: A theme has not been assigned to this store!

In our case, most of the modules were disabled when we upgraded to OpenCart 3. Thus we re-installed modules, theme, Order Totals, payment and shipping also.

Journal Theme Installation Error
Make sure you have refreshed Opencart Modifications.

This is straight forward, go to admin>> Extensions >> Modifications and click the refresh button.

Let us know your upgrade process and issues if you got any.

Notice: Constant DATE_RFC7231 already defined in includes/bootstrap.inc on line 258

Notice: Constant DATE_RFC7231 already defined in includes/bootstrap.inc on line 258

Drupal 7:

  • Open /includes/bootstrap.inc
  • Go to line number 258
  • Comment out the following line
    //define(‘DATE_RFC7231’, ‘D, d M Y H:i:s \G\M\T’);
  • Then add following line
    if (!defined(‘DATE_RFC7231’)) {
    define(‘DATE_RFC7231’, ‘D, d M Y H:i:s \G\M\T’);
    }
  • Save and you are good to go 🙂

Solution: Failed to load the MailChimp PHP library or The MailChimp PHP library is missing the required GuzzleHttp library

Failed to load the MailChimp PHP library. Please refer to the installation requirements.
The MailChimp PHP library is missing the required GuzzleHttp library. Please check the installation notes in README.txt.

Solution:

  • To remove this issue please choose the correct version of the MailChimp module with corresponding to the Drupal version.
  • Download the library and paste it at sites/all/libraries
    Go to MailChimp PHP library
    Please verify your versions. Go to your module and sites\all\modules\**\mailchimp\mailchimp.module then see the code which library to download.
    hook_libraries_info() let you use an external library in your module, you need to make it known first and can be done by implementing this function as mailchimp_libraries_info()
  • The folder structure will look like below images (may differ in your case, mine drupal version is 7.34):
  • Clear the cache
    Home » Administration » Configuration » Development » Performance

We hope this will solve your problem. If not let us know and we will dig more

Overview of library creator:
============================================
A PHP 5.2+ API client for [v2 of the MailChimp API](http://apidocs.mailchimp.com/api/2.0/). Please note that we generate this client/wrapper, so while we’re happy to look at any pull requests, ultimately we can’t technically accept them. We will however comment on any additions or changes made due to them before closing them.
###Usage
This can be installed via [Composer](http://getcomposer.org/) and our [packagist package](https://packagist.org/packages/mailchimp/mailchimp).

A basic example app to help kickstart you which – will also automatically install this package – is over in a public [github](https://github.com/mailchimp/mcapi2-php-examples) repo.

===============================================

Thanks
Rupak

How to add default or custom OpenCart modules in the Journal theme?

In Opencart tips and tricks, we are showing how to add default or custom OpenCart modules in Journal 3 OpenCart theme.

  • Go to Journal >> Layouts >> then edit where you want to show the OpenCart custom or default theme.
  • Then hover over to the row that you want to show the image and click “Add Module” + button.
Add Opencart module in Journal 3 theme

  • This will add a content section, then click on it and a popup with lists of modules shows.
Lists of modules in Opencart 3
  • Go to the bottom of the popup and click “Opencart”
  • This gives lists of default Opencart modules
  • Choose, edit them as per your requirement, and add them to that layout.

Read: Learn Journal theme customization coding tutorial

We hope that tips help someone. Let us know if you have any questions or suggestions, please subscribe to our YouTube Channel for Opencart video tutorials and find more Opencart tips and tricks. You can also join us on Twitter and Facebook.

How to install a free SSL certificate on Opencart Let’s Encrypt™

The SSL certificate is needed to encrypt all communication between the browser and the server, which ensures that all communication and data goes through a secure (HTTPS) connection.

Is the SSL certificate required on Opencart?

SSL certificate is required on OpenCart as it shows reliability and security to customer/visitors and gain your clients’ trust and somewhat helps to increase your website’s search engines ranking.

Which are the pages that we have to make SSL in the e-commerce site?

SSL should be activated everywhere, but important where sensitive data are to be transferred from user to server. My account, Login and checkout URL should be on SSL. But whoever is providing the SSL certificate they provide for the whole domain so just install throughout the domain.

Server settings for the Encrypts SSL

Login to your Cpanel and check the section Security

Cpanel Security Section

Click the “Lets Encrypt™ SSL“.

Let's Encrypt certificates

Click +Issue. SSL is installed on the domain.

Installation of SSL certificate

You can verify by going to the Security section of the dashboard and click “SSL/TLS Status” check if “AutoSSL Domain Validated” is showing for each domain.

Auto SSL domain validated

If you don’t see it then go to Security section of the dashboard and click “SSL/TLS”

Installed SSL websites

Then click on the “Browse Certificates” and select your certificate and install click install at the end.

Now your server is ready now need to do some setting change in the admin dashboard.

Three points to do for activation of the SSL certificate or digital certificate are below for OpenCart:

  • Enable SSL in System->Settings->Edit->Server->Use SSL and select Yes.
digital certificate for Opencart
  • Check if there is https in /config.php and /admin/config.php
  • Change the .htaccess in your Apache server like below:
RewriteCond %{HTTP_HOST} ^webocreation\.com [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://webocreation.com/$1 [R,L]

Replace webocreation.com with your site URL in the above code. It redirects all non-https to https URL, likewise, it will redirects www URLs to non-www URL if you want the www then add www at the last line.

If you encounter an SSL problem with opencart follow these steps to solve it.

1. Make sure you update both config files with “https”
2. Make sure you turn ON SSL under backend – system>settings>edit>server
3. If you are using Plesk make sure you check the box for domain settings that says “Use a single directory for housing SSL and non-SSL content”

How we can know that there is a problem in the Opencart installation of SSL?

Put up a simple index.html test file and then access it via https://yourdomain.com/index.html if you get an error there it has nothing to do with opencart. If you don’t then opencart should work.

If you found this error “SSL_ERROR_TX_RECORD_TOO_LONG”
-Then it means that the SSL was not installed on your host properly.

Stop Google from indexing all of your SSL pages

First, make 1 robots.txt file and 1 robots_ssl.txt file. You could put anything in them, but the default would be something like this:

In robots.txt

User-agent: *
Allow: /

In robots_ssl.txt:

User-agent: *
Disallow: /

Then, in your .htaccess file, add this

RewriteEngine on
Options +FollowSymlinks
RewriteCond %{SERVER_PORT} ^443$
RewriteRule ^robots.txt$ robots_ssl.txt

If you’re using the .htaccess that comes with OpenCart then the first two lines are already added in the .htaccess file for you, you would just add in the RewriteCond and RewriteRule lines.

We hope this helps someone to set up SSL properly and easily in Opencart. Please don’t forget to post your questions or comments so that we can add extra topics. You can follow us at our twitter account @rupaknpl and subscribe to our YouTube channel for opencart tutorials.

Marketo API – export all Forms and their Fields from our Marketo database

We worked in Marketo JavaScript Marketo API where we have to export all forms and their fields from our Marketo database. With custom API extraction, we are able to export all Forms and their Fields from our Marketo database which we tested through the API which is shown in the attached images.

Login into marketo.com and click admin >> Then Integration >> LaunchPoint where you will see a list of Service. If you already have created the API the service then click the “View Details”, then click the “GET TOKEN”

Get API token Marketo

This is the access token “7a96ebb0-58dd-45cd-8614-f5b2242664fd:sj” which is TOKENGENERATEDINMARKETOAPI in the URL. MARKETOID is the Marketo account id, you can get the REST API endpoint at admin >> Integration >> Web Services where you can find the endpoint URL like https://MARKETOID.mktorest.com/rest

To get all the forms the endpoint URL is

https://MARKETOID.mktorest.com/rest/asset/v1/forms.json?access_token=TOKENGENERATEDINMARKETOAPI

All forms Marketo

It pulls all of the forms from the Marketo database which are published. One of the form detail is like below:

{
    "id": 1424,
    "name": "2018.FORM-Request",
    "description": "",
    "createdAt": "2018-07-30T18:02:04Z+0000",
    "updatedAt": "2018-07-30T18:02:04Z+0000",
    "url": "https://app-sj44.marketo.com/#FO1424",
    "status": "approved",
    "theme": "simple",
    "language": "English",
    "locale": "en_US",
    "progressiveProfiling": true,
    "labelPosition": "above",
    "fontFamily": "Helvetica",
    "fontSize": "14px",
    "folder": {
        "type": "Folder",
        "value": 1408,
        "folderName": "Form"
    },
    "knownVisitor": {
        "type": "form",
        "template": null
    },
    "thankYouList": [
        {
            "followupType": "none",
            "followupValue": null,
            "default": true
        }
    ],
    "buttonLocation": 10,
    "buttonLabel": "CONTACT ME",
    "waitingLabel": "PLEASE WAIT..."
}

To get fields of a form the endpoint URL is

With the above JSON, we can get the ID of the form like “id”: 1424 then we pull the fields of that form with the following endpoint URL

https://MARKETOID.mktorest.com/rest/asset/v1/form/1424/fields.json?access_token=TOKENGENERATEDINMARKETOAPI

Forms fields Marketo

You will get the JSON response like below, as per below JSON the form has 3 fields First Name, Last Name and Email.

{
    "success": true,
    "errors": [],
    "requestId": "16376#1715271cde8",
    "warnings": [],
    "result": [
        {
            "id": "FirstName",
            "label": "First Name:",
            "labelWidth": 420,
            "fieldWidth": 420,
            "dataType": "text",
            "validationMessage": "This field is required.",
            "rowNumber": 0,
            "columnNumber": 0,
            "maxLength": 255,
            "required": true,
            "formPrefill": true,
            "visibilityRules": {
                "ruleType": "alwaysShow"
            }
        },
        {
            "id": "LastName",
            "label": "Last Name:",
            "labelWidth": 420,
            "fieldWidth": 420,
            "dataType": "text",
            "validationMessage": "This field is required.",
            "rowNumber": 1,
            "columnNumber": 0,
            "maxLength": 255,
            "required": true,
            "formPrefill": true,
            "visibilityRules": {
                "ruleType": "alwaysShow"
            }
        },
        {
            "id": "Email",
            "label": "Email Address:",
            "labelWidth": 420,
            "fieldWidth": 420,
            "dataType": "email",
            "validationMessage": "Must be valid email. <span class='mktoErrorDetail'>example@yourdomain.com</span>",
            "rowNumber": 2,
            "columnNumber": 0,
            "required": true,
            "formPrefill": true,
            "visibilityRules": {
                "ruleType": "alwaysShow"
            }
        }
    ]
}

In this way, we can export all forms and their fields from our Marketo database. The time taking part can be how you want the data to show. Please don’t forget to post your questions or comments or errors so that we can help you. You can follow us at our twitter account @rupaknpl. Click to see other Salesforce Marketo blog posts.

Display all products opencart module for free version 2.3, 2.2, 2.1, 2.0

Another free Opencart module to display all products on a custom page, we show you how to install steps and have provided all code definitions.

Steps to install “All Products Show in One Page” opencart 2.3 module free:
For OpenCart Version 3.0.*.* visit here

  • Download the module
    Download Show all product module in one page opencart versions 2.3
  • Extract the zip file.
  • Upload the catalog folder which is inside “List out all products OpenCart 2.2” to your server “catalog” folder
  • Now login to the admin section then go to Extensions >> Extension Installer >> where you upload the all.install.ocmod.xml if you see any error then see how to solve the Ocmod installation error.
  • After successful installation, go to Extensions>> Modification and click the log tab and see if some errors are showing, if the error shows then you have to solve it first.
  • If no error click the refresh button
  • You are all set.
  • If you have multiple languages then you have to translate the catalog/language/en-gb/product/allproduct.php and place into catalog/language/YOURLANGUAGEFOLDER/product
  • Enjoy the free module.

How to add modules on this page?

  • Go to Admin >> Design >> Layout >> Click the add button
  • Then fill out as follows:
  • The output will be as below:

How to stop showing all products link?

If you do not need this then you can disable and delete the “List Out All Products OpenCart 2.3 OCmod”.

Go to Admin >> Extensions >> Modifications >> Disable “List Out All Products OpenCart 2.3 OCmod” or you can delete it as well and you will not see the All products links in the menu.

You can follow at my twitter account @rupaknpl and subscribe to YouTube user Opencart Tutorials.

For questions, errors, suggestions at this email webocreation.com@gmail.com.

Below are steps for the OpenCart module 2.2 and below

Installation:

  1. Unzip “Show+All+Products+Module.zip” in the folder of your choice.
  2. Upload all the files to the root folder to your server, no files are overwritten.
  3. Be sure you have VqMod installed.

You can easily download here and enjoy the module. If you got any error or problems then let me know so that I can see how to improve it and make it more friendly.

DOWNLOAD SHOW ALL PRODUCT MODULE for 2.0.1.1

DOWNLOAD SHOW ALL PRODUCT MODULE for 2.2.0.0

eCommerce Solution: I have created the Show all products extension on OpenCart which I am sharing with you all for free

DEMO

It lists out all the products with the pagination feature available. Most of my clients asked for this extension so I think this will be helpful for you all so I post it here.

 Display All Products OpenCart Module

Codes are written are on the following files

Ocmod file named all.install.ocmod.xml for opencart version 2.3

<?xml version="1.0" encoding="utf-8"?>
<modification>
    <name>List Out All Products OpenCart 2.3 OCmod</name>
    <version>1.0</version>
    <author>Rupak Nepali, Webocreation.com</author>
    <code>List_all_Products</code>
    <link>https://webocreation.com</link>
    <file path="catalog/controller/common/header.php">
        <operation>
            <search><![CDATA[
            $data['categories'] = array();
            ]]></search>
            <add position="After"><![CDATA[
                $this->load->language('product/allproduct');
                $data['categories'][] = array(
                    'name'     => $this->language->get('all_product'),
                    'children' => "",
                    'column'   => 1,
                    'href'     => $this->url->link('product/allproduct')
                );
            ]]></add>
        </operation>
    </file>
</modification>

Vqmod vqmod\xml\all.install.ocmod.xml to show “All Products” link in the top menu.

<modification>	
	<version>OpenCart Version 2.2</version>
	<vqmver>2.0.0</vqmver>
	<author>Rupak Nepali</author>
	    <code>List_all_Products</code>
	<file name="catalog/view/theme/*/template/common/header.tpl" error="skip">
		<operation>
			<search position="after"><![CDATA[
				<ul class="nav navbar-nav">
			]]></search>
			<add><![CDATA[
				<li><a href="index.php?route=product/allproduct">All Products</a></li>
			]]></add>
		</operation>
	</file>
</modification>

Language file catalog\language\en-gb\product\allproduct.php

<?php

$_['page_title']        = 'All Products List';
$_['meta_description']  = 'All Products List';
$_['meta_keyword']      = 'All Products List';
$_['heading_title']     = 'All Products List';

// Text

$_['text_refine']       = 'Refine Search';
$_['text_product']      = 'Products';
$_['text_error']        = 'all products not found!';
$_['text_empty']        = 'There are no products to list in this all products.';
$_['text_quantity']     = 'Qty:';
$_['text_manufacturer'] = 'Brand:';
$_['text_model']        = 'Product Code:';
$_['text_points']       = 'Reward Points:';
$_['text_price']        = 'Price:';
$_['text_tax']          = 'Ex Tax:';
$_['text_compare']      = 'Product Compare (%s)';
$_['text_sort']         = 'Sort By:';
$_['text_default']      = 'Default';
$_['text_name_asc']     = 'Name (A - Z)';
$_['text_name_desc']    = 'Name (Z - A)';
$_['text_price_asc']    = 'Price (Low &gt; High)';
$_['text_price_desc']   = 'Price (High &gt; Low)';
$_['text_rating_asc']   = 'Rating (Lowest)';
$_['text_rating_desc']  = 'Rating (Highest)';
$_['text_model_asc']    = 'Model (A - Z)';
$_['text_model_desc']   = 'Model (Z - A)';
$_['text_limit']        = 'Show:';

Controller file catalog\controller\product\allproduct.php

<?php
class ControllerProductAllproduct extends Controller {
 public function index() {
 $this->load->language('product/allproduct');

 $this->load->model('catalog/allproduct');

 $this->load->model('catalog/product');

 $this->load->model('tool/image');
 $this->document->setTitle($this->language->get('page_title'));
 $this->document->setDescription($this->language->get('meta_description'));
 $this->document->setKeywords($this->language->get('meta_keyword'));

 $data['heading_title'] = $this->language->get('heading_title');
 if (isset($this->request->get['filter'])) {
 $filter = $this->request->get['filter'];
 } else {
 $filter = '';
 }

 if (isset($this->request->get['sort'])) {
 $sort = $this->request->get['sort'];
 } else {
 $sort = 'p.sort_order';
 }

 if (isset($this->request->get['order'])) {
 $order = $this->request->get['order'];
 } else {
 $order = 'ASC';
 }

 if (isset($this->request->get['page'])) {
 $page = $this->request->get['page'];
 } else {
 $page = 1;
 }

 if (isset($this->request->get['limit'])) {
 $limit = (int)$this->request->get['limit'];
 } else {
 $limit = $this->config->get($this->config->get('config_theme') . '_product_limit');
 }

 $data['breadcrumbs'] = array();

 $data['breadcrumbs'][] = array(
 'text' => $this->language->get('text_home'),
 'href' => $this->url->link('common/home')
 );

 $allproduct_info = $this->model_catalog_allproduct->getAllProduct();

 if ($allproduct_info) {


 $data['text_refine'] = $this->language->get('text_refine');
 $data['text_empty'] = $this->language->get('text_empty');
 $data['text_quantity'] = $this->language->get('text_quantity');
 $data['text_manufacturer'] = $this->language->get('text_manufacturer');
 $data['text_model'] = $this->language->get('text_model');
 $data['text_price'] = $this->language->get('text_price');
 $data['text_tax'] = $this->language->get('text_tax');
 $data['text_points'] = $this->language->get('text_points');
 $data['text_compare'] = sprintf($this->language->get('text_compare'), (isset($this->session->data['compare']) ? count($this->session->data['compare']) : 0));
 $data['text_sort'] = $this->language->get('text_sort');
 $data['text_limit'] = $this->language->get('text_limit');

 $data['button_cart'] = $this->language->get('button_cart');
 $data['button_wishlist'] = $this->language->get('button_wishlist');
 $data['button_compare'] = $this->language->get('button_compare');
 $data['button_continue'] = $this->language->get('button_continue');
 $data['button_list'] = $this->language->get('button_list');
 $data['button_grid'] = $this->language->get('button_grid');

$data['compare'] = $this->url->link('product/compare');


 // Set the last AllProduct breadcrumb
 $data['breadcrumbs'][] = array(
 'text' => $this->language->get('heading_title'),
 'href' => $this->url->link('product/allproduct')
 );
 $url = '';
 $data['products'] = array();
 $filter_data = array(
 'filter_filter'      => $filter,
 'sort'               => $sort,
 'order'              => $order,
 'start'              => ($page - 1) * $limit,
 'limit'              => $limit
 );

 $product_total = $this->model_catalog_product->getTotalProducts($filter_data);
 $results = $this->model_catalog_product->getProducts($filter_data);
 foreach ($results as $result) {
 if ($result['image']) {
 $image = $this->model_tool_image->resize($result['image'], $this->config->get($this->config->get('config_theme') . '_image_product_width'), $this->config->get($this->config->get('config_theme') . '_image_product_height'));
 } else {
 $image = $this->model_tool_image->resize('placeholder.png', $this->config->get($this->config->get('config_theme') . '_image_product_width'), $this->config->get($this->config->get('config_theme') . '_image_product_height'));
 }

 if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
 $price = $this->currency->format($this->tax->calculate($result['price'], $result['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
 } else {
 $price = false;
 }

 if ((float)$result['special']) {
 $special = $this->currency->format($this->tax->calculate($result['special'], $result['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
 } else {
 $special = false;
 }

 if ($this->config->get('config_tax')) {
 $tax = $this->currency->format((float)$result['special'] ? $result['special'] : $result['price'], $this->session->data['currency']);
 } else {
 $tax = false;
 }

 if ($this->config->get('config_review_status')) {
 $rating = (int)$result['rating'];
 } else {
 $rating = false;
 }

 $data['products'][] = array(
 'product_id'  => $result['product_id'],
 'thumb'       => $image,
 'name'        => $result['name'],
 'description' => utf8_substr(strip_tags(html_entity_decode($result['description'], ENT_QUOTES, 'UTF-8')), 0, $this->config->get($this->config->get('config_theme') . '_product_description_length')) . '..',
 'price'       => $price,
 'special'     => $special,
 'tax'         => $tax,
 'minimum'     => $result['minimum'] > 0 ? $result['minimum'] : 1,
 'rating'      => $result['rating'],
 'href'        => $this->url->link('product/product', '&product_id=' . $result['product_id'] .$url)
 );
 }

 $url = '';

 if (isset($this->request->get['filter'])) {
 $url .= '&filter=' . $this->request->get['filter'];
 }

 if (isset($this->request->get['limit'])) {
 $url .= '&limit=' . $this->request->get['limit'];
 }

 $data['sorts'] = array();

 $data['sorts'][] = array(
 'text'  => $this->language->get('text_default'),
 'value' => 'p.sort_order-ASC',
 'href'  => $this->url->link('product/allproduct', $url)
 );

 $data['sorts'][] = array(
 'text'  => $this->language->get('text_name_asc'),
 'value' => 'pd.name-ASC',
 'href'  => $this->url->link('product/allproduct', $url)
 );

 $data['sorts'][] = array(
 'text'  => $this->language->get('text_name_desc'),
 'value' => 'pd.name-DESC',
 'href'  => $this->url->link('product/allproduct', $url)
 );

 $data['sorts'][] = array(
 'text'  => $this->language->get('text_price_asc'),
 'value' => 'p.price-ASC',
 'href'  => $this->url->link('product/allproduct', $url)
 );

 $data['sorts'][] = array(
 'text'  => $this->language->get('text_price_desc'),
 'value' => 'p.price-DESC',
 'href'  => $this->url->link('product/allproduct', $url)
 );

 if ($this->config->get('config_review_status')) {
 $data['sorts'][] = array(
 'text'  => $this->language->get('text_rating_desc'),
 'value' => 'rating-DESC',
 'href'  => $this->url->link('product/allproduct', $url)
 );

 $data['sorts'][] = array(
 'text'  => $this->language->get('text_rating_asc'),
 'value' => 'rating-ASC',
 'href'  => $this->url->link('product/allproduct', $url)
 );
 }

 $data['sorts'][] = array(
 'text'  => $this->language->get('text_model_asc'),
 'value' => 'p.model-ASC',
 'href'  => $this->url->link('product/allproduct', $url)
 );

 $data['sorts'][] = array(
 'text'  => $this->language->get('text_model_desc'),
 'value' => 'p.model-DESC',
 'href'  => $this->url->link('product/allproduct', $url)
 );

 $url = '';

 if (isset($this->request->get['filter'])) {
 $url .= '&filter=' . $this->request->get['filter'];
 }

 if (isset($this->request->get['sort'])) {
 $url .= '&sort=' . $this->request->get['sort'];
 }

 if (isset($this->request->get['order'])) {
 $url .= '&order=' . $this->request->get['order'];
 }

 $data['limits'] = array();

 $limits = array_unique(array($this->config->get($this->config->get('config_theme') . '_product_limit'), 25, 50, 75, 100));

 sort($limits);

 foreach($limits as $value) {
 $data['limits'][] = array(
 'text'  => $value,
 'value' => $value,
 'href'  => $this->url->link('product/allproduct', $url . '&limit=' . $value)
 );
 }

 $url = '';

 if (isset($this->request->get['filter'])) {
 $url .= '&filter=' . $this->request->get['filter'];
 }

 if (isset($this->request->get['sort'])) {
 $url .= '&sort=' . $this->request->get['sort'];
 }

 if (isset($this->request->get['order'])) {
 $url .= '&order=' . $this->request->get['order'];
 }

 if (isset($this->request->get['limit'])) {
 $url .= '&limit=' . $this->request->get['limit'];
 }

 $pagination = new Pagination();
 $pagination->total = $product_total;
 $pagination->page = $page;
 $pagination->limit = $limit;
 $pagination->url = $this->url->link('product/allproduct', $url . '&page={page}');

 $data['pagination'] = $pagination->render();

 $data['results'] = sprintf($this->language->get('text_pagination'), ($product_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($product_total - $limit)) ? $product_total : ((($page - 1) * $limit) + $limit), $product_total, ceil($product_total / $limit));

 if ($page == 1) {
     $this->document->addLink($this->url->link('product/allproduct', '', true), 'canonical');
 } elseif ($page == 2) {
     $this->document->addLink($this->url->link('product/allproduct', '', true), 'prev');
 } else {
     $this->document->addLink($this->url->link('product/allproduct', '&page='. ($page - 1), true), 'prev');
 }

 if ($limit && ceil($product_total / $limit) > $page) {
     $this->document->addLink($this->url->link('product/allproduct', '&page='. ($page + 1), true), 'next');
 }

 $data['sort'] = $sort;
 $data['order'] = $order;
 $data['limit'] = $limit;

 $data['continue'] = $this->url->link('common/home');

 $data['column_left'] = $this->load->controller('common/column_left');
 $data['column_right'] = $this->load->controller('common/column_right');
 $data['content_top'] = $this->load->controller('common/content_top');
 $data['content_bottom'] = $this->load->controller('common/content_bottom');
 $data['footer'] = $this->load->controller('common/footer');
 $data['header'] = $this->load->controller('common/header');

 $this->response->setOutput($this->load->view('product/allproduct', $data));
 } else {
 $url = '';

 if (isset($this->request->get['filter'])) {
 $url .= '&filter=' . $this->request->get['filter'];
 }

 if (isset($this->request->get['sort'])) {
 $url .= '&sort=' . $this->request->get['sort'];
 }

 if (isset($this->request->get['order'])) {
 $url .= '&order=' . $this->request->get['order'];
 }

 if (isset($this->request->get['page'])) {
 $url .= '&page=' . $this->request->get['page'];
 }

 if (isset($this->request->get['limit'])) {
 $url .= '&limit=' . $this->request->get['limit'];
 }

 $data['breadcrumbs'][] = array(
 'text' => $this->language->get('text_error'),
 'href' => $this->url->link('product/allproduct', $url)
 );

 $this->document->setTitle($this->language->get('text_error'));

 $data['heading_title'] = $this->language->get('text_error');

 $data['text_error'] = $this->language->get('text_error');

 $data['button_continue'] = $this->language->get('button_continue');

 $data['continue'] = $this->url->link('common/home');

 $this->response->addHeader($this->request->server['SERVER_PROTOCOL'] . ' 404 Not Found');

 $data['column_left'] = $this->load->controller('common/column_left');
 $data['column_right'] = $this->load->controller('common/column_right');
 $data['content_top'] = $this->load->controller('common/content_top');
 $data['content_bottom'] = $this->load->controller('common/content_bottom');
 $data['footer'] = $this->load->controller('common/footer');
 $data['header'] = $this->load->controller('common/header');

 $this->response->setOutput($this->load->view('error/not_found', $data));
 }
 }
}

Model file at catalog\model\catalog\allproduct.php

<?php
class ModelCatalogAllProduct extends Model {
	public function getAllProduct($data = array()) {
		$sql = "SELECT p.product_id, (SELECT AVG(rating) AS total FROM " . DB_PREFIX . "review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id) AS rating, (SELECT price FROM " . DB_PREFIX . "product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1) AS discount, (SELECT price FROM " . DB_PREFIX . "product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special";

		if (!empty($data['filter_category_id'])) {
			if (!empty($data['filter_sub_category'])) {
				$sql .= " FROM " . DB_PREFIX . "category_path cp LEFT JOIN " . DB_PREFIX . "product_to_category p2c ON (cp.category_id = p2c.category_id)";
			} else {
				$sql .= " FROM " . DB_PREFIX . "product_to_category p2c";
			}

			if (!empty($data['filter_filter'])) {
				$sql .= " LEFT JOIN " . DB_PREFIX . "product_filter pf ON (p2c.product_id = pf.product_id) LEFT JOIN " . DB_PREFIX . "product p ON (pf.product_id = p.product_id)";
			} else {
				$sql .= " LEFT JOIN " . DB_PREFIX . "product p ON (p2c.product_id = p.product_id)";
			}
		} else {
			$sql .= " FROM " . DB_PREFIX . "product p";
		}

		$sql .= " LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";

		if (!empty($data['filter_category_id'])) {
			if (!empty($data['filter_sub_category'])) {
				$sql .= " AND cp.path_id = '" . (int)$data['filter_category_id'] . "'";
			} else {
				$sql .= " AND p2c.category_id = '" . (int)$data['filter_category_id'] . "'";
			}

			if (!empty($data['filter_filter'])) {
				$implode = array();

				$filters = explode(',', $data['filter_filter']);

				foreach ($filters as $filter_id) {
					$implode[] = (int)$filter_id;
				}

				$sql .= " AND pf.filter_id IN (" . implode(',', $implode) . ")";
			}
		}

		if (!empty($data['filter_name']) || !empty($data['filter_tag'])) {
			$sql .= " AND (";

			if (!empty($data['filter_name'])) {
				$implode = array();

				$words = explode(' ', trim(preg_replace('/\s+/', ' ', $data['filter_name'])));

				foreach ($words as $word) {
					$implode[] = "pd.name LIKE '%" . $this->db->escape($word) . "%'";
				}

				if ($implode) {
					$sql .= " " . implode(" AND ", $implode) . "";
				}

				if (!empty($data['filter_description'])) {
					$sql .= " OR pd.description LIKE '%" . $this->db->escape($data['filter_name']) . "%'";
				}
			}

			if (!empty($data['filter_name']) && !empty($data['filter_tag'])) {
				$sql .= " OR ";
			}

			if (!empty($data['filter_tag'])) {
				$sql .= "pd.tag LIKE '%" . $this->db->escape($data['filter_tag']) . "%'";
			}

			if (!empty($data['filter_name'])) {
				$sql .= " OR LCASE(p.model) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				$sql .= " OR LCASE(p.sku) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				$sql .= " OR LCASE(p.upc) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				$sql .= " OR LCASE(p.ean) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				$sql .= " OR LCASE(p.jan) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				$sql .= " OR LCASE(p.isbn) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				$sql .= " OR LCASE(p.mpn) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
			}

			$sql .= ")";
		}

		if (!empty($data['filter_manufacturer_id'])) {
			$sql .= " AND p.manufacturer_id = '" . (int)$data['filter_manufacturer_id'] . "'";
		}

		$sql .= " GROUP BY p.product_id";

		$sort_data = array(
			'pd.name',
			'p.model',
			'p.quantity',
			'p.price',
			'rating',
			'p.sort_order',
			'p.date_added'
		);

		if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
			if ($data['sort'] == 'pd.name' || $data['sort'] == 'p.model') {
				$sql .= " ORDER BY LCASE(" . $data['sort'] . ")";
			} elseif ($data['sort'] == 'p.price') {
				$sql .= " ORDER BY (CASE WHEN special IS NOT NULL THEN special WHEN discount IS NOT NULL THEN discount ELSE p.price END)";
			} else {
				$sql .= " ORDER BY " . $data['sort'];
			}
		} else {
			$sql .= " ORDER BY p.sort_order";
		}

		if (isset($data['order']) && ($data['order'] == 'DESC')) {
			$sql .= " DESC, LCASE(pd.name) DESC";
		} else {
			$sql .= " ASC, LCASE(pd.name) ASC";
		}

		if (isset($data['start']) || isset($data['limit'])) {
			if ($data['start'] < 0) {
				$data['start'] = 0;
			}

			if ($data['limit'] < 1) {
				$data['limit'] = 20;
			}

			$sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
		}

		$product_data = array();

		$query = $this->db->query($sql);

		foreach ($query->rows as $result) {
			$product_data[$result['product_id']] = $this->getProduct($result['product_id']);
		}

		return $product_data;
	}

	public function getProduct($product_id) {
		$query = $this->db->query("SELECT DISTINCT *, pd.name AS name, p.image, m.name AS manufacturer, (SELECT price FROM " . DB_PREFIX . "product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1) AS discount, (SELECT price FROM " . DB_PREFIX . "product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special, (SELECT points FROM " . DB_PREFIX . "product_reward pr WHERE pr.product_id = p.product_id AND customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "') AS reward, (SELECT ss.name FROM " . DB_PREFIX . "stock_status ss WHERE ss.stock_status_id = p.stock_status_id AND ss.language_id = '" . (int)$this->config->get('config_language_id') . "') AS stock_status, (SELECT wcd.unit FROM " . DB_PREFIX . "weight_class_description wcd WHERE p.weight_class_id = wcd.weight_class_id AND wcd.language_id = '" . (int)$this->config->get('config_language_id') . "') AS weight_class, (SELECT lcd.unit FROM " . DB_PREFIX . "length_class_description lcd WHERE p.length_class_id = lcd.length_class_id AND lcd.language_id = '" . (int)$this->config->get('config_language_id') . "') AS length_class, (SELECT AVG(rating) AS total FROM " . DB_PREFIX . "review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id) AS rating, (SELECT COUNT(*) AS total FROM " . DB_PREFIX . "review r2 WHERE r2.product_id = p.product_id AND r2.status = '1' GROUP BY r2.product_id) AS reviews, p.sort_order FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) LEFT JOIN " . DB_PREFIX . "manufacturer m ON (p.manufacturer_id = m.manufacturer_id) WHERE p.product_id = '" . (int)$product_id . "' AND pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'");

		if ($query->num_rows) {
			return array(
				'product_id'       => $query->row['product_id'],
				'name'             => $query->row['name'],
				'description'      => $query->row['description'],
				'meta_title'       => $query->row['meta_title'],
				'meta_description' => $query->row['meta_description'],
				'meta_keyword'     => $query->row['meta_keyword'],
				'tag'              => $query->row['tag'],
				'model'            => $query->row['model'],
				'sku'              => $query->row['sku'],
				'upc'              => $query->row['upc'],
				'ean'              => $query->row['ean'],
				'jan'              => $query->row['jan'],
				'isbn'             => $query->row['isbn'],
				'mpn'              => $query->row['mpn'],
				'location'         => $query->row['location'],
				'quantity'         => $query->row['quantity'],
				'stock_status'     => $query->row['stock_status'],
				'image'            => $query->row['image'],
				'manufacturer_id'  => $query->row['manufacturer_id'],
				'manufacturer'     => $query->row['manufacturer'],
				'price'            => ($query->row['discount'] ? $query->row['discount'] : $query->row['price']),
				'special'          => $query->row['special'],
				'reward'           => $query->row['reward'],
				'points'           => $query->row['points'],
				'tax_class_id'     => $query->row['tax_class_id'],
				'date_available'   => $query->row['date_available'],
				'weight'           => $query->row['weight'],
				'weight_class_id'  => $query->row['weight_class_id'],
				'length'           => $query->row['length'],
				'width'            => $query->row['width'],
				'height'           => $query->row['height'],
				'length_class_id'  => $query->row['length_class_id'],
				'subtract'         => $query->row['subtract'],
				'rating'           => round($query->row['rating']),
				'reviews'          => $query->row['reviews'] ? $query->row['reviews'] : 0,
				'minimum'          => $query->row['minimum'],
				'sort_order'       => $query->row['sort_order'],
				'status'           => $query->row['status'],
				'date_added'       => $query->row['date_added'],
				'date_modified'    => $query->row['date_modified'],
				'viewed'           => $query->row['viewed']
			);
		} else {
			return false;
		}
	}
}

Template file catalog\view\theme\default\template\product\allproduct.tpl

<?php echo $header; ?> <div class="container">
    <ul class="breadcrumb"> <?php foreach ($breadcrumbs as $breadcrumb) { ?> <li><a
                href="<?php echo $breadcrumb['href']; ?>"><?php echo $breadcrumb['text']; ?></a></li> <?php } ?> </ul>
    <div class="row"><?php echo $column_left; ?> <?php if ($column_left && $column_right) { ?>
        <?php $class = 'col-sm-6'; ?> <?php } elseif ($column_left || $column_right) { ?> <?php $class = 'col-sm-9'; ?>
        <?php } else { ?> <?php $class = 'col-sm-12'; ?> <?php } ?> <div id="content" class="<?php echo $class; ?>">
            <?php echo $content_top; ?> <h2><?php echo $heading_title; ?></h2> <?php if ($products) { ?> <p><a
                    href="<?php echo $compare; ?>" id="compare-total"><?php echo $text_compare; ?></a></p>
            <div class="row">
                <div class="col-md-4">
                    <div class="btn-group hidden-xs"> <button type="button" id="list-view" class="btn btn-default"
                            data-toggle="tooltip" title="<?php echo $button_list; ?>"><i
                                class="fa fa-th-list"></i></button> <button type="button" id="grid-view"
                            class="btn btn-default" data-toggle="tooltip" title="<?php echo $button_grid; ?>"><i
                                class="fa fa-th"></i></button> </div>
                </div>
                <div class="col-md-2 text-right"> <label class="control-label"
                        for="input-sort"><?php echo $text_sort; ?></label> </div>
                <div class="col-md-3 text-right"> <select id="input-sort" class="form-control"
                        onchange="location = this.value;"> <?php foreach ($sorts as $sorts) { ?>
                        <?php if ($sorts['value'] == $sort . '-' . $order) { ?> <option
                            value="<?php echo $sorts['href']; ?>" selected="selected"><?php echo $sorts['text']; ?>
                        </option> <?php } else { ?> <option value="<?php echo $sorts['href']; ?>">
                            <?php echo $sorts['text']; ?></option> <?php } ?> <?php } ?> </select> </div>
                <div class="col-md-1 text-right"> <label class="control-label"
                        for="input-limit"><?php echo $text_limit; ?></label> </div>
                <div class="col-md-2 text-right"> <select id="input-limit" class="form-control"
                        onchange="location = this.value;"> <?php foreach ($limits as $limits) { ?>
                        <?php if ($limits['value'] == $limit) { ?> <option value="<?php echo $limits['href']; ?>"
                            selected="selected"><?php echo $limits['text']; ?></option> <?php } else { ?> <option
                            value="<?php echo $limits['href']; ?>"><?php echo $limits['text']; ?></option> <?php } ?>
                        <?php } ?> </select> </div>
            </div> <br />
            <div class="row"> <?php foreach ($products as $product) { ?> <div
                    class="product-layout product-list col-xs-12">
                    <div class="product-thumb">
                        <div class="image"><a href="<?php echo $product['href']; ?>"><img
                                    src="<?php echo $product['thumb']; ?>" alt="<?php echo $product['name']; ?>"
                                    title="<?php echo $product['name']; ?>" class="img-responsive" /></a></div>
                        <div>
                            <div class="caption">
                                <h4><a href="<?php echo $product['href']; ?>"><?php echo $product['name']; ?></a></h4>
                                <p><?php echo $product['description']; ?></p> <?php if ($product['rating']) { ?> <div
                                    class="rating"> <?php for ($i = 1; $i <= 5; $i++) { ?>
                                    <?php if ($product['rating'] < $i) { ?> <span class="fa fa-stack"><i
                                            class="fa fa-star-o fa-stack-2x"></i></span> <?php } else { ?> <span
                                        class="fa fa-stack"><i class="fa fa-star fa-stack-2x"></i><i
                                            class="fa fa-star-o fa-stack-2x"></i></span> <?php } ?> <?php } ?> </div>
                                <?php } ?> <?php if ($product['price']) { ?> <p class="price">
                                    <?php if (!$product['special']) { ?> <?php echo $product['price']; ?>
                                    <?php } else { ?> <span class="price-new"><?php echo $product['special']; ?></span>
                                    <span class="price-old"><?php echo $product['price']; ?></span> <?php } ?>
                                    <?php if ($product['tax']) { ?> <span class="price-tax"><?php echo $text_tax; ?>
                                        <?php echo $product['tax']; ?></span> <?php } ?> </p> <?php } ?>
                            </div>
                            <div class="button-group"> <button type="button"
                                    onclick="cart.add('<?php echo $product['product_id']; ?>', '<?php echo $product['minimum']; ?>');"><i
                                        class="fa fa-shopping-cart"></i> <span
                                        class="hidden-xs hidden-sm hidden-md"><?php echo $button_cart; ?></span></button>
                                <button type="button" data-toggle="tooltip" title="<?php echo $button_wishlist; ?>"
                                    onclick="wishlist.add('<?php echo $product['product_id']; ?>');"><i
                                        class="fa fa-heart"></i></button> <button type="button" data-toggle="tooltip"
                                    title="<?php echo $button_compare; ?>"
                                    onclick="compare.add('<?php echo $product['product_id']; ?>');"><i
                                        class="fa fa-exchange"></i></button> </div>
                        </div>
                    </div>
                </div> <?php } ?> </div>
            <div class="row">
                <div class="col-sm-6 text-left"><?php echo $pagination; ?></div>
                <div class="col-sm-6 text-right"><?php echo $results; ?></div>
            </div> <?php } ?> <?php echo $content_bottom; ?>
        </div> <?php echo $column_right; ?></div>
</div> <?php echo $footer; ?>

what is the best salesforce tool to prevent overbooking?

What is the best salesforce tool to prevent overbooking?

Answer: Validation

Opencart eCommerce Advance Featured Module with product slider for free

We publishing another free Opencart eCommerce module “Advance Featured Module with product slider”. Some of the features of this free module are:

  • Show custom title
  • Aditional image flip flop
  • Hover over show add to cart, wishlist, and compare button
  • Sliding products
  • Can manage to slide of products from the admin
  • Show as many advances featured module as many you like
  • Absolutely free
  • None of the core files are changed
  • Responsive
featured front presentation section

Check demo: Click Advance Featured Module with product slider
You can see the following output after installing the module in information layout, which is only for demo purpose, you can install in any page and in any layout:

Advance Featured Module with product slider

Download the module for OpenCart 2.2 from below:

WebOCreation Featured Module

Installation:

  1. Unzip the downloaded folder.
  2. Upload the files and folders in the root folder to your server, put admin folder of zipping in admin folder of your server and catalog folder of zipping in catalog folder of your server
  3. Then activate the Advance Featured Module with product slider.

Activating the Advance Featured Module with product slider:

  1. After uploading files to servers, it’s time to install Advance Featured Module with product slider
  2. We are showing the Webocreation Featured Module with product slider in the content top and content-bottom of the information page but you can show it wherever you like as this is a normal module.
  3. Go to Admin section
  4. Then click on Extensions on the left menu
  5. After that Click Modules and go to Webocreation Featured Module with product slider in the modules list
  6. Then click the green button to install the module (see the image below)
  7. Then click blue edit button
  8. After that, you will see the form which has Module Name, Products, Limit, Width, Height, AutoPlay Speed, and status field, Fill it and select Enabled and then click Save button.
  9. Your module is active and is ready to use in the layout.

Setup layout for the Advance Featured Module at Information page:

  1. From the admin, section goes to Design >> Layouts.
  2. You will see a list of layouts, from which edit the Information layout.
  3. Then click Blue add a button to add rows at the module section which is shown in the image below:
  4. Second, you choose the Advance Featured Module in the module column and Column Bottom in the Position column and insert the sort order as required. Do the same to show another Webocreation Featured module at the content top also, refer to the above image.
  5. Then click save button

Your custom Advance Featured Module is showing in the two positions of the information page. Likewise, you can show in many other layouts and pages.

Let me know if you get any problem with performing the above tasks in the comment so that I can help.

Solution: Node.js Setup Wizard ended prematurely

How I fix “Node.js Setup Wizard ended prematurely”?

I am not able to install Nodejs. I was doing it with Setup Wizard downloaded for windows from nodejs.com and at the end of installation I get the message “Node.js Setup Wizard ended prematurely”.

Node.js setup wizard ended prematurely because of an error. Your system has not been modified. To install this program at a later time. run Setup Wizard again. Click the Finish button to exit the Setup Wizard.
I am able to install it by just disabling the “Performance Counter”.

Enjoy the video and happy NodeJs installation 🙂

Nodejs prematurely, Nodejs installation issues, Nodejs rollback

Solution M101JS: MongoDB for Node.js Developers

How to check if Customer or Admin is logged in the front page of Opencart 2 and 3?

This is opencart tips and tricks to check if Customer or Admin is logged in the front page of Opencart 2.3 and Opencart version 3. You can force login to customer. To check admin you should log in the same browser.

Force login for customer

Open catalog/controller/common/header.php

Find the index method: public function index() { then paste the following lines of code:

if ($this->request->get['route'] != "account/login") {
    if (!$this->customer->isLogged()) {
        $this->session->data['redirect'] = $this->url->link('common/home', '', true);
        $this->response->redirect($this->url->link('account/login', '', true));
    }
}

The above code check if route is login page or not and if it is not then it checks whether the customer is logged in or not, if not logged in then it redirects to login page. If the customer is logged in then it acts as normally.

Check whether Admin is logged in or not from the catalog or frontend

Now go to any controller and insert the code to check if user_id is set in the session. For example: Go to catalog/controller/common/header.php

Inside the index() method add the following code:

if($this->session->data['user_id']){
 echo 'Admin is logged in';
}else{
 echo 'Admin is not logged in';
}

Another way initialize the user object and check with isLogged() method

$loggeduser = new Cart\User($this->registry);
if($loggeduser->isLogged()){
 echo "Admin is in";
}else{
 echo "Admin not in";
}

This is how we can use Opencart library global objects methods.

Let us know if you find any difficulties or need any help from us. Likewise, you can see other Opencart tips and tricks and Opencart tutorial

Describe the relationship between sObjects and Salesforce records?

Describe the relationship between sObjects and Salesforce records.
A. The name of a sObject field in Apex is the label of the field in Salesforce.
B. A custom object’s API name and label are the same.
C. Every record in Salesforce is natively represented as a sObject in Apex.

Answer: C

You can obtain an instance of a sObject, such as Account, in one of the following ways:
A. By creating the sObject only.
B. Either by creating the sObject or by retrieving a persistent record from Salesforce using SOQL.
C. By retrieving the sObject only.  

Answer: C  

Which of the following is correct about a generic sObject variable?
A. A generic sObject variable can be assigned only to another generic sObject.
B. Generic sObjects can’t be created.
C. A generic sObject variable can be assigned to any specific sObject, standard or custom. Such as Account or Book__c.  

Answer: C

trailhead solution apex database sobjects

Uncaught exception ‘Exception’ with message ‘Error: Could not load model payment!’ in vqmod\vqcache\vq2-system_engine_loader.php

Uncaught exception ‘Exception’ with message ‘Error: Could not load model payment!’ in vqmod\vqcache\vq2-system_engine_loader.php or ‘Error: Could not load controller payment!’ or shipping or module then you have old folder existing in your folder so delete the old folder file which is at \catalog\model\payment or \catalog\model\shipping or \catalog\model\module. Once you delete that folder then hope it removes the opencart fatal error. DON’T FORGET TO KEEP BACKUP

Fatal error: Uncaught exception ‘Exception’ with message ‘Error: Could not load model payment!’ in vqmod\vqcache\-system_engine_loader.php on line 169
( ! ) Exception: Error: Could not load model payment! in vqmod\vqcache\vq2-system_engine_loader.php on line 169
Call Stack
# Time Memory Function Location
1 0.0000 135520 {main}( ) …\index.php:0
2 0.0150 755840 start( ) …\index.php:23
3 0.0150 781952 require_once( ‘system\framework.php’ ) …\vq2-system_startup.php:124
4 0.0450 1090320 Front->dispatch( ) …\framework.php:103
5 0.0825 1561336 Front->execute( ) …\front.php:29
6 0.0825 1561336 Action->execute( ) …\front.php:34
7 0.0825 1568880 call_user_func_array:{vqmod\vqcache\vq2-system_engine_action.php:51} ( ) …\vq2-system_engine_action.php:51
8 0.0825 1569112 ControllerStartupRouter->index( ) …\vq2-system_engine_action.php:51
9 0.0825 1569784 Action->execute( ) …\router.php:25
10 0.0850 1656912 call_user_func_array:{vqmod\vqcache\vq2-system_engine_action.php:51} ( ) …\vq2-system_engine_action.php:51
11 0.0850 1658328 ControllerQuickCheckoutPaymentMethod->index( ) …\vq2-system_engine_action.php:51
12 0.1500 1958272 getMethod ( ) …\payment_method.php:110
13 0.1500 1958520 Proxy->__call( ) …\payment_method.php:110
14 0.1500 1959200 call_user_func_array:{\system\engine\proxy.php:25} ( ) …\proxy.php:25
15 0.1500 1959976 Loader->{closure:vqmod\vqcache\vq2-system_engine_loader.php:147-191}( ) …\proxy.php:25

Just delete the folder by keeping the backup.

Hope it solve the problem. Happy Coding!!

USD to bitcoin, bitcoin exchange rate – Php code

Convert USD to bitcoin or get the latest value of bitcoin. The easiest way to get the bitcoin exchange rate

<?php
$amount=100;
$curl = curl_init();
curl_setopt_array($curl, array(
    CURLOPT_URL => "https://blockchain.info/tobtc?currency=USD&value=" . $amount,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => array(
        "cache-control: no-cache",
        "postman-token: fc62ebce-6d0b-ef4f-ba02-fcb05e284a02"
    ),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
echo $amount = json_decode($response);
?>

Above is programmatic code that you can use in your server but if you want to see in the browser then just do

https://blockchain.info/tobtc?currency=USD&value=100

Parameters
  • currency – A currency code. See the list above.
  • value – Value to convert.

Returns the value in BTC.

How to redirect Add to Cart button in opencart to the cart page directly

In this tutorial, we will show you how to redirect “Add to cart” button in Opencart version 1.4+, version 1.5+, version 2.0+ and version 3.0+ and take you directly to the shopping cart page.

For Opencart 1.4+ versions

For Opencart 1.4 versions it’s easy we can do it through the admin section
In Extensions->Modules under “Cart” you can disable ajax

For Opencart 1.5+ versions

But in Opencart 1.5+ there are no options to do those things so we have to edit in the codes.

Open the javascript file at catalog/view/javascript/common.js

Find the code below :

if (json['success']) {
    $('#notification').html('<div style="display: none;">' + json['success'] + '<img src="catalog/view/theme/default/image/close.png" alt="" /></div>');
    $('.attention').fadeIn('slow');
    $('#cart_total').html(json['total']);
    $('html, body').animate({ scrollTop: 0 }, 'slow');
}

Replace with

if (json['success']) {
    window.location.href='index.php?route=checkout/cart';
}

For OpenCart 2.3.0.2+ and Opencart 3.0+ follow following steps:

Find following code at catalog\view\javascript\common.js

var cart = { 'add': function(product_id, quantity) {

Inside that find success method:

success: function(json) {    $('.alert, .text-danger').remove();

Just below it add following code:

json['redirect']='index.php?route=checkout/cart';

Now open another file catalog\view\theme\ACTIVETHEME\template\product\product.tpl

Find following code:

<script type="text/javascript"><!-- $('#button-cart').on('click', function() {

Inside that find success method:

if (json['success']) {

Just below it add following code:

window.location.href='index.php?route=checkout/cart';

All is set now when someone add to cart then it directly redirect to cart page

Free Automated Testing and monitoring of Opencart functionalities and sites

We are showing how to do automated testing of opencart functionalities and keep on monitoring your sites and also freely available. Uptimerobot.com and ghostinspector.com are two websites that I am using right now which are great and free

How to set up https://uptimerobot.com in OpenCart?

Hi,

Thanks for registering Uptime Robot, the free website monitoring service.
In order to start monitoring your websites, please activate your account by clicking here.

Cheers From Uptime Robot,
  • Clicking the activation link, you will be taken to the Dashboard after login.
    opencart monitoring
  • Click Add New Monitor button
    Add monitoring on the Opencart
  • Choose Monitor Type as HTTPs, then enter your URL then click monitor by checking the alert contact.
  • You are all set to monitor your Opencart site.

Read More: A/B testing on Opencart with Google optimize for free

How to setup ghostinspector.com in Opencart?

With this setup, you will get automated End-to-end Testing, UI testing, Browser testing, Visual testing easily. So you can catch website bugs and regressions before they cost you.

  1. Add Ghost Inspector Extension: Simply install the extension in your Chrome or Firefox web browser. Click the toolbar icon on your website to start recording a test scenario.
  2. Record in your Browser: The extension records all your interactions. You can then set assertions that will be checked to determine if the test has passed
  3. Run Tests Continuously: Once saved, your browser tests can be run continuously on a schedule or triggered via their API. They track results and even compare screenshots.
  4. Set Custom Notifications: Get notified when tests fail via email or 3rd party integrations.

It checks UI like below:

Automate Test and flow Setup

The only limit is 100 tests for a month for free users, for my site it is ok as I just test 3 times a day so it reaches around 100 in a month.

Some pros and cons to consider are the following as I found online:

Pros

  • Low-Cost Tool
  • Browser Compatibility Testing
  • Choice of Language
  • Multiple Testing Frameworks
  • Easy to Integrate With Testing Ecosystem
  • Open for Enhancement
  • Test-Driven Development
  • Useful for Comprehensive Testing

Cons

  • Problems While Testing
  • Issues with finding Locators
  • Limitation in Browser Support
  • Manual Scripts Not Allowed
  • Slow Performance

Don’t try to automate everything in the OpenCart site but it is good to have some. Always be clear with your strategy what you are automating the test and it does not take too much time as we think but it will be beneficial in the long run as none like the down site and especially eCommerce sites where every second is money.

Similarly, another testing, has lots of features of automation testing, automated testing tools, automated web UI testing, automated browser testing so use it and you know issues before customers report it.

Enjoy your automated testing and monitoring of the Opencart website, let us know how you are monitoring your eCommerce website.

Change email send to the administrator of the opencart store when they get an order

This Opencart tutorial shows how to change and customize emails send out to the store administrator when they get the new order in the OpenCart store. Normally Opencart just sends an email with fewer details like below:

You have received an order.

Order ID: 1088
Date Added: 11/02/2019
Order Status: Complete

Products
1x .... $0.00

Order Totals
Sub-Total: $0.00
Total: $0.00

Let’s change that email to send full details like the one that customers get.

Change admin order alert email

Open catalog/controller/mail/order.php and remove the alert method and replace it with the below alert method.

// Admin Alert Mail
public function alert(&$route, &$args) {
    if (isset($args[0])) {
        $order_id = $args[0];
    } else {
        $order_id = 0;
    }
    
    if (isset($args[1])) {
        $order_status_id = $args[1];
    } else {
        $order_status_id = 0;
    }	
    
    if (isset($args[2])) {
        $comment = $args[2];
    } else {
        $comment = '';
    }
    
    if (isset($args[3])) {
        $notify = $args[3];
    } else {
        $notify = '';
    }

    $order_info = $this->model_checkout_order->getOrder($order_id);
    
    if ($order_info && !$order_info['order_status_id'] && $order_status_id && in_array('order', (array)$this->config->get('config_mail_alert'))) {	

        // Check for any downloadable products
    $download_status = false;

    $order_products = $this->model_checkout_order->getOrderProducts($order_info['order_id']);
    
    foreach ($order_products as $order_product) {
        // Check if there are any linked downloads
        $product_download_query = $this->db->query("SELECT COUNT(*) AS total FROM `" . DB_PREFIX . "product_to_download` WHERE product_id = '" . (int)$order_product['product_id'] . "'");

        if ($product_download_query->row['total']) {
            $download_status = true;
        }
    }
    
    // Load the language for any mails that might be required to be sent out
    $language = new Language($order_info['language_code']);
    $language->load($order_info['language_code']);
    $language->load('mail/order_add');
$this->load->language('mail/order_alert');

    // HTML Mail
    $data['title'] = sprintf($language->get('text_subject'), $order_info['store_name'], $order_info['order_id']);

    $data['text_greeting'] = sprintf($language->get('text_greeting'), $order_info['store_name']);
    $data['text_link'] = $language->get('text_link');
    $data['text_download'] = $language->get('text_download');
    $data['text_order_detail'] = $language->get('text_order_detail');
    $data['text_instruction'] = $language->get('text_instruction');
    $data['text_order_id'] = $language->get('text_order_id');
    $data['text_date_added'] = $language->get('text_date_added');
    $data['text_payment_method'] = $language->get('text_payment_method');
    $data['text_shipping_method'] = $language->get('text_shipping_method');
    $data['text_email'] = $language->get('text_email');
    $data['text_telephone'] = $language->get('text_telephone');
    $data['text_ip'] = $language->get('text_ip');
    $data['text_order_status'] = $language->get('text_order_status');
    $data['text_payment_address'] = $language->get('text_payment_address');
    $data['text_shipping_address'] = $language->get('text_shipping_address');
    $data['text_product'] = $language->get('text_product');
    $data['text_model'] = $language->get('text_model');
    $data['text_quantity'] = $language->get('text_quantity');
    $data['text_price'] = $language->get('text_price');
    $data['text_total'] = $language->get('text_total');
    $data['text_footer'] = $language->get('text_footer');

    $data['logo'] = $order_info['store_url'] . 'image/' . $this->config->get('config_logo');
    $data['store_name'] = $order_info['store_name'];
    $data['store_url'] = $order_info['store_url'];
    $data['customer_id'] = $order_info['customer_id'];
    $data['link'] = $order_info['store_url'] . 'index.php?route=account/order/info&order_id=' . $order_info['order_id'];

    if ($download_status) {
        $data['download'] = $order_info['store_url'] . 'index.php?route=account/download';
    } else {
        $data['download'] = '';
    }

    $data['order_id'] = $order_info['order_id'];
    $data['date_added'] = date($language->get('date_format_short'), strtotime($order_info['date_added']));
    $data['payment_method'] = $order_info['payment_method'];
    $data['shipping_method'] = $order_info['shipping_method'];
    $data['email'] = $order_info['email'];
    $data['telephone'] = $order_info['telephone'];
    $data['ip'] = $order_info['ip'];

    $order_status_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_status WHERE order_status_id = '" . (int)$order_status_id . "' AND language_id = '" . (int)$order_info['language_id'] . "'");

    if ($order_status_query->num_rows) {
        $data['order_status'] = $order_status_query->row['name'];
    } else {
        $data['order_status'] = '';
    }

    if ($comment && $notify) {
        $data['comment'] = nl2br($comment);
    } else {
        $data['comment'] = '';
    }

    if ($order_info['payment_address_format']) {
        $format = $order_info['payment_address_format'];
    } else {
        $format = '{firstname} {lastname}' . "\n" . '{company}' . "\n" . '{address_1}' . "\n" . '{address_2}' . "\n" . '{city} {postcode}' . "\n" . '{zone}' . "\n" . '{country}';
    }

    $find = array(
        '{firstname}',
        '{lastname}',
        '{company}',
        '{address_1}',
        '{address_2}',
        '{city}',
        '{postcode}',
        '{zone}',
        '{zone_code}',
        '{country}'
    );

    $replace = array(
        'firstname' => $order_info['payment_firstname'],
        'lastname'  => $order_info['payment_lastname'],
        'company'   => $order_info['payment_company'],
        'address_1' => $order_info['payment_address_1'],
        'address_2' => $order_info['payment_address_2'],
        'city'      => $order_info['payment_city'],
        'postcode'  => $order_info['payment_postcode'],
        'zone'      => $order_info['payment_zone'],
        'zone_code' => $order_info['payment_zone_code'],
        'country'   => $order_info['payment_country']
    );

    $data['payment_address'] = str_replace(array("\r\n", "\r", "\n"), '<br />', preg_replace(array("/\s\s+/", "/\r\r+/", "/\n\n+/"), '<br />', trim(str_replace($find, $replace, $format))));

    if ($order_info['shipping_address_format']) {
        $format = $order_info['shipping_address_format'];
    } else {
        $format = '{firstname} {lastname}' . "\n" . '{company}' . "\n" . '{address_1}' . "\n" . '{address_2}' . "\n" . '{city} {postcode}' . "\n" . '{zone}' . "\n" . '{country}';
    }

    $find = array(
        '{firstname}',
        '{lastname}',
        '{company}',
        '{address_1}',
        '{address_2}',
        '{city}',
        '{postcode}',
        '{zone}',
        '{zone_code}',
        '{country}'
    );

    $replace = array(
        'firstname' => $order_info['shipping_firstname'],
        'lastname'  => $order_info['shipping_lastname'],
        'company'   => $order_info['shipping_company'],
        'address_1' => $order_info['shipping_address_1'],
        'address_2' => $order_info['shipping_address_2'],
        'city'      => $order_info['shipping_city'],
        'postcode'  => $order_info['shipping_postcode'],
        'zone'      => $order_info['shipping_zone'],
        'zone_code' => $order_info['shipping_zone_code'],
        'country'   => $order_info['shipping_country']
    );

    $data['shipping_address'] = str_replace(array("\r\n", "\r", "\n"), '<br />', preg_replace(array("/\s\s+/", "/\r\r+/", "/\n\n+/"), '<br />', trim(str_replace($find, $replace, $format))));

    $this->load->model('tool/upload');

    // Products
    $data['products'] = array();

    foreach ($order_products as $order_product) {
        $option_data = array();

        $order_options = $this->model_checkout_order->getOrderOptions($order_info['order_id'], $order_product['order_product_id']);

        foreach ($order_options as $order_option) {
            if ($order_option['type'] != 'file') {
                $value = $order_option['value'];
            } else {
                $upload_info = $this->model_tool_upload->getUploadByCode($order_option['value']);

                if ($upload_info) {
                    $value = $upload_info['name'];
                } else {
                    $value = '';
                }
            }

            $option_data[] = array(
                'name'  => $order_option['name'],
                'value' => (utf8_strlen($value) > 20 ? utf8_substr($value, 0, 20) . '..' : $value)
            );
        }

        $data['products'][] = array(
            'name'     => $order_product['name'],
            'model'    => $order_product['model'],
            'option'   => $option_data,
            'quantity' => $order_product['quantity'],
            'price'    => $this->currency->format($order_product['price'] + ($this->config->get('config_tax') ? $order_product['tax'] : 0), $order_info['currency_code'], $order_info['currency_value']),
            'total'    => $this->currency->format($order_product['total'] + ($this->config->get('config_tax') ? ($order_product['tax'] * $order_product['quantity']) : 0), $order_info['currency_code'], $order_info['currency_value'])
        );
    }

    // Vouchers
    $data['vouchers'] = array();

    $order_vouchers = $this->model_checkout_order->getOrderVouchers($order_info['order_id']);

    foreach ($order_vouchers as $order_voucher) {
        $data['vouchers'][] = array(
            'description' => $order_voucher['description'],
            'amount'      => $this->currency->format($order_voucher['amount'], $order_info['currency_code'], $order_info['currency_value']),
        );
    }

    // Order Totals
    $data['totals'] = array();
    
    $order_totals = $this->model_checkout_order->getOrderTotals($order_info['order_id']);

    foreach ($order_totals as $order_total) {
        $data['totals'][] = array(
            'title' => $order_total['title'],
            'text'  => $this->currency->format($order_total['value'], $order_info['currency_code'], $order_info['currency_value']),
        );
    }

    $this->load->model('setting/setting');
    
    $from = $this->model_setting_setting->getSettingValue('config_email', $order_info['store_id']);
    
    if (!$from) {
        $from = $this->config->get('config_email');
    }


        $mail = new Mail($this->config->get('config_mail_engine'));
        $mail->parameter = $this->config->get('config_mail_parameter');
        $mail->smtp_hostname = $this->config->get('config_mail_smtp_hostname');
        $mail->smtp_username = $this->config->get('config_mail_smtp_username');
        $mail->smtp_password = html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8');
        $mail->smtp_port = $this->config->get('config_mail_smtp_port');
        $mail->smtp_timeout = $this->config->get('config_mail_smtp_timeout');

        $mail->setTo($this->config->get('config_email'));
        $mail->setFrom($this->config->get('config_email'));
        $mail->setSender(html_entity_decode($order_info['store_name'], ENT_QUOTES, 'UTF-8'));
        $mail->setSubject(html_entity_decode(sprintf($this->language->get('text_subject'), $this->config->get('config_name'), $order_info['order_id']), ENT_QUOTES, 'UTF-8'));
        $mail->setHtml($this->load->view('mail/order_alert', $data));
        $mail->send();

        // Send to additional alert emails
        $emails = explode(',', $this->config->get('config_mail_alert_email'));

        foreach ($emails as $email) {
            if ($email && filter_var($email, FILTER_VALIDATE_EMAIL)) {
                $mail->setTo($email);
                $mail->send();
            }
        }
    }
}

Then go to catalog/view/theme/YOUR_THEME/template/mail/order_mail.twig and remove all the code and replace with the following codes:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>{{ title }}</title>
</head>
<body style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #000000;">
<div style="width: 680px;"><a href="{{ store_url }}" title="{{ store_name }}"><img src="{{ logo }}" alt="{{ store_name }}" style="margin-bottom: 20px; border: none;" /></a>
  <p style="margin-top: 0px; margin-bottom: 20px;">{{ text_greeting }}</p>
  
  {% if download %}
  <p style="margin-top: 0px; margin-bottom: 20px;">{{ text_download }}</p>
  <p style="margin-top: 0px; margin-bottom: 20px;"><a href="{{ download }}">{{ download }}</a></p>
  <{% endif %}
  <table style="border-collapse: collapse; width: 100%; border-top: 1px solid #DDDDDD; border-left: 1px solid #DDDDDD; margin-bottom: 20px;">
    <thead>
      <tr>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: left; padding: 7px; color: #222222;" colspan="2">{{ text_order_detail }}</td>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;"><b>{{ text_order_id }}</b> {{ order_id }}<br />
          <b>{{ text_date_added }}</b> {{ date_added }}<br />
          <b>{{ text_payment_method }}</b> {{ payment_method }}<br />
          {% if shipping_method %} <b>{{ text_shipping_method }}</b> {{ shipping_method }}
          {% endif %}</td>
        <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;"><b>{{ text_email }}</b> {{ email }}<br />
          <b>{{ text_telephone }}</b> {{ telephone }}<br />
          <b>{{ text_ip }}</b> {{ ip }}<br />
          <b>{{ text_order_status }}</b> {{ order_status }}<br /></td>
      </tr>
    </tbody>
  </table>
  {% if comment %}
  <table style="border-collapse: collapse; width: 100%; border-top: 1px solid #DDDDDD; border-left: 1px solid #DDDDDD; margin-bottom: 20px;">
    <thead>
      <tr>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: left; padding: 7px; color: #222222;">{{ text_instruction }}</td>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;">{{ comment }}</td>
      </tr>
    </tbody>
  </table>
  {% endif %}
  <table style="border-collapse: collapse; width: 100%; border-top: 1px solid #DDDDDD; border-left: 1px solid #DDDDDD; margin-bottom: 20px;">
    <thead>
      <tr>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: left; padding: 7px; color: #222222;">{{ text_payment_address }}</td>
        {% if shipping_address %}
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: left; padding: 7px; color: #222222;">{{ text_shipping_address }}</td>
        {% endif %} </tr>
    </thead>
    <tbody>
      <tr>
        <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;">{{ payment_address }}</td>
        {% if shipping_address %}
        <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;">{{ shipping_address }}</td>
        {% endif %} </tr>
    </tbody>
  </table>
  <table style="border-collapse: collapse; width: 100%; border-top: 1px solid #DDDDDD; border-left: 1px solid #DDDDDD; margin-bottom: 20px;">
    <thead>
      <tr>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: left; padding: 7px; color: #222222;">{{ text_product }}</td>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: left; padding: 7px; color: #222222;">{{ text_model }}</td>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: right; padding: 7px; color: #222222;">{{ text_quantity }}</td>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: right; padding: 7px; color: #222222;">{{ text_price }}</td>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: right; padding: 7px; color: #222222;">{{ text_total }}</td>
      </tr>
    </thead>
    <tbody>
    
    {% for product in products %}
    <tr>
      <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;">{{ product.name }}
        {% for option in product.option %}<br />
         <small> - {{ option.name }}: {{ option.value }}</small>{% endfor %}</td>
      <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;">{{ product.model }}</td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">{{ product.quantity }}</td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">{{ product.price }}</td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">{{ product.total }}</td>
    </tr>
    {% endfor %}
    {% for voucher in vouchers %}
    <tr>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;">{{ voucher.description }}</td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;"></td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">1</td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">{{ voucher.amount }}</td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">{{ voucher.amount }}</td>
    </tr>
    {% endfor %}
      </tbody>
    
    <tfoot>
    
    {% for total in totals %}
    <tr>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;" colspan="4"><b>{{ total.title }}:</b></td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">{{ total.text }}</td>
    </tr>
    {% endfor %}
      </tfoot>
    
  </table>
  <p style="margin-top: 0px; margin-bottom: 20px;">{{ text_footer }}</p>
</div>
</body>
</html>

With these changes, you can get the customized full detail email for Admin as well.

If you want to change the email design for the affiliate alert, affiliate welcome email, forgotten password email, order notification to the customer, order alert to store administrator, edit order alert, register alert, register notification to the customer, transaction alert, voucher alert, you can change them at catalog/view/theme/YOUR_TEME/template/mail where you can change your design as per your need.

Let us know if you find any difficulties or need any help from us. Likewise, you can see other Opencart tips and tricks.

How can we remove index.php?route= in OpenCart for contact, home and other

This simple Opencart OCMod file will remove the index.php?route= in Opencart and shorten the URL of OpenCart for contact us page, common home, checkout, cart, voucher, account, log in, manufacturer, affiliate login, password forget URL, and others.

Once you download the above, you will get seo-url.ocmod_.zip extract it and rename it to seo-url.ocmod.zip, then go to admin >> Extensions >> Installer then upload the seo-url.ocmod.zip. Then download the following SEO-URL.sql

Once you download the above you will get seo-url-add.sql_.zip, extract it, you will get seo-url-add.sql. Then go to admin >> System >> Maintenance >> Backup & Restore, and click the Restore tab and click Import, and select seo-url-add.sql.

Backp and Restore Opencart

Once this is successful then go to admin >> Extensions >> Modifications >> then click refresh buttone

Modifications lists of extension Opencart

Then you are all set.

If you are still seeing issues then check if you complete all of the below:

  • Don’t forget to refresh your modifications.
  • Your SEO URL need to be active
  • If you are running your store in sub-folder then don’t forget to add it in .htaccess.

Read more: 25 SEO best practices for Opencart 3 with 3 free SEO Opencart 3 module

For those who are developer:

The developer can do the following to make more changes as needed. Open catalog/controller/startup/seo_url.php and in the public function rewrite($link) method add below code after parse_str($url_info[‘query’], $data);

if ($data['route'] == 'common/home'){
    $url .= '/';
}
if ($data['route'] == 'information/contact'){
    $url .= '/contact';
}
if ($data['route'] == 'account/return/add'){
    $url .= '/returnadd';
}
if ($data['route'] == 'information/sitemap'){
    $url .= '/sitemap';
}
if ($data['route'] == 'product/manufacturer'){
    $url .= '/manufacturer';
}
if ($data['route'] == 'account/voucher'){
    $url .= '/voucher';
}
if ($data['route'] == 'affiliate/login'){
    $url .= '/affiliatelogin';
}
if ($data['route'] == 'product/special'){
    $url .= '/special';
}
if ($data['route'] == 'account/login'){
    $url .= '/login';
}
if ($data['route'] == 'checkout/cart'){
    $url .= '/cart';
}

Add as many URLs as you want in here and it’s rewrite URL. Then go to admin >> Design >> SEO URL and add them each except for the home page. Like for contact us page

SEO URL opencart

So you need to insert for all, then you will see the changes or you can directly import the following seo-url.sql file at admin >> System >> Maintenance >> Backup/Restore. Download it. Check the database table prefix if it is different than oc_ if yes then need to change in the SQL file.

Or run the following SQL in your database

INSERT INTO `oc_seo_url` (`seo_url_id`, `store_id`, `language_id`, `query`, `keyword`) VALUES (NULL, '0', '1', 'checkout/cart', 'cart');
INSERT INTO `oc_seo_url` (`seo_url_id`, `store_id`, `language_id`, `query`, `keyword`) VALUES (NULL, '0', '1', 'account/login', 'login');
INSERT INTO `oc_seo_url` (`seo_url_id`, `store_id`, `language_id`, `query`, `keyword`) VALUES (NULL, '0', '1', 'affiliate/login', 'affiliatelogin');
INSERT INTO `oc_seo_url` (`seo_url_id`, `store_id`, `language_id`, `query`, `keyword`) VALUES (NULL, '0', '1', 'account/voucher', 'voucher');
INSERT INTO `oc_seo_url` (`seo_url_id`, `store_id`, `language_id`, `query`, `keyword`) VALUES (NULL, '0', '1', 'product/manufacturer', 'manufacturer');
INSERT INTO `oc_seo_url` (`seo_url_id`, `store_id`, `language_id`, `query`, `keyword`) VALUES (NULL, '0', '1', 'information/sitemap', 'sitemap');
INSERT INTO `oc_seo_url` (`seo_url_id`, `store_id`, `language_id`, `query`, `keyword`) VALUES (NULL, '0', '1', 'account/return/add', 'returnadd');
INSERT INTO `oc_seo_url` (`seo_url_id`, `store_id`, `language_id`, `query`, `keyword`) VALUES (NULL, '0', '1', 'information/contact', 'contact');
INSERT INTO `oc_seo_url` (`seo_url_id`, `store_id`, `language_id`, `query`, `keyword`) VALUES (NULL, '0', '1', 'checkout/checkout', 'checkout');
INSERT INTO `oc_seo_url` (`seo_url_id`, `store_id`, `language_id`, `query`, `keyword`) VALUES (NULL, '0', '1', 'product/special', 'special');

You can add other URLs as per your need. You can keep on customizing and let us know tips and tricks to improve it.

In this way, you can improve your URL and be SEO-friendly in Opencart. Let us know if need any support. Please subscribe to our YouTube Channel for Opencart video tutorials and get lots of other Opencart free modules. You can also find us on Twitter and Facebook.