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
feedwordpress / syndicatedlink.class.php

syndicatedlink.class.php in FeedWordPress 2011.0706, at syndicatedlink.class.php

796 lines 25.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 # class SyndicatedLink: represents a syndication feed stored within the
3 # WordPress database
4 #
5 # To keep things compact and editable from within WordPress, we use all the
6 # links under a particular category in the WordPress "Blogroll" for the list of
7 # feeds to syndicate. "Contributors" is the category used by default; you can
8 # configure that under Options --> Syndication.
9 #
10 # Fields used are:
11 #
12 # * link_rss: the URI of the Atom/RSS feed to syndicate
13 #
14 # * link_notes: user-configurable options, with keys and values
15 # like so:
16 #
17 # key: value
18 # cats: computers\nweb
19 # feed/key: value
20 #
21 # Keys that start with "feed/" are gleaned from the data supplied
22 # by the feed itself, and will be overwritten with each update.
23 #
24 # Values have linebreak characters escaped with C-style
25 # backslashes (so, for example, a newline becomes "\n").
26 #
27 # The value of `cats` is used as a newline-separated list of
28 # default categories for any post coming from a particular feed.
29 # (In the example above, any posts from this feed will be placed
30 # in the "computers" and "web" categories--*in addition to* any
31 # categories that may already be applied to the posts.)
32 #
33 # Values of keys in link_notes are accessible from templates using
34 # the function `get_feed_meta($key)` if this plugin is activated.
35
36 require_once(dirname(__FILE__).'/magpiefromsimplepie.class.php');
37
38 class SyndicatedLink {
39 var $id = null;
40 var $link = null;
41 var $settings = array ();
42 var $simplepie = null;
43 var $magpie = null;
44
45 function SyndicatedLink ($link) {
46 global $wpdb;
47
48 if (is_object($link)) :
49 $this->link = $link;
50 $this->id = $link->link_id;
51 else :
52 $this->id = $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;
61 endif;
62
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'];
89 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;
96
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;
103
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 () {
164 return is_object($this->link) and !is_wp_error($this->link);
165 } /* SyndicatedLink::found () */
166
167 function stale () {
168 global $feedwordpress;
169
170 $stale = true;
171 if (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='ping')) :
172 $stale = false; // don't update on any timed updates; pings only
173 elseif (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='next')) :
174 $stale = true; // update on the next timed update
175 elseif (!isset($this->settings['update/ttl']) or !isset($this->settings['update/last'])) :
176 $stale = true; // initial update
177 elseif ($feedwordpress->force_update_all()) :
178 $stale = true; // forced general updating
179 else :
180 $after = ((int) $this->settings['update/last'])
181 +((int) $this->settings['update/ttl'] * 60);
182 $stale = (time() >= $after);
183 endif;
184 return $stale;
185 } /* SyndicatedLink::stale () */
186
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
193 $timeout = $this->setting('fetch timeout', 'feedwordpress_fetch_timeout', FEEDWORDPRESS_FETCH_TIMEOUT_DEFAULT);
194
195 $this->simplepie = apply_filters(
196 'syndicated_feed',
197 FeedWordPress::fetch($url, array('timeout' => $timeout)),
198 $this
199 );
200
201 // Filter compatibility mode
202 if (is_wp_error($this->simplepie)) :
203 $this->magpie = $this->simplepie;
204 else :
205 $this->magpie = new MagpieFromSimplePie($this->simplepie, NULL);
206 endif;
207
208 $new_count = NULL;
209
210 $resume = FeedWordPress::affirmative($this->settings, 'update/unfinished');
211 if ($resume) :
212 // pick up where we left off
213 $processed = array_map('trim', explode("\n", $this->settings['update/processed']));
214 else :
215 // begin at the beginning
216 $processed = array();
217 endif;
218
219 if (is_wp_error($this->simplepie)) :
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
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
257 $new_count = array('new' => 0, 'updated' => 0);
258
259 # -- Update Link metadata live from feed
260 $channel = $this->magpie->channel;
261
262 if (!isset($channel['id'])) :
263 $channel['id'] = $this->link->link_rss;
264 endif;
265
266 $update = array();
267 if (!$this->hardcode('url') and isset($channel['link'])) :
268 $update[] = "link_url = '".$wpdb->escape($channel['link'])."'";
269 endif;
270
271 if (!$this->hardcode('name') and isset($channel['title'])) :
272 $update[] = "link_name = '".$wpdb->escape($channel['title'])."'";
273 endif;
274
275 if (!$this->hardcode('description')) :
276 if (isset($channel['tagline'])) :
277 $update[] = "link_description = '".$wpdb->escape($channel['tagline'])."'";
278 elseif (isset($channel['description'])) :
279 $update[] = "link_description = '".$wpdb->escape($channel['description'])."'";
280 endif;
281 endif;
282
283 $this->settings = array_merge($this->settings, $this->flatten_array($channel));
284
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);
294
295 if (!isset($this->settings['update/hold']) or $this->settings['update/hold']!='ping') :
296 $this->settings['update/hold'] = 'scheduled';
297 endif;
298
299 $this->settings['update/unfinished'] = 'yes';
300
301 $update[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
302
303 $update_set = implode(',', $update);
304
305 // Update the properties of the link from the feed information
306 $result = $wpdb->query("
307 UPDATE $wpdb->links
308 SET $update_set
309 WHERE link_id='$this->id'
310 ");
311 do_action('update_syndicated_feed', $this->id, $this);
312
313 # -- Add new posts from feed and update any updated posts
314 $crashed = false;
315
316 $posts = apply_filters(
317 'syndicated_feed_items',
318 $this->simplepie->get_items(),
319 &$this
320 );
321
322 $this->magpie->originals = $posts;
323
324 if (is_array($posts)) :
325 foreach ($posts as $key => $item) :
326 $post = new SyndicatedPost($item, $this);
327
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;
334
335 if (!is_null($crash_ts) and (time() > $crash_ts)) :
336 $crashed = true;
337 break;
338 endif;
339 endif;
340 unset($post);
341 endforeach;
342 endif;
343 $suffix = ($crashed ? 'crashed' : 'completed');
344 do_action('update_syndicated_feed_items', $this->id, $this);
345 do_action("update_syndicated_feed_items_${suffix}", $this->id, $this);
346
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';
353 endif;
354
355 $update_set = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
356
357 // Update the properties of the link from the feed information
358 $result = $wpdb->query("
359 UPDATE $wpdb->links
360 SET $update_set
361 WHERE link_id='$this->id'
362 ");
363
364 do_action("update_syndicated_feed_completed", $this->id, $this);
365 endif;
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
377 return $new_count;
378 } /* SyndicatedLink::poll() */
379
380 /**
381 * Updates the URL for the feed syndicated by this link.
382 *
383 * @param string $url The new feed URL to use for this source.
384 * @return bool TRUE on success, FALSE on failure.
385 */
386 function set_uri ($url) {
387 global $wpdb;
388
389 if ($this->found()) :
390 // Update link_rss
391 $result = $wpdb->query("
392 UPDATE $wpdb->links
393 SET
394 link_rss = '".$wpdb->escape($url)."'
395 WHERE link_id = '".$wpdb->escape($this->id)."'
396 ");
397
398 $ret = ($result ? true : false);
399 else :
400 $ret = false;
401 endif;
402 return $ret;
403 } /* SyndicatedLink::set_uri () */
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
453 function map_name_to_new_user ($name, $newuser_name) {
454 global $wpdb;
455
456 if (strlen($newuser_name) > 0) :
457 $newuser_id = fwp_insert_new_user($newuser_name);
458 if (is_numeric($newuser_id)) :
459 if (is_null($name)) : // Unfamiliar author
460 $this->settings['unfamiliar author'] = $newuser_id;
461 else :
462 $this->settings['map authors']['name'][$name] = $newuser_id;
463 endif;
464 else :
465 // TODO: Add some error detection and reporting
466 endif;
467 else :
468 // TODO: Add some error reporting
469 endif;
470 } /* SyndicatedLink::map_name_to_new_user () */
471
472 function imploded_settings () {
473 return array('cats', 'tags', 'match/cats', 'match/tags', 'match/filter');
474 }
475 function settings_to_notes () {
476 $to_notes = $this->settings;
477
478 unset($to_notes['link/id']); // Magic setting; don't save
479 unset($to_notes['link/uri']); // Magic setting; don't save
480 unset($to_notes['link/name']); // Magic setting; don't save
481 unset($to_notes['hardcode categories']); // Deprecated
482 unset($to_notes['unfamiliar categories']); // Deprecated
483
484 // Collapse array settings
485 if (isset($to_notes['update/processed']) and (is_array($to_notes['update/processed']))) :
486 $to_notes['update/processed'] = implode("\n", $to_notes['update/processed']);
487 endif;
488
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']);
501 endif;
502
503 // Collapse the author mapping rule structure back into a flat string
504 if (isset($to_notes['map authors'])) :
505 $ma = array();
506 foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
507 foreach ($author_rules as $author_name => $author_action) :
508 $ma[] = $rule_type."\n".$author_name."\n".$author_action;
509 endforeach;
510 endforeach;
511 $to_notes['map authors'] = implode("\n\n", $ma);
512 endif;
513
514 $notes = '';
515 foreach ($to_notes as $key => $value) :
516 $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
517 endforeach;
518 return $notes;
519 } /* SyndicatedLink::settings_to_notes () */
520
521 function save_settings ($reload = false) {
522 global $wpdb;
523
524 // Save channel-level meta-data
525 foreach (array('link_name', 'link_description', 'link_url') as $what) :
526 $alter[] = "{$what} = '".$wpdb->escape($this->link->{$what})."'";
527 endforeach;
528
529 // Save settings to the notes field
530 $alter[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
531
532 // Update the properties of the link from settings changes, etc.
533 $update_set = implode(", ", $alter);
534
535 $result = $wpdb->query("
536 UPDATE $wpdb->links
537 SET $update_set
538 WHERE link_id='$this->id'
539 ");
540
541 if ($reload) :
542 // force reload of link information from DB
543 if (function_exists('clean_bookmark_cache')) :
544 clean_bookmark_cache($this->id);
545 endif;
546 endif;
547 } /* SyndicatedLink::save_settings () */
548
549 /**
550 * Retrieves the value of a setting, allowing for a global setting to be
551 * used as a fallback, or a constant value, or both.
552 *
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.
557 */
558 function setting ($name, $fallback_global = NULL, $fallback_value = NULL, $default = 'default') {
559 $ret = NULL;
560 if (isset($this->settings[$name])) :
561 $ret = $this->settings[$name];
562 endif;
563
564 $no_value = (
565 is_null($ret)
566 or (is_string($ret) and strtolower($ret)==$default)
567 );
568
569 if ($no_value and !is_null($fallback_global)) :
570 // Avoid duplication of this correction
571 $fallback_global = preg_replace('/^feedwordpress_/', '', $fallback_global);
572
573 $ret = get_option('feedwordpress_'.$fallback_global, /*default=*/ NULL);
574 endif;
575
576 $no_value = (
577 is_null($ret)
578 or (is_string($ret) and strtolower($ret)==$default)
579 );
580
581 if ($no_value and !is_null($fallback_value)) :
582 $ret = $fallback_value;
583 endif;
584 return $ret;
585 } /* SyndicatedLink::setting () */
586
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;
622 } /* SyndicatedLink::uri () */
623
624 function property_cascade ($fromFeed, $link_field, $setting, $simplepie_method) {
625 $value = NULL;
626 if ($fromFeed) :
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;
633 else :
634 $value = $this->link->{$link_field};
635 endif;
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');
641 } /* SyndicatedLink::homepage () */
642
643 function name ($fromFeed = true) {
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;
669 endif;
670 return $ret;
671 }
672
673 function ttl () {
674 if (is_object($this->magpie)) :
675 $channel = $this->magpie->channel;
676 else :
677 $channel = array();
678 endif;
679
680 if (isset($channel['ttl'])) :
681 // "ttl stands for time to live. It's a number of
682 // minutes that indicates how long a channel can be
683 // cached before refreshing from the source."
684 // <http://blogs.law.harvard.edu/tech/rss#ltttlgtSubelementOfLtchannelgt>
685 $ret = $channel['ttl'];
686 elseif (isset($channel['sy']['updatefrequency']) or isset($channel['sy']['updateperiod'])) :
687 $period_minutes = array (
688 'hourly' => 60, /* minutes in an hour */
689 'daily' => 1440, /* minutes in a day */
690 'weekly' => 10080, /* minutes in a week */
691 'monthly' => 43200, /* minutes in a month */
692 'yearly' => 525600, /* minutes in a year */
693 );
694
695 // "sy:updatePeriod: Describes the period over which the
696 // channel format is updated. Acceptable values are:
697 // hourly, daily, weekly, monthly, yearly. If omitted,
698 // daily is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
699 if (isset($channel['sy']['updateperiod'])) : $period = $channel['sy']['updateperiod'];
700 else : $period = 'daily';
701 endif;
702
703 // "sy:updateFrequency: Used to describe the frequency
704 // of updates in relation to the update period. A
705 // positive integer indicates how many times in that
706 // period the channel is updated. ... If omitted a value
707 // of 1 is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
708 if (isset($channel['sy']['updatefrequency'])) : $freq = (int) $channel['sy']['updatefrequency'];
709 else : $freq = 1;
710 endif;
711
712 $ret = (int) ($period_minutes[$period] / $freq);
713 else :
714 $ret = NULL;
715 endif;
716 return $ret;
717 } /* SyndicatedLink::ttl() */
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
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;
745 else :
746 $ret = array_merge($ret, $this->flatten_array($value, $prefix.$key.$separator, $separator));
747 endif;
748 endforeach;
749 endif;
750 return $ret;
751 } /* SyndicatedLink::flatten_array () */
752
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;
767 } /* SyndicatedLink::hardcode () */
768
769 function syndicated_status ($what, $default, $fallback = true) {
770 global $wpdb;
771
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)));
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
794 } // class SyndicatedLink
795
796