protected function loadTemplate($moduleParts, $contentType, $parentTemplate, &$globals, $isFinalPass, $isDependentPass)
 {
     $this->globals = $globals;
     $template = new Template();
     $template->setContentType($contentType);
     $moduleString = $moduleParts[0];
     $moduleName = $moduleParts[1];
     $moduleParams = isset($moduleParts[3]) ? $moduleParts[3] : null;
     $parentLocals = !empty($parentTemplate) ? $parentTemplate->getLocals() : array();
     $template->setName($this->parseFormatVariables($moduleName, $parentLocals));
     if ($this->benchmarkRendering) {
         $this->Benchmark->start('load-template-' . $template->getName());
     }
     $matchString = '{% template ' . $template->getName();
     //        $this->Logger->error($template->getName());
     $usesGlobals = false;
     $deferable = false;
     $params = array();
     if (!empty($moduleParams)) {
         $matchString .= '?';
         $nvps = explode('&', html_entity_decode($moduleParams, ENT_QUOTES));
         foreach ($nvps as $param) {
             $split = explode('=', $param, 2);
             if ($split === FALSE || count($split) == 1) {
                 throw new Exception('Bad NVP in template call: ' . $moduleString);
             }
             list($name, $value) = $split;
             $dataparam = null;
             $previouslyFound = array();
             if (substr($value, 0, 1) == '%' && substr($value, -1) == '%' && strpos(substr($value, 1, -1), '%') === FALSE) {
                 $paramval = 'Data:' . substr($value, 1, -1);
                 $dataparam = substr($value, 1, -1);
                 //                    $template->setDependent(true);
                 //                    $this->Logger->debug('Marking template ['.$template->getName().'] as dependent');
             } else {
                 $paramval = $value;
                 if (strpos($paramval, 'Data:') === 0) {
                     $dataparam = substr($paramval, 5);
                     //                        $template->setDependent(true);
                     //                        $this->Logger->debug('Marking template ['.$template->getName().'] as dependent');
                     //                        $this->Logger->error('Marking template ['.$template->getName().'] as dependent');
                 } elseif (strpos($paramval, 'Global:') === 0) {
                     $dataparam = substr($paramval, 7);
                     $deferable = true;
                     $usesGlobals = true;
                 }
             }
             if (strlen($dataparam) >= 3 && strpos($dataparam, '%') !== false) {
                 $dataparam = $this->parseFormatVariables($dataparam, $parentLocals);
             }
             switch ($name) {
                 // manual datasource parameter
                 case 'data':
                     if (!empty($params)) {
                         throw new Exception("Error in template call {$moduleString} :: data parameter must be first parameter");
                     }
                     $template->setDependent(true);
                     if ($dataparam == 'DataSource') {
                         if (empty($parentTemplate)) {
                             throw new Exception('Impossible to use DataSource from non-existent parent template');
                         }
                         $template->setData($parentTemplate->getData());
                     } elseif (array_key_exists($dataparam, $parentLocals)) {
                         $template->setData($parentLocals[$dataparam]);
                     } elseif (array_key_exists($dataparam, $this->getConstants())) {
                         $template->setData($this->getConstant($dataparam));
                     } elseif (array_key_exists($dataparam, $globals)) {
                         $template->setData($globals[$dataparam]);
                     } elseif (strpos($dataparam, '.') !== false) {
                         $parts = explode('.', $dataparam);
                         if (!empty($parts)) {
                             $broken = true;
                             $array = $parentLocals;
                             foreach ($parts as $pname) {
                                 if (isset($array[$pname])) {
                                     $array = $array[$pname];
                                     $broken = false;
                                 } else {
                                     $broken = true;
                                     break;
                                 }
                             }
                             if (!$broken) {
                                 $value = $array;
                             }
                         }
                     }
                     if ($template->hasData() && !is_array($template->getData())) {
                         $template->setData(array($template->getData()));
                     }
                     //                            throw new Exception("Invalid data parameter in template call ".$moduleString.", must be an array :: $dataparam\n");
                     break;
                     // inherit all locals from parent
                 // inherit all locals from parent
                 case 'inherit':
                     if (StringUtils::strToBool($value) == true) {
                         $template->setDependent(true);
                         $newParents = $parentLocals;
                         unset($newParents['CacheTime']);
                         unset($newParents['DataSource']);
                         $params = array_merge($newParents, $params);
                     }
                     break;
                 case 'dependent':
                     if (StringUtils::strToBool($value) == true) {
                         $template->setDependent(true);
                     }
                     break;
                 default:
                     if ($dataparam != null) {
                         if ($usesGlobals) {
                             if (!$isFinalPass) {
                                 if (!empty($previouslyFound)) {
                                     $this->globals = array_merge($this->globals, $previouslyFound);
                                     $previouslyFound = array();
                                 }
                                 if (array_key_exists($dataparam, $parentLocals)) {
                                     $this->globals[$dataparam] = $parentLocals[$dataparam];
                                     $value = 'Global:' . $dataparam;
                                 }
                             } else {
                                 if (array_key_exists($dataparam, $this->getConstants())) {
                                     $value = $this->getConstant($dataparam);
                                 } elseif (array_key_exists($dataparam, $globals)) {
                                     $value = $globals[$dataparam];
                                 }
                             }
                             $template->setDeferred(true);
                         } else {
                             if (array_key_exists($dataparam, $this->getConstants())) {
                                 $value = $this->getConstant($dataparam);
                                 //                                } elseif (array_key_exists($dataparam, $this->deferredOrDependentParams)) {
                                 //                                    $value =  $this->deferredOrDependentParams[$dataparam];
                                 //                                } elseif ((!$deferable || $isFinalPass) && array_key_exists($dataparam, $globals)) {
                                 //                                    $value =  $globals[$dataparam];
                                 //                                } elseif (!$deferable && array_key_exists($dataparam, $parentLocals)) {
                             } elseif (array_key_exists($dataparam, $parentLocals)) {
                                 $value = $parentLocals[$dataparam];
                                 $previouslyFound[$dataparam] = $value;
                                 // if we're deferred or only parsing data dependent modules and this module is independent,
                                 //  save the passed parameters for later
                                 //                                    $this->Logger->error('Deferred? '.$template->isDeferred());
                                 //                                    $this->Logger->error('Independent? '.($isDependentPass && !$template->isDependent()));
                                 //                                    if ($template->isDeferred() || ($isDependentPass && !$template->isDependent())) {
                                 //                                        $c = $this->deferredOrDependentParamCount++;
                                 //                                        $this->deferredOrDependentParams[$dataparam.$c] = $parentLocals[$dataparam];
                                 //                                        $paramval = 'Data:'.$dataparam.$c;
                                 //                                        $this->Logger->error('Defer ['.$name.'] param: '.$paramval);
                                 //                                    } else {
                                 //                                        $value =  $parentLocals[$dataparam];
                                 //                                    }
                             } elseif (strpos($dataparam, '.') !== false) {
                                 $parts = explode('.', $dataparam);
                                 if (!empty($parts)) {
                                     $broken = true;
                                     $array = $parentLocals;
                                     foreach ($parts as $pname) {
                                         if (isset($array[$pname])) {
                                             $array = $array[$pname];
                                             $broken = false;
                                         } else {
                                             $broken = true;
                                             break;
                                         }
                                     }
                                     if (!$broken) {
                                         $value = $array;
                                     } else {
                                         $value = '';
                                     }
                                     //                                        elseif (!$isFinalPass && $deferable)
                                     //                                            $template->setDeferred(true);
                                 }
                                 //                                } elseif (!$isFinalPass && $deferable) {
                                 //                                    // defer setting a value until the final pass
                                 //                                    $template->setDeferred(true);
                             } else {
                                 $value = '';
                             }
                         }
                     } elseif (strlen($value) >= 4 && strpos($value, '%') !== false) {
                         $value = $this->parseFormatVariables($value, $parentLocals);
                         $paramval = $value;
                     }
                     $params[$name] = $value;
                     break;
             }
             $matchString = $matchString . $name . '=' . $paramval . '&';
         }
         $matchString = substr($matchString, 0, -1);
     }
     $matchString .= ' %}';
     $template->setMatchString($matchString);
     $template->setLocals($params);
     $this->Logger->debug("Loaded template call: " . $matchString);
     if ($this->benchmarkRendering) {
         $this->Benchmark->end('load-template-' . $template->getName());
     }
     //        $template = $this->loadTemplateExtended($template, $globals);
     return $template;
 }