FeedWordPress - Version 0.95

Version Description

Download this release

Release Info

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

Code changes from version 0.91 to 0.95

Files changed (3) hide show
  1. ChangeLog.text +109 -0
  2. README.text +378 -70
  3. wp-content/plugins/feedwordpress.php +235 -86
ChangeLog.text ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Change Log
2
+ ==========
3
+
4
+ Changes from 0.91 to 0.95
5
+ -------------------------
6
+
7
+ * BUG FIX: Fixed an obscure bug in the handling of categories: categories
8
+ with trailing whitespace could cause categories with duplicate names to
9
+ be created. This no longer happens. While I was at it I tightened up the
10
+ operation of FeedWordPress::lookup_categories() a bit in general.
11
+
12
+ * FEATURE DEPRECATED: the feed setting `hardcode categories` is now
13
+ deprecated in favor of `unknown categories` (see below), which allows
14
+ you to strip off any syndication categories not already in your database
15
+ using `unknown categories: default` or `unknown categories: filter`. If
16
+ you have `hardcode categories: yes` set on a feed, this will be treated
17
+ as `unknown categories: default` (i.e., no new categories will be added,
18
+ but if a post doesn't match any of the categories it will be added in
19
+ the default category--usually "Uncategorized" or "General").
20
+
21
+ * FEATURE: You can now set global defaults as to whether or not
22
+ FeedWordPress will update the Link Name and Link Description settings
23
+ for feeds automatically from the feed title and feed tagline. (By
24
+ default, it does, as it has in past versions.) Whether this behavior is
25
+ turned on or off, you can still override the default behavior using
26
+ feed settings of `hardcode name: yes`, `hardcode name: no`,
27
+ `hardcode description: yes`, or `hardcode description: no`.
28
+
29
+ * FEATURE: Users can now provide one or several "aliases" for an author,
30
+ just as they can for a category. For example, to make FeedWordPress
31
+ treat posts by "Joseph Cardinal Ratzinger" and "Pope Benedict XVI" as
32
+ by the same author, edit the user profile for Pope Benedict XVI and add
33
+ a line like this to the "User profile" field:
34
+
35
+ a.k.a.: Joseph Cardinal Ratzinger
36
+
37
+ You can add several aliases, each on a line by itself. You can also add
38
+ any other text you like to the Profile without interfering with the
39
+ aliases.
40
+
41
+ * FEATURE: Users can now choose how to handle syndicated posts that are
42
+ in unfamiliar categories or by unfamiliar authors (i.e., categories or
43
+ authors whose names are not yet in the WordPress database). By default,
44
+ FeedWordPress will (as before) create a new category (or new author) and
45
+ use it for the current post and any future posts. This behavior can be
46
+ changed, either for all feeds or for one or another particular feed.
47
+
48
+ There are now three different options for an unfamiliar author: (1)
49
+ FeedWordPress can create a new author account and attribute the
50
+ syndicated post to the new account; (2) FeedWordPress can attribute the
51
+ post to an author if the author's name is familiar, and to a default
52
+ author (currently, this means the Site Administrator account) if it is
53
+ not; (3) FeedWordPress can drop posts by unfamiliar authors and
54
+ syndicate only posts by authors who are already in the database.
55
+
56
+ There are, similarly, two different options for an unfamiliar category:
57
+ (1) FeedWordPress can create new categories and place the syndicated
58
+ post in them; (2) FeedWordPress can drop the unfamiliar categories and
59
+ place syndicated posts only in categories that it is already familiar
60
+ with. In addition, FeedWordPress 0.95 lets you choose whether posts that
61
+ are in *no* familiar categories should be syndicated (and placed in the
62
+ default category for the blog) or simply dropped.
63
+
64
+ You can set the default behavior for both authors and categories using
65
+ the settings in Options --> Syndication. You can also set different
66
+ behavior for specific feeds by adding the `unfamiliar author` and / or
67
+ `unfamiliar categories` settings to the Link Notes section of a feed:
68
+
69
+ unfamiliar author: (create|default|filter)
70
+ unfamiliar categories: (create|default|filter)
71
+
72
+ A setting of `unfamiliar author: create` will make FeedWordPress create
73
+ new authors to match unfamiliar author names *for this feed alone*. A
74
+ setting of `unfamiliar author: default` will make it assign posts from
75
+ unfamiliar authors to the default user account. A setting of
76
+ `unfamiliar author: filter` will cause all posts (from this feed alone)
77
+ to be dropped unless they are by an author already listed in the
78
+ database. Similiarly, `unfamiliar categories: create` will make
79
+ FeedWordPress create new categories to match unfamiliar category names
80
+ *for this feed alone*; `unfamiliar categories: default` will cause it
81
+ to drop any unfamiliar category names; and
82
+ `unfamiliar categories: filter` will cause it to *both* drop any
83
+ unfamiliar category names *and* to only syndicate posts that are placed
84
+ in one or more familiar categories.
85
+
86
+ These two new features allow users to do some coarse-grained filtering
87
+ without having to write a PHP filter. Specifically, they offer an easy
88
+ way for you to filter feeds by category or by author. Suppose, for
89
+ example, that you only wanted to syndicate posts that your contributors
90
+ place in the "Llamas" category. You could do so by setting up your
91
+ installation of WordPress so that the only category in the database is
92
+ "Llamas," and then use Options --> Syndication to set "Unfamiliar
93
+ categories" to "don't create new categories and don't syndicate posts
94
+ unless they match at least one familiar category". Now, when you update,
95
+ only posts in the "Llamas" category will be syndicated by FeedWordPress.
96
+
97
+ Similarly, if you wanted to filter one particular feed so that only
98
+ posts by (for example) the author "Earl J. Llama" were syndicated to
99
+ your site, you could do so by creating a user account for Earl J. Llama,
100
+ then adding the following line to the settings for the feed in Link
101
+ Notes:
102
+
103
+ unfamiliar author: filter
104
+
105
+ This will cause any posts from this feed that are not authored by Earl
106
+ J. Llama to be discarded, and only the posts by Earl J. Llama will be
107
+ syndicated. (If the setting is used on one specific feed, it will not
108
+ affect how posts from other feeds are syndicated.)
109
+
README.text CHANGED
@@ -2,7 +2,7 @@ FeedWordPress
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
 
@@ -68,38 +68,75 @@ own that has always-on Internet access.
68
  For detailed installation instructions, point your web browser to
69
  <http://projects.radgeek.com/feedwordpress/install>.
70
 
71
- Feed Settings
72
- -------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
- Once you have your links configured and regular feed updates scheduled, you can
75
- mostly leave FeedWordPress to run on its own. If you need to add, remove, or
76
- change information for any contributors, you can do so from the WordPress
77
- Dashboard under Links --> Syndicated. If you want to distribute the labor of
78
- adding, updating, and managing feeds, you can use the WordPress login and access
79
- privileges system. Users with an access level of 5 or greater can add or modify
80
- syndicated links, and change syndication options.
81
-
82
- All the information for a syndicated feed is managed through the WordPress Links
83
- database. Feeds in the category to be syndicated (by default, "Contributors")
84
- use several fields of the standard WordPress Link record:
85
 
86
- - The Link URI is used to store a URI to the front page (*not* the feed!)
87
- of the syndicated website.
 
 
 
88
 
89
  - The Link Name is used to store the title of the syndicated website.
 
 
 
 
 
 
 
 
90
 
91
  - The Short Description is used to store the tagline of the syndicated
92
- website.
 
 
 
 
 
 
 
93
 
94
- - The RSS URI is used to store the URI for the feed to be syndicated.
95
-
96
  - The Link Notes are used to store a collection of manually-encoded and
97
  automatically-generated settings that apply to this feed. The format of
98
  settings in Link Notes is:
99
 
100
  key1: value1
101
  key2: value2
102
- key3: value3
103
  feed/key1: value1
104
  feed/key2: value2
105
 
@@ -108,13 +145,27 @@ use several fields of the standard WordPress Link record:
108
  checked for updates. Values without the prefix are set manually by the
109
  user.
110
 
111
- Most settings in the Link Notes have no effect on FeedWordPress, but can be
112
- accessed from templates using the ``get_feed_meta()`` template function in a
113
- post context. For example, many aggregator sites use a "face" image for each
114
- feed to visually distinguish posts from different feeds. To implement a face
115
- feature, you could add a line like this to each feed's Link Notes section:
 
 
 
116
 
117
- face: http://www.zyx.com/mugs/ugly
 
 
 
 
 
 
 
 
 
 
 
118
 
119
  The URI should be changed out for each feed to point to the appropriate image,
120
  of course. Then, to use the setting from within a template:
@@ -130,7 +181,176 @@ particular feed, ``get_feed_meta()`` will return an empty string and no image
130
  will be displayed.
131
 
132
  Not all feed settings are only for templates. Some affect how FeedWordPress
133
- processes posts from that feed. Currently, the special settings are:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
  - `cats:` a colon-separated list of default categories for any post coming
136
  from this feed. So, for example, a this line in its Notes section:
@@ -138,62 +358,77 @@ processes posts from that feed. Currently, the special settings are:
138
  cats: computers:web
139
 
140
  ... will make FeedWordPress place any posts syndicated from that feed in
141
- the "computers" and "web" categories (*in addition to*, not *instead of*
142
- any categories that are applied to the post in the feed)
 
 
 
 
 
143
 
144
  - `hardcode name: (yes|no)`
145
 
146
- A yes/no setting. By default, FeedWordPress updates the value of the
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
@@ -209,6 +444,79 @@ processes posts from that feed. Currently, the special settings are:
209
  syndicated posts are closed to pings, but you can set this to 'open' or
210
  'closed' for particular feeds.
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  Template API
213
  ------------
214
  When activated, FeedWordPress makes the following functions available for use by
@@ -266,7 +574,7 @@ The hooks are the action ``feedwordpress_update``, the action
266
  filter ``syndicated_item``, the filter ``syndicated_post``, the action
267
  ``post_syndicated_item``, and the action ``update_syndicated_item``.
268
 
269
- For more information, see <http://projects.radgeek.com/feedwordpress/use>.
270
 
271
  License
272
  -------
2
  =============
3
 
4
  * Author: [Charles Johnson](http://www.radgeek.com/contact)
5
+ * Version: 0.95
6
  * Project URI: <http://projects.radgeek.com/feedwordpress>
7
  * License: GPL. See License below for copyright jots and tittles.
8
 
68
  For detailed installation instructions, point your web browser to
69
  <http://projects.radgeek.com/feedwordpress/install>.
70
 
71
+ Basic Concepts
72
+ --------------
73
+ FeedWordPress is written as a plugin for [WordPress 1.5][]. It is designed to
74
+ store all the data it needs within the WordPress database and to make that data
75
+ easy to manage from within the WordPress Dashboard.
76
+
77
+ ### Contributors / Newsfeeds ###
78
+
79
+ FeedWordPress uses the WordPress Links database to keep a list of the feeds from
80
+ which it will syndicate content. WordPress allows you to place links in
81
+ categories; FeedWordPress will treat all and only the links in one category
82
+ (by default, this is a category named "Contributors"; you can change the
83
+ category that FeedWordPress will use using Options --> Syndication).
84
+
85
+ From WordPress's perspective, the list of Contributors are normal links, and
86
+ they can be manipulated like other links through the WordPress Dashboard. If
87
+ you need to add, remove, or change information for any contributors, you can
88
+ do so easily under Links --> Syndicated. If you want to distribute the labor of
89
+ adding, updating, and managing feeds, you can use the WordPress login and
90
+ access privileges system. Users with an access level of 5 or greater can add,
91
+ delete, and modify Contributors; users with an access level of 6 or greater can
92
+ change syndication options.
93
+
94
+ When FeedWordPress looks for new posts, it does so by retrieving one or all of
95
+ the links from the Contributors category (depending on whether it has been told
96
+ to scan for new posts on one or all of the feeds).
97
+
98
+ __Feed settings:__ All of the information for a syndicated feed is stored in
99
+ the WordPress Links database. Feeds in the category to be syndicated (by
100
+ default, "Contributors") use several fields of the standard WordPress Link
101
+ record:
102
 
103
+ - The RSS URI is used to store the URI for the feed to be syndicated.
104
+ (Note that this is *not* the same as the Link URI. The Link URI points
105
+ to the human-readable *front page* of the website that the feed
106
+ syndicates.)
 
 
 
 
 
 
 
107
 
108
+ - The Link URI is used to store a URI to the human-readable front page
109
+ (*not* the feed!) of the syndicated website. FeedWordPress automatically
110
+ updates this URI using the URI that is reported by the newsfeed whenever
111
+ it checks the feed for new posts, so if the page moves this will be
112
+ reflected automatically on your Contributors links list.
113
 
114
  - The Link Name is used to store the title of the syndicated website.
115
+ By default, FeedWordPress automatically updates the name of the link
116
+ whenever it checks for new posts, using the title that the
117
+ newsfeed reports (so that if a Contributor changes the title of her
118
+ website, this is reflected automatically on your Contributors links
119
+ list). This behavior can be turned off for all feeds through the
120
+ settings in Options --> Syndication. The default behavior can be
121
+ overridden for specific feeds using the feed setting
122
+ `hardcode name`.
123
 
124
  - The Short Description is used to store the tagline of the syndicated
125
+ website. By default, FeedWordPress automatically updates the description
126
+ whenever it checks for new posts, using the tagline or description that
127
+ the newsfeed reports (so that if a Contributor changes the tagline of
128
+ her website, this is reflected automatically on your Contributors links
129
+ list). his behavior can be turned off for all feeds through the
130
+ settings in Options --> Syndication. The default behavior can be
131
+ overridden for specific feeds using the feed setting
132
+ `hardcode description`.
133
 
 
 
134
  - The Link Notes are used to store a collection of manually-encoded and
135
  automatically-generated settings that apply to this feed. The format of
136
  settings in Link Notes is:
137
 
138
  key1: value1
139
  key2: value2
 
140
  feed/key1: value1
141
  feed/key2: value2
142
 
145
  checked for updates. Values without the prefix are set manually by the
146
  user.
147
 
148
+ The Link Notes section can be used to add, remove, and change custom feed
149
+ settings. For example, if you want to *add* the feed setting for
150
+ `unfamiliar author` with the value `filter`, you can do so by going to Links -->
151
+ Syndicated, clicking the "Edit" link for the feed that you wish to add this
152
+ setting for, and then adding the following, on a line by itself, to the Link
153
+ Notes section:
154
+
155
+ unfamiliar author: filter
156
 
157
+ To remove the setting, follow the same procedure, but find the line for the
158
+ feed setting that you want to remove and remove it. To change the value, simply
159
+ change the text that follows after the colon.
160
+
161
+ Most settings in the Link Notes have no effect on FeedWordPress, but you can use
162
+ them to store information for templates to retrieve using the `get_feed_meta()`
163
+ template function in a post context (see Template API below). For example, many
164
+ aggregator sites use a "face" image for each feed to visually distinguish posts
165
+ from different feeds. To implement a face feature, you could add something
166
+ like this to each feed's Link Notes, on a line by itself:
167
+
168
+ face: http://www.zyx.com/mugs/ugly
169
 
170
  The URI should be changed out for each feed to point to the appropriate image,
171
  of course. Then, to use the setting from within a template:
181
  will be displayed.
182
 
183
  Not all feed settings are only for templates. Some affect how FeedWordPress
184
+ processes posts from that feed. Currently, the settings with special effects
185
+ on FeedWordPress are `cats`, `hardcode name`, `hardcode description`,
186
+ `hardcode categories`, `post status`, `comment status`, `ping status`,
187
+ `unfamiliar author`, and `unfamiliar categories`. For descriptions of their
188
+ effects, see Special Feed Settings below.
189
+
190
+ ### Syndicated Posts ###
191
+
192
+ Whenever FeedWordPress updates, it scans one or more of the feeds in its
193
+ Contributors list and adds any new posts that it finds to the WordPress
194
+ database. Syndicated posts are displayed on your WordPress pages like any other
195
+ posts: they can be listed in archives by category, author, or date; they can be
196
+ found with the search box; and they are included in the newsfeed of your blog.
197
+
198
+ In your WordPress templates (Presentation --> Theme Editor) you can access
199
+ special information about syndicated posts using functions provided by
200
+ FeedWordPress, such as `is_syndicated()`, `the_syndication_source()`,
201
+ `the_syndication_source_link()`, and `get_feed_meta()`. For example, here is
202
+ the template code that I use (in a post context) to display both the author's
203
+ name and the original source of the post in the templates for [Feminist Blogs][]:
204
+
205
+ <cite class="feed">from <?php the_author_posts_link()?><?php
206
+ if (is_syndicated() and (get_the_author() !== get_syndication_source())):
207
+ echo ' @ <a href="'; the_syndication_source_link(); echo '">';
208
+ the_syndication_source();
209
+ echo '</a>';
210
+ endif; ?></cite>
211
+
212
+ For more information on template functions, see Template API below.
213
+
214
+ ### Categories ###
215
+
216
+ WordPress allows for posts to be placed in *categories*. Each syndicated post
217
+ that FeedWordPress adds to the WordPress database is placed into a set of
218
+ categories. FeedWordPress gets the list of category names to use from two
219
+ sources:
220
+
221
+ 1. Categories (or "tags") that the original author placed the post in on
222
+ her blog
223
+
224
+ 2. Categories that you set explicitly for each feed using the `cats`
225
+ feed setting. For example, if you wanted all the posts from Alas, A Blog
226
+ to be placed in the "Pacific Northwest" category and the "Cartoonists"
227
+ category (in addition to any categories that they were placed in on
228
+ Alas, A Blog), you could do this by going to Links --> Syndicated,
229
+ clicking the "Edit" link for Alas, A Blog, and adding the following line
230
+ to the Link Notes section:
231
+
232
+ cats: Pacific Northwest:Cartoonists
233
+
234
+ (The colon separates one category name from the next.)
235
+
236
+ Given the list of category names, FeedWordPress looks for categories in the
237
+ WordPress database with the same name as either (1) the category name, or
238
+ (2) one of the "aliases" listed in the category description.
239
+
240
+ __Aliases:__ Different often authors use slightly different names for
241
+ categories that mean the same thing (contributors to Feminist Blogs, for
242
+ example, used categories including "Feminism", "feministy stuff",
243
+ "Women's Issues", "Gender Issues", "Gender Equality", and so on). If you want
244
+ FeedWordPress to treat one category name as a synonym for another, you can
245
+ do so by creating an "alias" for the category. For example, to make
246
+ FeedWordPress treat posts that are placed in the category "feministy stuff" as
247
+ if they had been placed in the category "Feminism", go to Manage --> Categories,
248
+ find the category "Feminism" and click the "Edit" link for it, and then add
249
+ the following to the Description field, on a line by itself:
250
+
251
+ a.k.a.: feministy stuff
252
+
253
+ You can add as many aliases as you like. You can also add any other text that
254
+ you like to the Description without interfering with FeedWordPress's ability to
255
+ use the aliases. Each alias must be on a line by itself.
256
+
257
+ __Unfamiliar categories:__ By default, if one of the category names that a
258
+ newsfeed provides is unfamiliar -- that is, if there is not yet any category
259
+ with that name (or with that name as an alias) in your WordPress database --
260
+ then by default FeedWordPress will *automatically create* a new category with
261
+ that name and place the current post in it. The default behavior can be changed,
262
+ using either the global settings in Options --> Syndication or the
263
+ `unfamiliar categories` feed setting (see Feed Settings above), so that unfamiliar
264
+ categories will not be added to the database. If you choose to disable the
265
+ creation of new categories, you can also choose whether or not FeedWordPress
266
+ should syndicate posts that do not match *any* of the categories that are
267
+ currently in the database.
268
+
269
+ One of the uses of this feature is filtering posts by category: if you want to
270
+ your blog to syndicate only the posts in one particular category from a feed
271
+ that has several categories, you could do so by creating a category by that
272
+ name, adding the new feed(s), and then adding the following line to the Link
273
+ Notes section of the feed(s) that you want to filter:
274
+
275
+ unfamiliar categories: filter
276
+
277
+ Since only posts in categories that are in your database will be included, and
278
+ only the category or categories that you wanted posts from has been added to
279
+ your database, this will filter out all the posts that aren't in the category
280
+ or categories that you defined ahead of time. (Similarly, you could set up
281
+ FeedWordPress so that *all* the feeds are filtered by author by creating the set
282
+ of users named after the authors you want to syndicate, and then setting the
283
+ default behavior for *all* feeds at Options --> Syndication).
284
+
285
+ If you need a category filter with more complex logic, you can always create a
286
+ `syndicated_item` filter in PHP (see Plugin API below) that manipulates the
287
+ `['categories']` array of a syndicated item.
288
+
289
+ ### Authors ###
290
+
291
+ Most newsfeeds include information about the author of the items on them.
292
+ (If a feed doesn't, then FeedWordPress will create an author's name based on
293
+ the title of the feed from which the item was taken.) This information is used
294
+ to determine the WordPress user that the post will be attributed to. Given the
295
+ name of the author, FeedWordPress looks for authors in the WordPress database
296
+ with the same name as either (1) their login, (2) their first name, (3) their
297
+ nickname, (4) their full name, or (5) one of the "aliases" listed in the
298
+ user's profile.
299
+
300
+ __Aliases:__ If there is an author who posts under more than one name (for
301
+ example, one of our contributors at [Feminist Blogs][] posts on several
302
+ different blogs, sometimes using her full name and sometimes using only her
303
+ first name), then you can ensure that FeedWordPress will attribute those posts
304
+ to the same author by creating "aliases" for the author. For example, to make
305
+ FeedWordPress treat posts by "Joseph Cardinal Ratzinger" and posts by "Pope
306
+ Benedict XVI" as having the same author, go to Users --> Authors & Users, click
307
+ on the "Edit" link for Pope Benedict XVI, and add a line like this to the
308
+ Profile text:
309
+
310
+ a.k.a.: Joseph Cardinal Ratzinger
311
+
312
+ You can add as many aliases as you like. You can also add any other text that
313
+ you like to the Profile without interfering with FeedWordPress's ability to use
314
+ the aliases. Each alias must be on a line by itself.
315
+
316
+ __Unfamiliar authors:__ By default, if the author named by the newsfeed is
317
+ unfamiliar -- that is, if there is no-one with that name registered in the
318
+ WordPress author's database -- then by default FeedWordPress will automatically
319
+ create a new user account with the given name and attribute the post to the new
320
+ user. The default behavior can be changed, using either the global settings in
321
+ Options --> Syndication or the `unfamiliar author` feed setting (see Feed
322
+ Settings above), so that posts by unfamiliar authors will either be attributed
323
+ to a default author (instead of creating a new user account to attribute them
324
+ to), or filtered out and not syndicated at all.
325
+
326
+ One of the uses of this feature is filtering posts by author: if you want to
327
+ your blog to syndicate only the posts by one particular author from a feed that
328
+ has several authors, you could do so by creating a user account with that
329
+ author's name, adding the new feed(s), and then adding the following line to the
330
+ Link Notes section of the feed(s) that you want to filter:
331
+
332
+ unfamiliar author: filter
333
+
334
+ Since only posts by authors that are in your database will be included, and only
335
+ the author that you wanted posts from has been added to your database, this will
336
+ filter out posts by anyone else on the feeds with that setting. (Similarly, you
337
+ could set up FeedWordPress so that *all* the feeds are filtered by author by
338
+ creating the set of users named after the authors you want to syndicate, and
339
+ then setting the default behavior for *all* feeds at Options --> Syndication).
340
+
341
+ If you need an author filter with more complex logic than this allows, you can
342
+ always create a `syndicated_item` filter in PHP (see Plugin API below) that
343
+ manipulates the `['author_name']` or `['dc']['creator']` elements of a
344
+ syndicated item.
345
+
346
+ Special Feed Settings
347
+ ---------------------
348
+ Most feed settings (see Feed Settings above) have no effect on FeedWordPress
349
+ itself, but can be useful because they can be accessed from templates using the
350
+ `get_feed_meta()` template function in a post context (see Feed Settings above
351
+ for an example). However, you can use some feed settings to affect how
352
+ FeedWordPress will process posts from that particular feed. Currently, these
353
+ special settings are:
354
 
355
  - `cats:` a colon-separated list of default categories for any post coming
356
  from this feed. So, for example, a this line in its Notes section:
358
  cats: computers:web
359
 
360
  ... will make FeedWordPress place any posts syndicated from that feed in
361
+ the "computers" and "web" categories. Note that by default,
362
+ FeedWordPress will place them in those categories *in addition to* any
363
+ categories that the author of the post put them in on her own website.
364
+ If you want to place posts from a feed *only* in the categories you
365
+ explicitly set, then you should use the `cats` setting together with
366
+ the `unfamiliar categories` setting. (See Categories above and
367
+ `unfamiliar categories` below for the nitty-gritty.)
368
 
369
  - `hardcode name: (yes|no)`
370
 
371
+ By default, FeedWordPress updates the value of the Link Name field
372
+ automatically to reflect the title that is reported by a syndicated
373
+ feed--so that if one of your contributors changes the title of her
374
+ website, the change will be reflected on your Contributors list after
375
+ the next update. If you want to stop this behavior (so that you can
376
+ set the title of a Contributor link manually -- e.g. so that you can use
377
+ an abbreviated form for reasons of space), you can change the default
378
+ behavior for *all* feeds using the settings in Options --> Syndication.
379
+ If you want to override the default behavior for only *one* feed, you
380
+ can use the `hardcode name` feed setting. If FeedWordPress updates the
381
+ title of all feeds by default, but you wish to use a manually-set title
382
+ for one particular feed, you can add a line like this to the Link Notes
383
+ section of the feed that you want to manually set the title for:
384
 
385
  hardcode name: yes
386
 
387
+ Similarly, if FeedWordPress uses your manually-entered titles for all
388
+ feeds by default, but you wish to use an automatically updated title for
389
+ one particular feed, you can add a line like this to the Link Notes
390
+ section of the feed that you want to manually set the title for:
391
+
392
+ hardcode name: no
393
+
394
+ If `hardcode name` is absent, or set to a value other than `yes` or
395
+ `no`, FeedWordPress will follow the default behavior set under
396
+ Options --> Syndication.
397
 
398
  - `hardcode description: (yes|no)`
399
 
400
+ By default, FeedWordPress updates the value of the Link Description
401
+ field automatically to reflect the tagline or description that is
402
+ reported by a syndicated feed--so that if one of your contributors
403
+ changes the tagline for her website, the change will be reflected on
404
+ your Contributors list after the next update. If you want to stop this
405
+ behavior (so that you can set the taglien of a Contributor link manually
406
+ -- e.g. so that you can use it to provide information of another sort or
407
+ use an abbreviated form for reasons of space), you can change the
408
+ default behavior for *all* feeds using the settings in Options -->
409
+ Syndication. If you want to override the default behavior for only *one*
410
+ feed, you can use the `hardcode description` feed setting. If
411
+ FeedWordPress updates the description of all feeds by default, but you
412
+ wish to use a manually-set description for one particular feed, you can
413
+ add a line like this to the Link Notes section of that particular feed:
414
+
415
  hardcode description: yes
416
 
417
+ Similarly, if FeedWordPress uses your manually-entered descriptions for
418
+ all feeds by default, but you wish to use an automatically updated
419
+ description for one particular feed, you can add a line like this to the
420
+ Link Notes section of that particular feed:
421
+
422
+ hardcode description: no
423
+
424
+ If `hardcode description` is absent, or set to a value other than `yes`
425
+ or `no`, FeedWordPress will follow the default behavior set under
426
+ Options --> Syndication.
427
 
428
  - `hardcode categories: (yes|no)`
429
 
430
+ **This setting has been deprecated.** If set to `yes` it is now treated
431
+ as equivalent to `unfamiliar categories: default`. (See below.)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
432
 
433
  - `post status:` sets the default post status for posts from this feed
434
  This can be 'publish', 'draft', or 'private'. By default, it is set to
444
  syndicated posts are closed to pings, but you can set this to 'open' or
445
  'closed' for particular feeds.
446
 
447
+ - `unfamiliar authors: (create|default|filter)`
448
+
449
+ By default, FeedWordPress creates new author accounts whenever it finds
450
+ a new post that is by an author whose name is not already in the
451
+ WordPress database, and uses that account for this post and any future
452
+ posts by an author of that name. FeedWordPress also allows you to
453
+ attribute posts by unfamiliar authors to a *default* user account
454
+ (currently, this means the System Administrator account), *instead of*
455
+ creating a new author, or simply not to syndicate posts by unfamiliar
456
+ authors (thus only syndicating posts by authors who are already in the
457
+ database).
458
+
459
+ Which of these FeedWordPress does by default can be set using the
460
+ settings in Options --> Syndicated. You can also override the default
461
+ behavior for specific feeds by adding the `unfamiliar author` feed
462
+ setting to the Link Notes section of a feed. For example, to ensure that
463
+ FeedWordPress filters out posts by unfamiliar authors for one particular
464
+ feed, add the setting:
465
+
466
+ unfamiliar author: filter
467
+
468
+ To ensure that FeedWordPress assigns posts by unfamiliar authors to the
469
+ default user account instead of creating a new user account, add the
470
+ setting:
471
+
472
+ unfamiliar author: default
473
+
474
+ If you changed the default behavior under Options --> Syndicated but
475
+ want to ensure that FeedWordPress creates new author accounts for
476
+ unfamiliar authors on one specific feed, add the setting:
477
+
478
+ unfamiliar author: create
479
+
480
+ If the setting is anything other than `create`, `default`, or `filter`,
481
+ FeedWordPress will ignore the setting and follow the default behavior
482
+ that you specified under Options --> Syndication.
483
+
484
+ - `unfamiliar categories: (create|default|filter)`
485
+
486
+ By default, FeedWordPress creates categories whenever it finds a new
487
+ post that is placed in categories whose names are not already in the
488
+ WordPress database. FeedWordPress allows you to change this behavior,
489
+ so that it will *not* create new category names. It also allows you to
490
+ choose whether or not posts must match *at least one* familiar category
491
+ to be syndicated at all.
492
+
493
+ Which of these FeedWordPress does by default can be set using the
494
+ settings in Options --> Syndicated. You can also override the default
495
+ behavior for specific feeds by adding the `unfamiliar categories` feed
496
+ setting to the Link Notes section of a feed. For example, to ensure
497
+ that, when adding new posts from *one particular feed*, FeedWordPress
498
+ does *not* create new categories, and filters out any posts that don't
499
+ match *at least one* of the categories that you have already defined,
500
+ add the setting:
501
+
502
+ unfamiliar categories: filter
503
+
504
+ To ensure that FeedWordPress does *not* create new categories, but
505
+ *will* still syndicate categories even if they don't match any of the
506
+ pre-defined categories, add the following to the feed settings:
507
+
508
+ unfamiliar categories: default
509
+
510
+ If you changed the default behavior under Options --> Syndicated but
511
+ want to ensure that FeedWordPress creates new categories for posts
512
+ from one particular feed, add the setting:
513
+
514
+ unfamiliar categories: create
515
+
516
+ If the setting is anything other than `create`, `default`, or `filter`,
517
+ FeedWordPress will ignore the setting and follow the default behavior
518
+ that you specified under Options --> Syndication.
519
+
520
  Template API
521
  ------------
522
  When activated, FeedWordPress makes the following functions available for use by
574
  filter ``syndicated_item``, the filter ``syndicated_post``, the action
575
  ``post_syndicated_item``, and the action ``update_syndicated_item``.
576
 
577
+ For more information, see <http://projects.radgeek.com/feedwordpress/api>.
578
 
579
  License
580
  -------
wp-content/plugins/feedwordpress.php CHANGED
@@ -3,11 +3,11 @@
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:
@@ -27,7 +27,7 @@ Last modified: 2005-04-09 2:00pm EDT
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
@@ -138,7 +138,7 @@ function get_feed_meta ($key) {
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 */
@@ -188,7 +188,7 @@ function syndication_permalink ($permalink = '') {
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 () {
@@ -205,6 +205,20 @@ function fwp_syndication_options_page () {
205
  update_option('feedwordpress_cat_id', $_REQUEST['syndication_category']);
206
  update_option('feedwordpress_munge_permalink', $_REQUEST['munge_permalink']);
207
  update_option('feedwordpress_update_logging', $_REQUEST['update_logging']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  ?>
209
  <div class="updated">
210
  <p><?php _e('Options saved.')?></p>
@@ -217,6 +231,20 @@ function fwp_syndication_options_page () {
217
  $rpc_secret = FeedWordPress::rpc_secret();
218
  $munge_permalink = get_settings('feedwordpress_munge_permalink');
219
  $update_logging = get_settings('feedwordpress_update_logging');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  $results = $wpdb->get_results("SELECT cat_id, cat_name, auto_toggle FROM $wpdb->linkcategories ORDER BY cat_id");
221
  ?>
222
  <div class="wrap">
@@ -255,6 +283,30 @@ function fwp_syndication_options_page () {
255
  echo "\n</select>\n";
256
  ?></td>
257
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  </table>
259
  <div class="submit"><input type="submit" name="action" value="<?=$caption?>" /></div>
260
  </fieldset>
@@ -647,10 +699,12 @@ class FeedWordPress {
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;
@@ -658,6 +712,15 @@ class FeedWordPress {
658
  $sec['uri'] = $link->link_rss;
659
  $sec['name'] = $link->link_name;
660
 
 
 
 
 
 
 
 
 
 
661
  if (isset($sec['cats'])):
662
  $sec['cats'] = explode(':',$sec['cats']);
663
  endif;
@@ -729,14 +792,14 @@ class FeedWordPress {
729
  // $a['feed/b/c/d'] with value 'e'.
730
  function flatten_array ($arr, $prefix = 'feed/', $separator = '/') {
731
  $ret = array ();
732
- if (is_array($arr)):
733
- foreach ($arr as $key => $value) {
734
- if (is_scalar($value)) {
735
  $ret[$prefix.$key] = $value;
736
- } else {
737
  $ret = array_merge($ret, $this->flatten_array($value, $prefix.$key.$separator, $separator));
738
- } /* if */
739
- } /* foreach */
740
  endif;
741
  return $ret;
742
  } // function FeedWordPress::flatten_array ()
@@ -745,7 +808,28 @@ class FeedWordPress {
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
  }
@@ -753,20 +837,20 @@ class FeedWordPress {
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'])) :
@@ -782,16 +866,17 @@ class FeedWordPress {
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);
793
 
794
- // if we've already have this feed, update
795
  $result = $wpdb->query("
796
  UPDATE $wpdb->links
797
  SET $update_set
@@ -960,18 +1045,19 @@ class FeedWordPress {
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'];
966
 
 
 
 
 
967
  // Categories: start with default categories
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));
@@ -991,11 +1077,11 @@ class FeedWordPress {
991
  FROM $wpdb->posts WHERE guid='$guid'
992
  ");
993
 
994
- if (!$result):
995
  $freshness = 2; // New content
996
- elseif ($post['epoch']['modified'] > $result->modified):
997
  $freshness = 1; // Updated content
998
- else:
999
  $freshness = 0;
1000
  endif;
1001
 
@@ -1005,21 +1091,32 @@ class FeedWordPress {
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
1012
- $post['post_category'] = $this->lookup_categories (
1013
- $wpdb,
1014
- $post['named']['category']
1015
- );
1016
-
1017
  unset($post['named']);
1018
  endif;
1019
 
1020
- $post = apply_filters('syndicated_post', $post);
1021
- if (is_null($post)) $freshness = 0;
1022
-
 
 
1023
  if ($freshness == 2) :
1024
  // The item has not yet been added. So let's add it.
1025
 
@@ -1104,7 +1201,7 @@ class FeedWordPress {
1104
  do_action('update_syndicated_item', $postId);
1105
 
1106
  $ret = 'updated';
1107
- else:
1108
  $ret = false;
1109
  endif;
1110
 
@@ -1166,7 +1263,7 @@ class FeedWordPress {
1166
 
1167
  // FeedWordPress::author_to_id (): get the ID for an author name from
1168
  // the feed. Create the author if necessary.
1169
- function author_to_id ($wpdb, $author, $email, $url) {
1170
  // Never can be too careful...
1171
  $nice_author = sanitize_title($author);
1172
  $author = $wpdb->escape($author);
@@ -1174,80 +1271,118 @@ class FeedWordPress {
1174
  $url = $wpdb->escape($url);
1175
 
1176
  $id = $wpdb->get_var(
1177
- "SELECT ID from $wpdb->users
1178
- WHERE
1179
- user_login = '$author' OR
1180
- user_firstname = '$author' OR
1181
- user_nickname = '$author' OR
1182
- user_description = '$author' OR
1183
- user_nicename = '$nice_author'");
 
 
 
1184
 
1185
- if (is_null($id)):
1186
- $wpdb->query (
1187
- "INSERT INTO $wpdb->users
1188
- SET
1189
- ID='0',
1190
- user_login='$author',
1191
- user_firstname='$author',
1192
- user_nickname='$author',
1193
- user_nicename='$nice_author',
1194
- user_description='$author',
1195
- user_email='$email',
1196
- user_url='$url'");
1197
- $id = $wpdb->insert_id;
 
 
 
 
1198
  endif;
1199
  return $id;
1200
  } // function FeedWordPress::author_to_id ()
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 ()
@@ -1255,7 +1390,21 @@ class FeedWordPress {
1255
  function rpc_secret () {
1256
  return get_settings('feedwordpress_rpc_secret');
1257
  } // function FeedWordPress::rpc_secret ()
1258
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1259
  function link_category_id () {
1260
  global $wpdb;
1261
 
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.95
7
  Author: Charles Johnson
8
  Author URI: http://www.radgeek.com/
9
  License: GPL
10
+ Last modified: 2005-04-20 10:58pm EDT
11
  */
12
 
13
  # This uses code derived from:
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.95');
31
  define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
32
 
33
  // Note that the rss-functions.php that comes prepackaged with WordPress is
138
  $notes = explode("\n", $result);
139
  foreach ($notes as $note):
140
  list($k, $v) = explode(': ', $note, 2);
141
+ $meta[$k] = stripcslashes(trim($v));
142
  endforeach;
143
  $ret = $meta[$key];
144
  endif; /* if */
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 Options', 'Syndication', 6, basename(__FILE__), 'fwp_syndication_options_page');
192
  } // function fwp_add_pages () */
193
 
194
  function fwp_syndication_options_page () {
205
  update_option('feedwordpress_cat_id', $_REQUEST['syndication_category']);
206
  update_option('feedwordpress_munge_permalink', $_REQUEST['munge_permalink']);
207
  update_option('feedwordpress_update_logging', $_REQUEST['update_logging']);
208
+ update_option('feedwordpress_unfamiliar_author', $_REQUEST['unfamiliar_author']);
209
+ update_option('feedwordpress_unfamiliar_category', $_REQUEST['unfamiliar_category']);
210
+
211
+ if (isset($_REQUEST['hardcode_name']) and ($_REQUEST['hardcode_name'] == 'no')) :
212
+ update_option('feedwordpress_hardcode_name', 'no');
213
+ else :
214
+ update_option('feedwordpress_hardcode_name', 'yes');
215
+ endif;
216
+
217
+ if (isset($_REQUEST['hardcode_description']) and ($_REQUEST['hardcode_description'] == 'no')) :
218
+ update_option('feedwordpress_hardcode_description', 'no');
219
+ else :
220
+ update_option('feedwordpress_hardcode_description', 'yes');
221
+ endif;
222
  ?>
223
  <div class="updated">
224
  <p><?php _e('Options saved.')?></p>
231
  $rpc_secret = FeedWordPress::rpc_secret();
232
  $munge_permalink = get_settings('feedwordpress_munge_permalink');
233
  $update_logging = get_settings('feedwordpress_update_logging');
234
+
235
+ $hardcode_name = get_settings('feedwordpress_hardcode_name');
236
+ $hardcode_description = get_settings('feedwordpress_hardcode_description');
237
+
238
+ $unfamiliar_author = array ('create' => '','default' => '','filter' => '');
239
+ $ua = FeedWordPress::on_unfamiliar('author');
240
+ if (is_string($ua) and array_key_exists($ua, $unfamiliar_author)) :
241
+ $unfamiliar_author[$ua] = ' checked="checked"';
242
+ endif;
243
+ $unfamiliar_category = array ('create'=>'','default'=>'','filter'=>'');
244
+ $uc = FeedWordPress::on_unfamiliar('category');
245
+ if (is_string($uc) and array_key_exists($uc, $unfamiliar_category)) :
246
+ $unfamiliar_category[$uc] = ' checked="checked"';
247
+ endif;
248
  $results = $wpdb->get_results("SELECT cat_id, cat_name, auto_toggle FROM $wpdb->linkcategories ORDER BY cat_id");
249
  ?>
250
  <div class="wrap">
283
  echo "\n</select>\n";
284
  ?></td>
285
  </tr>
286
+
287
+ <tr><th width="33%" scope="row" style="vertical-align:top">Update live from feed:</th>
288
+ <td width="67%"><ul style="margin:0;list-style:none">
289
+ <li><input type="checkbox" name="hardcode_name" value="no"<?=(($hardcode_name=='yes')?'':' checked="checked"')?>/> Contributor name (feed title)</li>
290
+ <li><input type="checkbox" name="hardcode_description" value="no"<?=(($hardcode_description=='yes')?'':' checked="checked"')?>/> Contributor description (feed tagline)</li>
291
+ </ul></td></tr>
292
+
293
+ <tr><th width="33%" scope="row" style="vertical-align:top">Unfamiliar authors:</th>
294
+ <td width="67%"><ul style="margin: 0;list-style:none">
295
+ <li><label><input type="radio" name="unfamiliar_author" value="create"<?=$unfamiliar_author['create']?>/> create a new author account</label></li>
296
+ <li><label><input type="radio" name="unfamiliar_author" value="default"<?=$unfamiliar_author['default']?> /> attribute the post to the default author</label></li>
297
+ <li><label><input type="radio" name="unfamiliar_author" value="filter"<?=$unfamiliar_author['filter']?> /> don't syndicate the post</label></li>
298
+ </ul></td></tr>
299
+ <tr><th width="33%" scope="row" style="vertical-align:top">Unfamiliar categories:</th>
300
+ <td width="67%"><ul style="margin: 0;list-style:none">
301
+ <li><label><input type="radio" name="unfamiliar_category" value="create"<?=$unfamiliar_category['create']?>/> create any categories the post is in</label></li>
302
+ <li><label><input type="radio" name="unfamiliar_category" value="default"<?=$unfamiliar_category['default']?>/> don't create new categories</li>
303
+ <li><label><input type="radio" name="unfamiliar_category" value="filter"<?=$unfamiliar_category['filter']?>/> don't create new categories and don't syndicate posts unless they match at least one familiar category</label></li>
304
+ </ul>
305
+
306
+ </ul></li>
307
+ </ul></td></tr>
308
+
309
+ </select></td></tr>
310
  </table>
311
  <div class="submit"><input type="submit" name="action" value="<?=$caption?>" /></div>
312
  </fieldset>
699
  list($key, $value) = explode(": ", $note, 2);
700
 
701
  if (strlen($key) > 0) :
702
+ // Unescape and trim() off the
703
+ // whitespace. Thanks to Ray
704
+ // Lischner for pointing out the
705
+ // need to trim.
706
+ $sec[$key] = stripcslashes (
707
+ trim($value)
708
  );
709
  endif;
710
  endforeach;
712
  $sec['uri'] = $link->link_rss;
713
  $sec['name'] = $link->link_name;
714
 
715
+ // `hardcode categories` is deprecated in favor
716
+ // of `unfamiliar categories`
717
+ if (
718
+ FeedWordPress::affirmative($sec, 'hardcode categories')
719
+ and !isset($sec['unfamiliar categories'])
720
+ ) :
721
+ $sec['unfamiliar categories'] = 'default';
722
+ endif;
723
+
724
  if (isset($sec['cats'])):
725
  $sec['cats'] = explode(':',$sec['cats']);
726
  endif;
792
  // $a['feed/b/c/d'] with value 'e'.
793
  function flatten_array ($arr, $prefix = 'feed/', $separator = '/') {
794
  $ret = array ();
795
+ if (is_array($arr)) :
796
+ foreach ($arr as $key => $value) :
797
+ if (is_scalar($value)) :
798
  $ret[$prefix.$key] = $value;
799
+ else :
800
  $ret = array_merge($ret, $this->flatten_array($value, $prefix.$key.$separator, $separator));
801
+ endif;
802
+ endforeach;
803
  endif;
804
  return $ret;
805
  } // function FeedWordPress::flatten_array ()
808
  return $matches[1].Relative_URI::resolve($matches[2], $this->_base).$matches[3];
809
  } // function FeedWordPress::resolve_relative_uri ()
810
 
811
+ function hardcode ($what, $f) {
812
+ $default = get_settings("feedwordpress_hardcode_$what");
813
+ if ( $default === 'yes' ) :
814
+ // If the default is to hardcode, then we want the
815
+ // negation of negative(): TRUE by default and FALSE if
816
+ // the setting is explicitly "no"
817
+ $ret = !FeedWordPress::negative($f, "hardcode $what");
818
+ else :
819
+ // If the default is NOT to hardcode, then we want
820
+ // affirmative(): FALSE by default and TRUE if the
821
+ // setting is explicitly "yes"
822
+ $ret = FeedWordPress::affirmative($f, "hardcode $what");
823
+ endif;
824
+ return $ret;
825
+ }
826
+
827
+ function negative ($f, $setting) {
828
+ $nego = array ('n', 'no', 'f', 'false');
829
+ return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $nego));
830
+ }
831
+
832
+ function affirmative ($f, $setting) {
833
  $affirmo = array ('y', 'yes', 't', 'true', 1);
834
  return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $affirmo));
835
  }
837
  function update_feed ($wpdb, $channel, $f) {
838
  $link_id = $f['link_id'];
839
 
840
+ if (!isset($channel['id'])) :
841
+ $channel['id'] = $f['uri'];
842
+ endif;
843
 
844
  $update = array();
845
  if (isset($channel['link'])) :
846
  $update[] = "link_url = '".$wpdb->escape($channel['link'])."'";
847
  endif;
848
 
849
+ if (!FeedWordPress::hardcode('name', $f) and isset($channel['title'])) :
850
  $update[] = "link_name = '".$wpdb->escape($channel['title'])."'";
851
  endif;
852
 
853
+ if (!FeedWordPress::hardcode('description', $f)) :
854
  if (isset($channel['tagline'])) :
855
  $update[] = "link_description = '".$wpdb->escape($channel['tagline'])."'";
856
  elseif (isset($channel['description'])) :
866
 
867
  # -- A few things we don't want to save in the notes
868
  unset($f['link_id']); unset($f['uri']); unset($f['name']);
869
+ unset($f['hardcode categories']); // Deprecated
870
 
871
  $notes = '';
872
  foreach ($f as $key => $value) :
873
+ $notes .= $key . ": ". addcslashes($value, "\0..\37") . "\n";
874
  endforeach;
875
  $update[] = "link_notes = '".$wpdb->escape($notes)."'";
876
 
877
  $update_set = implode(',', $update);
878
 
879
+ // Update the properties of the link from the feed information
880
  $result = $wpdb->query("
881
  UPDATE $wpdb->links
882
  SET $update_set
1045
  if (isset($channel['title'])) $post['syndication_source'] = $channel['title'];
1046
  if (isset($channel['link'])) $post['syndication_source_uri'] = $channel['link'];
1047
  $post['syndication_feed'] = $f['uri'];
1048
+
1049
  // In case you want to know the external permalink...
1050
  $post['syndication_permalink'] = $item['link'];
1051
 
1052
+ // Feed-by-feed options for author and category creation
1053
+ $post['named']['unfamiliar']['author'] = $f['unfamiliar author'];
1054
+ $post['named']['unfamiliar']['category'] = $f['unfamiliar categories'];
1055
+
1056
  // Categories: start with default categories
1057
  $post['named']['category'] = $f['cats'];
1058
 
1059
  // Now add categories from the post, if we have 'em
1060
+ if ( is_array($item['categories']) ) :
 
 
 
1061
  foreach ($item['categories'] as $cat):
1062
  if ( strpos($f['uri'], 'del.icio.us') !== false ):
1063
  $post['named']['category'] = array_merge($post['named']['category'], explode(' ', $cat));
1077
  FROM $wpdb->posts WHERE guid='$guid'
1078
  ");
1079
 
1080
+ if (!$result) :
1081
  $freshness = 2; // New content
1082
+ elseif ($post['epoch']['modified'] > $result->modified) :
1083
  $freshness = 1; // Updated content
1084
+ else :
1085
  $freshness = 0;
1086
  endif;
1087
 
1091
  $wpdb,
1092
  $post['named']['author']['name'],
1093
  $post['named']['author']['email'],
1094
+ $post['named']['author']['uri'],
1095
+ FeedWordPress::on_unfamiliar('author', $post['named']['unfamiliar']['author'])
1096
  );
1097
+
1098
+ if (is_null($post['post_author'])) :
1099
+ $freshness = 0;
1100
+ else :
1101
+ # -- Look up, or create, numeric ID for categories
1102
+ $post['post_category'] = $this->lookup_categories (
1103
+ $wpdb,
1104
+ $post['named']['category'],
1105
+ FeedWordPress::on_unfamiliar('category', $post['named']['unfamiliar']['category'])
1106
+ );
1107
+ if (is_null($post['post_category'])) :
1108
+ $freshness = 0;
1109
+ endif;
1110
+ endif;
1111
 
 
 
 
 
 
 
1112
  unset($post['named']);
1113
  endif;
1114
 
1115
+ if ($freshness > 0) :
1116
+ $post = apply_filters('syndicated_post', $post);
1117
+ if (is_null($post)) $freshness = 0;
1118
+ endif;
1119
+
1120
  if ($freshness == 2) :
1121
  // The item has not yet been added. So let's add it.
1122
 
1201
  do_action('update_syndicated_item', $postId);
1202
 
1203
  $ret = 'updated';
1204
+ else :
1205
  $ret = false;
1206
  endif;
1207
 
1263
 
1264
  // FeedWordPress::author_to_id (): get the ID for an author name from
1265
  // the feed. Create the author if necessary.
1266
+ function author_to_id ($wpdb, $author, $email, $url, $unfamiliar_author = 'create') {
1267
  // Never can be too careful...
1268
  $nice_author = sanitize_title($author);
1269
  $author = $wpdb->escape($author);
1271
  $url = $wpdb->escape($url);
1272
 
1273
  $id = $wpdb->get_var(
1274
+ "SELECT ID from $wpdb->users
1275
+ WHERE
1276
+ user_login = '$author' OR
1277
+ user_firstname = '$author' OR
1278
+ user_nickname = '$author' OR
1279
+ user_nicename = '$nice_author' OR
1280
+ user_description = '$author' OR
1281
+ (LOWER(user_description) RLIKE
1282
+ '(^|\n)a.k.a.( |\t)*:?( |\t)*".strtolower($author)."( |\t|\r)*(\n|\$)')
1283
+ ");
1284
 
1285
+ if (is_null($id)) :
1286
+ if ($unfamiliar_author === 'create') :
1287
+ $wpdb->query (
1288
+ "INSERT INTO $wpdb->users
1289
+ SET
1290
+ ID='0',
1291
+ user_login='$author',
1292
+ user_firstname='$author',
1293
+ user_nickname='$author',
1294
+ user_nicename='$nice_author',
1295
+ user_description='$author',
1296
+ user_email='$email',
1297
+ user_url='$url'");
1298
+ $id = $wpdb->insert_id;
1299
+ elseif ($unfamiliar_author === 'default') :
1300
+ $id = 1;
1301
+ endif;
1302
  endif;
1303
  return $id;
1304
  } // function FeedWordPress::author_to_id ()
1305
+
1306
  // look up (and create) category ids from a list of categories
1307
+ function lookup_categories ($wpdb, $cats, $unfamiliar_category = 'create') {
1308
+ // Normalize whitespace because (1) trailing whitespace can
1309
+ // cause PHP and MySQL not to see eye to eye on VARCHAR
1310
+ // comparisons for some versions of MySQL (cf.
1311
+ // <http://dev.mysql.com/doc/mysql/en/char.html>), and (2)
1312
+ // because I doubt most people want to make a semantic
1313
+ // distinction between 'Computers' and 'Computers '
1314
+ $cats = array_map('trim', $cats);
1315
+
1316
  $cat_ids = array ();
1317
+
1318
  if ( count($cats) > 0 ) :
1319
  # i'd kill for a decent map function in PHP
1320
  # but that would require functions to be first class object,
1321
  # or at least coderef support
1322
+ $cat_str = array ();
1323
+ $cat_aka = array ();
1324
  foreach ( $cats as $c ) :
1325
+ $esc = $wpdb->escape($c);
1326
+ $cat_str[] = "'$esc'";
1327
  $cat_aka[] = "(LOWER(category_description) RLIKE '(^|\n)a.k.a.( |\t)*:?( |\t)*".strtolower($esc)."( |\t|\r)*(\n|\$)')";
1328
  endforeach;
1329
 
1330
+ $match_cat_name = 'cat_name IN ('.join(',', $cat_str).')';
1331
+ $match_cat_alias = join(' OR ', $cat_aka);
1332
+
1333
+ // Normalizing case with LOWER() avoids conflicts in
1334
+ // VARCHAR comparison between PHP (which has
1335
+ // case-sensitive comparisons) and MySQL (which has
1336
+ // case-insensitive comparisons for the field types used
1337
+ // by WordPress)
1338
+ $results = $wpdb->get_results(
1339
+ "SELECT
1340
+ cat_ID,
1341
+ LOWER(TRIM(cat_name)) AS cat_name,
1342
+ LOWER(category_description) AS category_description
1343
+ FROM $wpdb->categories
1344
+ WHERE ($match_cat_name) OR ($match_cat_alias)"
1345
+ );
1346
 
1347
+ $cat_ids = array();
1348
+ $found = array();
1349
 
1350
  if (!is_null($results)):
1351
  foreach ( $results as $row ) :
1352
+ // Add existing ID to list of numerical
1353
+ // IDs to eventually place post in
1354
  $cat_ids[] = $row->cat_ID;
 
1355
 
1356
+ // Add name to list of categories not to
1357
+ // create afresh.
1358
+ $found[] = $row->cat_name;
1359
+
1360
+ // Add name of any aliases to list of
1361
+ // categories not to create afresh.
1362
  if (preg_match_all('/^a.k.a. \s* :? \s* (.*\S) \s*$/mx',
1363
  $row->category_description, $aka,
1364
  PREG_PATTERN_ORDER)) :
1365
+ $found = array_merge ($found, $aka[1]);
 
1366
  endif;
1367
  endforeach;
1368
  endif;
1369
 
1370
  foreach ($cats as $new_cat) :
1371
+ if (($unfamiliar_category==='create') and !in_array(strtolower($new_cat), $found)) :
 
 
1372
  $nice_cat = sanitize_title($new_cat);
1373
+ $wpdb->query(sprintf("
1374
+ INSERT INTO $wpdb->categories
1375
+ SET
1376
+ cat_name='%s',
1377
+ category_nicename='%s'
1378
+ ", $wpdb->escape($new_cat), $nice_cat));
1379
  $cat_ids[] = $wpdb->insert_id;
1380
  endif;
1381
  endforeach;
1382
+
1383
+ if ((count($cat_ids) == 0) and ($unfamiliar_category === 'filter')) :
1384
+ $cat_ids = NULL; // Drop the post
1385
+ endif;
1386
  endif;
1387
  return $cat_ids;
1388
  } // function FeedWordPress::lookup_categories ()
1390
  function rpc_secret () {
1391
  return get_settings('feedwordpress_rpc_secret');
1392
  } // function FeedWordPress::rpc_secret ()
1393
+
1394
+ function on_unfamiliar ($what = 'author', $override = NULL) {
1395
+ $set = array('create', 'default', 'filter');
1396
+
1397
+ $ret = strtolower($override);
1398
+ if (!in_array($ret, $set)) :
1399
+ $ret = get_settings('feedwordpress_unfamiliar_'.$what);
1400
+ if (!in_array($ret, $set)) :
1401
+ $ret = 'create';
1402
+ endif;
1403
+ endif;
1404
+
1405
+ return $ret;
1406
+ } // function FeedWordPress::on_unfamiliar()
1407
+
1408
  function link_category_id () {
1409
  global $wpdb;
1410