/**
  * Update all taxonomies.
  * This should only ever be called from a cron job scheduled by EasyRecipeScheduler 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 = EasyRecipeSettings::getInstance();
     $settings->taxonomiesCreated = true;
     $settings->update();
     /**
      * Mark this job as complete
      */
     $this->scheduler->terminate();
 }
 /**
  * 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
      */
     $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 = EasyRecipe::$EasyRecipeURL;
     /** @noinspection PhpUndefinedClassInspection */
     $this->pluginDir = EasyRecipe::$EasyRecipeDir;
     /**
      * Get our own settings. This is the same for all Easy Plugins and individualised by the build processs
      */
     /** @noinspection PhpUndefinedClassInspection */
     $settings = EasyRecipeSettings::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;
     }
     /**
      * Re-output anything that may have been in the buffer before we started
      */
     echo $existingOP;
 }
 /**
  * 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 = EasyRecipeSettings::getInstance();
         if ($this->settings->enableFooderific) {
             $this->fdPostStatusChanged('publish', 'future', $post);
         }
     }
 }
 /**
  * @static
  * @return EasyRecipeSettings
  */
 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('EasyRecipe', false);
         if (!self::$instance) {
             self::$instance = new EasyRecipeSettings();
             /**
              * 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
              */
             $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 EasyRecipeSettings) {
             self::$instance = new EasyRecipeSettings(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, EasyRecipe::$pluginVersion) == -1 || !self::$instance->taxonomiesCreated;
         if ($updateCheck) {
             EasyRecipeUpdate::check(self::$instance);
             /**
              * Save the new settings version (will be the same as the installed pluginVersion)
              */
             self::$instance->settingsVersion = EasyRecipe::$pluginVersion;
             $updateOptions = true;
         }
         /**
          * 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('EasyRecipe', self::$instance);
         }
     }
     return self::$instance;
 }
 /**
  * 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 = EasyRecipeSettings::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);
 }