/**
  * This function parses the os-template and os-data script tags.
  * It's of vital importance to call this function *before* the rewriteContent function
  * since the html/dom parser of the later breaks, mangles and otherwise destroys the
  * os template/data script tags. So we need to expand the templates to pure html
  * before we can proceeed to dom parse the resulting document
  *
  * @param string $content html to parse
  * @return string
  */
 public function parseTemplates($content)
 {
     $osTemplates = array();
     $osDataRequests = array();
     // First extract all the os-data tags, and execute those in a single combined request, saves latency
     // and is consistent with other server implementations
     preg_match_all('/(<script[^>]*type="text\\/(os-data)"[^>]*>)(.*)(<\\/script>)/imsxU', $content, $osDataRequests);
     $osDataRequestsCombined = '';
     foreach ($osDataRequests[0] as $match) {
         $osDataRequestsCombined .= $match . "\n";
         // Remove the reference from the html document
         $content = str_replace($match, '', $content);
     }
     if (!empty($osDataRequestsCombined)) {
         $this->performDataRequests($osDataRequestsCombined);
     }
     preg_match_all('/(<script[^>]*type="text\\/(os-template)"[^>]*>)(.*)(<\\/script>)/imxsU', $content, $osTemplates);
     $templateLibrary = false;
     if (count($osTemplates[0])) {
         // only load the template parser if there's any templates in the gadget content
         require_once 'src/gadgets/templates/TemplateParser.php';
         require_once 'src/gadgets/templates/TemplateLibrary.php';
         $templateLibrary = new TemplateLibrary($this->gadget->gadgetContext);
         if ($this->gadget->gadgetSpec->templatesRequireLibraries) {
             foreach ($this->gadget->gadgetSpec->templatesRequireLibraries as $library) {
                 $templateLibrary->addTemplateLibrary($library);
             }
         }
         foreach ($osTemplates[0] as $match) {
             if (!$this->gadget->gadgetSpec->templatesDisableAutoProcessing && ($renderedTemplate = $this->renderTemplate($match, $templateLibrary)) !== false) {
                 // Template was rendered, insert the rendered html into the document
                 $content = str_replace($match, $renderedTemplate, $content);
             } else {
                 /*
                  * The template could not be rendered, this could happen because:
                  * - @require is present, and at least one of the required pieces of data is unavailable
                  * - @name is present
                  * - @autoUpdate == true
                  * - $this->gadget->gadgetSpec->templatesDisableAutoProcessing is set to true
                  * So set a magic marker (<template_$index>) that after the dom document parsing will be replaced with the original script content
                  */
                 $index = count($this->unparsedTemplates);
                 $this->unparsedTemplates[$index] = $match;
                 $content = str_replace($match, "<template_{$index}></template_{$index}>", $content);
             }
         }
     }
     return $content;
 }