FeedWordPress - Version 2010.0903

Version Description

  • WORDPRESS 3 REQUIRED: Please note that this release of FeedWordPress requires WordPress 3.0 or later. If you are currently using a 2.x branch of WordPress, you will need to upgrade to WordPress 3 before you can successfully upgrade FeedWordPress.

  • BUGFIX: NO MORE DISAPPEARING "SYNDICATED SOURCES" PANEL; INTERNET EXPLORER UI GLITCH APPARENTLY FIXED: Several users independently reported a problem with FWP 2010.0623 and various versions of IE. A problem with the HTML markup caused IE (but not Firefox or Chrome) to completely hide the Syndicated Sources administration panel (the main list of currently-syndicated sources, and the main location for adding new sources, under the Syndication menu item) when a user added their first syndicated feed. Maddeningly, the glitch seemed to affect some IE users and not others: I was never able to reproduce the problem for myself on my own machines. However, the markup of Syndicated Sources has undergone significant changes and corrections since 2010.0623, and two independent sources who had been having this problem confirm that they no longer encounter it with the updated version. For the time being, I am going to declare this bug squashed.

  • BUGFIX: MORE PROTECTION AGAINST FATAL ERRORS FROM PLUGGABLE VERSIONS OF SimplePie: FeedWordPress now takes some precautions that should help to better avoid conflicts for users who have installed pluggable versions of SimplePie for another plugin or theme. (You may not know that you have done this; but if you've been encountering fatal errors indicating that you cannot redeclare class SimplePie, or something along those lines, there is now a better chance that those fatal errors will be eliminated.

  • PERFORMANCE: SIGNIFICANTLY REDUCED MEMORY CONSUMPTION FOR LARGE UPDATES: FeedWordPress is still a memory-hungry little module, especially when you are dealing with very large feeds. However, users should notice a significant reduction in memory overloads, especially if they update a large number of feeds at once.

  • USER INTERFACE IMPROVEMENTS: Nothing is radically different, but there's been a fair amount of extra spit and polish added, including a convenient new Dashboard widget that may save you a trip to the Syndication menu, a lot of effort to make the relationship between global and feed-by-feed settings more obvious to the user and more easily controllable, to make navigation between settings pages easier, to sand off a few rough edges, and to make other improvements on the margins. I hope you'll like how it looks.

  • ADDING MULTIPLE FEEDS: FeedWordPress now provides a convenient mode for adding multiple feeds at once, using either a copy-and-pasted list, or else an OPML file. Go to Syndication --> Syndicated Sources and check out the two new buttons underneath the New Source input box. When you have to add a number of feeds at once, this can save you considerable time and trouble.

  • IMPROVED HANDLING OF AUTHORS WITH DUPLICATE E-MAIL ADDRESS AND AUTHORS WITH NAMES WRITTEN IN FOREIGN SCRIPTS: WordPress 3 is increasingly picky about what it will accept for new author accounts, and some of the conditions it imposes can cause error conditions that prevent posts from being properly syndicated, or properly attributed, if authors happen to have identical e-mail addresses, or if users are given usernames that are written in non-Western scripts. FeedWordPress now handles these much better, and systematically works to avoid clashes between syndicated authors' account names or in their e-mail addresses, which should result in significantly better results in mapping author names to WordPress user accounts.

  • MAPPING CATEGORIES ON SYNDICATED POSTS TO TAGS NOW BETTER SUPPORTED: In previous versions, the only way for the Categories provided by a syndicated feed to be mapped into Post Tags was to instruct FWP to create new tags, rather than new categories, for unfamiliar categories from the feed. This works fine if you want tags to be the default; but if you want only a specific set of tags, there was no way to get them without getting most or all other categories imported as tags. You can now do this by creating a tag (under Posts ==> Post Tags) before importing the post; when the syndicated category matches a pre-existing tag, the incoming post will be tagged with that tag, without creating a local Post Category.

  • REL-TAG MICROFORMAT SUPPORT FOR INLINE TAGS: Syndicated posts that contain inline tags, marked up using the Rel-Tag microformat http://microformats.org/wiki/rel-tag, are now tagged with the tags provided by Rel-Tag format links.

  • MUCH GREATER CONTROL OVER CATEGORY AND TAG MAPPING: This is partly the result of building in support for a potentially endless set of custom taxonomies (see below), but in general there has been a great deal of effort towards giving you more control over how categories and tags provided by the feed are mapped into terms on the local blog. In particular, you can now force FeedWordPress to create only categories from categories and tags provided by the feed; or to create only tags; or to search both categories and tags for a match; or you can simply force it to drop all of the categories provided by the feed and use only categories or tags that you explicitly provide. In addition, you can now also choose whether to override global categories settings with a local, feed-specific setting; or whether to add together both the global categories and the local feed-specific categories -- depending on whatever your use-case may demand.

  • CUSTOM POST TYPES AND TAXONOMY SUPPORTS: This is mainly for the super-geeky, but if you use other plugins or themes that make significant use of WordPress's support for custom post types and custom taxonomies, you may be pleased to find that FeedWordPress now allows you to feed incoming posts into any custom feed type that you wish, and to map categories and tags from the feed to custom taxonomies as well as to the standard Category and Tag taxonomies.

  • STORING NAMESPACED CUSTOM FEED ELEMENTS IN POST CUSTOM FIELDS: If you would like to use FeedWordPress's support for storing custom meta-data from feed elements in the custom fields for a post (for example, to store geolocation data or iTunes media meta-data), you'll find that it's now much easier for you to access these namespaced elements. You always could access them, but in previous versions you might have to write something ugly like $(/{http://www.w3.org/2003/01/geo/wgs84_pos#}lat) just to get at the value of a <geo:lat> tag. Now, as long as you use the same mnemonic codes that the feed producer used, you should always be able to write a nice, simple expression like $(/geo:lat) to get the value of a geo:lat tag.

  • CUSTOM DIRECTORY STRUCTURE SUPPORT: if you poke at it enough, WordPress is relatively flexible about where it should store admin interface code, uploaded content, plugins, and a number of other things that occupy an important place in the WordPress directory structure. Previous versions of FeedWordPress encountered serious errors or broke entirely when used with directory structures other than the default. This should now be fixed: FWP now supports custom directory structures wherever WordPress allows them to be customized, rather than depending on the default locations. Enjoy your freedom!

  • MANY NEW FILTERS AND API UTILITY FUNCTIONS FOR ADD-ON PROGRAMMERS: There have been too many improvements to list them all in this ChangeLog, but it means that much more power and ease for folks who are customizing FeedWordPress through PHP filters or add-on modules. Fuller documentation will be put up at the Wiki at feedwordpress.radgeek.org soon.

Download this release

Release Info

Developer radgeek
Plugin Icon wp plugin FeedWordPress
Version 2010.0903
Comparing to
See all releases

Code changes from version 2010.0623 to 2010.0903

admin-ui.php CHANGED
@@ -5,6 +5,7 @@ class FeedWordPressAdminPage {
5
  var $link = NULL;
6
  var $dispatch = NULL;
7
  var $filename = NULL;
 
8
 
9
  /**
10
  * Construct the admin page object.
@@ -21,9 +22,72 @@ class FeedWordPressAdminPage {
21
  endif;
22
  } /* FeedWordPressAdminPage constructor */
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  function for_feed_settings () { return (is_object($this->link) and method_exists($this->link, 'found') and $this->link->found()); }
25
  function for_default_settings () { return !$this->for_feed_settings(); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  /*static*/ function submitted_link_id () {
28
  global $fwp_post;
29
 
@@ -99,52 +163,124 @@ class FeedWordPressAdminPage {
99
 
100
  function ajax_interface_js () {
101
  ?>
102
- <script type="text/javascript">
103
  function contextual_appearance (item, appear, disappear, value, visibleStyle, checkbox) {
104
  if (typeof(visibleStyle)=='undefined') visibleStyle = 'block';
105
 
106
  var rollup=document.getElementById(item);
107
- var newuser=document.getElementById(appear);
108
- var sitewide=document.getElementById(disappear);
109
  if (rollup) {
110
  if ((checkbox && rollup.checked) || (!checkbox && value==rollup.value)) {
111
- if (newuser) newuser.style.display=visibleStyle;
112
- if (sitewide) sitewide.style.display='none';
113
  } else {
114
- if (newuser) newuser.style.display='none';
115
- if (sitewide) sitewide.style.display=visibleStyle;
116
  }
117
  }
118
  }
119
- </script>
120
-
121
  <?php
122
  } /* FeedWordPressAdminPage::ajax_interface_js () */
123
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  function display_feed_select_dropdown() {
125
  $links = FeedWordPress::syndicated_links();
 
126
  ?>
127
- <p id="post-search">
128
- <select name="link_id" class="fwpfs" style="max-width: 20.0em;">
129
  <option value="*"<?php if ($this->for_default_settings()) : ?> selected="selected"<?php endif; ?>>- defaults for all feeds -</option>
130
  <?php if ($links) : foreach ($links as $ddlink) : ?>
131
  <option value="<?php print (int) $ddlink->link_id; ?>"<?php if (!is_null($this->link) and ($this->link->id==$ddlink->link_id)) : ?> selected="selected"<?php endif; ?>><?php print esc_html($ddlink->link_name); ?></option>
132
  <?php endforeach; endif; ?>
133
  </select>
134
- <input class="button" type="submit" name="go" value="<?php _e('Go') ?> &raquo;" />
135
- </p>
 
 
 
 
 
 
 
 
 
 
136
  <?php
137
  } /* FeedWordPressAdminPage::display_feed_select_dropdown() */
138
 
139
  function display_sheet_header ($pagename = 'Syndication', $all = false) {
140
- if (FeedWordPressCompatibility::test_version(FWP_SCHEMA_27)) :
141
- ?>
142
- <div class="icon32"><img src="<?php print esc_html(WP_PLUGIN_URL.'/'.$GLOBALS['fwp_path'].'/feedwordpress.png'); ?>" alt="" /></div>
143
- <?php
144
- endif;
145
  ?>
146
-
147
- <h2><?php print esc_html(__($pagename.($all ? '' : ' Settings'))); ?><?php if ($this->for_feed_settings()) : ?>: <?php echo esc_html($this->link->link->link_name); ?><?php endif; ?></h2>
148
  <?php
149
  }
150
 
@@ -182,20 +318,97 @@ class FeedWordPressAdminPage {
182
 
183
  /*static*/ function has_link () { return true; }
184
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  function open_sheet ($header) {
186
  // Set up prepatory AJAX stuff
 
 
 
187
  $this->ajax_interface_js();
188
- if (function_exists('add_meta_box')) :
189
- add_action(
190
- FeedWordPressCompatibility::bottom_script_hook($this->filename),
191
- /*callback=*/ array($this, 'fix_toggles'),
192
- /*priority=*/ 10000
193
- );
194
- FeedWordPressSettingsUI::ajax_nonce_fields();
195
- endif;
 
 
196
 
197
  ?>
198
- <div class="wrap" style="position:relative">
199
  <?php
200
  if (!is_null($header)) :
201
  $this->display_sheet_header($header);
@@ -203,7 +416,7 @@ class FeedWordPressAdminPage {
203
 
204
  if (!is_null($this->dispatch)) :
205
  ?>
206
- <form action="admin.php?page=<?php print $GLOBALS['fwp_path']; ?>/<?php echo basename($this->filename); ?>" method="post">
207
  <div><?php
208
  FeedWordPressCompatibility::stamp_nonce($this->dispatch);
209
  $this->stamp_link_id();
@@ -212,82 +425,216 @@ class FeedWordPressAdminPage {
212
  endif;
213
 
214
  if ($this->has_link()) :
215
- $this->display_feed_select_dropdown();
216
  $this->display_settings_scope_message();
217
  endif;
218
 
219
- if (function_exists('do_meta_boxes')) :
220
- ?>
221
- <div id="poststuff">
222
- <?php
223
- else :
224
- ?>
225
- </div> <!-- class="wrap" -->
226
- <?php
227
  endif;
228
 
229
- if (!is_null($this->dispatch)) :
230
- fwp_settings_form_single_submit();
231
  endif;
 
 
 
 
 
232
  } /* FeedWordPressAdminPage::open_sheet () */
233
 
234
  function close_sheet () {
235
- // WordPress 2.5+
236
- if (function_exists('do_meta_boxes')) :
237
- ?>
238
- </div> <!-- id="poststuff" -->
239
- <?php if (!is_null($this->dispatch)) : ?>
240
- <?php fwp_settings_form_single_submit_closer(); ?>
241
- </form>
242
- <?php endif; ?>
243
- </div> <!-- class="wrap" -->
244
- <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  endif;
246
- }
247
- } /* class FeedWordPressAdminPage */
248
 
249
- function fwp_settings_form_single_submit ($caption = NULL) {
250
- if (fwp_test_wp_version(FWP_SCHEMA_25, FWP_SCHEMA_27)) :
251
- if (is_null($caption)) : $caption = __('Save'); endif;
252
- ?>
253
- <div class="submitbox" id="submitlink">
254
- <div id="previewview"></div>
255
- <div class="inside"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
 
257
- <p class="submit">
258
- <input type="submit" name="save" value="<?php print $caption; ?>" />
259
- </p>
260
- </div>
261
- <?php
262
- endif;
263
- }
 
 
 
 
 
264
 
265
- function fwp_settings_form_periodic_submit ($caption = NULL) {
266
- if (!fwp_test_wp_version(FWP_SCHEMA_25)) :
267
- if (is_null($caption)) : $caption = __('Save Changes &raquo;'); endif;
268
- ?>
269
- <p class="submit">
270
- <input type="submit" name="save" value="<?php print $caption; ?>" />
271
- </p>
272
- <?php
273
- endif;
274
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
 
276
- function fwp_settings_form_single_submit_closer ($caption = NULL) {
277
- if (fwp_test_wp_version(FWP_SCHEMA_27)) :
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  if (is_null($caption)) : $caption = __('Save Changes'); endif;
279
- ?>
280
  <p class="submit">
281
  <input class="button-primary" type="submit" name="save" value="<?php print $caption; ?>" />
282
  </p>
283
- <?php
284
- endif;
285
- }
286
 
287
  function fwp_authors_single_submit ($link = NULL) {
288
- global $wp_db_version;
289
-
290
- if (fwp_test_wp_version(FWP_SCHEMA_25)) :
291
  ?>
292
  <div class="submitbox" id="submitlink">
293
  <div id="previewview">
@@ -300,23 +647,14 @@ function fwp_authors_single_submit ($link = NULL) {
300
  </p>
301
  </div>
302
  <?php
303
- endif;
304
  }
305
 
306
  function fwp_option_box_opener ($legend, $id, $class = "stuffbox") {
307
- // WordPress 2.5+
308
- if (FeedWordPressCompatibility::test_version(FWP_SCHEMA_25)) :
309
  ?>
310
  <div id="<?php print $id; ?>" class="<?php print $class; ?>">
311
  <h3><?php print htmlspecialchars($legend); ?></h3>
312
  <div class="inside">
313
  <?php
314
- else :
315
- ?>
316
- <div class="wrap">
317
- <h2><?php print htmlspecialchars($legend); ?></h2>
318
- <?php
319
- endif;
320
  }
321
 
322
  function fwp_option_box_closer () {
@@ -333,16 +671,14 @@ function fwp_option_box_closer () {
333
  endif;
334
  }
335
 
336
- function fwp_tags_box ($tags, $object) {
337
  if (!is_array($tags)) : $tags = array(); endif;
338
-
339
  $desc = "<p style=\"font-size:smaller;font-style:bold;margin:0\">Tag $object as...</p>";
340
 
341
- if (fwp_test_wp_version(FWP_SCHEMA_29)) : // WordPress 2.9+
342
- print $desc;
343
- $tax_name = 'post_tag';
344
- $helps = __('Separate tags with commas.');
345
- $box['title'] = __('Tags');
346
  ?>
347
  <div class="tagsdiv" id="<?php echo $tax_name; ?>">
348
  <div class="jaxtag">
@@ -353,51 +689,30 @@ function fwp_tags_box ($tags, $object) {
353
  <div class="ajaxtag hide-if-no-js">
354
  <label class="screen-reader-text" for="new-tag-<?php echo $tax_name; ?>"><?php echo $box['title']; ?></label>
355
  <div class="taghint"><?php _e('Add new tag'); ?></div>
 
356
  <input type="text" id="new-tag-<?php echo $tax_name; ?>" name="newtag[<?php echo $tax_name; ?>]" class="newtag form-input-tip" size="16" autocomplete="off" value="" />
357
  <input type="button" class="button tagadd" value="<?php esc_attr_e('Add'); ?>" tabindex="3" />
 
358
  </div></div>
359
  <p class="howto"><?php echo $helps; ?></p>
360
  <div class="tagchecklist"></div>
361
  </div>
362
  <p class="hide-if-no-js"><a href="#titlediv" class="tagcloud-link" id="link-<?php echo $tax_name; ?>"><?php printf( __('Choose from the most used tags in %s'), $box['title'] ); ?></a></p>
363
- <?php
364
- elseif (fwp_test_wp_version(FWP_SCHEMA_28)) : // WordPress 2.8+
365
- ?>
366
- <?php print $desc; ?>
367
- <div class="tagsdiv" id="post_tag">
368
- <div class="jaxtag">
369
- <div class="nojs-tags hide-if-js">
370
- <p><?php _e('Add or remove tags'); ?></p>
371
- <textarea name="tax_input[post_tag]" class="the-tags" id="tax-input[post_tag]"><?php echo implode(",", $tags); ?></textarea>
372
- </div>
373
-
374
- <span class="ajaxtag hide-if-no-js">
375
- <label class="screen-reader-text" for="new-tag-post_tag"><?php _e('Tags'); ?></label>
376
- <input type="text" id="new-tag-post_tag" name="newtag[post_tag]" class="newtag form-input-tip" size="16" autocomplete="off" value="<?php esc_attr_e('Add new tag'); ?>" />
377
- <input type="button" class="button tagadd" value="<?php esc_attr_e('Add'); ?>" />
378
- </span>
379
- </div>
380
- <p class="howto"><?php echo __('Separate tags with commas.'); ?></p>
381
- <div class="tagchecklist"></div>
382
- </div>
383
- <p class="tagcloud-link hide-if-no-js"><a href="#titlediv" class="tagcloud-link" id="link-post_tag"><?php printf( __('Choose from the most used tags in %s'), 'Post Tags'); ?></a></p>
384
- </div>
385
- </div>
386
- <?php
387
- else :
388
- ?>
389
- <?php print $desc; ?>
390
- <p id="jaxtag"><input type="text" name="tags_input" class="tags-input" id="tags-input" size="40" tabindex="3" value="<?php echo implode(",", $tags); ?>" /></p>
391
- <div id="tagchecklist"></div>
392
- </div>
393
- </div>
394
- <?php
395
- endif;
396
  }
397
 
398
- function fwp_category_box ($checked, $object, $tags = array(), $prefix = '') {
399
  global $wp_db_version;
400
 
 
 
 
 
 
 
 
 
 
401
  if (strlen($prefix) > 0) :
402
  $idPrefix = $prefix.'-';
403
  $idSuffix = "-".$prefix;
@@ -409,47 +724,58 @@ function fwp_category_box ($checked, $object, $tags = array(), $prefix = '') {
409
  endif;
410
 
411
  ?>
412
- <div id="<?php print $idPrefix; ?>taxonomy-category" class="feedwordpress-category-div">
413
- <ul id="<?php print $idPrefix; ?>category-tabs" class="category-tabs">
414
- <li class="ui-tabs-selected tabs"><a href="#<?php print $idPrefix; ?>categories-all" tabindex="3"><?php _e( 'All posts' ); ?></a>
415
- <p style="font-size:smaller;font-style:bold;margin:0">Give <?php print $object; ?> these categories</p>
416
  </li>
417
  </ul>
418
 
419
- <div id="<?php print $idPrefix; ?>categories-all" class="tabs-panel">
420
- <ul id="<?php print $idPrefix; ?>categorychecklist" class="list:category categorychecklist form-no-clear">
421
- <?php fwp_category_checklist(NULL, false, $checked, $prefix) ?>
 
422
  </ul>
423
  </div>
424
 
425
- <div id="<?php print $idPrefix; ?>category-adder" class="category-adder wp-hidden-children">
426
- <h4><a id="<?php print $idPrefix; ?>category-add-toggle" class="category-add-toggle" href="#<?php print $idPrefix; ?>category-add" class="hide-if-no-js" tabindex="3"><?php _e( '+ Add New Category' ); ?></a></h4>
427
- <p id="<?php print $idPrefix; ?>category-add" class="wp-hidden-child">
428
  <?php
429
- if (FeedWordPressCompatibility::test_version(FWP_SCHEMA_30)) :
430
- $newcat = 'newcategory'; // Well, thank God they added "egory" before WP 3.0 came out.
431
- else :
 
 
432
  $newcat = 'newcat';
433
  endif;
434
  ?>
435
-
436
- <input type="text" name="<?php print $newcat; ?>" id="<?php print $idPrefix; ?>newcategory" class="newcategory form-required form-input-tip" value="<?php _e( 'New category name' ); ?>" tabindex="3" />
437
- <label class="screen-reader-text" for="<?php print $idPrefix; ?>newcategory-parent"><?php _e('Parent Category:'); ?></label>
438
- <?php wp_dropdown_categories( array(
 
 
 
 
 
 
 
 
439
  'hide_empty' => 0,
440
- 'id' => $idPrefix.'newcategory-parent',
441
- 'class' => 'newcategory-parent',
442
  'name' => $newcat.'_parent',
443
  'orderby' => 'name',
444
  'hierarchical' => 1,
445
  'show_option_none' => __('Parent category'),
446
  'tab_index' => 3,
447
  ) ); ?>
448
- <input type="button" id="<?php print $idPrefix; ?>category-add-sumbit" class="add:<?php print $idPrefix; ?>categorychecklist:category-add add-categorychecklist-category-add button" value="<?php _e( 'Add' ); ?>" tabindex="3" />
449
  <?php /* wp_nonce_field currently doesn't let us set an id different from name, but we need a non-unique name and a unique id */ ?>
450
- <input type="hidden" id="_ajax_nonce<?php print esc_html($idSuffix); ?>" name="_ajax_nonce" value="<?php print wp_create_nonce('add-category'); ?>" />
451
- <input type="hidden" id="_ajax_nonce-add-category<?php print esc_html($idSuffix); ?>" name="_ajax_nonce-add-category" value="<?php print wp_create_nonce('add-category'); ?>" />
452
- <span id="<?php print $idPrefix; ?>category-ajax-response" class="category-ajax-response"></span>
453
  </p>
454
  </div>
455
 
@@ -472,24 +798,18 @@ function update_feeds_finish ($feed, $added, $dt) {
472
  else :
473
  echo " completed in $dt second".(($dt==1)?'':'s')."</li>\n";
474
  endif;
 
475
  }
476
 
477
  function fwp_author_list () {
478
  global $wpdb;
479
  $ret = array();
480
 
481
- // display_name introduced in WP 2.0
482
- if (fwp_test_wp_version(FWP_SCHEMA_20)) :
483
- $name_column = 'display_name';
484
- else :
485
- $name_column = 'user_nickname';
486
- endif;
487
-
488
- $users = $wpdb->get_results("SELECT * FROM $wpdb->users ORDER BY {$name_column}");
489
  if (is_array($users)) :
490
  foreach ($users as $user) :
491
  $id = (int) $user->ID;
492
- $ret[$id] = $user->{$name_column};
493
  if (strlen(trim($ret[$id])) == 0) :
494
  $ret[$id] = $user->user_login;
495
  endif;
@@ -524,62 +844,25 @@ class FeedWordPressSettingsUI {
524
  wp_register_script('feedwordpress-elements', WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-elements.js');
525
  wp_enqueue_script('feedwordpress-elements');
526
  }
527
-
528
- function instead_of_posts_box ($link_id = null) {
529
- if (!is_null($link_id)) :
530
- $from_this_feed = 'from this feed';
531
- $by_default = '';
532
- $id_param = "&amp;link_id=".$link_id;
533
- else :
534
- $from_this_feed = 'from syndicated feeds';
535
- $by_default = " by default";
536
- $id_param = "";
537
- endif;
538
- ?>
539
- <p>Use the <a href="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/posts-page.php<?php print $id_param; ?>"><?php _e('Posts & Links'); ?></a>
540
- settings page to set up how new posts <?php print $from_this_feed; ?> will be published<?php $by_default; ?>, whether they will accept
541
- comments and pings, any custom fields that should be set on each post, etc.</p>
542
- <?php
543
- } /* FeedWordPressSettingsUI::instead_of_posts_box () */
544
-
545
- function instead_of_authors_box ($link_id = null) {
546
- if (!is_null($link_id)) :
547
- $from_this_feed = 'from this feed';
548
- $by_default = '';
549
- $id_param = "&amp;link_id=".$link_id;
550
- else :
551
- $from_this_feed = 'from syndicated feeds';
552
- $by_default = " by default";
553
- $id_param = "";
554
- endif;
555
 
556
- ?>
557
- <p>Use the <a
558
- href="admin.php?page=<?php print $GLOBALS['fwp_path']
559
- ?>/authors-page.php<?php print $id_param; ?>"><?php _e('Authors');
560
- ?></a> settings page to set up how new posts
561
- <?php print $from_this_feed; ?> will be assigned to
562
- authors.</p>
563
- <?php
564
- } /* FeedWordPressSettingsUI::instead_of_authors_box () */
 
 
 
 
 
 
 
 
565
 
566
- function instead_of_categories_box ($link_id = null) {
567
- if (!is_null($link_id)) :
568
- $from_this_feed = 'from this feed';
569
- $by_default = '';
570
- $id_param = "&amp;link_id=".$link_id;
571
- else :
572
- $from_this_feed = 'from syndicated feeds';
573
- $by_default = " by default";
574
- $id_param = "";
575
- endif;
576
-
577
- ?>
578
- <p>Use the <a href="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/categories-page.php<?php print $id_param; ?>"><?php _e('Categories'.FEEDWORDPRESS_AND_TAGS); ?></a>
579
- settings page to set up how new posts <?php print $from_this_feed; ?> are assigned categories <?php if (FeedWordPressCompatibility::post_tags()) : ?>or tags<?php endif; ?><?php print $by_default; ?>.</p>
580
- <?php
581
- } /* FeedWordPressSettingsUI::instead_of_categories_box () */
582
-
583
  /*static*/ function ajax_nonce_fields () {
584
  if (function_exists('wp_nonce_field')) :
585
  echo "<form style='display: none' method='get' action=''>\n<p>\n";
@@ -592,34 +875,21 @@ settings page to set up how new posts <?php print $from_this_feed; ?> are assign
592
  /*static*/ function fix_toggles_js ($context) {
593
  ?>
594
  <script type="text/javascript">
595
- jQuery(document).ready( function($) {
596
- <?php if (FeedWordPressCompatibility::test_version(FWP_SCHEMA_29)) : ?>
597
- if ( $('#post_tag').length ) {
598
- tagBox.init();
599
- }
600
- <?php endif; ?>
601
- <?php if (FeedWordPressCompatibility::test_version(FWP_SCHEMA_25, FWP_SCHEMA_27)) : ?>
602
- // In case someone got here first...
603
- jQuery('.postbox h3').unbind('click');
604
-
605
- add_postbox_toggles('<?php print $context; ?>');
606
- <?php elseif (FeedWordPressCompatibility::test_version(FWP_SCHEMA_27)) : ?>
607
- // In case someone got here first...
608
- $('.postbox h3, .postbox .handlediv').unbind('click');
609
- $('.postbox h3 a').unbind('click');
610
- $('.hide-postbox-tog').unbind('click');
611
- $('.columns-prefs input[type="radio"]').unbind('click');
612
- $('.meta-box-sortables').sortable('destroy');
613
 
614
- postboxes.add_postbox_toggles('<?php print $context; ?>');
615
- <?php endif; ?>
616
  } );
617
  </script>
618
  <?php
619
  } /* FeedWordPressSettingsUI::fix_toggles_js () */
620
 
621
  function magic_input_tip_js ($id) {
622
- if (FeedWordPressCompatibility::test_version(FWP_SCHEMA_25)) :
623
  ?>
624
  <script type="text/javascript">
625
  jQuery(document).ready( function () {
@@ -637,7 +907,6 @@ settings page to set up how new posts <?php print $from_this_feed; ?> are assign
637
  } );
638
  </script>
639
  <?php
640
- endif;
641
  } /* FeedWordPressSettingsUI::magic_input_tip_js () */
642
  } /* class FeedWordPressSettingsUI */
643
 
@@ -664,131 +933,174 @@ function fwp_insert_new_user ($newuser_name) {
664
  return $ret;
665
  } /* fwp_insert_new_user () */
666
 
 
 
 
 
 
 
 
667
  function fwp_add_meta_box ($id, $title, $callback, $page, $context = 'advanced', $priority = 'default', $callback_args = null) {
668
- if (function_exists('add_meta_box')) :
669
- return add_meta_box($id, $title, $callback, $page, $context, $priority, $callback_args);
670
- else :
671
- /* Re-used as per terms of the GPL from add_meta_box() in WordPress 2.8.1 wp-admin/includes/template.php. */
672
- global $wp_meta_boxes;
673
-
674
- if ( !isset($wp_meta_boxes) )
675
- $wp_meta_boxes = array();
676
- if ( !isset($wp_meta_boxes[$page]) )
677
- $wp_meta_boxes[$page] = array();
678
- if ( !isset($wp_meta_boxes[$page][$context]) )
679
- $wp_meta_boxes[$page][$context] = array();
680
-
681
- foreach ( array_keys($wp_meta_boxes[$page]) as $a_context ) {
682
- foreach ( array('high', 'core', 'default', 'low') as $a_priority ) {
683
- if ( !isset($wp_meta_boxes[$page][$a_context][$a_priority][$id]) )
684
- continue;
685
-
686
- // If a core box was previously added or removed by a plugin, don't add.
687
- if ( 'core' == $priority ) {
688
- // If core box previously deleted, don't add
689
- if ( false === $wp_meta_boxes[$page][$a_context][$a_priority][$id] )
690
- return;
691
- // If box was added with default priority, give it core priority to maintain sort order
692
- if ( 'default' == $a_priority ) {
693
- $wp_meta_boxes[$page][$a_context]['core'][$id] = $wp_meta_boxes[$page][$a_context]['default'][$id];
694
- unset($wp_meta_boxes[$page][$a_context]['default'][$id]);
695
- }
696
- return;
697
- }
698
- // If no priority given and id already present, use existing priority
699
- if ( empty($priority) ) {
700
- $priority = $a_priority;
701
- // else if we're adding to the sorted priortiy, we don't know the title or callback. Glab them from the previously added context/priority.
702
- } elseif ( 'sorted' == $priority ) {
703
- $title = $wp_meta_boxes[$page][$a_context][$a_priority][$id]['title'];
704
- $callback = $wp_meta_boxes[$page][$a_context][$a_priority][$id]['callback'];
705
- $callback_args = $wp_meta_boxes[$page][$a_context][$a_priority][$id]['args'];
706
- }
707
- // An id can be in only one priority and one context
708
- if ( $priority != $a_priority || $context != $a_context )
709
- unset($wp_meta_boxes[$page][$a_context][$a_priority][$id]);
710
- }
711
- }
712
-
713
- if ( empty($priority) )
714
- $priority = 'low';
715
-
716
- if ( !isset($wp_meta_boxes[$page][$context][$priority]) )
717
- $wp_meta_boxes[$page][$context][$priority] = array();
718
-
719
- $wp_meta_boxes[$page][$context][$priority][$id] = array('id' => $id, 'title' => $title, 'callback' => $callback, 'args' => $callback_args);
720
- endif;
721
  } /* function fwp_add_meta_box () */
722
 
723
  function fwp_do_meta_boxes($page, $context, $object) {
724
- if (function_exists('do_meta_boxes')) :
725
- $ret = do_meta_boxes($page, $context, $object);
726
 
727
- // Avoid JavaScript error from WordPress 2.5 bug
728
  ?>
729
  <div style="display: none">
730
  <div id="tags-input"></div> <!-- avoid JS error from WP 2.5 bug -->
731
  </div>
732
  <?php
733
- return $ret;
734
- else :
735
- /* Derived as per terms of the GPL from do_meta_boxes() in WordPress 2.8.1 wp-admin/includes/template.php. */
736
- global $wp_meta_boxes;
737
- static $already_sorted = false;
738
-
739
- //do_action('do_meta_boxes', $page, $context, $object);
740
-
741
- echo "<div id='$context-sortables' class='meta-box-sortables'>\n";
742
-
743
- $i = 0;
744
- do {
745
- if ( !isset($wp_meta_boxes) || !isset($wp_meta_boxes[$page]) || !isset($wp_meta_boxes[$page][$context]) )
746
- break;
747
-
748
- foreach ( array('high', 'sorted', 'core', 'default', 'low') as $priority ) {
749
- if ( isset($wp_meta_boxes[$page][$context][$priority]) ) {
750
- foreach ( (array) $wp_meta_boxes[$page][$context][$priority] as $box ) {
751
- if ( false == $box || ! $box['title'] )
752
- continue;
753
- $i++;
754
- fwp_option_box_opener($box['title'], $box['id'], 'postbox' /*. postbox_classes($box['id'], $page)*/);
755
- call_user_func($box['callback'], $object, $box);
756
- fwp_option_box_closer();
757
-
758
- if (is_object($object) and method_exists($object, 'interstitial')) :
759
- $object->interstitial();
760
- else :
761
- // Submit button for WP 1.5, early 2.x style
762
- fwp_settings_form_periodic_submit();
763
- endif;
764
- }
765
- }
766
- }
767
- } while(0);
768
-
769
- echo "</div>";
770
-
771
- return $i;
772
- endif;
773
  } /* function fwp_do_meta_boxes() */
774
 
775
  function fwp_remove_meta_box($id, $page, $context) {
776
- if (function_exists('remove_meta_box')) :
777
- return remove_meta_box($id, $page, $context);
778
- else :
779
- /* Re-used as per terms of the GPL from remove_meta_box() in WordPress 2.8.1 wp-admin/includes/template.php */
780
- global $wp_meta_boxes;
781
-
782
- if ( !isset($wp_meta_boxes) )
783
- $wp_meta_boxes = array();
784
- if ( !isset($wp_meta_boxes[$page]) )
785
- $wp_meta_boxes[$page] = array();
786
- if ( !isset($wp_meta_boxes[$page][$context]) )
787
- $wp_meta_boxes[$page][$context] = array();
788
 
789
- foreach ( array('high', 'core', 'default', 'low') as $priority )
790
- $wp_meta_boxes[$page][$context][$priority][$id] = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
791
  endif;
792
- } /* function fwp_remove_meta_box() */
793
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
794
 
5
  var $link = NULL;
6
  var $dispatch = NULL;
7
  var $filename = NULL;
8
+ var $pagenames = array();
9
 
10
  /**
11
  * Construct the admin page object.
22
  endif;
23
  } /* FeedWordPressAdminPage constructor */
24
 
25
+ function pageslug () {
26
+ $slug = preg_replace('/FeedWordPress(.*)Page/', '$1', get_class($this));
27
+ return strtolower($slug);
28
+ }
29
+
30
+ function pagename ($context = NULL) {
31
+ if (is_null($context)) :
32
+ $context = 'default';
33
+ endif;
34
+
35
+ if (isset($this->pagenames[$context])) :
36
+ $name = $this->pagenames[$context];
37
+ elseif (isset($tis->pagenames['default'])) :
38
+ $name = $this->pagenames['default'];
39
+ else :
40
+ $name = $this->pageslug();
41
+ endif;
42
+ return __($name);
43
+ } /* FeedWordPressAdminPage::pagename () */
44
+
45
+ function accept_POST ($post) {
46
+ if ($this->save_requested_in($post)) : // User mashed Save Changes
47
+ $this->save_settings($post);
48
+ endif;
49
+ do_action($this->dispatch.'_post', $post, $this);
50
+ }
51
+
52
+ function save_settings ($post) {
53
+ if ($this->for_feed_settings()) :
54
+ // Save settings
55
+ $this->link->save_settings(/*reload=*/ true);
56
+ $this->updated = true;
57
+
58
+ // Reset, reload
59
+ $link_id = $this->link->id;
60
+ unset($this->link);
61
+ $this->link = new SyndicatedLink($link_id);
62
+ else :
63
+ $this->updated = true;
64
+ endif;
65
+ do_action($this->dispatch.'_save', $post, $this);
66
+ } /* FeedWordPressAdminPage::save_settings () */
67
+
68
  function for_feed_settings () { return (is_object($this->link) and method_exists($this->link, 'found') and $this->link->found()); }
69
  function for_default_settings () { return !$this->for_feed_settings(); }
70
 
71
+ function update_setting ($names, $value, $default = 'default') {
72
+ if (is_string($names)) :
73
+ $feed_name = $names;
74
+ $global_name = 'feedwordpress_'.preg_replace('![\s/]+!', '_', $names);
75
+ else :
76
+ $feed_name = $names['feed'];
77
+ $global_name = 'feedwordpress_'.$names['global'];
78
+ endif;
79
+
80
+ if ($this->for_feed_settings()) : // Update feed-specific setting
81
+ $this->link->update_setting($feed_name, $value, $default);
82
+ else : // Update global setting
83
+ update_option($global_name, $value);
84
+ endif;
85
+ } /* FeedWordPressAdminPage::update_setting () */
86
+
87
+ function save_requested_in ($post) {
88
+ return (isset($post['save']) or isset($post['submit']));
89
+ }
90
+
91
  /*static*/ function submitted_link_id () {
92
  global $fwp_post;
93
 
163
 
164
  function ajax_interface_js () {
165
  ?>
 
166
  function contextual_appearance (item, appear, disappear, value, visibleStyle, checkbox) {
167
  if (typeof(visibleStyle)=='undefined') visibleStyle = 'block';
168
 
169
  var rollup=document.getElementById(item);
 
 
170
  if (rollup) {
171
  if ((checkbox && rollup.checked) || (!checkbox && value==rollup.value)) {
172
+ jQuery('#'+disappear).hide();
173
+ jQuery('#'+appear).show(600);
174
  } else {
175
+ jQuery('#'+appear).hide();
176
+ jQuery('#'+disappear).show(600);
177
  }
178
  }
179
  }
 
 
180
  <?php
181
  } /* FeedWordPressAdminPage::ajax_interface_js () */
182
 
183
+ function display_feed_settings_page_links ($params = array()) {
184
+ global $fwp_path;
185
+
186
+ $params = wp_parse_args($params, array(
187
+ 'before' => '',
188
+ 'between' => ' | ',
189
+ 'after' => '',
190
+ 'long' => false,
191
+ 'subscription' => $this->link,
192
+ ));
193
+ $sub = $params['subscription'];
194
+
195
+ $links = array(
196
+ "Feed" => array('page' => 'feeds-page.php', 'long' => 'Feeds & Updates'),
197
+ "Posts" => array('page' => 'posts-page.php', 'long' => 'Posts & Links'),
198
+ "Authors" => array('page' => 'authors-page.php', 'long' => 'Authors'),
199
+ 'Categories' => array('page' => 'categories-page.php', 'long' => 'Categories'.FEEDWORDPRESS_AND_TAGS),
200
+ );
201
+
202
+ $hrefPrefix = 'admin.php?';
203
+
204
+ $link_id = NULL;
205
+ if (is_object($sub)) :
206
+ if (method_exists($sub, 'found')) :
207
+ if ($sub->found()) :
208
+ $link_id = $sub->link->link_id;
209
+ endif;
210
+ else :
211
+ $link_id = $sub->link_id;
212
+ endif;
213
+ endif;
214
+
215
+ if (!is_null($link_id)) :
216
+ $urlParam = "link_id={$link_id}";
217
+ $hrefPrefix .= $urlParam."&";
218
+ $urlSuffix = "&".$urlParam;
219
+ else :
220
+ $urlParam = '';
221
+ endif;
222
+ $hrefPrefix .= "page=${fwp_path}/";
223
+
224
+ print $params['before']; $first = true;
225
+ foreach ($links as $label => $link) :
226
+ if (!$first) : print $params['between']; endif;
227
+
228
+ if (isset($link['url'])) : $url = $link['url'].$urlSuffix;
229
+ else : $url = $hrefPrefix.$link['page'];
230
+ endif;
231
+ $url = esc_html($url);
232
+
233
+ if ($link['page']==basename($this->filename)) :
234
+ print "<strong>";
235
+ else :
236
+ print "<a href=\"${url}\">";
237
+ endif;
238
+
239
+ if ($params['long']) : print esc_html(__($link['long']));
240
+ else : print esc_html(__($label));
241
+ endif;
242
+
243
+ if ($link['page']==basename($this->filename)) :
244
+ print "</strong>";
245
+ else :
246
+ print "</a>";
247
+ endif;
248
+
249
+ $first = false;
250
+ endforeach;
251
+ print $params['after'];
252
+ } /* FeedWordPressAdminPage::display_feed_settings_page_links */
253
+
254
  function display_feed_select_dropdown() {
255
  $links = FeedWordPress::syndicated_links();
256
+
257
  ?>
258
+ <div id="fwpfs-container"><ul class="subsubsub">
259
+ <li><select name="link_id" class="fwpfs" style="max-width: 20.0em;">
260
  <option value="*"<?php if ($this->for_default_settings()) : ?> selected="selected"<?php endif; ?>>- defaults for all feeds -</option>
261
  <?php if ($links) : foreach ($links as $ddlink) : ?>
262
  <option value="<?php print (int) $ddlink->link_id; ?>"<?php if (!is_null($this->link) and ($this->link->id==$ddlink->link_id)) : ?> selected="selected"<?php endif; ?>><?php print esc_html($ddlink->link_name); ?></option>
263
  <?php endforeach; endif; ?>
264
  </select>
265
+ <input class="button" type="submit" name="go" value="<?php _e('Go') ?> &raquo;" /></li>
266
+
267
+ <?php
268
+ $this->display_feed_settings_page_links(array(
269
+ 'before' => '<li>',
270
+ 'between' => "</li>\n<li>",
271
+ 'after' => '</li>',
272
+ 'subscription' => $this->link,
273
+ ));
274
+ ?>
275
+ </ul>
276
+ </div>
277
  <?php
278
  } /* FeedWordPressAdminPage::display_feed_select_dropdown() */
279
 
280
  function display_sheet_header ($pagename = 'Syndication', $all = false) {
 
 
 
 
 
281
  ?>
282
+ <div class="icon32"><img src="<?php print esc_html(WP_PLUGIN_URL.'/'.$GLOBALS['fwp_path'].'/feedwordpress.png'); ?>" alt="" /></div>
283
+ <h2><?php print esc_html(__($pagename.($all ? '' : ' Settings'))); ?><?php if ($this->for_feed_settings()) : ?>: <?php echo esc_html($this->link->name(/*from feed=*/ false)); ?><?php endif; ?></h2>
284
  <?php
285
  }
286
 
318
 
319
  /*static*/ function has_link () { return true; }
320
 
321
+ function form_action ($filename = NULL) {
322
+ global $fwp_path;
323
+
324
+ if (is_null($filename)) :
325
+ $filename = basename($this->filename);
326
+ endif;
327
+ return "admin.php?page=${fwp_path}/".$filename;
328
+ } /* FeedWordPressAdminPage::form_action () */
329
+
330
+ function update_message () {
331
+ return NULL;
332
+ }
333
+
334
+ function display () {
335
+ if (FeedWordPress::needs_upgrade()) :
336
+ fwp_upgrade_page();
337
+ return;
338
+ endif;
339
+
340
+ FeedWordPressCompatibility::validate_http_request(/*action=*/ $this->dispatch, /*capability=*/ 'manage_links');
341
+
342
+ ////////////////////////////////////////////////
343
+ // Process POST request, if any ////////////////
344
+ ////////////////////////////////////////////////
345
+ if (strtoupper($_SERVER['REQUEST_METHOD'])=='POST') :
346
+ $this->accept_POST($GLOBALS['fwp_post']);
347
+ else :
348
+ $this->updated = false;
349
+ endif;
350
+
351
+ ////////////////////////////////////////////////
352
+ // Prepare settings page ///////////////////////
353
+ ////////////////////////////////////////////////
354
+
355
+ $this->display_update_notice_if_updated(
356
+ $this->pagename('settings-update'),
357
+ $this->update_message()
358
+ );
359
+
360
+ $this->open_sheet($this->pagename('open-sheet'));
361
+ ?>
362
+ <div id="post-body">
363
+ <?php
364
+ foreach ($this->boxes_by_methods as $method => $row) :
365
+ if (is_array($row)) :
366
+ $id = $row['id'];
367
+ $title = $row['title'];
368
+ else :
369
+ $id = 'feedwordpress_'.$method;
370
+ $title = $row;
371
+ endif;
372
+
373
+ add_meta_box(
374
+ /*id=*/ $id,
375
+ /*title=*/ $title,
376
+ /*callback=*/ array(&$this, $method),
377
+ /*page=*/ $this->meta_box_context(),
378
+ /*context=*/ $this->meta_box_context()
379
+ );
380
+ endforeach;
381
+ do_action($this->dispatch.'_meta_boxes', $this);
382
+ ?>
383
+ <div class="metabox-holder">
384
+ <?php
385
+ fwp_do_meta_boxes($this->meta_box_context(), $this->meta_box_context(), $this);
386
+ ?>
387
+ </div> <!-- class="metabox-holder" -->
388
+ </div> <!-- id="post-body" -->
389
+ <?php $this->close_sheet(); ?>
390
+ <?php
391
+ }
392
+
393
  function open_sheet ($header) {
394
  // Set up prepatory AJAX stuff
395
+ ?>
396
+ <script type="text/javascript">
397
+ <?php
398
  $this->ajax_interface_js();
399
+ ?>
400
+ </script>
401
+
402
+ <?php
403
+ add_action(
404
+ FeedWordPressCompatibility::bottom_script_hook($this->filename),
405
+ /*callback=*/ array($this, 'fix_toggles'),
406
+ /*priority=*/ 10000
407
+ );
408
+ FeedWordPressSettingsUI::ajax_nonce_fields();
409
 
410
  ?>
411
+ <div class="wrap feedwordpress-admin" id="feedwordpress-admin-<?php print $this->pageslug(); ?>">
412
  <?php
413
  if (!is_null($header)) :
414
  $this->display_sheet_header($header);
416
 
417
  if (!is_null($this->dispatch)) :
418
  ?>
419
+ <form action="<?php print $this->form_action(); ?>" method="post">
420
  <div><?php
421
  FeedWordPressCompatibility::stamp_nonce($this->dispatch);
422
  $this->stamp_link_id();
425
  endif;
426
 
427
  if ($this->has_link()) :
 
428
  $this->display_settings_scope_message();
429
  endif;
430
 
431
+ ?><div class="tablenav"><?php
432
+ if (!is_null($this->dispatch)) :
433
+ ?><div class="alignright"><?php
434
+ $this->save_button();
435
+ ?></div><?php
 
 
 
436
  endif;
437
 
438
+ if ($this->has_link()) :
439
+ $this->display_feed_select_dropdown();
440
  endif;
441
+ ?>
442
+ </div>
443
+
444
+ <div id="poststuff">
445
+ <?php
446
  } /* FeedWordPressAdminPage::open_sheet () */
447
 
448
  function close_sheet () {
449
+ ?>
450
+
451
+ </div> <!-- id="poststuff" -->
452
+ <?php
453
+ if (!is_null($this->dispatch)) :
454
+ $this->save_button();
455
+ print "</form>\n";
456
+ endif;
457
+ ?>
458
+ </div> <!-- class="wrap" -->
459
+
460
+ <?php
461
+ } /* FeedWordPressAdminPage::close_sheet () */
462
+
463
+ function setting_radio_control ($localName, $globalName, $options, $params = array()) {
464
+ global $fwp_path;
465
+
466
+ if (isset($params['filename'])) : $filename = $params['filename'];
467
+ else : $filename = basename($this->filename);
468
+ endif;
469
+
470
+ if (isset($params['site-wide-url'])) : $href = $params['site-wide-url'];
471
+ else : $href = "admin.php?page=${fwp_path}/${filename}";
472
+ endif;
473
+
474
+ if (isset($params['setting-default'])) : $settingDefault = $params['setting-default'];
475
+ else : $settingDefault = NULL;
476
+ endif;
477
+
478
+ if (isset($params['global-setting-default'])) : $globalSettingDefault = $params['global-setting-default'];
479
+ else : $globalSettingDefault = $settingDefault;
480
  endif;
 
 
481
 
482
+ $globalSetting = get_option('feedwordpress_'.$globalName, $globalSettingDefault);
483
+ if ($this->for_feed_settings()) :
484
+ $setting = $this->link->setting($localName, NULL, $settingDefault);
485
+ else :
486
+ $setting = $globalSetting;
487
+ endif;
488
+
489
+ if (isset($params['offer-site-wide'])) : $offerSiteWide = $params['offer-site-wide'];
490
+ else : $offerSiteWide = $this->for_feed_settings();
491
+ endif;
492
+
493
+ // This allows us to provide an alternative set of human-readable
494
+ // labels for each potential value. For use in Currently: line.
495
+ if (isset($params['labels'])) : $labels = $params['labels'];
496
+ else : $labels = $options;
497
+ endif;
498
+
499
+ if (isset($params['input-name'])) : $inputName = $params['input-name'];
500
+ else : $inputName = $globalName;
501
+ endif;
502
+
503
+ if (isset($params['default-input-id'])) : $defaultInputId = $params['default-input-id'];
504
+ else : $defaultInputId = NULL;
505
+ endif;
506
 
507
+ if (isset($params['default-input-id-no'])) : $defaultInputIdNo = $params['default-input-id-no'];
508
+ elseif (!is_null($defaultInputId)) : $defaultInputIdNo = $defaultInputId.'-no';
509
+ else : $defaultInputIdNo = NULL;
510
+ endif;
511
+
512
+ // This allows us to either include the site-default setting as
513
+ // one of the options within the radio box, or else as a simple
514
+ // yes/no toggle that controls whether or not to check another
515
+ // set of inputs.
516
+ if (isset($params['default-input-name'])) : $defaultInputName = $params['default-input-name'];
517
+ else : $defaultInputName = $inputName;
518
+ endif;
519
 
520
+ if ($defaultInputName != $inputName) :
521
+ $defaultInputValue = 'yes';
522
+ else :
523
+ $defaultInputValue = (
524
+ isset($params['default-input-value'])
525
+ ? $params['default-input-value']
526
+ : 'site-default'
527
+ );
528
+ endif;
529
+
530
+ $settingDefaulted = (is_null($setting) or ($settingDefault === $setting));
531
+
532
+ if (!is_callable($options)) :
533
+ $checked = array();
534
+ if ($settingDefaulted) :
535
+ $checked[$defaultInputValue] = ' checked="checked"';
536
+ endif;
537
+
538
+ foreach ($options as $value => $label) :
539
+ if ($setting == $value) :
540
+ $checked[$value] = ' checked="checked"';
541
+ else :
542
+ $checked[$value] = '';
543
+ endif;
544
+ endforeach;
545
+ endif;
546
 
547
+ $defaulted = array();
548
+ if ($defaultInputName != $inputName) :
549
+ $defaulted['yes'] = ($settingDefaulted ? ' checked="checked"' : '');
550
+ $defaulted['no'] = ($settingDefaulted ? '' : ' checked="checked"');
551
+ else :
552
+ $defaulted['yes'] = (isset($checked[$defaultInputValue]) ? $checked[$defaultInputValue] : '');
553
+ endif;
554
+
555
+ if (isset($params['defaulted'])) :
556
+ $defaulted['yes'] = ($params['defaulted'] ? ' checked="checked"' : '');
557
+ $defaulted['no'] = ($params['defaulted'] ? '' : ' checked="checked"');
558
+ endif;
559
+
560
+ if ($offerSiteWide) :
561
+ ?>
562
+ <table class="twofer">
563
+ <tbody>
564
+ <tr><td class="equals first inactive">
565
+ <ul class="options">
566
+ <li><label><input type="radio"
567
+ name="<?php print $defaultInputName; ?>"
568
+ value="<?php print $defaultInputValue; ?>"
569
+ <?php if (!is_null($defaultInputId)) : ?>id="<?php print $defaultInputId; ?>" <?php endif; ?>
570
+ <?php print $defaulted['yes']; ?> />
571
+ Use the site-wide setting</label>
572
+ <span class="current-setting">Currently:
573
+ <strong><?php if (is_callable($labels)) :
574
+ print call_user_func($labels, $globalSetting, $defaulted, $params);
575
+ else :
576
+ print $labels[$globalSetting];
577
+ endif; ?></strong> (<a href="<?php print $href; ?>">change</a>)</span></li>
578
+ </ul></td>
579
+
580
+ <td class="equals second inactive">
581
+ <?php if ($defaultInputName != $inputName) : ?>
582
+ <ul class="options">
583
+ <li><label><input type="radio"
584
+ name="<?php print $defaultInputName; ?>"
585
+ value="no"
586
+ <?php if (!is_null($defaultInputIdNo)) : ?>id="<?php print $defaultInputIdNo; ?>" <?php endif; ?>
587
+ <?php print $defaulted['no']; ?> />
588
+ <?php _e('Do something different with this feed.'); ?></label>
589
+ <?php endif;
590
+ endif;
591
+
592
+ // Let's spit out the controls here.
593
+ if (is_callable($options)) :
594
+ // Method call to print out options list
595
+ call_user_func($options, $setting, $defaulted, $params);
596
+ else :
597
+ ?>
598
+ <ul class="options">
599
+ <?php foreach ($options as $value => $label) : ?>
600
+ <li><label><input type="radio" name="<?php print $inputName; ?>"
601
+ value="<?php print $value; ?>"
602
+ <?php print $checked[$value]; ?> />
603
+ <?php print $label; ?></label></li>
604
+ <?php endforeach; ?>
605
+ </ul> <!-- class="options" -->
606
+ <?php
607
+ endif;
608
+
609
+ if ($offerSiteWide) :
610
+ if ($defaultInputName != $inputName) :
611
+ // Close the <li> and <ul class="options"> we opened above
612
+ ?>
613
+ </li>
614
+ </ul> <!-- class="options" -->
615
+ <?php
616
+ endif;
617
+
618
+ // Close off the twofer table that we opened up above.
619
+ ?>
620
+ </td></tr>
621
+ </tbody>
622
+ </table>
623
+ <?php
624
+ endif;
625
+ } /* FeedWordPressAdminPage::setting_radio_control () */
626
+
627
+ function save_button ($caption = NULL) {
628
  if (is_null($caption)) : $caption = __('Save Changes'); endif;
629
+ ?>
630
  <p class="submit">
631
  <input class="button-primary" type="submit" name="save" value="<?php print $caption; ?>" />
632
  </p>
633
+ <?php
634
+ }
635
+ } /* class FeedWordPressAdminPage */
636
 
637
  function fwp_authors_single_submit ($link = NULL) {
 
 
 
638
  ?>
639
  <div class="submitbox" id="submitlink">
640
  <div id="previewview">
647
  </p>
648
  </div>
649
  <?php
 
650
  }
651
 
652
  function fwp_option_box_opener ($legend, $id, $class = "stuffbox") {
 
 
653
  ?>
654
  <div id="<?php print $id; ?>" class="<?php print $class; ?>">
655
  <h3><?php print htmlspecialchars($legend); ?></h3>
656
  <div class="inside">
657
  <?php
 
 
 
 
 
 
658
  }
659
 
660
  function fwp_option_box_closer () {
671
  endif;
672
  }
673
 
674
+ function fwp_tags_box ($tags, $object, $params = array()) {
675
  if (!is_array($tags)) : $tags = array(); endif;
676
+ $tax_name = (isset($params['taxonomy']) ? $params['taxonomy'] : 'post_tag');
677
  $desc = "<p style=\"font-size:smaller;font-style:bold;margin:0\">Tag $object as...</p>";
678
 
679
+ print $desc;
680
+ $helps = __('Separate tags with commas.');
681
+ $box['title'] = __('Tags');
 
 
682
  ?>
683
  <div class="tagsdiv" id="<?php echo $tax_name; ?>">
684
  <div class="jaxtag">
689
  <div class="ajaxtag hide-if-no-js">
690
  <label class="screen-reader-text" for="new-tag-<?php echo $tax_name; ?>"><?php echo $box['title']; ?></label>
691
  <div class="taghint"><?php _e('Add new tag'); ?></div>
692
+ <p>
693
  <input type="text" id="new-tag-<?php echo $tax_name; ?>" name="newtag[<?php echo $tax_name; ?>]" class="newtag form-input-tip" size="16" autocomplete="off" value="" />
694
  <input type="button" class="button tagadd" value="<?php esc_attr_e('Add'); ?>" tabindex="3" />
695
+ </p>
696
  </div></div>
697
  <p class="howto"><?php echo $helps; ?></p>
698
  <div class="tagchecklist"></div>
699
  </div>
700
  <p class="hide-if-no-js"><a href="#titlediv" class="tagcloud-link" id="link-<?php echo $tax_name; ?>"><?php printf( __('Choose from the most used tags in %s'), $box['title'] ); ?></a></p>
701
+ <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
702
  }
703
 
704
+ function fwp_category_box ($checked, $object, $tags = array(), $params = array()) {
705
  global $wp_db_version;
706
 
707
+ if (is_string($params)) :
708
+ $prefix = $params;
709
+ $taxonomy = 'category';
710
+ elseif (is_array($params)) :
711
+ $prefix = (isset($params['prefix']) ? $params['prefix'] : '');
712
+ $taxonomy = (isset($params['taxonomy']) ? $params['taxonomy'] : 'category');
713
+ endif;
714
+ $tax = get_taxonomy($taxonomy);
715
+
716
  if (strlen($prefix) > 0) :
717
  $idPrefix = $prefix.'-';
718
  $idSuffix = "-".$prefix;
724
  endif;
725
 
726
  ?>
727
+ <div id="<?php print $idPrefix; ?>taxonomy-<?php print $taxonomy; ?>" class="feedwordpress-category-div">
728
+ <ul id="<?php print $idPrefix; ?><?php print $taxonomy; ?>-tabs" class="category-tabs">
729
+ <li class="ui-tabs-selected tabs"><a href="#<?php print $idPrefix; ?><?php print $taxonomy; ?>-all" tabindex="3"><?php _e( 'All posts' ); ?></a>
730
+ <p style="font-size:smaller;font-style:bold;margin:0">Give <?php print $object; ?> these <?php print $tax->labels->name; ?></p>
731
  </li>
732
  </ul>
733
 
734
+ <div id="<?php print $idPrefix; ?><?php print $taxonomy; ?>-all" class="tabs-panel">
735
+ <input type="hidden" value="0" name="tax_input[<?php print $taxonomy; ?>][]" />
736
+ <ul id="<?php print $idPrefix; ?><?php print $taxonomy; ?>checklist" class="list:<?php print $taxonomy; ?> categorychecklist form-no-clear">
737
+ <?php fwp_category_checklist(NULL, false, $checked, $params) ?>
738
  </ul>
739
  </div>
740
 
741
+ <div id="<?php print $idPrefix; ?><?php print $taxonomy; ?>-adder" class="<?php print $taxonomy; ?>-adder wp-hidden-children">
742
+ <h4><a id="<?php print $idPrefix; ?><?php print $taxonomy; ?>-add-toggle" class="category-add-toggle" href="#<?php print $idPrefix; ?><?php print $taxonomy; ?>-add" class="hide-if-no-js" tabindex="3"><?php _e( '+ Add New Category' ); ?></a></h4>
743
+ <p id="<?php print $idPrefix; ?><?php print $taxonomy; ?>-add" class="category-add wp-hidden-child">
744
  <?php
745
+ $newcat = 'new'.$taxonomy;
746
+
747
+ // Well, thank God they added "egory" before WP 3.0 came out.
748
+ if ('newcategory'==$newcat
749
+ and !FeedWordPressCompatibility::test_version(FWP_SCHEMA_30)) :
750
  $newcat = 'newcat';
751
  endif;
752
  ?>
753
+ <label class="screen-reader-text" for="<?php print $idPrefix; ?>new<?php print $taxonomy; ?>"><?php _e('Add New Category'); ?></label>
754
+ <input
755
+ id="<?php print $idPrefix; ?>new<?php print $taxonomy; ?>"
756
+ class="new<?php print $taxonomy; ?> form-required form-input-tip"
757
+ aria-required="true"
758
+ tabindex="3"
759
+ type="text" name="<?php print $newcat; ?>"
760
+ value="<?php _e( 'New category name' ); ?>"
761
+ />
762
+ <label class="screen-reader-text" for="<?php print $idPrefix; ?>new<?php print $taxonomy; ?>-parent"><?php _e('Parent Category:'); ?></label>
763
+ <?php wp_dropdown_categories( array(
764
+ 'taxonomy' => $taxonomy,
765
  'hide_empty' => 0,
766
+ 'id' => $idPrefix.'new'.$taxonomy.'-parent',
767
+ 'class' => 'new'.$taxonomy.'-parent',
768
  'name' => $newcat.'_parent',
769
  'orderby' => 'name',
770
  'hierarchical' => 1,
771
  'show_option_none' => __('Parent category'),
772
  'tab_index' => 3,
773
  ) ); ?>
774
+ <input type="button" id="<?php print $idPrefix; ?><?php print $taxonomy; ?>-add-sumbit" class="add:<?php print $idPrefix; ?><?php print $taxonomy; ?>checklist:<?php print $taxonomy; ?>-add add-categorychecklist-category-add button category-add-submit" value="<?php _e( 'Add' ); ?>" tabindex="3" />
775
  <?php /* wp_nonce_field currently doesn't let us set an id different from name, but we need a non-unique name and a unique id */ ?>
776
+ <input type="hidden" id="_ajax_nonce<?php print esc_html($idSuffix); ?>" name="_ajax_nonce" value="<?php print wp_create_nonce('add-'.$taxonomy); ?>" />
777
+ <input type="hidden" id="_ajax_nonce-add-<?php print $taxonomy; ?><?php print esc_html($idSuffix); ?>" name="_ajax_nonce-add-<?php print $taxonomy; ?>" value="<?php print wp_create_nonce('add-'.$taxonomy); ?>" />
778
+ <span id="<?php print $idPrefix; ?><?php print $taxonomy; ?>-ajax-response" class="<?php print $taxonomy; ?>-ajax-response"></span>
779
  </p>
780
  </div>
781
 
798
  else :
799
  echo " completed in $dt second".(($dt==1)?'':'s')."</li>\n";
800
  endif;
801
+ flush();
802
  }
803
 
804
  function fwp_author_list () {
805
  global $wpdb;
806
  $ret = array();
807
 
808
+ $users = $wpdb->get_results("SELECT * FROM $wpdb->users ORDER BY display_name");
 
 
 
 
 
 
 
809
  if (is_array($users)) :
810
  foreach ($users as $user) :
811
  $id = (int) $user->ID;
812
+ $ret[$id] = $user->display_name;
813
  if (strlen(trim($ret[$id])) == 0) :
814
  $ret[$id] = $user->user_login;
815
  endif;
844
  wp_register_script('feedwordpress-elements', WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-elements.js');
845
  wp_enqueue_script('feedwordpress-elements');
846
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
847
 
848
+ function admin_styles () {
849
+ ?>
850
+ <style type="text/css">
851
+ .fwpfs {
852
+ background-image: url(<?php print admin_url('images/fav.png'); ?>);
853
+ background-repeat: repeat-x;
854
+ background-position: left center;
855
+ background-attachment: scroll;
856
+ }
857
+ .fwpfs.slide-down {
858
+ background-image:url(<?php print admin_url('images/fav-top.png'); ?>);
859
+ background-position:0 top;
860
+ background-repeat:repeat-x;
861
+ }
862
+ </style>
863
+ <?php
864
+ } /* FeedWordPressSettingsUI::admin_styles () */
865
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
866
  /*static*/ function ajax_nonce_fields () {
867
  if (function_exists('wp_nonce_field')) :
868
  echo "<form style='display: none' method='get' action=''>\n<p>\n";
875
  /*static*/ function fix_toggles_js ($context) {
876
  ?>
877
  <script type="text/javascript">
878
+ jQuery(document).ready( function($) {
879
+ // In case someone got here first...
880
+ $('.postbox h3, .postbox .handlediv').unbind('click');
881
+ $('.postbox h3 a').unbind('click');
882
+ $('.hide-postbox-tog').unbind('click');
883
+ $('.columns-prefs input[type="radio"]').unbind('click');
884
+ $('.meta-box-sortables').sortable('destroy');
 
 
 
 
 
 
 
 
 
 
 
885
 
886
+ postboxes.add_postbox_toggles('<?php print $context; ?>');
 
887
  } );
888
  </script>
889
  <?php
890
  } /* FeedWordPressSettingsUI::fix_toggles_js () */
891
 
892
  function magic_input_tip_js ($id) {
 
893
  ?>
894
  <script type="text/javascript">
895
  jQuery(document).ready( function () {
907
  } );
908
  </script>
909
  <?php
 
910
  } /* FeedWordPressSettingsUI::magic_input_tip_js () */
911
  } /* class FeedWordPressSettingsUI */
912
 
933
  return $ret;
934
  } /* fwp_insert_new_user () */
935
 
936
+ /**
937
+ * fwp_add_meta_box
938
+ *
939
+ * This function is no longer necessary, since no versions of WordPress that FWP
940
+ * still supports lack add_meta_box(). But I've left it in place for the time
941
+ * being for add-on modules that may have used it in setting up their UI.
942
+ */
943
  function fwp_add_meta_box ($id, $title, $callback, $page, $context = 'advanced', $priority = 'default', $callback_args = null) {
944
+ return add_meta_box($id, $title, $callback, $page, $context, $priority, $callback_args);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
945
  } /* function fwp_add_meta_box () */
946
 
947
  function fwp_do_meta_boxes($page, $context, $object) {
948
+ $ret = do_meta_boxes($page, $context, $object);
 
949
 
950
+ // Avoid JavaScript error from WordPress 2.5 bug
951
  ?>
952
  <div style="display: none">
953
  <div id="tags-input"></div> <!-- avoid JS error from WP 2.5 bug -->
954
  </div>
955
  <?php
956
+ return $ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
957
  } /* function fwp_do_meta_boxes() */
958
 
959
  function fwp_remove_meta_box($id, $page, $context) {
960
+ return remove_meta_box($id, $page, $context);
961
+ } /* function fwp_remove_meta_box() */
962
+
963
+ function fwp_syndication_manage_page_links_table_rows ($links, $page, $visible = 'Y') {
964
+ global $fwp_path;
 
 
 
 
 
 
 
965
 
966
+ $subscribed = ('Y' == strtoupper($visible));
967
+ if ($subscribed or (count($links) > 0)) :
968
+ ?>
969
+ <table class="widefat<?php if (!$subscribed) : ?> unsubscribed<?php endif; ?>">
970
+ <thead>
971
+ <tr>
972
+ <th class="check-column" scope="col"><input type="checkbox" /></th>
973
+ <th scope="col"><?php _e('Name'); ?></th>
974
+ <th scope="col"><?php _e('Feed'); ?></th>
975
+ <th scope="col"><?php _e('Updated'); ?></th>
976
+ </tr>
977
+ </thead>
978
+
979
+ <tbody>
980
+ <?php
981
+ $alt_row = true;
982
+ if (count($links) > 0):
983
+ foreach ($links as $link):
984
+ $trClass = array();
985
+
986
+ // Prep: Get last updated timestamp
987
+ $sLink = new SyndicatedLink($link->link_id);
988
+ if (!is_null($sLink->setting('update/last'))) :
989
+ $lastUpdated = fwp_time_elapsed($sLink->setting('update/last'));
990
+ else :
991
+ $lastUpdated = __('None yet');
992
+ endif;
993
+
994
+ // Prep: get last error timestamp, if any
995
+ if (is_null($sLink->setting('update/error'))) :
996
+ $errorsSince = '';
997
+ else :
998
+ $trClass[] = 'feed-error';
999
+
1000
+ $theError = unserialize($sLink->setting('update/error'));
1001
+
1002
+ $errorsSince = "<div class=\"returning-errors\">"
1003
+ ."<p><strong>Returning errors</strong> since "
1004
+ .fwp_time_elapsed($theError['since'])
1005
+ ."</p>"
1006
+ ."<p>Most recent ("
1007
+ .fwp_time_elapsed($theError['ts'])
1008
+ ."):<br/><code>"
1009
+ .implode("</code><br/><code>", $theError['object']->get_error_messages())
1010
+ ."</code></p>"
1011
+ ."</div>\n";
1012
+ endif;
1013
+
1014
+ $nextUpdate = "<div style='font-style:italic;size:0.9em'>Ready for next update ";
1015
+ if (isset($sLink->settings['update/ttl']) and is_numeric($sLink->settings['update/ttl'])) :
1016
+ if (isset($sLink->settings['update/timed']) and $sLink->settings['update/timed']=='automatically') :
1017
+ $next = $sLink->settings['update/last'] + ((int) $sLink->settings['update/ttl'] * 60);
1018
+ $nextUpdate .= fwp_time_elapsed($next);
1019
+ if (FEEDWORDPRESS_DEBUG) : $nextUpdate .= " [".(($next-time())/60)." minutes]"; endif;
1020
+ else :
1021
+ $nextUpdate .= "every ".$sLink->settings['update/ttl']." minute".(($sLink->settings['update/ttl']!=1)?"s":"");
1022
+ endif;
1023
+ else:
1024
+ $nextUpdate .= "as soon as possible";
1025
+ endif;
1026
+ $nextUpdate .= "</div>";
1027
+
1028
+ unset($sLink);
1029
+
1030
+ $alt_row = !$alt_row;
1031
+
1032
+ if ($alt_row) :
1033
+ $trClass[] = 'alternate';
1034
+ endif;
1035
+ ?>
1036
+ <tr<?php echo ((count($trClass) > 0) ? ' class="'.implode(" ", $trClass).'"':''); ?>>
1037
+ <th class="check-column" scope="row"><input type="checkbox" name="link_ids[]" value="<?php echo $link->link_id; ?>" /></th>
1038
+ <?php
1039
+ $hrefPrefix = "admin.php?link_id={$link->link_id}&amp;page=${fwp_path}/";
1040
+ $caption = (
1041
+ (strlen($link->link_rss) > 0)
1042
+ ? __('Switch Feed')
1043
+ : $caption=__('Find Feed')
1044
+ );
1045
+ ?>
1046
+ <td>
1047
+ <strong><a href="<?php print $hrefPrefix; ?>feeds-page.php"><?php print esc_html($link->link_name); ?></a></strong>
1048
+ <div class="row-actions"><?php if ($subscribed) :
1049
+ $page->display_feed_settings_page_links(array(
1050
+ 'before' => '<div><strong>Settings &gt;</strong> ',
1051
+ 'after' => '</div>',
1052
+ 'subscription' => $link,
1053
+ ));
1054
+ endif; ?>
1055
+
1056
+ <div><strong>Actions &gt;</strong>
1057
+ <?php if ($subscribed) : ?>
1058
+ <a href="<?php print $hrefPrefix; ?>syndication.php&amp;action=feedfinder"><?php echo $caption; ?></a>
1059
+ <?php else : ?>
1060
+ <a href="<?php print $hrefPrefix; ?>syndication.php&amp;action=<?php print FWP_RESUB_CHECKED; ?>"><?php _e('Re-subscribe'); ?></a>
1061
+ <?php endif; ?>
1062
+ | <a href="<?php print $hrefPrefix; ?>syndication.php&amp;action=Unsubscribe"><?php _e(($subscribed ? 'Unsubscribe' : 'Delete permanently')); ?></a>
1063
+ | <a href="<?php print esc_html($link->link_url); ?>"><?php _e('View')?></a></div>
1064
+ </div>
1065
+ </td>
1066
+ <?php if (strlen($link->link_rss) > 0): ?>
1067
+ <td><a href="<?php echo esc_html($link->link_rss); ?>"><?php echo esc_html(feedwordpress_display_url($link->link_rss, 32)); ?></a></td>
1068
+ <?php else: ?>
1069
+ <td class="feed-missing"><p><strong>no feed assigned</strong></p></td>
1070
+ <?php endif; ?>
1071
+
1072
+ <td><?php print $lastUpdated; ?>
1073
+ <?php print $errorsSince; ?>
1074
+ <?php print $nextUpdate; ?>
1075
+ </td>
1076
+ </tr>
1077
+ <?php
1078
+ endforeach;
1079
+ else :
1080
+ ?>
1081
+ <tr><td colspan="4"><p>There are no websites currently listed for syndication.</p></td></tr>
1082
+ <?php
1083
+ endif;
1084
+ ?>
1085
+ </tbody>
1086
+ </table>
1087
+ <?php
1088
  endif;
1089
+ } /* function fwp_syndication_manage_page_links_table_rows () */
1090
 
1091
+ function fwp_syndication_manage_page_links_subsubsub ($sources, $showInactive) {
1092
+ global $fwp_path;
1093
+ $hrefPrefix = "admin.php?page=${fwp_path}/syndication.php";
1094
+ ?>
1095
+ <ul class="subsubsub">
1096
+ <li><a <?php if (!$showInactive) : ?>class="current" <?php endif; ?>href="<?php print $hrefPrefix; ?>&amp;visibility=Y">Subscribed
1097
+ <span class="count">(<?php print count($sources['Y']); ?>)</span></a></li>
1098
+ <?php if ($showInactive or (count($sources['N']) > 0)) : ?>
1099
+ <li><a <?php if ($showInactive) : ?>class="current" <?php endif; ?>href="<?php print $hrefPrefix; ?>&amp;visibility=N">Inactive</a>
1100
+ <span class="count">(<?php print count($sources['N']); ?>)</span></a></li>
1101
+ <?php endif; ?>
1102
+
1103
+ </ul> <!-- class="subsubsub" -->
1104
+ <?php
1105
+ }
1106
 
authors-page.php CHANGED
@@ -171,6 +171,7 @@ function fwp_authors_page () {
171
  $authorsPage = new FeedWordPressAuthorsPage($link);
172
 
173
  $mesg = null;
 
174
 
175
  if (isset($GLOBALS['fwp_post']['fix_mismatch'])) :
176
  if ('newuser'==$GLOBALS['fwp_post']['fix_mismatch_to']) :
@@ -197,11 +198,7 @@ function fwp_authors_page () {
197
  $post_set = "(".implode(",", $post_ids).")";
198
 
199
  // Getting the revisions too, if there are any
200
- if (fwp_test_wp_version(FWP_SCHEMA_26)) :
201
- $parent_in_clause = "OR {$wpdb->posts}.post_parent IN $post_set";
202
- else :
203
- $parent_in_clause = '';
204
- endif;
205
 
206
  $wpdb->query("
207
  UPDATE {$wpdb->posts}
@@ -356,7 +353,7 @@ function fwp_authors_page () {
356
  $title = $row;
357
  endif;
358
 
359
- fwp_add_meta_box(
360
  /*id=*/ $id,
361
  /*title=*/ $title,
362
  /*callback=*/ array('FeedWordPressAuthorsPage', $method),
171
  $authorsPage = new FeedWordPressAuthorsPage($link);
172
 
173
  $mesg = null;
174
+ $updated_link = false;
175
 
176
  if (isset($GLOBALS['fwp_post']['fix_mismatch'])) :
177
  if ('newuser'==$GLOBALS['fwp_post']['fix_mismatch_to']) :
198
  $post_set = "(".implode(",", $post_ids).")";
199
 
200
  // Getting the revisions too, if there are any
201
+ $parent_in_clause = "OR {$wpdb->posts}.post_parent IN $post_set";
 
 
 
 
202
 
203
  $wpdb->query("
204
  UPDATE {$wpdb->posts}
353
  $title = $row;
354
  endif;
355
 
356
+ add_meta_box(
357
  /*id=*/ $id,
358
  /*title=*/ $title,
359
  /*callback=*/ array('FeedWordPressAuthorsPage', $method),
categories-page.php CHANGED
@@ -2,55 +2,351 @@
2
  require_once(dirname(__FILE__) . '/admin-ui.php');
3
 
4
  class FeedWordPressCategoriesPage extends FeedWordPressAdminPage {
5
- function FeedWordPressCategoriesPage ($link) {
 
 
 
 
6
  FeedWordPressAdminPage::FeedWordPressAdminPage('feedwordpresscategories', $link);
7
- $this->dispatch = 'feedwordpress_categories_settings';
 
 
 
 
 
8
  $this->filename = __FILE__;
9
  }
10
 
11
- /*static*/ function feed_categories_box ($page, $box = NULL) {
12
-
 
 
 
 
 
 
 
 
13
  $link = $page->link;
14
-
15
- $unfamiliar = array ('create'=>'','tag' => '', 'default'=>'','filter'=>'');
16
- if ($page->for_feed_settings()) :
17
- $unfamiliar['site-default'] = '';
18
- $ucKey = $link->settings["unfamiliar category"];
19
- $ucDefault = 'site-default';
20
  else :
21
- $ucKey = FeedWordPress::on_unfamiliar('category');
22
- $ucDefault = 'create';
23
  endif;
24
-
25
- if (!is_string($ucKey) or !array_key_exists($ucKey, $unfamiliar)) :
26
- $ucKey = $ucDefault;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  endif;
28
- $unfamiliar[$ucKey] = ' checked="checked"';
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  // Hey ho, let's go...
 
31
  ?>
32
- <table class="edit-form">
33
  <tr>
34
- <th scope="row">Unfamiliar categories:</th>
35
- <td><p>When one of the categories on a syndicated post is a category that FeedWordPress has not encountered before ...</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
- <ul class="options">
38
- <?php if ($page->for_feed_settings()) : ?>
39
- <li><label><input type="radio" name="unfamiliar_category" value="site-default"<?php echo $unfamiliar['site-default']; ?> /> use the <a href="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/<?php print basename(__FILE__); ?>">site-wide setting</a>
40
- (currently <strong><?php echo FeedWordPress::on_unfamiliar('category'); ?></strong>)</label></li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  <?php endif; ?>
 
 
42
 
43
- <li><label><input type="radio" name="unfamiliar_category" value="create"<?php echo $unfamiliar['create']; ?> /> create a new category</label></li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
- <?php if (FeedWordPressCompatibility::post_tags()) : ?>
46
- <li><label><input type="radio" name="unfamiliar_category" value="tag"<?php echo $unfamiliar['tag']; ?>/> create a new tag</label></li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  <?php endif; ?>
48
 
49
- <li><label><input type="radio" name="unfamiliar_category" value="default"<?php echo $unfamiliar['default']; ?> /> don't create new categories<?php if (fwp_test_wp_version(FWP_SCHEMA_23)) : ?> or tags<?php endif; ?></label></li>
50
- <li><label><input type="radio" name="unfamiliar_category" value="filter"<?php echo $unfamiliar['filter']; ?> /> don't create new categories<?php if (fwp_test_wp_version(FWP_SCHEMA_23)) : ?> or tags<?php endif; ?> and don't syndicate posts unless they match at least one familiar category</label></li>
51
- </ul></td>
 
 
 
 
 
 
 
 
 
 
 
 
52
  </tr>
53
-
54
  <?php if ($page->for_feed_settings()) : ?>
55
  <tr>
56
  <th scope="row">Multiple categories:</th>
@@ -68,190 +364,254 @@ blank.</p></td>
68
  <?php
69
  } /* FeedWordPressCategoriesPage::feed_categories_box() */
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  function categories_box ($page, $box = NULL) {
72
  $link = $page->link;
73
- if ($page->for_feed_settings()) :
74
- if (is_array($link->settings['cats'])) : $cats = $link->settings['cats'];
75
- else : $cats = array();
76
- endif;
77
  else :
78
- $cats = array_map('trim',
79
- preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, get_option('feedwordpress_syndication_cats'))
80
- );
81
  endif;
82
- $dogs = SyndicatedPost::category_ids($cats, /*unfamiliar=*/ NULL);
83
 
84
- fwp_category_box($dogs, 'all '.$page->these_posts_phrase());
85
- } /* FeedWordPressCategoriesPage::categories_box () */
86
-
87
- function tags_box ($page, $box = NULL) {
88
- $link = $page->link;
89
  if ($page->for_feed_settings()) :
90
- $tags = $link->settings['tags'];
91
- else :
92
- $tags = array_map('trim',
93
- preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, get_option('feedwordpress_syndication_tags'))
94
- );
95
  endif;
96
 
97
- fwp_tags_box($tags, 'all '.$page->these_posts_phrase());
98
- } /* FeedWordPressCategoriesPage::tags_box () */
99
- }
100
-
101
- function fwp_categories_page () {
102
- global $wpdb, $wp_db_version;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
- if (FeedWordPress::needs_upgrade()) :
105
- fwp_upgrade_page();
106
- return;
107
- endif;
108
-
109
- FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_categories_settings', /*capability=*/ 'manage_links');
110
-
111
- $link = FeedWordPressAdminPage::submitted_link();
112
-
113
- $catsPage = new FeedWordPressCategoriesPage($link);
114
-
115
- $mesg = null;
116
-
117
- ////////////////////////////////////////////////
118
- // Process POST request, if any /////////////////
119
- ////////////////////////////////////////////////
120
- if (isset($GLOBALS['fwp_post']['save']) or isset($GLOBALS['fwp_post']['submit'])) :
121
- $saveCats = array();
122
- if (isset($GLOBALS['fwp_post']['post_category'])) :
123
- foreach ($GLOBALS['fwp_post']['post_category'] as $cat_id) :
124
- $saveCats[] = '{#'.$cat_id.'}';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  endforeach;
126
  endif;
 
 
127
 
128
- // Different variable names to cope with different WordPress AJAX UIs
129
- $syndicatedTags = array();
130
- if (isset($GLOBALS['fwp_post']['tax_input']['post_tag'])) :
131
- $syndicatedTags = explode(",", $GLOBALS['fwp_post']['tax_input']['post_tag']);
132
- elseif (isset($GLOBALS['fwp_post']['tags_input'])) :
133
- $syndicatedTags = explode(",", $GLOBALS['fwp_post']['tags_input']);
 
 
 
 
 
134
  endif;
135
- $syndicatedTags = array_map('trim', $syndicatedTags);
136
-
137
- if (is_object($link) and $link->found()) :
138
- $alter = array ();
139
 
140
- // Categories
141
- if (!empty($saveCats)) : $link->settings['cats'] = $saveCats;
142
- else : unset($link->settings['cats']);
 
 
 
 
 
 
 
 
143
  endif;
144
-
145
- // Tags
146
- $link->settings['tags'] = $syndicatedTags;
147
-
148
- // Unfamiliar categories
149
- if (isset($GLOBALS['fwp_post']["unfamiliar_category"])) :
150
- if ('site-default'==$GLOBALS['fwp_post']["unfamiliar_category"]) :
151
- unset($link->settings["unfamiliar category"]);
152
- else :
153
- $link->settings["unfamiliar category"] = $GLOBALS['fwp_post']["unfamiliar_category"];
154
- endif;
155
  endif;
 
156
 
157
- // Category spitting regex
158
- if (isset($GLOBALS['fwp_post']['cat_split'])) :
159
- if (strlen(trim($GLOBALS['fwp_post']['cat_split'])) > 0) :
160
- $link->settings['cat_split'] = trim($GLOBALS['fwp_post']['cat_split']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  else :
162
- unset($link->settings['cat_split']);
163
  endif;
164
  endif;
 
 
 
 
165
 
166
- // Save settings
167
- $link->save_settings(/*reload=*/ true);
168
- $catsPage->updated = true;
169
-
170
- // Reset, reload
171
- $link_id = $link->id;
172
- unset($link);
173
- $link = new SyndicatedLink($link_id);
174
- else :
175
- // Categories
176
- if (!empty($saveCats)) :
177
- update_option('feedwordpress_syndication_cats', implode(FEEDWORDPRESS_CAT_SEPARATOR, $saveCats));
178
- else :
179
- delete_option('feedwordpress_syndication_cats');
180
  endif;
181
-
182
- // Tags
183
- if (!empty($syndicatedTags)) :
184
- update_option('feedwordpress_syndication_tags', implode(FEEDWORDPRESS_CAT_SEPARATOR, $syndicatedTags));
185
- else :
186
- delete_option('feedwordpress_syndication_tags');
 
187
  endif;
188
-
189
- update_option('feedwordpress_unfamiliar_category', $_REQUEST['unfamiliar_category']);
190
-
191
- $catsPage->updated = true;
192
  endif;
193
-
194
- do_action('feedwordpress_admin_page_categories_save', $GLOBALS['fwp_post'], $catsPage);
195
- else :
196
- $catsPage->updated = false;
197
- endif;
198
-
199
- ////////////////////////////////////////////////
200
- // Prepare settings page ///////////////////////
201
- ////////////////////////////////////////////////
202
 
203
- $catsPage->display_update_notice_if_updated('Syndicated categories'.FEEDWORDPRESS_AND_TAGS, $mesg);
204
- $catsPage->open_sheet('Categories'.FEEDWORDPRESS_AND_TAGS);
205
- ?>
206
- <style type="text/css">
207
- table.edit-form th { width: 27%; vertical-align: top; }
208
- table.edit-form td { width: 73%; vertical-align: top; }
209
- table.edit-form td ul.options { margin: 0; padding: 0; list-style: none; }
210
- </style>
211
-
212
- <div id="post-body">
213
- <?php
214
- ////////////////////////////////////////////////
215
- // Display settings boxes //////////////////////
216
- ////////////////////////////////////////////////
217
-
218
- $boxes_by_methods = array(
219
- 'feed_categories_box' => __('Feed Categories'.FEEDWORDPRESS_AND_TAGS),
220
- 'categories_box' => array('title' => __('Categories'), 'id' => 'categorydiv'),
221
- 'tags_box' => __('Tags'),
222
- );
223
- if (!FeedWordPressCompatibility::post_tags()) :
224
- unset($boxes_by_methods['tags_box']);
225
- endif;
226
-
227
- foreach ($boxes_by_methods as $method => $row) :
228
- if (is_array($row)) :
229
- $id = $row['id'];
230
- $title = $row['title'];
231
- else :
232
- $id = 'feedwordpress_'.$method;
233
- $title = $row;
234
  endif;
235
 
236
- fwp_add_meta_box(
237
- /*id=*/ $id,
238
- /*title=*/ $title,
239
- /*callback=*/ array('FeedWordPressCategoriesPage', $method),
240
- /*page=*/ $catsPage->meta_box_context(),
241
- /*context=*/ $catsPage->meta_box_context()
242
- );
243
- endforeach;
244
- do_action('feedwordpress_admin_page_categories_meta_boxes', $catsPage);
245
- ?>
246
- <div class="metabox-holder">
247
- <?php
248
- fwp_do_meta_boxes($catsPage->meta_box_context(), $catsPage->meta_box_context(), $catsPage);
249
- ?>
250
- </div> <!-- class="metabox-holder" -->
251
- </div> <!-- id="post-body" -->
252
- <?php $catsPage->close_sheet(); ?>
253
- <?php
254
- } /* function fwp_categories_page () */
255
 
256
- fwp_categories_page();
 
257
 
2
  require_once(dirname(__FILE__) . '/admin-ui.php');
3
 
4
  class FeedWordPressCategoriesPage extends FeedWordPressAdminPage {
5
+ function FeedWordPressCategoriesPage ($link = -1) {
6
+ if (is_numeric($link) and -1 == $link) :
7
+ $link = $this->submitted_link();
8
+ endif;
9
+
10
  FeedWordPressAdminPage::FeedWordPressAdminPage('feedwordpresscategories', $link);
11
+ $this->dispatch = 'feedwordpress_admin_page_categories';
12
+ $this->pagenames = array(
13
+ 'default' => 'Categories'.FEEDWORDPRESS_AND_TAGS,
14
+ 'settings-update' => 'Syndicated Categories'.FEEDWORDPRESS_AND_TAGS,
15
+ 'open-sheet' => 'Categories'.FEEDWORDPRESS_AND_TAGS,
16
+ );
17
  $this->filename = __FILE__;
18
  }
19
 
20
+ function unfamiliar_category_label ($name) {
21
+ if (preg_match('/^create:(.*)$/', $name, $refs)) :
22
+ $tax = get_taxonomy($refs[1]);
23
+ $name = sprintf(__('Create new %s to match them'), $tax->labels->name);
24
+ endif;
25
+ return $name;
26
+ }
27
+
28
+
29
+ function feed_categories_box ($page, $box = NULL) {
30
  $link = $page->link;
31
+
32
+ $globalPostType = get_option('feedwordpress_syndicated_post_type', 'post');
33
+ if ($this->for_feed_settings()) :
34
+ $post_type = $link->setting('syndicated post type', 'syndicated_post_type', 'post');
 
 
35
  else :
36
+ $post_type = $globalPostType;
 
37
  endif;
38
+ $taxonomies = get_object_taxonomies(array('object_type' => $post_type), 'names');
39
+
40
+ $unmatched = array('category' => array(), 'post_tag' => array());
41
+ $matchUl = array('cats' => array(), 'tags' => array(), 'filter' => array());
42
+ $tagLikeTaxonomies = array();
43
+ foreach ($taxonomies as $tax) :
44
+ $taxonomy = get_taxonomy($tax);
45
+
46
+ if (!$taxonomy->hierarchical) :
47
+ $tagLikeTaxonomies[] = $tax;
48
+ endif;
49
+
50
+ $name = 'create:'.$tax;
51
+ foreach (array('category', 'post_tag') as $what) :
52
+ $unmatched[$what][$name] = array(
53
+ 'label' => $this->unfamiliar_category_label($name),
54
+ );
55
+ $unmatchedRadio[$what][$name] = '';
56
+ endforeach;
57
+
58
+ foreach (array('cats', 'tags', 'filter') as $what) :
59
+ $matchUl[$what][$tax] = array(
60
+ 'checked' => '',
61
+ 'labels' => $taxonomy->labels,
62
+ );
63
+ endforeach;
64
+ endforeach;
65
+
66
+ foreach ($unmatched as $what => $um) :
67
+ $unmatched[$what]['null'] = array('label' => __('Don\'t create any matching terms'));
68
+ $unmatchedRadio[$what]['null'] = '';
69
+ endforeach;
70
+
71
+ $globalUnmatched = array(
72
+ 'category' => FeedWordPress::on_unfamiliar('category'),
73
+ 'post_tag' => FeedWordPress::on_unfamiliar('post_tag'),
74
+ );
75
+ foreach ($globalUnmatched as $what => $value) :
76
+ if ($value=='create') : $value = 'create:category'; endif;
77
+ if ($value=='tag') : $value = 'create:post_tag'; endif;
78
+ $globalUnmatched[$what] = $value;
79
+ endforeach;
80
+
81
+ $globalMatch['cats'] = get_option('feedwordpress_match_cats', $taxonomies);
82
+ $globalMatch['tags'] = get_option('feedwordpress_match_tags', $tagLikeTaxonomies);
83
+ $globalMatch['filter'] = get_option('feedwordpress_match_filter', array());
84
+
85
+ $globalMatchLabels = array();
86
+ $nothingDoing = array('cats' => "won't try to match", 'tags' => "won't try to match", "filter" => "won't filter");
87
+
88
+ foreach ($globalMatch as $what => $domain) :
89
+ $labels = array(); $domain = array_filter($domain, 'remove_dummy_zero');
90
+ foreach ($domain as $tax) :
91
+ $tax = get_taxonomy($tax);
92
+ $labels[] = $tax->labels->name;
93
+ endforeach;
94
+
95
+ if (count($labels) > 0) :
96
+ $globalMatchLabels[$what] = implode(", ", $labels);
97
+ else :
98
+ $globalMatchLabels[$what] = $nothingDoing[$what];
99
+ endif;
100
+ endforeach;
101
+
102
+ if ($this->for_feed_settings()) :
103
+ $href = "admin.php?page={$GLOBALS['fwp_path']}/".basename(__FILE__);
104
+
105
+ foreach ($unmatched as $what => $um) :
106
+ // Is the global default setting appropriate to this post type?
107
+ $GUC = $globalUnmatched[$what];
108
+ if (isset($um[$GUC])) :
109
+ // Yup. Let's add a site-default option
110
+ $currently = $um[$GUC]['label'];
111
+ $defaultLi = array(
112
+ 'site-default' => array(
113
+ 'label' => sprintf(
114
+ __('Use the <a href="%s">site-wide setting</a> <span class="current-setting">Currently: <strong>%s</strong></span>'),
115
+ $href,
116
+ $currently
117
+ ),
118
+ ), );
119
+ $unmatchedColumns[$what] = array(
120
+ $defaultLi,
121
+ );
122
+ $unmatchedDefault[$what] = 'site-default';
123
+ $unmatchedRadio[$what]['site-default'] = '';
124
+ else :
125
+ $opts = array_keys($unmatched[$what]);
126
+ $unmatchedDefault[$what] = $opts[0];
127
+ $unmatchedColumns[$what] = array();
128
+ endif;
129
+
130
+ $ucKey[$what] = $link->setting("unfamiliar $what", NULL, NULL);
131
+ endforeach;
132
+
133
+ $match['cats'] = $this->link->setting('match/cats', NULL, NULL);
134
+ $match['tags'] = $this->link->setting('match/tags', NULL, NULL);
135
+ $match['filter'] = $this->link->setting('match/filter', NULL, NULL);
136
+ else :
137
+ foreach ($unmatched as $what => $um) :
138
+ $ucKey[$what] = FeedWordPress::on_unfamiliar($what);
139
+ endforeach;
140
+
141
+ $match = $globalMatch;
142
  endif;
 
143
 
144
+ foreach ($ucKey as $what => $uck) :
145
+ if ($uck == 'tag') : $uck = 'create:post_tag'; endif;
146
+ if ($uck == 'create') : $uck = 'create:category'; endif;
147
+
148
+ if (!is_string($uck)) :
149
+ $uck = $unmatchedDefault[$what];
150
+ endif;
151
+ $ucKey[$what] = $uck;
152
+
153
+ if (!array_key_exists($uck, $unmatchedRadio[$what])) :
154
+ $obsoleteLi = array(
155
+ $uck => array(
156
+ 'label' => ' <span style="font-style: italic; color: #777;">'.$this->unfamiliar_category_label($uck).'</span> <span style="background-color: #ffff90; color: black;">(This setting is no longer applicable to the type of post syndicated from this feed!)</span><p>Please change this one of the following settings:</p>',
157
+ ),
158
+ );
159
+ $unmatched[$what] = array_merge($obsoleteLi, $unmatched[$what]);
160
+ $unmatchedRadio[$what][$uck] = ' disabled="disabled"';
161
+ endif;
162
+
163
+ $unmatchedRadio[$what][$uck] .= ' checked="checked"';
164
+
165
+ $unmatchedColumns[$what][] = $unmatched[$what];
166
+ endforeach;
167
+
168
+ $defaulted = array();
169
+ foreach ($match as $what => $set) :
170
+ $defaulted[$what] = false;
171
+ if (is_null($set) or (count($set) < 1)) :
172
+ $defaulted[$what] = true;
173
+ if ($this->for_feed_settings()) :
174
+ $set = $globalMatch[$what];
175
+ $match[$what] = $globalMatch[$what];
176
+ endif;
177
+ endif;
178
+
179
+ if (!$defaulted[$what] or $this->for_feed_settings()) :
180
+ foreach ($set as $against) :
181
+ if (array_key_exists($against, $matchUl[$what])) :
182
+ $matchUl[$what][$against]['checked'] = ' checked="checked"';
183
+ endif;
184
+ endforeach;
185
+ endif;
186
+ endforeach;
187
+
188
  // Hey ho, let's go...
189
+ $offerSiteWideSettings = ($page->for_feed_settings() and ($post_type==$globalPostType));
190
  ?>
191
+ <table class="edit-form narrow">
192
  <tr>
193
+ <th scope="row">Match feed categories:</th>
194
+ <td><input type="hidden" name="match_categories[cats][]" value="0" />
195
+ <?php if ($offerSiteWideSettings) : ?>
196
+ <table class="twofer">
197
+ <tbody>
198
+ <tr><td class="equals first <?php if ($defaulted['cats']) : ?>active<?php else: ?>inactive<?php endif; ?>"><p><label><input type="radio" name="match_default[cats]"
199
+ value="yes" <?php if ($defaulted['cats']) : ?> checked="checked"<?php endif; ?> />
200
+ Use the <a href="<?php print $href; ?>">site-wide setting</a>
201
+ <span class="current-setting">Currently: <strong><?php print $globalMatchLabels['cats']; ?></strong></span></label></p></td>
202
+ <td class="equals second <?php if ($defaulted['cats']) : ?>inactive<?php else: ?>active<?php endif; ?>"><p><label><input type="radio" name="match_default[cats]"
203
+ value="no" <?php if (!$defaulted['cats']) : ?> checked="checked"<?php endif; ?> />
204
+ Do something different with this feed.</label>
205
+ <?php else : ?>
206
+ <p>
207
+ <?php endif; ?>
208
+ When a feed provides categories for a post, try to match those categories
209
+ locally with:</p>
210
+ <ul class="options compact">
211
+ <?php foreach ($matchUl['cats'] as $name => $li) : ?>
212
+ <li><label><input type="checkbox"
213
+ name="match_categories[cats][]" value="<?php print $name; ?>"
214
+ <?php print $li['checked']; ?> /> <?php $l = $li['labels']; print $l->name; ?></label></li>
215
+ <?php endforeach; ?>
216
+ </ul>
217
+ <?php if ($offerSiteWideSettings) : ?>
218
+ </td></tr>
219
+ </tbody>
220
+ </table>
221
+ <?php endif; ?>
222
+ </td>
223
+ </tr>
224
 
225
+ <tr>
226
+ <th scope="row">Unmatched categories:</th>
227
+ <td><p>When <?php print $this->these_posts_phrase(); ?> have categories on
228
+ the feed that don't have any local matches yet...</p>
229
+
230
+ <?php if (count($unmatchedColumns['category']) > 1) : ?>
231
+ <table class="twofer">
232
+ <?php else : ?>
233
+ <table style="width: 100%">
234
+ <?php endif; ?>
235
+ <tbody>
236
+ <tr>
237
+ <?php foreach ($unmatchedColumns['category'] as $index => $column) : ?>
238
+ <td class="equals <?php print (($index == 0) ? 'first' : 'second'); ?> inactive"><ul class="options">
239
+ <?php foreach ($column as $name => $li) : ?>
240
+ <li><label><input type="radio" name="unfamiliar_category" value="<?php print $name; ?>"<?php print $unmatchedRadio['category'][$name]; ?> /> <?php print $li['label']; ?></label></li>
241
+ <?php endforeach; ?>
242
+ </ul></td>
243
+ <?php endforeach; ?>
244
+ </tr>
245
+ </tbody>
246
+ </table>
247
+ </td></tr>
248
+
249
+ <tr>
250
+ <th scope="row">Match inline tags:
251
+ <p class="setting-description">Applies only to inline tags marked
252
+ as links in the text of syndicated posts, using the
253
+ <code>&lt;a rel="tag"&gt;...&lt;/a&gt;</code> microformat.
254
+ Most feeds with "tags" just treat them as normal feed categories,
255
+ like those handled above.</p>
256
+ </th>
257
+ <td><input type="hidden" name="match_categories[tags][]" value="0" />
258
+ <?php if ($offerSiteWideSettings) : ?>
259
+ <table class="twofer">
260
+ <tbody>
261
+ <tr><td class="equals first <?php if ($defaulted['tags']) : ?>active<?php else: ?>inactive<?php endif; ?>"><p><label><input type="radio" name="match_default[tags]"
262
+ value="yes" <?php if ($defaulted['tags']) : ?> checked="checked"<?php endif; ?> />
263
+ Use the <a href="<?php print $href; ?>">site-wide setting</a>
264
+ <span class="current-setting">Currently: <strong><?php print $globalMatchLabels['tags']; ?></strong></span></label></p>
265
+ </td>
266
+ <td class="equals second <?php if ($defaulted['tags']) : ?>inactive<?php else: ?>active<?php endif; ?>"><p><label><input type="radio" name="match_default[tags]"
267
+ value="no" <?php if (!$defaulted['tags']) : ?> checked="checked"<?php endif; ?> />
268
+ Do something different with this feed.</label>
269
+ <?php else : ?>
270
+ <p>
271
+ <?php endif; ?>
272
+ When a feed provides tags inline in a post, try to match those tags
273
+ locally with:</p>
274
+ <ul class="options compact">
275
+ <?php foreach ($matchUl['tags'] as $name => $li) : ?>
276
+ <li><label><input type="checkbox"
277
+ name="match_categories[tags][]" value="<?php print $name; ?>"
278
+ <?php print $li['checked']; ?> /> <?php $l = $li['labels']; print $l->name; ?></label></li>
279
+ <?php endforeach; ?>
280
+ </ul>
281
+ <?php if ($offerSiteWideSettings) : ?>
282
+ </td></tr>
283
+ </tbody>
284
+ </table>
285
  <?php endif; ?>
286
+ </td>
287
+ </tr>
288
 
289
+ <tr>
290
+ <th scope="row">Unmatched inline tags:</th>
291
+ <td><p>When the text of <?php print $this->these_posts_phrase(); ?> contains
292
+ inline tags that don't have any local matches yet...</p>
293
+
294
+ <?php if (count($unmatchedColumns['post_tag']) > 1) : ?>
295
+ <table class="twofer">
296
+ <?php else : ?>
297
+ <table style="width: 100%">
298
+ <?php endif; ?>
299
+ <tbody>
300
+ <tr>
301
+ <?php foreach ($unmatchedColumns['post_tag'] as $index => $column) : ?>
302
+ <td class="equals <?php print (($index == 0) ? 'first' : 'second'); ?> inactive"><ul class="options">
303
+ <?php foreach ($column as $name => $li) : ?>
304
+ <li><label><input type="radio" name="unfamiliar_post_tag" value="<?php print $name; ?>"<?php print $unmatchedRadio['post_tag'][$name]; ?> /> <?php print $li['label']; ?></label></li>
305
+ <?php endforeach; ?>
306
+ </ul></td>
307
+ <?php endforeach; ?>
308
+ </tr>
309
+ </tbody>
310
+ </table>
311
+
312
+ </td></tr>
313
 
314
+ <tr>
315
+ <th scope="row">Filter:</th>
316
+ <td><input type="hidden" name="match_categories[filter][]" value="0" />
317
+ <?php if ($offerSiteWideSettings) : ?>
318
+ <table class="twofer">
319
+ <tbody>
320
+ <tr>
321
+ <td class="equals first <?php if ($defaulted['filter']) : ?>active<?php else: ?>inactive<?php endif; ?>">
322
+ <p><label><input type="radio" name="match_default[filter]"
323
+ value="yes" <?php if ($defaulted['filter']) : ?> checked="checked"<?php endif; ?> />
324
+ Use the <a href="<?php print $href; ?>">site-wide setting</a>
325
+ <span class="current-setting">Currently: <strong><?php print $globalMatchLabels['filter']; ?></strong></span></label></p>
326
+ </td>
327
+ <td class="equals second <?php if ($defaulted['filter']) : ?>inactive<?php else: ?>active<?php endif; ?>">
328
+ <p><label><input type="radio" name="match_default[filter]"
329
+ value="no" <?php if (!$defaulted['filter']) : ?> checked="checked"<?php endif; ?> />
330
+ Do something different with this feed:</label></p>
331
+ <div style="margin-left: 3.0em;">
332
  <?php endif; ?>
333
 
334
+ <ul class="options">
335
+ <?php foreach ($matchUl['filter'] as $tax => $li) : ?>
336
+ <li><label><input type="checkbox" name="match_categories[filter][]" value="<?php print $tax; ?>"
337
+ <?php print $li['checked']; ?> /> Don't syndicate posts unless they match at
338
+ least one local <strong><?php $l = $li['labels']; print $l->singular_name; ?></strong></label></li>
339
+ <?php endforeach; ?>
340
+ </ul>
341
+
342
+ <?php if ($offerSiteWideSettings) : ?>
343
+ </div>
344
+ </td></tr>
345
+ </tbody>
346
+ </table>
347
+ <?php endif; ?>
348
+ </td>
349
  </tr>
 
350
  <?php if ($page->for_feed_settings()) : ?>
351
  <tr>
352
  <th scope="row">Multiple categories:</th>
364
  <?php
365
  } /* FeedWordPressCategoriesPage::feed_categories_box() */
366
 
367
+ function term_option_map () {
368
+ return array(
369
+ 'category' => 'feedwordpress_syndication_cats',
370
+ 'post_tag' => 'feedwordpress_syndication_tags',
371
+ );
372
+ }
373
+ function term_setting_map () {
374
+ return array(
375
+ 'category' => 'cats',
376
+ 'post_tag' => 'tags',
377
+ );
378
+ }
379
+
380
  function categories_box ($page, $box = NULL) {
381
  $link = $page->link;
382
+
383
+ if ($this->for_feed_settings()) :
384
+ $post_type = $link->setting('syndicated post type', 'syndicated_post_type', 'post');
 
385
  else :
386
+ $post_type = get_option('feedwordpress_syndicated_post_type', 'post');
 
 
387
  endif;
388
+ $taxonomies = get_object_taxonomies(array('object_type' => $post_type), 'names');
389
 
390
+ $option_map = $this->term_option_map();
391
+ $setting_map = $this->term_setting_map();
392
+ $globalTax = get_option('feedwordpress_syndication_terms', array());
 
 
393
  if ($page->for_feed_settings()) :
394
+ $terms = $link->setting('terms', NULL, array());
 
 
 
 
395
  endif;
396
 
397
+ ?>
398
+ <table class="edit-form narrow">
399
+ <tbody>
400
+ <?php
401
+ foreach ($taxonomies as $tax) :
402
+ $taxonomy = get_taxonomy($tax);
403
+ ?>
404
+ <tr><th><?php print $taxonomy->labels->name; ?></th>
405
+ <td><?php
406
+ if (isset($option_map[$tax])) :
407
+ $option = $option_map[$tax];
408
+ $globalCats = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, get_option($option));
409
+ elseif (isset($globalTax[$tax])) :
410
+ $globalCats = $globalTax[$tax];
411
+ else :
412
+ $globalCats = array();
413
+ endif;
414
+ $globalCats = array_map('trim', $globalCats);
415
+
416
+ if ($page->for_feed_settings()) :
417
+ $add_global_categories = $link->setting("add/$tax", NULL, 'yes');
418
+ $checked = array('yes' => '', 'no' => '');
419
+ $checked[$add_global_categories] = ' checked="checked"';
420
+
421
+ if (isset($setting_map[$tax])) :
422
+ $setting = $setting_map[$tax];
423
+ $cats = $link->setting($setting, NULL, NULL);
424
+ if (is_null($cats)) : $cats = array(); endif;
425
+ elseif (isset($terms[$tax])) :
426
+ $cats = $terms[$tax];
427
+ else :
428
+ $cats = array();
429
+ endif;
430
+ else :
431
+ $cats = $globalCats;
432
+ endif;
433
+
434
+ if ($page->for_feed_settings()) :
435
+ ?>
436
+ <table class="twofer">
437
+ <tbody>
438
+ <tr>
439
+ <td class="primary">
440
+ <?php
441
+ endif;
442
+
443
+ $dogs = SyndicatedPost::category_ids($cats, /*unfamiliar=*/ NULL, /*taxonomies=*/ array($tax));
444
+
445
+ if ($taxonomy->hierarchical) : // Use a category-style checkbox
446
+ fwp_category_box($dogs, 'all '.$page->these_posts_phrase(), /*tags=*/ array(), /*params=*/ array('taxonomy' => $tax));
447
+ else : // Use a tag-style edit box
448
+ fwp_tags_box($cats, 'all '.$page->these_posts_phrase(), /*params=*/ array('taxonomy' => $tax));
449
+ endif;
450
+
451
+ $globalDogs = SyndicatedPost::category_ids($globalCats, /*unfamiliar=*/ 'create:'.$tax, /*taxonomies=*/ array($tax));
452
 
453
+ $siteWideHref = 'admin.php?page='.$GLOBALS['fwp_path'].'/'.basename(__FILE__);
454
+ if ($page->for_feed_settings()) :
455
+ ?>
456
+ </td>
457
+ <td class="secondary">
458
+ <h4>Site-wide <?php print $taxonomy->labels->name; ?></h4>
459
+ <?php if (count($globalCats) > 0) : ?>
460
+ <ul class="current-setting">
461
+ <?php
462
+ foreach ($globalDogs as $dog) :
463
+ ?>
464
+ <li><?php $cat = get_term($dog, $tax); print $cat->name; ?></li>
465
+ <?php endforeach; ?>
466
+ </ul>
467
+ </div>
468
+ <p>
469
+ <?php else : ?>
470
+ <p>Site-wide settings may also assign categories to syndicated
471
+ posts.
472
+ <?php endif; ?>
473
+ Should <?php print $page->these_posts_phrase(); ?> be assigned
474
+ these <?php print $taxonomy->labels->name; ?> from the <a href="<?php print esc_html($siteWideHref); ?>">site-wide settings</a>, in
475
+ addition to the feed-specific <?php print $taxonomy->labels->name; ?> you set up here?</p>
476
+
477
+ <ul class="settings">
478
+ <li><p><label><input type="radio" name="add_global[<?php print $tax; ?>]" value="yes" <?php print $checked['yes']; ?> /> Yes. Place <?php print $page->these_posts_phrase(); ?> under all these categories.</label></p></li>
479
+ <li><p><label><input type="radio" name="add_global[<?php print $tax; ?>]" value="no" <?php print $checked['no']; ?> /> No. Only use the categories I set up on the left. Do not ise the global defaults for <?php print $page->these_posts_phrase(); ?></label></p></li>
480
+ </ul>
481
+ </td>
482
+ </tr>
483
+ </tbody>
484
+ </table>
485
+ <?php
486
+ endif;
487
+ ?>
488
+ </td>
489
+ </tr>
490
+ <?php
491
+ endforeach;
492
+ ?>
493
+ </tbody>
494
+ </table>
495
+ <?php
496
+ } /* FeedWordPressCategoriesPage::categories_box () */
497
+
498
+ function save_settings ($post) {
499
+ if (isset($post['match_categories'])) :
500
+ foreach ($post['match_categories'] as $what => $set) :
501
+ // Defaulting is controlled by a separate radio button
502
+ if ($this->for_feed_settings()
503
+ and isset($post['match_default'])
504
+ and isset($post['match_default'][$what])
505
+ and $post['match_default'][$what]=='yes') :
506
+ $set = NULL; // Defaulted!
507
+ endif;
508
+
509
+ $this->update_setting("match/$what", $set, NULL);
510
  endforeach;
511
  endif;
512
+ $optionMap = $this->term_option_map();
513
+ $settingMap = $this->term_setting_map();
514
 
515
+ $saveTerms = array(); $separateSaveTerms = array('category' => array(), 'post_tag' => array());
516
+
517
+ if (!isset($post['tax_input'])) : $post['tax_input'] = array(); endif;
518
+
519
+ // Merge in data from older-notation category check boxes
520
+ if (isset($post['post_category'])) :
521
+ // Just merging in for processing below.
522
+ $post['tax_input']['category'] = array_merge(
523
+ (isset($post['tax_input']['category']) ? $post['tax_input']['category'] : array()),
524
+ $post['post_category']
525
+ );
526
  endif;
 
 
 
 
527
 
528
+ // Process data from term tag boxes and check boxes
529
+ foreach ($post['tax_input'] as $tax => $terms) :
530
+ $saveTerms[$tax] = array();
531
+ if (is_array($terms)) : // Numeric IDs from checklist
532
+ foreach ($terms as $term) :
533
+ if ($term) :
534
+ $saveTerms[$tax][] = '{'.$tax.'#'.$term.'}';
535
+ endif;
536
+ endforeach;
537
+ else : // String from tag input
538
+ $saveTerms[$tax] = explode(",", $terms);
539
  endif;
540
+ $saveTerms[$tax] = array_map('trim', $saveTerms[$tax]);
541
+
542
+ if (isset($optionMap[$tax])) :
543
+ $separateSaveTerms[$tax] = $saveTerms[$tax];
544
+ unset($saveTerms[$tax]);
 
 
 
 
 
 
545
  endif;
546
+ endforeach;
547
 
548
+ if (isset($post['post_category'])) :
549
+ foreach ($post['post_category'] as $cat) :
550
+ $separateSaveTerms['category'][] = '{category#'.$cat.'}';
551
+ endforeach;
552
+ endif;
553
+
554
+ // Unmatched categories and tags
555
+ foreach (array('category', 'post_tag') as $what) :
556
+ if (isset($post["unfamiliar_{$what}"])) :
557
+ $this->update_setting(
558
+ "unfamiliar {$what}",
559
+ $post["unfamiliar_{$what}"],
560
+ 'site-default'
561
+ );
562
+ endif;
563
+ endforeach;
564
+
565
+ // Categories and Tags
566
+ foreach ($separateSaveTerms as $tax => $terms) :
567
+ if ($this->for_feed_settings()) :
568
+ $this->link->update_setting($settingMap[$tax], $terms, array());
569
+ else :
570
+ if (!empty($terms)) :
571
+ update_option($optionMap[$tax], implode(FEEDWORDPRESS_CAT_SEPARATOR, $terms));
572
  else :
573
+ delete_option($optionMap[$tax]);
574
  endif;
575
  endif;
576
+ endforeach;
577
+
578
+ // Other terms
579
+ $this->update_setting(array('feed'=>'terms', 'global'=>'syndication_terms'), $saveTerms, array());
580
 
581
+ if ($this->for_feed_settings()) :
582
+ // Category splitting regex
583
+ if (isset($post['cat_split'])) :
584
+ $this->link->update_setting('cat_split', trim($post['cat_split']), '');
 
 
 
 
 
 
 
 
 
 
585
  endif;
586
+
587
+ // Treat global terms (cats, tags, etc.) as additional,
588
+ // or as defaults to be overridden and replaced?
589
+ if (isset($post['add_global'])) :
590
+ foreach ($post['add_global'] as $what => $value) :
591
+ $this->link->update_setting("add/$what", $value);
592
+ endforeach;
593
  endif;
 
 
 
 
594
  endif;
595
+ parent::save_settings($post);
596
+ } /* FeedWordPressCategoriesPage::save_settings() */
 
 
 
 
 
 
 
597
 
598
+ function display () {
599
+ ////////////////////////////////////////////////
600
+ // Display settings boxes //////////////////////
601
+ ////////////////////////////////////////////////
602
+
603
+ $this->boxes_by_methods = array(
604
+ 'feed_categories_box' => __('Feed Categories'.FEEDWORDPRESS_AND_TAGS),
605
+ 'categories_box' => array('title' => __('Categories'), 'id' => 'categorydiv'),
606
+ );
607
+ if (!FeedWordPressCompatibility::post_tags()) :
608
+ unset($this->boxes_by_methods['tags_box']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
609
  endif;
610
 
611
+ parent::display();
612
+ }
613
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
614
 
615
+ $categoriesPage = new FeedWordPressCategoriesPage;
616
+ $categoriesPage->display();
617
 
compatability.php CHANGED
@@ -3,21 +3,17 @@
3
  ## LEGACY API: Replicate or mock up functions for legacy support purposes ######
4
  ################################################################################
5
 
6
- // version testing
7
- function fwp_test_wp_version ($floor, $ceiling = NULL) {
8
- global $wp_db_version;
9
-
10
- $ver = (isset($wp_db_version) ? $wp_db_version : 0);
11
- $good = ($ver >= $floor);
12
- if (!is_null($ceiling)) :
13
- $good = ($good and ($ver < $ceiling));
14
- endif;
15
- return $good;
16
- } /* function fwp_test_wp_version () */
17
-
18
  class FeedWordPressCompatibility {
 
19
  /*static*/ function test_version ($floor, $ceiling = null) {
20
- return fwp_test_wp_version($floor, $ceiling);
 
 
 
 
 
 
 
21
  } /* FeedWordPressCompatibility::test_version() */
22
 
23
  /*static*/ function insert_link_category ($name) {
@@ -26,30 +22,8 @@ class FeedWordPressCompatibility {
26
  $name = $wpdb->escape($name);
27
 
28
  // WordPress 2.3+ term/taxonomy API
29
- if (function_exists('wp_insert_term')) :
30
- $term = wp_insert_term($name, 'link_category');
31
- $cat_id = $term['term_id'];
32
- // WordPress 2.1, 2.2 category API. By the way, why the fuck is this API function only available in a wp-admin module?
33
- elseif (function_exists('wp_insert_category') and !fwp_test_wp_version(FWP_SCHEMA_20, FWP_SCHEMA_21)) :
34
- $cat_id = wp_insert_category(array('cat_name' => $name));
35
- // WordPress 1.5 and 2.0.x
36
- elseif (fwp_test_wp_version(0, FWP_SCHEMA_21)) :
37
- $result = $wpdb->query("
38
- INSERT INTO $wpdb->linkcategories
39
- SET
40
- cat_id = 0,
41
- cat_name='$name',
42
- show_images='N',
43
- show_description='N',
44
- show_rating='N',
45
- show_updated='N',
46
- sort_order='name'
47
- ");
48
- $cat_id = $wpdb->insert_id;
49
- // This should never happen.
50
- else :
51
- FeedWordPress::critical_bug('FeedWordPress::link_category_id::wp_db_version', $wp_db_version, __LINE__);
52
- endif;
53
 
54
  // Return newly-created category ID
55
  return $cat_id;
@@ -124,101 +98,11 @@ if (!function_exists('stripslashes_deep')) {
124
  }
125
  }
126
 
127
- if (!function_exists('get_option')) {
128
- function get_option ($option) {
129
- return get_settings($option);
130
- }
131
- }
132
- if (!function_exists('current_user_can')) {
133
- $fwp_capability['manage_options'] = 6;
134
- $fwp_capability['manage_links'] = 5;
135
- function current_user_can ($task) {
136
- global $user_level;
137
-
138
- $can = false;
139
-
140
- // This is **not** a full replacement for current_user_can. It
141
- // is only for checking the capabilities we care about via the
142
- // WordPress 1.5 user levels.
143
- switch ($task) :
144
- case 'manage_options':
145
- $can = ($user_level >= 6);
146
- break;
147
- case 'manage_links':
148
- $can = ($user_level >= 5);
149
- break;
150
- case 'edit_files':
151
- $can = ($user_level >= 9);
152
- break;
153
- endswitch;
154
- return $can;
155
- }
156
- } else {
157
- $fwp_capability['manage_options'] = 'manage_options';
158
- $fwp_capability['manage_links'] = 'manage_links';
159
- }
160
  if (!function_exists('sanitize_user')) {
161
  function sanitize_user ($text, $strict = false) {
162
  return $text; // Don't munge it if it wasn't munged going in...
163
  }
164
  }
165
- if (!function_exists('wp_insert_user')) {
166
- function wp_insert_user ($userdata) {
167
- global $wpdb;
168
-
169
- #-- Help WordPress 1.5.x quack like a duck
170
- $login = $userdata['user_login'];
171
- $author = $userdata['display_name'];
172
- $nice_author = $userdata['user_nicename'];
173
- $email = $userdata['user_email'];
174
- $url = $userdata['user_url'];
175
-
176
- $wpdb->query (
177
- "INSERT INTO $wpdb->users
178
- SET
179
- ID='0',
180
- user_login='$login',
181
- user_firstname='$author',
182
- user_nickname='$author',
183
- user_nicename='$nice_author',
184
- user_description='$author',
185
- user_email='$email',
186
- user_url='$url'");
187
- $id = $wpdb->insert_id;
188
-
189
- return $id;
190
- }
191
- } /* if (!function_exists('wp_insert_user')) */
192
-
193
- if (!function_exists('wp_die')) {
194
- function wp_die ( $message, $title = '', $args = array() ) {
195
- die($message);
196
- } /* wp_die() */
197
- } /* if */
198
-
199
- if (!function_exists('add_post_meta')) {
200
- function add_post_meta ($postId, $key, $value, $unique) {
201
- global $wpdb;
202
-
203
- $postId = (int) $postId;
204
- $key = $wpdb->escape($key);
205
- $value = $wpdb->escape($value);
206
-
207
- $result = $wpdb->query("
208
- INSERT INTO $wpdb->postmeta
209
- SET
210
- post_id='$postId',
211
- meta_key='$key',
212
- meta_value='$value'
213
- ");
214
- if (!$result) :
215
- $err = mysql_error();
216
- if (FEEDWORDPRESS_DEBUG) :
217
- echo "[DEBUG:".date('Y-m-d H:i:S')."][feedwordpress]: post metadata insertion FAILED for field '$key' := '$value': [$err]";
218
- endif;
219
- endif;
220
- } /* add_post_meta() */
221
- } /* if */
222
 
223
  if (!function_exists('disabled')) {
224
  /**
@@ -244,36 +128,29 @@ if (!function_exists('term_exists')) {
244
  return is_term($term, $taxonomy, $parent);
245
  }
246
  } /* if */
247
- require_once(dirname(__FILE__).'/feedwordpress-walker-category-checklist.class.php');
248
 
249
- function fwp_category_checklist ($post_id = 0, $descendents_and_self = 0, $selected_cats = false, $prefix = '') {
250
- if (function_exists('wp_category_checklist')) :
251
- $walker = new FeedWordPress_Walker_Category_Checklist;
252
- $walker->set_prefix($prefix);
253
- wp_category_checklist(
254
- /*post_id=*/ $post_id,
255
- /*descendents_and_self=*/ $descendents_and_self,
256
- /*selected_cats=*/ $selected_cats,
257
- /*popular_cats=*/ false,
258
- /*walker=*/ $walker
259
- );
260
- else :
261
- // selected_cats is an array of integer cat_IDs / term_ids for
262
- // the categories that should be checked
263
- global $post_ID;
264
 
265
- $cats = get_nested_categories();
266
-
267
- // Undo damage from usort() in WP 2.0
268
- $dogs = array();
269
- foreach ($cats as $cat) :
270
- $dogs[$cat['cat_ID']] = $cat;
271
- endforeach;
272
- foreach ($selected_cats as $cat_id) :
273
- $dogs[$cat_id]['checked'] = true;
274
- endforeach;
275
- write_nested_categories($dogs);
276
  endif;
 
 
 
 
 
 
 
 
 
 
 
 
277
  }
278
 
279
  function fwp_time_elapsed ($ts) {
@@ -339,3 +216,7 @@ like me you may want to back up your database before you proceed.</p>
339
  <?php
340
  } // function fwp_upgrade_page ()
341
 
 
 
 
 
3
  ## LEGACY API: Replicate or mock up functions for legacy support purposes ######
4
  ################################################################################
5
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  class FeedWordPressCompatibility {
7
+ // version testing based on database schema version
8
  /*static*/ function test_version ($floor, $ceiling = null) {
9
+ global $wp_db_version;
10
+
11
+ $ver = (isset($wp_db_version) ? $wp_db_version : 0);
12
+ $good = ($ver >= $floor);
13
+ if (!is_null($ceiling)) :
14
+ $good = ($good and ($ver < $ceiling));
15
+ endif;
16
+ return $good;
17
  } /* FeedWordPressCompatibility::test_version() */
18
 
19
  /*static*/ function insert_link_category ($name) {
22
  $name = $wpdb->escape($name);
23
 
24
  // WordPress 2.3+ term/taxonomy API
25
+ $term = wp_insert_term($name, 'link_category');
26
+ $cat_id = $term['term_id'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
  // Return newly-created category ID
29
  return $cat_id;
98
  }
99
  }
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  if (!function_exists('sanitize_user')) {
102
  function sanitize_user ($text, $strict = false) {
103
  return $text; // Don't munge it if it wasn't munged going in...
104
  }
105
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
  if (!function_exists('disabled')) {
108
  /**
128
  return is_term($term, $taxonomy, $parent);
129
  }
130
  } /* if */
 
131
 
132
+ require_once(dirname(__FILE__).'/feedwordpress-walker-category-checklist.class.php');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
+ function fwp_category_checklist ($post_id = 0, $descendents_and_self = 0, $selected_cats = false, $params = array()) {
135
+ if (is_string($params)) :
136
+ $prefix = $params;
137
+ $taxonomy = 'category';
138
+ elseif (is_array($params)) :
139
+ $prefix = (isset($params['prefix']) ? $params['prefix'] : '');
140
+ $taxonomy = (isset($params['taxonomy']) ? $params['taxonomy'] : 'category');
 
 
 
 
141
  endif;
142
+
143
+ $walker = new FeedWordPress_Walker_Category_Checklist;
144
+ $walker->set_prefix($prefix);
145
+ $walker->set_taxonomy($taxonomy);
146
+ wp_terms_checklist(/*post_id=*/ $post_id, array(
147
+ 'taxonomy' => $taxonomy,
148
+ 'descendents_and_self' => $descendents_and_self,
149
+ 'selected_cats' => $selected_cats,
150
+ 'popular_cats' => false,
151
+ 'walker' => $walker,
152
+ 'checked_ontop' => true,
153
+ ));
154
  }
155
 
156
  function fwp_time_elapsed ($ts) {
216
  <?php
217
  } // function fwp_upgrade_page ()
218
 
219
+ function remove_dummy_zero ($var) {
220
+ return !(is_numeric($var) and ((int) $var == 0));
221
+ }
222
+
diagnostics-page.php CHANGED
@@ -44,7 +44,7 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
44
  );
45
 
46
  foreach ($boxes_by_methods as $method => $title) :
47
- fwp_add_meta_box(
48
  /*id=*/ 'feedwordpress_'.$method,
49
  /*title=*/ $title,
50
  /*callback=*/ array('FeedWordPressDiagnosticsPage', $method),
@@ -68,7 +68,6 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
68
  function accept_POST ($post) {
69
  if (isset($post['submit'])
70
  or isset($post['save'])) :
71
- update_option('feedwordpress_update_logging', $post['update_logging']);
72
  update_option('feedwordpress_debug', $post['feedwordpress_debug']);
73
 
74
  if (!isset($post['diagnostics_output'])
@@ -89,38 +88,35 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
89
 
90
  /*static*/ function diagnostics_box ($page, $box = NULL) {
91
  $settings = array();
92
- $settings['update_logging'] = (get_option('feedwordpress_update_logging')=='yes');
93
  $settings['debug'] = (get_option('feedwordpress_debug')=='yes');
94
 
95
  $diagnostics_output = get_option('feedwordpress_diagnostics_output', array());
96
 
97
  // Hey ho, let's go...
98
  ?>
99
- <table class="editform" width="100%" cellspacing="2" cellpadding="5">
100
  <tr style="vertical-align: top">
101
- <th width="33%" scope="row">Logging:</th>
102
- <td width="67%"><select name="update_logging" size="1">
103
- <option value="yes"<?php echo ($settings['update_logging'] ?' selected="selected"':''); ?>>log updates, new posts, and updated posts in PHP logs</option>
104
- <option value="no"<?php echo ($settings['update_logging'] ?'':' selected="selected"'); ?>>don't log updates</option>
105
- </select></td>
106
- </tr>
107
- <tr style="vertical-align: top">
108
- <th width="33%" scope="row">Debugging mode:</th>
109
- <td width="67%"><select name="feedwordpress_debug" size="1">
110
  <option value="yes"<?php echo ($settings['debug'] ? ' selected="selected"' : ''); ?>>on</option>
111
  <option value="no"<?php echo ($settings['debug'] ? '' : ' selected="selected"'); ?>>off</option>
112
  </select>
113
- <p>When debugging mode is <strong>ON</strong>, FeedWordPress displays many diagnostic error messages,
114
- warnings, and notices that are ordinarily suppressed, and turns off all caching of feeds. Use with
115
- caution: this setting is absolutely inappropriate for a production server.</p>
 
 
 
116
  </td>
117
  </tr>
118
- <tr style="vertical-align: top">
119
- <th width="33%" scope="row">Diagnostics output:</th>
120
- <td width="67%"><ul class="options">
121
  <li><input type="checkbox" name="diagnostics_output[]" value="error_log" <?php print (in_array('error_log', $diagnostics_output) ? ' checked="checked"' : ''); ?> /> Log in PHP error logs</label></li>
122
  <li><input type="checkbox" name="diagnostics_output[]" value="admin_footer" <?php print (in_array('admin_footer', $diagnostics_output) ? ' checked="checked"' : ''); ?> /> Display in WordPress admin footer</label></li>
123
  <li><input type="checkbox" name="diagnostics_output[]" value="echo" <?php print (in_array('echo', $diagnostics_output) ? ' checked="checked"' : ''); ?> /> Echo in web browser as they are issued</label></li>
 
 
124
  </ul></td>
125
  </tr>
126
  </table>
@@ -129,7 +125,8 @@ caution: this setting is absolutely inappropriate for a production server.</p>
129
 
130
  /*static*/ function updates_box ($page, $box = NULL) {
131
  $checked = array(
132
- 'updated_feeds' => '',
 
133
  "syndicated_posts" => '', 'syndicated_posts:meta_data' => '',
134
  'feed_items' => '',
135
  'memory_usage' => '',
@@ -142,20 +139,21 @@ caution: this setting is absolutely inappropriate for a production server.</p>
142
 
143
  // Hey ho, let's go...
144
  ?>
145
- <table class="editform" width="100%" cellspacing="2" cellpadding="5">
146
- <tr style="vertical-align: top">
147
- <th width="33%" scope="row">Update diagnostics:</th>
148
- <td width="67%">
149
- <p>Show a diagnostic message...</p>
150
  <ul class="options">
151
  <li><label><input type="checkbox" name="diagnostics_show[]" value="updated_feeds" <?php print $checked['updated_feeds']; ?> /> as each feed checked for updates</label></li>
 
 
152
  <li><label><input type="checkbox" name="diagnostics_show[]" value="syndicated_posts" <?php print $checked['syndicated_posts']; ?> /> as each syndicated post is added to the database</label></li>
153
  <li><label><input type="checkbox" name="diagnostics_show[]" value="feed_items" <?php print $checked['feed_items']; ?> /> as each syndicated item is considered on the feed</label></li>
154
  <li><label><input type="checkbox" name="diagnostics_show[]" value="memory_usage" <?php print $checked['memory_usage']; ?> /> indicating how much memory was used</label></li>
155
  </ul></td>
156
  </tr>
157
- <tr style="vertical-align: top">
158
- <th width="33%" scope="row">Syndicated post details:</th>
159
  <td><p>Show a diagnostic message...</p>
160
  <ul class="options">
161
  <li><label><input type="checkbox" name="diagnostics_show[]" value="syndicated_posts:meta_data" <?php print $checked['syndicated_posts:meta_data']; ?> /> as syndication meta-data is added on the post</label></li>
44
  );
45
 
46
  foreach ($boxes_by_methods as $method => $title) :
47
+ add_meta_box(
48
  /*id=*/ 'feedwordpress_'.$method,
49
  /*title=*/ $title,
50
  /*callback=*/ array('FeedWordPressDiagnosticsPage', $method),
68
  function accept_POST ($post) {
69
  if (isset($post['submit'])
70
  or isset($post['save'])) :
 
71
  update_option('feedwordpress_debug', $post['feedwordpress_debug']);
72
 
73
  if (!isset($post['diagnostics_output'])
88
 
89
  /*static*/ function diagnostics_box ($page, $box = NULL) {
90
  $settings = array();
 
91
  $settings['debug'] = (get_option('feedwordpress_debug')=='yes');
92
 
93
  $diagnostics_output = get_option('feedwordpress_diagnostics_output', array());
94
 
95
  // Hey ho, let's go...
96
  ?>
97
+ <table class="edit-form">
98
  <tr style="vertical-align: top">
99
+ <th scope="row">Debugging mode:</th>
100
+ <td><select name="feedwordpress_debug" size="1">
 
 
 
 
 
 
 
101
  <option value="yes"<?php echo ($settings['debug'] ? ' selected="selected"' : ''); ?>>on</option>
102
  <option value="no"<?php echo ($settings['debug'] ? '' : ' selected="selected"'); ?>>off</option>
103
  </select>
104
+
105
+ <p>When debugging mode is <strong>ON</strong>, FeedWordPress displays many
106
+ diagnostic error messages, warnings, and notices that are ordinarily suppressed,
107
+ and turns off all caching of feeds. Use with caution: this setting is useful for
108
+ testing but absolutely inappropriate for a production server.</p>
109
+
110
  </td>
111
  </tr>
112
+ <tr>
113
+ <th scope="row">Diagnostics output:</th>
114
+ <td><ul class="options">
115
  <li><input type="checkbox" name="diagnostics_output[]" value="error_log" <?php print (in_array('error_log', $diagnostics_output) ? ' checked="checked"' : ''); ?> /> Log in PHP error logs</label></li>
116
  <li><input type="checkbox" name="diagnostics_output[]" value="admin_footer" <?php print (in_array('admin_footer', $diagnostics_output) ? ' checked="checked"' : ''); ?> /> Display in WordPress admin footer</label></li>
117
  <li><input type="checkbox" name="diagnostics_output[]" value="echo" <?php print (in_array('echo', $diagnostics_output) ? ' checked="checked"' : ''); ?> /> Echo in web browser as they are issued</label></li>
118
+ <li><input type="checkbox" name="diagnostics_output[]" value="echo_in_cronjob" <?php print (in_array('echo_in_cronjob', $diagnostics_output) ? ' checked="checked"' : ''); ?> /> Echo to output when they are issued during an update cron job</label></li>
119
+ <li><input type="checkbox" name="diagnostics_output[]" value="email" <?php print (in_array('email', $diagnostics_output) ? ' checked="checked"' : ''); ?> /> Send a daily email digest to the site administrator</label></li>
120
  </ul></td>
121
  </tr>
122
  </table>
125
 
126
  /*static*/ function updates_box ($page, $box = NULL) {
127
  $checked = array(
128
+ 'updated_feeds' => '', 'updated_feeds:errors' => '',
129
+ 'updated_feeds:errors:persistent' => '',
130
  "syndicated_posts" => '', 'syndicated_posts:meta_data' => '',
131
  'feed_items' => '',
132
  'memory_usage' => '',
139
 
140
  // Hey ho, let's go...
141
  ?>
142
+ <table class="edit-form">
143
+ <tr>
144
+ <th scope="row">Update diagnostics:</th>
145
+ <td><p>Show a diagnostic message...</p>
 
146
  <ul class="options">
147
  <li><label><input type="checkbox" name="diagnostics_show[]" value="updated_feeds" <?php print $checked['updated_feeds']; ?> /> as each feed checked for updates</label></li>
148
+ <li><label><input type="checkbox" name="diagnostics_show[]" value="updated_feeds:errors:persistent" <?php print $checked['updated_feeds:errors:persistent'] ?> /> when FeedWordPress encounters repeated errors while checking a feed for updates</label></li>
149
+ <li><label><input type="checkbox" name="diagnostics_show[]" value="updated_feeds:errors" <?php print $checked['updated_feeds:errors']; ?> /> any time FeedWordPress encounters any errors while checking a feed for updates</label></li>
150
  <li><label><input type="checkbox" name="diagnostics_show[]" value="syndicated_posts" <?php print $checked['syndicated_posts']; ?> /> as each syndicated post is added to the database</label></li>
151
  <li><label><input type="checkbox" name="diagnostics_show[]" value="feed_items" <?php print $checked['feed_items']; ?> /> as each syndicated item is considered on the feed</label></li>
152
  <li><label><input type="checkbox" name="diagnostics_show[]" value="memory_usage" <?php print $checked['memory_usage']; ?> /> indicating how much memory was used</label></li>
153
  </ul></td>
154
  </tr>
155
+ <tr>
156
+ <th>Syndicated post details:</th>
157
  <td><p>Show a diagnostic message...</p>
158
  <ul class="options">
159
  <li><label><input type="checkbox" name="diagnostics_show[]" value="syndicated_posts:meta_data" <?php print $checked['syndicated_posts:meta_data']; ?> /> as syndication meta-data is added on the post</label></li>
down.png ADDED
Binary file
feedfinder.class.php CHANGED
@@ -5,14 +5,18 @@
5
  * @uses SimplePie_Misc
6
  */
7
 
8
- require_once(ABSPATH . WPINC . '/class-simplepie.php');
 
 
 
9
 
10
  class FeedFinder {
11
  var $uri = NULL;
12
  var $_cache_uri = NULL;
13
 
14
  var $verify = FALSE;
15
-
 
16
  var $_response = NULL;
17
  var $_data = NULL;
18
  var $_error = NULL;
@@ -28,50 +32,65 @@ class FeedFinder {
28
  );
29
  var $_feed_markers = array('\\<feed', '\\<rss', 'xmlns="http://purl.org/rss/1.0');
30
  var $_html_markers = array('\\<html');
 
31
  var $_obvious_feed_url = array('[./]rss', '[./]rdf', '[./]atom', '[./]feed', '\.xml');
32
  var $_maybe_feed_url = array ('rss', 'rdf', 'atom', 'feed', 'xml');
33
 
34
- function FeedFinder ($uri = NULL, $verify = TRUE) {
35
  $this->uri = $uri; $this->verify = $verify;
 
36
  } /* FeedFinder::FeedFinder () */
37
 
38
  function find ($uri = NULL) {
39
  $ret = array ();
40
- if (!is_null($this->data($uri))) {
41
- if ($this->is_feed($uri)) {
42
- $href = array($this->uri);
43
- } else {
44
- // Assume that we have HTML or XHTML (even if we don't, who's it gonna hurt?)
45
- // Autodiscovery is the preferred method
46
- $href = $this->_link_rel_feeds();
47
-
48
- // ... but we'll also take the little orange buttons
49
- $href = array_merge($href, $this->_a_href_feeds(TRUE));
50
-
51
- // If all that failed, look harder
52
- if (count($href) == 0) $href = $this->_a_href_feeds(FALSE);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
- // Our search may turn up duplicate URIs. We only need to do any given URI once.
55
- // Props to Camilo <http://projects.radgeek.com/2008/12/14/feedwordpress-20081214/#comment-20090122160414>
56
- $href = array_unique($href);
57
- } /* if */
 
58
 
59
- // Try some clever URL little tricks before we go
60
- $href = array_merge($href, $this->_url_manipulation_feeds());
61
  $href = array_unique($href);
62
 
63
  // Verify feeds and resolve relative URIs
64
- foreach ($href as $u) {
65
  $the_uri = SimplePie_Misc::absolutize_url($u, $this->uri);
66
- if ($this->verify and ($u != $this->uri and $the_uri != $this->uri)) {
67
  $feed = new FeedFinder($the_uri);
68
  if ($feed->is_feed()) : $ret[] = $the_uri; endif;
69
  unset($feed);
70
- } else {
71
  $ret[] = $the_uri;
72
- }
73
- } /* foreach */
74
- } /* if */
75
 
76
  return array_values($ret);
77
  } /* FeedFinder::find () */
@@ -79,8 +98,13 @@ class FeedFinder {
79
  function data ($uri = NULL) {
80
  $this->_get($uri);
81
  return $this->_data;
82
- }
83
 
 
 
 
 
 
84
  function status ($uri = NULL) {
85
  $this->_get($uri);
86
 
@@ -118,12 +142,22 @@ class FeedFinder {
118
  );
119
  } /* FeedFinder::is_feed () */
120
 
 
 
 
 
 
 
 
 
 
 
121
  # --- Private methods ---
122
  function _get ($uri = NULL) {
123
  if ($uri) $this->uri = $uri;
124
 
125
  // Is the result not yet cached?
126
- if ($this->_cache_uri !== $this->uri) :
127
  $headers['Connection'] = 'close';
128
  $headers['Accept'] = 'application/atom+xml application/rdf+xml application/rss+xml application/xml text/html */*';
129
  $headers['User-Agent'] = 'feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress';
@@ -148,6 +182,23 @@ class FeedFinder {
148
  endif;
149
  } /* FeedFinder::_get () */
150
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  function _link_rel_feeds () {
152
  $links = $this->_tags('link');
153
  $link_count = count($links);
@@ -162,7 +213,7 @@ class FeedFinder {
162
  } /* if */
163
  } /* for */
164
  return $href;
165
- }
166
 
167
  function _a_href_feeds ($obvious = TRUE) {
168
  $pattern = ($obvious ? $this->_obvious_feed_url : $this->_maybe_feed_url);
@@ -178,11 +229,11 @@ class FeedFinder {
178
  } /* if */
179
  } /* for */
180
  return $href;
181
- }
182
 
183
  function _url_manipulation_feeds () {
184
  $href = array();
185
-
186
  // check for HTTP GET parameters that look feed-like.
187
  $bits = parse_url($this->uri);
188
  foreach (array('rss', 'rss2', 'atom', 'rdf') as $format) :
@@ -233,7 +284,7 @@ class FeedFinder {
233
  $href = array_merge($href, $newUrl);
234
  endforeach;
235
  return array_unique($href);
236
- }
237
 
238
  function _tags ($tag) {
239
  $html = $this->data();
@@ -256,6 +307,6 @@ class FeedFinder {
256
  $ret[$n] = $final_link;
257
  } /* for */
258
  return $ret;
259
- }
260
  } /* class FeedFinder */
261
 
5
  * @uses SimplePie_Misc
6
  */
7
 
8
+ if (!class_exists('SimplePie')) :
9
+ require_once(ABSPATH . WPINC . '/class-simplepie.php');
10
+ endif;
11
+ require_once(dirname(__FILE__).'/feedwordpresshtml.class.php');
12
 
13
  class FeedFinder {
14
  var $uri = NULL;
15
  var $_cache_uri = NULL;
16
 
17
  var $verify = FALSE;
18
+ var $fallbacks = 3;
19
+
20
  var $_response = NULL;
21
  var $_data = NULL;
22
  var $_error = NULL;
32
  );
33
  var $_feed_markers = array('\\<feed', '\\<rss', 'xmlns="http://purl.org/rss/1.0');
34
  var $_html_markers = array('\\<html');
35
+ var $_opml_markers = array('\\<opml', '\\<outline');
36
  var $_obvious_feed_url = array('[./]rss', '[./]rdf', '[./]atom', '[./]feed', '\.xml');
37
  var $_maybe_feed_url = array ('rss', 'rdf', 'atom', 'feed', 'xml');
38
 
39
+ function FeedFinder ($uri = NULL, $verify = TRUE, $fallbacks = 3) {
40
  $this->uri = $uri; $this->verify = $verify;
41
+ $this->fallbacks = $fallbacks;
42
  } /* FeedFinder::FeedFinder () */
43
 
44
  function find ($uri = NULL) {
45
  $ret = array ();
46
+ if (!is_null($this->data($uri))) :
47
+ if ($this->is_opml($uri)) :
48
+ $href = $this->_opml_rss_uris();
49
+ else :
50
+ if ($this->is_feed($uri)) :
51
+ $href = array($this->uri);
52
+ else :
53
+ // Assume that we have HTML or XHTML (even if we don't, who's it gonna hurt?)
54
+ // Autodiscovery is the preferred method
55
+ $href = $this->_link_rel_feeds();
56
+
57
+ // ... but we'll also take the little orange buttons
58
+ if ($this->fallbacks > 0) :
59
+ $href = array_merge($href, $this->_a_href_feeds(TRUE));
60
+ endif;
61
+
62
+ // If all that failed, look harder
63
+ if ($this->fallbacks > 1) :
64
+ if (count($href) == 0) :
65
+ $href = $this->_a_href_feeds(FALSE);
66
+ endif;
67
+ endif;
68
+
69
+ // Our search may turn up duplicate URIs. We only need to do any given URI once.
70
+ // Props to Camilo <http://projects.radgeek.com/2008/12/14/feedwordpress-20081214/#comment-20090122160414>
71
+ $href = array_unique($href);
72
+ endif;
73
 
74
+ // Try some clever URL little tricks before we go
75
+ if ($this->fallbacks > 2) :
76
+ $href = array_merge($href, $this->_url_manipulation_feeds());
77
+ endif;
78
+ endif;
79
 
 
 
80
  $href = array_unique($href);
81
 
82
  // Verify feeds and resolve relative URIs
83
+ foreach ($href as $u) :
84
  $the_uri = SimplePie_Misc::absolutize_url($u, $this->uri);
85
+ if ($this->verify and ($u != $this->uri and $the_uri != $this->uri)) :
86
  $feed = new FeedFinder($the_uri);
87
  if ($feed->is_feed()) : $ret[] = $the_uri; endif;
88
  unset($feed);
89
+ else :
90
  $ret[] = $the_uri;
91
+ endif;
92
+ endforeach;
93
+ endif;
94
 
95
  return array_values($ret);
96
  } /* FeedFinder::find () */
98
  function data ($uri = NULL) {
99
  $this->_get($uri);
100
  return $this->_data;
101
+ } /* FeedFinder::data () */
102
 
103
+ function upload_data ($data) {
104
+ $this->uri = 'tag:localhost';
105
+ $this->_data = $data;
106
+ } /* FeedFinder::upload_data () */
107
+
108
  function status ($uri = NULL) {
109
  $this->_get($uri);
110
 
142
  );
143
  } /* FeedFinder::is_feed () */
144
 
145
+ function is_opml ($uri = NULL) {
146
+ $data = $this->data($uri);
147
+ return (
148
+ preg_match (
149
+ "\007(".implode('|',$this->_opml_markers).")\007i",
150
+ $data
151
+ )
152
+ );
153
+ } /* FeedFinder::is_opml () */
154
+
155
  # --- Private methods ---
156
  function _get ($uri = NULL) {
157
  if ($uri) $this->uri = $uri;
158
 
159
  // Is the result not yet cached?
160
+ if ($this->uri != 'tag:localhost' and $this->_cache_uri !== $this->uri) :
161
  $headers['Connection'] = 'close';
162
  $headers['Accept'] = 'application/atom+xml application/rdf+xml application/rss+xml application/xml text/html */*';
163
  $headers['User-Agent'] = 'feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress';
182
  endif;
183
  } /* FeedFinder::_get () */
184
 
185
+ function _opml_rss_uris () {
186
+ // Really we should parse the XML and use the structure to
187
+ // return something intelligent to programs that want to use it
188
+ // Oh babe! maybe some day...
189
+
190
+ $opml = $this->data();
191
+
192
+ $rx = FeedWordPressHTML::attributeRegex('outline', 'xmlUrl');
193
+ if (preg_match_all($rx, $opml, $matches, PREG_SET_ORDER)) :
194
+ foreach ($matches as $m) :
195
+ $match = FeedWordPressHTML::attributeMatch($m);
196
+ $r[] = $match['value'];
197
+ endforeach;
198
+ endif;
199
+ return $r;
200
+ } /* FeedFinder::_opml_rss_uris () */
201
+
202
  function _link_rel_feeds () {
203
  $links = $this->_tags('link');
204
  $link_count = count($links);
213
  } /* if */
214
  } /* for */
215
  return $href;
216
+ } /* FeedFinder::_link_rel_feeds () */
217
 
218
  function _a_href_feeds ($obvious = TRUE) {
219
  $pattern = ($obvious ? $this->_obvious_feed_url : $this->_maybe_feed_url);
229
  } /* if */
230
  } /* for */
231
  return $href;
232
+ } /* FeedFinder::_link_a_href_feeds () */
233
 
234
  function _url_manipulation_feeds () {
235
  $href = array();
236
+
237
  // check for HTTP GET parameters that look feed-like.
238
  $bits = parse_url($this->uri);
239
  foreach (array('rss', 'rss2', 'atom', 'rdf') as $format) :
284
  $href = array_merge($href, $newUrl);
285
  endforeach;
286
  return array_unique($href);
287
+ } /* FeedFinder::_url_manipulation_feeds () */
288
 
289
  function _tags ($tag) {
290
  $html = $this->data();
307
  $ret[$n] = $final_link;
308
  } /* for */
309
  return $ret;
310
+ } /* FeedFinder::_tags () */
311
  } /* class FeedFinder */
312
 
feeds-page.php CHANGED
@@ -59,7 +59,12 @@ class FeedWordPressFeedsPage extends FeedWordPressAdminPage {
59
 
60
  FeedWordPressAdminPage::FeedWordPressAdminPage('feedwordpressfeeds', $link);
61
 
62
- $this->dispatch = get_class($this);
 
 
 
 
 
63
  $this->filename = __FILE__;
64
  $this->updatedPosts = new UpdatedPostsControl($this);
65
  } /* FeedWordPressFeedsPage constructor */
@@ -67,130 +72,94 @@ class FeedWordPressFeedsPage extends FeedWordPressAdminPage {
67
  var $special_settings = array ( /* Regular expression syntax is OK here */
68
  'cats',
69
  'cat_split',
 
70
  'hardcode name',
71
  'hardcode url',
72
  'hardcode description',
73
  'hardcode categories', /* Deprecated */
74
- 'post status',
75
  'comment status',
 
 
 
76
  'ping status',
 
 
 
 
 
77
  'unfamiliar author',
78
  'unfamliar categories', /* Deprecated */
79
  'unfamiliar category',
80
- 'map authors',
81
- 'tags',
82
- 'postmeta',
83
- 'resolve relative',
84
- 'freeze updates',
85
- 'munge permalink',
86
  'update/.*',
87
  'feed/.*',
88
  'link/.*',
 
89
  );
90
 
91
  function display () {
92
- global $wpdb;
93
  global $fwp_post;
94
  global $post_source;
95
-
96
- if (FeedWordPress::needs_upgrade()) :
97
- fwp_upgrade_page();
98
- return;
99
- endif;
100
 
 
 
 
 
 
 
 
 
 
 
101
  // Allow overriding of normal source for FeedFinder, which may
102
  // be called from multiple points.
103
  if (isset($post_source) and !is_null($post_source)) :
104
  $source = $post_source;
105
  else :
106
- $source = get_class($this);
107
  endif;
108
 
109
- // If this is a POST, validate source and user credentials
110
- FeedWordPressCompatibility::validate_http_request(/*action=*/ $source, /*capability=*/ 'manage_links');
111
-
112
  if (isset($_REQUEST['feedfinder'])
113
  or (isset($_REQUEST['action']) and $_REQUEST['action']=='feedfinder')
114
  or (isset($_REQUEST['action']) and $_REQUEST['action']==FWP_SYNDICATE_NEW)) :
 
 
 
115
  return $this->display_feedfinder(); // re-route to Feed Finder page
116
- else :
117
- if (strtoupper($_SERVER['REQUEST_METHOD'])=='POST') :
118
- $this->accept_POST($fwp_post);
119
- do_action('feedwordpress_admin_page_feeds_save', $GLOBALS['fwp_post'], $this);
120
- endif;
121
-
122
- ////////////////////////////////////////////////
123
- // Prepare settings page ///////////////////////
124
- ////////////////////////////////////////////////
125
-
126
- $this->ajax_interface_js();
127
- $this->display_update_notice_if_updated('Syndicated feed');
128
- $this->open_sheet('Feed and Update');
129
- ?>
130
- <div id="post-body">
131
- <?php
132
- ////////////////////////////////////////////////
133
- // Display settings boxes //////////////////////
134
- ////////////////////////////////////////////////
135
-
136
- $boxes_by_methods = array(
137
- 'feed_information_box' => __('Feed Information'),
138
- 'global_feeds_box' => __('Update Scheduling'),
139
- 'updated_posts_box' => __('Updated Posts'),
140
- 'posts_box' => __('Syndicated Posts, Links, Comments & Pings'),
141
- 'authors_box' => __('Syndicated Authors'),
142
- 'categories_box' => __('Categories'.FEEDWORDPRESS_AND_TAGS),
143
- 'custom_settings_box' => __('Custom Feed Settings (for use in templates)'),
144
- );
145
- if ($this->for_default_settings()) :
146
- unset($boxes_by_methods['custom_settings_box']);
147
- endif;
148
-
149
- foreach ($boxes_by_methods as $method => $row) :
150
- if (is_array($row)) :
151
- $id = $row['id'];
152
- $title = $row['title'];
153
- else :
154
- $id = 'feedwordpress_'.$method;
155
- $title = $row;
156
- endif;
157
-
158
- fwp_add_meta_box(
159
- /*id=*/ $id,
160
- /*title=*/ $title,
161
- /*callback=*/ array(get_class($this), $method),
162
- /*page=*/ $this->meta_box_context(),
163
- /*context=*/ $this->meta_box_context()
164
- );
165
- endforeach;
166
- do_action('feedwordpress_admin_page_feeds_meta_boxes', $this);
167
- ?>
168
- <div class="metabox-holder">
169
- <?php
170
- fwp_do_meta_boxes($this->meta_box_context(), $this->meta_box_context(), $this);
171
- ?>
172
- </div> <!-- class="metabox-holder" -->
173
- </div> <!-- id="post-body" -->
174
- <?php $this->close_sheet(); ?>
175
-
176
- <script type="text/javascript">
177
- var els = ['name', 'description', 'url'];
178
- for (var i = 0; i < els.length; i++) {
179
- contextual_appearance(
180
- /*item=*/ 'basics-hardcode-'+els[i],
181
- /*appear=*/ 'basics-'+els[i]+'-view',
182
- /*disappear=*/ 'basics-'+els[i]+'-edit',
183
- /*value=*/ 'no',
184
- /*visibleStyle=*/ 'block',
185
- /*checkbox=*/ true
186
- );
187
- } /* for */
188
- </script>
189
- <?php
190
  endif;
 
 
191
  return false; // Don't continue
192
  } /* FeedWordPressFeedsPage::display() */
193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  /*static*/ function updated_posts_box ($page, $box = NULL) {
195
  ?>
196
  <table class="edit-form">
@@ -200,22 +169,14 @@ class FeedWordPressFeedsPage extends FeedWordPressAdminPage {
200
  } /* FeedWordPressFeedsPage::updated_posts_box() */
201
 
202
  /*static*/ function global_feeds_box ($page, $box = NULL) {
203
- global $wpdb;
 
204
 
205
- $defaultUpdateWindow = get_option('feedwordpress_update_window');
206
- if (!is_numeric($defaultUpdateWindow)) :
207
- $defaultUpdateWindow = DEFAULT_UPDATE_PERIOD;
208
- else :
209
- $defaultUpdateWindow = (int) $defaultUpdateWindow;
210
- endif;
211
  ?>
212
-
213
  <table class="edit-form">
214
- <?php
215
- if ($page->for_default_settings()) :
216
- $automatic_updates = get_option('feedwordpress_automatic_updates');
217
- $update_time_limit = (int) get_option('feedwordpress_update_time_limit');
218
- ?>
219
 
220
  <tr>
221
  <th scope="row">Updates:</th>
@@ -236,36 +197,7 @@ class FeedWordPressFeedsPage extends FeedWordPressAdminPage {
236
  </td>
237
  </tr>
238
 
239
- <tr>
240
- <th scope="row"><?php print __('Update scheduling:') ?></th>
241
- <td><p style="margin-top:0px">How long should FeedWordPress wait between updates before it considers a feed ready to be polled for updates again?</p>
242
- <p style="font-style: italic; margin-left: 2.0em"><label>Wait <input type="text" name="update_window" value="<?php print $defaultUpdateWindow; ?>" size="4" /> minutes between polling.</label></p>
243
- <div class="setting-description">
244
- <p<?php if ($defaultUpdateWindow<50) : ?> style="color: white; background-color: #703030; padding: 1.0em;"<?php endif; ?>><strong>Recommendation.</strong> Unless you are positive that you have the webmaster's permission, you generally should not set FeedWordPress to poll feeds more frequently than once every 60 minutes. Many webmasters consider more frequent automated polling to be abusive, and may complain to your web host, or ban your IP address, as retaliation for hammering their servers too hard.</p>
245
- <p><strong>Note.</strong> This is a default setting that FeedWordPress uses to schedule updates when the feed does not provide any scheduling requests. If a feed does provide update scheduling information (through elements such as <code>&lt;rss:ttl&gt;</code> or <code>&lt;sy:updateFrequency&gt;</code>), FeedWordPress will respect the feed's request.</p>
246
- </div></td>
247
- </tr>
248
-
249
- <tr>
250
- <th scope="row"><?php print __('Time limit on updates'); ?>:</th>
251
- <td><select id="time-limit" name="update_time_limit" size="1" onchange="contextual_appearance('time-limit', 'time-limit-box', null, 'yes');">
252
- <option value="no"<?php echo ($update_time_limit>0)?'':' selected="selected"'; ?>>no time limit on updates</option>
253
- <option value="yes"<?php echo ($update_time_limit>0)?' selected="selected"':''; ?>>limit updates to no more than...</option>
254
- </select>
255
- <span id="time-limit-box"><label><input type="text" name="time_limit_seconds" value="<?php print $update_time_limit; ?>" size="5" /> seconds</label></span>
256
- </tr>
257
-
258
- <?php else :
259
- $useDefaultUpdateWindow = !(isset($page->link->settings['update/window']));
260
-
261
- $updateWindow = (isset($page->link->settings['update/window']) ? $page->link->settings['update/window'] : null);
262
- if (!is_numeric($updateWindow)) :
263
- $updateWindow = 60;
264
- else :
265
- $updateWindow = (int) $updateWindow;
266
- endif;
267
-
268
- ?>
269
 
270
  <tr>
271
  <th scope="row"><?php _e('Last update') ?>:</th>
@@ -303,31 +235,69 @@ class FeedWordPressFeedsPage extends FeedWordPressAdminPage {
303
  <option value="next"<?php echo ($holdem=='next')?' selected="selected"':''; ?>>update ASAP</option>
304
  <option value="ping"<?php echo ($holdem=='ping')?' selected="selected"':''; ?>>update only when pinged</option>
305
  </select></td></tr>
306
-
 
 
307
  <tr>
308
  <th scope="row"><?php print __('Update scheduling:') ?></th>
309
  <td><p style="margin-top:0px">How long should FeedWordPress wait between updates before it considers this feed ready to be polled for updates again?</p>
310
- <ul>
311
- <li><label><input type="radio" name="use_default_update_window" value="Yes" <?php if ($useDefaultUpdateWindow) : ?>checked="checked"<?php endif; ?> /> Use site-wide setting (currently <?php print $defaultUpdateWindow; ?> minutes)</li>
312
- <li><label><input type="radio" name="use_default_update_window" value="No" <?php if (!$useDefaultUpdateWindow) : ?>checked="checked"<?php endif; ?> /> Wait <input type="text" name="update_window" value="<?php print $updateWindow; ?>" size="4" /> minutes between polling.</label></li>
313
- </ul>
314
-
315
- <div class="setting-description">
316
- <p<?php if ($updateWindow<50) : ?> style="color: white; background-color: #703030; padding: 1.0em;"<?php endif; ?>><strong>Recommendation.</strong> Unless you are positive that you have the webmaster's permission, you generally should not set FeedWordPress to poll feeds more frequently than once every 60 minutes. Many webmasters consider more frequent automated polling to be abusive, and may complain to your web host, or ban your IP address, as retaliation for hammering their servers too hard.</p>
317
- <p><strong>Note.</strong> This is a default setting that FeedWordPress uses to schedule updates when the feed does not provide any scheduling requests. If this feed does provide update scheduling information (through elements such as <code>&lt;rss:ttl&gt;</code> or <code>&lt;sy:updateFrequency&gt;</code>), FeedWordPress will respect the feed's request.</p>
318
- </div></td>
 
 
 
 
 
319
  </tr>
320
- <?php endif; ?>
321
 
 
 
 
 
 
 
 
 
 
 
322
 
323
- </table>
324
- <script type="text/javascript">
325
- contextual_appearance('automatic-updates-selector', 'cron-job-explanation', null, 'no');
326
- contextual_appearance('time-limit', 'time-limit-box', null, 'yes');
327
- </script>
328
- <?php
329
  } /* FeedWordPressFeedsPage::global_feeds_box() */
330
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
331
  function feed_information_box ($page, $box = NULL) {
332
  global $wpdb;
333
  if ($page->for_feed_settings()) :
@@ -374,13 +344,6 @@ contextual_appearance('time-limit', 'time-limit-box', null, 'yes');
374
 
375
  // Hey ho, let's go
376
  ?>
377
- <style type="text/css">
378
- table.edit-form { width: 100%; }
379
- table.edit-form th { width: 25%; vertical-align: top; text-align: right; padding: 0.5em; }
380
- table.edit-form td { width: 75%; vertical-align: top; padding: 0.5em; }
381
- table.edit-form td ul.options { margin: 0; padding: 0; list-style: none; }
382
- </style>
383
-
384
  <table class="edit-form">
385
 
386
  <?php if ($page->for_feed_settings()) : ?>
@@ -472,21 +435,6 @@ contextual_appearance('time-limit', 'time-limit-box', null, 'yes');
472
  <?php
473
  } /* FeedWordPressFeedsPage::feed_information_box() */
474
 
475
- function posts_box ($page, $box = NULL) {
476
- $id = (isset($page->link) ? $page->link->id : NULL);
477
- FeedWordPressSettingsUI::instead_of_posts_box($id);
478
- } /* FeedWordPressFeedsPage::posts_box() */
479
-
480
- function authors_box ($page, $box = NULL) {
481
- $id = (isset($page->link) ? $page->link->id : NULL);
482
- FeedWordPressSettingsUI::instead_of_authors_box($id);
483
- } /* FeedWordPressFeedsPage::authors_box() */
484
-
485
- function categories_box ($page, $box = NULL) {
486
- $id = (isset($page->link) ? $page->link->id : NULL);
487
- FeedWordPressSettingsUI::instead_of_categories_box($id);
488
- } /* FeedWordPressFeedsPage::categories_box() */
489
-
490
  function custom_settings_box ($page, $box = NULL) {
491
  ?>
492
  <p class="setting-description">These custom settings are special fields for the <strong>feed</strong> you are
@@ -604,8 +552,8 @@ contextual_appearance('time-limit', 'time-limit-box', null, 'yes');
604
  $rss = (is_wp_error($pie) ? $pie : new MagpieFromSimplePie($pie));
605
 
606
  if ($rss and !is_wp_error($rss)):
607
- $feed_title = isset($rss->channel['title'])?$rss->channel['title']:$rss->channel['link'];
608
- $feed_link = isset($rss->channel['link'])?$rss->channel['link']:'';
609
  $feed_type = ($rss->feed_type ? $rss->feed_type : 'Unknown');
610
  $feed_version_template = '%.1f';
611
  $feed_version = $rss->feed_version;
@@ -748,14 +696,14 @@ contextual_appearance('time-limit', 'time-limit-box', null, 'yes');
748
  </div> <!-- class="wrap" -->
749
  <?php
750
  return false; // Don't continue
751
- } /* WordPressFeedsPage::display_feedfinder() */
752
 
753
  function display_alt_feed_box ($lookup, $alt = false) {
754
  global $fwp_post;
755
  ?>
756
  <form action="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/<?php echo basename(__FILE__); ?>" method="post">
757
  <div class="inside"><?php
758
- FeedWordPressCompatibility::stamp_nonce(get_class($this));
759
  ?>
760
  <fieldset class="alt"
761
  <?php if (!$alt): ?>style="margin: 1.0em 3.0em; font-size: smaller;"<?php endif; ?>>
@@ -783,116 +731,83 @@ contextual_appearance('time-limit', 'time-limit-box', null, 'yes');
783
  </fieldset></form>
784
 
785
  <?php
786
- } /* WordPressFeedsPage::display_alt_feed_box() */
787
 
788
- function accept_POST ($post) {
789
- global $wpdb;
790
-
791
- // User mashed a Save Changes button
792
- if (isset($post['save']) or isset($post['submit'])) :
793
-
794
- if ($this->for_feed_settings()) :
795
- $alter = array ();
796
-
797
- // custom feed settings first
798
- foreach ($post['notes'] as $mn) :
799
- $mn['key0'] = trim($mn['key0']);
800
- $mn['key1'] = trim($mn['key1']);
801
- if (preg_match("\007^(("
802
- .implode(')|(',$this->special_settings)
803
- ."))$\007i",
804
- $mn['key1'])) :
805
- $mn['key1'] = 'user/'.$mn['key1'];
806
- endif;
807
-
808
- if (strlen($mn['key0']) > 0) :
809
- unset($this->link->settings[$mn['key0']]); // out with the old
810
- endif;
811
-
812
- if (($mn['action']=='update') and (strlen($mn['key1']) > 0)) :
813
- $this->link->settings[$mn['key1']] = $mn['value']; // in with the new
814
- endif;
815
- endforeach;
816
-
817
- // now stuff through the web form
818
- // hardcoded feed info
819
-
820
- foreach (array('name', 'description', 'url') as $what) :
821
- // We have a checkbox for "No," so if it's unchecked, mark as "Yes."
822
- $this->link->settings["hardcode {$what}"] = (isset($post["hardcode_{$what}"]) ? $post["hardcode_{$what}"] : 'yes');
823
- if (FeedWordPress::affirmative($this->link->settings, "hardcode {$what}")) :
824
- $this->link->link->{'link_'.$what} = $post['link'.$what];
825
- endif;
826
- endforeach;
827
-
828
- // Update scheduling
829
- if (isset($post['update_schedule'])) :
830
- $this->link->settings['update/hold'] = $post['update_schedule'];
831
  endif;
832
 
833
- if (isset($post['use_default_update_window']) and strtolower($post['use_default_update_window'])=='yes') :
834
- unset($this->link->settings['update/window']);
835
- elseif (isset($post['update_window'])):
836
- if ((int) $post['update_window'] > 0) :
837
- $this->link->settings['update/window'] = (int) $post['update_window'];
838
- endif;
839
  endif;
840
 
841
- else :
842
- // Global
843
- update_option('feedwordpress_cat_id', $post['syndication_category']);
844
-
845
- if (!isset($post['automatic_updates']) or !in_array($post['automatic_updates'], array('init', 'shutdown'))) :
846
- $automatic_updates = false;
847
- else :
848
- $automatic_updates = $post['automatic_updates'];
849
  endif;
850
- update_option('feedwordpress_automatic_updates', $automatic_updates);
851
-
852
- if (isset($post['update_window'])):
853
- if ((int) $post['update_window'] > 0) :
854
- update_option('feedwordpress_update_window', (int) $post['update_window']);
855
- endif;
 
 
 
 
856
  endif;
857
-
858
- update_option('feedwordpress_update_time_limit', ($post['update_time_limit']=='yes')?(int) $post['time_limit_seconds']:0);
859
-
860
- foreach (array('name', 'description', 'url') as $what) :
861
- // We have a checkbox for "No," so if it's unchecked, mark as "Yes."
862
- $hardcode = (isset($post["hardcode_{$what}"]) ? $post["hardcode_{$what}"] : 'yes');
863
- update_option("feedwordpress_hardcode_{$what}", $hardcode);
864
- endforeach;
865
-
866
- $this->updated = true;
867
  endif;
868
- $this->updatedPosts->accept_POST($post);
869
-
870
- if ($this->for_feed_settings()) :
871
- // Save changes to channel-level meta-data
872
- //$alter_set = implode(", ", $alter);
873
-
874
- // issue update query
875
- //$result = $wpdb->query("
876
- //UPDATE $wpdb->links
877
- //SET $alter_set
878
- //WHERE link_id='{$this->link->id}'
879
- //");
880
-
881
- // Save settings
882
- $this->link->save_settings(/*reload=*/ true);
883
 
884
- $this->updated = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
885
 
886
- // Reset, reload
887
- $link_id = $this->link->id; unset($this->link);
888
- $this->link = new SyndicatedLink($link_id);
 
889
  endif;
890
 
891
- // Probably a "Go" button for the drop-down
892
- else :
893
- $this->updated = false;
 
 
 
 
894
  endif;
895
- } /* WordPressFeedsPage::accept_POST() */
 
 
 
896
 
897
  } /* class FeedWordPressFeedsPage */
898
 
59
 
60
  FeedWordPressAdminPage::FeedWordPressAdminPage('feedwordpressfeeds', $link);
61
 
62
+ $this->dispatch = 'feedwordpress_admin_page_feeds';
63
+ $this->pagenames = array(
64
+ 'default' => 'Feeds',
65
+ 'settings-update' => 'Syndicated feed',
66
+ 'open-sheet' => 'Feed and Update',
67
+ );
68
  $this->filename = __FILE__;
69
  $this->updatedPosts = new UpdatedPostsControl($this);
70
  } /* FeedWordPressFeedsPage constructor */
72
  var $special_settings = array ( /* Regular expression syntax is OK here */
73
  'cats',
74
  'cat_split',
75
+ 'freeze updates',
76
  'hardcode name',
77
  'hardcode url',
78
  'hardcode description',
79
  'hardcode categories', /* Deprecated */
 
80
  'comment status',
81
+ 'terms',
82
+ 'map authors',
83
+ 'munge permalink',
84
  'ping status',
85
+ 'post status',
86
+ 'postmeta',
87
+ 'resolve relative',
88
+ 'syndicated post type',
89
+ 'tags',
90
  'unfamiliar author',
91
  'unfamliar categories', /* Deprecated */
92
  'unfamiliar category',
93
+ 'unfamiliar post_tag',
 
 
 
 
 
94
  'update/.*',
95
  'feed/.*',
96
  'link/.*',
97
+ 'match/.*',
98
  );
99
 
100
  function display () {
 
101
  global $fwp_post;
102
  global $post_source;
 
 
 
 
 
103
 
104
+ $this->boxes_by_methods = array(
105
+ 'feed_information_box' => __('Feed Information'),
106
+ 'global_feeds_box' => __('Update Scheduling'),
107
+ 'updated_posts_box' => __('Updated Posts'),
108
+ 'custom_settings_box' => __('Custom Feed Settings (for use in templates)'),
109
+ );
110
+ if ($this->for_default_settings()) :
111
+ unset($this->boxes_by_methods['custom_settings_box']);
112
+ endif;
113
+
114
  // Allow overriding of normal source for FeedFinder, which may
115
  // be called from multiple points.
116
  if (isset($post_source) and !is_null($post_source)) :
117
  $source = $post_source;
118
  else :
119
+ $source = $this->dispatch;
120
  endif;
121
 
 
 
 
122
  if (isset($_REQUEST['feedfinder'])
123
  or (isset($_REQUEST['action']) and $_REQUEST['action']=='feedfinder')
124
  or (isset($_REQUEST['action']) and $_REQUEST['action']==FWP_SYNDICATE_NEW)) :
125
+ // If this is a POST, validate source and user credentials
126
+ FeedWordPressCompatibility::validate_http_request(/*action=*/ $source, /*capability=*/ 'manage_links');
127
+
128
  return $this->display_feedfinder(); // re-route to Feed Finder page
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  endif;
130
+
131
+ parent::display();
132
  return false; // Don't continue
133
  } /* FeedWordPressFeedsPage::display() */
134
 
135
+ function ajax_interface_js () {
136
+ FeedWordPressAdminPage::ajax_interface_js();
137
+ ?>
138
+
139
+ jQuery(document).ready( function () {
140
+ contextual_appearance('automatic-updates-selector', 'cron-job-explanation', null, 'no');
141
+ contextual_appearance('time-limit', 'time-limit-box', null, 'yes');
142
+ contextual_appearance('use-default-update-window-no', 'update-scheduling-note', null, null, 'block', true);
143
+ jQuery('#use-default-update-window-yes, #use-default-update-window-no').click( function () {
144
+ contextual_appearance('use-default-update-window-no', 'update-scheduling-note', null, null, 'block', true);
145
+ } );
146
+
147
+ var els = ['name', 'description', 'url'];
148
+ for (var i = 0; i < els.length; i++) {
149
+ contextual_appearance(
150
+ /*item=*/ 'basics-hardcode-'+els[i],
151
+ /*appear=*/ 'basics-'+els[i]+'-view',
152
+ /*disappear=*/ 'basics-'+els[i]+'-edit',
153
+ /*value=*/ 'no',
154
+ /*visibleStyle=*/ 'block',
155
+ /*checkbox=*/ true
156
+ );
157
+ } /* for */
158
+ } );
159
+
160
+ <?php
161
+ }
162
+
163
  /*static*/ function updated_posts_box ($page, $box = NULL) {
164
  ?>
165
  <table class="edit-form">
169
  } /* FeedWordPressFeedsPage::updated_posts_box() */
170
 
171
  /*static*/ function global_feeds_box ($page, $box = NULL) {
172
+ $automatic_updates = get_option('feedwordpress_automatic_updates');
173
+ $update_time_limit = (int) get_option('feedwordpress_update_time_limit');
174
 
175
+ // Hey, ho, let's go...
 
 
 
 
 
176
  ?>
177
+
178
  <table class="edit-form">
179
+ <?php if ($page->for_default_settings()) : ?>
 
 
 
 
180
 
181
  <tr>
182
  <th scope="row">Updates:</th>
197
  </td>
198
  </tr>
199
 
200
+ <?php else : /* Feed-specific settings */ ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
 
202
  <tr>
203
  <th scope="row"><?php _e('Last update') ?>:</th>
235
  <option value="next"<?php echo ($holdem=='next')?' selected="selected"':''; ?>>update ASAP</option>
236
  <option value="ping"<?php echo ($holdem=='ping')?' selected="selected"':''; ?>>update only when pinged</option>
237
  </select></td></tr>
238
+
239
+ <?php endif; ?>
240
+
241
  <tr>
242
  <th scope="row"><?php print __('Update scheduling:') ?></th>
243
  <td><p style="margin-top:0px">How long should FeedWordPress wait between updates before it considers this feed ready to be polled for updates again?</p>
244
+ <?php
245
+
246
+ $this->setting_radio_control(
247
+ 'update/window', 'update_window',
248
+ array(&$this, 'update_window_edit_box'),
249
+ array(
250
+ 'global-setting-default' => DEFAULT_UPDATE_PERIOD,
251
+ 'default-input-name' => 'use_default_update_window',
252
+ 'default-input-id' => 'use-default-update-window-yes',
253
+ 'default-input-id-no' => 'use-default-update-window-no',
254
+ 'labels' => array(&$this, 'update_window_currently'),
255
+ )
256
+ );
257
+ ?></td>
258
  </tr>
 
259
 
260
+ <?php if ($this->for_default_settings()) : ?>
261
+
262
+ <tr>
263
+ <th scope="row"><?php print __('Time limit on updates'); ?>:</th>
264
+ <td><select id="time-limit" name="update_time_limit" size="1" onchange="contextual_appearance('time-limit', 'time-limit-box', null, 'yes');">
265
+ <option value="no"<?php echo ($update_time_limit>0)?'':' selected="selected"'; ?>>no time limit on updates</option>
266
+ <option value="yes"<?php echo ($update_time_limit>0)?' selected="selected"':''; ?>>limit updates to no more than...</option>
267
+ </select>
268
+ <span id="time-limit-box"><label><input type="text" name="time_limit_seconds" value="<?php print $update_time_limit; ?>" size="5" /> seconds</label></span>
269
+ </tr>
270
 
271
+ <?php endif; ?>
272
+
273
+ </table>
274
+
275
+ <?php
 
276
  } /* FeedWordPressFeedsPage::global_feeds_box() */
277
 
278
+ function update_window_edit_box ($updateWindow, $defaulted, $params) {
279
+ if (!is_numeric($updateWindow)) :
280
+ $updateWindow = DEFAULT_UPDATE_PERIOD;
281
+ endif;
282
+ ?>
283
+ <p>Wait <input type="text" name="update_window" value="<?php print $updateWindow; ?>" size="4" /> minutes between polling.</p>
284
+ <div class="setting-description" id="update-scheduling-note">
285
+ <p<?php if ($updateWindow<50) : ?> style="color: white; background-color: #703030; padding: 1.0em;"<?php endif; ?>><strong>Recommendation.</strong> Unless you are positive that you have the webmaster's permission, you generally should not set FeedWordPress to poll feeds more frequently than once every 60 minutes. Many webmasters consider more frequent automated polling to be abusive, and may complain to your web host, or ban your IP address, as retaliation for hammering their servers too hard.</p>
286
+ <p><strong>Note.</strong> This is a default setting that FeedWordPress uses to schedule updates when the feed does not provide any scheduling requests. If this feed does provide update scheduling information (through elements such as <code>&lt;rss:ttl&gt;</code> or <code>&lt;sy:updateFrequency&gt;</code>), FeedWordPress will respect the feed's request.</p>
287
+ </div>
288
+ <?php
289
+ } /* FeedWordPressFeedsPage::update_window_edit_box () */
290
+
291
+ function update_window_currently ($updateWindow, $defaulted, $params) {
292
+ $updateWindow = (int) $updateWindow;
293
+ if (1==$updateWindow) :
294
+ $caption = 'wait %d minute between polling';
295
+ else :
296
+ $caption = 'wait %d minutes between polling';
297
+ endif;
298
+ return sprintf(__($caption), $updateWindow);
299
+ } /* FeedWordPressFeedsPage::update_window_currently () */
300
+
301
  function feed_information_box ($page, $box = NULL) {
302
  global $wpdb;
303
  if ($page->for_feed_settings()) :
344
 
345
  // Hey ho, let's go
346
  ?>
 
 
 
 
 
 
 
347
  <table class="edit-form">
348
 
349
  <?php if ($page->for_feed_settings()) : ?>
435
  <?php
436
  } /* FeedWordPressFeedsPage::feed_information_box() */
437
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
438
  function custom_settings_box ($page, $box = NULL) {
439
  ?>
440
  <p class="setting-description">These custom settings are special fields for the <strong>feed</strong> you are
552
  $rss = (is_wp_error($pie) ? $pie : new MagpieFromSimplePie($pie));
553
 
554
  if ($rss and !is_wp_error($rss)):
555
+ $feed_link = (isset($rss->channel['link'])?$rss->channel['link']:'');
556
+ $feed_title = (isset($rss->channel['title'])?$rss->channel['title']:$feed_link);
557
  $feed_type = ($rss->feed_type ? $rss->feed_type : 'Unknown');
558
  $feed_version_template = '%.1f';
559
  $feed_version = $rss->feed_version;
696
  </div> <!-- class="wrap" -->
697
  <?php
698
  return false; // Don't continue
699
+ } /* FeedWordPressFeedsPage::display_feedfinder() */
700
 
701
  function display_alt_feed_box ($lookup, $alt = false) {
702
  global $fwp_post;
703
  ?>
704
  <form action="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/<?php echo basename(__FILE__); ?>" method="post">
705
  <div class="inside"><?php
706
+ FeedWordPressCompatibility::stamp_nonce($this->dispatch);
707
  ?>
708
  <fieldset class="alt"
709
  <?php if (!$alt): ?>style="margin: 1.0em 3.0em; font-size: smaller;"<?php endif; ?>>
731
  </fieldset></form>
732
 
733
  <?php
734
+ } /* FeedWordPressFeedsPage::display_alt_feed_box() */
735
 
736
+ function save_settings ($post) {
737
+ if ($this->for_feed_settings()) :
738
+ // custom feed settings first
739
+ foreach ($post['notes'] as $mn) :
740
+ $mn['key0'] = (isset($mn['key0']) ? trim($mn['key0']) : NULL);
741
+ $mn['key1'] = trim($mn['key1']);
742
+ if (preg_match("\007^(("
743
+ .implode(')|(',$this->special_settings)
744
+ ."))$\007i",
745
+ $mn['key1'])) :
746
+ $mn['key1'] = 'user/'.$mn['key1'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
747
  endif;
748
 
749
+ if (strlen($mn['key0']) > 0) :
750
+ unset($this->link->settings[$mn['key0']]); // out with the old
 
 
 
 
751
  endif;
752
 
753
+ if (($mn['action']=='update') and (strlen($mn['key1']) > 0)) :
754
+ $this->link->settings[$mn['key1']] = $mn['value']; // in with the new
 
 
 
 
 
 
755
  endif;
756
+ endforeach;
757
+
758
+ // now stuff through the web form
759
+ // hardcoded feed info
760
+
761
+ foreach (array('name', 'description', 'url') as $what) :
762
+ // We have a checkbox for "No," so if it's unchecked, mark as "Yes."
763
+ $this->link->settings["hardcode {$what}"] = (isset($post["hardcode_{$what}"]) ? $post["hardcode_{$what}"] : 'yes');
764
+ if (FeedWordPress::affirmative($this->link->settings, "hardcode {$what}")) :
765
+ $this->link->link->{'link_'.$what} = $post['link'.$what];
766
  endif;
767
+ endforeach;
768
+
769
+ // Update scheduling
770
+ if (isset($post['update_schedule'])) :
771
+ $this->link->settings['update/hold'] = $post['update_schedule'];
 
 
 
 
 
772
  endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
773
 
774
+ if (isset($post['use_default_update_window']) and strtolower($post['use_default_update_window'])=='yes') :
775
+ unset($this->link->settings['update/window']);
776
+ elseif (isset($post['update_window'])):
777
+ if ((int) $post['update_window'] > 0) :
778
+ $this->link->settings['update/window'] = (int) $post['update_window'];
779
+ endif;
780
+ endif;
781
+
782
+ else :
783
+ // Global
784
+ update_option('feedwordpress_cat_id', $post['syndication_category']);
785
+
786
+ if (!isset($post['automatic_updates']) or !in_array($post['automatic_updates'], array('init', 'shutdown'))) :
787
+ $automatic_updates = false;
788
+ else :
789
+ $automatic_updates = $post['automatic_updates'];
790
+ endif;
791
+ update_option('feedwordpress_automatic_updates', $automatic_updates);
792
 
793
+ if (isset($post['update_window'])):
794
+ if ((int) $post['update_window'] > 0) :
795
+ update_option('feedwordpress_update_window', (int) $post['update_window']);
796
+ endif;
797
  endif;
798
 
799
+ update_option('feedwordpress_update_time_limit', ($post['update_time_limit']=='yes')?(int) $post['time_limit_seconds']:0);
800
+
801
+ foreach (array('name', 'description', 'url') as $what) :
802
+ // We have a checkbox for "No," so if it's unchecked, mark as "Yes."
803
+ $hardcode = (isset($post["hardcode_{$what}"]) ? $post["hardcode_{$what}"] : 'yes');
804
+ update_option("feedwordpress_hardcode_{$what}", $hardcode);
805
+ endforeach;
806
  endif;
807
+
808
+ $this->updatedPosts->accept_POST($post);
809
+ parent::save_settings($post);
810
+ } /* FeedWordPressFeedsPage::save_settings() */
811
 
812
  } /* class FeedWordPressFeedsPage */
813
 
feedwordpress-elements.css CHANGED
@@ -34,19 +34,26 @@
34
  }
35
 
36
  /* Common settings page elements */
37
- #post-search {
38
- float: right;
39
  margin:11px 12px 0;
40
  min-width: 130px;
41
  position:relative;
42
  }
 
 
 
 
 
 
 
43
  .fwpfs {
44
  color: #dddddd !important; background-color: #333 !important;
45
- background:#797979 url(<?php bloginfo('url') ?>/wp-admin/images/fav.png) repeat-x scroll left center;
46
- border-color:#777777 #777777 #666666 !important; -moz-border-radius-bottomleft:12px;
47
- -moz-border-radius-bottomright:12px;
48
- -moz-border-radius-topleft:12px;
49
- -moz-border-radius-topright:12px;
 
50
  border-style:solid;
51
  border-width:1px;
52
  line-height:15px;
@@ -54,17 +61,33 @@
54
  }
55
  .fwpfs.slide-down {
56
  border-bottom-color: #626262;
57
- -moz-border-radius-bottomleft:0;
58
- -moz-border-radius-bottomright:0;
59
- -moz-border-radius-topleft:12px;
60
- -moz-border-radius-topright:12px;
61
- background-image:url(<?php bloginfo('url') ?>/wp-admin/images/fav-top.png);
62
- background-position:0 top;
63
- background-repeat:repeat-x;
 
64
  border-bottom-style:solid;
65
  border-bottom-width:1px;
66
  }
67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  /* Switchfeed interface elements */
69
 
70
  #feed-finder form {
@@ -144,3 +167,215 @@
144
  margin-bottom: 0.5em;
145
  }
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  }
35
 
36
  /* Common settings page elements */
37
+ #fwpfs-container {
 
38
  margin:11px 12px 0;
39
  min-width: 130px;
40
  position:relative;
41
  }
42
+ #fwpfs-container .subsubsub {
43
+ float: none !important;
44
+ }
45
+ .tablenav p.submit {
46
+ margin: 0px;
47
+ padding: 0px;
48
+ }
49
  .fwpfs {
50
  color: #dddddd !important; background-color: #333 !important;
51
+ background-color: #797979;
52
+ border-color:#777777 #777777 #666666 !important;
53
+ border-radius: 12px;
54
+ -moz-border-radius: 12px;
55
+ -webkit-border-radius: 12px;
56
+ -khtml-border-radius: 12px;
57
  border-style:solid;
58
  border-width:1px;
59
  line-height:15px;
61
  }
62
  .fwpfs.slide-down {
63
  border-bottom-color: #626262;
64
+ border-top-left-radius: 12px; border-top-right-radius: 12px;
65
+ border-bottom-left-radius: 0; border-bottom-right-radius: 0;
66
+ -webkit-border-top-left-radius: 12px; -webkit-border-top-right-radius: 12px;
67
+ -webkit-border-bottom-left-radius: 0; -webkit-border-bottom-right-radius: 0;
68
+ -khtml-border-top-left-radius: 12px; -khtml-border-top-right-radius: 12px;
69
+ -khtml-border-bottom-left-radius: 0; -khtml-border-bottom-right-radius: 0;
70
+ -moz-border-radius-topleft:12px; -moz-border-radius-topright:12px;
71
+ -moz-border-radius-bottomleft:0; -moz-border-radius-bottomright:0;
72
  border-bottom-style:solid;
73
  border-bottom-width:1px;
74
  }
75
 
76
+ .current-setting {
77
+ display: block;
78
+ font-size: smaller;
79
+ margin-left: 2.0em;
80
+ font-size: smaller;
81
+ }
82
+ .twofer tr td h4 {
83
+ margin-top: 0px;
84
+ margin-bottom: 3px;
85
+ }
86
+ ul.current-setting {
87
+ list-style: disc outside;
88
+ padding-left: 2.0em;
89
+ }
90
+
91
  /* Switchfeed interface elements */
92
 
93
  #feed-finder form {
167
  margin-bottom: 0.5em;
168
  }
169
 
170
+ table.edit-form { width: 100%; }
171
+ table.edit-form th { width: 27%; vertical-align: top; text-align: right; padding: 0.5em; }
172
+ table.edit-form th .setting-description { font-weight: normal; font-size: smaller; font-style: italic; }
173
+
174
+ table.edit-form td { width: 73%; vertical-align: top; padding: 0.5em; }
175
+ table.edit-form td ul.options { margin: 0; padding: 0; list-style: none; }
176
+ table.edit-form td ul.options.compact li { display: inline; margin-left: 3.0em; white-space: nowrap; }
177
+ table.edit-form.narrow th { width: 15%; }
178
+ table.edit-form.narrow td { width: 85%; }
179
+ table.edit-form td p { margin-top: 0px; }
180
+
181
+ table.twofer { width: 100%; border: none; }
182
+ table.twofer tr { vertical-align: top; }
183
+ table.twofer td.equals.first { width: 49% !important; border-right: 1px dotted #777; padding-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 10px; }
184
+ table.twofer td.equals.second { width: 49% !important; padding-top: 0px; padding-bottom: 0px; padding-left: 10px; padding-right: 0px; }
185
+
186
+ table.twofer td.active { color: black; background-color: #cfc; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; -khtml-border-radius: 5px; }
187
+ table.twofer td.inactive { color: #333; }
188
+ table.twofer td.equals.first.active { border-right: none; }
189
+ table.twofer td.equals.first.inactive { border-right: none; }
190
+
191
+ table.twofer td.primary { width: 69%; border-right: 1px dotted #777; padding-right: 10px; }
192
+ table.twofer td.secondary { padding-left: 10px; width: 30%; }
193
+
194
+ #add-multiple-uri, #upload-opml {
195
+ float: right;
196
+ position: relative;
197
+ width: 50%;
198
+ background-color: #cfc;
199
+ padding-left: 1.0em; padding-right: 1.0em;
200
+ padding-top: 0.5em; padding-bottom: 0.5em;
201
+ right: 0;
202
+ top: auto;
203
+ }
204
+ #add-multiple-uri textarea {
205
+ width: 100%;
206
+ margin-top: 0.5em;
207
+ }
208
+ #add-multiple-uri h4 {
209
+ margin-bottom: 2px;
210
+ margin-top: 0px;
211
+ border-bottom: 1px dotted black;
212
+ }
213
+
214
+ #dashboard-widgets #feedwordpress_dashboard h4 {
215
+ color: #777777;
216
+ font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;
217
+ font-size: 13px;
218
+ font-style: italic;
219
+ font-weight: normal;
220
+
221
+ margin: 0px;
222
+
223
+ border-bottom: 1px solid #ececec;
224
+
225
+ padding-left: 15px;
226
+ padding-top: 10px;
227
+ padding-bottom: 5px;
228
+ padding-right: 0px;
229
+ }
230
+
231
+ #feedwordpress_dashboard .feedwordpress-stats {
232
+ width: 49%;
233
+ }
234
+ #feedwordpress_dashboard .feedwordpress-stats table {
235
+ margin-top: 5px;
236
+ margin-left: 15px;
237
+ }
238
+ #feedwordpress_dashboard .feedwordpress-actions ul.options {
239
+ margin-left: 15px !important;
240
+ margin-top: 5px !important;
241
+ }
242
+
243
+ #feedwordpress_dashboard .feedwordpress-actions {
244
+ width: 49%;
245
+ float: right;
246
+ }
247
+ #feedwordpress_dashboard td.b {
248
+ padding-right: 12px;
249
+ }
250
+ #feedwordpress_dashboard td.b a {
251
+ font-size: 18px;
252
+ }
253
+
254
+ #feedwordpress_dashboard td.t.active a:link,
255
+ #feedwordpress_dashboard td.t.active a:visited {
256
+ color: green;
257
+ }
258
+ #feedwordpress_dashboard td.t.inactive a:link,
259
+ #feedwordpress_dashboard td.t.inactive a:visited {
260
+ color: red;
261
+ }
262
+
263
+ #feedwordpress_dashboard #add-single-uri {
264
+ clear: both;
265
+ margin-top: 15px;
266
+ }
267
+
268
+ #feedwordpress_dashboard #add-single-uri #syndicated-links {
269
+ border-top: 1px solid #ececec;
270
+ width: 49%;
271
+ }
272
+ #feedwordpress_dashboard #add-single-uri #syndicated-links .container {
273
+ margin-top: 5px;
274
+ margin-left: 15px;
275
+ }
276
+
277
+ #feedwordpress_dashboard #add-single-uri #check-for-updates {
278
+ border-top: 1px solid #ececec;
279
+ float: right;
280
+ text-align: left;
281
+ width: 49%;
282
+ }
283
+ #feedwordpress_dashboard #add-single-uri #check-for-updates .container {
284
+ margin-top: 5px;
285
+ margin-left: 15px;
286
+ }
287
+ #multiadd-status {
288
+ position: absolute;
289
+ padding: 10px;
290
+ background-color: #ecec70;
291
+ border-radius: 10px;
292
+ -moz-border-radius: 10px;
293
+ -webkit-border-radius: 10px;
294
+ -khtml-border-radius: 10px;
295
+ opacity: 0.85;
296
+ top: auto;
297
+ left: 45%;
298
+ right: auto;
299
+ bottom: -5px;
300
+ }
301
+ #multiadd-form {
302
+ position: relative;
303
+ padding-bottom: 3.0em;
304
+ }
305
+ #multiadd-status img {
306
+ vertical-align: middle;
307
+ }
308
+ #multiadd-list {
309
+ border-top: 1px dotted black;
310
+ padding-top: 5px;
311
+ padding-bottom: 5px;
312
+ border-bottom: 1px dotted black;
313
+ }
314
+ #multiadd-buttons {
315
+ position: absolute;
316
+ bottom: 0px;
317
+ margin-top: 15px;
318
+ margin-left: 15px;
319
+ }
320
+
321
+ .feedwordpress-admin {
322
+ position: relative;
323
+ }
324
+ .feedwordpress-admin .submit { position: relative; z-index: 40; }
325
+
326
+ #feedwordpress-admin-syndication .heads-up {
327
+ background-color: #d0d0d0;
328
+ color: black;
329
+ padding: 1.0em;
330
+ margin: 0.5em 4.0em !important;
331
+ }
332
+ #feedwordpress-admin-syndication .update-form.with-donation {
333
+ margin-right: 50%;
334
+ min-height: 255px;
335
+ }
336
+ #feedwordpress-admin-syndication .donation-form,
337
+ #feedwordpress-admin-syndication .donation-thanks {
338
+ background-color: #ffffcc;
339
+ text-align: left;
340
+ padding: 0.5em 0.5em;
341
+ border-left: thin dashed #777777;
342
+ font-size: 70%;
343
+ position: absolute;
344
+ top: 0; bottom: 0; right: 0; left: auto;
345
+ width: 50%;
346
+ }
347
+ #feedwordpress-admin-syndication .donation-thanks {
348
+ background-color: #ccffcc;
349
+ }
350
+ #feedwordpress-admin-syndication .donation-thanks .signature {
351
+ text-align: right;
352
+ font-style: italic;
353
+ }
354
+ #feedwordpress-admin-syndication .donation-form h4,
355
+ #feedwordpress-admin-syndication .donation-thanks h4 {
356
+ font-size: 10px;
357
+ text-align: center;
358
+ border-bottom: 1px solid #777777;
359
+ margin: 0px;
360
+ }
361
+ #feedwordpress-admin-syndication .donation-form .donate {
362
+ text-align: center;
363
+ }
364
+ #feedwordpress-admin-syndication .donation-form .sod-off {
365
+ padding-top: 0.5em;
366
+ margin-top: 0.5em;
367
+ border-top: thin solid #777777;
368
+ }
369
+ #feedwordpress-admin-syndication .feed-missing {
370
+ background-color:#FFFFD0;
371
+ }
372
+ #feedwordpress-admin-syndication .unsubscribed tr {
373
+ background-color: #FFE0E0;
374
+ }
375
+ #feedwordpress-admin-syndication .unsubscribed tr.alternate {
376
+ background-color: #FFF0F0;
377
+ }
378
+ #feedwordpress-admin-syndication tr.feed-error {
379
+ background-color: #FFFFD0;
380
+ }
381
+
feedwordpress-elements.js CHANGED
@@ -257,7 +257,6 @@ fwpList = {
257
 
258
  add: function( e, s ) {
259
  e = $(e);
260
-
261
  var list = $(this),
262
  old = false,
263
  _s = { pos: 0, id: 0, oldId: null },
@@ -299,6 +298,7 @@ fwpList = {
299
  color = fwpList.getColor( e );
300
  e.css( 'backgroundColor', s.addColor ).animate( { backgroundColor: color }, { complete: function() { $(this).css( 'backgroundColor', '' ); } } );
301
  }
 
302
  list.each( function() { this.fwpList.process( e ); } );
303
  return e;
304
  },
@@ -387,13 +387,13 @@ jQuery(document).ready( function($) {
387
  // Ajax Cat
388
  var containerId = $(this).attr('id');
389
  var checkboxId = $(this).find('.categorychecklist').attr('id');
390
- var newCatId = $(this).find('.newcategory').attr('id');
391
  var responseId = $(this).find('.'+taxonomy+'-ajax-response').attr('id');
392
  var taxAdderId = $(this).find('.'+taxonomy+'-adder').attr('id');
393
 
394
- $(this).find('.newcategory').one( 'focus', function () { $(this).val('').removeClass('form-input-tip'); } );
395
  $(this).find('.add-categorychecklist-category-add').click( function() {
396
- $(this).parent().children('.newcategory').focus();
397
  } );
398
 
399
  catAddBefore = function (s) {
@@ -404,13 +404,16 @@ jQuery(document).ready( function($) {
404
  }
405
  catAddAfter = function (r, s) {
406
  // Clear out input box
407
- $('.newcategory', '#'+this_id).val('');
408
 
409
  // Clear out parent dropbox
410
- var sup, drop = $('.newcategory-parent', '#'+this_id);
 
411
 
412
  if ( 'undefined' != s.parsed.responses[0] && (sup = s.parsed.responses[0].supplemental.newcat_parent) ) {
 
413
  drop.before(sup);
 
414
  drop.remove();
415
  }
416
  };
@@ -433,6 +436,10 @@ jQuery(document).ready( function($) {
433
  } ); /* jQuery(document).ready() */
434
 
435
  jQuery(document).ready(function($){
 
 
 
 
436
  $('.fwpfs').toggle(
437
  function(){$('.fwpfs').removeClass('slideUp').addClass('slideDown'); setTimeout(function(){if ( $('.fwpfs').hasClass('slideDown') ) { $('.fwpfs').addClass('slide-down'); }}, 10) },
438
  function(){$('.fwpfs').removeClass('slideDown').addClass('slideUp'); setTimeout(function(){if ( $('.fwpfs').hasClass('slideUp') ) { $('.fwpfs').removeClass('slide-down'); }}, 10) }
@@ -441,6 +448,42 @@ jQuery(document).ready(function($){
441
  'change',
442
  function () { this.form.submit(); }
443
  );
444
- $('#post-search .button').css( 'display', 'none' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
  });
446
 
257
 
258
  add: function( e, s ) {
259
  e = $(e);
 
260
  var list = $(this),
261
  old = false,
262
  _s = { pos: 0, id: 0, oldId: null },
298
  color = fwpList.getColor( e );
299
  e.css( 'backgroundColor', s.addColor ).animate( { backgroundColor: color }, { complete: function() { $(this).css( 'backgroundColor', '' ); } } );
300
  }
301
+
302
  list.each( function() { this.fwpList.process( e ); } );
303
  return e;
304
  },
387
  // Ajax Cat
388
  var containerId = $(this).attr('id');
389
  var checkboxId = $(this).find('.categorychecklist').attr('id');
390
+ var newCatId = $(this).find('.new'+taxonomy).attr('id');
391
  var responseId = $(this).find('.'+taxonomy+'-ajax-response').attr('id');
392
  var taxAdderId = $(this).find('.'+taxonomy+'-adder').attr('id');
393
 
394
+ $(this).find('.new'+taxonomy).one( 'focus', function () { $(this).val('').removeClass('form-input-tip'); } );
395
  $(this).find('.add-categorychecklist-category-add').click( function() {
396
+ $(this).parent().children('.new'+taxonomy).focus();
397
  } );
398
 
399
  catAddBefore = function (s) {
404
  }
405
  catAddAfter = function (r, s) {
406
  // Clear out input box
407
+ $('.new' + taxonomy, '#'+this_id).val('');
408
 
409
  // Clear out parent dropbox
410
+ var sup, drop = $('.new' + taxonomy + '-parent', '#'+this_id);
411
+ var keep = $('.new' + taxonomy, '#'+this_id);
412
 
413
  if ( 'undefined' != s.parsed.responses[0] && (sup = s.parsed.responses[0].supplemental.newcat_parent) ) {
414
+ sup = sup.replace(/id=['"]new[^'"]*_parent['"]/g, 'id="' + keep.attr('id') + '-parent"');
415
  drop.before(sup);
416
+ $('#'+keep.attr('id')+'-parent').addClass('new' + taxonomy + '-parent');
417
  drop.remove();
418
  }
419
  };
436
  } ); /* jQuery(document).ready() */
437
 
438
  jQuery(document).ready(function($){
439
+ if ( $('.jaxtag').length ) {
440
+ tagBox.init();
441
+ }
442
+
443
  $('.fwpfs').toggle(
444
  function(){$('.fwpfs').removeClass('slideUp').addClass('slideDown'); setTimeout(function(){if ( $('.fwpfs').hasClass('slideDown') ) { $('.fwpfs').addClass('slide-down'); }}, 10) },
445
  function(){$('.fwpfs').removeClass('slideDown').addClass('slideUp'); setTimeout(function(){if ( $('.fwpfs').hasClass('slideUp') ) { $('.fwpfs').removeClass('slide-down'); }}, 10) }
448
  'change',
449
  function () { this.form.submit(); }
450
  );
451
+ $('#fwpfs-container .button').css( 'display', 'none' );
452
+
453
+ $('table.twofer td.active input[type="radio"], table.twofer td.inactive input[type="radio"]').each( function () {
454
+ $(this).click( function () {
455
+ var name = $(this).attr('name');
456
+ var table = $(this).closest('table');
457
+ table.find('td').removeClass('active').addClass('inactive');
458
+ table.find('td:has(input[name="'+name+'"]:checked)').removeClass('inactive').addClass('active');
459
+ } );
460
+
461
+ var name = $(this).attr('name');
462
+ var table = $(this).closest('table');
463
+ table.find('td').removeClass('active').addClass('inactive');
464
+ table.find('td:has(input[name="'+name+'"]:checked)').removeClass('inactive').addClass('active');
465
+ } );
466
+
467
+ $('#turn-on-multiple-sources').click ( function () {
468
+ $('#add-single-uri').hide();
469
+ $('#add-multiple-uri').show(600);
470
+ return false;
471
+ ;
472
+ } );
473
+ $('#turn-off-multiple-sources').click ( function () {
474
+ $('#add-multiple-uri').hide(600);
475
+ $('#add-single-uri').show();
476
+ return false;
477
+ } );
478
+ $('#turn-on-opml-upload').click ( function () {
479
+ $('#add-single-uri').hide();
480
+ $('#upload-opml').show(600);
481
+ return false;
482
+ } );
483
+ $('#turn-off-opml-upload').click ( function () {
484
+ $('#upload-opml').hide(600);
485
+ $('#add-single-uri').show();
486
+ return false;
487
+ } );
488
  });
489
 
feedwordpress-walker-category-checklist.class.php CHANGED
@@ -7,30 +7,37 @@
7
  * This is the fucking stupidest thing ever.
8
  */
9
 
10
- require_once(ABSPATH.'/wp-admin/includes/template.php');
11
  // Fucking fuck.
12
 
13
  class FeedWordPress_Walker_Category_Checklist extends Walker_Category_Checklist {
14
- var $prefix = '';
 
 
 
 
15
  function set_prefix ($prefix) {
16
  $this->prefix = $prefix;
17
  }
 
 
 
18
 
19
  function start_el (&$output, $category, $depth, $args) {
20
  extract($args);
21
- if ( empty($taxonomy) ) :
22
- $taxonomy = 'category';
23
- endif;
24
-
25
- if ( $taxonomy == 'category' ) :
26
- $name = 'post_category';
27
  else :
28
- $name = 'tax_input['.$taxonomy.']';
29
- endif;
30
-
31
- $unit = array();
32
- if (strlen($this->prefix) > 0) :
33
- $unit[] = $this->prefix;
34
  endif;
35
  $unit[] = $taxonomy;
36
  $unit[] = $category->term_id;
7
  * This is the fucking stupidest thing ever.
8
  */
9
 
10
+ require_once(ABSPATH.'/wp-admin/includes/template.php');
11
  // Fucking fuck.
12
 
13
  class FeedWordPress_Walker_Category_Checklist extends Walker_Category_Checklist {
14
+ var $prefix = ''; var $taxonomy = 'category';
15
+ function FeedWordPress_Walker_Category_Checklist () {
16
+ $this->set_taxonomy('category');
17
+ }
18
+
19
  function set_prefix ($prefix) {
20
  $this->prefix = $prefix;
21
  }
22
+ function set_taxonomy ($taxonomy) {
23
+ $this->taxonomy = $taxonomy;
24
+ }
25
 
26
  function start_el (&$output, $category, $depth, $args) {
27
  extract($args);
28
+ if ( empty($taxonomy) ) :
29
+ $taxonomy = 'category';
30
+ endif;
31
+
32
+ if ($taxonomy=='category') :
33
+ $name = 'post_category';
34
  else :
35
+ $name = 'tax_input['.$taxonomy.']';
36
+ endif;
37
+
38
+ $unit = array();
39
+ if (strlen($this->prefix) > 0) :
40
+ $unit[] = $this->prefix;
41
  endif;
42
  $unit[] = $taxonomy;
43
  $unit[] = $category->term_id;
feedwordpress.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: FeedWordPress
4
  Plugin URI: http://feedwordpress.radgeek.com/
5
  Description: simple and flexible Atom/RSS syndication for WordPress
6
- Version: 2010.0623
7
  Author: Charles Johnson
8
  Author URI: http://radgeek.com/
9
  License: GPL
@@ -11,7 +11,7 @@ License: GPL
11
 
12
  /**
13
  * @package FeedWordPress
14
- * @version 2010.0623
15
  */
16
 
17
  # This uses code derived from:
@@ -34,9 +34,13 @@ License: GPL
34
 
35
  # -- Don't change these unless you know what you're doing...
36
 
37
- define ('FEEDWORDPRESS_VERSION', '2010.0623');
38
  define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
39
 
 
 
 
 
40
  // Defaults
41
  define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
42
  define ('DEFAULT_UPDATE_PERIOD', 60); // value in minutes
@@ -96,14 +100,19 @@ add_filter('wp_feed_cache_transient_lifetime', array('FeedWordPress', 'cache_lif
96
 
97
  // Ensure that we have SimplePie loaded up and ready to go.
98
  // We no longer need a MagpieRSS upgrade module. Hallelujah!
99
- require_once(ABSPATH . WPINC . '/feed.php');
 
 
100
  require_once(ABSPATH . WPINC . '/class-feed.php');
101
- require_once(ABSPATH . WPINC . '/class-simplepie.php');
102
 
103
  require_once (ABSPATH . WPINC . '/registration.php'); // for wp_insert_user
104
 
105
  require_once(dirname(__FILE__) . '/admin-ui.php');
 
106
  require_once(dirname(__FILE__) . '/compatability.php'); // LEGACY API: Replicate or mock up functions for legacy support purposes
 
 
 
107
  require_once(dirname(__FILE__) . '/feedwordpresshtml.class.php');
108
  require_once(dirname(__FILE__) . '/feedwordpress-content-type-sniffer.class.php');
109
 
@@ -114,7 +123,7 @@ endif;
114
 
115
  // Get the path relative to the plugins directory in which FWP is stored
116
  preg_match (
117
- '|/wp-content/plugins/(.+)$|',
118
  dirname(__FILE__),
119
  $ref
120
  );
@@ -127,18 +136,19 @@ endif;
127
 
128
  // If this is a FeedWordPress admin page, queue up scripts for AJAX functions that FWP uses
129
  // If it is a display page or a non-FeedWordPress admin page, don't.
 
130
  if (FeedWordPressSettingsUI::is_admin()) :
 
131
  add_action('admin_print_scripts', array('FeedWordPressSettingsUI', 'admin_scripts'));
132
 
133
- wp_register_style('feedwordpress-elements', WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-elements.css');
 
134
 
135
  wp_enqueue_style('dashboard');
136
  wp_enqueue_style('feedwordpress-elements');
137
 
138
  if (function_exists('wp_admin_css')) :
139
- if (fwp_test_wp_version(FWP_SCHEMA_25)) :
140
- wp_admin_css('css/dashboard');
141
- endif;
142
  endif;
143
  endif;
144
 
@@ -189,8 +199,8 @@ if (!FeedWordPress::needs_upgrade()) : // only work if the conditions are safe!
189
  add_action('admin_footer', array('FeedWordPress', 'admin_footer'));
190
 
191
  # Inbound XML-RPC update methods
192
- add_filter('xmlrpc_methods', 'feedwordpress_xmlrpc_hook');
193
-
194
  # Outbound XML-RPC ping reform
195
  remove_action('publish_post', 'generic_ping'); // WP 1.5.x
196
  remove_action('do_pings', 'do_all_pings', 10, 1); // WP 2.1, 2.2
@@ -201,41 +211,22 @@ if (!FeedWordPress::needs_upgrade()) : // only work if the conditions are safe!
201
  add_action('feedwordpress_update', 'fwp_hold_pings');
202
  add_action('feedwordpress_update_complete', 'fwp_release_pings');
203
 
204
- # Hook in logging functions only if the logging option is ON
205
- $update_logging = get_option('feedwordpress_update_logging');
206
- if ($update_logging == 'yes') :
207
- add_action('post_syndicated_item', 'log_feedwordpress_post', 100);
208
- add_action('update_syndicated_item', 'log_feedwordpress_update_post', 100);
209
- add_action('feedwordpress_update', 'log_feedwordpress_update_feeds', 100);
210
- add_action('feedwordpress_check_feed', 'log_feedwordpress_check_feed', 100);
211
- add_action('feedwordpress_update_complete', 'log_feedwordpress_update_complete', 100);
212
- endif;
213
-
214
- if (FeedWordPress::update_requested()) :
215
- if (FEEDWORDPRESS_DEBUG) :
216
- add_action('post_syndicated_item', 'debug_out_feedwordpress_post', 100);
217
- add_action('update_syndicated_item', 'debug_out_feedwordpress_update_post', 100);
218
- add_action('feedwordpress_update', 'debug_out_feedwordpress_update_feeds', 100);
219
- add_action('feedwordpress_check_feed', 'debug_out_feedwordpress_check_feed', 100);
220
- add_action('feedwordpress_update_complete', 'debug_out_feedwordpress_update_complete', 100);
221
- endif;
222
-
223
- add_action('feedwordpress_check_feed_complete', 'debug_out_feedwordpress_feed_error', 100, 3);
224
- endif;
225
 
226
  add_action('wp_footer', 'debug_out_feedwordpress_footer', -100);
227
  add_action('admin_footer', 'debug_out_feedwordpress_footer', -100);
228
 
229
- add_action('init', 'feedwordpress_clear_cache_magic_url');
230
 
231
  # Cron-less auto-update. Hooray!
232
  $autoUpdateHook = get_option('feedwordpress_automatic_updates');
233
  if ($autoUpdateHook != 'init') :
234
  $autoUpdateHook = 'shutdown';
235
  endif;
236
- add_action($autoUpdateHook, 'feedwordpress_auto_update');
237
-
238
- add_action('init', 'feedwordpress_update_magic_url');
 
239
 
240
  # Default sanitizers
241
  add_filter('syndicated_item_content', array('SyndicatedPost', 'resolve_relative_uris'), 0, 2);
@@ -246,138 +237,55 @@ else :
246
  add_action('admin_menu', 'fwp_add_pages');
247
  endif; // if (!FeedWordPress::needs_upgrade())
248
 
249
- function feedwordpress_auto_update () {
250
- if (FeedWordPress::stale()) :
251
- $feedwordpress = new FeedWordPress;
252
- $feedwordpress->update();
253
- endif;
254
- } /* feedwordpress_auto_update () */
255
-
256
- function feedwordpress_clear_cache_magic_url () {
257
- if (FeedWordPress::clear_cache_requested()) :
258
- FeedWordPress::clear_cache();
259
- endif;
260
- }
261
-
262
- function feedwordpress_update_magic_url () {
263
- global $wpdb;
264
-
265
- // Explicit update request in the HTTP request (e.g. from a cron job)
266
- if (FeedWordPress::update_requested()) :
267
- $feedwordpress = new FeedWordPress;
268
- $feedwordpress->update(FeedWordPress::update_requested_url());
269
-
270
- if (FEEDWORDPRESS_DEBUG and count($wpdb->queries) > 0) :
271
- $mysqlTime = 0.0;
272
- $byTime = array();
273
- foreach ($wpdb->queries as $query) :
274
- $time = $query[1] * 1000000.0;
275
- $mysqlTime += $query[1];
276
- if (!isset($byTime[$time])) : $byTime[$time] = array(); endif;
277
- $byTime[$time][] = $query[0]. ' // STACK: ' . $query[2];
278
- endforeach;
279
- krsort($byTime);
280
-
281
- foreach ($byTime as $time => $querySet) :
282
- foreach ($querySet as $query) :
283
- print "[".(sprintf('%4.4f', $time/1000.0)) . "ms] $query\n";
284
- endforeach;
285
- endforeach;
286
- echo "[feedwordpress] $wpdb->num_queries queries. $mysqlTime seconds in MySQL. Total of "; timer_stop(1); print " seconds.";
287
- endif;
288
-
289
- debug_out_feedwordpress_footer();
290
-
291
- // Magic URL should return nothing but a 200 OK header packet
292
- // when successful.
293
- exit;
294
- endif;
295
- } /* feedwordpress_magic_update_url () */
296
-
297
  ################################################################################
298
  ## LOGGING FUNCTIONS: log status updates to error_log if you want it ###########
299
  ################################################################################
300
 
301
- function log_feedwordpress_post ($id) {
302
- $post = wp_get_single_post($id);
303
- error_log("[".date('Y-m-d H:i:s')."][feedwordpress] posted "
304
- ."'{$post->post_title}' ({$post->post_date})");
305
- }
306
-
307
- function log_feedwordpress_update_post ($id) {
308
- $post = wp_get_single_post($id);
309
- error_log("[".date('Y-m-d H:i:s')."][feedwordpress] updated "
310
- ."'{$post->post_title}' ({$post->post_date})"
311
- ." (as of {$post->post_modified})");
312
- }
313
-
314
- function log_feedwordpress_update_feeds ($uri) {
315
- error_log("[".date('Y-m-d H:i:s')."][feedwordpress] update('$uri')");
316
- }
317
-
318
- function log_feedwordpress_check_feed ($feed) {
319
- $uri = $feed['link/uri']; $name = $feed['link/name'];
320
- error_log("[".date('Y-m-d H:i:s')."][feedwordpress] Examining $name <$uri>");
321
- }
322
-
323
- function log_feedwordpress_update_complete ($delta) {
324
- $mesg = array();
325
- if (isset($delta['new'])) $mesg[] = 'added '.$delta['new'].' new posts';
326
- if (isset($delta['updated'])) $mesg[] = 'updated '.$delta['updated'].' existing posts';
327
- if (empty($mesg)) $mesg[] = 'nothing changed';
328
-
329
- error_log("[".date('Y-m-d H:i:s')."][feedwordpress] "
330
- .(is_null($delta) ? "Error: I don't syndicate that URI"
331
- : implode(' and ', $mesg)));
332
- }
333
-
334
- function debug_out_feedwordpress_post ($id) {
335
- $post = wp_get_single_post($id);
336
- print ("[".date('Y-m-d H:i:s')."][feedwordpress] posted "
337
- ."'{$post->post_title}' ({$post->post_date})\n");
338
- }
339
-
340
- function debug_out_feedwordpress_update_post ($id) {
341
- $post = wp_get_single_post($id);
342
- print ("[".date('Y-m-d H:i:s')."][feedwordpress] updated "
343
- ."'{$post->post_title}' ({$post->post_date})"
344
- ." (as of {$post->post_modified})\n");
345
- }
346
-
347
- function debug_out_feedwordpress_update_feeds ($uri) {
348
- print ("[".date('Y-m-d H:i:s')."][feedwordpress] update('$uri')\n");
349
- }
350
-
351
- function debug_out_feedwordpress_check_feed ($feed) {
352
- $uri = $feed['link/uri']; $name = $feed['link/name'];
353
- print ("[".date('Y-m-d H:i:s')."][feedwordpress] Examining $name <$uri>\n");
354
- }
355
-
356
- function debug_out_feedwordpress_update_complete ($delta) {
357
- $mesg = array();
358
- if (isset($delta['new'])) $mesg[] = 'added '.$delta['new'].' new posts';
359
- if (isset($delta['updated'])) $mesg[] = 'updated '.$delta['updated'].' existing posts';
360
- if (empty($mesg)) $mesg[] = 'nothing changed';
361
-
362
- print ("[".date('Y-m-d H:i:s')."][feedwordpress] "
363
- .(is_null($delta) ? "Error: I don't syndicate that URI"
364
- : implode(' and ', $mesg))."\n");
365
- }
366
-
367
- function debug_out_feedwordpress_feed_error ($feed, $added, $dt) {
368
- if (is_wp_error($added)) :
369
- $mesgs = $added->get_error_messages();
370
  foreach ($mesgs as $mesg) :
371
- echo "[feedwordpress] Error updating [{$feed['link/uri']}]: $mesg\n";
372
- endforeach;
373
- endif;
374
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
 
376
  function debug_out_human_readable_bytes ($quantity) {
377
  $quantity = (int) $quantity;
378
  $magnitude = 'B';
379
  $orders = array('KB', 'MB', 'GB', 'TB');
380
- while (($quantity > 1024) and (count($orders) > 0)) :
381
  $quantity = floor($quantity / 1024);
382
  $magnitude = array_shift($orders);
383
  endwhile;
@@ -412,32 +320,14 @@ function is_syndicated ($id = NULL) {
412
  return (strlen(get_syndication_feed_id($id)) > 0);
413
  } /* function is_syndicated() */
414
 
415
- function get_syndication_source_link ($original = NULL, $id = NULL) {
416
- if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
417
- endif;
418
-
419
- if ($original) : $vals = get_post_custom_values('syndication_source_uri_original', $id);
420
- else : $vals = array();
421
- endif;
422
-
423
- if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source_uri', $id);
424
- endif;
425
-
426
- if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
427
-
428
- return $ret;
429
- } /* function get_syndication_source_link() */
430
-
431
- function the_syndication_source_link ($original = NULL, $id = NULL) {
432
- echo get_syndication_source_link($original, $id);
433
- }
434
-
435
  function feedwordpress_display_url ($url, $before = 60, $after = 0) {
436
  $bits = parse_url($url);
437
 
438
  // Strip out crufty subdomains
439
- $bits['host'] = preg_replace('/^www[0-9]*\./i', '', $bits['host']);
440
-
 
 
441
  // Reassemble bit-by-bit with minimum of crufty elements
442
  $url = (isset($bits['user'])?$bits['user'].'@':'')
443
  .(isset($bits['host'])?$bits['host']:'')
@@ -450,75 +340,57 @@ function feedwordpress_display_url ($url, $before = 60, $after = 0) {
450
  endif;
451
 
452
  return $url;
453
- }
454
 
455
- function get_syndication_source ($original = NULL, $id = NULL) {
 
456
  if (is_null($original)) :
457
  $original = FeedWordPress::use_aggregator_source_data();
458
  endif;
459
-
460
- if ($original) :
461
- $vals = get_post_custom_values('syndication_source_original', $id);
462
- else :
463
- $vals = array();
464
  endif;
465
 
466
- if (count($vals) == 0) :
467
- $vals = get_post_custom_values('syndication_source', $id);
 
468
  endif;
469
 
470
  if (count($vals) > 0) :
471
  $ret = $vals[0];
472
- else :
473
- $ret = NULL;
474
  endif;
 
 
475
 
476
- if (is_null($ret) or strlen(trim($ret)) == 0) :
477
- // Fall back to URL of blog
 
 
 
 
 
 
 
478
  $ret = feedwordpress_display_url(get_syndication_source_link());
479
  endif;
480
-
481
  return $ret;
482
  } /* function get_syndication_source() */
483
 
484
- function the_syndication_source ($original = NULL, $id = NULL) { echo get_syndication_source($original, $id); }
485
-
486
  function get_syndication_feed ($original = NULL, $id = NULL) {
487
- if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
488
- endif;
489
-
490
- if ($original) : $vals = get_post_custom_values('syndication_feed_original', $id);
491
- else : $vals = array();
492
- endif;
493
-
494
- if (count($vals) == 0) : $vals = get_post_custom_values('syndication_feed', $id);
495
- endif;
496
-
497
- if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
498
-
499
- return $ret;
500
  } /* function get_syndication_feed() */
501
 
502
- function the_syndication_feed ($original = NULL, $id = NULL) { echo get_syndication_feed($original, $id); }
503
-
504
  function get_syndication_feed_guid ($original = NULL, $id = NULL) {
505
- if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
 
 
506
  endif;
507
-
508
- if ($original) : $vals = get_post_custom_values('syndication_source_id_original', $id);
509
- else : $vals = array();
510
- endif;
511
-
512
- if (count($vals) == 0) : $vals = array(get_feed_meta('feed/id', $id));
513
- endif;
514
-
515
- if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
516
-
517
  return $ret;
518
  } /* function get_syndication_feed_guid () */
519
 
520
- function the_syndication_feed_guid ($original = NULL, $id = NULL) { echo get_syndication_feed_guid($original, $id); }
521
-
522
  function get_syndication_feed_id ($id = NULL) { list($u) = get_post_custom_values('syndication_feed_id', $id); return $u; }
523
  function the_syndication_feed_id ($id = NULL) { echo get_syndication_feed_id($id); }
524
 
@@ -798,22 +670,21 @@ function syndication_comments_feed_link ($link) {
798
  ################################################################################
799
 
800
  function fwp_add_pages () {
801
- global $fwp_capability;
802
  global $fwp_path;
803
 
804
- $menu = array('Syndicated Sites', 'Syndication', $fwp_capability['manage_links'], $fwp_path.'/syndication.php', NULL);
805
- if (fwp_test_wp_version(FWP_SCHEMA_27)) :
806
- // add icon parameter
807
- $menu[] = WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-tiny.png';
808
- endif;
809
-
810
- call_user_func_array('add_menu_page', $menu);
811
- add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Feeds & Updates', 'Feeds & Updates', $fwp_capability['manage_options'], $fwp_path.'/feeds-page.php');
812
- add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Posts & Links', 'Posts & Links', $fwp_capability['manage_options'], $fwp_path.'/posts-page.php');
813
- add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Authors', 'Authors', $fwp_capability['manage_options'], $fwp_path.'/authors-page.php');
814
- add_submenu_page($fwp_path.'/syndication.php', 'Categories'.FEEDWORDPRESS_AND_TAGS, 'Categories'.FEEDWORDPRESS_AND_TAGS, $fwp_capability['manage_options'], $fwp_path.'/categories-page.php');
815
- add_submenu_page($fwp_path.'/syndication.php', 'FeedWordPress Performance', 'Performance', $fwp_capability['manage_options'], $fwp_path.'/performance-page.php');
816
- add_submenu_page($fwp_path.'/syndication.php', 'FeedWordPress Diagnostics', 'Diagnostics', $fwp_capability['manage_options'], $fwp_path.'/diagnostics-page.php');
817
  } /* function fwp_add_pages () */
818
 
819
  function fwp_check_debug () {
@@ -1059,7 +930,7 @@ class FeedWordPress {
1059
  return NULL;
1060
  endif;
1061
 
1062
- if (!is_null($uri)) :
1063
  $uri = trim($uri);
1064
  else : // Update all
1065
  update_option('feedwordpress_last_update_all', time());
@@ -1075,11 +946,13 @@ class FeedWordPress {
1075
  $crash_ts = NULL;
1076
  endif;
1077
  endif;
1078
-
1079
  // Randomize order for load balancing purposes
1080
  $feed_set = $this->feeds;
1081
  shuffle($feed_set);
1082
 
 
 
1083
  // Loop through and check for new posts
1084
  $delta = NULL;
1085
  foreach ($feed_set as $feed) :
@@ -1095,7 +968,7 @@ class FeedWordPress {
1095
  $timely = $feed->stale();
1096
  endif;
1097
 
1098
- if ($pinged_that and is_null($delta)) : // If at least one feed was hit for updating...
1099
  $delta = array('new' => 0, 'updated' => 0); // ... don't return error condition
1100
  endif;
1101
 
@@ -1147,6 +1020,108 @@ class FeedWordPress {
1147
  endif;
1148
  return $ret;
1149
  } // FeedWordPress::stale()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1150
 
1151
  function clear_cache_requested () {
1152
  return (
@@ -1163,58 +1138,54 @@ class FeedWordPress {
1163
  } // FeedWordPress::update_requested()
1164
 
1165
  function update_requested_url () {
1166
- $ret = null;
1167
-
1168
- if (($_REQUEST['update_feedwordpress']=='*')
1169
- or (preg_match('|^http://.*|i', $_REQUEST['update_feedwordpress']))) :
1170
- $ret = $_REQUEST['update_feedwordpress'];
1171
- endif;
1172
 
1173
- return $ret;
1174
  } // FeedWordPress::update_requested_url()
1175
 
1176
- function syndicate_link ($name, $uri, $rss) {
 
 
 
 
 
 
1177
  global $wpdb;
1178
 
 
 
 
 
 
 
 
 
 
 
 
1179
  // Get the category ID#
1180
  $cat_id = FeedWordPress::link_category_id();
1181
 
1182
  // WordPress gets cranky if there's no homepage URI
1183
- if (!isset($uri) or strlen($uri)<1) : $uri = $rss; endif;
1184
 
1185
- if (function_exists('wp_insert_link')) : // WordPress 2.x
1186
- if (FeedWordPressCompatibility::test_version(0, FWP_SCHEMA_21)) :
1187
- // Morons.
1188
- $name = $wpdb->escape($name);
1189
- $uri = $wpdb->escape($uri);
1190
- $rss = $wpdb->escape($rss);
1191
-
1192
- // Comes in as a single category
1193
- $linkCats = $cat_id;
1194
- else :
1195
- // Comes in as an array of categories
1196
- $linkCats = array($cat_id);
1197
- endif;
1198
 
1199
- $link_id = wp_insert_link(array(
1200
- "link_name" => $name,
1201
- "link_url" => $uri,
1202
- "link_category" => $linkCats,
1203
- "link_rss" => $rss
1204
- ));
1205
- else : // WordPress 1.5.x
1206
- $result = $wpdb->query("
1207
- INSERT INTO $wpdb->links
1208
- SET
1209
- link_name = '".$wpdb->escape($name)."',
1210
- link_url = '".$wpdb->escape($uri)."',
1211
- link_category = '".$wpdb->escape($cat_id)."',
1212
- link_rss = '".$wpdb->escape($rss)."'
1213
- ");
1214
- $link_id = $wpdb->insert_id;
1215
- endif;
1216
  return $link_id;
1217
- } // function FeedWordPress::syndicate_link()
1218
 
1219
  /*static*/ function syndicated_status ($what, $default) {
1220
  $ret = get_option("feedwordpress_syndicated_{$what}_status");
@@ -1224,26 +1195,14 @@ class FeedWordPress {
1224
  return $ret;
1225
  } /* FeedWordPress::syndicated_status() */
1226
 
1227
- function on_unfamiliar ($what = 'author', $override = NULL) {
1228
- $set = array(
1229
- 'author' => array('create', 'default', 'filter'),
1230
- 'category' => array('create', 'tag', 'default', 'filter'),
1231
- );
 
1232
 
1233
- if (is_string($override)) :
1234
- $ret = strtolower($override);
1235
- else :
1236
- $ret = NULL;
1237
- endif;
1238
-
1239
- if (!is_numeric($override) and !in_array($ret, $set[$what])) :
1240
- $ret = get_option('feedwordpress_unfamiliar_'.$what);
1241
- if (!is_numeric($ret) and !in_array($ret, $set[$what])) :
1242
- $ret = 'create';
1243
- endif;
1244
- endif;
1245
-
1246
- return $ret;
1247
  } // function FeedWordPress::on_unfamiliar()
1248
 
1249
  function null_email_set () {
@@ -1344,13 +1303,45 @@ class FeedWordPress {
1344
  endif;
1345
  elseif ($fwp_db_version < 2009.0707) :
1346
  // We need to clear out any busted AJAX crap
1347
- if (fwp_test_wp_version(FWP_SCHEMA_HAS_USERMETA)) :
1348
- $wpdb->query("
1349
- DELETE FROM $wpdb->usermeta
1350
- WHERE LOCATE('feedwordpress', meta_key)
1351
- AND LOCATE('box', meta_key);
1352
- ");
 
 
 
 
 
1353
  endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1354
  update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
1355
  else :
1356
  // No. Just brand it with the new version.
@@ -1420,6 +1411,7 @@ class FeedWordPress {
1420
  $feed->set_file_class('WP_SimplePie_File');
1421
  $feed->set_content_type_sniffer_class('FeedWordPress_Content_Type_Sniffer');
1422
  $feed->set_file_class('FeedWordPress_File');
 
1423
  $feed->force_feed($force_feed);
1424
  $feed->set_cache_duration(FeedWordPress::cache_duration());
1425
  $feed->init();
@@ -1527,36 +1519,166 @@ class FeedWordPress {
1527
  return (in_array($level, $show));
1528
  } /* FeedWordPress::diagnostic_on () */
1529
 
1530
- function diagnostic ($level, $out) {
1531
  global $feedwordpress_admin_footer;
1532
 
1533
  $output = get_option('feedwordpress_diagnostics_output', array());
1534
-
 
1535
  $diagnostic_nesting = count(explode(":", $level));
1536
 
1537
  if (FeedWordPress::diagnostic_on($level)) :
1538
  foreach ($output as $method) :
1539
  switch ($method) :
1540
  case 'echo' :
1541
- echo "<div><pre><strong>Diag".str_repeat('====', $diagnostic_nesting-1).'|</strong> '.esc_html($out)."</pre></div>";
 
 
 
 
 
1542
  break;
1543
  case 'admin_footer' :
1544
  $feedwordpress_admin_footer[] = $out;
1545
  break;
1546
  case 'error_log' :
1547
- error_log('[feedwordpress]' . $out);
1548
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1549
  endswitch;
1550
  endforeach;
1551
  endif;
 
 
1552
  } /* FeedWordPress::diagnostic () */
1553
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1554
  function admin_footer () {
1555
  global $feedwordpress_admin_footer;
1556
  foreach ($feedwordpress_admin_footer as $line) :
1557
- echo '<div><pre>'.esc_html($line).'</pre></div>';
1558
  endforeach;
1559
  } /* FeedWordPress::admin_footer () */
 
 
 
 
 
 
 
 
 
1560
  } // class FeedWordPress
1561
 
1562
  class FeedWordPress_File extends WP_SimplePie_File {
@@ -1571,33 +1693,331 @@ class FeedWordPress_File extends WP_SimplePie_File {
1571
  }
1572
  } /* class FeedWordPress_File () */
1573
 
1574
- $feedwordpress_admin_footer = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1575
 
1576
- require_once(dirname(__FILE__) . '/syndicatedpost.class.php');
1577
- require_once(dirname(__FILE__) . '/syndicatedlink.class.php');
1578
 
1579
  ################################################################################
1580
  ## XML-RPC HOOKS: accept XML-RPC update pings from Contributors ################
1581
  ################################################################################
1582
 
1583
- function feedwordpress_xmlrpc_hook ($args = array ()) {
1584
- $args['weblogUpdates.ping'] = 'feedwordpress_pong';
1585
- return $args;
1586
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1587
 
1588
- function feedwordpress_pong ($args) {
1589
- $feedwordpress = new FeedWordPress;
1590
- $delta = @$feedwordpress->update($args[1]);
1591
- if (is_null($delta)):
1592
- return array('flerror' => true, 'message' => "Sorry. I don't syndicate <$args[1]>.");
1593
- else:
1594
- $mesg = array();
1595
- if (isset($delta['new'])) { $mesg[] = ' '.$delta['new'].' new posts were syndicated'; }
1596
- if (isset($delta['updated'])) { $mesg[] = ' '.$delta['updated'].' existing posts were updated'; }
1597
-
1598
- return array('flerror' => false, 'message' => "Thanks for the ping.".implode(' and', $mesg));
1599
- endif;
1600
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1601
 
1602
  // take your best guess at the realname and e-mail, given a string
1603
  define('FWP_REGEX_EMAIL_ADDY', '([^@"(<\s]+@[^"@(<\s]+\.[^"@(<\s]+)');
3
  Plugin Name: FeedWordPress
4
  Plugin URI: http://feedwordpress.radgeek.com/
5
  Description: simple and flexible Atom/RSS syndication for WordPress
6
+ Version: 2010.0903
7
  Author: Charles Johnson
8
  Author URI: http://radgeek.com/
9
  License: GPL
11
 
12
  /**
13
  * @package FeedWordPress
14
+ * @version 2010.0903
15
  */
16
 
17
  # This uses code derived from:
34
 
35
  # -- Don't change these unless you know what you're doing...
36
 
37
+ define ('FEEDWORDPRESS_VERSION', '2010.0903');
38
  define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
39
 
40
+ if (!defined('FEEDWORDPRESS_BLEG')) :
41
+ define ('FEEDWORDPRESS_BLEG', true);
42
+ endif;
43
+
44
  // Defaults
45
  define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
46
  define ('DEFAULT_UPDATE_PERIOD', 60); // value in minutes
100
 
101
  // Ensure that we have SimplePie loaded up and ready to go.
102
  // We no longer need a MagpieRSS upgrade module. Hallelujah!
103
+ if (!class_exists('SimplePie')) :
104
+ require_once(ABSPATH . WPINC . '/class-simplepie.php');
105
+ endif;
106
  require_once(ABSPATH . WPINC . '/class-feed.php');
 
107
 
108
  require_once (ABSPATH . WPINC . '/registration.php'); // for wp_insert_user
109
 
110
  require_once(dirname(__FILE__) . '/admin-ui.php');
111
+ require_once(dirname(__FILE__) . '/feedwordpresssyndicationpage.class.php');
112
  require_once(dirname(__FILE__) . '/compatability.php'); // LEGACY API: Replicate or mock up functions for legacy support purposes
113
+
114
+ require_once(dirname(__FILE__) . '/syndicatedpost.class.php');
115
+ require_once(dirname(__FILE__) . '/syndicatedlink.class.php');
116
  require_once(dirname(__FILE__) . '/feedwordpresshtml.class.php');
117
  require_once(dirname(__FILE__) . '/feedwordpress-content-type-sniffer.class.php');
118
 
123
 
124
  // Get the path relative to the plugins directory in which FWP is stored
125
  preg_match (
126
+ '|'.preg_quote(WP_PLUGIN_DIR).'/(.+)$|',
127
  dirname(__FILE__),
128
  $ref
129
  );
136
 
137
  // If this is a FeedWordPress admin page, queue up scripts for AJAX functions that FWP uses
138
  // If it is a display page or a non-FeedWordPress admin page, don't.
139
+ wp_register_style('feedwordpress-elements', WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-elements.css');
140
  if (FeedWordPressSettingsUI::is_admin()) :
141
+ // For JavaScript that needs to be generated dynamically
142
  add_action('admin_print_scripts', array('FeedWordPressSettingsUI', 'admin_scripts'));
143
 
144
+ // For CSS that needs to be generated dynamically.
145
+ add_action('admin_print_styles', array('FeedWordPressSettingsUI', 'admin_styles'));
146
 
147
  wp_enqueue_style('dashboard');
148
  wp_enqueue_style('feedwordpress-elements');
149
 
150
  if (function_exists('wp_admin_css')) :
151
+ wp_admin_css('css/dashboard');
 
 
152
  endif;
153
  endif;
154
 
199
  add_action('admin_footer', array('FeedWordPress', 'admin_footer'));
200
 
201
  # Inbound XML-RPC update methods
202
+ $feedwordpressRPC = new FeedWordPressRPC;
203
+
204
  # Outbound XML-RPC ping reform
205
  remove_action('publish_post', 'generic_ping'); // WP 1.5.x
206
  remove_action('do_pings', 'do_all_pings', 10, 1); // WP 2.1, 2.2
211
  add_action('feedwordpress_update', 'fwp_hold_pings');
212
  add_action('feedwordpress_update_complete', 'fwp_release_pings');
213
 
214
+ add_action('syndicated_feed_error', array('FeedWordPressDiagnostic', 'feed_error'), 100, 3);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
 
216
  add_action('wp_footer', 'debug_out_feedwordpress_footer', -100);
217
  add_action('admin_footer', 'debug_out_feedwordpress_footer', -100);
218
 
219
+ $feedwordpress = new FeedWordPress;
220
 
221
  # Cron-less auto-update. Hooray!
222
  $autoUpdateHook = get_option('feedwordpress_automatic_updates');
223
  if ($autoUpdateHook != 'init') :
224
  $autoUpdateHook = 'shutdown';
225
  endif;
226
+ add_action($autoUpdateHook, array(&$feedwordpress, 'auto_update'));
227
+ add_action('init', array(&$feedwordpress, 'init'));
228
+ add_action('shutdown', array(&$feedwordpress, 'email_diagnostic_log'));
229
+ add_action('wp_dashboard_setup', array(&$feedwordpress, 'dashboard_setup'));
230
 
231
  # Default sanitizers
232
  add_filter('syndicated_item_content', array('SyndicatedPost', 'resolve_relative_uris'), 0, 2);
237
  add_action('admin_menu', 'fwp_add_pages');
238
  endif; // if (!FeedWordPress::needs_upgrade())
239
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  ################################################################################
241
  ## LOGGING FUNCTIONS: log status updates to error_log if you want it ###########
242
  ################################################################################
243
 
244
+ class FeedWordPressDiagnostic {
245
+ function feed_error ($error, $old, $link) {
246
+ $wpError = $error['object'];
247
+ $url = $link->uri();
248
+
249
+ $mesgs = $wpError->get_error_messages();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  foreach ($mesgs as $mesg) :
251
+ $mesg = esc_html($mesg);
252
+ FeedWordPress::diagnostic(
253
+ 'updated_feeds:errors',
254
+ "Feed Error: [${url}] update returned error: $mesg"
255
+ );
256
+ if ($error['ts'] > $error['since']) :
257
+ $since = date('r', $error['since']);
258
+ $mostRecent = date('r', $error['ts']);
259
+ FeedWordPress::diagnostic(
260
+ 'updated_feeds:errors:persistent',
261
+ "Feed Update Error: [${url}] returning errors"
262
+ ." since ${since}:<br/><code>$mesg</code>",
263
+ $url, $error['since'], $error['ts']
264
+ );
265
+ endif;
266
+ endforeach;
267
+ }
268
+
269
+ function admin_emails ($id = '') {
270
+ $users = get_users_of_blog($id);
271
+ $recipients = array();
272
+ foreach ($users as $user) :
273
+ $dude = new WP_User($user->user_id);
274
+ if ($dude->has_cap('administrator')) :
275
+ if ($dude->user_email) :
276
+ $recipients[] = $dude->user_email;
277
+ endif;
278
+ endif;
279
+ endforeach;
280
+ return $recipients;
281
+ }
282
+ } /* class FeedWordPressDiagnostic */
283
 
284
  function debug_out_human_readable_bytes ($quantity) {
285
  $quantity = (int) $quantity;
286
  $magnitude = 'B';
287
  $orders = array('KB', 'MB', 'GB', 'TB');
288
+ while (($quantity > (1024*100)) and (count($orders) > 0)) :
289
  $quantity = floor($quantity / 1024);
290
  $magnitude = array_shift($orders);
291
  endwhile;
320
  return (strlen(get_syndication_feed_id($id)) > 0);
321
  } /* function is_syndicated() */
322
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
  function feedwordpress_display_url ($url, $before = 60, $after = 0) {
324
  $bits = parse_url($url);
325
 
326
  // Strip out crufty subdomains
327
+ if (isset($bits['host'])) :
328
+ $bits['host'] = preg_replace('/^www[0-9]*\./i', '', $bits['host']);
329
+ endif;
330
+
331
  // Reassemble bit-by-bit with minimum of crufty elements
332
  $url = (isset($bits['user'])?$bits['user'].'@':'')
333
  .(isset($bits['host'])?$bits['host']:'')
340
  endif;
341
 
342
  return $url;
343
+ } /* feedwordpress_display_url () */
344
 
345
+ function get_syndication_source_property ($original, $id, $local, $remote = NULL) {
346
+ $ret = NULL;
347
  if (is_null($original)) :
348
  $original = FeedWordPress::use_aggregator_source_data();
349
  endif;
350
+
351
+ if (is_null($remote)) :
352
+ $remote = $local . '_original';
 
 
353
  endif;
354
 
355
+ $vals = ($original ? get_post_custom_values($remote, $id) : array());
356
+ if (count($vals) < 1) :
357
+ $vals = get_post_custom_values($local, $id);
358
  endif;
359
 
360
  if (count($vals) > 0) :
361
  $ret = $vals[0];
 
 
362
  endif;
363
+ return $ret;
364
+ } /* function get_syndication_source_property () */
365
 
366
+ function the_syndication_source_link ($original = NULL, $id = NULL) { echo get_syndication_source_link($original, $id); }
367
+ function get_syndication_source_link ($original = NULL, $id = NULL) {
368
+ return get_syndication_source_property($original, $id, 'syndication_source_uri');
369
+ } /* function get_syndication_source_link() */
370
+
371
+ function the_syndication_source ($original = NULL, $id = NULL) { echo get_syndication_source($original, $id); }
372
+ function get_syndication_source ($original = NULL, $id = NULL) {
373
+ $ret = get_syndication_source_property($original, $id, 'syndication_source');
374
+ if (is_null($ret) or strlen(trim($ret)) == 0) : // Fall back to URL of blog
375
  $ret = feedwordpress_display_url(get_syndication_source_link());
376
  endif;
 
377
  return $ret;
378
  } /* function get_syndication_source() */
379
 
380
+ function the_syndication_feed ($original = NULL, $id = NULL) { echo get_syndication_feed($original, $id); }
 
381
  function get_syndication_feed ($original = NULL, $id = NULL) {
382
+ return get_syndication_source_property($original, $id, 'syndication_feed');
 
 
 
 
 
 
 
 
 
 
 
 
383
  } /* function get_syndication_feed() */
384
 
385
+ function the_syndication_feed_guid ($original = NULL, $id = NULL) { echo get_syndication_feed_guid($original, $id); }
 
386
  function get_syndication_feed_guid ($original = NULL, $id = NULL) {
387
+ $ret = get_syndication_source_property($original, $id, 'syndication_source_id');
388
+ if (is_null($ret) or strlen(trim($ret))==0) : // Fall back to URL of feed
389
+ $ret = get_syndication_feed();
390
  endif;
 
 
 
 
 
 
 
 
 
 
391
  return $ret;
392
  } /* function get_syndication_feed_guid () */
393
 
 
 
394
  function get_syndication_feed_id ($id = NULL) { list($u) = get_post_custom_values('syndication_feed_id', $id); return $u; }
395
  function the_syndication_feed_id ($id = NULL) { echo get_syndication_feed_id($id); }
396
 
670
  ################################################################################
671
 
672
  function fwp_add_pages () {
 
673
  global $fwp_path;
674
 
675
+ add_menu_page('Syndicated Sites', 'Syndication', 'manage_links', $fwp_path.'/syndication.php', NULL, WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-tiny.png');
676
+ do_action('feedwordpress_admin_menu_pre_feeds');
677
+ add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Feeds & Updates', 'Feeds & Updates', 'manage_options', $fwp_path.'/feeds-page.php');
678
+ do_action('feedwordpress_admin_menu_pre_posts');
679
+ add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Posts & Links', 'Posts & Links', 'manage_options', $fwp_path.'/posts-page.php');
680
+ do_action('feedwordpress_admin_menu_pre_authors');
681
+ add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Authors', 'Authors', 'manage_options', $fwp_path.'/authors-page.php');
682
+ do_action('feedwordpress_admin_menu_pre_categories');
683
+ add_submenu_page($fwp_path.'/syndication.php', 'Categories'.FEEDWORDPRESS_AND_TAGS, 'Categories'.FEEDWORDPRESS_AND_TAGS, 'manage_options', $fwp_path.'/categories-page.php');
684
+ do_action('feedwordpress_admin_menu_pre_performance');
685
+ add_submenu_page($fwp_path.'/syndication.php', 'FeedWordPress Performance', 'Performance', 'manage_options', $fwp_path.'/performance-page.php');
686
+ do_action('feedwordpress_admin_menu_pre_diagnostics');
687
+ add_submenu_page($fwp_path.'/syndication.php', 'FeedWordPress Diagnostics', 'Diagnostics', 'manage_options', $fwp_path.'/diagnostics-page.php');
688
  } /* function fwp_add_pages () */
689
 
690
  function fwp_check_debug () {
930
  return NULL;
931
  endif;
932
 
933
+ if (!is_null($uri) and $uri != '*') :
934
  $uri = trim($uri);
935
  else : // Update all
936
  update_option('feedwordpress_last_update_all', time());
946
  $crash_ts = NULL;
947
  endif;
948
  endif;
949
+
950
  // Randomize order for load balancing purposes
951
  $feed_set = $this->feeds;
952
  shuffle($feed_set);
953
 
954
+ $feed_set = apply_filters('feedwordpress_update_feeds', $feed_set, $uri);
955
+
956
  // Loop through and check for new posts
957
  $delta = NULL;
958
  foreach ($feed_set as $feed) :
968
  $timely = $feed->stale();
969
  endif;
970
 
971
+ if ($pinged_that and is_null($delta)) : // If at least one feed was hit for updating...
972
  $delta = array('new' => 0, 'updated' => 0); // ... don't return error condition
973
  endif;
974
 
1020
  endif;
1021
  return $ret;
1022
  } // FeedWordPress::stale()
1023
+
1024
+ function init () {
1025
+ $this->clear_cache_magic_url();
1026
+ $this->update_magic_url();
1027
+ } /* FeedWordPress::init() */
1028
+
1029
+ function dashboard_setup () {
1030
+ // Get the stylesheet
1031
+ wp_enqueue_style('feedwordpress-elements');
1032
+
1033
+ $widget_id = 'feedwordpress_dashboard';
1034
+ $widget_name = __('Syndicated Sources');
1035
+ $column = 'side';
1036
+ $priority = 'core';
1037
+
1038
+ // I would love to use wp_add_dashboard_widget() here and save
1039
+ // myself some trouble. But WP 3 does not yet have any way to
1040
+ // push a dashboard widget onto the side, or to give it a default
1041
+ // location.
1042
+ add_meta_box(
1043
+ /*id=*/ $widget_id,
1044
+ /*title=*/ $widget_name,
1045
+ /*callback=*/ array(&$this, 'dashboard'),
1046
+ /*page=*/ 'dashboard',
1047
+ /*context=*/ $column,
1048
+ /*priority=*/ $priority
1049
+ );
1050
+ /*control_callback= array(&$this, 'dashboard_control') */
1051
+
1052
+ // This is kind of rude, I know, but the dashboard widget isn't
1053
+ // worth much if users don't know that it exists, and I don't
1054
+ // know of any better way to reorder the boxen.
1055
+ //
1056
+ // Gleefully ripped off of codex.wordpress.org/Dashboard_Widgets_API
1057
+
1058
+ // Globalize the metaboxes array, this holds all the widgets for wp-admin
1059
+ global $wp_meta_boxes;
1060
+
1061
+ // Get the regular dashboard widgets array
1062
+ // (which has our new widget already but at the end)
1063
+
1064
+ $normal_dashboard = $wp_meta_boxes['dashboard'][$column][$priority];
1065
+
1066
+ // Backup and delete our new dashbaord widget from the end of the array
1067
+ if (isset($normal_dashboard[$widget_id])) :
1068
+ $backup = array();
1069
+ $backup[$widget_id] = $normal_dashboard[$widget_id];
1070
+ unset($normal_dashboard[$widget_id]);
1071
+
1072
+ // Merge the two arrays together so our widget is at the
1073
+ // beginning
1074
+ $sorted_dashboard = array_merge($backup, $normal_dashboard);
1075
+
1076
+ // Save the sorted array back into the original metaboxes
1077
+ $wp_meta_boxes['dashboard'][$column][$priority] = $sorted_dashboard;
1078
+ endif;
1079
+ } /* FeedWordPress::dashboard_setup () */
1080
+
1081
+ function dashboard () {
1082
+ $syndicationPage = new FeedWordPressSyndicationPage(dirname(__FILE__).'/syndication.php');
1083
+ $syndicationPage->dashboard_box($syndicationPage);
1084
+ } /* FeedWordPress::dashboard () */
1085
+
1086
+ function update_magic_url () {
1087
+ global $wpdb;
1088
+
1089
+ // Explicit update request in the HTTP request (e.g. from a cron job)
1090
+ if ($this->update_requested()) :
1091
+ $this->update($this->update_requested_url());
1092
+
1093
+ if (FEEDWORDPRESS_DEBUG and count($wpdb->queries) > 0) :
1094
+ $mysqlTime = 0.0;
1095
+ $byTime = array();
1096
+ foreach ($wpdb->queries as $query) :
1097
+ $time = $query[1] * 1000000.0;
1098
+ $mysqlTime += $query[1];
1099
+ if (!isset($byTime[$time])) : $byTime[$time] = array(); endif;
1100
+ $byTime[$time][] = $query[0]. ' // STACK: ' . $query[2];
1101
+ endforeach;
1102
+ krsort($byTime);
1103
+
1104
+ foreach ($byTime as $time => $querySet) :
1105
+ foreach ($querySet as $query) :
1106
+ print "[".(sprintf('%4.4f', $time/1000.0)) . "ms] $query\n";
1107
+ endforeach;
1108
+ endforeach;
1109
+ echo $this->log_prefix()."$wpdb->num_queries queries. $mysqlTime seconds in MySQL. Total of "; timer_stop(1); print " seconds.";
1110
+ endif;
1111
+
1112
+ debug_out_feedwordpress_footer();
1113
+
1114
+ // Magic URL should return nothing but a 200 OK header packet
1115
+ // when successful.
1116
+ exit;
1117
+ endif;
1118
+ } /* FeedWordPress::magic_update_url () */
1119
+
1120
+ function clear_cache_magic_url () {
1121
+ if ($this->clear_cache_requested()) :
1122
+ $this->clear_cache();
1123
+ endif;
1124
+ } /* FeedWordPress::clear_cache_magic_url() */
1125
 
1126
  function clear_cache_requested () {
1127
  return (
1138
  } // FeedWordPress::update_requested()
1139
 
1140
  function update_requested_url () {
1141
+ $ret = null;
1142
+
1143
+ if (($_REQUEST['update_feedwordpress']=='*')
1144
+ or (preg_match('|^http://.*|i', $_REQUEST['update_feedwordpress']))) :
1145
+ $ret = $_REQUEST['update_feedwordpress'];
1146
+ endif;
1147
 
1148
+ return $ret;
1149
  } // FeedWordPress::update_requested_url()
1150
 
1151
+ function auto_update () {
1152
+ if ($this->stale()) :
1153
+ $this->update();
1154
+ endif;
1155
+ } /* FeedWordPress::auto_update () */
1156
+
1157
+ function find_link ($uri, $field = 'link_rss') {
1158
  global $wpdb;
1159
 
1160
+ $unslashed = untrailingslashit($uri);
1161
+ $slashed = trailingslashit($uri);
1162
+ $link_id = $wpdb->get_var($wpdb->prepare("
1163
+ SELECT link_id FROM $wpdb->links WHERE $field IN ('%s', '%s')
1164
+ LIMIT 1", $unslashed, $slashed
1165
+ ));
1166
+
1167
+ return $link_id;
1168
+ } /* FeedWordPress::find_link () */
1169
+
1170
+ function syndicate_link ($name, $uri, $rss) {
1171
  // Get the category ID#
1172
  $cat_id = FeedWordPress::link_category_id();
1173
 
1174
  // WordPress gets cranky if there's no homepage URI
1175
+ if (!is_string($uri) or strlen($uri)<1) : $uri = $rss; endif;
1176
 
1177
+ // Check if this feed URL is already being syndicated.
1178
+ $link_id = wp_insert_link(array(
1179
+ "link_id" => FeedWordPress::find_link($rss), // insert if nothing was found; else update
1180
+ "link_rss" => $rss,
1181
+ "link_name" => $name,
1182
+ "link_url" => $uri,
1183
+ "link_category" => array($cat_id),
1184
+ "link_visible" => 'Y', // reactivate if inactivated
1185
+ ));
 
 
 
 
1186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1187
  return $link_id;
1188
+ } /* function FeedWordPress::syndicate_link() */
1189
 
1190
  /*static*/ function syndicated_status ($what, $default) {
1191
  $ret = get_option("feedwordpress_syndicated_{$what}_status");
1195
  return $ret;
1196
  } /* FeedWordPress::syndicated_status() */
1197
 
1198
+ function on_unfamiliar ($what = 'author') {
1199
+ switch ($what) :
1200
+ case 'category' : $suffix = ':category'; break;
1201
+ case 'post_tag' : $suffix = ':post_tag'; break;
1202
+ default: $suffix = '';
1203
+ endswitch;
1204
 
1205
+ return get_option('feedwordpress_unfamiliar_'.$what, 'create'.$suffix);
 
 
 
 
 
 
 
 
 
 
 
 
 
1206
  } // function FeedWordPress::on_unfamiliar()
1207
 
1208
  function null_email_set () {
1303
  endif;
1304
  elseif ($fwp_db_version < 2009.0707) :
1305
  // We need to clear out any busted AJAX crap
1306
+ $wpdb->query("
1307
+ DELETE FROM $wpdb->usermeta
1308
+ WHERE LOCATE('feedwordpress', meta_key)
1309
+ AND LOCATE('box', meta_key);
1310
+ ");
1311
+
1312
+ update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
1313
+ elseif ($fwp_db_version < 2010.0814) :
1314
+ // Change in terminology.
1315
+ if (get_option('feedwordpress_unfamiliar_category', 'create')=='default') :
1316
+ update_option('feedwordpress_unfamiliar_category', 'null');
1317
  endif;
1318
+ foreach (FeedWordPress::syndicated_links() as $link) :
1319
+ $sub = new SyndicatedLink($link);
1320
+
1321
+ $remap_uf = array(
1322
+ 'default' => 'null',
1323
+ 'filter' => 'null',
1324
+ 'create' => 'create:category',
1325
+ 'tag' => 'create:post_tag'
1326
+ );
1327
+ if (isset($sub->settings['unfamiliar category'])) :
1328
+ if ($sub->settings['unfamiliar category']=='filter') :
1329
+ $sub->settings['match/filter'] = array('category');
1330
+ endif;
1331
+ foreach ($remap_uf as $from => $to) :
1332
+ if ($sub->settings['unfamiliar category']==$from) :
1333
+ $sub->settings['unfamiliar category'] = $to;
1334
+ endif;
1335
+ endforeach;
1336
+ endif;
1337
+
1338
+ if (isset($sub->settings['add global categories'])) :
1339
+ $sub->settings['add/category'] = $sub->settings['add global categories'];
1340
+ unset($sub->settings['add global categories']);
1341
+ endif;
1342
+
1343
+ $sub->save_settings(/*reload=*/ true);
1344
+ endforeach;
1345
  update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
1346
  else :
1347
  // No. Just brand it with the new version.
1411
  $feed->set_file_class('WP_SimplePie_File');
1412
  $feed->set_content_type_sniffer_class('FeedWordPress_Content_Type_Sniffer');
1413
  $feed->set_file_class('FeedWordPress_File');
1414
+ $feed->set_parser_class('FeedWordPress_Parser');
1415
  $feed->force_feed($force_feed);
1416
  $feed->set_cache_duration(FeedWordPress::cache_duration());
1417
  $feed->init();
1519
  return (in_array($level, $show));
1520
  } /* FeedWordPress::diagnostic_on () */
1521
 
1522
+ function diagnostic ($level, $out, $persist = NULL, $since = NULL, $mostRecent = NULL) {
1523
  global $feedwordpress_admin_footer;
1524
 
1525
  $output = get_option('feedwordpress_diagnostics_output', array());
1526
+ $dlog = get_option('feedwordpress_diagnostics_log', array());
1527
+
1528
  $diagnostic_nesting = count(explode(":", $level));
1529
 
1530
  if (FeedWordPress::diagnostic_on($level)) :
1531
  foreach ($output as $method) :
1532
  switch ($method) :
1533
  case 'echo' :
1534
+ echo "<div><pre><strong>Diag".str_repeat('====', $diagnostic_nesting-1).'|</strong> '.$out."</pre></div>";
1535
+ break;
1536
+ case 'echo_in_cronjob' :
1537
+ if (FeedWordPress::update_requested()) :
1538
+ echo FeedWordPress::log_prefix()." ".$out."\n";
1539
+ endif;
1540
  break;
1541
  case 'admin_footer' :
1542
  $feedwordpress_admin_footer[] = $out;
1543
  break;
1544
  case 'error_log' :
1545
+ error_log(FeedWordPress::log_prefix().' '.$out);
1546
  break;
1547
+ case 'email' :
1548
+ if (is_null($persist)) :
1549
+ $sect = 'occurrent';
1550
+ $hook = (isset($dlog['mesg'][$sect]) ? count($dlog['mesg'][$sect]) : 0);
1551
+ $line = array("Time" => time(), "Message" => $out);
1552
+ else :
1553
+ $sect = 'persistent';
1554
+ $hook = md5($level."\n".$persist);
1555
+ $line = array("Since" => $since, "Message" => $out, "Most Recent" => $mostRecent);
1556
+ endif;
1557
+
1558
+ if (!isset($dlog['mesg'])) : $dlog['mesg'] = array(); endif;
1559
+ if (!isset($dlog['mesg'][$sect])) : $dlog['mesg'][$sect] = array(); endif;
1560
+
1561
+ $dlog['mesg'][$sect][$hook] = $line;
1562
  endswitch;
1563
  endforeach;
1564
  endif;
1565
+
1566
+ update_option('feedwordpress_diagnostics_log', $dlog);
1567
  } /* FeedWordPress::diagnostic () */
1568
 
1569
+ function email_diagnostic_log () {
1570
+ $dlog = get_option('feedwordpress_diagnostics_log', array());
1571
+
1572
+ $recipients = get_option('feedwordpress_diagnostics_log_recipients', NULL);
1573
+ if (is_null($recipients)) :
1574
+ $recipients = FeedWordPressDiagnostic::admin_emails();
1575
+ endif;
1576
+
1577
+ if (isset($dlog['schedule']) and isset($dlog['schedule']['last'])) :
1578
+ if (time() > ($dlog['schedule']['last'] + $dlog['schedule']['freq'])) :
1579
+ // No news is good news; only send if
1580
+ // there are some messages to send.
1581
+ $body = NULL;
1582
+ foreach ($dlog['mesg'] as $sect => $mesgs) :
1583
+ if (count($mesgs) > 0) :
1584
+ if (is_null($body)) : $body = ''; endif;
1585
+
1586
+ $paradigm = reset($mesgs);
1587
+ $body .= "<h2>".ucfirst($sect)." issues</h2>\n"
1588
+ ."<table>\n"
1589
+ ."<thead><tr>\n";
1590
+ foreach ($paradigm as $col => $value) :
1591
+ $body .= '<th scope="col">'.$col."</th>\n";
1592
+ endforeach;
1593
+ $body .= "</tr></thead>\n"
1594
+ ."<tbody>\n";
1595
+
1596
+ foreach ($mesgs as $line) :
1597
+ $body .= "<tr>\n";
1598
+ foreach ($line as $col => $cell) :
1599
+ if (is_numeric($cell)) :
1600
+ $cell = date('j-M-y, h:i a', $cell);
1601
+ endif;
1602
+ $class = strtolower(preg_replace('/\s+/', '-', $col));
1603
+ $body .= "<td class=\"$class\">${cell}</td>";
1604
+ endforeach;
1605
+ $body .= "</tr>\n";
1606
+ endforeach;
1607
+
1608
+ $body .= "</tbody>\n</table>\n\n";
1609
+ endif;
1610
+ endforeach;
1611
+
1612
+ if (!is_null($body)) :
1613
+ $home = feedwordpress_display_url(get_bloginfo('url'));
1614
+ $subj = $home . " syndication issues for ".date('j-M-y', time());
1615
+ $agent = 'FeedWordPress '.FEEDWORDPRESS_VERSION;
1616
+ $body = <<<EOMAIL
1617
+ <html>
1618
+ <head>
1619
+ <title>$subj</title>
1620
+ <style type="text/css">
1621
+ body { background-color: white; color: black; }
1622
+ table { width: 100%; border: 1px solid black; }
1623
+ table thead tr th { background-color: #ff7700; color: white; border-bottom: 1px solid black; }
1624
+ table thead tr { border-bottom: 1px solid black; }
1625
+ table tr { vertical-align: top; }
1626
+ table .since { width: 20%; }
1627
+ table .time { width: 20%; }
1628
+ table .most-recently { width: 20%; }
1629
+ table .message { width: auto; }
1630
+ </style>
1631
+ </head>
1632
+ <body>
1633
+ <h1>Syndication Issues encountered by $agent on $home</h1>
1634
+ $body
1635
+ </body>
1636
+ </html>
1637
+
1638
+ EOMAIL;
1639
+ foreach ($recipients as $email) :
1640
+ add_filter('wp_mail_content_type', array('FeedWordPress', 'allow_html_mail'));
1641
+ wp_mail($email, $subj, $body);
1642
+ remove_filter('wp_mail_content_type', array('FeedWordPress', 'allow_html_mail'));
1643
+ endforeach;
1644
+ endif;
1645
+
1646
+ // Clear the logs
1647
+ $dlog['mesg']['persistent'] = array();
1648
+ $dlog['mesg']['occurrent'] = array();
1649
+
1650
+ // Set schedule for next update
1651
+ $dlog['schedule']['last'] = time();
1652
+ endif;
1653
+ else :
1654
+ $dlog['schedule'] = array(
1655
+ 'freq' =>24 /*hr*/ * 60 /*min*/ * 60 /*s*/,
1656
+ 'last' => time(),
1657
+ );
1658
+ endif;
1659
+
1660
+ update_option('feedwordpress_diagnostics_log', $dlog);
1661
+ } /* FeedWordPress::email_diagnostic_log () */
1662
+
1663
+ function allow_html_mail () {
1664
+ return 'text/html';
1665
+ } /* FeedWordPress::allow_html_mail () */
1666
+
1667
  function admin_footer () {
1668
  global $feedwordpress_admin_footer;
1669
  foreach ($feedwordpress_admin_footer as $line) :
1670
+ echo '<div><pre>'.$line.'</pre></div>';
1671
  endforeach;
1672
  } /* FeedWordPress::admin_footer () */
1673
+
1674
+ function log_prefix ($date = false) {
1675
+ $home = get_bloginfo('url');
1676
+ $prefix = '['.feedwordpress_display_url($home).'] [feedwordpress] ';
1677
+ if ($date) :
1678
+ $prefix = "[".date('Y-m-d H:i:s')."]".$prefix;
1679
+ endif;
1680
+ return $prefix;
1681
+ } /* FeedWordPress::log_prefix () */
1682
  } // class FeedWordPress
1683
 
1684
  class FeedWordPress_File extends WP_SimplePie_File {
1693
  }
1694
  } /* class FeedWordPress_File () */
1695
 
1696
+ class FeedWordPress_Parser extends SimplePie_Parser {
1697
+ function parse (&$data, $encoding) {
1698
+ // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
1699
+ if (strtoupper($encoding) === 'US-ASCII')
1700
+ {
1701
+ $this->encoding = 'UTF-8';
1702
+ }
1703
+ else
1704
+ {
1705
+ $this->encoding = $encoding;
1706
+ }
1707
+
1708
+ // Strip BOM:
1709
+ // UTF-32 Big Endian BOM
1710
+ if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
1711
+ {
1712
+ $data = substr($data, 4);
1713
+ }
1714
+ // UTF-32 Little Endian BOM
1715
+ elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
1716
+ {
1717
+ $data = substr($data, 4);
1718
+ }
1719
+ // UTF-16 Big Endian BOM
1720
+ elseif (substr($data, 0, 2) === "\xFE\xFF")
1721
+ {
1722
+ $data = substr($data, 2);
1723
+ }
1724
+ // UTF-16 Little Endian BOM
1725
+ elseif (substr($data, 0, 2) === "\xFF\xFE")
1726
+ {
1727
+ $data = substr($data, 2);
1728
+ }
1729
+ // UTF-8 BOM
1730
+ elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
1731
+ {
1732
+ $data = substr($data, 3);
1733
+ }
1734
+
1735
+ if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
1736
+ {
1737
+ $declaration =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
1738
+ if ($declaration->parse())
1739
+ {
1740
+ $data = substr($data, $pos + 2);
1741
+ $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
1742
+ }
1743
+ else
1744
+ {
1745
+ $this->error_string = 'SimplePie bug! Please report this!';
1746
+ return false;
1747
+ }
1748
+ }
1749
+
1750
+ $return = true;
1751
+
1752
+ static $xml_is_sane = null;
1753
+ if ($xml_is_sane === null)
1754
+ {
1755
+ $parser_check = xml_parser_create();
1756
+ xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1757
+ xml_parser_free($parser_check);
1758
+ $xml_is_sane = isset($values[0]['value']);
1759
+ }
1760
+
1761
+ // Create the parser
1762
+ if ($xml_is_sane)
1763
+ {
1764
+ $xml = xml_parser_create_ns($this->encoding, $this->separator);
1765
+ xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
1766
+ xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
1767
+ xml_set_object($xml, $this);
1768
+ xml_set_character_data_handler($xml, 'cdata');
1769
+ xml_set_element_handler($xml, 'tag_open', 'tag_close');
1770
+ xml_set_start_namespace_decl_handler($xml, 'start_xmlns');
1771
+
1772
+ // Parse!
1773
+ if (!xml_parse($xml, $data, true))
1774
+ {
1775
+ $this->error_code = xml_get_error_code($xml);
1776
+ $this->error_string = xml_error_string($this->error_code);
1777
+ $return = false;
1778
+ }
1779
+
1780
+ $this->current_line = xml_get_current_line_number($xml);
1781
+ $this->current_column = xml_get_current_column_number($xml);
1782
+ $this->current_byte = xml_get_current_byte_index($xml);
1783
+ xml_parser_free($xml);
1784
+
1785
+ return $return;
1786
+ }
1787
+ else
1788
+ {
1789
+ libxml_clear_errors();
1790
+ $xml =& new XMLReader();
1791
+ $xml->xml($data);
1792
+ while (@$xml->read())
1793
+ {
1794
+ switch ($xml->nodeType)
1795
+ {
1796
+
1797
+ case constant('XMLReader::END_ELEMENT'):
1798
+ if ($xml->namespaceURI !== '')
1799
+ {
1800
+ $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
1801
+ }
1802
+ else
1803
+ {
1804
+ $tagName = $xml->localName;
1805
+ }
1806
+ $this->tag_close(null, $tagName);
1807
+ break;
1808
+ case constant('XMLReader::ELEMENT'):
1809
+ $empty = $xml->isEmptyElement;
1810
+ if ($xml->namespaceURI !== '')
1811
+ {
1812
+ $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
1813
+ }
1814
+ else
1815
+ {
1816
+ $tagName = $xml->localName;
1817
+ }
1818
+ $attributes = array();
1819
+ while ($xml->moveToNextAttribute())
1820
+ {
1821
+ if ($xml->namespaceURI !== '')
1822
+ {
1823
+ $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
1824
+ }
1825
+ else
1826
+ {
1827
+ $attrName = $xml->localName;
1828
+ }
1829
+ $attributes[$attrName] = $xml->value;
1830
+ }
1831
+
1832
+ foreach ($attributes as $attr => $value) :
1833
+ list($ns, $local) = $this->split_ns($attr);
1834
+ if ($ns=='http://www.w3.org/2000/xmlns/') :
1835
+ if ('xmlns' == $local) : $local = false; endif;
1836
+ $this->start_xmlns(null, $local, $value);
1837
+ endif;
1838
+ endforeach;
1839
+
1840
+ $this->tag_open(null, $tagName, $attributes);
1841
+ if ($empty)
1842
+ {
1843
+ $this->tag_close(null, $tagName);
1844
+ }
1845
+ break;
1846
+ case constant('XMLReader::TEXT'):
1847
+
1848
+ case constant('XMLReader::CDATA'):
1849
+ $this->cdata(null, $xml->value);
1850
+ break;
1851
+ }
1852
+ }
1853
+ if ($error = libxml_get_last_error())
1854
+ {
1855
+ $this->error_code = $error->code;
1856
+ $this->error_string = $error->message;
1857
+ $this->current_line = $error->line;
1858
+ $this->current_column = $error->column;
1859
+ return false;
1860
+ }
1861
+ else
1862
+ {
1863
+ return true;
1864
+ }
1865
+ }
1866
+ } /* FeedWordPress_Parser::parse() */
1867
+
1868
+ var $xmlns_stack = array();
1869
+ var $xmlns_current = array();
1870
+ function tag_open ($parser, $tag, $attributes) {
1871
+ $ret = parent::tag_open($parser, $tag, $attributes);
1872
+ if ($this->current_xhtml_construct < 0) :
1873
+ $this->data['xmlns'] = $this->xmlns_current;
1874
+ $this->xmlns_stack[] = $this->xmlns_current;
1875
+ endif;
1876
+ return $ret;
1877
+ }
1878
+
1879
+ function tag_close($parser, $tag) {
1880
+ if ($this->current_xhtml_construct < 0) :
1881
+ $this->xmlns_current = array_pop($this->xmlns_stack);
1882
+ endif;
1883
+ $ret = parent::tag_close($parser, $tag);
1884
+ return $ret;
1885
+ }
1886
+
1887
+ function start_xmlns ($parser, $prefix, $uri) {
1888
+ if (!$prefix) :
1889
+ $prefix = '';
1890
+ endif;
1891
+ if ($this->current_xhtml_construct < 0) :
1892
+ $this->xmlns_current[$prefix] = $uri;
1893
+ endif;
1894
+ return true;
1895
+ } /* FeedWordPress_Parser::start_xmlns() */
1896
+ }
1897
 
1898
+ $feedwordpress_admin_footer = array();
 
1899
 
1900
  ################################################################################
1901
  ## XML-RPC HOOKS: accept XML-RPC update pings from Contributors ################
1902
  ################################################################################
1903
 
1904
+ class FeedWordPressRPC {
1905
+ function FeedWordPressRPC () {
1906
+ add_filter('xmlrpc_methods', array(&$this, 'xmlrpc_methods'));
1907
+ }
1908
+
1909
+ function xmlrpc_methods ($args = array()) {
1910
+ $args['weblogUpdates.ping'] = array(&$this, 'ping');
1911
+ $args['feedwordpress.subscribe'] = array(&$this, 'subscribe');
1912
+ $args['feedwordpress.deactivate'] = array(&$this, 'deactivate');
1913
+ $args['feedwordpress.delete'] = array(&$this, 'delete');
1914
+ $args['feedwordpress.nuke'] = array(&$this, 'nuke');
1915
+ return $args;
1916
+ }
1917
+
1918
+ function ping ($args) {
1919
+ global $feedwordpress;
1920
+
1921
+ $delta = @$feedwordpress->update($args[1]);
1922
+ if (is_null($delta)):
1923
+ return array('flerror' => true, 'message' => "Sorry. I don't syndicate <$args[1]>.");
1924
+ else:
1925
+ $mesg = array();
1926
+ if (isset($delta['new'])) { $mesg[] = ' '.$delta['new'].' new posts were syndicated'; }
1927
+ if (isset($delta['updated'])) { $mesg[] = ' '.$delta['updated'].' existing posts were updated'; }
1928
+
1929
+ return array('flerror' => false, 'message' => "Thanks for the ping.".implode(' and', $mesg));
1930
+ endif;
1931
+ }
1932
+
1933
+ function validate (&$args) {
1934
+ global $wp_xmlrpc_server;
1935
+
1936
+ // First two params are username/password
1937
+ $username = $wp_xmlrpc_server->escape(array_shift($args));
1938
+ $password = $wp_xmlrpc_server->escape(array_shift($args));
1939
+
1940
+ $ret = array();
1941
+ if ( !$user = $wp_xmlrpc_server->login($username, $password) ) :
1942
+ $ret = $wp_xmlrpc_server->error;
1943
+ elseif (!current_user_can('manage_links')) :
1944
+ $ret = new IXR_Error(401, 'Sorry, you cannot change the subscription list.');
1945
+ endif;
1946
+ return $ret;
1947
+ }
1948
 
1949
+ function subscribe ($args) {
1950
+ $ret = $this->validate($args);
1951
+ if (is_array($ret)) : // Success
1952
+ // The remaining params are feed URLs
1953
+ foreach ($args as $arg) :
1954
+ $finder = new FeedFinder($arg, /*verify=*/ false, /*fallbacks=*/ 1);
1955
+ $feeds = array_values(array_unique($finder->find()));
1956
+
1957
+ if (count($feeds) > 0) :
1958
+ $link_id = FeedWordPress::syndicate_link(
1959
+ /*title=*/ feedwordpress_display_url($feeds[0]),
1960
+ /*homepage=*/ $feeds[0],
1961
+ /*feed=*/ $feeds[0]
1962
+ );
1963
+ $ret[] = array(
1964
+ 'added',
1965
+ $feeds[0],
1966
+ $arg,
1967
+ );
1968
+ else :
1969
+ $ret[] = array(
1970
+ 'error',
1971
+ $arg
1972
+ );
1973
+ endif;
1974
+ endforeach;
1975
+ endif;
1976
+ return $ret;
1977
+ } /* FeedWordPressRPC::subscribe () */
1978
+
1979
+ function unsubscribe ($method, $args) {
1980
+ $ret = $this->validate($args);
1981
+ if (is_array($ret)) : // Success
1982
+ // The remaining params are feed URLs
1983
+ foreach ($args as $arg) :
1984
+ $link_id = FeedWordPress::find_link($arg);
1985
+
1986
+ if (!$link_id) :
1987
+ $link_id = FeedWordPress::find_link($arg, 'link_url');
1988
+ endif;
1989
+
1990
+ if ($link_id) :
1991
+ $link = new SyndicatedLink($link_id);
1992
+
1993
+ $link->{$method}();
1994
+ $ret[] = array(
1995
+ 'deactivated',
1996
+ $arg,
1997
+ );
1998
+ else :
1999
+ $ret[] = array(
2000
+ 'error',
2001
+ $arg,
2002
+ );
2003
+ endif;
2004
+ endforeach;
2005
+ endif;
2006
+ return $ret;
2007
+ } /* FeedWordPress::unsubscribe () */
2008
+
2009
+ function deactivate ($args) {
2010
+ return $this->unsubscribe('deactivate', $args);
2011
+ } /* FeedWordPressRPC::deactivate () */
2012
+
2013
+ function delete ($args) {
2014
+ return $this->unsubscribe('delete', $args);
2015
+ } /* FeedWordPressRPC::delete () */
2016
+
2017
+ function nuke ($args) {
2018
+ return $this->unsubscribe('nuke', $args);
2019
+ } /* FeedWordPressRPC::nuke () */
2020
+ } /* class FeedWordPressRPC */
2021
 
2022
  // take your best guess at the realname and e-mail, given a string
2023
  define('FWP_REGEX_EMAIL_ADDY', '([^@"(<\s]+@[^"@(<\s]+\.[^"@(<\s]+)');
feedwordpresshtml.class.php CHANGED
@@ -17,8 +17,14 @@ class FeedWordPressHTML {
17
  } /* function FeedWordPressHTML::attributeRegex () */
18
 
19
  function attributeMatch ($matches) {
20
- $suffix = (isset($matches[12]) ? $matches[12] : $matches[9]);
21
- $value = (isset($matches[10]) ? $matches[10] : $matches[7]);
 
 
 
 
 
 
22
 
23
  return array(
24
  "tag" => $matches[3],
@@ -31,5 +37,50 @@ class FeedWordPressHTML {
31
  "after_attribute" => $suffix,
32
  );
33
  } /* function FeedWordPressHTML::attributeMatch () */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  } /* class FeedWordPressHTML */
35
 
17
  } /* function FeedWordPressHTML::attributeRegex () */
18
 
19
  function attributeMatch ($matches) {
20
+ for ($i = 0; $i <= 12; $i++) :
21
+ if (!isset($matches[$i])) :
22
+ $matches[$i] = '';
23
+ endif;
24
+ endfor;
25
+
26
+ $suffix = $matches[12].$matches[9];
27
+ $value = $matches[10].$matches[7];
28
 
29
  return array(
30
  "tag" => $matches[3],
37
  "after_attribute" => $suffix,
38
  );
39
  } /* function FeedWordPressHTML::attributeMatch () */
40
+
41
+ function tagWithAttributeRegex ($tag, $attr, $value) {
42
+ return ":(
43
+ (<($tag)\s+[^>]*)
44
+ ($attr)=
45
+ )
46
+ (
47
+ \s*(\"|')
48
+ ((((?!\\6).)*\s)*($value)(\s((?!\\6).)*)*)
49
+ \\6([^>]*>)
50
+ |
51
+ \s*((?!/>)($value))
52
+ ([^>]*>)
53
+ )
54
+ (((?!</($tag)>).)*)
55
+ (</($tag)>)
56
+ :ix";
57
+ } /* FeedWordPressHTML::tagWithAttributeRegex () */
58
+
59
+ function tagWithAttributeMatch ($matches) {
60
+ for ($i = 0; $i <= 21; $i++) :
61
+ if (!isset($matches[$i])) :
62
+ $matches[$i] = '';
63
+ endif;
64
+ endfor;
65
+
66
+ $suffix = $matches[16].$matches[13];
67
+ $value = $matches[14].$matches[7];
68
+
69
+ return array(
70
+ "full" => $matches[0],
71
+ "tag" => $matches[3],
72
+ "attribute" => $matches[4],
73
+ "value" => $value,
74
+ "quote" => $matches[6],
75
+ "prefix" => $matches[1].$matches[6],
76
+ "suffix" => $matches[6].$suffix,
77
+ "before_attribute" => $matches[2],
78
+ "after_attribute" => $suffix,
79
+ "open_tag" => $matches[1].$matches[6].$value.$matches[6].$suffix,
80
+ "content" => $matches[17],
81
+ "close_tag" => $matches[20],
82
+ );
83
+
84
+ } /* FeedWordPressHTML::tagWithAttributeMatch () */
85
  } /* class FeedWordPressHTML */
86
 
feedwordpresssyndicationpage.class.php ADDED
@@ -0,0 +1,1143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once(dirname(__FILE__) . '/admin-ui.php');
3
+ require_once(dirname(__FILE__) . '/feedfinder.class.php');
4
+
5
+ ################################################################################
6
+ ## ADMIN MENU ADD-ONS: implement Dashboard management pages ####################
7
+ ################################################################################
8
+
9
+ define('FWP_UPDATE_CHECKED', 'Update Checked');
10
+ define('FWP_UNSUB_CHECKED', 'Unsubscribe');
11
+ define('FWP_DELETE_CHECKED', 'Delete');
12
+ define('FWP_RESUB_CHECKED', 'Re-subscribe');
13
+ define('FWP_SYNDICATE_NEW', 'Add →');
14
+ define('FWP_UNSUB_FULL', 'Unsubscribe from selected feeds →');
15
+ define('FWP_CANCEL_BUTTON', '× Cancel');
16
+ define('FWP_CHECK_FOR_UPDATES', 'Update');
17
+
18
+ class FeedWordPressSyndicationPage extends FeedWordPressAdminPage {
19
+ function FeedWordPressSyndicationPage ($filename = NULL) {
20
+ FeedWordPressAdminPage::FeedWordPressAdminPage('feedwordpresssyndication', /*link=*/ NULL);
21
+
22
+ // No over-arching form element
23
+ $this->dispatch = NULL;
24
+ if (is_null($filename)) :
25
+ $this->filename = __FILE__;
26
+ else :
27
+ $this->filename = $filename;
28
+ endif;
29
+ } /* FeedWordPressSyndicationPage constructor */
30
+
31
+ function has_link () { return false; }
32
+
33
+ var $_sources = NULL;
34
+
35
+ function sources ($visibility = 'Y') {
36
+ if (is_null($this->_sources)) :
37
+ $links = FeedWordPress::syndicated_links(array("hide_invisible" => false));
38
+ $this->_sources = array("Y" => array(), "N" => array());
39
+ foreach ($links as $link) :
40
+ $this->_sources[$link->link_visible][] = $link;
41
+ endforeach;
42
+ endif;
43
+ $ret = (
44
+ array_key_exists($visibility, $this->_sources)
45
+ ? $this->_sources[$visibility]
46
+ : $this->_sources
47
+ );
48
+ return $ret;
49
+ } /* FeedWordPressSyndicationPage::sources() */
50
+
51
+ function visibility_toggle () {
52
+ $sources = $this->sources('*');
53
+
54
+ $defaultVisibility = 'Y';
55
+ if ((count($this->sources('N')) > 0)
56
+ and (count($this->sources('Y'))==0)) :
57
+ $defaultVisibility = 'N';
58
+ endif;
59
+
60
+ $visibility = (
61
+ isset($_REQUEST['visibility'])
62
+ ? $_REQUEST['visibility']
63
+ : $defaultVisibility
64
+ );
65
+
66
+ return $visibility;
67
+ } /* FeedWordPressSyndicationPage::visibility_toggle() */
68
+
69
+ function show_inactive () {
70
+ return ($this->visibility_toggle() == 'N');
71
+ }
72
+
73
+ function updates_requested () {
74
+ global $wpdb;
75
+
76
+ if (isset($_POST['update']) or isset($_POST['action']) or isset($_POST['update_uri'])) :
77
+ // Only do things with side-effects for HTTP POST or command line
78
+ $fwp_update_invoke = 'post';
79
+ else :
80
+ $fwp_update_invoke = 'get';
81
+ endif;
82
+
83
+ $update_set = array();
84
+ if ($fwp_update_invoke != 'get') :
85
+ if (isset($_POST['link_ids']) and is_array($_POST['link_ids']) and ($_POST['action']==FWP_UPDATE_CHECKED)) :
86
+ $targets = $wpdb->get_results("
87
+ SELECT * FROM $wpdb->links
88
+ WHERE link_id IN (".implode(",",$_POST['link_ids']).")
89
+ ");
90
+ if (is_array($targets)) :
91
+ foreach ($targets as $target) :
92
+ $update_set[] = $target->link_rss;
93
+ endforeach;
94
+ else : // This should never happen
95
+ FeedWordPress::critical_bug('fwp_syndication_manage_page::targets', $targets, __LINE__);
96
+ endif;
97
+ elseif (isset($_POST['update_uri'])) :
98
+ $targets = $_POST['update_uri'];
99
+ if (!is_array($targets)) :
100
+ $targets = array($targets);
101
+ endif;
102
+ $update_set = $targets;
103
+ endif;
104
+ endif;
105
+ return $update_set;
106
+ }
107
+
108
+ function accept_multiadd () {
109
+ global $fwp_post;
110
+
111
+ if (isset($fwp_post['cancel']) and $fwp_post['cancel']==__(FWP_CANCEL_BUTTON)) :
112
+ return true; // Continue ....
113
+ endif;
114
+
115
+ // If this is a POST, validate source and user credentials
116
+ FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_feeds', /*capability=*/ 'manage_links');
117
+
118
+ $in = (isset($fwp_post['multilookup']) ? $fwp_post['multilookup'] : '')
119
+ .(isset($fwp_post['opml_lookup']) ? $fwp_post['opml_lookup'] : '');
120
+ if (isset($fwp_post['confirm']) and $fwp_post['confirm']=='multiadd') :
121
+ $chex = $fwp_post['multilookup'];
122
+ $added = array(); $errors = array();
123
+ foreach ($chex as $feed) :
124
+ if (isset($feed['add']) and $feed['add']=='yes') :
125
+ // Then, add in the URL.
126
+ $link_id = FeedWordPress::syndicate_link(
127
+ $feed['title'],
128
+ $feed['link'],
129
+ $feed['url']
130
+ );
131
+ if ($link_id and !is_wp_error($link_id)):
132
+ $added[] = $link_id;
133
+ else :
134
+ $errors[] = array($feed['url'], $link_id);
135
+ endif;
136
+ endif;
137
+ endforeach;
138
+
139
+ print "<div class='updated'>\n";
140
+ print "<p>Added ".count($added)." new syndicated sources.</p>";
141
+ if (count($errors) > 0) :
142
+ print "<p>FeedWordPress encountered errors trying to add the following sources:</p>
143
+ <ul>\n";
144
+ foreach ($errors as $err) :
145
+ $url = $err[0];
146
+ $short = esc_html(feedwordpress_display_url($url));
147
+ $url = esc_html($url);
148
+ $wp = $err[1];
149
+ if (is_wp_error($err[1])) :
150
+ $error = $err[1];
151
+ $mesg = " (<code>".$error->get_error_messages()."</code>)";
152
+ else :
153
+ $mesg = '';
154
+ endif;
155
+ print "<li><a href='$url'>$short</a>$mesg</li>\n";
156
+ endforeach;
157
+ print "</ul>\n";
158
+ endif;
159
+ print "</div>\n";
160
+
161
+ elseif (is_array($in) or strlen($in) > 0) :
162
+ add_meta_box(
163
+ /*id=*/ 'feedwordpress_multiadd_box',
164
+ /*title=*/ __('Add Feeds'),
165
+ /*callback=*/ array($this, 'multiadd_box'),
166
+ /*page=*/ $this->meta_box_context(),
167
+ /*context =*/ $this->meta_box_context()
168
+ );
169
+ endif;
170
+ return true; // Continue...
171
+ }
172
+
173
+ function display_multiadd_line ($line) {
174
+ $short_feed = esc_html(feedwordpress_display_url($line['feed']));
175
+ $feed = esc_html($line['feed']);
176
+ $link = esc_html($line['link']);
177
+ $title = esc_html($line['title']);
178
+ $checked = $line['checked'];
179
+ $i = esc_html($line['i']);
180
+
181
+ print "<li><label><input type='checkbox' name='multilookup[$i][add]' value='yes' $checked />
182
+ $title</label> &middot; <a href='$feed'>$short_feed</a>";
183
+
184
+ if (isset($line['extra'])) :
185
+ print " &middot; ".esc_html($line['extra']);
186
+ endif;
187
+
188
+ print "<input type='hidden' name='multilookup[$i][url]' value='$feed' />
189
+ <input type='hidden' name='multilookup[$i][link]' value='$link' />
190
+ <input type='hidden' name='multilookup[$i][title]' value='$title' />
191
+ </li>\n";
192
+
193
+ flush();
194
+ }
195
+
196
+ function multiadd_box ($page, $box = NULL) {
197
+ global $fwp_post;
198
+
199
+ $localData = NULL;
200
+
201
+ if (isset($_FILES['opml_upload']['name']) and
202
+ (strlen($_FILES['opml_upload']['name']) > 0)) :
203
+ $in = 'tag:localhost';
204
+ $localData = file_get_contents($_FILES['opml_upload']['tmp_name']);
205
+ $merge_all = true;
206
+ elseif (isset($fwp_post['multilookup'])) :
207
+ $in = $fwp_post['multilookup'];
208
+ $merge_all = false;
209
+ elseif (isset($fwp_post['opml_lookup'])) :
210
+ $in = $fwp_post['opml_lookup'];
211
+ $merge_all = true;
212
+ else :
213
+ $in = '';
214
+ $merge_all = false;
215
+ endif;
216
+
217
+ if (strlen($in) > 0) :
218
+ $lines = preg_split(
219
+ "/\s+/",
220
+ $in,
221
+ /*no limit soldier*/ -1,
222
+ PREG_SPLIT_NO_EMPTY
223
+ );
224
+
225
+ $i = 0;
226
+ ?>
227
+ <form id="multiadd-form" action="<?php print $this->form_action(); ?>" method="post">
228
+ <div><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?>
229
+ <input type="hidden" name="multiadd" value="<?php print FWP_SYNDICATE_NEW; ?>" />
230
+ <input type="hidden" name="confirm" value="multiadd" />
231
+
232
+ <input type="hidden" name="multiadd" value="<?php print FWP_SYNDICATE_NEW; ?>" />
233
+ <input type="hidden" name="confirm" value="multiadd" /></div>
234
+
235
+ <div id="multiadd-status">
236
+ <p><img src="<?php print esc_url ( admin_url( 'images/wpspin_light.gif' ) ); ?>" alt="" />
237
+ Looking up feed information...</p>
238
+ </div>
239
+
240
+ <div id="multiadd-buttons">
241
+ <input type="submit" class="button" name="cancel" value="<?php _e(FWP_CANCEL_BUTTON); ?>" />
242
+ <input type="submit" class="button-primary" value="<?php print _e('Subscribe to selected sources →'); ?>" />
243
+ </div>
244
+
245
+ <p><?php _e('Here are the feeds that FeedWordPress has discovered from the addresses that you provided. To opt out of a subscription, unmark the checkbox next to the feed.'); ?></p>
246
+
247
+ <?php
248
+ print "<ul id=\"multiadd-list\">\n"; flush();
249
+ foreach ($lines as $line) :
250
+ $url = trim($line);
251
+ if (strlen($url) > 0) :
252
+ // First, use FeedFinder to check the URL.
253
+ if (is_null($localData)) :
254
+ $finder = new FeedFinder($url, /*verify=*/ false, /*fallbacks=*/ 1);
255
+ else :
256
+ $finder = new FeedFinder('tag:localhost', /*verify=*/ false, /*fallbacks=*/ 1);
257
+ $finder->upload_data($localData);
258
+ endif;
259
+
260
+ $feeds = array_values(
261
+ array_unique(
262
+ $finder->find()
263
+ )
264
+ );
265
+
266
+ $found = false;
267
+ if (count($feeds) > 0) :
268
+ foreach ($feeds as $feed) :
269
+ $pie = FeedWordPress::fetch($feed);
270
+ if (!is_wp_error($pie)) :
271
+ $found = true;
272
+
273
+ $short_feed = esc_html(feedwordpress_display_url($feed));
274
+ $feed = esc_html($feed);
275
+ $title = esc_html($pie->get_title());
276
+ $checked = ' checked="checked"';
277
+ $link = esc_html($pie->get_link());
278
+
279
+ $this->display_multiadd_line(array(
280
+ 'feed' => $feed,
281
+ 'title' => $pie->get_title(),
282
+ 'link' => $pie->get_link(),
283
+ 'checked' => ' checked="checked"',
284
+ 'i' => $i,
285
+ ));
286
+
287
+ $i++; // Increment field counter
288
+
289
+ if (!$merge_all) : // Break out after first find
290
+ break;
291
+ endif;
292
+ endif;
293
+ endforeach;
294
+ endif;
295
+
296
+ if (!$found) :
297
+ $this->display_multiadd_line(array(
298
+ 'feed' => $url,
299
+ 'title' => feedwordpress_display_url($url),
300
+ 'extra' => " [FeedWordPress couldn't detect any feeds for this URL.]",
301
+ 'link' => NULL,
302
+ 'checked' => '',
303
+ 'i' => $i,
304
+ ));
305
+ $i++; // Increment field counter
306
+ endif;
307
+ endif;
308
+ endforeach;
309
+ print "</ul>\n";
310
+ ?>
311
+ </form>
312
+
313
+ <script type="text/javascript">
314
+ jQuery(document).ready( function () {
315
+ // Hide it now that we're done.
316
+ jQuery('#multiadd-status').fadeOut(500 /*ms*/);
317
+ } );
318
+ </script>
319
+ <?php
320
+ endif;
321
+
322
+ $this->_sources = NULL; // Force reload of sources list
323
+ return true; // Continue
324
+ }
325
+
326
+ function display () {
327
+ global $wpdb;
328
+ global $fwp_post;
329
+
330
+ if (FeedWordPress::needs_upgrade()) :
331
+ fwp_upgrade_page();
332
+ return;
333
+ endif;
334
+
335
+ ?>
336
+ <?php
337
+ $cont = true;
338
+ $dispatcher = array(
339
+ "feedfinder" => 'fwp_feedfinder_page',
340
+ FWP_SYNDICATE_NEW => 'fwp_feedfinder_page',
341
+ "switchfeed" => 'fwp_switchfeed_page',
342
+ FWP_UNSUB_CHECKED => 'multidelete_page',
343
+ FWP_DELETE_CHECKED => 'multidelete_page',
344
+ 'Unsubscribe' => 'multidelete_page',
345
+ FWP_RESUB_CHECKED => 'multiundelete_page',
346
+ );
347
+ if (isset($_REQUEST['action']) and isset($dispatcher[$_REQUEST['action']])) :
348
+ $method = $dispatcher[$_REQUEST['action']];
349
+ if (method_exists($this, $method)) :
350
+ $cont = $this->{$method}();
351
+ else :
352
+ $cont = call_user_func($method);
353
+ endif;
354
+ elseif (isset($fwp_post['multiadd']) and $fwp_post['multiadd']==FWP_SYNDICATE_NEW) :
355
+ $cont = $this->accept_multiadd($fwp_post);
356
+ endif;
357
+
358
+ if ($cont):
359
+ $links = $this->sources('Y');
360
+ $potential_updates = (!$this->show_inactive() and (count($this->sources('Y')) > 0));
361
+
362
+ $this->open_sheet('Syndicated Sites');
363
+ ?>
364
+ <div id="post-body">
365
+ <?php
366
+ if ($potential_updates
367
+ or (count($this->updates_requested()) > 0)) :
368
+ add_meta_box(
369
+ /*id=*/ 'feedwordpress_update_box',
370
+ /*title=*/ __('Update feeds now'),
371
+ /*callback=*/ 'fwp_syndication_manage_page_update_box',
372
+ /*page=*/ $this->meta_box_context(),
373
+ /*context =*/ $this->meta_box_context()
374
+ );
375
+ endif;
376
+ add_meta_box(
377
+ /*id=*/ 'feedwordpress_feeds_box',
378
+ /*title=*/ __('Syndicated sources'),
379
+ /*callback=*/ array(&$this, 'syndicated_sources_box'),
380
+ /*page=*/ $this->meta_box_context(),
381
+ /*context =*/ $this->meta_box_context()
382
+ );
383
+
384
+ do_action('feedwordpress_admin_page_syndication_meta_boxes', $this);
385
+ ?>
386
+ <div class="metabox-holder">
387
+ <?php
388
+ fwp_do_meta_boxes($this->meta_box_context(), $this->meta_box_context(), $this);
389
+ ?>
390
+ </div> <!-- class="metabox-holder" -->
391
+ </div> <!-- id="post-body" -->
392
+
393
+ <?php $this->close_sheet(/*dispatch=*/ NULL); ?>
394
+
395
+ <div style="display: none">
396
+ <div id="tags-input"></div> <!-- avoid JS error from WP 2.5 bug -->
397
+ </div>
398
+ <?php
399
+ endif;
400
+ } /* FeedWordPressSyndicationPage::display () */
401
+
402
+ function dashboard_box ($page, $box = NULL) {
403
+ global $fwp_path;
404
+
405
+ $links = FeedWordPress::syndicated_links(array("hide_invisible" => false));
406
+ $sources = $this->sources('*');
407
+
408
+ $visibility = 'Y';
409
+ $hrefPrefix = $this->form_action();
410
+ $activeHref = $hrefPrefix.'&visibility=Y';
411
+ $inactiveHref = $hrefPrefix.'&visibility=N';
412
+
413
+ $lastUpdate = get_option('feedwordpress_last_update_all', NULL);
414
+ $automatic_updates = get_option('feedwordpress_automatic_updates', NULL);
415
+
416
+ if ('init'==$automatic_updates) :
417
+ $update_setting = 'automatically before page loads';
418
+ elseif ('shutdown'==$automatic_updates) :
419
+ $update_setting = 'automatically after page loads';
420
+ else :
421
+ $update_setting = 'using a cron job or manual check-ins';
422
+ endif;
423
+
424
+ // Hey ho, let's go...
425
+ ?>
426
+ <p class="info" style="margin-bottom: 0px; border-bottom: 1px dotted black;">Managed by <a href="http://feedwordpress.radgeek.com/">FeedWordPress</a>
427
+ <?php print FEEDWORDPRESS_VERSION; ?>.</p>
428
+ <?php if (FEEDWORDPRESS_BLEG) : ?>
429
+ <div style="float: left; background: white; margin-top: 5px; margin-right: 5px;"><a href="<?php print $this->form_action(); ?>"><img src="<?php print esc_html(WP_PLUGIN_URL.'/'.$GLOBALS['fwp_path'].'/feedwordpress.png'); ?>" alt="" /></a></div>
430
+ <p class="info" style="margin-top: 0px; font-style: italic; font-size: 75%; color: #666;">If you find this tool useful for your daily work, you can
431
+ contribute to ongoing support and development with
432
+ <a href="http://feedwordpress.radgeek.com/donate/">a modest donation</a>.</p>
433
+ <br style="clear: left;" />
434
+ <?php endif; ?>
435
+
436
+ <div class="feedwordpress-actions">
437
+ <h4>Updates</h4>
438
+ <ul class="options">
439
+ <li><strong>Scheduled:</strong> <?php print $update_setting; ?>
440
+ (<a href="<?php print $this->form_action('feeds-page.php'); ?>">change setting</a>)</li>
441
+
442
+ <li><?php if (!is_null($lastUpdate)) : ?>
443
+ <strong>Last checked:</strong> <?php print fwp_time_elapsed($lastUpdate); ?>
444
+ <?php else : ?>
445
+ <strong>Last checked:</strong> none yet
446
+ <?php endif; ?> </li>
447
+
448
+ </ul>
449
+ </div>
450
+
451
+ <div class="feedwordpress-stats">
452
+ <h4>Subscriptions</h4>
453
+ <table>
454
+ <tbody>
455
+ <tr class="first">
456
+ <td class="first b b-active"><a href="<?php print esc_html($activeHref); ?>"><?php print count($sources['Y']); ?></a></td>
457
+ <td class="t active"><a href="<?php print esc_html($activeHref); ?>">Active</a></td>
458
+ </tr>
459
+
460
+ <tr>
461
+ <td class="b b-inactive"><a href="<?php print esc_html($inactiveHref); ?>"><?php print count($sources['N']); ?></a></td>
462
+ <td class="t inactive"><a href="<?php print esc_html($inactiveHref); ?>">Inactive</a></td>
463
+ </tr>
464
+ </table>
465
+ </div>
466
+
467
+ <div id="add-single-uri">
468
+ <?php if (count($sources['Y']) > 0) : ?>
469
+ <form id="check-for-updates" action="<?php print $this->form_action(); ?>" method="POST">
470
+ <div class="container"><input type="submit" class="button-primary" name"update" value="<?php print FWP_CHECK_FOR_UPDATES; ?>" />
471
+ <?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?>
472
+ <input type="hidden" name="update_uri" value="*" /></div>
473
+ </form>
474
+ <?php endif; ?>
475
+
476
+ <form id="syndicated-links" action="<?php print $hrefPrefix; ?>&amp;visibility=<?php print $visibility; ?>" method="post">
477
+ <div class="container"><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?>
478
+ <label for="add-uri">Add:
479
+ <input type="text" name="lookup" id="add-uri" placeholder="Source URL"
480
+ value="Source URL" style="width: 55%;" /></label>
481
+
482
+ <?php FeedWordPressSettingsUI::magic_input_tip_js('add-uri'); ?>
483
+
484
+ <input style="vertical-align: middle;" type="image" src="<?php print WP_PLUGIN_URL.'/'.$fwp_path; ?>/plus.png" alt="<?php print FWP_SYNDICATE_NEW; ?>" name="action" value="<?php print FWP_SYNDICATE_NEW; ?>" /></div>
485
+ </form>
486
+ </div> <!-- id="add-single-uri" -->
487
+
488
+ <br style="clear: both;" />
489
+
490
+ <?php
491
+ } /* FeedWordPressSyndicationPage::dashboard_box () */
492
+
493
+ function syndicated_sources_box ($page, $box = NULL) {
494
+ global $fwp_path;
495
+
496
+ $links = FeedWordPress::syndicated_links(array("hide_invisible" => false));
497
+ $sources = $this->sources('*');
498
+
499
+ $visibility = $this->visibility_toggle();
500
+ $showInactive = $this->show_inactive();
501
+
502
+ $hrefPrefix = $this->form_action();
503
+ ?>
504
+ <div><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?></div>
505
+ <div class="tablenav">
506
+
507
+ <div id="add-multiple-uri" class="hide-if-js">
508
+ <form action="<?php print $hrefPrefix; ?>&amp;visibility=<?php print $visibility; ?>" method="post">
509
+ <div><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?></div>
510
+ <h4>Add Multiple Sources</h4>
511
+ <div>Enter one feed or website URL per line. If a URL links to a website which provides multiple feeds, FeedWordPress will use the first one listed.</div>
512
+ <div><textarea name="multilookup" rows="8" cols="60"
513
+ style="vertical-align: top"></textarea></div>
514
+ <div style="border-top: 1px dotted black; padding-top: 10px">
515
+ <div class="alignright"><input type="submit" class="button-primary" name="multiadd" value="<?php print FWP_SYNDICATE_NEW; ?>" /></div>
516
+ <div class="alignleft"><input type="button" class="button-secondary" name="action" value="<?php print FWP_CANCEL_BUTTON; ?>" id="turn-off-multiple-sources" /></div>
517
+ </div>
518
+ </form>
519
+ </div> <!-- id="add-multiple-uri" -->
520
+
521
+ <div id="upload-opml" style="float: right" class="hide-if-js">
522
+ <h4>Import source list</h4>
523
+ <p>You can import a list of sources in OPML format, either by providing
524
+ a URL for the OPML document, or by uploading a copy from your
525
+ computer.</p>
526
+
527
+ <form enctype="multipart/form-data" action="<?php print $hrefPrefix; ?>&amp;visibility=<?php print $visibility; ?>" method="post">
528
+ <div><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?><input type="hidden" name="MAX_FILE_SIZE" value="100000" /></div>
529
+ <div style="clear: both"><label for="opml-lookup" style="float: left; width: 8.0em; margin-top: 5px;">From URL:</label> <input type="text" id="opml-lookup" name="opml_lookup" value="OPML document" /></div>
530
+ <div style="clear: both"><label for="opml-upload" style="float: left; width: 8.0em; margin-top: 5px;">From file:</label> <input type="file" id="opml-upload" name="opml_upload" /></div>
531
+
532
+ <div style="border-top: 1px dotted black; padding-top: 10px">
533
+ <div class="alignright"><input type="submit" class="button-primary" name="action" value="<?php print FWP_SYNDICATE_NEW; ?>" /></div>
534
+ <div class="alignleft"><input type="button" class="button-secondary" name="action" value="<?php print FWP_CANCEL_BUTTON; ?>" id="turn-off-opml-upload" /></div>
535
+ </div>
536
+ </form>
537
+ </div> <!-- id="upload-opml" -->
538
+
539
+ <div id="add-single-uri" class="alignright">
540
+ <form id="syndicated-links" action="<?php print $hrefPrefix; ?>&amp;visibility=<?php print $visibility; ?>" method="post">
541
+ <div><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?></div>
542
+ <ul class="subsubsub">
543
+ <li><label for="add-uri">New source:</label>
544
+ <input type="text" name="lookup" id="add-uri" value="Website or feed URI" />
545
+
546
+ <?php FeedWordPressSettingsUI::magic_input_tip_js('add-uri'); FeedWordPressSettingsUI::magic_input_tip_js('opml-lookup'); ?>
547
+
548
+ <input type="hidden" name="action" value="feedfinder" />
549
+ <input type="submit" class="button-secondary" name="action" value="<?php print FWP_SYNDICATE_NEW; ?>" />
550
+ <div style="text-align: right; margin-right: 2.0em"><a id="turn-on-multiple-sources" href="#add-multiple-uri"><img style="vertical-align: middle" src="<?php print WP_PLUGIN_URL.'/'.$fwp_path; ?>/down.png" alt="" /> add multiple</a>
551
+ <span class="screen-reader-text"> or </span>
552
+ <a id="turn-on-opml-upload" href="#upload-opml"><img src="<?php print WP_PLUGIN_URL.'/'.$fwp_path; ?>/plus.png" alt="" style="vertical-align: middle" /> import source list</a></div>
553
+ </li>
554
+ </ul>
555
+ </form>
556
+ </div> <!-- class="alignright" -->
557
+
558
+ <div class="alignleft">
559
+ <?php
560
+ if (count($sources[$visibility]) > 0) :
561
+ fwp_syndication_manage_page_links_subsubsub($sources, $showInactive);
562
+ endif;
563
+ ?>
564
+ </div> <!-- class="alignleft" -->
565
+
566
+ </div> <!-- class="tablenav" -->
567
+
568
+ <form id="syndicated-links" action="<?php print $hrefPrefix; ?>&amp;visibility=<?php print $visibility; ?>" method="post">
569
+ <div><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?></div>
570
+
571
+ <?php if ($showInactive) : ?>
572
+ <div style="clear: right" class="alignright">
573
+ <p style="font-size: smaller; font-style: italic">FeedWordPress used to syndicate
574
+ posts from these sources, but you have unsubscribed from them.</p>
575
+ </div>
576
+ <?php
577
+ endif;
578
+ ?>
579
+
580
+ <?php if (count($sources[$visibility]) > 0) : ?>
581
+ <div style="clear: left" class="alignleft">
582
+ <?php if ($showInactive) : ?>
583
+ <input class="button-secondary" type="submit" name="action" value="<?php print FWP_RESUB_CHECKED; ?>" />
584
+ <input class="button-secondary" type="submit" name="action" value="<?php print FWP_DELETE_CHECKED; ?>" />
585
+ <?php else : ?>
586
+ <input class="button-secondary" type="submit" name="action" value="<?php print FWP_UPDATE_CHECKED; ?>" />
587
+ <input class="button-secondary delete" type="submit" name="action" value="<?php print FWP_UNSUB_CHECKED; ?>" />
588
+ <?php endif ; ?>
589
+ </div> <!-- class="alignleft" -->
590
+
591
+ <?php else : ?>
592
+ <?php fwp_syndication_manage_page_links_subsubsub($sources, $showInactive); ?>
593
+ <?php endif; ?>
594
+
595
+ <br class="clear" />
596
+
597
+ <?php
598
+ fwp_syndication_manage_page_links_table_rows($sources[$visibility], $this, $visibility);
599
+ ?>
600
+ </form>
601
+ <?php
602
+ } /* FeedWordPressSyndicationPage::syndicated_sources_box() */
603
+
604
+ function bleg_thanks ($page, $box = NULL) {
605
+ ?>
606
+ <div class="donation-thanks">
607
+ <h4>Thank you!</h4>
608
+ <p><strong>Thank you</strong> for your contribution to <a href="http://feedwordpress.radgeek.com/">FeedWordPress</a> development.
609
+ Your generous gifts make ongoing support and development for
610
+ FeedWordPress possible.</p>
611
+ <p>If you have any questions about FeedWordPress, or if there
612
+ is anything I can do to help make FeedWordPress more useful for
613
+ you, please <a href="http://feedwordpress.radgeek.com/contact">contact me</a>
614
+ and let me know what you're thinking about.</p>
615
+ <p class="signature">&#8212;<a href="http://radgeek.com/">Charles Johnson</a>, Developer, <a href="http://feedwordpress.radgeek.com/">FeedWordPress</a>.</p>
616
+ </div>
617
+ <?php
618
+ } /* FeedWordPressSyndicationPage::bleg_thanks () */
619
+
620
+ function bleg_box ($page, $box = NULL) {
621
+ ?>
622
+ <div class="donation-form">
623
+ <h4>Keep FeedWordPress improving</h4>
624
+ <form action="https://www.paypal.com/cgi-bin/webscr" accept-charset="UTF-8" method="post"><div>
625
+ <p><a href="http://feedwordpress.radgeek.com/">FeedWordPress</a> makes syndication
626
+ simple and empowers you to stream content from all over the web into your
627
+ WordPress hub. That's got to be worth a few lattes. If you're finding FWP useful,
628
+ <a href="http://feedwordpress.radgeek.com/donate/">a modest gift</a>
629
+ is the best way to support steady progress on development, enhancements,
630
+ support, and documentation.</p>
631
+ <div class="donate">
632
+ <input type="hidden" name="business" value="commerce@radgeek.com" />
633
+ <input type="hidden" name="cmd" value="_xclick" />
634
+ <input type="hidden" name="item_name" value="FeedWordPress donation" />
635
+ <input type="hidden" name="no_shipping" value="1" />
636
+ <input type="hidden" name="return" value="<?php print admin_url('admin.php'); ?>?page=<?php print $GLOBALS['fwp_path'] ?>/<?php print basename($this->filename); ?>&amp;paid=yes" />
637
+ <input type="hidden" name="currency_code" value="USD" />
638
+ <input type="hidden" name="notify_url" value="http://feedwordpress.radgeek.com/ipn/donation" />
639
+ <input type="hidden" name="custom" value="1" />
640
+ <input type="image" name="submit" src="https://www.paypal.com/en_GB/i/btn/btn_donate_SM.gif" alt="Donate through PayPal" />
641
+ </div>
642
+ </div></form>
643
+
644
+ <p>You can make a gift online (or
645
+ <a href="http://feedwordpress.radgeek.com/donation">set up an automatic
646
+ regular donation</a>) using an existing PayPal account or any major credit card.</p>
647
+
648
+ <div class="sod-off">
649
+ <form style="text-align: center" action="<?php print $this->form_action(); ?>" method="POST"><div>
650
+ <input class="button" type="submit" name="maybe_later" value="Maybe Later" />
651
+ <input class="button" type="submit" name="go_away" value="Dismiss" />
652
+ </div></form>
653
+ </div>
654
+ </div> <!-- class="donation-form" -->
655
+ <?php
656
+ } /* FeedWordPressSyndicationPage::bleg_box () */
657
+
658
+ /**
659
+ * Override the default display of a save-settings button and replace
660
+ * it with nothing.
661
+ */
662
+ function interstitial () {
663
+ /* NOOP */
664
+ } /* FeedWordPressSyndicationPage::interstitial() */
665
+
666
+ function multidelete_page () {
667
+ global $wpdb;
668
+ global $fwp_post;
669
+
670
+ // If this is a POST, validate source and user credentials
671
+ FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_feeds', /*capability=*/ 'manage_links');
672
+
673
+ if (isset($fwp_post['submit']) and $fwp_post['submit']==FWP_CANCEL_BUTTON) :
674
+ return true; // Continue without further ado.
675
+ endif;
676
+
677
+ $link_ids = (isset($_REQUEST['link_ids']) ? $_REQUEST['link_ids'] : array());
678
+ if (isset($_REQUEST['link_id'])) : array_push($link_ids, $_REQUEST['link_id']); endif;
679
+
680
+ if (isset($GLOBALS['fwp_post']['confirm']) and $GLOBALS['fwp_post']['confirm']=='Delete'):
681
+ if (isset($GLOBALS['fwp_post']['link_action']) and is_array($GLOBALS['fwp_post']['link_action'])) :
682
+ $actions = $GLOBALS['fwp_post']['link_action'];
683
+ else :
684
+ $actions = array();
685
+ endif;
686
+
687
+ $do_it = array(
688
+ 'hide' => array(),
689
+ 'nuke' => array(),
690
+ 'delete' => array(),
691
+ );
692
+
693
+ foreach ($actions as $link_id => $what) :
694
+ $do_it[$what][] = $link_id;
695
+ endforeach;
696
+
697
+ $alter = array();
698
+ if (count($do_it['hide']) > 0) :
699
+ $hidem = "(".implode(', ', $do_it['hide']).")";
700
+ $alter[] = "
701
+ UPDATE $wpdb->links
702
+ SET link_visible = 'N'
703
+ WHERE link_id IN {$hidem}
704
+ ";
705
+ endif;
706
+
707
+ if (count($do_it['nuke']) > 0) :
708
+ $nukem = "(".implode(', ', $do_it['nuke']).")";
709
+
710
+ // Make a list of the items syndicated from this feed...
711
+ $post_ids = $wpdb->get_col("
712
+ SELECT post_id FROM $wpdb->postmeta
713
+ WHERE meta_key = 'syndication_feed_id'
714
+ AND meta_value IN {$nukem}
715
+ ");
716
+
717
+ // ... and kill them all
718
+ if (count($post_ids) > 0) :
719
+ foreach ($post_ids as $post_id) :
720
+ if (FeedWordPressCompatibility::test_version(FWP_SCHEMA_29)) :
721
+ // Force scrubbing of deleted post
722
+ // rather than sending to Trashcan
723
+ wp_delete_post(
724
+ /*postid=*/ $post_id,
725
+ /*force_delete=*/ true
726
+ );
727
+ else :
728
+ wp_delete_post($post_id);
729
+ endif;
730
+ endforeach;
731
+ endif;
732
+
733
+ $alter[] = "
734
+ DELETE FROM $wpdb->links
735
+ WHERE link_id IN {$nukem}
736
+ ";
737
+ endif;
738
+
739
+ if (count($do_it['delete']) > 0) :
740
+ $deletem = "(".implode(', ', $do_it['delete']).")";
741
+
742
+ // Make the items syndicated from this feed appear to be locally-authored
743
+ $alter[] = "
744
+ DELETE FROM $wpdb->postmeta
745
+ WHERE meta_key = 'syndication_feed_id'
746
+ AND meta_value IN {$deletem}
747
+ ";
748
+
749
+ // ... and delete the links themselves.
750
+ $alter[] = "
751
+ DELETE FROM $wpdb->links
752
+ WHERE link_id IN {$deletem}
753
+ ";
754
+ endif;
755
+
756
+ $errs = array(); $success = array ();
757
+ foreach ($alter as $sql) :
758
+ $result = $wpdb->query($sql);
759
+ if (!$result):
760
+ $errs[] = mysql_error();
761
+ endif;
762
+ endforeach;
763
+
764
+ if (count($alter) > 0) :
765
+ echo "<div class=\"updated\">\n";
766
+ if (count($errs) > 0) :
767
+ echo "There were some problems processing your ";
768
+ echo "unsubscribe request. [SQL: ".implode('; ', $errs)."]";
769
+ else :
770
+ echo "Your unsubscribe request(s) have been processed.";
771
+ endif;
772
+ echo "</div>\n";
773
+ endif;
774
+
775
+ return true; // Continue on to Syndicated Sites listing
776
+ else :
777
+ $targets = $wpdb->get_results("
778
+ SELECT * FROM $wpdb->links
779
+ WHERE link_id IN (".implode(",",$link_ids).")
780
+ ");
781
+ ?>
782
+ <form action="<?php print $this->form_action(); ?>" method="post">
783
+ <div class="wrap">
784
+ <?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?>
785
+ <input type="hidden" name="action" value="Unsubscribe" />
786
+ <input type="hidden" name="confirm" value="Delete" />
787
+
788
+ <h2>Unsubscribe from Syndicated Links:</h2>
789
+ <?php foreach ($targets as $link) :
790
+ $subscribed = ('Y' == strtoupper($link->link_visible));
791
+ $link_url = esc_html($link->link_url);
792
+ $link_name = esc_html($link->link_name);
793
+ $link_description = esc_html($link->link_description);
794
+ $link_rss = esc_html($link->link_rss);
795
+ ?>
796
+ <fieldset>
797
+ <legend><?php echo $link_name; ?></legend>
798
+ <table class="editform" width="100%" cellspacing="2" cellpadding="5">
799
+ <tr><th scope="row" width="20%"><?php _e('Feed URI:') ?></th>
800
+ <td width="80%"><a href="<?php echo $link_rss; ?>"><?php echo $link_rss; ?></a></td></tr>
801
+ <tr><th scope="row" width="20%"><?php _e('Short description:') ?></th>
802
+ <td width="80%"><?php echo $link_description; ?></span></td></tr>
803
+ <tr><th width="20%" scope="row"><?php _e('Homepage:') ?></th>
804
+ <td width="80%"><a href="<?php echo $link_url; ?>"><?php echo $link_url; ?></a></td></tr>
805
+ <tr style="vertical-align:top"><th width="20%" scope="row">Subscription <?php _e('Options') ?>:</th>
806
+ <td width="80%"><ul style="margin:0; padding: 0; list-style: none">
807
+ <?php if ($subscribed) : ?>
808
+ <li><input type="radio" id="hide-<?php echo $link->link_id; ?>"
809
+ name="link_action[<?php echo $link->link_id; ?>]" value="hide" checked="checked" />
810
+ <label for="hide-<?php echo $link->link_id; ?>">Turn off the subscription for this
811
+ syndicated link<br/><span style="font-size:smaller">(Keep the feed information
812
+ and all the posts from this feed in the database, but don't syndicate any
813
+ new posts from the feed.)</span></label></li>
814
+ <?php endif; ?>
815
+ <li><input type="radio" id="nuke-<?php echo $link->link_id; ?>"<?php if (!$subscribed) : ?> checked="checked"<?php endif; ?>
816
+ name="link_action[<?php echo $link->link_id; ?>]" value="nuke" />
817
+ <label for="nuke-<?php echo $link->link_id; ?>">Delete this syndicated link and all the
818
+ posts that were syndicated from it</label></li>
819
+ <li><input type="radio" id="delete-<?php echo $link->link_id; ?>"
820
+ name="link_action[<?php echo $link->link_id; ?>]" value="delete" />
821
+ <label for="delete-<?php echo $link->link_id; ?>">Delete this syndicated link, but
822
+ <em>keep</em> posts that were syndicated from it (as if they were authored
823
+ locally).</label></li>
824
+ <li><input type="radio" id="nothing-<?php echo $link->link_id; ?>"
825
+ name="link_action[<?php echo $link->link_id; ?>]" value="nothing" />
826
+ <label for="nothing-<?php echo $link->link_id; ?>">Keep this feed as it is. I changed
827
+ my mind.</label></li>
828
+ </ul>
829
+ </table>
830
+ </fieldset>
831
+ <?php endforeach; ?>
832
+
833
+ <div class="submit">
834
+ <input type="submit" name="submit" value="<?php _e(FWP_CANCEL_BUTTON); ?>" />
835
+ <input class="delete" type="submit" name="submit" value="<?php _e(FWP_UNSUB_FULL) ?>" />
836
+ </div>
837
+ </div>
838
+ <?php
839
+ return false; // Don't continue on to Syndicated Sites listing
840
+ endif;
841
+ } /* FeedWordPressSyndicationPage::multidelete_page() */
842
+
843
+ function multiundelete_page () {
844
+ global $wpdb;
845
+
846
+ // If this is a POST, validate source and user credentials
847
+ FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_feeds', /*capability=*/ 'manage_links');
848
+
849
+ $link_ids = (isset($_REQUEST['link_ids']) ? $_REQUEST['link_ids'] : array());
850
+ if (isset($_REQUEST['link_id'])) : array_push($link_ids, $_REQUEST['link_id']); endif;
851
+
852
+ if (isset($GLOBALS['fwp_post']['confirm']) and $GLOBALS['fwp_post']['confirm']=='Undelete'):
853
+ if (isset($GLOBALS['fwp_post']['link_action']) and is_array($GLOBALS['fwp_post']['link_action'])) :
854
+ $actions = $GLOBALS['fwp_post']['link_action'];
855
+ else :
856
+ $actions = array();
857
+ endif;
858
+
859
+ $do_it = array(
860
+ 'unhide' => array(),
861
+ );
862
+
863
+ foreach ($actions as $link_id => $what) :
864
+ $do_it[$what][] = $link_id;
865
+ endforeach;
866
+
867
+ $alter = array();
868
+ if (count($do_it['unhide']) > 0) :
869
+ $unhiddem = "(".implode(', ', $do_it['unhide']).")";
870
+ $alter[] = "
871
+ UPDATE $wpdb->links
872
+ SET link_visible = 'Y'
873
+ WHERE link_id IN {$unhiddem}
874
+ ";
875
+ endif;
876
+
877
+ $errs = array(); $success = array ();
878
+ foreach ($alter as $sql) :
879
+ $result = $wpdb->query($sql);
880
+ if (!$result):
881
+ $errs[] = mysql_error();
882
+ endif;
883
+ endforeach;
884
+
885
+ if (count($alter) > 0) :
886
+ echo "<div class=\"updated\">\n";
887
+ if (count($errs) > 0) :
888
+ echo "There were some problems processing your ";
889
+ echo "re-subscribe request. [SQL: ".implode('; ', $errs)."]";
890
+ else :
891
+ echo "Your re-subscribe request(s) have been processed.";
892
+ endif;
893
+ echo "</div>\n";
894
+ endif;
895
+
896
+ return true; // Continue on to Syndicated Sites listing
897
+ else :
898
+ $targets = $wpdb->get_results("
899
+ SELECT * FROM $wpdb->links
900
+ WHERE link_id IN (".implode(",",$link_ids).")
901
+ ");
902
+ ?>
903
+ <form action="<?php print $this->form_action(); ?>" method="post">
904
+ <div class="wrap">
905
+ <?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?>
906
+ <input type="hidden" name="action" value="<?php print FWP_RESUB_CHECKED; ?>" />
907
+ <input type="hidden" name="confirm" value="Undelete" />
908
+
909
+ <h2>Re-subscribe to Syndicated Links:</h2>
910
+ <?php
911
+ foreach ($targets as $link) :
912
+ $subscribed = ('Y' == strtoupper($link->link_visible));
913
+ $link_url = esc_html($link->link_url);
914
+ $link_name = esc_html($link->link_name);
915
+ $link_description = esc_html($link->link_description);
916
+ $link_rss = esc_html($link->link_rss);
917
+
918
+ if (!$subscribed) :
919
+ ?>
920
+ <fieldset>
921
+ <legend><?php echo $link_name; ?></legend>
922
+ <table class="editform" width="100%" cellspacing="2" cellpadding="5">
923
+ <tr><th scope="row" width="20%"><?php _e('Feed URI:') ?></th>
924
+ <td width="80%"><a href="<?php echo $link_rss; ?>"><?php echo $link_rss; ?></a></td></tr>
925
+ <tr><th scope="row" width="20%"><?php _e('Short description:') ?></th>
926
+ <td width="80%"><?php echo $link_description; ?></span></td></tr>
927
+ <tr><th width="20%" scope="row"><?php _e('Homepage:') ?></th>
928
+ <td width="80%"><a href="<?php echo $link_url; ?>"><?php echo $link_url; ?></a></td></tr>
929
+ <tr style="vertical-align:top"><th width="20%" scope="row">Subscription <?php _e('Options') ?>:</th>
930
+ <td width="80%"><ul style="margin:0; padding: 0; list-style: none">
931
+ <li><input type="radio" id="unhide-<?php echo $link->link_id; ?>"
932
+ name="link_action[<?php echo $link->link_id; ?>]" value="unhide" checked="checked" />
933
+ <label for="unhide-<?php echo $link->link_id; ?>">Turn back on the subscription
934
+ for this syndication source.</label></li>
935
+ <li><input type="radio" id="nothing-<?php echo $link->link_id; ?>"
936
+ name="link_action[<?php echo $link->link_id; ?>]" value="nothing" />
937
+ <label for="nothing-<?php echo $link->link_id; ?>">Leave this feed as it is.
938
+ I changed my mind.</label></li>
939
+ </ul>
940
+ </table>
941
+ </fieldset>
942
+ <?php
943
+ endif;
944
+ endforeach;
945
+ ?>
946
+
947
+ <div class="submit">
948
+ <input class="button-primary delete" type="submit" name="submit" value="<?php _e('Re-subscribe to selected feeds &raquo;') ?>" />
949
+ </div>
950
+ </div>
951
+ <?php
952
+ return false; // Don't continue on to Syndicated Sites listing
953
+ endif;
954
+ } /* FeedWordPressSyndicationPage::multiundelete_page() */
955
+
956
+
957
+
958
+ } /* class FeedWordPressSyndicationPage */
959
+
960
+ function fwp_dashboard_update_if_requested ($object) {
961
+ global $wpdb;
962
+
963
+ $update_set = $object->updates_requested();
964
+
965
+ if (count($update_set) > 0) :
966
+ shuffle($update_set); // randomize order for load balancing purposes...
967
+
968
+ $feedwordpress = new FeedWordPress;
969
+ add_action('feedwordpress_check_feed', 'update_feeds_mention');
970
+ add_action('feedwordpress_check_feed_complete', 'update_feeds_finish', 10, 3);
971
+
972
+ $crash_dt = (int) get_option('feedwordpress_update_time_limit');
973
+ if ($crash_dt > 0) :
974
+ $crash_ts = time() + $crash_dt;
975
+ else :
976
+ $crash_ts = NULL;
977
+ endif;
978
+
979
+ echo "<div class=\"update-results\">\n";
980
+ echo "<ul>\n";
981
+ $tdelta = NULL;
982
+ foreach ($update_set as $uri) :
983
+ if (!is_null($crash_ts) and (time() > $crash_ts)) :
984
+ echo "<li><p><strong>Further updates postponed:</strong> update time limit of ".$crash_dt." second".(($crash_dt==1)?"":"s")." exceeded.</p></li>";
985
+ break;
986
+ endif;
987
+
988
+ if ($uri == '*') : $uri = NULL; endif;
989
+ $delta = $feedwordpress->update($uri, $crash_ts);
990
+ if (!is_null($delta)) :
991
+ if (is_null($tdelta)) :
992
+ $tdelta = $delta;
993
+ else :
994
+ $tdelta['new'] += $delta['new'];
995
+ $tdelta['updated'] += $delta['updated'];
996
+ endif;
997
+ else :
998
+ echo "<li><p><strong>Error:</strong> There was a problem updating <a href=\"$uri\">$uri</a></p></li>\n";
999
+ endif;
1000
+ endforeach;
1001
+ echo "</ul>\n";
1002
+
1003
+ if (!is_null($tdelta)) :
1004
+ $mesg = array();
1005
+ if (isset($delta['new'])) : $mesg[] = ' '.$tdelta['new'].' new posts were syndicated'; endif;
1006
+ if (isset($delta['updated'])) : $mesg[] = ' '.$tdelta['updated'].' existing posts were updated'; endif;
1007
+ echo "<p>Update complete.".implode(' and', $mesg)."</p>";
1008
+ echo "\n"; flush();
1009
+ endif;
1010
+ echo "</div> <!-- class=\"updated\" -->\n";
1011
+ endif;
1012
+ }
1013
+
1014
+ define('FEEDWORDPRESS_BLEG_MAYBE_LATER_OFFSET', (60 /*sec/min*/ * 60 /*min/hour*/ * 24 /*hour/day*/ * 31 /*days*/));
1015
+ define('FEEDWORDPRESS_BLEG_ALREADY_PAID_OFFSET', (60 /*sec/min*/ * 60 /*min/hour*/ * 24 /*hour/day*/ * 183 /*days*/));
1016
+ function fwp_syndication_manage_page_update_box ($object = NULL, $box = NULL) {
1017
+ $bleg_box_hidden = null;
1018
+ if (isset($_POST['maybe_later'])) :
1019
+ $bleg_box_hidden = time() + FEEDWORDPRESS_BLEG_MAYBE_LATER_OFFSET;
1020
+ elseif (isset($_REQUEST['paid']) and $_REQUEST['paid']) :
1021
+ $bleg_box_hidden = time() + FEEDWORDPRESS_BLEG_ALREADY_PAID_OFFSET;
1022
+ elseif (isset($_POST['go_away'])) :
1023
+ $bleg_box_hidden = 'permanent';
1024
+ endif;
1025
+
1026
+ if (!is_null($bleg_box_hidden)) :
1027
+ update_option('feedwordpress_bleg_box_hidden', $bleg_box_hidden);
1028
+ else :
1029
+ $bleg_box_hidden = get_option('feedwordpress_bleg_box_hidden');
1030
+ endif;
1031
+ ?>
1032
+ <?php
1033
+ $bleg_box_ready = (FEEDWORDPRESS_BLEG and (
1034
+ !$bleg_box_hidden
1035
+ or (is_numeric($bleg_box_hidden) and $bleg_box_hidden < time())
1036
+ ));
1037
+
1038
+ if (isset($_REQUEST['paid']) and $_REQUEST['paid']) :
1039
+ $object->bleg_thanks($subject, $box);
1040
+ elseif ($bleg_box_ready) :
1041
+ $object->bleg_box($object, $box);
1042
+ endif;
1043
+ ?>
1044
+
1045
+ <form
1046
+ action="<?php print $object->form_action(); ?>"
1047
+ method="POST"
1048
+ class="update-form<?php if ($bleg_box_ready) : ?> with-donation<?php endif; ?>"
1049
+ >
1050
+ <div><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?></div>
1051
+ <p>Check currently scheduled feeds for new and updated posts.</p>
1052
+
1053
+ <?php
1054
+ fwp_dashboard_update_if_requested($object);
1055
+
1056
+ if (!get_option('feedwordpress_automatic_updates')) :
1057
+ ?>
1058
+ <p class="heads-up"><strong>Note:</strong> Automatic updates are currently turned
1059
+ <strong>off</strong>. New posts from your feeds will not be syndicated
1060
+ until you manually check for them here. You can turn on automatic
1061
+ updates under <a href="admin.php?page=<?php print $GLOBALS['fwp_path']; ?>/feeds-page.php">Feed &amp; Update Settings<a></a>.</p>
1062
+ <?php
1063
+ endif;
1064
+ ?>
1065
+
1066
+ <div class="submit"><?php if ($object->show_inactive()) : ?>
1067
+ <?php foreach ($object->updates_requested() as $req) : ?>
1068
+ <input type="hidden" name="update_uri[]" value="<?php print esc_html($req); ?>" />
1069
+ <?php endforeach; ?>
1070
+ <?php else : ?>
1071
+ <input type="hidden" name="update_uri" value="*" />
1072
+ <?php endif; ?>
1073
+ <input class="button-primary" type="submit" name="update" value="<?php _e(FWP_CHECK_FOR_UPDATES); ?>" /></div>
1074
+
1075
+ <br style="clear: both" />
1076
+ </form>
1077
+ <?php
1078
+ } /* function fwp_syndication_manage_page_update_box () */
1079
+
1080
+ function fwp_feedfinder_page () {
1081
+ global $post_source, $fwp_post, $syndicationPage;
1082
+
1083
+ if (isset($fwp_post['opml_lookup']) or isset($_FILES['opml_upload'])) :
1084
+ $syndicationPage->accept_multiadd();
1085
+ return true;
1086
+ else :
1087
+ $post_source = 'feedwordpress_feeds';
1088
+
1089
+ // With action=feedfinder, this goes directly to the feedfinder page
1090
+ include_once(dirname(__FILE__) . '/feeds-page.php');
1091
+ return false;
1092
+ endif;
1093
+ } /* function fwp_feedfinder_page () */
1094
+
1095
+ function fwp_switchfeed_page () {
1096
+ global $wpdb, $wp_db_version;
1097
+ global $fwp_post;
1098
+
1099
+ // If this is a POST, validate source and user credentials
1100
+ FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_switchfeed', /*capability=*/ 'manage_links');
1101
+
1102
+ $changed = false;
1103
+ if (!isset($fwp_post['Cancel'])):
1104
+ if (isset($fwp_post['save_link_id']) and ($fwp_post['save_link_id']=='*')) :
1105
+ $changed = true;
1106
+ $link_id = FeedWordPress::syndicate_link($fwp_post['feed_title'], $fwp_post['feed_link'], $fwp_post['feed']);
1107
+ if ($link_id):
1108
+ $existingLink = new SyndicatedLink($link_id);
1109
+ ?>
1110
+ <div class="updated"><p><a href="<?php print $fwp_post['feed_link']; ?>"><?php print esc_html($fwp_post['feed_title']); ?></a>
1111
+ has been added as a contributing site, using the feed at
1112
+ &lt;<a href="<?php print $fwp_post['feed']; ?>"><?php print esc_html($fwp_post['feed']); ?></a>&gt;.
1113
+ | <a href="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/feeds-page.php&amp;link_id=<?php print $link_id; ?>">Configure settings</a>.</p></div>
1114
+ <?php else: ?>
1115
+ <div class="updated"><p>There was a problem adding the feed. [SQL: <?php echo esc_html(mysql_error()); ?>]</p></div>
1116
+ <?php endif;
1117
+ elseif (isset($fwp_post['save_link_id'])):
1118
+ $existingLink = new SyndicatedLink($fwp_post['save_link_id']);
1119
+ $changed = $existingLink->set_uri($fwp_post['feed']);
1120
+
1121
+ if ($changed):
1122
+ $home = $existingLink->homepage(/*from feed=*/ false);
1123
+ $name = $existingLink->name(/*from feed=*/ false);
1124
+ ?>
1125
+ <div class="updated"><p>Feed for <a href="<?php echo esc_html($home); ?>"><?php echo esc_html($name); ?></a>
1126
+ updated to &lt;<a href="<?php echo esc_html($fwp_post['feed']); ?>"><?php echo esc_html($fwp_post['feed']); ?></a>&gt;.</p></div>
1127
+ <?php
1128
+ endif;
1129
+ endif;
1130
+ endif;
1131
+
1132
+ if (isset($existingLink)) :
1133
+ do_action('feedwordpress_admin_switchfeed', $fwp_post['feed'], $existingLink);
1134
+ endif;
1135
+
1136
+ if (!$changed) :
1137
+ ?>
1138
+ <div class="updated"><p>Nothing was changed.</p></div>
1139
+ <?php
1140
+ endif;
1141
+ return true; // Continue
1142
+ }
1143
+
performance-page.php CHANGED
@@ -43,7 +43,7 @@ class FeedWordPressPerformancePage extends FeedWordPressAdminPage {
43
  );
44
 
45
  foreach ($boxes_by_methods as $method => $title) :
46
- fwp_add_meta_box(
47
  /*id=*/ 'feedwordpress_'.$method,
48
  /*title=*/ $title,
49
  /*callback=*/ array('FeedWordPressPerformancePage', $method),
43
  );
44
 
45
  foreach ($boxes_by_methods as $method => $title) :
46
+ add_meta_box(
47
  /*id=*/ 'feedwordpress_'.$method,
48
  /*title=*/ $title,
49
  /*callback=*/ array('FeedWordPressPerformancePage', $method),
plus.png ADDED
Binary file
posts-page.php CHANGED
@@ -11,107 +11,115 @@ class FeedWordPressPostsPage extends FeedWordPressAdminPage {
11
  *
12
  * @param mixed $link An object of class {@link SyndicatedLink} if created for one feed's settings, NULL if created for global default settings
13
  */
14
- function FeedWordPressPostsPage ($link = NULL) {
 
 
 
 
15
  FeedWordPressAdminPage::FeedWordPressAdminPage('feedwordpresspostspage', $link);
16
- $this->dispatch = 'feedwordpress_posts_settings';
17
  $this->filename = __FILE__;
18
  $this->updatedPosts = new UpdatedPostsControl($this);
 
 
 
 
 
 
19
  } /* FeedWordPressPostsPage constructor */
20
 
21
- function accept_POST ($post) {
22
- global $wpdb;
23
-
24
- // User mashed a Save Changes button
25
- if (isset($post['save']) or isset($post['submit'])) :
26
- // custom post settings
27
- $custom_settings = $this->custom_post_settings();
28
 
29
- foreach ($post['notes'] as $mn) :
 
30
  $mn['key0'] = trim($mn['key0']);
31
- $mn['key1'] = trim($mn['key1']);
32
-
33
  if (strlen($mn['key0']) > 0) :
34
  unset($custom_settings[$mn['key0']]); // out with the old
35
  endif;
 
36
 
 
 
 
37
  if (($mn['action']=='update') and (strlen($mn['key1']) > 0)) :
38
  $custom_settings[$mn['key1']] = $mn['value']; // in with the new
39
  endif;
40
- endforeach;
41
-
42
- $this->updatedPosts->accept_POST($post);
43
- if ($this->for_feed_settings()) :
44
- $alter = array ();
45
-
46
- $this->link->settings['postmeta'] = serialize($custom_settings);
47
-
48
- if (isset($post['resolve_relative'])) :
49
- $this->link->settings['resolve relative'] = $post['resolve_relative'];
50
- endif;
51
- if (isset($post['munge_permalink'])) :
52
- $this->link->settings['munge permalink'] = $post['munge_permalink'];
53
- endif;
54
- if (isset($post['munge_comments_feed_links'])) :
55
- $this->link->settings['munge comments feed links'] = $post['munge_comments_feed_links'];
56
- endif;
57
 
58
- // Post status, comment status, ping status
59
- foreach (array('post', 'comment', 'ping') as $what) :
60
- $sfield = "feed_{$what}_status";
61
- if (isset($post[$sfield])) :
62
- if ($post[$sfield]=='site-default') :
63
- unset($this->link->settings["{$what} status"]);
64
- else :
65
- $this->link->settings["{$what} status"] = $post[$sfield];
66
- endif;
67
- endif;
68
- endforeach;
69
 
70
- // Save settings
71
- $this->link->save_settings(/*reload=*/ true);
72
- $this->updated = true;
73
 
74
- // Reset, reload
75
- $link_id = $this->link->id;
76
- unset($this->link);
77
- $this->link = new SyndicatedLink($link_id);
78
- else :
79
- // update_option ...
80
- if (isset($post['feed_post_status'])) :
81
- update_option('feedwordpress_syndicated_post_status', $post['feed_post_status']);
82
- endif;
83
 
84
- update_option('feedwordpress_custom_settings', serialize($custom_settings));
85
-
86
- update_option('feedwordpress_munge_permalink', $_REQUEST['munge_permalink']);
87
- update_option('feedwordpress_use_aggregator_source_data', $_REQUEST['use_aggregator_source_data']);
88
- update_option('feedwordpress_formatting_filters', $_REQUEST['formatting_filters']);
89
-
90
- if (isset($post['resolve_relative'])) :
91
- update_option('feedwordpress_resolve_relative', $post['resolve_relative']);
92
- endif;
93
- if (isset($post['munge_comments_feed_links'])) :
94
- update_option('feedwordpress_munge_comments_feed_links', $post['munge_comments_feed_links']);
95
- endif;
96
- if (isset($_REQUEST['feed_comment_status']) and ($_REQUEST['feed_comment_status'] == 'open')) :
97
- update_option('feedwordpress_syndicated_comment_status', 'open');
98
- else :
99
- update_option('feedwordpress_syndicated_comment_status', 'closed');
100
  endif;
101
-
102
- if (isset($_REQUEST['feed_ping_status']) and ($_REQUEST['feed_ping_status'] == 'open')) :
103
- update_option('feedwordpress_syndicated_ping_status', 'open');
 
 
104
  else :
105
- update_option('feedwordpress_syndicated_ping_status', 'closed');
106
  endif;
107
-
108
- $this->updated = true;
109
  endif;
110
 
111
- // Probably a "Go" button for the drop-down
112
  else :
113
- $this->updated = false;
114
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  }
116
 
117
  /**
@@ -128,66 +136,37 @@ class FeedWordPressPostsPage extends FeedWordPressAdminPage {
128
  * @uses SyndicatedPost::use_api()
129
  */
130
  /*static*/ function publication_box ($page, $box = NULL) {
131
- global $fwp_path;
132
-
133
- $post_status_global = FeedWordPress::syndicated_status('post', /*default=*/ 'publish');
134
  $thesePosts = $page->these_posts_phrase();
135
-
136
- // Set up array for selector
137
- $setting = array(
138
- 'publish' => array ('label' => "Publish %s immediately", 'checked' => ''),
139
- 'draft' => array('label' => "Save %s as drafts", 'checked' => ''),
140
- 'private' => array('label' => "Save %s as private posts", 'checked' => ''),
141
  );
142
- if (SyndicatedPost::use_api('post_status_pending')) :
143
- $setting['pending'] = array('label' => "Hold %s for review; mark as Pending", 'checked' => '');
144
- endif;
145
-
146
-
147
- if ($page->for_feed_settings()) :
148
- $href = $fwp_path.'/'.basename(__FILE__);
149
- $currently = str_replace('%s', '', strtolower(strtok($setting[$post_status_global]['label'], ';')));
150
- $setting['site-default'] = array('label' => "Use <a href=\"admin.php?page=${href}\">site-wide setting</a>", 'checked' => '');
151
- $setting['site-default']['label'] .= " (currently: <strong>${currently}</strong>)";
152
-
153
- $checked = $page->link->syndicated_status('post', 'site-default', /*fallback=*/ false);
154
- else :
155
- $checked = $post_status_global;
156
- endif;
157
-
158
- // Re-order appropriately
159
- $selector = array();
160
- $order = array(
161
- 'site-default',
162
- 'publish',
163
- 'pending',
164
- 'draft',
165
- 'private',
166
- );
167
- foreach ($order as $line) :
168
- if (isset($setting[$line])) :
169
- $selector[$line] = $setting[$line];
170
- endif;
171
  endforeach;
172
- $selector[$checked]['checked'] = ' checked="checked"';
173
-
 
 
 
 
 
 
174
  // Hey ho, let's go...
175
  ?>
176
- <style type="text/css">
177
- #syndicated-publication-form th { width: 27%; vertical-align: top; }
178
- #syndicated-publication-form td { width: 73%; vertical-align: top; }
179
- </style>
180
-
181
- <table id="syndicated-publication-form" class="form-table" cellspacing="2" cellpadding="5">
182
  <tr><th scope="row"><?php _e('New posts:'); ?></th>
183
- <td><ul class="options">
184
- <?php foreach ($selector as $code => $li) : ?>
185
- <li><label><input type="radio" name="feed_post_status"
186
- value="<?php print $code; ?>"<?php print $li['checked']; ?> />
187
- <?php print str_replace('%s', $thesePosts, $li['label']); ?></label></li>
188
- <?php endforeach; ?>
189
- </ul></td>
190
- </tr>
191
 
192
  <?php $page->updatedPosts->display(); ?>
193
  </table>
@@ -205,25 +184,17 @@ class FeedWordPressPostsPage extends FeedWordPressAdminPage {
205
  *
206
  */
207
  function formatting_box ($page, $box = NULL) {
208
- global $fwp_path;
209
  $thesePosts = $page->these_posts_phrase();
210
- $global_resolve_relative = get_option('feedwordpress_resolve_relative', 'yes');
211
  if ($page->for_feed_settings()) :
212
  $formatting_filters = null;
213
- $resolve_relative = $page->link->setting('resolve relative', NULL, 'default');
214
  $url = preg_replace('|/+$|', '', $page->link->homepage());
215
- $setting = array(
216
- 'yes' => __('resolve relative URIs'),
217
- 'no' => __('leave relative URIs unresolved'),
218
- );
219
- $href = $fwp_path.'/'.basename(__FILE__);
220
  else :
221
  $formatting_filters = get_option('feedwordpress_formatting_filters', 'no');
222
- $resolve_relative = $global_resolve_relative;
223
  $url = 'http://example.com';
224
  endif;
225
  ?>
226
- <table class="form-table" cellspacing="2" cellpadding="5">
227
  <?php if (!is_null($formatting_filters)) : ?>
228
 
229
  <tr><th scope="row">Formatting filters:</th>
@@ -240,20 +211,30 @@ class FeedWordPressPostsPage extends FeedWordPressAdminPage {
240
  <?php endif; ?>
241
 
242
  <tr><th scope="row">Relative URIs:</th>
243
- <td>If link or image in a syndicated post from <code><?php print $url; ?></code>
244
  refers to a partial URI like <code>/about</code>, where should
245
  the syndicated copy point to?</p>
246
 
247
- <ul>
248
- <?php if ($page->for_feed_settings()) : ?>
249
- <li><p><label><input type="radio" name="resolve_relative" value='default' <?php echo ($resolve_relative=='default')?' checked="checked"':''; ?>/> Use <a href="admin.php?page=<?php print $href; ?>">site-wide setting</a><br/>
250
- <small style="margin-left: 2.0em;">Currently: <strong><?php print $setting[$global_resolve_relative]; ?></strong></small></label></p></li>
251
- <?php endif; ?>
252
- <li><p><label><input type="radio" name="resolve_relative" value="yes"<?php echo ($resolve_relative!='no' and $resolve_relative!='default')?' checked="checked"':''; ?>/> Resolve the URI so it points to <code><?php print $url; ?></code><br/>
253
- <small style="margin-left: 2.0em;"><code>/contact</code> is rewritten as <code><?php print $url; ?>/contact</code></label></small></p></li>
254
- <li><p><label><input type="radio" name="resolve_relative" value="no"<?php echo ($resolve_relative=='no')?' checked="checked"':''; ?>/> Leave relative URIs unchanged, so they point to this site<br/>
255
- <small style="margin-left: 2.0em;"><code>/contact</code> is left as <code>/contact</code></small></label></li>
256
- </ul>
 
 
 
 
 
 
 
 
 
 
257
  </td></tr>
258
 
259
  </table>
@@ -272,30 +253,31 @@ class FeedWordPressPostsPage extends FeedWordPressAdminPage {
272
  /*static*/ function links_box ($page, $box = NULL) {
273
  $setting = array(
274
  'munge_permalink' => array(
275
- 'yes' => 'the copy on the original website',
276
- 'no' => 'the local copy on this website',
277
  ),
278
  );
279
 
280
- $global_munge_permalink = get_option('feedwordpress_munge_permalink');
281
- if ($page->for_feed_settings()) :
282
- $munge_permalink = $page->link->setting('munge permalink', NULL);
283
- else :
284
- $munge_permalink = $global_munge_permalink;
285
  $use_aggregator_source_data = get_option('feedwordpress_use_aggregator_source_data');
286
  endif;
287
-
288
  ?>
289
- <table class="form-table" cellspacing="2" cellpadding="5">
290
  <tr><th scope="row">Permalinks point to:</th>
291
- <td><ul class="options">
292
- <?php if ($page->for_feed_settings()) : ?>
293
- <li><label><input type="radio" name="munge_permalink" value="default"<?php echo ($munge_permalink!='yes' and $munge_permalink != 'no')?' checked="checked"':''; ?>/> use site-wide setting (currently <?php print $setting['munge_permalink'][$global_munge_permalink]; ?>)</label></li>
294
- <?php endif; ?>
295
- <li><label><input type="radio" name="munge_permalink" value="yes"<?php echo ($munge_permalink=='yes')?' checked="checked"':''; ?>><?php print $setting['munge_permalink']['yes']; ?></label></li>
296
- <li><label><input type="radio" name="munge_permalink" value="no"<?php echo ($munge_permalink=='no')?' checked="checked"':''; ?>><?php print $setting['munge_permalink']['no']; ?></label></li>
297
- </ul></td>
298
- </tr>
 
 
 
 
 
 
299
 
300
  <?php if (!$page->for_feed_settings()) : ?>
301
  <tr><th scope="row">Posts from aggregator feeds:</th>
@@ -323,93 +305,71 @@ class FeedWordPressPostsPage extends FeedWordPressAdminPage {
323
  *
324
  */
325
  /*static*/ function comments_and_pings_box ($page, $box = NULL) {
326
- global $fwp_path;
327
-
328
- $setting = array();
329
- $selector = array();
330
-
331
  $whatsits = array(
332
  'comment' => array('label' => __('Comments'), 'accept' => 'Allow comments'),
333
  'ping' => array('label' => __('Pings'), 'accept' => 'Accept pings'),
334
  );
335
  $onThesePosts = 'on '.$page->these_posts_phrase();
336
-
337
- $selected = array(
338
- 'munge_comments_feed_links' => array('yes' => '', 'no' => '')
339
- );
340
 
341
- $globalMungeCommentsFeedLinks = get_option('feedwordpress_munge_comments_feed_links', 'yes');
342
- if ($page->for_feed_settings()) :
343
- $selected['munge_comments_feed_links']['default'] = '';
344
-
345
- $sel = $page->link->setting('munge comments feed links', NULL, 'default');
346
- else :
347
- $sel = $globalMungeCommentsFeedLinks;
348
- endif;
349
- $selected['munge_comments_feed_links'][$sel] = ' checked="checked"';
350
-
351
- if ($globalMungeCommentsFeedLinks != 'no') : $siteWide = __('comment feeds from the original website');
352
- else : $siteWide = __('local comment feeds on this website');
353
- endif;
354
 
 
355
  foreach ($whatsits as $what => $how) :
356
  $whatsits[$what]['default'] = FeedWordPress::syndicated_status($what, /*default=*/ 'closed');
357
 
358
  // Set up array for selector
359
- $setting = array(
360
- 'open' => array ('label' => "{$how['accept']} %s", 'checked' => ''),
361
- 'closed' => array('label' => "Don't ".strtolower($how['accept'])." %s", 'checked' => ''),
362
  );
363
- if ($page->for_feed_settings()) :
364
- $href = $fwp_path.'/'.basename(__FILE__);
365
- $currently = trim(str_replace('%s', '', strtolower(strtok($setting[$whatsits[$what]['default']]['label'], ';'))));
366
- $setting['site-default'] = array('label' => "Use <a href=\"admin.php?page=${href}\">site-wide setting</a>", 'checked' => '');
367
- $setting['site-default']['label'] .= " (currently: <strong>${currently}</strong>)";
368
-
369
- $checked = $page->link->syndicated_status($what, 'site-default', /*fallback=*/ false);
370
- else :
371
- $checked = $whatsits[$what]['default'];
372
- endif;
373
-
374
- // Re-order appropriately
375
- $selector[$what] = array();
376
- $order = array(
377
- 'site-default',
378
- 'open',
379
- 'closed',
380
  );
381
- foreach ($order as $line) :
382
- if (isset($setting[$line])) :
383
- $selector[$what][$line] = $setting[$line];
384
- endif;
385
- endforeach;
386
- $selector[$what][$checked]['checked'] = ' checked="checked"';
387
  endforeach;
388
 
389
  // Hey ho, let's go...
390
  ?>
391
- <table class="form-table" cellspacing="2" cellpadding="5">
392
  <?php foreach ($whatsits as $what => $how) : ?>
 
393
  <tr><th scope="row"><?php print $how['label']; ?>:</th>
394
- <td><ul class="options">
395
- <?php foreach ($selector[$what] as $code => $li) : ?>
396
- <li><label><input type="radio" name="feed_<?php print $what; ?>_status"
397
- value="<?php print $code; ?>"<?php print $li['checked']; ?> />
398
- <?php print trim(str_replace('%s', $onThesePosts, $li['label'])); ?></label></li>
399
- <?php endforeach; ?>
400
- </ul></td></tr>
401
  <?php endforeach; ?>
 
402
  <tr><th scope="row"><?php _e('Comment feeds'); ?></th>
403
  <td><p>When WordPress feeds and templates link to comments
404
  feeds for <?php print $page->these_posts_phrase(); ?>, the
405
  URLs for the feeds should...</p>
406
- <ul class="options">
407
- <?php if ($page->for_feed_settings()) : ?>
408
- <li><label><input type="radio" name="munge_comments_feed_links" value="default"<?php print $selected['munge_comments_feed_links']['default']; ?> /> Use <a href="admin.php?page=<?php print $href; ?>">site-wide setting</a> (currently: <strong><?php _e($siteWide); ?></strong>)</label></li>
409
- <?php endif; ?>
410
- <li><label><input type="radio" name="munge_comments_feed_links" value="yes"<?php print $selected['munge_comments_feed_links']['yes']; ?> /> <?php _e('Point to comment feeds from the original website (when provided by the syndicated feed)'); ?></label></li>
411
- <li><label><input type="radio" name="munge_comments_feed_links" value="no"<?php print $selected['munge_comments_feed_links']['no']; ?> /> <?php _e('Point to local comment feeds on this website'); ?></label></li>
412
- </ul></td></tr>
413
  </table>
414
 
415
  <?php
@@ -421,7 +381,7 @@ class FeedWordPressPostsPage extends FeedWordPressAdminPage {
421
  endif;
422
 
423
  if ($page->for_feed_settings()) :
424
- $custom_settings = $page->link->settings["postmeta"];
425
  else :
426
  $custom_settings = get_option('feedwordpress_custom_settings');
427
  endif;
@@ -491,82 +451,64 @@ class FeedWordPressPostsPage extends FeedWordPressAdminPage {
491
  </div> <!-- id="postcustomstuff" -->
492
 
493
  <?php
494
- } /* FeedWordPressPostsPage::custom_post_settings_box() */
495
- }
496
-
497
- function fwp_posts_page () {
498
- global $wpdb, $wp_db_version;
499
- global $fwp_post;
500
 
501
- if (FeedWordPress::needs_upgrade()) :
502
- fwp_upgrade_page();
503
- return;
504
- endif;
505
-
506
- // If this is a POST, validate source and user credentials
507
- FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_posts_settings', /*capability=*/ 'manage_links');
508
-
509
- $link = FeedWordPressAdminPage::submitted_link();
510
-
511
- $postsPage = new FeedWordPressPostsPage($link);
512
-
513
- $mesg = null;
514
-
515
- ////////////////////////////////////////////////
516
- // Process POST request, if any ////////////////
517
- ////////////////////////////////////////////////
518
- if (strtoupper($_SERVER['REQUEST_METHOD'])=='POST') :
519
- $postsPage->accept_POST($fwp_post);
520
- do_action('feedwordpress_admin_page_posts_save', $fwp_post, $postsPage);
521
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
522
 
523
- $postsPage->ajax_interface_js();
524
-
525
- if ($postsPage->updated) : ?>
526
- <div class="updated"><p>Syndicated posts settings updated.</p></div>
527
- <?php elseif (!is_null($mesg)) : ?>
528
- <div class="updated"><p><?php print esc_html($mesg); ?></p></div>
529
- <?php endif; ?>
530
-
531
- <?php
532
- $links = FeedWordPress::syndicated_links();
533
- $postsPage->open_sheet('Syndicated Posts & Links');
534
- ?>
535
- <style type="text/css">
536
- table.edit-form th, table.form-table th { width: 27%; vertical-align: top; }
537
- table.edit-form td, table.form-table td { width: 73%; vertical-align: top; }
538
- ul.options { margin: 0; padding: 0; list-style: none; }
539
- </style>
540
- <div id="post-body">
541
- <?php
542
- $boxes_by_methods = array(
543
- 'publication_box' => __('Syndicated Posts'),
544
- 'links_box' => __('Links'),
545
- 'formatting_box' => __('Formatting'),
546
- 'comments_and_pings_box' => __('Comments & Pings'),
547
- 'custom_post_settings_box' => __('Custom Post Settings (to apply to each syndicated post)'),
548
- );
549
-
550
- foreach ($boxes_by_methods as $method => $title) :
551
- fwp_add_meta_box(
552
- /*id=*/ 'feedwordpress_'.$method,
553
- /*title=*/ $title,
554
- /*callback=*/ array('FeedWordPressPostsPage', $method),
555
- /*page=*/ $postsPage->meta_box_context(),
556
- /*context=*/ $postsPage->meta_box_context()
557
  );
558
- endforeach;
559
- do_action('feedwordpress_admin_page_posts_meta_boxes', $postsPage);
560
- ?>
561
- <div class="metabox-holder">
562
- <?php
563
- fwp_do_meta_boxes($postsPage->meta_box_context(), $postsPage->meta_box_context(), $postsPage);
564
- ?>
565
- </div> <!-- class="metabox-holder" -->
566
- </div> <!-- id="post-body" -->
567
- <?php
568
- $postsPage->close_sheet();
569
- } /* function fwp_posts_page () */
570
 
571
- fwp_posts_page();
 
572
 
11
  *
12
  * @param mixed $link An object of class {@link SyndicatedLink} if created for one feed's settings, NULL if created for global default settings
13
  */
14
+ function FeedWordPressPostsPage ($link = -1) {
15
+ if (is_numeric($link) and -1 == $link) :
16
+ $link = FeedWordPressAdminPage::submitted_link();
17
+ endif;
18
+
19
  FeedWordPressAdminPage::FeedWordPressAdminPage('feedwordpresspostspage', $link);
20
+ $this->dispatch = 'feedwordpress_admin_page_posts';
21
  $this->filename = __FILE__;
22
  $this->updatedPosts = new UpdatedPostsControl($this);
23
+
24
+ $this->pagenames = array(
25
+ 'default' => 'Posts',
26
+ 'settings-update' => 'Syndicated posts',
27
+ 'open-sheet' => 'Syndicated Posts & Links',
28
+ );
29
  } /* FeedWordPressPostsPage constructor */
30
 
31
+ function save_settings ($post) {
32
+ // custom post settings
33
+ $custom_settings = $this->custom_post_settings();
 
 
 
 
34
 
35
+ foreach ($post['notes'] as $mn) :
36
+ if (isset($mn['key0'])) :
37
  $mn['key0'] = trim($mn['key0']);
 
 
38
  if (strlen($mn['key0']) > 0) :
39
  unset($custom_settings[$mn['key0']]); // out with the old
40
  endif;
41
+ endif;
42
 
43
+ if (isset($mn['key1'])) :
44
+ $mn['key1'] = trim($mn['key1']);
45
+
46
  if (($mn['action']=='update') and (strlen($mn['key1']) > 0)) :
47
  $custom_settings[$mn['key1']] = $mn['value']; // in with the new
48
  endif;
49
+ endif;
50
+ endforeach;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
 
52
+ $this->updatedPosts->accept_POST($post);
53
+ if ($this->for_feed_settings()) :
54
+ $alter = array ();
 
 
 
 
 
 
 
 
55
 
56
+ $this->link->settings['postmeta'] = serialize($custom_settings);
 
 
57
 
58
+ if (isset($post['resolve_relative'])) :
59
+ $this->link->settings['resolve relative'] = $post['resolve_relative'];
60
+ endif;
61
+ if (isset($post['munge_permalink'])) :
62
+ $this->link->settings['munge permalink'] = $post['munge_permalink'];
63
+ endif;
64
+ if (isset($post['munge_comments_feed_links'])) :
65
+ $this->link->settings['munge comments feed links'] = $post['munge_comments_feed_links'];
66
+ endif;
67
 
68
+ // Post status, comment status, ping status
69
+ foreach (array('post', 'comment', 'ping') as $what) :
70
+ $sfield = "feed_{$what}_status";
71
+ if (isset($post[$sfield])) :
72
+ if ($post[$sfield]=='site-default') :
73
+ unset($this->link->settings["{$what} status"]);
74
+ else :
75
+ $this->link->settings["{$what} status"] = $post[$sfield];
76
+ endif;
 
 
 
 
 
 
 
77
  endif;
78
+ endforeach;
79
+
80
+ if (isset($post['syndicated_post_type'])) :
81
+ if ($post['syndicated_post_type']=='default') :
82
+ unset($this->link->settings['syndicated post type']);
83
  else :
84
+ $this->link->settings['syndicated post type'] = $post['syndicated_post_type'];
85
  endif;
 
 
86
  endif;
87
 
 
88
  else :
89
+ // update_option ...
90
+ if (isset($post['feed_post_status'])) :
91
+ update_option('feedwordpress_syndicated_post_status', $post['feed_post_status']);
92
+ endif;
93
+
94
+ update_option('feedwordpress_custom_settings', serialize($custom_settings));
95
+
96
+ update_option('feedwordpress_munge_permalink', $_REQUEST['munge_permalink']);
97
+ update_option('feedwordpress_use_aggregator_source_data', $_REQUEST['use_aggregator_source_data']);
98
+ update_option('feedwordpress_formatting_filters', $_REQUEST['formatting_filters']);
99
+
100
+ if (isset($post['resolve_relative'])) :
101
+ update_option('feedwordpress_resolve_relative', $post['resolve_relative']);
102
+ endif;
103
+ if (isset($post['munge_comments_feed_links'])) :
104
+ update_option('feedwordpress_munge_comments_feed_links', $post['munge_comments_feed_links']);
105
+ endif;
106
+ if (isset($_REQUEST['feed_comment_status']) and ($_REQUEST['feed_comment_status'] == 'open')) :
107
+ update_option('feedwordpress_syndicated_comment_status', 'open');
108
+ else :
109
+ update_option('feedwordpress_syndicated_comment_status', 'closed');
110
+ endif;
111
+
112
+ if (isset($_REQUEST['feed_ping_status']) and ($_REQUEST['feed_ping_status'] == 'open')) :
113
+ update_option('feedwordpress_syndicated_ping_status', 'open');
114
+ else :
115
+ update_option('feedwordpress_syndicated_ping_status', 'closed');
116
+ endif;
117
+
118
+ if (isset($post['syndicated_post_type'])) :
119
+ update_option('feedwordpress_syndicated_post_type', $post['syndicated_post_type']);
120
+ endif;
121
+ endif;
122
+ parent::save_settings($post);
123
  }
124
 
125
  /**
136
  * @uses SyndicatedPost::use_api()
137
  */
138
  /*static*/ function publication_box ($page, $box = NULL) {
 
 
 
139
  $thesePosts = $page->these_posts_phrase();
140
+ $postSelector = array(
141
+ 'publish' => "Publish %s immediately",
142
+ 'pending' => "Hold %s for review; mark as Pending",
143
+ 'draft' => "Save %s as drafts",
144
+ 'private' => "Save %s as private posts",
 
145
  );
146
+ $labels = array();
147
+ foreach ($postSelector as $index => $value) :
148
+ $postSelector[$index] = sprintf(__($value), $thesePosts);
149
+ $labels[$index] = __(str_replace(' %s', '', strtolower(strtok($value, ';'))));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  endforeach;
151
+
152
+ $params = array(
153
+ 'input-name' => 'feed_post_status',
154
+ 'setting-default' => NULL,
155
+ 'global-setting-default' => 'publish',
156
+ 'labels' => $labels,
157
+ );
158
+
159
  // Hey ho, let's go...
160
  ?>
161
+ <table id="syndicated-publication-form" class="edit-form narrow">
 
 
 
 
 
162
  <tr><th scope="row"><?php _e('New posts:'); ?></th>
163
+ <td><?php
164
+ $this->setting_radio_control(
165
+ 'post status', 'syndicated_post_status',
166
+ $postSelector, $params
167
+ );
168
+ ?>
169
+ </td></tr>
 
170
 
171
  <?php $page->updatedPosts->display(); ?>
172
  </table>
184
  *
185
  */
186
  function formatting_box ($page, $box = NULL) {
 
187
  $thesePosts = $page->these_posts_phrase();
188
+
189
  if ($page->for_feed_settings()) :
190
  $formatting_filters = null;
 
191
  $url = preg_replace('|/+$|', '', $page->link->homepage());
 
 
 
 
 
192
  else :
193
  $formatting_filters = get_option('feedwordpress_formatting_filters', 'no');
 
194
  $url = 'http://example.com';
195
  endif;
196
  ?>
197
+ <table class="edit-form narrow">
198
  <?php if (!is_null($formatting_filters)) : ?>
199
 
200
  <tr><th scope="row">Formatting filters:</th>
211
  <?php endif; ?>
212
 
213
  <tr><th scope="row">Relative URIs:</th>
214
+ <td><p>If link or image in a syndicated post from <code><?php print $url; ?></code>
215
  refers to a partial URI like <code>/about</code>, where should
216
  the syndicated copy point to?</p>
217
 
218
+ <?php
219
+ $options = array(
220
+ 'yes' => 'Resolve the URI so it points to <code>'.$url.'</code><br/><small style="margin-left: 2.0em;"><code>/contact</code> is rewritten as <code>'.$url.'/contact</code></small>',
221
+ 'no' => 'Leave relative URIs unchanged, so they point to this site<br/><small style="margin-left: 2.0em;"><code>/contact</code> is left as <code>/contact</code></small>',
222
+ );
223
+ $params = array(
224
+ 'setting-default' => 'default',
225
+ 'global-setting-default' => 'yes',
226
+ 'labels' => array(
227
+ 'yes' => __('resolve relative URIs'),
228
+ 'no' => __('leave relative URIs unresolved'),
229
+ ),
230
+ 'default-input-value' => 'default',
231
+ );
232
+
233
+ $this->setting_radio_control(
234
+ 'resolve relative', 'resolve_relative',
235
+ $options, $params
236
+ );
237
+ ?>
238
  </td></tr>
239
 
240
  </table>
253
  /*static*/ function links_box ($page, $box = NULL) {
254
  $setting = array(
255
  'munge_permalink' => array(
256
+ 'yes' => __('The copy on the original website'),
257
+ 'no' => __('The local copy on this website'),
258
  ),
259
  );
260
 
261
+ if (!$page->for_feed_settings()) :
 
 
 
 
262
  $use_aggregator_source_data = get_option('feedwordpress_use_aggregator_source_data');
263
  endif;
 
264
  ?>
265
+ <table class="edit-form narrow">
266
  <tr><th scope="row">Permalinks point to:</th>
267
+ <td><?php
268
+
269
+ $params = array(
270
+ 'setting-default' => 'default',
271
+ 'global-setting-default' => 'yes',
272
+ 'default-input-value' => 'default',
273
+ );
274
+ $this->setting_radio_control(
275
+ 'munge permalink', 'munge_permalink',
276
+ $setting['munge_permalink'], $params
277
+ );
278
+ ?>
279
+
280
+ </td></tr>
281
 
282
  <?php if (!$page->for_feed_settings()) : ?>
283
  <tr><th scope="row">Posts from aggregator feeds:</th>
305
  *
306
  */
307
  /*static*/ function comments_and_pings_box ($page, $box = NULL) {
 
 
 
 
 
308
  $whatsits = array(
309
  'comment' => array('label' => __('Comments'), 'accept' => 'Allow comments'),
310
  'ping' => array('label' => __('Pings'), 'accept' => 'Accept pings'),
311
  );
312
  $onThesePosts = 'on '.$page->these_posts_phrase();
 
 
 
 
313
 
314
+ $mcflSettings = array(
315
+ "yes" => __('Point to comment feeds from the original website (when provided by the syndicated feed)'),
316
+ "no" => __('Point to local comment feeds on this website'),
317
+ );
318
+ $mcflParams = array(
319
+ 'setting-default' => 'default',
320
+ 'global-setting-default' => 'yes',
321
+ 'labels' => array(
322
+ 'yes' => __('comment feeds from the original website'),
323
+ 'no' => __('local comment feeds on this website')
324
+ ),
325
+ 'default-input-value' => 'default',
326
+ );
327
 
328
+ $settings = array(); $params = array();
329
  foreach ($whatsits as $what => $how) :
330
  $whatsits[$what]['default'] = FeedWordPress::syndicated_status($what, /*default=*/ 'closed');
331
 
332
  // Set up array for selector
333
+ $settings[$what] = array(
334
+ 'open' => sprintf(__("{$how['accept']} %s"), __($onThesePosts)),
335
+ 'closed' => sprintf(__("Don't ".strtolower($how['accept'])." %s"), __($onThesePosts)),
336
  );
337
+ $params[$what] = array(
338
+ 'input-name' => "feed_${what}_status",
339
+ 'setting-default' => NULL,
340
+ 'global-setting-default' => FeedWordPress::syndicated_status($what, /*default=*/ 'closed'),
341
+ 'labels' => array(
342
+ 'open' => strtolower(__($how['accept'])),
343
+ 'closed' => strtolower(__("Don't ".$how['accept'])),
344
+ ),
 
 
 
 
 
 
 
 
 
345
  );
 
 
 
 
 
 
346
  endforeach;
347
 
348
  // Hey ho, let's go...
349
  ?>
350
+ <table class="edit-form narrow">
351
  <?php foreach ($whatsits as $what => $how) : ?>
352
+
353
  <tr><th scope="row"><?php print $how['label']; ?>:</th>
354
+ <td><?php
355
+ $this->setting_radio_control(
356
+ "$what status", "syndicated_${what}_status",
357
+ $settings[$what], $params[$what]
358
+ );
359
+ ?></td></tr>
360
+
361
  <?php endforeach; ?>
362
+
363
  <tr><th scope="row"><?php _e('Comment feeds'); ?></th>
364
  <td><p>When WordPress feeds and templates link to comments
365
  feeds for <?php print $page->these_posts_phrase(); ?>, the
366
  URLs for the feeds should...</p>
367
+ <?php
368
+ $this->setting_radio_control(
369
+ "munge comments feed links", "munge_comments_feed_links",
370
+ $mcflSettings, $mcflParams
371
+ );
372
+ ?></td></tr>
 
373
  </table>
374
 
375
  <?php
381
  endif;
382
 
383
  if ($page->for_feed_settings()) :
384
+ $custom_settings = $page->link->setting("postmeta", NULL, array());
385
  else :
386
  $custom_settings = get_option('feedwordpress_custom_settings');
387
  endif;
451
  </div> <!-- id="postcustomstuff" -->
452
 
453
  <?php
454
+ } /* FeedWordPressPostsPage::custom_post_settings_box() */
 
 
 
 
 
455
 
456
+ function custom_post_types_box ($page, $box = NULL) {
457
+ global $fwp_path;
458
+
459
+ // local: syndicated post type // default NULL
460
+ // global: syndicated_post_type // default 'post'
461
+ // default-input-value => 'default'
462
+
463
+ // Get all custom post types
464
+ $post_types = get_post_types(array(
465
+ '_builtin' => false,
466
+ ), 'objects');
467
+
468
+ $ul = array();
469
+ $ul['post'] = __('Normal WordPress posts');
470
+ foreach ($post_types as $post_type) :
471
+ $ul[$post_type->name] = __($post_type->labels->name);
472
+ endforeach;
473
+
474
+ $params = array(
475
+ 'global-setting-default' => 'post',
476
+ 'default-input-value' => 'default',
477
+ );
478
+
479
+ // Hey, ho, let's go...
480
+ ?>
481
+ <table class="edit-form narrow">
482
+ <tbody>
483
+ <tr><th><?php _e('Custom Post Types:'); ?></th>
484
+ <td><p>Incoming syndicated posts should be stored in the
485
+ posts database as...</p>
486
+ <?php
487
+ $this->setting_radio_control(
488
+ 'syndicated post type', 'syndicated_post_type',
489
+ $ul, $params
490
+ );
491
+ ?>
492
+ </td></tr>
493
+ </tbody>
494
+ </table>
495
+ <?php
496
+ } /* FeedWordPressPostsPage::custom_post_types_box() */
497
 
498
+ function display () {
499
+ $this->boxes_by_methods = array(
500
+ 'publication_box' => __('Syndicated Posts'),
501
+ 'links_box' => __('Links'),
502
+ 'formatting_box' => __('Formatting'),
503
+ 'comments_and_pings_box' => __('Comments & Pings'),
504
+ 'custom_post_settings_box' => __('Custom Post Settings (to apply to each syndicated post)'),
505
+ 'custom_post_types_box' => ('Custom Post Types (advanced database settings)'),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
506
  );
507
+
508
+ parent::display();
509
+ } /* FeedWordPressPostsPage::display () */
510
+ }
 
 
 
 
 
 
 
 
511
 
512
+ $postsPage = new FeedWordPressPostsPage;
513
+ $postsPage->display();
514
 
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: Charles Johnson
3
  Donate link: http://feedwordpress.radgeek.com/
4
  Tags: syndication, aggregation, feed, atom, rss
5
- Requires at least: 2.8
6
- Tested up to: 3.0
7
- Stable tag: 2010.0623
8
 
9
  FeedWordPress syndicates content from feeds you choose into your WordPress weblog.
10
 
@@ -26,7 +26,7 @@ to use at [Feminist Blogs][].
26
 
27
  FeedWordPress is designed with flexibility, ease of use, and ease of
28
  configuration in mind. You'll need a working installation of WordPress or
29
- WordPress MU (version [2.8] or later), and also FTP or SFTP access to your web
30
  host. The ability to create cron jobs on your web host is helpful but not
31
  required. You *don't* need to tweak any plain-text configuration files and you
32
  *don't* need shell access to your web host to make it work. (Although, I should
@@ -34,14 +34,14 @@ point out, web hosts that *don't* offer shell access are *bad web hosts*.)
34
 
35
  [WordPress]: http://wordpress.org/
36
  [WordPress MU]: http://mu.wordpress.org/
37
- [2.8]: http://codex.wordpress.org/Version_2.8
38
 
39
  == Installation ==
40
 
41
  To use FeedWordPress, you will need:
42
 
43
  * an installed and configured copy of [WordPress][] or [WordPress MU][]
44
- (version 2.8 or later).
45
 
46
  * FTP, SFTP or shell access to your web host
47
 
@@ -93,6 +93,139 @@ outs, see the documentation at the [FeedWordPress project homepage][].
93
 
94
  == Changelog ==
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  = 2010.0623 =
97
 
98
  * WORDPRESS 3.0 COMPATIBILITY / AUTHOR MAPPING INTERFACE ISSUES: I
2
  Contributors: Charles Johnson
3
  Donate link: http://feedwordpress.radgeek.com/
4
  Tags: syndication, aggregation, feed, atom, rss
5
+ Requires at least: 3.0
6
+ Tested up to: 3.0.1
7
+ Stable tag: 2010.0903
8
 
9
  FeedWordPress syndicates content from feeds you choose into your WordPress weblog.
10
 
26
 
27
  FeedWordPress is designed with flexibility, ease of use, and ease of
28
  configuration in mind. You'll need a working installation of WordPress or
29
+ WordPress MU (version [3.0] or later), and also FTP or SFTP access to your web
30
  host. The ability to create cron jobs on your web host is helpful but not
31
  required. You *don't* need to tweak any plain-text configuration files and you
32
  *don't* need shell access to your web host to make it work. (Although, I should
34
 
35
  [WordPress]: http://wordpress.org/
36
  [WordPress MU]: http://mu.wordpress.org/
37
+ [3.0]: http://codex.wordpress.org/Version_3.0
38
 
39
  == Installation ==
40
 
41
  To use FeedWordPress, you will need:
42
 
43
  * an installed and configured copy of [WordPress][] or [WordPress MU][]
44
+ (version 3.0 or later).
45
 
46
  * FTP, SFTP or shell access to your web host
47
 
93
 
94
  == Changelog ==
95
 
96
+ = 2010.0903 =
97
+
98
+ * WORDPRESS 3 REQUIRED: Please note that this release of FeedWordPress
99
+ *requires* WordPress 3.0 or later. If you are currently using a 2.x
100
+ branch of WordPress, you will need to upgrade to WordPress 3 before you
101
+ can successfully upgrade FeedWordPress.
102
+
103
+ * BUGFIX: NO MORE DISAPPEARING "SYNDICATED SOURCES" PANEL; INTERNET
104
+ EXPLORER UI GLITCH APPARENTLY FIXED: Several users independently
105
+ reported a problem with FWP 2010.0623 and various versions of IE. A
106
+ problem with the HTML markup caused IE (but not Firefox or
107
+ Chrome) to completely hide the Syndicated Sources administration panel
108
+ (the main list of currently-syndicated sources, and the main location
109
+ for adding new sources, under the Syndication menu item) when a user
110
+ added their first syndicated feed. Maddeningly, the glitch seemed to
111
+ affect some IE users and not others: I was never able to reproduce the
112
+ problem for myself on my own machines. However, the markup of Syndicated
113
+ Sources has undergone significant changes and corrections since
114
+ 2010.0623, and two independent sources who had been having this problem
115
+ confirm that they no longer encounter it with the updated version. For
116
+ the time being, I am going to declare this bug squashed.
117
+
118
+ * BUGFIX: MORE PROTECTION AGAINST FATAL ERRORS FROM PLUGGABLE VERSIONS OF
119
+ SimplePie: FeedWordPress now takes some precautions that should help to
120
+ better avoid conflicts for users who have installed pluggable versions
121
+ of SimplePie for another plugin or theme. (You may not know that you have
122
+ done this; but if you've been encountering fatal errors indicating that
123
+ you cannot redeclare class SimplePie, or something along those lines,
124
+ there is now a better chance that those fatal errors will be eliminated.
125
+
126
+ * PERFORMANCE: SIGNIFICANTLY REDUCED MEMORY CONSUMPTION FOR LARGE UPDATES:
127
+ FeedWordPress is still a memory-hungry little module, especially when
128
+ you are dealing with very large feeds. However, users should notice a
129
+ significant reduction in memory overloads, especially if they update a
130
+ large number of feeds at once.
131
+
132
+ * USER INTERFACE IMPROVEMENTS: Nothing is radically different, but there's
133
+ been a fair amount of extra spit and polish added, including a convenient
134
+ new Dashboard widget that may save you a trip to the Syndication menu,
135
+ a lot of effort to make the relationship between global and feed-by-feed
136
+ settings more obvious to the user and more easily controllable, to make
137
+ navigation between settings pages easier, to sand off a few rough edges,
138
+ and to make other improvements on the margins. I hope you'll like how
139
+ it looks.
140
+
141
+ * ADDING MULTIPLE FEEDS: FeedWordPress now provides a convenient mode for
142
+ adding multiple feeds at once, using either a copy-and-pasted list, or
143
+ else an OPML file. Go to Syndication --> Syndicated Sources and check
144
+ out the two new buttons underneath the New Source input box. When you
145
+ have to add a number of feeds at once, this can save you considerable
146
+ time and trouble.
147
+
148
+ * IMPROVED HANDLING OF AUTHORS WITH DUPLICATE E-MAIL ADDRESS AND AUTHORS
149
+ WITH NAMES WRITTEN IN FOREIGN SCRIPTS: WordPress 3 is increasingly picky
150
+ about what it will accept for new author accounts, and some of the
151
+ conditions it imposes can cause error conditions that prevent posts from
152
+ being properly syndicated, or properly attributed, if authors happen to
153
+ have identical e-mail addresses, or if users are given usernames that are
154
+ written in non-Western scripts. FeedWordPress now handles these much
155
+ better, and systematically works to avoid clashes between syndicated
156
+ authors' account names or in their e-mail addresses, which should result
157
+ in significantly better results in mapping author names to WordPress
158
+ user accounts.
159
+
160
+ * MAPPING CATEGORIES ON SYNDICATED POSTS TO TAGS NOW BETTER SUPPORTED:
161
+ In previous versions, the only way for the Categories provided by a
162
+ syndicated feed to be mapped into Post Tags was to instruct FWP to
163
+ create new tags, rather than new categories, for unfamiliar categories
164
+ from the feed. This works fine if you want tags to be the default; but
165
+ if you want only a *specific* set of tags, there was no way to get them
166
+ without getting most or all other categories imported as tags. You can
167
+ now do this by creating a tag (under Posts ==> Post Tags) before
168
+ importing the post; when the syndicated category matches a pre-existing
169
+ tag, the incoming post will be tagged with that tag, without creating
170
+ a local Post Category.
171
+
172
+ * REL-TAG MICROFORMAT SUPPORT FOR INLINE TAGS: Syndicated posts that
173
+ contain inline tags, marked up using the Rel-Tag microformat
174
+ <http://microformats.org/wiki/rel-tag>, are now tagged with the tags
175
+ provided by Rel-Tag format links.
176
+
177
+ * MUCH GREATER CONTROL OVER CATEGORY AND TAG MAPPING: This is partly the
178
+ result of building in support for a potentially endless set of custom
179
+ taxonomies (see below), but in general there has been a great deal of
180
+ effort towards giving you more control over how categories and tags
181
+ provided by the feed are mapped into terms on the local blog. In
182
+ particular, you can now force FeedWordPress to create only categories
183
+ from categories and tags provided by the feed; or to create only tags;
184
+ or to search both categories and tags for a match; or you can simply
185
+ force it to drop all of the categories provided by the feed and use
186
+ only categories or tags that you explicitly provide. In addition, you
187
+ can now also choose whether to override global categories settings with
188
+ a local, feed-specific setting; or whether to *add together* *both* the
189
+ global categories and the local feed-specific categories -- depending
190
+ on whatever your use-case may demand.
191
+
192
+ * CUSTOM POST TYPES AND TAXONOMY SUPPORTS: This is mainly for the
193
+ super-geeky, but if you use other plugins or themes that make
194
+ significant use of WordPress's support for custom post types and custom
195
+ taxonomies, you may be pleased to find that FeedWordPress now allows you
196
+ to feed incoming posts into any custom feed type that you wish, and to
197
+ map categories and tags from the feed to custom taxonomies as well as
198
+ to the standard Category and Tag taxonomies.
199
+
200
+ * STORING NAMESPACED CUSTOM FEED ELEMENTS IN POST CUSTOM FIELDS: If you
201
+ would like to use FeedWordPress's support for storing custom meta-data
202
+ from feed elements in the custom fields for a post (for example, to
203
+ store geolocation data or iTunes media meta-data), you'll find that it's
204
+ now much easier for you to access these namespaced elements. You always
205
+ could access them, but in previous versions you might have to write
206
+ something ugly like $(/{http://www.w3.org/2003/01/geo/wgs84_pos#}lat)
207
+ just to get at the value of a `<geo:lat>` tag. Now, as long as you use
208
+ the same mnemonic codes that the feed producer used, you should always
209
+ be able to write a nice, simple expression like $(/geo:lat) to get the
210
+ value of a <geo:lat> tag.
211
+
212
+ * CUSTOM DIRECTORY STRUCTURE SUPPORT: if you poke at it enough, WordPress
213
+ is relatively flexible about where it should store admin interface code,
214
+ uploaded content, plugins, and a number of other things that occupy an
215
+ important place in the WordPress directory structure. Previous versions
216
+ of FeedWordPress encountered serious errors or broke entirely when used
217
+ with directory structures other than the default. This should now be
218
+ fixed: FWP now supports custom directory structures wherever WordPress
219
+ allows them to be customized, rather than depending on the default
220
+ locations. Enjoy your freedom!
221
+
222
+ * MANY NEW FILTERS AND API UTILITY FUNCTIONS FOR ADD-ON PROGRAMMERS: There
223
+ have been too many improvements to list them all in this ChangeLog, but
224
+ it means that much more power and ease for folks who are customizing
225
+ FeedWordPress through PHP filters or add-on modules. Fuller
226
+ documentation will be put up at the Wiki at feedwordpress.radgeek.org
227
+ soon.
228
+
229
  = 2010.0623 =
230
 
231
  * WORDPRESS 3.0 COMPATIBILITY / AUTHOR MAPPING INTERFACE ISSUES: I
syndicatedlink.class.php CHANGED
@@ -101,11 +101,25 @@ class SyndicatedLink {
101
  $this->settings['cat_split'] = '\s'; // Whitespace separates multiple tags in del.icio.us RSS feeds
102
  endif;
103
 
104
- if (isset($this->settings['cats'])):
105
- $this->settings['cats'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['cats']);
106
- endif;
107
- if (isset($this->settings['tags'])):
108
- $this->settings['tags'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['tags']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  endif;
110
 
111
  if (isset($this->settings['map authors'])) :
@@ -149,7 +163,7 @@ class SyndicatedLink {
149
  function poll ($crash_ts = NULL) {
150
  global $wpdb;
151
 
152
- FeedWordPress::diagnostic('updated_feeds', 'Polling feed <'.$this->link->link_rss.'>');
153
 
154
  $this->simplepie = apply_filters(
155
  'syndicated_feed',
@@ -202,6 +216,8 @@ class SyndicatedLink {
202
  $this->settings['update/timed'] = 'automatically';
203
  endif;
204
 
 
 
205
  $this->settings['update/error'] = serialize($theError);
206
  $this->save_settings(/*reload=*/ true);
207
 
@@ -322,6 +338,16 @@ class SyndicatedLink {
322
  do_action("update_syndicated_feed_completed", $this->id, $this);
323
  endif;
324
 
 
 
 
 
 
 
 
 
 
 
325
  return $new_count;
326
  } /* SyndicatedLink::poll() */
327
 
@@ -350,6 +376,54 @@ class SyndicatedLink {
350
  return $ret;
351
  } /* SyndicatedLink::set_uri () */
352
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
353
  function map_name_to_new_user ($name, $newuser_name) {
354
  global $wpdb;
355
 
@@ -369,6 +443,9 @@ class SyndicatedLink {
369
  endif;
370
  } /* SyndicatedLink::map_name_to_new_user () */
371
 
 
 
 
372
  function settings_to_notes () {
373
  $to_notes = $this->settings;
374
 
@@ -383,13 +460,23 @@ class SyndicatedLink {
383
  $to_notes['update/processed'] = implode("\n", $to_notes['update/processed']);
384
  endif;
385
 
386
- if (isset($to_notes['cats']) and is_array($to_notes['cats'])) :
387
- $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
388
- endif;
389
- if (isset($to_notes['tags']) and is_array($to_notes['tags'])) :
390
- $to_notes['tags'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['tags']);
 
 
 
 
 
 
 
 
 
 
391
  endif;
392
-
393
  // Collapse the author mapping rule structure back into a flat string
394
  if (isset($to_notes['map authors'])) :
395
  $ma = array();
@@ -471,6 +558,14 @@ class SyndicatedLink {
471
  return $ret;
472
  } /* SyndicatedLink::setting () */
473
 
 
 
 
 
 
 
 
 
474
  function uri () {
475
  return (is_object($this->link) ? $this->link->link_rss : NULL);
476
  } /* SyndicatedLink::uri () */
@@ -498,6 +593,32 @@ class SyndicatedLink {
498
  return $this->property_cascade($fromFeed, 'link_name', 'feed/title', 'get_title');
499
  } /* SyndicatedLink::name () */
500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
501
  function ttl () {
502
  if (is_object($this->magpie)) :
503
  $channel = $this->magpie->channel;
@@ -613,5 +734,11 @@ class SyndicatedLink {
613
 
614
  return $wpdb->escape(trim(strtolower($ret)));
615
  } /* SyndicatedLink:syndicated_status () */
 
 
 
 
 
 
616
  } // class SyndicatedLink
617
 
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'])) :
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',
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
 
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
 
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
 
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
 
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();
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 () */
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;
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
 
syndicatedpost.class.php CHANGED
@@ -10,7 +10,7 @@ require_once(dirname(__FILE__).'/feedtime.class.php');
10
  * different feed formats, which may be useful to FeedWordPress users
11
  * who make use of feed data in PHP add-ons and filters.
12
  *
13
- * @version 2010.0531
14
  */
15
  class SyndicatedPost {
16
  var $item = null; // MagpieRSS representation
@@ -49,12 +49,12 @@ class SyndicatedPost {
49
  $this->item = $item;
50
  endif;
51
 
52
- FeedWordPress::diagnostic('feed_items', 'Considering item ['.$this->guid().'] "'.$this->entry->get_title().'"');
53
-
54
  $this->link = $source;
55
  $this->feed = $source->magpie;
56
  $this->feedmeta = $source->settings;
57
 
 
 
58
  # Dealing with namespaces can get so fucking fucked.
59
  $this->xmlns['forward'] = $source->magpie->_XMLNS_FAMILIAR;
60
  $this->xmlns['reverse'] = array();
@@ -84,14 +84,16 @@ class SyndicatedPost {
84
  $fwp_channel = $this->feed; $fwp_feedmeta = $this->feedmeta;
85
 
86
  // Trigger global syndicated_item filter.
87
- $this->item = apply_filters('syndicated_item', $this->item, $this);
 
88
 
89
  // Allow for feed-specific syndicated_item filters.
90
- $this->item = apply_filters(
91
  "syndicated_item_".$source->uri(),
92
  $this->item,
93
  $this
94
  );
 
95
 
96
  # Filters can halt further processing by returning NULL
97
  if (is_null($this->item)) :
@@ -202,27 +204,49 @@ class SyndicatedPost {
202
  apply_filters('syndicated_item_enclosure_type', $enclosure->get_type(), $this);
203
  endforeach; endif;
204
 
205
- // In case you want to point back to the blog this was syndicated from
206
- if (isset($this->feed->channel['title'])) :
207
- $this->post['meta']['syndication_source'] = apply_filters('syndicated_item_source_title', $this->feed->channel['title'], $this);
208
- endif;
209
-
210
- if (isset($this->feed->channel['link'])) :
211
- $this->post['meta']['syndication_source_uri'] = apply_filters('syndicated_item_source_link', $this->feed->channel['link'], $this);
212
- endif;
 
 
 
 
 
 
 
 
 
 
213
 
214
  // Make use of atom:source data, if present in an aggregated feed
215
- if (isset($this->item['source_title'])) :
216
- $this->post['meta']['syndication_source_original'] = $this->item['source_title'];
217
- endif;
218
-
219
- if (isset($this->item['source_link'])) :
220
- $this->post['meta']['syndication_source_uri_original'] = $this->item['source_link'];
 
 
 
 
 
 
 
 
 
 
221
  endif;
222
 
223
- if (isset($this->item['source_id'])) :
224
- $this->post['meta']['syndication_source_id_original'] = $this->item['source_id'];
225
- endif;
 
 
226
 
227
  // Store information on human-readable and machine-readable comment URIs
228
 
@@ -254,51 +278,90 @@ class SyndicatedPost {
254
  // Store a hash of the post content for checking whether something needs to be updated
255
  $this->post['meta']['syndication_item_hash'] = $this->update_hash();
256
 
257
- // Feed-by-feed options for author and category creation
258
- $this->post['named']['unfamiliar']['author'] = (isset($this->feedmeta['unfamiliar author']) ? $this->feedmeta['unfamiliar author'] : null);
259
- $this->post['named']['unfamiliar']['category'] = (isset($this->feedmeta['unfamiliar category']) ? $this->feedmeta['unfamiliar category'] : null);
260
-
261
- // Categories: start with default categories, if any
262
- $fc = get_option("feedwordpress_syndication_cats");
263
- if ($fc) :
264
- $this->post['named']['preset/category'] = explode("\n", $fc);
265
- else :
266
- $this->post['named']['preset/category'] = array();
267
  endif;
268
 
269
- if (isset($this->feedmeta['cats']) and is_array($this->feedmeta['cats'])) :
270
- $this->post['named']['preset/category'] = array_merge($this->post['named']['preset/category'], $this->feedmeta['cats']);
 
271
  endif;
272
-
 
273
  // Now add categories from the post, if we have 'em
274
- $this->post['named']['category'] = array();
275
- if ( isset($this->item['category#']) ) :
276
- for ($i = 1; $i <= $this->item['category#']; $i++) :
277
- $cat_idx = (($i > 1) ? "#{$i}" : "");
278
- $cat = $this->item["category{$cat_idx}"];
279
-
280
- if ( isset($this->feedmeta['cat_split']) and strlen($this->feedmeta['cat_split']) > 0) :
281
- $pcre = "\007".$this->feedmeta['cat_split']."\007";
282
- $this->post['named']['category'] = array_merge($this->post['named']['category'], preg_split($pcre, $cat, -1 /*=no limit*/, PREG_SPLIT_NO_EMPTY));
283
- else :
284
- $this->post['named']['category'][] = $cat;
285
- endif;
286
- endfor;
287
- endif;
288
- $this->post['named']['category'] = apply_filters('syndicated_item_categories', $this->post['named']['category'], $this);
 
 
 
 
 
 
 
 
289
 
290
  // Tags: start with default tags, if any
291
- $ft = get_option("feedwordpress_syndication_tags");
292
- if ($ft) :
293
- $this->post['tags_input'] = explode(FEEDWORDPRESS_CAT_SEPARATOR, $ft);
294
- else :
295
- $this->post['tags_input'] = array();
296
  endif;
297
 
298
- if (isset($this->feedmeta['tags']) and is_array($this->feedmeta['tags'])) :
299
- $this->post['tags_input'] = array_merge($this->post['tags_input'], $this->feedmeta['tags']);
 
300
  endif;
301
- $this->post['tags_input'] = apply_filters('syndicated_item_tags', $this->post['tags_input'], $this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  endif;
303
  } /* SyndicatedPost::SyndicatedPost() */
304
 
@@ -349,60 +412,48 @@ class SyndicatedPost {
349
  switch ($node) :
350
  case 'feed' :
351
  case 'channel' :
352
- $method = "get_${node}_tags";
353
  $node = array_shift($path);
 
 
354
  break;
355
  case 'item' :
356
  $node = array_shift($path);
357
  default :
 
358
  $method = NULL;
359
  endswitch;
360
 
361
- $data = array();
362
- if (!is_null($node)) :
363
- list($namespaces, $element) = $this->xpath_extended_name($node);
364
-
365
- $matches = array();
366
- foreach ($namespaces as $ns) :
367
- if (!is_null($method)) :
368
- $el = $this->link->simplepie->{$method}($ns, $element);
369
- else :
370
- $el = $this->entry->get_item_tags($ns, $element);
371
- endif;
372
-
373
- if (!is_null($el)) :
374
- $matches = array_merge($matches, $el);
375
- endif;
376
- endforeach;
377
- $data = $matches;
378
-
379
- $node = array_shift($path);
380
- endif;
381
-
382
  while (!is_null($node)) :
383
  if (strlen($node) > 0) :
384
  $matches = array();
385
-
386
- list($ns, $element) = $this->xpath_extended_name($node);
387
-
388
- if (preg_match('/^@(.*)$/', $element, $ref)) :
389
- $element = $ref[1];
390
- $axis = 'attribs';
391
- else :
392
- $axis = 'child';
393
- endif;
394
 
395
  foreach ($data as $datum) :
396
- foreach ($namespaces as $ns) :
397
- if (!is_string($datum)
398
- and isset($datum[$axis][$ns][$element])) :
399
- if (is_string($datum[$axis][$ns][$element])) :
400
- $matches[] = $datum[$axis][$ns][$element];
401
- else :
402
- $matches = array_merge($matches, $datum[$axis][$ns][$element]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403
  endif;
404
- endif;
405
- endforeach;
406
  endforeach;
407
 
408
  $data = $matches;
@@ -421,6 +472,34 @@ class SyndicatedPost {
421
  return $matches;
422
  } /* SyndicatedPost::query() */
423
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
  function xpath_default_namespace () {
425
  // Get the default namespace.
426
  $type = $this->link->simplepie->get_type();
@@ -439,20 +518,40 @@ class SyndicatedPost {
439
  endif;
440
  return $defaultNS;
441
  } /* SyndicatedPost::xpath_default_namespace() */
442
-
443
- function xpath_extended_name ($node) {
444
  $ns = NULL; $element = NULL;
445
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
446
  if (substr($node, 0, 1)=='@') :
447
  $attr = '@'; $node = substr($node, 1);
448
  else :
449
  $attr = '';
450
  endif;
451
-
452
  if (preg_match('/^{([^}]*)}(.*)$/', $node, $ref)) :
453
- $ns = array($ref[1]); $element = $ref[2];
454
  elseif (strpos($node, ':') !== FALSE) :
455
  list($xmlns, $element) = explode(':', $node, 2);
 
456
  if (isset($this->xmlns['reverse'][$xmlns])) :
457
  $ns = $this->xmlns['reverse'][$xmlns];
458
  else :
@@ -460,17 +559,24 @@ class SyndicatedPost {
460
  endif;
461
 
462
  // Fucking SimplePie. For attributes in default xmlns.
463
- if ($xmlns==$this->xmlns['forward'][$defaultNS[0]]) :
 
 
464
  $ns[] = '';
465
  endif;
 
 
 
 
 
 
466
  else :
467
  // Often in SimplePie, the default namespace gets stored
468
  // as an empty string rather than a URL.
469
  $ns = array($this->xpath_default_namespace(), '');
470
- $element = $node;
471
  endif;
472
- return array(array_unique($ns), $attr.$element);
473
- } /* SyndicatedPost::xpath_extended_name () */
474
 
475
  function content () {
476
  $content = NULL;
@@ -482,7 +588,7 @@ class SyndicatedPost {
482
  $content = $this->item['xhtml']['div'];
483
  elseif (isset($this->item['content']['encoded']) and $this->item['content']['encoded']):
484
  $content = $this->item['content']['encoded'];
485
- else:
486
  $content = $this->item['description'];
487
  endif;
488
  return $content;
@@ -537,6 +643,7 @@ class SyndicatedPost {
537
 
538
  function published ($fallback = true, $default = NULL) {
539
  $date = '';
 
540
 
541
  # RSS is a fucking mess. Figure out whether we have a date in
542
  # <dc:date>, <issued>, <pubDate>, etc., and get it into Unix
@@ -575,6 +682,7 @@ class SyndicatedPost {
575
 
576
  function updated ($fallback = true, $default = -1) {
577
  $date = '';
 
578
 
579
  # As far as I know, only dcterms and Atom have reliable ways to
580
  # specify when something was *modified* last. If neither is
@@ -627,7 +735,7 @@ class SyndicatedPost {
627
  // unique identifier, so we'll have to cobble together
628
  // a tag: URI that might work for us. The base of the
629
  // URI will be the host name of the feed source ...
630
- $bits = parse_url($this->feedmeta['link/uri']);
631
  $guid = 'tag:'.$bits['host'];
632
 
633
  // If we have a date of creation, then we can use that
@@ -646,7 +754,9 @@ class SyndicatedPost {
646
  // title *and* the same link for two different items. So
647
  // this is about the best we can do.
648
  else :
649
- $guid .= '://'.md5($this->item['link'].'/'.$this->item['title']);
 
 
650
  endif;
651
  endif;
652
  return $guid;
@@ -680,8 +790,11 @@ class SyndicatedPost {
680
  $author['name'] = $this->feed->channel['title'];
681
  endif;
682
  endif;
 
 
683
  else :
684
- $author['name'] = $this->feed->channel['title'];
 
685
  endif;
686
 
687
  if (isset($this->item['author_email'])):
@@ -701,6 +814,27 @@ class SyndicatedPost {
701
  return $author;
702
  } /* SyndicatedPost::author() */
703
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
704
  /**
705
  * SyndicatedPost::isTaggedAs: Test whether a feed item is
706
  * tagged / categorized with a given string. Case and leading and
@@ -785,6 +919,34 @@ class SyndicatedPost {
785
  return $enclosures;
786
  } /* SyndicatedPost::enclosures() */
787
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
788
  function comment_link () {
789
  $url = null;
790
 
@@ -902,7 +1064,7 @@ class SyndicatedPost {
902
  if ($set and $set != 'no') :
903
  // Fallback: if we don't have anything better, use the
904
  // item link from the feed
905
- $obj->_base = $obj->item['link']; // Reset the base for resolving relative URIs
906
 
907
  // What we should do here, properly, is to use
908
  // SimplePie_Item::get_base() -- but that method is
@@ -1028,7 +1190,7 @@ class SyndicatedPost {
1028
  and !$frozen_post
1029
  and !$frozen_feed
1030
  );
1031
-
1032
  if ($updated) :
1033
  $this->_freshness = 1; // Updated content
1034
  $this->_wp_id = $result->id;
@@ -1067,7 +1229,7 @@ class SyndicatedPost {
1067
  if ($freshness > 0) :
1068
  # -- Look up, or create, numeric ID for author
1069
  $this->post['post_author'] = $this->author_id (
1070
- FeedWordPress::on_unfamiliar('author', $this->post['named']['unfamiliar']['author'])
1071
  );
1072
 
1073
  if (is_null($this->post['post_author'])) :
@@ -1076,32 +1238,77 @@ class SyndicatedPost {
1076
  endif;
1077
 
1078
  if (!$this->filtered() and $freshness > 0) :
1079
- # -- Look up, or create, numeric ID for categories
1080
- list($pcats, $ptags) = $this->category_ids (
1081
- $this->post['named']['category'],
1082
- FeedWordPress::on_unfamiliar('category', $this->post['named']['unfamiliar']['category']),
1083
- /*tags_too=*/ true
1084
  );
1085
 
1086
- $this->post['post_category'] = $pcats;
1087
- $this->post['tags_input'] = array_merge($this->post['tags_input'], $ptags);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1088
 
1089
- if (is_null($this->post['post_category'])) :
1090
- // filter mode on, no matching categories; drop the post
1091
  $this->post = NULL;
1092
- else :
1093
- // filter mode off or at least one match; now add on the feed and global presets
1094
- $this->post['post_category'] = array_merge (
1095
- $this->post['post_category'],
1096
- $this->category_ids (
1097
- $this->post['named']['preset/category'],
1098
- 'default'
1099
- )
1100
- );
 
 
1101
 
1102
- if (count($this->post['post_category']) < 1) :
1103
- $this->post['post_category'][] = 1; // Default to category 1 ("Uncategorized" / "General") if nothing else
1104
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1105
  endif;
1106
  endif;
1107
 
@@ -1161,78 +1368,23 @@ class SyndicatedPost {
1161
 
1162
  $dbpost = $this->normalize_post(/*new=*/ true);
1163
  if (!is_null($dbpost)) :
1164
- if ($this->use_api('wp_insert_post')) :
1165
- $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
1166
 
1167
- // This is a ridiculous fucking kludge necessitated by WordPress 2.6 munging authorship meta-data
1168
- add_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1169
 
1170
- // Kludge to prevent kses filters from stripping the
1171
- // content of posts when updating without a logged in
1172
- // user who has `unfiltered_html` capability.
1173
- add_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1174
-
1175
- $this->_wp_id = wp_insert_post($dbpost);
1176
-
1177
- // Turn off ridiculous fucking kludges #1 and #2
1178
- remove_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1179
- remove_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1180
-
1181
- $this->validate_post_id($dbpost, array(__CLASS__, __FUNCTION__));
1182
-
1183
- // Unfortunately, as of WordPress 2.3, wp_insert_post()
1184
- // *still* offers no way to use a guid of your choice,
1185
- // and munges your post modified timestamp, too.
1186
- $result = $wpdb->query("
1187
- UPDATE $wpdb->posts
1188
- SET
1189
- guid='{$dbpost['guid']}',
1190
- post_modified='{$dbpost['post_modified']}',
1191
- post_modified_gmt='{$dbpost['post_modified_gmt']}'
1192
- WHERE ID='{$this->_wp_id}'
1193
- ");
1194
- else :
1195
- # The right way to do this is the above. But, alas,
1196
- # in earlier versions of WordPress, wp_insert_post has
1197
- # too much behavior (mainly related to pings) that can't
1198
- # be overridden. In WordPress 1.5, it's enough of a
1199
- # resource hog to make PHP segfault after inserting
1200
- # 50-100 posts. This can get pretty annoying, especially
1201
- # if you are trying to update your feeds for the first
1202
- # time.
1203
-
1204
- $result = $wpdb->query("
1205
- INSERT INTO $wpdb->posts
1206
- SET
1207
- guid = '{$dbpost['guid']}',
1208
- post_author = '{$dbpost['post_author']}',
1209
- post_date = '{$dbpost['post_date']}',
1210
- post_date_gmt = '{$dbpost['post_date_gmt']}',
1211
- post_content = '{$dbpost['post_content']}',"
1212
- .(isset($dbpost['post_excerpt']) ? "post_excerpt = '{$dbpost['post_excerpt']}'," : "")."
1213
- post_title = '{$dbpost['post_title']}',
1214
- post_name = '{$dbpost['post_name']}',
1215
- post_modified = '{$dbpost['post_modified']}',
1216
- post_modified_gmt = '{$dbpost['post_modified_gmt']}',
1217
- comment_status = '{$dbpost['comment_status']}',
1218
- ping_status = '{$dbpost['ping_status']}',
1219
- post_status = '{$dbpost['post_status']}'
1220
- ");
1221
- $this->_wp_id = $wpdb->insert_id;
1222
 
1223
- $this->validate_post_id($dbpost, array(__CLASS__, __FUNCTION__));
 
 
1224
 
1225
- // WordPress 1.5.x - 2.0.x
1226
- wp_set_post_cats('1', $this->wp_id(), $this->post['post_category']);
1227
-
1228
- // Since we are not going through official channels, we need to
1229
- // manually tell WordPress that we've published a new post.
1230
- // We need to make sure to do this in order for FeedWordPress
1231
- // to play well with the staticize-reloaded plugin (something
1232
- // that a large aggregator website is going to *want* to be
1233
- // able to use).
1234
- do_action('publish_post', $this->_wp_id);
1235
- endif;
1236
  endif;
1237
  } /* SyndicatedPost::insert_new() */
1238
 
@@ -1242,76 +1394,31 @@ class SyndicatedPost {
1242
  // Why the fuck doesn't wp_insert_post already do this?
1243
  $dbpost = $this->normalize_post(/*new=*/ false);
1244
  if (!is_null($dbpost)) :
1245
- if ($this->use_api('wp_insert_post')) :
1246
- $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
1247
 
1248
- // This is a ridiculous fucking kludge necessitated by WordPress 2.6 munging authorship meta-data
1249
- add_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1250
 
1251
- // Kludge to prevent kses filters from stripping the
1252
- // content of posts when updating without a logged in
1253
- // user who has `unfiltered_html` capability.
1254
- add_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1255
-
1256
- // Don't munge status fields that the user may have reset manually
1257
- if (function_exists('get_post_field')) :
1258
- $doNotMunge = array('post_status', 'comment_status', 'ping_status');
1259
- foreach ($doNotMunge as $field) :
1260
- $dbpost[$field] = get_post_field($field, $this->wp_id());
1261
- endforeach;
1262
- endif;
1263
 
1264
- $this->_wp_id = wp_insert_post($dbpost);
1265
-
1266
- // Turn off ridiculous fucking kludges #1 and #2
1267
- remove_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1268
- remove_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1269
 
1270
- $this->validate_post_id($dbpost, array(__CLASS__, __FUNCTION__));
 
 
1271
 
1272
- // Unfortunately, as of WordPress 2.3, wp_insert_post()
1273
- // munges your post modified timestamp.
1274
- $result = $wpdb->query("
1275
- UPDATE $wpdb->posts
1276
- SET
1277
- post_modified='{$dbpost['post_modified']}',
1278
- post_modified_gmt='{$dbpost['post_modified_gmt']}'
1279
- WHERE ID='{$this->_wp_id}'
1280
- ");
1281
- else :
1282
-
1283
- $result = $wpdb->query("
1284
- UPDATE $wpdb->posts
1285
- SET
1286
- post_author = '{$dbpost['post_author']}',
1287
- post_content = '{$dbpost['post_content']}',"
1288
- .(isset($dbpost['post_excerpt']) ? "post_excerpt = '{$dbpost['post_excerpt']}'," : "")."
1289
- post_title = '{$dbpost['post_title']}',
1290
- post_name = '{$dbpost['post_name']}',
1291
- post_modified = '{$dbpost['post_modified']}',
1292
- post_modified_gmt = '{$dbpost['post_modified_gmt']}'
1293
- WHERE guid='{$dbpost['guid']}'
1294
- ");
1295
-
1296
- // WordPress 2.1.x and up
1297
- if (function_exists('wp_set_post_categories')) :
1298
- wp_set_post_categories($this->wp_id(), $this->post['post_category']);
1299
- // WordPress 1.5.x - 2.0.x
1300
- elseif (function_exists('wp_set_post_cats')) :
1301
- wp_set_post_cats('1', $this->wp_id(), $this->post['post_category']);
1302
- // This should never happen.
1303
- else :
1304
- FeedWordPress::critical_bug(__CLASS__.'::'.__FUNCTION.'(): no post categorizing function', array("dbpost" => $dbpost, "this" => $this), __LINE__);
1305
- endif;
1306
-
1307
- // Since we are not going through official channels, we need to
1308
- // manually tell WordPress that we've published a new post.
1309
- // We need to make sure to do this in order for FeedWordPress
1310
- // to play well with the staticize-reloaded plugin (something
1311
- // that a large aggregator website is going to *want* to be
1312
- // able to use).
1313
- do_action('edit_post', $this->post['ID']);
1314
- endif;
1315
  endif;
1316
  } /* SyndicatedPost::update_existing() */
1317
 
@@ -1335,13 +1442,21 @@ class SyndicatedPost {
1335
  endif;
1336
  endforeach;
1337
 
1338
- if (strlen($out['post_title'].$out['post_content'].$out['post_excerpt']) == 0) :
 
 
1339
  // FIXME: Option for filtering out empty posts
1340
  endif;
1341
  if (strlen($out['post_title'])==0) :
1342
  $offset = (int) get_option('gmt_offset') * 60 * 60;
1343
- $out['post_title'] =
1344
- $this->post['meta']['syndication_source']
 
 
 
 
 
 
1345
  .' '.gmdate('Y-m-d H:i:s', $this->published() + $offset);
1346
  // FIXME: Option for what to fill a blank title with...
1347
  endif;
@@ -1483,6 +1598,11 @@ class SyndicatedPost {
1483
  $email = (isset($a['email']) ? $a['email'] : NULL);
1484
  $authorUrl = (isset($a['uri']) ? $a['uri'] : NULL);
1485
 
 
 
 
 
 
1486
  $match_author_by_email = !('yes' == get_option("feedwordpress_do_not_match_author_by_email"));
1487
  if ($match_author_by_email and !FeedWordPress::is_null_email($email)) :
1488
  $test_email = $email;
@@ -1492,6 +1612,26 @@ class SyndicatedPost {
1492
 
1493
  // Never can be too careful...
1494
  $login = sanitize_user($author, /*strict=*/ true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1495
  $login = apply_filters('pre_user_login', $login);
1496
 
1497
  $nice_author = sanitize_title($author);
@@ -1524,14 +1664,11 @@ class SyndicatedPost {
1524
  // First try the user core data table.
1525
  $id = $wpdb->get_var(
1526
  "SELECT ID FROM $wpdb->users
1527
- WHERE
1528
- TRIM(LCASE(user_login)) = TRIM(LCASE('$login'))
1529
- OR (
1530
- LENGTH(TRIM(LCASE(user_email))) > 0
1531
- AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
1532
- )
1533
- OR TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author'))
1534
- ");
1535
 
1536
  // If that fails, look for aliases in the user meta data table
1537
  if (is_null($id)) :
@@ -1560,10 +1697,6 @@ class SyndicatedPost {
1560
  // more than one user account with an empty e-mail address, so we
1561
  // need *something* here. Ugh.
1562
  if (strlen($email) == 0 or FeedWordPress::is_null_email($email)) :
1563
- $hostUrl = $this->link->homepage();
1564
- if (is_null($hostUrl) or (strlen($hostUrl) < 0)) :
1565
- $hostUrl = $this->link->uri();
1566
- endif;
1567
  $url = parse_url($hostUrl);
1568
  $email = $nice_author.'@'.$url['host'];
1569
  endif;
@@ -1576,8 +1709,30 @@ class SyndicatedPost {
1576
  $userdata['user_email'] = $email;
1577
  $userdata['user_url'] = $authorUrl;
1578
  $userdata['display_name'] = $author;
1579
-
1580
- $id = wp_insert_user($userdata);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1581
  elseif (is_numeric($unfamiliar_author) and get_userdata((int) $unfamiliar_author)) :
1582
  $id = (int) $unfamiliar_author;
1583
  elseif ($unfamiliar_author === 'default') :
@@ -1592,9 +1747,23 @@ class SyndicatedPost {
1592
  return $id;
1593
  } // function SyndicatedPost::author_id ()
1594
 
1595
- // look up (and create) category ids from a list of categories
1596
- function category_ids ($cats, $unfamiliar_category = 'create', $tags_too = false) {
1597
- global $wpdb;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1598
 
1599
  // We need to normalize whitespace because (1) trailing
1600
  // whitespace can cause PHP and MySQL not to see eye to eye on
@@ -1604,59 +1773,98 @@ class SyndicatedPost {
1604
  // distinction between 'Computers' and 'Computers '
1605
  $cats = array_map('trim', $cats);
1606
 
1607
- $tags = array();
1608
-
1609
- $cat_ids = array ();
 
 
1610
  foreach ($cats as $cat_name) :
1611
- if (preg_match('/^{#([0-9]+)}$/', $cat_name, $backref)) :
1612
- $cat_id = (int) $backref[1];
1613
- if (term_exists($cat_id, 'category')) :
1614
- $cat_ids[] = $cat_id;
1615
- elseif (get_category($cat_id)) :
1616
- $cat_ids[] = $cat_id;
 
 
 
 
 
 
 
1617
  endif;
1618
  elseif (strlen($cat_name) > 0) :
1619
- $esc = $wpdb->escape($cat_name);
1620
- $resc = $wpdb->escape(preg_quote($cat_name));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1621
 
1622
- $cat_id = term_exists($cat_name, 'category');
1623
- if ($cat_id) :
1624
- $cat_ids[] = $cat_id['term_id'];
1625
- // There must be a better way to do this...
1626
- elseif ($results = $wpdb->get_results(
1627
- "SELECT term_id
1628
- FROM $wpdb->term_taxonomy
1629
- WHERE
1630
- LOWER(description) RLIKE
1631
- CONCAT('(^|\\n)a\\.?k\\.?a\\.?( |\\t)*:?( |\\t)*', LOWER('{$resc}'), '( |\\t|\\r)*(\\n|\$)')"
1632
- )) :
1633
- foreach ($results as $term) :
1634
- $cat_ids[] = (int) $term->term_id;
1635
- endforeach;
1636
- elseif ('tag'==$unfamiliar_category) :
1637
- $tags[] = $cat_name;
1638
- elseif ('create'===$unfamiliar_category) :
1639
- $term = wp_insert_term($cat_name, 'category');
1640
- if (is_wp_error($term)) :
1641
- FeedWordPress::noncritical_bug('term insertion problem', array('cat_name' => $cat_name, 'term' => $term, 'this' => $this), __LINE__);
1642
- else :
1643
- $cat_ids[] = $term['term_id'];
1644
  endif;
1645
  endif;
1646
  endif;
1647
  endforeach;
1648
 
1649
- if ((count($cat_ids) == 0) and ($unfamiliar_category === 'filter')) :
1650
- $cat_ids = NULL; // Drop the post
1651
- else :
1652
- $cat_ids = array_unique($cat_ids);
 
 
 
1653
  endif;
1654
 
1655
- if ($tags_too) : $ret = array($cat_ids, $tags);
1656
- else : $ret = $cat_ids;
1657
- endif;
 
 
 
 
 
 
 
 
1658
 
1659
- return $ret;
 
 
 
1660
  } // function SyndicatedPost::category_ids ()
1661
 
1662
  function use_api ($tag) {
10
  * different feed formats, which may be useful to FeedWordPress users
11
  * who make use of feed data in PHP add-ons and filters.
12
  *
13
+ * @version 2010.0814
14
  */
15
  class SyndicatedPost {
16
  var $item = null; // MagpieRSS representation
49
  $this->item = $item;
50
  endif;
51
 
 
 
52
  $this->link = $source;
53
  $this->feed = $source->magpie;
54
  $this->feedmeta = $source->settings;
55
 
56
+ FeedWordPress::diagnostic('feed_items', 'Considering item ['.$this->guid().'] "'.$this->entry->get_title().'"');
57
+
58
  # Dealing with namespaces can get so fucking fucked.
59
  $this->xmlns['forward'] = $source->magpie->_XMLNS_FAMILIAR;
60
  $this->xmlns['reverse'] = array();
84
  $fwp_channel = $this->feed; $fwp_feedmeta = $this->feedmeta;
85
 
86
  // Trigger global syndicated_item filter.
87
+ $changed = apply_filters('syndicated_item', $this->item, $this);
88
+ $this->item = $changed;
89
 
90
  // Allow for feed-specific syndicated_item filters.
91
+ $changed = apply_filters(
92
  "syndicated_item_".$source->uri(),
93
  $this->item,
94
  $this
95
  );
96
+ $this->item = $changed;
97
 
98
  # Filters can halt further processing by returning NULL
99
  if (is_null($this->item)) :
204
  apply_filters('syndicated_item_enclosure_type', $enclosure->get_type(), $this);
205
  endforeach; endif;
206
 
207
+ // In case you want to point back to the blog this was
208
+ // syndicated from.
209
+
210
+ $sourcemeta['syndication_source'] = apply_filters(
211
+ 'syndicated_item_source_title',
212
+ $this->link->name(),
213
+ $this
214
+ );
215
+ $sourcemeta['syndication_source_uri'] = apply_filters(
216
+ 'syndicated_item_source_link',
217
+ $this->link->homepage(),
218
+ $this
219
+ );
220
+ $sourcemeta['syndication_source_id'] = apply_filters(
221
+ 'syndicated_item_source_id',
222
+ $this->link->guid(),
223
+ $this
224
+ );
225
 
226
  // Make use of atom:source data, if present in an aggregated feed
227
+ $entry_source = $this->source();
228
+ if (!is_null($entry_source)) :
229
+ foreach ($entry_source as $what => $value) :
230
+ if (!is_null($value)) :
231
+ if ($what=='title') : $key = 'syndication_source';
232
+ elseif ($what=='feed') : $key = 'syndication_feed';
233
+ else : $key = "syndication_source_${what}";
234
+ endif;
235
+
236
+ $sourcemeta["${key}_original"] = apply_filters(
237
+ 'syndicated_item_original_source_'.$what,
238
+ $value,
239
+ $this
240
+ );
241
+ endif;
242
+ endforeach;
243
  endif;
244
 
245
+ foreach ($sourcemeta as $meta_key => $value) :
246
+ if (!is_null($value)) :
247
+ $this->post['meta'][$meta_key] = $value;
248
+ endif;
249
+ endforeach;
250
 
251
  // Store information on human-readable and machine-readable comment URIs
252
 
278
  // Store a hash of the post content for checking whether something needs to be updated
279
  $this->post['meta']['syndication_item_hash'] = $this->update_hash();
280
 
281
+ // Categories: start with default categories, if any.
282
+ $cats = array();
283
+ if ('no' != $this->link->setting('add/category', NULL, 'yes')) :
284
+ $fc = get_option("feedwordpress_syndication_cats");
285
+ if ($fc) :
286
+ $cats = array_merge($cats, explode("\n", $fc));
287
+ endif;
 
 
 
288
  endif;
289
 
290
+ $fc = $this->link->setting('cats', NULL, array());
291
+ if (is_array($fc)) :
292
+ $cats = array_merge($cats, $fc);
293
  endif;
294
+ $this->post['pretax']['category'] = $cats;
295
+
296
  // Now add categories from the post, if we have 'em
297
+ $cats = array();
298
+ $post_cats = $this->entry->get_categories();
299
+ if (is_array($post_cats)) : foreach ($post_cats as $cat) :
300
+ $cat_name = $cat->get_term();
301
+ if (!$cat_name) : $cat_name = $cat->get_label(); endif;
302
+
303
+ if ($this->link->setting('cat_split', NULL, NULL)) :
304
+ $pcre = "\007".$this->feedmeta['cat_split']."\007";
305
+ $cats = array_merge(
306
+ $cats,
307
+ preg_split(
308
+ $pcre,
309
+ $cat_name,
310
+ -1 /*=no limit*/,
311
+ PREG_SPLIT_NO_EMPTY
312
+ )
313
+ );
314
+ else :
315
+ $cats[] = $cat_name;
316
+ endif;
317
+ endforeach; endif;
318
+
319
+ $this->post['taxed']['category'] = apply_filters('syndicated_item_categories', $cats, $this);
320
 
321
  // Tags: start with default tags, if any
322
+ $tags = array();
323
+ if ('no' != $this->link->setting('add/post_tag', NULL, 'yes')) :
324
+ $ft = get_option("feedwordpress_syndication_tags", NULL);
325
+ $tags = (is_null($ft) ? array() : explode(FEEDWORDPRESS_CAT_SEPARATOR, $ft));
 
326
  endif;
327
 
328
+ $ft = $this->link->setting('tags', NULL, array());
329
+ if (is_array($ft)) :
330
+ $tags = array_merge($tags, $ft);
331
  endif;
332
+ $this->post['pretax']['post_tag'] = $tags;
333
+
334
+ // Scan post for /a[@rel='tag'] and use as tags if present
335
+ $tags = $this->inline_tags();
336
+ $this->post['taxed']['post_tag'] = apply_filters('syndicated_item_tags', $tags, $this);
337
+
338
+ $taxonomies = $this->link->taxonomies();
339
+ $feedTerms = $this->link->setting('terms', NULL, array());
340
+ $globalTerms = get_option('feedwordpress_syndication_terms', array());
341
+
342
+ $specials = array('category' => 'cats', 'post_tag' => 'tags');
343
+ foreach ($taxonomies as $tax) :
344
+ if (!isset($specials[$tax])) :
345
+ $terms = array();
346
+
347
+ // See if we should get the globals
348
+ if ('no' != $this->link->setting("add/$tax", NULL, 'yes')) :
349
+ if (isset($globalTerms[$tax])) :
350
+ $terms = $globalTerms[$tax];
351
+ endif;
352
+ endif;
353
+
354
+ // Now merge in the locals
355
+ if (isset($feedTerms[$tax])) :
356
+ $terms = array_merge($terms, $feedTerms[$tax]);
357
+ endif;
358
+
359
+ // That's all, folks.
360
+ $this->post['pretax'][$tax] = $terms;
361
+ endif;
362
+ endforeach;
363
+
364
+ $this->post['post_type'] = apply_filters('syndicated_post_type', $this->link->setting('syndicated post type', 'syndicated_post_type', 'post'), $this);
365
  endif;
366
  } /* SyndicatedPost::SyndicatedPost() */
367
 
412
  switch ($node) :
413
  case 'feed' :
414
  case 'channel' :
 
415
  $node = array_shift($path);
416
+ $data = $this->get_feed_root_element();
417
+ $data = array_merge($data, $this->get_feed_channel_elements());
418
  break;
419
  case 'item' :
420
  $node = array_shift($path);
421
  default :
422
+ $data = array($this->entry->data);
423
  $method = NULL;
424
  endswitch;
425
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
426
  while (!is_null($node)) :
427
  if (strlen($node) > 0) :
428
  $matches = array();
429
+
430
+ list($axis, $element) = $this->xpath_name_and_axis($node);
 
 
 
 
 
 
 
431
 
432
  foreach ($data as $datum) :
433
+ if (!is_string($datum) and isset($datum[$axis])) :
434
+ foreach ($datum[$axis] as $ns => $elements) :
435
+ if (isset($elements[$element])) :
436
+ // Potential match.
437
+ // Check namespace.
438
+ if (is_string($elements[$element])) : // Attribute
439
+ $addenda = array($elements[$element]);
440
+ $contexts = array($datum);
441
+ else : // Element
442
+ $addenda = $elements[$element];
443
+ $contexts = $elements[$element];
444
+ endif;
445
+
446
+ foreach ($addenda as $index => $addendum) :
447
+ $context = $contexts[$index];
448
+
449
+ $namespaces = $this->xpath_possible_namespaces($node, $context);
450
+ if (in_array($ns, $namespaces)) :
451
+ $matches[] = $addendum;
452
+ endif;
453
+ endforeach;
454
  endif;
455
+ endforeach;
456
+ endif;
457
  endforeach;
458
 
459
  $data = $matches;
472
  return $matches;
473
  } /* SyndicatedPost::query() */
474
 
475
+ function get_feed_root_element () {
476
+ $matches = array();
477
+ foreach ($this->link->simplepie->data['child'] as $ns => $root) :
478
+ foreach ($root as $element => $data) :
479
+ $matches = array_merge($matches, $data);
480
+ endforeach;
481
+ endforeach;
482
+ return $matches;
483
+ } /* SyndicatedPost::get_feed_root_element() */
484
+
485
+ function get_feed_channel_elements () {
486
+ $rss = array(
487
+ SIMPLEPIE_NAMESPACE_RSS_090,
488
+ SIMPLEPIE_NAMESPACE_RSS_10,
489
+ 'http://backend.userland.com/RSS2',
490
+ SIMPLEPIE_NAMESPACE_RSS_20,
491
+ );
492
+
493
+ $matches = array();
494
+ foreach ($rss as $ns) :
495
+ $data = $this->link->simplepie->get_feed_tags($ns, 'channel');
496
+ if (!is_null($data)) :
497
+ $matches = array_merge($matches, $data);
498
+ endif;
499
+ endforeach;
500
+ return $matches;
501
+ } /* SyndicatedPost::get_feed_channel_elements() */
502
+
503
  function xpath_default_namespace () {
504
  // Get the default namespace.
505
  $type = $this->link->simplepie->get_type();
518
  endif;
519
  return $defaultNS;
520
  } /* SyndicatedPost::xpath_default_namespace() */
521
+
522
+ function xpath_name_and_axis ($node) {
523
  $ns = NULL; $element = NULL;
524
+
525
+ if (substr($node, 0, 1)=='@') :
526
+ $axis = 'attribs'; $node = substr($node, 1);
527
+ else :
528
+ $axis = 'child';
529
+ endif;
530
+
531
+ if (preg_match('/^{([^}]*)}(.*)$/', $node, $ref)) :
532
+ $element = $ref[2];
533
+ elseif (strpos($node, ':') !== FALSE) :
534
+ list($xmlns, $element) = explode(':', $node, 2);
535
+ else :
536
+ $element = $node;
537
+ endif;
538
+ return array($axis, $element);
539
+ } /* SyndicatedPost::xpath_local_name () */
540
+
541
+ function xpath_possible_namespaces ($node, $datum = array()) {
542
+ $ns = NULL; $element = NULL;
543
+
544
  if (substr($node, 0, 1)=='@') :
545
  $attr = '@'; $node = substr($node, 1);
546
  else :
547
  $attr = '';
548
  endif;
549
+
550
  if (preg_match('/^{([^}]*)}(.*)$/', $node, $ref)) :
551
+ $ns = array($ref[1]);
552
  elseif (strpos($node, ':') !== FALSE) :
553
  list($xmlns, $element) = explode(':', $node, 2);
554
+
555
  if (isset($this->xmlns['reverse'][$xmlns])) :
556
  $ns = $this->xmlns['reverse'][$xmlns];
557
  else :
559
  endif;
560
 
561
  // Fucking SimplePie. For attributes in default xmlns.
562
+ $defaultNS = $this->xpath_default_namespace();
563
+ if (isset($this->xmlns['forward'][$defaultNS])
564
+ and ($xmlns==$this->xmlns['forward'][$defaultNS])) :
565
  $ns[] = '';
566
  endif;
567
+
568
+ if (isset($datum['xmlns'])) :
569
+ if (isset($datum['xmlns'][$xmlns])) :
570
+ $ns[] = $datum['xmlns'][$xmlns];
571
+ endif;
572
+ endif;
573
  else :
574
  // Often in SimplePie, the default namespace gets stored
575
  // as an empty string rather than a URL.
576
  $ns = array($this->xpath_default_namespace(), '');
 
577
  endif;
578
+ return array_unique($ns);
579
+ } /* SyndicatedPost::xpath_possible_namespaces() */
580
 
581
  function content () {
582
  $content = NULL;
588
  $content = $this->item['xhtml']['div'];
589
  elseif (isset($this->item['content']['encoded']) and $this->item['content']['encoded']):
590
  $content = $this->item['content']['encoded'];
591
+ elseif (isset($this->item['description'])) :
592
  $content = $this->item['description'];
593
  endif;
594
  return $content;
643
 
644
  function published ($fallback = true, $default = NULL) {
645
  $date = '';
646
+ $epoch = null;
647
 
648
  # RSS is a fucking mess. Figure out whether we have a date in
649
  # <dc:date>, <issued>, <pubDate>, etc., and get it into Unix
682
 
683
  function updated ($fallback = true, $default = -1) {
684
  $date = '';
685
+ $epoch = null;
686
 
687
  # As far as I know, only dcterms and Atom have reliable ways to
688
  # specify when something was *modified* last. If neither is
735
  // unique identifier, so we'll have to cobble together
736
  // a tag: URI that might work for us. The base of the
737
  // URI will be the host name of the feed source ...
738
+ $bits = parse_url($this->link->uri());
739
  $guid = 'tag:'.$bits['host'];
740
 
741
  // If we have a date of creation, then we can use that
754
  // title *and* the same link for two different items. So
755
  // this is about the best we can do.
756
  else :
757
+ $link = $this->permalink();
758
+ if (is_null($link)) : $link = $this->link->uri(); endif;
759
+ $guid .= '://'.md5($link.'/'.$this->item['title']);
760
  endif;
761
  endif;
762
  return $guid;
790
  $author['name'] = $this->feed->channel['title'];
791
  endif;
792
  endif;
793
+ elseif ($this->link->name()) :
794
+ $author['name'] = $this->link->name();
795
  else :
796
+ $url = parse_url($this->link->uri());
797
+ $author['name'] = $url['host'];
798
  endif;
799
 
800
  if (isset($this->item['author_email'])):
814
  return $author;
815
  } /* SyndicatedPost::author() */
816
 
817
+ /**
818
+ * SyndicatedPost::inline_tags: Return a list of all the tags embedded
819
+ * in post content using the a[@rel="tag"] microformat.
820
+ *
821
+ * @since 2010.0630
822
+ * @return array of string values containing the name of each tag
823
+ */
824
+ function inline_tags () {
825
+ $tags = array();
826
+ $content = $this->content();
827
+ $pattern = FeedWordPressHTML::tagWithAttributeRegex('a', 'rel', 'tag');
828
+ preg_match_all($pattern, $content, $refs, PREG_SET_ORDER);
829
+ if (count($refs) > 0) :
830
+ foreach ($refs as $ref) :
831
+ $tag = FeedWordPressHTML::tagWithAttributeMatch($ref);
832
+ $tags[] = $tag['content'];
833
+ endforeach;
834
+ endif;
835
+ return $tags;
836
+ }
837
+
838
  /**
839
  * SyndicatedPost::isTaggedAs: Test whether a feed item is
840
  * tagged / categorized with a given string. Case and leading and
919
  return $enclosures;
920
  } /* SyndicatedPost::enclosures() */
921
 
922
+ function source ($what = NULL) {
923
+ $ret = NULL;
924
+ $source = $this->entry->get_source();
925
+ if ($source) :
926
+ $ret = array();
927
+ $ret['title'] = $source->get_title();
928
+ $ret['uri'] = $source->get_link();
929
+ $ret['feed'] = $source->get_link(0, 'self');
930
+
931
+ if ($id_tags = $source->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id')) :
932
+ $ret['id'] = $id_tags[0]['data'];
933
+ elseif ($id_tags = $source->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id')) :
934
+ $ret['id'] = $id_tags[0]['data'];
935
+ elseif ($id_tags = $source->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid')) :
936
+ $ret['id'] = $id_tags[0]['data'];
937
+ elseif ($id_tags = $source->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'guid')) :
938
+ $ret['id'] = $id_tags[0]['data'];
939
+ elseif ($id_tags = $source->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'guid')) :
940
+ $ret['id'] = $id_tags[0]['data'];
941
+ endif;
942
+ endif;
943
+
944
+ if (!is_null($what) and is_scalar($what)) :
945
+ $ret = $ret[$what];
946
+ endif;
947
+ return $ret;
948
+ }
949
+
950
  function comment_link () {
951
  $url = null;
952
 
1064
  if ($set and $set != 'no') :
1065
  // Fallback: if we don't have anything better, use the
1066
  // item link from the feed
1067
+ $obj->_base = $obj->permalink(); // Reset the base for resolving relative URIs
1068
 
1069
  // What we should do here, properly, is to use
1070
  // SimplePie_Item::get_base() -- but that method is
1190
  and !$frozen_post
1191
  and !$frozen_feed
1192
  );
1193
+
1194
  if ($updated) :
1195
  $this->_freshness = 1; // Updated content
1196
  $this->_wp_id = $result->id;
1229
  if ($freshness > 0) :
1230
  # -- Look up, or create, numeric ID for author
1231
  $this->post['post_author'] = $this->author_id (
1232
+ $this->link->setting('unfamiliar author', 'unfamiliar_author', 'create')
1233
  );
1234
 
1235
  if (is_null($this->post['post_author'])) :
1238
  endif;
1239
 
1240
  if (!$this->filtered() and $freshness > 0) :
1241
+ $consider = array(
1242
+ 'category' => array('abbr' => 'cats', 'domain' => array('category', 'post_tag')),
1243
+ 'post_tag' => array('abbr' => 'tags', 'domain' => array('post_tag')),
 
 
1244
  );
1245
 
1246
+ $termSet = array(); $valid = null;
1247
+ foreach ($consider as $what => $taxes) :
1248
+ if (!is_null($this->post)) : // Not filtered out yet
1249
+ # -- Look up, or create, numeric ID for categories
1250
+ $taxonomies = $this->link->setting("match/".$taxes['abbr'], 'match_'.$taxes['abbr'], $taxes['domain']);
1251
+
1252
+ // Eliminate dummy variables
1253
+ $taxonomies = array_filter($taxonomies, 'remove_dummy_zero');
1254
+
1255
+ $terms = $this->category_ids (
1256
+ $this->post['taxed'][$what],
1257
+ $this->link->setting("unfamiliar {$what}", "unfamiliar_{$what}", 'create:'.$what),
1258
+ /*taxonomies=*/ $taxonomies,
1259
+ array(
1260
+ 'singleton' => false, // I don't like surprises
1261
+ 'filters' => true,
1262
+ )
1263
+ );
1264
+
1265
+ if (is_null($terms) or is_null($termSet)) :
1266
+ // filtered out -- no matches
1267
+ else :
1268
+ $valid = true;
1269
+
1270
+ // filter mode off, or at least one match
1271
+ foreach ($terms as $tax => $term_ids) :
1272
+ if (!isset($termSet[$tax])) :
1273
+ $termSet[$tax] = array();
1274
+ endif;
1275
+ $termSet[$tax] = array_merge($termSet[$tax], $term_ids);
1276
+ endforeach;
1277
+ endif;
1278
+ endif;
1279
+ endforeach;
1280
 
1281
+ if (is_null($valid)) : // Plonked
 
1282
  $this->post = NULL;
1283
+ else : // We can proceed
1284
+ $this->post['tax_input'] = array();
1285
+ foreach ($termSet as $tax => $term_ids) :
1286
+ if (!isset($this->post['tax_input'][$tax])) :
1287
+ $this->post['tax_input'][$tax] = array();
1288
+ endif;
1289
+ $this->post['tax_input'][$tax] = array_merge(
1290
+ $this->post['tax_input'][$tax],
1291
+ $term_ids
1292
+ );
1293
+ endforeach;
1294
 
1295
+ // Now let's add on the feed and global presets
1296
+ foreach ($this->post['pretax'] as $tax => $term_ids) :
1297
+ if (!isset($this->post['tax_input'][$tax])) :
1298
+ $this->post['tax_input'][$tax] = array();
1299
+ endif;
1300
+
1301
+ $this->post['tax_input'][$tax] = array_merge (
1302
+ $this->post['tax_input'][$tax],
1303
+ $this->category_ids (
1304
+ /*terms=*/ $term_ids,
1305
+ /*unfamiliar=*/ 'create:'.$tax, // These are presets; for those added in a tagbox editor, the tag may not yet exist
1306
+ /*taxonomies=*/ array($tax),
1307
+ array(
1308
+ 'singleton' => true,
1309
+ ))
1310
+ );
1311
+ endforeach;
1312
  endif;
1313
  endif;
1314
 
1368
 
1369
  $dbpost = $this->normalize_post(/*new=*/ true);
1370
  if (!is_null($dbpost)) :
1371
+ $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
 
1372
 
1373
+ // This is a ridiculous fucking kludge necessitated by WordPress 2.6 munging authorship meta-data
1374
+ add_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1375
 
1376
+ // Kludge to prevent kses filters from stripping the
1377
+ // content of posts when updating without a logged in
1378
+ // user who has `unfiltered_html` capability.
1379
+ add_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1380
+
1381
+ $this->_wp_id = wp_insert_post($dbpost);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1382
 
1383
+ // Turn off ridiculous fucking kludges #1 and #2
1384
+ remove_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1385
+ remove_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1386
 
1387
+ $this->validate_post_id($dbpost, array(__CLASS__, __FUNCTION__));
 
 
 
 
 
 
 
 
 
 
1388
  endif;
1389
  } /* SyndicatedPost::insert_new() */
1390
 
1394
  // Why the fuck doesn't wp_insert_post already do this?
1395
  $dbpost = $this->normalize_post(/*new=*/ false);
1396
  if (!is_null($dbpost)) :
1397
+ $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
 
1398
 
1399
+ // This is a ridiculous fucking kludge necessitated by WordPress 2.6 munging authorship meta-data
1400
+ add_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1401
 
1402
+ // Kludge to prevent kses filters from stripping the
1403
+ // content of posts when updating without a logged in
1404
+ // user who has `unfiltered_html` capability.
1405
+ add_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1406
+
1407
+ // Don't munge status fields that the user may have reset manually
1408
+ if (function_exists('get_post_field')) :
1409
+ $doNotMunge = array('post_status', 'comment_status', 'ping_status');
1410
+ foreach ($doNotMunge as $field) :
1411
+ $dbpost[$field] = get_post_field($field, $this->wp_id());
1412
+ endforeach;
1413
+ endif;
1414
 
1415
+ $this->_wp_id = wp_insert_post($dbpost);
 
 
 
 
1416
 
1417
+ // Turn off ridiculous fucking kludges #1 and #2
1418
+ remove_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1419
+ remove_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1420
 
1421
+ $this->validate_post_id($dbpost, array(__CLASS__, __FUNCTION__));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1422
  endif;
1423
  } /* SyndicatedPost::update_existing() */
1424
 
1442
  endif;
1443
  endforeach;
1444
 
1445
+ $fullPost = $out['post_title'].$out['post_content'];
1446
+ $fullPost .= (isset($out['post_excerpt']) ? $out['post_excerpt'] : '');
1447
+ if (strlen($fullPost) < 1) :
1448
  // FIXME: Option for filtering out empty posts
1449
  endif;
1450
  if (strlen($out['post_title'])==0) :
1451
  $offset = (int) get_option('gmt_offset') * 60 * 60;
1452
+ if (isset($this->post['meta']['syndication_source'])) :
1453
+ $source_title = $this->post['meta']['syndication_source'];
1454
+ else :
1455
+ $feed_url = parse_url($this->post['meta']['syndication_feed']);
1456
+ $source_title = $feed_url['host'];
1457
+ endif;
1458
+
1459
+ $out['post_title'] = $source_title
1460
  .' '.gmdate('Y-m-d H:i:s', $this->published() + $offset);
1461
  // FIXME: Option for what to fill a blank title with...
1462
  endif;
1598
  $email = (isset($a['email']) ? $a['email'] : NULL);
1599
  $authorUrl = (isset($a['uri']) ? $a['uri'] : NULL);
1600
 
1601
+ $hostUrl = $this->link->homepage();
1602
+ if (is_null($hostUrl) or (strlen($hostUrl) < 0)) :
1603
+ $hostUrl = $this->link->uri();
1604
+ endif;
1605
+
1606
  $match_author_by_email = !('yes' == get_option("feedwordpress_do_not_match_author_by_email"));
1607
  if ($match_author_by_email and !FeedWordPress::is_null_email($email)) :
1608
  $test_email = $email;
1612
 
1613
  // Never can be too careful...
1614
  $login = sanitize_user($author, /*strict=*/ true);
1615
+
1616
+ // Possible for, e.g., foreign script author names
1617
+ if (strlen($login) < 1) :
1618
+ // No usable characters in author name for a login.
1619
+ // (Sometimes results from, e.g., foreign scripts.)
1620
+ //
1621
+ // We just need *something* in Western alphanumerics,
1622
+ // so let's try the domain name.
1623
+ //
1624
+ // Uniqueness will be guaranteed below if necessary.
1625
+
1626
+ $url = parse_url($hostUrl);
1627
+
1628
+ $login = sanitize_user($url['host'], /*strict=*/ true);
1629
+ if (strlen($login) < 1) :
1630
+ // This isn't working. Frak it.
1631
+ $login = 'syndicated';
1632
+ endif;
1633
+ endif;
1634
+
1635
  $login = apply_filters('pre_user_login', $login);
1636
 
1637
  $nice_author = sanitize_title($author);
1664
  // First try the user core data table.
1665
  $id = $wpdb->get_var(
1666
  "SELECT ID FROM $wpdb->users
1667
+ WHERE TRIM(LCASE(display_name)) = TRIM(LCASE('$author'))
1668
+ OR (
1669
+ LENGTH(TRIM(LCASE(user_email))) > 0
1670
+ AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
1671
+ )");
 
 
 
1672
 
1673
  // If that fails, look for aliases in the user meta data table
1674
  if (is_null($id)) :
1697
  // more than one user account with an empty e-mail address, so we
1698
  // need *something* here. Ugh.
1699
  if (strlen($email) == 0 or FeedWordPress::is_null_email($email)) :
 
 
 
 
1700
  $url = parse_url($hostUrl);
1701
  $email = $nice_author.'@'.$url['host'];
1702
  endif;
1709
  $userdata['user_email'] = $email;
1710
  $userdata['user_url'] = $authorUrl;
1711
  $userdata['display_name'] = $author;
1712
+
1713
+ do { // Keep trying until you get it right. Or until PHP crashes, I guess.
1714
+ $id = wp_insert_user($userdata);
1715
+ if (is_wp_error($id)) :
1716
+ $codes = $id->get_error_code();
1717
+ switch ($codes) :
1718
+ case 'empty_user_login' :
1719
+ case 'existing_user_login' :
1720
+ // Add a random disambiguator
1721
+ $userdata['user_login'] .= substr(md5(uniqid(microtime())), 0, 6);
1722
+ break;
1723
+ case 'existing_user_email' :
1724
+ // No disassemble!
1725
+ $parts = explode('@', $userdata['user_email'], 2);
1726
+
1727
+ // Add a random disambiguator as a gmail-style username extension
1728
+ $parts[0] .= '+'.substr(md5(uniqid(microtime())), 0, 6);
1729
+
1730
+ // Reassemble
1731
+ $userdata['user_email'] = $parts[0].'@'.$parts[1];
1732
+ break;
1733
+ endswitch;
1734
+ endif;
1735
+ } while (is_wp_error($id));
1736
  elseif (is_numeric($unfamiliar_author) and get_userdata((int) $unfamiliar_author)) :
1737
  $id = (int) $unfamiliar_author;
1738
  elseif ($unfamiliar_author === 'default') :
1747
  return $id;
1748
  } // function SyndicatedPost::author_id ()
1749
 
1750
+ /**
1751
+ * category_ids: look up (and create) category ids from a list of categories
1752
+ *
1753
+ * @param array $cats
1754
+ * @param string $unfamiliar_category
1755
+ * @param array|null $taxonomies
1756
+ * @return array
1757
+ */
1758
+ function category_ids ($cats, $unfamiliar_category = 'create', $taxonomies = NULL, $params = array()) {
1759
+ $singleton = (isset($params['singleton']) ? $params['singleton'] : true);
1760
+ $allowFilters = (isset($params['filters']) ? $params['filters'] : false);
1761
+
1762
+ $catTax = 'category';
1763
+
1764
+ if (is_null($taxonomies)) :
1765
+ $taxonomies = array('category');
1766
+ endif;
1767
 
1768
  // We need to normalize whitespace because (1) trailing
1769
  // whitespace can cause PHP and MySQL not to see eye to eye on
1773
  // distinction between 'Computers' and 'Computers '
1774
  $cats = array_map('trim', $cats);
1775
 
1776
+ $terms = array();
1777
+ foreach ($taxonomies as $tax) :
1778
+ $terms[$tax] = array();
1779
+ endforeach;
1780
+
1781
  foreach ($cats as $cat_name) :
1782
+ if (preg_match('/^{([^#}]*)#([0-9]+)}$/', $cat_name, $backref)) :
1783
+ $cat_id = (int) $backref[2];
1784
+ $tax = $backref[1];
1785
+ if (strlen($tax) < 1) :
1786
+ $tax = $catTax;
1787
+ endif;
1788
+
1789
+ $term = term_exists($cat_id, $tax);
1790
+ if (!is_wp_error($term) and !!$term) :
1791
+ if (!isset($terms[$tax])) :
1792
+ $terms[$tax] = array();
1793
+ endif;
1794
+ $terms[$tax][] = $cat_id;
1795
  endif;
1796
  elseif (strlen($cat_name) > 0) :
1797
+ $familiar = false;
1798
+ foreach ($taxonomies as $tax) :
1799
+ if ($tax!='category' or strtolower($cat_name)!='uncategorized') :
1800
+ $term = term_exists($cat_name, $tax);
1801
+ if (!is_wp_error($term) and !!$term) :
1802
+ $familiar = true;
1803
+
1804
+ if (is_array($term)) :
1805
+ $term_id = (int) $term['term_id'];
1806
+ else :
1807
+ $term_id = (int) $term;
1808
+ endif;
1809
+
1810
+ if (!isset($terms[$tax])) :
1811
+ $terms[$tax] = array();
1812
+ endif;
1813
+ $terms[$tax][] = $term_id;
1814
+ break; // We're done here.
1815
+ endif;
1816
+ endif;
1817
+ endforeach;
1818
 
1819
+ if (!$familiar) :
1820
+ if ('tag'==$unfamiliar_category) :
1821
+ $unfamiliar_category = 'create:post_tag';
1822
+ endif;
1823
+
1824
+ if (preg_match('/^create(:(.*))?$/i', $unfamiliar_category, $ref)) :
1825
+ $tax = $catTax; // Default
1826
+ if (isset($ref[2]) and strlen($ref[2]) > 2) :
1827
+ $tax = $ref[2];
1828
+ endif;
1829
+ $term = wp_insert_term($cat_name, $tax);
1830
+ if (is_wp_error($term)) :
1831
+ FeedWordPress::noncritical_bug('term insertion problem', array('cat_name' => $cat_name, 'term' => $term, 'this' => $this), __LINE__);
1832
+ else :
1833
+ if (!isset($terms[$tax])) :
1834
+ $terms[$tax] = array();
1835
+ endif;
1836
+ $terms[$tax][] = (int) $term['term_id'];
1837
+ endif;
 
 
 
1838
  endif;
1839
  endif;
1840
  endif;
1841
  endforeach;
1842
 
1843
+ $filtersOn = $allowFilters;
1844
+ if ($allowFilters) :
1845
+ $filters = array_filter(
1846
+ $this->link->setting('match/filter', 'match_filter', array()),
1847
+ 'remove_dummy_zero'
1848
+ );
1849
+ $filtersOn = ($filtersOn and is_array($filters) and (count($filters) > 0));
1850
  endif;
1851
 
1852
+ // Check for filter conditions
1853
+ foreach ($terms as $tax => $term_ids) :
1854
+ if ($filtersOn
1855
+ and (count($term_ids)==0)
1856
+ and in_array($tax, $filters)) :
1857
+ $terms = NULL; // Drop the post
1858
+ break;
1859
+ else :
1860
+ $terms[$tax] = array_unique($term_ids);
1861
+ endif;
1862
+ endforeach;
1863
 
1864
+ if ($singleton and count($terms)==1) : // If we only searched one, just return the term IDs
1865
+ $terms = end($terms);
1866
+ endif;
1867
+ return $terms;
1868
  } // function SyndicatedPost::category_ids ()
1869
 
1870
  function use_api ($tag) {
syndication.php CHANGED
@@ -1,977 +1,6 @@
1
  <?php
2
- require_once(dirname(__FILE__) . '/admin-ui.php');
3
 
4
- ################################################################################
5
- ## ADMIN MENU ADD-ONS: implement Dashboard management pages ####################
6
- ################################################################################
7
-
8
- define('FWP_UPDATE_CHECKED', 'Update Checked');
9
- define('FWP_UNSUB_CHECKED', 'Unsubscribe');
10
- define('FWP_DELETE_CHECKED', 'Delete');
11
- define('FWP_RESUB_CHECKED', 'Re-subscribe');
12
- define('FWP_SYNDICATE_NEW', 'Add →');
13
-
14
- class FeedWordPressSyndicationPage extends FeedWordPressAdminPage {
15
- function FeedWordPressSyndicationPage () {
16
- FeedWordPressAdminPage::FeedWordPressAdminPage('feedwordpresssyndication', /*link=*/ NULL);
17
-
18
- // No over-arching form element
19
- $this->dispatch = NULL;
20
- $this->filename = __FILE__;
21
- } /* FeedWordPressSyndicationPage constructor */
22
-
23
- function has_link () { return false; }
24
-
25
- var $_sources = NULL;
26
-
27
- function sources ($visibility = 'Y') {
28
- if (is_null($this->_sources)) :
29
- $links = FeedWordPress::syndicated_links(array("hide_invisible" => false));
30
- $this->_sources = array("Y" => array(), "N" => array());
31
- foreach ($links as $link) :
32
- $this->_sources[$link->link_visible][] = $link;
33
- endforeach;
34
- endif;
35
- $ret = (
36
- array_key_exists($visibility, $this->_sources)
37
- ? $this->_sources[$visibility]
38
- : $this->_sources
39
- );
40
- return $ret;
41
- } /* FeedWordPressSyndicationPage::sources() */
42
-
43
- function visibility_toggle () {
44
- $sources = $this->sources('*');
45
-
46
- $defaultVisibility = 'Y';
47
- if ((count($this->sources('N')) > 0)
48
- and (count($this->sources('Y'))==0)) :
49
- $defaultVisibility = 'N';
50
- endif;
51
-
52
- $visibility = (
53
- isset($_REQUEST['visibility'])
54
- ? $_REQUEST['visibility']
55
- : $defaultVisibility
56
- );
57
-
58
- return $visibility;
59
- } /* FeedWordPressSyndicationPage::visibility_toggle() */
60
-
61
- function show_inactive () {
62
- return ($this->visibility_toggle() == 'N');
63
- }
64
-
65
- function updates_requested () {
66
- global $wpdb;
67
-
68
- if (isset($_POST['update']) or isset($_POST['action']) or isset($_POST['update_uri'])) :
69
- // Only do things with side-effects for HTTP POST or command line
70
- $fwp_update_invoke = 'post';
71
- else :
72
- $fwp_update_invoke = 'get';
73
- endif;
74
-
75
- $update_set = array();
76
- if ($fwp_update_invoke != 'get') :
77
- if (isset($_POST['link_ids']) and is_array($_POST['link_ids']) and ($_POST['action']==FWP_UPDATE_CHECKED)) :
78
- $targets = $wpdb->get_results("
79
- SELECT * FROM $wpdb->links
80
- WHERE link_id IN (".implode(",",$_POST['link_ids']).")
81
- ");
82
- if (is_array($targets)) :
83
- foreach ($targets as $target) :
84
- $update_set[] = $target->link_rss;
85
- endforeach;
86
- else : // This should never happen
87
- FeedWordPress::critical_bug('fwp_syndication_manage_page::targets', $targets, __LINE__);
88
- endif;
89
- elseif (isset($_POST['update_uri'])) :
90
- $targets = $_POST['update_uri'];
91
- if (!is_array($targets)) :
92
- $targets = array($targets);
93
- endif;
94
- $update_set = $targets;
95
- endif;
96
- endif;
97
- return $update_set;
98
- }
99
-
100
- function display () {
101
- global $wpdb;
102
-
103
- if (FeedWordPress::needs_upgrade()) :
104
- fwp_upgrade_page();
105
- return;
106
- endif;
107
-
108
- ?>
109
- <?php
110
- $cont = true;
111
- $dispatcher = array(
112
- "feedfinder" => 'fwp_feedfinder_page',
113
- FWP_SYNDICATE_NEW => 'fwp_feedfinder_page',
114
- "switchfeed" => 'fwp_switchfeed_page',
115
- FWP_UNSUB_CHECKED => 'fwp_multidelete_page',
116
- FWP_DELETE_CHECKED => 'fwp_multidelete_page',
117
- 'Unsubscribe' => 'fwp_multidelete_page',
118
- FWP_RESUB_CHECKED => 'fwp_multiundelete_page',
119
- );
120
- if (isset($_REQUEST['action']) and isset($dispatcher[$_REQUEST['action']])) :
121
- $method = $dispatcher[$_REQUEST['action']];
122
- $cont = call_user_func($method);
123
- endif;
124
-
125
- if ($cont):
126
- ?>
127
- <style type="text/css">
128
- .heads-up {
129
- background-color: #d0d0d0;
130
- color: black;
131
- padding: 1.0em;
132
- margin: 0.5em 4.0em !important;
133
- }
134
- .update-form.with-donation {
135
- margin-right: 50%;
136
- min-height: 255px;
137
- }
138
- .donation-form, .donation-thanks {
139
- background-color: #ffffcc;
140
- text-align: left;
141
- padding: 0.5em 0.5em;
142
- border-left: thin dashed #777777;
143
- font-size: 70%;
144
- position: absolute;
145
- top: 0; bottom: 0; right: 0; left: auto;
146
- width: 50%;
147
- }
148
- .donation-thanks {
149
- background-color: #ccffcc;
150
- }
151
- .donation-thanks .signature {
152
- text-align: right;
153
- font-style: italic;
154
- }
155
- .donation-form h4, .donation-thanks h4 {
156
- font-size: 10px;
157
- text-align: center;
158
- border-bottom: 1px solid #777777;
159
- margin: 0px;
160
- }
161
- .donation-form .donate {
162
- text-align: center;
163
- }
164
- .donation-form .sod-off {
165
- padding-top: 0.5em;
166
- margin-top: 0.5em;
167
- border-top: thin solid #777777;
168
- }
169
- .feed-missing {
170
- background-color:#FFFFD0;
171
- }
172
- .unsubscribed tr {
173
- background-color: #FFE0E0;
174
- }
175
- .unsubscribed tr.alternate {
176
- background-color: #FFF0F0;
177
- }
178
- tr.feed-error {
179
- background-color: #FFFFD0;
180
- }
181
- </style>
182
- <?php
183
- $links = $this->sources('Y');
184
- $potential_updates = (!$this->show_inactive() and (count($this->sources('Y')) > 0));
185
-
186
- $this->open_sheet('Syndicated Sites');
187
- ?>
188
- <div id="post-body">
189
- <?php
190
- if ($potential_updates
191
- or (count($this->updates_requested()) > 0)) :
192
- fwp_add_meta_box(
193
- /*id=*/ 'feedwordpress_update_box',
194
- /*title=*/ __('Update feeds now'),
195
- /*callback=*/ 'fwp_syndication_manage_page_update_box',
196
- /*page=*/ $this->meta_box_context(),
197
- /*context =*/ $this->meta_box_context()
198
- );
199
- endif;
200
- fwp_add_meta_box(
201
- /*id=*/ 'feedwordpress_feeds_box',
202
- /*title=*/ __('Syndicated sources'),
203
- /*callback=*/ 'fwp_syndication_manage_page_links_box',
204
- /*page=*/ $this->meta_box_context(),
205
- /*context =*/ $this->meta_box_context()
206
- );
207
- if (FeedWordPressCompatibility::test_version(0, FWP_SCHEMA_25)) :
208
- fwp_add_meta_box(
209
- /*id=*/ 'feedwordpress_add_feed_box',
210
- /*title=*/ 'Add a new syndicated source',
211
- /*callback=*/ 'fwp_syndication_manage_page_add_feed_box',
212
- /*page=*/ $this->meta_box_context(),
213
- /*context=*/ $this->meta_box_context()
214
- );
215
- endif;
216
-
217
- do_action('feedwordpress_admin_page_syndication_meta_boxes', $this);
218
- ?>
219
- <div class="metabox-holder">
220
- <?php
221
- fwp_do_meta_boxes($this->meta_box_context(), $this->meta_box_context(), $this);
222
- ?>
223
- </div> <!-- class="metabox-holder" -->
224
- </div> <!-- id="post-body" -->
225
-
226
- <?php $this->close_sheet(/*dispatch=*/ NULL); ?>
227
-
228
- <div style="display: none">
229
- <div id="tags-input"></div> <!-- avoid JS error from WP 2.5 bug -->
230
- </div>
231
- <?php
232
- endif;
233
- } /* FeedWordPressSyndicationPage::display () */
234
-
235
- function bleg_thanks ($page, $box = NULL) {
236
- ?>
237
- <div class="donation-thanks">
238
- <h4>Thank you!</h4>
239
- <p><strong>Thank you</strong> for your contribution to <a href="http://feedwordpress.radgeek.com/">FeedWordPress</a> development.
240
- Your generous gifts make ongoing support and development for
241
- FeedWordPress possible.</p>
242
- <p>If you have any questions about FeedWordPress, or if there
243
- is anything I can do to help make FeedWordPress more useful for
244
- you, please <a href="http://feedwordpress.radgeek.com/contact">contact me</a>
245
- and let me know what you're thinking about.</p>
246
- <p class="signature">&#8212;<a href="http://radgeek.com/">Charles Johnson</a>, Developer, <a href="http://feedwordpress.radgeek.com/">FeedWordPress</a>.</p>
247
- </div>
248
- <?php
249
- } /* FeedWordPressSyndicationPage::bleg_thanks () */
250
-
251
- function bleg_box ($page, $box = NULL) {
252
- ?>
253
- <div class="donation-form">
254
- <h4>Keep FeedWordPress improving</h4>
255
- <form action="https://www.paypal.com/cgi-bin/webscr" accept-charset="UTF-8" method="post"><div>
256
- <p><a href="http://feedwordpress.radgeek.com/">FeedWordPress</a> makes syndication
257
- simple and empowers you to stream content from all over the web into your
258
- WordPress hub. That's got to be worth a few lattes. If you're finding FWP useful,
259
- <a href="http://feedwordpress.radgeek.com/donate/">a modest gift</a>
260
- is the best way to support steady progress on development, enhancements,
261
- support, and documentation.</p>
262
- <div class="donate">
263
- <input type="hidden" name="business" value="commerce@radgeek.com" />
264
- <input type="hidden" name="cmd" value="_xclick" />
265
- <input type="hidden" name="item_name" value="FeedWordPress donation" />
266
- <input type="hidden" name="no_shipping" value="1" />
267
- <input type="hidden" name="return" value="<?php bloginfo('url'); ?>/wp-admin/admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/<?php print basename(__FILE__); ?>&amp;paid=yes" />
268
- <input type="hidden" name="currency_code" value="USD" />
269
- <input type="hidden" name="notify_url" value="http://feedwordpress.radgeek.com/ipn/donation" />
270
- <input type="hidden" name="custom" value="1" />
271
- <input type="image" name="submit" src="https://www.paypal.com/en_GB/i/btn/btn_donate_SM.gif" alt="Donate through PayPal" />
272
- </div>
273
- </div></form>
274
-
275
- <p>You can make a gift online (or
276
- <a href="http://feedwordpress.radgeek.com/donation">set up an automatic
277
- regular donation</a>) using an existing PayPal account or any major credit card.</p>
278
-
279
- <div class="sod-off">
280
- <form style="text-align: center" action="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/<?php print basename(__FILE__); ?>" method="POST"><div>
281
- <input class="button-primary" type="submit" name="maybe_later" value="Maybe Later" />
282
- <input class="button-secondary" type="submit" name="go_away" value="Dismiss" />
283
- </div></form>
284
- </div>
285
- </div> <!-- class="donation-form" -->
286
- <?php
287
- } /* FeedWordPressSyndicationPage::bleg_box () */
288
-
289
- /**
290
- * Override the default display of a save-settings button and replace
291
- * it with nothing.
292
- */
293
- function interstitial () {
294
- /* NOOP */
295
- } /* FeedWordPressSyndicationPage::interstitial() */
296
- } /* class FeedWordPressSyndicationPage */
297
-
298
- function fwp_dashboard_update_if_requested ($object) {
299
- global $wpdb;
300
-
301
- $update_set = $object->updates_requested();
302
-
303
- if (count($update_set) > 0) :
304
- shuffle($update_set); // randomize order for load balancing purposes...
305
-
306
- $feedwordpress = new FeedWordPress;
307
- add_action('feedwordpress_check_feed', 'update_feeds_mention');
308
- add_action('feedwordpress_check_feed_complete', 'update_feeds_finish', 10, 3);
309
-
310
- $crash_dt = (int) get_option('feedwordpress_update_time_limit');
311
- if ($crash_dt > 0) :
312
- $crash_ts = time() + $crash_dt;
313
- else :
314
- $crash_ts = NULL;
315
- endif;
316
-
317
- echo "<div class=\"update-results\">\n";
318
- echo "<ul>\n";
319
- $tdelta = NULL;
320
- foreach ($update_set as $uri) :
321
- if (!is_null($crash_ts) and (time() > $crash_ts)) :
322
- echo "<li><p><strong>Further updates postponed:</strong> update time limit of ".$crash_dt." second".(($crash_dt==1)?"":"s")." exceeded.</p></li>";
323
- break;
324
- endif;
325
-
326
- if ($uri == '*') : $uri = NULL; endif;
327
- $delta = $feedwordpress->update($uri, $crash_ts);
328
- if (!is_null($delta)) :
329
- if (is_null($tdelta)) :
330
- $tdelta = $delta;
331
- else :
332
- $tdelta['new'] += $delta['new'];
333
- $tdelta['updated'] += $delta['updated'];
334
- endif;
335
- else :
336
- echo "<li><p><strong>Error:</strong> There was a problem updating <a href=\"$uri\">$uri</a></p></li>\n";
337
- endif;
338
- endforeach;
339
- echo "</ul>\n";
340
-
341
- if (!is_null($tdelta)) :
342
- $mesg = array();
343
- if (isset($delta['new'])) : $mesg[] = ' '.$tdelta['new'].' new posts were syndicated'; endif;
344
- if (isset($delta['updated'])) : $mesg[] = ' '.$tdelta['updated'].' existing posts were updated'; endif;
345
- echo "<p>Update complete.".implode(' and', $mesg)."</p>";
346
- echo "\n"; flush();
347
- endif;
348
- echo "</div> <!-- class=\"updated\" -->\n";
349
- endif;
350
- }
351
-
352
- function fwp_syndication_manage_page_add_feed_box ($object = NULL, $box = NULL) {
353
- ?>
354
- <form action="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/<?php print basename(__FILE__); ?>" method="post">
355
- <div>
356
- <?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?>
357
- <label for="add-uri">Website or feed:</label>
358
- <input type="text" name="lookup" id="add-uri" value="URI" size="64" />
359
- <input type="hidden" name="action" value="feedfinder" />
360
- </div>
361
- <div class="submit"><input type="submit" value="<?php print FWP_SYNDICATE_NEW; ?>" /></div>
362
- </form>
363
- <?php
364
- }
365
-
366
- define('FEEDWORDPRESS_BLEG_MAYBE_LATER_OFFSET', (60 /*sec/min*/ * 60 /*min/hour*/ * 24 /*hour/day*/ * 31 /*days*/));
367
- define('FEEDWORDPRESS_BLEG_ALREADY_PAID_OFFSET', (60 /*sec/min*/ * 60 /*min/hour*/ * 24 /*hour/day*/ * 183 /*days*/));
368
- function fwp_syndication_manage_page_update_box ($object = NULL, $box = NULL) {
369
- $bleg_box_hidden = null;
370
- if (isset($_POST['maybe_later'])) :
371
- $bleg_box_hidden = time() + FEEDWORDPRESS_BLEG_MAYBE_LATER_OFFSET;
372
- elseif (isset($_REQUEST['paid']) and $_REQUEST['paid']) :
373
- $bleg_box_hidden = time() + FEEDWORDPRESS_BLEG_ALREADY_PAID_OFFSET;
374
- elseif (isset($_POST['go_away'])) :
375
- $bleg_box_hidden = 'permanent';
376
- endif;
377
-
378
- if (!is_null($bleg_box_hidden)) :
379
- update_option('feedwordpress_bleg_box_hidden', $bleg_box_hidden);
380
- else :
381
- $bleg_box_hidden = get_option('feedwordpress_bleg_box_hidden');
382
- endif;
383
- ?>
384
- <?php
385
- $bleg_box_ready = (!$bleg_box_hidden or (is_numeric($bleg_box_hidden) and $bleg_box_hidden < time()));
386
- if (isset($_REQUEST['paid']) and $_REQUEST['paid']) :
387
- $object->bleg_thanks($subject, $box);
388
- elseif ($bleg_box_ready) :
389
- $object->bleg_box($object, $box);
390
- endif;
391
- ?>
392
-
393
- <form
394
- action="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/<?php print basename(__FILE__); ?>"
395
- method="POST"
396
- class="update-form<?php if ($bleg_box_ready) : ?> with-donation<?php endif; ?>"
397
- >
398
- <div><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?></div>
399
- <p>Check currently scheduled feeds for new and updated posts.</p>
400
-
401
- <?php
402
- fwp_dashboard_update_if_requested($object);
403
-
404
- if (!get_option('feedwordpress_automatic_updates')) :
405
- ?>
406
- <p class="heads-up"><strong>Note:</strong> Automatic updates are currently turned
407
- <strong>off</strong>. New posts from your feeds will not be syndicated
408
- until you manually check for them here. You can turn on automatic
409
- updates under <a href="admin.php?page=<?php print $GLOBALS['fwp_path']; ?>/feeds-page.php">Feed &amp; Update Settings<a></a>.</p>
410
- <?php
411
- endif;
412
- ?>
413
-
414
- <div class="submit"><?php if ($object->show_inactive()) : ?>
415
- <?php foreach ($object->updates_requested() as $req) : ?>
416
- <input type="hidden" name="update_uri[]" value="<?php print esc_html($req); ?>" />
417
- <?php endforeach; ?>
418
- <?php else : ?>
419
- <input type="hidden" name="update_uri" value="*" />
420
- <?php endif; ?>
421
- <input class="button-primary" type="submit" name="update" value="Update" /></div>
422
-
423
- <br style="clear: both" />
424
- </form>
425
- <?php
426
- } /* function fwp_syndication_manage_page_update_box () */
427
-
428
- function fwp_syndication_manage_page_links_table_rows ($links, $visible = 'Y') {
429
- global $fwp_path;
430
-
431
- $subscribed = ('Y' == strtoupper($visible));
432
- if ($subscribed or (count($links) > 0)) :
433
- ?>
434
- <table class="widefat<?php if (!$subscribed) : ?> unsubscribed<?php endif; ?>">
435
- <thead>
436
- <tr>
437
- <th class="check-column" scope="col"><input type="checkbox" /></th>
438
- <th scope="col"><?php _e('Name'); ?></th>
439
- <th scope="col"><?php _e('Feed'); ?></th>
440
- <th scope="col"><?php _e('Updated'); ?></th>
441
- </tr>
442
- </thead>
443
-
444
- <tbody>
445
- <?php
446
- $alt_row = true;
447
- if (count($links) > 0):
448
- foreach ($links as $link):
449
- $trClass = array();
450
-
451
- // Prep: Get last updated timestamp
452
- $sLink = new SyndicatedLink($link->link_id);
453
- if (!is_null($sLink->setting('update/last'))) :
454
- $lastUpdated = fwp_time_elapsed($sLink->setting('update/last'));
455
- else :
456
- $lastUpdated = __('None yet');
457
- endif;
458
-
459
- // Prep: get last error timestamp, if any
460
- if (is_null($sLink->setting('update/error'))) :
461
- $errorsSince = '';
462
- else :
463
- $trClass[] = 'feed-error';
464
-
465
- $theError = unserialize($sLink->setting('update/error'));
466
-
467
- $errorsSince = "<div class=\"returning-errors\">"
468
- ."<p><strong>Returning errors</strong> since "
469
- .fwp_time_elapsed($theError['since'])
470
- ."</p>"
471
- ."<p>Most recent ("
472
- .fwp_time_elapsed($theError['ts'])
473
- ."):<br/><code>"
474
- .implode("</code><br/><code>", $theError['object']->get_error_messages())
475
- ."</code></p>"
476
- ."</div>\n";
477
- endif;
478
-
479
- $nextUpdate = "<div style='font-style:italic;size:0.9em'>Ready for next update ";
480
- if (isset($sLink->settings['update/ttl']) and is_numeric($sLink->settings['update/ttl'])) :
481
- if (isset($sLink->settings['update/timed']) and $sLink->settings['update/timed']=='automatically') :
482
- $next = $sLink->settings['update/last'] + ((int) $sLink->settings['update/ttl'] * 60);
483
- $nextUpdate .= fwp_time_elapsed($next);
484
- if (FEEDWORDPRESS_DEBUG) : $nextUpdate .= " [".(($next-time())/60)." minutes]"; endif;
485
- else :
486
- $nextUpdate .= "every ".$sLink->settings['update/ttl']." minute".(($sLink->settings['update/ttl']!=1)?"s":"");
487
- endif;
488
- else:
489
- $nextUpdate .= "as soon as possible";
490
- endif;
491
- $nextUpdate .= "</div>";
492
-
493
- unset($sLink);
494
-
495
- $alt_row = !$alt_row;
496
-
497
- if ($alt_row) :
498
- $trClass[] = 'alternate';
499
- endif;
500
- ?>
501
- <tr<?php echo ((count($trClass) > 0) ? ' class="'.implode(" ", $trClass).'"':''); ?>>
502
- <th class="check-column" scope="row"><input type="checkbox" name="link_ids[]" value="<?php echo $link->link_id; ?>" /></th>
503
- <?php
504
- $hrefPrefix = "admin.php?link_id={$link->link_id}&amp;page=${fwp_path}/";
505
- $caption = (
506
- (strlen($link->link_rss) > 0)
507
- ? __('Switch Feed')
508
- : $caption=__('Find Feed')
509
- );
510
- ?>
511
- <td>
512
- <strong><a href="<?php print $hrefPrefix; ?>feeds-page.php"><?php print esc_html($link->link_name); ?></a></strong>
513
- <div class="row-actions"><?php if ($subscribed) : ?>
514
- <div><strong>Settings &gt;</strong>
515
- <a href="<?php print $hrefPrefix; ?>feeds-page.php"><?php _e('Feed'); ?></a>
516
- | <a href="<?php print $hrefPrefix; ?>posts-page.php"><?php _e('Posts'); ?></a>
517
- | <a href="<?php print $hrefPrefix; ?>authors-page.php"><?php _e('Authors'); ?></a>
518
- | <a href="<?php print $hrefPrefix; ?>categories-page.php"><?php print htmlspecialchars(__('Categories'.FEEDWORDPRESS_AND_TAGS)); ?></a></div>
519
- <?php endif; ?>
520
-
521
- <div><strong>Actions &gt;</strong>
522
- <?php if ($subscribed) : ?>
523
- <a href="<?php print $hrefPrefix; ?><?php echo basename(__FILE__); ?>&amp;action=feedfinder"><?php echo $caption; ?></a>
524
- <?php else : ?>
525
- <a href="<?php print $hrefPrefix; ?><?php echo basename(__FILE__); ?>&amp;action=<?php print FWP_RESUB_CHECKED; ?>"><?php _e('Re-subscribe'); ?></a>
526
- <?php endif; ?>
527
- | <a href="<?php print $hrefPrefix; ?><?php echo basename(__FILE__); ?>&amp;action=Unsubscribe"><?php _e(($subscribed ? 'Unsubscribe' : 'Delete permanently')); ?></a>
528
- | <a href="<?php print esc_html($link->link_url); ?>"><?php _e('View')?></a></div>
529
- </div>
530
- </td>
531
- <?php if (strlen($link->link_rss) > 0): ?>
532
- <td><a href="<?php echo esc_html($link->link_rss); ?>"><?php echo esc_html(feedwordpress_display_url($link->link_rss, 32)); ?></a></td>
533
- <?php else: ?>
534
- <td class="feed-missing"><p><strong>no feed assigned</strong></p></td>
535
- <?php endif; ?>
536
-
537
- <td><?php print $lastUpdated; ?>
538
- <?php print $errorsSince; ?>
539
- <?php print $nextUpdate; ?>
540
- </td>
541
- </tr>
542
- <?php
543
- endforeach;
544
- else :
545
- ?>
546
- <tr><td colspan="4"><p>There are no websites currently listed for syndication.</p></td></tr>
547
- <?php
548
- endif;
549
- ?>
550
- </tbody>
551
- </table>
552
- <?php
553
- endif;
554
- } /* function fwp_syndication_manage_page_links_table_rows () */
555
-
556
- function fwp_syndication_manage_page_links_subsubsub ($sources, $showInactive) {
557
- global $fwp_path;
558
- $hrefPrefix = "admin.php?page=${fwp_path}/".basename(__FILE__);
559
- ?>
560
- <ul class="subsubsub">
561
- <li><a <?php if (!$showInactive) : ?>class="current" <?php endif; ?>href="<?php print $hrefPrefix; ?>&amp;visibility=Y">Subscribed
562
- <span class="count">(<?php print count($sources['Y']); ?>)</span></a></li>
563
- <?php if ($showInactive or (count($sources['N']) > 0)) : ?>
564
- <li><a <?php if ($showInactive) : ?>class="current" <?php endif; ?>href="<?php print $hrefPrefix; ?>&amp;visibility=N">Inactive</a>
565
- <span class="count">(<?php print count($sources['N']); ?>)</span></a></li>
566
- <?php endif; ?>
567
-
568
- </ul> <!-- class="subsubsub" -->
569
- <?php
570
- }
571
-
572
- function fwp_syndication_manage_page_links_box ($object = NULL, $box = NULL) {
573
- global $fwp_path;
574
-
575
- $links = FeedWordPress::syndicated_links(array("hide_invisible" => false));
576
- $sources = $object->sources('*');
577
-
578
- $visibility = $object->visibility_toggle();
579
- $showInactive = $object->show_inactive();
580
-
581
- $hrefPrefix = "admin.php?page=${fwp_path}/".basename(__FILE__);
582
- ?>
583
- <form id="syndicated-links" action="<?php print $hrefPrefix; ?>&amp;visibility=<?php print $visibility; ?>" method="post">
584
- <div><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?></div>
585
- <?php
586
- if (count($sources[$visibility]) > 0) :
587
- fwp_syndication_manage_page_links_subsubsub($sources, $showInactive);
588
- endif;
589
-
590
- if ($showInactive) : ?>
591
- <p style="clear: both; font-size: smaller; font-style: italic">FeedWordPress used to syndicate
592
- posts from these sources, but you have unsubscribed from them.</p>
593
- <?php
594
- endif;
595
- ?>
596
-
597
- <div class="tablenav">
598
- <div class="alignright">
599
- <label for="add-uri">New source:</label>
600
- <input type="text" name="lookup" id="add-uri" value="Website or feed URI" />
601
- <?php FeedWordPressSettingsUI::magic_input_tip_js('add-uri'); ?>
602
-
603
- <input type="hidden" name="action" value="feedfinder" />
604
- <input type="submit" class="button-secondary" name="action" value="<?php print FWP_SYNDICATE_NEW; ?>" /></div>
605
-
606
- <?php if (count($sources[$visibility]) > 0) : ?>
607
- <div class="alignleft">
608
- <?php if ($showInactive) : ?>
609
- <input class="button-secondary" type="submit" name="action" value="<?php print FWP_RESUB_CHECKED; ?>" />
610
- <input class="button-secondary" type="submit" name="action" value="<?php print FWP_DELETE_CHECKED; ?>" />
611
- <?php else : ?>
612
- <input class="button-secondary" type="submit" name="action" value="<?php print FWP_UPDATE_CHECKED; ?>" />
613
- <input class="button-secondary delete" type="submit" name="action" value="<?php print FWP_UNSUB_CHECKED; ?>" />
614
- <?php endif ; ?>
615
- </div>
616
-
617
- <?php else : ?>
618
- <?php fwp_syndication_manage_page_links_subsubsub($sources, $showInactive); ?>
619
- <?php endif; ?>
620
-
621
- <br class="clear" />
622
- </div>
623
- <br class="clear" />
624
-
625
- <?php
626
- fwp_syndication_manage_page_links_table_rows($sources[$visibility], $visibility);
627
- ?>
628
- </form>
629
- <?php
630
- } /* function fwp_syndication_manage_page_links_box() */
631
-
632
- function fwp_feedfinder_page () {
633
- global $post_source;
634
-
635
- $post_source = 'feedwordpress_feeds';
636
-
637
- // With action=feedfinder, this goes directly to the feedfinder page
638
- include_once(dirname(__FILE__) . '/feeds-page.php');
639
- return false;
640
- } /* function fwp_feedfinder_page () */
641
-
642
- function fwp_switchfeed_page () {
643
- global $wpdb, $wp_db_version;
644
- global $fwp_post;
645
-
646
- // If this is a POST, validate source and user credentials
647
- FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_switchfeed', /*capability=*/ 'manage_links');
648
-
649
- $changed = false;
650
- if (!isset($fwp_post['Cancel'])):
651
- if (isset($fwp_post['save_link_id']) and ($fwp_post['save_link_id']=='*')) :
652
- $changed = true;
653
- $link_id = FeedWordPress::syndicate_link($fwp_post['feed_title'], $fwp_post['feed_link'], $fwp_post['feed']);
654
- if ($link_id):
655
- $existingLink = new SyndicatedLink($link_id);
656
- ?>
657
- <div class="updated"><p><a href="<?php print $fwp_post['feed_link']; ?>"><?php print esc_html($fwp_post['feed_title']); ?></a>
658
- has been added as a contributing site, using the feed at
659
- &lt;<a href="<?php print $fwp_post['feed']; ?>"><?php print esc_html($fwp_post['feed']); ?></a>&gt;.
660
- | <a href="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/feeds-page.php&amp;link_id=<?php print $link_id; ?>">Configure settings</a>.</p></div>
661
- <?php else: ?>
662
- <div class="updated"><p>There was a problem adding the feed. [SQL: <?php echo esc_html(mysql_error()); ?>]</p></div>
663
- <?php endif;
664
- elseif (isset($fwp_post['save_link_id'])):
665
- $existingLink = new SyndicatedLink($fwp_post['save_link_id']);
666
- $changed = $existingLink->set_uri($fwp_post['feed']);
667
-
668
- if ($changed):
669
- $home = $existingLink->homepage(/*from feed=*/ false);
670
- $name = $existingLink->name(/*from feed=*/ false);
671
- ?>
672
- <div class="updated"><p>Feed for <a href="<?php echo esc_html($home); ?>"><?php echo esc_html($name); ?></a>
673
- updated to &lt;<a href="<?php echo esc_html($fwp_post['feed']); ?>"><?php echo esc_html($fwp_post['feed']); ?></a>&gt;.</p></div>
674
- <?php
675
- endif;
676
- endif;
677
- endif;
678
-
679
- if (isset($existingLink)) :
680
- do_action('feedwordpress_admin_switchfeed', $fwp_post['feed'], $existingLink);
681
- endif;
682
-
683
- if (!$changed) :
684
- ?>
685
- <div class="updated"><p>Nothing was changed.</p></div>
686
- <?php
687
- endif;
688
- return true; // Continue
689
- }
690
-
691
- function fwp_multiundelete_page () {
692
- global $wpdb;
693
-
694
- // If this is a POST, validate source and user credentials
695
- FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_feeds', /*capability=*/ 'manage_links');
696
-
697
- $link_ids = (isset($_REQUEST['link_ids']) ? $_REQUEST['link_ids'] : array());
698
- if (isset($_REQUEST['link_id'])) : array_push($link_ids, $_REQUEST['link_id']); endif;
699
-
700
- if (isset($GLOBALS['fwp_post']['confirm']) and $GLOBALS['fwp_post']['confirm']=='Undelete'):
701
- if (isset($GLOBALS['fwp_post']['link_action']) and is_array($GLOBALS['fwp_post']['link_action'])) :
702
- $actions = $GLOBALS['fwp_post']['link_action'];
703
- else :
704
- $actions = array();
705
- endif;
706
-
707
- $do_it = array(
708
- 'unhide' => array(),
709
- );
710
-
711
- foreach ($actions as $link_id => $what) :
712
- $do_it[$what][] = $link_id;
713
- endforeach;
714
-
715
- $alter = array();
716
- if (count($do_it['unhide']) > 0) :
717
- $unhiddem = "(".implode(', ', $do_it['unhide']).")";
718
- $alter[] = "
719
- UPDATE $wpdb->links
720
- SET link_visible = 'Y'
721
- WHERE link_id IN {$unhiddem}
722
- ";
723
- endif;
724
-
725
- $errs = array(); $success = array ();
726
- foreach ($alter as $sql) :
727
- $result = $wpdb->query($sql);
728
- if (!$result):
729
- $errs[] = mysql_error();
730
- endif;
731
- endforeach;
732
-
733
- if (count($alter) > 0) :
734
- echo "<div class=\"updated\">\n";
735
- if (count($errs) > 0) :
736
- echo "There were some problems processing your ";
737
- echo "re-subscribe request. [SQL: ".implode('; ', $errs)."]";
738
- else :
739
- echo "Your re-subscribe request(s) have been processed.";
740
- endif;
741
- echo "</div>\n";
742
- endif;
743
-
744
- return true; // Continue on to Syndicated Sites listing
745
- else :
746
- $targets = $wpdb->get_results("
747
- SELECT * FROM $wpdb->links
748
- WHERE link_id IN (".implode(",",$link_ids).")
749
- ");
750
- ?>
751
- <form action="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/<?php echo basename(__FILE__); ?>" method="post">
752
- <div class="wrap">
753
- <?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?>
754
- <input type="hidden" name="action" value="<?php print FWP_RESUB_CHECKED; ?>" />
755
- <input type="hidden" name="confirm" value="Undelete" />
756
-
757
- <h2>Re-subscribe to Syndicated Links:</h2>
758
- <?php
759
- foreach ($targets as $link) :
760
- $subscribed = ('Y' == strtoupper($link->link_visible));
761
- $link_url = esc_html($link->link_url);
762
- $link_name = esc_html($link->link_name);
763
- $link_description = esc_html($link->link_description);
764
- $link_rss = esc_html($link->link_rss);
765
-
766
- if (!$subscribed) :
767
- ?>
768
- <fieldset>
769
- <legend><?php echo $link_name; ?></legend>
770
- <table class="editform" width="100%" cellspacing="2" cellpadding="5">
771
- <tr><th scope="row" width="20%"><?php _e('Feed URI:') ?></th>
772
- <td width="80%"><a href="<?php echo $link_rss; ?>"><?php echo $link_rss; ?></a></td></tr>
773
- <tr><th scope="row" width="20%"><?php _e('Short description:') ?></th>
774
- <td width="80%"><?php echo $link_description; ?></span></td></tr>
775
- <tr><th width="20%" scope="row"><?php _e('Homepage:') ?></th>
776
- <td width="80%"><a href="<?php echo $link_url; ?>"><?php echo $link_url; ?></a></td></tr>
777
- <tr style="vertical-align:top"><th width="20%" scope="row">Subscription <?php _e('Options') ?>:</th>
778
- <td width="80%"><ul style="margin:0; padding: 0; list-style: none">
779
- <li><input type="radio" id="unhide-<?php echo $link->link_id; ?>"
780
- name="link_action[<?php echo $link->link_id; ?>]" value="unhide" checked="checked" />
781
- <label for="unhide-<?php echo $link->link_id; ?>">Turn back on the subscription
782
- for this syndication source.</label></li>
783
- <li><input type="radio" id="nothing-<?php echo $link->link_id; ?>"
784
- name="link_action[<?php echo $link->link_id; ?>]" value="nothing" />
785
- <label for="nothing-<?php echo $link->link_id; ?>">Leave this feed as it is.
786
- I changed my mind.</label></li>
787
- </ul>
788
- </table>
789
- </fieldset>
790
- <?php
791
- endif;
792
- endforeach;
793
- ?>
794
-
795
- <div class="submit">
796
- <input class="button-primary delete" type="submit" name="submit" value="<?php _e('Re-subscribe to selected feeds &raquo;') ?>" />
797
- </div>
798
- </div>
799
- <?php
800
- return false; // Don't continue on to Syndicated Sites listing
801
- endif;
802
- }
803
-
804
- function fwp_multidelete_page () {
805
- global $wpdb;
806
-
807
- // If this is a POST, validate source and user credentials
808
- FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_feeds', /*capability=*/ 'manage_links');
809
-
810
- $link_ids = (isset($_REQUEST['link_ids']) ? $_REQUEST['link_ids'] : array());
811
- if (isset($_REQUEST['link_id'])) : array_push($link_ids, $_REQUEST['link_id']); endif;
812
-
813
- if (isset($GLOBALS['fwp_post']['confirm']) and $GLOBALS['fwp_post']['confirm']=='Delete'):
814
- if (isset($GLOBALS['fwp_post']['link_action']) and is_array($GLOBALS['fwp_post']['link_action'])) :
815
- $actions = $GLOBALS['fwp_post']['link_action'];
816
- else :
817
- $actions = array();
818
- endif;
819
-
820
- $do_it = array(
821
- 'hide' => array(),
822
- 'nuke' => array(),
823
- 'delete' => array(),
824
- );
825
-
826
- foreach ($actions as $link_id => $what) :
827
- $do_it[$what][] = $link_id;
828
- endforeach;
829
-
830
- $alter = array();
831
- if (count($do_it['hide']) > 0) :
832
- $hidem = "(".implode(', ', $do_it['hide']).")";
833
- $alter[] = "
834
- UPDATE $wpdb->links
835
- SET link_visible = 'N'
836
- WHERE link_id IN {$hidem}
837
- ";
838
- endif;
839
-
840
- if (count($do_it['nuke']) > 0) :
841
- $nukem = "(".implode(', ', $do_it['nuke']).")";
842
-
843
- // Make a list of the items syndicated from this feed...
844
- $post_ids = $wpdb->get_col("
845
- SELECT post_id FROM $wpdb->postmeta
846
- WHERE meta_key = 'syndication_feed_id'
847
- AND meta_value IN {$nukem}
848
- ");
849
-
850
- // ... and kill them all
851
- if (count($post_ids) > 0) :
852
- foreach ($post_ids as $post_id) :
853
- if (FeedWordPressCompatibility::test_version(FWP_SCHEMA_29)) :
854
- // Force scrubbing of deleted post
855
- // rather than sending to Trashcan
856
- wp_delete_post(
857
- /*postid=*/ $post_id,
858
- /*force_delete=*/ true
859
- );
860
- else :
861
- wp_delete_post($post_id);
862
- endif;
863
- endforeach;
864
- endif;
865
-
866
- $alter[] = "
867
- DELETE FROM $wpdb->links
868
- WHERE link_id IN {$nukem}
869
- ";
870
- endif;
871
-
872
- if (count($do_it['delete']) > 0) :
873
- $deletem = "(".implode(', ', $do_it['delete']).")";
874
-
875
- // Make the items syndicated from this feed appear to be locally-authored
876
- $alter[] = "
877
- DELETE FROM $wpdb->postmeta
878
- WHERE meta_key = 'syndication_feed_id'
879
- AND meta_value IN {$deletem}
880
- ";
881
-
882
- // ... and delete the links themselves.
883
- $alter[] = "
884
- DELETE FROM $wpdb->links
885
- WHERE link_id IN {$deletem}
886
- ";
887
- endif;
888
-
889
- $errs = array(); $success = array ();
890
- foreach ($alter as $sql) :
891
- $result = $wpdb->query($sql);
892
- if (!$result):
893
- $errs[] = mysql_error();
894
- endif;
895
- endforeach;
896
-
897
- if (count($alter) > 0) :
898
- echo "<div class=\"updated\">\n";
899
- if (count($errs) > 0) :
900
- echo "There were some problems processing your ";
901
- echo "unsubscribe request. [SQL: ".implode('; ', $errs)."]";
902
- else :
903
- echo "Your unsubscribe request(s) have been processed.";
904
- endif;
905
- echo "</div>\n";
906
- endif;
907
-
908
- return true; // Continue on to Syndicated Sites listing
909
- else :
910
- $targets = $wpdb->get_results("
911
- SELECT * FROM $wpdb->links
912
- WHERE link_id IN (".implode(",",$link_ids).")
913
- ");
914
- ?>
915
- <form action="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/<?php echo basename(__FILE__); ?>" method="post">
916
- <div class="wrap">
917
- <?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds'); ?>
918
- <input type="hidden" name="action" value="Unsubscribe" />
919
- <input type="hidden" name="confirm" value="Delete" />
920
-
921
- <h2>Unsubscribe from Syndicated Links:</h2>
922
- <?php foreach ($targets as $link) :
923
- $subscribed = ('Y' == strtoupper($link->link_visible));
924
- $link_url = esc_html($link->link_url);
925
- $link_name = esc_html($link->link_name);
926
- $link_description = esc_html($link->link_description);
927
- $link_rss = esc_html($link->link_rss);
928
- ?>
929
- <fieldset>
930
- <legend><?php echo $link_name; ?></legend>
931
- <table class="editform" width="100%" cellspacing="2" cellpadding="5">
932
- <tr><th scope="row" width="20%"><?php _e('Feed URI:') ?></th>
933
- <td width="80%"><a href="<?php echo $link_rss; ?>"><?php echo $link_rss; ?></a></td></tr>
934
- <tr><th scope="row" width="20%"><?php _e('Short description:') ?></th>
935
- <td width="80%"><?php echo $link_description; ?></span></td></tr>
936
- <tr><th width="20%" scope="row"><?php _e('Homepage:') ?></th>
937
- <td width="80%"><a href="<?php echo $link_url; ?>"><?php echo $link_url; ?></a></td></tr>
938
- <tr style="vertical-align:top"><th width="20%" scope="row">Subscription <?php _e('Options') ?>:</th>
939
- <td width="80%"><ul style="margin:0; padding: 0; list-style: none">
940
- <?php if ($subscribed) : ?>
941
- <li><input type="radio" id="hide-<?php echo $link->link_id; ?>"
942
- name="link_action[<?php echo $link->link_id; ?>]" value="hide" checked="checked" />
943
- <label for="hide-<?php echo $link->link_id; ?>">Turn off the subscription for this
944
- syndicated link<br/><span style="font-size:smaller">(Keep the feed information
945
- and all the posts from this feed in the database, but don't syndicate any
946
- new posts from the feed.)</span></label></li>
947
- <?php endif; ?>
948
- <li><input type="radio" id="nuke-<?php echo $link->link_id; ?>"<?php if (!$subscribed) : ?> checked="checked"<?php endif; ?>
949
- name="link_action[<?php echo $link->link_id; ?>]" value="nuke" />
950
- <label for="nuke-<?php echo $link->link_id; ?>">Delete this syndicated link and all the
951
- posts that were syndicated from it</label></li>
952
- <li><input type="radio" id="delete-<?php echo $link->link_id; ?>"
953
- name="link_action[<?php echo $link->link_id; ?>]" value="delete" />
954
- <label for="delete-<?php echo $link->link_id; ?>">Delete this syndicated link, but
955
- <em>keep</em> posts that were syndicated from it (as if they were authored
956
- locally).</label></li>
957
- <li><input type="radio" id="nothing-<?php echo $link->link_id; ?>"
958
- name="link_action[<?php echo $link->link_id; ?>]" value="nothing" />
959
- <label for="nothing-<?php echo $link->link_id; ?>">Keep this feed as it is. I changed
960
- my mind.</label></li>
961
- </ul>
962
- </table>
963
- </fieldset>
964
- <?php endforeach; ?>
965
-
966
- <div class="submit">
967
- <input class="delete" type="submit" name="submit" value="<?php _e('Unsubscribe from selected feeds &raquo;') ?>" />
968
- </div>
969
- </div>
970
- <?php
971
- return false; // Don't continue on to Syndicated Sites listing
972
- endif;
973
- }
974
-
975
- $syndicationPage = new FeedWordPressSyndicationPage;
976
  $syndicationPage->display();
977
 
1
  <?php
2
+ require_once(dirname(__FILE__).'/feedwordpresssyndicationpage.class.php');
3
 
4
+ $syndicationPage = new FeedWordPressSyndicationPage(__FILE__);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  $syndicationPage->display();
6
 
updatedpostscontrol.class.php CHANGED
@@ -6,18 +6,26 @@ class UpdatedPostsControl {
6
  } /* UpdatedPostsControl constructor */
7
 
8
  function display () {
9
- $setting = array(
10
- 'yes' => 'leave unmodified',
11
- 'no' => 'update to match',
 
 
 
 
 
12
  );
13
-
14
- $global_freeze_updates = get_option('feedwordpress_freeze_updates', 'no');
 
 
 
 
 
15
  if ($this->page->for_feed_settings()) :
16
  $aFeed = 'this feed';
17
- $freeze_updates = $this->page->link->setting('freeze updates', NULL, 'default');
18
  else :
19
  $aFeed = 'a syndicated feed';
20
- $freeze_updates = $global_freeze_updates;
21
  endif;
22
  ?>
23
  <tr>
@@ -25,14 +33,15 @@ class UpdatedPostsControl {
25
  <td><p>When <?php print $aFeed; ?> includes updated content for
26
  a post that was already syndicated, should the syndicated copy
27
  of the post be updated to match the revised version?</p>
28
- <ul>
29
- <?php if ($this->page->for_feed_settings()) : ?>
30
- <li><label><input type="radio" name="freeze_updates" value="default" <?php print ($freeze_updates=='default') ? 'checked="checked"':'' ?> /> Use the <a href="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/<?php print basename(__FILE__); ?>">site-wide setting</a> (currently: <strong><?php print $setting[$global_freeze_updates]; ?></strong>)</label></li>
31
- <?php endif; ?>
32
- <li><label><input type="radio" name="freeze_updates" value="no" <?php print ($freeze_updates!='yes' and $freeze_updates!='default') ? 'checked="checked"':'' ?> /> Yes, update the syndicated copy to match</label></li>
33
- <li><label><input type="radio" name="freeze_updates" value="yes" <?php print ($freeze_updates=='yes') ? 'checked="checked"':'' ?> /> No, leave the syndicated copy unmodified</label></li>
34
- </ul></td>
35
- </tr>
 
36
  <?php
37
  } /* UpdatedPostsControl::display() */
38
 
6
  } /* UpdatedPostsControl constructor */
7
 
8
  function display () {
9
+ $settings = array(
10
+ // This is all bass-ackwards because the actual yes/no
11
+ // setting is whether to *freeze* posts out of being
12
+ // updated, not whether to *expose* it to being updated,
13
+ // but in the UI we ask whether the user wants to
14
+ // *expose* it. I have my reasons. Stop judging me!
15
+ 'no' => __('Yes, update the syndicated copy to match'),
16
+ 'yes' => __('No, leave the syndicated copy unmodified'),
17
  );
18
+ $params = array(
19
+ 'setting-default' => 'default',
20
+ 'global-setting-default' => 'no',
21
+ 'labels' => array('yes' => 'leave unmodified', 'no' => 'update to match'),
22
+ 'default-input-value' => 'default',
23
+ );
24
+
25
  if ($this->page->for_feed_settings()) :
26
  $aFeed = 'this feed';
 
27
  else :
28
  $aFeed = 'a syndicated feed';
 
29
  endif;
30
  ?>
31
  <tr>
33
  <td><p>When <?php print $aFeed; ?> includes updated content for
34
  a post that was already syndicated, should the syndicated copy
35
  of the post be updated to match the revised version?</p>
36
+
37
+ <?php
38
+ $this->page->setting_radio_control(
39
+ 'freeze updates', 'freeze_updates',
40
+ $settings, $params
41
+ );
42
+ ?>
43
+
44
+ </td></tr>
45
  <?php
46
  } /* UpdatedPostsControl::display() */
47