private function doConvert($postID, $postType)
 {
     /** @global $wpdb wpdb */
     global $wpdb;
     $result = new stdClass();
     switch ($postType) {
         case 'ultimate-recipe':
             $result->recipe = new stdClass();
             if ($postID == 'random') {
                 $posts = get_posts(array('post_type' => 'recipe', 'nopaging' => true));
                 $post = $posts[array_rand($posts)];
             } else {
                 $post = get_post($postID);
             }
             $recipe = get_post_custom($post->ID);
             $user = get_userdata($post->post_author);
             $image = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID), 'full');
             $cuisine = wp_get_object_terms($post->ID, 'cuisine');
             if ($cuisine instanceof WP_Error) {
                 register_taxonomy('cuisine', 'recipe');
                 $cuisine = wp_get_object_terms($post->ID, 'cuisine');
             }
             $course = wp_get_object_terms($post->ID, 'course');
             if ($course instanceof WP_Error) {
                 register_taxonomy('course', 'recipe');
                 $course = wp_get_object_terms($post->ID, 'course');
             }
             /**
              * Very dodgy way of processing times - not sure what else we can do!
              * Times other than "x minutes" are going to be unparsable reliably
              * Will have to adjust this based on real user values as we come across them
              *
              * Try for xlated "minutes" first
              * If that doesn't work, at least try some likely English duration specifiers
              */
             $xMinutes = __('minutes', 'wp-ultimate-recipe');
             $timeText = !empty($recipe['recipe_prep_time_text']) ? $recipe['recipe_prep_time_text'][0] : '';
             if ($timeText == $xMinutes || $timeText == 'minute') {
                 $result->recipe->prep_time = 'PT' . $recipe['recipe_prep_time'][0] . 'M';
             } elseif ($timeText == 'hours' || $timeText == 'hour') {
                 $result->recipe->prep_time = 'PT' . $recipe['recipe_prep_time'][0] . 'H0M';
             } else {
                 $result->recipe->prep_time = '';
             }
             $timeText = !empty($recipe['recipe_cook_time_text']) ? $recipe['recipe_cook_time_text'][0] : '';
             if ($timeText == $xMinutes || $timeText == 'minute') {
                 $result->recipe->cook_time = 'PT' . $recipe['recipe_cook_time'][0] . 'M';
             } elseif ($timeText == 'hours' || $timeText == 'hour') {
                 $result->recipe->cook_time = 'PT' . $recipe['recipe_cook_time'][0] . 'H0M';
             } else {
                 $result->recipe->cook_time = '';
             }
             $result->recipe->recipe_image = !empty($image) ? $image[0] : '';
             if (is_array($cuisine) && !empty($cuisine[0])) {
                 $result->recipe->cuisine = htmlspecialchars($cuisine[0]->name);
             }
             if (is_array($course) && !empty($course[0])) {
                 $result->recipe->mealType = htmlspecialchars($course[0]->name);
             }
             $result->recipe->recipe_title = !empty($recipe['recipe_title']) ? htmlspecialchars($recipe['recipe_title'][0]) : '';
             /** @noinspection PhpUndefinedFieldInspection */
             $result->recipe->author = htmlspecialchars($user->data->display_name);
             $result->recipe->summary = !empty($recipe['recipe_description']) ? htmlspecialchars($recipe['recipe_description'][0]) : '';
             $notes = !empty($recipe['recipe_notes'][0]) ? preg_replace_callback('%<(strong|em)>(.*?)</\\1>%', array($this, 'notesConversion'), $recipe['recipe_notes'][0]) : '';
             $result->recipe->notes = preg_replace('%<a ([^>]+)>(.*?)</a>%i', '[url $1]$2[/url]', $notes);
             $section = '';
             $ingredients = array();
             $urIngredients = @unserialize($recipe['recipe_ingredients'][0]);
             if (!$urIngredients) {
                 $urIngredients = array();
             }
             foreach ($urIngredients as $urIngredient) {
                 if ($urIngredient['group'] != $section) {
                     $section = $urIngredient['group'];
                     $ingredients[] = '!' . htmlspecialchars($urIngredient['group']);
                 }
                 $ingredient = htmlspecialchars($urIngredient['amount']) . ' ' . htmlspecialchars($urIngredient['unit']) . ' ' . htmlspecialchars($urIngredient['ingredient']);
                 if (!empty($urIngredient['notes'])) {
                     $ingredient .= ' ' . htmlspecialchars($urIngredient['notes']);
                 }
                 $ingredients[] = $ingredient;
             }
             $result->ingredients = $ingredients;
             $section = '';
             $instructions = array();
             $urInstructions = @unserialize($recipe['recipe_instructions'][0]);
             if (!$urInstructions) {
                 $urInstructions = array();
             }
             foreach ($urInstructions as $urInstruction) {
                 if ($urInstruction['group'] != $section) {
                     $section = $urInstruction['group'];
                     $instructions[] = '!' . htmlspecialchars($urInstruction['group']);
                 }
                 $instruction = htmlspecialchars($urInstruction['description']);
                 if (!empty($urInstruction['image'])) {
                     $instructionImage = wp_get_attachment_image_src($urInstruction['image'], 'large');
                     if (!empty($instructionImage)) {
                         $instruction .= '[br][img src="' . $instructionImage[0] . '" width="' . $instructionImage[1] . '" height="' . $instructionImage[2] . '" /]';
                     }
                 }
                 $instructions[] = $instruction;
             }
             $result->recipe->instructions = implode("\n", $instructions);
             break;
         case 'recipage':
             /** @var WP_Post $post */
             $post = $wpdb->get_row("SELECT * FROM " . $wpdb->posts . " WHERE ID=" . $postID);
             $content = $post->post_content;
             $document = new EasyRecipePlusDOMDocument($content);
             if (!$document->isValid()) {
                 return null;
             }
             $hrecipe = $document->getElementByClassName('hrecipe');
             if (!$hrecipe) {
                 return null;
             }
             $result->recipe = new stdClass();
             $result->recipe->total_time = '';
             $result->recipe->serving_size = '';
             $result->recipe->notes = '';
             $result->recipe->calories = '';
             $result->recipe->fat = '';
             $result->recipe->rating = '';
             /** @var DOMElement $element */
             $element = $document->getElementByClassName('photo', 'img', $hrecipe);
             $result->recipe->recipe_image = $element != null ? $element->getAttribute('src') : '';
             $element = $document->getElementByClassName('fn', '*', $hrecipe);
             $result->recipe->recipe_title = $element != null ? htmlspecialchars($element->textContent) : '';
             $element = $document->getElementByClassName('author', '*', $hrecipe);
             $result->recipe->author = $element != null ? htmlspecialchars($element->textContent) : '';
             $element = $document->getElementByClassName('summary', '*', $hrecipe);
             $result->recipe->summary = $element != null ? htmlspecialchars($element->textContent) : '';
             $element = $document->getElementByClassName('yield', '*', $hrecipe);
             $result->recipe->yield = $element != null ? htmlspecialchars($element->textContent) : '';
             $element = $document->getElementByClassName('preptime', '*', $hrecipe);
             $prepTime = $element != null ? $element->textContent : '';
             $result->recipe->prep_time = $this->convertTimeString($prepTime);
             $element = $document->getElementByClassName('cooktime', '*', $hrecipe);
             $cookTime = $element != null ? $element->textContent : '';
             $result->recipe->cook_time = $this->convertTimeString($cookTime);
             $result->ingredients = array();
             $ingredients = $document->getElementsByClassName('ingredient', '*', $hrecipe);
             /** @var DOMElement $ingredient */
             foreach ($ingredients as $ingredient) {
                 $result->ingredients[] = trim($ingredient->textContent);
             }
             $instructions = array();
             $elements = $document->getElementsByClassName('instruction', '*', $hrecipe);
             /** @var DOMElement $instruction */
             foreach ($elements as $instruction) {
                 $instructions[] = trim($instruction->textContent);
             }
             $result->recipe->instructions = implode("\n", $instructions);
             break;
         case 'recipeseo':
             $result->recipe = $wpdb->get_row("SELECT * FROM " . $wpdb->prefix . "amd_recipeseo_recipes WHERE recipe_id=" . $postID);
             $ingredients = $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . "amd_recipeseo_ingredients WHERE recipe_id=" . $postID . " ORDER BY ingredient_id");
             $result->ingredients = array();
             foreach ($ingredients as $ingredient) {
                 $result->ingredients[] = $ingredient->amount . " " . $ingredient->name;
             }
             break;
         case 'zlrecipe':
             $result->recipe = $wpdb->get_row("SELECT * FROM " . $wpdb->prefix . "amd_zlrecipe_recipes WHERE recipe_id=" . $postID);
             $result->recipe->nReviews = 1;
             $result->recipe->summary = $this->decodeMarkdown($result->recipe->summary);
             $result->recipe->notes = $this->decodeMarkdown($result->recipe->notes);
             /**
              * If only total time is specified, use it as the cook time
              * TODO - Do this for all plugins?
              */
             if ($result->recipe->cook_time == '' && $result->recipe->prep_time == '') {
                 $result->recipe->cook_time = $result->recipe->total_time;
             }
             $ingredients = explode("\n", str_replace("\r", "", $result->recipe->ingredients));
             $result->ingredients = array();
             foreach ($ingredients as $ingredient) {
                 $ingredient = trim($ingredient);
                 if ($ingredient != '') {
                     if (preg_match('/^%([^\\s]+)/', $ingredient, $regs)) {
                         if (($n = count($result->ingredients)) > 0 && $result->ingredients[$n - 1][0] != '!') {
                             $result->ingredients[$n - 1] .= '[br][img src="' . $regs[1] . '"]';
                             continue;
                         } else {
                             $ingredient = '[img src="' . $regs[1] . '"]';
                         }
                     } else {
                         $ingredient = $this->decodeMarkdown($ingredient);
                     }
                     $result->ingredients[] = $ingredient;
                 }
             }
             unset($result->recipe->ingredients);
             $instructions = explode("\n", str_replace("\r", "", $result->recipe->instructions));
             $convertedInstructions = array();
             foreach ($instructions as $instruction) {
                 $instruction = trim($instruction);
                 if ($instruction != '') {
                     if (preg_match('/^%([^\\s]+)/', $instruction, $regs)) {
                         if (($n = count($convertedInstructions)) > 0 && $convertedInstructions[$n - 1][0] != '!') {
                             $convertedInstructions[$n - 1] .= '[br][img src="' . $regs[1] . '"]';
                             continue;
                         } else {
                             $instruction = '[img src="' . $regs[1] . '"]';
                         }
                     } else {
                         $instruction = $this->decodeMarkdown($instruction);
                     }
                     $convertedInstructions[] = $instruction;
                 }
             }
             /**
              * For silly historical reasons, instructions are returned as a string
              */
             $result->recipe->instructions = implode("\n", $convertedInstructions);
             break;
         case 'recipress':
             $meta = get_post_custom($postID);
             $result->recipe = new stdClass();
             $result->ingredients = array();
             $result->recipe->instructions = '';
             /** @noinspection PhpUndefinedFunctionInspection */
             $size = recipress_options('instruction_image_size');
             $result->recipe->recipe_title = $meta['title'][0] ? $meta['title'][0] : '';
             $photo = wp_get_attachment_image_src($meta['photo'][0], 'thumbnail', false);
             $result->recipe->recipe_image = $photo ? $photo[0] : '';
             $result->recipe->summary = $meta['summary'][0] ? $meta['summary'][0] : '';
             $terms = get_the_terms($postID, 'cuisine');
             $result->recipe->cuisine = $terms[0]->name;
             $terms = get_the_terms($postID, 'course');
             $result->recipe->mealType = $terms[0]->name;
             /** @noinspection PhpUndefinedFunctionInspection */
             $result->recipe->cook_time = $meta['cook_time'][0] ? recipress_time($meta['cook_time'][0], 'iso') : '';
             /** @noinspection PhpUndefinedFunctionInspection */
             $result->recipe->prep_time = $meta['prep_time'][0] ? recipress_time($meta['prep_time'][0], 'iso') : '';
             $result->recipe->yield = $meta['yield'][0] ? $meta['yield'][0] : '';
             $result->recipe->serves = $meta['servings'][0] ? $meta['servings'][0] : '';
             $ingredients = $meta['ingredient'];
             $ingredients = unserialize($ingredients[0]);
             foreach ($ingredients as $ingredient) {
                 $newIngredient = $ingredient['amount'] . ' ' . $ingredient['measurement'] . ' ' . $ingredient['ingredient'];
                 if (!empty($ingredient['notes'])) {
                     $newIngredient .= ', ' . $ingredient['notes'];
                 }
                 $result->ingredients[] = trim(str_replace('  ', ' ', $newIngredient));
             }
             $instructions = $meta['instruction'];
             $instructions = unserialize($instructions[0]);
             foreach ($instructions as $instruction) {
                 $result->recipe->instructions .= $instruction['description'];
                 if (!empty($instruction['image'])) {
                     $result->recipe->instructions .= "[br]" . wp_get_attachment_image($instruction['image'], $size, false);
                     $result->recipe->instructions = str_replace('<', '[', $result->recipe->instructions);
                     $result->recipe->instructions = str_replace('>', ']', $result->recipe->instructions);
                 }
                 $result->recipe->instructions .= "\n";
             }
             break;
             /**
              * Make the Recipe Card data look like RecipeSEO/Ziplist - only because we already have the JS for those
              */
         /**
          * Make the Recipe Card data look like RecipeSEO/Ziplist - only because we already have the JS for those
          */
         case 'yumprint':
             $post = $wpdb->get_row("SELECT * FROM " . $wpdb->prefix . "yumprint_recipe_recipe WHERE id=" . $postID);
             $nutrition = @json_decode($post->nutrition);
             $recipe = @json_decode($post->recipe);
             if (empty($recipe)) {
                 $recipe = new stdClass();
             }
             $recipe->recipe_title = !empty($recipe->title) ? $recipe->title : '';
             $recipe->recipe_image = !empty($recipe->image) ? $recipe->image : '';
             $ingredients = !empty($recipe->ingredients) && is_array($recipe->ingredients) ? $recipe->ingredients : array();
             $result->ingredients = array();
             foreach ($ingredients as $value) {
                 if ($value->title != '') {
                     $result->ingredients[] = '!' . $value->title;
                 }
                 foreach ($value->lines as $line) {
                     $result->ingredients[] = $line;
                 }
             }
             $instructions = !empty($recipe->directions) && is_array($recipe->directions) ? $recipe->directions : array();
             $recipe->instructions = array();
             foreach ($instructions as $value) {
                 if ($value->title != '') {
                     $recipe->instructions[] = '!' . $value->title;
                 }
                 foreach ($value->lines as $line) {
                     $recipe->instructions[] = $line;
                 }
             }
             $recipe->instructions = implode("\n", $recipe->instructions);
             $recipe->notes = !empty($recipe->notes) && is_array($recipe->notes) ? implode("\n", $recipe->notes[0]->lines) : '';
             $recipe->prep_time = !empty($recipe->prepTime) ? $this->yumprintTime($recipe->prepTime) : '';
             $recipe->cook_time = !empty($recipe->cookTime) ? $this->yumprintTime($recipe->cookTime) : '';
             $recipe->yield = !empty($recipe->yields) ? $recipe->yields : '';
             $recipe->serving_size = !empty($recipe->servings) ? $recipe->servings : '';
             $serves = !empty($recipe->servings) ? (int) $recipe->servings : '';
             $div = !empty($serves) ? $serves : 1;
             if (!empty($nutrition)) {
                 /** @noinspection PhpUnusedLocalVariableInspection */
                 foreach ($nutrition as $key => &$value) {
                     $value /= $div;
                 }
                 $nutrition->calories = round($nutrition->calories);
                 $nutrition->totalFat = round($nutrition->totalFat) . 'g';
                 $nutrition->saturatedFat = round($nutrition->saturatedFat) . 'g';
                 $nutrition->transFat = round($nutrition->transFat) . 'g';
                 $nutrition->polyunsaturatedFat = round($nutrition->polyunsaturatedFat);
                 $nutrition->monounsaturatedFat = round($nutrition->monounsaturatedFat);
                 $nutrition->unsaturatedFat = $nutrition->polyunsaturatedFat + $nutrition->monounsaturatedFat . 'g';
                 $nutrition->cholesterol = round($nutrition->cholesterol) . 'mg';
                 $nutrition->sodium = round($nutrition->sodium) . 'mg';
                 $nutrition->totalCarbohydrates = round($nutrition->totalCarbohydrates) . 'g';
                 $nutrition->dietaryFiber = round($nutrition->dietaryFiber) . 'g';
                 $nutrition->sugars = round($nutrition->sugars) . 'g';
                 $nutrition->protein = round($nutrition->protein) . 'g';
                 foreach ($nutrition as $key => &$value) {
                     if ($value == '0g' || $value == '0mg') {
                         $value = '';
                     }
                 }
             } else {
                 $nutrition = new stdClass();
                 $nutrition->calories = '';
                 $nutrition->totalFat = '';
                 $nutrition->saturatedFat = '';
                 $nutrition->transFat = '';
                 $nutrition->polyunsaturatedFat = '';
                 $nutrition->monounsaturatedFat = '';
                 $nutrition->unsaturatedFat = '';
                 $nutrition->cholesterol = '';
                 $nutrition->sodium = '';
                 $nutrition->totalCarbohydrates = '';
                 $nutrition->dietaryFiber = '';
                 $nutrition->sugars = '';
                 $nutrition->protein = '';
             }
             $result->recipe = $recipe;
             $result->recipe->nutrition = $nutrition;
             unset($result->recipe->prepTime);
             unset($result->recipe->cookTime);
             unset($result->recipe->totalTime);
             unset($result->recipe->yields);
             unset($result->recipe->servings);
             unset($result->recipe->title);
             unset($result->recipe->image);
             unset($result->recipe->ingredients);
             unset($result->recipe->directions);
             break;
             /**
              * Get me cooking
              */
         /**
          * Get me cooking
          */
         case 'gmc':
         case 'gmc_recipe':
             /**
              * If GMC is installed, use it to get ingredients, but turn off error reporting to stop it crashing
              */
             if (function_exists('print_ingredient_description')) {
                 error_reporting(0);
                 $gmcInstalled = true;
             } else {
                 $gmcInstalled = false;
             }
             $result->recipe = new stdClass();
             $post = get_post($postID);
             $result->recipe->recipe_title = html_entity_decode(get_the_title($postID), ENT_COMPAT, 'UTF-8');
             $result->recipe->author = get_post_meta($postID, 'gmc-source-name', true);
             $result->recipe->summary = get_post_meta($post->ID, "gmc-description", true);
             $thumbID = get_post_thumbnail_id($postID);
             $postThumb = $thumbID != 0 ? wp_get_attachment_image_src($thumbID, 'medium') : '';
             if (!empty($postThumb)) {
                 $result->recipe->recipe_image = $postThumb[0];
             }
             $prepHour = (int) get_post_meta($postID, "gmc-prep-time-hours", true);
             $prepMinute = (int) get_post_meta($postID, "gmc-prep-time-mins", true);
             $cookHour = (int) get_post_meta($postID, "gmc-cooking-time-hours", true);
             $cookMinute = (int) get_post_meta($postID, "gmc-cooking-time-mins", true);
             $result->recipe->prep_time = "PT{$prepHour}H{$prepMinute}M";
             $result->recipe->cook_time = "PT{$cookHour}H{$cookMinute}M";
             $mealTypes = wp_get_object_terms($postID, 'gmc_course');
             if ($mealTypes instanceof WP_Error) {
                 register_taxonomy('gmc_course', 'gmc_recipe');
                 $mealTypes = wp_get_object_terms($postID, 'gmc_course');
             }
             if (is_array($mealTypes) && count($mealTypes) > 0) {
                 $result->recipe->mealType = $mealTypes[0]->name;
             }
             $regions = wp_get_object_terms($postID, 'gmc_region');
             if ($regions instanceof WP_Error) {
                 register_taxonomy('gmc_region', 'gmc_recipe');
                 $regions = wp_get_object_terms($postID, 'gmc_region');
             }
             if (is_array($regions) && count($regions) > 0) {
                 $result->recipe->cuisine = $regions[0]->name;
             }
             $result->ingredients = array();
             $result->recipe->instructions = '';
             $currentSection = '';
             $steps = get_posts('post_status=publish&post_type=gmc_recipestep&nopaging=1&orderby=menu_order&order=ASC&post_parent=' . $postID);
             /** @var $step WP_Post */
             foreach ($steps as $step) {
                 if (!empty($step->post_content)) {
                     $section = get_post_meta($step->ID, 'gmc_stepgroup', true);
                     if (!empty($section) && $section != $currentSection) {
                         $result->recipe->instructions .= "!{$section}\n";
                         $currentSection = $section;
                     }
                     $content = preg_replace('/\\r?\\n/i', '[br]', $step->post_content);
                     $thumbID = get_post_thumbnail_id($step->ID);
                     if ($thumbID) {
                         $postThumb = wp_get_attachment_image_src($thumbID, 'medium');
                         if ($postThumb) {
                             $content .= '[br][img src="' . $postThumb[0] . '" width="' . $postThumb[1] . '" height="' . $postThumb[2] . '"]';
                         }
                     }
                     $result->recipe->instructions .= $content . "\n";
                 }
             }
             $result->recipe->instructions = rtrim($result->recipe->instructions, "\n");
             $ingredients = get_posts('post_status=publish&post_type=gmc_recipeingredient&nopaging=1&orderby=menu_order&order=ASC&post_parent=' . $postID);
             $currentSection = '';
             /** @var $ingredient WP_Post */
             foreach ($ingredients as $ingredient) {
                 $section = get_post_meta($ingredient->ID, "gmc-ingredientgroup", true);
                 if (!empty($section) && $section != $currentSection) {
                     $result->ingredients[] = "!{$section}";
                     $currentSection = $section;
                 }
                 if ($gmcInstalled) {
                     /** @noinspection PhpUndefinedFunctionInspection */
                     $iLine = trim(print_ingredient_description($ingredient));
                 } else {
                     $quantity = get_post_meta($ingredient->ID, "gmc-ingredientquantity", true);
                     $measurement = get_post_meta($ingredient->ID, 'gmc-ingredientmeasurement', true);
                     $title = $ingredient->post_title;
                     $iLine = trim("{$quantity} {$measurement} {$title}");
                 }
                 if (!empty($iLine)) {
                     $result->ingredients[] = $iLine;
                 }
             }
             /**
              * Try to convert HTML in notes into something EasyRecipe will understand
              */
             $notes = preg_replace_callback('%<(strong|em)>(.*?)</\\1>%', array($this, 'notesConversion'), $post->post_content);
             $notes = preg_replace('%<a ([^>]+)>(.*?)</a>%i', '[url $1]$2[/url]', $notes);
             $result->recipe->notes = strip_tags($notes);
             $result->recipe->yield = $servings = get_post_meta($post->ID, "gmc-nr-servings", true);
             $nutrition = new stdClass();
             if (get_post_meta($postID, "gmc_has_nutrition", true)) {
                 $result->recipe->serving_size = get_post_meta($post->ID, "gmc_gda_servings", true);
                 $nutrition->calories = get_post_meta($post->ID, "gmc_nutrition_kcal_serving", true);
                 if ($nutrition->calories != '') {
                     $nutrition->calories *= 1000;
                 }
                 $nutrition->totalFat = round(get_post_meta($post->ID, "gmc_nutrition_fat_total_serving", true)) . 'g';
                 $nutrition->saturatedFat = round(get_post_meta($post->ID, "gmc_nutrition_fat_sat_serving", true)) . 'g';
                 $nutrition->sodium = round(get_post_meta($post->ID, "gmc_nutrition_salt_sod_serving", true)) . 'mg';
                 $nutrition->totalCarbohydrates = round(get_post_meta($post->ID, "gmc_nutrition_carb_total_serving", true)) . 'g';
                 $nutrition->dietaryFiber = round(get_post_meta($post->ID, "gmc_nutrition_fibre_serving", true)) . 'g';
                 $nutrition->sugars = round(get_post_meta($post->ID, "gmc_nutrition_carb_sugar_serving", true)) . 'g';
                 $nutrition->protein = round(get_post_meta($post->ID, "gmc_nutrition_protein_serving", true)) . 'g';
             }
             $result->recipe->nutrition = $nutrition;
             break;
         case 'kitchebug':
             break;
     }
     return $result;
 }
 /**
  * Process any EasyRecipes in all the posts on the page
  * We need to do this here rather than in the_content hook because by then it's too late to queue up the scripts/styles we'll need
  *
  * @param $posts
  *
  * @return array
  */
 function thePosts($posts)
 {
     /* @var $wp_rewrite WP_Rewrite */
     global $wp_rewrite;
     /** @global  $wpdb wpdb */
     global $wpdb;
     /**
      * We don't want to process anything if it's a missing URL
      */
     if (is_404()) {
         return $posts;
     }
     global $shortcode_tags;
     $guestpost = null;
     $newPosts = array();
     /**
      * Process each post and replace placeholders with relevant data
      */
     foreach ($posts as $post) {
         /**
          * Have we already processed this post?
          */
         if (isset($this->easyrecipes[$post->ID])) {
             $post->post_content = $this->postContent[$post->ID];
             $newPosts[] = $post;
             continue;
         }
         /**
          * We may have to change the rating method (e.g. for Ziplist recipes) so make a local copy
          */
         $this->ratingMethod = $this->settings->ratings;
         /**
          * Do we want to take over processing of other recipe plugins posts?
          * If this is a post from another plugin and we are displaying it, make the rating method "Self Rated" unless ratings are disabled
          */
         if (!is_admin()) {
             $this->converted = false;
             if ($this->settings->displayZiplist) {
                 $post->post_content = preg_replace_callback('/\\[amd-(zlrecipe)-recipe:(\\d+)\\]/', array($this, 'doConvert'), $post->post_content);
                 if ($this->converted && $this->settings->ratings != 'Disabled') {
                     $this->ratingMethod = 'SelfRated';
                 }
             }
             if ($this->settings->displayRecipeCard) {
                 $post->post_content = preg_replace_callback('/\\[(yumprint)-recipe id=[\'"]"(\\d+)[\'"]\\]/', array($this, 'doConvert'), $post->post_content);
                 if ($this->converted && $this->settings->ratings != 'Disabled') {
                     $this->ratingMethod = 'SelfRated';
                 }
             }
             if ($this->settings->displayGMC) {
                 $post->post_content = preg_replace_callback('/\\[(gmc_recipe) (\\d+)\\]/', array($this, 'doConvert'), $post->post_content);
                 if ($this->converted && $this->settings->ratings != 'Disabled') {
                     $this->ratingMethod = 'SelfRated';
                 }
             }
             if ($this->settings->displayUltimateRecipe) {
                 if ($post->post_type == 'recipe') {
                     $post->post_content = "[ultimate-recipe id='{$post->ID}']";
                     $post->post_type = 'post';
                 }
                 $post->post_content = preg_replace_callback('/\\[(ultimate-recipe) id=["\'](\\d+|random)["\']\\]/i', array($this, 'doConvert'), $post->post_content);
                 if ($this->converted && $this->settings->ratings != 'Disabled') {
                     $this->ratingMethod = 'SelfRated';
                 }
             }
             if ($this->settings->displayRecipage) {
                 /**
                  * Do a quick check before we go to the expense of instantiating a DOMDocument
                  */
                 if (strpos($post->post_content, 'hrecipe f') !== false) {
                     $document = new EasyRecipePlusDOMDocument($post->post_content);
                     if ($document->isValid()) {
                         /** @var DOMElement $hrecipe */
                         $hrecipe = $document->getElementByClassName('hrecipe');
                         if ($hrecipe) {
                             $matches = array();
                             $matches[1] = 'recipage';
                             $matches[2] = $post->ID;
                             $convertedRecipe = $this->doConvert($matches);
                             /** @var DOMDocumentFragment $fragment */
                             $fragment = $document->createDocumentFragment();
                             $fragment->appendXML($convertedRecipe);
                             $hrecipe->parentNode->replaceChild($fragment, $hrecipe);
                             $content = $document->saveHTML();
                             $post->post_content = preg_replace('%^.*</head><body>(.*)</body></html>\\s*$%sm', '$1', $content);
                         }
                     }
                 }
             }
         }
         /**
          * Handle the guest post shortcodes here because WP doesn't process them until much later
          * We may need to redirect so we need to do it before anything else has a chance to do output
          * We may also need to process a recipe
          */
         if ($post->ID == $this->settings->gpDetailsPage || $post->ID == $this->settings->gpEntryPage || $post->ID == $this->settings->gpThanksPage) {
             if (empty($guestPost)) {
                 $guestPost = new EasyRecipePlusGuestPost($this);
             }
             $gpResult = $guestPost->process($post);
             /**
              * If $guestPost->process() returns something, we processed the GP entry page
              * In this case, all we need to do is save it in $newPosts and continue
              * Otherwise, continue with processing since there may conceivably be an EasyRecipe on the post/page
              *
              * TODO - do we really need to do this?  Won't it get picked up just below anyway?
              */
             if ($gpResult) {
                 $newPosts[] = $gpResult;
                 continue;
             }
         }
         $postDOM = new EasyRecipePlusDocument($post->post_content);
         if (!$postDOM->isEasyRecipe) {
             if (strncasecmp($post->post_content, '[easyrecipe_page]', 17) === 0) {
                 $this->easyrecipes[$post->ID] = true;
                 $post->post_content = str_replace('[easyrecipe_page]', '', $post->post_content);
             }
             $newPosts[] = $post;
             continue;
         }
         $postDOM->setSettings($this->settings);
         /**
          * Mark this post as an easyrecipe so that the comment and rating processing know
          */
         $this->easyrecipes[$post->ID] = true;
         /**
          * Make sure we haven't already formatted this post. This can happen in preview mode where WP replaces the post_content
          * of the parent with the autosave content which we've already processed.
          * If this is the case, save the formatted code and mark this post as having been processed
          * TODO - are there implications for the object cache for themes that re-read posts?
          */
         if ($postDOM->isFormatted) {
             $this->postContent[$post->ID] = $post->post_content;
             $newPosts[] = $post;
             continue;
         }
         /**
          * Fix possibly broken times in older posts
          * Fix the Cholesterol typo oops in early versions
          */
         if ($postDOM->recipeVersion < '3') {
             $postDOM->fixTimes("preptime");
             $postDOM->fixTimes("cooktime");
             $postDOM->fixTimes("duration");
             $postDOM->setParentValueByClassName("cholestrol", $this->settings->lblCholesterol, "Cholestrol");
         }
         $data = new stdClass();
         /**
          * Get the ratings from the comment meta table if we use the EasyRecipe comment method
          * Other rating methods are handled in EasyRecipePlusDocument->applyStyle()
          * hasRatings is left unset for Self Rating
          */
         if ($this->ratingMethod == 'EasyRecipe') {
             $q = "SELECT COUNT(*) AS count, SUM(meta_value) AS sum FROM {$wpdb->comments} JOIN {$wpdb->commentmeta} ON {$wpdb->commentmeta}.comment_id = {$wpdb->comments}.comment_ID ";
             $q .= "WHERE comment_approved = 1 AND meta_key = 'ERRating' AND comment_post_ID = {$post->ID} AND meta_value > 0";
             $ratings = $wpdb->get_row($q);
             if ((int) $ratings->count > 0) {
                 $data->ratingCount = $ratings->count;
                 $data->ratingValue = number_format($ratings->sum / $ratings->count, 1);
                 $data->ratingPC = $data->ratingValue * 100 / 5;
                 $data->hasRating = true;
             } else {
                 $data->hasRating = false;
             }
         } else {
             if ($this->ratingMethod == 'Disabled') {
                 $data->hasRating = false;
             }
         }
         switch ($this->settings->saveButton) {
             case 'Ziplist':
                 $data->saveButtonJS = self::ZIPLISTJS;
                 $data->saveButton = sprintf(self::ZIPLISTBUTTON, $this->settings->ziplistPartnerKey, urlencode(get_permalink($post->ID)), $this->settings->lblSave);
                 $data->hasSave = true;
                 break;
             case 'BigOven':
                 $data->saveButtonJS = '';
                 $data->saveButton = sprintf(self::BIGOVENBUTTON, self::$EasyRecipePlusUrl);
                 $data->hasSave = true;
                 break;
         }
         $this->settings->getLabels($data);
         $data->hasLinkback = $this->settings->allowLink;
         $data->displayPrint = $this->settings->displayPrint;
         $data->style = $this->styleName;
         $data->title = $post->post_title;
         $data->blogname = get_option("blogname");
         // TODO - do all this stuff at initialise time?
         $data->siteURL = $this->homeURL;
         /**
          * If the site isn't using permalinks then just pass the print stuff as a qurerystring param
          */
         if ($wp_rewrite->using_permalinks()) {
             $data->sitePrintURL = $data->siteURL;
         } else {
             $data->sitePrintURL = $data->siteURL . "?";
         }
         $data->postID = $post->ID;
         $data->recipeurl = get_permalink($post->ID);
         $data->convertFractions = $this->settings->convertFractions;
         if ($this->styleName[0] == '_') {
             $styleName = substr($this->styleName, 1);
             $templateFile = $this->settings->customTemplates . "/styles/{$styleName}/style.html";
         } else {
             $templateFile = self::$EasyRecipePlusDir . "/styles/{$this->styleName}/style.html";
         }
         $template = new EasyRecipePlusTemplate($templateFile);
         $data->isLoggedIn = is_user_logged_in();
         /**
          * Apply styles to the recipe data and return the content with recipes replace by a shortcode and also each recipe's HTML
          * Also keep a copy so we don't have to reformat in the case where the theme asks for the same post again
          *
          * This didn't work!  Some themes don't call the_content() (esp for excerpts) so we can't rely on hooking into that to supply the formatted html
          * We need to do it right here - it seems that the_posts is the only reliable place to replace the base recipe HTML with the formatted recipe HTML
          */
         /**
          * Replace the original content with the one that has the easyrecipe(s) nicely formatted and marked up
          * Also keep a copy so we don't have to reformat in the case where the theme asks for the same post again
          */
         $this->postContent[$post->ID] = $post->post_content = $postDOM->applyStyle($template, $data);
         /**
          * If we haven't already done so, hook into the_content filter to stop wpauto() messing with recipe HTML
          */
         if (empty($shortcode_tags['easyrecipe'])) {
             add_filter('the_content', array($this, 'theContent'), 0);
             add_shortcode('easyrecipe', array($this, 'replaceRecipeShortcode'));
         }
         /**
          * Some themes do a get_post() again instead of using the posts as modified by plugins
          * So make sure our modified post is in cache so the get_post() picks up the modified version not the original
          * Need to do both add and replace since add doesn't replace and replace doesn't add and we can't be sure if the cache key exists at this point
          */
         wp_cache_add($post->ID, $post, 'posts');
         wp_cache_replace($post->ID, $post, 'posts');
         $newPosts[] = $post;
     }
     return $newPosts;
 }
 /**
  * Possibly convert other recipe plugin data
  * Most of these are handled by shortcodes which we replace with an EasyRecipe equivalent
  * Recipage is a little more involved. It is hrecipe formatted and we can't reliably extract the recipe code with a regex, so we need to use a DOMDocument
  *
  * @param $postID
  * @param $postType
  * @param $content
  * @return mixed|string
  */
 public function possiblyConvert($postID, $postType, $content)
 {
     $this->converted = false;
     $this->convertedType = $postType;
     if ($this->settings->displayZiplist) {
         $content = preg_replace_callback('/\\[amd-(zlrecipe)-recipe:(\\d+)\\]/', array($this, 'doConvert'), $content);
         if ($this->converted && $this->settings->ratings != 'Disabled') {
             $this->ratingMethod = 'SelfRated';
         }
     }
     if ($this->settings->displayRecipeCard) {
         $content = preg_replace_callback('/\\[(yumprint)-recipe id=[\'"](\\d+)[\'"]\\]/', array($this, 'doConvert'), $content);
         if ($this->converted && $this->settings->ratings != 'Disabled') {
             $this->ratingMethod = 'SelfRated';
         }
     }
     if ($this->settings->displayGMC) {
         $content = preg_replace_callback('/\\[(gmc_recipe) (\\d+)\\]/', array($this, 'doConvert'), $content);
         if ($this->converted && $this->settings->ratings != 'Disabled') {
             $this->ratingMethod = 'SelfRated';
         }
     }
     if ($this->settings->displayUltimateRecipe) {
         //            if ($postType == 'recipe') {
         $content = str_replace('[recipe]', "[ultimate-recipe id='{$postID}']", $content);
         $content = preg_replace_callback('/\\[(ultimate-recipe) id=["\'](\\d+|random)["\']\\]/i', array($this, 'doConvert'), $content);
         if ($this->converted && $this->settings->ratings != 'Disabled') {
             $this->ratingMethod = 'SelfRated';
         }
         $this->convertedType = 'post';
         //            }
     }
     if ($this->settings->displayRecipage) {
         /**
          * Do a quick check before we go to the expense of instantiating a DOMDocument
          */
         if (strpos($content, 'hrecipe f') !== false) {
             $document = new EasyRecipePlusDOMDocument($content);
             if ($document->isValid()) {
                 /** @var DOMElement $hrecipe */
                 $hrecipe = $document->getElementByClassName('hrecipe');
                 if ($hrecipe) {
                     $matches = array();
                     $matches[1] = 'recipage';
                     $matches[2] = $postID;
                     $convertedRecipe = $this->doConvert($matches);
                     /** @var DOMDocumentFragment $fragment */
                     $fragment = $document->createDocumentFragment();
                     $fragment->appendXML($convertedRecipe);
                     $hrecipe->parentNode->replaceChild($fragment, $hrecipe);
                     $content = $document->saveHTML();
                     $content = preg_replace('%^.*</head><body>(.*)</body></html>\\s*$%sm', '$1', $content);
                 }
             }
         }
     }
     return $content;
 }