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 +267 -60 2010.0528 → 2011.0706 View file →
@@ -100,14 +100,48 @@
100 100 if (!isset($this->settings['cat_split']) and in_array($bits['host'], $tagspacers)) :
101 101 $this->settings['cat_split'] = '\s'; // Whitespace separates multiple tags in del.icio.us RSS feeds
102 102 endif;
103 103
104 - if (isset($this->settings['cats'])):
105 - $this->settings['cats'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['cats']);
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;
106 143 endif;
107 - if (isset($this->settings['tags'])):
108 - $this->settings['tags'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['tags']);
109 - endif;
110 144
111 145 if (isset($this->settings['map authors'])) :
112 146 $author_rules = explode("\n\n", $this->settings['map authors']);
113 147 $ma = array();
@@ -130,8 +164,10 @@
130 164 return is_object($this->link) and !is_wp_error($this->link);
131 165 } /* SyndicatedLink::found () */
132 166
133 167 function stale () {
168 + global $feedwordpress;
169 +
134 170 $stale = true;
135 171 if (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='ping')) :
136 172 $stale = false; // don't update on any timed updates; pings only
137 173 elseif (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='next')) :
@@ -137,8 +173,10 @@
137 173 elseif (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='next')) :
138 174 $stale = true; // update on the next timed update
139 175 elseif (!isset($this->settings['update/ttl']) or !isset($this->settings['update/last'])) :
140 176 $stale = true; // initial update
177 + elseif ($feedwordpress->force_update_all()) :
178 + $stale = true; // forced general updating
141 179 else :
142 180 $after = ((int) $this->settings['update/last'])
143 181 +((int) $this->settings['update/ttl'] * 60);
144 182 $stale = (time() >= $after);
@@ -148,11 +186,16 @@
148 186
149 187 function poll ($crash_ts = NULL) {
150 188 global $wpdb;
151 189
190 + $url = $this->uri(array('add_params' => true));
191 + FeedWordPress::diagnostic('updated_feeds', 'Polling feed ['.$url.']');
192 +
193 + $timeout = $this->setting('fetch timeout', 'feedwordpress_fetch_timeout', FEEDWORDPRESS_FETCH_TIMEOUT_DEFAULT);
194 +
152 195 $this->simplepie = apply_filters(
153 196 'syndicated_feed',
154 - FeedWordPress::fetch($this->link->link_rss),
197 + FeedWordPress::fetch($url, array('timeout' => $timeout)),
155 198 $this
156 199 );
157 200
158 201 // Filter compatibility mode
@@ -158,9 +201,9 @@
158 201 // Filter compatibility mode
159 202 if (is_wp_error($this->simplepie)) :
160 203 $this->magpie = $this->simplepie;
161 204 else :
162 - $this->magpie = new MagpieFromSimplePie($this->simplepie);
205 + $this->magpie = new MagpieFromSimplePie($this->simplepie, NULL);
163 206 endif;
164 207
165 208 $new_count = NULL;
166 209
@@ -174,9 +217,44 @@
174 217 endif;
175 218
176 219 if (is_wp_error($this->simplepie)) :
177 220 $new_count = $this->simplepie;
221 + // Error; establish an error setting.
222 + $theError = array();
223 + $theError['ts'] = time();
224 + $theError['since'] = time();
225 + $theError['object'] = $this->simplepie;
226 +
227 + $oldError = $this->setting('update/error', NULL, NULL);
228 + if (is_string($oldError)) :
229 + $oldError = unserialize($oldError);
230 + endif;
231 +
232 + if (!is_null($oldError)) :
233 + // Copy over the in-error-since timestamp
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);
242 +
243 + $this->settings['update/timed'] = 'automatically';
244 + endif;
245 +
246 + do_action('syndicated_feed_error', $theError, $oldError, $this);
247 +
248 + $this->settings['update/error'] = serialize($theError);
249 + $this->save_settings(/*reload=*/ true);
250 +
178 251 elseif (is_object($this->simplepie)) :
252 + // Success; clear out error setting, if any.
253 + if (isset($this->settings['update/error'])) :
254 + unset($this->settings['update/error']);
255 + endif;
256 +
179 257 $new_count = array('new' => 0, 'updated' => 0);
180 258
181 259 # -- Update Link metadata live from feed
182 260 $channel = $this->magpie->channel;
@@ -208,20 +286,9 @@
208 286 if (!is_null($ttl)) :
209 287 $this->settings['update/ttl'] = $ttl;
210 288 $this->settings['update/timed'] = 'feed';
211 289 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);
290 + $this->settings['update/ttl'] = $this->automatic_ttl();
224 291 $this->settings['update/timed'] = 'automatically';
225 292 endif;
226 293 $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl', $this->settings['update/ttl'], $this);
227 294
@@ -247,18 +314,17 @@
247 314 $crashed = false;
248 315
249 316 $posts = apply_filters(
250 317 'syndicated_feed_items',
251 - $this->magpie->originals,
252 - $this
318 + $this->simplepie->get_items(),
319 + &$this
253 320 );
321 +
322 + $this->magpie->originals = $posts;
323 +
254 324 if (is_array($posts)) :
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);
325 + foreach ($posts as $key => $item) :
326 + $post = new SyndicatedPost($item, $this);
261 327
262 328 if (!$resume or !in_array(trim($post->guid()), $processed)) :
263 329 $processed[] = $post->guid();
264 330 if (!$post->filtered()) :
@@ -297,8 +363,18 @@
297 363
298 364 do_action("update_syndicated_feed_completed", $this->id, $this);
299 365 endif;
300 366
367 + // All done; let's clean up.
368 + $this->magpie = NULL;
369 +
370 + // Avoid circular-reference memory leak in PHP < 5.3.
371 + // Cf. <http://simplepie.org/wiki/faq/i_m_getting_memory_leaks>
372 + if (method_exists($this->simplepie, '__destruct')) :
373 + $this->simplepie->__destruct();
374 + endif;
375 + $this->simplepie = NULL;
376 +
301 377 return $new_count;
302 378 } /* SyndicatedLink::poll() */
303 379
304 380 /**
@@ -325,24 +401,61 @@
325 401 endif;
326 402 return $ret;
327 403 } /* SyndicatedLink::set_uri () */
328 404
405 + function deactivate () {
406 + global $wpdb;
407 +
408 + $wpdb->query($wpdb->prepare("
409 + UPDATE $wpdb->links SET link_visible = 'N' WHERE link_id = %d
410 + ", (int) $this->id));
411 + } /* SyndicatedLink::deactivate () */
412 +
413 + function delete () {
414 + global $wpdb;
415 +
416 + $wpdb->query($wpdb->prepare("
417 + DELETE FROM $wpdb->postmeta WHERE meta_key='syndication_feed_id'
418 + AND meta_value = '%s'
419 + ", $this->id));
420 +
421 + $wpdb->query($wpdb->prepare("
422 + DELETE FROM $wpdb->links WHERE link_id = %d
423 + ", (int) $this->id));
424 +
425 + $this->id = NULL;
426 + } /* SyndicatedLink::delete () */
427 +
428 + function nuke () {
429 + global $wpdb;
430 +
431 + // Make a list of the items syndicated from this feed...
432 + $post_ids = $wpdb->get_col($wpdb->prepare("
433 + SELECT post_id FROM $wpdb->postmeta
434 + WHERE meta_key = 'syndication_feed_id'
435 + AND meta_value = '%s'
436 + ", $this->id));
437 +
438 + // ... and kill them all
439 + if (count($post_ids) > 0) :
440 + foreach ($post_ids as $post_id) :
441 + // Force scrubbing of deleted post
442 + // rather than sending to Trashcan
443 + wp_delete_post(
444 + /*postid=*/ $post_id,
445 + /*force_delete=*/ true
446 + );
447 + endforeach;
448 + endif;
449 +
450 + $this->delete();
451 + } /* SyndicatedLink::nuke () */
452 +
329 453 function map_name_to_new_user ($name, $newuser_name) {
330 454 global $wpdb;
331 455
332 456 if (strlen($newuser_name) > 0) :
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);
457 + $newuser_id = fwp_insert_new_user($newuser_name);
345 458 if (is_numeric($newuser_id)) :
346 459 if (is_null($name)) : // Unfamiliar author
347 460 $this->settings['unfamiliar author'] = $newuser_id;
348 461 else :
@@ -355,8 +468,11 @@
355 468 // TODO: Add some error reporting
356 469 endif;
357 470 } /* SyndicatedLink::map_name_to_new_user () */
358 471
472 + function imploded_settings () {
473 + return array('cats', 'tags', 'match/cats', 'match/tags', 'match/filter');
474 + }
359 475 function settings_to_notes () {
360 476 $to_notes = $this->settings;
361 477
362 478 unset($to_notes['link/id']); // Magic setting; don't save
@@ -369,15 +485,22 @@
369 485 if (isset($to_notes['update/processed']) and (is_array($to_notes['update/processed']))) :
370 486 $to_notes['update/processed'] = implode("\n", $to_notes['update/processed']);
371 487 endif;
372 488
373 - if (isset($to_notes['cats']) and is_array($to_notes['cats'])) :
374 - $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
489 + foreach ($this->imploded_settings() as $what) :
490 + if (isset($to_notes[$what]) and is_array($to_notes[$what])) :
491 + $to_notes[$what] = implode(
492 + FEEDWORDPRESS_CAT_SEPARATOR,
493 + $to_notes[$what]
494 + );
495 + endif;
496 + endforeach;
497 +
498 + if (isset($to_notes['terms']) and is_array($to_notes['terms'])) :
499 + // Serialize it.
500 + $to_notes['terms'] = serialize($to_notes['terms']);
375 501 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;
379 -
502 +
380 503 // Collapse the author mapping rule structure back into a flat string
381 504 if (isset($to_notes['map authors'])) :
382 505 $ma = array();
383 506 foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
@@ -431,9 +554,9 @@
431 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.
432 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.
433 556 * @return bool TRUE on success, FALSE on failure.
434 557 */
435 - function setting ($name, $fallback_global = NULL, $fallback_value = NULL) {
558 + function setting ($name, $fallback_global = NULL, $fallback_value = NULL, $default = 'default') {
436 559 $ret = NULL;
437 560 if (isset($this->settings[$name])) :
438 561 $ret = $this->settings[$name];
439 562 endif;
@@ -439,18 +562,21 @@
439 562 endif;
440 563
441 564 $no_value = (
442 565 is_null($ret)
443 - or (is_string($ret) and strtolower($ret)=='default')
566 + or (is_string($ret) and strtolower($ret)==$default)
444 567 );
445 568
446 569 if ($no_value and !is_null($fallback_global)) :
570 + // Avoid duplication of this correction
571 + $fallback_global = preg_replace('/^feedwordpress_/', '', $fallback_global);
572 +
447 573 $ret = get_option('feedwordpress_'.$fallback_global, /*default=*/ NULL);
448 574 endif;
449 575
450 576 $no_value = (
451 577 is_null($ret)
452 - or (is_string($ret) and strtolower($ret)=='default')
578 + or (is_string($ret) and strtolower($ret)==$default)
453 579 );
454 580
455 581 if ($no_value and !is_null($fallback_value)) :
456 582 $ret = $fallback_value;
@@ -457,29 +583,93 @@
457 583 endif;
458 584 return $ret;
459 585 } /* SyndicatedLink::setting () */
460 586
461 - function uri () {
462 - return (is_object($this->link) ? $this->link->link_rss : NULL);
587 + function update_setting ($name, $value, $default = 'default') {
588 + if (!is_null($value) and $value != $default) :
589 + $this->settings[$name] = $value;
590 + else : // Zap it.
591 + unset($this->settings[$name]);
592 + endif;
593 + } /* SyndicatedLink::update_setting () */
594 +
595 + function uri ($params = array()) {
596 + $params = shortcode_atts(array(
597 + 'add_params' => false,
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']) :
602 + $qp = maybe_unserialize($this->setting('query parameters', array()));
603 +
604 + // For high-tech HTTP feed request kung fu
605 + $qp = apply_filters('syndicated_feed_parameters', $qp, $uri, $this);
606 +
607 + $q = array();
608 + if (is_array($qp) and count($qp) > 0) :
609 + foreach ($qp as $pair) :
610 + $q[] = urlencode($pair[0]).'='.urlencode($pair[1]);
611 + endforeach;
612 +
613 + // Are we appending to a URI that already has params?
614 + $sep = ((strpos('?', $uri)===false) ? '?' : '&');
615 +
616 + // Tack it on
617 + $uri .= $sep . implode("&", $q);
618 + endif;
619 + endif;
620 +
621 + return $uri;
463 622 } /* SyndicatedLink::uri () */
464 623
465 - function homepage ($fromFeed = true) {
624 + function property_cascade ($fromFeed, $link_field, $setting, $simplepie_method) {
625 + $value = NULL;
466 626 if ($fromFeed) :
467 - $url = (isset($this->settings['feed/link']) ? $this->settings['feed/link'] : NULL);
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}();
632 + endif;
468 633 else :
469 - $url = $this->link->link_url;
634 + $value = $this->link->{$link_field};
470 635 endif;
471 - return $url;
636 + return $value;
637 + } /* SyndicatedLink::property_cascade () */
638 +
639 + function homepage ($fromFeed = true) {
640 + return $this->property_cascade($fromFeed, 'link_url', 'feed/link', 'get_link');
472 641 } /* SyndicatedLink::homepage () */
473 642
474 643 function name ($fromFeed = true) {
475 - if ($fromFeed) :
476 - $name = (isset($this->settings['feed/title']) ? $this->settings['feed/title'] : NULL);
477 - else :
478 - $name = $this->link->link_name;
644 + return $this->property_cascade($fromFeed, 'link_name', 'feed/title', 'get_title');
645 + } /* SyndicatedLink::name () */
646 +
647 + function guid () {
648 + $ret = $this->setting('feed/id', NULL, $this->uri());
649 +
650 + // If we can get it live from the feed, do so.
651 + if (is_object($this->simplepie)) :
652 + $search = array(
653 + array(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'),
654 + array(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'),
655 + array(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'),
656 + array(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'),
657 + array(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'),
658 + );
659 +
660 + foreach ($search as $pair) :
661 + if ($id_tags = $this->simplepie->get_feed_tags($pair[0], $pair[1])) :
662 + $ret = $id_tags[0]['data'];
663 + break;
664 + elseif ($id_tags = $this->simplepie->get_channel_tags($pair[0], $pair[1])) :
665 + $ret = $id_tags[0]['data'];
666 + break;
667 + endif;
668 + endforeach;
479 669 endif;
480 - return $name;
481 - } /* SyndicatedLink::name () */
670 + return $ret;
671 + }
482 672
483 673 function ttl () {
484 674 if (is_object($this->magpie)) :
485 675 $channel = $this->magpie->channel;
@@ -525,8 +715,19 @@
525 715 endif;
526 716 return $ret;
527 717 } /* SyndicatedLink::ttl() */
528 718
719 + function automatic_ttl () {
720 + // spread out over a time interval for staggered updates
721 + $updateWindow = $this->setting('update/window', 'update_window', DEFAULT_UPDATE_PERIOD);
722 + if (!is_numeric($updateWindow) or ($updateWindow < 1)) :
723 + $updateWindow = DEFAULT_UPDATE_PERIOD;
724 + endif;
725 +
726 + $fudgedInterval = $updateWindow+rand(0, 2*($updateWindow/3));
727 + return apply_filters('syndicated_feed_automatic_ttl', $fudgedInterval, $this);
728 + } /* SyndicatedLink::automatic_ttl () */
729 +
529 730 // SyndicatedLink::flatten_array (): flatten an array. Useful for
530 731 // hierarchical and namespaced elements.
531 732 //
532 733 // Given an array which may contain array or object elements in it,
@@ -583,6 +784,12 @@
583 784 endif;
584 785
585 786 return $wpdb->escape(trim(strtolower($ret)));
586 787 } /* SyndicatedLink:syndicated_status () */
788 +
789 + function taxonomies () {
790 + $post_type = $this->setting('syndicated post type', 'syndicated_post_type', 'post');
791 + return get_object_taxonomies(array('object_type' => $post_type), 'names');
792 + } /* SyndicatedLink::taxonomies () */
793 +
587 794 } // class SyndicatedLink
588 795