Page 1 of 3
OC 3.0.x Events System: How to modify twig template file?
Posted: Fri Dec 11, 2020 8:55 pm
by JNeuhoff
It can be done with a before-event handler, though it's a bit convoluted:
Code: Select all
// event handler for admin/view/catalog/product_form/before
public function eventViewCatalogProductFormBefore( &$route, &$data, &$template_code=null ) {
$template_buffer = $this->getTemplateBuffer( $route, $template_code );
$search = '{% if customer_group.customer_group_id == product_special.customer_group_id %}';
$replace = '{% if customer_group.customer_group_id == product_special.customer_group_id and some_new_variable_equal_true %}';
$template_buffer = str_replace( $search, $replace, $template_buffer );
$template_code = $template_buffer;
return null;
}
// return template file contents as a string
protected function getTemplateBuffer( $route, $event_template_buffer ) {
// if there already is a modified template from view/*/before events use that one
if ($event_template_buffer) {
return $event_template_buffer;
}
// load the template file (possibly modified by ocmod and vqmod) into a string buffer
if ($this->isAdmin()) {
$dir_template = DIR_TEMPLATE;
} else {
if ($this->config->get('config_theme') == 'default') {
$theme = $this->config->get('theme_default_directory');
} else {
$theme = $this->config->get('config_theme');
}
$dir_template = DIR_TEMPLATE . $theme . '/template/';
}
$template_file = $dir_template . $route . '.twig';
if (file_exists( $template_file ) && is_file( $template_file )) {
$template_file = $this->modCheck( $template_file );
return file_get_contents( $template_file );
}
if ($this->isAdmin()) {
trigger_error("Cannot find template file for route '$route'");
exit;
}
$dir_template = DIR_TEMPLATE . 'default/template/';
$template_file = $dir_template . $route . '.twig';
if (file_exists( $template_file ) && is_file( $template_file )) {
$template_file = $this->modCheck( $template_file );
return file_get_contents( $template_file );
}
trigger_error("Cannot find template file for route '$route'");
exit;
}
protected function isAdmin() {
return defined( 'DIR_CATALOG' ) ? true : false;
}
protected function modCheck( $file ) {
// return a PHP file possibly modified by OpenCart's system/storage/modification,
// and then possibly modified by vqmod (see also https://github.com/vqmod/vqmod)
// Use OpenCart's modified file is available
$original_file = $file;
if (defined('DIR_MODIFICATION')) {
if ($this->startsWith($file,DIR_APPLICATION)) {
if ($this->isAdmin()) {
if (file_exists( DIR_MODIFICATION . 'admin/' . substr($file,strlen(DIR_APPLICATION)) )) {
$file = DIR_MODIFICATION . 'admin/' . substr($file,strlen(DIR_APPLICATION));
}
} else {
if (file_exists( DIR_MODIFICATION . 'catalog/' . substr($file,strlen(DIR_APPLICATION)) )) {
$file = DIR_MODIFICATION . 'catalog/' . substr($file,strlen(DIR_APPLICATION));
}
}
} else if ($this->startsWith($file,DIR_SYSTEM)) {
if (file_exists( DIR_MODIFICATION . 'system/' . substr($file,strlen(DIR_SYSTEM)) )) {
$file = DIR_MODIFICATION . 'system/' . substr($file,strlen(DIR_SYSTEM));
}
}
}
// Don't use VQmod 2.3.2 or earlier if available
if (array_key_exists('vqmod', get_defined_vars())) {
trigger_error( "You are using an old VQMod version '2.3.2' or earlier, please upgrade your VQMod!" );
exit;
}
// Use modification through VQmod 2.4.0 or later if available
if (class_exists('VQMod',false)) {
if (VQMod::$directorySeparator) {
if (strpos($file,'vq2-')!==FALSE) {
return $file;
}
if (version_compare(VQMod::$_vqversion,'2.5.0','<')) {
trigger_error( "You are using an old VQMod version '".VQMod::$_vqversion."', please upgrade your VQMod!" );
exit;
}
if ($original_file != $file) {
return VQMod::modCheck($file,$original_file);
}
return VQMod::modCheck($original_file);
}
}
// no VQmod
return $file;
}
protected function startsWith( $haystack, $needle ) {
if (strlen( $haystack ) < strlen( $needle )) {
return false;
}
return (substr( $haystack, 0, strlen($needle) ) == $needle);
}
The basic idea is to use a simple
str_replace call in the event handler.
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Fri Dec 11, 2020 9:40 pm
by straightlight
Interesting ... all lookups done together ...

Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Fri Dec 11, 2020 9:49 pm
by JNeuhoff
It would be good to have the getTemplateBuffer function available in e.g. the system/library/template.php, this way it can be used in view/*/before event handlers, without having to redefine it each time.
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Fri Dec 11, 2020 9:56 pm
by straightlight
JNeuhoff wrote: ↑Fri Dec 11, 2020 9:49 pm
It would be good to have the
getTemplateBuffer function available in e.g. the
system/library/template.php, this way it can be used in view/*/before event handlers, without having to redefine it each time.
You could submit a pull request about it.
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Fri Dec 11, 2020 10:06 pm
by straightlight
As for $this->startsWith, I am not sure where that one originates from.
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Fri Dec 11, 2020 10:49 pm
by JNeuhoff
straightlight wrote: ↑Fri Dec 11, 2020 10:06 pm
As for $this->startsWith, I am not sure where that one originates from.
OK, added that one now, too.
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Fri Dec 11, 2020 10:50 pm
by straightlight
Perhaps this line:
should be replaced with:
Code: Select all
if (array_key_exists('vqmod', get_defined_vars())) {
since $GLOBALS is not safe to be used:
https://stackoverflow.com/a/41982330 .
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Fri Dec 11, 2020 11:56 pm
by JNeuhoff
You are right, now updated.
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Sat Dec 12, 2020 1:05 am
by madimar
Great guys! I was sure someone of you could be so kind to give his valuable opinion and suggestion. I'll try to arrange a first simple "modification" via event soon and, why not, I'll post a full example here.
Regards,
M
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Sun Dec 13, 2020 12:18 am
by madimar
Hi, here I am again, as promised, trying to arrange a simple mod as exercize. Things begin to work, thanks to your suggestions, even if I'm still facing some difficulties. Template part works perfectly, thanks to JNeuhoff suggestions. Now I'm trying to understand who to modify properly controller and Model.
Let me sum up my exercize full goal: To add some fields in admin Customer Group in order to be able to decide if to show Company field or not in registration form. So besides, template modification, I need to get and update 2 new fields I added in oc_customer_group table.
This is current full code:
Code: Select all
<?php
class ControllerExtensionModuleOcTest extends Controller {
private $codename = 'oc_test';
private $config_file = 'oc_test';
public function install() {
$this->load->model('extension/oc_module/oc_test');
$this->model_extension_oc_module_oc_test->install();
$this->load->model('setting/event');
// List of events
$this->model_setting_event->addEvent($this->codename, 'admin/view/customer/customer_group_form/before', 'extension/module/oc_test/eventViewCustomerGroupFormBefore');
$this->model_setting_event->addEvent($this->codename, 'admin/model/customer/customer_group/editCustomerGroup/after', 'extension/module/oc_test/eventModelCustomerGroupAddEditAfter');
$this->model_setting_event->addEvent($this->codename, 'admin/model/customer/customer_group/addCustomerGroup/after', 'extension/module/oc_test/eventModelCustomerGroupAddEditAfter');
}
public function uninstall() {
$this->load->model('extension/oc_module/oc_test');
$this->model_extension_oc_module_oc_test->uninstall();
$this->load->model('setting/event');
$this->model_setting_event->deleteEventByCode($this->codename);
}
// event handler for admin/view/customer/customer_group_form/before
public function eventViewCustomerGroupFormBefore( &$route, &$data, &$template_code=null ) {
$this->load->language('extension/oc_module/oc_test');
$this->load->model('localisation/language');
// Entry
$data['entry_company_show'] = $this->language->get('entry_company_show');
$data['entry_company_oblige'] = $this->language->get('entry_company_oblige');
// Help
$data['help_company_show'] = $this->language->get('help_company_show');
$data['help_company_oblige'] = $this->language->get('help_company_oblige');
$this->load->model('customer/customer_group');
if (isset($this->request->get['customer_group_id']) && ($this->request->server['REQUEST_METHOD'] != 'POST')) {
$customer_group_info = $this->model_customer_customer_group->getCustomerGroup($this->request->get['customer_group_id']);
}
if (isset($this->request->post['company_show'])) {
$data['company_show'] = $this->request->post['company_show'];
} elseif (!empty($customer_group_info)) {
$data['company_show'] = $customer_group_info['company_show'];
} else {
$data['company_show'] = '';
}
if (isset($this->request->post['company_oblige'])) {
$data['company_oblige'] = $this->request->post['company_oblige'];
} elseif (!empty($customer_group_info)) {
$data['company_oblige'] = $customer_group_info['company_oblige'];
} else {
$data['company_oblige'] = '';
}
$template_buffer = $this->getTemplateBuffer( $route, $template_code );
$search = ' <div class="form-group">
<label class="col-sm-2 control-label" for="input-sort-order">{{ entry_sort_order }}</label>';
$replace = ' <div class="form-group">
<label class="col-sm-2 control-label"><span data-toggle="tooltip" title="{{ help_company_view }}">{{ entry_company_view }}</span></label>
<div class="col-sm-10">
<label class="radio-inline">
{% if company_view %}
<input type="radio" name="company_view" value="1" checked="checked" />
{{ text_yes }}
{% else %}
<input type="radio" name="company_view" value="1" />
{{ text_yes }}
{% endif %}
</label>
<label class="radio-inline">
{% if not company_view %}
<input type="radio" name="company_view" value="0" checked="checked" />
{{ text_no }}
{% else %}
<input type="radio" name="company_view" value="0" />
{{ text_no }}
{% endif %}
</label>
</div>
<label class="col-sm-2 control-label"><span data-toggle="tooltip" title="{{ help_company_oblige }}">{{ entry_company_oblige }}</span></label>
<div class="col-sm-10">
<label class="radio-inline">
{% if company_oblige %}
<input type="radio" name="company_oblige" value="1" checked="checked" />
{{ text_yes }}
{% else %}
<input type="radio" name="company_oblige" value="1" />
{{ text_yes }}
{% endif %}
</label>
<label class="radio-inline">
{% if not company_oblige %}
<input type="radio" name="company_oblige" value="0" checked="checked" />
{{ text_no }}
{% else %}
<input type="radio" name="company_oblige" value="0" />
{{ text_no }}
{% endif %}
</label>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="input-sort-order">{{ entry_sort_order }}</label>';
$template_buffer = str_replace( $search, $replace, $template_buffer );
$template_code = $template_buffer;
return null;
}
// event handler for admin/model/customer/customer_group/edit/after
public function eventModelCustomerGroupAddEditAfter(&$route, &$data, &$template_code=null ) {
$this->db->query("UPDATE " . DB_PREFIX . "customer_group SET company_show = '" . (int)$data['1']['company_show'] . "', company_oblige = '" . (int)$data['1']['company_oblige'] . "' WHERE customer_group_id = '" . (int)$data['0'] . "'");
return null;
}
Actually new fields are shown, but I can get values from db and neither to update them. What am I wrong?
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Thu Dec 17, 2020 12:35 am
by OSWorX
madimar wrote: ↑Sun Dec 13, 2020 12:18 am
Actually new fields are shown, but I can get values from db and neither to update them. What am I wrong?
Usually an
event is called like this:
Code: Select all
public function eventModelCustomerGroupAddEditAfter(&$route, &$data [, &$output]) { .. }
(
$output is used only if the event is called with
after not with before)
which means, if you call it
Code: Select all
public function eventModelCustomerGroupAddEditAfter($data)
$data is the string
$route and therefore no data here ..
Re: OpenCart Events
Posted: Thu Dec 17, 2020 6:48 pm
by JNeuhoff
Try this, the event handlers require certain arguments:
Code: Select all
// event handler for admin/controller/customer/customer_group/edit/before
public function eventControllerCustomerGroupAddEditBefore($route,&$data) {
// ........
}
// event handler for admin/model/customer/customer_group/edit/after
public function eventModelCustomerGroupAddEditAfter(&$route,&$data,&$output) {
// ........
}
Re: OpenCart Events
Posted: Thu Dec 17, 2020 7:12 pm
by OSWorX
JNeuhoff wrote: ↑Thu Dec 17, 2020 6:48 pm
Try this, the event handlers require certain arguments
Just what I wrote above ..
Re: OpenCart Events > missing code fragment
Posted: Thu Dec 17, 2020 7:17 pm
by OSWorX
Just a short update to Juergens code.
Inside that, he use the variable:
$template_engine
But it is never defined which will lead to troubles (1) and (2) code is not useable if you use it for OpenCart 2.x
Therefore add following:
Code: Select all
// get engine type, OC >= 3.x has template_engine
if( !$template_engine = $this->config->get( 'template_engine' ) ) {
$template_engine = 'tpl';
}
and replace
Code: Select all
$template_file = $dir_template . $route . '.twig';
with:
Code: Select all
$template_file = $dir_template . $route . ' . template_engine ;
Maybe Juergen does it not this way ..
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Thu Dec 17, 2020 7:39 pm
by JNeuhoff
Inside that, he use the variable: $template_engine
But it is never defined which will lead to troubles (1) and (2) code is not useable if you use it for OpenCart 2.x
Well spotted, I have now updated my sample code for OC 3.0.x.
Personally, I tend to write my own event handlers for views to support both twig and PHP templates because I often use the
Template Switcher on OC 3.0.x sites.
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Thu Dec 17, 2020 8:01 pm
by OSWorX
JNeuhoff wrote: ↑Thu Dec 17, 2020 7:39 pm
Inside that, he use the variable: $template_engine
But it is never defined which will lead to troubles (1) and (2) code is not useable if you use it for OpenCart 2.x
Well spotted, I have now updated my sample code for OC 3.0.x.
Personally, I tend to write my own event handlers for views to support both twig and PHP templates because I often use the
Template Switcher on OC 3.0.x sites.
Well okay, but the less extensions are used, the more I like it.
And here there are only 3 lines of code, instead of a "full extension" or what else ..
And not to forget, your Template Switcher is only for OC 3.x - so if someone use the above code inside OC 2.x > he is lost.
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Thu Dec 17, 2020 10:39 pm
by straightlight
@JNeuhoff: OSWorX addresses a good point here. If we want to encourage forum users to use the Events engine from the core, then additional extension Engines should not be imported in the validations but rather to validate the Events as stand-alone.
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Mon Dec 21, 2020 1:53 am
by madimar
Thanks again for suggestions, I edited my code above, and now thigns generally work. Regarding event "model...after", to write additional data to db, it was actually easiest thanks to your suggestions.
On the other side I've had more difficulties for the "get" part and I'm not sure what I made is the best way to achieve the result. What I don't like to much it is to need to perform an additional getCustomerGroup before view in order to have all data.
What do you think about that? Is there another more elegant/efficent way to achieve the same result?
Thanks in advance, regards,
M
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Mon Dec 21, 2020 8:40 am
by straightlight
madimar wrote: ↑Mon Dec 21, 2020 1:53 am
Thanks again for suggestions, I edited my code above, and now thigns generally work. Regarding event "model...after", to write additional data to db, it was actually easiest thanks to your suggestions.
On the other side I've had more difficulties for the "get" part and I'm not sure what I made is the best way to achieve the result. What I don't like to much it is to need to perform an additional getCustomerGroup before view in order to have all data.
What do you think about that? Is there another more elegant/efficent way to achieve the same result?
Thanks in advance, regards,
M
Directly into the install.xml file to search for lines and alter them.
Re: OC 3.0.x Events System: How to modify twig template file?
Posted: Tue Dec 22, 2020 2:04 am
by madimar
straightlight wrote: ↑Mon Dec 21, 2020 8:40 am
Directly into the install.xml file to search for lines and alter them.
DO YOU MEAN OCMOD ?!?