Post by glolar » Thu Apr 30, 2020 8:57 pm

Hello,

I am trying to learn more about extensions, and how the Extension Installer works. Here is a snippet of an install.xml file that is supposed to add some lines of code to admin/view/template/sale/order_info.twig:

Code: Select all

	<file path="admin/view/template/sale/order_info.twig">
		<operation error="skip">
			<search trim="true"><![CDATA[
			{% if shipping_method %}
            		<tr>
              			<td><button data-toggle="tooltip" title="{{ text_shipping_method }}" class="btn btn-info btn-xs"><i class="fa fa-truck fa-fw"></i></button></td>
              			<td>{{ shipping_method }}</td>
            		</tr>
            		{% endif %}
			]]></search>
			<add position="after" trim="true"><![CDATA[
				<!-- Added by Extension -->
            			<tr>
              				<td><button data-toggle="tooltip" title="Tracking Number" class="btn btn-info btn-xs"><i class="fa fa-plane fa-fw"></i></button></td>
              				<td><a href="https://tools.usps.com/go/TrackConfirmAction.action?tLabels={{ tracking }}" target="_blank">{{ tracking }}</a></td>
            			</tr>
            			<!-- End of addition -->
			]]></add>
		</operation>
	</file>
Well, it appears that the search is not finding the code it is looking for. That block of code in the search is a direct copy/paste out of the file, so it SHOULD be finding it, then adding the new block of code after it.

I have updated numerous other files, and even .twig files, but this is the first time I have had a search that is looking for a snippet of code that is in an "{% if <condition> %} - {% endif %} block. Is the conditional block causing the search to fail? I must put my new code right after this conditional "{% endif %}" because the code after the "{% endif %}" is not unique, so I cannot search for the code after the "{% endif %}" and use an "add position="before" option.

Here is the code for the entire table that I am trying to add a row to. Would appreciate any suggestions:

Code: Select all

<table class="table">
            <tbody>
              <tr>
                <td style="width: 1%;"><button data-toggle="tooltip" title="{{ text_store }}" class="btn btn-info btn-xs"><i class="fa fa-shopping-cart fa-fw"></i></button></td>
                <td><a href="{{ store_url }}" target="_blank">{{ store_name }}</a></td>
              </tr>
              <tr>
                <td><button data-toggle="tooltip" title="{{ text_date_added }}" class="btn btn-info btn-xs"><i class="fa fa-calendar fa-fw"></i></button></td>
                <td>{{ date_added }}</td>
              </tr>
              <tr>
                <td><button data-toggle="tooltip" title="{{ text_payment_method }}" class="btn btn-info btn-xs"><i class="fa fa-credit-card fa-fw"></i></button></td>
                <td>{{ payment_method }}</td>
              </tr>
            {% if shipping_method %}
            <tr>
              <td><button data-toggle="tooltip" title="{{ text_shipping_method }}" class="btn btn-info btn-xs"><i class="fa fa-truck fa-fw"></i></button></td>
              <td>{{ shipping_method }}</td>
            </tr>
            {% endif %}
              </tbody>            
          </table>
Again, the "</tbody> tag is not unique, so I cannot use an "<add position="before">" tag.

Thanks!

Increase Your Child's I.Q.
iPad Wallpapers
Turtle & Tortoise Screen Savers


User avatar
Active Member

Posts

Joined
Thu Jul 29, 2010 12:35 pm
Location - San Diego, CA

Post by letxobnav » Thu Apr 30, 2020 10:40 pm

Again, the "</tbody> tag is not unique, so I cannot use an "<add position="before">" tag.
you could use index.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by glolar » Fri May 01, 2020 2:51 am

letxobnav wrote:
Thu Apr 30, 2020 10:40 pm
Again, the "</tbody> tag is not unique, so I cannot use an "<add position="before">" tag.
you could use index.
Could you please elaborate?

Increase Your Child's I.Q.
iPad Wallpapers
Turtle & Tortoise Screen Savers


User avatar
Active Member

Posts

Joined
Thu Jul 29, 2010 12:35 pm
Location - San Diego, CA

Post by JNeuhoff » Fri May 01, 2020 4:06 am

You should use event handlers, e.g. for admin/view/template/sale/order_info/before and admin/view/template/sale/order_info/after.

In the before-handler, create a new controller variable, e.g.

Code: Select all

$data['new_row'] = .... rendered output just for the new row ...
In the after-handler, dynamically add it to the rendered output of the order_info.twig via a simple jquery, e.g. something like

Code: Select all

$output .= '<script type="text/javascript"><!--';
$output .= "$(document).ready(function() {";
$output .= " $('.table > tbody > tr > td > button > .fa-shopping-cart).parent().parent().parent().parent().append( ".$data['new_row'].");";
$output .= "});";
$output .= "//--></script>";  
This should make it robust enough, avoiding clashes with other 3rd party extensions trying to modify the same template.

XML-based modification systems like OCmod or VQmod tend to be quite cumbersome, XML is mainly for structured documents or protocols, it's not really a programming language. OpenCart should strive to move away from the XML-based modification systems.

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 letxobnav » Fri May 01, 2020 10:40 am

I agree that both OCMOD and VQMOD are both subject to modification clashes with oneanother and new versions but putting jquery code into your output to unconditionally change the very same output are band-aid practices and definitely not the way to go.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by JNeuhoff » Fri May 01, 2020 4:24 pm

The main idea is to use event handlers, and to regard the output as a DOM tree into which to add a new node. Admittedly this particular example is a worst-case scenario because the table-element into which to insert the extra row has no id-attribute, only a generic class="table", which isn't good enough to identify it, whereas chances are that the element with class="fa-shopping-cart" only occurs once on the page, hence the idea to start from there and work our way up to its table-parent.

VOmod and OCmod are only temporary band-aid solutions, and future versions of OpenCart should remove them altogether, instead introducing better event handlers, including for system library classes. Also, the templates, and sub-templates, should be improved so as to make it easier for event handlers to parse them as trees should they need to modify them.

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 letxobnav » Fri May 01, 2020 6:09 pm

that I can agree with.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by paulfeakins » Fri May 01, 2020 6:10 pm

JNeuhoff wrote:
Fri May 01, 2020 4:24 pm
VOmod and OCmod are only temporary band-aid solutions, and future versions of OpenCart should remove them altogether, instead introducing better event handlers, including for system library classes. Also, the templates, and sub-templates, should be improved so as to make it easier for event handlers to parse them as trees should they need to modify them.
That is your opinion but I disagree.

What if there is not an event where you need it? Then the change is not possible.

Having good events is fine, but sometimes they are not enough.

UK OpenCart Hosting | OpenCart Audits | OpenCart Support - please email info@antropy.co.uk


User avatar
Legendary Member
Online

Posts

Joined
Mon Aug 22, 2011 11:01 pm
Location - London Gatwick, United Kingdom

Post by JNeuhoff » Fri May 01, 2020 6:32 pm

What if there is not an event where you need it? Then the change is not possible.
I have done hundreds of OpenCart modifications and/or extensions, without the need for OCmod/VQmod. What modifications did you encounter you couldn't do with event handlers? Perhaps OpenCart has reached a point where it could learn from other PHP frameworks, to see how they handle modifications.

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 letxobnav » Fri May 01, 2020 7:26 pm

Fact of the matter is, MODs clash, amongst eachother and with new versions of OC.
So even the claim that you should use one of these so that you can easily upgrade is a farce.
The only true benefit of these MODs (if they do not clash amongst eachother) is that you can easily turn them on and off, that's about it.

your disagreement on this is noted in advance.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by JNeuhoff » Fri May 01, 2020 7:53 pm

I agree there is always the danger of different 3rd party extensions clashing with each other, it's just a matter of reducing the chances for this to happen. That's why I think event handlers are a step in the right direction.

IMHO there could still be better ways to handle this, which should include better upgrade mechanisms, too. E.g. if during an automated OpenCart upgrade it should also check for versions of the extensions that support the new OpenCart release, or else be automatically disabled. We have upgraded whole Linux operating systems successfully, with hundred of dependent software items, thanks to a well-organized package manager. Maybe OpenCart needs a better package management for extensions along similar lines, too? I wonder how other PHP frameworks are dealing with this problem.

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 straightlight » Fri May 01, 2020 7:56 pm

VOmod and OCmod are only temporary band-aid solutions, and future versions of OpenCart should remove them altogether, instead introducing better event handlers, including for system library classes. Also, the templates, and sub-templates, should be improved so as to make it easier for event handlers to parse them as trees should they need to modify them.
I have already suggested this approach to Daniel in the past on Github. Unfortunately, the request was denied since, according to his views, there are too many templates out there.

Source: https://github.com/opencart/opencart/pu ... -500318268 .

My personal note on this is if the Event Engine would have a great start since the OC v2.x releases, in the first place, we wouldn't need to convince other users to use the modified engine on Github with the /before which is also the main reason why I encourage users to use the most up-to-date OC release rather than the fallback versions. While the objective is not strictly based on that, the Event engine has been re-worked on OC v3.x releases as opposed to OC v2.x releases in the mean time.

While all the pointers seem to be valid on this topic, in order to convince the people to stick with the events, and while I do agree this is the best approach, users would need to be convinced not to fallback on their purchased extensions nor to remain on older OC releases, among all the modified OC versions that forum users might address about, sticking to the idea to evolve with the modified Event Engine should rather be considered without impacting the sales on the Marketplace. If that idea was to come up one day, without conflicting the filenames of those created events, despite if the oc_event have different code names in the field, it would be a better start as compared to the use of VQMod / OCMod. With VQMod / OCMod, activity logs are still dependable to the store owners where operations aborted and operations skipped can still be noticed as opposed to the Event Engine which VQMod / OCMod does have its advantage on that side.

While I may also have to agree that using the $output such ways may not be used in best practices, the internal theme editor of OC won't be able to track this JS code specifically. Which is why, if considering to others to use Events shall shed some lights at this point, better encourage to use TWIG files on OC v3.x releases (or the Template Switcher extension but even there this extension may not cover the modified event engine on Github neither).

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 Majnoon » Tue Aug 22, 2023 4:05 pm

If i want to replace a entire block via event system let say in
<file path="catalog/view/theme/*/template/product/product.twig">

Code: Select all

                {% if recurrings %}
                  <h3 class="title recurring-title">{{ text_payment_recurring }}</h3>
                  <div class="form-group required">
                    <select name="recurring_id" class="form-control">
                      <option value="">{{ text_select }}</option>
                      {% for recurring in recurrings %}
                        <option value="{{ recurring.recurring_id }}">{{ recurring.name }}</option>
                      {% endfor %}
                    </select>
                    <div class="help-block" id="recurring-description"></div>
                  </div>
                {% endif %}
and replace with :

Code: Select all

{% if recurrings %}
<hr>
<div class="form-group required">
    <label>
        <input type="radio" name="recurring_id" value="0" checked="checked" />
        One-time purchase: {{ price }}
    </label>
    {% for recurring in recurrings %}
    <label>
        <input type="radio" name="recurring_id" value="{{ recurring.recurring_id }}" />
        {{ recurring.name }}: {{ recurring.price }}</label><div class="help-block" id="recurring-description-{{ recurring.recurring_id }}"></div>
    {% endfor %}
</div>
{% endif %}
how would you advice me to achive this?
let say i create and place a file in catalog/controller/event/recurring_test.php

Code: Select all

<?php
class ControllerEventRecurringTest extends Controller {
    public function modifyRecurringTest(&$route, &$data, &$output) {
        // Find the existing HTML code
        $search =  {% if recurrings %}
                  <h3 class="title recurring-title">{{ text_payment_recurring }}</h3>
                  <div class="form-group required">
                    <select name="recurring_id" class="form-control">
                      <option value="">{{ text_select }}</option>
                      {% for recurring in recurrings %}
                        <option value="{{ recurring.recurring_id }}">{{ recurring.name }}</option>
                      {% endfor %}
                    </select>
                    <div class="help-block" id="recurring-description"></div>
                  </div>
                {% endif %}';

        // Replacement HTML code
        $replace = '{% if recurrings %}
            <hr>
            <div class="form-group required">
                <label>
                    <input type="radio" name="recurring_id" value="0" checked="checked" />
                    One-time purchase: {{ price }}
                </label>
                {% for recurring in recurrings %}
                <label>
                    <input type="radio" name="recurring_id" value="{{ recurring.recurring_id }}" />
                    {{ recurring.name }}: {{ recurring.price }}</label><div class="help-block" id="recurring-description-{{ recurring.recurring_id }}"></div>
                {% endfor %}
            </div>
            {% endif %}';

        // Perform the replacement
        $output = str_replace($search, $replace, $output);
    }
}
also can i register this event in the same file as well?

Code: Select all

$this->load->model('setting/event');
$this->model_setting_event->addEvent('recurring_test', 'view/*/template/product/product/after', 'event/recurring_test/modifyRecurringTest');
Is this is right approach in opencart?

Active Member

Posts

Joined
Fri Feb 05, 2021 8:29 pm

Post by paulfeakins » Tue Aug 22, 2023 5:43 pm

JNeuhoff wrote:
Fri May 01, 2020 6:32 pm
What modifications did you encounter you couldn't do with event handlers?
Well, a method can only be totally overwritten rather than modified, so it can only be changed by one extension at a time. Surely that's a problem?

UK OpenCart Hosting | OpenCart Audits | OpenCart Support - please email info@antropy.co.uk


User avatar
Legendary Member
Online

Posts

Joined
Mon Aug 22, 2011 11:01 pm
Location - London Gatwick, United Kingdom
Who is online

Users browsing this forum: No registered users and 15 guests