PluginProbe
FeedWordPress / 2010.0528
FeedWordPress v2010.0528
trunk 0.8 0.9 0.91 0.95 0.96 0.97 0.98 0.981 0.99 0.991 0.992 0.993 2008.1030 2008.1101 2008.1105 2008.1214 2009.0612 2009.0613 2009.0618 2009.0707 2009.1111 2009.1112 2010.0127 2010.0528 All 65 releases
← All changes | syndicatedlink.class.php +278 -983 trunk2010.0528 View file →
@@ -24,9 +24,9 @@
24 24 # Values have linebreak characters escaped with C-style
25 25 # backslashes (so, for example, a newline becomes "\n").
26 26 #
27 27 # The value of `cats` is used as a newline-separated list of
28 -# default categories for any post coming from a particular feed.
28 +# default categories for any post coming from a particular feed.
29 29 # (In the example above, any posts from this feed will be placed
30 30 # in the "computers" and "web" categories--*in addition to* any
31 31 # categories that may already be applied to the posts.)
32 32 #
@@ -32,119 +32,143 @@
32 32 #
33 33 # Values of keys in link_notes are accessible from templates using
34 34 # the function `get_feed_meta($key)` if this plugin is activated.
35 35
36 -require_once dirname( __FILE__ ) . '/magpiefromsimplepie.class.php';
37 -require_once dirname( __FILE__ ) . '/feedwordpressparsedpostmeta.class.php';
36 +require_once(dirname(__FILE__).'/magpiefromsimplepie.class.php');
38 37
39 38 class SyndicatedLink {
40 39 var $id = null;
41 40 var $link = null;
42 41 var $settings = array ();
43 - public $simplepie = null;
42 + var $simplepie = null;
44 43 var $magpie = null;
45 44
46 - public function __construct( $link ) {
45 + function SyndicatedLink ($link) {
46 + global $wpdb;
47 +
47 48 if (is_object($link)) :
48 49 $this->link = $link;
49 50 $this->id = $link->link_id;
50 51 else :
51 52 $this->id = $link;
52 - $this->link = get_bookmark($link);
53 + if (function_exists('get_bookmark')) : // WP 2.1+
54 + $this->link = get_bookmark($link);
55 + else :
56 + $this->link = $wpdb->get_row("
57 + SELECT * FROM $wpdb->links
58 + WHERE (link_id = '".$wpdb->escape($link)."')"
59 + );
60 + endif;
53 61 endif;
54 62
55 - if (is_object($this->link)) :
56 - if (strlen($this->link->link_rss) > 0) :
57 - $this->get_settings_from_notes();
63 + if (strlen($this->link->link_rss) > 0) :
64 + // Read off feed settings from link_notes
65 + $notes = explode("\n", $this->link->link_notes);
66 + foreach ($notes as $note):
67 + $pair = explode(": ", $note, 2);
68 + $key = (isset($pair[0]) ? $pair[0] : null);
69 + $value = (isset($pair[1]) ? $pair[1] : null);
70 + if (!is_null($key) and !is_null($value)) :
71 + // Unescape and trim() off the whitespace.
72 + // Thanks to Ray Lischner for pointing out the
73 + // need to trim off whitespace.
74 + $this->settings[$key] = stripcslashes (trim($value));
75 + endif;
76 + endforeach;
77 +
78 + // "Magic" feed settings
79 + $this->settings['link/uri'] = $this->link->link_rss;
80 + $this->settings['link/name'] = $this->link->link_name;
81 + $this->settings['link/id'] = $this->link->link_id;
82 +
83 + // `hardcode categories` and `unfamiliar categories` are deprecated in favor of `unfamiliar category`
84 + if (
85 + isset($this->settings['unfamiliar categories'])
86 + and !isset($this->settings['unfamiliar category'])
87 + ) :
88 + $this->settings['unfamiliar category'] = $this->settings['unfamiliar categories'];
58 89 endif;
59 - endif;
90 + if (
91 + FeedWordPress::affirmative($this->settings, 'hardcode categories')
92 + and !isset($this->settings['unfamiliar category'])
93 + ) :
94 + $this->settings['unfamiliar category'] = 'default';
95 + endif;
60 96
61 - add_filter('feedwordpress_update_complete', array($this, 'process_retirements'), 1000, 1);
62 - } /* SyndicatedLink::__construct () */
97 + // Set this up automagically for del.icio.us
98 + $bits = parse_url($this->link->link_rss);
99 + $tagspacers = array('del.icio.us', 'feeds.delicious.com');
100 + if (!isset($this->settings['cat_split']) and in_array($bits['host'], $tagspacers)) :
101 + $this->settings['cat_split'] = '\s'; // Whitespace separates multiple tags in del.icio.us RSS feeds
102 + endif;
63 103
64 - public function found () {
104 + if (isset($this->settings['cats'])):
105 + $this->settings['cats'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['cats']);
106 + endif;
107 + if (isset($this->settings['tags'])):
108 + $this->settings['tags'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['tags']);
109 + endif;
110 +
111 + if (isset($this->settings['map authors'])) :
112 + $author_rules = explode("\n\n", $this->settings['map authors']);
113 + $ma = array();
114 + foreach ($author_rules as $rule) :
115 + list($rule_type, $author_name, $author_action) = explode("\n", $rule);
116 +
117 + // Normalize for case and whitespace
118 + $rule_type = strtolower(trim($rule_type));
119 + $author_name = strtolower(trim($author_name));
120 + $author_action = strtolower(trim($author_action));
121 +
122 + $ma[$rule_type][$author_name] = $author_action;
123 + endforeach;
124 + $this->settings['map authors'] = $ma;
125 + endif;
126 + endif;
127 + } /* SyndicatedLink::SyndicatedLink () */
128 +
129 + function found () {
65 130 return is_object($this->link) and !is_wp_error($this->link);
66 131 } /* SyndicatedLink::found () */
67 132
68 - public function id () {
69 - return (is_object($this->link) ? $this->link->link_id : NULL);
70 - }
71 -
72 - public function stale () {
73 - global $feedwordpress;
74 -
133 + function stale () {
75 134 $stale = true;
76 - if ($this->setting('update/hold')=='ping') :
135 + if (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='ping')) :
77 136 $stale = false; // don't update on any timed updates; pings only
78 - elseif ($this->setting('update/hold')=='next') :
137 + elseif (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='next')) :
79 138 $stale = true; // update on the next timed update
80 - elseif ( ! $this->setting('update/last') ) :
139 + elseif (!isset($this->settings['update/ttl']) or !isset($this->settings['update/last'])) :
81 140 $stale = true; // initial update
82 - elseif ( !empty($feedwordpress) and $feedwordpress->force_update_all()) :
83 - $stale = true; // forced general updating
84 141 else :
85 - $after = (
86 - (int) $this->setting('update/last')
87 - + (int) $this->setting('update/fudge')
88 - + ((int) $this->setting('update/ttl') * 60)
89 - );
142 + $after = ((int) $this->settings['update/last'])
143 + +((int) $this->settings['update/ttl'] * 60);
90 144 $stale = (time() >= $after);
91 145 endif;
92 146 return $stale;
93 147 } /* SyndicatedLink::stale () */
94 148
95 - public function fetch () {
96 - $timeout = $this->setting('fetch timeout', 'feedwordpress_fetch_timeout', FEEDWORDPRESS_FETCH_TIMEOUT_DEFAULT);
149 + function poll ($crash_ts = NULL) {
150 + global $wpdb;
97 151
98 152 $this->simplepie = apply_filters(
99 153 'syndicated_feed',
100 - FeedWordPress::fetch($this, array('timeout' => $timeout)),
154 + FeedWordPress::fetch($this->link->link_rss),
101 155 $this
102 156 );
103 -
157 +
104 158 // Filter compatibility mode
105 159 if (is_wp_error($this->simplepie)) :
106 160 $this->magpie = $this->simplepie;
107 161 else :
108 - $this->magpie = new MagpieFromSimplePie($this->simplepie, NULL);
162 + $this->magpie = new MagpieFromSimplePie($this->simplepie);
109 163 endif;
110 - } /* SyndicatedLink::fetch () */
111 164
112 - public function live_posts () {
113 - if ( !is_object($this->simplepie)) :
114 - $this->fetch();
115 - endif;
116 -
117 - if (is_object($this->simplepie) and method_exists($this->simplepie, 'get_items')) :
118 - $ret = apply_filters(
119 - 'syndicated_feed_items',
120 - $this->simplepie->get_items(),
121 - $this
122 - );
123 - else :
124 - $ret = $this->simplepie;
125 - endif;
126 - return $ret;
127 - } /* SyndicatedLink::live_posts () */
128 -
129 - protected function pause_updates () {
130 - return ('yes'==$this->setting("update/pause", "update_pause", 'no'));
131 - } /* SyndicatedLink::pause_updates () */
132 -
133 - public function poll ($crash_ts = NULL) {
134 - global $wpdb;
135 -
136 - $url = $this->uri(array('add_params' => true, 'fetch' => true));
137 - FeedWordPress::diagnostic('updated_feeds', 'Polling feed ['.$url.']');
138 -
139 - $this->fetch();
140 -
141 165 $new_count = NULL;
142 166
143 - $resume = ('yes'==$this->setting('update/unfinished'));
167 + $resume = FeedWordPress::affirmative($this->settings, 'update/unfinished');
144 168 if ($resume) :
145 169 // pick up where we left off
146 - $processed = array_map('trim', explode("\n", $this->setting('update/processed')));
170 + $processed = array_map('trim', explode("\n", $this->settings['update/processed']));
147 171 else :
148 172 // begin at the beginning
149 173 $processed = array();
150 174 endif;
@@ -150,87 +174,68 @@
150 174 endif;
151 175
152 176 if (is_wp_error($this->simplepie)) :
153 177 $new_count = $this->simplepie;
154 - // Error; establish an error setting.
155 - $theError = array();
156 - $theError['ts'] = time();
157 - $theError['since'] = time();
158 - $theError['object'] = $this->simplepie;
159 -
160 - $oldError = $this->setting('update/error', NULL, NULL);
161 - if (is_string($oldError)) :
162 - $oldError = unserialize($oldError);
163 - endif;
164 -
165 - if ( !is_null($oldError)) :
166 - // Copy over the in-error-since timestamp
167 - $theError['since'] = $oldError['since'];
168 -
169 - // If this is a repeat error, then we should
170 - // take a step back before we try to fetch it
171 - // again.
172 - $this->update_setting('update/last', time(), NULL);
173 - $ttl = $this->automatic_ttl();
174 - $ttl = apply_filters('syndicated_feed_ttl', $ttl, $this);
175 - $ttl = apply_filters('syndicated_feed_ttl_from_error', $ttl, $this);
176 - $this->update_setting('update/ttl', $ttl);
177 - $this->update_setting('update/timed', 'automatically');
178 - endif;
179 -
180 - do_action('syndicated_feed_error', $theError, $oldError, $this);
181 -
182 - $this->update_setting('update/error', serialize($theError));
183 - $this->save_settings(/*reload=*/ true);
184 -
185 178 elseif (is_object($this->simplepie)) :
179 + $new_count = array('new' => 0, 'updated' => 0);
186 180
187 - // Success; clear out error setting, if any.
188 - $this->update_setting('update/error', NULL);
189 -
190 - $new_count = array('new' => 0, 'updated' => 0, 'stored' => 0);
191 -
192 181 # -- Update Link metadata live from feed
193 182 $channel = $this->magpie->channel;
194 183
195 - if ( !isset($channel['id'])) :
184 + if (!isset($channel['id'])) :
196 185 $channel['id'] = $this->link->link_rss;
197 186 endif;
198 -
187 +
199 188 $update = array();
200 - if ( ! $this->hardcode('url') and isset($channel['link'])) :
201 - $update[] = "link_url = '".esc_sql($channel['link'])."'";
189 + if (!$this->hardcode('url') and isset($channel['link'])) :
190 + $update[] = "link_url = '".$wpdb->escape($channel['link'])."'";
202 191 endif;
203 -
204 - if ( ! $this->hardcode('name') and isset($channel['title'])) :
205 - $update[] = "link_name = '".esc_sql($channel['title'])."'";
192 +
193 + if (!$this->hardcode('name') and isset($channel['title'])) :
194 + $update[] = "link_name = '".$wpdb->escape($channel['title'])."'";
206 195 endif;
207 -
208 - if ( ! $this->hardcode('description')) :
196 +
197 + if (!$this->hardcode('description')) :
209 198 if (isset($channel['tagline'])) :
210 - $update[] = "link_description = '".esc_sql($channel['tagline'])."'";
199 + $update[] = "link_description = '".$wpdb->escape($channel['tagline'])."'";
211 200 elseif (isset($channel['description'])) :
212 - $update[] = "link_description = '".esc_sql($channel['description'])."'";
201 + $update[] = "link_description = '".$wpdb->escape($channel['description'])."'";
213 202 endif;
214 203 endif;
204 +
205 + $this->settings = array_merge($this->settings, $this->flatten_array($channel));
215 206
216 - $this->update_setting('link/feed_type', $this->simplepie->get_type());
207 + $this->settings['update/last'] = time(); $ttl = $this->ttl();
208 + if (!is_null($ttl)) :
209 + $this->settings['update/ttl'] = $ttl;
210 + $this->settings['update/timed'] = 'feed';
211 + else :
212 + // spread out over a time interval for staggered updates
213 + $updateWindow = $this->setting(
214 + 'update/window',
215 + 'update_window',
216 + DEFAULT_UPDATE_PERIOD
217 + );
218 + if (!is_numeric($updateWindow) or ($updateWindow < 1)) :
219 + $updateWindow = DEFAULT_UPDATE_PERIOD;
220 + endif;
221 +
222 + $fudgedInterval = $updateWindow+rand(0, 2*($updateWindow/3));
223 + $this->settings['update/ttl'] = apply_filters('syndicated_feed_automatic_ttl', $fudgedInterval, $this);
224 + $this->settings['update/timed'] = 'automatically';
225 + endif;
226 + $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl', $this->settings['update/ttl'], $this);
217 227
218 - $this->merge_settings($channel, 'feed/');
219 -
220 - $this->update_setting('update/last', time());
221 - $this->do_update_ttl();
222 -
223 - if ( ! $this->setting('update/hold') != 'ping') :
224 - $this->update_setting('update/hold', 'scheduled');
228 + if (!isset($this->settings['update/hold']) or $this->settings['update/hold']!='ping') :
229 + $this->settings['update/hold'] = 'scheduled';
225 230 endif;
226 231
227 - $this->update_setting('update/unfinished', 'yes');
232 + $this->settings['update/unfinished'] = 'yes';
228 233
229 - $update[] = "link_notes = '".esc_sql($this->settings_to_notes())."'";
234 + $update[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
230 235
231 236 $update_set = implode(',', $update);
232 -
237 +
233 238 // Update the properties of the link from the feed information
234 239 $result = $wpdb->query("
235 240 UPDATE $wpdb->links
236 241 SET $update_set
@@ -240,187 +245,70 @@
240 245
241 246 # -- Add new posts from feed and update any updated posts
242 247 $crashed = false;
243 248
244 - $posts = $this->live_posts();
245 -
246 - $this->magpie->originals = $posts;
247 -
248 - // If this is a complete feed, rather than an incremental feed, we
249 - // need to prepare to mark everything for presumptive retirement.
250 - if ($this->is_non_incremental()) :
251 - $q = new WP_Query(array(
252 - 'fields' => '_synfrom',
253 - 'post_status__not' => 'fwpretired',
254 - 'ignore_sticky_posts' => true,
255 - 'meta_key' => 'syndication_feed_id',
256 - 'meta_value' => $this->id,
257 - ));
258 - foreach ($q->posts as $p) :
259 - update_post_meta($p->ID, '_feedwordpress_retire_me_'.$this->id, '1');
260 - endforeach;
261 - endif;
262 -
249 + $posts = apply_filters(
250 + 'syndicated_feed_items',
251 + $this->magpie->originals,
252 + $this
253 + );
263 254 if (is_array($posts)) :
264 - foreach ($posts as $key => $item) :
265 - if ( ! $this->pause_updates()) :
266 - $post = new SyndicatedPost($item, $this);
255 + foreach ($posts as $key => $original) :
256 + $item = $this->magpie->items[$key];
257 + $post = new SyndicatedPost(array(
258 + 'simplepie' => $original,
259 + 'magpie' => $item,
260 + ), $this);
267 261
268 - if ( ! $resume or !in_array(trim($post->guid()), $processed)) :
269 - $processed[] = $post->guid();
270 - if ( ! $post->filtered()) :
271 - $new = $post->store();
272 - if ( $new !== false ) $new_count[$new]++;
273 - endif;
262 + if (!$resume or !in_array(trim($post->guid()), $processed)) :
263 + $processed[] = $post->guid();
264 + if (!$post->filtered()) :
265 + $new = $post->store();
266 + if ( $new !== false ) $new_count[$new]++;
267 + endif;
274 268
275 - if ( !is_null($crash_ts) and (time() > $crash_ts)) :
276 - $crashed = true;
277 - break;
278 - endif;
269 + if (!is_null($crash_ts) and (time() > $crash_ts)) :
270 + $crashed = true;
271 + break;
279 272 endif;
280 -
281 - unset($post);
282 273 endif;
274 + unset($post);
283 275 endforeach;
284 276 endif;
285 -
286 - if ('yes'==$this->setting('tombstones', 'tombstones', 'yes')) :
287 - // Check for use of Atom tombstones. Spec:
288 - // <http://tools.ietf.org/html/draft-snell-atompub-tombstones-18>
289 - $tombstones = $this->simplepie->get_feed_tags('http://purl.org/atompub/tombstones/1.0', 'deleted-entry');
290 - if ( !is_null($tombstones) && count($tombstones) > 0) :
291 - foreach ($tombstones as $tombstone) :
292 - $ref = NULL;
293 - foreach (array('', 'http://purl.org/atompub/tombstones/1.0') as $ns) :
294 - if (isset($tombstone['attribs'][$ns])
295 - and isset($tombstone['attribs'][$ns]['ref'])) :
296 - $ref = $tombstone['attribs'][$ns]['ref'];
297 - endif;
298 - endforeach;
299 -
300 - $q = new WP_Query(array(
301 - 'ignore_sticky_posts' => true,
302 - 'guid' => $ref,
303 - 'meta_key' => 'syndication_feed_id',
304 - 'meta_value' => $this->id, // Only allow a feed to tombstone its own entries.
305 - ));
306 -
307 - foreach ($q->posts as $p) :
308 - $old_status = $p->post_status;
309 - FeedWordPress::diagnostic('syndicated_posts', 'Retiring existing post # '.$p->ID.' "'.$p->post_title.'" due to Atom tombstone element in feed.');
310 - set_post_field('post_status', 'fwpretired', $p->ID);
311 - wp_transition_post_status('fwpretired', $old_status, $p);
312 - endforeach;
313 -
314 - endforeach;
315 - endif;
316 - endif;
317 -
318 277 $suffix = ($crashed ? 'crashed' : 'completed');
319 278 do_action('update_syndicated_feed_items', $this->id, $this);
320 - do_action("update_syndicated_feed_items_{$suffix}", $this->id, $this);
279 + do_action("update_syndicated_feed_items_${suffix}", $this->id, $this);
321 280
322 - $this->update_setting('update/processed', $processed);
323 - if ( ! $crashed) :
324 - $this->update_setting('update/unfinished', 'no');
281 + // Copy back any changes to feed settings made in the course of updating (e.g. new author rules)
282 + $to_notes = $this->settings;
283 +
284 + $this->settings['update/processed'] = $processed;
285 + if (!$crashed) :
286 + $this->settings['update/unfinished'] = 'no';
325 287 endif;
326 - $this->update_setting('link/item count', count($posts));
327 288
328 - // Copy back any changes to feed settings made in the
329 - // course of updating (e.g. new author rules)
330 - $update_set = "link_notes = '" . esc_sql($this->settings_to_notes())."'";
331 -
289 + $update_set = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
290 +
332 291 // Update the properties of the link from the feed information
333 292 $result = $wpdb->query("
334 - UPDATE {$wpdb->links}
335 - SET {$update_set}
336 - WHERE link_id='{$this->id}'
293 + UPDATE $wpdb->links
294 + SET $update_set
295 + WHERE link_id='$this->id'
337 296 ");
338 - if ( FALSE === $result ) :
339 - FeedWordPress::diagnostic(
340 - 'SyndicatedLink/poll',
341 - 'Database update failed',
342 - );
343 - endif;
344 -
297 +
345 298 do_action("update_syndicated_feed_completed", $this->id, $this);
346 299 endif;
347 -
348 - // All done; let's clean up.
349 - $this->magpie = NULL;
350 -
351 - // Avoid circular-reference memory leak in PHP < 5.3.
352 - // Cf. <http://simplepie.org/wiki/faq/i_m_getting_memory_leaks>
353 - if (method_exists($this->simplepie, '__destruct')) :
354 - $this->simplepie->__destruct();
355 - endif;
356 - $this->simplepie = NULL;
357 -
300 +
358 301 return $new_count;
359 302 } /* SyndicatedLink::poll() */
360 303
361 304 /**
362 - * Update the time to live of this link.
363 - */
364 - public function do_update_ttl(): void {
365 - // Get ttl and xml elements, return them if available
366 - list( $ttl, $xml ) = $this->ttl( /*return element=*/ true);
367 -
368 - // Check if ttl is not null
369 - if ( !is_null( $ttl ) ) {
370 - $this->update_setting( 'update/ttl', $ttl );
371 - $this->update_setting( 'update/xml', $xml );
372 - $this->update_setting( 'update/timed', 'feed' );
373 - } else {
374 - // Fallback to automatic ttl if null
375 - $ttl = $this->automatic_ttl();
376 - $this->update_setting( 'update/ttl', $ttl );
377 - $this->update_setting( 'update/xml', null ); // Explicit null
378 - $this->update_setting( 'update/timed', 'automatically' );
379 - }
380 -
381 - // Adding a random fudge value (ensure it works across versions)
382 - $this->update_setting( 'update/fudge', rand( 0, (int) ( $ttl / 3 ) ) * 60 );
383 -
384 - // Apply filter to ttl (should be compatible with all PHP 8.x versions)
385 - $this->update_setting(
386 - 'update/ttl',
387 - apply_filters(
388 - 'syndicated_feed_ttl',
389 - $this->setting( 'update/ttl' ),
390 - $this
391 - )
392 - );
393 - } /* SyndicatedLink::do_update_ttl () */
394 -
395 - public function process_retirements ($delta) {
396 - $q = new WP_Query(array(
397 - 'fields' => '_synfrom',
398 - 'post_status__not' => 'fwpretired',
399 - 'ignore_sticky_posts' => true,
400 - 'meta_key' => '_feedwordpress_retire_me_'.$this->id,
401 - 'meta_value' => '1',
402 - ));
403 - if ($q->have_posts()) :
404 - foreach ($q->posts as $p) :
405 - $old_status = $p->post_status;
406 - FeedWordPress::diagnostic('syndicated_posts', 'Retiring existing post # '.$p->ID.' "'.$p->post_title.'" due to absence from a non-incremental feed.');
407 - set_post_field('post_status', 'fwpretired', $p->ID);
408 - wp_transition_post_status('fwpretired', $old_status, $p);
409 - delete_post_meta($p->ID, '_feedwordpress_retire_me_'.$this->id);
410 - endforeach;
411 - endif;
412 -
413 - return $delta;
414 - } /* SyndicatedLink::process_retirements () */
415 -
416 - /**
417 305 * Updates the URL for the feed syndicated by this link.
418 306 *
419 307 * @param string $url The new feed URL to use for this source.
420 308 * @return bool TRUE on success, FALSE on failure.
421 309 */
422 - public function set_uri ($url) {
310 + function set_uri ($url) {
423 311 global $wpdb;
424 312
425 313 if ($this->found()) :
426 314 // Update link_rss
@@ -426,12 +314,12 @@
426 314 // Update link_rss
427 315 $result = $wpdb->query("
428 316 UPDATE $wpdb->links
429 317 SET
430 - link_rss = '".esc_sql($url)."'
431 - WHERE link_id = '".esc_sql($this->id)."'
318 + link_rss = '".$wpdb->escape($url)."'
319 + WHERE link_id = '".$wpdb->escape($this->id)."'
432 320 ");
433 -
321 +
434 322 $ret = ($result ? true : false);
435 323 else :
436 324 $ret = false;
437 325 endif;
@@ -436,89 +324,30 @@
436 324 $ret = false;
437 325 endif;
438 326 return $ret;
439 327 } /* SyndicatedLink::set_uri () */
440 -
441 - public function deactivate () {
328 +
329 + function map_name_to_new_user ($name, $newuser_name) {
442 330 global $wpdb;
443 331
444 - $wpdb->query($wpdb->prepare("
445 - UPDATE $wpdb->links SET link_visible = 'N' WHERE link_id = %d
446 - ", (int) $this->id));
447 - } /* SyndicatedLink::deactivate () */
448 -
449 - /**
450 - * SyndicatedLink::delete() deletes a subscription from the WordPress links
451 - * table. Any posts that were syndicated through that subscription will still
452 - * be present in the wp_posts table; but postmeta fields that refer to the
453 - * syndication feed's numeric id (which will no longer be valid) will be
454 - * deleted. For most purposes, the posts remaining will be treated as if they
455 - * were locally authored posts rather than syndicated posts.
456 - *
457 - * @global $wpdb
458 - * @uses wpdb::query
459 - */
460 - public function delete () {
461 - global $wpdb;
462 -
463 - $wpdb->query($wpdb->prepare("
464 - DELETE FROM $wpdb->postmeta WHERE meta_key='syndication_feed_id'
465 - AND meta_value = '%s'
466 - ", $this->id));
467 -
468 - $wpdb->query($wpdb->prepare("
469 - DELETE FROM $wpdb->links WHERE link_id = %d
470 - ", (int) $this->id));
471 -
472 - $this->id = NULL;
473 - } /* SyndicatedLink::delete () */
474 -
475 - /**
476 - * SyndicatedLink::nuke() deletes a subscription AND all of the
477 - * posts syndicated through that subscription.
478 - *
479 - * @global $wpdb
480 - * @uses wpdb::get_col
481 - * @uses wp_delete_post
482 - * @uses SyndicatedLink::delete
483 - */
484 - public function nuke () {
485 - global $wpdb;
486 -
487 - // Make a list of the items syndicated from this feed...
488 - $post_ids = $wpdb->get_col($wpdb->prepare("
489 - SELECT post_id FROM $wpdb->postmeta
490 - WHERE meta_key = 'syndication_feed_id'
491 - AND meta_value = '%s'
492 - ", $this->id));
493 -
494 - // ... and kill them all
495 - if (count($post_ids) > 0) :
496 - foreach ($post_ids as $post_id) :
497 - // Force scrubbing of deleted post
498 - // rather than sending to Trashcan
499 - wp_delete_post(
500 - /*postid=*/ $post_id,
501 - /*force_delete=*/ true
502 - );
503 - endforeach;
504 - endif;
505 -
506 - $this->delete();
507 - } /* SyndicatedLink::nuke () */
508 -
509 - public function map_name_to_new_user ($name, $newuser_name) {
510 - global $wpdb;
511 -
512 332 if (strlen($newuser_name) > 0) :
513 - $newuser_id = fwp_insert_new_user($newuser_name);
333 + $userdata = array();
334 + $userdata['ID'] = NULL;
335 +
336 + $userdata['user_login'] = sanitize_user($newuser_name);
337 + $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
338 +
339 + $userdata['user_nicename'] = sanitize_title($newuser_name);
340 + $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
341 +
342 + $userdata['display_name'] = $wpdb->escape($newuser_name);
343 +
344 + $newuser_id = wp_insert_user($userdata);
514 345 if (is_numeric($newuser_id)) :
515 346 if (is_null($name)) : // Unfamiliar author
516 - $this->update_setting('unfamiliar author', $newuser_id);
347 + $this->settings['unfamiliar author'] = $newuser_id;
517 348 else :
518 - $map = $this->setting('map authors');
519 - $map['name'][$name] = $newuser_id;
520 - $this->update_setting('map authors', $map);
349 + $this->settings['map authors']['name'][$name] = $newuser_id;
521 350 endif;
522 351 else :
523 352 // TODO: Add some error detection and reporting
524 353 endif;
@@ -526,115 +355,9 @@
526 355 // TODO: Add some error reporting
527 356 endif;
528 357 } /* SyndicatedLink::map_name_to_new_user () */
529 358
530 - protected function imploded_settings () {
531 - return array('cats', 'tags', 'match/cats', 'match/tags', 'match/filter');
532 - } /* SyndicatedLink::imploded_settings () */
533 -
534 - protected function get_settings_from_notes () {
535 - // Read off feed settings from link_notes
536 - $notes = explode("\n", $this->link->link_notes);
537 - foreach ($notes as $note):
538 - $pair = explode(": ", $note, 2);
539 - $key = (isset($pair[0]) ? $pair[0] : null);
540 - $value = (isset($pair[1]) ? $pair[1] : null);
541 - if ( !is_null($key) and !is_null($value)) :
542 - // Unescape and trim() off the whitespace.
543 - // Thanks to Ray Lischner for pointing out the
544 - // need to trim off whitespace.
545 - $this->settings[$key] = stripcslashes (trim($value));
546 - endif;
547 - endforeach;
548 -
549 - // "Magic" feed settings
550 - $this->settings['link/uri'] = $this->link->link_rss;
551 - $this->settings['link/name'] = $this->link->link_name;
552 - $this->settings['link/id'] = $this->link->link_id;
553 -
554 - // `hardcode categories` and `unfamiliar categories` are
555 - // deprecated in favor of `unfamiliar category`
556 - if (
557 - isset($this->settings['unfamiliar categories'])
558 - and !isset($this->settings['unfamiliar category'])
559 - ) :
560 - $this->settings['unfamiliar category'] = $this->settings['unfamiliar categories'];
561 - endif;
562 - if (
563 - FeedWordPress::affirmative($this->settings, 'hardcode categories')
564 - and !isset($this->settings['unfamiliar category'])
565 - ) :
566 - $this->settings['unfamiliar category'] = 'default';
567 - endif;
568 -
569 - // Set this up automagically for del.icio.us
570 - $bits = parse_url($this->link->link_rss);
571 - $tagspacers = array('del.icio.us', 'feeds.delicious.com');
572 - if ( !isset($this->settings['cat_split']) and in_array($bits['host'], $tagspacers)) :
573 - $this->settings['cat_split'] = '\s'; // Whitespace separates multiple tags in del.icio.us RSS feeds
574 - endif;
575 -
576 - // Simple lists
577 - foreach ($this->imploded_settings() as $what) :
578 - if (isset($this->settings[$what])):
579 - $this->settings[$what] = explode(
580 - FEEDWORDPRESS_CAT_SEPARATOR,
581 - $this->settings[$what]
582 - );
583 - endif;
584 - endforeach;
585 -
586 - if (isset($this->settings['terms'])) :
587 - // Look for new format
588 - $this->settings['terms'] = maybe_unserialize($this->settings['terms']);
589 -
590 - if ( !is_array($this->settings['terms'])) :
591 - // Deal with old format instead. Ugh.
592 -
593 - // Split on two *or more* consecutive breaks
594 - // because in the old format, a taxonomy
595 - // without any associated terms would
596 - // produce tax_name#1\n\n\ntax_name#2\nterm,
597 - // and the naive split on the first \n\n
598 - // would screw up the tax_name#2 list.
599 - //
600 - // Props to David Morris for pointing this
601 - // out.
602 -
603 - $this->settings['terms'] = preg_split(
604 - "/".FEEDWORDPRESS_CAT_SEPARATOR."{2,}/",
605 - $this->settings['terms']
606 - );
607 - $terms = array();
608 - foreach ($this->settings['terms'] as $line) :
609 - $line = explode(FEEDWORDPRESS_CAT_SEPARATOR, $line);
610 - $tax = array_shift($line);
611 - $terms[$tax] = $line;
612 - endforeach;
613 - $this->settings['terms'] = $terms;
614 - endif;
615 - endif;
616 -
617 - if (isset($this->settings['map authors'])) :
618 - $author_rules = explode("\n\n", $this->settings['map authors']);
619 - $ma = array();
620 - foreach ($author_rules as $rule) :
621 - $parts = array_pad(explode("\n", $rule), 3, '');
622 - list($rule_type, $author_name, $author_action) = $parts;
623 -
624 - // Normalize for case and whitespace
625 - $rule_type = strtolower(trim($rule_type));
626 - $author_name = strtolower(trim($author_name));
627 - $author_action = strtolower(trim($author_action));
628 -
629 - $ma[$rule_type][$author_name] = $author_action;
630 - endforeach;
631 - $this->settings['map authors'] = $ma;
632 - endif;
633 -
634 - } /* SyndicatedLink::get_settings_from_notes () */
635 -
636 - protected function settings_to_notes () {
359 + function settings_to_notes () {
637 360 $to_notes = $this->settings;
638 361
639 362 unset($to_notes['link/id']); // Magic setting; don't save
640 363 unset($to_notes['link/uri']); // Magic setting; don't save
@@ -646,21 +369,14 @@
646 369 if (isset($to_notes['update/processed']) and (is_array($to_notes['update/processed']))) :
647 370 $to_notes['update/processed'] = implode("\n", $to_notes['update/processed']);
648 371 endif;
649 372
650 - foreach ($this->imploded_settings() as $what) :
651 - if (isset($to_notes[$what]) and is_array($to_notes[$what])) :
652 - $to_notes[$what] = implode(
653 - FEEDWORDPRESS_CAT_SEPARATOR,
654 - $to_notes[$what]
655 - );
656 - endif;
657 - endforeach;
658 -
659 - if (isset($to_notes['terms']) and is_array($to_notes['terms'])) :
660 - // Serialize it.
661 - $to_notes['terms'] = serialize($to_notes['terms']);
373 + if (isset($to_notes['cats']) and is_array($to_notes['cats'])) :
374 + $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
662 375 endif;
376 + if (isset($to_notes['tags']) and is_array($to_notes['tags'])) :
377 + $to_notes['tags'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['tags']);
378 + endif;
663 379
664 380 // Collapse the author mapping rule structure back into a flat string
665 381 if (isset($to_notes['map authors'])) :
666 382 $ma = array();
@@ -678,18 +394,18 @@
678 394 endforeach;
679 395 return $notes;
680 396 } /* SyndicatedLink::settings_to_notes () */
681 397
682 - public function save_settings ($reload = false) {
398 + function save_settings ($reload = false) {
683 399 global $wpdb;
684 400
685 401 // Save channel-level meta-data
686 402 foreach (array('link_name', 'link_description', 'link_url') as $what) :
687 - $alter[] = "{$what} = '".esc_sql($this->link->{$what})."'";
403 + $alter[] = "{$what} = '".$wpdb->escape($this->link->{$what})."'";
688 404 endforeach;
689 405
690 406 // Save settings to the notes field
691 - $alter[] = "link_notes = '".esc_sql($this->settings_to_notes())."'";
407 + $alter[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
692 408
693 409 // Update the properties of the link from settings changes, etc.
694 410 $update_set = implode(", ", $alter);
695 411
@@ -697,14 +413,9 @@
697 413 UPDATE $wpdb->links
698 414 SET $update_set
699 415 WHERE link_id='$this->id'
700 416 ");
701 -
702 - if ( $result === false )
703 - {
704 - error_log("query failed: " . $wpdb->last_error);
705 - }
706 -
417 +
707 418 if ($reload) :
708 419 // force reload of link information from DB
709 420 if (function_exists('clean_bookmark_cache')) :
710 421 clean_bookmark_cache($this->id);
@@ -715,330 +426,62 @@
715 426 /**
716 427 * Retrieves the value of a setting, allowing for a global setting to be
717 428 * used as a fallback, or a constant value, or both.
718 429 *
719 - * @param string $name The link setting key.
720 - * @param mixed $fallback_global If the link setting is nonexistent or
721 - * marked as a use-default value, fall back
722 - * to the value of this global setting.
723 - * @param mixed $fallback_value If the link setting and the global setting are
724 - * nonexistent or marked as ause-default value,
725 - * fall back to this constant value.
726 - *
727 - * @return mixed|null Should *not* return a boolean!!
430 + * @param string $name The link setting key
431 + * @param mixed $fallback_global If the link setting is nonexistent or marked as a use-default value, fall back to the value of this global setting.
432 + * @param mixed $fallback_value If the link setting and the global setting are nonexistent or marked as a use-default value, fall back to this constant value.
433 + * @return bool TRUE on success, FALSE on failure.
728 434 */
729 - public function setting( $name, $fallback_global = NULL, $fallback_value = NULL, $default = 'default' ) {
435 + function setting ($name, $fallback_global = NULL, $fallback_value = NULL) {
730 436 $ret = NULL;
731 - if ( isset( $this->settings[ $name ] ) ) :
732 - $ret = $this->settings[ $name ];
437 + if (isset($this->settings[$name])) :
438 + $ret = $this->settings[$name];
733 439 endif;
734 -
440 +
735 441 $no_value = (
736 - is_null( $ret )
737 - or ( is_string( $ret ) and strtolower( $ret ) == $default )
442 + is_null($ret)
443 + or (is_string($ret) and strtolower($ret)=='default')
738 444 );
739 445
740 - if ( $no_value and ! is_null( $fallback_global ) ) :
741 - // Avoid duplication of this correction
742 - $fallback_global = preg_replace( '/^feedwordpress_/', '', $fallback_global );
743 -
744 - // Occasionally we'll get an array back. Convert it to a string
745 - if ( is_array( $fallback_global ) && sizeof( $fallback_global ) ) :
746 - $fallback_global = reset( $fallback_global );
747 - endif;
748 -
749 - if ( ! empty( $fallback_global ) ) :
750 - $ret = get_option( 'feedwordpress_' . $fallback_global, /*default=*/ NULL );
751 - endif;
446 + if ($no_value and !is_null($fallback_global)) :
447 + $ret = get_option('feedwordpress_'.$fallback_global, /*default=*/ NULL);
752 448 endif;
753 449
754 450 $no_value = (
755 - is_null( $ret )
756 - or ( is_string( $ret ) and strtolower( $ret ) == $default )
451 + is_null($ret)
452 + or (is_string($ret) and strtolower($ret)=='default')
757 453 );
758 454
759 - if ( $no_value and ! is_null( $fallback_value ) ) :
455 + if ($no_value and !is_null($fallback_value)) :
760 456 $ret = $fallback_value;
761 457 endif;
762 458 return $ret;
763 - } /* SyndicatedLink::setting() */
459 + } /* SyndicatedLink::setting () */
764 460
765 - /**
766 - * Merge current settings with array of additional data.
767 - *
768 - * @param array $data Settings to merge with.
769 - * @param string $prefix Hierarchical prefix (e.g. "feed/" as in "feed/a/b/c").
770 - * @param string $separator Hierarchy separator (e.g., '/').
771 - *
772 - * @see SyndicatedLink::flatten_array()
773 - */
774 - public function merge_settings( $data, $prefix, $separator = '/' ) {
775 - $dd = $this->flatten_array( $data, $prefix, $separator );
776 - $this->settings = array_merge( $this->settings, $dd );
777 - } /* SyndicatedLink::merge_settings () */
778 -
779 - public function update_setting( $name, $value, $default = 'default' ) {
780 - if ( !is_null( $value ) and $value != $default ) :
781 - $this->settings[ $name ] = $value;
782 - else : // Zap it.
783 - unset( $this->settings[ $name ] );
784 - endif;
785 - } /* SyndicatedLink::update_setting () */
786 -
787 - public function is_non_incremental () {
788 - return ('complete'==$this->setting('update_incremental', 'update_incremental', 'incremental'));
789 - } /* SyndicatedLink::is_non_incremental () */
790 -
791 - public function get_feed_type () {
792 - $type_code = $this->setting('link/feed_type');
793 -
794 - // list derived from: <http://simplepie.org/api/class-SimplePie.html>, retrieved 2020/01/18
795 - $bitmasks = array(
796 - SIMPLEPIE_TYPE_RSS_090 => 'RSS 0.90',
797 - SIMPLEPIE_TYPE_RSS_091_NETSCAPE => 'RSS 0.91 (Netscape)',
798 - SIMPLEPIE_TYPE_RSS_091_USERLAND => 'RSS 0.91 (Userland)',
799 - SIMPLEPIE_TYPE_RSS_091 => 'RSS 0.91',
800 - SIMPLEPIE_TYPE_RSS_092 => 'RSS 0.92',
801 - SIMPLEPIE_TYPE_RSS_093 => 'RSS 0.93',
802 - SIMPLEPIE_TYPE_RSS_094 => 'RSS 0.94',
803 - SIMPLEPIE_TYPE_RSS_10 => 'RSS 1.0',
804 - SIMPLEPIE_TYPE_RSS_20 => 'RSS 2.0.x',
805 - SIMPLEPIE_TYPE_RSS_RDF => 'RDF-based RSS',
806 - SIMPLEPIE_TYPE_RSS_SYNDICATION => 'Non-RDF-based RSS',
807 - SIMPLEPIE_TYPE_RSS_ALL => 'Any version of RSS',
808 - SIMPLEPIE_TYPE_ATOM_03 => 'Atom 0.3',
809 - SIMPLEPIE_TYPE_ATOM_10 => 'Atom 1.0',
810 - SIMPLEPIE_TYPE_ATOM_ALL => 'Atom (any version)',
811 - SIMPLEPIE_TYPE_ALL => 'Supported Feed (unspecified format)',
812 - );
813 -
814 - $type = "Unknown or unsupported format";
815 - foreach ($bitmasks as $format_flag => $format_string) :
816 - if (is_numeric($format_flag)) : // Guard against failure of constants to be defined.
817 - if ($type_code & $format_flag) :
818 - $type = $format_string;
819 - break; // foreach
820 - endif;
821 - endif;
822 - endforeach;
823 -
824 - return $type;
825 - } /* SyndicatedLink::get_feed_type () */
826 -
827 - public function uri ($params = array()) {
828 - $params = wp_parse_args($params, array(
829 - 'add_params' => false,
830 - 'fetch' => false,
831 - ));
832 -
833 - // Initialize $qp (= array for added query parameters, if any)
834 - $qp = array();
835 -
836 - $link_rss = (is_object($this->link) ? $this->link->link_rss : NULL);
837 -
838 - // $link_rss stores the URI for the subscription as stored in the feed's record.
839 - // $uri stores the effective URI of the request including any/all added query parameters
840 - $uri = $link_rss;
841 - if ( !is_null($uri) and strlen($uri) > 0 and $params['add_params']) :
842 - $qp = maybe_unserialize($this->setting('query parameters', array()));
843 -
844 - // For high-tech HTTP feed request kung fu
845 - $qp = apply_filters('syndicated_feed_parameters', $qp, $uri, $this);
846 -
847 - // $qp is an array of key-value pairs stored as arrays of format [$key, $value]
848 - $q = array();
849 - if (is_array($qp) and count($qp) > 0) :
850 - foreach ($qp as $pair) :
851 - $q[] = urlencode($pair[0]).'='.urlencode($pair[1]);
852 - endforeach;
853 -
854 - // Are we appending to a URI that already has params?
855 - $sep = ((strpos($uri, "?")===false) ? '?' : '&');
856 -
857 - // Tack it on
858 - $uri .= $sep . implode("&", $q);
859 - endif;
860 - endif;
861 -
862 - // Do we have any filters that apply here?
863 - $uri = apply_filters('syndicated_link_uri', $uri, $link_rss, $qp, $params, $this);
864 -
865 - // Return the filtered link URI.
866 - return $uri;
461 + function uri () {
462 + return (is_object($this->link) ? $this->link->link_rss : NULL);
867 463 } /* SyndicatedLink::uri () */
868 464
869 - public function username () {
870 - return $this->setting('http username', 'http_username', NULL);
871 - } /* SyndicatedLink::username () */
872 -
873 - public function password () {
874 - return $this->setting('http password', 'http_password', NULL);
875 - } /* SyndicatedLink::password () */
876 -
877 - public function authentication_method () {
878 - // Retrieve the authentication method from settings
879 - $auth = $this->setting( 'http auth method', null );
880 -
881 - // If the value is '-' or empty, treat it as NULL
882 - if ( '-' === $auth || empty( $auth ) ) {
883 - $auth = null;
884 - }
885 -
886 - return $auth;
887 - } /* SyndicatedLink::authentication_method () */
888 -
889 - var $postmeta = array();
890 - public function postmeta ($params = array()) {
891 - $params = wp_parse_args($params, /*defaults=*/ array(
892 - "field" => NULL,
893 - "parsed" => false,
894 - "force" => false,
895 - ));
896 -
897 - if ($params['force'] or !isset($this->postmeta[/*parsed = */ false])) :
898 - // First, get the global settings.
899 - $default_custom_settings = get_option('feedwordpress_custom_settings');
900 - if ($default_custom_settings and !is_array($default_custom_settings)) :
901 - $default_custom_settings = unserialize($default_custom_settings);
902 - endif;
903 - if ( !is_array($default_custom_settings)) :
904 - $default_custom_settings = array();
905 - endif;
906 -
907 - // Next, get the settings for this particular feed.
908 - $custom_settings = $this->setting('postmeta', NULL, NULL);
909 - if ($custom_settings and !is_array($custom_settings)) :
910 - $custom_settings = unserialize($custom_settings);
911 - endif;
912 - if ( !is_array($custom_settings)) :
913 - $custom_settings = array();
914 - endif;
915 -
916 - $this->postmeta[/*parsed=*/ false] = array_merge($default_custom_settings, $custom_settings);
917 - $this->postmeta[/*parsed=*/ true] = array();
918 -
919 - // Now, run through and parse them all.
920 - foreach ($this->postmeta[/*parsed=*/ false] as $key => $meta) :
921 - $meta = apply_filters("syndicated_link_post_meta_{$key}_pre", $meta, $this);
922 - $this->postmeta[/*parsed=*/ false][$key] = $meta;
923 - $this->postmeta[/*parsed=*/ true][$key] = new FeedWordPressParsedPostMeta($meta);
924 - endforeach;
465 + function homepage ($fromFeed = true) {
466 + if ($fromFeed) :
467 + $url = (isset($this->settings['feed/link']) ? $this->settings['feed/link'] : NULL);
468 + else :
469 + $url = $this->link->link_url;
925 470 endif;
471 + return $url;
472 + } /* SyndicatedLink::homepage () */
926 473
927 - $ret = $this->postmeta[!! $params['parsed']];
928 - if (is_string($params['field'])) :
929 - $ret = $ret[$params['field']];
930 - endif;
931 - return $ret;
932 - } /* SyndicatedLink::postmeta () */
933 -
934 - public function property_cascade ($fromFeed, $link_field, $setting, $method) {
935 - $value = NULL;
474 + function name ($fromFeed = true) {
936 475 if ($fromFeed) :
937 - $value = $this->setting($setting, NULL, NULL, NULL);
938 -
939 - $simp_pie = $this->simplepie;
940 - $callable = ( is_object( $simp_pie ) and method_exists( $simp_pie, $method ) );
941 - if ( is_null( $value ) and $callable ) :
942 -// $fallback = $s->{$method}(); // what is fallback supposed to be here? (gwyneth 20230816)
943 - $value = $simp_pie->{$method}(); // makes more sense this way!
944 - endif;
476 + $name = (isset($this->settings['feed/title']) ? $this->settings['feed/title'] : NULL);
945 477 else :
946 - $value = $this->link->{$link_field};
478 + $name = $this->link->link_name;
947 479 endif;
948 - return $value;
949 - } /* SyndicatedLink::property_cascade () */
950 -
951 - public function homepage ($fromFeed = true) {
952 - return $this->property_cascade($fromFeed, 'link_url', 'feed/link', 'get_link');
953 - } /* SyndicatedLink::homepage () */
954 -
955 - public function name ($fromFeed = true) {
956 - return $this->property_cascade($fromFeed, 'link_name', 'feed/title', 'get_title');
480 + return $name;
957 481 } /* SyndicatedLink::name () */
958 482
959 - public function guid () {
960 - $ret = $this->setting('feed/id', NULL, $this->uri());
961 -
962 - // If we can get it live from the feed, do so.
963 - if (is_object($this->simplepie)) :
964 - $search = array(
965 - array('', 'id'),
966 - array(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'),
967 - array(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'),
968 - array(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'),
969 - array(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'),
970 - array(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'),
971 - );
972 -
973 - foreach ($search as $pair) :
974 - if ($id_tags = $this->simplepie->get_feed_tags($pair[0], $pair[1])) :
975 - $ret = $id_tags[0]['data'];
976 - break;
977 - elseif ($id_tags = $this->simplepie->get_channel_tags($pair[0], $pair[1])) :
978 - $ret = $id_tags[0]['data'];
979 - break;
980 - endif;
981 - endforeach;
982 - endif;
983 - return $ret;
984 - }
985 -
986 - public function links ($params = array()) {
987 - $params = wp_parse_args($params, array(
988 - "rel" => NULL,
989 - ));
990 -
991 - $fLinks = array();
992 - $search = array(
993 - array('', 'link'),
994 - array(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'),
995 - array(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'),
996 - );
997 -
998 - foreach ($search as $pair) :
999 - if ($link_tags = $this->simplepie->get_feed_tags($pair[0], $pair[1])) :
1000 - $fLinks = array_merge($fLinks, $link_tags);
1001 - endif;
1002 - if ($link_tags = $this->simplepie->get_channel_tags($pair[0], $pair[1])) :
1003 - $fLinks = array_merge($fLinks, $link_tags);
1004 - endif;
1005 - endforeach;
1006 -
1007 - $ret = array();
1008 - foreach ($fLinks as $link) :
1009 - $filter = false;
1010 - if ( !is_null($params['rel'])) :
1011 - $filter = true;
1012 -
1013 - if (isset($link['attribs'])) :
1014 - // Get a list of NSes from the search
1015 - foreach ($search as $pair) :
1016 - $ns = $pair[0];
1017 -
1018 - if (isset($link['attribs'][$ns])
1019 - and isset($link['attribs'][$ns]['rel'])
1020 - ) :
1021 - $rel = strtolower(trim($link['attribs'][$ns]['rel']));
1022 - $fRel = strtolower(trim($params['rel']));
1023 -
1024 - if ($rel == $fRel) :
1025 - $filter = false;
1026 - endif;
1027 - endif;
1028 - endforeach;
1029 - endif;
1030 - endif;
1031 -
1032 - if ( ! $filter) :
1033 - $ret[] = $link;
1034 - endif;
1035 - endforeach;
1036 -
1037 - return $ret;
1038 - }
1039 -
1040 - public function ttl ($return_element = false) {
483 + function ttl () {
1041 484 if (is_object($this->magpie)) :
1042 485 $channel = $this->magpie->channel;
1043 486 else :
1044 487 $channel = array();
@@ -1047,10 +490,9 @@
1047 490 if (isset($channel['ttl'])) :
1048 491 // "ttl stands for time to live. It's a number of
1049 492 // minutes that indicates how long a channel can be
1050 493 // cached before refreshing from the source."
1051 - // <http://blogs.law.harvard.edu/tech/rss#ltttlgtSubelementOfLtchannelgt>
1052 - $xml = 'rss:ttl';
494 + // <http://blogs.law.harvard.edu/tech/rss#ltttlgtSubelementOfLtchannelgt>
1053 495 $ret = $channel['ttl'];
1054 496 elseif (isset($channel['sy']['updatefrequency']) or isset($channel['sy']['updateperiod'])) :
1055 497 $period_minutes = array (
1056 498 'hourly' => 60, /* minutes in an hour */
@@ -1063,13 +505,13 @@
1063 505 // "sy:updatePeriod: Describes the period over which the
1064 506 // channel format is updated. Acceptable values are:
1065 507 // hourly, daily, weekly, monthly, yearly. If omitted,
1066 508 // daily is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
1067 - if (isset($channel['sy']['updateperiod'])) : $period = trim($channel['sy']['updateperiod']);
509 + if (isset($channel['sy']['updateperiod'])) : $period = $channel['sy']['updateperiod'];
1068 510 else : $period = 'daily';
1069 511 endif;
1070 -
1071 - // "sy:updateFrequency: Used to describe the frequency
512 +
513 + // "sy:updateFrequency: Used to describe the frequency
1072 514 // of updates in relation to the update period. A
1073 515 // positive integer indicates how many times in that
1074 516 // period the channel is updated. ... If omitted a value
1075 517 // of 1 is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
@@ -1075,219 +517,72 @@
1075 517 // of 1 is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
1076 518 if (isset($channel['sy']['updatefrequency'])) : $freq = (int) $channel['sy']['updatefrequency'];
1077 519 else : $freq = 1;
1078 520 endif;
1079 -
1080 - // normalize the period name...
1081 - $period = strtolower(trim($period));
1082 -
1083 - // do we recognize the alphanumeric period name? if not, then guess
1084 - // a responsible default, e.g. roughly hourly
1085 - $mins = (isset($period_minutes[$period]) ? $period_minutes[$period] : 67);
1086 -
1087 - $xml = 'sy:updateFrequency';
1088 - $ret = (int) ($mins / $freq);
1089 -
521 +
522 + $ret = (int) ($period_minutes[$period] / $freq);
1090 523 else :
1091 - $xml = NULL;
1092 524 $ret = NULL;
1093 525 endif;
1094 -
1095 - if ('yes'==$this->setting('update/minimum', 'update_minimum', 'no')) :
1096 - $min = (int) $this->setting('update/window', 'update_window', DEFAULT_UPDATE_PERIOD);
1097 -
1098 - if ($min > $ret) :
1099 - $ret = NULL;
1100 - endif;
1101 - endif;
1102 - return ( $return_element ? array( $ret, $xml ) : $ret );
526 + return $ret;
1103 527 } /* SyndicatedLink::ttl() */
1104 528
1105 - /**
1106 - * Sets the automatic time interval for
1107 - *
1108 - * @return
1109 - */
1110 - public function automatic_ttl() {
1111 - // spread out over a time interval for staggered updates
1112 - $updateWindow = $this->setting( 'update/window', 'update_window', DEFAULT_UPDATE_PERIOD );
1113 - if ( ! is_numeric( $updateWindow ) or ( $updateWindow < 1 ) ) :
1114 - $updateWindow = DEFAULT_UPDATE_PERIOD;
1115 - endif;
1116 -
1117 - // We get a fudge of 1/3 of window from elsewhere. We'll do some more
1118 - // fudging here.
1119 - $fudgedInterval = $updateWindow + rand( - ( $updateWindow / 6 ), 5 * ( $updateWindow / 12 ) );
1120 - return apply_filters( 'syndicated_feed_automatic_ttl', $fudgedInterval, $this );
1121 - } /* SyndicatedLink::automatic_ttl() */
1122 -
1123 - /**
1124 - * SyndicatedLink::flatten_array (): flatten an array. Useful for
1125 - * hierarchical and namespaced elements.
1126 - *
1127 - * Given an array which may contain array or object elements in it,
1128 - * return a "flattened" array: a one-dimensional array of scalars
1129 - * containing each of the scalar elements contained within the array
1130 - * structure. Thus, for example, if $a['b']['c']['d'] == 'e', then the
1131 - * returned array for FeedWordPress::flatten_array($a) will contain a key
1132 - * $a['feed/b/c/d'] with value 'e'.
1133 - *
1134 - * @param array $arr Array to flatten.
1135 - * @param string $prefix Hierarchical prefix (e.g. "feed/" as in "feed/a/b/c").
1136 - * @param string $separator Hierarchy separator (e.g., '/').
1137 - * @return array Flattened one-dimensional array.
1138 - */
1139 - public function flatten_array( $arr, $prefix = 'feed/', $separator = '/' ) {
1140 - $ret = array();
1141 - if ( is_array( $arr ) ) :
1142 - foreach ( $arr as $key => $value ) :
1143 - if ( is_scalar( $value ) ) :
1144 - $ret[ $prefix.$key ] = $value;
529 + // SyndicatedLink::flatten_array (): flatten an array. Useful for
530 + // hierarchical and namespaced elements.
531 + //
532 + // Given an array which may contain array or object elements in it,
533 + // return a "flattened" array: a one-dimensional array of scalars
534 + // containing each of the scalar elements contained within the array
535 + // structure. Thus, for example, if $a['b']['c']['d'] == 'e', then the
536 + // returned array for FeedWordPress::flatten_array($a) will contain a key
537 + // $a['feed/b/c/d'] with value 'e'.
538 + function flatten_array ($arr, $prefix = 'feed/', $separator = '/') {
539 + $ret = array ();
540 + if (is_array($arr)) :
541 + foreach ($arr as $key => $value) :
542 + if (is_scalar($value)) :
543 + $ret[$prefix.$key] = $value;
1145 544 else :
1146 - $ret = array_merge( $ret, $this->flatten_array( $value, $prefix.$key.$separator, $separator ) );
545 + $ret = array_merge($ret, $this->flatten_array($value, $prefix.$key.$separator, $separator));
1147 546 endif;
1148 547 endforeach;
1149 548 endif;
1150 549 return $ret;
1151 - } /* SyndicatedLink::flatten_array() */
550 + } /* SyndicatedLink::flatten_array () */
1152 551
1153 - /**
1154 - * Check if a setting is hardcoded or not.
1155 - *
1156 - * @param string $what The setting we're checking for.
1157 - *
1158 - * @return bool True if the setting's value is 'yes', false otherwise.
1159 - */
1160 - public function hardcode( $what ) {
1161 - return 'yes' == $this->setting( 'hardcode ' . $what, 'hardcode_' . $what, NULL );
1162 - // Simplified logic. (gwyneth 20230920)
552 + function hardcode ($what) {
553 + $default = get_option("feedwordpress_hardcode_$what");
554 + if ( $default === 'yes' ) :
555 + // If the default is to hardcode, then we want the
556 + // negation of negative(): TRUE by default and FALSE if
557 + // the setting is explicitly "no"
558 + $ret = !FeedWordPress::negative($this->settings, "hardcode $what");
559 + else :
560 + // If the default is NOT to hardcode, then we want
561 + // affirmative(): FALSE by default and TRUE if the
562 + // setting is explicitly "yes"
563 + $ret = FeedWordPress::affirmative($this->settings, "hardcode $what");
564 + endif;
565 + return $ret;
1163 566 } /* SyndicatedLink::hardcode () */
1164 567
1165 - /**
1166 - * Returns the syndicated status for one item.
1167 - *
1168 - * @param string $what Item's name.
1169 - * @param mixed $default Default value for this item.
1170 - * @param boolean $fallback If true, falls back to global setting.
1171 - *
1172 - * @return string SQL-ready escaped status.
1173 - */
1174 - public function syndicated_status( $what, $default, $fallback = true ) {
1175 - $g_set = ( $fallback ? 'syndicated_' . $what . '_status' : NULL );
1176 - $ret = $this->setting( $what . ' status', $g_set, $default );
568 + function syndicated_status ($what, $default, $fallback = true) {
569 + global $wpdb;
1177 570
1178 - return esc_sql( trim( strtolower( $ret ) ) );
1179 - } /* SyndicatedLink:syndicated_status () */
571 + // Use local setting if we have it
572 + if ( isset($this->settings["$what status"]) ) :
573 + $ret = $this->settings["$what status"];
574 +
575 + // Or fall back to global default if we can
576 + elseif ($fallback) :
577 + $ret = FeedWordPress::syndicated_status($what, $default);
1180 578
1181 - public function taxonomies () {
1182 - $post_type = $this->setting('syndicated post type', 'syndicated_post_type', 'post');
1183 - return get_object_taxonomies(array('object_type' => $post_type), 'names');
1184 - } /* SyndicatedLink::taxonomies () */
579 + // Or use default value if we can't.
580 + else :
581 + $ret = $default;
1185 582
1186 - /**
1187 - * category_ids: look up (and create) category ids from a list of
1188 - * categories
1189 - *
1190 - * @param array $cats
1191 - * @param string $unfamiliar_category
1192 - * @param array|null $taxonomies
1193 - * @return array
1194 - */
1195 - public function category_ids ($post, $cats, $unfamiliar_category = 'create', $taxonomies = NULL, $params = array()) {
1196 - $singleton = (isset($params['singleton']) ? $params['singleton'] : true);
1197 - $allowFilters = (isset($params['filters']) ? $params['filters'] : false);
1198 -
1199 - $catTax = 'category';
1200 -
1201 - if (is_null($taxonomies)) :
1202 - $taxonomies = array('category');
1203 583 endif;
1204 584
1205 - // We need to normalize whitespace because (1) trailing
1206 - // whitespace can cause PHP and MySQL not to see eye to eye on
1207 - // VARCHAR comparisons for some versions of MySQL (cf.
1208 - // <http://dev.mysql.com/doc/mysql/en/char.html>), and (2)
1209 - // because I doubt most people want to make a semantic
1210 - // distinction between 'Computers' and 'Computers '
1211 - $cats = array_map('trim', $cats);
1212 -
1213 - $terms = array();
1214 - foreach ($taxonomies as $tax) :
1215 - $terms[$tax] = array();
1216 - endforeach;
1217 -
1218 - foreach ($cats as $cat_name) :
1219 - if (strlen(trim($cat_name)) < 1) :
1220 - continue;
1221 - endif;
1222 -
1223 - $oTerm = new SyndicatedPostTerm($cat_name, $taxonomies, $post);
1224 -
1225 - if ($oTerm->is_familiar()) :
1226 -
1227 - $tax = $oTerm->taxonomy();
1228 - if ( !isset($terms[$tax])) :
1229 - $terms[$tax] = array();
1230 - endif;
1231 - $terms[$tax][] = $oTerm->id();
1232 -
1233 - else :
1234 -
1235 - if ('tag'==$unfamiliar_category) :
1236 - $unfamiliar_category = 'create:post_tag';
1237 - endif;
1238 -
1239 - if (preg_match('/^create(:(.*))?$/i', $unfamiliar_category, $ref)) :
1240 - $tax = $catTax; // Default
1241 -
1242 - if (isset($ref[2])
1243 - and strlen($ref[2]) > 2) :
1244 - $tax = $ref[2];
1245 - endif;
1246 -
1247 - $inserted = $oTerm->insert($tax);
1248 - if ( !is_null($inserted)) :
1249 - if ( !isset($terms[$tax])) :
1250 - $terms[$tax] = array();
1251 - endif;
1252 - $terms[$tax][] = $inserted;
1253 - else :
1254 -
1255 - endif; // !is_null($inserted)
1256 - endif; // preg_match(...)
1257 -
1258 - endif; /* ($oTerm->is_familiar()) */
1259 - endforeach;
1260 -
1261 - $filtersOn = $allowFilters;
1262 - if ($allowFilters) :
1263 - $filters = array_filter(
1264 - $this->setting('match/filter', 'match_filter', array()),
1265 - 'remove_dummy_zero'
1266 - );
1267 - $filtersOn = ($filtersOn and is_array($filters) and (count($filters) > 0));
1268 - endif;
1269 -
1270 - // Check for filter conditions
1271 - foreach ($terms as $tax => $term_ids) :
1272 - if ($filtersOn
1273 - and (count($term_ids)==0)
1274 - and in_array($tax, $filters)) :
1275 - $terms = NULL; // Drop the post
1276 - break;
1277 - else :
1278 - $terms[$tax] = array_unique($term_ids);
1279 - endif;
1280 - endforeach;
1281 -
1282 - if ($singleton and count($terms)==1) : // If we only searched one, just return the term IDs
1283 - $terms = end($terms);
1284 - endif;
1285 -
1286 - FeedWordPress::diagnostic(
1287 - 'syndicated_posts:categories',
1288 - 'Category: MAPPED term names '.json_encode($cats).' to IDs: '.json_encode($terms)
1289 - );
1290 - return $terms;
1291 - } /* SyndicatedLink::category_ids () */
1292 -} /* class SyndicatedLink */
585 + return $wpdb->escape(trim(strtolower($ret)));
586 + } /* SyndicatedLink:syndicated_status () */
587 +} // class SyndicatedLink
1293 588