All instances of controller, model, or library classes are created by a special factory class.
An additional override feature is supported. This allows 3rd party addons to do changes to the OpenCart core classes, templates, and language files. Core controller, model and library classes can be extended and their methods be overridden in a normal object oriented programming manner.
VQmod is supported, too, but I think this new Override Engine allows the modifications of OpenCart core files to be done in an easier way. The Override Engine uses object oriented programming techniques to modify OpenCart core classes, whereas VQmod uses dynamic search and replace operations for this.
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
Ingat Gadget, Ingat DroidLime https://www.droidlime.com/
I have it already running on 2 new live sites in the UK:qahar wrote:I'm not test it yet but from what I read, it's sound interesting!
The only concern is conflict possibility and performance of the chain-class.
Well, I think I will found an answer after test it
http://www.ion.uk.com
http://www.madeinharwich.com
And it has no performance degradation, to the contrary, it is slighly faster. Of course, I'd only know for sure if I do some precise performance measurement with and without the override engine. I am planning to port another 5 websites over to the latest OpenCart with this new override engine.
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
Let me know how your testing goes. I already have some addons where each one of them extends the same header.php, amongst other classes, and the automatic chaining of class extensions works just fine.Qphoria wrote:Ah.. Great to see something finally came from the old 0.x discussions! Looks like you guys have done a nice job with this. I haven't tried it yet but it sounds great the way you got the automatic subclassing system working for multiple mods. I will have to try this.
Nice Work!
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
How's the upgrade process with this system?
Looks great, I'll see for my next project what the options are for using this with VQMod, although it might not be worth the trouble.
I don't use VQmod at all anymore for new OpenCart projects3rdcorner wrote:Something like this is what I've built in-house. The only problem I have is it replacing the core files. Right now I use VQMod to modify the core files and keep my override system separated.
How's the upgrade process with this system?
Looks great, I'll see for my next project what the options are for using this with VQMod, although it might not be worth the trouble.
You can easily modify OpenCart core classes, language files and even templates with the new Override Engine.
Upgrading to newer future OpenCart versions should be a lot easier with this Override Engine, compared to VQmod, because all your overrides (e.g. extended core classes with their overriden methods) are in a separate 'override' folder. VQmod's dynamic XML search and replace operations get more easily broken in OpenCart upgrades.
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
Lets say I want to change this line in the catalog/model/account/customer.php file:
INSTEAD OF THIS:
I WANT THIS:$this->db->query("UPDATE " . DB_PREFIX . "customer SET address_id = '" . (int)$address_id . "' WHERE customer_id = '" . (int)$customer_id . "'");
I assume I need to subclass the function$this->db->query("UPDATE " . DB_PREFIX . "customer SET address_id = '" . (int)$address_id . "', newfield = 1 WHERE customer_id = '" . (int)$customer_id . "'");
Code: Select all
public function addCustomer($data)
Code: Select all
<?php
class myaddon_ModelAccountCustomer extends ModelAccountCustomer {
public function addCustomer($data) {
parent::addCustomer($data);
// also add the newfield to the customer record
$sql = "UPDATE `".DB_PREFIX."customer` SET newfield = '".$data['newfield']."' ";
$sql .= "WHERE email = '".$data['email']."'";
$this->db->query( $sql );
}
}
....
?>
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
But then how would you do the same thing for an order? You can "cheat" by using the email field for a customer because that is also unique per customer. But the order table has only one unique field.
Easy enough againQphoria wrote: But then how would you do the same thing for an order? You can "cheat" by using the email field for a customer because that is also unique per customer. But the order table has only one unique field.
Code: Select all
<?php
class myaddon_ModelCheckoutOrder extends ModelCheckoutOrder {
// override function
public function addOrder($data) {
$order_id = parent::addOrder($data);
// add new field into order record
$sql = "UPDATE `".DB_PREFIX."order` SET newfield='".$data['newfield']."' ";
$sql .= "WHERE order_id = '".(int)$order_id."'";
$this->db->query( $sql );
return $order_id;
}
}
?>
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
Yea i get what it is doing.. just wasn't sure where it comes in. I guess it depends on where you call the parent. In this case you are fortunate that addOrder returns the order_id, so I'll try something more difficult...JNeuhoff wrote:Easy enough againQphoria wrote: But then how would you do the same thing for an order? You can "cheat" by using the email field for a customer because that is also unique per customer. But the order table has only one unique field.
You have to think differently here. This is object oriented programming, in particular, extending classes and overrding methods to get an additional and/or modified behavior for the method. I have a few live sites now using this new Override Engine, with lots of modifications, no problems so far.Code: Select all
<?php class myaddon_ModelCheckoutOrder extends ModelCheckoutOrder { // override function public function addOrder($data) { $order_id = parent::addOrder($data); // add new field into order record $sql = "UPDATE `".DB_PREFIX."order` SET newfield='".$data['newfield']."' "; $sql .= "WHERE order_id = '".(int)$order_id."'"; $this->db->query( $sql ); return $order_id; } } ?>
In the catalog/model/checkout/order.php
in the confirm() function
I want to change
Code: Select all
$order_download_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_download WHERE order_id = '" . (int)$order_id . "'");
Code: Select all
$order_download_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_download LEFT JOIN order_download_master odm WHERE order_id = '" . (int)$order_id . "'");
M
-----------------------------------------------------------------------
My last mods: Partita IVA e CF | Pro EU VAT Number | Sales Agents | Pricelist Pro
-----------------------------------------------------------------------
You are really trying to make my life miserable hereQphoria wrote: Yea i get what it is doing.. just wasn't sure where it comes in. I guess it depends on where you call the parent. In this case you are fortunate that addOrder returns the order_id, so I'll try something more difficult...
In the catalog/model/checkout/order.php
in the confirm() function
I want to changetoCode: Select all
$order_download_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_download WHERE order_id = '" . (int)$order_id . "'");
Code: Select all
$order_download_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_download LEFT JOIN order_download_master odm WHERE order_id = '" . (int)$order_id . "'");
Well, Rome wasn't built in a day. My Override Engine may need some more refinement to cater for all these crazy cases, you got me there
I must admit the catalog/model/checkout/order.php is a real mess here because it has some non-model code in it, such as sending a mail message. It should have been splitted up between the model, and a sendMail. It is usually called from a payment controller's callback function. I'd probably use my own confirm method altogether (e.g. a confirmPayment), and override the payment controller's callback function, which then would invoke the model's new confirmPayment and sendMail functions.
Or even better: Maybe in the next version of the Override Engine, I'll add a non-chained bugfix folder, replacing some of the buggy or messy core methods, which can then be overridden for addons.
I noticed there are still some OpenCart classes such as Mail, Pagination, or Template whose instances aren't yet created through the override engine's Factory class. I'll correct that one in the next version of the Override Engine.
Your order_download_query is probably used in 2 places within method confirm:
Code: Select all
$template = new Template();
if ($order_download_query->num_rows) {
$template->data['download'] = $order_info['store_url'] . 'index.php?route=account/download';
} else {
$template->data['download'] = '';
}
...
$html = $template->fetch('default/template/mail/order.tpl');
...
Code: Select all
if ($order_download_query->num_rows) {
$text .= $language->get('text_new_download') . "\n";
$text .= $order_info['store_url'] . 'index.php?route=account/download' . "\n\n";
}
Code: Select all
$mail = new Mail();
...
$mail->setHtml($html);
$mail->setText(html_entity_decode($text, ENT_QUOTES, 'UTF-8'));
$mail->send();
I think in the next version of the override engine I will make sure it uses the Factory class for creating instances of Template and Mail, e.g.:
Code: Select all
$template = $this->factory->newTemplate();
...
$mail = $this->factory->newMail();
...
Code: Select all
$template = new Template();
...
$mail = new Mail();
...
Code: Select all
class myaddon_Mail extends Mail {
// override method
function setText( $text ) {
parent::setText( $text );
// run the modified order_download_query
// change $this->text accordingly
...
}
// override method
function setHtml( $html ) {
parent::setHtml( $html );
// run the modified order_download_query
// change $this->html accordingly
...
}
}
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
As you may have noticed from this forum thread, there is still some room for improvements for the Override Engine. That's why I am always grateful for some feedback.madimar wrote:Just to say... Really interesting topic... I will try to check the new override system soon. Thanks for your work jneuhoff.
M
I noticed there are a few classes such as Mail, Pagination, or Template whose instances aren't created like the model or controller classes. So I think the next version of the Override Engine will make sure that any instance creation of these remaining few classes will go through the Factory class, too, as is already the case for controller or model classes. This way they'll become extendable, too.
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
LOL I just wanted to press a little... maybe for being a bit dismissive of vQmodJNeuhoff wrote: You are really trying to make my life miserable here
Well, Rome wasn't built in a day. My Override Engine may need some more refinement to cater for all these crazy cases, you got me there
Granted your way is indeed a much better programmatic way of proper modification. vQmod is just that little hack engine that could.
I'd still like to see your override engine in the core for larger mods, leaving vQmod for the smaller one line changes like this.
I appreciate your comments. I am already working on some larger addons, have about 50 VQmods scripts to be converted to this override engine.Qphoria wrote: LOL I just wanted to press a little... maybe for being a bit dismissive of vQmod
Granted your way is indeed a much better programmatic way of proper modification. vQmod is just that little hack engine that could.
I'd still like to see your override engine in the core for larger mods, leaving vQmod for the smaller one line changes like this.
BTW.: For your specific example, with the existing Override Engine, depending on what you were trying to accomplish, I'd probaly do something like this:
Code: Select all
<?php
class myaddon_ModelCheckoutOrder extends ModelCheckoutOrder {
// override function
public function confirm($order_id, $order_status_id, $comment = '', $notify = false) {
// prevent parent function from sending mail, because we need some modifications
$saved_mail_protocol = $this->config->get('config_mail_protocol');
$this->config->set( 'config_mail_protocol', '' );
// call parent method`
parent::confirm( $order_id, $order_status_id, $comment, $notify );
// let's use our modifified download_order_query
$order_download_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_download LEFT JOIN order_download_master odm WHERE order_id = '" . (int)$order_id . "'");
$has_downloads = ($order_download_query->num_rows > 0);
// use the modified order downloads query data for populating the mail message body,
// then send the confirmation mail
$this->config->set( 'config_mail_protocol', $saved_mail_protocol );
$mail = new Mail();
// .....
$mail->send();
}
}
?>
I think many PHP programmers will find it easier to use the object oriented way of extending classes and overriding methods, rather than having to specify core changes in XML search and replace operations. However, the Override Engine does support VQmod, too!
I hope that future releases of OpenCart can also introduce some hook functions into its MVC framwork, the Override Eingine can easily support them. I have already introduced one hook: Method preRender in class Controller, to give the addon the chance to add its own variables, and to modify the template before rendering it.
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
Exactly as I pointed out from one of the topics last year; to use overrides.
This override system seem to be exactly what I was looking for which could definitely replace the XML utility in OpenCart. If all works well as demonstrated from your ZIP file, I will modify my contributions based on this engine instead.
Edit: One aspect I did encountered is that preRender uses the same template buffer name whether it comes from the same or different author. It would be great to have an override system for template files as well.
Dedication and passion goes to those who are able to push and merge a project.
Regards,
Straightlight
Programmer / Opencart Tester
Except this Override Engine is more than that: It can also handle the case where multple addons happen to extend the same class and override the same method, in which case it uses a dynamic chain of class extensions. That's why an overridden method always has to call the parent method, too, so as not to break the chain.straightlight wrote: Exactly as I pointed out from one of the topics last year; to use overrides.
Let us know how you get on with your testing.
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
Users browsing this forum: No registered users and 95 guests