Post by rph » Fri Feb 14, 2014 5:58 am

I've been experimenting with directly editing the DOM with PHP. I believe it would add many benefits for moding:

1) It's much more resilient than direct template modding with vQmod
2) It doesn't add loads of extra javascript to the page
3) It's more secure since effects can't be disabled in the browser

The problem I'm having is that the default OpenCart theme (and by extension many custom ones) has javascript with embedded HTML. It really throws a wrench in parsing/saving the template HTML. I've tried using the PHP DOMDocument class and PHP Simple HTML DOM Parser with no luck. Does anyone have experience with any other libraries that might be able to get around the issue?

-Ryan


rph
Expert Member

Posts

Joined
Fri Jan 08, 2010 5:05 am
Location - Lincoln, Nebraska

Post by rempong » Fri Feb 14, 2014 9:36 am

So you want php to crawl to javascript code in some ".tpl" file then do DOM parser ?

OPENCART MODULE :
Opencart Compare Link Link your compared product to forum/email

Frontend Link From Admin Dashboard
Get link to product , category, manufacturer, information from admin backend.

Copy and DIRECTLY Edit Product the easy way.

Custom Product Sort Full control to product sorting options

Already Sold Product Module, shows total product sold


Active Member

Posts

Joined
Fri Sep 14, 2012 2:38 pm
Location - Indonesia

Post by rph » Fri Feb 14, 2014 4:02 pm

I'm hoping for a DOM manipulation library that can handle template code like:

Code: Select all

$('#notification').html('<div class="success" style="display: none;">' + json['success'] + '<img src="catalog/view/theme/default/image/close.png" alt="" class="close" /></div>');
I started playing with this concept a few months ago because I'm looking to update my Catalog Mode extension. I threw together a quick proof of concept that modified the output before rendering. It works well until it hits the jQuery snippet above:

Image

The smart thing would be to get rid of all the embedded script in the templates but that's obviously not an option. I've tried DOMDocument and PHP Simple HTML DOM Parser with no luck (I believe I had the issue with phpQuery also but I'd have to check my old work).

-Ryan


rph
Expert Member

Posts

Joined
Fri Jan 08, 2010 5:05 am
Location - Lincoln, Nebraska

Post by JNeuhoff » Sat Feb 15, 2014 6:40 am

As regards the cumbersome Javascript: What happens if your Javascript code is wrapped up in a HTML comment, e.g. the normal

Code: Select all

<script type="text/javascript"><!--
  .... javascript code ....
//--></script>
BTW.: I have been thinking about using the PHP DOM parser for changing tpl-files for quite a while, too. Doing it via VQmod, or even directly with str_replace() calls, is not an elegant way. Picking DOM elemens by their ids and then manipulating them with dom seems to be a better approach. However, there are some tpl-files which contain sections of HTML with some unclosed tags, such as the header.tpl which has an opening <body> tag, but no matching </body>. This wasn't an issue in older OpenCart versions which used to have a top-level common.tpl for all pages.

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 rph » Sat Feb 15, 2014 12:28 pm

JNeuhoff wrote:What happens if your Javascript code is wrapped up in a HTML comment
Same thing unfortunately. OpenCart already has the tags, in fact.
BTW.: I have been thinking about using the PHP DOM parser for changing tpl-files for quite a while, too. Doing it via VQmod, or even directly with str_replace() calls, is not an elegant way. Picking DOM elemens by their ids and then manipulating them with dom seems to be a better approach. However, there are some tpl-files which contain sections of HTML with some unclosed tags, such as the header.tpl which has an opening <body> tag, but no matching </body>.
I just intercepted the output in response.php before it's echoed out.

Code: Select all

public function output() {
    if ($this->output) {
        if ($this->level) {
            $ouput = $this->compress($this->output, $this->level);
        } else {
            $ouput = $this->output;
        }    
            
        if (!headers_sent()) {
            foreach ($this->headers as $header) {
                header($header, true);
            }
        }
        
        echo $this->editDom($ouput);
    }
}

private function editDom($html) {
    libxml_use_internal_errors(true);

    $dom = new DOMDocument('1.0','UTF-8');
    $dom->loadHTML($html);

    // voodoo

    $output = $dom->saveHTML();

    return $output;
}
 
All the changes are hardcoded in the editDom() method right now but I imagine you could use a class property and a setter similar to the way output works. Then you'd just feed that into editDom().

-Ryan


rph
Expert Member

Posts

Joined
Fri Jan 08, 2010 5:05 am
Location - Lincoln, Nebraska

Post by JNeuhoff » Sun Feb 16, 2014 3:53 am

rph wrote:
JNeuhoff wrote: I just intercepted the output in response.php before it's echoed out.
I see. Still, would be nice if the tpl files could be manipulated with a DOM parser instead of VQmod for 3rd party extensions. By the time you intercept the output in the response.php all PHP code has already been executed. Also, bear in mind the output could be compressed!

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 rph » Sun Feb 16, 2014 5:55 am

JNeuhoff wrote:By the time you intercept the output in the response.php all PHP code has already been executed.
I don't think it's too big a deal. If you wanted to use the controller data you could just edit in something like:

Code: Select all

$template = new Template();
$template->data = $this->data; // Or whatever data you want to pass

$element = $template->fetch('mod/twitter/template/product/product-twitter.tpl');

$this->response->setDomEdit('add_child', 'id', 'tabs', $element);
before the end of the controller.
Also, bear in mind the output could be compressed!
That's easy enough to move around.

None of this really matters with the embedded javascript issue though. :(

-Ryan


rph
Expert Member

Posts

Joined
Fri Jan 08, 2010 5:05 am
Location - Lincoln, Nebraska

Post by dolrichfortich » Sun Feb 16, 2014 2:44 pm

Try going through dompdf or tcpdf codes, they seem to have a parser for javascript.

Opencart Options Pro, Reward Points For Review, DISQUS Comment Form,
Dolrich Fortich - Freelance web developer

Image


User avatar
New member

Posts

Joined
Thu Aug 05, 2010 8:09 pm
Location - Philippines

Post by JNeuhoff » Mon Feb 17, 2014 11:19 pm

None of this really matters with the embedded javascript issue though.
Just to make sure I correctly understood you: You basically want to parse the whole HTML template, do some DOM tree manipulation, and then output the modified DOM tree as the new template HTML. All of this while treating any script-tag as a whole DOM-node (no parsing inside the script tag). Is that correct?

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 rph » Thu Feb 20, 2014 1:58 am

It's the fully constructed output HTML, but yes. The ultimate issue is the DOMDocument class is parsing embed HTML within a <script> tag which breaks things. This question at Stackoverflow is parallel to the issue. The two main solutions (offload the javascript or load the page as XML) are unfortunately non-starters because of compatibility concerns.

The only two things left I know to try are checking out the html5lib on the off-chance that'll work or break down and use a regex.

-Ryan


rph
Expert Member

Posts

Joined
Fri Jan 08, 2010 5:05 am
Location - Lincoln, Nebraska

Post by JNeuhoff » Thu Feb 20, 2014 2:11 am

rph wrote:The ultimate issue is the DOMDocument class is parsing embed HTML within a <script> tag which breaks things.
Can't you just replace all instances of <script ....> and </script> with something like <div><!--start of script--><![CDATA[ and ]]><!--end of script--></div> before loading and parsing the HTML with a DOM parser, and reverse the replacement after the final output has been re-generated?

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 rph » Sat Feb 22, 2014 12:40 am

That was Plan Z. I really like your CDATA idea but it looks like it'll only work with well-structured XHTML. I was originally looking at commenting out the script but that has issues too which would need to be worked out.

-Ryan


rph
Expert Member

Posts

Joined
Fri Jan 08, 2010 5:05 am
Location - Lincoln, Nebraska
Who is online

Users browsing this forum: No registered users and 16 guests