FeedWordPress - Version 0.91

Version Description

Download this release

Release Info

Developer radgeek
Plugin Icon wp plugin FeedWordPress
Version 0.91
Comparing to
See all releases

Code changes from version 0.9 to 0.91

README.text CHANGED
@@ -2,33 +2,31 @@ FeedWordPress
2
  =============
3
 
4
  * Author: [Charles Johnson](http://www.radgeek.com/contact)
5
- * Version: 0.9
6
  * Project URI: <http://projects.radgeek.com/feedwordpress>
7
  * License: GPL. See License below for copyright jots and tittles.
8
 
9
  Introduction
10
  ------------
11
  FeedWordPress is an Atom/RSS aggregator for WordPress. It syndicates content
12
- from newsfeeds that you select; if you syndicate several newsfeeds then you can
13
- WordPress's posts database and templating engine as the back-end of an
14
- aggregation ("planet") website.
15
-
16
- FeedWordPress is similar in conception to software such as [Planet][]--in fact,
17
- I started developing it because I needed a more flexible replacement for
18
- Planet at to run [Feminist Blogs](http://www.feministblogs.org/). Since it
19
- works on top of WordPress's database and templating system, however, it boasts
20
- far more flexibility than many other aggregators. It is also designed with ease
21
- of configuration and use in mind.
22
-
23
- You'll need a working installation of [WordPress 1.5][] and FTP or SFTP access
24
- to your web host. The ability to create cron jobs on your web host would be very
25
- helpful but it's not absolutely necessary. You *don't* need to tweak any
26
- plain-text configuration files and you *don't* need shell access to your web
27
- host to make it work. (Although, I should point out, web hosts that *don't*
28
- offer shell access are *bad web hosts*.)
29
 
30
- [WordPress 1.5]: http://wordpress.org/development/2005/02/strayhorn/
31
  [Planet]: http://www.planetplanet.org/ "Planet Planet"
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  Installation & Requirements
34
  ---------------------------
@@ -122,7 +120,7 @@ The URI should be changed out for each feed to point to the appropriate image,
122
  of course. Then, to use the setting from within a template:
123
 
124
  // In a post context
125
- <?php $img = get_feed_meta('face'); if strlen($img) > 0): ?>
126
  <img src="<?=$img?>" alt="" />
127
  <?php endif; ?>
128
 
@@ -149,16 +147,54 @@ processes posts from that feed. Currently, the special settings are:
149
  Link Name field automatically to reflect the title that is reported by a
150
  syndicated feed. (So, for example, if one of your contributors changes
151
  the title of her weblog, the change will be reflected on your
152
- Contributors list after the next update.) To override that behavior for
153
- a particular feed (e.g. to force WordPress to use an abbreviated form of
154
- the site's title for reasons of space), add a line like this to the Link
155
- Notes section:
 
156
 
157
  hardcode name: yes
158
 
159
  If `hardcode name` is absent, or set to a value other than `yes`,
160
  FeedWordPress will take that as a 'no' and follow the default behavior.
161
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  - `post status:` sets the default post status for posts from this feed
163
  This can be 'publish', 'draft', or 'private'. By default, it is set to
164
  'publish' (syndicated posts go online immediately).
2
  =============
3
 
4
  * Author: [Charles Johnson](http://www.radgeek.com/contact)
5
+ * Version: 0.91
6
  * Project URI: <http://projects.radgeek.com/feedwordpress>
7
  * License: GPL. See License below for copyright jots and tittles.
8
 
9
  Introduction
10
  ------------
11
  FeedWordPress is an Atom/RSS aggregator for WordPress. It syndicates content
12
+ from newsfeeds that you select into your WordPress blog; if you syndicate
13
+ several newsfeeds then you can WordPress's posts database and templating engine
14
+ as the back-end of an aggregation ("planet") website. I originally developed it
15
+ because I needed a more flexible replacement for [Planet][] to use at
16
+ [Feminist Blogs][].
 
 
 
 
 
 
 
 
 
 
 
 
17
 
 
18
  [Planet]: http://www.planetplanet.org/ "Planet Planet"
19
+ [Feminist Blogs]: http://www.feministblogs.org/
20
+
21
+ FeedWordPress is designed with flexibility, ease of use, and ease of
22
+ configuration in mind. You'll need a working installation of [WordPress 1.5][]
23
+ and FTP or SFTP access to your web host. The ability to create cron jobs on your
24
+ web host would be very helpful but it's not absolutely necessary. You *don't*
25
+ need to tweak any plain-text configuration files and you *don't* need shell
26
+ access to your web host to make it work. (Although, I should point out, web
27
+ hosts that *don't* offer shell access are *bad web hosts*.)
28
+
29
+ [WordPress 1.5]: http://wordpress.org/development/2005/02/strayhorn/
30
 
31
  Installation & Requirements
32
  ---------------------------
120
  of course. Then, to use the setting from within a template:
121
 
122
  // In a post context
123
+ <?php $img = get_feed_meta('face'); if (strlen($img) > 0): ?>
124
  <img src="<?=$img?>" alt="" />
125
  <?php endif; ?>
126
 
147
  Link Name field automatically to reflect the title that is reported by a
148
  syndicated feed. (So, for example, if one of your contributors changes
149
  the title of her weblog, the change will be reflected on your
150
+ Contributors list after the next update.) To manually set the Link Name
151
+ and prevent your new name from being overridden by FeedWordPress (so as
152
+ to, for example, use an abbreviated form of the site's title for reasons
153
+ of space), change the Link Name to a title of your choosing and then add
154
+ a line like this to the Link Notes section:
155
 
156
  hardcode name: yes
157
 
158
  If `hardcode name` is absent, or set to a value other than `yes`,
159
  FeedWordPress will take that as a 'no' and follow the default behavior.
160
 
161
+ - `hardcode description: (yes|no)`
162
+
163
+ A yes/no setting. By default, FeedWordPress updates the value of the
164
+ Link Description field automatically to reflect the tagline or
165
+ description that is reported by a syndicated feed. To manually set the
166
+ Link Description and prevent your new description from being overridden
167
+ by FeedWordPress (so as to, for example, use an abbreviated form of the
168
+ site's tagline for reasons of space), change the Link Description to a
169
+ title of your choosing and then add a line like this to the Link Notes
170
+ section:
171
+
172
+ hardcode description: yes
173
+
174
+ If `hardcode description` is absent, or set to a value other than `yes`,
175
+ FeedWordPress will take that as a 'no' and follow the default behavior.
176
+
177
+ - `hardcode categories: (yes|no)`
178
+
179
+ A yes/no setting. FeedWordPress places each syndicated post in a set of
180
+ categories within WordPress. It gets that list from two sources:
181
+
182
+ 1. Categories that you set explicitly for each feed (see the `cats` setting above)
183
+
184
+ 2. Categories that the original author placed the post in on her blog
185
+
186
+ If any of the categories on the list do not exist, they are created automatically.
187
+
188
+ If you want the posts from a particular feed to be placed *only* in the
189
+ categories that you set manually (see the `cats` setting above), and not
190
+ in the categories that they are in on the Contributor's blog, then add
191
+ a line like this to the Link Notes section:
192
+
193
+ hardcode categories: yes
194
+
195
+ If `hardcode categories` is absent, or set to a value other than `yes`,
196
+ FeedWordPress will take that as a 'no' and follow the default behavior.
197
+
198
  - `post status:` sets the default post status for posts from this feed
199
  This can be 'publish', 'draft', or 'private'. By default, it is set to
200
  'publish' (syndicated posts go online immediately).
wp-content/plugins/feedwordpress.php CHANGED
@@ -3,15 +3,13 @@
3
  Plugin Name: FeedWordPress
4
  Plugin URI: http://projects.radgeek.com/feedwordpress
5
  Description: simple and flexible Atom/RSS syndication for WordPress
6
- Version: 0.9
7
  Author: Charles Johnson
8
  Author URI: http://www.radgeek.com/
 
 
9
  */
10
 
11
- # Author: Charles Johnson <technophilia@radgeek.com>
12
- # License: GPL
13
- # Last modified: 2005-03-25
14
- #
15
  # This uses code derived from:
16
  # - wp-rss-aggregate.php by Kellan Elliot-McCrea <kellan@protest.net>
17
  # - HTTP Navigator 2 by Keyvan Minoukadeh <keyvan@k1m.com>
@@ -27,12 +25,9 @@ Author URI: http://www.radgeek.com/
27
  # <http://www.zyx.com/blog>, XML-RPC requests should be sent to
28
  # <http://www.zyx.com/blog/xmlrpc.php>), or see `update-feeds.php`
29
 
30
- # -- Change these as you please
31
- define ('FEEDWORDPRESS_LOG_UPDATES', true); // Make false if you hate status updates sent to error_log()
32
-
33
  # -- Don't change these unless you know what you're doing...
34
  define ('RPC_MAGIC', 'tag:radgeek.com/projects/feedwordpress/');
35
- define ('FEEDWORDPRESS_VERSION', '0.9');
36
  define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
37
 
38
  // Note that the rss-functions.php that comes prepackaged with WordPress is
@@ -40,30 +35,25 @@ define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
40
  // this archive into wp-includes/rss-functions.php
41
  require_once (ABSPATH . WPINC . '/rss-functions.php');
42
 
43
- // Is this being loaded from within WordPress?
44
- if (!isset($wp_version)):
45
- echo "FeedWordPress/".FEEDWORDPRESS_VERSION.": an Atom/RSS aggregator plugin for WordPress 1.5\n";
46
- exit;
47
- endif;
48
-
49
- # Remove default WordPress auto-paragraph filter.
50
- remove_filter('the_content', 'wpautop');
51
- remove_filter('the_excerpt', 'wpautop');
52
- remove_filter('comment_text', 'wpautop');
53
-
54
- # What really should happen here is that we create our own ueber-filter,
55
- # to run with the highest possible priority, which would intercept
56
- # and check whether or not the post comes from off the wire, and
57
- # pre-empty any further formatting filters if it does. Then we could
58
- # leave wpautop in peace and not worry about Markdown, Textile, etc.
59
- # Sadly, WordPress 1.5 gives you no way to pre-empt downstream filters
60
- # (and no way for the furthest downstream filter to recover the original
61
- # content, either.)
62
 
63
- # add_filter('the_content', 'feedwordpress_preempt', 10);
64
- # add_filter('the_excerpt', 'feedwordpress_preempt', 10);
65
- # add_filter('comment_text', 'feedwordpress_preempt', 30);
 
 
 
 
 
 
 
 
 
 
 
66
 
 
67
  add_filter('post_link', 'syndication_permalink', 1);
68
 
69
  # Admin menu
@@ -76,48 +66,50 @@ endif;
76
  remove_action('publish_post', 'generic_ping');
77
  add_action('publish_post', 'fwp_catch_ping');
78
 
79
- $update_logging = get_settings('feedwordpress_update_logging');
80
-
81
- # -- Logging status updates to error_log, if you want it
82
- if ($update_logging == 'yes') :
83
- add_action('post_syndicated_item', 'log_feedwordpress_post', 100);
84
- add_action('update_syndicated_item', 'log_feedwordpress_update_post', 100);
85
- add_action('feedwordpress_update', 'log_feedwordpress_update_feeds', 100);
86
- add_action('feedwordpress_check_feed', 'log_feedwordpress_check_feed', 100);
87
- add_action('feedwordpress_update_complete', 'log_feedwordpress_update_complete', 100);
88
-
89
- function log_feedwordpress_post ($id) {
90
- $post = wp_get_single_post($id);
91
- error_log("[".date('Y-m-d H:i:s')."][feedwordpress] posted "
92
- ."'{$post->post_title}' ({$post->post_date})");
93
- }
94
 
95
- function log_feedwordpress_update_post ($id) {
96
- $post = wp_get_single_post($id);
97
- error_log("[".date('Y-m-d H:i:s')."][feedwordpress] updated "
98
- ."'{$post->post_title}' ({$post->post_date})"
99
- ." (as of {$post->post_modified})");
100
- }
 
101
 
102
- function log_feedwordpress_update_feeds ($uri) {
103
- error_log("[".date('Y-m-d H:i:s')."][feedwordpress] update('$uri')");
104
- }
 
 
105
 
106
- function log_feedwordpress_check_feed ($feed) {
107
- $uri = $feed['url']; $name = $feed['name'];
108
- error_log("[".date('Y-m-d H:i:s')."][feedwordpress] Examining $name <$uri>");
109
- }
110
-
111
- function log_feedwordpress_update_complete ($delta) {
112
- $mesg = array();
113
- if (isset($delta['new'])) $mesg[] = 'added '.$delta['new'].' new posts';
114
- if (isset($delta['updated'])) $mesg[] = 'updated '.$delta['updated'].' existing posts';
115
- if (empty($mesg)) $mesg[] = 'nothing changed';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
- error_log("[".date('Y-m-d H:i:s')."][feedwordpress] "
118
- .(is_null($delta) ? "I don't syndicate <$uri>"
119
- : implode(' and ', $mesg)));
120
- }
121
  endif;
122
 
123
  # -- Template functions for syndication sites
@@ -146,7 +138,7 @@ function get_feed_meta ($key) {
146
  $notes = explode("\n", $result);
147
  foreach ($notes as $note):
148
  list($k, $v) = explode(': ', $note, 2);
149
- $meta[$k] = $v;
150
  endforeach;
151
  $ret = $meta[$key];
152
  endif; /* if */
@@ -161,6 +153,29 @@ function the_syndication_permalink () {
161
  }
162
 
163
  # -- Filters for templates and feeds
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  function syndication_permalink ($permalink = '') {
165
  if (get_settings('feedwordpress_munge_permalink') != 'no'):
166
  $uri = get_syndication_permalink();
@@ -172,8 +187,8 @@ function syndication_permalink ($permalink = '') {
172
 
173
  # -- Admin menu add-ons
174
  function fwp_add_pages () {
175
- add_submenu_page('link-manager.php', 'Syndicated Sites', 'Syndicated', 5, __FILE__, 'fwp_syndication_manage_page');
176
- add_options_page('Syndication', 'Syndication', 6, __FILE__, 'fwp_syndication_options_page');
177
  } // function fwp_add_pages () */
178
 
179
  function fwp_syndication_options_page () {
@@ -285,7 +300,7 @@ if ($cont):
285
  $links = get_linkobjects(FeedWordPress::link_category_id());
286
  ?>
287
  <div class="wrap">
288
- <form action="link-manager.php?page=feedwordpress.php" method="post">
289
  <h2>Syndicate a new site:</h2>
290
  <div>
291
  <label for="add-uri">Website or newsfeed:</label>
@@ -296,7 +311,7 @@ if ($cont):
296
  </form>
297
  </div>
298
 
299
- <form action="link-manager.php?page=feedwordpress.php" method="post">
300
  <div class="wrap">
301
  <h2>Syndicated Sites</h2>
302
  <?php $alt_row = true;
@@ -325,7 +340,7 @@ src="../wp-images/smilies/icon_arrow.gif" alt="&rarr;" /></a></td>
325
  feed assigned</strong></p></td>
326
  <? endif; ?>
327
  <?php if (($link->user_level <= $user_level)): ?>
328
- <td><a href="link-manager.php?page=feedwordpress.php&amp;link_id=<?=$link->link_id?>&amp;action=feedfinder" class="edit"><?=$caption?></a></div></td>
329
  <td><a href="link-manager.php?link_id=<?=$link->link_id?>&amp;action=linkedit" class="edit"><?php _e('Edit')?></a></td>
330
  <td><a href="link-manager.php?link_id=<?=$link->link_id?>&amp;action=Delete" onclick="return confirm('You are about to delete this link.\\n \'Cancel\' to stop, \'OK\' to delete.');" class="delete"><?php _e('Delete'); ?></a></td>
331
  <td><input type="checkbox" name="linkcheck[]" value="<?=$link->link_id?>" /></td>
@@ -386,7 +401,7 @@ function fwp_feedfinder_page () {
386
  $feed_title = isset($rss->channel['title'])?$rss->channel['title']:$rss->channel['link'];
387
  $feed_link = isset($rss->channel['link'])?$rss->channel['link']:'';
388
  ?>
389
- <form action="link-manager.php?page=feedwordpress.php" method="post">
390
  <fieldset style="clear: both">
391
  <legend><?=$rss->feed_type?> <?=$rss->feed_version?> feed</legend>
392
 
@@ -439,7 +454,7 @@ function fwp_feedfinder_page () {
439
  ?>
440
  </div>
441
 
442
- <form action="link-manager.php?page=feedwordpress.php" method="post">
443
  <div class="wrap">
444
  <h2>Use another feed</h2>
445
  <div><label>Feed:</label>
@@ -630,10 +645,17 @@ class FeedWordPress {
630
  $notes = explode("\n", $link->link_notes);
631
  foreach ($notes as $note):
632
  list($key, $value) = explode(": ", $note, 2);
633
- if (strlen($key) > 0) $sec[$key] = $value;
 
 
 
 
 
 
 
634
  endforeach;
635
 
636
- $sec['url'] = $link->link_rss;
637
  $sec['name'] = $link->link_name;
638
 
639
  if (isset($sec['cats'])):
@@ -662,7 +684,7 @@ class FeedWordPress {
662
  $delta = NULL;
663
  foreach ($this->feeds as $feed) {
664
  if (($uri === $secret)
665
- or ($uri === $feed['url'])
666
  or ($uri === $feed['feed/link'])) {
667
  if (is_null($delta)) $delta = array('new' => 0, 'updated' => 0);
668
  do_action('feedwordpress_check_feed', array($feed));
@@ -679,7 +701,7 @@ class FeedWordPress {
679
  }
680
 
681
  function feed2wp ($wpdb, $f) {
682
- $feed = fetch_rss($f['url']);
683
  $new_count = array('new' => 0, 'updated' => 0);
684
 
685
  $this->update_feed($wpdb, $feed->channel, $f);
@@ -723,43 +745,48 @@ class FeedWordPress {
723
  return $matches[1].Relative_URI::resolve($matches[2], $this->_base).$matches[3];
724
  } // function FeedWordPress::resolve_relative_uri ()
725
 
726
- function update_feed ($wpdb, $channel, $f) {
727
  $affirmo = array ('y', 'yes', 't', 'true', 1);
 
 
728
 
 
729
  $link_id = $f['link_id'];
730
 
731
  if (!isset($channel['id'])) {
732
- $channel['id'] = $f['url'];
733
  }
734
 
735
  $update = array();
736
- if (isset($channel['link'])) {
737
  $update[] = "link_url = '".$wpdb->escape($channel['link'])."'";
738
- }
739
- if (isset($channel['title']) and (!isset($f['hardcode name'])
740
- or in_array(trim(strtolower($f['hardcode name'])), $affirmo))) {
741
  $update[] = "link_name = '".$wpdb->escape($channel['title'])."'";
742
- }
743
 
744
- if (isset($channel['tagline'])) {
745
- $update[] = "link_description = '".$wpdb->escape($channel['tagline'])."'";
746
- } elseif (isset($channel['description'])) {
747
- $update[] = "link_description = '".$wpdb->escape($channel['description'])."'";
748
- }
 
 
749
 
750
- if (is_array($f['cats'])) {
751
- $f['cats'] = implode(':',$f['cats']);
752
- } /* if */
753
 
754
  $f = array_merge($f, $this->flatten_array($channel));
755
 
756
  # -- A few things we don't want to save in the notes
757
- unset($f['link_id']); unset($f['uri']); unset($f['url']);
758
 
759
  $notes = '';
760
- foreach ($f as $key => $value) {
761
- $notes .= "${key}: $value\n";
762
- }
763
  $update[] = "link_notes = '".$wpdb->escape($notes)."'";
764
 
765
  $update_set = implode(',', $update);
@@ -823,9 +850,9 @@ class FeedWordPress {
823
  endif;
824
 
825
  if (isset($item['author_url'])):
826
- $post['named']['author']['url'] = $item['author_url'];
827
  else:
828
- $post['named']['author']['url'] = $channel['link'];
829
  endif;
830
 
831
  // ... So far we just have an alphanumeric
@@ -858,7 +885,7 @@ class FeedWordPress {
858
  $content
859
  );
860
  endforeach;
861
-
862
  # Sanitize problematic attributes
863
  foreach ($this->strip_attrs as $pair):
864
  list($tag,$attr) = $pair;
@@ -868,9 +895,24 @@ class FeedWordPress {
868
  $content
869
  );
870
  endforeach;
871
-
 
 
 
 
 
 
 
 
 
 
 
872
  $post['post_content'] = $wpdb->escape($content);
873
-
 
 
 
 
874
  # This is unneeded if wp_insert_post can be used.
875
  # --- cut here ---
876
  $post['post_name'] = sanitize_title($post['post_title']);
@@ -889,7 +931,7 @@ class FeedWordPress {
889
  else:
890
  $post['epoch']['issued'] = time();
891
  endif;
892
-
893
  # As far as I know, only atom currently has a reliable way to
894
  # specify when something was *modified* last
895
  if (isset($item['modified'])):
@@ -897,7 +939,7 @@ class FeedWordPress {
897
  else:
898
  $post['epoch']['modified'] = $post['epoch']['issued'];
899
  endif;
900
-
901
  $post['post_date'] = date('Y-m-d H:i:s', $post['epoch']['issued']);
902
  $post['post_modified'] = date('Y-m-d H:i:s', $post['epoch']['modified']);
903
  $post['post_date_gmt'] = gmdate('Y-m-d H:i:s', $post['epoch']['issued']);
@@ -917,7 +959,7 @@ class FeedWordPress {
917
 
918
  if (isset($channel['title'])) $post['syndication_source'] = $channel['title'];
919
  if (isset($channel['link'])) $post['syndication_source_uri'] = $channel['link'];
920
- $post['syndication_feed'] = $f['url'];
921
 
922
  // In case you want to know the external permalink...
923
  $post['syndication_permalink'] = $item['link'];
@@ -926,9 +968,12 @@ class FeedWordPress {
926
  $post['named']['category'] = $f['cats'];
927
 
928
  // Now add categories from the post, if we have 'em
929
- if (is_array($item['categories'])):
 
 
 
930
  foreach ($item['categories'] as $cat):
931
- if ( strpos($f['url'], 'del.icio.us') !== false ):
932
  $post['named']['category'] = array_merge($post['named']['category'], explode(' ', $cat));
933
  else:
934
  $post['named']['category'][] = $cat;
@@ -960,7 +1005,7 @@ class FeedWordPress {
960
  $wpdb,
961
  $post['named']['author']['name'],
962
  $post['named']['author']['email'],
963
- $post['named']['author']['url']
964
  );
965
 
966
  # -- Look up, or create, numeric ID for categories
@@ -1003,7 +1048,8 @@ class FeedWordPress {
1003
  post_author = '".$post['post_author']."',
1004
  post_date = '".$post['post_date']."',
1005
  post_date_gmt = '".$post['post_date_gmt']."',
1006
- post_content = '".$post['post_content']."',
 
1007
  post_title = '".$post['post_title']."',
1008
  post_name = '".$post['post_name']."',
1009
  post_modified = '".$post['post_modified']."',
@@ -1155,40 +1201,54 @@ class FeedWordPress {
1155
 
1156
  // look up (and create) category ids from a list of categories
1157
  function lookup_categories ($wpdb, $cats) {
1158
- if ( !count($cats) ) return array();
1159
-
1160
- # i'd kill for a decent map function in PHP
1161
- # but that would require functiosn to be first class object, or at least
1162
- # coderef support
1163
- $cat_strs = array();
1164
- foreach ( $cats as $c ) {
1165
- $c = $wpdb->escape($c); $c = "'$c'";
1166
- $cat_strs[] = $c;
1167
- }
1168
-
1169
- $cat_sql = join(',', $cat_strs);
1170
- $sql = "SELECT cat_ID,cat_name from $wpdb->categories WHERE cat_name IN ($cat_sql)";
1171
- $results = $wpdb->get_results($sql);
1172
-
1173
- $cat_ids = array();
1174
- $cat_found = array();
1175
-
1176
- if (!is_null($results)):
1177
- foreach ( $results as $row ) {
1178
- $cat_ids[] = $row->cat_ID;
1179
- $cat_found[] = strtolower($row->cat_name); // Normalize to avoid case problems
1180
- }
1181
- endif;
1182
-
1183
- foreach ($cats as $new_cat):
1184
- $sql = "INSERT INTO $wpdb->categories (cat_name, category_nicename)
1185
- VALUES ('%s', '%s')";
1186
- if (!in_array(strtolower($new_cat), $cat_found)):
1187
- $nice_cat = sanitize_title($new_cat);
1188
- $wpdb->query(sprintf($sql, $wpdb->escape($new_cat), $nice_cat));
1189
- $cat_ids[] = $wpdb->insert_id;
 
 
 
 
1190
  endif;
1191
- endforeach;
 
 
 
 
 
 
 
 
 
 
1192
  return $cat_ids;
1193
  } // function FeedWordPress::lookup_categories ()
1194
 
@@ -1348,24 +1408,23 @@ class FeedFinder {
1348
  if ($uri) $this->uri = $uri;
1349
 
1350
  // Is the result not yet cached?
1351
- if ($this->_cache_uri !== $this->uri) {
1352
- // Retrieve, with headers, using cURL
1353
- $ch = curl_init($this->uri);
1354
- curl_setopt($ch, CURLOPT_HEADER, false);
1355
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
1356
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: close'));
1357
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress'));
1358
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
1359
- curl_setopt($ch, CURLOPT_TIMEOUT, 15);
1360
- $response = curl_exec($ch);
1361
- curl_close($ch);
1362
-
1363
- // Split into headers and content
1364
- $this->_data = $response;
1365
-
1366
- // Kilroy was here
1367
- $this->_cache_uri = $this->uri;
1368
- } /* if */
1369
  } /* FeedFinder::_get () */
1370
 
1371
  function _link_rel_feeds () {
3
  Plugin Name: FeedWordPress
4
  Plugin URI: http://projects.radgeek.com/feedwordpress
5
  Description: simple and flexible Atom/RSS syndication for WordPress
6
+ Version: 0.91
7
  Author: Charles Johnson
8
  Author URI: http://www.radgeek.com/
9
+ License: GPL
10
+ Last modified: 2005-04-09 2:00pm EDT
11
  */
12
 
 
 
 
 
13
  # This uses code derived from:
14
  # - wp-rss-aggregate.php by Kellan Elliot-McCrea <kellan@protest.net>
15
  # - HTTP Navigator 2 by Keyvan Minoukadeh <keyvan@k1m.com>
25
  # <http://www.zyx.com/blog>, XML-RPC requests should be sent to
26
  # <http://www.zyx.com/blog/xmlrpc.php>), or see `update-feeds.php`
27
 
 
 
 
28
  # -- Don't change these unless you know what you're doing...
29
  define ('RPC_MAGIC', 'tag:radgeek.com/projects/feedwordpress/');
30
+ define ('FEEDWORDPRESS_VERSION', '0.91');
31
  define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
32
 
33
  // Note that the rss-functions.php that comes prepackaged with WordPress is
35
  // this archive into wp-includes/rss-functions.php
36
  require_once (ABSPATH . WPINC . '/rss-functions.php');
37
 
38
+ // Is this being loaded from within WordPress 1.5 or later?
39
+ if (isset($wp_version) and $wp_version >= 1.5):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
+ # Syndicated items should not be folded, crumpled, mutilated, or
42
+ # spindled by WordPress formatting filters. But we don't want to
43
+ # interfere with filters for any locally-authored posts.
44
+ #
45
+ # What WordPress should really have is a way for upstream filters to
46
+ # stop downstream filters from running at all. Since it doesn't, and
47
+ # since a downstream filter can't access the original copy of the text
48
+ # that is being filtered, what we will do here is (1) save a copy of the
49
+ # original text upstream, before any other filters run, and then (2)
50
+ # retrieve that copy downstream, after all the other filters run, if
51
+ # this is a syndicated post
52
+ #
53
+ add_filter('the_content', 'feedwordpress_preserve_syndicated_content', -10000);
54
+ add_filter('the_content', 'feedwordpress_restore_syndicated_content', 10000);
55
 
56
+ # Filter in original permalinks if the user wants that
57
  add_filter('post_link', 'syndication_permalink', 1);
58
 
59
  # Admin menu
66
  remove_action('publish_post', 'generic_ping');
67
  add_action('publish_post', 'fwp_catch_ping');
68
 
69
+ $update_logging = get_settings('feedwordpress_update_logging');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
+ # -- Logging status updates to error_log, if you want it
72
+ if ($update_logging == 'yes') :
73
+ add_action('post_syndicated_item', 'log_feedwordpress_post', 100);
74
+ add_action('update_syndicated_item', 'log_feedwordpress_update_post', 100);
75
+ add_action('feedwordpress_update', 'log_feedwordpress_update_feeds', 100);
76
+ add_action('feedwordpress_check_feed', 'log_feedwordpress_check_feed', 100);
77
+ add_action('feedwordpress_update_complete', 'log_feedwordpress_update_complete', 100);
78
 
79
+ function log_feedwordpress_post ($id) {
80
+ $post = wp_get_single_post($id);
81
+ error_log("[".date('Y-m-d H:i:s')."][feedwordpress] posted "
82
+ ."'{$post->post_title}' ({$post->post_date})");
83
+ }
84
 
85
+ function log_feedwordpress_update_post ($id) {
86
+ $post = wp_get_single_post($id);
87
+ error_log("[".date('Y-m-d H:i:s')."][feedwordpress] updated "
88
+ ."'{$post->post_title}' ({$post->post_date})"
89
+ ." (as of {$post->post_modified})");
90
+ }
91
+
92
+ function log_feedwordpress_update_feeds ($uri) {
93
+ error_log("[".date('Y-m-d H:i:s')."][feedwordpress] update('$uri')");
94
+ }
95
+
96
+ function log_feedwordpress_check_feed ($feed) {
97
+ $uri = $feed['uri']; $name = $feed['name'];
98
+ error_log("[".date('Y-m-d H:i:s')."][feedwordpress] Examining $name <$uri>");
99
+ }
100
+
101
+ function log_feedwordpress_update_complete ($delta) {
102
+ $mesg = array();
103
+ if (isset($delta['new'])) $mesg[] = 'added '.$delta['new'].' new posts';
104
+ if (isset($delta['updated'])) $mesg[] = 'updated '.$delta['updated'].' existing posts';
105
+ if (empty($mesg)) $mesg[] = 'nothing changed';
106
+
107
+ error_log("[".date('Y-m-d H:i:s')."][feedwordpress] "
108
+ .(is_null($delta) ? "I don't syndicate <$uri>"
109
+ : implode(' and ', $mesg)));
110
+ }
111
+ endif;
112
 
 
 
 
 
113
  endif;
114
 
115
  # -- Template functions for syndication sites
138
  $notes = explode("\n", $result);
139
  foreach ($notes as $note):
140
  list($k, $v) = explode(': ', $note, 2);
141
+ $meta[$k] = trim($v);
142
  endforeach;
143
  $ret = $meta[$key];
144
  endif; /* if */
153
  }
154
 
155
  # -- Filters for templates and feeds
156
+ $feedwordpress_the_syndicated_content = NULL;
157
+
158
+ function feedwordpress_preserve_syndicated_content ($text) {
159
+ global $feedwordpress_the_syndicated_content;
160
+
161
+ if ( is_syndicated() ) :
162
+ $feedwordpress_the_syndicated_content = $text;
163
+ else :
164
+ $feedwordpress_the_syndicated_content = NULL;
165
+ endif;
166
+ return $text;
167
+ }
168
+
169
+ function feedwordpress_restore_syndicated_content ($text) {
170
+ global $feedwordpress_the_syndicated_content;
171
+
172
+ if ( !is_null($feedwordpress_the_syndicated_content) ) :
173
+ $text = $feedwordpress_the_syndicated_content;
174
+ endif;
175
+
176
+ return $text;
177
+ }
178
+
179
  function syndication_permalink ($permalink = '') {
180
  if (get_settings('feedwordpress_munge_permalink') != 'no'):
181
  $uri = get_syndication_permalink();
187
 
188
  # -- Admin menu add-ons
189
  function fwp_add_pages () {
190
+ add_submenu_page('link-manager.php', 'Syndicated Sites', 'Syndicated', 5, basename(__FILE__), 'fwp_syndication_manage_page');
191
+ add_options_page('Syndication', 'Syndication', 6, basename(__FILE__), 'fwp_syndication_options_page');
192
  } // function fwp_add_pages () */
193
 
194
  function fwp_syndication_options_page () {
300
  $links = get_linkobjects(FeedWordPress::link_category_id());
301
  ?>
302
  <div class="wrap">
303
+ <form action="link-manager.php?page=<?=basename(__FILE__)?>" method="post">
304
  <h2>Syndicate a new site:</h2>
305
  <div>
306
  <label for="add-uri">Website or newsfeed:</label>
311
  </form>
312
  </div>
313
 
314
+ <form action="link-manager.php?page=<?=basename(__FILE__)?>" method="post">
315
  <div class="wrap">
316
  <h2>Syndicated Sites</h2>
317
  <?php $alt_row = true;
340
  feed assigned</strong></p></td>
341
  <? endif; ?>
342
  <?php if (($link->user_level <= $user_level)): ?>
343
+ <td><a href="link-manager.php?page=<?=basename(__FILE__)?>&amp;link_id=<?=$link->link_id?>&amp;action=feedfinder" class="edit"><?=$caption?></a></div></td>
344
  <td><a href="link-manager.php?link_id=<?=$link->link_id?>&amp;action=linkedit" class="edit"><?php _e('Edit')?></a></td>
345
  <td><a href="link-manager.php?link_id=<?=$link->link_id?>&amp;action=Delete" onclick="return confirm('You are about to delete this link.\\n \'Cancel\' to stop, \'OK\' to delete.');" class="delete"><?php _e('Delete'); ?></a></td>
346
  <td><input type="checkbox" name="linkcheck[]" value="<?=$link->link_id?>" /></td>
401
  $feed_title = isset($rss->channel['title'])?$rss->channel['title']:$rss->channel['link'];
402
  $feed_link = isset($rss->channel['link'])?$rss->channel['link']:'';
403
  ?>
404
+ <form action="link-manager.php?page=<?=basename(__FILE__)?>" method="post">
405
  <fieldset style="clear: both">
406
  <legend><?=$rss->feed_type?> <?=$rss->feed_version?> feed</legend>
407
 
454
  ?>
455
  </div>
456
 
457
+ <form action="link-manager.php?page=<?=basename(__FILE__)?>" method="post">
458
  <div class="wrap">
459
  <h2>Use another feed</h2>
460
  <div><label>Feed:</label>
645
  $notes = explode("\n", $link->link_notes);
646
  foreach ($notes as $note):
647
  list($key, $value) = explode(": ", $note, 2);
648
+
649
+ if (strlen($key) > 0) :
650
+ $sec[$key] = str_replace (
651
+ '%newline%',
652
+ "\n",
653
+ trim($value) // trim() off the whitespace. Thanks to Ray Lischner for pointing this out.
654
+ );
655
+ endif;
656
  endforeach;
657
 
658
+ $sec['uri'] = $link->link_rss;
659
  $sec['name'] = $link->link_name;
660
 
661
  if (isset($sec['cats'])):
684
  $delta = NULL;
685
  foreach ($this->feeds as $feed) {
686
  if (($uri === $secret)
687
+ or ($uri === $feed['uri'])
688
  or ($uri === $feed['feed/link'])) {
689
  if (is_null($delta)) $delta = array('new' => 0, 'updated' => 0);
690
  do_action('feedwordpress_check_feed', array($feed));
701
  }
702
 
703
  function feed2wp ($wpdb, $f) {
704
+ $feed = fetch_rss($f['uri']);
705
  $new_count = array('new' => 0, 'updated' => 0);
706
 
707
  $this->update_feed($wpdb, $feed->channel, $f);
745
  return $matches[1].Relative_URI::resolve($matches[2], $this->_base).$matches[3];
746
  } // function FeedWordPress::resolve_relative_uri ()
747
 
748
+ function setting_on ($f, $setting) {
749
  $affirmo = array ('y', 'yes', 't', 'true', 1);
750
+ return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $affirmo));
751
+ }
752
 
753
+ function update_feed ($wpdb, $channel, $f) {
754
  $link_id = $f['link_id'];
755
 
756
  if (!isset($channel['id'])) {
757
+ $channel['id'] = $f['uri'];
758
  }
759
 
760
  $update = array();
761
+ if (isset($channel['link'])) :
762
  $update[] = "link_url = '".$wpdb->escape($channel['link'])."'";
763
+ endif;
764
+
765
+ if (!FeedWordPress::setting_on($f, 'hardcode name') and isset($channel['title'])) :
766
  $update[] = "link_name = '".$wpdb->escape($channel['title'])."'";
767
+ endif;
768
 
769
+ if (!FeedWordPress::setting_on($f, 'hardcode description')) :
770
+ if (isset($channel['tagline'])) :
771
+ $update[] = "link_description = '".$wpdb->escape($channel['tagline'])."'";
772
+ elseif (isset($channel['description'])) :
773
+ $update[] = "link_description = '".$wpdb->escape($channel['description'])."'";
774
+ endif;
775
+ endif;
776
 
777
+ if (is_array($f['cats'])) :
778
+ $f['cats'] = implode(':',$f['cats']);
779
+ endif;
780
 
781
  $f = array_merge($f, $this->flatten_array($channel));
782
 
783
  # -- A few things we don't want to save in the notes
784
+ unset($f['link_id']); unset($f['uri']); unset($f['name']);
785
 
786
  $notes = '';
787
+ foreach ($f as $key => $value) :
788
+ $notes .= $key . ": ". str_replace("\n", "%newline%", $value) . "\n";
789
+ endforeach;
790
  $update[] = "link_notes = '".$wpdb->escape($notes)."'";
791
 
792
  $update_set = implode(',', $update);
850
  endif;
851
 
852
  if (isset($item['author_url'])):
853
+ $post['named']['author']['uri'] = $item['author_url'];
854
  else:
855
+ $post['named']['author']['uri'] = $channel['link'];
856
  endif;
857
 
858
  // ... So far we just have an alphanumeric
885
  $content
886
  );
887
  endforeach;
888
+
889
  # Sanitize problematic attributes
890
  foreach ($this->strip_attrs as $pair):
891
  list($tag,$attr) = $pair;
895
  $content
896
  );
897
  endforeach;
898
+
899
+ # Identify and sanitize excerpt
900
+ $excerpt = NULL;
901
+ if ( isset($item['description']) and $item['description'] ) :
902
+ $excerpt = $item['description'];
903
+ elseif ( isset($content) and $content ) :
904
+ $excerpt = strip_tags($content);
905
+ if (strlen($excerpt) > 255) :
906
+ $excerpt = substr($excerpt,0,252).'...';
907
+ endif;
908
+ endif;
909
+
910
  $post['post_content'] = $wpdb->escape($content);
911
+
912
+ if (!is_null($excerpt)):
913
+ $post['post_excerpt'] = $wpdb->escape($excerpt);
914
+ endif;
915
+
916
  # This is unneeded if wp_insert_post can be used.
917
  # --- cut here ---
918
  $post['post_name'] = sanitize_title($post['post_title']);
931
  else:
932
  $post['epoch']['issued'] = time();
933
  endif;
934
+
935
  # As far as I know, only atom currently has a reliable way to
936
  # specify when something was *modified* last
937
  if (isset($item['modified'])):
939
  else:
940
  $post['epoch']['modified'] = $post['epoch']['issued'];
941
  endif;
942
+
943
  $post['post_date'] = date('Y-m-d H:i:s', $post['epoch']['issued']);
944
  $post['post_modified'] = date('Y-m-d H:i:s', $post['epoch']['modified']);
945
  $post['post_date_gmt'] = gmdate('Y-m-d H:i:s', $post['epoch']['issued']);
959
 
960
  if (isset($channel['title'])) $post['syndication_source'] = $channel['title'];
961
  if (isset($channel['link'])) $post['syndication_source_uri'] = $channel['link'];
962
+ $post['syndication_feed'] = $f['uri'];
963
 
964
  // In case you want to know the external permalink...
965
  $post['syndication_permalink'] = $item['link'];
968
  $post['named']['category'] = $f['cats'];
969
 
970
  // Now add categories from the post, if we have 'em
971
+ if (
972
+ !FeedWordPress::setting_on($f, 'hardcode categories')
973
+ and is_array($item['categories'])
974
+ ):
975
  foreach ($item['categories'] as $cat):
976
+ if ( strpos($f['uri'], 'del.icio.us') !== false ):
977
  $post['named']['category'] = array_merge($post['named']['category'], explode(' ', $cat));
978
  else:
979
  $post['named']['category'][] = $cat;
1005
  $wpdb,
1006
  $post['named']['author']['name'],
1007
  $post['named']['author']['email'],
1008
+ $post['named']['author']['uri']
1009
  );
1010
 
1011
  # -- Look up, or create, numeric ID for categories
1048
  post_author = '".$post['post_author']."',
1049
  post_date = '".$post['post_date']."',
1050
  post_date_gmt = '".$post['post_date_gmt']."',
1051
+ post_content = '".$post['post_content']."',"
1052
+ .(isset($post['post_excerpt']) ? "post_excerpt = '".$post['post_excerpt']."'," : "")."
1053
  post_title = '".$post['post_title']."',
1054
  post_name = '".$post['post_name']."',
1055
  post_modified = '".$post['post_modified']."',
1201
 
1202
  // look up (and create) category ids from a list of categories
1203
  function lookup_categories ($wpdb, $cats) {
1204
+ $cat_ids = array ();
1205
+ if ( count($cats) > 0 ) :
1206
+ # i'd kill for a decent map function in PHP
1207
+ # but that would require functions to be first class object,
1208
+ # or at least coderef support
1209
+ $cat_strs = array();
1210
+ $cat_aka = array();
1211
+ foreach ( $cats as $c ) :
1212
+ $esc = $wpdb->escape(trim($c));
1213
+ $cat_strs[] = "'$esc'";
1214
+ $cat_aka[] = "(LOWER(category_description) RLIKE '(^|\n)a.k.a.( |\t)*:?( |\t)*".strtolower($esc)."( |\t|\r)*(\n|\$)')";
1215
+ endforeach;
1216
+
1217
+ $cat_sql = join(',', $cat_strs);
1218
+ $cat_akas = join(' OR ', $cat_aka);
1219
+
1220
+ $sql = "SELECT cat_ID,cat_name,category_description from $wpdb->categories
1221
+ WHERE cat_name IN ($cat_sql)
1222
+ OR ($cat_akas)";
1223
+ $results = $wpdb->get_results($sql);
1224
+
1225
+ $cat_ids = array();
1226
+ $cat_found = array();
1227
+
1228
+ if (!is_null($results)):
1229
+ foreach ( $results as $row ) :
1230
+ $cat_ids[] = $row->cat_ID;
1231
+ $cat_found[] = strtolower($row->cat_name); // Normalize to avoid case problems
1232
+
1233
+ if (preg_match_all('/^a.k.a. \s* :? \s* (.*\S) \s*$/mx',
1234
+ $row->category_description, $aka,
1235
+ PREG_PATTERN_ORDER)) :
1236
+ $cat_found = array_merge($cat_found,
1237
+ array_map('strtolower', $aka[1]));
1238
+ endif;
1239
+ endforeach;
1240
  endif;
1241
+
1242
+ foreach ($cats as $new_cat) :
1243
+ $sql = "INSERT INTO $wpdb->categories (cat_name, category_nicename)
1244
+ VALUES ('%s', '%s')";
1245
+ if (!in_array(strtolower($new_cat), $cat_found)):
1246
+ $nice_cat = sanitize_title($new_cat);
1247
+ $wpdb->query(sprintf($sql, $wpdb->escape($new_cat), $nice_cat));
1248
+ $cat_ids[] = $wpdb->insert_id;
1249
+ endif;
1250
+ endforeach;
1251
+ endif;
1252
  return $cat_ids;
1253
  } // function FeedWordPress::lookup_categories ()
1254
 
1408
  if ($uri) $this->uri = $uri;
1409
 
1410
  // Is the result not yet cached?
1411
+ if ($this->_cache_uri !== $this->uri) :
1412
+ // Snoopy is an HTTP client in PHP
1413
+ $client = new Snoopy();
1414
+
1415
+ // Prepare headers and internal settings
1416
+ $client->rawheaders['Connection'] = 'close';
1417
+ $client->accept = 'application/atom+xml application/rdf+xml application/rss+xml application/xml text/html */*';
1418
+ $client->agent = 'feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress';
1419
+ $client->read_timeout = 5;
1420
+
1421
+ // Fetch the HTML or feed
1422
+ @$client->fetch($this->uri);
1423
+ $this->_data = $client->results;
1424
+
1425
+ // Kilroy was here
1426
+ $this->_cache_uri = $this->uri;
1427
+ endif;
 
1428
  } /* FeedFinder::_get () */
1429
 
1430
  function _link_rel_feeds () {
wp-content/update-feeds.php CHANGED
@@ -5,8 +5,7 @@
5
  # URI: <http://projects.radgeek.com/feedwordpress>
6
  # Author: Charles Johnson <technophilia@radgeek.com>
7
  # License: GPL
8
- # Version: 0.8
9
- # Last modified: 2005-03-21
10
  #
11
  # USAGE
12
  # -----
@@ -40,10 +39,8 @@
40
  require_once ('../wp-config.php');
41
  require_once (ABSPATH . WPINC . '/class-IXR.php');
42
 
43
- # -- CHANGE THESE TO REFLECT YOUR SITE SETTINGS!
44
- define ('RPC_URI', NULL); // Change this setting to ping a URI of your own devising
45
-
46
  # -- Don't change these unless you know what you're doing...
 
47
  define ('RPC_MAGIC', 'tag:radgeek.com/projects/feedwordpress/'); // update all
48
 
49
  if (is_null(RPC_URI)):
5
  # URI: <http://projects.radgeek.com/feedwordpress>
6
  # Author: Charles Johnson <technophilia@radgeek.com>
7
  # License: GPL
8
+ # Version: 2005.04.09
 
9
  #
10
  # USAGE
11
  # -----
39
  require_once ('../wp-config.php');
40
  require_once (ABSPATH . WPINC . '/class-IXR.php');
41
 
 
 
 
42
  # -- Don't change these unless you know what you're doing...
43
+ define ('RPC_URI', NULL); // Change this setting to ping a URI of your own devising
44
  define ('RPC_MAGIC', 'tag:radgeek.com/projects/feedwordpress/'); // update all
45
 
46
  if (is_null(RPC_URI)):