/**
 * Creates a blacklist entry for the given feed item.
 * 
 * @since 4.4
 * @param int|string The ID of the feed item to add to the blacklist
 */
function wprss_blacklist_item($ID)
{
    // Return if feed item is null
    if (is_null($ID)) {
        return;
    }
    // Get the feed item data
    $item_title = get_the_title($ID);
    $item_permalink = get_post_meta($ID, 'wprss_item_permalink', TRUE);
    // If not an imported item, stop
    if ($item_permalink === '') {
        wprss_log_obj('An item being blacklisted was ignored for not being an imported item', $ID, null, WPRSS_LOG_LEVEL_INFO);
        return;
    }
    // Prepare the data for blacklisting
    $title = apply_filters('wprss_blacklist_title', trim($item_title));
    $permalink = apply_filters('wprss_blacklist_permalink', trim($item_permalink));
    // Get the blacklisted items
    $blacklist = wprss_get_blacklist();
    // Add the item to the blacklist
    $blacklist[$permalink] = $title;
    // Delete the item
    wp_delete_post($ID, TRUE);
    // Add the blacklisted item
    $id = wp_insert_post(array('post_title' => $title, 'post_type' => 'wprss_blacklist', 'post_status' => 'publish'));
    update_post_meta($id, 'wprss_permalink', $permalink);
}
 /**
  * Copied from {@see SimplePie_File#__construct()}.
  * Adds call to {@see _before_curl_exec()}.
  * 
  * @since 4.7
  */
 public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
 {
     if (class_exists('idna_convert')) {
         $idn = new idna_convert();
         $parsed = SimplePie_Misc::parse_url($url);
         $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
         wprss_log_obj('Converted IDNA URL', $url, null, WPRSS_LOG_LEVEL_SYSTEM);
     }
     $this->url = $url;
     $this->useragent = $useragent;
     if (preg_match('/^http(s)?:\\/\\//i', $url)) {
         if ($useragent === null) {
             $useragent = ini_get('user_agent');
             $this->useragent = $useragent;
         }
         if (!is_array($headers)) {
             $headers = array();
         }
         if (!$force_fsockopen && function_exists('curl_exec')) {
             $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
             $fp = curl_init();
             $headers2 = array();
             foreach ($headers as $key => $value) {
                 $headers2[] = "{$key}: {$value}";
             }
             if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>=')) {
                 curl_setopt($fp, CURLOPT_ENCODING, '');
             }
             curl_setopt($fp, CURLOPT_URL, $url);
             curl_setopt($fp, CURLOPT_HEADER, 1);
             curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
             curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
             curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
             curl_setopt($fp, CURLOPT_REFERER, $url);
             curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
             curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
             if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>=')) {
                 curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
                 curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
             }
             $this->_before_curl_exec($fp, $url);
             $this->headers = curl_exec($fp);
             if (curl_errno($fp) === 23 || curl_errno($fp) === 61) {
                 curl_setopt($fp, CURLOPT_ENCODING, 'none');
                 $this->headers = curl_exec($fp);
             }
             if (curl_errno($fp)) {
                 $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
                 $this->success = false;
             } else {
                 $info = curl_getinfo($fp);
                 curl_close($fp);
                 $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
                 $this->headers = array_pop($this->headers);
                 $parser = new SimplePie_HTTP_Parser($this->headers);
                 if ($parser->parse()) {
                     $this->headers = $parser->headers;
                     $this->body = $parser->body;
                     $this->status_code = $parser->status_code;
                     if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) {
                         $this->redirects++;
                         $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
                         return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
                     }
                 }
             }
         } else {
             $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
             $url_parts = parse_url($url);
             $socket_host = $url_parts['host'];
             if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https') {
                 $socket_host = "ssl://{$url_parts['host']}";
                 $url_parts['port'] = 443;
             }
             if (!isset($url_parts['port'])) {
                 $url_parts['port'] = 80;
             }
             $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
             if (!$fp) {
                 $this->error = 'fsockopen error: ' . $errstr;
                 $this->success = false;
             } else {
                 stream_set_timeout($fp, $timeout);
                 if (isset($url_parts['path'])) {
                     if (isset($url_parts['query'])) {
                         $get = "{$url_parts['path']}?{$url_parts['query']}";
                     } else {
                         $get = $url_parts['path'];
                     }
                 } else {
                     $get = '/';
                 }
                 $out = "GET {$get} HTTP/1.1\r\n";
                 $out .= "Host: {$url_parts['host']}\r\n";
                 $out .= "User-Agent: {$useragent}\r\n";
                 if (extension_loaded('zlib')) {
                     $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
                 }
                 if (isset($url_parts['user']) && isset($url_parts['pass'])) {
                     $out .= "Authorization: Basic " . base64_encode("{$url_parts['user']}:{$url_parts['pass']}") . "\r\n";
                 }
                 foreach ($headers as $key => $value) {
                     $out .= "{$key}: {$value}\r\n";
                 }
                 $out .= "Connection: Close\r\n\r\n";
                 fwrite($fp, $out);
                 $info = stream_get_meta_data($fp);
                 $this->headers = '';
                 while (!$info['eof'] && !$info['timed_out']) {
                     $this->headers .= fread($fp, 1160);
                     $info = stream_get_meta_data($fp);
                 }
                 if (!$info['timed_out']) {
                     $parser = new SimplePie_HTTP_Parser($this->headers);
                     if ($parser->parse()) {
                         $this->headers = $parser->headers;
                         $this->body = $parser->body;
                         $this->status_code = $parser->status_code;
                         if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) {
                             $this->redirects++;
                             $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
                             return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
                         }
                         if (isset($this->headers['content-encoding'])) {
                             // Hey, we act dumb elsewhere, so let's do that here too
                             switch (strtolower(trim($this->headers['content-encoding'], "\t\n\r "))) {
                                 case 'gzip':
                                 case 'x-gzip':
                                     $decoder = new SimplePie_gzdecode($this->body);
                                     if (!$decoder->parse()) {
                                         $this->error = 'Unable to decode HTTP "gzip" stream';
                                         $this->success = false;
                                     } else {
                                         $this->body = $decoder->data;
                                     }
                                     break;
                                 case 'deflate':
                                     if (($decompressed = gzinflate($this->body)) !== false) {
                                         $this->body = $decompressed;
                                     } else {
                                         if (($decompressed = gzuncompress($this->body)) !== false) {
                                             $this->body = $decompressed;
                                         } else {
                                             if (function_exists('gzdecode') && ($decompressed = gzdecode($this->body)) !== false) {
                                                 $this->body = $decompressed;
                                             } else {
                                                 $this->error = 'Unable to decode HTTP "deflate" stream';
                                                 $this->success = false;
                                             }
                                         }
                                     }
                                     break;
                                 default:
                                     $this->error = 'Unknown content coding';
                                     $this->success = false;
                             }
                         }
                     }
                 } else {
                     $this->error = 'fsocket timed out';
                     $this->success = false;
                 }
                 fclose($fp);
             }
         }
     } else {
         $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
         if (!($this->body = file_get_contents($url))) {
             $this->error = 'file_get_contents could not read the file';
             $this->success = false;
         }
     }
 }
Beispiel #3
0
/**
 * Insert wprss_feed_item posts into the DB
 *
 * @since 3.0
 */
function wprss_items_insert_post($items, $feed_ID)
{
    // Gather the permalinks of existing feed item's related to this feed source
    $existing_permalinks = get_existing_permalinks($feed_ID);
    foreach ($items as $item) {
        // Convert the url if it is a video url and the conversion is enabled in the settings.
        $permalink = wprss_convert_video_permalink($item->get_permalink());
        // Save the enclosure URL
        $enclosure_url = '';
        if ($enclosure = $item->get_enclosure(0)) {
            if ($enclosure->get_link()) {
                $enclosure_url = $enclosure->get_link();
            }
        }
        /* OLD NORMALIZATION CODE - TO NORMALIZE URLS FROM PROXY URLS
        			$response = wp_remote_head( $permalink );
        			if ( !is_wp_error(  $response ) && isset( $response['headers']['location'] ) ) {
        				$permalink = current( explode( '?', $response['headers']['location'] ) );
        			}*/
        // Check if newly fetched item already present in existing feed items,
        // if not insert it into wp_posts and insert post meta.
        if (!in_array($permalink, $existing_permalinks)) {
            // Apply filters that determine if the feed item should be inserted into the DB or not.
            $item = apply_filters('wprss_insert_post_item_conditionals', $item, $feed_ID, $permalink);
            // If the item is not NULL, continue to inserting the feed item post into the DB
            if ($item !== NULL) {
                $feed_item = apply_filters('wprss_populate_post_data', array('post_title' => html_entity_decode($item->get_title()), 'post_content' => '', 'post_status' => 'publish', 'post_type' => 'wprss_feed_item', 'post_date' => get_date_from_gmt($item->get_date('Y-m-d H:i:s')), 'post_date_gmt' => $item->get_date('Y-m-d H:i:s')), $item);
                if (defined('ICL_SITEPRESS_VERSION')) {
                    @(include_once WP_PLUGIN_DIR . '/sitepress-multilingual-cms/inc/wpml-api.php');
                }
                if (defined('ICL_LANGUAGE_CODE')) {
                    $_POST['icl_post_language'] = $language_code = ICL_LANGUAGE_CODE;
                }
                // Create and insert post object into the DB
                $inserted_ID = wp_insert_post($feed_item);
                if (!is_wp_error($inserted_ID)) {
                    if (is_object($inserted_ID)) {
                        if (isset($inserted_ID['ID'])) {
                            $inserted_ID = $inserted_ID['ID'];
                        } elseif (isset($inserted_ID->ID)) {
                            $inserted_ID = $inserted_ID->ID;
                        }
                    }
                    // Create and insert post meta into the DB
                    wprss_items_insert_post_meta($inserted_ID, $item, $feed_ID, $permalink, $enclosure_url);
                    // Remember newly added permalink
                    $existing_permalinks[] = $permalink;
                } else {
                    wprss_log_obj('Failed to insert post', $feed_item, 'wprss_items_insert_post > wp_insert_post');
                }
            }
        }
    }
}
/**
 * Generate a preview of the latest 5 posts from the feed source being added/edited
 *
 * @since 2.0
 */
function wprss_preview_meta_box_callback()
{
    global $post;
    $feed_url = get_post_meta($post->ID, 'wprss_url', true);
    $help = WPRSS_Help::get_instance();
    /* @var $help WPRSS_Help */
    echo '<div id="feed-preview-container">';
    if (!empty($feed_url)) {
        $feed = wprss_fetch_feed($feed_url, $post->ID);
        if (!is_wp_error($feed)) {
            $items = $feed->get_items();
            // Figure out how many total items there are
            $total = $feed->get_item_quantity();
            // Get the number of items again, but limit it to 5.
            $maxitems = $feed->get_item_quantity(5);
            // Build an array of all the items, starting with element 0 (first element).
            $items = $feed->get_items(0, $maxitems);
            ?>
				<h4><?php 
            echo sprintf(__('Latest %1$s feed items out of %2$s available from %3$s'), $maxitems, $total, get_the_title());
            ?>
</h4>
                <ul>
				<?php 
            foreach ($items as $item) {
                // Get human date (comment if you want to use non human date)
                $has_date = $item->get_date('U') ? TRUE : FALSE;
                if ($has_date) {
                    $item_date = human_time_diff($item->get_date('U'), current_time('timestamp')) . ' ' . __('ago', 'rc_mdm');
                } else {
                    $item_date = '<em>[' . __('No Date', WPRSS_TEXT_DOMAIN) . ']</em>';
                }
                // Start displaying item content within a <li> tag
                echo '<li>';
                // create item link
                //echo '<a href="'.esc_url( $item->get_permalink() ).'" title="'.$item_date.'">';
                // Get item title
                echo esc_html($item->get_title());
                //echo '</a>';
                // Display date
                echo ' <div class="rss-date"><small>' . $item_date . '</small></div>';
                // End <li> tag
                echo '</li>';
            }
            ?>
				</ul>
				<?php 
        } else {
            ?>
                <span class="invalid-feed-url">
                    <?php 
            _e('<strong>Invalid feed URL</strong> - Double check the feed source URL setting above.', WPRSS_TEXT_DOMAIN);
            ?>
                    <?php 
            wprss_log_obj('Failed to preview feed.', $feed->get_error_message(), NULL, WPRSS_LOG_LEVEL_INFO);
            ?>
                </span>
				<?php 
            echo wpautop(sprintf(__('Not sure where to find the RSS feed on a website? <a target="_blank" href="%1$s">Click here</a> for a visual guide. ', WPRSS_TEXT_DOMAIN), 'http://webtrends.about.com/od/webfeedsyndicationrss/ss/rss_howto.htm'));
        }
    } else {
        echo '<p>' . __('No feed URL defined yet', WPRSS_TEXT_DOMAIN) . '</p>';
    }
    echo '</div>';
    echo '<div id="force-feed-container">';
    wprss_render_force_feed_option($post->ID, TRUE);
    echo '</div>';
}
/**
 * Insert wprss_feed_item posts into the DB
 *
 * @since 3.0
 */
function wprss_items_insert_post($items, $feed_ID)
{
    update_post_meta($feed_ID, 'wprss_feed_is_updating', $update_started_at = time());
    wprss_log_obj('Starting import of items for feed ' . $feed_ID, $update_started_at, null, WPRSS_LOG_LEVEL_INFO);
    // Gather the permalinks of existing feed item's related to this feed source
    $existing_permalinks = wprss_get_existing_permalinks($feed_ID);
    // Count of items inserted
    $items_inserted = 0;
    foreach ($items as $item) {
        // Normalize the URL
        $permalink = wprss_normalize_permalink($item->get_permalink());
        wprss_log_obj('Importing item', $permalink, null, WPRSS_LOG_LEVEL_INFO);
        wprss_log_obj('Original permalink', $item->get_permalink(), null, WPRSS_LOG_LEVEL_SYSTEM);
        // Save the enclosure URL
        $enclosure_url = '';
        if ($enclosure = $item->get_enclosure(0)) {
            wprss_log('Item has an enclosure', null, WPRSS_LOG_LEVEL_SYSTEM);
            if ($enclosure->get_link()) {
                $enclosure_url = $enclosure->get_link();
                wprss_log_obj('Enclosure has link', $enclosure_url, null, WPRSS_LOG_LEVEL_SYSTEM);
            }
        }
        /* OLD NORMALIZATION CODE - TO NORMALIZE URLS FROM PROXY URLS
        			$response = wp_remote_head( $permalink );
        			if ( !is_wp_error(  $response ) && isset( $response['headers']['location'] ) ) {
        				$permalink = current( explode( '?', $response['headers']['location'] ) );
        			}*/
        // Check if newly fetched item already present in existing feed items,
        // if not insert it into wp_posts and insert post meta.
        if (!array_key_exists($permalink, $existing_permalinks)) {
            wprss_log("Importing (unique) feed item (Source: {$feed_ID})", null, WPRSS_LOG_LEVEL_INFO);
            // Extend the importing time and refresh the feed's updating flag to reflect that it is active
            $extend_time = wprss_flag_feed_as_updating($feed_ID);
            $extend_time_f = date('Y-m-d H:i:s', $extend_time);
            $time_limit = wprss_get_item_import_time_limit();
            wprss_log("Extended execution time limit by {$time_limit}. (Current Time: {$extend_time_f})", null, WPRSS_LOG_LEVEL_INFO);
            set_time_limit($time_limit);
            // Apply filters that determine if the feed item should be inserted into the DB or not.
            $item = apply_filters('wprss_insert_post_item_conditionals', $item, $feed_ID, $permalink);
            // Check if the imported count should still be updated, even if the item is NULL
            $still_update_count = apply_filters('wprss_still_update_import_count', FALSE);
            // If the item is not NULL, continue to inserting the feed item post into the DB
            if ($item !== NULL && !is_bool($item)) {
                wprss_log('Using core logic', null, WPRSS_LOG_LEVEL_SYSTEM);
                // Get the date and GTM date and normalize if not valid dor not present
                $format = 'Y-m-d H:i:s';
                $has_date = $item->get_date('U') ? TRUE : FALSE;
                $timestamp = $has_date ? $item->get_date('U') : date('U');
                $date = date($format, $timestamp);
                $date_gmt = gmdate($format, $timestamp);
                // Prepare the item data
                $feed_item = apply_filters('wprss_populate_post_data', array('post_title' => html_entity_decode($item->get_title()), 'post_content' => '', 'post_status' => 'publish', 'post_type' => 'wprss_feed_item', 'post_date' => $date, 'post_date_gmt' => $date_gmt), $item);
                wprss_log('Post data filters applied', null, WPRSS_LOG_LEVEL_SYSTEM);
                if (defined('ICL_SITEPRESS_VERSION')) {
                    @(include_once WP_PLUGIN_DIR . '/sitepress-multilingual-cms/inc/wpml-api.php');
                }
                if (defined('ICL_LANGUAGE_CODE')) {
                    $_POST['icl_post_language'] = $language_code = ICL_LANGUAGE_CODE;
                    wprss_log_obj('WPML detected. Language code determined', $language_code, null, WPRSS_LOG_LEVEL_SYSTEM);
                }
                // Create and insert post object into the DB
                $inserted_ID = wp_insert_post($feed_item);
                if (!is_wp_error($inserted_ID)) {
                    if (is_object($inserted_ID)) {
                        if (isset($inserted_ID['ID'])) {
                            $inserted_ID = $inserted_ID['ID'];
                        } elseif (isset($inserted_ID->ID)) {
                            $inserted_ID = $inserted_ID->ID;
                        }
                    }
                    // Increment the inserted items counter
                    $items_inserted++;
                    // Create and insert post meta into the DB
                    wprss_items_insert_post_meta($inserted_ID, $item, $feed_ID, $permalink, $enclosure_url);
                    // Remember newly added permalink
                    $existing_permalinks[$permalink] = 1;
                    wprss_log_obj('Item imported', $inserted_ID, null, WPRSS_LOG_LEVEL_INFO);
                } else {
                    update_post_meta($source, 'wprss_error_last_import', 'An error occurred while inserting a feed item into the database.');
                    wprss_log_obj('Failed to insert post', $feed_item, 'wprss_items_insert_post > wp_insert_post');
                }
            } elseif (is_bool($item) && $item === TRUE || $still_update_count === TRUE && $item !== FALSE) {
                $items_inserted++;
            }
        } else {
            wprss_log('Item already exists and will be skipped', null, WPRSS_LOG_LEVEL_NOTICE);
        }
        wprss_log_obj('Finished importing item', $permalink, null, WPRSS_LOG_LEVEL_INFO);
    }
    update_post_meta($feed_ID, 'wprss_last_update_items', $items_inserted);
    wprss_log_obj(sprintf('Finished importing %1$d items for feed source', $items_inserted), $feed_ID, null, WPRSS_LOG_LEVEL_INFO);
}
Beispiel #6
0
/**
 * Deletes N oldest feed items for the given source
 *
 * @since 4.2
 */
function wprss_delete_oldest_feed_items($n, $source)
{
    // If the source does not exist, do nothing
    if (get_post($source) == NULL) {
        return;
    }
    // Make sure $n is an integer
    $n = intval($n);
    // Do nothing if n is zero or negative
    if ($n <= 0) {
        return;
    }
    // Get the feed items, as an array, not WP_Query.
    // We will need to perform some array operations
    $feed_items = wprss_get_feed_items_for_source($source);
    $feed_items = $feed_items->get_posts();
    // Get number of feed items
    $count = count($feed_items);
    // Index of first feed item to delete
    $start = $count - $n;
    // Cut the array of feed items to get the items to delete
    $to_delete = array_slice($feed_items, $start);
    // log -- for now
    foreach ($to_delete as $fi) {
        wprss_log_obj("To delete", $fi->ID);
    }
}
	/**
	 * Determines the featured image for the imported post.
	 *
	 * This is ran after images have been downloaded, and remote URLS have
	 * been replaced with local ones, if necessary.
	 *
	 * @since 2.7.4
	 * @param int $post_ID The ID of the post that is being imported.
	 * @param int $source The ID of the feed source, which is importing the post
	 * @param array $images A numeric array, where each value is the local URL of an image in post content.
	 */
	public function determine_featured_image_for_post( $post_ID, $source, $images ) {
		wprss_log_obj( 'Beginning featured image selection for post:', $post_ID, NULL, WPRSS_LOG_LEVEL_SYSTEM );

		// Get the post form the ID
		$post = get_post( $post_ID );
		// If the post is null, return null.
		if ( $post === NULL ) {
			wprss_log( 'Received incorrect or NULL post ID.', NULL, WPRSS_LOG_LEVEL_ERROR );
			// Trigger action for no featured image determined for this post
			do_action( 'wprss_ftp_no_featured_image', $post_ID, $source );
			return null;
		}

		// Get the post content
		$content = $post->post_content;

		// Get the computed settings for the feed source
		$options = WPRSS_FTP_Settings::get_instance()->get_computed_options( $source );

		// If the featured image option is disabled, do NOT continue.
		if ( WPRSS_FTP_Utils::multiboolean( $options['use_featured_image'] ) === FALSE ) {
			wprss_log( "Feed source for this post has featured images disabled. Stopping ...", NULL, WPRSS_LOG_LEVEL_SYSTEM );
			// Trigger action for no featured image determined for this post
			do_action( 'wprss_ftp_no_featured_image', $post_ID, $source );
			return null;
		}

		// Start by trimming whitespace from image URLs
		$images = array_map( 'trim', $images );

		// The URL of the determined featured image
		$featured_image_url = NULL;

		// Get the minimum image size settings
		$min_width = $options['image_min_width'];
		$min_height = $options['image_min_height'];

		// DETERMINED FEATURED IMAGE
		$featured_image = NULL;
		// WHETHER OR NOT USING THE FALLBACK IMAGE (used to skip most of the image processing in the function)
		$using_fallback = FALSE;

		wprss_log( 'Featured image option: `'.$options['featured_image'].'`', NULL, WPRSS_LOG_LEVEL_SYSTEM );

		// Check which featured image option is being used
		switch ( $options['featured_image'] ) {
			default:

			// FIRST/LAST image in post content
			case 'first':
			case 'last':

				// If using the Last Image option, reverse the images array
				if ( $options['featured_image'] === 'last' )
					$images = array_reverse( $images, true );

				wprss_log( "Iterating images in post.", NULL, WPRSS_LOG_LEVEL_SYSTEM );

				// Iterate through all the images
				foreach( $images as $_old => $_image ) {
					// The the image URL is empty, or it does not obey the minimum size constraint, jump to next image
					if ( empty( $images[ $_old ] ) || !$this->image_obeys_minimum_size( $_old, $min_width, $min_height ) )
						continue;

					// Attempt to use this iamge as featured imafe
					$ft_image_found = $_image;
					$featured_image = $_image;

					wprss_log_obj( "Found good image:", $featured_image, NULL, WPRSS_LOG_LEVEL_SYSTEM );

					// Check if the image URL is local
					if ( !wprss_ftp_is_url_local( $featured_image ) ) {
						wprss_log( "Not found in gallery. Downloading ...", NULL, WPRSS_LOG_LEVEL_SYSTEM );
						// If not, download it and attach it to the post
						$featured_image = apply_filters( 'wprss_ftp_featured_image_url', $featured_image, $post_ID, $source, $options['featured_image'] );
						$featured_image = wprss_ftp_media_sideload_image( $featured_image, $post_ID, TRUE );
					}
					// If it is local, simply attach it to the post
					else {
						wprss_log( "Found in gallery. Attaching to post ...", NULL, WPRSS_LOG_LEVEL_SYSTEM );
						$featured_image = apply_filters( 'wprss_ftp_featured_image_url', $featured_image, $post_ID, $source, $options['featured_image'] );
						self::set_featured_image( $post_ID, $featured_image, TRUE );
					}

					// If no error was encountered, exit the loop
					// If an error was encountered, the next image will be tested.
					if ( !is_wp_error( $featured_image ) )
						break;
				}

				// Indicate that NO image was used as featured image
				if ( is_wp_error( $featured_image ) ) {
					$featured_image = NULL;
					WPRSS_FTP_Utils::log_object( 'Could not determine featured image from first/last', $featured_image->get_error_message(), __METHOD__, WPRSS_FTP_Utils::LOG_LEVEL_SYSTEM );
				}

				break; // END OF FIRST / LAST IMAGE CASE


			// FEED <MEDIA:THUMBNAIL> IMAGE / <ENCLOSURE> TAG
			case 'thumb':
			case 'enclosure':

				// Prepare the tag in which to look for the image
				$tag = ( $options['featured_image'] == 'thumb' )? 'media:thumbnail' : 'enclosure:thumbnail';
				$orig_tag = $tag;
				$tag = apply_filters( 'wprss_ftp_featured_image_meta_key', $tag, $post_ID, $source, $options['featured_image'] );
				WPRSS_FTP_Utils::log_object( 'Custom field used for featured image', $tag, null, WPRSS_FTP_Utils::LOG_LEVEL_SYSTEM );

				/* Get the media thumbnail from post meta ( converter class places the tag contents in post meta ).
				 * If the original meta key was modified by the `wprss_ftp_featured_image_meta_key` filter,
				 * no prefix is applied to the meta key.
				 */
				$thumbnail = trim( WPRSS_FTP_Meta::get_instance()->get_meta( $post_ID, $tag, ($use_prefix = $tag === $orig_tag) ) );

				// Check if the thumbnail is large enough to accept
				if ( $this->image_obeys_minimum_size( $thumbnail, $min_width, $min_height ) === TRUE ) {
					// Download this image, attach it to the post and use it as the featured image
					$thumbnail = apply_filters( 'wprss_ftp_featured_image_url', $thumbnail, $post_ID, $source, $options['featured_image'] );
					$featured_image = wprss_ftp_media_sideload_image( $thumbnail, $post_ID, TRUE );
					// If an error was encountered, set the featured image to NULL
					if ( is_wp_error( $featured_image ) ) {
						WPRSS_FTP_Utils::log_object( 'Could not determine featured image from thumb/emclosure', $featured_image->get_error_message(), __METHOD__, WPRSS_FTP_Utils::LOG_LEVEL_SYSTEM );
						$featured_image = NULL;
					}
				}

				break; // END OF MEDIA:THUMBNAIL / ENCLOSURE CASE


			// FALLBACK FEATURED IMAGE
			case 'fallback':

				// Get the fallback featured image
				$fallback_image = get_post_thumbnail_id( $source );

				// Check if the fallback featured image is set
				if ( !empty( $fallback_image ) ) {
					// If it is set, use it as featured image for the imported post
					self::set_featured_image( $post_ID, $fallback_image );
					// Indicate that the fallback was used
					$using_fallback = TRUE;
				}
				break;

		} // End of switch


		// If the fallback image was used, then we are done.
		if ( ! $using_fallback ) {
			// If a featured image was determined
			if ( $featured_image !== NULL && !is_wp_error( $featured_image ) ) {
				// Check for filter to remove featured image from post
				$remove_ft_image = apply_filters( 'wprss_ftp_remove_ft_image_from_content', FALSE );
				// We remove the ft image, if the filter returns TRUE, or if it returns an array and the post source is in the array.
				$remove = $remove_ft_image === TRUE || ( is_array( $remove_ft_image ) && in_array( $source, $remove_ft_image ) );

				// If removing and the ft image is in the content (not media:thumbnail)
				// (Determined either by legacy filter or meta option)
				if ( $remove || WPRSS_FTP_Utils::multiboolean( $options['remove_ft_image'] ) === TRUE ) {
					$img_to_remove = $featured_image;
					if ( $options['featured_image'] === 'first' || $options['featured_image'] === 'last' ) {
						$img_to_remove = $ft_image_found;
					}
					// Prepare the img tag regex
					$d = '|'; // In case the image tag contains the pipe somewhere, it needs to be escaped too
					$tag_search = '<img.*?src=[\'"]' . preg_quote( esc_attr( $img_to_remove ), $d ) . '[\'"].*?>';
					// Replace the tag with an empty string, and get the new content
					$new_content = preg_replace( $d . $tag_search . $d . 'i', '', $content, apply_filters('wprss_ftp_remove_ft_image_limit', 1) );
					WPRSS_FTP_Utils::log_object( sprintf('Featured image %1$sremoved from content', $new_content === $content ? 'not ' : ''), $img_to_remove, __FUNCTION__, WPRSS_FTP_Utils::LOG_LEVEL_INFO);
					// Update the post content
					WPRSS_FTP_Utils::update_post_content( $post_ID, $new_content );
				}
			}

			// However,
			// If NO featued image was determined
			else {
				$featured_image = NULL;

				// Get the user filter for using the feed image
				$user_filter = apply_filters( 'wprss_ftp_feed_image_fallback', FALSE, $post_ID, $source, $images );
				$user_filter_enabled = $user_filter === TRUE || ( is_array( $user_filter ) && in_array( $source, $user_filter ) );

				// Check if the core supports getting the feed image and if the user filter is enabled
				if ( function_exists( 'wprss_get_feed_image' ) && $user_filter_enabled ) {
					// Get the url of the feed image
					$feed_image = wprss_get_feed_image( $source );

					// Attempt to download it and attach it to the post
					$feed_image = apply_filters( 'wprss_ftp_featured_image_url', $feed_image, $post_ID, $source, $options['featured_image'] );
					$featured_image = wprss_ftp_media_sideload_image( $feed_image, $post_ID, TRUE );

					// If an error was encountered, indicate it by setting the featured image to NULL
					if ( is_wp_error( $featured_image ) || $featured_image === NULL ) {
						$featured_image = NULL;
					}
				}

				// If the feed image did not work, resort to using the fallback, if set
				if ( $featured_image == NULL ) {
					// Get the fallback image
					$fallback_image = get_post_thumbnail_id( $source );
					// If it is set, use it as the featured image for the post
					if ( !empty( $fallback_image ) ) {
						self::set_featured_image( $post_ID, $fallback_image );
					} else {
						// Trigger action for no featured image determined for this post
						do_action( 'wprss_ftp_no_featured_image', $post_ID, $source );
					}
				}
			}
		}

		do_action( 'wprss_ftp_determined_featured_image', $post_ID, $source );
	}
	/**
	 * Handles extraction for the given post.
	 * 
	 * @since 2.5
	 */
	public static function extract( $post_id, $source ) {

		// If a source is set ( hence an imported post ), ...
		if ( $source !== '' ) {

			// Get the extraction rules of the source
			$rules = self::get_extraction_rules_and_types( $source );
			wprss_log_obj( 'Got extraction rules', $rules, NULL, WPRSS_LOG_LEVEL_SYSTEM );

			// If the rules are not an array or there are no rules, return
			if ( !is_array( $rules ) && count( $rules ) == 0 ) return;

			// Load the ganon library
			if ( version_compare(phpversion(), '5.3.1', '<') ) {
				// PHP4 Ganon
				require_once( WPRSS_FTP_LIB . 'ganon.php4' );
			}
			else {
				// PHP5+ Ganon
				require_once( WPRSS_FTP_LIB . 'ganon.php' );
			}

			// Get the post
			$post = get_post( $post_id );
			// If the post is a WP error, return
			if ( is_wp_error( $post ) || !is_object( $post ) ) return;
			// Otherwise, get the content
			$content = $post->post_content;

			// Parse the post content
			$html = str_get_dom( $content );

			// For each rule and its type
			foreach ( $rules as $rule => $type ) {

				// Trim the rule string
				$rule = trim( $rule );
				// If the rule is empty, skip it
				if ( strlen( $rule ) === 0 ) {
					continue;
				}

				// Used to replace the current html DOM
				$new_html = '';

				// Each found element ...
				foreach ( $html->select($rule) as $element ) {
					// Check the rule type
					switch( $type ) {
						// If keeping the matched element
						case 'keep' :
							// Add the element as a string to the new_html variable
							$new_html .= $element->toString(TRUE, TRUE, FALSE);
							break;
						// Remove the element
						case 'remove' :
							$element->detach();
							break;
						// Remove the element, and keep its children
						case 'remove_keep_children' :
							$element->detach( TRUE );
							break;
					}
				}

				// If the new_html variable has changed, use it as the new HMTL DOM
				if ( strlen( $new_html ) > 0 ) {
					$html = str_get_dom( $new_html );
				}

			} // End of rules foreach

			// Update the post with its new content
			$new_content = (string)$html;
			WPRSS_FTP_Utils::update_post_content( $post_id, $new_content );
		}

	}