/** * Explicitly allow the itemprop, datetime and link attributes otherwise WP will strip them * * @param $postID */ function publishFuturePost($postID) { global $allowedposttags; $post = get_post($postID); if (strpos($post->post_content, 'easyrecipe') !== false) { $allowedposttags['time'] = array('itemprop' => true, 'datetime' => true); $allowedposttags['link'] = array('itemprop' => true, 'href' => true); $this->settings = EasyRecipePlusSettings::getInstance(); if ($this->settings->enableFooderific) { $this->fdPostStatusChanged('publish', 'future', $post); } } }
/** * 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; }
/** * Scan all posts for recipes if $postID == 0, or a single post if $postID <> 0 and send basic details to fooderific * If it's a sitewide scan, data is batched up to minimize network traffic * * @param int $postID Scan all posts if this is zero, else a single post if not */ function scanRun($postID = 0) { /* @var $wpdb wpdb */ global $wpdb; $settings = EasyRecipePlusSettings::getInstance(); $this->delay = $settings->scanDelay; $this->getRecipePlugins(); /** * Read each published post (or the specific post if we're processing a specific post's update) and if it contains a recipe, then shoot the details off to fooderific.com * We're not interested in attachments or revisions. Also probably not interested in other types, but we don't know about custom post types so process anything else */ if ($postID != 0) { $q = "SELECT * FROM {$wpdb->prefix}posts WHERE ID = '{$postID}' AND post_type <> 'attachment' AND post_type <> 'revision'"; $this->batchSize = 1; } else { $q = "SELECT * FROM {$wpdb->prefix}posts WHERE post_status = 'publish' AND post_type <> 'attachment' AND post_type <> 'revision' ORDER BY ID DESC"; $this->batchSize = self::BATCHSIZE; $settings->lastScanStarted = time(); $settings->update(); } $posts = $wpdb->get_results($q); /** * If this is a scan, notify fooderific that we're starting */ if ($postID == 0) { $data = new stdClass(); $data->action = 'start'; $data->wpurl = get_bloginfo("wpurl"); $data->count = count($posts); $args = array('body' => array('data' => serialize($data))); wp_remote_post(self::FOODERIFIC_URL, $args); } $this->nPostsSent = 0; $this->results = array(); /** * Flag that we're running in scan so we don't schedule another scan on top of this one * Don't hold for longer than SCAN_TIMEOUT seconds so if the process crashes or has some kind of problem, it's not going to stop another scan later */ set_transient(self::FOODERIFIC_SCAN, 'run', self::SCAN_TIMEOUT); /** * Also reset the run time limit to SCAN_TIMEOUT seconds so unintended loops or horribly slow processing doesn't tie this up forever */ @set_time_limit(self::SCAN_TIMEOUT); foreach ($posts as $post) { $this->processPost($post); } if (count($this->results) > 0) { $this->nPostsSent += count($this->results); $args = array('body' => array('data' => serialize($this->results))); wp_remote_post(self::FOODERIFIC_URL, $args); $this->results = array(); } /** * If this was a scan, notify fooderific that we're done */ if ($postID == 0) { $data = new stdClass(); $data->action = 'stop'; $data->wpurl = get_bloginfo("wpurl"); $data->count = $this->nPostsSent; $args = array('body' => array('data' => serialize($data))); wp_remote_post(self::FOODERIFIC_URL, $args); } delete_transient(self::FOODERIFIC_SCAN); }
/** * Save a reference to the global settings * Add a reference to this instance in an array indexed by postID so that, given a postID, we can figure out which instance to use * * @param EasyRecipePlus $plugin */ function __construct(EasyRecipePlus $plugin) { $this->plugin = $plugin; $this->settings = EasyRecipePlusSettings::getInstance(); }
/** * @static * @return EasyRecipePlusSettings */ static function getInstance() { $freeSettings = null; $updateOptions = false; /** * If we haven't already instantiated settings, try to do it from the options */ if (!self::$instance) { self::$instance = get_option('EasyRecipePlus', false); if (!self::$instance) { self::$instance = new EasyRecipePlusSettings(); /** * There were no Plus settings saved * See if we have any free version settings and copy those if there are */ $freeSettings = get_option('EasyRecipe'); if (!empty($freeSettings)) { foreach (self::$defaultSettings as $setting => $default) { if (isset($freeSettings->{$setting})) { self::$instance->{$setting} = $freeSettings->{$setting}; } } $updateOptions = true; } /** * If we're updating from a very early version, copy the old settings which are still relevant * Any not set in the defaults are deprecated and we can drop them */ if (empty($freeSettings)) { $v31Settings = get_option('ERPlusSettings'); if (!$v31Settings) { $v31Settings = get_option('ERSettings'); } if (!empty($v31Settings)) { foreach ($v31Settings as $setting => $value) { if (isset(self::$defaultSettings[$setting])) { self::$instance->{$setting} = $value; } } $updateOptions = true; } } } /** * Fixup possible legacy problems where the options weren't stored as the correct class */ if (!self::$instance instanceof EasyRecipePlusSettings) { self::$instance = new EasyRecipePlusSettings(self::$instance); $updateOptions = true; } /** * If this is the first run of the plugin after an update, see if we need to do any processing specific to this update. * Also do the update check if the taxonomies haven't been created yet * * TODO - determine if this is a new install - won't need to check if so? */ $updateCheck = version_compare(self::$instance->settingsVersion, EasyRecipePlus::$pluginVersion) == -1 || !self::$instance->taxonomiesCreated; if ($updateCheck) { EasyRecipePlusUpdate::check(self::$instance); /** * Save the new settings version (will be the same as the installed pluginVersion) */ self::$instance->settingsVersion = EasyRecipePlus::$pluginVersion; $updateOptions = true; } /** * Do we need to fix the .tmp stuff up that happened on some installs of ER 3.2.2802? * Only need to check if the current version is > 2802 * Should be able to remove this once the few sites that it affects get updated */ if (version_compare(EasyRecipePlus::$pluginVersion, '3.2.2802') == 1) { EasyRecipePlusUpdate::check2802(); } /** * Set any defaults which haven't been set in the current version (i.e. new settings just introduced) * TODO - remove any options no longer needed? */ foreach (self::$defaultSettings as $setting => $default) { if (!isset(self::$instance->{$setting})) { self::$instance->{$setting} = $default; $updateOptions = true; } } /** * Update the settings if we changed them during construction */ if ($updateOptions) { update_option('EasyRecipePlus', self::$instance); } } return self::$instance; }
/** * Gets details about the site and installed plugins etc * * @return stdClass Object containing diagnostics data */ function get() { global $wp_version; /** @var wpdb $wpdb */ global $wpdb; /** * Get the php info. Save anything already in the output buffer, just in case it's relevant for the site's output in show() */ $this->existingOP = ob_get_clean(); ob_start(); phpinfo(); $phpinfo = ob_get_contents(); ob_end_clean(); preg_match('%<body>(.*)</body>%si', $phpinfo, $regs); $this->phpinfo = $regs[1]; /** @noinspection PhpUndefinedClassInspection */ $this->pluginURL = EasyRecipePlus::$EasyRecipePlusUrl; /** @noinspection PhpUndefinedClassInspection */ $this->pluginDir = EasyRecipePlus::$EasyRecipePlusDir; /** * Get our own settings. This is the same for all Easy Plugins and individualised by the build processs */ /** @noinspection PhpUndefinedClassInspection */ $settings = EasyRecipePlusSettings::getInstance(); /** * Don't send any settings (passwords etc) that we really have no business knowing */ if (isset($settings->privateSettings)) { foreach ($settings->privateSettings as $privateSetting) { if (isset($settings->{$privateSetting})) { unset($settings->{$privateSetting}); } } unset($settings->privateSettings); } $this->settings = $settings; $capabilities = ""; get_currentuserinfo(); $user = $GLOBALS['current_user']; if (isset($user->caps)) { foreach ($user->caps as $cap => $allowed) { if ($allowed) { $capabilities .= "{$cap},"; } } } $this->wpCapabilities = rtrim($capabilities, ","); $this->wpVersion = $wp_version; $this->wpSiteURL = site_url(); $this->wpHomeURL = home_url(); $this->wpMultiSite = is_multisite() ? 'Yes' : 'No'; $this->mysqlVersion = $wpdb->db_version(); $this->gmtOffset = get_option('gmt_offset'); $this->timezone = get_option('timezone_string'); if ($wp_version < '3.4') { /** @noinspection PhpDeprecationInspection */ $themeData = get_theme_data(get_stylesheet_directory() . "/style.css"); $this->wpTheme = $themeData["Name"]; $this->wpThemeVersion = $themeData["Version"]; $this->wpThemeURL = $themeData["URI"]; } else { $themeData = wp_get_theme(); $this->wpTheme = $themeData->get("Name"); $this->wpThemeVersion = $themeData->get("Version"); $this->wpThemeURL = $themeData->get("ThemeURI"); } if (!function_exists('get_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $plugins = get_plugins(); foreach ($plugins as $pluginFile => $null) { $plugins[$pluginFile]["active"] = is_plugin_active($pluginFile) ? "Active" : "Inactive"; } usort($plugins, array($this, "sortPlugins")); $this->PLUGINS = array(); foreach ($plugins as $plugin) { $item = new stdClass(); $item->name = $plugin["Title"]; $item->active = $plugin["active"]; $item->version = $plugin["Version"]; $item->url = $plugin["PluginURI"]; $this->PLUGINS[] = $item; } }
/** * Update all taxonomies. * This should only ever be called from a cron job scheduled by EasyRecipePlusScheduler because it can potentially take quite a while */ function updateAll() { /** @var wpdb $wpdb */ global $wpdb; /** * If we are already running, don't do it again */ if ($this->scheduler->isRunning()) { return; } /** * Set as running * Set a "timeout" of 10 minutes. This will prevent it being re-run for 10 minutes if the current run terminates abnormally for any reason */ $this->scheduler->setRunning(10 * 60); $q = "SELECT ID FROM {$wpdb->posts} WHERE post_type NOT IN ('attachment','index','nav_menu_item')"; $postIDs = $wpdb->get_col($q); $this->countTerms['cuisine'] = array(); $this->countTerms['course'] = array(); foreach ($postIDs as $postID) { $post = WP_Post::get_instance($postID); $this->update($post, false); } /** * Update any term counts that we may have adjusted */ if (count($this->countTerms['cuisine']) > 0) { wp_update_term_count_now(array_unique(array_keys($this->countTerms['cuisine'])), 'cuisine'); } if (count($this->countTerms['course']) > 0) { wp_update_term_count_now(array_unique(array_keys($this->countTerms['course'])), 'course'); } /** * Mark the taxonomies as having been created */ $settings = EasyRecipePlusSettings::getInstance(); $settings->taxonomiesCreated = true; $settings->update(); /** * Mark this job as complete */ $this->scheduler->terminate(); }