We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 9207 ☆ A M B ☆
    • 2,475 Posts
    I’m working on a mobile detection script -- it works, but it currently requires that the page be uncached (which I don’t like). I’m wondering a couple things and I couldn’t find them in the API docs (this is for 0.9.6.3 at the moment, but looking forward to 1.0 and 2.0):

    1. Can I cache 2 versions of the same page? In other words, even though a page has a single page ID, can I somehow cache a mobile version and a regular version of the page?
    2. How do I check to see if a cached version of a page exists using the API?
    3. How do I load a page from cache using the API?

    Any references / tips are most welcome!
    Thanks!
      • 9207 ☆ A M B ☆
      • 2,475 Posts
      Man, I looked through the core code of the manager/includes/document.parser.class.inc.php file for a solution to this, and it seems that custom caching isn’t easy with MODx Evolution. I can write my own custom versions of the cache files, but due to the location of some of the relevant events (primarily OnLoadWebPageCache -- see around line #1121) I may not get the behavior I want.

      My plan was to write 2 versions of the cache file, depending on whether or not the template was being overridden (e.g. for a mobile device), but the basic check that sees if a there is a cached version of the page uses a hardcoded file name (see the function checkCache in the same file):
      $cacheFile= "assets/cache/docid_" . $id . ".pageCache.php";


      In other words, the event is called right AFTER the cache file is read, whereas I was hoping to intercept the code immediately BEFORE the cache file was read. Bummer.

      This looks like it’d be much easier in Revolution... I really don’t want to hack the code... even if I pushed some things around in the SVN repo and released an update... chances are good that I’d fix my own plugin......... but I’d break thousands of others.
        • 29774
        • 386 Posts
        therebechips Reply #3, 17 years ago
        Hi Everett

        have you considered storing two versions of the content on the same cached page and stripping the unwanted version using the system event OnWebPagePrerender?

        This is the approach I’ve used it for my own custom multilingual solution.

        Essentially I wrap each content block in xml tags, eg <lang_en>English</lang_en> and <lang_fr>French</lang_fr>

        Then I remove the unwanted languages and wrapping tag (in my case this is contingent on the server domain)

        
        $domains  = array(
        	'en' => array('English','mysite.com','ltr'),
        	'fr' => array('Français','fr.mysite.com','ltr'),
        	);
        
        # what's the URI of the current page?
        $url = $_SERVER['REQUEST_URI'];
        
        # what's the name of the server?
        $server = $domains['en'][1]; // English by default
        $language = 'en';
        
        # check that the server name is in the predefined array before assigning it 
        # to prevent injection via headers
        foreach ($domains as $key => $value) {
        	if ($value[1] == $_SERVER["HTTP_HOST"]) {
        		$server = $value[1];
        		$language = $key;
        	}
        }
        
        
        foreach ($domains as $key => $value) {
        		if ($key != $language) {
        			$pattern = '/\<lang_'.$key.'\>(.*)\<\/lang_'.$key.'\>/Usi';
        			$modx->documentOutput = preg_replace($pattern,'',$modx->documentOutput);
        		} else {
        			// remove the wrapping tags on remaining content
        			$patterns = array('<lang_'.$key.'>','</lang_'.$key.'>');
        			$modx->documentOutput = str_replace($patterns,'',$modx->documentOutput);
        		}
        	}
        
        

          Snippets: GoogleMap | FileDetails | Related Plugin: SSL
          • 22851
          • 805 Posts
          PaulSuckling Reply #4, 17 years ago
          Yup. That’s the same basic technique that I would use and is also the same technique that the YAMS multilingual module uses.
            YAMS: Yet Another Multilingual Solution for MODx
            YAMS Forums | Latest: YAMS 1.1.9 | YAMS Documentation
            Please consider donating if you appreciate the time and effort spent developing and supporting YAMS.
            • 9207 ☆ A M B ☆
            • 2,475 Posts
            Good to know... I hadn’t seriously considered it because it seemed inefficient, but I can see that it is a viable solution. I’d have to intercept the cache writing event and put in both versions of the templates involved, too. In a way, it’s the opposite of what you’ve done: you’ve changed the content and preserved the template, whereas I want to use the same content, but change the template.

            Thanks for the tip.. I’ll look into this.
              • 22851
              • 805 Posts
              PaulSuckling Reply #6, 17 years ago
              @Everett.

              Following therebeschip’s approach, you don’t need to intercept caching or anything like that. Your main template simply becomes the following:
              <screen><!--normal template--></screen><mobile><!--mobile template goes here---></mobile>
              

              That way both normal and mobile parts of the template are subject to normal MODx caching etc and both use the same content. It’s just that only one part of the template is served when the document is requested. This only becomes a significant overhead if you have lots of uncacheable content, since the uncacheable parts will run once for the normal template and once for the mobile template.
                YAMS: Yet Another Multilingual Solution for MODx
                YAMS Forums | Latest: YAMS 1.1.9 | YAMS Documentation
                Please consider donating if you appreciate the time and effort spent developing and supporting YAMS.
                • 9207 ☆ A M B ☆
                • 2,475 Posts
                So, in other words, I’d maintain one set of templates for a site, but but within each template, I would have a portion dedicated solely to mobile browsers and a portion dedicated solely to standard "desktop" browsers, e.g.

                <!-- this is my template -->
                <mobile>
                   <html><head><title>[*pagetitle*]</title></head><body><!-- super simple streamlined formatting -->
                </moble>
                <standard>
                   <html><head><title>[*pagetitle*]</title></head><body><!-- standard, graphic intensive formatting -->
                </standard>


                And then on the OnWebPagePrerender event, I’d find and replace one or the other parts of the template? The cache file would then contain all the full template file, including both the <mobile> and <standard> parts (and the page content). Caching would function normally on any page, yes? This is a fascinating approach... I just worry about the overhead of regexing each page request, but I imagine it’s much speedier to regex a cache file than it is to re-render everything from scratch.

                Using the OnWebPagePrerender poses some changes too... currently, I’m using the OnLoadWebDocument to override the standard template with a mobile template based on either a URL parameter, a cookie value, or a browser detection script. By shifting to the <mobile> vs. <standard> dual-purpose templates, I could still rely on the URL parameters/cookie values/browser-detection scripts, but the result would determine which portion of the template to erase. Am I understanding this correctly?

                The only drawback I can see here is UI for the designers: templates would become 2 in 1 hybrids, possibly making them more confusing to work with.

                Many thanks for your clever input on this!
                  • 22851
                  • 805 Posts
                  PaulSuckling Reply #8, 17 years ago
                  Quote from: Everett at Sep 28, 2009, 02:00 PM

                  So, in other words, I’d maintain one set of templates for a site, but but within each template, I would have a portion dedicated solely to mobile browsers and a portion dedicated solely to standard "desktop" browsers, e.g.

                  <!-- this is my template -->
                  <mobile>
                     <html><head><title>[*pagetitle*]</title></head><body><!-- super simple streamlined formatting -->
                  </moble>
                  <standard>
                     <html><head><title>[*pagetitle*]</title></head><body><!-- standard, graphic intensive formatting -->
                  </standard>

                  Yes.

                  Quote from: Everett at Sep 28, 2009, 02:00 PM

                  And then on the OnWebPagePrerender event, I’d find and replace one or the other parts of the template? The cache file would then contain all the full template file, including both the <mobile> and <standard> parts (and the page content). Caching would function normally on any page, yes? This is a fascinating approach... I just worry about the overhead of regexing each page request, but I imagine it’s much speedier to regex a cache file than it is to re-render everything from scratch.
                  The overhead of a single regexp on each page load is minimal. The overhead comes with running the uncacheable content twice.

                  Quote from: Everett at Sep 28, 2009, 02:00 PM

                  Using the OnWebPagePrerender poses some changes too... currently, I’m using the OnLoadWebDocument to override the standard template with a mobile template based on either a URL parameter, a cookie value, or a browser detection script. By shifting to the <mobile> vs. <standard> dual-purpose templates, I could still rely on the URL parameters/cookie values/browser-detection scripts, but the result would determine which portion of the template to erase. Am I understanding this correctly?
                  Yes.

                  Quote from: Everett at Sep 28, 2009, 02:00 PM

                  The only drawback I can see here is UI for the designers: templates would become 2 in 1 hybrids, possibly making them more confusing to work with.
                  You could put your individual templates in chunks and do something like:
                  <!-- this is my template -->
                  <mobile>{{mobile_tpl}}</moble>
                  <standard>{{standard_tpl}}</standard>


                  By the way, I have been planning to do exactly this for quite some time. I currently have a mobile switcher implemented on one of my sites using a different approach that I don’t like. It was my first attempt and it’s a bit ill conceived. The approach above is far better in my opinion. Would it be possible to make this into some kind of standalone plugin that could be shared?
                    YAMS: Yet Another Multilingual Solution for MODx
                    YAMS Forums | Latest: YAMS 1.1.9 | YAMS Documentation
                    Please consider donating if you appreciate the time and effort spent developing and supporting YAMS.
                    • 9207 ☆ A M B ☆
                    • 2,475 Posts
                    Yes, I’ll publish this as a plugin... the one I downloaded had errors: http://modxcms.com/extras/package/557 so I revised it considerably, but as discussed, the inability of it to work with cached pages is a severe limitation.
                      • 1841
                      • 141 Posts
                      Hi I am trying to build something similiar, I am using the existing MODX plugin with a jqtouch layout but as this means only using 1 template it isn’t ideal.

                      Has anyone got any further with this method, or tested it to see if it works?