PluginProbe
FeedWordPress / 2011.0706
FeedWordPress v2011.0706
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 +348 -846 trunk2011.0706 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,76 +32,173 @@
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 + // Simple lists
105 + foreach ($this->imploded_settings() as $what) :
106 + if (isset($this->settings[$what])):
107 + $this->settings[$what] = explode(
108 + FEEDWORDPRESS_CAT_SEPARATOR,
109 + $this->settings[$what]
110 + );
111 + endif;
112 + endforeach;
113 +
114 + if (isset($this->settings['terms'])) :
115 + // Look for new format
116 + $this->settings['terms'] = maybe_unserialize($this->settings['terms']);
117 +
118 + if (!is_array($this->settings['terms'])) :
119 + // Deal with old format instead. Ugh.
120 +
121 + // Split on two *or more* consecutive breaks
122 + // because in the old format, a taxonomy
123 + // without any associated terms would
124 + // produce tax_name#1\n\n\ntax_name#2\nterm,
125 + // and the naive split on the first \n\n
126 + // would screw up the tax_name#2 list.
127 + //
128 + // Props to David Morris for pointing this
129 + // out.
130 +
131 + $this->settings['terms'] = preg_split(
132 + "/".FEEDWORDPRESS_CAT_SEPARATOR."{2,}/",
133 + $this->settings['terms']
134 + );
135 + $terms = array();
136 + foreach ($this->settings['terms'] as $line) :
137 + $line = explode(FEEDWORDPRESS_CAT_SEPARATOR, $line);
138 + $tax = array_shift($line);
139 + $terms[$tax] = $line;
140 + endforeach;
141 + $this->settings['terms'] = $terms;
142 + endif;
143 + endif;
144 +
145 + if (isset($this->settings['map authors'])) :
146 + $author_rules = explode("\n\n", $this->settings['map authors']);
147 + $ma = array();
148 + foreach ($author_rules as $rule) :
149 + list($rule_type, $author_name, $author_action) = explode("\n", $rule);
150 +
151 + // Normalize for case and whitespace
152 + $rule_type = strtolower(trim($rule_type));
153 + $author_name = strtolower(trim($author_name));
154 + $author_action = strtolower(trim($author_action));
155 +
156 + $ma[$rule_type][$author_name] = $author_action;
157 + endforeach;
158 + $this->settings['map authors'] = $ma;
159 + endif;
160 + endif;
161 + } /* SyndicatedLink::SyndicatedLink () */
162 +
163 + function found () {
65 164 return is_object($this->link) and !is_wp_error($this->link);
66 165 } /* SyndicatedLink::found () */
67 166
68 - public function id () {
69 - return (is_object($this->link) ? $this->link->link_id : NULL);
70 - }
71 -
72 - public function stale () {
167 + function stale () {
73 168 global $feedwordpress;
74 -
169 +
75 170 $stale = true;
76 - if ($this->setting('update/hold')=='ping') :
171 + if (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='ping')) :
77 172 $stale = false; // don't update on any timed updates; pings only
78 - elseif ($this->setting('update/hold')=='next') :
173 + elseif (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='next')) :
79 174 $stale = true; // update on the next timed update
80 - elseif ( ! $this->setting('update/last') ) :
175 + elseif (!isset($this->settings['update/ttl']) or !isset($this->settings['update/last'])) :
81 176 $stale = true; // initial update
82 - elseif ( !empty($feedwordpress) and $feedwordpress->force_update_all()) :
177 + elseif ($feedwordpress->force_update_all()) :
83 178 $stale = true; // forced general updating
84 179 else :
85 - $after = (
86 - (int) $this->setting('update/last')
87 - + (int) $this->setting('update/fudge')
88 - + ((int) $this->setting('update/ttl') * 60)
89 - );
180 + $after = ((int) $this->settings['update/last'])
181 + +((int) $this->settings['update/ttl'] * 60);
90 182 $stale = (time() >= $after);
91 183 endif;
92 184 return $stale;
93 185 } /* SyndicatedLink::stale () */
94 186
95 - public function fetch () {
187 + function poll ($crash_ts = NULL) {
188 + global $wpdb;
189 +
190 + $url = $this->uri(array('add_params' => true));
191 + FeedWordPress::diagnostic('updated_feeds', 'Polling feed ['.$url.']');
192 +
96 193 $timeout = $this->setting('fetch timeout', 'feedwordpress_fetch_timeout', FEEDWORDPRESS_FETCH_TIMEOUT_DEFAULT);
97 194
98 195 $this->simplepie = apply_filters(
99 196 'syndicated_feed',
100 - FeedWordPress::fetch($this, array('timeout' => $timeout)),
197 + FeedWordPress::fetch($url, array('timeout' => $timeout)),
101 198 $this
102 199 );
103 -
200 +
104 201 // Filter compatibility mode
105 202 if (is_wp_error($this->simplepie)) :
106 203 $this->magpie = $this->simplepie;
107 204 else :
@@ -106,45 +203,15 @@
106 203 $this->magpie = $this->simplepie;
107 204 else :
108 205 $this->magpie = new MagpieFromSimplePie($this->simplepie, NULL);
109 206 endif;
110 - } /* SyndicatedLink::fetch () */
111 207
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 208 $new_count = NULL;
142 209
143 - $resume = ('yes'==$this->setting('update/unfinished'));
210 + $resume = FeedWordPress::affirmative($this->settings, 'update/unfinished');
144 211 if ($resume) :
145 212 // pick up where we left off
146 - $processed = array_map('trim', explode("\n", $this->setting('update/processed')));
213 + $processed = array_map('trim', explode("\n", $this->settings['update/processed']));
147 214 else :
148 215 // begin at the beginning
149 216 $processed = array();
150 217 endif;
@@ -161,76 +228,81 @@
161 228 if (is_string($oldError)) :
162 229 $oldError = unserialize($oldError);
163 230 endif;
164 231
165 - if ( !is_null($oldError)) :
232 + if (!is_null($oldError)) :
166 233 // Copy over the in-error-since timestamp
167 234 $theError['since'] = $oldError['since'];
235 +
236 + // If this is a repeat error, then we should take
237 + // a step back before we try to fetch it again.
238 + $this->settings['update/last'] = time();
239 + $this->settings['update/ttl'] = $this->automatic_ttl();
240 + $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl', $this->settings['update/ttl'], $this);
241 + $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl_from_error', $this->settings['update/ttl'], $this);
168 242
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');
243 + $this->settings['update/timed'] = 'automatically';
178 244 endif;
179 -
245 +
180 246 do_action('syndicated_feed_error', $theError, $oldError, $this);
181 -
182 - $this->update_setting('update/error', serialize($theError));
247 +
248 + $this->settings['update/error'] = serialize($theError);
183 249 $this->save_settings(/*reload=*/ true);
184 250
185 251 elseif (is_object($this->simplepie)) :
186 -
187 252 // Success; clear out error setting, if any.
188 - $this->update_setting('update/error', NULL);
253 + if (isset($this->settings['update/error'])) :
254 + unset($this->settings['update/error']);
255 + endif;
189 256
190 - $new_count = array('new' => 0, 'updated' => 0, 'stored' => 0);
257 + $new_count = array('new' => 0, 'updated' => 0);
191 258
192 259 # -- Update Link metadata live from feed
193 260 $channel = $this->magpie->channel;
194 261
195 - if ( !isset($channel['id'])) :
262 + if (!isset($channel['id'])) :
196 263 $channel['id'] = $this->link->link_rss;
197 264 endif;
198 -
265 +
199 266 $update = array();
200 - if ( ! $this->hardcode('url') and isset($channel['link'])) :
201 - $update[] = "link_url = '".esc_sql($channel['link'])."'";
267 + if (!$this->hardcode('url') and isset($channel['link'])) :
268 + $update[] = "link_url = '".$wpdb->escape($channel['link'])."'";
202 269 endif;
203 -
204 - if ( ! $this->hardcode('name') and isset($channel['title'])) :
205 - $update[] = "link_name = '".esc_sql($channel['title'])."'";
270 +
271 + if (!$this->hardcode('name') and isset($channel['title'])) :
272 + $update[] = "link_name = '".$wpdb->escape($channel['title'])."'";
206 273 endif;
207 -
208 - if ( ! $this->hardcode('description')) :
274 +
275 + if (!$this->hardcode('description')) :
209 276 if (isset($channel['tagline'])) :
210 - $update[] = "link_description = '".esc_sql($channel['tagline'])."'";
277 + $update[] = "link_description = '".$wpdb->escape($channel['tagline'])."'";
211 278 elseif (isset($channel['description'])) :
212 - $update[] = "link_description = '".esc_sql($channel['description'])."'";
279 + $update[] = "link_description = '".$wpdb->escape($channel['description'])."'";
213 280 endif;
214 281 endif;
282 +
283 + $this->settings = array_merge($this->settings, $this->flatten_array($channel));
215 284
216 - $this->update_setting('link/feed_type', $this->simplepie->get_type());
285 + $this->settings['update/last'] = time(); $ttl = $this->ttl();
286 + if (!is_null($ttl)) :
287 + $this->settings['update/ttl'] = $ttl;
288 + $this->settings['update/timed'] = 'feed';
289 + else :
290 + $this->settings['update/ttl'] = $this->automatic_ttl();
291 + $this->settings['update/timed'] = 'automatically';
292 + endif;
293 + $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl', $this->settings['update/ttl'], $this);
217 294
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');
295 + if (!isset($this->settings['update/hold']) or $this->settings['update/hold']!='ping') :
296 + $this->settings['update/hold'] = 'scheduled';
225 297 endif;
226 298
227 - $this->update_setting('update/unfinished', 'yes');
299 + $this->settings['update/unfinished'] = 'yes';
228 300
229 - $update[] = "link_notes = '".esc_sql($this->settings_to_notes())."'";
301 + $update[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
230 302
231 303 $update_set = implode(',', $update);
232 -
304 +
233 305 // Update the properties of the link from the feed information
234 306 $result = $wpdb->query("
235 307 UPDATE $wpdb->links
236 308 SET $update_set
@@ -240,115 +312,62 @@
240 312
241 313 # -- Add new posts from feed and update any updated posts
242 314 $crashed = false;
243 315
244 - $posts = $this->live_posts();
316 + $posts = apply_filters(
317 + 'syndicated_feed_items',
318 + $this->simplepie->get_items(),
319 + &$this
320 + );
245 321
246 322 $this->magpie->originals = $posts;
247 323
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 -
263 324 if (is_array($posts)) :
264 325 foreach ($posts as $key => $item) :
265 - if ( ! $this->pause_updates()) :
266 - $post = new SyndicatedPost($item, $this);
326 + $post = new SyndicatedPost($item, $this);
267 327
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;
328 + if (!$resume or !in_array(trim($post->guid()), $processed)) :
329 + $processed[] = $post->guid();
330 + if (!$post->filtered()) :
331 + $new = $post->store();
332 + if ( $new !== false ) $new_count[$new]++;
333 + endif;
274 334
275 - if ( !is_null($crash_ts) and (time() > $crash_ts)) :
276 - $crashed = true;
277 - break;
278 - endif;
335 + if (!is_null($crash_ts) and (time() > $crash_ts)) :
336 + $crashed = true;
337 + break;
279 338 endif;
280 -
281 - unset($post);
282 339 endif;
340 + unset($post);
283 341 endforeach;
284 342 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 343 $suffix = ($crashed ? 'crashed' : 'completed');
319 344 do_action('update_syndicated_feed_items', $this->id, $this);
320 - do_action("update_syndicated_feed_items_{$suffix}", $this->id, $this);
345 + do_action("update_syndicated_feed_items_${suffix}", $this->id, $this);
321 346
322 - $this->update_setting('update/processed', $processed);
323 - if ( ! $crashed) :
324 - $this->update_setting('update/unfinished', 'no');
347 + // Copy back any changes to feed settings made in the course of updating (e.g. new author rules)
348 + $to_notes = $this->settings;
349 +
350 + $this->settings['update/processed'] = $processed;
351 + if (!$crashed) :
352 + $this->settings['update/unfinished'] = 'no';
325 353 endif;
326 - $this->update_setting('link/item count', count($posts));
327 354
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 -
355 + $update_set = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
356 +
332 357 // Update the properties of the link from the feed information
333 358 $result = $wpdb->query("
334 - UPDATE {$wpdb->links}
335 - SET {$update_set}
336 - WHERE link_id='{$this->id}'
359 + UPDATE $wpdb->links
360 + SET $update_set
361 + WHERE link_id='$this->id'
337 362 ");
338 - if ( FALSE === $result ) :
339 - FeedWordPress::diagnostic(
340 - 'SyndicatedLink/poll',
341 - 'Database update failed',
342 - );
343 - endif;
344 -
363 +
345 364 do_action("update_syndicated_feed_completed", $this->id, $this);
346 365 endif;
347 -
366 +
348 367 // All done; let's clean up.
349 368 $this->magpie = NULL;
350 -
369 +
351 370 // Avoid circular-reference memory leak in PHP < 5.3.
352 371 // Cf. <http://simplepie.org/wiki/faq/i_m_getting_memory_leaks>
353 372 if (method_exists($this->simplepie, '__destruct')) :
354 373 $this->simplepie->__destruct();
@@ -353,74 +372,19 @@
353 372 if (method_exists($this->simplepie, '__destruct')) :
354 373 $this->simplepie->__destruct();
355 374 endif;
356 375 $this->simplepie = NULL;
357 -
376 +
358 377 return $new_count;
359 378 } /* SyndicatedLink::poll() */
360 379
361 380 /**
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 381 * Updates the URL for the feed syndicated by this link.
418 382 *
419 383 * @param string $url The new feed URL to use for this source.
420 384 * @return bool TRUE on success, FALSE on failure.
421 385 */
422 - public function set_uri ($url) {
386 + function set_uri ($url) {
423 387 global $wpdb;
424 388
425 389 if ($this->found()) :
426 390 // Update link_rss
@@ -426,12 +390,12 @@
426 390 // Update link_rss
427 391 $result = $wpdb->query("
428 392 UPDATE $wpdb->links
429 393 SET
430 - link_rss = '".esc_sql($url)."'
431 - WHERE link_id = '".esc_sql($this->id)."'
394 + link_rss = '".$wpdb->escape($url)."'
395 + WHERE link_id = '".$wpdb->escape($this->id)."'
432 396 ");
433 -
397 +
434 398 $ret = ($result ? true : false);
435 399 else :
436 400 $ret = false;
437 401 endif;
@@ -436,55 +400,35 @@
436 400 $ret = false;
437 401 endif;
438 402 return $ret;
439 403 } /* SyndicatedLink::set_uri () */
440 -
441 - public function deactivate () {
404 +
405 + function deactivate () {
442 406 global $wpdb;
443 -
407 +
444 408 $wpdb->query($wpdb->prepare("
445 409 UPDATE $wpdb->links SET link_visible = 'N' WHERE link_id = %d
446 410 ", (int) $this->id));
447 411 } /* 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 () {
412 +
413 + function delete () {
461 414 global $wpdb;
462 -
415 +
463 416 $wpdb->query($wpdb->prepare("
464 417 DELETE FROM $wpdb->postmeta WHERE meta_key='syndication_feed_id'
465 418 AND meta_value = '%s'
466 419 ", $this->id));
467 -
420 +
468 421 $wpdb->query($wpdb->prepare("
469 422 DELETE FROM $wpdb->links WHERE link_id = %d
470 423 ", (int) $this->id));
471 -
424 +
472 425 $this->id = NULL;
473 426 } /* 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 () {
427 +
428 + function nuke () {
485 429 global $wpdb;
486 -
430 +
487 431 // Make a list of the items syndicated from this feed...
488 432 $post_ids = $wpdb->get_col($wpdb->prepare("
489 433 SELECT post_id FROM $wpdb->postmeta
490 434 WHERE meta_key = 'syndication_feed_id'
@@ -489,9 +433,9 @@
489 433 SELECT post_id FROM $wpdb->postmeta
490 434 WHERE meta_key = 'syndication_feed_id'
491 435 AND meta_value = '%s'
492 436 ", $this->id));
493 -
437 +
494 438 // ... and kill them all
495 439 if (count($post_ids) > 0) :
496 440 foreach ($post_ids as $post_id) :
497 441 // Force scrubbing of deleted post
@@ -501,13 +445,13 @@
501 445 /*force_delete=*/ true
502 446 );
503 447 endforeach;
504 448 endif;
505 -
449 +
506 450 $this->delete();
507 451 } /* SyndicatedLink::nuke () */
508 -
509 - public function map_name_to_new_user ($name, $newuser_name) {
452 +
453 + function map_name_to_new_user ($name, $newuser_name) {
510 454 global $wpdb;
511 455
512 456 if (strlen($newuser_name) > 0) :
513 457 $newuser_id = fwp_insert_new_user($newuser_name);
@@ -512,13 +456,11 @@
512 456 if (strlen($newuser_name) > 0) :
513 457 $newuser_id = fwp_insert_new_user($newuser_name);
514 458 if (is_numeric($newuser_id)) :
515 459 if (is_null($name)) : // Unfamiliar author
516 - $this->update_setting('unfamiliar author', $newuser_id);
460 + $this->settings['unfamiliar author'] = $newuser_id;
517 461 else :
518 - $map = $this->setting('map authors');
519 - $map['name'][$name] = $newuser_id;
520 - $this->update_setting('map authors', $map);
462 + $this->settings['map authors']['name'][$name] = $newuser_id;
521 463 endif;
522 464 else :
523 465 // TODO: Add some error detection and reporting
524 466 endif;
@@ -526,115 +468,12 @@
526 468 // TODO: Add some error reporting
527 469 endif;
528 470 } /* SyndicatedLink::map_name_to_new_user () */
529 471
530 - protected function imploded_settings () {
472 + function imploded_settings () {
531 473 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 () {
474 + }
475 + function settings_to_notes () {
637 476 $to_notes = $this->settings;
638 477
639 478 unset($to_notes['link/id']); // Magic setting; don't save
640 479 unset($to_notes['link/uri']); // Magic setting; don't save
@@ -654,14 +493,14 @@
654 493 $to_notes[$what]
655 494 );
656 495 endif;
657 496 endforeach;
658 -
497 +
659 498 if (isset($to_notes['terms']) and is_array($to_notes['terms'])) :
660 499 // Serialize it.
661 500 $to_notes['terms'] = serialize($to_notes['terms']);
662 501 endif;
663 -
502 +
664 503 // Collapse the author mapping rule structure back into a flat string
665 504 if (isset($to_notes['map authors'])) :
666 505 $ma = array();
667 506 foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
@@ -678,18 +517,18 @@
678 517 endforeach;
679 518 return $notes;
680 519 } /* SyndicatedLink::settings_to_notes () */
681 520
682 - public function save_settings ($reload = false) {
521 + function save_settings ($reload = false) {
683 522 global $wpdb;
684 523
685 524 // Save channel-level meta-data
686 525 foreach (array('link_name', 'link_description', 'link_url') as $what) :
687 - $alter[] = "{$what} = '".esc_sql($this->link->{$what})."'";
526 + $alter[] = "{$what} = '".$wpdb->escape($this->link->{$what})."'";
688 527 endforeach;
689 528
690 529 // Save settings to the notes field
691 - $alter[] = "link_notes = '".esc_sql($this->settings_to_notes())."'";
530 + $alter[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
692 531
693 532 // Update the properties of the link from settings changes, etc.
694 533 $update_set = implode(", ", $alter);
695 534
@@ -697,14 +536,9 @@
697 536 UPDATE $wpdb->links
698 537 SET $update_set
699 538 WHERE link_id='$this->id'
700 539 ");
701 -
702 - if ( $result === false )
703 - {
704 - error_log("query failed: " . $wpdb->last_error);
705 - }
706 -
540 +
707 541 if ($reload) :
708 542 // force reload of link information from DB
709 543 if (function_exists('clean_bookmark_cache')) :
710 544 clean_bookmark_cache($this->id);
@@ -715,233 +549,87 @@
715 549 /**
716 550 * Retrieves the value of a setting, allowing for a global setting to be
717 551 * used as a fallback, or a constant value, or both.
718 552 *
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!!
553 + * @param string $name The link setting key
554 + * @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.
555 + * @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.
556 + * @return bool TRUE on success, FALSE on failure.
728 557 */
729 - public function setting( $name, $fallback_global = NULL, $fallback_value = NULL, $default = 'default' ) {
558 + function setting ($name, $fallback_global = NULL, $fallback_value = NULL, $default = 'default') {
730 559 $ret = NULL;
731 - if ( isset( $this->settings[ $name ] ) ) :
732 - $ret = $this->settings[ $name ];
560 + if (isset($this->settings[$name])) :
561 + $ret = $this->settings[$name];
733 562 endif;
734 -
563 +
735 564 $no_value = (
736 - is_null( $ret )
737 - or ( is_string( $ret ) and strtolower( $ret ) == $default )
565 + is_null($ret)
566 + or (is_string($ret) and strtolower($ret)==$default)
738 567 );
739 568
740 - if ( $no_value and ! is_null( $fallback_global ) ) :
569 + if ($no_value and !is_null($fallback_global)) :
741 570 // 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;
571 + $fallback_global = preg_replace('/^feedwordpress_/', '', $fallback_global);
572 +
573 + $ret = get_option('feedwordpress_'.$fallback_global, /*default=*/ NULL);
752 574 endif;
753 575
754 576 $no_value = (
755 - is_null( $ret )
756 - or ( is_string( $ret ) and strtolower( $ret ) == $default )
577 + is_null($ret)
578 + or (is_string($ret) and strtolower($ret)==$default)
757 579 );
758 580
759 - if ( $no_value and ! is_null( $fallback_value ) ) :
581 + if ($no_value and !is_null($fallback_value)) :
760 582 $ret = $fallback_value;
761 583 endif;
762 584 return $ret;
763 - } /* SyndicatedLink::setting() */
585 + } /* SyndicatedLink::setting () */
764 586
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;
587 + function update_setting ($name, $value, $default = 'default') {
588 + if (!is_null($value) and $value != $default) :
589 + $this->settings[$name] = $value;
782 590 else : // Zap it.
783 - unset( $this->settings[ $name ] );
591 + unset($this->settings[$name]);
784 592 endif;
785 593 } /* 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(
594 +
595 + function uri ($params = array()) {
596 + $params = shortcode_atts(array(
829 597 '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']) :
598 + ), $params);
599 +
600 + $uri = (is_object($this->link) ? $this->link->link_rss : NULL);
601 + if (!is_null($uri) and strlen($uri) > 0 and $params['add_params']) :
842 602 $qp = maybe_unserialize($this->setting('query parameters', array()));
843 -
603 +
844 604 // For high-tech HTTP feed request kung fu
845 605 $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]
606 +
848 607 $q = array();
849 608 if (is_array($qp) and count($qp) > 0) :
850 609 foreach ($qp as $pair) :
851 610 $q[] = urlencode($pair[0]).'='.urlencode($pair[1]);
852 611 endforeach;
853 -
612 +
854 613 // Are we appending to a URI that already has params?
855 - $sep = ((strpos($uri, "?")===false) ? '?' : '&');
856 -
614 + $sep = ((strpos('?', $uri)===false) ? '?' : '&');
615 +
857 616 // Tack it on
858 617 $uri .= $sep . implode("&", $q);
859 618 endif;
860 619 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.
620 +
866 621 return $uri;
867 622 } /* SyndicatedLink::uri () */
868 623
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;
925 - endif;
926 -
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) {
624 + function property_cascade ($fromFeed, $link_field, $setting, $simplepie_method) {
935 625 $value = NULL;
936 626 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!
627 + if (isset($this->settings[$setting])) :
628 + $value = $this->settings[$setting];
629 + elseif (is_object($this->simplepie)
630 + and method_exists($this->simplepie, $simplepie_method)) :
631 + $value = $this->simplepie->{$simplepie_method}();
944 632 endif;
945 633 else :
946 634 $value = $this->link->{$link_field};
947 635 endif;
@@ -946,24 +634,23 @@
946 634 $value = $this->link->{$link_field};
947 635 endif;
948 636 return $value;
949 637 } /* SyndicatedLink::property_cascade () */
950 -
951 - public function homepage ($fromFeed = true) {
638 +
639 + function homepage ($fromFeed = true) {
952 640 return $this->property_cascade($fromFeed, 'link_url', 'feed/link', 'get_link');
953 641 } /* SyndicatedLink::homepage () */
954 642
955 - public function name ($fromFeed = true) {
643 + function name ($fromFeed = true) {
956 644 return $this->property_cascade($fromFeed, 'link_name', 'feed/title', 'get_title');
957 645 } /* SyndicatedLink::name () */
958 646
959 - public function guid () {
647 + function guid () {
960 648 $ret = $this->setting('feed/id', NULL, $this->uri());
961 -
649 +
962 650 // If we can get it live from the feed, do so.
963 651 if (is_object($this->simplepie)) :
964 652 $search = array(
965 - array('', 'id'),
966 653 array(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'),
967 654 array(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'),
968 655 array(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'),
969 656 array(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'),
@@ -968,9 +655,9 @@
968 655 array(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'),
969 656 array(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'),
970 657 array(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'),
971 658 );
972 -
659 +
973 660 foreach ($search as $pair) :
974 661 if ($id_tags = $this->simplepie->get_feed_tags($pair[0], $pair[1])) :
975 662 $ret = $id_tags[0]['data'];
976 663 break;
@@ -982,63 +669,9 @@
982 669 endif;
983 670 return $ret;
984 671 }
985 672
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) {
673 + function ttl () {
1041 674 if (is_object($this->magpie)) :
1042 675 $channel = $this->magpie->channel;
1043 676 else :
1044 677 $channel = array();
@@ -1047,10 +680,9 @@
1047 680 if (isset($channel['ttl'])) :
1048 681 // "ttl stands for time to live. It's a number of
1049 682 // minutes that indicates how long a channel can be
1050 683 // cached before refreshing from the source."
1051 - // <http://blogs.law.harvard.edu/tech/rss#ltttlgtSubelementOfLtchannelgt>
1052 - $xml = 'rss:ttl';
684 + // <http://blogs.law.harvard.edu/tech/rss#ltttlgtSubelementOfLtchannelgt>
1053 685 $ret = $channel['ttl'];
1054 686 elseif (isset($channel['sy']['updatefrequency']) or isset($channel['sy']['updateperiod'])) :
1055 687 $period_minutes = array (
1056 688 'hourly' => 60, /* minutes in an hour */
@@ -1063,13 +695,13 @@
1063 695 // "sy:updatePeriod: Describes the period over which the
1064 696 // channel format is updated. Acceptable values are:
1065 697 // hourly, daily, weekly, monthly, yearly. If omitted,
1066 698 // daily is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
1067 - if (isset($channel['sy']['updateperiod'])) : $period = trim($channel['sy']['updateperiod']);
699 + if (isset($channel['sy']['updateperiod'])) : $period = $channel['sy']['updateperiod'];
1068 700 else : $period = 'daily';
1069 701 endif;
1070 -
1071 - // "sy:updateFrequency: Used to describe the frequency
702 +
703 + // "sy:updateFrequency: Used to describe the frequency
1072 704 // of updates in relation to the update period. A
1073 705 // positive integer indicates how many times in that
1074 706 // period the channel is updated. ... If omitted a value
1075 707 // of 1 is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
@@ -1075,219 +707,89 @@
1075 707 // of 1 is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
1076 708 if (isset($channel['sy']['updatefrequency'])) : $freq = (int) $channel['sy']['updatefrequency'];
1077 709 else : $freq = 1;
1078 710 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 -
711 +
712 + $ret = (int) ($period_minutes[$period] / $freq);
1090 713 else :
1091 - $xml = NULL;
1092 714 $ret = NULL;
1093 715 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 );
716 + return $ret;
1103 717 } /* SyndicatedLink::ttl() */
1104 718
1105 - /**
1106 - * Sets the automatic time interval for
1107 - *
1108 - * @return
1109 - */
1110 - public function automatic_ttl() {
719 + function automatic_ttl () {
1111 720 // 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 ) ) :
721 + $updateWindow = $this->setting('update/window', 'update_window', DEFAULT_UPDATE_PERIOD);
722 + if (!is_numeric($updateWindow) or ($updateWindow < 1)) :
1114 723 $updateWindow = DEFAULT_UPDATE_PERIOD;
1115 724 endif;
1116 725
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() */
726 + $fudgedInterval = $updateWindow+rand(0, 2*($updateWindow/3));
727 + return apply_filters('syndicated_feed_automatic_ttl', $fudgedInterval, $this);
728 + } /* SyndicatedLink::automatic_ttl () */
1122 729
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;
730 + // SyndicatedLink::flatten_array (): flatten an array. Useful for
731 + // hierarchical and namespaced elements.
732 + //
733 + // Given an array which may contain array or object elements in it,
734 + // return a "flattened" array: a one-dimensional array of scalars
735 + // containing each of the scalar elements contained within the array
736 + // structure. Thus, for example, if $a['b']['c']['d'] == 'e', then the
737 + // returned array for FeedWordPress::flatten_array($a) will contain a key
738 + // $a['feed/b/c/d'] with value 'e'.
739 + function flatten_array ($arr, $prefix = 'feed/', $separator = '/') {
740 + $ret = array ();
741 + if (is_array($arr)) :
742 + foreach ($arr as $key => $value) :
743 + if (is_scalar($value)) :
744 + $ret[$prefix.$key] = $value;
1145 745 else :
1146 - $ret = array_merge( $ret, $this->flatten_array( $value, $prefix.$key.$separator, $separator ) );
746 + $ret = array_merge($ret, $this->flatten_array($value, $prefix.$key.$separator, $separator));
1147 747 endif;
1148 748 endforeach;
1149 749 endif;
1150 750 return $ret;
1151 - } /* SyndicatedLink::flatten_array() */
751 + } /* SyndicatedLink::flatten_array () */
1152 752
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)
753 + function hardcode ($what) {
754 + $default = get_option("feedwordpress_hardcode_$what");
755 + if ( $default === 'yes' ) :
756 + // If the default is to hardcode, then we want the
757 + // negation of negative(): TRUE by default and FALSE if
758 + // the setting is explicitly "no"
759 + $ret = !FeedWordPress::negative($this->settings, "hardcode $what");
760 + else :
761 + // If the default is NOT to hardcode, then we want
762 + // affirmative(): FALSE by default and TRUE if the
763 + // setting is explicitly "yes"
764 + $ret = FeedWordPress::affirmative($this->settings, "hardcode $what");
765 + endif;
766 + return $ret;
1163 767 } /* SyndicatedLink::hardcode () */
1164 768
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 );
769 + function syndicated_status ($what, $default, $fallback = true) {
770 + global $wpdb;
1177 771
1178 - return esc_sql( trim( strtolower( $ret ) ) );
772 + // Use local setting if we have it
773 + if ( isset($this->settings["$what status"]) ) :
774 + $ret = $this->settings["$what status"];
775 +
776 + // Or fall back to global default if we can
777 + elseif ($fallback) :
778 + $ret = FeedWordPress::syndicated_status($what, $default);
779 +
780 + // Or use default value if we can't.
781 + else :
782 + $ret = $default;
783 +
784 + endif;
785 +
786 + return $wpdb->escape(trim(strtolower($ret)));
1179 787 } /* SyndicatedLink:syndicated_status () */
1180 -
1181 - public function taxonomies () {
788 +
789 + function taxonomies () {
1182 790 $post_type = $this->setting('syndicated post type', 'syndicated_post_type', 'post');
1183 791 return get_object_taxonomies(array('object_type' => $post_type), 'names');
1184 792 } /* SyndicatedLink::taxonomies () */
1185 -
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 - endif;
1204 -
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 */
793 +
794 +} // class SyndicatedLink
1293 795