PluginProbe
FeedWordPress / 2010.0903
FeedWordPress v2010.0903
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 2010.0903, at syndicatedlink.class.php

745 lines 23.8 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 $this->settings['terms'] = explode(FEEDWORDPRESS_CAT_SEPARATOR.FEEDWORDPRESS_CAT_SEPARATOR, $this->settings['terms']);
116 $terms = array();
117 foreach ($this->settings['terms'] as $line) :
118 $line = explode(FEEDWORDPRESS_CAT_SEPARATOR, $line);
119 $tax = array_shift($line);
120 $terms[$tax] = $line;
121 endforeach;
122 $this->settings['terms'] = $terms;
123 endif;
124
125 if (isset($this->settings['map authors'])) :
126 $author_rules = explode("\n\n", $this->settings['map authors']);
127 $ma = array();
128 foreach ($author_rules as $rule) :
129 list($rule_type, $author_name, $author_action) = explode("\n", $rule);
130
131 // Normalize for case and whitespace
132 $rule_type = strtolower(trim($rule_type));
133 $author_name = strtolower(trim($author_name));
134 $author_action = strtolower(trim($author_action));
135
136 $ma[$rule_type][$author_name] = $author_action;
137 endforeach;
138 $this->settings['map authors'] = $ma;
139 endif;
140 endif;
141 } /* SyndicatedLink::SyndicatedLink () */
142
143 function found () {
144 return is_object($this->link) and !is_wp_error($this->link);
145 } /* SyndicatedLink::found () */
146
147 function stale () {
148 $stale = true;
149 if (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='ping')) :
150 $stale = false; // don't update on any timed updates; pings only
151 elseif (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='next')) :
152 $stale = true; // update on the next timed update
153 elseif (!isset($this->settings['update/ttl']) or !isset($this->settings['update/last'])) :
154 $stale = true; // initial update
155 else :
156 $after = ((int) $this->settings['update/last'])
157 +((int) $this->settings['update/ttl'] * 60);
158 $stale = (time() >= $after);
159 endif;
160 return $stale;
161 } /* SyndicatedLink::stale () */
162
163 function poll ($crash_ts = NULL) {
164 global $wpdb;
165
166 FeedWordPress::diagnostic('updated_feeds', 'Polling feed ['.$this->link->link_rss.']');
167
168 $this->simplepie = apply_filters(
169 'syndicated_feed',
170 FeedWordPress::fetch($this->link->link_rss),
171 $this
172 );
173
174 // Filter compatibility mode
175 if (is_wp_error($this->simplepie)) :
176 $this->magpie = $this->simplepie;
177 else :
178 $this->magpie = new MagpieFromSimplePie($this->simplepie);
179 endif;
180
181 $new_count = NULL;
182
183 $resume = FeedWordPress::affirmative($this->settings, 'update/unfinished');
184 if ($resume) :
185 // pick up where we left off
186 $processed = array_map('trim', explode("\n", $this->settings['update/processed']));
187 else :
188 // begin at the beginning
189 $processed = array();
190 endif;
191
192 if (is_wp_error($this->simplepie)) :
193 $new_count = $this->simplepie;
194 // Error; establish an error setting.
195 $theError = array();
196 $theError['ts'] = time();
197 $theError['since'] = time();
198 $theError['object'] = $this->simplepie;
199
200 $oldError = $this->setting('update/error', NULL, NULL);
201 if (is_string($oldError)) :
202 $oldError = unserialize($oldError);
203 endif;
204
205 if (!is_null($oldError)) :
206 // Copy over the in-error-since timestamp
207 $theError['since'] = $oldError['since'];
208
209 // If this is a repeat error, then we should take
210 // a step back before we try to fetch it again.
211 $this->settings['update/last'] = time();
212 $this->settings['update/ttl'] = $this->automatic_ttl();
213 $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl', $this->settings['update/ttl'], $this);
214 $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl_from_error', $this->settings['update/ttl'], $this);
215
216 $this->settings['update/timed'] = 'automatically';
217 endif;
218
219 do_action('syndicated_feed_error', $theError, $oldError, $this);
220
221 $this->settings['update/error'] = serialize($theError);
222 $this->save_settings(/*reload=*/ true);
223
224 elseif (is_object($this->simplepie)) :
225 // Success; clear out error setting, if any.
226 if (isset($this->settings['update/error'])) :
227 unset($this->settings['update/error']);
228 endif;
229
230 $new_count = array('new' => 0, 'updated' => 0);
231
232 # -- Update Link metadata live from feed
233 $channel = $this->magpie->channel;
234
235 if (!isset($channel['id'])) :
236 $channel['id'] = $this->link->link_rss;
237 endif;
238
239 $update = array();
240 if (!$this->hardcode('url') and isset($channel['link'])) :
241 $update[] = "link_url = '".$wpdb->escape($channel['link'])."'";
242 endif;
243
244 if (!$this->hardcode('name') and isset($channel['title'])) :
245 $update[] = "link_name = '".$wpdb->escape($channel['title'])."'";
246 endif;
247
248 if (!$this->hardcode('description')) :
249 if (isset($channel['tagline'])) :
250 $update[] = "link_description = '".$wpdb->escape($channel['tagline'])."'";
251 elseif (isset($channel['description'])) :
252 $update[] = "link_description = '".$wpdb->escape($channel['description'])."'";
253 endif;
254 endif;
255
256 $this->settings = array_merge($this->settings, $this->flatten_array($channel));
257
258 $this->settings['update/last'] = time(); $ttl = $this->ttl();
259 if (!is_null($ttl)) :
260 $this->settings['update/ttl'] = $ttl;
261 $this->settings['update/timed'] = 'feed';
262 else :
263 $this->settings['update/ttl'] = $this->automatic_ttl();
264 $this->settings['update/timed'] = 'automatically';
265 endif;
266 $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl', $this->settings['update/ttl'], $this);
267
268 if (!isset($this->settings['update/hold']) or $this->settings['update/hold']!='ping') :
269 $this->settings['update/hold'] = 'scheduled';
270 endif;
271
272 $this->settings['update/unfinished'] = 'yes';
273
274 $update[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
275
276 $update_set = implode(',', $update);
277
278 // Update the properties of the link from the feed information
279 $result = $wpdb->query("
280 UPDATE $wpdb->links
281 SET $update_set
282 WHERE link_id='$this->id'
283 ");
284 do_action('update_syndicated_feed', $this->id, $this);
285
286 # -- Add new posts from feed and update any updated posts
287 $crashed = false;
288
289 $posts = apply_filters(
290 'syndicated_feed_items',
291 $this->magpie->originals,
292 $this
293 );
294 if (is_array($posts)) :
295 foreach ($posts as $key => $original) :
296 $item = $this->magpie->items[$key];
297 $post = new SyndicatedPost(array(
298 'simplepie' => $original,
299 'magpie' => $item,
300 ), $this);
301
302 if (!$resume or !in_array(trim($post->guid()), $processed)) :
303 $processed[] = $post->guid();
304 if (!$post->filtered()) :
305 $new = $post->store();
306 if ( $new !== false ) $new_count[$new]++;
307 endif;
308
309 if (!is_null($crash_ts) and (time() > $crash_ts)) :
310 $crashed = true;
311 break;
312 endif;
313 endif;
314 unset($post);
315 endforeach;
316 endif;
317 $suffix = ($crashed ? 'crashed' : 'completed');
318 do_action('update_syndicated_feed_items', $this->id, $this);
319 do_action("update_syndicated_feed_items_${suffix}", $this->id, $this);
320
321 // Copy back any changes to feed settings made in the course of updating (e.g. new author rules)
322 $to_notes = $this->settings;
323
324 $this->settings['update/processed'] = $processed;
325 if (!$crashed) :
326 $this->settings['update/unfinished'] = 'no';
327 endif;
328
329 $update_set = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
330
331 // Update the properties of the link from the feed information
332 $result = $wpdb->query("
333 UPDATE $wpdb->links
334 SET $update_set
335 WHERE link_id='$this->id'
336 ");
337
338 do_action("update_syndicated_feed_completed", $this->id, $this);
339 endif;
340
341 // All done; let's clean up.
342 $this->magpie = NULL;
343
344 // Avoid circular-reference memory leak in PHP < 5.3.
345 // Cf. <http://simplepie.org/wiki/faq/i_m_getting_memory_leaks>
346 if (method_exists($this->simplepie, '__destruct')) :
347 $this->simplepie->__destruct();
348 endif;
349 $this->simplepie = NULL;
350
351 return $new_count;
352 } /* SyndicatedLink::poll() */
353
354 /**
355 * Updates the URL for the feed syndicated by this link.
356 *
357 * @param string $url The new feed URL to use for this source.
358 * @return bool TRUE on success, FALSE on failure.
359 */
360 function set_uri ($url) {
361 global $wpdb;
362
363 if ($this->found()) :
364 // Update link_rss
365 $result = $wpdb->query("
366 UPDATE $wpdb->links
367 SET
368 link_rss = '".$wpdb->escape($url)."'
369 WHERE link_id = '".$wpdb->escape($this->id)."'
370 ");
371
372 $ret = ($result ? true : false);
373 else :
374 $ret = false;
375 endif;
376 return $ret;
377 } /* SyndicatedLink::set_uri () */
378
379 function deactivate () {
380 global $wpdb;
381
382 $wpdb->query($wpdb->prepare("
383 UPDATE $wpdb->links SET link_visible = 'N' WHERE link_id = %d
384 ", (int) $this->id));
385 } /* SyndicatedLink::deactivate () */
386
387 function delete () {
388 global $wpdb;
389
390 $wpdb->query($wpdb->prepare("
391 DELETE FROM $wpdb->postmeta WHERE meta_key='syndication_feed_id'
392 AND meta_value = '%s'
393 ", $this->id));
394
395 $wpdb->query($wpdb->prepare("
396 DELETE FROM $wpdb->links WHERE link_id = %d
397 ", (int) $this->id));
398
399 $this->id = NULL;
400 } /* SyndicatedLink::delete () */
401
402 function nuke () {
403 global $wpdb;
404
405 // Make a list of the items syndicated from this feed...
406 $post_ids = $wpdb->get_col($wpdb->prepare("
407 SELECT post_id FROM $wpdb->postmeta
408 WHERE meta_key = 'syndication_feed_id'
409 AND meta_value = '%s'
410 ", $this->id));
411
412 // ... and kill them all
413 if (count($post_ids) > 0) :
414 foreach ($post_ids as $post_id) :
415 // Force scrubbing of deleted post
416 // rather than sending to Trashcan
417 wp_delete_post(
418 /*postid=*/ $post_id,
419 /*force_delete=*/ true
420 );
421 endforeach;
422 endif;
423
424 $this->delete();
425 } /* SyndicatedLink::nuke () */
426
427 function map_name_to_new_user ($name, $newuser_name) {
428 global $wpdb;
429
430 if (strlen($newuser_name) > 0) :
431 $newuser_id = fwp_insert_new_user($newuser_name);
432 if (is_numeric($newuser_id)) :
433 if (is_null($name)) : // Unfamiliar author
434 $this->settings['unfamiliar author'] = $newuser_id;
435 else :
436 $this->settings['map authors']['name'][$name] = $newuser_id;
437 endif;
438 else :
439 // TODO: Add some error detection and reporting
440 endif;
441 else :
442 // TODO: Add some error reporting
443 endif;
444 } /* SyndicatedLink::map_name_to_new_user () */
445
446 function imploded_settings () {
447 return array('cats', 'tags', 'match/cats', 'match/tags', 'match/filter');
448 }
449 function settings_to_notes () {
450 $to_notes = $this->settings;
451
452 unset($to_notes['link/id']); // Magic setting; don't save
453 unset($to_notes['link/uri']); // Magic setting; don't save
454 unset($to_notes['link/name']); // Magic setting; don't save
455 unset($to_notes['hardcode categories']); // Deprecated
456 unset($to_notes['unfamiliar categories']); // Deprecated
457
458 // Collapse array settings
459 if (isset($to_notes['update/processed']) and (is_array($to_notes['update/processed']))) :
460 $to_notes['update/processed'] = implode("\n", $to_notes['update/processed']);
461 endif;
462
463 foreach ($this->imploded_settings() as $what) :
464 if (isset($to_notes[$what]) and is_array($to_notes[$what])) :
465 $to_notes[$what] = implode(
466 FEEDWORDPRESS_CAT_SEPARATOR,
467 $to_notes[$what]
468 );
469 endif;
470 endforeach;
471
472 if (isset($to_notes['terms']) and is_array($to_notes['terms'])) :
473 $tt = array();
474 foreach ($to_notes['terms'] as $tax => $terms) :
475 $tt[] = $tax.FEEDWORDPRESS_CAT_SEPARATOR.implode(FEEDWORDPRESS_CAT_SEPARATOR, $terms);
476 endforeach;
477 $to_notes['terms'] = implode(FEEDWORDPRESS_CAT_SEPARATOR.FEEDWORDPRESS_CAT_SEPARATOR, $tt);
478 endif;
479
480 // Collapse the author mapping rule structure back into a flat string
481 if (isset($to_notes['map authors'])) :
482 $ma = array();
483 foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
484 foreach ($author_rules as $author_name => $author_action) :
485 $ma[] = $rule_type."\n".$author_name."\n".$author_action;
486 endforeach;
487 endforeach;
488 $to_notes['map authors'] = implode("\n\n", $ma);
489 endif;
490
491 $notes = '';
492 foreach ($to_notes as $key => $value) :
493 $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
494 endforeach;
495 return $notes;
496 } /* SyndicatedLink::settings_to_notes () */
497
498 function save_settings ($reload = false) {
499 global $wpdb;
500
501 // Save channel-level meta-data
502 foreach (array('link_name', 'link_description', 'link_url') as $what) :
503 $alter[] = "{$what} = '".$wpdb->escape($this->link->{$what})."'";
504 endforeach;
505
506 // Save settings to the notes field
507 $alter[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
508
509 // Update the properties of the link from settings changes, etc.
510 $update_set = implode(", ", $alter);
511
512 $result = $wpdb->query("
513 UPDATE $wpdb->links
514 SET $update_set
515 WHERE link_id='$this->id'
516 ");
517
518 if ($reload) :
519 // force reload of link information from DB
520 if (function_exists('clean_bookmark_cache')) :
521 clean_bookmark_cache($this->id);
522 endif;
523 endif;
524 } /* SyndicatedLink::save_settings () */
525
526 /**
527 * Retrieves the value of a setting, allowing for a global setting to be
528 * used as a fallback, or a constant value, or both.
529 *
530 * @param string $name The link setting key
531 * @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.
532 * @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.
533 * @return bool TRUE on success, FALSE on failure.
534 */
535 function setting ($name, $fallback_global = NULL, $fallback_value = NULL) {
536 $ret = NULL;
537 if (isset($this->settings[$name])) :
538 $ret = $this->settings[$name];
539 endif;
540
541 $no_value = (
542 is_null($ret)
543 or (is_string($ret) and strtolower($ret)=='default')
544 );
545
546 if ($no_value and !is_null($fallback_global)) :
547 $ret = get_option('feedwordpress_'.$fallback_global, /*default=*/ NULL);
548 endif;
549
550 $no_value = (
551 is_null($ret)
552 or (is_string($ret) and strtolower($ret)=='default')
553 );
554
555 if ($no_value and !is_null($fallback_value)) :
556 $ret = $fallback_value;
557 endif;
558 return $ret;
559 } /* SyndicatedLink::setting () */
560
561 function update_setting ($name, $value, $default = 'default') {
562 if (!is_null($value) and $value != $default) :
563 $this->settings[$name] = $value;
564 else : // Zap it.
565 unset($this->settings[$name]);
566 endif;
567 } /* SyndicatedLink::update_setting () */
568
569 function uri () {
570 return (is_object($this->link) ? $this->link->link_rss : NULL);
571 } /* SyndicatedLink::uri () */
572
573 function property_cascade ($fromFeed, $link_field, $setting, $simplepie_method) {
574 $value = NULL;
575 if ($fromFeed) :
576 if (isset($this->settings[$setting])) :
577 $value = $this->settings[$setting];
578 elseif (is_object($this->simplepie)
579 and method_exists($this->simplepie, $simplepie_method)) :
580 $value = $this->simplepie->{$simplepie_method}();
581 endif;
582 else :
583 $value = $this->link->{$link_field};
584 endif;
585 return $value;
586 } /* SyndicatedLink::property_cascade () */
587
588 function homepage ($fromFeed = true) {
589 return $this->property_cascade($fromFeed, 'link_url', 'feed/link', 'get_link');
590 } /* SyndicatedLink::homepage () */
591
592 function name ($fromFeed = true) {
593 return $this->property_cascade($fromFeed, 'link_name', 'feed/title', 'get_title');
594 } /* SyndicatedLink::name () */
595
596 function guid () {
597 $ret = $this->setting('feed/id', NULL, $this->uri());
598
599 // If we can get it live from the feed, do so.
600 if (is_object($this->simplepie)) :
601 $search = array(
602 array(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'),
603 array(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'),
604 array(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'),
605 array(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'),
606 array(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'),
607 );
608
609 foreach ($search as $pair) :
610 if ($id_tags = $this->simplepie->get_feed_tags($pair[0], $pair[1])) :
611 $ret = $id_tags[0]['data'];
612 break;
613 elseif ($id_tags = $this->simplepie->get_channel_tags($pair[0], $pair[1])) :
614 $ret = $id_tags[0]['data'];
615 break;
616 endif;
617 endforeach;
618 endif;
619 return $ret;
620 }
621
622 function ttl () {
623 if (is_object($this->magpie)) :
624 $channel = $this->magpie->channel;
625 else :
626 $channel = array();
627 endif;
628
629 if (isset($channel['ttl'])) :
630 // "ttl stands for time to live. It's a number of
631 // minutes that indicates how long a channel can be
632 // cached before refreshing from the source."
633 // <http://blogs.law.harvard.edu/tech/rss#ltttlgtSubelementOfLtchannelgt>
634 $ret = $channel['ttl'];
635 elseif (isset($channel['sy']['updatefrequency']) or isset($channel['sy']['updateperiod'])) :
636 $period_minutes = array (
637 'hourly' => 60, /* minutes in an hour */
638 'daily' => 1440, /* minutes in a day */
639 'weekly' => 10080, /* minutes in a week */
640 'monthly' => 43200, /* minutes in a month */
641 'yearly' => 525600, /* minutes in a year */
642 );
643
644 // "sy:updatePeriod: Describes the period over which the
645 // channel format is updated. Acceptable values are:
646 // hourly, daily, weekly, monthly, yearly. If omitted,
647 // daily is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
648 if (isset($channel['sy']['updateperiod'])) : $period = $channel['sy']['updateperiod'];
649 else : $period = 'daily';
650 endif;
651
652 // "sy:updateFrequency: Used to describe the frequency
653 // of updates in relation to the update period. A
654 // positive integer indicates how many times in that
655 // period the channel is updated. ... If omitted a value
656 // of 1 is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
657 if (isset($channel['sy']['updatefrequency'])) : $freq = (int) $channel['sy']['updatefrequency'];
658 else : $freq = 1;
659 endif;
660
661 $ret = (int) ($period_minutes[$period] / $freq);
662 else :
663 $ret = NULL;
664 endif;
665 return $ret;
666 } /* SyndicatedLink::ttl() */
667
668 function automatic_ttl () {
669 // spread out over a time interval for staggered updates
670 $updateWindow = $this->setting('update/window', 'update_window', DEFAULT_UPDATE_PERIOD);
671 if (!is_numeric($updateWindow) or ($updateWindow < 1)) :
672 $updateWindow = DEFAULT_UPDATE_PERIOD;
673 endif;
674
675 $fudgedInterval = $updateWindow+rand(0, 2*($updateWindow/3));
676 return apply_filters('syndicated_feed_automatic_ttl', $fudgedInterval, $this);
677 } /* SyndicatedLink::automatic_ttl () */
678
679 // SyndicatedLink::flatten_array (): flatten an array. Useful for
680 // hierarchical and namespaced elements.
681 //
682 // Given an array which may contain array or object elements in it,
683 // return a "flattened" array: a one-dimensional array of scalars
684 // containing each of the scalar elements contained within the array
685 // structure. Thus, for example, if $a['b']['c']['d'] == 'e', then the
686 // returned array for FeedWordPress::flatten_array($a) will contain a key
687 // $a['feed/b/c/d'] with value 'e'.
688 function flatten_array ($arr, $prefix = 'feed/', $separator = '/') {
689 $ret = array ();
690 if (is_array($arr)) :
691 foreach ($arr as $key => $value) :
692 if (is_scalar($value)) :
693 $ret[$prefix.$key] = $value;
694 else :
695 $ret = array_merge($ret, $this->flatten_array($value, $prefix.$key.$separator, $separator));
696 endif;
697 endforeach;
698 endif;
699 return $ret;
700 } /* SyndicatedLink::flatten_array () */
701
702 function hardcode ($what) {
703 $default = get_option("feedwordpress_hardcode_$what");
704 if ( $default === 'yes' ) :
705 // If the default is to hardcode, then we want the
706 // negation of negative(): TRUE by default and FALSE if
707 // the setting is explicitly "no"
708 $ret = !FeedWordPress::negative($this->settings, "hardcode $what");
709 else :
710 // If the default is NOT to hardcode, then we want
711 // affirmative(): FALSE by default and TRUE if the
712 // setting is explicitly "yes"
713 $ret = FeedWordPress::affirmative($this->settings, "hardcode $what");
714 endif;
715 return $ret;
716 } /* SyndicatedLink::hardcode () */
717
718 function syndicated_status ($what, $default, $fallback = true) {
719 global $wpdb;
720
721 // Use local setting if we have it
722 if ( isset($this->settings["$what status"]) ) :
723 $ret = $this->settings["$what status"];
724
725 // Or fall back to global default if we can
726 elseif ($fallback) :
727 $ret = FeedWordPress::syndicated_status($what, $default);
728
729 // Or use default value if we can't.
730 else :
731 $ret = $default;
732
733 endif;
734
735 return $wpdb->escape(trim(strtolower($ret)));
736 } /* SyndicatedLink:syndicated_status () */
737
738 function taxonomies () {
739 $post_type = $this->setting('syndicated post type', 'syndicated_post_type', 'post');
740 return get_object_taxonomies(array('object_type' => $post_type), 'names');
741 } /* SyndicatedLink::taxonomies () */
742
743 } // class SyndicatedLink
744
745