We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 13370
    • 45 Posts
    I’m attempting application development via SVN using this method: http://svn.modxcms.com/docs/display/revolution/Managing+Resources+and+Elements+via+SVN. It’s working fine for snippets and static chunks, but I can’t seem to get templating/dynamic processing(http://svn.modxcms.com/docs/display/revolution/Chunks#Chunks-ProcessingChunkviatheAPI) to work properly.
    I’m using a chunk to template table rows for output similar to the example in the documentation, but when using the include snippet, I get the first row repeated. If I make the call to the include snippet uncached by adding ! to it, I don’t get the placeholders processed properly. Any suggestions?
      • 22295
      • 153 Posts
      send over your code, so we can see exactly what you do.


      I use this function in my model for the same purpose (you can find it in some components)
          public function getChunk($name,$properties = array()) {
              /* first check internal cache */
              if (!isset($this->chunks[$name])) {
                  /* if specifying chunk value in snippet properties */
                  if (!empty($this->config['tpl'.$name])) {
                      $chunk = $this->modx->newObject('modChunk');
                      $chunk->setContent($this->config['tpl'.$name]);
                  }
                  /* if using default chunk names, defaulting to files */
                  if (empty($chunk)) {
                      $chunk = $this->_getTplChunk($name);
                      if ($chunk == false) return false;
                  }
                  $this->chunks[$name] = $chunk->getContent();
              } else { /* load chunk from cache */
                  $o = $this->chunks[$name];
                  $chunk = $this->modx->newObject('modChunk');
                  $chunk->setContent($o);
              }
              $chunk->setCacheable(false);
              return $chunk->process($properties);
          }
        • 13370
        • 45 Posts
        So this is my include snippet:
        <?php
        $base_path = (isset($scriptProperties['base_path'])) ? $scriptProperties['base_path'] : '' ;
        $file_name = (isset($scriptProperties['file'])) ? $base_path.$scriptProperties['file'] : '';
        if (file_exists($file_name))
        {
            if (strrchr($file_name, '.') == '.php')
            {
                return include $file_name;
            }
            else
            {
                include $file_name;
                return '';
            }
        }
        else
        {
            $modx->log(MODX_LOG_LEVEL_ERROR,'File not found at'.$file_name);
            return '';
        }
        ?>
        


        I call it like this in a chunk:
        [[!IncludeFromFile? &base_path=`path/to/files` &file=`somefile.chunk.html`]]
        


        The included chunk code:
        <tr class="[[+rowClass]]" id="account[[+id]]">
          <td>[[+description]]</td>
          <td>[[+date]]</td>
          <td>[[+amount]]</td>
        </tr>
        


        The output then becomes:
        <tr class="" id="account">
          <td></td>
          <td></td>
          <td></td>
        </tr>
        


        So the placeholders does not seem to be processed in this case. Any suggestions?
          • 13370
          • 45 Posts
          Forgot the processing code I use (directly from example):
          	$accountcells = '';
          	foreach ($accounts as $account)
          	{
          	    $properties = $account->toArray();
          	    $accountcells .= $this->modx->getChunk($rowTpl, $properties);
          	}
          
            • 22295
            • 153 Posts
            Your getChunk calls a chunk which uses a include snippet to include a chunk, and the placeholders are not processed.

            So it should be something like this (extracted from the function i sent you):

            $properties = $account->toArray();
            $chunk = $this->modx->newObject('modChunk');
            $chunkContent = $this->modx->getSnippet('IncludeFromFile',array('file'=> $rowTpl.'chunk.html'));
            $chunk->set('name',$rowTpl); // not sure this is needed
            $chunk->setContent($chunkContent);
            $accountcells .= $chunk->process($properties);
            




            Look again at the function I sent you in the first post. (btw, i forgot one function, here it is all again)
            and just to be consistent, core team has always used ’.chunk.tpl’ and not ’.chunk.html’. it’s not mandatory to follow this, but the below script uses this naming in case you try it.

                /**
                 * Processes the content of a chunk in either of the following ways:
                 *
                 * - Should the property tpl+chunkName be set, uses that content
                 * - Otherwise, loads chunk from file
                 *
                 * Also caches the preprocessed chunk content to an array to speed loading
                 * times, especially when looping through collections.
                 *
                 * @access public
                 * @param string $name The name of the chunk to process
                 * @param array $properties (optional) An array of properties
                 * @return string The processed content string
                 */
                public function getChunk($name,$properties = array()) {
                    /* first check internal cache */
                    if (!isset($this->chunks[$name])) {
                        /* if specifying chunk value in snippet properties */
                        if (!empty($this->config['tpl'.$name])) {
                            $chunk = $this->modx->newObject('modChunk');
                            $chunk->setContent($this->config['tpl'.$name]);
                        }
                        /* if using default chunk names, defaulting to files */
                        if (empty($chunk)) {
                            $chunk = $this->_getTplChunk($name);
                            if ($chunk == false) return false;
                        }
                        $this->chunks[$name] = $chunk->getContent();
                    } else { /* load chunk from cache */
                        $o = $this->chunks[$name];
                        $chunk = $this->modx->newObject('modChunk');
                        $chunk->setContent($o);
                    }
                    $chunk->setCacheable(false);
                    return $chunk->process($properties);
                }
            
                /**
                 * Creates a temporary modChunk object from a tpl file.
                 *
                 * @access private
                 * @param string $name The name of the chunk to load from file.
                 * @return modChunk The newly created modChunk object.
                 */
                private function _getTplChunk($name) {
                    $chunk = false;
                    $f = $this->config['chunks_path'].$name.'.chunk.tpl';
                    if (file_exists($f)) {
                        $o = file_get_contents($f);
                        $chunk = $this->modx->newObject('modChunk');
                        $chunk->set('name',$name);
                        $chunk->setContent($o);
                    }
                    return $chunk;
                }
              • 13370
              • 45 Posts
              Thanks! Got it working now.

              Relating to the fix, I have a few observations:

              • http://svn.modxcms.com/docs/display/revolution/Managing+Resources+and+Elements+via+SVN does not work for template chunks. Instead, make your snippet aware of the template coming from a file, and include the file directly in the code
              • $chunk->process() cannot be called multiple times with different properties, since the output will just be cached. Instead, create a new $chunk for each ->process() call
              • $chunk->set(’name’,$rowTpl) is indeed not needed, since the name is only used for referencing, and we reference the $chunk object directly here, and do not save it to the database
                • 22303 MODX Staff
                • 10,725 Posts
                Quote from: Jacob at Apr 05, 2010, 08:45 AM

                • $chunk->process() cannot be called multiple times with different properties, since the output will just be cached. Instead, create a new $chunk for each ->process() call
                Sure it can; you have to set the instance to not be cacheable though, consider the code from the parseTpl function used by getResources that similarly loads the chunk source:
                <?php
                                $chunk = null;
                                if (!isset($_cache['@CHUNK'])) $_cache['@CHUNK'] = array();
                                if (!array_key_exists($source, $_cache['@CHUNK'])) {
                                    if ($chunk = $modx->getObject('modChunk', array('name' => $source))) {
                                        $_cache['@CHUNK'][$source] = $chunk->toArray('', true);
                                    } else {
                                        $_cache['@CHUNK'][$source] = false;
                                    }
                                } elseif (is_array($_cache['@CHUNK'][$source])) {
                                    $chunk = $modx->newObject('modChunk');
                                    $chunk->fromArray($_cache['@CHUNK'][$source], '', true, true, true);
                                }
                                if (is_object($chunk)) {
                                    $chunk->setCacheable(false);
                                    $output = $chunk->process($properties);
                                }
                ?>


                NOTE that you also do not "have" to setContent() since you can pass it specifically as the second parameter of process(). This can reduce memory usage in certain situations.

                That said, I am considering some internal improvements to the the modX::getChunk() function that will make all of this unnecessary. More on this soon.
                  • 13370
                  • 45 Posts
                  Actually, I already used $chunk->setCacheable(false), but I still got the output repeated from the first entry. I then changed it to use newObject() for each row like oori’s example, and then it worked as expected.