We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 8784
    • 32 Posts
    A newbie-ish dev question:
    The best way to GenerateResource cache programmatically?

    I want to generate a cache file for a resource file after a save without relying on webpage visit to spur the cache generation.

    I have a working snippet…

    $z = $modx->getCacheManager();
    $resource = $modx->getObject('modResource',1);
    $results = $z->generateResource($resource);
    


    …but I'm having trouble making this work as a plugin. I've tried "OnDocFormSave". The snippet runs but it appears the cache refresh happens after the save and removes my newly written file. "OnCacheUpdate" might work but I'd like to restrict execution to only resource edits/creation.

    Any ideas modxers?

    This question has been answered by multiple community members. See the first response.

      • 37480
      • 9 Posts
      Hey,

      did you get it to work? Can you tell me what was the best way for you?

      I'm looking for a solution to generate the whole cache for all resources programmatically.

      Martin [ed. note: gwampi last edited this post 12 years, 6 months ago.]
        • 8784
        • 32 Posts
        Quote from: gwampi at Nov 17, 2011, 12:01 PM
        Hey,
        did you get it to work? Can you tell me what was the best way for you!?

        Sorry for the long response…

        I kinda have it working but there are issues.

        But let me back up…
        My Problem:

        I have certain High-Traffic pages which cannot have database reliance on the front-end. These HT pages cannot rely on Modx's default method of cache file creation—where a web visit initiates the creation of a new cache file.
        Cache files for HT pages would be initiated whenever a "siteRefresh" system event occurs, most commonly when an editor "Saves" a page.

        Strategy:

        A plug-in, tied to the "siteRefresh" system event, would create cache files for HT pages.

        Here's how it works, basic Sample code:
        $modx->setLogLevel(modX::LOG_LEVEL_DEBUG);
        
        $HTpages = $modx->getCollection('modResource');
        
        $modx->getCacheManager();
        foreach($HTpages as $page) {
        	$results = $modx->cacheManager->generateResource($page);
        }
        $modx->log(modX::LOG_LEVEL_DEBUG, 'We wrote some cache files!!!'); 
        


        Basic description of the issues:

        I can write cache files programmatically using a snippet, but the same code called from a plug-in fails. The cache files I'm writing aren't complete, the cached snippets are being run dynamically.

        Here's a detailed look at each issue:


        Issue 1:
        For me, the 'generateResource' method fails unless I remove one of its conditions. If I comment out the check for "$obj->getProcessed()" in core/model/modx/modcachemanager.class.php the method works perfectly.
        Here's the working code compared to modx default:
        //Modx original code. This fails: 
        if (is_object($obj) && $obj instanceof modResource && $obj->getProcessed() && $obj->get('cacheable') && $obj->get('id')) {
        //Modified code. This works (kindof): 
        if (is_object($obj) && $obj instanceof modResource /*&& $obj->getProcessed()*/ && $obj->get('cacheable') && $obj->get('id')) {
        


        Issue 2:
        If the cache file is created by my modified version of “generateResource” (see above) it’s different than the cache Modx creates by default. Snippets aren't parsed. If the page contains a cached snippet, the output is not rendered. The snippet is called uncached on every page load. See the difference below.

        Here's a bit of Modx's default cache file:
         
         '_content' => '
        This is the time (cached): Thursday 17th of November 2011 12:04:30 PM
        This is the time (UNcached): [[!test time]]
        ',
        

        And here's my cache file created with "generateResource", notice '_content' is blank:
         
        '_content' => '',
        


        Issue 3:
        In this file: '/core/model/modx/processors/resource/update.php'
        Updating a resource does not fire a "onSiteRefresh" event, even though site's cache is cleared (line 486) whenever a resource is updated. I had to add this code (to line 492):
         
        /* invoke OnSiteRefresh event */
        $modx->invokeEvent('OnSiteRefresh');
        


        Issue 4:
        The plug-in is executing the "Sample code" (see above), I can I see it writing a log entry, but the files are not written. If the same code is run from a snippet, the files are written.
        The code is called from the plug-in (and snippet) like this:
         
        <?php
        include_once('/a/server/path/phpClasses/generateCacheFiles.php');
        


        So I can write cache files programmatically using a snippet, but the same code called from a plug-in fails.
        The cache files I'm writing aren't complete, the cached snippets are being run dynamically.

        Hope this helps, I'm open to any help/suggestions. [ed. note: elvispresley2k last edited this post 12 years, 6 months ago.]
          • 37480
          • 9 Posts
          Thank you for the great answer!

          I got the same problem, that it is not working in the plugin. In the snippet, it is kind of working....

          Possible solutions:

          Issue 1: If you process the resource before generating it. Shouldn't this solve this issue?

              $page->process();
              $results = $modx->cacheManager->generateResource($page);
          


          Issue 2: Maybe the second argument of getcollection() could solve this issue! You can set criteria to define what to include in the result. That's what getresources is doing as well. They have different criteria if you set the parameter includecontent. I think that this might be the problem here too, because you want to include the content!

          I would need to include the TVs as well. But I didn't really understand these criteria yet wink I need another look at it!
            • 8784
            • 32 Posts
            Quote from: gwampi at Nov 18, 2011, 09:25 AM
            Thank you for the great answer!
            I got the same problem, that it is not working in the plugin. In the snippet, it is kind of working....
            Possible solutions:
            Issue 1: If you process the resource before generating it. Shouldn't this solve this issue?
                $page->process();
                $results = $modx->cacheManager->generateResource($page);
            


            Yes! This solves both Issue 1 AND 2.

            I was looking for this method, wasn't sure how to implement it.

            "$page->process()" seems to work. When I cache a page myself the cached snippet it contains is output to the cache file. An example, here's the raw content of the page (ID 1) to be cached. It contains both a cached and uncached snippet:
               
            [[test time?]] This is a timestamp (Cached)
            
            [[!test time]] This is a timestamp (UNcached)
            

            And here's my written cache file "_content" for ID 1:
               
            Sunday 20th of November 2011 09:30:29 AM This is a timestamp (Cached)
            
            [[!test time]] This is a timestamp (UNcached)
            

            (The cached snippet is being processed as expected.)

            I do notice the cache file I create for ID 1 is different than the default cache file Modx creates for the same page. My cache file is larger. It includes some data about the other page (ID 3) calling the generateResource snippet. This does not seem to affect the ultimate output however, so I hope it's not a big deal. [ed. note: elvispresley2k last edited this post 12 years, 6 months ago.]
              • 8784
              • 32 Posts
              So two questions remain:

              Issue 3:
              Updating a page does NOT fire a "onSiteRefresh" event. Is this a bug?
              The page in question: '/core/model/modx/processors/resource/update.php'


              Issue 4:
              While generateResource writes files when called from a snippet, the same code when called from a plug-in does NOT write files. Also a bug?

              Actually, I guess I have another question too:

              When I write my own cache file with generateResource, can I set a custom expiration time for the cache file? I want to put a very long expiration time on the file (1 year?)--so Modx never tries to refresh the cache file on its own.

              [Edit, poking around]
              It seems "cache_resource_expires" is used by generateResource() and defaults to '0' (never expires)?
              http://rtfm.modx.com/display/revolution20/cache_resource_expires [ed. note: elvispresley2k last edited this post 12 years, 6 months ago.]
                • 3749
                • 24,544 Posts
                It looks like if $scriptProperties['clearCache'] or $scriptProperties['syncsite'] are set, the resource update processor calls cachemanager->refresh() which fires OnSiteRefresh.

                I would assume that if "clear cache" is checked on the Create/Edit Resource page (as it is by default), that would happen, but I'm not sure.
                  Did I help you? Buy me a beer
                  Get my Book: MODX:The Official Guide
                  MODX info for everyone: http://bobsguides.com/modx.html
                  My MODX Extras
                  Bob's Guides is now hosted at A2 MODX Hosting
                  • 8784
                  • 32 Posts
                  Hi BobRay,

                  For me, 'update.php' wasn't firing the event (I'll double check this however.)

                  See the comments in the code below. (This a modification beginning at line 484 of update.php.)

                  if (!empty($scriptProperties['syncsite']) || !empty($scriptProperties['clearCache'])) {
                      /* empty cache */
                      $modx->cacheManager->refresh(array(
                          'db' => array(),
                          'auto_publish' => array('contexts' => array($resource->get('context_key'))),
                          'context_settings' => array('contexts' => array($resource->get('context_key'))),
                          'resource' => array('contexts' => array($resource->get('context_key'))),
                      ));
                      /* I could see the if statement was occurring because of this log statement... */
                  	$modx->log(modX::LOG_LEVEL_DEBUG, 'The site refresh happened.'); 
                      /* But I had to add invokeEvent to get plug-in to fire... */
                  	$modx->invokeEvent('OnSiteRefresh');
                  }
                    • 3749
                    • 24,544 Posts
                    How are you triggering update.php?
                      Did I help you? Buy me a beer
                      Get my Book: MODX:The Official Guide
                      MODX info for everyone: http://bobsguides.com/modx.html
                      My MODX Extras
                      Bob's Guides is now hosted at A2 MODX Hosting
                      • 8784
                      • 32 Posts
                      Okay, here's my test to see if the code in update.php fires the siteRefresh event. (The only modification here is adding a log entry to confirm the refresh occurred.)
                      if (!empty($scriptProperties['syncsite']) || !empty($scriptProperties['clearCache'])) {
                          /* empty cache */
                          $modx->cacheManager->refresh(array(
                              'db' => array(),
                              'auto_publish' => array('contexts' => array($resource->get('context_key'))),
                              'context_settings' => array('contexts' => array($resource->get('context_key'))),
                              'resource' => array('contexts' => array($resource->get('context_key'))),
                          ));
                          /* confirm refresh happened: */
                          $modx->setLogLevel(modX::LOG_LEVEL_DEBUG);
                      	$modx->log(modX::LOG_LEVEL_DEBUG, 'The refresh happened.'); 
                      }


                      Here's my plug-in:
                      <?php
                      /* confirm plugin fired: */
                      $modx->setLogLevel(modX::LOG_LEVEL_DEBUG);
                      $modx->log(modX::LOG_LEVEL_DEBUG, 'The plugin fired.');


                      Here's the log results. The update.php site refresh happens as the log attests, but the plug-in does not fire:
                      [2011-11-20 23:03:07] (DEBUG @ /modxRevo/connectors/resource/index.php) The refresh happened.


                      [ed. note: elvispresley2k last edited this post 12 years, 6 months ago.]