/**
  * Lists any debug logs
  */
 function showLogs()
 {
     /* @var $wp_rewrite WP_Rewrite */
     global $wp_rewrite;
     $siteDiagnosticsURL = home_url();
     if (!$wp_rewrite->using_permalinks()) {
         $siteDiagnosticsURL .= "?";
     }
     $files = scandir($this->logDirectory, SCANDIR_SORT_DESCENDING);
     $data = new stdClass();
     $data->LOGS = array();
     foreach ($files as $file) {
         if ($file == '.' || $file == '..' || $file == 'index.html') {
             continue;
         }
         $item = new stdClass();
         $item->logfile = $file;
         $item->siteDiagnosticsURL = $siteDiagnosticsURL;
         $data->LOGS[] = $item;
     }
     $template = new EasyRecipePlusTemplate(EasyRecipePlus::$EasyRecipePlusDir . "/templates/easyrecipe-debuglogs.html");
     $html = $template->replace($data);
     header("HTTP/1.1 200 OK");
     header("Content-Length: " . strlen($html));
     echo $html;
     exit;
 }
    /**
     * Insert the easyrecipe dialogs and template HTML at the end of the
     * page - they're display:none by default
     */
    function addDialogHTML()
    {
        global $post;
        if (!$this->isGuest && !isset($post)) {
            return;
        }
        $data = new stdClass();
        $data->isSelfRated = $this->settings->ratings == 'SelfRated';
        $template = new EasyRecipePlusTemplate(self::$EasyRecipePlusDir . "/templates/easyrecipe-entry.html");
        echo $template->replace($data);
        $template = new EasyRecipePlusTemplate(self::$EasyRecipePlusDir . "/templates/easyrecipe-select.html");
        echo $template->replace();
        $data = new stdClass();
        $data->easyrecipeURL = self::$EasyRecipePlusUrl;
        $template = new EasyRecipePlusTemplate(self::$EasyRecipePlusDir . "/templates/easyrecipe-convert.html");
        echo $template->replace($data);
        $template = new EasyRecipePlusTemplate(self::$EasyRecipePlusDir . "/templates/easyrecipe-htmlwarning.html");
        echo $template->getTemplateHTML();
        /**
         * Get the basic data template
         * We need to preserve comments here because the template is processed by the javascript template engine and it needs the INCLUDEIF/REPEATS
         */
        $template = new EasyRecipePlusTemplate(self::$EasyRecipePlusDir . "/templates/easyrecipe-template.html");
        $html = $template->getTemplateHTML(EasyRecipePlusTemplate::PRESERVECOMMENTS);
        $html = preg_replace('/\\n */', ' ', $html);
        $html = trim(str_replace("'", "\"", $html));
        /*
         * Unless this is a guest post, get the URL we can test at Google (as long as it's published)
         */
        if (!$this->isGuest) {
            $testURL = $post->post_status == 'publish' ? urlencode(get_permalink($post->ID)) : '';
        } else {
            $testURL = '';
        }
        if ($this->isGuest) {
            /** @var $guestAuthor WP_User */
            $guestAuthor = get_user_by('id', $this->settings->gpUserID);
            /** @noinspection PhpUndefinedFieldInspection */
            $author = str_replace("'", '\\x27', json_encode(str_replace('"', '\\"', $guestAuthor->data->display_name)));
        } else {
            $author = str_replace("'", '\\x27', json_encode(str_replace('"', '\\"', $this->settings->author)));
        }
        $cuisines = str_replace("'", '\\x27', json_encode(explode('|', str_replace('"', '\\"', $this->settings->cuisines))));
        $recipeTypes = str_replace("'", '\\x27', json_encode(explode('|', str_replace('"', '\\"', $this->settings->recipeTypes))));
        $ingredients = str_replace("'", '\\x27', json_encode(str_replace('"', '\\"', $this->settings->lblIngredients)));
        $instructions = str_replace("'", '\\x27', json_encode(str_replace('"', '\\"', $this->settings->lblInstructions)));
        $notes = str_replace("'", '\\x27', json_encode(str_replace('"', '\\"', $this->settings->lblNotes)));
        if (!function_exists('get_upload_iframe_src')) {
            require_once ABSPATH . 'wp-admin/includes/media.php';
        }
        // $upIframeSrc = get_upload_iframe_src();
        $guestPost = $this->isGuest ? 'true' : 'false';
        $noWarn = $this->settings->noHTMLWarn ? 'true' : 'false';
        $wpurl = get_bloginfo('wpurl');
        $url = self::$EasyRecipePlusUrl;
        $pluginVersion = self::$pluginVersion;
        echo <<<EOD
<script type="text/javascript">
/* <![CDATA[ */
window.EASYRECIPE = window.EASYRECIPE || {};
EASYRECIPE.ingredients ='{$ingredients}';
EASYRECIPE.instructions ='{$instructions}';
EASYRECIPE.notes ='{$notes}';
EASYRECIPE.version = '{$pluginVersion}';
EASYRECIPE.easyrecipeURL = '{$url}';
EASYRECIPE.recipeTemplate = '{$html}';
EASYRECIPE.testURL = '{$testURL}';
EASYRECIPE.author = '{$author}';
EASYRECIPE.recipeTypes = '{$recipeTypes}';
EASYRECIPE.cuisines = '{$cuisines}';
EASYRECIPE.isGuest = {$guestPost};
EASYRECIPE.wpurl = '{$wpurl}';
EASYRECIPE.wpVersion = '{$this->wpVersion}';
EASYRECIPE.postID = {$post->ID};
EASYRECIPE.noHTMLWarn = {$noWarn};
/* ]]> */
</script>
EOD;
    }
 /**
  * Get the post, extract the recipe and combine with the current style and output it
  *
  * @param integer $postID The post ID to print
  * @param integer $recipeIX The zero based index of the recipe in the post
  */
 public function printRecipe($postID, $recipeIX)
 {
     /** @var $wpdb wpdb */
     global $wpdb;
     $settings = EasyRecipePlusSettings::getInstance();
     /**
      * Be paranoid and force the ID to an integer
      */
     $postID = (int) $postID;
     $q = "SELECT * FROM {$wpdb->posts} WHERE ID = {$postID}";
     $post = $wpdb->get_row($q);
     if (!$post) {
         return;
     }
     /**
      * Process the [br] shortcodes and remove the spurious <br>'s that wp_auto() inserts
      */
     $content = str_replace("[br]", "<br>", $post->post_content);
     $content = preg_replace('%</div>\\s*</p></div>%im', '</div></div>', $content);
     $content = $this->plugin->possiblyConvert($postID, $post->post_type, $content);
     $postDOM = new EasyRecipePlusDocument($content);
     if (!$postDOM->isEasyRecipe) {
         return;
     }
     /**
      * If the post is formatted already then it came from the Object cache (?)
      * If that's the case we need to re-read the original
      */
     if ($postDOM->isFormatted) {
         $post = $wpdb->get_row("SELECT * FROM " . $wpdb->prefix . "posts WHERE ID = {$postID}");
         $content = str_replace("[br]", "<br>", $post->post_content);
         $content = preg_replace('%</div>\\s*</p></div>%im', '</div></div>', $content);
         $content = $this->plugin->possiblyConvert($postID, '', $content);
         $postDOM = new EasyRecipePlusDocument($content);
         if (!$postDOM->isEasyRecipe) {
             return;
         }
     }
     if (isset($_GET['style'])) {
         $styleName = $_GET['style'];
     } else {
         $styleName = $settings->printStyle;
     }
     //        $printStyleData = call_user_func(array($this->stylesClass, 'getStyleData'), $styleName, $settings->get('customTemplates'), true);
     $printStyleData = EasyRecipePlusStyles::getStyleData($styleName, $settings->customTemplates, true);
     if (get_locale() != 'en_US') {
         EasyRecipePlusTemplate::setTranslate('easyrecipe');
     }
     /**
      * Fix possibly broken times in older posts
      * Fix the Cholesterol oops in early versions
      */
     if ($postDOM->recipeVersion < '3') {
         $postDOM->fixTimes("preptime");
         $postDOM->fixTimes("cooktime");
         $postDOM->fixTimes("duration");
         $postDOM->setParentValueByClassName("cholestrol", $settings->lblCholesterol, "Cholestrol");
     }
     $postDOM->setSettings($settings);
     $data = new stdClass();
     $data->hasRating = false;
     $data->convertFractions = $settings->convertFractions;
     $settings->getLabels($data);
     $data->hasLinkback = $settings->allowLink;
     $data->title = $post->post_title;
     $data->blogname = get_option("blogname");
     $data->recipeurl = get_permalink($post->ID);
     $data->customCSS = $this->plugin->getCSS('Print');
     $data->extraPrintHeader = $settings->extraPrintHeader;
     $data->easyrecipeURL = EasyRecipePlus::$EasyRecipePlusUrl;
     $recipe = $postDOM->getRecipe($recipeIX);
     $photoURL = $postDOM->findPhotoURL($recipe);
     $data->hasPhoto = !empty($photoURL);
     $data->jqueryjs = self::JQUERYJS;
     $data->jqueryuijs = self::JQUERYUIJS;
     $data->jqueryuicss = self::JQUERYUICSS;
     if (current_user_can('edit_posts')) {
         $data->isAdmin = true;
         $data->formatDialog = $this->plugin->getFormatDialog($printStyleData, true);
         $cssLink = '<link href="' . EasyRecipePlus::$EasyRecipePlusUrl . '/css/%s?version=' . EasyRecipePlus::$pluginVersion . '" rel="stylesheet" type="text/css"/>';
         $jsLink = '<script type="text/javascript" src="' . EasyRecipePlus::$EasyRecipePlusUrl . '/js/%s?version=' . EasyRecipePlus::$pluginVersion . '"></script>';
         $data->formatCSS = sprintf($cssLink, 'easyrecipe-format-min.css');
         $data->formatJS = sprintf($jsLink, 'easyrecipe-format-min.js');
     } else {
         $data->formatDialog = '';
         $data->printJS = '<script type="text/javascript" src="' . EasyRecipePlus::$EasyRecipePlusUrl . '/js/easyrecipe-print-min.js?version=' . EasyRecipePlus::$pluginVersion . '"></script>';
     }
     $data->style = $styleName;
     if ($data->style[0] == '_') {
         $style = substr($data->style, 1);
         $data->css = "/easyrecipe-printstyle";
         $templateFile = $settings->customTemplates . "/printstyles/{$style}/style.html";
     } else {
         $data->css = EasyRecipePlus::$EasyRecipePlusUrl . "/printstyles/{$data->style}";
         $templateFile = EasyRecipePlus::$EasyRecipePlusDir . "/printstyles/{$data->style}/style.html";
     }
     $data->css .= "/style.css?version=" . EasyRecipePlus::$pluginVersion . ".{$printStyleData->version}";
     $template = new EasyRecipePlusTemplate($templateFile);
     /**
      * Brain dead IE shows "friendly" error pages (i.e. it's non-compliant) so we need to force a 200
      */
     header("HTTP/1.1 200 OK");
     /**
      * Set the character encoding explicitly
      */
     $charset = get_bloginfo('charset');
     header("Content-Type:text/html; charset={$charset}");
     echo $postDOM->formatRecipe($recipe, $template, $data);
     flush();
     exit;
 }
 /**
  * Convert another recipe plugin's data to an EasyRecipe base template
  *
  * @param int $postID The recipe's post ID
  * @param string $plugin The plugin we're converting from
  *
  * @return string
  */
 function convertHTML($postID, $plugin = '')
 {
     /**
      * TODO - The conversion process isn't exactly optimal - it's the result of a series of quick hacks over time and needs to be rewritten
      */
     $result = $this->doConvert($postID, $plugin);
     $data = new stdClass();
     $data->INGREDIENTS = array();
     foreach ($result->ingredients as $ingredient) {
         $item = new stdClass();
         if ($ingredient[0] == '!') {
             $item->hasHeading = true;
             $item->ingredient = substr($ingredient, 1);
         } else {
             $item->ingredient = $ingredient;
         }
         $data->INGREDIENTS[] = $item;
     }
     $result = $result->recipe;
     $data->name = $result->recipe_title;
     $data->hasPhoto = !empty($result->recipe_image);
     $data->photoURL = $data->hasPhoto ? $result->recipe_image : '';
     $data->cuisine = isset($result->cuisine) ? $result->cuisine : '';
     $data->type = isset($result->mealType) ? $result->mealType : '';
     if ($result->cook_time == '') {
         $result->cook_time = 'PT0M';
     }
     $space = '';
     $cookTime = 0;
     if (preg_match('/PT(?:(\\d+)H)?(\\d+)M/', $result->cook_time, $regs)) {
         $time = '';
         if (!empty($regs[1])) {
             $time = $regs[1] . ' hour' . ($regs[1] > 1 ? 's' : '');
             $cookTime = 60 * $regs[1];
             $space = ' ';
         }
         $time .= $space . $regs[2] . ' min' . ($regs[2] > 1 ? 's' : '');
         $data->cooktimeISO = $result->cook_time;
         $data->cooktime = $time;
         $cookTime += $regs[2];
     }
     if ($result->prep_time == '') {
         $result->prep_time = 'PT0M';
     }
     $space = '';
     $prepTime = 0;
     if (preg_match('/PT(?:(\\d+)H)?(\\d+)M/', $result->prep_time, $regs)) {
         $time = '';
         if (!empty($regs[1])) {
             $time = $regs[1] . ' hour' . ($regs[1] > 1 ? 's' : '');
             $prepTime = 60 * $regs[1];
             $space = ' ';
         }
         $time .= $space . $regs[2] . ' min' . ($regs[2] > 1 ? 's' : '');
         $data->preptimeISO = $result->prep_time;
         $data->preptime = $time;
         $prepTime += $regs[2];
     }
     if (empty($result->total_time)) {
         $totalTime = $cookTime + $prepTime;
         $hrs = floor($totalTime / 60);
         $mins = $totalTime % 60;
         $result->total_time = 'PT';
         if ($hrs > 0) {
             $result->total_time .= $hrs . 'H';
         }
         $result->total_time .= $mins . 'M';
     }
     $space = '';
     if (preg_match('/PT(?:(\\d+)H)?(\\d+)M/', $result->total_time, $regs)) {
         $time = '';
         if (!empty($regs[1])) {
             $time = $regs[1] . ' hour' . ($regs[1] > 1 ? 's' : '');
             $space = ' ';
         }
         $time .= $space . $regs[2] . ' min' . ($regs[2] > 1 ? 's' : '');
         $data->totaltimeISO = $result->total_time;
         $data->totaltime = $time;
     }
     $data->STEPS = array();
     $step = new stdClass();
     $step->INSTRUCTIONS = array();
     $instructions = explode("\n", $result->instructions);
     foreach ($instructions as $instruction) {
         if (trim($instruction) !== '') {
             if ($instruction[0] == '!') {
                 if (count($step->INSTRUCTIONS) > 0 || !empty($step->heading)) {
                     $data->STEPS[] = $step;
                 }
                 $step = new stdClass();
                 $step->INSTRUCTIONS = array();
                 $step->heading = substr($instruction, 1);
             } else {
                 $item = new stdClass();
                 $item->instruction = $instruction;
                 $step->INSTRUCTIONS[] = $item;
             }
         }
     }
     if (count($step->INSTRUCTIONS) > 0 || !empty($step->heading)) {
         $data->STEPS[] = $step;
     }
     $data->yield = empty($result->yield) ? '' : $result->yield;
     $data->summary = empty($result->summary) ? '' : $result->summary;
     $data->servesize = empty($result->serving_size) ? '' : $result->serving_size;
     $data->notes = empty($result->notes) ? '' : $result->notes;
     $data->notes = preg_replace('/\\r?\\n/i', '[br]', $result->notes);
     if (!empty($result->nutrition)) {
         $nutrition = empty($result->nutrition) ? '' : $result->nutrition;
         $data->calories = empty($nutrition->calories) ? '' : $nutrition->calories;
         $data->fat = empty($nutrition->totalFat) ? '' : $nutrition->totalFat;
         $data->satfat = empty($nutrition->saturatedFat) ? '' : $nutrition->saturatedFat;
         $data->transfat = empty($nutrition->transFat) ? '' : $nutrition->transFat;
         $data->unsatfat = empty($nutrition->unsaturatedFat) ? '' : $nutrition->unsaturatedFat;
         $data->cholesterol = empty($nutrition->cholesterol) ? '' : $nutrition->cholesterol;
         $data->sodium = empty($nutrition->sodium) ? '' : $nutrition->sodium;
         $data->carbs = empty($nutrition->totalCarbohydrates) ? '' : $nutrition->totalCarbohydrates;
         $data->fiber = empty($nutrition->dietaryFiber) ? '' : $nutrition->dietaryFiber;
         $data->sugar = empty($nutrition->sugars) ? '' : $nutrition->sugars;
         $data->protein = empty($nutrition->protein) ? '' : $nutrition->protein;
     } else {
         $data->calories = empty($result->calories) ? '' : $result->calories;
         $data->fat = empty($result->fat) ? '' : $result->fat;
     }
     $data->rating = empty($result->rating) ? '' : $result->rating;
     $data->version = EasyRecipePlus::$pluginVersion;
     $template = new EasyRecipePlusTemplate(EasyRecipePlus::$EasyRecipePlusDir . "/templates/easyrecipe-template.html");
     return $template->replace($data);
 }
 /**
  * Process the template text
  *
  * @param null $data
  * @param int $options
  * @return mixed|string
  */
 function replace($data = null, $options = 0)
 {
     /**
      * If we have replacements, pre-process the template and remove conditionally INCLUDEd stuff
      */
     if ($data === null) {
         $data = new stdClass();
     }
     $currentPosition = 0;
     $this->opText = '';
     $inText = $this->inText;
     $firstType = null;
     /**
      * We return from within this loop when we have nothing left to process
      */
     while (true) {
         /**
          * Look for stuff to replace and find the first of them
          */
         $firstPosition = strlen($inText);
         $varPosition = strpos($inText, $this->delimiter, $currentPosition);
         if ($varPosition !== false) {
             $firstPosition = $varPosition;
             $firstType = self::VARIABLEREPLACE;
         }
         $repeatPosition = strpos($inText, '<!-- START REPEAT ', $currentPosition);
         if ($repeatPosition !== false && $repeatPosition < $firstPosition) {
             $firstPosition = $repeatPosition;
             $firstType = self::REPEATREPLACE;
         }
         $includeifPosition = strpos($inText, '<!-- START INCLUDEIF ', $currentPosition);
         if ($includeifPosition !== false && $includeifPosition < $firstPosition) {
             $firstPosition = $includeifPosition;
             $firstType = self::INCLUDEIF;
         }
         $startStripPosition = strpos($inText, '<!-- START STRIP WHITESPACE ', $currentPosition);
         if ($startStripPosition !== false && $startStripPosition < $firstPosition) {
             $firstPosition = $startStripPosition;
             $firstType = self::STARTSTRIP;
         }
         $endStripPosition = strpos($inText, '<!-- END STRIP WHITESPACE ', $currentPosition);
         if ($endStripPosition !== false && $endStripPosition < $firstPosition) {
             $firstPosition = $endStripPosition;
             $firstType = self::ENDSTRIP;
         }
         /**
          * If there's nothing to do, just return what we've got
          */
         if ($firstPosition == strlen($inText)) {
             /**
              * Copy any remaining input over to the output
              */
             $this->opText .= substr($inText, $currentPosition);
             /*
              * If there's any block to whitespace strip, do it
              * Tidy up the start/stop positions first to make it easy to process
              * This allows overlapping and unterminated stip blocks
              */
             if (count($this->stripWhitespace) > 0) {
                 $stripBlocks = array();
                 $startPosition = -1;
                 foreach ($this->stripWhitespace as $position) {
                     /**
                      * End strip?
                      */
                     if ($position < 0) {
                         /**
                          * If there's no previous unterminated START STRIP, ignore this END
                          */
                         if ($startPosition == -1) {
                             continue;
                         }
                         $stripBlocks[] = array($startPosition, abs($position));
                         $startPosition = -1;
                     } else {
                         /**
                          * If there's a previous unterminated START STRIP, ignore this one
                          */
                         if ($startPosition != -1) {
                             continue;
                         }
                         $startPosition = $position;
                     }
                 }
                 /**
                  * Allow for a missing END STRIP
                  */
                 if ($startPosition != -1) {
                     $stripBlocks[] = array($startPosition, strlen($this->opText));
                 }
                 /**
                  * Actually strip out whitespace in the strip blocks
                  */
                 $currentPosition = 0;
                 $strippedText = '';
                 foreach ($stripBlocks as $stripBlock) {
                     $strippedText .= substr($this->opText, $currentPosition, $stripBlock[0] - $currentPosition);
                     $text = substr($this->opText, $stripBlock[0], $stripBlock[1] - $stripBlock[0]);
                     $text = preg_replace('/>\\s+</', '><', $text);
                     $strippedText .= trim($text);
                     $currentPosition = $stripBlock[1];
                 }
                 $strippedText .= substr($this->opText, $currentPosition, strlen($this->opText) - $currentPosition);
                 $this->opText = $strippedText;
             }
             /**
              * If we aren't translating, then just (optionally) clean up whitespace and return
              */
             if (!self::$translate || !class_exists('EasyRecipePlusDOMDocument')) {
                 return $this->cleanWhitespace($this->opText, $options);
             }
             $doc = new EasyRecipePlusDOMDocument($this->opText, true);
             if (!$doc) {
                 return $this->opText;
             }
             $xlates = $doc->getElementsByClassName('xlate');
             if (count($xlates) == 0) {
                 return $this->cleanWhitespace($this->opText, $options);
             }
             // FIXME - use gettext if no __
             foreach ($xlates as $xlate) {
                 $original = $doc->innerHTML($xlate);
                 $translation = __($original, self::$textDomain);
                 if ($translation != $original) {
                     $xlate->nodeValue = $translation;
                 }
             }
             $html = $doc->getHTML(true);
             return $this->cleanWhitespace($html, $options);
         }
         /**
          * Copy over everything up to the first thing we need to process
          */
         $length = $firstPosition - $currentPosition;
         $this->opText .= substr($inText, $currentPosition, $length);
         $currentPosition = $firstPosition;
         /**
          * Get the thing to be replaced
          */
         switch ($firstType) {
             /**
              * INCLUDEIF includes the code up to the matching END INCLUDEIF:
              *  IF the condition variable exists and it's not false or null
              */
             case self::INCLUDEIF:
                 /**
                  * Get the conditional.
                  * Only check a smallish substring for efficiency
                  * This limits include condition names to 20 characters
                  */
                 $subString = substr($inText, $currentPosition, 60);
                 if (preg_match('/<!-- START INCLUDEIF (!?)([_a-z][_0-9a-z]{0,31}) -->/i', $subString, $regs)) {
                     $negate = $regs[1];
                     $trueFalse = $negate != '!';
                     $includeCondition = $regs[2];
                 } else {
                     trigger_error("Malformed START INCLUDEIF at {$currentPosition} ({$subString})", E_USER_NOTICE);
                     $this->opText .= "<";
                     $currentPosition++;
                     continue;
                 }
                 $endInclude = "<!-- END INCLUDEIF {$negate}{$includeCondition} -->";
                 $endIncludeLength = strlen($endInclude);
                 $endPosition = strpos($inText, $endInclude);
                 if ($endPosition == false) {
                     trigger_error(htmlspecialchars("'{$endInclude}'") . " not found", E_USER_NOTICE);
                     $this->opText .= "<";
                     $currentPosition++;
                     break;
                 }
                 /**
                  * If the condition is met, just remove the INCLUDEIF comments
                  * If the condition isn't met, remove everything up to the END INCLUDEIF
                  * The condition must be present, and NOT false or NULL
                  */
                 $condition = isset($data->{$includeCondition}) && $data->{$includeCondition} !== false && $data->{$includeCondition} !== null;
                 if ($condition === $trueFalse) {
                     $startInclude = "<!-- START INCLUDEIF {$negate}{$includeCondition} -->";
                     $startIncludeLength = strlen($startInclude);
                     $inText = substr($inText, 0, $currentPosition) . substr($inText, $currentPosition + $startIncludeLength, $endPosition - $currentPosition - $startIncludeLength) . substr($inText, $endPosition + $endIncludeLength);
                 } else {
                     $inText = substr($inText, 0, $currentPosition) . substr($inText, $endPosition + $endIncludeLength);
                 }
                 break;
                 /**
                  * Remove whitespace between tags.
                  * Useful to remove unwanted significant HTML whitespace that may have been introduced by auto formatting the source template
                  */
             /**
              * Remove whitespace between tags.
              * Useful to remove unwanted significant HTML whitespace that may have been introduced by auto formatting the source template
              */
             case self::STARTSTRIP:
                 $currentPosition += 31;
                 $this->stripWhitespace[] = strlen($this->opText);
                 break;
                 /**
                  * Save the output position at which to stop stripping. -ve indicates that it's an end position
                  */
             /**
              * Save the output position at which to stop stripping. -ve indicates that it's an end position
              */
             case self::ENDSTRIP:
                 $currentPosition += 29;
                 $this->stripWhitespace[] = -strlen($this->opText);
                 break;
                 /**
                  * A variable is a valid PHP variable name (limited to 20 chars) between delimiters
                  * If we don't find a valid name, copy over the delimiter and continue
                  * FIXME - fall back to caller's vars if it doesn't exist
                  */
             /**
              * A variable is a valid PHP variable name (limited to 20 chars) between delimiters
              * If we don't find a valid name, copy over the delimiter and continue
              * FIXME - fall back to caller's vars if it doesn't exist
              */
             case self::VARIABLEREPLACE:
                 $s = substr($inText, $currentPosition, 34);
                 if (!preg_match("/^{$this->delimiter}([_a-z][_0-9a-z]{0,31}){$this->delimiter}/si", $s, $regs)) {
                     $this->opText .= $this->delimiter;
                     $currentPosition++;
                     continue;
                 }
                 /**
                  * If we don't have a match for the variable, just assume it's not what we wanted to do
                  * so put the string we matched back into the output and continue from the trailing delimiter
                  */
                 $varName = $regs[1];
                 if (!isset($data->{$varName})) {
                     $this->opText .= $this->delimiter . $varName;
                     $currentPosition += strlen($varName) + 1;
                     continue;
                 }
                 /**
                  * Got a match - replace the <delimiter>...<delimiter> with the vars stuff
                  * We *could* pass this on for recursive processing, but it's not something we would normally want to do
                  * Maybe have a special naming convention for vars we want to do recursively?
                  */
                 $this->opText .= $data->{$varName};
                 $currentPosition += strlen($varName) + 2;
                 break;
                 /**
                  * We've seen a start repeat.
                  * Find the name of the repeat (limited to 20 chars)
                  * If we can't find the name, assume it's not what we want and continue
                  *
                  * Look for a valid START REPEAT in the next 45 characters
                  */
             /**
              * We've seen a start repeat.
              * Find the name of the repeat (limited to 20 chars)
              * If we can't find the name, assume it's not what we want and continue
              *
              * Look for a valid START REPEAT in the next 45 characters
              */
             case self::REPEATREPLACE:
                 $s = substr($inText, $currentPosition, 45);
                 if (!preg_match('/<!-- START REPEAT ([_a-zA-Z][_0-9a-zA-Z]{0,19}) -->/m', $s, $regs)) {
                     $this->opText .= '<';
                     $currentPosition++;
                     continue;
                 }
                 $rptName = $regs[1];
                 /**
                  * Make sure we have a matching key and it's an array
                  */
                 if (!isset($data->{$rptName}) || !is_array($data->{$rptName})) {
                     $this->opText .= '<';
                     $currentPosition++;
                     continue;
                 }
                 /**
                  * Now try to find the end of this repeat
                  */
                 $currentPosition += strlen($rptName) + 22;
                 $rptEnd = strpos($inText, "<!-- END REPEAT {$rptName} -->", $currentPosition);
                 if ($rptEnd === false) {
                     $this->opText .= '<!-- START REPEAT $rptName -->';
                     trigger_error("END REPEAT not found for {$rptName}", E_USER_NOTICE);
                     continue;
                 }
                 /**
                  * Do the repeat processing.
                  * For each item in the repeated array, process as a new template
                  */
                 $rptLength = $rptEnd - $currentPosition;
                 $rptString = substr($inText, $currentPosition, $rptLength);
                 $rptVars = $data->{$rptName};
                 for ($i = 0; $i < count($rptVars); $i++) {
                     $saveTranslate = self::$translate;
                     self::$translate = false;
                     $rpt = new EasyRecipePlusTemplate($rptString, self::TEXT, $this->delimiter);
                     $this->opText .= $rpt->replace($rptVars[$i], $options);
                     self::$translate = $saveTranslate;
                 }
                 /**
                  * Step over the end repeat
                  */
                 $currentPosition += strlen($rptName) + $rptLength + 20;
                 break;
         }
     }
     return '';
 }
 function guestPostEntry()
 {
     $this->plugin->isGuest = true;
     add_filter('tiny_mce_before_init', array($this->plugin, 'mcePreInitialise'));
     add_filter('mce_external_plugins', array($this->plugin, 'mcePlugins'));
     add_filter('mce_buttons', array($this->plugin, 'mceButtons'));
     $data = new stdClass();
     $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : '';
     $postData = isset($_POST['ERGuestPost']) ? $_POST['ERGuestPost'] : '';
     if (!wp_verify_nonce($nonce, 'guestpostdetails') || $postData == '' || !isset($postData['egpname']) || !isset($postData['egpemail']) || !isset($postData['egpurl'])) {
         wp_redirect(get_permalink($this->settings->gpDetailsPage));
         exit;
     }
     $postData = $_POST['ERGuestPost'];
     $data->name = $postData['egpname'];
     $data->email = $postData['egpemail'];
     $data->url = $postData['egpurl'];
     //        add_filter('tiny_mce_before_init', array($this, 'mcePreInitialise'));
     //        add_filter('mce_external_plugins', array($this, 'mcePlugins'));
     //        add_filter('mce_buttons', array($this, 'mceButtons'));
     ob_flush();
     // fixme - check to see if there IS a buffer
     ob_start();
     wp_editor('', 'guestpost');
     $data->editor = ob_get_clean();
     $data->postID = 0;
     $data->gpHideFooter = $this->settings->gpHideFooter;
     $data->lblGPPostTitle = $this->settings->lblGPPostTitle;
     $data->lblGPHint = $this->settings->lblGPHint;
     $data->lblGPMessage = $this->settings->lblGPMessage;
     $data->lblGPSubmitPost = $this->settings->lblGPSubmitPost;
     $data->nonce = wp_create_nonce('guestpostentry');
     $data->next = $data->next = get_permalink($this->settings->gpThanksPage);
     $template = new EasyRecipePlusTemplate(EasyRecipePlus::$EasyRecipePlusDir . "/templates/easyrecipe-upload.html");
     $data->uploadDialog = $template->getTemplateHTML();
     $template = new EasyRecipePlusTemplate(EasyRecipePlus::$EasyRecipePlusDir . "/templates/easyrecipe-links.html");
     $data->linksDialog = $template->getTemplateHTML();
     $template = new EasyRecipePlusTemplate(EasyRecipePlus::$EasyRecipePlusDir . "/templates/easyrecipe-guestpost.html");
     return $template->replace($data);
 }
 /**
  * Sets the URL in the print button <a> tag href
  *
  * Later versions of tinyMCE may silently remove the <a> tag altogether, so we need to put it back if it's not there
  *
  * @param     $recipe
  * @param     $template
  * @param     $data
  * @param int $nRecipe
  *
  * @return string
  */
 function formatRecipe($recipe, EasyRecipePlusTemplate $template, $data, $nRecipe = 0)
 {
     $data = $this->extractData($recipe, $data, $nRecipe);
     $html = $template->replace($data);
     /**
      * Convert fractions if asked to
      */
     if ($data->convertFractions) {
         $html = preg_replace_callback('%(. |^|>)([1-457])/([2-68])([^\\d]|$)%', array($this, 'convertFractionsCallback'), $html);
     }
     /**
      * Handle our own shortcodes because Wordpress's braindead implementation doesn't handle consecutive shortcodes properly
      */
     $html = str_replace("[br]", "<br>", $html);
     /**
      * Do our own shortcode handling
      * Don't bother with the regex's if there's no need - saves a few cycles
      * Not a great way of doing these - shortcodes embedded in shortcodes aren't always handled all that well
      * TODO - Would be better implemented using a stack so we we can absolutely match beginning and end codes and eliminate the possibilty of infinite recursion
      */
     if (strpos($html, "[") !== false) {
         if (preg_match(self::regexShortCodes, $html)) {
             $html = preg_replace_callback('%\\[(i|b|u)\\](.*?)\\[/\\1\\]%si', array($this, "shortCodes"), $html);
             $html = preg_replace_callback('%\\[(img)(?:&nbsp; *| +|\\p{Zs}+)(.*?) */?\\]%iu', array($this, "shortCodes"), $html);
             $html = preg_replace_callback('%\\[(url|a)(?:&nbsp; *| +|\\p{Zs}+)([^\\]]+?)\\](.*?)\\[/url\\]%iu', array($this, "shortCodes"), $html);
             $html = preg_replace_callback('%\\[(cap)(?:&nbsp; *| +|\\p{Zs}+)([^\\]]+?)\\](.*?)\\[/cap\\]%iu', array($this, "shortCodes"), $html);
         }
     }
     /**
      * Process possible captions that have been exposed by the easyrecipe shortcode expansion
      */
     if (strpos($html, '[caption ') !== false) {
         $html = do_shortcode($html);
     }
     /**
      * Decode any quotes that have possibly been "double encoded" when we inserted an image
      */
     $html = str_replace("&amp;quot;", '&quot;', $html);
     /**
      * Remove leftover template comments and then remove linebreaks and blank lines
      */
     $html = preg_replace('/<!-- .*? -->/', '', $html);
     $lines = explode("\n", $html);
     $html = '';
     foreach ($lines as $line) {
         if (($trimmed = trim($line)) != '') {
             $html .= "{$trimmed} ";
         }
     }
     return $html;
 }
 function createPosts()
 {
     $result = new stdClass();
     $result->status = 'FAIL';
     if (!isset($_POST['files']) || !is_array($_POST['files'])) {
         $result->error = "No files found";
         return $result;
     }
     foreach ($_POST['files'] as $file) {
         $s = @file_get_contents($file);
         if ($s === false) {
             $result->error = "Can't read " . $file;
             return $result;
         }
         $recipes = @unserialize($s);
         if ($recipes === false) {
             $result->error = "Error while unserializing " . $file;
             return $result;
         }
         if (!is_array($recipes)) {
             $result->error = "Problem parsing " . $file;
             return $result;
         }
         foreach ($recipes as $recipe) {
             $post = array();
             $post['post_author'] = wp_strip_all_tags($recipe->author);
             $post['post_title'] = wp_strip_all_tags($recipe->name);
             $template = new EasyRecipePlusTemplate(dirname(__FILE__) . "/../templates/easyrecipe-template.html");
             /**
              * Clean out optional data
              */
             foreach (array("name", "type", "cuisine", "author", "preptime", "cooktime", "yield", "summary") as $field) {
                 if (empty($recipe->{$field})) {
                     unset($recipe->{$field});
                 }
             }
             $post['post_content'] = $template->replace($recipe);
             wp_insert_post($post, true);
             // TODO - handle errors
         }
         @unlink($file);
     }
     $result->status = 'OK';
     return $result;
 }
    public function showPage()
    {
        /* @var $wp_rewrite WP_Rewrite */
        global $wp_rewrite;
        /** @var $wpdb wpdb */
        global $wpdb;
        global $wp_version;
        if (isset($_POST['action']) && $_POST['action'] == 'save') {
            $this->save($_POST["EasyRecipePlus"]);
        }
        $data = new stdClass();
        foreach (self::$defaultSettings as $setting => $default) {
            $data->{$setting} = isset($this->{$setting}) ? $this->{$setting} : $default;
        }
        $data->settingsname = 'EasyRecipePlus';
        $wpurl = get_bloginfo("wpurl");
        $data->fdsite = preg_replace('%^(?:http://)(.*)$%i', '$1', $wpurl);
        $isWP39 = version_compare($wp_version, '3.9.dev', '>') > 0 ? 'true' : 'false';
        $editURL = "{$wpurl}/wp-admin/edit.php";
        $data->pluginversion = EasyRecipePlus::$pluginVersion;
        $license = $this->licenseKey;
        /**
         * Figure out what we need to display on the Fooderific tab
         *
         * If we had MBRB enabled but this is the first run, show the welcome (firstRun = true) and hide the "retrieving" splash
         * Otherwise, show the "retrieving" splash
         */
        $data->fdFirstRun = false;
        $data->fdNotEnabled = false;
        $fdAPIKey = $this->fooderificAPIKey;
        if (!$this->enableFooderific) {
            $data->fdNotEnabled = true;
            $data->retrieveclass = 'FDDisplayNone';
            $lastScan = 0;
        } else {
            if ($this->lastScanStarted == 0) {
                $data->fdFirstRun = true;
                $data->retrieveclass = 'FDDisplayNone';
                $lastScan = 0;
            } else {
                $data->retrieveclass = '';
                $tzOffet = get_option('gmt_offset');
                $lastScan = date_i18n("j M y g:ia", $this->lastScanStarted + $tzOffet * 3600);
            }
        }
        $pluginVersion = EasyRecipePlus::$pluginVersion;
        $data->javascript = <<<EOD
<script type="text/javascript">
//<![CDATA[
    window.EASYRECIPE = window.EASYRECIPE || {};
    EASYRECIPE.settingsName = 'EasyRecipePlus';
    EASYRECIPE.editURL = '{$editURL}';
    EASYRECIPE.pluginVersion = '{$pluginVersion}';
    EASYRECIPE.wpurl = '{$wpurl}';
    EASYRECIPE.slug = 'easyrecipeplus';
    EASYRECIPE.license = '{$license}';
    EASYRECIPE.lastScan = '{$lastScan}';
    EASYRECIPE.fdAPIKey = '{$fdAPIKey}';
    EASYRECIPE.isWP39 = {$isWP39};
//]]>
</script>
EOD;
        /**
         * If the site isn't using permalinks then just pass the print stuff as a qurerystring param
         */
        $data->siteDiagnosticsURL = home_url();
        if (!$wp_rewrite->using_permalinks()) {
            $data->siteDiagnosticsURL .= "?";
        }
        $data->useFeaturedImageChecked = $this->useFeaturedImage ? 'checked="checked"' : '';
        $data->displayPrintChecked = $this->displayPrint ? 'checked="checked"' : '';
        $data->filterExcerptsChecked = $this->filterExcerpts ? 'checked="checked"' : '';
        $data->displayZiplistChecked = $this->displayZiplist ? 'checked="checked"' : '';
        $data->displayRecipeCardChecked = $this->displayRecipeCard ? 'checked="checked"' : '';
        $data->displayRecipageChecked = $this->displayRecipage ? 'checked="checked"' : '';
        $data->displayGMCChecked = $this->displayGMC ? 'checked="checked"' : '';
        $data->displayUltimateRecipeChecked = $this->displayUltimateRecipe ? 'checked="checked"' : '';
        $data->allowLinkChecked = $this->allowLink ? 'checked="checked"' : '';
        $data->convertFractionsChecked = $this->convertFractions ? 'checked="checked"' : '';
        $data->removeMFChecked = $this->removeMicroformat ? 'checked="checked"' : '';
        $data->fdLinkChecked = $this->enableFooderific ? 'checked="checked"' : '';
        $data->enableSwoopChecked = $this->enableSwoop ? 'checked="checked"' : '';
        $data->swoopclass = $this->enableSwoop ? '' : 'ERSNoSwoop';
        $data->forcejQueryChecked = $this->forcejQuery ? 'checked="checked"' : '';
        $data->noHTMLWarnChecked = $this->noHTMLWarn ? 'checked="checked"' : '';
        $data->genesisGridChecked = $this->genesisGrid ? 'checked="checked"' : '';
        $data->saveButtonBigOvenChecked = $data->saveButtonZiplistChecked = $data->saveButtonSaltyFigChecked = $data->saveButtonNoneChecked = '';
        $data->ziplistclass = $data->saltyfigclass = "ERSDisplayNone";
        /**
         * Only show the Ziplist stuff if we are already using it and then only so it can be unselected
         */
        $data->showZiplist = false;
        switch ($data->saveButton) {
            case 'BigOven':
                $data->saveButtonBigOvenChecked = 'checked="checked"';
                break;
            case 'Ziplist':
                $data->saveButtonZiplistChecked = 'checked="checked"';
                $data->ziplistclass = '';
                $data->showZiplist = true;
                break;
            case 'SaltyFig':
                $data->saveButtonSaltyFigChecked = 'checked="checked"';
                $data->saltyfigclass = '';
                break;
            default:
                $data->saveButtonNoneChecked = 'checked="checked"';
                break;
        }
        $data->ratingEasyRecipeChecked = $data->ratingSelfRatedChecked = $data->ratingDisabledChecked = '';
        $ratingChecked = "rating" . $this->ratings . "Checked";
        $data->{$ratingChecked} = 'checked="checked"';
        $data->erSubscribeChecked = $this->erSubscribe ? 'checked="checked"' : '';
        $data->subscribeclass = $this->erSubscribe ? '' : 'ERSNoSubscribe';
        /*
         * Set up Swoop stuff
         */
        if ($data->swoopSiteID != '') {
            $data->registerswoop = 'ERSDisplayNone';
            $data->loginswoop = '';
        } else {
            $data->registerswoop = '';
            $data->loginswoop = 'ERSDisplayNone';
        }
        /*
         * Set up the register data even if we're already registered in case we remove the current ID
         */
        $swoopData = new stdClass();
        $swoopData->email = get_bloginfo("admin_email");
        $swoopData->blog_url = get_bloginfo("wpurl");
        $swoopData->blog_title = get_bloginfo("description");
        $swoopData->rss_url = get_bloginfo("rss_url");
        $swoopData->tz = get_option('timezone_string');
        /** @noinspection PhpParamsInspection */
        $data->swoopqs = http_build_query($swoopData);
        $data->easyrecipeURL = EasyRecipePlus::$EasyRecipePlusUrl;
        $data->siteurl = get_site_url();
        $data->erplus = 'Plus';
        $data->isPlus = true;
        $data->author = $this->author;
        $data->cuisines = str_replace('|', "\n", $this->cuisines);
        $data->recipeTypes = str_replace('|', "\n", $this->recipeTypes);
        $data->plus = "EasyRecipePlus" == "easyrecipeplus" ? "Plus" : "";
        $data->pluginName = "EasyRecipePlus";
        $optionsHTML = "<input type='hidden' name='option_page' value='EROptionSettings' />";
        $optionsHTML .= '<input type="hidden" name="action" value="update" />';
        $optionsHTML .= wp_nonce_field("EROptionSettings-options", '_wpnonce', true, false);
        $optionsHTML .= wp_referer_field(false);
        $styles = EasyRecipePlusStyles::getStyles($this->customTemplates);
        //        $styles = call_user_func(array ($this->stylesClass, 'getStyles'), $this->settings['customTemplates']);
        $data->styleDirectory = $this->style;
        $styleNum = 0;
        $styleTab = 1;
        $styleItem = false;
        $data->STYLETABS = array();
        foreach ($styles as $style) {
            if ($styleNum % 3 == 0) {
                if ($styleItem !== false) {
                    /** @noinspection PhpUndefinedFieldInspection */
                    $styleItem->styleTab = $styleTab++;
                    $data->STYLETABS[] = $styleItem;
                }
                $styleItem = new stdClass();
                $styleItem->STYLES = array();
            }
            $style->selected = $data->style == $style->directory ? 'ERSStyleSelected' : '';
            $styleItem->STYLES[] = $style;
            $styleNum++;
        }
        if ($styleItem) {
            $styleItem->styleTab = $styleTab;
            $data->STYLETABS[] = $styleItem;
        }
        $styles = EasyRecipePlusStyles::getStyles($this->customTemplates, EasyRecipePlusStyles::ISPRINT);
        //$styles = call_user_func(array ($this->stylesClass, 'getStyles'), $this->settings['customTemplates'], constant("$this->stylesClass::ISPRINT"));
        $data->printStyleDirectory = $this->printStyle;
        $styleNum = 0;
        $styleTab = 1;
        $styleItem = false;
        $data->PRINTSTYLETABS = array();
        foreach ($styles as $style) {
            if ($styleNum % 3 == 0) {
                if ($styleItem !== false) {
                    /** @noinspection PhpUndefinedFieldInspection */
                    $styleItem->styleTab = $styleTab++;
                    $data->PRINTSTYLETABS[] = $styleItem;
                }
                $styleItem = new stdClass();
                $styleItem->PRINTSTYLES = array();
            }
            $style->selected = $data->printStyle == $style->directory ? 'ERSStyleSelected' : '';
            $styleItem->PRINTSTYLES[] = $style;
            $styleNum++;
        }
        if ($styleItem) {
            $styleItem->styleTab = $styleTab;
            $data->PRINTSTYLETABS[] = $styleItem;
        }
        $data->optionsHTML = $optionsHTML;
        $data->customTemplates = $this->customTemplates;
        /**
         * The Guest Post template is separate simply because it's somewhat complex
         * and it's much easier to handle it in Dreamweaver separately
         */
        $gpData = new stdClass();
        $gpData->settingsname = "EasyRecipePlus";
        $gpData->gpHideFooterChecked = $this->gpHideFooter ? 'checked="checked"' : '';
        $gpData->gpCopyDetailsChecked = $this->gpCopyDetails ? 'checked="checked"' : '';
        $gpData->lblGPName = $this->lblGPName;
        $gpData->lblGPEmail = $this->lblGPEmail;
        $gpData->lblGPWebsite = $this->lblGPWebsite;
        $gpData->lblGPContinue = $this->lblGPContinue;
        $gpData->lblGPPostTitle = $this->lblGPPostTitle;
        $gpData->lblGPHint = $this->lblGPHint;
        $gpData->lblGPMessage = $this->lblGPMessage;
        $gpData->lblGPSubmitPost = $this->lblGPSubmitPost;
        /**
         * Get users so we can select one for the nominal guest poster - restricted to non-subscribers
         * It seems some blogs have tens of thousands of spam subscribers and reading them all will crash WP (and make a drop down select useless obviously!)
         * Since there's no reliable, clean standard way of getting users who *don't* have some specific role, we have to do it ourselves
         *  TODO - probably should check the number of non-subscribers too before we commit to reading them all
         * There is no efficient way to select by user role - we have to use a LIKE
         */
        $q = "SELECT ID, user_login FROM {$wpdb->users} JOIN {$wpdb->usermeta} ON ID = user_id WHERE meta_key = 'wp_capabilities' AND meta_value NOT LIKE '%subscriber%'";
        $users = $wpdb->get_results($q);
        //        $users = get_users();
        $pages = get_pages(array('post_status' => 'publish,draft,private'));
        $gpData->GPUSERS = array();
        $item = new stdClass();
        $item->userid = 0;
        $item->username = '******';
        $gpData->GPUSERS[] = $item;
        foreach ($users as $user) {
            $item = new stdClass();
            $item->userid = $user->ID;
            $item->username = $user->user_login;
            $item->selected = $user->ID == $this->gpUserID ? 'selected="selected"' : '';
            $gpData->GPUSERS[] = $item;
        }
        $gpData->GPDETAILSPAGE = array();
        $gpData->GPENTRYPAGE = array();
        $gpData->GPTHANKSPAGE = array();
        $item = new stdClass();
        $item->pageid = 0;
        $item->pagename = 'Please select...';
        $gpData->GPDETAILSPAGE[] = $item;
        $gpData->GPENTRYPAGE[] = $item;
        $gpData->GPTHANKSPAGE[] = $item;
        foreach ($pages as $page) {
            $item = new stdClass();
            $item->pageid = $page->ID;
            $item->pagename = $page->post_title;
            $item->selected = $page->ID == $this->gpDetailsPage ? 'selected="selected"' : '';
            $gpData->GPDETAILSPAGE[] = $item;
            $item = clone $item;
            $item->selected = $page->ID == $this->gpEntryPage ? 'selected="selected"' : '';
            $gpData->GPENTRYPAGE[] = $item;
            $item = clone $item;
            $item->selected = $page->ID == $this->gpThanksPage ? 'selected="selected"' : '';
            $gpData->GPTHANKSPAGE[] = $item;
        }
        $gpData->easyrecipeURL = EasyRecipePlus::$EasyRecipePlusUrl;
        $gpTemplate = new EasyRecipePlusTemplate(EasyRecipePlus::$EasyRecipePlusDir . "/templates/easyrecipe-guestpostsettings.html");
        $data->guestpostsettings = $gpTemplate->replace($gpData);
        //$data->guestpostsettings="XXX";
        /*
         * We need to preserve whitespace on this template because newlines in the the textareas are significant
         */
        $template = new EasyRecipePlusTemplate(EasyRecipePlus::$EasyRecipePlusDir . "/templates/easyrecipe-settings.html");
        $html = $template->replace($data, EasyRecipePlusTemplate::PRESERVEWHITESPACE);
        echo $html;
    }
 /**
  * Display the plugin diagnostics page
  */
 function show()
 {
     /**
      * Just ignore if we're not logged in as admin
      */
     if (!current_user_can('administrator')) {
         return;
     }
     if (!$this->haveData) {
         $this->get();
     }
     /**
      * Get only public settings properties
      */
     $settings = new stdClass();
     foreach ($this->settings as $property => $value) {
         $settings->{$property} = $value;
     }
     $this->settings = print_r($settings, true);
     $template = new EasyRecipePlusTemplate($this->getTemplate(), EasyRecipePlusTemplate::TEXT);
     $html = $template->replace($this, EasyRecipePlusTemplate::PRESERVEWHITESPACE);
     /**
      * Switch off any output buffereing
      */
     $level = ob_get_level();
     while ($level > 0) {
         ob_end_clean();
         $level = ob_get_level();
     }
     $html = $this->existingOP . $html;
     header("HTTP/1.1 200 OK");
     header("Content-Length: " . strlen($html));
     echo $html;
     exit;
 }