X-Cart: shopping cart software

X-Cart forums (https://forum.x-cart.com/index.php)
-   Dev Questions (X-Cart 5) (https://forum.x-cart.com/forumdisplay.php?f=56)
-   -   How to integrate X-Cart 5 with a CMS site: Tutorial (https://forum.x-cart.com/showthread.php?t=70436)

drholmes 11-06-2014 06:07 AM

How to integrate X-Cart 5 with a CMS site: Tutorial
 
Hi,

I've been struggling for a while to get content pulled from our CMS, and I finally worked it out. The X-Cart documentation leaves much to be desired, so I'm trying to post the tutorial I wish I had, so somebody else may save the time.


This is a pretty hard-coded example because I have a specific problem to solve, and I'm trying not to have to become an expert on the entire X-Cart class structure just to do this thing. Two things would be worth it to do for this to be a more useful module for everyone:

  • It ought to be configurable in a control panel. Everything is hard-coded into the module.
  • It ought to have more ways to pull from the CMS, for example just pulling a single CMS page and using HTML comments (e.g. <!-- HEADER START/END --> to extract the parts you need.
So the objective is:This way, we can get our site CSS and Javascript into the header, and the top and bottom of our page HTML will appear before and after all of X-Cart.

CREATING THE MODULE

Create a folder xcart/classes/XLite/Module/HCW/CMSContent <-- HCW is the name of our company, CMSContent is the name of the module.

Inside that folder, create a file Main.php containing:

Code:

<?php
namespace XLite\Module\HCW\CMSContent;


abstract class Main extends \XLite\Module\AModule
{
    /**
    * Author name
    *
    * @return string
    */
    public static function getAuthorName()
    {
        return 'HCW';
    }

    /**
    * Module name
    *
    * @return string
    */
    public static function getModuleName()
    {
        return 'CMS Content';
    }

    /**
    * Get module major version
    *
    * @return string
    */
    public static function getMajorVersion()
    {
        return '5.1';
    }

    /**
    * Module version
    *
    * @return string
    */
    public static function getMinorVersion()
    {
        return 0;
    }

    /**
    * Module description
    *
    * @return string
    */
    public static function getDescription()
    {
        return 'Pulls CMS Content and renders it into <head> tag, after <body> and before </body>';
    }
}



Nothing special here, this is the default blank module example from X-Cart's website.

Next, create a folder View in your module folder (total path will be xcart/classes/XLite/Module/HCW/CMSContent/View). Inside that folder, we're creating 3 nearly identical files. I'll paste them first and explain afterwards:

Create the file PullHeadContent.php:

Code:

<?php

namespace XLite\Module\HCW\CMSContent\View;

/**
* @ListChild (list="head", zone="customer", weight="10000")
*/

class PullHeadContent extends \XLite\View\AView
{
    protected function getDefaultTemplate()
    {
        return 'modules/HCW/CMSContent/head.tpl';
    }
   
    public function pullCMSHeadContent()
    {
        return file_get_contents("http://www.example.com/headcontent.html");
    }
}



Create the file PullBodyTopContent.php:

Code:

<?php

namespace XLite\Module\HCW\CMSContent\View;

/**
* @ListChild (list="body", zone="customer", weight="-10000")
*/

class PullBodyTopContent extends \XLite\View\AView
{
    protected function getDefaultTemplate()
    {
        return 'modules/HCW/CMSContent/bodytop.tpl';
    }
   
    public function pullCMSBodyTopContent()
    {
        return file_get_contents("http://www.example.com/bodytopcontent.html");
    }
}



And finally, create the file PullBodyBottomContent.php:

Code:

<?php

namespace XLite\Module\HCW\CMSContent\View;

/**
* @ListChild (list="body", zone="customer", weight="99999")
*/

class PullBodyBottomContent extends \XLite\View\AView
{
    protected function getDefaultTemplate()
    {
        return 'modules/HCW/CMSContent/bodybottom.tpl';
    }
   
    public function pullCMSBodyBottomContent()
    {
        return file_get_contents("http://www.example.com.com/bodybottomcontent.html");
    }
}



What to notice:
  • How this works is that the getDefaultTemplate() function (which is a required function) tells X-Cart the path to the template file (we'll do that one in a minute)
  • The template file will contain the template code that calls the pullCMSBodyBottomContent()
  • Notice the @ListChild command in the comment block. That's not a comment, that's an actual command to select which list (part of page) it goes into, and its weight (order). The body contents both go into the body list, but one goes at the top (weight=-10000), another goes at the bottom (weight=99999).
  • Make sure that if you change the name of the module that you change all the namespaces as well, otherwise Re-deploy crashes.
  • Be aware that the class inside the module must have the same name as the PHP file. If you change the PHP file to "HelloThere.php", the class must become "class HelloThere {}". Otherwise it won't compile.
CREATING THE TEMPLATES:

The templates go inside the skin, so create the folder xcart/skins/default/en/modules/HCW/CMSContent/ (you're creating only the HCW/CMSContent folders, the rest are already there). Inside that, create 3 files:

Create head.tpl (this is lowercase on purpose):

Code:

{pullCMSHeadContent():h}


Create bodytop.tpl:

Code:

{pullCMSBodyTopContent():h}


And finally, create bodybottom.tpl:

Code:

{pullCMSBodyBottomContent():h}


What to notice:
  • This is the Flexy template code that calls the function we defined in the module.
  • Notice the ":h" flag after the function call. This ensures that the output is rendered untouched. Without this flag, your CMS HTML is escaped (< becomes &lt;), and is useless.
Redeploy the store, activate the module, Redeploy the store again, and you're good to go:

PRACTICAL PROBLEMS:
  • Pulling from a CMS should be fast if the pages are cached. On the very first load, the CMS caches the pages, and then the next time X-Cart fetches, Apache is serving the HTML from a static cache. Make sure that caching is enabled in your CMS for these pages that you pull from.
  • It's problematic to overlay two sites' CSS on top of each other, and there's some weirdness that has to be worked out. Everybody is fighting to control all the tags.
So, I hope this solves somebody's problem. Feel free to ask questions, but remember, I'm not an expert on X-Cart, I'm just a guy trying to figure it out.

Per

totaltec 11-06-2014 01:18 PM

Re: How to integrate X-Cart 5 with a CMS site: Tutorial
 
Very nicely done sir. I'm sure this will help others.

drholmes 11-06-2014 01:43 PM

Re: How to integrate X-Cart 5 with a CMS site: Tutorial
 
Thanks, Mike.

Here's the variation I talked about. Many people will have a CMS where they can't just break the page up into individual chunks in different HTML pages. Instead, they'll be able to put some comments into their CMS template, and then the following alternative pullCMSHeadContent() function will extract the part they marked:

Code:

public function pullCMSHeadContent()
{   
    $source = file_get_contents("http://www.example.com/blankpage.html");
   
    $startMarker = "<!-- HEAD START -->";
    $endMarker = "<!-- HEAD END -->";

    $startPos = strpos($source, $startMarker);
    $endPos = strpos($source, $endMarker);

    if ($startPos === false || $endPos === false)
        return '';

    $startMarkerLen = strlen($startMarker);

    $output = substr($source, $startPos + $startMarkerLen, ($endPos - $startPos) - $startMarkerLen);
    return $output;
}


Then using CNN.com as an example, here's how you would modify your basic CMS template (the same template used for all pages in your CMS):

Code:

<link href="http://www.cnn.com/" rel="canonical"/>
<link href="http://www.cnn.com/favicon.ie9.ico" rel="Shortcut Icon" type="image/x-icon"/>
<link href="/tools/search/cnncom.xml" rel="search" title="CNN.com" type="application/opensearchdescription+xml"/>
<!-- HEAD START -->
<link href="/tools/search/cnncomvideo.xml" rel="search" title="CNN.com Video" type="application/opensearchdescription+xml"/>
<link href="http://i.cdn.turner.com/cnn/.e/img/3.0/global/misc/apple-touch-icon.png" rel="apple-touch-icon" type="image/png"/>
<link href="http://rss.cnn.com/rss/cnn_topstories.rss" rel="alternate" title="CNN - Top Stories [RSS]" type="application/rss+xml"/>
<link href="http://rss.cnn.com/rss/cnn_latest.rss" rel="alternate" title="CNN - Recent Stories [RSS]" type="application/rss+xml"/>
<!-- HEAD END -->
<link href="http://edition.cnn.com" hreflang="en-gb" rel="alternate" title="CNN International" type="text/html"/>
<link href="http://arabic.cnn.com" hreflang="ar" rel="alternate" title="CNN Arabic" type="text/html"/>
<link href="http://mexico.cnn.com" hreflang="es" rel="alternate" title="CNN Mexico" type="text/html"/>


So you just put HTML comments into your main CMS template, and these parts get reused in X-Cart. If you make a blank page, and then insert this for your <head> content (exclude the <title> tag, it's better that X-Cart generates it, you mark another range for after <body> until the content, and the final range for after-content-until-</body>, then X-Cart gets wrapped into your site.

A little caveat, this adds CPU overhead. Especially because you're pulling the same page 3 times. Even if it's coming from a static cache, it's three times processing. It would be better to store it and use it three times. Or to only extract your segments one time and store them until the source has changed.

Anyway, these examples are very basic, I just feel that that's what we need in order to get a handle on the massive X-Cart structure. And they're just to show the principle as I imagine it. This isn't, and shouldn't be rocket science. I've just been stumped with the X-Cart documentation, which reads like a phone book, and there are bugs in the examples, so I've actually spent two days getting to this Hello World example.

But I have it running beautifully here. The rest of the stuff we do runs directly on the database, so I won't likely need to write any more modules. That's why I was trying to avoid getting a whole education in X-Cart development just to do this one thing :-)

Best,

Per


Per


All times are GMT -8. The time now is 12:53 PM.

Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.