Post by Jsf » Fri May 24, 2019 8:43 pm

Hello,

OpenCart Events systems (https://github.com/opencart/opencart/wiki/Events-System) looks interesting, but I has a question:
How to edit twig file without ocmod/vqmod? For example I need to replace one line in product_form.twig:

Code: Select all

{% if customer_group.customer_group_id == product_special.customer_group_id %}
to

Code: Select all

{% if customer_group.customer_group_id == product_special.customer_group_id and some_new_variable_equal_true %}
Please give a hint how can I do it.

User avatar
Jsf
New member

Posts

Joined
Sun Jan 26, 2014 4:08 am

Post by D3MO » Fri May 24, 2019 10:36 pm

without ocmod you can edit it either in theme editor or directly in ftp no other way

Opencart Expert | voldemaras@gmail.com
Skype - programanija | Gtalk - voldemaras@gmail.com
Extensions for Opencart @ https://www.opencartextensions.eu / or Opencart Marketplace

Need Custom Module? debug third party module or simply have any question related to Opencart? feel free to contact directly for a live chat session:) - INSTANT LIVE CHAT


User avatar
Active Member

Posts

Joined
Mon Apr 04, 2011 6:57 am

Post by diegospm » Sat May 25, 2019 5:31 am

Jsf wrote:
Fri May 24, 2019 8:43 pm
Hello,

OpenCart Events systems (https://github.com/opencart/opencart/wiki/Events-System) looks interesting, but I has a question:
How to edit twig file without ocmod/vqmod? For example I need to replace one line in product_form.twig:

Code: Select all

{% if customer_group.customer_group_id == product_special.customer_group_id %}
to

Code: Select all

{% if customer_group.customer_group_id == product_special.customer_group_id and some_new_variable_equal_true %}
Please give a hint how can I do it.
Just like @D3MO has specified, to change this line you can do in the OC native theme editor since version 3.0. But I do not recommend doing the editing with FTP or another remote method, because you will have to make backups locally of the files if you want to recover the last version or the original.

If you really need the event, you need to add a controller file and add an event trigger before into the class of that file. In the class that will receive the event you need to change the array key that you want to change in the twig file.

After that, you need to create a twig file that will receive the new render and then edit as needed.

Events are a milestone in the OC, but it's a not-so-clear subject yet and in my point of view, editing the twig file could has edited directly (without going through the controller). But there must be a good reason to be so, the devs/managers of the OC are incredible in designing the tools for platform.

Newbie

Posts

Joined
Thu Apr 18, 2019 8:49 am

Post by grgr » Sat May 25, 2019 11:35 am

Not sure you can even do that. One way to do it though would be to replace the template product_form.twig with your own template file (my_product_form.twig) with the changes you want in it.

First, add an event; normally do this this by the install function of a module but can be done directly in phpMyadmin
In module:

Code: Select all

        $this->model_setting_event->addEvent('change_product_form', 'admin/view/catalog/product_form/before', 'extension/module/my_module/changeProductFormTemplate');
By phpMyAdmin (change db name)

Code: Select all

INSERT INTO `3032`.`oc_event` (`event_id` ,`code` ,`trigger` ,`action` ,`status` ,`sort_order`) VALUES (NULL , 'change_product_form', 'admin/view/catalog/product_form/before', 'extension/module/my_module/changeProductFormTemplate', '1', '1');
Create the module file ..admin/controller/extension/module/my_module.php and put in the following code:

Code: Select all

<?php
class ControllerExtensionModuleMyModule extends Controller {
/*	
Name: 		change_product_form
Trigger:	admin/view/catalog/product_form/before
Action:		extension/module/my_module/changeProductFormTemplate
Order:		1
Purpose:	Change the product_form.twig template to my_product_form.twig template.
*/
	public function changeProductFormTemplate(&$route, &$data) {
		$route = str_replace('catalog/product_form', 'catalog/my_product_form', $route);
	}
}
Create your new template file: admin/view/template/catalog/my_product_form.twig

-
Image Image Image Image
VIEW ALL EXTENSIONS * EXTENSION SUPPORT * WEBSITE * CUSTOM REQUESTS


User avatar
Active Member

Posts

Joined
Mon Mar 28, 2011 4:08 pm
Location - UK

Post by Jsf » Sat May 25, 2019 2:48 pm

Thank you for replies. All mentioned methods not very good looking forward because unexpected problems with other modules may occur. Events is good when you need to add something new or replace data array in controller. But as I understand to make small replaces in template files still best way with ocmod.

User avatar
Jsf
New member

Posts

Joined
Sun Jan 26, 2014 4:08 am

Post by softvision » Sun Nov 08, 2020 8:39 pm

Hi all
Even this topic isn't that new and quiet well discussed til the near end, I would like to share some thoughts for people like me, using OpenCart since a week. I had a hart time too, figuring out all these caches and override mechanism in OC3. Any hints about cash-refresh I will leave aside, as they have been discussed alot already.

I saw, that installing Modifications are mainly XML-Files with some add/replace actions, stored in mySQL-Table dbPrefix_modification (as dbPrefix depends your installation). If ever the built-in OC-ThemeEditor is used to modify themes, it will create a copy of the source code of the current template file (by example: products.twig) and potential mods, affection the same .twig, then store it in the mySQL-Tabl dbPrefix_theme. From that moment on, changes made on products.twig will not have anymore effect, as OC will only use the content from the _theme-Table. With other words, any changes in Modifications and .twigg source files will not have anymore effect.

Solution 1:
Don't use the built in OC Theme editor at all and make changes in the source files (with the disvantage, that updates will become a headache).

Solution 2:
After making changes on a source-File (like products.twig) or after installing a mod, that includes changes on a .twig, you need to reset the .twig by using the OC built-in theme editor, so the .twig will be generated again from the current source files and mods and stored in the database. But then, possible earlier changes on the .twig made by the built-in editor will be lost and need to be implemented again.

Personal conclusion:
As I prefer coding direct in the .php and .twig with some external editors using FTP to update the files, I prefer not using the OC built in editor at all. All changes I have made to this point I will remove from dbPrefix_theme. So any Mods and changes made in the source will take effect (after the cache's have been refreshed).

Newbie

Posts

Joined
Tue Nov 03, 2020 9:09 am

Post by madimar » Fri Dec 11, 2020 4:06 pm

Hi all, I think this topic is really interesting with relation to the idea to abandon OCMOD/VQMOD and use only Events System, as suggested by main developers.
I'm approaching Event Systems too, with some difficulties, all the guides on the net are very simple and without examples.
It could be good to have some real useful examples, expecially to modify twig template, etc.
As far as I saw, it is possible using some HTML DOM and referencing to it for add extra code in specific position. In this way original template files are preserved and Events System logic and tidiness is preserved too. Said that, if any expert could help us providing some simple full samples, I think it could be really helpful for all.

Regards,

M

-----------------------------------------------------------------------
My last mods: Partita IVA e CF | Pro EU VAT Number | Sales Agents | Pricelist Pro
-----------------------------------------------------------------------


User avatar
Active Member

Posts

Joined
Thu Sep 24, 2009 6:27 pm


Post by grgr » Fri Dec 11, 2020 7:58 pm

You can do a find a replace as well :

Code: Select all

		$find = '<div class="tab-pane" id="tab-reward">';
	
		$replace = '<div class="tab-pane" id="tab-product">
             			<fieldset>
                			<legend>'. $this->language->get('text_products_bought') .'</legend>
                			<div id="products"></div>
             		 </fieldset>
            		</div>
			<div class="tab-pane" id="tab-reward">';
		
		$output = str_replace($find, $replace, $output);
-

-
Image Image Image Image
VIEW ALL EXTENSIONS * EXTENSION SUPPORT * WEBSITE * CUSTOM REQUESTS


User avatar
Active Member

Posts

Joined
Mon Mar 28, 2011 4:08 pm
Location - UK

Post by straightlight » Fri Dec 11, 2020 8:10 pm

Hi all, I think this topic is really interesting with relation to the idea to abandon OCMOD/VQMOD and use only Events System, as suggested by main developers.
Definitely!

Dedication and passion goes to those who are able to push and merge a project.

Regards,
Straightlight
Programmer / Opencart Tester


Legendary Member

Posts

Joined
Mon Nov 14, 2011 11:38 pm
Location - Canada, ON

Post by qahar » Sat Jan 09, 2021 7:21 pm

The best approach for the template is still using ocmod, but for this specific case, there is still a workaround with Event. Let's just assume the code was in the product template.

Code: Select all

<?php
public function adminViewProductProductFromBefore(&$route, &$data, &$template)
{
    /**
     * Assuming:
     * $data['customer_group']['customer_group_id']  = 2;
     * $data['product_special']['customer_group_id'] = 2;
     *
     * In the template, both value is equal, condition return true
     * {% if customer_group.customer_group_id == product_special.customer_group_id %}
     *
     * New condition:
     * $other_variable = false;
     *
     * Q: How to make the condition in template false?
     */
    if ($data['customer_group']['customer_group_id'] == $data['product_special']['customer_group_id'] && !$other_variable) {
        // Condition in template is false because both "customer_group_id" no longer equal
        $data['product_special']['customer_group_id'] = (int)$data['customer_group']['customer_group_id'] + 1;
    }

    /**
     * Assuming:
     * $data['customer_group']['customer_group_id']  = 2;
     * $data['product_special']['customer_group_id'] = 3;
     *
     * In the template, both value is different, condition return false
     * {% if customer_group.customer_group_id == product_special.customer_group_id %}
     *
     * New condition:
     * $other_variable = true;
     *
     * Q: How to make the condition in template true?
     */
    if ($data['customer_group']['customer_group_id'] != $data['product_special']['customer_group_id'] && $other_variable) {
        // Condition in template become true, because both "customer_group_id" is equal
        $data['product_special']['customer_group_id'] = $data['customer_group']['customer_group_id'];
    }

    // Cautions: use wisely or someone going to spend the night in headache debugging it :D
}


The reason why Events introduced was, I think because there is a lot of code conflict when several vQmod/OcMod change the same file. It's hard to think in a more efficient way when you can do whatever you want, to CRUD code directly with OcMod in a way that the whole thing becomes fragile.
There is a time when I think that it would be great if OcMod <add> tags have characters limit, force us to think in the most efficient way.

Code: Select all

// OcMod to change product price, use OcMod similar to Event listener
// Make the method implement the single-responsibility principle.
list($price, $special, $tax) = $this->load->controller('extension/module/my_module/updateProductPrice', array($data['price'], $data['special'], $data['tax']));
And we can do whatever we want at my_module::updateProductPrice() while keeping the change to core files as minimum as possible. And imagine how many lines of code, caffeine, and aspirin we can save to change product price at the categories, view cart, checkout, etc.

IMO, the "$this->load->controller()" is the most usefull OpenCart library to be combined with OcMod. Even if we need to load several models, use complex condition, and do NASA like algorithm calculation; it can be replaced with $this->load->controller('extension/module/my_module/checkThoroughly') and do those check at my_module::checkThoroughly() then return a simple primitive value.

But of course, if Event was hooked manually like how WordPress does, then things can be easier. Add them several dozen Event "hook" for each Opencart release, in a few releases we can have a hundred of them.

Code: Select all

list($price, $special, $tax) = $this->event->trigger('catalog/controller/product/product/mainPrice', array($data['price'], $data['special'], $data['tax']));

User avatar
Expert Member

Posts

Joined
Tue Jun 29, 2010 10:24 pm
Location - Indonesia

Post by JNeuhoff » Sat Jan 09, 2021 8:20 pm

@qahar: Thank you for sharing your thoughts with us.

As it stands, OC 4 won't have a built-in OCmod at all, modifications can only be done via event handlers.

Personally, I tend to use the Override Engine for our sites, which uses a factory class and a dynamic chain of object-oriented class extensions for method overrides, and it has a preRender method in its core engine which can be overridden in class extensions where it can then modify templates, too.

And since we are using Twig for rendering templates: We might as well make use of Twig's capabilities of template extensions (parent > class templates) and its block tags which allow you to override parent blocks with your own block code in a child template. Of course, in the real world there will be plenty of horrible web themes coming up again for OC 4 making clean design patterns impossible, similar to what Journal3 did for OC 3.

Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig


User avatar
Guru Member

Posts

Joined
Wed Dec 05, 2007 3:38 am


Post by qahar » Sun Jan 10, 2021 3:23 pm

JNeuhoff wrote:
Sat Jan 09, 2021 8:20 pm
@qahar: Thank you for sharing your thoughts with us.

As it stands, OC 4 won't have a built-in OCmod at all, modifications can only be done via event handlers.

Personally, I tend to use the Override Engine for our sites, which uses a factory class and a dynamic chain of object-oriented class extensions for method overrides, and it has a preRender method in its core engine which can be overridden in class extensions where it can then modify templates, too.
If OC 4 only accepting Event I hope it has manual hook Event inside the codes, besides the current before/after Event. Thus we have more control over variables inside the controller/ module process.

JNeuhoff wrote:
Sat Jan 09, 2021 8:20 pm
And since we are using Twig for rendering templates: We might as well make use of Twig's capabilities of template extensions (parent > class templates) and its block tags which allow you to override parent blocks with your own block code in a child template. Of course, in the real world there will be plenty of horrible web themes coming up again for OC 4 making clean design patterns impossible, similar to what Journal3 did for OC 3.
Yup, OpenCart needs to maximize the use of the TWIG feature such as template inheritance, partial template, and global variables.

Code: Select all

{# File: base.twig #}
<!DOCTYPE html>
<html>
    <head>
        {# Global variable #}
        {% for style in $global.document.getStyle() %}
            <link rel="stylesheet" href="{{ style.href }}" media="{{ style.media }}">
        {% endfor %}
    </head>
    <body>
        <div id="header">{{ header }}</div>
        <div id="content">
            {% block content %}{% endblock %}
        </div>
        <div id="footer">
            {{ footer }}
        </div>
    </body>
</html>


{# Inheritance at file: category.twig #}
{% extends "base.html" %}

{% block content %}
    <h1>Desktop</h1>
    <div id="category-profile">...</div>

    {# Can be used to output banner, special offers etc #}
    {{ $global->event->trigger('view/product/category/beforeProducts') }}

    <div id="products">
        <div class="row">
            <div class="product-item col-lg-3 col-md-3 col-sm-6 col-xs-12">
                {% for product in products %}
                    {# Partial Template #}
                    {% include 'partial/product_list.twig' with {'mode' : 'card-dark'} %}
                {% endfor %}
            </div>
        </div>
    </div>
{% endblock %}

{# Partial template at file: module_latest.twig #}
<div id="module-latest">
    <div class="row">
        <div class="product-item col-lg-3 col-md-3 col-sm-6 col-xs-12">
            {% for product in products %}
                {# Partial Template #}
                {% include 'partial/product_list.twig' with {'mode' : 'card-minimum'} %}
            {% endfor %}
        </div>
    </div>
</div>

{# File: partial/product_list.twig (Edit this file at Design > Theme, applied to all pages) #}
<div class="product-card {{ mode }}">
    <div class="image">{{ item.image }}</div>
    <h3>{{ item.title }}</h3>
    <p>{{ item.price }}</p>
</div>

User avatar
Expert Member

Posts

Joined
Tue Jun 29, 2010 10:24 pm
Location - Indonesia

Post by xxvirusxx » Sun Jan 24, 2021 4:35 pm

A question.

For example when you use ocmod/vqmod sometime you need to add some code in controller then to read values in twig.

Using event this is not necessary anymore?
To add code in controller then code in twig.

Upgrade Service | OC 2.3.0.2 PHP 8 | My Custom OC 3.0.3.8 | Buy me a beer


User avatar
Expert Member

Posts

Joined
Tue Jul 17, 2012 10:35 pm
Location - România

Post by JNeuhoff » Sun Jan 24, 2021 8:03 pm

xxvirusxx wrote:
Sun Jan 24, 2021 4:35 pm
A question.

For example when you use ocmod/vqmod sometime you need to add some code in controller then to read values in twig.

Using event this is not necessary anymore?
To add code in controller then code in twig.
You'd use a controller-before event to add some more business logic for additional variables, and then use a view-before or view-after event for adding the extra variables to the template for rendering.

Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig


User avatar
Guru Member

Posts

Joined
Wed Dec 05, 2007 3:38 am


Post by xxvirusxx » Sun Jan 24, 2021 8:14 pm

So for each file is necessary an event.
If you want to add some code in controller ,model, and twig, install function will have 3 events, right?

LE. Before and after is like before and after from ocmod?
Or is like before render twig, the data from controller is replaced/added...then after that twig is rendered?

Upgrade Service | OC 2.3.0.2 PHP 8 | My Custom OC 3.0.3.8 | Buy me a beer


User avatar
Expert Member

Posts

Joined
Tue Jul 17, 2012 10:35 pm
Location - România

Post by straightlight » Sun Jan 24, 2021 11:57 pm

xxvirusxx wrote:
Sun Jan 24, 2021 8:14 pm
So for each file is necessary an event.
If you want to add some code in controller ,model, and twig, install function will have 3 events, right?

LE. Before and after is like before and after from ocmod?
Or is like before render twig, the data from controller is replaced/added...then after that twig is rendered?
Just read the wiki documentation on Github ...

Dedication and passion goes to those who are able to push and merge a project.

Regards,
Straightlight
Programmer / Opencart Tester


Legendary Member

Posts

Joined
Mon Nov 14, 2011 11:38 pm
Location - Canada, ON

Post by kestas » Sat Jan 30, 2021 5:40 pm

straightlight wrote:
Sun Jan 24, 2021 11:57 pm
xxvirusxx wrote:
Sun Jan 24, 2021 8:14 pm
So for each file is necessary an event.
If you want to add some code in controller ,model, and twig, install function will have 3 events, right?

LE. Before and after is like before and after from ocmod?
Or is like before render twig, the data from controller is replaced/added...then after that twig is rendered?
Just read the wiki documentation on Github ...
You mean this one: https://github.com/opencart/opencart/wiki/Events-System
Seems there are some mistakes in explanation of the Registering your Events
To initiate the before event.

Code: Select all

$this->model_setting_event->addEvent('product_notification', 'admin/model/catalog/product/addProduct/before', 'extension/module/product_notification/addProduct');
To initiate an after event, simply change it to:

Code: Select all

$this->model_setting_event->addEvent('product_notification', 'admin/model/catalog/product/addProduct/after', 'extension/module/product_notification/addProduct');
The same string in example is used for before and after triggering.

All sounds good, but if I correctly understand there no possibility, using events, add to the twig files particular code... For example if I need additional column in order list (admin) to display which shipping method was used for the order... If it is possible to add specific code to twig files using events, can anyone give an example of how to do this properly?
It would be great if the manual of the event system has more examples of how to use this system. Particularly how to add or replace some code in files (php or twig) using events system, how it was possible using OCMOD, or vqmod.

Custom OpenCart modules and solutions. You can write PM with additional questions... Extensions you can find here


Active Member

Posts

Joined
Tue Oct 12, 2010 2:23 am

Post by OSWorX » Sat Jan 30, 2021 7:02 pm

kestas wrote:
Sat Jan 30, 2021 5:40 pm
All sounds good, but if I correctly understand there no possibility, using events, add to the twig files particular code...
For example if I need additional column in order list (admin) to display which shipping method was used for the order...
If it is possible to add specific code to twig files using events, can anyone give an example of how to do this properly?
jneuhoff made a clever pull request: https://github.com/opencart/opencart/pull/7153
Did not check further the current master code how far his idea is implemented, but the idea is, to load the raw content of the template instead the parsed.

Basically your should be able to load the raw template code like:

Code: Select all

if (is_file(DIR_TEMPLATE . $theme . '/template/' . $route . $ext)) {
	$file = DIR_TEMPLATE . $theme . '/template/' . $route . $ext;
	$tpl = file_get_contents( modification($file) );
}
where $theme is the used theme (config_theme), $route (given by the event), $ext can be .tpl or .twig (preferred) or fix twig (because we are now at OpenCart 4.x where twig is used only).

This will load the raw content of the template, and then you can modify how-/whatever you want.
A simple

Code: Select all

$tpl = str_replace( $search, $replace, $tpl );
will do that (of course $search & $replace defined before).

A trigger could be: catalog/view/extension/module/*/before
Means the event will be called for each extension module before the template is parsed.

p.s.: modification($file) is used, because I do such also currently in older extensions also for OC 2.3.x
With OC 4.x this is not needed anymore.

Full Stack Web Developer :: Dedicated OpenCart Development & Support DACH Region
Contact for Custom Work / Fast Support.


User avatar
Guru Member

Posts

Joined
Mon Jan 11, 2010 10:52 pm
Location - Austria

Post by kestas » Sat Jan 30, 2021 7:10 pm

Thank you @OSWorX, getting clear... I will check this.

Custom OpenCart modules and solutions. You can write PM with additional questions... Extensions you can find here


Active Member

Posts

Joined
Tue Oct 12, 2010 2:23 am

Post by JNeuhoff » Sat Jan 30, 2021 8:16 pm

kestas wrote:
Sat Jan 30, 2021 5:40 pm

All sounds good, but if I correctly understand there no possibility, using events, add to the twig files particular code... For example if I need additional column in order list (admin) to display which shipping method was used for the order... If it is possible to add specific code to twig files using events, can anyone give an example of how to do this properly?
Take a look at this forum post which should answer your question.

Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig


User avatar
Guru Member

Posts

Joined
Wed Dec 05, 2007 3:38 am

Who is online

Users browsing this forum: No registered users and 14 guests