FeedWordPress - Version 2014.0805

Version Description

  • FILTERS AND ADD-ONS: A number of new hooks for filters and add-ons to further customize the behavior of FWP have been added.

  • COMPATIBILITY/BUGFIX: Many users saw odd characters, especially "n," appearing in posts in versions of WordPress from 3.6 on, due to a change in when the API expects HTML data for posts to be slashed and when it does not. This has been fixed, so that the junk characters should no longer appear, regardless of your version of WordPress.

  • BUGFIX: A bug preventing FWP from saving categories assigned under Syndication > Categories & Tags has been fixed.

  • BUGFIX: Post-editing related metaboxes should now show up when you edit items of any post type, including custom types, not only normal WordPress posts.

  • BUGFIX: A bug in the admin UI that caused the "Alternative Feeds" / "Find Feeds" box to throw a permissions error has been fixed.

  • BUGFIX: A bug preventing proper mapping of categories and other terms in 2013.0504 has been fixed.

  • BUGFIX: A number of small fixes contributed through Github by Flynsarmy should eliminate PHP warnings for many users on several methods that are called as static methods within FeedWordPress.

Download this release

Release Info

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

Code changes from version 2013.0504 to 2014.0805

admin-ui.php CHANGED
@@ -28,7 +28,7 @@ class FeedWordPressAdminPage {
28
  $slug = preg_replace('/FeedWordPress(.*)Page/', '$1', get_class($this));
29
  return strtolower($slug);
30
  }
31
-
32
  function pagename ($context = NULL) {
33
  if (is_null($context)) :
34
  $context = 'default';
@@ -50,7 +50,7 @@ class FeedWordPressAdminPage {
50
  elseif ($this->save_requested_in($post)) : // User mashed Save Changes
51
  $this->save_settings($post);
52
  endif;
53
- do_action($this->dispatch.'_post', $post, $this);
54
  }
55
 
56
  function update_feed () {
@@ -58,22 +58,25 @@ class FeedWordPressAdminPage {
58
 
59
  add_action('feedwordpress_check_feed', 'update_feeds_mention');
60
  add_action('feedwordpress_check_feed_complete', 'update_feeds_finish', 10, 3);
61
-
62
  print '<div class="updated">';
63
  print "<ul>";
64
  $uri = $this->link->uri();
 
 
 
 
 
 
65
  $delta = $feedwordpress->update($uri);
66
  print "</ul>";
67
 
68
  if (!is_null($delta)) :
69
- $mesg = array();
70
- if (isset($delta['new'])) : $mesg[] = ' '.$delta['new'].' new posts were syndicated'; endif;
71
- if (isset($delta['updated'])) : $mesg[] = ' '.$delta['updated'].' existing posts were updated'; endif;
72
- echo "<p><strong>Update complete.</strong>".implode(' and', $mesg)."</p>";
73
  echo "\n"; flush();
74
  else :
75
- $uri = esc_html($uri);
76
- echo "<p><strong>Error:</strong> There was a problem updating <a href=\"$uri\">$uri</a></p>\n";
77
  endif;
78
  print "</div>\n";
79
  remove_action('feedwordpress_check_feed', 'update_feeds_mention');
@@ -87,7 +90,7 @@ class FeedWordPressAdminPage {
87
  // Save settings
88
  $this->link->save_settings(/*reload=*/ true);
89
  $this->updated = true;
90
-
91
  // Reset, reload
92
  $link_id = $this->link->id;
93
  unset($this->link);
@@ -118,7 +121,7 @@ class FeedWordPressAdminPage {
118
  endif;
119
 
120
  if ($this->for_feed_settings()) : // Check feed-specific setting first; fall back to global
121
- if (!$params['fallback']) : $global_name = NULL; endif;
122
  $ret = $this->link->setting($feed_name, $global_name, $fallback_value, $params['default']);
123
  else : // Check global setting
124
  $ret = get_option($global_name, $fallback_value);
@@ -134,7 +137,7 @@ class FeedWordPressAdminPage {
134
  $feed_name = $names['feed'];
135
  $global_name = 'feedwordpress_'.$names['global'];
136
  endif;
137
-
138
  if ($this->for_feed_settings()) : // Update feed-specific setting
139
  $this->link->update_setting($feed_name, $value, $default);
140
  else : // Update global setting
@@ -148,7 +151,7 @@ class FeedWordPressAdminPage {
148
  function update_requested_in ($post) {
149
  return (isset($post['update']) and (strlen($post['update']) > 0));
150
  }
151
-
152
  /*static*/ function submitted_link_id () {
153
  global $fwp_post;
154
 
@@ -166,7 +169,7 @@ class FeedWordPressAdminPage {
166
  $link_id = MyPHP::request('save_link_id');
167
  endif;
168
  endforeach;
169
-
170
  if (is_null($link_id) and isset($_REQUEST['link_id'])) :
171
  $link_id = MyPHP::request('link_id');
172
  endif;
@@ -212,7 +215,7 @@ class FeedWordPressAdminPage {
212
  function meta_box_context () {
213
  return $this->context;
214
  } /* FeedWordPressAdminPage::meta_box_context () */
215
-
216
  /**
217
  * Outputs JavaScript to fix AJAX toggles settings.
218
  *
@@ -252,7 +255,7 @@ class FeedWordPressAdminPage {
252
  $link_id = NULL;
253
  if (is_object($link)) :
254
  if (method_exists($link, 'found')) :
255
- // Is this a SyndicatedLink object?
256
  if ($link->found()) :
257
  $link_id = $link->link->link_id;
258
  endif;
@@ -284,14 +287,14 @@ class FeedWordPressAdminPage {
284
  'subscription' => $this->link,
285
  ));
286
  $sub = $params['subscription'];
287
-
288
  $links = array(
289
  "Feed" => array('page' => 'feeds-page.php', 'long' => 'Feeds & Updates'),
290
  "Posts" => array('page' => 'posts-page.php', 'long' => 'Posts & Links'),
291
  "Authors" => array('page' => 'authors-page.php', 'long' => 'Authors'),
292
  'Categories' => array('page' => 'categories-page.php', 'long' => 'Categories & Tags'),
293
  );
294
-
295
  $link_id = NULL;
296
  if (is_object($sub)) :
297
  if (method_exists($sub, 'found')) :
@@ -302,40 +305,40 @@ class FeedWordPressAdminPage {
302
  $link_id = $sub->link_id;
303
  endif;
304
  endif;
305
-
306
  print $params['before']; $first = true;
307
  foreach ($links as $label => $link) :
308
  if (!$first) : print $params['between']; endif;
309
-
310
  if (isset($link['url'])) : MyPHP::url($link['url'], array("link_id" => $link_id));
311
  else : $url = $this->admin_page_href($link['page'], array(), $sub);
312
  endif;
313
  $url = esc_html($url);
314
-
315
  if ($link['page']==basename($this->filename)) :
316
  print "<strong>";
317
  else :
318
  print "<a href=\"${url}\">";
319
  endif;
320
-
321
  if ($params['long']) : print esc_html(__($link['long']));
322
  else : print esc_html(__($label));
323
  endif;
324
-
325
  if ($link['page']==basename($this->filename)) :
326
  print "</strong>";
327
  else :
328
  print "</a>";
329
  endif;
330
-
331
  $first = false;
332
  endforeach;
333
  print $params['after'];
334
  } /* FeedWordPressAdminPage::display_feed_settings_page_links */
335
-
336
  function display_feed_select_dropdown() {
337
  $links = FeedWordPress::syndicated_links();
338
-
339
  ?>
340
  <div id="fwpfs-container"><ul class="subsubsub">
341
  <li><select name="link_id" class="fwpfs" style="max-width: 20.0em;">
@@ -353,14 +356,14 @@ class FeedWordPressAdminPage {
353
  'after' => '</li>',
354
  'subscription' => $this->link,
355
  ));
356
-
357
  if ($this->for_feed_settings()) :
358
  ?>
359
  <li><input class="button" type="submit" name="update" value="Update Now" /></li>
360
  <?php
361
  endif;
362
  ?>
363
- </ul>
364
  </div>
365
  <?php
366
  } /* FeedWordPressAdminPage::display_feed_select_dropdown() */
@@ -385,7 +388,7 @@ class FeedWordPressAdminPage {
385
  $this->mesg = $this->updated;
386
  endif;
387
  endif;
388
-
389
  if (!is_null($this->mesg)) :
390
  ?>
391
  <div class="updated">
@@ -408,12 +411,12 @@ class FeedWordPressAdminPage {
408
  <?php
409
  endif;
410
  } /* FeedWordPressAdminPage::display_settings_scope_message () */
411
-
412
  /*static*/ function has_link () { return true; }
413
 
414
  function form_action ($filename = NULL) {
415
  global $fwp_path;
416
-
417
  if (is_null($filename)) :
418
  $filename = basename($this->filename);
419
  endif;
@@ -451,7 +454,7 @@ class FeedWordPressAdminPage {
451
  $this->pagename('settings-update'),
452
  $this->update_message()
453
  );
454
-
455
  $this->open_sheet($this->pagename('open-sheet'));
456
  ?>
457
  <div id="post-body">
@@ -464,7 +467,7 @@ class FeedWordPressAdminPage {
464
  $id = 'feedwordpress_'.$method;
465
  $title = $row;
466
  endif;
467
-
468
  add_meta_box(
469
  /*id=*/ $id,
470
  /*title=*/ $title,
@@ -493,7 +496,7 @@ class FeedWordPressAdminPage {
493
  $this->ajax_interface_js();
494
  ?>
495
  </script>
496
-
497
  <?php
498
  add_action(
499
  FeedWordPressCompatibility::bottom_script_hook($this->filename),
@@ -535,14 +538,14 @@ class FeedWordPressAdminPage {
535
  endif;
536
  ?>
537
  </div>
538
-
539
  <div id="poststuff">
540
  <?php
541
  } /* FeedWordPressAdminPage::open_sheet () */
542
-
543
  function close_sheet () {
544
  ?>
545
-
546
  </div> <!-- id="poststuff" -->
547
  <?php
548
  if (!is_null($this->dispatch)) :
@@ -551,51 +554,51 @@ class FeedWordPressAdminPage {
551
  endif;
552
  ?>
553
  </div> <!-- class="wrap" -->
554
-
555
  <?php
556
  } /* FeedWordPressAdminPage::close_sheet () */
557
-
558
  function setting_radio_control ($localName, $globalName, $options, $params = array()) {
559
  global $fwp_path;
560
-
561
  if (isset($params['filename'])) : $filename = $params['filename'];
562
  else : $filename = basename($this->filename);
563
  endif;
564
-
565
  if (isset($params['site-wide-url'])) : $href = $params['site-wide-url'];
566
  else : $href = $this->admin_page_href($filename);
567
  endif;
568
-
569
  if (isset($params['setting-default'])) : $settingDefault = $params['setting-default'];
570
  else : $settingDefault = NULL;
571
  endif;
572
-
573
  if (isset($params['global-setting-default'])) : $globalSettingDefault = $params['global-setting-default'];
574
  else : $globalSettingDefault = $settingDefault;
575
  endif;
576
 
577
- $globalSetting = get_option('feedwordpress_'.$globalName, $globalSettingDefault);
578
  if ($this->for_feed_settings()) :
579
  $setting = $this->link->setting($localName, NULL, $settingDefault);
580
  else :
581
  $setting = $globalSetting;
582
  endif;
583
-
584
  if (isset($params['offer-site-wide'])) : $offerSiteWide = $params['offer-site-wide'];
585
  else : $offerSiteWide = $this->for_feed_settings();
586
  endif;
587
-
588
  // This allows us to provide an alternative set of human-readable
589
  // labels for each potential value. For use in Currently: line.
590
  if (isset($params['labels'])) : $labels = $params['labels'];
591
  elseif (is_callable($options)) : $labels = NULL;
592
  else : $labels = $options;
593
  endif;
594
-
595
  if (isset($params['input-name'])) : $inputName = $params['input-name'];
596
  else : $inputName = $globalName;
597
  endif;
598
-
599
  if (isset($params['default-input-id'])) : $defaultInputId = $params['default-input-id'];
600
  else : $defaultInputId = NULL;
601
  endif;
@@ -604,7 +607,7 @@ class FeedWordPressAdminPage {
604
  elseif (!is_null($defaultInputId)) : $defaultInputIdNo = $defaultInputId.'-no';
605
  else : $defaultInputIdNo = NULL;
606
  endif;
607
-
608
  // This allows us to either include the site-default setting as
609
  // one of the options within the radio box, or else as a simple
610
  // yes/no toggle that controls whether or not to check another
@@ -622,7 +625,7 @@ class FeedWordPressAdminPage {
622
  : 'site-default'
623
  );
624
  endif;
625
-
626
  $settingDefaulted = (is_null($setting) or ($settingDefault === $setting));
627
 
628
  if (!is_callable($options)) :
@@ -630,7 +633,7 @@ class FeedWordPressAdminPage {
630
  if ($settingDefaulted) :
631
  $checked[$defaultInputValue] = ' checked="checked"';
632
  endif;
633
-
634
  foreach ($options as $value => $label) :
635
  if ($setting == $value) :
636
  $checked[$value] = ' checked="checked"';
@@ -647,7 +650,7 @@ class FeedWordPressAdminPage {
647
  else :
648
  $defaulted['yes'] = (isset($checked[$defaultInputValue]) ? $checked[$defaultInputValue] : '');
649
  endif;
650
-
651
  if (isset($params['defaulted'])) :
652
  $defaulted['yes'] = ($params['defaulted'] ? ' checked="checked"' : '');
653
  $defaulted['no'] = ($params['defaulted'] ? '' : ' checked="checked"');
@@ -674,7 +677,7 @@ class FeedWordPressAdminPage {
674
  print $labels[$globalSetting];
675
  endif; ?></strong> (<a href="<?php print $href; ?>">change</a>)</span></li>
676
  </ul></td>
677
-
678
  <td class="equals second inactive">
679
  <?php if ($defaultInputName != $inputName) : ?>
680
  <ul class="options">
@@ -686,7 +689,7 @@ class FeedWordPressAdminPage {
686
  <?php _e('Do something different with this feed.'); ?></label>
687
  <?php endif;
688
  endif;
689
-
690
  // Let's spit out the controls here.
691
  if (is_callable($options)) :
692
  // Method call to print out options list
@@ -703,7 +706,7 @@ class FeedWordPressAdminPage {
703
  </ul> <!-- class="options" -->
704
  <?php
705
  endif;
706
-
707
  if ($offerSiteWide) :
708
  if ($defaultInputName != $inputName) :
709
  // Close the <li> and <ul class="options"> we opened above
@@ -712,7 +715,7 @@ class FeedWordPressAdminPage {
712
  </ul> <!-- class="options" -->
713
  <?php
714
  endif;
715
-
716
  // Close off the twofer table that we opened up above.
717
  ?>
718
  </td></tr>
@@ -721,7 +724,7 @@ class FeedWordPressAdminPage {
721
  <?php
722
  endif;
723
  } /* FeedWordPressAdminPage::setting_radio_control () */
724
-
725
  function save_button ($caption = NULL) {
726
  if (is_null($caption)) : $caption = __('Save Changes'); endif;
727
  ?>
@@ -732,6 +735,18 @@ class FeedWordPressAdminPage {
732
  }
733
  } /* class FeedWordPressAdminPage */
734
 
 
 
 
 
 
 
 
 
 
 
 
 
735
  function fwp_authors_single_submit ($link = NULL) {
736
  ?>
737
  <div class="submitbox" id="submitlink">
@@ -772,13 +787,13 @@ function fwp_tags_box ($tags, $object, $params = array()) {
772
  'id' => NULL,
773
  'box_title' => __('Post Tags'),
774
  ));
775
-
776
  if (!is_array($tags)) : $tags = array(); endif;
777
-
778
  $tax_name = $params['taxonomy'];
779
  $taxonomy = get_taxonomy($params['taxonomy']);
780
  $disabled = (!current_user_can($taxonomy->cap->assign_terms) ? 'disabled="disabled"' : '');
781
-
782
  $desc = "<p style=\"font-size:smaller;font-style:bold;margin:0\">Tag $object as...</p>";
783
 
784
  if (is_null($params['textarea_name'])) :
@@ -793,11 +808,11 @@ function fwp_tags_box ($tags, $object, $params = array()) {
793
  if (is_null($params['input_name'])) :
794
  $params['input_name'] = "newtag[$tax_name]";
795
  endif;
796
-
797
  if (is_null($params['id'])) :
798
  $params['id'] = $tax_name;
799
  endif;
800
-
801
  print $desc;
802
  $helps = __('Separate tags with commas.');
803
  $box['title'] = __('Tags');
@@ -807,7 +822,7 @@ function fwp_tags_box ($tags, $object, $params = array()) {
807
  <div class="nojs-tags hide-if-js">
808
  <p><?php echo $taxonomy->labels->add_or_remove_items; ?></p>
809
  <textarea name="<?php echo $params['textarea_name']; ?>" class="the-tags" id="<?php echo $params['textarea_id']; ?>"><?php echo esc_attr(implode(",", $tags)); ?></textarea></div>
810
-
811
  <?php if ( current_user_can($taxonomy->cap->assign_terms) ) :?>
812
  <div class="ajaxtag hide-if-no-js">
813
  <label class="screen-reader-text" for="<?php echo $params['input_id']; ?>"><?php echo $params['box_title']; ?></label>
@@ -818,7 +833,7 @@ function fwp_tags_box ($tags, $object, $params = array()) {
818
  <p class="howto"><?php echo esc_attr( $taxonomy->labels->separate_items_with_commas ); ?></p>
819
  <?php endif; ?>
820
  </div>
821
-
822
  <div class="tagchecklist"></div>
823
  </div>
824
  <?php if ( current_user_can($taxonomy->cap->assign_terms) ) : ?>
@@ -869,7 +884,7 @@ function fwp_category_box ($checked, $object, $tags = array(), $params = array()
869
  <p id="<?php print $idPrefix; ?><?php print $taxonomy; ?>-add" class="category-add wp-hidden-child">
870
  <?php
871
  $newcat = 'new'.$taxonomy;
872
-
873
  ?>
874
  <label class="screen-reader-text" for="<?php print $idPrefix; ?>new<?php print $taxonomy; ?>"><?php _e('Add New Category'); ?></label>
875
  <input
@@ -877,7 +892,7 @@ function fwp_category_box ($checked, $object, $tags = array(), $params = array()
877
  class="new<?php print $taxonomy; ?> form-required form-input-tip"
878
  aria-required="true"
879
  tabindex="3"
880
- type="text" name="<?php print $newcat; ?>"
881
  value="<?php _e( 'New category name' ); ?>"
882
  />
883
  <label class="screen-reader-text" for="<?php print $idPrefix; ?>new<?php print $taxonomy; ?>-parent"><?php _e('Parent Category:'); ?></label>
@@ -926,7 +941,7 @@ function fwp_author_list () {
926
  global $wpdb;
927
  $ret = array();
928
 
929
- $users = get_users_of_blog();
930
  if (is_array($users)) :
931
  foreach ($users as $user) :
932
  $id = (int) $user->ID;
@@ -940,9 +955,9 @@ function fwp_author_list () {
940
  }
941
 
942
  class FeedWordPressSettingsUI {
943
- function is_admin () {
944
  global $fwp_path;
945
-
946
  $admin_page = false; // Innocent until proven guilty
947
  if (isset($_REQUEST['page'])) :
948
  $admin_page = (
@@ -952,18 +967,18 @@ class FeedWordPressSettingsUI {
952
  endif;
953
  return $admin_page;
954
  }
955
-
956
- function admin_scripts () {
957
  global $fwp_path;
958
-
959
  wp_enqueue_script('post'); // for magic tag and category boxes
960
  wp_enqueue_script('admin-forms'); // for checkbox selection
961
-
962
  wp_register_script('feedwordpress-elements', WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-elements.js');
963
  wp_enqueue_script('feedwordpress-elements');
964
  }
965
 
966
- function admin_styles () {
967
  ?>
968
  <style type="text/css">
969
  #feedwordpress-admin-feeds .link-rss-params-remove .x, .feedwordpress-admin .remove-it .x {
@@ -985,7 +1000,7 @@ class FeedWordPressSettingsUI {
985
  background-position:0 top;
986
  background-repeat:repeat-x;
987
  }
988
-
989
  .update-results {
990
  max-width: 100%;
991
  overflow: auto;
@@ -994,8 +1009,8 @@ class FeedWordPressSettingsUI {
994
  </style>
995
  <?php
996
  } /* FeedWordPressSettingsUI::admin_styles () */
997
-
998
- /*static*/ function ajax_nonce_fields () {
999
  if (function_exists('wp_nonce_field')) :
1000
  echo "<form style='display: none' method='get' action=''>\n<p>\n";
1001
  wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
@@ -1004,24 +1019,24 @@ class FeedWordPressSettingsUI {
1004
  endif;
1005
  } /* FeedWordPressSettingsUI::ajax_nonce_fields () */
1006
 
1007
- /*static*/ function fix_toggles_js ($context) {
1008
  ?>
1009
  <script type="text/javascript">
1010
- jQuery(document).ready( function($) {
1011
  // In case someone got here first...
1012
  $('.postbox h3, .postbox .handlediv').unbind('click');
1013
  $('.postbox h3 a').unbind('click');
1014
  $('.hide-postbox-tog').unbind('click');
1015
  $('.columns-prefs input[type="radio"]').unbind('click');
1016
  $('.meta-box-sortables').sortable('destroy');
1017
-
1018
  postboxes.add_postbox_toggles('<?php print $context; ?>');
1019
  } );
1020
  </script>
1021
  <?php
1022
  } /* FeedWordPressSettingsUI::fix_toggles_js () */
1023
-
1024
- function magic_input_tip_js ($id) {
1025
  if (!preg_match('/^[.#]/', $id)) :
1026
  $id = '#'.$id;
1027
  endif;
@@ -1038,7 +1053,7 @@ class FeedWordPressSettingsUI {
1038
  inputBox.blur(function() {
1039
  if ( this.value == '' )
1040
  jQuery(this).val( this.defaultValue ).addClass( 'form-input-tip' );
1041
- });
1042
  } );
1043
  </script>
1044
  <?php
@@ -1056,10 +1071,10 @@ function fwp_insert_new_user ($newuser_name) {
1056
  $userdata['user_nicename'] = apply_filters('pre_user_nicename', sanitize_title($newuser_name));
1057
  $userdata['display_name'] = $newuser_name;
1058
  $userdata['user_pass'] = substr(md5(uniqid(microtime())), 0, 6); // just something random to lock it up
1059
-
1060
  $blahUrl = get_bloginfo('url'); $url = parse_url($blahUrl);
1061
  $userdata['user_email'] = substr(md5(uniqid(microtime())), 0, 6).'@'.$url['host'];
1062
-
1063
  $newuser_id = wp_insert_user($userdata);
1064
  $ret = $newuser_id; // Either a numeric ID or a WP_Error object
1065
  else :
@@ -1081,7 +1096,7 @@ function fwp_add_meta_box ($id, $title, $callback, $page, $context = 'advanced',
1081
 
1082
  function fwp_do_meta_boxes($page, $context, $object) {
1083
  $ret = do_meta_boxes($page, $context, $object);
1084
-
1085
  // Avoid JavaScript error from WordPress 2.5 bug
1086
  ?>
1087
  <div style="display: none">
@@ -1096,7 +1111,7 @@ function fwp_remove_meta_box($id, $page, $context) {
1096
  } /* function fwp_remove_meta_box() */
1097
 
1098
  function fwp_syndication_manage_page_links_table_rows ($links, $page, $visible = 'Y') {
1099
-
1100
  $subscribed = ('Y' == strtoupper($visible));
1101
  if ($subscribed or (count($links) > 0)) :
1102
  ?>
@@ -1112,7 +1127,7 @@ function fwp_syndication_manage_page_links_table_rows ($links, $page, $visible =
1112
 
1113
  <tbody>
1114
  <?php
1115
- $alt_row = true;
1116
  if (count($links) > 0):
1117
  foreach ($links as $link):
1118
  $trClass = array();
@@ -1130,7 +1145,7 @@ function fwp_syndication_manage_page_links_table_rows ($links, $page, $visible =
1130
  if (is_null($sLink->setting('update/error'))) :
1131
  $errorsSince = '';
1132
  if (!is_null($sLink->setting('link/item count'))) :
1133
- $N = $sLink->setting('link/item count');
1134
  $fileSizeLines[] = sprintf((($N==1) ? __('%d item') : __('%d items')), $N);
1135
  endif;
1136
 
@@ -1141,7 +1156,7 @@ function fwp_syndication_manage_page_links_table_rows ($links, $page, $visible =
1141
  $trClass[] = 'feed-error';
1142
 
1143
  $theError = unserialize($sLink->setting('update/error'));
1144
-
1145
  $errorsSince = "<div class=\"returning-errors\">"
1146
  ."<p><strong>Returning errors</strong> since "
1147
  .fwp_time_elapsed($theError['since'])
@@ -1155,7 +1170,7 @@ function fwp_syndication_manage_page_links_table_rows ($links, $page, $visible =
1155
  endif;
1156
 
1157
  $nextUpdate = "<div style='max-width: 30.0em; font-size: 0.9em;'><div style='font-style:italic;'>";
1158
-
1159
  $ttl = $sLink->setting('update/ttl');
1160
  if (is_numeric($ttl)) :
1161
  $next = $sLink->setting('update/last') + $sLink->setting('update/fudge') + ((int) $ttl * 60);
@@ -1178,7 +1193,7 @@ function fwp_syndication_manage_page_links_table_rows ($links, $page, $visible =
1178
  else :
1179
  $lastUpdated .= gmdate('F j', $next + (get_option('gmt_offset') * 3600));
1180
  endif;
1181
-
1182
  $nextUpdate .= "Scheduled to be checked for updates every ".$ttl." minute".(($ttl!=1)?"s":"")."</div><div style='size:0.9em; margin-top: 0.5em'> This update schedule was requested by the feed provider";
1183
  if ($sLink->setting('update/xml')) :
1184
  $nextUpdate .= " using a standard <code style=\"font-size: inherit; padding: 0; background: transparent\">&lt;".$sLink->setting('update/xml')."&gt;</code> element";
@@ -1194,11 +1209,11 @@ function fwp_syndication_manage_page_links_table_rows ($links, $page, $visible =
1194
  if (count($fileSizeLines) > 0) :
1195
  $fileSize = '<div>'.implode(" / ", $fileSizeLines)."</div>";
1196
  endif;
1197
-
1198
  unset($sLink);
1199
-
1200
  $alt_row = !$alt_row;
1201
-
1202
  if ($alt_row) :
1203
  $trClass[] = 'alternate';
1204
  endif;
28
  $slug = preg_replace('/FeedWordPress(.*)Page/', '$1', get_class($this));
29
  return strtolower($slug);
30
  }
31
+
32
  function pagename ($context = NULL) {
33
  if (is_null($context)) :
34
  $context = 'default';
50
  elseif ($this->save_requested_in($post)) : // User mashed Save Changes
51
  $this->save_settings($post);
52
  endif;
53
+ do_action($this->dispatch.'_post', $post, $this);
54
  }
55
 
56
  function update_feed () {
58
 
59
  add_action('feedwordpress_check_feed', 'update_feeds_mention');
60
  add_action('feedwordpress_check_feed_complete', 'update_feeds_finish', 10, 3);
61
+
62
  print '<div class="updated">';
63
  print "<ul>";
64
  $uri = $this->link->uri();
65
+ $displayUrl = $uri;
66
+
67
+ // check for effects of an effective-url filter
68
+ $effectiveUrl = $link->uri(array('fetch' => true));
69
+ if ($uri != $effectiveUrl) : $displayUrl .= ' | ' . $effectiveUrl; endif;
70
+
71
  $delta = $feedwordpress->update($uri);
72
  print "</ul>";
73
 
74
  if (!is_null($delta)) :
75
+ echo "<p><strong>Update complete.</strong>".fwp_update_set_results_message($delta)."</p>";
 
 
 
76
  echo "\n"; flush();
77
  else :
78
+ $effectiveUrl = esc_html($effectiveUrl);
79
+ echo "<p><strong>Error:</strong> There was a problem updating <a href=\"$effectiveUrl\">$displayUrl</a></p>\n";
80
  endif;
81
  print "</div>\n";
82
  remove_action('feedwordpress_check_feed', 'update_feeds_mention');
90
  // Save settings
91
  $this->link->save_settings(/*reload=*/ true);
92
  $this->updated = true;
93
+
94
  // Reset, reload
95
  $link_id = $this->link->id;
96
  unset($this->link);
121
  endif;
122
 
123
  if ($this->for_feed_settings()) : // Check feed-specific setting first; fall back to global
124
+ if (!$params['fallback']) : $global_name = NULL; endif;
125
  $ret = $this->link->setting($feed_name, $global_name, $fallback_value, $params['default']);
126
  else : // Check global setting
127
  $ret = get_option($global_name, $fallback_value);
137
  $feed_name = $names['feed'];
138
  $global_name = 'feedwordpress_'.$names['global'];
139
  endif;
140
+
141
  if ($this->for_feed_settings()) : // Update feed-specific setting
142
  $this->link->update_setting($feed_name, $value, $default);
143
  else : // Update global setting
151
  function update_requested_in ($post) {
152
  return (isset($post['update']) and (strlen($post['update']) > 0));
153
  }
154
+
155
  /*static*/ function submitted_link_id () {
156
  global $fwp_post;
157
 
169
  $link_id = MyPHP::request('save_link_id');
170
  endif;
171
  endforeach;
172
+
173
  if (is_null($link_id) and isset($_REQUEST['link_id'])) :
174
  $link_id = MyPHP::request('link_id');
175
  endif;
215
  function meta_box_context () {
216
  return $this->context;
217
  } /* FeedWordPressAdminPage::meta_box_context () */
218
+
219
  /**
220
  * Outputs JavaScript to fix AJAX toggles settings.
221
  *
255
  $link_id = NULL;
256
  if (is_object($link)) :
257
  if (method_exists($link, 'found')) :
258
+ // Is this a SyndicatedLink object?
259
  if ($link->found()) :
260
  $link_id = $link->link->link_id;
261
  endif;
287
  'subscription' => $this->link,
288
  ));
289
  $sub = $params['subscription'];
290
+
291
  $links = array(
292
  "Feed" => array('page' => 'feeds-page.php', 'long' => 'Feeds & Updates'),
293
  "Posts" => array('page' => 'posts-page.php', 'long' => 'Posts & Links'),
294
  "Authors" => array('page' => 'authors-page.php', 'long' => 'Authors'),
295
  'Categories' => array('page' => 'categories-page.php', 'long' => 'Categories & Tags'),
296
  );
297
+
298
  $link_id = NULL;
299
  if (is_object($sub)) :
300
  if (method_exists($sub, 'found')) :
305
  $link_id = $sub->link_id;
306
  endif;
307
  endif;
308
+
309
  print $params['before']; $first = true;
310
  foreach ($links as $label => $link) :
311
  if (!$first) : print $params['between']; endif;
312
+
313
  if (isset($link['url'])) : MyPHP::url($link['url'], array("link_id" => $link_id));
314
  else : $url = $this->admin_page_href($link['page'], array(), $sub);
315
  endif;
316
  $url = esc_html($url);
317
+
318
  if ($link['page']==basename($this->filename)) :
319
  print "<strong>";
320
  else :
321
  print "<a href=\"${url}\">";
322
  endif;
323
+
324
  if ($params['long']) : print esc_html(__($link['long']));
325
  else : print esc_html(__($label));
326
  endif;
327
+
328
  if ($link['page']==basename($this->filename)) :
329
  print "</strong>";
330
  else :
331
  print "</a>";
332
  endif;
333
+
334
  $first = false;
335
  endforeach;
336
  print $params['after'];
337
  } /* FeedWordPressAdminPage::display_feed_settings_page_links */
338
+
339
  function display_feed_select_dropdown() {
340
  $links = FeedWordPress::syndicated_links();
341
+
342
  ?>
343
  <div id="fwpfs-container"><ul class="subsubsub">
344
  <li><select name="link_id" class="fwpfs" style="max-width: 20.0em;">
356
  'after' => '</li>',
357
  'subscription' => $this->link,
358
  ));
359
+
360
  if ($this->for_feed_settings()) :
361
  ?>
362
  <li><input class="button" type="submit" name="update" value="Update Now" /></li>
363
  <?php
364
  endif;
365
  ?>
366
+ </ul>
367
  </div>
368
  <?php
369
  } /* FeedWordPressAdminPage::display_feed_select_dropdown() */
388
  $this->mesg = $this->updated;
389
  endif;
390
  endif;
391
+
392
  if (!is_null($this->mesg)) :
393
  ?>
394
  <div class="updated">
411
  <?php
412
  endif;
413
  } /* FeedWordPressAdminPage::display_settings_scope_message () */
414
+
415
  /*static*/ function has_link () { return true; }
416
 
417
  function form_action ($filename = NULL) {
418
  global $fwp_path;
419
+
420
  if (is_null($filename)) :
421
  $filename = basename($this->filename);
422
  endif;
454
  $this->pagename('settings-update'),
455
  $this->update_message()
456
  );
457
+
458
  $this->open_sheet($this->pagename('open-sheet'));
459
  ?>
460
  <div id="post-body">
467
  $id = 'feedwordpress_'.$method;
468
  $title = $row;
469
  endif;
470
+
471
  add_meta_box(
472
  /*id=*/ $id,
473
  /*title=*/ $title,
496
  $this->ajax_interface_js();
497
  ?>
498
  </script>
499
+
500
  <?php
501
  add_action(
502
  FeedWordPressCompatibility::bottom_script_hook($this->filename),
538
  endif;
539
  ?>
540
  </div>
541
+
542
  <div id="poststuff">
543
  <?php
544
  } /* FeedWordPressAdminPage::open_sheet () */
545
+
546
  function close_sheet () {
547
  ?>
548
+
549
  </div> <!-- id="poststuff" -->
550
  <?php
551
  if (!is_null($this->dispatch)) :
554
  endif;
555
  ?>
556
  </div> <!-- class="wrap" -->
557
+
558
  <?php
559
  } /* FeedWordPressAdminPage::close_sheet () */
560
+
561
  function setting_radio_control ($localName, $globalName, $options, $params = array()) {
562
  global $fwp_path;
563
+
564
  if (isset($params['filename'])) : $filename = $params['filename'];
565
  else : $filename = basename($this->filename);
566
  endif;
567
+
568
  if (isset($params['site-wide-url'])) : $href = $params['site-wide-url'];
569
  else : $href = $this->admin_page_href($filename);
570
  endif;
571
+
572
  if (isset($params['setting-default'])) : $settingDefault = $params['setting-default'];
573
  else : $settingDefault = NULL;
574
  endif;
575
+
576
  if (isset($params['global-setting-default'])) : $globalSettingDefault = $params['global-setting-default'];
577
  else : $globalSettingDefault = $settingDefault;
578
  endif;
579
 
580
+ $globalSetting = get_option('feedwordpress_'.$globalName, $globalSettingDefault);
581
  if ($this->for_feed_settings()) :
582
  $setting = $this->link->setting($localName, NULL, $settingDefault);
583
  else :
584
  $setting = $globalSetting;
585
  endif;
586
+
587
  if (isset($params['offer-site-wide'])) : $offerSiteWide = $params['offer-site-wide'];
588
  else : $offerSiteWide = $this->for_feed_settings();
589
  endif;
590
+
591
  // This allows us to provide an alternative set of human-readable
592
  // labels for each potential value. For use in Currently: line.
593
  if (isset($params['labels'])) : $labels = $params['labels'];
594
  elseif (is_callable($options)) : $labels = NULL;
595
  else : $labels = $options;
596
  endif;
597
+
598
  if (isset($params['input-name'])) : $inputName = $params['input-name'];
599
  else : $inputName = $globalName;
600
  endif;
601
+
602
  if (isset($params['default-input-id'])) : $defaultInputId = $params['default-input-id'];
603
  else : $defaultInputId = NULL;
604
  endif;
607
  elseif (!is_null($defaultInputId)) : $defaultInputIdNo = $defaultInputId.'-no';
608
  else : $defaultInputIdNo = NULL;
609
  endif;
610
+
611
  // This allows us to either include the site-default setting as
612
  // one of the options within the radio box, or else as a simple
613
  // yes/no toggle that controls whether or not to check another
625
  : 'site-default'
626
  );
627
  endif;
628
+
629
  $settingDefaulted = (is_null($setting) or ($settingDefault === $setting));
630
 
631
  if (!is_callable($options)) :
633
  if ($settingDefaulted) :
634
  $checked[$defaultInputValue] = ' checked="checked"';
635
  endif;
636
+
637
  foreach ($options as $value => $label) :
638
  if ($setting == $value) :
639
  $checked[$value] = ' checked="checked"';
650
  else :
651
  $defaulted['yes'] = (isset($checked[$defaultInputValue]) ? $checked[$defaultInputValue] : '');
652
  endif;
653
+
654
  if (isset($params['defaulted'])) :
655
  $defaulted['yes'] = ($params['defaulted'] ? ' checked="checked"' : '');
656
  $defaulted['no'] = ($params['defaulted'] ? '' : ' checked="checked"');
677
  print $labels[$globalSetting];
678
  endif; ?></strong> (<a href="<?php print $href; ?>">change</a>)</span></li>
679
  </ul></td>
680
+
681
  <td class="equals second inactive">
682
  <?php if ($defaultInputName != $inputName) : ?>
683
  <ul class="options">
689
  <?php _e('Do something different with this feed.'); ?></label>
690
  <?php endif;
691
  endif;
692
+
693
  // Let's spit out the controls here.
694
  if (is_callable($options)) :
695
  // Method call to print out options list
706
  </ul> <!-- class="options" -->
707
  <?php
708
  endif;
709
+
710
  if ($offerSiteWide) :
711
  if ($defaultInputName != $inputName) :
712
  // Close the <li> and <ul class="options"> we opened above
715
  </ul> <!-- class="options" -->
716
  <?php
717
  endif;
718
+
719
  // Close off the twofer table that we opened up above.
720
  ?>
721
  </td></tr>
724
  <?php
725
  endif;
726
  } /* FeedWordPressAdminPage::setting_radio_control () */
727
+
728
  function save_button ($caption = NULL) {
729
  if (is_null($caption)) : $caption = __('Save Changes'); endif;
730
  ?>
735
  }
736
  } /* class FeedWordPressAdminPage */
737
 
738
+ function fwp_update_set_results_message ($delta, $joiner = ';') {
739
+ $mesg = array();
740
+ if (isset($delta['new'])) : $mesg[] = ' '.$delta['new'].' new posts were syndicated'; endif;
741
+ if (isset($delta['updated']) and ($delta['updated'] != 0)) : $mesg[] = ' '.$delta['updated'].' existing posts were updated'; endif;
742
+ if (isset($delta['stored']) and ($delta['stored'] != 0)) : $mesg[] = ' '.$delta['stored'].' alternate versions of existing posts were stored for reference'; endif;
743
+
744
+ if (!is_null($joiner)) :
745
+ $mesg = implode($joiner, $mesg);
746
+ endif;
747
+ return $mesg;
748
+ } /* function fwp_update_set_results_message () */
749
+
750
  function fwp_authors_single_submit ($link = NULL) {
751
  ?>
752
  <div class="submitbox" id="submitlink">
787
  'id' => NULL,
788
  'box_title' => __('Post Tags'),
789
  ));
790
+
791
  if (!is_array($tags)) : $tags = array(); endif;
792
+
793
  $tax_name = $params['taxonomy'];
794
  $taxonomy = get_taxonomy($params['taxonomy']);
795
  $disabled = (!current_user_can($taxonomy->cap->assign_terms) ? 'disabled="disabled"' : '');
796
+
797
  $desc = "<p style=\"font-size:smaller;font-style:bold;margin:0\">Tag $object as...</p>";
798
 
799
  if (is_null($params['textarea_name'])) :
808
  if (is_null($params['input_name'])) :
809
  $params['input_name'] = "newtag[$tax_name]";
810
  endif;
811
+
812
  if (is_null($params['id'])) :
813
  $params['id'] = $tax_name;
814
  endif;
815
+
816
  print $desc;
817
  $helps = __('Separate tags with commas.');
818
  $box['title'] = __('Tags');
822
  <div class="nojs-tags hide-if-js">
823
  <p><?php echo $taxonomy->labels->add_or_remove_items; ?></p>
824
  <textarea name="<?php echo $params['textarea_name']; ?>" class="the-tags" id="<?php echo $params['textarea_id']; ?>"><?php echo esc_attr(implode(",", $tags)); ?></textarea></div>
825
+
826
  <?php if ( current_user_can($taxonomy->cap->assign_terms) ) :?>
827
  <div class="ajaxtag hide-if-no-js">
828
  <label class="screen-reader-text" for="<?php echo $params['input_id']; ?>"><?php echo $params['box_title']; ?></label>
833
  <p class="howto"><?php echo esc_attr( $taxonomy->labels->separate_items_with_commas ); ?></p>
834
  <?php endif; ?>
835
  </div>
836
+
837
  <div class="tagchecklist"></div>
838
  </div>
839
  <?php if ( current_user_can($taxonomy->cap->assign_terms) ) : ?>
884
  <p id="<?php print $idPrefix; ?><?php print $taxonomy; ?>-add" class="category-add wp-hidden-child">
885
  <?php
886
  $newcat = 'new'.$taxonomy;
887
+
888
  ?>
889
  <label class="screen-reader-text" for="<?php print $idPrefix; ?>new<?php print $taxonomy; ?>"><?php _e('Add New Category'); ?></label>
890
  <input
892
  class="new<?php print $taxonomy; ?> form-required form-input-tip"
893
  aria-required="true"
894
  tabindex="3"
895
+ type="text" name="<?php print $newcat; ?>"
896
  value="<?php _e( 'New category name' ); ?>"
897
  />
898
  <label class="screen-reader-text" for="<?php print $idPrefix; ?>new<?php print $taxonomy; ?>-parent"><?php _e('Parent Category:'); ?></label>
941
  global $wpdb;
942
  $ret = array();
943
 
944
+ $users = get_users();
945
  if (is_array($users)) :
946
  foreach ($users as $user) :
947
  $id = (int) $user->ID;
955
  }
956
 
957
  class FeedWordPressSettingsUI {
958
+ static function is_admin () {
959
  global $fwp_path;
960
+
961
  $admin_page = false; // Innocent until proven guilty
962
  if (isset($_REQUEST['page'])) :
963
  $admin_page = (
967
  endif;
968
  return $admin_page;
969
  }
970
+
971
+ static function admin_scripts () {
972
  global $fwp_path;
973
+
974
  wp_enqueue_script('post'); // for magic tag and category boxes
975
  wp_enqueue_script('admin-forms'); // for checkbox selection
976
+
977
  wp_register_script('feedwordpress-elements', WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-elements.js');
978
  wp_enqueue_script('feedwordpress-elements');
979
  }
980
 
981
+ static function admin_styles () {
982
  ?>
983
  <style type="text/css">
984
  #feedwordpress-admin-feeds .link-rss-params-remove .x, .feedwordpress-admin .remove-it .x {
1000
  background-position:0 top;
1001
  background-repeat:repeat-x;
1002
  }
1003
+
1004
  .update-results {
1005
  max-width: 100%;
1006
  overflow: auto;
1009
  </style>
1010
  <?php
1011
  } /* FeedWordPressSettingsUI::admin_styles () */
1012
+
1013
+ static function ajax_nonce_fields () {
1014
  if (function_exists('wp_nonce_field')) :
1015
  echo "<form style='display: none' method='get' action=''>\n<p>\n";
1016
  wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
1019
  endif;
1020
  } /* FeedWordPressSettingsUI::ajax_nonce_fields () */
1021
 
1022
+ static function fix_toggles_js ($context) {
1023
  ?>
1024
  <script type="text/javascript">
1025
+ jQuery(document).ready( function($) {
1026
  // In case someone got here first...
1027
  $('.postbox h3, .postbox .handlediv').unbind('click');
1028
  $('.postbox h3 a').unbind('click');
1029
  $('.hide-postbox-tog').unbind('click');
1030
  $('.columns-prefs input[type="radio"]').unbind('click');
1031
  $('.meta-box-sortables').sortable('destroy');
1032
+
1033
  postboxes.add_postbox_toggles('<?php print $context; ?>');
1034
  } );
1035
  </script>
1036
  <?php
1037
  } /* FeedWordPressSettingsUI::fix_toggles_js () */
1038
+
1039
+ static function magic_input_tip_js ($id) {
1040
  if (!preg_match('/^[.#]/', $id)) :
1041
  $id = '#'.$id;
1042
  endif;
1053
  inputBox.blur(function() {
1054
  if ( this.value == '' )
1055
  jQuery(this).val( this.defaultValue ).addClass( 'form-input-tip' );
1056
+ });
1057
  } );
1058
  </script>
1059
  <?php
1071
  $userdata['user_nicename'] = apply_filters('pre_user_nicename', sanitize_title($newuser_name));
1072
  $userdata['display_name'] = $newuser_name;
1073
  $userdata['user_pass'] = substr(md5(uniqid(microtime())), 0, 6); // just something random to lock it up
1074
+
1075
  $blahUrl = get_bloginfo('url'); $url = parse_url($blahUrl);
1076
  $userdata['user_email'] = substr(md5(uniqid(microtime())), 0, 6).'@'.$url['host'];
1077
+
1078
  $newuser_id = wp_insert_user($userdata);
1079
  $ret = $newuser_id; // Either a numeric ID or a WP_Error object
1080
  else :
1096
 
1097
  function fwp_do_meta_boxes($page, $context, $object) {
1098
  $ret = do_meta_boxes($page, $context, $object);
1099
+
1100
  // Avoid JavaScript error from WordPress 2.5 bug
1101
  ?>
1102
  <div style="display: none">
1111
  } /* function fwp_remove_meta_box() */
1112
 
1113
  function fwp_syndication_manage_page_links_table_rows ($links, $page, $visible = 'Y') {
1114
+
1115
  $subscribed = ('Y' == strtoupper($visible));
1116
  if ($subscribed or (count($links) > 0)) :
1117
  ?>
1127
 
1128
  <tbody>
1129
  <?php
1130
+ $alt_row = true;
1131
  if (count($links) > 0):
1132
  foreach ($links as $link):
1133
  $trClass = array();
1145
  if (is_null($sLink->setting('update/error'))) :
1146
  $errorsSince = '';
1147
  if (!is_null($sLink->setting('link/item count'))) :
1148
+ $N = $sLink->setting('link/item count');
1149
  $fileSizeLines[] = sprintf((($N==1) ? __('%d item') : __('%d items')), $N);
1150
  endif;
1151
 
1156
  $trClass[] = 'feed-error';
1157
 
1158
  $theError = unserialize($sLink->setting('update/error'));
1159
+
1160
  $errorsSince = "<div class=\"returning-errors\">"
1161
  ."<p><strong>Returning errors</strong> since "
1162
  .fwp_time_elapsed($theError['since'])
1170
  endif;
1171
 
1172
  $nextUpdate = "<div style='max-width: 30.0em; font-size: 0.9em;'><div style='font-style:italic;'>";
1173
+
1174
  $ttl = $sLink->setting('update/ttl');
1175
  if (is_numeric($ttl)) :
1176
  $next = $sLink->setting('update/last') + $sLink->setting('update/fudge') + ((int) $ttl * 60);
1193
  else :
1194
  $lastUpdated .= gmdate('F j', $next + (get_option('gmt_offset') * 3600));
1195
  endif;
1196
+
1197
  $nextUpdate .= "Scheduled to be checked for updates every ".$ttl." minute".(($ttl!=1)?"s":"")."</div><div style='size:0.9em; margin-top: 0.5em'> This update schedule was requested by the feed provider";
1198
  if ($sLink->setting('update/xml')) :
1199
  $nextUpdate .= " using a standard <code style=\"font-size: inherit; padding: 0; background: transparent\">&lt;".$sLink->setting('update/xml')."&gt;</code> element";
1209
  if (count($fileSizeLines) > 0) :
1210
  $fileSize = '<div>'.implode(" / ", $fileSizeLines)."</div>";
1211
  endif;
1212
+
1213
  unset($sLink);
1214
+
1215
  $alt_row = !$alt_row;
1216
+
1217
  if ($alt_row) :
1218
  $trClass[] = 'alternate';
1219
  endif;
btc-qr-64px.png ADDED
Binary file
categories-page.php CHANGED
@@ -6,7 +6,7 @@ class FeedWordPressCategoriesPage extends FeedWordPressAdminPage {
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(
@@ -16,7 +16,7 @@ class FeedWordPressCategoriesPage extends FeedWordPressAdminPage {
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]);
@@ -24,11 +24,11 @@ class FeedWordPressCategoriesPage extends FeedWordPressAdminPage {
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');
@@ -42,7 +42,7 @@ class FeedWordPressCategoriesPage extends FeedWordPressAdminPage {
42
  $tagLikeTaxonomies = array();
43
  foreach ($taxonomies as $tax) :
44
  $taxonomy = get_taxonomy($tax);
45
-
46
  if (!$taxonomy->hierarchical) :
47
  $tagLikeTaxonomies[] = $tax;
48
  endif;
@@ -62,12 +62,12 @@ class FeedWordPressCategoriesPage extends FeedWordPressAdminPage {
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'),
@@ -77,21 +77,21 @@ class FeedWordPressCategoriesPage extends FeedWordPressAdminPage {
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 :
@@ -126,30 +126,30 @@ class FeedWordPressCategoriesPage extends FeedWordPressAdminPage {
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(
@@ -159,12 +159,12 @@ class FeedWordPressCategoriesPage extends FeedWordPressAdminPage {
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;
@@ -175,7 +175,7 @@ class FeedWordPressCategoriesPage extends FeedWordPressAdminPage {
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])) :
@@ -350,7 +350,7 @@ least one local <strong><?php $l = $li['labels']; print $l->singular_name; ?></s
350
  <?php if ($page->for_feed_settings()) : ?>
351
  <tr>
352
  <th scope="row">Multiple categories:</th>
353
- <td>
354
  <input type="text" size="20" id="cat_split" name="cat_split" value="<?php if (isset($link->settings['cat_split'])) : echo htmlspecialchars($link->settings['cat_split']); endif; ?>" />
355
  <p class="setting-description">Enter a <a href="http://us.php.net/manual/en/reference.pcre.pattern.syntax.php">Perl-compatible regular expression</a> here if the feed provides multiple
356
  categories in a single category element. The regular expression should match
@@ -376,9 +376,11 @@ blank.</p></td>
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');
@@ -417,7 +419,7 @@ blank.</p></td>
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);
@@ -430,7 +432,7 @@ blank.</p></td>
430
  else :
431
  $cats = $globalCats;
432
  endif;
433
-
434
  if ($page->for_feed_settings()) :
435
  ?>
436
  <table class="twofer">
@@ -439,17 +441,17 @@ blank.</p></td>
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 = $this->admin_page_href(basename(__FILE__));
454
 
455
  if ($page->for_feed_settings()) :
@@ -472,7 +474,7 @@ blank.</p></td>
472
  Should <?php print $page->these_posts_phrase(); ?> be assigned
473
  these <?php print $taxonomy->labels->name; ?> from the <a href="<?php print esc_html($siteWideHref); ?>">site-wide settings</a>, in
474
  addition to the feed-specific <?php print $taxonomy->labels->name; ?> you set up here?</p>
475
-
476
  <ul class="settings">
477
  <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>
478
  <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 use the global defaults for <?php print $page->these_posts_phrase(); ?></label></p></li>
@@ -493,7 +495,7 @@ blank.</p></td>
493
  </table>
494
  <?php
495
  } /* FeedWordPressCategoriesPage::categories_box () */
496
-
497
  function save_settings ($post) {
498
  if (isset($post['match_categories'])) :
499
  foreach ($post['match_categories'] as $what => $set) :
@@ -504,7 +506,7 @@ blank.</p></td>
504
  and $post['match_default'][$what]=='yes') :
505
  $set = NULL; // Defaulted!
506
  endif;
507
-
508
  $this->update_setting("match/$what", $set, NULL);
509
  endforeach;
510
  endif;
@@ -512,9 +514,9 @@ blank.</p></td>
512
  $settingMap = $this->term_setting_map();
513
 
514
  $saveTerms = array(); $separateSaveTerms = array('category' => array(), 'post_tag' => array());
515
-
516
  if (!isset($post['tax_input'])) : $post['tax_input'] = array(); endif;
517
-
518
  // Merge in data from older-notation category check boxes
519
  if (isset($post['post_category'])) :
520
  // Just merging in for processing below.
@@ -537,7 +539,7 @@ blank.</p></td>
537
  $saveTerms[$tax] = explode(",", $terms);
538
  endif;
539
  $saveTerms[$tax] = array_map('trim', $saveTerms[$tax]);
540
-
541
  if (isset($optionMap[$tax])) :
542
  $separateSaveTerms[$tax] = $saveTerms[$tax];
543
  unset($saveTerms[$tax]);
@@ -546,10 +548,10 @@ blank.</p></td>
546
 
547
  if (isset($post['post_category'])) :
548
  foreach ($post['post_category'] as $cat) :
549
- $separateSaveTerms['category'][] = '{category#'.$cat.'}';
550
  endforeach;
551
  endif;
552
-
553
  // Unmatched categories and tags
554
  foreach (array('category', 'post_tag') as $what) :
555
  if (isset($post["unfamiliar_{$what}"])) :
@@ -560,7 +562,7 @@ blank.</p></td>
560
  );
561
  endif;
562
  endforeach;
563
-
564
  // Categories and Tags
565
  foreach ($separateSaveTerms as $tax => $terms) :
566
  if ($this->for_feed_settings()) :
@@ -573,7 +575,7 @@ blank.</p></td>
573
  endif;
574
  endif;
575
  endforeach;
576
-
577
  // Other terms
578
  $this->update_setting(array('feed'=>'terms', 'global'=>'syndication_terms'), $saveTerms, array());
579
 
@@ -582,7 +584,7 @@ blank.</p></td>
582
  if (isset($post['cat_split'])) :
583
  $this->link->update_setting('cat_split', trim($post['cat_split']), '');
584
  endif;
585
-
586
  // Treat global terms (cats, tags, etc.) as additional,
587
  // or as defaults to be overridden and replaced?
588
  if (isset($post['add_global'])) :
@@ -593,18 +595,18 @@ blank.</p></td>
593
  endif;
594
  parent::save_settings($post);
595
  } /* FeedWordPressCategoriesPage::save_settings() */
596
-
597
  function display () {
598
  ////////////////////////////////////////////////
599
  // Display settings boxes //////////////////////
600
  ////////////////////////////////////////////////
601
-
602
  $this->boxes_by_methods = array(
603
  'feed_categories_box' => __('Feed Categories & Tags'),
604
  'categories_box' => array('title' => __('Categories'), 'id' => 'categorydiv'),
605
  );
606
 
607
- parent::display();
608
  }
609
  }
610
 
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(
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]);
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');
42
  $tagLikeTaxonomies = array();
43
  foreach ($taxonomies as $tax) :
44
  $taxonomy = get_taxonomy($tax);
45
+
46
  if (!$taxonomy->hierarchical) :
47
  $tagLikeTaxonomies[] = $tax;
48
  endif;
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'),
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 :
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(
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;
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])) :
350
  <?php if ($page->for_feed_settings()) : ?>
351
  <tr>
352
  <th scope="row">Multiple categories:</th>
353
+ <td>
354
  <input type="text" size="20" id="cat_split" name="cat_split" value="<?php if (isset($link->settings['cat_split'])) : echo htmlspecialchars($link->settings['cat_split']); endif; ?>" />
355
  <p class="setting-description">Enter a <a href="http://us.php.net/manual/en/reference.pcre.pattern.syntax.php">Perl-compatible regular expression</a> here if the feed provides multiple
356
  categories in a single category element. The regular expression should match
376
  'post_tag' => 'tags',
377
  );
378
  }
379
+
380
  function categories_box ($page, $box = NULL) {
381
  $link = $page->link;
382
+ $dummy = null;
383
+ $syndicatedlink = new SyndicatedLink($dummy);
384
 
385
  if ($this->for_feed_settings()) :
386
  $post_type = $link->setting('syndicated post type', 'syndicated_post_type', 'post');
419
  $add_global_categories = $link->setting("add/$tax", NULL, 'yes');
420
  $checked = array('yes' => '', 'no' => '');
421
  $checked[$add_global_categories] = ' checked="checked"';
422
+
423
  if (isset($setting_map[$tax])) :
424
  $setting = $setting_map[$tax];
425
  $cats = $link->setting($setting, NULL, NULL);
432
  else :
433
  $cats = $globalCats;
434
  endif;
435
+
436
  if ($page->for_feed_settings()) :
437
  ?>
438
  <table class="twofer">
441
  <td class="primary">
442
  <?php
443
  endif;
444
+
445
+ $dogs = $syndicatedlink->category_ids(/*post=*/ NULL, $cats, /*unfamiliar=*/ NULL, /*taxonomies=*/ array($tax));
446
 
447
  if ($taxonomy->hierarchical) : // Use a category-style checkbox
448
  fwp_category_box($dogs, 'all '.$page->these_posts_phrase(), /*tags=*/ array(), /*params=*/ array('taxonomy' => $tax));
449
  else : // Use a tag-style edit box
450
  fwp_tags_box($cats, 'all '.$page->these_posts_phrase(), /*params=*/ array('taxonomy' => $tax));
451
  endif;
452
+
453
+ $globalDogs = $syndicatedlink->category_ids(/*post=*/ NULL, $globalCats, /*unfamiliar=*/ 'create:'.$tax, /*taxonomies=*/ array($tax));
454
+
455
  $siteWideHref = $this->admin_page_href(basename(__FILE__));
456
 
457
  if ($page->for_feed_settings()) :
474
  Should <?php print $page->these_posts_phrase(); ?> be assigned
475
  these <?php print $taxonomy->labels->name; ?> from the <a href="<?php print esc_html($siteWideHref); ?>">site-wide settings</a>, in
476
  addition to the feed-specific <?php print $taxonomy->labels->name; ?> you set up here?</p>
477
+
478
  <ul class="settings">
479
  <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>
480
  <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 use the global defaults for <?php print $page->these_posts_phrase(); ?></label></p></li>
495
  </table>
496
  <?php
497
  } /* FeedWordPressCategoriesPage::categories_box () */
498
+
499
  function save_settings ($post) {
500
  if (isset($post['match_categories'])) :
501
  foreach ($post['match_categories'] as $what => $set) :
506
  and $post['match_default'][$what]=='yes') :
507
  $set = NULL; // Defaulted!
508
  endif;
509
+
510
  $this->update_setting("match/$what", $set, NULL);
511
  endforeach;
512
  endif;
514
  $settingMap = $this->term_setting_map();
515
 
516
  $saveTerms = array(); $separateSaveTerms = array('category' => array(), 'post_tag' => array());
517
+
518
  if (!isset($post['tax_input'])) : $post['tax_input'] = array(); endif;
519
+
520
  // Merge in data from older-notation category check boxes
521
  if (isset($post['post_category'])) :
522
  // Just merging in for processing below.
539
  $saveTerms[$tax] = explode(",", $terms);
540
  endif;
541
  $saveTerms[$tax] = array_map('trim', $saveTerms[$tax]);
542
+
543
  if (isset($optionMap[$tax])) :
544
  $separateSaveTerms[$tax] = $saveTerms[$tax];
545
  unset($saveTerms[$tax]);
548
 
549
  if (isset($post['post_category'])) :
550
  foreach ($post['post_category'] as $cat) :
551
+ $separateSaveTerms['category'][] = '{category#'.$cat.'}';
552
  endforeach;
553
  endif;
554
+
555
  // Unmatched categories and tags
556
  foreach (array('category', 'post_tag') as $what) :
557
  if (isset($post["unfamiliar_{$what}"])) :
562
  );
563
  endif;
564
  endforeach;
565
+
566
  // Categories and Tags
567
  foreach ($separateSaveTerms as $tax => $terms) :
568
  if ($this->for_feed_settings()) :
575
  endif;
576
  endif;
577
  endforeach;
578
+
579
  // Other terms
580
  $this->update_setting(array('feed'=>'terms', 'global'=>'syndication_terms'), $saveTerms, array());
581
 
584
  if (isset($post['cat_split'])) :
585
  $this->link->update_setting('cat_split', trim($post['cat_split']), '');
586
  endif;
587
+
588
  // Treat global terms (cats, tags, etc.) as additional,
589
  // or as defaults to be overridden and replaced?
590
  if (isset($post['add_global'])) :
595
  endif;
596
  parent::save_settings($post);
597
  } /* FeedWordPressCategoriesPage::save_settings() */
598
+
599
  function display () {
600
  ////////////////////////////////////////////////
601
  // Display settings boxes //////////////////////
602
  ////////////////////////////////////////////////
603
+
604
  $this->boxes_by_methods = array(
605
  'feed_categories_box' => __('Feed Categories & Tags'),
606
  'categories_box' => array('title' => __('Categories'), 'id' => 'categorydiv'),
607
  );
608
 
609
+ parent::display();
610
  }
611
  }
612
 
compatability.php CHANGED
@@ -15,9 +15,9 @@ class FeedWordPressCompatibility {
15
  * @return bool TRUE if within the range of versions, FALSE if too low
16
  * or too high.
17
  */
18
- /*static*/ function test_version ($floor, $ceiling = null) {
19
  global $wp_db_version;
20
-
21
  $ver = (isset($wp_db_version) ? $wp_db_version : 0);
22
  $good = ($ver >= $floor);
23
  if (!is_null($ceiling)) :
@@ -26,7 +26,7 @@ class FeedWordPressCompatibility {
26
  return $good;
27
  } /* FeedWordPressCompatibility::test_version() */
28
 
29
- /*static*/ function insert_link_category ($name) {
30
  global $wpdb;
31
 
32
  // WordPress 2.3+ term/taxonomy API
@@ -45,12 +45,12 @@ class FeedWordPressCompatibility {
45
  else :
46
  $cat_id = $term;
47
  endif;
48
-
49
  // Return newly-created category ID
50
  return $cat_id;
51
  } /* FeedWordPressCompatibility::insert_link_category () */
52
 
53
- /*static*/ function link_category_id ($value, $key = 'cat_name') {
54
  global $wpdb;
55
 
56
  $cat_id = NULL;
@@ -65,11 +65,11 @@ class FeedWordPressCompatibility {
65
  else :
66
  $cat_id = $the_term;
67
  endif;
68
-
69
  return $cat_id;
70
  } /* FeedWordPressCompatibility::link_category_id () */
71
 
72
- /*static*/ function validate_http_request ($action = -1, $capability = null) {
73
  // Only worry about this if we're using a method with significant side-effects
74
  if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST') :
75
  // Limit post by user capabilities
@@ -87,15 +87,15 @@ class FeedWordPressCompatibility {
87
  endif;
88
  endif;
89
  } /* FeedWordPressCompatibility::validate_http_request() */
90
-
91
- /*static*/ function stamp_nonce ($action = -1) {
92
  // stamp form with hidden fields for a nonce in WP 2.0.3 & later
93
  if (function_exists('wp_nonce_field')) :
94
  wp_nonce_field($action);
95
  endif;
96
  } /* FeedWordPressCompatibility::stamp_nonce() */
97
-
98
- /*static*/ function bottom_script_hook ($filename) {
99
  global $fwp_path;
100
 
101
  $hook = 'admin_footer-'.$fwp_path.'/'.basename($filename);
@@ -125,11 +125,11 @@ if (!function_exists('set_post_field')) {
125
  * Included under terms of GPL from WordPress Ticket #10946 <http://core.trac.wordpress.org/attachment/ticket/10946/post.php.diff>
126
  */
127
  function set_post_field ($field, $value, $post_id) {
128
- global $wpdb;
129
 
130
  $post_id = absint($post_id);
131
  // sigh ... when FWP is active, I need to avoid avoid_kses_munge
132
- // $value = sanitize_post_field($field, $value, $post_id, 'db');
133
  return $wpdb->update($wpdb->posts, array($field => $value), array('ID' => $post_id));
134
  } /* function set_post_field () */
135
 
@@ -145,10 +145,10 @@ function fwp_category_checklist ($post_id = 0, $descendents_and_self = 0, $selec
145
  $prefix = (isset($params['prefix']) ? $params['prefix'] : '');
146
  $taxonomy = (isset($params['taxonomy']) ? $params['taxonomy'] : 'category');
147
  endif;
148
-
149
  $walker = new FeedWordPress_Walker_Category_Checklist($params);
150
  $walker->set_prefix($prefix);
151
- $walker->set_taxonomy($taxonomy);
152
  wp_terms_checklist(/*post_id=*/ $post_id, array(
153
  'taxonomy' => $taxonomy,
154
  'descendents_and_self' => $descendents_and_self,
15
  * @return bool TRUE if within the range of versions, FALSE if too low
16
  * or too high.
17
  */
18
+ static function test_version ($floor, $ceiling = null) {
19
  global $wp_db_version;
20
+
21
  $ver = (isset($wp_db_version) ? $wp_db_version : 0);
22
  $good = ($ver >= $floor);
23
  if (!is_null($ceiling)) :
26
  return $good;
27
  } /* FeedWordPressCompatibility::test_version() */
28
 
29
+ static function insert_link_category ($name) {
30
  global $wpdb;
31
 
32
  // WordPress 2.3+ term/taxonomy API
45
  else :
46
  $cat_id = $term;
47
  endif;
48
+
49
  // Return newly-created category ID
50
  return $cat_id;
51
  } /* FeedWordPressCompatibility::insert_link_category () */
52
 
53
+ static function link_category_id ($value, $key = 'cat_name') {
54
  global $wpdb;
55
 
56
  $cat_id = NULL;
65
  else :
66
  $cat_id = $the_term;
67
  endif;
68
+
69
  return $cat_id;
70
  } /* FeedWordPressCompatibility::link_category_id () */
71
 
72
+ static function validate_http_request ($action = -1, $capability = null) {
73
  // Only worry about this if we're using a method with significant side-effects
74
  if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST') :
75
  // Limit post by user capabilities
87
  endif;
88
  endif;
89
  } /* FeedWordPressCompatibility::validate_http_request() */
90
+
91
+ static function stamp_nonce ($action = -1) {
92
  // stamp form with hidden fields for a nonce in WP 2.0.3 & later
93
  if (function_exists('wp_nonce_field')) :
94
  wp_nonce_field($action);
95
  endif;
96
  } /* FeedWordPressCompatibility::stamp_nonce() */
97
+
98
+ static function bottom_script_hook ($filename) {
99
  global $fwp_path;
100
 
101
  $hook = 'admin_footer-'.$fwp_path.'/'.basename($filename);
125
  * Included under terms of GPL from WordPress Ticket #10946 <http://core.trac.wordpress.org/attachment/ticket/10946/post.php.diff>
126
  */
127
  function set_post_field ($field, $value, $post_id) {
128
+ global $wpdb;
129
 
130
  $post_id = absint($post_id);
131
  // sigh ... when FWP is active, I need to avoid avoid_kses_munge
132
+ // $value = sanitize_post_field($field, $value, $post_id, 'db');
133
  return $wpdb->update($wpdb->posts, array($field => $value), array('ID' => $post_id));
134
  } /* function set_post_field () */
135
 
145
  $prefix = (isset($params['prefix']) ? $params['prefix'] : '');
146
  $taxonomy = (isset($params['taxonomy']) ? $params['taxonomy'] : 'category');
147
  endif;
148
+
149
  $walker = new FeedWordPress_Walker_Category_Checklist($params);
150
  $walker->set_prefix($prefix);
151
+ $walker->set_taxonomy($taxonomy);
152
  wp_terms_checklist(/*post_id=*/ $post_id, array(
153
  'taxonomy' => $taxonomy,
154
  'descendents_and_self' => $descendents_and_self,
diagnostics-page.php CHANGED
@@ -7,7 +7,7 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
7
  FeedWordPressAdminPage::FeedWordPressAdminPage('feedwordpressdiagnosticspage');
8
  $this->dispatch = 'feedwordpress_diagnostics';
9
  $this->filename = __FILE__;
10
-
11
  $this->test_html = array();
12
  add_action('feedwordpress_diagnostics_do_http_test', array($this, 'do_http_test'), 10, 1);
13
  }
@@ -17,15 +17,15 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
17
  function display () {
18
  global $wpdb, $wp_db_version, $fwp_path;
19
  global $fwp_post;
20
-
21
  if (FeedWordPress::needs_upgrade()) :
22
  fwp_upgrade_page();
23
  return;
24
  endif;
25
-
26
  // If this is a POST, validate source and user credentials
27
  FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_diagnostics', /*capability=*/ 'manage_options');
28
-
29
  if (strtoupper($_SERVER['REQUEST_METHOD'])=='POST') :
30
  $this->accept_POST($fwp_post);
31
  do_action('feedwordpress_admin_page_diagnostics_save', $fwp_post, $this);
@@ -47,7 +47,7 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
47
  'updates_box' => __('Updates'),
48
  'tests_box' => __('Diagnostic Tests'),
49
  );
50
-
51
  foreach ($boxes_by_methods as $method => $title) :
52
  add_meta_box(
53
  /*id=*/ 'feedwordpress_'.$method,
@@ -76,13 +76,13 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
76
  or isset($post['feedwordpress_diagnostics_do'])) :
77
  update_option('feedwordpress_debug', $post['feedwordpress_debug']);
78
  update_option('feedwordpress_secret_key', $post['feedwordpress_secret_key']);
79
-
80
  if (!isset($post['diagnostics_output'])
81
  or !is_array($post['diagnostics_output'])) :
82
  $post['diagnostics_output'] = array();
83
  endif;
84
  update_option('feedwordpress_diagnostics_output', $post['diagnostics_output']);
85
-
86
  if (!isset($post['diagnostics_show'])
87
  or !is_array($post['diagnostics_show'])) :
88
  $post['diagnostics_show'] = array();
@@ -95,7 +95,7 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
95
  else :
96
  delete_option('feedwordpress_diagnostics_persistent_errors_hours');
97
  endif;
98
-
99
  if (in_array('email', $post['diagnostics_output'])) :
100
  $ded = $post['diagnostics_email_destination'];
101
  if ('mailto'==$ded) :
@@ -106,18 +106,18 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
106
  else :
107
  delete_option('feedwordpress_diagnostics_email_destination');
108
  endif;
109
-
110
  if (isset($post['feedwordpress_diagnostics_do'])) :
111
  foreach ($post['feedwordpress_diagnostics_do'] as $do => $value) :
112
  do_action('feedwordpress_diagnostics_do_'.$do, $post);
113
  endforeach;
114
  endif;
115
-
116
  $this->updated = true; // Default update message
117
  endif;
118
  } /* FeedWordPressDiagnosticsPage::accept_POST () */
119
 
120
- function info_box ($page, $box = NULL) {
121
  global $feedwordpress;
122
  global $wp_version;
123
  $link_category_id = FeedWordPress::link_category_id();
@@ -147,7 +147,7 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
147
  </ul>
148
  </td>
149
  </tr>
150
-
151
  <tr>
152
  <th scope="row">Link Category:</th>
153
  <td><?php if (!is_wp_error($link_category_id)) :
@@ -168,13 +168,13 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
168
  <?php $data = $link_category_id->get_error_data(); if (!empty($data)) : ?>
169
  <tr>
170
  <th scope="row">Auxiliary Data:</th>
171
- <td><pre><?php print esc_html(FeedWordPress::val($link_category_id->get_error_data())); ?></pre></td>
172
  </tr>
173
  <?php endif; ?>
174
  </table>
175
  <?php endif; ?></td>
176
  </tr>
177
-
178
  <tr>
179
  <th scope="row"><?php _e('Secret Key:'); ?></th>
180
  <td><input type="text" name="feedwordpress_secret_key" value="<?php print esc_attr($feedwordpress->secret_key()); ?>" />
@@ -186,13 +186,13 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
186
 
187
  <?php
188
  } /* FeedWordPressDiagnosticsPage::info_box () */
189
-
190
- function diagnostics_box ($page, $box = NULL) {
191
  $settings = array();
192
  $settings['debug'] = (get_option('feedwordpress_debug')=='yes');
193
 
194
  $diagnostics_output = get_option('feedwordpress_diagnostics_output', array());
195
-
196
  $users = fwp_author_list();
197
 
198
  $ded = get_option('feedwordpress_diagnostics_email_destination', 'admins');
@@ -202,7 +202,7 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
202
  else :
203
  $ded_addy = NULL;
204
  endif;
205
-
206
  // Hey ho, let's go...
207
  ?>
208
  <table class="edit-form">
@@ -255,16 +255,16 @@ testing but absolutely inappropriate for a production server.</p>
255
  'mailto',
256
  'inline'
257
  );
258
- } );
259
  </script>
260
  <?php
261
  } /* FeedWordPressDiagnosticsPage::diagnostics_box () */
262
-
263
- /*static*/ function updates_box ($page, $box = NULL) {
264
  $hours = get_option('feedwordpress_diagnostics_persistent_errors_hours', 2);
265
  $fields = apply_filters('feedwordpress_diagnostics', array(
266
  'Update Diagnostics' => array(
267
- 'update_schedule:check' => 'whenever a FeedWordPress checks in on the update schedule',
268
  'updated_feeds' => 'as each feed is checked for updates',
269
  'updated_feeds:errors:persistent' => 'when attempts to update a feed have resulted in errors</label> <label>for at least <input type="number" min="1" max="360" step="1" name="diagnostics_persistent_error_hours" value="'.$hours.'" /> hours',
270
  'updated_feeds:errors' => 'any time FeedWordPress encounters any errors while checking a feed for updates',
@@ -276,15 +276,17 @@ testing but absolutely inappropriate for a production server.</p>
276
  'Syndicated Post Details' => array(
277
  'feed_items:freshness' => 'as FeedWordPress decides whether to treat an item as a new post, an update, or a duplicate of an existing post',
278
  'feed_items:rejected' => 'when FeedWordPress rejects a post without syndicating it',
 
279
  'syndicated_posts:meta_data' => 'as syndication meta-data is added on the post',
280
  ),
281
  'Advanced Diagnostics' => array(
282
  'feed_items:freshness:reasons' => 'explaining the reason that a post was treated as an update to an existing post',
283
- 'feed_items:freshness:sql' => 'when FeedWordPress issues the SQL query it uses to decide whether to treat items as new, updates, or duplicates',
 
284
  'syndicated_posts:static_meta_data' => 'providing meta-data about syndicated posts in the Edit Posts interface',
285
  ),
286
  ), $page);
287
-
288
  foreach ($fields as $section => $items) :
289
  foreach ($items as $key => $label) :
290
  $checked[$key] = '';
@@ -317,8 +319,8 @@ testing but absolutely inappropriate for a production server.</p>
317
  </table>
318
  <?php
319
  } /* FeedWordPressDiagnosticsPage::updates_box () */
320
-
321
- function tests_box ($page, $box = NULL) {
322
  ?>
323
  <script type="text/javascript">
324
  function clone_http_test_args_keyvalue_prototype () {
@@ -327,7 +329,7 @@ function clone_http_test_args_keyvalue_prototype () {
327
  newRow.find('.http_test_args_key').attr('name', 'http_test_args_key['+next+']').val('');
328
  newRow.find('.http_test_args_value').attr('name', 'http_test_args_value['+next+']').val('');
329
 
330
- newRow.appendTo('#http-test-args');
331
  return false;
332
  }
333
  </script>
@@ -354,7 +356,7 @@ function clone_http_test_args_keyvalue_prototype () {
354
  <td><a href="#http-test-args" onclick="return clone_http_test_args_keyvalue_prototype();">+ Add</a></td>
355
  </tr>
356
  </table>
357
-
358
  <?php if (isset($page->test_html['http_test'])) : ?>
359
  <div style="position: relative">
360
  <div style="width: 100%; overflow: scroll; background-color: #eed">
@@ -370,10 +372,10 @@ function clone_http_test_args_keyvalue_prototype () {
370
  } /* FeedWordPressDiagnosticsPage::tests_box () */
371
 
372
  var $test_html;
373
- function do_http_test ($post) {
374
  if (isset($post['http_test_url']) and isset($post['http_test_method'])) :
375
  $url = $post['http_test_url'];
376
-
377
  $args = array();
378
  if (isset($post['http_test_args_key'])) :
379
  foreach ($post['http_test_args_key'] as $idx => $name) :
@@ -384,21 +386,21 @@ function clone_http_test_args_keyvalue_prototype () {
384
  and isset($post['http_test_args_value'][$idx])) :
385
  $value = $post['http_test_args_value'][$idx];
386
  endif;
387
-
388
  if (preg_match('/^javascript:(.*)$/i', $value, $refs)) :
389
- if (function_exists('json_decode')) :
390
  $json_value = json_decode($refs[1]);
391
  if (!is_null($json_value)) :
392
  $value = $json_value;
393
  endif;
394
  endif;
395
  endif;
396
-
397
  $args[$name] = $value;
398
  endif;
399
  endforeach;
400
  endif;
401
-
402
  switch ($post['http_test_method']) :
403
  case 'wp_remote_request' :
404
  $out = wp_remote_request($url, $args);
@@ -408,10 +410,10 @@ function clone_http_test_args_keyvalue_prototype () {
408
  break;
409
  endswitch;
410
 
411
- $this->test_html['http_test'] = esc_html(FeedWordPress::val($out));
412
  endif;
413
  } /* FeedWordPressDiagnosticsPage::do_http_test () */
414
-
415
  } /* class FeedWordPressDiagnosticsPage */
416
 
417
  $diagnosticsPage = new FeedWordPressDiagnosticsPage;
7
  FeedWordPressAdminPage::FeedWordPressAdminPage('feedwordpressdiagnosticspage');
8
  $this->dispatch = 'feedwordpress_diagnostics';
9
  $this->filename = __FILE__;
10
+
11
  $this->test_html = array();
12
  add_action('feedwordpress_diagnostics_do_http_test', array($this, 'do_http_test'), 10, 1);
13
  }
17
  function display () {
18
  global $wpdb, $wp_db_version, $fwp_path;
19
  global $fwp_post;
20
+
21
  if (FeedWordPress::needs_upgrade()) :
22
  fwp_upgrade_page();
23
  return;
24
  endif;
25
+
26
  // If this is a POST, validate source and user credentials
27
  FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_diagnostics', /*capability=*/ 'manage_options');
28
+
29
  if (strtoupper($_SERVER['REQUEST_METHOD'])=='POST') :
30
  $this->accept_POST($fwp_post);
31
  do_action('feedwordpress_admin_page_diagnostics_save', $fwp_post, $this);
47
  'updates_box' => __('Updates'),
48
  'tests_box' => __('Diagnostic Tests'),
49
  );
50
+
51
  foreach ($boxes_by_methods as $method => $title) :
52
  add_meta_box(
53
  /*id=*/ 'feedwordpress_'.$method,
76
  or isset($post['feedwordpress_diagnostics_do'])) :
77
  update_option('feedwordpress_debug', $post['feedwordpress_debug']);
78
  update_option('feedwordpress_secret_key', $post['feedwordpress_secret_key']);
79
+
80
  if (!isset($post['diagnostics_output'])
81
  or !is_array($post['diagnostics_output'])) :
82
  $post['diagnostics_output'] = array();
83
  endif;
84
  update_option('feedwordpress_diagnostics_output', $post['diagnostics_output']);
85
+
86
  if (!isset($post['diagnostics_show'])
87
  or !is_array($post['diagnostics_show'])) :
88
  $post['diagnostics_show'] = array();
95
  else :
96
  delete_option('feedwordpress_diagnostics_persistent_errors_hours');
97
  endif;
98
+
99
  if (in_array('email', $post['diagnostics_output'])) :
100
  $ded = $post['diagnostics_email_destination'];
101
  if ('mailto'==$ded) :
106
  else :
107
  delete_option('feedwordpress_diagnostics_email_destination');
108
  endif;
109
+
110
  if (isset($post['feedwordpress_diagnostics_do'])) :
111
  foreach ($post['feedwordpress_diagnostics_do'] as $do => $value) :
112
  do_action('feedwordpress_diagnostics_do_'.$do, $post);
113
  endforeach;
114
  endif;
115
+
116
  $this->updated = true; // Default update message
117
  endif;
118
  } /* FeedWordPressDiagnosticsPage::accept_POST () */
119
 
120
+ static function info_box ($page, $box = NULL) {
121
  global $feedwordpress;
122
  global $wp_version;
123
  $link_category_id = FeedWordPress::link_category_id();
147
  </ul>
148
  </td>
149
  </tr>
150
+
151
  <tr>
152
  <th scope="row">Link Category:</th>
153
  <td><?php if (!is_wp_error($link_category_id)) :
168
  <?php $data = $link_category_id->get_error_data(); if (!empty($data)) : ?>
169
  <tr>
170
  <th scope="row">Auxiliary Data:</th>
171
+ <td><pre><?php print esc_html(MyPHP::val($link_category_id->get_error_data())); ?></pre></td>
172
  </tr>
173
  <?php endif; ?>
174
  </table>
175
  <?php endif; ?></td>
176
  </tr>
177
+
178
  <tr>
179
  <th scope="row"><?php _e('Secret Key:'); ?></th>
180
  <td><input type="text" name="feedwordpress_secret_key" value="<?php print esc_attr($feedwordpress->secret_key()); ?>" />
186
 
187
  <?php
188
  } /* FeedWordPressDiagnosticsPage::info_box () */
189
+
190
+ static function diagnostics_box ($page, $box = NULL) {
191
  $settings = array();
192
  $settings['debug'] = (get_option('feedwordpress_debug')=='yes');
193
 
194
  $diagnostics_output = get_option('feedwordpress_diagnostics_output', array());
195
+
196
  $users = fwp_author_list();
197
 
198
  $ded = get_option('feedwordpress_diagnostics_email_destination', 'admins');
202
  else :
203
  $ded_addy = NULL;
204
  endif;
205
+
206
  // Hey ho, let's go...
207
  ?>
208
  <table class="edit-form">
255
  'mailto',
256
  'inline'
257
  );
258
+ } );
259
  </script>
260
  <?php
261
  } /* FeedWordPressDiagnosticsPage::diagnostics_box () */
262
+
263
+ static function updates_box ($page, $box = NULL) {
264
  $hours = get_option('feedwordpress_diagnostics_persistent_errors_hours', 2);
265
  $fields = apply_filters('feedwordpress_diagnostics', array(
266
  'Update Diagnostics' => array(
267
+ 'update_schedule:check' => 'whenever a FeedWordPress checks in on the update schedule',
268
  'updated_feeds' => 'as each feed is checked for updates',
269
  'updated_feeds:errors:persistent' => 'when attempts to update a feed have resulted in errors</label> <label>for at least <input type="number" min="1" max="360" step="1" name="diagnostics_persistent_error_hours" value="'.$hours.'" /> hours',
270
  'updated_feeds:errors' => 'any time FeedWordPress encounters any errors while checking a feed for updates',
276
  'Syndicated Post Details' => array(
277
  'feed_items:freshness' => 'as FeedWordPress decides whether to treat an item as a new post, an update, or a duplicate of an existing post',
278
  'feed_items:rejected' => 'when FeedWordPress rejects a post without syndicating it',
279
+ 'syndicated_posts:categories' => 'as categories, tags, and other terms are added on the post',
280
  'syndicated_posts:meta_data' => 'as syndication meta-data is added on the post',
281
  ),
282
  'Advanced Diagnostics' => array(
283
  'feed_items:freshness:reasons' => 'explaining the reason that a post was treated as an update to an existing post',
284
+ 'feed_items:freshness:sql' => 'when FeedWordPress issues the SQL query it uses to decide whether to treat items as new, updates, or duplicates',
285
+ 'syndicated_posts:categories:test' => 'as FeedWordPress checks for the familiarity of feed categories and tags',
286
  'syndicated_posts:static_meta_data' => 'providing meta-data about syndicated posts in the Edit Posts interface',
287
  ),
288
  ), $page);
289
+
290
  foreach ($fields as $section => $items) :
291
  foreach ($items as $key => $label) :
292
  $checked[$key] = '';
319
  </table>
320
  <?php
321
  } /* FeedWordPressDiagnosticsPage::updates_box () */
322
+
323
+ static function tests_box ($page, $box = NULL) {
324
  ?>
325
  <script type="text/javascript">
326
  function clone_http_test_args_keyvalue_prototype () {
329
  newRow.find('.http_test_args_key').attr('name', 'http_test_args_key['+next+']').val('');
330
  newRow.find('.http_test_args_value').attr('name', 'http_test_args_value['+next+']').val('');
331
 
332
+ newRow.appendTo('#http-test-args');
333
  return false;
334
  }
335
  </script>
356
  <td><a href="#http-test-args" onclick="return clone_http_test_args_keyvalue_prototype();">+ Add</a></td>
357
  </tr>
358
  </table>
359
+
360
  <?php if (isset($page->test_html['http_test'])) : ?>
361
  <div style="position: relative">
362
  <div style="width: 100%; overflow: scroll; background-color: #eed">
372
  } /* FeedWordPressDiagnosticsPage::tests_box () */
373
 
374
  var $test_html;
375
+ static function do_http_test ($post) {
376
  if (isset($post['http_test_url']) and isset($post['http_test_method'])) :
377
  $url = $post['http_test_url'];
378
+
379
  $args = array();
380
  if (isset($post['http_test_args_key'])) :
381
  foreach ($post['http_test_args_key'] as $idx => $name) :
386
  and isset($post['http_test_args_value'][$idx])) :
387
  $value = $post['http_test_args_value'][$idx];
388
  endif;
389
+
390
  if (preg_match('/^javascript:(.*)$/i', $value, $refs)) :
391
+ if (function_exists('json_decode')) :
392
  $json_value = json_decode($refs[1]);
393
  if (!is_null($json_value)) :
394
  $value = $json_value;
395
  endif;
396
  endif;
397
  endif;
398
+
399
  $args[$name] = $value;
400
  endif;
401
  endforeach;
402
  endif;
403
+
404
  switch ($post['http_test_method']) :
405
  case 'wp_remote_request' :
406
  $out = wp_remote_request($url, $args);
410
  break;
411
  endswitch;
412
 
413
+ $this->test_html['http_test'] = esc_html(MyPHP::val($out));
414
  endif;
415
  } /* FeedWordPressDiagnosticsPage::do_http_test () */
416
+
417
  } /* class FeedWordPressDiagnosticsPage */
418
 
419
  $diagnosticsPage = new FeedWordPressDiagnosticsPage;
externals/myphp/myphp.class.php CHANGED
@@ -1,7 +1,23 @@
1
  <?php
 
 
 
 
 
 
 
2
  if (!class_exists('MyPHP')) :
3
  class MyPHP {
4
- // For dealing with HTTP GET/POST parameters sent to us as input
 
 
 
 
 
 
 
 
 
5
  static public function param ($key, $default = NULL, $type = 'REQUEST') {
6
  // PHP 5.4 introduces "just-in-time" initialization of
7
  // $GLOBALS. Which seems to me largely to defeat the
@@ -26,14 +42,40 @@ if (!class_exists('MyPHP')) :
26
  return $ret;
27
  } /* MyPHP::param () */
28
 
 
 
 
 
 
 
 
 
29
  static function post ($key, $default = NULL) {
30
  return self::param($key, $default, 'POST');
31
  } /*MyPHP::post () */
32
 
 
 
 
 
 
 
 
 
33
  static function get ($key, $default = NULL) {
34
  return self::param($key, $default, "GET");
35
  } /* MyPHP::get () */
36
 
 
 
 
 
 
 
 
 
 
 
37
  static function request ($key, $default = NULL) {
38
  return self::param($key, $default, "REQUEST");
39
  } /* MyPHP::request () */
@@ -82,7 +124,26 @@ if (!class_exists('MyPHP')) :
82
  endforeach;
83
  return implode("&", $getQuery);
84
  } /* MyPHP::to_http_post () */
85
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  endif;
87
-
88
-
1
  <?php
2
+ /**
3
+ * MyPHP: handy general utility functions, for things that PHP should do, but
4
+ * doesn't do (yet).
5
+ *
6
+ * @package MyPHP
7
+ * @version 2014.0805
8
+ */
9
  if (!class_exists('MyPHP')) :
10
  class MyPHP {
11
+ /**
12
+ * MyPHP::param: For dealing with HTTP GET/POST parameters sent
13
+ * to us as input.
14
+ *
15
+ * @param string $key The name of the GET/POST parameter
16
+ * @param mixed $default Default to return if parameter is unset
17
+ * @param string $type 'GET', 'POST' or 'REQUEST' (=both GET and POST)
18
+ * @return mixed The value of the named parameter, or the fallback
19
+ * in $default if there is no value set for that param name.
20
+ */
21
  static public function param ($key, $default = NULL, $type = 'REQUEST') {
22
  // PHP 5.4 introduces "just-in-time" initialization of
23
  // $GLOBALS. Which seems to me largely to defeat the
42
  return $ret;
43
  } /* MyPHP::param () */
44
 
45
+ /**
46
+ * MyPHP::post: For dealing with HTTP POST parameters sent as input
47
+ *
48
+ * @param string $key The name of the POST parameter
49
+ * @param mixed $default Default to return if parameter is unset
50
+ * @return mixed The value of the named parameter, or the fallback
51
+ * in $default if there is no value set for that param name.
52
+ */
53
  static function post ($key, $default = NULL) {
54
  return self::param($key, $default, 'POST');
55
  } /*MyPHP::post () */
56
 
57
+ /**
58
+ * MyPHP::post: For dealing with HTTP GET parameters sent as input
59
+ *
60
+ * @param string $key The name of the GET parameter
61
+ * @param mixed $default Default to return if parameter is unset
62
+ * @return mixed The value of the named parameter, or the fallback
63
+ * in $default if there is no value set for that param name.
64
+ */
65
  static function get ($key, $default = NULL) {
66
  return self::param($key, $default, "GET");
67
  } /* MyPHP::get () */
68
 
69
+ /**
70
+ * MyPHP::request: For dealing with HTTP GET/POST parameters
71
+ * sent as input. This method checks both GET parameters and POST
72
+ * parameters and will return values from either.
73
+ *
74
+ * @param string $key The name of the GET/POST parameter
75
+ * @param mixed $default Default to return if parameter is unset
76
+ * @return mixed The value of the named parameter, or the fallback
77
+ * in $default if there is no value set for that param name.
78
+ */
79
  static function request ($key, $default = NULL) {
80
  return self::param($key, $default, "REQUEST");
81
  } /* MyPHP::request () */
124
  endforeach;
125
  return implode("&", $getQuery);
126
  } /* MyPHP::to_http_post () */
127
+
128
+ /**
129
+ * MyPHP::val(): Captures the output of var_dump() to a string,
130
+ * with some optional filtering removing newlines and replacing
131
+ * them with spaces) applied.
132
+ *
133
+ * @param mixed $v Value to dump to a string representation
134
+ * @param bool $no_newlines Whether to filter out newline chars
135
+ *
136
+ * @return string
137
+ */
138
+ static function val ($v, $no_newlines = false) {
139
+ ob_start();
140
+ var_dump($v);
141
+ $out = ob_get_contents(); ob_end_clean();
142
+
143
+ if ($no_newlines) :
144
+ $out = preg_replace('/\s+/', " ", $out);
145
+ endif;
146
+ return $out;
147
+ } /* MyPHP::val () */
148
+ } /* class MyPHP */
149
  endif;
 
 
feeds-page.php CHANGED
@@ -901,7 +901,7 @@ class FeedWordPressFeedsPage extends FeedWordPressAdminPage {
901
  $feed_version = '';
902
  endif;
903
  ?>
904
- <form<?php print $form_class; ?> action="<?php $this->form_action('syndication.php'); ?>" method="post">
905
  <div class="inside"><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_switchfeed'); ?>
906
 
907
  <?php
@@ -1034,7 +1034,7 @@ class FeedWordPressFeedsPage extends FeedWordPressAdminPage {
1034
 
1035
  print "<h4>".__("HTTP Transport").":</h4>\n";
1036
  print "<ol>\n";
1037
- print "<li>".FeedWordPress::val($transport)."</li>\n";
1038
  print "</ol>\n";
1039
  endif;
1040
 
@@ -1069,9 +1069,9 @@ class FeedWordPressFeedsPage extends FeedWordPressAdminPage {
1069
  $alt = $params['alt'];
1070
 
1071
  ?>
1072
- <form action="<?php $this->form_action(); ?>" method="post">
1073
  <div class="inside"><?php
1074
- FeedWordPressCompatibility::stamp_nonce($this->dispatch);
1075
  ?>
1076
  <fieldset class="alt"
1077
  <?php if (!$alt): ?>style="margin: 1.0em 3.0em; font-size: smaller;"<?php endif; ?>>
901
  $feed_version = '';
902
  endif;
903
  ?>
904
+ <form<?php print $form_class; ?> action="<?php print $this->form_action('syndication.php'); ?>" method="post">
905
  <div class="inside"><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_switchfeed'); ?>
906
 
907
  <?php
1034
 
1035
  print "<h4>".__("HTTP Transport").":</h4>\n";
1036
  print "<ol>\n";
1037
+ print "<li>".MyPHP::val($transport)."</li>\n";
1038
  print "</ol>\n";
1039
  endif;
1040
 
1069
  $alt = $params['alt'];
1070
 
1071
  ?>
1072
+ <form action="<?php print $this->form_action('syndication.php'); ?>" method="post">
1073
  <div class="inside"><?php
1074
+ FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds');
1075
  ?>
1076
  <fieldset class="alt"
1077
  <?php if (!$alt): ?>style="margin: 1.0em 3.0em; font-size: smaller;"<?php endif; ?>>
feedwordpie.class.php CHANGED
@@ -10,7 +10,7 @@ class FeedWordPie extends SimplePie {
10
 
11
  // Get URL with relevant parameters attached.
12
  // Credentials will be handled further down.
13
- $new_url = $url->uri(array('add_params' => true));
14
 
15
  // Store for reference.
16
  $this->subscription = $url->id();
@@ -43,10 +43,12 @@ class FeedWordPie extends SimplePie {
43
  }
44
 
45
  function get_feed_tags ($namespace, $tag) {
 
 
46
  // Allow filters to filter SimplePie handling
47
  return apply_filters(
48
  'feedwordpie_get_feed_tags',
49
- parent::get_feed_tags($namespace, $tag),
50
  $namespace,
51
  $tag,
52
  $this
10
 
11
  // Get URL with relevant parameters attached.
12
  // Credentials will be handled further down.
13
+ $new_url = $url->uri(array('add_params' => true, 'fetch' => true));
14
 
15
  // Store for reference.
16
  $this->subscription = $url->id();
43
  }
44
 
45
  function get_feed_tags ($namespace, $tag) {
46
+ $tags = parent::get_feed_tags($namespace, $tag);
47
+
48
  // Allow filters to filter SimplePie handling
49
  return apply_filters(
50
  'feedwordpie_get_feed_tags',
51
+ $tags,
52
  $namespace,
53
  $tag,
54
  $this
feedwordpress-elements.css CHANGED
@@ -330,7 +330,7 @@ table.twofer td.secondary { padding-left: 10px; width: 30%; }
330
  }
331
  #feedwordpress-admin-syndication .update-form.with-donation {
332
  margin-right: 50%;
333
- min-height: 255px;
334
  }
335
  #feedwordpress-admin-syndication .donation-form,
336
  #feedwordpress-admin-syndication .donation-thanks {
@@ -468,4 +468,6 @@ table.twofer td.secondary { padding-left: 10px; width: 30%; }
468
  padding: 10px;
469
  }
470
 
471
-
 
 
330
  }
331
  #feedwordpress-admin-syndication .update-form.with-donation {
332
  margin-right: 50%;
333
+ min-height: 355px;
334
  }
335
  #feedwordpress-admin-syndication .donation-form,
336
  #feedwordpress-admin-syndication .donation-thanks {
468
  padding: 10px;
469
  }
470
 
471
+ .hovered-component .hover-on { display: none; }
472
+ .hovered-component:hover .hover-on { display: inline; }
473
+ .hovered-component:hover .hover-on.pop-over { display: block; position: absolute; }
feedwordpress-walker-category-checklist.class.php CHANGED
@@ -15,12 +15,12 @@ class FeedWordPress_Walker_Category_Checklist extends Walker_Category_Checklist
15
  var $checkbox_name = NULL;
16
  function FeedWordPress_Walker_Category_Checklist ($params = array()) {
17
  $this->set_taxonomy('category');
18
-
19
  if (isset($params['checkbox_name'])) :
20
  $this->checkbox_name = $params['checkbox_name'];
21
  endif;
22
  }
23
-
24
  function set_prefix ($prefix) {
25
  $this->prefix = $prefix;
26
  }
@@ -28,11 +28,11 @@ class FeedWordPress_Walker_Category_Checklist extends Walker_Category_Checklist
28
  $this->taxonomy = $taxonomy;
29
  }
30
 
31
- function start_el (&$output, $category, $depth, $args) {
32
  extract($args);
33
  if ( empty($taxonomy) ) :
34
  $taxonomy = 'category';
35
- endif;
36
 
37
  if (!is_null($this->checkbox_name)) :
38
  $name = $this->checkbox_name;
@@ -41,7 +41,7 @@ class FeedWordPress_Walker_Category_Checklist extends Walker_Category_Checklist
41
  else :
42
  $name = 'tax_input['.$taxonomy.']';
43
  endif;
44
-
45
  $unit = array();
46
  if (strlen($this->prefix) > 0) :
47
  $unit[] = $this->prefix;
15
  var $checkbox_name = NULL;
16
  function FeedWordPress_Walker_Category_Checklist ($params = array()) {
17
  $this->set_taxonomy('category');
18
+
19
  if (isset($params['checkbox_name'])) :
20
  $this->checkbox_name = $params['checkbox_name'];
21
  endif;
22
  }
23
+
24
  function set_prefix ($prefix) {
25
  $this->prefix = $prefix;
26
  }
28
  $this->taxonomy = $taxonomy;
29
  }
30
 
31
+ function start_el( &$output, $category, $depth = 0, $args = array(), $current_object_id = 0 ) {
32
  extract($args);
33
  if ( empty($taxonomy) ) :
34
  $taxonomy = 'category';
35
+ endif;
36
 
37
  if (!is_null($this->checkbox_name)) :
38
  $name = $this->checkbox_name;
41
  else :
42
  $name = 'tax_input['.$taxonomy.']';
43
  endif;
44
+
45
  $unit = array();
46
  if (strlen($this->prefix) > 0) :
47
  $unit[] = $this->prefix;
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: 2013.0504
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 2013.0504
15
  */
16
 
17
  # This uses code derived from:
@@ -27,17 +27,18 @@ License: GPL
27
  # USAGE: once FeedWordPress is installed, you manage just about everything from
28
  # the WordPress Dashboard, under the Syndication menu. To keep fresh content
29
  # coming in as it becomes available, you'll have to either check for updates
30
- # manually, or set up one of the automatically-scheduled update methods. See
31
  # <http://feedwordpress.radgeek.com/wiki/quick-start/> for some details.
32
 
33
  # -- Don't change these unless you know what you're doing...
34
 
35
- define ('FEEDWORDPRESS_VERSION', '2013.0504');
36
  define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
37
 
38
  if (!defined('FEEDWORDPRESS_BLEG')) :
39
  define ('FEEDWORDPRESS_BLEG', true);
40
  endif;
 
41
 
42
  // Defaults
43
  define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
@@ -70,9 +71,9 @@ if (FEEDWORDPRESS_DEBUG) :
70
  // Help us to pick out errors, if any.
71
  ini_set('error_reporting', E_ALL & ~E_NOTICE);
72
  ini_set('display_errors', true);
73
-
74
  // When testing we don't want cache issues to interfere. But this is
75
- // a VERY BAD SETTING for a production server. Webmasters will eat your
76
  // face for breakfast if you use it, and the baby Jesus will cry. So
77
  // make sure FEEDWORDPRESS_DEBUG is FALSE for any site that will be
78
  // used for more than testing purposes!
@@ -101,11 +102,11 @@ if (!function_exists('wp_insert_user')) :
101
  require_once (ABSPATH . WPINC . '/registration.php'); // for wp_insert_user
102
  endif;
103
 
104
- $dir = dirname(__FILE__);
105
  require_once("${dir}/externals/myphp/myphp.class.php");
106
  require_once("${dir}/admin-ui.php");
107
  require_once("${dir}/feedwordpresssyndicationpage.class.php");
108
- require_once("${dir}/compatability.php"); // Legacy API
109
  require_once("${dir}/syndicatedpost.class.php");
110
  require_once("${dir}/syndicatedlink.class.php");
111
  require_once("${dir}/feedwordpresshtml.class.php");
@@ -141,7 +142,8 @@ else : // Something went wrong. Let's just guess.
141
  $fwp_path = 'feedwordpress';
142
  endif;
143
 
144
- if (!FeedWordPress::needs_upgrade()) : // only work if the conditions are safe!
 
145
 
146
  # Syndicated items are generally received in output-ready (X)HTML and
147
  # should not be folded, crumpled, mutilated, or spindled by WordPress
@@ -158,18 +160,18 @@ if (!FeedWordPress::needs_upgrade()) : // only work if the conditions are safe!
158
 
159
  add_filter('the_content', 'feedwordpress_preserve_syndicated_content', -10000);
160
  add_filter('the_content', 'feedwordpress_restore_syndicated_content', 10000);
161
-
162
  add_action('atom_entry', 'feedwordpress_item_feed_data');
163
-
164
  # Filter in original permalinks if the user wants that
165
  add_filter('post_link', 'syndication_permalink', /*priority=*/ 1, /*arguments=*/ 3);
166
  add_filter('post_type_link', 'syndication_permalink', /*priority=*/ 1, /*arguments=*/ 4);
167
-
168
  # When foreign URLs are used for permalinks in feeds or display
169
  # contexts, they need to be escaped properly.
170
  add_filter('the_permalink', 'syndication_permalink_escaped');
171
  add_filter('the_permalink_rss', 'syndication_permalink_escaped');
172
-
173
  add_filter('post_comments_feed_link', 'syndication_comments_feed_link');
174
 
175
  # WTF? By default, wp_insert_link runs incoming link_url and link_rss
@@ -178,17 +180,17 @@ if (!FeedWordPress::needs_upgrade()) : // only work if the conditions are safe!
178
  # happens to fuck up any URI with a & to separate GET parameters.
179
  remove_filter('pre_link_rss', 'wp_filter_kses');
180
  remove_filter('pre_link_url', 'wp_filter_kses');
181
-
182
  # Admin menu
183
- add_action('admin_init', array('feedwordpress', 'admin_init'));
184
  add_action('admin_menu', 'fwp_add_pages');
185
  add_action('admin_notices', 'fwp_check_debug');
186
 
187
  add_action('admin_menu', 'feedwordpress_add_post_edit_controls');
188
  add_action('save_post', 'feedwordpress_save_post_edit_controls');
189
 
190
- add_action('admin_footer', array('FeedWordPress', 'admin_footer'));
191
-
192
  # Inbound XML-RPC update methods
193
  $feedwordpressRPC = new FeedWordPressRPC;
194
 
@@ -206,24 +208,25 @@ if (!FeedWordPress::needs_upgrade()) : // only work if the conditions are safe!
206
 
207
  add_action('wp_footer', 'debug_out_feedwordpress_footer', -100);
208
  add_action('admin_footer', 'debug_out_feedwordpress_footer', -100);
209
-
210
- $feedwordpress = new FeedWordPress;
211
 
212
  # Cron-less auto-update. Hooray!
213
  $autoUpdateHook = $feedwordpress->automatic_update_hook();
214
  if (!is_null($autoUpdateHook)) :
215
  add_action($autoUpdateHook, array($feedwordpress, 'auto_update'));
216
  endif;
217
-
218
  add_action('init', array($feedwordpress, 'init'));
219
  add_action('shutdown', array($feedwordpress, 'email_diagnostic_log'));
 
220
  add_action('wp_dashboard_setup', array($feedwordpress, 'dashboard_setup'));
221
 
222
  # Default sanitizers
223
  add_filter('syndicated_item_content', array('SyndicatedPost', 'resolve_relative_uris'), 0, 2);
224
  add_filter('syndicated_item_content', array('SyndicatedPost', 'sanitize_content'), 0, 2);
225
 
226
- add_action('plugins_loaded', array('FeedWordPress', 'admin_api'));
 
 
227
  else :
228
  # Hook in the menus, which will just point to the upgrade interface
229
  add_action('admin_menu', 'fwp_add_pages');
@@ -238,6 +241,10 @@ class FeedWordPressDiagnostic {
238
  $wpError = $error['object'];
239
  $url = $link->uri();
240
 
 
 
 
 
241
  $mesgs = $wpError->get_error_messages();
242
  foreach ($mesgs as $mesg) :
243
  $mesg = esc_html($mesg);
@@ -245,7 +252,7 @@ class FeedWordPressDiagnostic {
245
  'updated_feeds:errors',
246
  "Feed Error: [${url}] update returned error: $mesg"
247
  );
248
-
249
  $hours = get_option('feedwordpress_diagnostics_persistent_errors_hours', 2);
250
  $span = ($error['ts'] - $error['since']);
251
 
@@ -311,8 +318,8 @@ function debug_out_feedwordpress_footer () {
311
  * displaying a post.
312
  *
313
  * @param int $id The post to check for syndicated status. Defaults to the current post in a Loop context.
314
- * @return bool TRUE if the post's meta-data indicates it was syndicated; FALSE otherwise
315
- */
316
  function is_syndicated ($id = NULL) {
317
  $p = new FeedWordPressLocalPost($id);
318
  return $p->is_syndicated();
@@ -320,12 +327,12 @@ function is_syndicated ($id = NULL) {
320
 
321
  function feedwordpress_display_url ($url, $before = 60, $after = 0) {
322
  $bits = parse_url($url);
323
-
324
  // Strip out crufty subdomains
325
  if (isset($bits['host'])) :
326
  $bits['host'] = preg_replace('/^www[0-9]*\./i', '', $bits['host']);
327
  endif;
328
-
329
  // Reassemble bit-by-bit with minimum of crufty elements
330
  $url = (isset($bits['user'])?$bits['user'].'@':'')
331
  .(isset($bits['host'])?$bits['host']:'')
@@ -334,7 +341,7 @@ function feedwordpress_display_url ($url, $before = 60, $after = 0) {
334
  .(isset($bits['query'])?'?'.$bits['query']:'');
335
 
336
  if (strlen($url) > ($before+$after)) :
337
- $url = substr($url, 0, $before).''.substr($url, 0 - $after, $after);
338
  endif;
339
 
340
  return $url;
@@ -433,7 +440,7 @@ function the_syndication_permalink ($id = NULL) {
433
  */
434
  function get_local_permalink ($id = NULL) {
435
  global $feedwordpress_the_original_permalink;
436
-
437
  // get permalink, and thus activate filter and force global to be filled
438
  // with original URL.
439
  $url = get_permalink($id);
@@ -476,7 +483,7 @@ function feedwordpress_preserve_syndicated_content ($text) {
476
 
477
  function feedwordpress_restore_syndicated_content ($text) {
478
  global $feedwordpress_the_syndicated_content;
479
-
480
  if ( !is_null($feedwordpress_the_syndicated_content) ) :
481
  $text = $feedwordpress_the_syndicated_content;
482
  endif;
@@ -531,7 +538,7 @@ function feedwordpress_item_feed_data () {
531
  function syndication_permalink ($permalink = '', $post = null, $leavename = false, $sample = false) {
532
  global $id;
533
  global $feedwordpress_the_original_permalink;
534
-
535
  // Save the local permalink in case we need to retrieve it later.
536
  $feedwordpress_the_original_permalink = $permalink;
537
 
@@ -581,11 +588,11 @@ function syndication_permalink_escaped ($permalink) {
581
  $permalink = esc_html($permalink);
582
  endif;
583
  return $permalink;
584
- } /* function syndication_permalink_escaped() */
585
 
586
  /**
587
  * syndication_comments_feed_link: Escape XML special characters in comments
588
- * feed links
589
  *
590
  * @param string $link
591
  * @return string
@@ -602,7 +609,7 @@ function syndication_comments_feed_link ($link) {
602
  // that value here.
603
  $source = get_syndication_feed_object();
604
  $replacement = NULL;
605
-
606
  if ($source->setting('munge comments feed links', 'munge_comments_feed_links', 'yes') != 'no') :
607
  $commentFeeds = get_post_custom_values('wfw:commentRSS');
608
  if (
@@ -611,14 +618,14 @@ function syndication_comments_feed_link ($link) {
611
  and (strlen($commentFeeds[0]) > 0)
612
  ) :
613
  $replacement = $commentFeeds[0];
614
-
615
  // This is a foreign link; WordPress can't vouch for its not
616
  // having any entities that need to be &-escaped. So we'll do it
617
  // here.
618
  $replacement = esc_html($replacement);
619
  endif;
620
  endif;
621
-
622
  if (is_null($replacement)) :
623
  // Q: How can we get the proper feed format, since the
624
  // format is, stupidly, not passed to the filter?
@@ -642,7 +649,7 @@ function syndication_comments_feed_link ($link) {
642
  // comments feed link is never munged by FWP.
643
  endif;
644
  endif;
645
-
646
  if (!is_null($replacement)) : $link = $replacement; endif;
647
  endif;
648
  return $link;
@@ -654,11 +661,11 @@ function syndication_comments_feed_link ($link) {
654
 
655
  function fwp_add_pages () {
656
  global $feedwordpress;
657
-
658
  $menu_cap = FeedWordPress::menu_cap();
659
  $settings_cap = FeedWordPress::menu_cap(/*sub=*/ true);
660
  $syndicationMenu = FeedWordPress::path('syndication.php');
661
-
662
  add_menu_page(
663
  'Syndicated Sites', 'Syndication',
664
  $menu_cap,
@@ -708,7 +715,7 @@ function fwp_add_pages () {
708
  $syndicationMenu, 'FeedWordPress Diagnostics', 'Diagnostics',
709
  $settings_cap, FeedWordPress::path('diagnostics-page.php')
710
  );
711
-
712
  add_filter('page_row_actions', array($feedwordpress, 'row_actions'), 10, 2);
713
  add_filter('post_row_actions', array($feedwordpress, 'row_actions'), 10, 2);
714
  } /* function fwp_add_pages () */
@@ -779,7 +786,7 @@ function fwp_publish_post_hook ($post_id) {
779
  do_action('xmlrpc_publish_post', $post_id);
780
  if ( defined('APP_REQUEST') )
781
  do_action('app_publish_post', $post_id);
782
-
783
  if ( defined('WP_IMPORTING') )
784
  return;
785
 
@@ -797,18 +804,29 @@ function fwp_publish_post_hook ($post_id) {
797
  global $inspectPostMeta;
798
 
799
  // Put in Manual Editing checkbox
800
- add_meta_box('feedwordpress-post-controls', __('Syndication'), 'feedwordpress_post_edit_controls', 'post', 'side', 'high');
801
 
802
  add_filter('user_can_richedit', array($feedwordpress, 'user_can_richedit'), 1000, 1);
803
-
804
  if (FeedWordPress::diagnostic_on('syndicated_posts:static_meta_data')) :
805
  $inspectPostMeta = new InspectPostMeta;
806
  endif;
807
- } // function FeedWordPress::postEditControls
808
-
 
 
 
 
 
 
 
 
 
 
 
809
  function feedwordpress_post_edit_controls () {
810
  global $post;
811
-
812
  $frozen_values = get_post_custom_values('_syndication_freeze_updates', $post->ID);
813
  $frozen_post = (count($frozen_values) > 0 and 'yes' == $frozen_values[0]);
814
 
@@ -817,47 +835,71 @@ function fwp_publish_post_hook ($post_id) {
817
  <p>This is a syndicated post, which originally appeared at
818
  <cite><?php print esc_html(get_syndication_source(NULL, $post->ID)); ?></cite>.
819
  <a href="<?php print esc_html(get_syndication_permalink($post->ID)); ?>">View original post</a>.</p>
 
 
820
 
821
  <p><input type="hidden" name="feedwordpress_noncename" id="feedwordpress_noncename" value="<?php print wp_create_nonce(plugin_basename(__FILE__)); ?>" />
822
  <label><input type="checkbox" name="freeze_updates" value="yes" <?php if ($frozen_post) : ?>checked="checked"<?php endif; ?> /> <strong>Manual editing.</strong>
823
  If set, FeedWordPress will not overwrite the changes you make manually
824
  to this post, if the syndicated content is updated on the
825
  feed.</label></p>
 
 
 
826
  <?php
827
  else :
828
  ?>
829
  <p>This post was created locally at this website.</p>
830
  <?php
831
  endif;
832
- } // function feedwordpress_post_edit_controls () */
833
 
834
  function feedwordpress_save_post_edit_controls ( $post_id ) {
835
  global $post;
836
-
837
  if (!isset($_POST['feedwordpress_noncename']) or !wp_verify_nonce($_POST['feedwordpress_noncename'], plugin_basename(__FILE__))) :
838
  return $post_id;
839
  endif;
840
-
841
  // Verify if this is an auto save routine. If it is our form has
842
  // not been submitted, so we don't want to do anything.
843
  if ( defined('DOING_AUTOSAVE') and DOING_AUTOSAVE ) :
844
  return $post_id;
845
  endif;
 
 
 
 
 
 
846
 
847
  // Check permissions
848
- if ( !current_user_can( 'edit_'.$_POST['post_type'], $post_id) ) :
 
 
 
 
 
849
  return $post_id;
850
  endif;
851
 
852
  // OK, we're golden. Now let's save some data.
853
  if (isset($_POST['freeze_updates'])) :
 
854
  update_post_meta($post_id, '_syndication_freeze_updates', $_POST['freeze_updates']);
855
  $ret = $_POST['freeze_updates'];
 
 
 
 
 
 
856
  else :
857
  delete_post_meta($post_id, '_syndication_freeze_updates');
858
  $ret = NULL;
859
  endif;
860
-
 
 
861
  return $ret;
862
  } // function feedwordpress_save_edit_controls
863
 
@@ -902,16 +944,19 @@ class FeedWordPress {
902
  var $feeds = NULL;
903
  var $feedurls = NULL;
904
  var $httpauth = NULL;
905
-
906
- # function FeedWordPress (): Contructor; retrieve a list of feeds
907
- function FeedWordPress () {
 
 
 
908
  $this->feeds = array ();
909
  $this->feedurls = array();
910
  $links = FeedWordPress::syndicated_links();
911
  if ($links): foreach ($links as $link):
912
  $id = intval($link->link_id);
913
  $url = $link->link_rss;
914
-
915
  // Store for later reference.
916
  $this->feeds[$id] = $id;
917
  if (strlen($url) > 0) :
@@ -919,20 +964,37 @@ class FeedWordPress {
919
  endif;
920
  endforeach; endif;
921
 
 
 
922
  $this->httpauth = new FeedWordPressHTTPAuthenticator;
923
- } // FeedWordPress::FeedWordPress ()
924
 
925
- function subscribed ($id) {
 
 
 
 
 
 
 
926
  return (isset($this->feedurls[$id]) or isset($this->feeds[$id]));
927
  } /* FeedWordPress::subscribed () */
928
-
929
- function subscription ($which) {
 
 
 
 
 
 
 
 
930
  $sub = NULL;
931
-
932
  if (is_string($which) and isset($this->feedurls[$which])) :
933
  $which = $this->feedurls[$which];
934
  endif;
935
-
936
  if (isset($this->feeds[$which])) :
937
  $sub = $this->feeds[$which];
938
  endif;
@@ -950,10 +1012,10 @@ class FeedWordPress {
950
  $this->feeds[$which] = $link;
951
  $sub = $link;
952
  endif;
953
-
954
  return $sub;
955
  } /* FeedWordPress::subscription () */
956
-
957
  # function update (): polls for updates on one or more Contributor feeds
958
  #
959
  # Arguments:
@@ -999,17 +1061,17 @@ class FeedWordPress {
999
  # (between 30 minutes and 2 hours).
1000
  #
1001
  # * New posts from the polled feed are added to the WordPress store.
1002
- #
1003
  # * Updates to existing posts since the last poll are mirrored in the
1004
  # WordPress store.
1005
  #
1006
- function update ($uri = null, $crash_ts = null) {
1007
  global $wpdb;
1008
 
1009
  if (FeedWordPress::needs_upgrade()) : // Will make duplicate posts if we don't hold off
1010
  return NULL;
1011
  endif;
1012
-
1013
  if (!is_null($uri) and $uri != '*') :
1014
  $uri = trim($uri);
1015
  else : // Update all
@@ -1028,7 +1090,7 @@ class FeedWordPress {
1028
  if (is_null($crash_ts)) :
1029
  $crash_ts = $this->crash_ts();
1030
  endif;
1031
-
1032
  // Randomize order for load balancing purposes
1033
  $feed_set = array_keys($this->feeds);
1034
  shuffle($feed_set);
@@ -1045,8 +1107,8 @@ class FeedWordPress {
1045
  ), $uri);
1046
 
1047
  $feed_set = apply_filters('feedwordpress_update_feeds', $feed_set, $uri);
1048
-
1049
-
1050
  // Loop through and check for new posts
1051
  $delta = NULL; $remaining = $max_polls;
1052
  foreach ($feed_set as $feed_id) :
@@ -1057,13 +1119,13 @@ class FeedWordPress {
1057
  if (
1058
  // Over time limit?
1059
  (!is_null($crash_ts) and (time() > $crash_ts))
1060
-
1061
  // Over feed count?
1062
- or ($remaining == 0)
1063
  ) :
1064
  break;
1065
  endif;
1066
-
1067
  $pinged_that = (is_null($uri) or ($uri=='*') or in_array($uri, array($feed->uri(), $feed->homepage())));
1068
 
1069
  if (!is_null($uri)) : // A site-specific ping always updates
@@ -1072,8 +1134,10 @@ class FeedWordPress {
1072
  $timely = $feed->stale();
1073
  endif;
1074
 
1075
- if ($pinged_that and is_null($delta)) : // If at least one feed was hit for updating...
1076
- $delta = array('new' => 0, 'updated' => 0); // ... don't return error condition
 
 
1077
  endif;
1078
 
1079
  if ($pinged_that and $timely) :
@@ -1085,18 +1149,18 @@ class FeedWordPress {
1085
  do_action('feedwordpress_check_feed_complete', $feed->settings, $added, time() - $start_ts);
1086
 
1087
  if (is_array($added)) : // Success
1088
- if (isset($added['new'])) : $delta['new'] += $added['new']; endif;
1089
- if (isset($added['updated'])) : $delta['updated'] += $added['updated']; endif;
 
1090
  endif;
1091
  endif;
1092
  endforeach;
1093
 
1094
  do_action('feedwordpress_update_complete', $delta);
1095
-
1096
  return $delta;
1097
- }
1098
 
1099
- function crash_ts ($default = NULL) {
1100
  $crash_dt = (int) get_option('feedwordpress_update_time_limit', 0);
1101
  if ($crash_dt > 0) :
1102
  $crash_ts = time() + $crash_dt;
@@ -1104,32 +1168,23 @@ class FeedWordPress {
1104
  $crash_ts = $default;
1105
  endif;
1106
  return $crash_ts;
1107
- }
1108
-
1109
- function secret_key () {
1110
  $secret = get_option('feedwordpress_secret_key', false);
1111
  if (!$secret) : // Generate random key.
1112
  $secret = substr(md5(uniqid(microtime())), 0, 6);
1113
  update_option('feedwordpress_secret_key', $secret);
1114
  endif;
1115
  return $secret;
1116
- }
1117
-
1118
- function has_secret () {
1119
- return ($this->by_request('feedwordpress_key', $this->secret_key()));
1120
- }
1121
 
1122
- // Utility function so I don't have to repeat myself w/ 1,000,003 isset()'s
1123
- function by_request ($param, $eq = NULL) {
1124
- $match = false;
1125
- if (isset($_REQUEST[$param])) :
1126
- $match = (is_null($eq) ? $_REQUEST[$param] : ($eq==$_REQUEST[$param]));
1127
- endif;
1128
- return $match;
1129
- }
1130
-
1131
  var $update_hooked = NULL;
1132
- function automatic_update_hook ($params = array()) {
1133
  $params = wp_parse_args($params, array( // Defaults
1134
  'setting only' => false,
1135
  ));
@@ -1140,51 +1195,53 @@ class FeedWordPress {
1140
  if (
1141
  !$params['setting only']
1142
  and $this->has_secret()
1143
- and $this->by_request('automatic_update')
1144
  ) :
1145
- $hook = $_REQUEST['automatic_update'];
1146
  $method = 'URL parameter';
1147
  endif;
1148
-
1149
  $exact = $hook; // Before munging
1150
-
1151
  if (!!$hook) :
1152
  if ($hook != 'init') : // Constrain values.
1153
  $hook = 'shutdown';
1154
  endif;
1155
  endif;
1156
-
1157
  if ($hook) :
1158
  $this->update_hooked = "Initiating an AUTOMATIC CHECK FOR UPDATES ON PAGE LOAD ".$hook." due to ".$method." = ".trim($this->val($exact));
1159
  endif;
1160
-
1161
- return $hook;
1162
- }
1163
- function last_update_all () {
 
1164
  $last = get_option('feedwordpress_last_update_all');
1165
- if ($this->has_secret() and $this->by_request('automatic_update')) :
1166
  $last = 1; // A long, long time ago.
1167
- elseif ($this->has_secret() and $this->by_request('last_update_all')) :
1168
- $last = $_REQUEST['last_update_all'];
1169
  endif;
1170
  return $last;
1171
- }
1172
- function force_update_all () {
1173
- return ($this->has_secret() and $this->by_request('force_update_feeds'));
1174
- }
1175
-
1176
- function stale () {
 
1177
  if (!is_null($this->automatic_update_hook())) :
1178
  // Do our best to avoid possible simultaneous
1179
  // updates by getting up-to-the-minute settings.
1180
-
1181
  $last = $this->last_update_all();
1182
-
1183
  // If we haven't updated all yet, give it a time window
1184
  if (false === $last) :
1185
  $ret = false;
1186
  update_option('feedwordpress_last_update_all', time());
1187
-
1188
  // Otherwise, check against freshness interval
1189
  elseif (is_numeric($last)) : // Expect a timestamp
1190
  $freshness = get_option('feedwordpress_freshness');
@@ -1192,7 +1249,7 @@ class FeedWordPress {
1192
  $freshness = FEEDWORDPRESS_FRESHNESS_INTERVAL;
1193
  endif;
1194
  $ret = ( (time() - $last) > $freshness );
1195
-
1196
  // This should never happen.
1197
  else :
1198
  FeedWordPress::critical_bug('FeedWordPress::stale::last', $last, __LINE__, __FILE__);
@@ -1202,7 +1259,7 @@ class FeedWordPress {
1202
  $ret = false;
1203
  endif;
1204
  return $ret;
1205
- } // FeedWordPress::stale()
1206
 
1207
  static function admin_init () {
1208
  // WordPress 3.5+ compat: the WP devs are in the midst of removing Links from the WordPress core. Eventually we'll have to deal
@@ -1211,34 +1268,200 @@ class FeedWordPress {
1211
  if (!intval(get_option('link_manager_enabled', false))) :
1212
  update_option('link_manager_enabled', true);
1213
  endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1214
  } /* FeedWordPress::admin_init() */
1215
 
1216
- function admin_api () {
1217
  // This sucks, but WordPress doesn't give us any other way to
1218
  // easily invoke a permanent-delete from a plugged in post
1219
  // actions link. So we create a magic parameter, and when this
1220
  // magic parameter is activated, the WordPress trashcan is
1221
  // temporarily de-activated.
1222
-
1223
  if (MyPHP::request('fwp_post_delete')=='nuke') :
1224
  // Get post ID #
1225
  $post_id = MyPHP::request('post');
1226
  if (!$post_id) :
1227
  $post_id = MyPHP::request('post_ID');
1228
  endif;
1229
-
1230
  // Make sure we've got the right nonce and all that.
1231
  check_admin_referer('delete-post_' . $post_id);
1232
-
1233
  // If so, disable the trashcan.
1234
  define('EMPTY_TRASH_DAYS', 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1235
  endif;
 
 
 
 
1236
 
 
1237
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
1238
 
1239
- function init () {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1240
  global $fwp_path;
1241
-
1242
  // If this is a FeedWordPress admin page, queue up scripts for AJAX
1243
  // functions that FWP uses. If it is a display page or a non-FWP admin
1244
  // page, don't.
@@ -1246,19 +1469,21 @@ class FeedWordPress {
1246
  if (FeedWordPressSettingsUI::is_admin()) :
1247
  // For JavaScript that needs to be generated dynamically
1248
  add_action('admin_print_scripts', array('FeedWordPressSettingsUI', 'admin_scripts'));
1249
-
1250
  // For CSS that needs to be generated dynamically.
1251
  add_action('admin_print_styles', array('FeedWordPressSettingsUI', 'admin_styles'));
1252
-
1253
  wp_enqueue_style('dashboard');
1254
  wp_enqueue_style('feedwordpress-elements');
1255
-
1256
  /*if (function_exists('wp_admin_css')) :
1257
  wp_admin_css('css/dashboard');
1258
  endif;*/
1259
  endif;
1260
 
1261
- // This is a special post status for hiding posts that have expired
 
 
1262
  register_post_status('fwpretired', array(
1263
  'label' => _x('Retired', 'post'),
1264
  'label_count' => _n_noop('Retired <span class="count">(%s)</span>', 'Retired <span class="count">(%s)</span>'),
@@ -1268,6 +1493,15 @@ class FeedWordPress {
1268
  'show_in_admin_all_list' => false,
1269
  'show_in_admin_status_list' => true,
1270
  ));
 
 
 
 
 
 
 
 
 
1271
  add_action(
1272
  /*hook=*/ 'template_redirect',
1273
  /*function=*/ array($this, 'redirect_retired'),
@@ -1277,15 +1511,15 @@ class FeedWordPress {
1277
  add_action('wp_ajax_fwp_feeds', array($this, 'fwp_feeds'));
1278
  add_action('wp_ajax_fwp_feedcontents', array($this, 'fwp_feedcontents'));
1279
  add_action('wp_ajax_fwp_xpathtest', array($this, 'fwp_xpathtest'));
1280
-
1281
  $this->clear_cache_magic_url();
1282
  $this->update_magic_url();
1283
  } /* FeedWordPress::init() */
1284
-
1285
- function fwp_feeds () {
1286
  $feeds = array();
1287
  $feed_ids = $this->feeds;
1288
-
1289
  foreach ($feed_ids as $id) :
1290
  $sub = $this->subscription($id);
1291
  $feeds[] = array(
@@ -1295,18 +1529,18 @@ class FeedWordPress {
1295
  );
1296
  endforeach;
1297
 
1298
- header("Content-Type: application/json");
1299
  echo json_encode($feeds);
1300
  exit;
1301
- }
1302
 
1303
- function fwp_feedcontents () {
1304
  $feed_id = MyPHP::request('feed_id');
1305
-
1306
  // Let's load up some data from the feed . . .
1307
  $feed = $this->subscription($feed_id);
1308
  $posts = $feed->live_posts();
1309
-
1310
  if (is_wp_error($posts)) :
1311
  header("HTTP/1.1 502 Bad Gateway");
1312
  $result = $posts;
@@ -1315,7 +1549,7 @@ class FeedWordPress {
1315
 
1316
  foreach ($posts as $post) :
1317
  $p = new SyndicatedPost($post, $feed);
1318
-
1319
  $result[] = array(
1320
  "post_title" => $p->entry->get_title(),
1321
  "post_link" => $p->permalink(),
@@ -1324,42 +1558,42 @@ class FeedWordPress {
1324
  );
1325
  endforeach;
1326
  endif;
1327
-
1328
  header("Content-Type: application/json");
1329
-
1330
  echo json_encode($result);
1331
-
1332
  // This is an AJAX request, so close it out thus.
1333
  die;
1334
  } /* FeedWordPress::fwp_feedcontents () */
1335
-
1336
- function fwp_xpathtest () {
1337
  $xpath = MyPHP::request('xpath');
1338
  $feed_id = MyPHP::request('feed_id');
1339
  $post_id = MyPHP::request('post_id');
1340
-
1341
  $expr = new FeedWordPressParsedPostMeta($xpath);
1342
-
1343
  // Let's load up some data from the feed . . .
1344
  $feed = $this->subscription($feed_id);
1345
  $posts = $feed->live_posts();
1346
-
1347
  if (!is_wp_error($posts)) :
1348
  if (strlen($post_id) == 0) :
1349
  $post = $posts[0];
1350
  else :
1351
  $post = null;
1352
-
1353
  foreach ($posts as $p) :
1354
  if ($p->get_id() == $post_id) :
1355
  $post = $p;
1356
  endif;
1357
  endforeach;
1358
  endif;
1359
-
1360
  $post = new SyndicatedPost($post, $feed);
1361
  $meta = $expr->do_substitutions($post);
1362
-
1363
  $result = array(
1364
  "post_title" => $post->entry->get_title(),
1365
  "post_link" => $post->permalink(),
@@ -1374,24 +1608,27 @@ class FeedWordPress {
1374
  "post_id" => $post_id,
1375
  "results" => $posts
1376
  );
1377
-
1378
  header("HTTP/1.1 503 Bad Gateway");
1379
  endif;
1380
-
1381
  header("Content-Type: application/json");
1382
-
1383
  echo json_encode($result);
1384
-
1385
  // This is an AJAX request, so close it out thus.
1386
  die;
1387
  } /* FeedWordPress::fwp_xpathtest () */
1388
-
1389
- function redirect_retired () {
1390
  global $wp_query;
1391
  if (is_singular()) :
1392
- if ('fwpretired'==$wp_query->post->post_status) :
 
 
 
1393
  do_action('feedwordpress_redirect_retired', $wp_query->post);
1394
-
1395
  if (!($template = get_404_template())) :
1396
  $template = get_index_template();
1397
  endif;
@@ -1402,48 +1639,73 @@ class FeedWordPress {
1402
  exit;
1403
  endif;
1404
  endif;
1405
- }
1406
-
1407
- function row_actions ($actions, $post) {
1408
  if (is_syndicated($post->ID)) :
1409
  $link = get_delete_post_link($post->ID, '', true);
1410
- $link = MyPHP::url($link, array("fwp_post_delete" => "nuke"));
 
 
 
1411
 
1412
- $caption = 'Erase the record of this post (will be re-syndicated if it still appears on the feed).';
1413
- $linktext = 'Erase/Resyndicate';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1414
 
1415
  $keys = array_keys($actions);
1416
  $links = array();
1417
  foreach ($keys as $key) :
1418
  $links[$key] = $actions[$key];
1419
-
1420
  if ('trash'==$key) :
1421
- $links[$key] = "<a class='submitdelete' title='" . esc_attr( __( 'Move this item to the Trash (will NOT be re-syndicated)' ) ) . "' href='" . get_delete_post_link( $post->ID ) . "'>" . __( 'Trash/Don&#8217;t Resyndicate' ) . "</a>";
1422
-
1423
  // Placeholder.
 
 
 
1424
  $links['delete'] = '';
1425
  endif;
1426
  endforeach;
1427
-
1428
- $links['delete'] = '<a class="submitdelete" title="'.esc_attr(__($caption)).'" href="' . $link . '">' . __($linktext) . '</a>';
 
 
 
1429
 
1430
  $actions = $links;
1431
  endif;
1432
  return $actions;
1433
- }
1434
-
1435
- function dashboard_setup () {
1436
  $see_it = FeedWordPress::menu_cap();
1437
-
1438
  if (current_user_can($see_it)) :
1439
  // Get the stylesheet
1440
  wp_enqueue_style('feedwordpress-elements');
1441
-
1442
  $widget_id = 'feedwordpress_dashboard';
1443
  $widget_name = __('Syndicated Sources');
1444
  $column = 'side';
1445
  $priority = 'core';
1446
-
1447
  // I would love to use wp_add_dashboard_widget() here and save
1448
  // myself some trouble. But WP 3 does not yet have any way to
1449
  // push a dashboard widget onto the side, or to give it a default
@@ -1457,57 +1719,57 @@ class FeedWordPress {
1457
  /*priority=*/ $priority
1458
  );
1459
  /*control_callback= array($this, 'dashboard_control') */
1460
-
1461
  // This is kind of rude, I know, but the dashboard widget isn't
1462
  // worth much if users don't know that it exists, and I don't
1463
  // know of any better way to reorder the boxen.
1464
  //
1465
  // Gleefully ripped off of codex.wordpress.org/Dashboard_Widgets_API
1466
-
1467
  // Globalize the metaboxes array, this holds all the widgets for wp-admin
1468
  global $wp_meta_boxes;
1469
-
1470
- // Get the regular dashboard widgets array
1471
  // (which has our new widget already but at the end)
1472
-
1473
  $normal_dashboard = $wp_meta_boxes['dashboard'][$column][$priority];
1474
-
1475
  // Backup and delete our new dashbaord widget from the end of the array
1476
  if (isset($normal_dashboard[$widget_id])) :
1477
  $backup = array();
1478
  $backup[$widget_id] = $normal_dashboard[$widget_id];
1479
  unset($normal_dashboard[$widget_id]);
1480
-
1481
  // Merge the two arrays together so our widget is at the
1482
  // beginning
1483
  $sorted_dashboard = array_merge($backup, $normal_dashboard);
1484
-
1485
- // Save the sorted array back into the original metaboxes
1486
  $wp_meta_boxes['dashboard'][$column][$priority] = $sorted_dashboard;
1487
  endif;
1488
  endif;
1489
  } /* FeedWordPress::dashboard_setup () */
1490
-
1491
- function dashboard () {
1492
  $syndicationPage = new FeedWordPressSyndicationPage(dirname(__FILE__).'/syndication.php');
1493
  $syndicationPage->dashboard_box($syndicationPage);
1494
  } /* FeedWordPress::dashboard () */
1495
 
1496
- function user_can_richedit ($rich_edit) {
1497
 
1498
  $post = new FeedWordPressLocalPost;
1499
-
1500
  if (!$post->is_exposed_to_formatting_filters()) :
1501
  // Disable visual editor and only allow operations
1502
  // directly on HTML if post is bypassing fmt filters
1503
- $rich_edit = false;
1504
  endif;
1505
-
1506
  return $rich_edit;
1507
 
1508
  } /* FeedWordPress::user_can_richedit () */
1509
-
1510
- function update_magic_url () {
1511
  global $wpdb;
1512
 
1513
  // Explicit update request in the HTTP request (e.g. from a cron job)
@@ -1515,7 +1777,7 @@ class FeedWordPress {
1515
  $this->update_hooked = "Initiating a CRON JOB CHECK-IN ON UPDATE SCHEDULE due to URL parameter = ".trim($this->val($_REQUEST['update_feedwordpress']));
1516
 
1517
  $this->update($this->update_requested_url());
1518
-
1519
  if (FEEDWORDPRESS_DEBUG and count($wpdb->queries) > 0) :
1520
  $mysqlTime = 0.0;
1521
  $byTime = array();
@@ -1523,58 +1785,58 @@ class FeedWordPress {
1523
  $time = $query[1] * 1000000.0;
1524
  $mysqlTime += $query[1];
1525
  if (!isset($byTime[$time])) : $byTime[$time] = array(); endif;
1526
- $byTime[$time][] = $query[0]. ' // STACK: ' . $query[2];
1527
  endforeach;
1528
  krsort($byTime);
1529
-
1530
  foreach ($byTime as $time => $querySet) :
1531
  foreach ($querySet as $query) :
1532
  print "[".(sprintf('%4.4f', $time/1000.0)) . "ms] $query\n";
1533
  endforeach;
1534
  endforeach;
1535
- echo $this->log_prefix()."$wpdb->num_queries queries. $mysqlTime seconds in MySQL. Total of "; timer_stop(1); print " seconds.";
1536
  endif;
1537
-
1538
  debug_out_feedwordpress_footer();
1539
-
1540
  // Magic URL should return nothing but a 200 OK header packet
1541
  // when successful.
1542
  exit;
1543
  endif;
1544
  } /* FeedWordPress::magic_update_url () */
1545
 
1546
- function clear_cache_magic_url () {
1547
  if ($this->clear_cache_requested()) :
1548
  $this->clear_cache();
1549
  endif;
1550
  } /* FeedWordPress::clear_cache_magic_url() */
1551
-
1552
- function clear_cache_requested () {
1553
  return MyPHP::request('clear_cache');
1554
  } /* FeedWordPress::clear_cache_requested() */
1555
 
1556
- function update_requested () {
1557
- return FeedWordPress::by_request('update_feedwordpress');
1558
- } // FeedWordPress::update_requested()
1559
 
1560
- function update_requested_url () {
1561
  $ret = null;
1562
-
1563
  if (($_REQUEST['update_feedwordpress']=='*')
1564
  or (preg_match('|^http://.*|i', $_REQUEST['update_feedwordpress']))) :
1565
  $ret = $_REQUEST['update_feedwordpress'];
1566
  endif;
1567
 
1568
  return $ret;
1569
- } // FeedWordPress::update_requested_url()
1570
 
1571
- function auto_update () {
1572
  if ($this->stale()) :
1573
  $this->update();
1574
  endif;
1575
  } /* FeedWordPress::auto_update () */
1576
 
1577
- function find_link ($uri, $field = 'link_rss') {
1578
  global $wpdb;
1579
 
1580
  $unslashed = untrailingslashit($uri);
@@ -1583,11 +1845,40 @@ class FeedWordPress {
1583
  SELECT link_id FROM $wpdb->links WHERE $field IN ('%s', '%s')
1584
  LIMIT 1", $unslashed, $slashed
1585
  ));
1586
-
1587
  return $link_id;
1588
  } /* FeedWordPress::find_link () */
1589
 
1590
- function syndicate_link ($name, $uri, $rss) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1591
  // Get the category ID#
1592
  $cat_id = FeedWordPress::link_category_id();
1593
  if (!is_wp_error($cat_id)) :
@@ -1598,21 +1889,21 @@ class FeedWordPress {
1598
 
1599
  // WordPress gets cranky if there's no homepage URI
1600
  if (!is_string($uri) or strlen($uri)<1) : $uri = $rss; endif;
1601
-
1602
  // Check if this feed URL is already being syndicated.
1603
- $link_id = wp_insert_link(array(
1604
  "link_id" => FeedWordPress::find_link($rss), // insert if nothing was found; else update
1605
  "link_rss" => $rss,
1606
  "link_name" => $name,
1607
  "link_url" => $uri,
1608
  "link_category" => $link_category,
1609
  "link_visible" => 'Y', // reactivate if inactivated
1610
- ));
1611
 
1612
  return $link_id;
1613
  } /* function FeedWordPress::syndicate_link() */
1614
 
1615
- /*static*/ function syndicated_status ($what, $default) {
1616
  $ret = get_option("feedwordpress_syndicated_{$what}_status");
1617
  if (!$ret) :
1618
  $ret = $default;
@@ -1620,17 +1911,17 @@ class FeedWordPress {
1620
  return $ret;
1621
  } /* FeedWordPress::syndicated_status() */
1622
 
1623
- function on_unfamiliar ($what = 'author') {
1624
  switch ($what) :
1625
  case 'category' : $suffix = ':category'; break;
1626
  case 'post_tag' : $suffix = ':post_tag'; break;
1627
  default: $suffix = '';
1628
  endswitch;
1629
-
1630
  return get_option('feedwordpress_unfamiliar_'.$what, 'create'.$suffix);
1631
  } // function FeedWordPress::on_unfamiliar()
1632
 
1633
- function null_email_set () {
1634
  $base = get_option('feedwordpress_null_email_set');
1635
 
1636
  if ($base===false) :
@@ -1644,16 +1935,16 @@ class FeedWordPress {
1644
 
1645
  } /* FeedWordPress::null_email_set () */
1646
 
1647
- function is_null_email ($email) {
1648
  $ret = in_array(strtolower(trim($email)), FeedWordPress::null_email_set());
1649
  $ret = apply_filters('syndicated_item_author_is_null_email', $ret, $email);
1650
  return $ret;
1651
  } /* FeedWordPress::is_null_email () */
1652
 
1653
- function use_aggregator_source_data () {
1654
  $ret = get_option('feedwordpress_use_aggregator_source_data');
1655
  return apply_filters('syndicated_post_use_aggregator_source_data', ($ret=='yes'));
1656
- }
1657
 
1658
  /**
1659
  * FeedWordPress::munge_permalinks: check whether or not FeedWordPress
@@ -1662,11 +1953,11 @@ class FeedWordPress {
1662
  *
1663
  * @return bool TRUE if FeedWordPress SHOULD rewrite permalinks; FALSE otherwise
1664
  */
1665
- /*static*/ function munge_permalinks () {
1666
  return (get_option('feedwordpress_munge_permalink', /*default=*/ 'yes') != 'no');
1667
  } /* FeedWordPress::munge_permalinks() */
1668
 
1669
- function syndicated_links ($args = array()) {
1670
  $contributors = FeedWordPress::link_category_id();
1671
  if (!is_wp_error($contributors)) :
1672
  $links = get_bookmarks(array_merge(
@@ -1678,13 +1969,13 @@ class FeedWordPress {
1678
  endif;
1679
 
1680
  return $links;
1681
- } // function FeedWordPress::syndicated_links()
1682
 
1683
- function link_category_id () {
1684
  global $wpdb, $wp_db_version;
1685
 
1686
  $cat_id = get_option('feedwordpress_cat_id');
1687
-
1688
  // If we don't yet have the category ID stored, search by name
1689
  if (!$cat_id) :
1690
  $cat_id = FeedWordPressCompatibility::link_category_id(DEFAULT_SYNDICATION_CATEGORY);
@@ -1698,7 +1989,7 @@ class FeedWordPress {
1698
  else :
1699
  $cat_id = FeedWordPressCompatibility::link_category_id((int) $cat_id, 'cat_id');
1700
  endif;
1701
-
1702
  // If we could not find an appropriate link category,
1703
  // make a new one for ourselves.
1704
  if (!$cat_id) :
@@ -1710,45 +2001,35 @@ class FeedWordPress {
1710
  endif;
1711
 
1712
  return $cat_id;
1713
- } // function FeedWordPress::link_category_id()
1714
 
1715
  # Upgrades and maintenance...
1716
- function needs_upgrade () {
 
1717
  global $wpdb;
1718
- $fwp_db_version = get_option('feedwordpress_version');
1719
  $ret = false; // innocent until proven guilty
1720
- if (!$fwp_db_version or $fwp_db_version < FEEDWORDPRESS_VERSION) :
1721
- // This is an older version or a fresh install. Does it
1722
- // require a database upgrade or database initialization?
1723
- if ($fwp_db_version <= 0.96) :
1724
- // Yes. Check to see whether this is a fresh install or an upgrade.
1725
- $syn = $wpdb->get_col("
1726
- SELECT post_id
1727
- FROM $wpdb->postmeta
1728
- WHERE meta_key = 'syndication_feed'
1729
- ");
1730
- if (count($syn) > 0) : // contains at least one syndicated post
1731
- $ret = true;
1732
- else : // fresh install; brand it as ours
1733
- update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
1734
- endif;
1735
- elseif ($fwp_db_version < 2009.0707) :
1736
- // We need to clear out any busted AJAX crap
1737
- $wpdb->query("
1738
- DELETE FROM $wpdb->usermeta
1739
- WHERE LOCATE('feedwordpress', meta_key)
1740
- AND LOCATE('box', meta_key);
1741
- ");
1742
 
 
 
 
 
 
 
 
 
1743
  update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
 
1744
  elseif ($fwp_db_version < 2010.0814) :
 
1745
  // Change in terminology.
1746
  if (get_option('feedwordpress_unfamiliar_category', 'create')=='default') :
1747
  update_option('feedwordpress_unfamiliar_category', 'null');
1748
  endif;
1749
  foreach (FeedWordPress::syndicated_links() as $link) :
1750
  $sub = new SyndicatedLink($link);
1751
-
1752
  $remap_uf = array(
1753
  'default' => 'null',
1754
  'filter' => 'null',
@@ -1765,34 +2046,38 @@ class FeedWordPress {
1765
  endif;
1766
  endforeach;
1767
  endif;
1768
-
1769
  if (isset($sub->settings['add global categories'])) :
1770
  $sub->settings['add/category'] = $sub->settings['add global categories'];
1771
  unset($sub->settings['add global categories']);
1772
  endif;
1773
-
1774
  $sub->save_settings(/*reload=*/ true);
1775
  endforeach;
1776
  update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
 
1777
  else :
1778
- // No. Just brand it with the new version.
 
1779
  update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
 
1780
  endif;
 
1781
  endif;
1782
  return $ret;
1783
- }
1784
 
1785
- function upgrade_database ($from = NULL) {
1786
  global $wpdb;
1787
 
1788
  if (is_null($from) or $from <= 0.96) : $from = 0.96; endif;
1789
 
1790
  switch ($from) :
1791
  case 0.96:
1792
- // Dropping legacy upgrade code. If anyone is still
1793
- // using 0.96 and just now decided to upgrade, well, I'm
1794
- // sorry about that. You'll just have to cope with a few
1795
- // duplicate posts.
1796
 
1797
  // Mark the upgrade as successful.
1798
  update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
@@ -1800,9 +2085,9 @@ class FeedWordPress {
1800
  echo "<p>Upgrade complete. FeedWordPress is now ready to use again.</p>";
1801
  } /* FeedWordPress::upgrade_database() */
1802
 
1803
- function has_guid_index () {
1804
  global $wpdb;
1805
-
1806
  $found = false; // Guilty until proven innocent.
1807
 
1808
  $results = $wpdb->get_results("
@@ -1818,41 +2103,42 @@ class FeedWordPress {
1818
  endif;
1819
  return $found;
1820
  } /* FeedWordPress::has_guid_index () */
1821
-
1822
- function create_guid_index () {
1823
  global $wpdb;
1824
-
1825
  $wpdb->query("
1826
  CREATE INDEX {$wpdb->posts}_guid_idx ON {$wpdb->posts}(guid)
1827
  ");
1828
  } /* FeedWordPress::create_guid_index () */
1829
-
1830
- function remove_guid_index () {
1831
  global $wpdb;
1832
-
1833
  $wpdb->query("
1834
  DROP INDEX {$wpdb->posts}_guid_idx ON {$wpdb->posts}
1835
  ");
1836
  }
1837
 
1838
- /*static*/ function fetch_timeout () {
1839
  return apply_filters(
1840
  'feedwordpress_fetch_timeout',
1841
  intval(get_option('feedwordpress_fetch_timeout', FEEDWORDPRESS_FETCH_TIMEOUT_DEFAULT))
1842
  );
1843
  }
1844
-
1845
- /*static*/ function fetch ($url, $params = array()) {
1846
  if (is_wp_error($url)) :
1847
  // Let's bounce.
1848
  return $url;
1849
  endif;
1850
-
1851
  $force_feed = true; // Default
1852
 
1853
- // Allow user to change default feed-fetch timeout with a global setting. Props Erigami Scholey-Fuller <http://www.piepalace.ca/blog/2010/11/feedwordpress-broke-my-heart.html> 'timeout' =>
 
1854
  $timeout = FeedWordPress::fetch_timeout();
1855
-
1856
  if (!is_array($params)) :
1857
  $force_feed = $params;
1858
  else : // Parameter array
@@ -1860,11 +2146,11 @@ class FeedWordPress {
1860
  'force_feed' => $force_feed,
1861
  'timeout' => $timeout
1862
  ), $params);
1863
-
1864
  extract($args);
1865
  endif;
1866
  $timeout = intval($timeout);
1867
-
1868
  $pie_class = apply_filters('feedwordpress_simplepie_class', 'FeedWordPie');
1869
  $cache_class = apply_filters('feedwordpress_cache_class', 'WP_Feed_Cache');
1870
  $file_class = apply_filters('feedwordpress_file_class', 'FeedWordPress_File');
@@ -1876,7 +2162,7 @@ class FeedWordPress {
1876
  $feed->set_feed_url($url);
1877
  $feed->set_cache_class($cache_class);
1878
  $feed->set_timeout($timeout);
1879
-
1880
  $feed->set_content_type_sniffer_class($sniffer_class);
1881
  $feed->set_file_class($file_class);
1882
  $feed->set_parser_class($parser_class);
@@ -1885,7 +2171,7 @@ class FeedWordPress {
1885
  $feed->set_cache_duration(FeedWordPress::cache_duration($params));
1886
  $feed->init();
1887
  $feed->handle_content_type();
1888
-
1889
  if ($feed->error()) :
1890
  $ret = new WP_Error('simplepie-error', $feed->error());
1891
  else :
@@ -1893,10 +2179,10 @@ class FeedWordPress {
1893
  endif;
1894
  return $ret;
1895
  } /* FeedWordPress::fetch () */
1896
-
1897
- function clear_cache () {
1898
  global $wpdb;
1899
-
1900
  // Just in case, clear out any old MagpieRSS cache records.
1901
  $magpies = $wpdb->query("
1902
  DELETE FROM {$wpdb->options}
@@ -1919,11 +2205,11 @@ class FeedWordPress {
1919
  return ($magpies + $simplepies);
1920
  } /* FeedWordPress::clear_cache () */
1921
 
1922
- function cache_duration ($params = array()) {
1923
  $params = wp_parse_args($params, array(
1924
  "cache" => true,
1925
  ));
1926
-
1927
  $duration = NULL;
1928
  if (!$params['cache']) :
1929
  $duration = 0;
@@ -1932,7 +2218,8 @@ class FeedWordPress {
1932
  endif;
1933
  return $duration;
1934
  }
1935
- function cache_lifetime ($duration) {
 
1936
  // Check for explicit setting of a lifetime duration
1937
  if (defined('FEEDWORDPRESS_CACHE_LIFETIME')) :
1938
  $duration = FEEDWORDPRESS_CACHE_LIFETIME;
@@ -1941,32 +2228,32 @@ class FeedWordPress {
1941
  elseif (defined('FEEDWORDPRESS_CACHE_AGE')) :
1942
  $duration = FEEDWORDPRESS_CACHE_AGE;
1943
  endif;
1944
-
1945
  // Fall back to WordPress default
1946
  return $duration;
1947
  } /* FeedWordPress::cache_lifetime () */
1948
 
1949
  # Utility functions for handling text settings
1950
- function negative ($f, $setting) {
1951
  $nego = array ('n', 'no', 'f', 'false');
1952
  return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $nego));
1953
- }
1954
 
1955
- function affirmative ($f, $setting) {
1956
  $affirmo = array ('y', 'yes', 't', 'true', 1);
1957
  return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $affirmo));
1958
- }
1959
 
1960
  # Internal debugging functions
1961
- function critical_bug ($varname, $var, $line, $file = NULL) {
1962
  global $wp_version;
1963
-
1964
  if (!is_null($file)) :
1965
  $location = "line # ${line} of ".basename($file);
1966
  else :
1967
  $location = "line # ${line}";
1968
  endif;
1969
-
1970
  print '<p><strong>Critical error:</strong> There may be a bug in FeedWordPress. Please <a href="'.FEEDWORDPRESS_AUTHOR_CONTACT.'">contact the author</a> and paste the following information into your e-mail:</p>';
1971
  print "\n<plaintext>";
1972
  print "Triggered at ${location}\n";
@@ -1976,31 +2263,24 @@ class FeedWordPress {
1976
  print "Error data: ";
1977
  print $varname.": "; var_dump($var); echo "\n";
1978
  die;
1979
- }
1980
-
1981
- function noncritical_bug ($varname, $var, $line, $file = NULL) {
1982
  if (FEEDWORDPRESS_DEBUG) : // halt only when we are doing debugging
1983
  FeedWordPress::critical_bug($varname, $var, $line, $file);
1984
  endif;
1985
- }
1986
-
1987
- function val ($v, $no_newlines = false) {
1988
- ob_start();
1989
- var_dump($v);
1990
- $out = ob_get_contents(); ob_end_clean();
1991
-
1992
- if ($no_newlines) :
1993
- $out = preg_replace('/\s+/', " ", $out);
1994
- endif;
1995
- return $out;
1996
  } /* FeedWordPress::val () */
1997
 
1998
- function diagnostic_on ($level) {
1999
  $show = get_option('feedwordpress_diagnostics_show', array());
2000
  return (in_array($level, $show));
2001
  } /* FeedWordPress::diagnostic_on () */
2002
 
2003
- function diagnostic ($level, $out, $persist = NULL, $since = NULL, $mostRecent = NULL) {
2004
  global $feedwordpress_admin_footer;
2005
 
2006
  $output = get_option('feedwordpress_diagnostics_output', array());
@@ -2013,7 +2293,7 @@ class FeedWordPress {
2013
  switch ($method) :
2014
  case 'echo' :
2015
  if (!FeedWordPress::update_requested()) :
2016
- echo "<div><pre><strong>Diag".str_repeat('====', $diagnostic_nesting-1).'|</strong> '.$out."</pre></div>";
2017
  endif;
2018
  break;
2019
  case 'echo_in_cronjob' :
@@ -2028,7 +2308,7 @@ class FeedWordPress {
2028
  error_log(FeedWordPress::log_prefix().' '.$out);
2029
  break;
2030
  case 'email' :
2031
-
2032
  if (is_null($persist)) :
2033
  $sect = 'occurrent';
2034
  $hook = (isset($dlog['mesg'][$sect]) ? count($dlog['mesg'][$sect]) : 0);
@@ -2038,56 +2318,58 @@ class FeedWordPress {
2038
  $hook = md5($level."\n".$persist);
2039
  $line = array("Since" => $since, "Message" => $out, "Most Recent" => $mostRecent);
2040
  endif;
2041
-
2042
  if (!isset($dlog['mesg'])) : $dlog['mesg'] = array(); endif;
2043
  if (!isset($dlog['mesg'][$sect])) : $dlog['mesg'][$sect] = array(); endif;
2044
-
2045
  $dlog['mesg'][$sect][$hook] = $line;
2046
  endswitch;
2047
  endforeach;
2048
  endif;
2049
-
2050
- update_option('feedwordpress_diagnostics_log', $dlog);
2051
  } /* FeedWordPress::diagnostic () */
2052
-
2053
- function email_diagnostics_override () {
2054
  return ($this->has_secret() and isset($_REQUEST['feedwordpress_email_diagnostics']) and !!$_REQUEST['feedwordpress_email_diagnostics']);
2055
- }
2056
- function has_emailed_diagnostics ($dlog) {
 
2057
  $ret = false;
2058
  if ($this->email_diagnostics_override()
2059
  or (isset($dlog['schedule']) and isset($dlog['schedule']['last']))) :
2060
  $ret = true;
2061
  endif;
2062
  return $ret;
2063
- }
2064
- function ready_to_email_diagnostics ($dlog) {
 
2065
  $ret = false;
2066
  if ($this->email_diagnostics_override()
2067
  or (time() > ($dlog['schedule']['last'] + $dlog['schedule']['freq']))) :
2068
  $ret = true;
2069
  endif;
2070
  return $ret;
2071
- }
2072
-
2073
- function email_diagnostic_log ($params = array()) {
2074
  $params = wp_parse_args($params, array(
2075
  "force" => false,
2076
  ));
2077
 
2078
  $dlog = get_option('feedwordpress_diagnostics_log', array());
2079
-
2080
  if ($this->has_emailed_diagnostics($dlog)) :
2081
  if ($this->ready_to_email_diagnostics($dlog)) :
2082
  // No news is good news; only send if
2083
  // there are some messages to send.
2084
  $body = NULL;
2085
  if (!isset($dlog['mesg'])) : $dlog['mesg'] = array(); endif;
2086
-
2087
  foreach ($dlog['mesg'] as $sect => $mesgs) :
2088
  if (count($mesgs) > 0) :
2089
  if (is_null($body)) : $body = ''; endif;
2090
-
2091
  $paradigm = reset($mesgs);
2092
  $body .= "<h2>".ucfirst($sect)." issues</h2>\n"
2093
  ."<table>\n"
@@ -2097,7 +2379,7 @@ class FeedWordPress {
2097
  endforeach;
2098
  $body .= "</tr></thead>\n"
2099
  ."<tbody>\n";
2100
-
2101
  foreach ($mesgs as $line) :
2102
  $body .= "<tr>\n";
2103
  foreach ($line as $col => $cell) :
@@ -2109,11 +2391,11 @@ class FeedWordPress {
2109
  endforeach;
2110
  $body .= "</tr>\n";
2111
  endforeach;
2112
-
2113
  $body .= "</tbody>\n</table>\n\n";
2114
  endif;
2115
  endforeach;
2116
-
2117
  $body = apply_filters('feedwordpress_diagnostic_email_body', $body, $dlog);
2118
  if (!is_null($body)) :
2119
  $home = feedwordpress_display_url(get_bloginfo('url'));
@@ -2148,12 +2430,12 @@ EOMAIL;
2148
  // e-mail address
2149
  if (preg_match('/^mailto:(.*)$/', $ded, $ref)) :
2150
  $recipients = array($ref[1]);
2151
-
2152
  // userid
2153
  elseif (preg_match('/^user:(.*)$/', $ded, $ref)) :
2154
  $userdata = get_userdata((int) $ref[1]);
2155
  $recipients = array($userdata->user_email);
2156
-
2157
  // admins
2158
  else :
2159
  $recipients = FeedWordPressDiagnostic::admin_emails();
@@ -2176,17 +2458,17 @@ EOMAIL;
2176
  endif;
2177
  $head = apply_filters('feedwordpress_diagnostic_email_headers', $head);
2178
 
2179
- foreach ($recipients as $email) :
2180
  add_filter('wp_mail_content_type', array('FeedWordPress', 'allow_html_mail'));
2181
  wp_mail($email, $subj, $body, $head);
2182
  remove_filter('wp_mail_content_type', array('FeedWordPress', 'allow_html_mail'));
2183
  endforeach;
2184
  endif;
2185
-
2186
  // Clear the logs
2187
  $dlog['mesg']['persistent'] = array();
2188
  $dlog['mesg']['occurrent'] = array();
2189
-
2190
  // Set schedule for next update
2191
  $dlog['schedule']['last'] = time();
2192
  endif;
@@ -2196,22 +2478,22 @@ EOMAIL;
2196
  'last' => time(),
2197
  );
2198
  endif;
2199
-
2200
  update_option('feedwordpress_diagnostics_log', $dlog);
2201
  } /* FeedWordPress::email_diagnostic_log () */
2202
-
2203
- function allow_html_mail () {
2204
  return 'text/html';
2205
  } /* FeedWordPress::allow_html_mail () */
2206
 
2207
- function admin_footer () {
2208
  global $feedwordpress_admin_footer;
2209
  foreach ($feedwordpress_admin_footer as $line) :
2210
  echo '<div><pre>'.$line.'</pre></div>';
2211
  endforeach;
2212
  } /* FeedWordPress::admin_footer () */
2213
-
2214
- function log_prefix ($date = false) {
2215
  $home = get_bloginfo('url');
2216
  $prefix = '['.feedwordpress_display_url($home).'] [feedwordpress] ';
2217
  if ($date) :
@@ -2219,8 +2501,8 @@ EOMAIL;
2219
  endif;
2220
  return $prefix;
2221
  } /* FeedWordPress::log_prefix () */
2222
-
2223
- function menu_cap ($sub = false) {
2224
  if ($sub) :
2225
  $cap = apply_filters('feedwordpress_menu_settings_capacity', 'manage_options');
2226
  else :
@@ -2228,26 +2510,29 @@ EOMAIL;
2228
  endif;
2229
  return $cap;
2230
  } /* FeedWordPress::menu_cap () */
2231
-
2232
- function path ($filename = '') {
2233
  global $fwp_path;
2234
-
2235
  $path = $fwp_path;
2236
  if (strlen($filename) > 0) :
2237
  $path .= '/'.$filename;
2238
  endif;
2239
  return $path;
2240
- }
2241
-
2242
  // These are superceded by MyPHP::param/post/get/request, but kept
2243
  // here for backward compatibility.
2244
- function param ($key, $type = 'REQUEST', $default = NULL) {
 
2245
  return MyPHP::param($key, $default, $type);
2246
- }
2247
- function post ($key, $default = NULL) {
 
2248
  return MyPHP::post($key, $default);
2249
- }
2250
- } // class FeedWordPress
 
2251
 
2252
  $feedwordpress_admin_footer = array();
2253
 
3
  Plugin Name: FeedWordPress
4
  Plugin URI: http://feedwordpress.radgeek.com/
5
  Description: simple and flexible Atom/RSS syndication for WordPress
6
+ Version: 2014.0805
7
  Author: Charles Johnson
8
  Author URI: http://radgeek.com/
9
  License: GPL
11
 
12
  /**
13
  * @package FeedWordPress
14
+ * @version 2014.0805
15
  */
16
 
17
  # This uses code derived from:
27
  # USAGE: once FeedWordPress is installed, you manage just about everything from
28
  # the WordPress Dashboard, under the Syndication menu. To keep fresh content
29
  # coming in as it becomes available, you'll have to either check for updates
30
+ # manually, or set up one of the automatically-scheduled update methods. See
31
  # <http://feedwordpress.radgeek.com/wiki/quick-start/> for some details.
32
 
33
  # -- Don't change these unless you know what you're doing...
34
 
35
+ define ('FEEDWORDPRESS_VERSION', '2014.0805');
36
  define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
37
 
38
  if (!defined('FEEDWORDPRESS_BLEG')) :
39
  define ('FEEDWORDPRESS_BLEG', true);
40
  endif;
41
+ define('FEEDWORDPRESS_BLEG_BTC', '1FN3Q4VSR4jV7unRjaknVQVe5ky88ktPHS');
42
 
43
  // Defaults
44
  define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
71
  // Help us to pick out errors, if any.
72
  ini_set('error_reporting', E_ALL & ~E_NOTICE);
73
  ini_set('display_errors', true);
74
+
75
  // When testing we don't want cache issues to interfere. But this is
76
+ // a VERY BAD SETTING for a production server. Webmasters will eat your
77
  // face for breakfast if you use it, and the baby Jesus will cry. So
78
  // make sure FEEDWORDPRESS_DEBUG is FALSE for any site that will be
79
  // used for more than testing purposes!
102
  require_once (ABSPATH . WPINC . '/registration.php'); // for wp_insert_user
103
  endif;
104
 
105
+ $dir = dirname(__FILE__);
106
  require_once("${dir}/externals/myphp/myphp.class.php");
107
  require_once("${dir}/admin-ui.php");
108
  require_once("${dir}/feedwordpresssyndicationpage.class.php");
109
+ require_once("${dir}/compatability.php"); // Legacy API
110
  require_once("${dir}/syndicatedpost.class.php");
111
  require_once("${dir}/syndicatedlink.class.php");
112
  require_once("${dir}/feedwordpresshtml.class.php");
142
  $fwp_path = 'feedwordpress';
143
  endif;
144
 
145
+ $feedwordpress = new FeedWordPress;
146
+ if (!$feedwordpress->needs_upgrade()) : // only work if the conditions are safe!
147
 
148
  # Syndicated items are generally received in output-ready (X)HTML and
149
  # should not be folded, crumpled, mutilated, or spindled by WordPress
160
 
161
  add_filter('the_content', 'feedwordpress_preserve_syndicated_content', -10000);
162
  add_filter('the_content', 'feedwordpress_restore_syndicated_content', 10000);
163
+
164
  add_action('atom_entry', 'feedwordpress_item_feed_data');
165
+
166
  # Filter in original permalinks if the user wants that
167
  add_filter('post_link', 'syndication_permalink', /*priority=*/ 1, /*arguments=*/ 3);
168
  add_filter('post_type_link', 'syndication_permalink', /*priority=*/ 1, /*arguments=*/ 4);
169
+
170
  # When foreign URLs are used for permalinks in feeds or display
171
  # contexts, they need to be escaped properly.
172
  add_filter('the_permalink', 'syndication_permalink_escaped');
173
  add_filter('the_permalink_rss', 'syndication_permalink_escaped');
174
+
175
  add_filter('post_comments_feed_link', 'syndication_comments_feed_link');
176
 
177
  # WTF? By default, wp_insert_link runs incoming link_url and link_rss
180
  # happens to fuck up any URI with a & to separate GET parameters.
181
  remove_filter('pre_link_rss', 'wp_filter_kses');
182
  remove_filter('pre_link_url', 'wp_filter_kses');
183
+
184
  # Admin menu
185
+ add_action('admin_init', array($feedwordpress, 'admin_init'));
186
  add_action('admin_menu', 'fwp_add_pages');
187
  add_action('admin_notices', 'fwp_check_debug');
188
 
189
  add_action('admin_menu', 'feedwordpress_add_post_edit_controls');
190
  add_action('save_post', 'feedwordpress_save_post_edit_controls');
191
 
192
+ add_action('admin_footer', array($feedwordpress, 'admin_footer'));
193
+
194
  # Inbound XML-RPC update methods
195
  $feedwordpressRPC = new FeedWordPressRPC;
196
 
208
 
209
  add_action('wp_footer', 'debug_out_feedwordpress_footer', -100);
210
  add_action('admin_footer', 'debug_out_feedwordpress_footer', -100);
 
 
211
 
212
  # Cron-less auto-update. Hooray!
213
  $autoUpdateHook = $feedwordpress->automatic_update_hook();
214
  if (!is_null($autoUpdateHook)) :
215
  add_action($autoUpdateHook, array($feedwordpress, 'auto_update'));
216
  endif;
217
+
218
  add_action('init', array($feedwordpress, 'init'));
219
  add_action('shutdown', array($feedwordpress, 'email_diagnostic_log'));
220
+ add_action('shutdown', array($feedwordpress, 'feedwordpress_cleanup'));
221
  add_action('wp_dashboard_setup', array($feedwordpress, 'dashboard_setup'));
222
 
223
  # Default sanitizers
224
  add_filter('syndicated_item_content', array('SyndicatedPost', 'resolve_relative_uris'), 0, 2);
225
  add_filter('syndicated_item_content', array('SyndicatedPost', 'sanitize_content'), 0, 2);
226
 
227
+ add_action('plugins_loaded', array($feedwordpress, 'admin_api'));
228
+ add_action('all_admin_notices', array($feedwordpress, 'all_admin_notices'));
229
+
230
  else :
231
  # Hook in the menus, which will just point to the upgrade interface
232
  add_action('admin_menu', 'fwp_add_pages');
241
  $wpError = $error['object'];
242
  $url = $link->uri();
243
 
244
+ // check for effects of an effective-url filter
245
+ $effectiveUrl = $link->uri(array('fetch' => true));
246
+ if ($url != $effectiveUrl) : $url .= ' | ' . $effectiveUrl; endif;
247
+
248
  $mesgs = $wpError->get_error_messages();
249
  foreach ($mesgs as $mesg) :
250
  $mesg = esc_html($mesg);
252
  'updated_feeds:errors',
253
  "Feed Error: [${url}] update returned error: $mesg"
254
  );
255
+
256
  $hours = get_option('feedwordpress_diagnostics_persistent_errors_hours', 2);
257
  $span = ($error['ts'] - $error['since']);
258
 
318
  * displaying a post.
319
  *
320
  * @param int $id The post to check for syndicated status. Defaults to the current post in a Loop context.
321
+ * @return bool TRUE if the post's meta-data indicates it was syndicated; FALSE otherwise
322
+ */
323
  function is_syndicated ($id = NULL) {
324
  $p = new FeedWordPressLocalPost($id);
325
  return $p->is_syndicated();
327
 
328
  function feedwordpress_display_url ($url, $before = 60, $after = 0) {
329
  $bits = parse_url($url);
330
+
331
  // Strip out crufty subdomains
332
  if (isset($bits['host'])) :
333
  $bits['host'] = preg_replace('/^www[0-9]*\./i', '', $bits['host']);
334
  endif;
335
+
336
  // Reassemble bit-by-bit with minimum of crufty elements
337
  $url = (isset($bits['user'])?$bits['user'].'@':'')
338
  .(isset($bits['host'])?$bits['host']:'')
341
  .(isset($bits['query'])?'?'.$bits['query']:'');
342
 
343
  if (strlen($url) > ($before+$after)) :
344
+ $url = substr($url, 0, $before).'.'.substr($url, 0 - $after, $after);
345
  endif;
346
 
347
  return $url;
440
  */
441
  function get_local_permalink ($id = NULL) {
442
  global $feedwordpress_the_original_permalink;
443
+
444
  // get permalink, and thus activate filter and force global to be filled
445
  // with original URL.
446
  $url = get_permalink($id);
483
 
484
  function feedwordpress_restore_syndicated_content ($text) {
485
  global $feedwordpress_the_syndicated_content;
486
+
487
  if ( !is_null($feedwordpress_the_syndicated_content) ) :
488
  $text = $feedwordpress_the_syndicated_content;
489
  endif;
538
  function syndication_permalink ($permalink = '', $post = null, $leavename = false, $sample = false) {
539
  global $id;
540
  global $feedwordpress_the_original_permalink;
541
+
542
  // Save the local permalink in case we need to retrieve it later.
543
  $feedwordpress_the_original_permalink = $permalink;
544
 
588
  $permalink = esc_html($permalink);
589
  endif;
590
  return $permalink;
591
+ } /* function syndication_permalink_escaped() */
592
 
593
  /**
594
  * syndication_comments_feed_link: Escape XML special characters in comments
595
+ * feed links
596
  *
597
  * @param string $link
598
  * @return string
609
  // that value here.
610
  $source = get_syndication_feed_object();
611
  $replacement = NULL;
612
+
613
  if ($source->setting('munge comments feed links', 'munge_comments_feed_links', 'yes') != 'no') :
614
  $commentFeeds = get_post_custom_values('wfw:commentRSS');
615
  if (
618
  and (strlen($commentFeeds[0]) > 0)
619
  ) :
620
  $replacement = $commentFeeds[0];
621
+
622
  // This is a foreign link; WordPress can't vouch for its not
623
  // having any entities that need to be &-escaped. So we'll do it
624
  // here.
625
  $replacement = esc_html($replacement);
626
  endif;
627
  endif;
628
+
629
  if (is_null($replacement)) :
630
  // Q: How can we get the proper feed format, since the
631
  // format is, stupidly, not passed to the filter?
649
  // comments feed link is never munged by FWP.
650
  endif;
651
  endif;
652
+
653
  if (!is_null($replacement)) : $link = $replacement; endif;
654
  endif;
655
  return $link;
661
 
662
  function fwp_add_pages () {
663
  global $feedwordpress;
664
+
665
  $menu_cap = FeedWordPress::menu_cap();
666
  $settings_cap = FeedWordPress::menu_cap(/*sub=*/ true);
667
  $syndicationMenu = FeedWordPress::path('syndication.php');
668
+
669
  add_menu_page(
670
  'Syndicated Sites', 'Syndication',
671
  $menu_cap,
715
  $syndicationMenu, 'FeedWordPress Diagnostics', 'Diagnostics',
716
  $settings_cap, FeedWordPress::path('diagnostics-page.php')
717
  );
718
+
719
  add_filter('page_row_actions', array($feedwordpress, 'row_actions'), 10, 2);
720
  add_filter('post_row_actions', array($feedwordpress, 'row_actions'), 10, 2);
721
  } /* function fwp_add_pages () */
786
  do_action('xmlrpc_publish_post', $post_id);
787
  if ( defined('APP_REQUEST') )
788
  do_action('app_publish_post', $post_id);
789
+
790
  if ( defined('WP_IMPORTING') )
791
  return;
792
 
804
  global $inspectPostMeta;
805
 
806
  // Put in Manual Editing checkbox
807
+ add_action('add_meta_boxes', 'feedwordpress_post_add_meta_boxes', 10, 2);
808
 
809
  add_filter('user_can_richedit', array($feedwordpress, 'user_can_richedit'), 1000, 1);
810
+
811
  if (FeedWordPress::diagnostic_on('syndicated_posts:static_meta_data')) :
812
  $inspectPostMeta = new InspectPostMeta;
813
  endif;
814
+ } // function feedwordpress_add_post_edit_controls ()
815
+
816
+ function feedwordpress_post_add_meta_boxes ($post_type, $post) {
817
+ add_meta_box(
818
+ 'feedwordpress-post-controls',
819
+ __('Syndication'),
820
+ 'feedwordpress_post_edit_controls',
821
+ $post_type,
822
+ 'side',
823
+ 'high'
824
+ );
825
+ }
826
+
827
  function feedwordpress_post_edit_controls () {
828
  global $post;
829
+
830
  $frozen_values = get_post_custom_values('_syndication_freeze_updates', $post->ID);
831
  $frozen_post = (count($frozen_values) > 0 and 'yes' == $frozen_values[0]);
832
 
835
  <p>This is a syndicated post, which originally appeared at
836
  <cite><?php print esc_html(get_syndication_source(NULL, $post->ID)); ?></cite>.
837
  <a href="<?php print esc_html(get_syndication_permalink($post->ID)); ?>">View original post</a>.</p>
838
+
839
+ <?php do_action('feedwordpress_post_edit_controls_pre', $post); ?>
840
 
841
  <p><input type="hidden" name="feedwordpress_noncename" id="feedwordpress_noncename" value="<?php print wp_create_nonce(plugin_basename(__FILE__)); ?>" />
842
  <label><input type="checkbox" name="freeze_updates" value="yes" <?php if ($frozen_post) : ?>checked="checked"<?php endif; ?> /> <strong>Manual editing.</strong>
843
  If set, FeedWordPress will not overwrite the changes you make manually
844
  to this post, if the syndicated content is updated on the
845
  feed.</label></p>
846
+
847
+ <?php do_action('feedwordpress_post_edit_controls', $post); ?>
848
+
849
  <?php
850
  else :
851
  ?>
852
  <p>This post was created locally at this website.</p>
853
  <?php
854
  endif;
855
+ } /* function feedwordpress_post_edit_controls () */
856
 
857
  function feedwordpress_save_post_edit_controls ( $post_id ) {
858
  global $post;
 
859
  if (!isset($_POST['feedwordpress_noncename']) or !wp_verify_nonce($_POST['feedwordpress_noncename'], plugin_basename(__FILE__))) :
860
  return $post_id;
861
  endif;
862
+
863
  // Verify if this is an auto save routine. If it is our form has
864
  // not been submitted, so we don't want to do anything.
865
  if ( defined('DOING_AUTOSAVE') and DOING_AUTOSAVE ) :
866
  return $post_id;
867
  endif;
868
+
869
+ // The data in $_POST is for applying only to the post actually
870
+ // in the edit window, i.e. $post
871
+ if ($post_id != $post->ID) :
872
+ return $post_id;
873
+ endif;
874
 
875
  // Check permissions
876
+ $cap[0] = 'edit_post';
877
+ $cap[1] = 'edit_' . $_POST['post_type'];
878
+ if (
879
+ !current_user_can( $cap[0], $post_id )
880
+ and !current_user_can( $cap[1], $post_id )
881
+ ) :
882
  return $post_id;
883
  endif;
884
 
885
  // OK, we're golden. Now let's save some data.
886
  if (isset($_POST['freeze_updates'])) :
887
+
888
  update_post_meta($post_id, '_syndication_freeze_updates', $_POST['freeze_updates']);
889
  $ret = $_POST['freeze_updates'];
890
+
891
+ // If you make manual edits through the WordPress editing
892
+ // UI then they should be run through normal WP formatting
893
+ // filters.
894
+ update_post_meta($post_id, '_feedwordpress_formatting_filters', 'yes');
895
+
896
  else :
897
  delete_post_meta($post_id, '_syndication_freeze_updates');
898
  $ret = NULL;
899
  endif;
900
+
901
+ do_action('feedwordpress_save_edit_controls', $post_id);
902
+
903
  return $ret;
904
  } // function feedwordpress_save_edit_controls
905
 
944
  var $feeds = NULL;
945
  var $feedurls = NULL;
946
  var $httpauth = NULL;
947
+
948
+ /**
949
+ * FeedWordPress::__construct (): Construct FeedWordPress singleton object
950
+ * and retrieves a list of feeds for later reference.
951
+ */
952
+ public function __construct () {
953
  $this->feeds = array ();
954
  $this->feedurls = array();
955
  $links = FeedWordPress::syndicated_links();
956
  if ($links): foreach ($links as $link):
957
  $id = intval($link->link_id);
958
  $url = $link->link_rss;
959
+
960
  // Store for later reference.
961
  $this->feeds[$id] = $id;
962
  if (strlen($url) > 0) :
964
  endif;
965
  endforeach; endif;
966
 
967
+ add_filter('feedwordpress_update_complete', array($this, 'process_retirements'), 1000, 1);
968
+
969
  $this->httpauth = new FeedWordPressHTTPAuthenticator;
970
+ } /* FeedWordPress::__construct () */
971
 
972
+ /**
973
+ * FeedWordPress::subscribed (): Check whether a feed is currently in the
974
+ * subscription list for FeedWordPress.
975
+ *
976
+ * @param mixed $id Numeric ID of a WordPress link object or URL of a feed
977
+ * @return bool TRUE if currently subscribed; FALSE otherwise.
978
+ */
979
+ public function subscribed ($id) {
980
  return (isset($this->feedurls[$id]) or isset($this->feeds[$id]));
981
  } /* FeedWordPress::subscribed () */
982
+
983
+ /**
984
+ * FeedWordPress::subscription (): Get the SyndicatedLink object for a
985
+ * given URL or numeric ID, if we have either an active subscription to
986
+ * it; or a de-activated subscription.
987
+ *
988
+ * @param mixed $which Numeric ID for a WordPress link object or string URL for a feed
989
+ * @return mixed SyndicatedLink object if subscription is found; NULL if not
990
+ */
991
+ public function subscription ($which) {
992
  $sub = NULL;
993
+
994
  if (is_string($which) and isset($this->feedurls[$which])) :
995
  $which = $this->feedurls[$which];
996
  endif;
997
+
998
  if (isset($this->feeds[$which])) :
999
  $sub = $this->feeds[$which];
1000
  endif;
1012
  $this->feeds[$which] = $link;
1013
  $sub = $link;
1014
  endif;
1015
+
1016
  return $sub;
1017
  } /* FeedWordPress::subscription () */
1018
+
1019
  # function update (): polls for updates on one or more Contributor feeds
1020
  #
1021
  # Arguments:
1061
  # (between 30 minutes and 2 hours).
1062
  #
1063
  # * New posts from the polled feed are added to the WordPress store.
1064
+ #
1065
  # * Updates to existing posts since the last poll are mirrored in the
1066
  # WordPress store.
1067
  #
1068
+ public function update ($uri = null, $crash_ts = null) {
1069
  global $wpdb;
1070
 
1071
  if (FeedWordPress::needs_upgrade()) : // Will make duplicate posts if we don't hold off
1072
  return NULL;
1073
  endif;
1074
+
1075
  if (!is_null($uri) and $uri != '*') :
1076
  $uri = trim($uri);
1077
  else : // Update all
1090
  if (is_null($crash_ts)) :
1091
  $crash_ts = $this->crash_ts();
1092
  endif;
1093
+
1094
  // Randomize order for load balancing purposes
1095
  $feed_set = array_keys($this->feeds);
1096
  shuffle($feed_set);
1107
  ), $uri);
1108
 
1109
  $feed_set = apply_filters('feedwordpress_update_feeds', $feed_set, $uri);
1110
+
1111
+
1112
  // Loop through and check for new posts
1113
  $delta = NULL; $remaining = $max_polls;
1114
  foreach ($feed_set as $feed_id) :
1119
  if (
1120
  // Over time limit?
1121
  (!is_null($crash_ts) and (time() > $crash_ts))
1122
+
1123
  // Over feed count?
1124
+ or ($remaining == 0)
1125
  ) :
1126
  break;
1127
  endif;
1128
+
1129
  $pinged_that = (is_null($uri) or ($uri=='*') or in_array($uri, array($feed->uri(), $feed->homepage())));
1130
 
1131
  if (!is_null($uri)) : // A site-specific ping always updates
1134
  $timely = $feed->stale();
1135
  endif;
1136
 
1137
+ // If at least one feed was hit for updating...
1138
+ if ($pinged_that and is_null($delta)) :
1139
+ // ... don't return error condition
1140
+ $delta = array('new' => 0, 'updated' => 0, 'stored' => 0);
1141
  endif;
1142
 
1143
  if ($pinged_that and $timely) :
1149
  do_action('feedwordpress_check_feed_complete', $feed->settings, $added, time() - $start_ts);
1150
 
1151
  if (is_array($added)) : // Success
1152
+ foreach ($added as $key => $count) :
1153
+ $delta[$key] += $added[$key];
1154
+ endforeach;
1155
  endif;
1156
  endif;
1157
  endforeach;
1158
 
1159
  do_action('feedwordpress_update_complete', $delta);
 
1160
  return $delta;
1161
+ } /* FeedWordPress::update () */
1162
 
1163
+ public function crash_ts ($default = NULL) {
1164
  $crash_dt = (int) get_option('feedwordpress_update_time_limit', 0);
1165
  if ($crash_dt > 0) :
1166
  $crash_ts = time() + $crash_dt;
1168
  $crash_ts = $default;
1169
  endif;
1170
  return $crash_ts;
1171
+ } /* FeedWordPress::crash_ts () */
1172
+
1173
+ public function secret_key () {
1174
  $secret = get_option('feedwordpress_secret_key', false);
1175
  if (!$secret) : // Generate random key.
1176
  $secret = substr(md5(uniqid(microtime())), 0, 6);
1177
  update_option('feedwordpress_secret_key', $secret);
1178
  endif;
1179
  return $secret;
1180
+ } /* FeedWordPress::secret_key () */
1181
+
1182
+ public function has_secret () {
1183
+ return (MyPHP::request('feedwordpress_key')==$this->secret_key());
1184
+ } /* FeedWordPress::has_secret () */
1185
 
 
 
 
 
 
 
 
 
 
1186
  var $update_hooked = NULL;
1187
+ public function automatic_update_hook ($params = array()) {
1188
  $params = wp_parse_args($params, array( // Defaults
1189
  'setting only' => false,
1190
  ));
1195
  if (
1196
  !$params['setting only']
1197
  and $this->has_secret()
1198
+ and MyPHP::request('automatic_update')
1199
  ) :
1200
+ $hook = MyPHP::request('automatic_update');
1201
  $method = 'URL parameter';
1202
  endif;
1203
+
1204
  $exact = $hook; // Before munging
1205
+
1206
  if (!!$hook) :
1207
  if ($hook != 'init') : // Constrain values.
1208
  $hook = 'shutdown';
1209
  endif;
1210
  endif;
1211
+
1212
  if ($hook) :
1213
  $this->update_hooked = "Initiating an AUTOMATIC CHECK FOR UPDATES ON PAGE LOAD ".$hook." due to ".$method." = ".trim($this->val($exact));
1214
  endif;
1215
+
1216
+ return $hook;
1217
+ } /* FeedWordPress::automatic_update_hook () */
1218
+
1219
+ public function last_update_all () {
1220
  $last = get_option('feedwordpress_last_update_all');
1221
+ if ($this->has_secret() and MyPHP::request('automatic_update')) :
1222
  $last = 1; // A long, long time ago.
1223
+ elseif ($this->has_secret() and MyPHP::request('last_update_all')) :
1224
+ $last = MyPHP::request('last_update_all');
1225
  endif;
1226
  return $last;
1227
+ } /* FeedWordPress::last_update_all () */
1228
+
1229
+ public function force_update_all () {
1230
+ return ($this->has_secret() and MyPHP::request('force_update_feeds'));
1231
+ } /* FeedWordPress::force_update_all () */
1232
+
1233
+ public function stale () {
1234
  if (!is_null($this->automatic_update_hook())) :
1235
  // Do our best to avoid possible simultaneous
1236
  // updates by getting up-to-the-minute settings.
1237
+
1238
  $last = $this->last_update_all();
1239
+
1240
  // If we haven't updated all yet, give it a time window
1241
  if (false === $last) :
1242
  $ret = false;
1243
  update_option('feedwordpress_last_update_all', time());
1244
+
1245
  // Otherwise, check against freshness interval
1246
  elseif (is_numeric($last)) : // Expect a timestamp
1247
  $freshness = get_option('feedwordpress_freshness');
1249
  $freshness = FEEDWORDPRESS_FRESHNESS_INTERVAL;
1250
  endif;
1251
  $ret = ( (time() - $last) > $freshness );
1252
+
1253
  // This should never happen.
1254
  else :
1255
  FeedWordPress::critical_bug('FeedWordPress::stale::last', $last, __LINE__, __FILE__);
1259
  $ret = false;
1260
  endif;
1261
  return $ret;
1262
+ } /* FeedWordPress::stale() */
1263
 
1264
  static function admin_init () {
1265
  // WordPress 3.5+ compat: the WP devs are in the midst of removing Links from the WordPress core. Eventually we'll have to deal
1268
  if (!intval(get_option('link_manager_enabled', false))) :
1269
  update_option('link_manager_enabled', true);
1270
  endif;
1271
+
1272
+ if (defined('FEEDWORDPRESS_PREPARE_TO_ZAP') and FEEDWORDPRESS_PREPARE_TO_ZAP) :
1273
+ $post_id = FEEDWORDPRESS_PREPARE_TO_ZAP;
1274
+ $sendback = wp_get_referer();
1275
+ if (
1276
+ ! $sendback
1277
+ or strpos( $sendback, 'post.php' ) !== false
1278
+ or strpos( $sendback, 'post-new.php' ) !== false
1279
+ ) :
1280
+ if ( 'attachment' == $post_type ) :
1281
+ $sendback = admin_url( 'upload.php' );
1282
+ else :
1283
+ $sendback = admin_url( 'edit.php' );
1284
+ $sendback .= ( ! empty( $post_type ) ) ? '?post_type=' . $post_type : '';
1285
+ endif;
1286
+ else :
1287
+ $sendback = remove_query_arg( array('trashed', 'untrashed', 'deleted', 'zapped', 'unzapped', 'ids'), $sendback );
1288
+ endif;
1289
+
1290
+ // Make sure we have a post corresponding to this ID.
1291
+ $post = $post_type = $post_type_object = null;
1292
+ if ( $post_id ) :
1293
+ $post = get_post( $post_id );
1294
+ endif;
1295
+
1296
+ if ( $post ) :
1297
+ $post_type = $post->post_type;
1298
+ endif;
1299
+ $p = get_post($post_id);
1300
+
1301
+ if ( ! $post ) :
1302
+ wp_die( __( 'The item you are trying to zap no longer exists.' ) );
1303
+ endif;
1304
+
1305
+ if ( ! current_user_can( 'delete_post', $post_id ) ) :
1306
+ wp_die( __( 'You are not allowed to zap this item.' ) );
1307
+ endif;
1308
+
1309
+ if ( $user_id = wp_check_post_lock( $post_id ) ) :
1310
+ $user = get_userdata( $user_id );
1311
+ wp_die( sprintf( __( 'You cannot retire this item. %s is currently editing.' ), $user->display_name ) );
1312
+ endif;
1313
+
1314
+ if (MyPHP::request('fwp_post_delete')=='zap') :
1315
+ FeedWordPress::diagnostic('syndicated_posts', 'Zapping existing post # '.$p->ID.' "'.$p->post_title.'" due to user request.');
1316
+
1317
+ $old_status = $post->post_status;
1318
+
1319
+ set_post_field('post_status', 'fwpzapped', $post_id);
1320
+ wp_transition_post_status('fwpzapped', $old_status, $post);
1321
+
1322
+ # Set up the post to have its content blanked on
1323
+ # next update if you do not undo the zapping.
1324
+ add_post_meta($post_id, '_feedwordpress_zapped_blank_me', 1, /*unique=*/ true);
1325
+ add_post_meta($post_id, '_feedwordpress_zapped_blank_old_status', $old_status, /*unique=*/ true);
1326
+
1327
+ wp_redirect( add_query_arg( array('zapped' => 1, 'ids' => $post_id), $sendback ) );
1328
+
1329
+ else :
1330
+ $old_status = get_post_meta($post_id, '_feedwordpress_zapped_blank_old_status', /*single=*/ true);
1331
+
1332
+ set_post_field('post_status', $old_status, $post_id);
1333
+ wp_transition_post_status($old_status, 'fwpzapped', $post);
1334
+
1335
+ # O.K., make sure this post does not get blanked
1336
+ delete_post_meta($post_id, '_feedwordpress_zapped_blank_me');
1337
+ delete_post_meta($post_id, '_feedwordpress_zapped_blank_old_status');
1338
+
1339
+ wp_redirect( add_query_arg( array('unzapped' => 1, 'ids' => $post_id), $sendback ) );
1340
+
1341
+ endif;
1342
+
1343
+ // Intercept, don't pass on.
1344
+ exit;
1345
+ endif;
1346
  } /* FeedWordPress::admin_init() */
1347
 
1348
+ public function admin_api () {
1349
  // This sucks, but WordPress doesn't give us any other way to
1350
  // easily invoke a permanent-delete from a plugged in post
1351
  // actions link. So we create a magic parameter, and when this
1352
  // magic parameter is activated, the WordPress trashcan is
1353
  // temporarily de-activated.
1354
+
1355
  if (MyPHP::request('fwp_post_delete')=='nuke') :
1356
  // Get post ID #
1357
  $post_id = MyPHP::request('post');
1358
  if (!$post_id) :
1359
  $post_id = MyPHP::request('post_ID');
1360
  endif;
1361
+
1362
  // Make sure we've got the right nonce and all that.
1363
  check_admin_referer('delete-post_' . $post_id);
1364
+
1365
  // If so, disable the trashcan.
1366
  define('EMPTY_TRASH_DAYS', 0);
1367
+
1368
+ elseif (MyPHP::request('fwp_post_delete')=='zap' OR MyPHP::request('fwp_post_delete') == 'unzap') :
1369
+ // Get post ID #
1370
+ $post_id = MyPHP::request('post');
1371
+ if (!$post_id) :
1372
+ $post_id = MyPHP::request('post_ID');
1373
+ endif;
1374
+
1375
+ // Make sure we've got the right nonce and all that
1376
+ check_admin_referer('delete-post_' . $post_id);
1377
+
1378
+ // If so, get ready to intercept the call a little
1379
+ // further down the line.
1380
+
1381
+ define('FEEDWORDPRESS_PREPARE_TO_ZAP', $post_id);
1382
+
1383
+ endif;
1384
+
1385
+ } /* FeedWordPress::admin_api () */
1386
+
1387
+ public function all_admin_notices () {
1388
+ if (MyPHP::request('zapped')) :
1389
+ $n = intval(MyPHP::request('zapped'));
1390
+ ?>
1391
+ <div id="message" class="updated"><p><?php print $n; ?> syndicated item<?php print ($n!=1?'s':''); ?> zapped. <strong>These items will not be re-syndicated.</strong> If this was a mistake, you must <strong>immediately</strong> Un-Zap them in the Zapped items section to avoid losing the data.</p></div>
1392
+ <?php
1393
+ endif;
1394
+
1395
+ if (MyPHP::request('unzapped')) :
1396
+ $n = intval(MyPHP::request('unzapped'));
1397
+ ?>
1398
+ <div id="message" class="updated"><p><?php print $n; ?> syndicated item<?php print ($n!=1?'s':'') ?> un-zapped and restored to normal.</p></div>
1399
+ <?php
1400
  endif;
1401
+ } /* FeedWordPress::all_admin_notices () */
1402
+
1403
+ public function process_retirements ($delta) {
1404
+ update_option('feedwordpress_process_zaps', 1);
1405
 
1406
+ return $delta;
1407
  }
1408
+
1409
+ public function feedwordpress_cleanup () {
1410
+ if (get_option('feedwordpress_process_zaps', null)) :
1411
+ $q = new WP_Query(array(
1412
+ 'fields' => '_synfrom',
1413
+ 'post_status' => 'fwpzapped',
1414
+ 'ignore_sticky_posts' => true,
1415
+ 'meta_key' => '_feedwordpress_zapped_blank_me',
1416
+ 'meta_value' => 1,
1417
+ ));
1418
+
1419
+ if ($q->have_posts()) :
1420
+ foreach ($q->posts as $p) :
1421
 
1422
+ $post_id = $p->ID;
1423
+ $revisions = wp_get_post_revisions($post_id, array("check_enabled" => false));
1424
+
1425
+ # Now nuke the content of the post & its revisions
1426
+ set_post_field('post_content', '', $post_id);
1427
+ set_post_field('post_excerpt', '', $post_id);
1428
+
1429
+ foreach ($revisions as $rev) :
1430
+ set_post_field('post_content', '', $rev->ID);
1431
+ set_post_field('post_excerpt', '', $rev->ID);
1432
+ endforeach;
1433
+
1434
+ # Un-tag it for blanking.
1435
+ delete_post_meta($p->ID, '_feedwordpress_zapped_blank_me');
1436
+
1437
+ # Don't remove old_status indicator. A later
1438
+ # update from the feed may cause us to once
1439
+ # again have some content so we can un-zap.
1440
+
1441
+ endforeach;
1442
+ endif;
1443
+
1444
+ $q = new WP_Query(array(
1445
+ 'fields' => '_synfrom',
1446
+ 'post_status' => 'fwpzapped',
1447
+ 'ignore_sticky_posts' => true,
1448
+ 'meta_key' => '_feedwordpress_zapped_blank_me',
1449
+ 'meta_value' => 2,
1450
+ ));
1451
+
1452
+ if ($q->have_posts()) :
1453
+ foreach ($q->posts as $p) :
1454
+ update_post_meta($p->ID, '_feedwordpress_zapped_blank_me', 1);
1455
+ endforeach;
1456
+ endif;
1457
+
1458
+ update_option('feedwordpress_process_zaps', 0);
1459
+ endif;
1460
+ } /* FeedWordPress::feedwordpress_cleanup () */
1461
+
1462
+ public function init () {
1463
  global $fwp_path;
1464
+
1465
  // If this is a FeedWordPress admin page, queue up scripts for AJAX
1466
  // functions that FWP uses. If it is a display page or a non-FWP admin
1467
  // page, don't.
1469
  if (FeedWordPressSettingsUI::is_admin()) :
1470
  // For JavaScript that needs to be generated dynamically
1471
  add_action('admin_print_scripts', array('FeedWordPressSettingsUI', 'admin_scripts'));
1472
+
1473
  // For CSS that needs to be generated dynamically.
1474
  add_action('admin_print_styles', array('FeedWordPressSettingsUI', 'admin_styles'));
1475
+
1476
  wp_enqueue_style('dashboard');
1477
  wp_enqueue_style('feedwordpress-elements');
1478
+
1479
  /*if (function_exists('wp_admin_css')) :
1480
  wp_admin_css('css/dashboard');
1481
  endif;*/
1482
  endif;
1483
 
1484
+ // These are a special post statuses for hiding posts that have
1485
+ // expired from the feed or been marked for permanent zapping by
1486
+ // the FWP admin.
1487
  register_post_status('fwpretired', array(
1488
  'label' => _x('Retired', 'post'),
1489
  'label_count' => _n_noop('Retired <span class="count">(%s)</span>', 'Retired <span class="count">(%s)</span>'),
1493
  'show_in_admin_all_list' => false,
1494
  'show_in_admin_status_list' => true,
1495
  ));
1496
+ register_post_status('fwpzapped', array(
1497
+ 'label' => _x('Zapped', 'post'),
1498
+ 'label_count' => _n_noop('Zapped <span class="count">(%s)</span>', 'Retired <span class="count">(%s)</span>'),
1499
+ 'exclude_from_search' => true,
1500
+ 'public' => false,
1501
+ 'publicly_queryable' => false,
1502
+ 'show_in_admin_all_list' => false,
1503
+ 'show_in_admin_status_list' => true,
1504
+ ));
1505
  add_action(
1506
  /*hook=*/ 'template_redirect',
1507
  /*function=*/ array($this, 'redirect_retired'),
1511
  add_action('wp_ajax_fwp_feeds', array($this, 'fwp_feeds'));
1512
  add_action('wp_ajax_fwp_feedcontents', array($this, 'fwp_feedcontents'));
1513
  add_action('wp_ajax_fwp_xpathtest', array($this, 'fwp_xpathtest'));
1514
+
1515
  $this->clear_cache_magic_url();
1516
  $this->update_magic_url();
1517
  } /* FeedWordPress::init() */
1518
+
1519
+ public function fwp_feeds () {
1520
  $feeds = array();
1521
  $feed_ids = $this->feeds;
1522
+
1523
  foreach ($feed_ids as $id) :
1524
  $sub = $this->subscription($id);
1525
  $feeds[] = array(
1529
  );
1530
  endforeach;
1531
 
1532
+ header("Content-Type: application/json");
1533
  echo json_encode($feeds);
1534
  exit;
1535
+ } /* FeedWordPress::fwp_feeds () */
1536
 
1537
+ public function fwp_feedcontents () {
1538
  $feed_id = MyPHP::request('feed_id');
1539
+
1540
  // Let's load up some data from the feed . . .
1541
  $feed = $this->subscription($feed_id);
1542
  $posts = $feed->live_posts();
1543
+
1544
  if (is_wp_error($posts)) :
1545
  header("HTTP/1.1 502 Bad Gateway");
1546
  $result = $posts;
1549
 
1550
  foreach ($posts as $post) :
1551
  $p = new SyndicatedPost($post, $feed);
1552
+
1553
  $result[] = array(
1554
  "post_title" => $p->entry->get_title(),
1555
  "post_link" => $p->permalink(),
1558
  );
1559
  endforeach;
1560
  endif;
1561
+
1562
  header("Content-Type: application/json");
1563
+
1564
  echo json_encode($result);
1565
+
1566
  // This is an AJAX request, so close it out thus.
1567
  die;
1568
  } /* FeedWordPress::fwp_feedcontents () */
1569
+
1570
+ public function fwp_xpathtest () {
1571
  $xpath = MyPHP::request('xpath');
1572
  $feed_id = MyPHP::request('feed_id');
1573
  $post_id = MyPHP::request('post_id');
1574
+
1575
  $expr = new FeedWordPressParsedPostMeta($xpath);
1576
+
1577
  // Let's load up some data from the feed . . .
1578
  $feed = $this->subscription($feed_id);
1579
  $posts = $feed->live_posts();
1580
+
1581
  if (!is_wp_error($posts)) :
1582
  if (strlen($post_id) == 0) :
1583
  $post = $posts[0];
1584
  else :
1585
  $post = null;
1586
+
1587
  foreach ($posts as $p) :
1588
  if ($p->get_id() == $post_id) :
1589
  $post = $p;
1590
  endif;
1591
  endforeach;
1592
  endif;
1593
+
1594
  $post = new SyndicatedPost($post, $feed);
1595
  $meta = $expr->do_substitutions($post);
1596
+
1597
  $result = array(
1598
  "post_title" => $post->entry->get_title(),
1599
  "post_link" => $post->permalink(),
1608
  "post_id" => $post_id,
1609
  "results" => $posts
1610
  );
1611
+
1612
  header("HTTP/1.1 503 Bad Gateway");
1613
  endif;
1614
+
1615
  header("Content-Type: application/json");
1616
+
1617
  echo json_encode($result);
1618
+
1619
  // This is an AJAX request, so close it out thus.
1620
  die;
1621
  } /* FeedWordPress::fwp_xpathtest () */
1622
+
1623
+ public function redirect_retired () {
1624
  global $wp_query;
1625
  if (is_singular()) :
1626
+ if (
1627
+ 'fwpretired'==$wp_query->post->post_status
1628
+ or 'fwpzapped'==$wp_query->post->post_status
1629
+ ) :
1630
  do_action('feedwordpress_redirect_retired', $wp_query->post);
1631
+
1632
  if (!($template = get_404_template())) :
1633
  $template = get_index_template();
1634
  endif;
1639
  exit;
1640
  endif;
1641
  endif;
1642
+ } /* FeedWordPress::redirect_retired () */
1643
+
1644
+ public function row_actions ($actions, $post) {
1645
  if (is_syndicated($post->ID)) :
1646
  $link = get_delete_post_link($post->ID, '', true);
1647
+ $eraseLink = MyPHP::url($link, array("fwp_post_delete" => "nuke"));
1648
+
1649
+ $caption = apply_filters('feedwordpress_ui_erase_link_caption', __('Erase the record of this post (will be re-syndicated if it still appears on the feed).'));
1650
+ $linktext = apply_filters('feedwordpress_ui_erase_link_text', __('Erase/Resyndicate'));
1651
 
1652
+ $retireClass = NULL;
1653
+ if ($post->post_status == 'fwpzapped') :
1654
+ if (count(get_post_meta($post->ID, '_feedwordpress_zapped_blank_me')) > 0) :
1655
+ $retireCap = 'Un-Zap this syndicated post (so it will appear on the site again)';
1656
+ $retireText = 'Un-Zap &amp; Restore';
1657
+ $retireLink = MyPHP::url($link, array("fwp_post_delete" => "unzap"));
1658
+ else :
1659
+ // No Un-Zap link for posts that have
1660
+ // been blanked. You'll just have to
1661
+ // Erase and hope you can resyndicate...
1662
+ $retireLink = NULL;
1663
+ endif;
1664
+ else :
1665
+ $retireCap = apply_filters('feedwordpress_ui_zap_link_caption', __('Zap this syndicated post (so it will not be re-syndicated if it still appears on the feed).'));
1666
+ $retireText = apply_filters('feedwordpress_ui_zap_link_text', __('Zap/Don&#8217;t Resyndicate'));
1667
+ $retireLink = MyPHP::url($link, array("fwp_post_delete" => "zap"));
1668
+ $retireClass = 'submitdelete';
1669
+ endif;
1670
 
1671
  $keys = array_keys($actions);
1672
  $links = array();
1673
  foreach ($keys as $key) :
1674
  $links[$key] = $actions[$key];
1675
+
1676
  if ('trash'==$key) :
1677
+ #$links[$key] = "<a class='submitdelete' title='" . esc_attr( __( 'Move this item to the Trash (will NOT be re-syndicated)' ) ) . "' href='" . get_delete_post_link( $post->ID ) . "'>" . __( 'Trash' ) . "</a>";
1678
+
1679
  // Placeholder.
1680
+ if (!is_null($retireLink)) :
1681
+ $links['zap trash'] = '';
1682
+ endif;
1683
  $links['delete'] = '';
1684
  endif;
1685
  endforeach;
1686
+
1687
+ if (!is_null($retireLink)) :
1688
+ $links['zap trash'] = '<a class="'.esc_attr($retireClass).'" title="'.esc_attr(__($retireCap)).'" href="' . $retireLink . '">' . __($retireText) . '</a>';
1689
+ endif;
1690
+ $links['delete'] = '<a class="submitdelete" title="'.esc_attr(__($caption)).'" href="' . $eraseLink . '">' . __($linktext) . '</a>';
1691
 
1692
  $actions = $links;
1693
  endif;
1694
  return $actions;
1695
+ } /* FeedWordPress::row_actions () */
1696
+
1697
+ public function dashboard_setup () {
1698
  $see_it = FeedWordPress::menu_cap();
1699
+
1700
  if (current_user_can($see_it)) :
1701
  // Get the stylesheet
1702
  wp_enqueue_style('feedwordpress-elements');
1703
+
1704
  $widget_id = 'feedwordpress_dashboard';
1705
  $widget_name = __('Syndicated Sources');
1706
  $column = 'side';
1707
  $priority = 'core';
1708
+
1709
  // I would love to use wp_add_dashboard_widget() here and save
1710
  // myself some trouble. But WP 3 does not yet have any way to
1711
  // push a dashboard widget onto the side, or to give it a default
1719
  /*priority=*/ $priority
1720
  );
1721
  /*control_callback= array($this, 'dashboard_control') */
1722
+
1723
  // This is kind of rude, I know, but the dashboard widget isn't
1724
  // worth much if users don't know that it exists, and I don't
1725
  // know of any better way to reorder the boxen.
1726
  //
1727
  // Gleefully ripped off of codex.wordpress.org/Dashboard_Widgets_API
1728
+
1729
  // Globalize the metaboxes array, this holds all the widgets for wp-admin
1730
  global $wp_meta_boxes;
1731
+
1732
+ // Get the regular dashboard widgets array
1733
  // (which has our new widget already but at the end)
1734
+
1735
  $normal_dashboard = $wp_meta_boxes['dashboard'][$column][$priority];
1736
+
1737
  // Backup and delete our new dashbaord widget from the end of the array
1738
  if (isset($normal_dashboard[$widget_id])) :
1739
  $backup = array();
1740
  $backup[$widget_id] = $normal_dashboard[$widget_id];
1741
  unset($normal_dashboard[$widget_id]);
1742
+
1743
  // Merge the two arrays together so our widget is at the
1744
  // beginning
1745
  $sorted_dashboard = array_merge($backup, $normal_dashboard);
1746
+
1747
+ // Save the sorted array back into the original metaboxes
1748
  $wp_meta_boxes['dashboard'][$column][$priority] = $sorted_dashboard;
1749
  endif;
1750
  endif;
1751
  } /* FeedWordPress::dashboard_setup () */
1752
+
1753
+ public function dashboard () {
1754
  $syndicationPage = new FeedWordPressSyndicationPage(dirname(__FILE__).'/syndication.php');
1755
  $syndicationPage->dashboard_box($syndicationPage);
1756
  } /* FeedWordPress::dashboard () */
1757
 
1758
+ public function user_can_richedit ($rich_edit) {
1759
 
1760
  $post = new FeedWordPressLocalPost;
1761
+
1762
  if (!$post->is_exposed_to_formatting_filters()) :
1763
  // Disable visual editor and only allow operations
1764
  // directly on HTML if post is bypassing fmt filters
1765
+ # $rich_edit = false;
1766
  endif;
1767
+
1768
  return $rich_edit;
1769
 
1770
  } /* FeedWordPress::user_can_richedit () */
1771
+
1772
+ public function update_magic_url () {
1773
  global $wpdb;
1774
 
1775
  // Explicit update request in the HTTP request (e.g. from a cron job)
1777
  $this->update_hooked = "Initiating a CRON JOB CHECK-IN ON UPDATE SCHEDULE due to URL parameter = ".trim($this->val($_REQUEST['update_feedwordpress']));
1778
 
1779
  $this->update($this->update_requested_url());
1780
+
1781
  if (FEEDWORDPRESS_DEBUG and count($wpdb->queries) > 0) :
1782
  $mysqlTime = 0.0;
1783
  $byTime = array();
1785
  $time = $query[1] * 1000000.0;
1786
  $mysqlTime += $query[1];
1787
  if (!isset($byTime[$time])) : $byTime[$time] = array(); endif;
1788
+ $byTime[$time][] = $query[0]. ' // STACK: ' . $query[2];
1789
  endforeach;
1790
  krsort($byTime);
1791
+
1792
  foreach ($byTime as $time => $querySet) :
1793
  foreach ($querySet as $query) :
1794
  print "[".(sprintf('%4.4f', $time/1000.0)) . "ms] $query\n";
1795
  endforeach;
1796
  endforeach;
1797
+ echo self::log_prefix()."$wpdb->num_queries queries. $mysqlTime seconds in MySQL. Total of "; timer_stop(1); print " seconds.";
1798
  endif;
1799
+
1800
  debug_out_feedwordpress_footer();
1801
+
1802
  // Magic URL should return nothing but a 200 OK header packet
1803
  // when successful.
1804
  exit;
1805
  endif;
1806
  } /* FeedWordPress::magic_update_url () */
1807
 
1808
+ public function clear_cache_magic_url () {
1809
  if ($this->clear_cache_requested()) :
1810
  $this->clear_cache();
1811
  endif;
1812
  } /* FeedWordPress::clear_cache_magic_url() */
1813
+
1814
+ public function clear_cache_requested () {
1815
  return MyPHP::request('clear_cache');
1816
  } /* FeedWordPress::clear_cache_requested() */
1817
 
1818
+ public function update_requested () {
1819
+ return MyPHP::request('update_feedwordpress');
1820
+ } /* FeedWordPress::update_requested() */
1821
 
1822
+ public function update_requested_url () {
1823
  $ret = null;
1824
+
1825
  if (($_REQUEST['update_feedwordpress']=='*')
1826
  or (preg_match('|^http://.*|i', $_REQUEST['update_feedwordpress']))) :
1827
  $ret = $_REQUEST['update_feedwordpress'];
1828
  endif;
1829
 
1830
  return $ret;
1831
+ } /* FeedWordPress::update_requested_url() */
1832
 
1833
+ public function auto_update () {
1834
  if ($this->stale()) :
1835
  $this->update();
1836
  endif;
1837
  } /* FeedWordPress::auto_update () */
1838
 
1839
+ public static function find_link ($uri, $field = 'link_rss') {
1840
  global $wpdb;
1841
 
1842
  $unslashed = untrailingslashit($uri);
1845
  SELECT link_id FROM $wpdb->links WHERE $field IN ('%s', '%s')
1846
  LIMIT 1", $unslashed, $slashed
1847
  ));
1848
+
1849
  return $link_id;
1850
  } /* FeedWordPress::find_link () */
1851
 
1852
+ /**
1853
+ * FeedWordPress:syndicate_link(): add or update a feed subscription
1854
+ *
1855
+ * Add a new subscription to, or update an existing subscription in,
1856
+ * FWP's list of subscribed feeds.
1857
+ *
1858
+ * Postcondition: If $rss is the URL of a feed not yet on FWP's list of
1859
+ * subscribed feeds, then a new subscription will be added, using $name
1860
+ * as its initial title and $uri as its initial homepage URL (normally
1861
+ * these will be updated with new values taken from the feed, the first
1862
+ * time the new feed is checked for syndicated content, unless feed
1863
+ * settings prevent this). If $rss is the URL of a feed that is already
1864
+ * on FWP's list of subscribed feeds, then that feed will be updated to
1865
+ * use the title provided in $name and the homepage URL in $uri
1866
+ *
1867
+ * @param string $name The human-readable title of the feed (for example, "Rad Geek People's Daily")
1868
+ * @param string $uri The URI for the human-readable homepage associated with the feed (for example, <http://radgeek.com/>)
1869
+ * @param string $rss The URI for the feed itself (for example, <http://radgeek.com/feed/>)
1870
+ *
1871
+ * @return mixed Returns an int with the numeric ID of the new
1872
+ * subscription's wp_links record if successful or a WP_Error object
1873
+ * if wp_insert_link() failed.
1874
+ *
1875
+ * @uses FeedWordPress::link_category_id()
1876
+ * @uses FeedWordPress::find_link()
1877
+ * @uses is_wp_error()
1878
+ * @uses wp_insert_link()
1879
+ *
1880
+ */
1881
+ public static function syndicate_link ($name, $uri, $rss) {
1882
  // Get the category ID#
1883
  $cat_id = FeedWordPress::link_category_id();
1884
  if (!is_wp_error($cat_id)) :
1889
 
1890
  // WordPress gets cranky if there's no homepage URI
1891
  if (!is_string($uri) or strlen($uri)<1) : $uri = $rss; endif;
1892
+
1893
  // Check if this feed URL is already being syndicated.
1894
+ $link_id = wp_insert_link(/*linkdata=*/ array(
1895
  "link_id" => FeedWordPress::find_link($rss), // insert if nothing was found; else update
1896
  "link_rss" => $rss,
1897
  "link_name" => $name,
1898
  "link_url" => $uri,
1899
  "link_category" => $link_category,
1900
  "link_visible" => 'Y', // reactivate if inactivated
1901
+ ), /*wp_error=*/ true);
1902
 
1903
  return $link_id;
1904
  } /* function FeedWordPress::syndicate_link() */
1905
 
1906
+ static function syndicated_status ($what, $default) {
1907
  $ret = get_option("feedwordpress_syndicated_{$what}_status");
1908
  if (!$ret) :
1909
  $ret = $default;
1911
  return $ret;
1912
  } /* FeedWordPress::syndicated_status() */
1913
 
1914
+ public static function on_unfamiliar ($what = 'author') {
1915
  switch ($what) :
1916
  case 'category' : $suffix = ':category'; break;
1917
  case 'post_tag' : $suffix = ':post_tag'; break;
1918
  default: $suffix = '';
1919
  endswitch;
1920
+
1921
  return get_option('feedwordpress_unfamiliar_'.$what, 'create'.$suffix);
1922
  } // function FeedWordPress::on_unfamiliar()
1923
 
1924
+ public static function null_email_set () {
1925
  $base = get_option('feedwordpress_null_email_set');
1926
 
1927
  if ($base===false) :
1935
 
1936
  } /* FeedWordPress::null_email_set () */
1937
 
1938
+ public static function is_null_email ($email) {
1939
  $ret = in_array(strtolower(trim($email)), FeedWordPress::null_email_set());
1940
  $ret = apply_filters('syndicated_item_author_is_null_email', $ret, $email);
1941
  return $ret;
1942
  } /* FeedWordPress::is_null_email () */
1943
 
1944
+ public static function use_aggregator_source_data () {
1945
  $ret = get_option('feedwordpress_use_aggregator_source_data');
1946
  return apply_filters('syndicated_post_use_aggregator_source_data', ($ret=='yes'));
1947
+ } /* FeedWordPress::use_aggregator_source_data () */
1948
 
1949
  /**
1950
  * FeedWordPress::munge_permalinks: check whether or not FeedWordPress
1953
  *
1954
  * @return bool TRUE if FeedWordPress SHOULD rewrite permalinks; FALSE otherwise
1955
  */
1956
+ static function munge_permalinks () {
1957
  return (get_option('feedwordpress_munge_permalink', /*default=*/ 'yes') != 'no');
1958
  } /* FeedWordPress::munge_permalinks() */
1959
 
1960
+ public static function syndicated_links ($args = array()) {
1961
  $contributors = FeedWordPress::link_category_id();
1962
  if (!is_wp_error($contributors)) :
1963
  $links = get_bookmarks(array_merge(
1969
  endif;
1970
 
1971
  return $links;
1972
+ } /* FeedWordPress::syndicated_links() */
1973
 
1974
+ public static function link_category_id () {
1975
  global $wpdb, $wp_db_version;
1976
 
1977
  $cat_id = get_option('feedwordpress_cat_id');
1978
+
1979
  // If we don't yet have the category ID stored, search by name
1980
  if (!$cat_id) :
1981
  $cat_id = FeedWordPressCompatibility::link_category_id(DEFAULT_SYNDICATION_CATEGORY);
1989
  else :
1990
  $cat_id = FeedWordPressCompatibility::link_category_id((int) $cat_id, 'cat_id');
1991
  endif;
1992
+
1993
  // If we could not find an appropriate link category,
1994
  // make a new one for ourselves.
1995
  if (!$cat_id) :
2001
  endif;
2002
 
2003
  return $cat_id;
2004
+ } /* FeedWordPress::link_category_id() */
2005
 
2006
  # Upgrades and maintenance...
2007
+ static function needs_upgrade () {
2008
+
2009
  global $wpdb;
2010
+ $fwp_db_version = get_option('feedwordpress_version', NULL);
2011
  $ret = false; // innocent until proven guilty
2012
+ if (is_null($fwp_db_version) or ($fwp_db_version < FEEDWORDPRESS_VERSION)) :
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2013
 
2014
+ // This is an older version or a fresh install. Does it require a database
2015
+ // upgrade or database initialization?
2016
+
2017
+ if (is_null($fwp_db_version)) :
2018
+
2019
+ // Fresh install; brand it as ours. Or possibly a version of FWP
2020
+ // from before 0.96. But I'm no longer supporting upgrade paths
2021
+ // for versions from the previous decade. Sorry.
2022
  update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
2023
+
2024
  elseif ($fwp_db_version < 2010.0814) :
2025
+
2026
  // Change in terminology.
2027
  if (get_option('feedwordpress_unfamiliar_category', 'create')=='default') :
2028
  update_option('feedwordpress_unfamiliar_category', 'null');
2029
  endif;
2030
  foreach (FeedWordPress::syndicated_links() as $link) :
2031
  $sub = new SyndicatedLink($link);
2032
+
2033
  $remap_uf = array(
2034
  'default' => 'null',
2035
  'filter' => 'null',
2046
  endif;
2047
  endforeach;
2048
  endif;
2049
+
2050
  if (isset($sub->settings['add global categories'])) :
2051
  $sub->settings['add/category'] = $sub->settings['add global categories'];
2052
  unset($sub->settings['add global categories']);
2053
  endif;
2054
+
2055
  $sub->save_settings(/*reload=*/ true);
2056
  endforeach;
2057
  update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
2058
+
2059
  else :
2060
+
2061
+ // No upgrade needed. Just brand it with the new version.
2062
  update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
2063
+
2064
  endif;
2065
+
2066
  endif;
2067
  return $ret;
2068
+ } /* FeedWordPress::needs_upgrade () */
2069
 
2070
+ static function upgrade_database ($from = NULL) {
2071
  global $wpdb;
2072
 
2073
  if (is_null($from) or $from <= 0.96) : $from = 0.96; endif;
2074
 
2075
  switch ($from) :
2076
  case 0.96:
2077
+ // Dropping legacy upgrade code. If anyone is still
2078
+ // using 0.96 and just now decided to upgrade, well, I'm
2079
+ // sorry about that. You'll just have to cope with a few
2080
+ // duplicate posts.
2081
 
2082
  // Mark the upgrade as successful.
2083
  update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
2085
  echo "<p>Upgrade complete. FeedWordPress is now ready to use again.</p>";
2086
  } /* FeedWordPress::upgrade_database() */
2087
 
2088
+ public static function has_guid_index () {
2089
  global $wpdb;
2090
+
2091
  $found = false; // Guilty until proven innocent.
2092
 
2093
  $results = $wpdb->get_results("
2103
  endif;
2104
  return $found;
2105
  } /* FeedWordPress::has_guid_index () */
2106
+
2107
+ public static function create_guid_index () {
2108
  global $wpdb;
2109
+
2110
  $wpdb->query("
2111
  CREATE INDEX {$wpdb->posts}_guid_idx ON {$wpdb->posts}(guid)
2112
  ");
2113
  } /* FeedWordPress::create_guid_index () */
2114
+
2115
+ public static function remove_guid_index () {
2116
  global $wpdb;
2117
+
2118
  $wpdb->query("
2119
  DROP INDEX {$wpdb->posts}_guid_idx ON {$wpdb->posts}
2120
  ");
2121
  }
2122
 
2123
+ static function fetch_timeout () {
2124
  return apply_filters(
2125
  'feedwordpress_fetch_timeout',
2126
  intval(get_option('feedwordpress_fetch_timeout', FEEDWORDPRESS_FETCH_TIMEOUT_DEFAULT))
2127
  );
2128
  }
2129
+
2130
+ static function fetch ($url, $params = array()) {
2131
  if (is_wp_error($url)) :
2132
  // Let's bounce.
2133
  return $url;
2134
  endif;
2135
+
2136
  $force_feed = true; // Default
2137
 
2138
+ // Allow user to change default feed-fetch timeout with a global setting.
2139
+ // Props Erigami Scholey-Fuller <http://www.piepalace.ca/blog/2010/11/feedwordpress-broke-my-heart.html>
2140
  $timeout = FeedWordPress::fetch_timeout();
2141
+
2142
  if (!is_array($params)) :
2143
  $force_feed = $params;
2144
  else : // Parameter array
2146
  'force_feed' => $force_feed,
2147
  'timeout' => $timeout
2148
  ), $params);
2149
+
2150
  extract($args);
2151
  endif;
2152
  $timeout = intval($timeout);
2153
+
2154
  $pie_class = apply_filters('feedwordpress_simplepie_class', 'FeedWordPie');
2155
  $cache_class = apply_filters('feedwordpress_cache_class', 'WP_Feed_Cache');
2156
  $file_class = apply_filters('feedwordpress_file_class', 'FeedWordPress_File');
2162
  $feed->set_feed_url($url);
2163
  $feed->set_cache_class($cache_class);
2164
  $feed->set_timeout($timeout);
2165
+
2166
  $feed->set_content_type_sniffer_class($sniffer_class);
2167
  $feed->set_file_class($file_class);
2168
  $feed->set_parser_class($parser_class);
2171
  $feed->set_cache_duration(FeedWordPress::cache_duration($params));
2172
  $feed->init();
2173
  $feed->handle_content_type();
2174
+
2175
  if ($feed->error()) :
2176
  $ret = new WP_Error('simplepie-error', $feed->error());
2177
  else :
2179
  endif;
2180
  return $ret;
2181
  } /* FeedWordPress::fetch () */
2182
+
2183
+ public function clear_cache () {
2184
  global $wpdb;
2185
+
2186
  // Just in case, clear out any old MagpieRSS cache records.
2187
  $magpies = $wpdb->query("
2188
  DELETE FROM {$wpdb->options}
2205
  return ($magpies + $simplepies);
2206
  } /* FeedWordPress::clear_cache () */
2207
 
2208
+ static public function cache_duration ($params = array()) {
2209
  $params = wp_parse_args($params, array(
2210
  "cache" => true,
2211
  ));
2212
+
2213
  $duration = NULL;
2214
  if (!$params['cache']) :
2215
  $duration = 0;
2218
  endif;
2219
  return $duration;
2220
  }
2221
+
2222
+ static public function cache_lifetime ($duration) {
2223
  // Check for explicit setting of a lifetime duration
2224
  if (defined('FEEDWORDPRESS_CACHE_LIFETIME')) :
2225
  $duration = FEEDWORDPRESS_CACHE_LIFETIME;
2228
  elseif (defined('FEEDWORDPRESS_CACHE_AGE')) :
2229
  $duration = FEEDWORDPRESS_CACHE_AGE;
2230
  endif;
2231
+
2232
  // Fall back to WordPress default
2233
  return $duration;
2234
  } /* FeedWordPress::cache_lifetime () */
2235
 
2236
  # Utility functions for handling text settings
2237
+ static function negative ($f, $setting) {
2238
  $nego = array ('n', 'no', 'f', 'false');
2239
  return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $nego));
2240
+ } /* FeedWordPress::negative () */
2241
 
2242
+ static function affirmative ($f, $setting) {
2243
  $affirmo = array ('y', 'yes', 't', 'true', 1);
2244
  return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $affirmo));
2245
+ } /* FeedWordPress::affirmative () */
2246
 
2247
  # Internal debugging functions
2248
+ static function critical_bug ($varname, $var, $line, $file = NULL) {
2249
  global $wp_version;
2250
+
2251
  if (!is_null($file)) :
2252
  $location = "line # ${line} of ".basename($file);
2253
  else :
2254
  $location = "line # ${line}";
2255
  endif;
2256
+
2257
  print '<p><strong>Critical error:</strong> There may be a bug in FeedWordPress. Please <a href="'.FEEDWORDPRESS_AUTHOR_CONTACT.'">contact the author</a> and paste the following information into your e-mail:</p>';
2258
  print "\n<plaintext>";
2259
  print "Triggered at ${location}\n";
2263
  print "Error data: ";
2264
  print $varname.": "; var_dump($var); echo "\n";
2265
  die;
2266
+ } /* FeedWordPress::critical_bug () */
2267
+
2268
+ static function noncritical_bug ($varname, $var, $line, $file = NULL) {
2269
  if (FEEDWORDPRESS_DEBUG) : // halt only when we are doing debugging
2270
  FeedWordPress::critical_bug($varname, $var, $line, $file);
2271
  endif;
2272
+ } /* FeedWordPress::noncritical_bug () */
2273
+
2274
+ static function val ($v, $no_newlines = false) {
2275
+ return MyPHP::val($v, $no_newlines);
 
 
 
 
 
 
 
2276
  } /* FeedWordPress::val () */
2277
 
2278
+ static function diagnostic_on ($level) {
2279
  $show = get_option('feedwordpress_diagnostics_show', array());
2280
  return (in_array($level, $show));
2281
  } /* FeedWordPress::diagnostic_on () */
2282
 
2283
+ static function diagnostic ($level, $out, $persist = NULL, $since = NULL, $mostRecent = NULL) {
2284
  global $feedwordpress_admin_footer;
2285
 
2286
  $output = get_option('feedwordpress_diagnostics_output', array());
2293
  switch ($method) :
2294
  case 'echo' :
2295
  if (!FeedWordPress::update_requested()) :
2296
+ echo "<div><pre><strong>Diag".str_repeat('====', $diagnostic_nesting-1).'|</strong> '.$out."</pre></div>\n";
2297
  endif;
2298
  break;
2299
  case 'echo_in_cronjob' :
2308
  error_log(FeedWordPress::log_prefix().' '.$out);
2309
  break;
2310
  case 'email' :
2311
+
2312
  if (is_null($persist)) :
2313
  $sect = 'occurrent';
2314
  $hook = (isset($dlog['mesg'][$sect]) ? count($dlog['mesg'][$sect]) : 0);
2318
  $hook = md5($level."\n".$persist);
2319
  $line = array("Since" => $since, "Message" => $out, "Most Recent" => $mostRecent);
2320
  endif;
2321
+
2322
  if (!isset($dlog['mesg'])) : $dlog['mesg'] = array(); endif;
2323
  if (!isset($dlog['mesg'][$sect])) : $dlog['mesg'][$sect] = array(); endif;
2324
+
2325
  $dlog['mesg'][$sect][$hook] = $line;
2326
  endswitch;
2327
  endforeach;
2328
  endif;
2329
+
2330
+ update_option('feedwordpress_diagnostics_log', $dlog);
2331
  } /* FeedWordPress::diagnostic () */
2332
+
2333
+ public function email_diagnostics_override () {
2334
  return ($this->has_secret() and isset($_REQUEST['feedwordpress_email_diagnostics']) and !!$_REQUEST['feedwordpress_email_diagnostics']);
2335
+ } /* FeedWordPress::email_diagnostics_override () */
2336
+
2337
+ public function has_emailed_diagnostics ($dlog) {
2338
  $ret = false;
2339
  if ($this->email_diagnostics_override()
2340
  or (isset($dlog['schedule']) and isset($dlog['schedule']['last']))) :
2341
  $ret = true;
2342
  endif;
2343
  return $ret;
2344
+ } /* FeedWordPress::has_emailed_diagnostics () */
2345
+
2346
+ public function ready_to_email_diagnostics ($dlog) {
2347
  $ret = false;
2348
  if ($this->email_diagnostics_override()
2349
  or (time() > ($dlog['schedule']['last'] + $dlog['schedule']['freq']))) :
2350
  $ret = true;
2351
  endif;
2352
  return $ret;
2353
+ } /* FeedWordPress::ready_to_email_diagnostics () */
2354
+
2355
+ public function email_diagnostic_log ($params = array()) {
2356
  $params = wp_parse_args($params, array(
2357
  "force" => false,
2358
  ));
2359
 
2360
  $dlog = get_option('feedwordpress_diagnostics_log', array());
2361
+
2362
  if ($this->has_emailed_diagnostics($dlog)) :
2363
  if ($this->ready_to_email_diagnostics($dlog)) :
2364
  // No news is good news; only send if
2365
  // there are some messages to send.
2366
  $body = NULL;
2367
  if (!isset($dlog['mesg'])) : $dlog['mesg'] = array(); endif;
2368
+
2369
  foreach ($dlog['mesg'] as $sect => $mesgs) :
2370
  if (count($mesgs) > 0) :
2371
  if (is_null($body)) : $body = ''; endif;
2372
+
2373
  $paradigm = reset($mesgs);
2374
  $body .= "<h2>".ucfirst($sect)." issues</h2>\n"
2375
  ."<table>\n"
2379
  endforeach;
2380
  $body .= "</tr></thead>\n"
2381
  ."<tbody>\n";
2382
+
2383
  foreach ($mesgs as $line) :
2384
  $body .= "<tr>\n";
2385
  foreach ($line as $col => $cell) :
2391
  endforeach;
2392
  $body .= "</tr>\n";
2393
  endforeach;
2394
+
2395
  $body .= "</tbody>\n</table>\n\n";
2396
  endif;
2397
  endforeach;
2398
+
2399
  $body = apply_filters('feedwordpress_diagnostic_email_body', $body, $dlog);
2400
  if (!is_null($body)) :
2401
  $home = feedwordpress_display_url(get_bloginfo('url'));
2430
  // e-mail address
2431
  if (preg_match('/^mailto:(.*)$/', $ded, $ref)) :
2432
  $recipients = array($ref[1]);
2433
+
2434
  // userid
2435
  elseif (preg_match('/^user:(.*)$/', $ded, $ref)) :
2436
  $userdata = get_userdata((int) $ref[1]);
2437
  $recipients = array($userdata->user_email);
2438
+
2439
  // admins
2440
  else :
2441
  $recipients = FeedWordPressDiagnostic::admin_emails();
2458
  endif;
2459
  $head = apply_filters('feedwordpress_diagnostic_email_headers', $head);
2460
 
2461
+ foreach ($recipients as $email) :
2462
  add_filter('wp_mail_content_type', array('FeedWordPress', 'allow_html_mail'));
2463
  wp_mail($email, $subj, $body, $head);
2464
  remove_filter('wp_mail_content_type', array('FeedWordPress', 'allow_html_mail'));
2465
  endforeach;
2466
  endif;
2467
+
2468
  // Clear the logs
2469
  $dlog['mesg']['persistent'] = array();
2470
  $dlog['mesg']['occurrent'] = array();
2471
+
2472
  // Set schedule for next update
2473
  $dlog['schedule']['last'] = time();
2474
  endif;
2478
  'last' => time(),
2479
  );
2480
  endif;
2481
+
2482
  update_option('feedwordpress_diagnostics_log', $dlog);
2483
  } /* FeedWordPress::email_diagnostic_log () */
2484
+
2485
+ static function allow_html_mail () {
2486
  return 'text/html';
2487
  } /* FeedWordPress::allow_html_mail () */
2488
 
2489
+ static function admin_footer () {
2490
  global $feedwordpress_admin_footer;
2491
  foreach ($feedwordpress_admin_footer as $line) :
2492
  echo '<div><pre>'.$line.'</pre></div>';
2493
  endforeach;
2494
  } /* FeedWordPress::admin_footer () */
2495
+
2496
+ static function log_prefix ($date = false) {
2497
  $home = get_bloginfo('url');
2498
  $prefix = '['.feedwordpress_display_url($home).'] [feedwordpress] ';
2499
  if ($date) :
2501
  endif;
2502
  return $prefix;
2503
  } /* FeedWordPress::log_prefix () */
2504
+
2505
+ static function menu_cap ($sub = false) {
2506
  if ($sub) :
2507
  $cap = apply_filters('feedwordpress_menu_settings_capacity', 'manage_options');
2508
  else :
2510
  endif;
2511
  return $cap;
2512
  } /* FeedWordPress::menu_cap () */
2513
+
2514
+ static function path ($filename = '') {
2515
  global $fwp_path;
2516
+
2517
  $path = $fwp_path;
2518
  if (strlen($filename) > 0) :
2519
  $path .= '/'.$filename;
2520
  endif;
2521
  return $path;
2522
+ } /* FeedWordPress::path () */
2523
+
2524
  // These are superceded by MyPHP::param/post/get/request, but kept
2525
  // here for backward compatibility.
2526
+
2527
+ static function param ($key, $type = 'REQUEST', $default = NULL) {
2528
  return MyPHP::param($key, $default, $type);
2529
+ } /* FeedWordPress::param () */
2530
+
2531
+ static function post ($key, $default = NULL) {
2532
  return MyPHP::post($key, $default);
2533
+ } /* FeedWordPress::post () */
2534
+
2535
+ } /* class FeedWordPress */
2536
 
2537
  $feedwordpress_admin_footer = array();
2538
 
feedwordpress_file.class.php CHANGED
@@ -5,10 +5,6 @@ $fwp_credentials = NULL;
5
 
6
  class FeedWordPress_File extends WP_SimplePie_File {
7
  function FeedWordPress_File ($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) {
8
- self::__construct($url, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
9
- }
10
-
11
- function __construct ($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) {
12
  global $feedwordpress;
13
  global $wp_version;
14
 
@@ -16,7 +12,7 @@ class FeedWordPress_File extends WP_SimplePie_File {
16
  if ($feedwordpress->subscribed($url)) :
17
  $source = $feedwordpress->subscription($url);
18
  endif;
19
-
20
  $this->url = $url;
21
  $this->timeout = $timeout;
22
  $this->redirects = $redirects;
@@ -24,13 +20,13 @@ class FeedWordPress_File extends WP_SimplePie_File {
24
  $this->useragent = $useragent;
25
 
26
  $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE;
27
-
28
  global $wpdb;
29
  global $fwp_credentials;
30
-
31
  if ( preg_match('/^http(s)?:\/\//i', $url) ) :
32
  $args = array( 'timeout' => $this->timeout, 'redirection' => $this->redirects);
33
-
34
  if ( !empty($this->headers) )
35
  $args['headers'] = $this->headers;
36
 
@@ -62,12 +58,12 @@ class FeedWordPress_File extends WP_SimplePie_File {
62
  $args['authentication'] = $source->authentication_method();
63
  $args['username'] = $source->username();
64
  $args['password'] = $source->password();
65
-
66
  endif;
67
 
68
- FeedWordPress::diagnostic('updated_feeds:http', "HTTP [$url] &#8668; ".esc_html(FeedWordPress::val($args)));
69
  $res = wp_remote_request($url, $args);
70
- FeedWordPress::diagnostic('updated_feeds:http', "HTTP [$url] &#8669; ".esc_html(FeedWordPress::val($res)));
71
 
72
  if ( is_wp_error($res) ) {
73
  $this->error = 'WP HTTP Error: ' . $res->get_error_message();
@@ -77,13 +73,13 @@ class FeedWordPress_File extends WP_SimplePie_File {
77
  $this->body = wp_remote_retrieve_body( $res );
78
  $this->status_code = wp_remote_retrieve_response_code( $res );
79
  }
80
-
81
  if ($source InstanceOf SyndicatedLink) :
82
  $source->update_setting('link/filesize', strlen($this->body));
83
  $source->update_setting('link/http status', $this->status_code);
84
  $source->save_settings(/*reload=*/ true);
85
  endif;
86
-
87
  // Do not allow schemes other than http(s)? for the time being.
88
  // They are unlikely to be used; and unrestricted use of schemes
89
  // allows for user to use an unrestricted file:/// scheme, which
5
 
6
  class FeedWordPress_File extends WP_SimplePie_File {
7
  function FeedWordPress_File ($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) {
 
 
 
 
8
  global $feedwordpress;
9
  global $wp_version;
10
 
12
  if ($feedwordpress->subscribed($url)) :
13
  $source = $feedwordpress->subscription($url);
14
  endif;
15
+
16
  $this->url = $url;
17
  $this->timeout = $timeout;
18
  $this->redirects = $redirects;
20
  $this->useragent = $useragent;
21
 
22
  $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE;
23
+
24
  global $wpdb;
25
  global $fwp_credentials;
26
+
27
  if ( preg_match('/^http(s)?:\/\//i', $url) ) :
28
  $args = array( 'timeout' => $this->timeout, 'redirection' => $this->redirects);
29
+
30
  if ( !empty($this->headers) )
31
  $args['headers'] = $this->headers;
32
 
58
  $args['authentication'] = $source->authentication_method();
59
  $args['username'] = $source->username();
60
  $args['password'] = $source->password();
61
+
62
  endif;
63
 
64
+ FeedWordPress::diagnostic('updated_feeds:http', "HTTP [$url] &#8668; ".esc_html(MyPHP::val($args)));
65
  $res = wp_remote_request($url, $args);
66
+ FeedWordPress::diagnostic('updated_feeds:http', "HTTP [$url] &#8669; ".esc_html(MyPHP::val($res)));
67
 
68
  if ( is_wp_error($res) ) {
69
  $this->error = 'WP HTTP Error: ' . $res->get_error_message();
73
  $this->body = wp_remote_retrieve_body( $res );
74
  $this->status_code = wp_remote_retrieve_response_code( $res );
75
  }
76
+
77
  if ($source InstanceOf SyndicatedLink) :
78
  $source->update_setting('link/filesize', strlen($this->body));
79
  $source->update_setting('link/http status', $this->status_code);
80
  $source->save_settings(/*reload=*/ true);
81
  endif;
82
+
83
  // Do not allow schemes other than http(s)? for the time being.
84
  // They are unlikely to be used; and unrestricted use of schemes
85
  // allows for user to use an unrestricted file:/// scheme, which
feedwordpresshtml.class.php CHANGED
@@ -1,6 +1,6 @@
1
- <?php
2
  class FeedWordPressHTML {
3
- function attributeRegex ($tag, $attr) {
4
  return ":(
5
  (<($tag)\s+[^>]*)
6
  ($attr)=
@@ -16,7 +16,7 @@ class FeedWordPressHTML {
16
  :ix";
17
  } /* function FeedWordPressHTML::attributeRegex () */
18
 
19
- function attributeMatch ($matches) {
20
  for ($i = 0; $i <= 12; $i++) :
21
  if (!isset($matches[$i])) :
22
  $matches[$i] = '';
@@ -38,7 +38,7 @@ class FeedWordPressHTML {
38
  );
39
  } /* function FeedWordPressHTML::attributeMatch () */
40
 
41
- function tagWithAttributeRegex ($tag, $attr, $value, $closing = true) {
42
  return ":(
43
  (<($tag)\s+[^>]*)
44
  ($attr)=
@@ -57,7 +57,7 @@ class FeedWordPressHTML {
57
  :ix";
58
  } /* FeedWordPressHTML::tagWithAttributeRegex () */
59
 
60
- function tagWithAttributeMatch ($matches, $closing = true) {
61
  for ($i = 0; $i <= 21; $i++) :
62
  if (!isset($matches[$i])) :
63
  $matches[$i] = '';
1
+ <?php
2
  class FeedWordPressHTML {
3
+ static function attributeRegex ($tag, $attr) {
4
  return ":(
5
  (<($tag)\s+[^>]*)
6
  ($attr)=
16
  :ix";
17
  } /* function FeedWordPressHTML::attributeRegex () */
18
 
19
+ static function attributeMatch ($matches) {
20
  for ($i = 0; $i <= 12; $i++) :
21
  if (!isset($matches[$i])) :
22
  $matches[$i] = '';
38
  );
39
  } /* function FeedWordPressHTML::attributeMatch () */
40
 
41
+ static function tagWithAttributeRegex ($tag, $attr, $value, $closing = true) {
42
  return ":(
43
  (<($tag)\s+[^>]*)
44
  ($attr)=
57
  :ix";
58
  } /* FeedWordPressHTML::tagWithAttributeRegex () */
59
 
60
+ static function tagWithAttributeMatch ($matches, $closing = true) {
61
  for ($i = 0; $i <= 21; $i++) :
62
  if (!isset($matches[$i])) :
63
  $matches[$i] = '';
feedwordpresslocalpost.class.php CHANGED
@@ -1,8 +1,9 @@
1
  <?php
2
 
3
  class FeedWordPressLocalPost {
4
- private $post;
5
-
 
6
  public function __construct ($p = NULL) {
7
  global $post;
8
 
@@ -92,7 +93,8 @@ class FeedWordPressLocalPost {
92
 
93
  public function feed () {
94
  global $feedwordpress;
95
- return $feedwordpress->subscription($this->feed_id());
 
96
  }
97
 
98
  public function feed_id () {
@@ -146,5 +148,41 @@ class FeedWordPressLocalPost {
146
 
147
  } /* FeedWordPressLocalPost::is_exposed_to_formatting_filters () */
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  } /* class FeedWordPressLocalPost */
150
 
1
  <?php
2
 
3
  class FeedWordPressLocalPost {
4
+ public $post;
5
+ public $link;
6
+
7
  public function __construct ($p = NULL) {
8
  global $post;
9
 
93
 
94
  public function feed () {
95
  global $feedwordpress;
96
+ $this->link = $feedwordpress->subscription($this->feed_id());
97
+ return $this->link;
98
  }
99
 
100
  public function feed_id () {
148
 
149
  } /* FeedWordPressLocalPost::is_exposed_to_formatting_filters () */
150
 
151
+
152
+ public function content () {
153
+ return apply_filters('the_content', $this->post->post_content, $this->post->ID);
154
+ }
155
+
156
+ public function title () {
157
+ return apply_filters('the_title', $this->post->post_title, $this->post->ID);
158
+ }
159
+
160
+ public function guid () {
161
+ return apply_filters('get_the_guid', $this->post->guid);
162
+ }
163
+
164
+ public function get_categories () {
165
+ $terms = wp_get_object_terms(
166
+ $this->post->ID,
167
+ get_taxonomies(array(
168
+ 'public' => true,
169
+ ), 'names'),
170
+ 'all'
171
+ );
172
+ $rootUrl = get_bloginfo('url');
173
+
174
+ $cats = array();
175
+ foreach ($terms as $term) :
176
+ $taxUrl = MyPHP::url($rootUrl, array("taxonomy" => $term->taxonomy));
177
+ //array("taxonomy" => $term->taxonomy ));
178
+ $cats[] = new SimplePie_Category(
179
+ /*term=*/ $term->slug,
180
+ /*scheme=*/ $taxUrl,
181
+ /*label=*/ $term->name
182
+ );
183
+ endforeach;
184
+ return $cats;
185
+ }
186
+
187
  } /* class FeedWordPressLocalPost */
188
 
feedwordpressrpc.class.php CHANGED
@@ -24,11 +24,8 @@ class FeedWordPressRPC {
24
  if (is_null($delta)):
25
  return array('flerror' => true, 'message' => "Sorry. I don't syndicate <$args[1]>.");
26
  else:
27
- $mesg = array();
28
- if (isset($delta['new'])) { $mesg[] = ' '.$delta['new'].' new posts were syndicated'; }
29
- if (isset($delta['updated'])) { $mesg[] = ' '.$delta['updated'].' existing posts were updated'; }
30
-
31
- return array('flerror' => false, 'message' => "Thanks for the ping.".implode(' and', $mesg));
32
  endif;
33
  }
34
 
24
  if (is_null($delta)):
25
  return array('flerror' => true, 'message' => "Sorry. I don't syndicate <$args[1]>.");
26
  else:
27
+ $mesg = array();
28
+ return array('flerror' => false, 'message' => "Thanks for the ping.".fwp_update_set_results_message($delta));
 
 
 
29
  endif;
30
  }
31
 
feedwordpresssyndicationpage.class.php CHANGED
@@ -649,17 +649,48 @@ class FeedWordPressSyndicationPage extends FeedWordPressAdminPage {
649
 
650
  function bleg_box ($page, $box = NULL) {
651
  ?>
 
 
 
 
 
 
 
 
 
 
 
652
  <div class="donation-form">
653
- <h4>Keep FeedWordPress improving</h4>
654
  <form action="https://www.paypal.com/cgi-bin/webscr" accept-charset="UTF-8" method="post"><div>
655
  <p><a href="http://feedwordpress.radgeek.com/">FeedWordPress</a> makes syndication
656
  simple and empowers you to stream content from all over the web into your
657
- WordPress hub. That's got to be worth a few lattes. If you're finding FWP useful,
658
  <a href="http://feedwordpress.radgeek.com/donate/">a modest gift</a>
659
  is the best way to support steady progress on development, enhancements,
660
  support, and documentation.</p>
661
- <div class="donate">
662
- <input type="hidden" name="business" value="commerce@radgeek.com" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
663
  <input type="hidden" name="cmd" value="_xclick" />
664
  <input type="hidden" name="item_name" value="FeedWordPress donation" />
665
  <input type="hidden" name="no_shipping" value="1" />
@@ -667,9 +698,14 @@ support, and documentation.</p>
667
  <input type="hidden" name="currency_code" value="USD" />
668
  <input type="hidden" name="notify_url" value="http://feedwordpress.radgeek.com/ipn/donation" />
669
  <input type="hidden" name="custom" value="1" />
670
- <input type="image" name="submit" src="https://www.paypal.com/en_GB/i/btn/btn_donate_SM.gif" alt="Donate through PayPal" />
671
- </div>
672
- </div></form>
 
 
 
 
 
673
 
674
  <p>You can make a gift online (or
675
  <a href="http://feedwordpress.radgeek.com/donation">set up an automatic
@@ -1023,10 +1059,7 @@ function fwp_dashboard_update_if_requested ($object) {
1023
  echo "</ul>\n";
1024
 
1025
  if (!is_null($tdelta)) :
1026
- $mesg = array();
1027
- if (isset($delta['new'])) : $mesg[] = ' '.$tdelta['new'].' new posts were syndicated'; endif;
1028
- if (isset($delta['updated'])) : $mesg[] = ' '.$tdelta['updated'].' existing posts were updated'; endif;
1029
- echo "<p>Update complete.".implode(' and', $mesg)."</p>";
1030
  echo "\n"; flush();
1031
  endif;
1032
  echo "</div> <!-- class=\"updated\" -->\n";
649
 
650
  function bleg_box ($page, $box = NULL) {
651
  ?>
652
+ <script type="text/javascript">
653
+ /* <![CDATA[ */
654
+ (function() {
655
+ var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
656
+ s.type = 'text/javascript';
657
+ s.async = true;
658
+ s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
659
+ t.parentNode.insertBefore(s, t);
660
+ })();
661
+ /* ]]> */</script>
662
+
663
  <div class="donation-form">
664
+ <h4>Consider a Donation to FeedWordPress</h4>
665
  <form action="https://www.paypal.com/cgi-bin/webscr" accept-charset="UTF-8" method="post"><div>
666
  <p><a href="http://feedwordpress.radgeek.com/">FeedWordPress</a> makes syndication
667
  simple and empowers you to stream content from all over the web into your
668
+ WordPress hub. If you&#8217;re finding FWP useful,
669
  <a href="http://feedwordpress.radgeek.com/donate/">a modest gift</a>
670
  is the best way to support steady progress on development, enhancements,
671
  support, and documentation.</p>
672
+
673
+ <div class="donate" style="vertical-align: middle">
674
+
675
+ <div id="flattr-paypal">
676
+
677
+ <div style="display: inline-block; vertical-align: middle; ">
678
+ <a class="FlattrButton" style="display:none;" href="http://feedwordpress.radgeek.com/"></a>
679
+ <noscript>
680
+ <a href="http://flattr.com/thing/1380856/FeedWordPress" target="_blank"><img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a>
681
+ </noscript>
682
+ <div>via Flattr</div>
683
+
684
+ </div> <!-- style="display: inline-block" -->
685
+
686
+ <div class="hovered-component" style="display: inline-block; vertical-align: bottom">
687
+ <a href="bitcoin:<?php print esc_attr(FEEDWORDPRESS_BLEG_BTC); ?>"><img src="<?php print esc_url(WP_PLUGIN_URL.'/'.FeedWordPress::path('btc-qr-64px.png')); ?>" alt="Donate" /></a>
688
+ <div><a href="bitcoin:<?php print esc_attr(FEEDWORDPRESS_BLEG_BTC); ?>">via bitcoin<span class="hover-on pop-over" style="background-color: #ddffdd; padding: 5px; color: black; border-radius: 5px;">bitcoin:<?php print esc_html(FEEDWORDPRESS_BLEG_BTC); ?></span></a></div>
689
+ </div>
690
+
691
+ <div style="display: inline-block; vertical-align: bottom">
692
+ <input type="image" name="submit" src="<?php print esc_url(WP_PLUGIN_URL.'/'.FeedWordPress::path('paypal-donation-64px.png')); ?>" alt="Donate through PayPal" />
693
+ <input type="hidden" name="business" value="distro.to.feedback@radgeek.com" />
694
  <input type="hidden" name="cmd" value="_xclick" />
695
  <input type="hidden" name="item_name" value="FeedWordPress donation" />
696
  <input type="hidden" name="no_shipping" value="1" />
698
  <input type="hidden" name="currency_code" value="USD" />
699
  <input type="hidden" name="notify_url" value="http://feedwordpress.radgeek.com/ipn/donation" />
700
  <input type="hidden" name="custom" value="1" />
701
+ <div>via PayPal</div>
702
+ </div> <!-- style="display: inline-block" -->
703
+
704
+ </div> <!-- id="flattr-paypal" -->
705
+ </div> <!-- class="donate" -->
706
+
707
+ </div> <!-- class="donation-form" -->
708
+ </form>
709
 
710
  <p>You can make a gift online (or
711
  <a href="http://feedwordpress.radgeek.com/donation">set up an automatic
1059
  echo "</ul>\n";
1060
 
1061
  if (!is_null($tdelta)) :
1062
+ echo "<p><strong>Update complete.</strong>".fwp_update_set_results_message($delta)."</p>";
 
 
 
1063
  echo "\n"; flush();
1064
  endif;
1065
  echo "</div> <!-- class=\"updated\" -->\n";
inspectpostmeta.class.php CHANGED
@@ -9,19 +9,15 @@
9
 
10
  class InspectPostMeta {
11
  function InspectPostMeta ($in_hook = true) {
12
- if (!$in_hook) :
13
- add_action('admin_menu', array($this, 'add_meta_box'));
14
- else :
15
- $this->add_meta_box();
16
- endif;
17
  }
18
 
19
- function add_meta_box () {
20
  add_meta_box(
21
  /*id=*/ 'inspect_post_guid_box',
22
  /*title=*/ 'Post GUID and Meta Data',
23
  /*callback=*/ array($this, 'meta_box'),
24
- /*page=*/ 'post',
25
  /*context=*/ 'normal',
26
  /*priority=*/ 'default'
27
  );
9
 
10
  class InspectPostMeta {
11
  function InspectPostMeta ($in_hook = true) {
12
+ add_action('add_meta_boxes', array($this, 'add_meta_boxes'), 10, 2);
 
 
 
 
13
  }
14
 
15
+ function add_meta_boxes ($post_type, $post) {
16
  add_meta_box(
17
  /*id=*/ 'inspect_post_guid_box',
18
  /*title=*/ 'Post GUID and Meta Data',
19
  /*callback=*/ array($this, 'meta_box'),
20
+ /*page=*/ $post_type,
21
  /*context=*/ 'normal',
22
  /*priority=*/ 'default'
23
  );
magpiefromsimplepie.class.php CHANGED
@@ -89,7 +89,7 @@ class MagpieFromSimplePie {
89
  endif;
90
 
91
  $this->normalize();
92
-
93
  // In case anyone goes poking around our private members (uh...)
94
  $this->feed_type = ($this->is_atom() ? 'Atom' : 'RSS');
95
  $this->feed_version = $this->feed_version();
89
  endif;
90
 
91
  $this->normalize();
92
+
93
  // In case anyone goes poking around our private members (uh...)
94
  $this->feed_type = ($this->is_atom() ? 'Atom' : 'RSS');
95
  $this->feed_version = $this->feed_version();
magpiemocklink.class.php CHANGED
@@ -6,7 +6,7 @@ class MagpieMockLink extends SyndicatedLink {
6
 
7
  function MagpieMockLink ($rss, $url) {
8
  $this->link = $rss;
9
-
10
  if (is_array($rss) and isset($rss['simplepie']) and isset($rss['magpie'])) :
11
  $this->simplepie = $rss['simplepie'];
12
  $this->magpie = $rss['magpie'];
@@ -18,7 +18,7 @@ class MagpieMockLink extends SyndicatedLink {
18
  $this->id = -1;
19
  $this->settings = array(
20
  'unfamiliar category' => 'default',
21
-
22
  );
23
  } /* function MagpieMockLink::MagpieMockLink () */
24
 
@@ -30,14 +30,14 @@ class MagpieMockLink extends SyndicatedLink {
30
  $this->link = $this->magpie;
31
  } /* function MagpieMockLink::poll () */
32
 
33
- function uri () {
34
  return $this->url;
35
  } /* function MagpieMockLink::uri() */
36
 
37
- function homepage () {
38
  return (!is_wp_error($this->simplepie) ? $this->simplepie->get_link() : null);
39
  } /* function MagpieMockLink::homepage () */
40
-
41
  function save_settings ($reload = false) {
42
  // NOOP.
43
  }
6
 
7
  function MagpieMockLink ($rss, $url) {
8
  $this->link = $rss;
9
+
10
  if (is_array($rss) and isset($rss['simplepie']) and isset($rss['magpie'])) :
11
  $this->simplepie = $rss['simplepie'];
12
  $this->magpie = $rss['magpie'];
18
  $this->id = -1;
19
  $this->settings = array(
20
  'unfamiliar category' => 'default',
21
+
22
  );
23
  } /* function MagpieMockLink::MagpieMockLink () */
24
 
30
  $this->link = $this->magpie;
31
  } /* function MagpieMockLink::poll () */
32
 
33
+ function uri ($params = array()) {
34
  return $this->url;
35
  } /* function MagpieMockLink::uri() */
36
 
37
+ function homepage ($fromFeed = true) {
38
  return (!is_wp_error($this->simplepie) ? $this->simplepie->get_link() : null);
39
  } /* function MagpieMockLink::homepage () */
40
+
41
  function save_settings ($reload = false) {
42
  // NOOP.
43
  }
paypal-donation-64px.png ADDED
Binary file
performance-page.php CHANGED
@@ -14,15 +14,15 @@ class FeedWordPressPerformancePage extends FeedWordPressAdminPage {
14
  function display () {
15
  global $wpdb, $wp_db_version, $fwp_path;
16
  global $fwp_post;
17
-
18
  if (FeedWordPress::needs_upgrade()) :
19
  fwp_upgrade_page();
20
  return;
21
  endif;
22
-
23
  // If this is a POST, validate source and user credentials
24
  FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_performance', /*capability=*/ 'manage_options');
25
-
26
  if (strtoupper($_SERVER['REQUEST_METHOD'])=='POST') :
27
  $this->accept_POST($fwp_post);
28
  do_action('feedwordpress_admin_page_performance_save', $fwp_post, $this);
@@ -41,7 +41,7 @@ class FeedWordPressPerformancePage extends FeedWordPressAdminPage {
41
  $boxes_by_methods = array(
42
  'performance_box' => __('Performance'),
43
  );
44
-
45
  foreach ($boxes_by_methods as $method => $title) :
46
  add_meta_box(
47
  /*id=*/ 'feedwordpress_'.$method,
@@ -79,19 +79,11 @@ class FeedWordPressPerformancePage extends FeedWordPressAdminPage {
79
  $feeds = (($N == 1) ? __("feed") : __("feeds"));
80
  $this->updated = sprintf(__("Cleared %d cached %s from WordPress database."), $N, $feeds);
81
  endif;
82
-
83
- if (isset($post['optimize_in'])) :
84
- update_option('feedwordpress_optimize_in_clauses', true);
85
- $this->updated = sprintf(__("Enabled optimizing inefficient IN clauses in SQL queries."));
86
- elseif (isset($post['optimize_out'])) :
87
- update_option('feedwordpress_optimize_in_clauses', false);
88
- $this->updated = sprintf(__("Disabled optimizing inefficient IN clauses in SQL queries."));
89
- endif;
90
  } /* FeedWordPressPerformancePage::accept_POST () */
91
 
92
- /*static*/ function performance_box ($page, $box = NULL) {
93
- $optimize_in = get_option('feedwordpress_optimize_in_clauses', false);
94
-
95
  // Hey ho, let's go...
96
  ?>
97
  <table class="editform" width="100%" cellspacing="2" cellpadding="5">
@@ -116,33 +108,6 @@ table. If you'd like to remove the index for any reason, you can do so here.</p>
116
 
117
  <?php endif; ?>
118
 
119
- <tr style="vertical-align: top">
120
- <th width="33%" scope="row">Optimize IN clauses:</th>
121
- <td width="67%"><?php if (!$optimize_in) : ?>
122
- <input class="button" type="submit" name="optimize_in" value="Optimize inefficient IN clauses in SQL queries" />
123
-
124
- <p><strong>Advanced setting.</strong> As of releases up to 3.3.2, WordPress
125
- still generates many SQL queries with an extremely inefficient use of the IN
126
- operator (for example, <code>SELECT user_id, meta_key, meta_value FROM
127
- wp_usermeta WHERE user_id IN (1)</code>). When there is only one item in the
128
- set, the IN operator is unnecessary; and inefficient, because it prevents SQL
129
- from making use of indexes on the table being queried. Activating this setting
130
- will cause these queries to get rewritten to use a simple equality operator when
131
- there is only one item in the set (for example, the example query above would be
132
- rewritten as <code>SELECT user_id, meta_key, meta_value FROM wp_usermeta WHERE
133
- user_id = 1</code>).</p>
134
-
135
- <p><strong>Note.</strong> This is an advanced setting, which affects WordPress's
136
- database queries at a very low level. The change should be harmless, but
137
- proceed with caution, and only if you are confident in your ability to restore
138
- your WordPress installation from backups if something important should stop
139
- working.</p>
140
-
141
- <?php else : ?>
142
- <input class="button" type="submit" name="optimize_out" value="Disable optimizing inefficient IN clauses" />
143
- <p>You can use this setting to disable any attempts by FeedWordPress to optimize
144
- or rewrite WordPress's SQL queries.</p>
145
- <?php endif; ?></td>
146
  </tr>
147
 
148
  </td>
14
  function display () {
15
  global $wpdb, $wp_db_version, $fwp_path;
16
  global $fwp_post;
17
+
18
  if (FeedWordPress::needs_upgrade()) :
19
  fwp_upgrade_page();
20
  return;
21
  endif;
22
+
23
  // If this is a POST, validate source and user credentials
24
  FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_performance', /*capability=*/ 'manage_options');
25
+
26
  if (strtoupper($_SERVER['REQUEST_METHOD'])=='POST') :
27
  $this->accept_POST($fwp_post);
28
  do_action('feedwordpress_admin_page_performance_save', $fwp_post, $this);
41
  $boxes_by_methods = array(
42
  'performance_box' => __('Performance'),
43
  );
44
+
45
  foreach ($boxes_by_methods as $method => $title) :
46
  add_meta_box(
47
  /*id=*/ 'feedwordpress_'.$method,
79
  $feeds = (($N == 1) ? __("feed") : __("feeds"));
80
  $this->updated = sprintf(__("Cleared %d cached %s from WordPress database."), $N, $feeds);
81
  endif;
82
+
 
 
 
 
 
 
 
83
  } /* FeedWordPressPerformancePage::accept_POST () */
84
 
85
+ static function performance_box ($page, $box = NULL) {
86
+
 
87
  // Hey ho, let's go...
88
  ?>
89
  <table class="editform" width="100%" cellspacing="2" cellpadding="5">
108
 
109
  <?php endif; ?>
110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  </tr>
112
 
113
  </td>
readme.txt CHANGED
@@ -3,8 +3,8 @@ 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.5.1
7
- Stable tag: 2013.0504
8
 
9
  FeedWordPress syndicates content from feeds you choose into your WordPress weblog.
10
 
@@ -94,12 +94,46 @@ outs, see the documentation at the [FeedWordPress project homepage][].
94
 
95
  == Changelog ==
96
 
97
- = 2012.0504 =
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
 
 
99
  * BUGFIX: PHP 5.4 compatibility -- includes some more extensive fixes to
100
  compatibility issues with PHP 5.4's handling of global variables
101
 
102
- * MODULE REORGANIZATION: Should ensures that all needed submodules will be
 
 
 
 
 
103
  properly included regardless of whether you are installing from github,
104
  from SVN, or from the WordPress plugins page. If you've been getting
105
  fatal errors about required modules not being found, this release should
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.9.1
7
+ Stable tag: 2014.0805
8
 
9
  FeedWordPress syndicates content from feeds you choose into your WordPress weblog.
10
 
94
 
95
  == Changelog ==
96
 
97
+ = 2014.0805 =
98
+
99
+
100
+ * FILTERS AND ADD-ONS: A number of new hooks for filters and add-ons to
101
+ further customize the behavior of FWP have been added.
102
+
103
+ * COMPATIBILITY/BUGFIX: Many users saw odd characters, especially "n,"
104
+ appearing in posts in versions of WordPress from 3.6 on, due to a change
105
+ in when the API expects HTML data for posts to be slashed and when it
106
+ does not. This has been fixed, so that the junk characters should no
107
+ longer appear, regardless of your version of WordPress.
108
+
109
+ * BUGFIX: A bug preventing FWP from saving categories assigned under
110
+ Syndication > Categories & Tags has been fixed.
111
+
112
+ * BUGFIX: Post-editing related metaboxes should now show up when you edit
113
+ items of any post type, including custom types, not only normal WordPress
114
+ posts.
115
+
116
+ * BUGFIX: A bug in the admin UI that caused the "Alternative Feeds" /
117
+ "Find Feeds" box to throw a permissions error has been fixed.
118
+
119
+ * BUGFIX: A bug preventing proper mapping of categories and other terms in
120
+ 2013.0504 has been fixed.
121
+
122
+ * BUGFIX: A number of small fixes contributed through Github by Flynsarmy
123
+ should eliminate PHP warnings for many users on several methods that are
124
+ called as static methods within FeedWordPress.
125
 
126
+ = 2013.0504 =
127
+
128
  * BUGFIX: PHP 5.4 compatibility -- includes some more extensive fixes to
129
  compatibility issues with PHP 5.4's handling of global variables
130
 
131
+ * DIAGNOSTICS: New diagnostics settings added to help track behavior of
132
+ terms (categories, post tags, etc.) for syndicated posts.
133
+
134
+ = 2012.0504 =
135
+
136
+ * MODULE REORGANIZATION: Should ensure that all needed submodules will be
137
  properly included regardless of whether you are installing from github,
138
  from SVN, or from the WordPress plugins page. If you've been getting
139
  fatal errors about required modules not being found, this release should
syndicatedlink.class.php CHANGED
@@ -25,7 +25,7 @@
25
  # backslashes (so, for example, a newline becomes "\n").
26
  #
27
  # The value of `cats` is used as a newline-separated list of
28
- # default categories for any post coming from a particular feed.
29
  # (In the example above, any posts from this feed will be placed
30
  # in the "computers" and "web" categories--*in addition to* any
31
  # categories that may already be applied to the posts.)
@@ -40,7 +40,7 @@ class SyndicatedLink {
40
  var $id = null;
41
  var $link = null;
42
  var $settings = array ();
43
- var $simplepie = null;
44
  var $magpie = null;
45
 
46
  function SyndicatedLink ($link) {
@@ -50,17 +50,17 @@ class SyndicatedLink {
50
  $this->link = $link;
51
  $this->id = $link->link_id;
52
  else :
53
- $this->id = $link;
54
  $this->link = get_bookmark($link);
55
  endif;
56
 
57
  if (strlen($this->link->link_rss) > 0) :
58
  $this->get_settings_from_notes();
59
  endif;
60
-
61
  add_filter('feedwordpress_update_complete', array($this, 'process_retirements'), 1000, 1);
62
  } /* SyndicatedLink::SyndicatedLink () */
63
-
64
  function found () {
65
  return is_object($this->link) and !is_wp_error($this->link);
66
  } /* SyndicatedLink::found () */
@@ -68,10 +68,10 @@ class SyndicatedLink {
68
  function id () {
69
  return (is_object($this->link) ? $this->link->link_id : NULL);
70
  }
71
-
72
  function stale () {
73
  global $feedwordpress;
74
-
75
  $stale = true;
76
  if ($this->setting('update/hold')=='ping') :
77
  $stale = false; // don't update on any timed updates; pings only
@@ -112,7 +112,7 @@ class SyndicatedLink {
112
  if (!is_object($this->simplepie)) :
113
  $this->fetch();
114
  endif;
115
-
116
  if (is_object($this->simplepie) and method_exists($this->simplepie, 'get_items')) :
117
  $ret = apply_filters(
118
  'syndicated_feed_items',
@@ -124,11 +124,11 @@ class SyndicatedLink {
124
  endif;
125
  return $ret;
126
  }
127
-
128
  function poll ($crash_ts = NULL) {
129
  global $wpdb;
130
 
131
- $url = $this->uri(array('add_params' => true));
132
  FeedWordPress::diagnostic('updated_feeds', 'Polling feed ['.$url.']');
133
 
134
  $this->fetch();
@@ -160,7 +160,7 @@ class SyndicatedLink {
160
  if (!is_null($oldError)) :
161
  // Copy over the in-error-since timestamp
162
  $theError['since'] = $oldError['since'];
163
-
164
  // If this is a repeat error, then we should
165
  // take a step back before we try to fetch it
166
  // again.
@@ -171,9 +171,9 @@ class SyndicatedLink {
171
  $this->update_setting('update/ttl', $ttl, $this);
172
  $this->update_setting('update/timed', 'automatically');
173
  endif;
174
-
175
  do_action('syndicated_feed_error', $theError, $oldError, $this);
176
-
177
  $this->update_setting('update/error', serialize($theError));
178
  $this->save_settings(/*reload=*/ true);
179
 
@@ -189,21 +189,21 @@ class SyndicatedLink {
189
  if (!isset($channel['id'])) :
190
  $channel['id'] = $this->link->link_rss;
191
  endif;
192
-
193
  $update = array();
194
  if (!$this->hardcode('url') and isset($channel['link'])) :
195
- $update[] = "link_url = '".$wpdb->escape($channel['link'])."'";
196
  endif;
197
-
198
  if (!$this->hardcode('name') and isset($channel['title'])) :
199
- $update[] = "link_name = '".$wpdb->escape($channel['title'])."'";
200
  endif;
201
-
202
  if (!$this->hardcode('description')) :
203
  if (isset($channel['tagline'])) :
204
- $update[] = "link_description = '".$wpdb->escape($channel['tagline'])."'";
205
  elseif (isset($channel['description'])) :
206
- $update[] = "link_description = '".$wpdb->escape($channel['description'])."'";
207
  endif;
208
  endif;
209
 
@@ -211,7 +211,7 @@ class SyndicatedLink {
211
 
212
  $this->update_setting('update/last', time());
213
  list($ttl, $xml) = $this->ttl(/*return element=*/ true);
214
-
215
  if (!is_null($ttl)) :
216
  $this->update_setting('update/ttl', $ttl);
217
  $this->update_setting('update/xml', $xml);
@@ -235,10 +235,10 @@ class SyndicatedLink {
235
 
236
  $this->update_setting('update/unfinished', 'yes');
237
 
238
- $update[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
239
 
240
  $update_set = implode(',', $update);
241
-
242
  // Update the properties of the link from the feed information
243
  $result = $wpdb->query("
244
  UPDATE $wpdb->links
@@ -251,12 +251,12 @@ class SyndicatedLink {
251
  $crashed = false;
252
 
253
  $posts = $this->live_posts();
254
-
255
  $this->magpie->originals = $posts;
256
 
257
  // If this is a complete feed, rather than an incremental feed, we
258
  // need to prepare to mark everything for presumptive retirement.
259
- if ($this->is_incremental()) :
260
  $q = new WP_Query(array(
261
  'fields' => '_synfrom',
262
  'post_status__not' => 'fwpretired',
@@ -268,7 +268,7 @@ class SyndicatedLink {
268
  update_post_meta($p->ID, '_feedwordpress_retire_me_'.$this->id, '1');
269
  endforeach;
270
  endif;
271
-
272
  if (is_array($posts)) :
273
  foreach ($posts as $key => $item) :
274
  $post = new SyndicatedPost($item, $this);
@@ -288,7 +288,7 @@ class SyndicatedLink {
288
  unset($post);
289
  endforeach;
290
  endif;
291
-
292
  if ('yes'==$this->setting('tombstones', 'tombstones', 'yes')) :
293
  // Check for use of Atom tombstones. Spec:
294
  // <http://tools.ietf.org/html/draft-snell-atompub-tombstones-18>
@@ -302,25 +302,25 @@ class SyndicatedLink {
302
  $ref = $tombstone['attribs'][$ns]['ref'];
303
  endif;
304
  endforeach;
305
-
306
  $q = new WP_Query(array(
307
  'ignore_sticky_posts' => true,
308
  'guid' => $ref,
309
  'meta_key' => 'syndication_feed_id',
310
  'meta_value' => $this->id, // Only allow a feed to tombstone its own entries.
311
  ));
312
-
313
  foreach ($q->posts as $p) :
314
  $old_status = $p->post_status;
315
  FeedWordPress::diagnostic('syndicated_posts', 'Retiring existing post # '.$p->ID.' "'.$p->post_title.'" due to Atom tombstone element in feed.');
316
  set_post_field('post_status', 'fwpretired', $p->ID);
317
  wp_transition_post_status('fwpretired', $old_status, $p);
318
  endforeach;
319
-
320
  endforeach;
321
  endif;
322
  endif;
323
-
324
  $suffix = ($crashed ? 'crashed' : 'completed');
325
  do_action('update_syndicated_feed_items', $this->id, $this);
326
  do_action("update_syndicated_feed_items_${suffix}", $this->id, $this);
@@ -333,28 +333,28 @@ class SyndicatedLink {
333
 
334
  // Copy back any changes to feed settings made in the
335
  // course of updating (e.g. new author rules)
336
- $update_set = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
337
-
338
  // Update the properties of the link from the feed information
339
  $result = $wpdb->query("
340
  UPDATE $wpdb->links
341
  SET $update_set
342
  WHERE link_id='$this->id'
343
  ");
344
-
345
  do_action("update_syndicated_feed_completed", $this->id, $this);
346
  endif;
347
-
348
  // All done; let's clean up.
349
  $this->magpie = NULL;
350
-
351
  // Avoid circular-reference memory leak in PHP < 5.3.
352
  // Cf. <http://simplepie.org/wiki/faq/i_m_getting_memory_leaks>
353
  if (method_exists($this->simplepie, '__destruct')) :
354
  $this->simplepie->__destruct();
355
  endif;
356
  $this->simplepie = NULL;
357
-
358
  return $new_count;
359
  } /* SyndicatedLink::poll() */
360
 
@@ -377,9 +377,10 @@ class SyndicatedLink {
377
  delete_post_meta($p->ID, '_feedwordpress_retire_me_'.$this->id);
378
  endforeach;
379
  endif;
 
380
  return $delta;
381
  }
382
-
383
  /**
384
  * Updates the URL for the feed syndicated by this link.
385
  *
@@ -394,50 +395,50 @@ class SyndicatedLink {
394
  $result = $wpdb->query("
395
  UPDATE $wpdb->links
396
  SET
397
- link_rss = '".$wpdb->escape($url)."'
398
- WHERE link_id = '".$wpdb->escape($this->id)."'
399
  ");
400
-
401
  $ret = ($result ? true : false);
402
  else :
403
  $ret = false;
404
  endif;
405
  return $ret;
406
  } /* SyndicatedLink::set_uri () */
407
-
408
  function deactivate () {
409
  global $wpdb;
410
-
411
  $wpdb->query($wpdb->prepare("
412
  UPDATE $wpdb->links SET link_visible = 'N' WHERE link_id = %d
413
  ", (int) $this->id));
414
  } /* SyndicatedLink::deactivate () */
415
-
416
  function delete () {
417
  global $wpdb;
418
-
419
  $wpdb->query($wpdb->prepare("
420
  DELETE FROM $wpdb->postmeta WHERE meta_key='syndication_feed_id'
421
  AND meta_value = '%s'
422
  ", $this->id));
423
-
424
  $wpdb->query($wpdb->prepare("
425
  DELETE FROM $wpdb->links WHERE link_id = %d
426
  ", (int) $this->id));
427
-
428
  $this->id = NULL;
429
  } /* SyndicatedLink::delete () */
430
-
431
  function nuke () {
432
  global $wpdb;
433
-
434
  // Make a list of the items syndicated from this feed...
435
  $post_ids = $wpdb->get_col($wpdb->prepare("
436
  SELECT post_id FROM $wpdb->postmeta
437
  WHERE meta_key = 'syndication_feed_id'
438
  AND meta_value = '%s'
439
  ", $this->id));
440
-
441
  // ... and kill them all
442
  if (count($post_ids) > 0) :
443
  foreach ($post_ids as $post_id) :
@@ -449,10 +450,10 @@ class SyndicatedLink {
449
  );
450
  endforeach;
451
  endif;
452
-
453
  $this->delete();
454
  } /* SyndicatedLink::nuke () */
455
-
456
  function map_name_to_new_user ($name, $newuser_name) {
457
  global $wpdb;
458
 
@@ -477,7 +478,7 @@ class SyndicatedLink {
477
  function imploded_settings () {
478
  return array('cats', 'tags', 'match/cats', 'match/tags', 'match/filter');
479
  }
480
-
481
  function get_settings_from_notes () {
482
  // Read off feed settings from link_notes
483
  $notes = explode("\n", $this->link->link_notes);
@@ -497,7 +498,7 @@ class SyndicatedLink {
497
  $this->settings['link/uri'] = $this->link->link_rss;
498
  $this->settings['link/name'] = $this->link->link_name;
499
  $this->settings['link/id'] = $this->link->link_id;
500
-
501
  // `hardcode categories` and `unfamiliar categories` are
502
  // deprecated in favor of `unfamiliar category`
503
  if (
@@ -516,7 +517,7 @@ class SyndicatedLink {
516
  // Set this up automagically for del.icio.us
517
  $bits = parse_url($this->link->link_rss);
518
  $tagspacers = array('del.icio.us', 'feeds.delicious.com');
519
- if (!isset($this->settings['cat_split']) and in_array($bits['host'], $tagspacers)) :
520
  $this->settings['cat_split'] = '\s'; // Whitespace separates multiple tags in del.icio.us RSS feeds
521
  endif;
522
 
@@ -533,7 +534,7 @@ class SyndicatedLink {
533
  if (isset($this->settings['terms'])) :
534
  // Look for new format
535
  $this->settings['terms'] = maybe_unserialize($this->settings['terms']);
536
-
537
  if (!is_array($this->settings['terms'])) :
538
  // Deal with old format instead. Ugh.
539
 
@@ -566,19 +567,19 @@ class SyndicatedLink {
566
  $ma = array();
567
  foreach ($author_rules as $rule) :
568
  list($rule_type, $author_name, $author_action) = explode("\n", $rule);
569
-
570
  // Normalize for case and whitespace
571
  $rule_type = strtolower(trim($rule_type));
572
  $author_name = strtolower(trim($author_name));
573
  $author_action = strtolower(trim($author_action));
574
-
575
  $ma[$rule_type][$author_name] = $author_action;
576
  endforeach;
577
  $this->settings['map authors'] = $ma;
578
  endif;
579
 
580
  } /* SyndicatedLink::get_settings_from_notes () */
581
-
582
  function settings_to_notes () {
583
  $to_notes = $this->settings;
584
 
@@ -601,12 +602,12 @@ class SyndicatedLink {
601
  );
602
  endif;
603
  endforeach;
604
-
605
  if (isset($to_notes['terms']) and is_array($to_notes['terms'])) :
606
  // Serialize it.
607
  $to_notes['terms'] = serialize($to_notes['terms']);
608
  endif;
609
-
610
  // Collapse the author mapping rule structure back into a flat string
611
  if (isset($to_notes['map authors'])) :
612
  $ma = array();
@@ -630,11 +631,11 @@ class SyndicatedLink {
630
 
631
  // Save channel-level meta-data
632
  foreach (array('link_name', 'link_description', 'link_url') as $what) :
633
- $alter[] = "{$what} = '".$wpdb->escape($this->link->{$what})."'";
634
  endforeach;
635
 
636
  // Save settings to the notes field
637
- $alter[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
638
 
639
  // Update the properties of the link from settings changes, etc.
640
  $update_set = implode(", ", $alter);
@@ -644,7 +645,7 @@ class SyndicatedLink {
644
  SET $update_set
645
  WHERE link_id='$this->id'
646
  ");
647
-
648
  if ($reload) :
649
  // force reload of link information from DB
650
  if (function_exists('clean_bookmark_cache')) :
@@ -667,7 +668,7 @@ class SyndicatedLink {
667
  if (isset($this->settings[$name])) :
668
  $ret = $this->settings[$name];
669
  endif;
670
-
671
  $no_value = (
672
  is_null($ret)
673
  or (is_string($ret) and strtolower($ret)==$default)
@@ -676,8 +677,13 @@ class SyndicatedLink {
676
  if ($no_value and !is_null($fallback_global)) :
677
  // Avoid duplication of this correction
678
  $fallback_global = preg_replace('/^feedwordpress_/', '', $fallback_global);
679
-
680
- $ret = get_option('feedwordpress_'.$fallback_global, /*default=*/ NULL);
 
 
 
 
 
681
  endif;
682
 
683
  $no_value = (
@@ -695,7 +701,7 @@ class SyndicatedLink {
695
  $dd = $this->flatten_array($data, $prefix, $separator);
696
  $this->settings = array_merge($this->settings, $dd);
697
  } /* SyndicatedLink::merge_settings () */
698
-
699
  function update_setting ($name, $value, $default = 'default') {
700
  if (!is_null($value) and $value != $default) :
701
  $this->settings[$name] = $value;
@@ -703,48 +709,55 @@ class SyndicatedLink {
703
  unset($this->settings[$name]);
704
  endif;
705
  } /* SyndicatedLink::update_setting () */
706
-
707
- function is_incremental () {
708
  return ('complete'==$this->setting('update_incremental', 'update_incremental', 'incremental'));
709
- } /* SyndicatedLink::is_incremental () */
710
-
711
  function uri ($params = array()) {
712
  $params = wp_parse_args($params, array(
713
  'add_params' => false,
 
714
  ));
715
-
716
- $uri = (is_object($this->link) ? $this->link->link_rss : NULL);
 
 
717
  if (!is_null($uri) and strlen($uri) > 0 and $params['add_params']) :
718
  $qp = maybe_unserialize($this->setting('query parameters', array()));
719
-
720
  // For high-tech HTTP feed request kung fu
721
  $qp = apply_filters('syndicated_feed_parameters', $qp, $uri, $this);
722
-
723
  $q = array();
724
  if (is_array($qp) and count($qp) > 0) :
725
  foreach ($qp as $pair) :
726
  $q[] = urlencode($pair[0]).'='.urlencode($pair[1]);
727
  endforeach;
728
-
729
  // Are we appending to a URI that already has params?
730
  $sep = ((strpos($uri, "?")===false) ? '?' : '&');
731
-
732
  // Tack it on
733
  $uri .= $sep . implode("&", $q);
734
- endif;
735
  endif;
736
-
 
 
 
 
737
  return $uri;
738
  } /* SyndicatedLink::uri () */
739
 
740
  function username () {
741
  return $this->setting('http username', 'http_username', NULL);
742
  } /* SyndicatedLink::username () */
743
-
744
  function password () {
745
  return $this->setting('http password', 'http_password', NULL);
746
  } /* SyndicatedLink::password () */
747
-
748
  function authentication_method () {
749
  $auth = $this->setting('http auth method', NULL);
750
  if (('-' == $auth) or (strlen($auth)==0)) :
@@ -753,7 +766,7 @@ class SyndicatedLink {
753
  return $auth;
754
  } /* SyndicatedLink::authentication_method () */
755
 
756
- var $postmeta = array();
757
  function postmeta ($params = array()) {
758
  $params = wp_parse_args($params, /*defaults=*/ array(
759
  "field" => NULL,
@@ -770,7 +783,7 @@ class SyndicatedLink {
770
  if (!is_array($default_custom_settings)) :
771
  $default_custom_settings = array();
772
  endif;
773
-
774
  // Next, get the settings for this particular feed.
775
  $custom_settings = $this->setting('postmeta', NULL, NULL);
776
  if ($custom_settings and !is_array($custom_settings)) :
@@ -779,10 +792,10 @@ class SyndicatedLink {
779
  if (!is_array($custom_settings)) :
780
  $custom_settings = array();
781
  endif;
782
-
783
  $this->postmeta[/*parsed=*/ false] = array_merge($default_custom_settings, $custom_settings);
784
  $this->postmeta[/*parsed=*/ true] = array();
785
-
786
  // Now, run through and parse them all.
787
  foreach ($this->postmeta[/*parsed=*/ false] as $key => $meta) :
788
  $meta = apply_filters("syndicated_link_post_meta_${key}_pre", $meta, $this);
@@ -797,12 +810,12 @@ class SyndicatedLink {
797
  endif;
798
  return $ret;
799
  } /* SyndicatedLink::postmeta () */
800
-
801
  function property_cascade ($fromFeed, $link_field, $setting, $method) {
802
  $value = NULL;
803
  if ($fromFeed) :
804
  $value = $this->setting($setting, NULL, NULL, NULL);
805
-
806
  $s = $this->simplepie;
807
  $callable = (is_object($s) and method_exists($s, $method));
808
  if (is_null($value) and $callable) :
@@ -813,7 +826,7 @@ class SyndicatedLink {
813
  endif;
814
  return $value;
815
  } /* SyndicatedLink::property_cascade () */
816
-
817
  function homepage ($fromFeed = true) {
818
  return $this->property_cascade($fromFeed, 'link_url', 'feed/link', 'get_link');
819
  } /* SyndicatedLink::homepage () */
@@ -824,17 +837,18 @@ class SyndicatedLink {
824
 
825
  function guid () {
826
  $ret = $this->setting('feed/id', NULL, $this->uri());
827
-
828
  // If we can get it live from the feed, do so.
829
  if (is_object($this->simplepie)) :
830
  $search = array(
 
831
  array(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'),
832
  array(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'),
833
  array(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'),
834
  array(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'),
835
  array(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'),
836
  );
837
-
838
  foreach ($search as $pair) :
839
  if ($id_tags = $this->simplepie->get_feed_tags($pair[0], $pair[1])) :
840
  $ret = $id_tags[0]['data'];
@@ -848,6 +862,60 @@ class SyndicatedLink {
848
  return $ret;
849
  }
850
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
851
  function ttl ($return_element = false) {
852
  if (is_object($this->magpie)) :
853
  $channel = $this->magpie->channel;
@@ -859,7 +927,7 @@ class SyndicatedLink {
859
  // "ttl stands for time to live. It's a number of
860
  // minutes that indicates how long a channel can be
861
  // cached before refreshing from the source."
862
- // <http://blogs.law.harvard.edu/tech/rss#ltttlgtSubelementOfLtchannelgt>
863
  $xml = 'rss:ttl';
864
  $ret = $channel['ttl'];
865
  elseif (isset($channel['sy']['updatefrequency']) or isset($channel['sy']['updateperiod'])) :
@@ -878,8 +946,8 @@ class SyndicatedLink {
878
  if (isset($channel['sy']['updateperiod'])) : $period = $channel['sy']['updateperiod'];
879
  else : $period = 'daily';
880
  endif;
881
-
882
- // "sy:updateFrequency: Used to describe the frequency
883
  // of updates in relation to the update period. A
884
  // positive integer indicates how many times in that
885
  // period the channel is updated. ... If omitted a value
@@ -887,17 +955,17 @@ class SyndicatedLink {
887
  if (isset($channel['sy']['updatefrequency'])) : $freq = (int) $channel['sy']['updatefrequency'];
888
  else : $freq = 1;
889
  endif;
890
-
891
  $xml = 'sy:updateFrequency';
892
  $ret = (int) ($period_minutes[$period] / $freq);
893
  else :
894
  $xml = NULL;
895
  $ret = NULL;
896
  endif;
897
-
898
  if ('yes'==$this->setting('update/minimum', 'update_minimum', 'no')) :
899
  $min = (int) $this->setting('update/window', 'update_window', DEFAULT_UPDATE_PERIOD);
900
-
901
  if ($min > $ret) :
902
  $ret = NULL;
903
  endif;
@@ -942,9 +1010,9 @@ class SyndicatedLink {
942
  } /* SyndicatedLink::flatten_array () */
943
 
944
  function hardcode ($what) {
945
-
946
  $ret = $this->setting('hardcode '.$what, 'hardcode_'.$what, NULL);
947
-
948
  if ('yes' == $ret) :
949
  $ret = true;
950
  else :
@@ -959,13 +1027,119 @@ class SyndicatedLink {
959
  $g_set = ($fallback ? 'syndicated_' . $what . '_status' : NULL);
960
  $ret = $this->setting($what.' status', $g_set, $default);
961
 
962
- return $wpdb->escape(trim(strtolower($ret)));
963
  } /* SyndicatedLink:syndicated_status () */
964
-
965
  function taxonomies () {
966
  $post_type = $this->setting('syndicated post type', 'syndicated_post_type', 'post');
967
  return get_object_taxonomies(array('object_type' => $post_type), 'names');
968
  } /* SyndicatedLink::taxonomies () */
969
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
970
  } // class SyndicatedLink
971
 
25
  # backslashes (so, for example, a newline becomes "\n").
26
  #
27
  # The value of `cats` is used as a newline-separated list of
28
+ # default categories for any post coming from a particular feed.
29
  # (In the example above, any posts from this feed will be placed
30
  # in the "computers" and "web" categories--*in addition to* any
31
  # categories that may already be applied to the posts.)
40
  var $id = null;
41
  var $link = null;
42
  var $settings = array ();
43
+ public $simplepie = null;
44
  var $magpie = null;
45
 
46
  function SyndicatedLink ($link) {
50
  $this->link = $link;
51
  $this->id = $link->link_id;
52
  else :
53
+ $this->id = $link;
54
  $this->link = get_bookmark($link);
55
  endif;
56
 
57
  if (strlen($this->link->link_rss) > 0) :
58
  $this->get_settings_from_notes();
59
  endif;
60
+
61
  add_filter('feedwordpress_update_complete', array($this, 'process_retirements'), 1000, 1);
62
  } /* SyndicatedLink::SyndicatedLink () */
63
+
64
  function found () {
65
  return is_object($this->link) and !is_wp_error($this->link);
66
  } /* SyndicatedLink::found () */
68
  function id () {
69
  return (is_object($this->link) ? $this->link->link_id : NULL);
70
  }
71
+
72
  function stale () {
73
  global $feedwordpress;
74
+
75
  $stale = true;
76
  if ($this->setting('update/hold')=='ping') :
77
  $stale = false; // don't update on any timed updates; pings only
112
  if (!is_object($this->simplepie)) :
113
  $this->fetch();
114
  endif;
115
+
116
  if (is_object($this->simplepie) and method_exists($this->simplepie, 'get_items')) :
117
  $ret = apply_filters(
118
  'syndicated_feed_items',
124
  endif;
125
  return $ret;
126
  }
127
+
128
  function poll ($crash_ts = NULL) {
129
  global $wpdb;
130
 
131
+ $url = $this->uri(array('add_params' => true, 'fetch' => true));
132
  FeedWordPress::diagnostic('updated_feeds', 'Polling feed ['.$url.']');
133
 
134
  $this->fetch();
160
  if (!is_null($oldError)) :
161
  // Copy over the in-error-since timestamp
162
  $theError['since'] = $oldError['since'];
163
+
164
  // If this is a repeat error, then we should
165
  // take a step back before we try to fetch it
166
  // again.
171
  $this->update_setting('update/ttl', $ttl, $this);
172
  $this->update_setting('update/timed', 'automatically');
173
  endif;
174
+
175
  do_action('syndicated_feed_error', $theError, $oldError, $this);
176
+
177
  $this->update_setting('update/error', serialize($theError));
178
  $this->save_settings(/*reload=*/ true);
179
 
189
  if (!isset($channel['id'])) :
190
  $channel['id'] = $this->link->link_rss;
191
  endif;
192
+
193
  $update = array();
194
  if (!$this->hardcode('url') and isset($channel['link'])) :
195
+ $update[] = "link_url = '".esc_sql($channel['link'])."'";
196
  endif;
197
+
198
  if (!$this->hardcode('name') and isset($channel['title'])) :
199
+ $update[] = "link_name = '".esc_sql($channel['title'])."'";
200
  endif;
201
+
202
  if (!$this->hardcode('description')) :
203
  if (isset($channel['tagline'])) :
204
+ $update[] = "link_description = '".esc_sql($channel['tagline'])."'";
205
  elseif (isset($channel['description'])) :
206
+ $update[] = "link_description = '".esc_sql($channel['description'])."'";
207
  endif;
208
  endif;
209
 
211
 
212
  $this->update_setting('update/last', time());
213
  list($ttl, $xml) = $this->ttl(/*return element=*/ true);
214
+
215
  if (!is_null($ttl)) :
216
  $this->update_setting('update/ttl', $ttl);
217
  $this->update_setting('update/xml', $xml);
235
 
236
  $this->update_setting('update/unfinished', 'yes');
237
 
238
+ $update[] = "link_notes = '".esc_sql($this->settings_to_notes())."'";
239
 
240
  $update_set = implode(',', $update);
241
+
242
  // Update the properties of the link from the feed information
243
  $result = $wpdb->query("
244
  UPDATE $wpdb->links
251
  $crashed = false;
252
 
253
  $posts = $this->live_posts();
254
+
255
  $this->magpie->originals = $posts;
256
 
257
  // If this is a complete feed, rather than an incremental feed, we
258
  // need to prepare to mark everything for presumptive retirement.
259
+ if ($this->is_non_incremental()) :
260
  $q = new WP_Query(array(
261
  'fields' => '_synfrom',
262
  'post_status__not' => 'fwpretired',
268
  update_post_meta($p->ID, '_feedwordpress_retire_me_'.$this->id, '1');
269
  endforeach;
270
  endif;
271
+
272
  if (is_array($posts)) :
273
  foreach ($posts as $key => $item) :
274
  $post = new SyndicatedPost($item, $this);
288
  unset($post);
289
  endforeach;
290
  endif;
291
+
292
  if ('yes'==$this->setting('tombstones', 'tombstones', 'yes')) :
293
  // Check for use of Atom tombstones. Spec:
294
  // <http://tools.ietf.org/html/draft-snell-atompub-tombstones-18>
302
  $ref = $tombstone['attribs'][$ns]['ref'];
303
  endif;
304
  endforeach;
305
+
306
  $q = new WP_Query(array(
307
  'ignore_sticky_posts' => true,
308
  'guid' => $ref,
309
  'meta_key' => 'syndication_feed_id',
310
  'meta_value' => $this->id, // Only allow a feed to tombstone its own entries.
311
  ));
312
+
313
  foreach ($q->posts as $p) :
314
  $old_status = $p->post_status;
315
  FeedWordPress::diagnostic('syndicated_posts', 'Retiring existing post # '.$p->ID.' "'.$p->post_title.'" due to Atom tombstone element in feed.');
316
  set_post_field('post_status', 'fwpretired', $p->ID);
317
  wp_transition_post_status('fwpretired', $old_status, $p);
318
  endforeach;
319
+
320
  endforeach;
321
  endif;
322
  endif;
323
+
324
  $suffix = ($crashed ? 'crashed' : 'completed');
325
  do_action('update_syndicated_feed_items', $this->id, $this);
326
  do_action("update_syndicated_feed_items_${suffix}", $this->id, $this);
333
 
334
  // Copy back any changes to feed settings made in the
335
  // course of updating (e.g. new author rules)
336
+ $update_set = "link_notes = '".esc_sql($this->settings_to_notes())."'";
337
+
338
  // Update the properties of the link from the feed information
339
  $result = $wpdb->query("
340
  UPDATE $wpdb->links
341
  SET $update_set
342
  WHERE link_id='$this->id'
343
  ");
344
+
345
  do_action("update_syndicated_feed_completed", $this->id, $this);
346
  endif;
347
+
348
  // All done; let's clean up.
349
  $this->magpie = NULL;
350
+
351
  // Avoid circular-reference memory leak in PHP < 5.3.
352
  // Cf. <http://simplepie.org/wiki/faq/i_m_getting_memory_leaks>
353
  if (method_exists($this->simplepie, '__destruct')) :
354
  $this->simplepie->__destruct();
355
  endif;
356
  $this->simplepie = NULL;
357
+
358
  return $new_count;
359
  } /* SyndicatedLink::poll() */
360
 
377
  delete_post_meta($p->ID, '_feedwordpress_retire_me_'.$this->id);
378
  endforeach;
379
  endif;
380
+
381
  return $delta;
382
  }
383
+
384
  /**
385
  * Updates the URL for the feed syndicated by this link.
386
  *
395
  $result = $wpdb->query("
396
  UPDATE $wpdb->links
397
  SET
398
+ link_rss = '".esc_sql($url)."'
399
+ WHERE link_id = '".esc_sql($this->id)."'
400
  ");
401
+
402
  $ret = ($result ? true : false);
403
  else :
404
  $ret = false;
405
  endif;
406
  return $ret;
407
  } /* SyndicatedLink::set_uri () */
408
+
409
  function deactivate () {
410
  global $wpdb;
411
+
412
  $wpdb->query($wpdb->prepare("
413
  UPDATE $wpdb->links SET link_visible = 'N' WHERE link_id = %d
414
  ", (int) $this->id));
415
  } /* SyndicatedLink::deactivate () */
416
+
417
  function delete () {
418
  global $wpdb;
419
+
420
  $wpdb->query($wpdb->prepare("
421
  DELETE FROM $wpdb->postmeta WHERE meta_key='syndication_feed_id'
422
  AND meta_value = '%s'
423
  ", $this->id));
424
+
425
  $wpdb->query($wpdb->prepare("
426
  DELETE FROM $wpdb->links WHERE link_id = %d
427
  ", (int) $this->id));
428
+
429
  $this->id = NULL;
430
  } /* SyndicatedLink::delete () */
431
+
432
  function nuke () {
433
  global $wpdb;
434
+
435
  // Make a list of the items syndicated from this feed...
436
  $post_ids = $wpdb->get_col($wpdb->prepare("
437
  SELECT post_id FROM $wpdb->postmeta
438
  WHERE meta_key = 'syndication_feed_id'
439
  AND meta_value = '%s'
440
  ", $this->id));
441
+
442
  // ... and kill them all
443
  if (count($post_ids) > 0) :
444
  foreach ($post_ids as $post_id) :
450
  );
451
  endforeach;
452
  endif;
453
+
454
  $this->delete();
455
  } /* SyndicatedLink::nuke () */
456
+
457
  function map_name_to_new_user ($name, $newuser_name) {
458
  global $wpdb;
459
 
478
  function imploded_settings () {
479
  return array('cats', 'tags', 'match/cats', 'match/tags', 'match/filter');
480
  }
481
+
482
  function get_settings_from_notes () {
483
  // Read off feed settings from link_notes
484
  $notes = explode("\n", $this->link->link_notes);
498
  $this->settings['link/uri'] = $this->link->link_rss;
499
  $this->settings['link/name'] = $this->link->link_name;
500
  $this->settings['link/id'] = $this->link->link_id;
501
+
502
  // `hardcode categories` and `unfamiliar categories` are
503
  // deprecated in favor of `unfamiliar category`
504
  if (
517
  // Set this up automagically for del.icio.us
518
  $bits = parse_url($this->link->link_rss);
519
  $tagspacers = array('del.icio.us', 'feeds.delicious.com');
520
+ if (!isset($this->settings['cat_split']) and in_array($bits['host'], $tagspacers)) :
521
  $this->settings['cat_split'] = '\s'; // Whitespace separates multiple tags in del.icio.us RSS feeds
522
  endif;
523
 
534
  if (isset($this->settings['terms'])) :
535
  // Look for new format
536
  $this->settings['terms'] = maybe_unserialize($this->settings['terms']);
537
+
538
  if (!is_array($this->settings['terms'])) :
539
  // Deal with old format instead. Ugh.
540
 
567
  $ma = array();
568
  foreach ($author_rules as $rule) :
569
  list($rule_type, $author_name, $author_action) = explode("\n", $rule);
570
+
571
  // Normalize for case and whitespace
572
  $rule_type = strtolower(trim($rule_type));
573
  $author_name = strtolower(trim($author_name));
574
  $author_action = strtolower(trim($author_action));
575
+
576
  $ma[$rule_type][$author_name] = $author_action;
577
  endforeach;
578
  $this->settings['map authors'] = $ma;
579
  endif;
580
 
581
  } /* SyndicatedLink::get_settings_from_notes () */
582
+
583
  function settings_to_notes () {
584
  $to_notes = $this->settings;
585
 
602
  );
603
  endif;
604
  endforeach;
605
+
606
  if (isset($to_notes['terms']) and is_array($to_notes['terms'])) :
607
  // Serialize it.
608
  $to_notes['terms'] = serialize($to_notes['terms']);
609
  endif;
610
+
611
  // Collapse the author mapping rule structure back into a flat string
612
  if (isset($to_notes['map authors'])) :
613
  $ma = array();
631
 
632
  // Save channel-level meta-data
633
  foreach (array('link_name', 'link_description', 'link_url') as $what) :
634
+ $alter[] = "{$what} = '".esc_sql($this->link->{$what})."'";
635
  endforeach;
636
 
637
  // Save settings to the notes field
638
+ $alter[] = "link_notes = '".esc_sql($this->settings_to_notes())."'";
639
 
640
  // Update the properties of the link from settings changes, etc.
641
  $update_set = implode(", ", $alter);
645
  SET $update_set
646
  WHERE link_id='$this->id'
647
  ");
648
+
649
  if ($reload) :
650
  // force reload of link information from DB
651
  if (function_exists('clean_bookmark_cache')) :
668
  if (isset($this->settings[$name])) :
669
  $ret = $this->settings[$name];
670
  endif;
671
+
672
  $no_value = (
673
  is_null($ret)
674
  or (is_string($ret) and strtolower($ret)==$default)
677
  if ($no_value and !is_null($fallback_global)) :
678
  // Avoid duplication of this correction
679
  $fallback_global = preg_replace('/^feedwordpress_/', '', $fallback_global);
680
+
681
+ // Occasionally we'll get an array back. Convert it to a string
682
+ if ( is_array($fallback_global) && sizeof($fallback_global) )
683
+ $fallback_global = reset($fallback_global);
684
+
685
+ if ( !empty($fallback_global) )
686
+ $ret = get_option('feedwordpress_'.$fallback_global, /*default=*/ NULL);
687
  endif;
688
 
689
  $no_value = (
701
  $dd = $this->flatten_array($data, $prefix, $separator);
702
  $this->settings = array_merge($this->settings, $dd);
703
  } /* SyndicatedLink::merge_settings () */
704
+
705
  function update_setting ($name, $value, $default = 'default') {
706
  if (!is_null($value) and $value != $default) :
707
  $this->settings[$name] = $value;
709
  unset($this->settings[$name]);
710
  endif;
711
  } /* SyndicatedLink::update_setting () */
712
+
713
+ function is_non_incremental () {
714
  return ('complete'==$this->setting('update_incremental', 'update_incremental', 'incremental'));
715
+ } /* SyndicatedLink::is_non_incremental () */
716
+
717
  function uri ($params = array()) {
718
  $params = wp_parse_args($params, array(
719
  'add_params' => false,
720
+ 'fetch' => false,
721
  ));
722
+
723
+ $link_rss = (is_object($this->link) ? $this->link->link_rss : NULL);
724
+
725
+ $uri = $link_rss;
726
  if (!is_null($uri) and strlen($uri) > 0 and $params['add_params']) :
727
  $qp = maybe_unserialize($this->setting('query parameters', array()));
728
+
729
  // For high-tech HTTP feed request kung fu
730
  $qp = apply_filters('syndicated_feed_parameters', $qp, $uri, $this);
731
+
732
  $q = array();
733
  if (is_array($qp) and count($qp) > 0) :
734
  foreach ($qp as $pair) :
735
  $q[] = urlencode($pair[0]).'='.urlencode($pair[1]);
736
  endforeach;
737
+
738
  // Are we appending to a URI that already has params?
739
  $sep = ((strpos($uri, "?")===false) ? '?' : '&');
740
+
741
  // Tack it on
742
  $uri .= $sep . implode("&", $q);
743
+ endif;
744
  endif;
745
+
746
+ // Do we have any filters that apply here?
747
+ $uri = apply_filters('syndicated_link_uri', $uri, $link_rss, $qp, $params, $this);
748
+
749
+ // Return the filtered link URI.
750
  return $uri;
751
  } /* SyndicatedLink::uri () */
752
 
753
  function username () {
754
  return $this->setting('http username', 'http_username', NULL);
755
  } /* SyndicatedLink::username () */
756
+
757
  function password () {
758
  return $this->setting('http password', 'http_password', NULL);
759
  } /* SyndicatedLink::password () */
760
+
761
  function authentication_method () {
762
  $auth = $this->setting('http auth method', NULL);
763
  if (('-' == $auth) or (strlen($auth)==0)) :
766
  return $auth;
767
  } /* SyndicatedLink::authentication_method () */
768
 
769
+ var $postmeta = array();
770
  function postmeta ($params = array()) {
771
  $params = wp_parse_args($params, /*defaults=*/ array(
772
  "field" => NULL,
783
  if (!is_array($default_custom_settings)) :
784
  $default_custom_settings = array();
785
  endif;
786
+
787
  // Next, get the settings for this particular feed.
788
  $custom_settings = $this->setting('postmeta', NULL, NULL);
789
  if ($custom_settings and !is_array($custom_settings)) :
792
  if (!is_array($custom_settings)) :
793
  $custom_settings = array();
794
  endif;
795
+
796
  $this->postmeta[/*parsed=*/ false] = array_merge($default_custom_settings, $custom_settings);
797
  $this->postmeta[/*parsed=*/ true] = array();
798
+
799
  // Now, run through and parse them all.
800
  foreach ($this->postmeta[/*parsed=*/ false] as $key => $meta) :
801
  $meta = apply_filters("syndicated_link_post_meta_${key}_pre", $meta, $this);
810
  endif;
811
  return $ret;
812
  } /* SyndicatedLink::postmeta () */
813
+
814
  function property_cascade ($fromFeed, $link_field, $setting, $method) {
815
  $value = NULL;
816
  if ($fromFeed) :
817
  $value = $this->setting($setting, NULL, NULL, NULL);
818
+
819
  $s = $this->simplepie;
820
  $callable = (is_object($s) and method_exists($s, $method));
821
  if (is_null($value) and $callable) :
826
  endif;
827
  return $value;
828
  } /* SyndicatedLink::property_cascade () */
829
+
830
  function homepage ($fromFeed = true) {
831
  return $this->property_cascade($fromFeed, 'link_url', 'feed/link', 'get_link');
832
  } /* SyndicatedLink::homepage () */
837
 
838
  function guid () {
839
  $ret = $this->setting('feed/id', NULL, $this->uri());
840
+
841
  // If we can get it live from the feed, do so.
842
  if (is_object($this->simplepie)) :
843
  $search = array(
844
+ array('', 'id'),
845
  array(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'),
846
  array(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'),
847
  array(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'),
848
  array(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'),
849
  array(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'),
850
  );
851
+
852
  foreach ($search as $pair) :
853
  if ($id_tags = $this->simplepie->get_feed_tags($pair[0], $pair[1])) :
854
  $ret = $id_tags[0]['data'];
862
  return $ret;
863
  }
864
 
865
+ function links ($params = array()) {
866
+ $params = wp_parse_args($params, array(
867
+ "rel" => NULL,
868
+ ));
869
+
870
+ $fLinks = array();
871
+ $search = array(
872
+ array('', 'link'),
873
+ array(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'),
874
+ array(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'),
875
+ );
876
+
877
+ foreach ($search as $pair) :
878
+ if ($link_tags = $this->simplepie->get_feed_tags($pair[0], $pair[1])) :
879
+ $fLinks = array_merge($fLinks, $link_tags);
880
+ endif;
881
+ if ($link_tags = $this->simplepie->get_channel_tags($pair[0], $pair[1])) :
882
+ $fLinks = array_merge($fLinks, $link_tags);
883
+ endif;
884
+ endforeach;
885
+
886
+ $ret = array();
887
+ foreach ($fLinks as $link) :
888
+ $filter = false;
889
+ if (!is_null($params['rel'])) :
890
+ $filter = true;
891
+
892
+ if (isset($link['attribs'])) :
893
+ // Get a list of NSes from the search
894
+ foreach ($search as $pair) :
895
+ $ns = $pair[0];
896
+
897
+ if (isset($link['attribs'][$ns])
898
+ and isset($link['attribs'][$ns]['rel'])
899
+ ) :
900
+ $rel = strtolower(trim($link['attribs'][$ns]['rel']));
901
+ $fRel = strtolower(trim($params['rel']));
902
+
903
+ if ($rel == $fRel) :
904
+ $filter = false;
905
+ endif;
906
+ endif;
907
+ endforeach;
908
+ endif;
909
+ endif;
910
+
911
+ if (!$filter) :
912
+ $ret[] = $link;
913
+ endif;
914
+ endforeach;
915
+
916
+ return $ret;
917
+ }
918
+
919
  function ttl ($return_element = false) {
920
  if (is_object($this->magpie)) :
921
  $channel = $this->magpie->channel;
927
  // "ttl stands for time to live. It's a number of
928
  // minutes that indicates how long a channel can be
929
  // cached before refreshing from the source."
930
+ // <http://blogs.law.harvard.edu/tech/rss#ltttlgtSubelementOfLtchannelgt>
931
  $xml = 'rss:ttl';
932
  $ret = $channel['ttl'];
933
  elseif (isset($channel['sy']['updatefrequency']) or isset($channel['sy']['updateperiod'])) :
946
  if (isset($channel['sy']['updateperiod'])) : $period = $channel['sy']['updateperiod'];
947
  else : $period = 'daily';
948
  endif;
949
+
950
+ // "sy:updateFrequency: Used to describe the frequency
951
  // of updates in relation to the update period. A
952
  // positive integer indicates how many times in that
953
  // period the channel is updated. ... If omitted a value
955
  if (isset($channel['sy']['updatefrequency'])) : $freq = (int) $channel['sy']['updatefrequency'];
956
  else : $freq = 1;
957
  endif;
958
+
959
  $xml = 'sy:updateFrequency';
960
  $ret = (int) ($period_minutes[$period] / $freq);
961
  else :
962
  $xml = NULL;
963
  $ret = NULL;
964
  endif;
965
+
966
  if ('yes'==$this->setting('update/minimum', 'update_minimum', 'no')) :
967
  $min = (int) $this->setting('update/window', 'update_window', DEFAULT_UPDATE_PERIOD);
968
+
969
  if ($min > $ret) :
970
  $ret = NULL;
971
  endif;
1010
  } /* SyndicatedLink::flatten_array () */
1011
 
1012
  function hardcode ($what) {
1013
+
1014
  $ret = $this->setting('hardcode '.$what, 'hardcode_'.$what, NULL);
1015
+
1016
  if ('yes' == $ret) :
1017
  $ret = true;
1018
  else :
1027
  $g_set = ($fallback ? 'syndicated_' . $what . '_status' : NULL);
1028
  $ret = $this->setting($what.' status', $g_set, $default);
1029
 
1030
+ return esc_sql(trim(strtolower($ret)));
1031
  } /* SyndicatedLink:syndicated_status () */
1032
+
1033
  function taxonomies () {
1034
  $post_type = $this->setting('syndicated post type', 'syndicated_post_type', 'post');
1035
  return get_object_taxonomies(array('object_type' => $post_type), 'names');
1036
  } /* SyndicatedLink::taxonomies () */
1037
+
1038
+ /**
1039
+ * category_ids: look up (and create) category ids from a list of
1040
+ * categories
1041
+ *
1042
+ * @param array $cats
1043
+ * @param string $unfamiliar_category
1044
+ * @param array|null $taxonomies
1045
+ * @return array
1046
+ */
1047
+ function category_ids ($post, $cats, $unfamiliar_category = 'create', $taxonomies = NULL, $params = array()) {
1048
+ $singleton = (isset($params['singleton']) ? $params['singleton'] : true);
1049
+ $allowFilters = (isset($params['filters']) ? $params['filters'] : false);
1050
+
1051
+ $catTax = 'category';
1052
+
1053
+ if (is_null($taxonomies)) :
1054
+ $taxonomies = array('category');
1055
+ endif;
1056
+
1057
+ // We need to normalize whitespace because (1) trailing
1058
+ // whitespace can cause PHP and MySQL not to see eye to eye on
1059
+ // VARCHAR comparisons for some versions of MySQL (cf.
1060
+ // <http://dev.mysql.com/doc/mysql/en/char.html>), and (2)
1061
+ // because I doubt most people want to make a semantic
1062
+ // distinction between 'Computers' and 'Computers '
1063
+ $cats = array_map('trim', $cats);
1064
+
1065
+ $terms = array();
1066
+ foreach ($taxonomies as $tax) :
1067
+ $terms[$tax] = array();
1068
+ endforeach;
1069
+
1070
+ foreach ($cats as $cat_name) :
1071
+ if (strlen(trim($cat_name)) < 1) :
1072
+ continue;
1073
+ endif;
1074
+
1075
+ $oTerm = new SyndicatedPostTerm($cat_name, $taxonomies, $post);
1076
+
1077
+ if ($oTerm->is_familiar()) :
1078
+
1079
+ $tax = $oTerm->taxonomy();
1080
+ if (!isset($terms[$tax])) :
1081
+ $terms[$tax] = array();
1082
+ endif;
1083
+ $terms[$tax][] = $oTerm->id();
1084
+
1085
+ else :
1086
+
1087
+ if ('tag'==$unfamiliar_category) :
1088
+ $unfamiliar_category = 'create:post_tag';
1089
+ endif;
1090
+
1091
+ if (preg_match('/^create(:(.*))?$/i', $unfamiliar_category, $ref)) :
1092
+ $tax = $catTax; // Default
1093
+
1094
+ if (isset($ref[2])
1095
+ and strlen($ref[2]) > 2) :
1096
+ $tax = $ref[2];
1097
+ endif;
1098
+
1099
+ $inserted = $oTerm->insert($tax);
1100
+ if (!is_null($inserted)) :
1101
+ if (!isset($terms[$tax])) :
1102
+ $terms[$tax] = array();
1103
+ endif;
1104
+ $terms[$tax][] = $inserted;
1105
+ else :
1106
+
1107
+ endif; // !is_null($inserted)
1108
+ endif; // preg_match(...)
1109
+
1110
+ endif; /* ($oTerm->is_familiar()) */
1111
+ endforeach;
1112
+
1113
+ $filtersOn = $allowFilters;
1114
+ if ($allowFilters) :
1115
+ $filters = array_filter(
1116
+ $this->setting('match/filter', 'match_filter', array()),
1117
+ 'remove_dummy_zero'
1118
+ );
1119
+ $filtersOn = ($filtersOn and is_array($filters) and (count($filters) > 0));
1120
+ endif;
1121
+
1122
+ // Check for filter conditions
1123
+ foreach ($terms as $tax => $term_ids) :
1124
+ if ($filtersOn
1125
+ and (count($term_ids)==0)
1126
+ and in_array($tax, $filters)) :
1127
+ $terms = NULL; // Drop the post
1128
+ break;
1129
+ else :
1130
+ $terms[$tax] = array_unique($term_ids);
1131
+ endif;
1132
+ endforeach;
1133
+
1134
+ if ($singleton and count($terms)==1) : // If we only searched one, just return the term IDs
1135
+ $terms = end($terms);
1136
+ endif;
1137
+
1138
+ FeedWordPress::diagnostic(
1139
+ 'syndicated_posts:categories',
1140
+ 'Category: MAPPED term names '.json_encode($cats).' to IDs: '.json_encode($terms)
1141
+ );
1142
+ return $terms;
1143
+ } /* SyndicatedLink::category_ids () */
1144
  } // class SyndicatedLink
1145
 
syndicatedpost.class.php CHANGED
@@ -1,5 +1,6 @@
1
  <?php
2
  require_once(dirname(__FILE__).'/feedtime.class.php');
 
3
 
4
  /**
5
  * class SyndicatedPost: FeedWordPress uses to manage the conversion of
@@ -10,7 +11,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 2011.0831
14
  */
15
  class SyndicatedPost {
16
  var $item = null; // MagpieRSS representation
@@ -19,7 +20,7 @@ class SyndicatedPost {
19
  var $link = null;
20
  var $feed = null;
21
  var $feedmeta = null;
22
-
23
  var $xmlns = array ();
24
 
25
  var $post = array ();
@@ -27,7 +28,7 @@ class SyndicatedPost {
27
  var $named = array ();
28
  var $preset_terms = array ();
29
  var $feed_terms = array ();
30
-
31
  var $_freshness = null;
32
  var $_wp_id = null;
33
  var $_wp_post = null;
@@ -44,6 +45,9 @@ class SyndicatedPost {
44
  function SyndicatedPost ($item, &$source) {
45
  global $wpdb;
46
 
 
 
 
47
  if (is_array($item)
48
  and isset($item['simplepie'])
49
  and isset($item['magpie'])) :
@@ -52,11 +56,11 @@ class SyndicatedPost {
52
  $item = $item['magpie'];
53
  elseif (is_a($item, 'SimplePie_Item')) :
54
  $this->entry = $item;
55
-
56
  // convert to Magpie for compat purposes
57
  $mp = new MagpieFromSimplePie($source->simplepie, $this->entry);
58
  $this->item = $mp->get_item();
59
-
60
  // done with conversion object
61
  $mp = NULL; unset($mp);
62
  else :
@@ -76,9 +80,9 @@ class SyndicatedPost {
76
  if (!isset($this->xmlns['reverse'][$ns])) :
77
  $this->xmlns['reverse'][$ns] = array();
78
  endif;
79
- $this->xmlns['reverse'][$ns][] = $url;
80
  endforeach;
81
-
82
  // Fucking SimplePie.
83
  $this->xmlns['reverse']['rss'][] = '';
84
 
@@ -100,7 +104,7 @@ class SyndicatedPost {
100
  // Trigger global syndicated_item filter.
101
  $changed = apply_filters('syndicated_item', $this->item, $this);
102
  $this->item = $changed;
103
-
104
  // Allow for feed-specific syndicated_item filters.
105
  $changed = apply_filters(
106
  "syndicated_item_".$source->uri(),
@@ -108,12 +112,12 @@ class SyndicatedPost {
108
  $this
109
  );
110
  $this->item = $changed;
111
-
112
  # Filters can halt further processing by returning NULL
113
  if (is_null($this->item)) :
114
  $this->post = NULL;
115
  else :
116
- # Note that nothing is run through $wpdb->escape() here.
117
  # That's deliberate. The escaping is done at the point
118
  # of insertion, not here, to avoid double-escaping and
119
  # to avoid screwing with syndicated_post filters
@@ -130,7 +134,7 @@ class SyndicatedPost {
130
  // This just gives us an alphanumeric name for the author.
131
  // We look up (or create) the numeric ID for the author
132
  // in SyndicatedPost::add().
133
-
134
  $this->post['post_content'] = apply_filters(
135
  'syndicated_item_content',
136
  $this->content(), $this
@@ -164,18 +168,18 @@ class SyndicatedPost {
164
  // overwrite if necessary; thus preventing any munging.
165
  $postMetaIn = $this->link->postmeta(array("parsed" => true));
166
  $postMetaOut = array();
167
-
168
  foreach ($postMetaIn as $key => $meta) :
169
  $postMetaOut[$key] = $meta->do_substitutions($this);
170
  endforeach;
171
-
172
  foreach ($postMetaOut as $key => $values) :
173
  $this->post['meta'][$key] = array();
174
  foreach ($values as $value) :
175
  $this->post['meta'][$key][] = apply_filters("syndicated_post_meta_{$key}", $value, $this);
176
  endforeach;
177
  endforeach;
178
-
179
  // RSS 2.0 / Atom 1.0 enclosure support
180
  $enclosures = $this->entry->get_enclosures();
181
  if (is_array($enclosures)) : foreach ($enclosures as $enclosure) :
@@ -187,7 +191,7 @@ class SyndicatedPost {
187
 
188
  // In case you want to point back to the blog this was
189
  // syndicated from.
190
-
191
  $sourcemeta['syndication_source'] = apply_filters(
192
  'syndicated_item_source_title',
193
  $this->link->name(),
@@ -203,7 +207,7 @@ class SyndicatedPost {
203
  $this->link->guid(),
204
  $this
205
  );
206
-
207
  // Make use of atom:source data, if present in an aggregated feed
208
  $entry_source = $this->source();
209
  if (!is_null($entry_source)) :
@@ -213,7 +217,7 @@ class SyndicatedPost {
213
  elseif ($what=='feed') : $key = 'syndication_feed';
214
  else : $key = "syndication_source_${what}";
215
  endif;
216
-
217
  $sourcemeta["${key}_original"] = apply_filters(
218
  'syndicated_item_original_source_'.$what,
219
  $value,
@@ -222,7 +226,7 @@ class SyndicatedPost {
222
  endif;
223
  endforeach;
224
  endif;
225
-
226
  foreach ($sourcemeta as $meta_key => $value) :
227
  if (!is_null($value)) :
228
  $this->post['meta'][$meta_key] = $value;
@@ -230,7 +234,7 @@ class SyndicatedPost {
230
  endforeach;
231
 
232
  // Store information on human-readable and machine-readable comment URIs
233
-
234
  // Human-readable comment URI
235
  $commentLink = apply_filters('syndicated_item_comments', $this->comment_link(), $this);
236
  if (!is_null($commentLink)) : $this->post['meta']['rss:comments'] = $commentLink; endif;
@@ -273,14 +277,14 @@ class SyndicatedPost {
273
  $cats = array_merge($cats, $fc);
274
  endif;
275
  $this->preset_terms['category'] = $cats;
276
-
277
  // Now add categories from the post, if we have 'em
278
  $cats = array();
279
  $post_cats = $this->entry->get_categories();
280
  if (is_array($post_cats)) : foreach ($post_cats as $cat) :
281
  $cat_name = $cat->get_term();
282
  if (!$cat_name) : $cat_name = $cat->get_label(); endif;
283
-
284
  if ($this->link->setting('cat_split', NULL, NULL)) :
285
  $pcre = "\007".$this->feedmeta['cat_split']."\007";
286
  $cats = array_merge(
@@ -298,24 +302,24 @@ class SyndicatedPost {
298
  endforeach; endif;
299
 
300
  $this->feed_terms['category'] = apply_filters('syndicated_item_categories', $cats, $this);
301
-
302
  // Tags: start with default tags, if any
303
  $tags = array();
304
  if ('no' != $this->link->setting('add/post_tag', NULL, 'yes')) :
305
  $ft = get_option("feedwordpress_syndication_tags", NULL);
306
  $tags = (is_null($ft) ? array() : explode(FEEDWORDPRESS_CAT_SEPARATOR, $ft));
307
  endif;
308
-
309
  $ft = $this->link->setting('tags', NULL, array());
310
  if (is_array($ft)) :
311
  $tags = array_merge($tags, $ft);
312
  endif;
313
  $this->preset_terms['post_tag'] = $tags;
314
-
315
  // Scan post for /a[@rel='tag'] and use as tags if present
316
  $tags = $this->inline_tags();
317
  $this->feed_terms['post_tag'] = apply_filters('syndicated_item_tags', $tags, $this);
318
-
319
  $taxonomies = $this->link->taxonomies();
320
  $feedTerms = $this->link->setting('terms', NULL, array());
321
  $globalTerms = get_option('feedwordpress_syndication_terms', array());
@@ -324,14 +328,14 @@ class SyndicatedPost {
324
  foreach ($taxonomies as $tax) :
325
  if (!isset($specials[$tax])) :
326
  $terms = array();
327
-
328
  // See if we should get the globals
329
  if ('no' != $this->link->setting("add/$tax", NULL, 'yes')) :
330
  if (isset($globalTerms[$tax])) :
331
  $terms = $globalTerms[$tax];
332
  endif;
333
  endif;
334
-
335
  // Now merge in the locals
336
  if (isset($feedTerms[$tax])) :
337
  $terms = array_merge($terms, $feedTerms[$tax]);
@@ -352,7 +356,7 @@ class SyndicatedPost {
352
 
353
  function substitution_function ($name) {
354
  $ret = NULL;
355
-
356
  switch ($name) :
357
  // Allowed PHP string functions
358
  case 'trim':
@@ -366,7 +370,7 @@ class SyndicatedPost {
366
  endswitch;
367
  return $ret;
368
  }
369
-
370
  /**
371
  * SyndicatedPost::query uses an XPath-like syntax to query arbitrary
372
  * elements within the syndicated item.
@@ -383,9 +387,9 @@ class SyndicatedPost {
383
  foreach ($match as $ref) :
384
  $urlHash[md5($ref[1])] = $ref[1];
385
  endforeach;
386
-
387
  foreach ($urlHash as $hash => $url) :
388
- $path = str_replace('{'.$url.'}', '{#'.$hash.'}', $path);
389
  endforeach;
390
 
391
  $path = explode('/', $path);
@@ -406,7 +410,7 @@ class SyndicatedPost {
406
  while (strlen($node)==0 and !is_null($node)) :
407
  $node = array_shift($path);
408
  endwhile;
409
-
410
  switch ($node) :
411
  case 'feed' :
412
  case 'channel' :
@@ -440,7 +444,7 @@ class SyndicatedPost {
440
  $addenda = $elements[$element];
441
  $contexts = $elements[$element];
442
  endif;
443
-
444
  foreach ($addenda as $index => $addendum) :
445
  $context = $contexts[$index];
446
 
@@ -450,15 +454,15 @@ class SyndicatedPost {
450
  endif;
451
  endforeach;
452
  endif;
453
- endforeach;
454
  endif;
455
  endforeach;
456
-
457
  $data = $matches;
458
  endif;
459
  $node = array_shift($path);
460
  endwhile;
461
-
462
  $matches = array();
463
  foreach ($data as $datum) :
464
  if (is_string($datum)) :
@@ -487,7 +491,7 @@ class SyndicatedPost {
487
  'http://backend.userland.com/RSS2',
488
  SIMPLEPIE_NAMESPACE_RSS_20,
489
  );
490
-
491
  $matches = array();
492
  foreach ($rss as $ns) :
493
  $data = $this->link->simplepie->get_feed_tags($ns, 'channel');
@@ -514,7 +518,7 @@ class SyndicatedPost {
514
  else :
515
  $defaultNS = SIMPLEPIE_NAMESPACE_RSS_20;
516
  endif;
517
- return $defaultNS;
518
  } /* SyndicatedPost::xpath_default_namespace() */
519
 
520
  function xpath_name_and_axis ($node) {
@@ -549,20 +553,20 @@ class SyndicatedPost {
549
  $ns = array($ref[1]);
550
  elseif (strpos($node, ':') !== FALSE) :
551
  list($xmlns, $element) = explode(':', $node, 2);
552
-
553
  if (isset($this->xmlns['reverse'][$xmlns])) :
554
  $ns = $this->xmlns['reverse'][$xmlns];
555
  else :
556
  $ns = array($xmlns);
557
  endif;
558
-
559
  // Fucking SimplePie. For attributes in default xmlns.
560
  $defaultNS = $this->xpath_default_namespace();
561
  if (isset($this->xmlns['forward'][$defaultNS])
562
  and ($xmlns==$this->xmlns['forward'][$defaultNS])) :
563
  $ns[] = '';
564
  endif;
565
-
566
  if (isset($datum['xmlns'])) :
567
  if (isset($datum['xmlns'][$xmlns])) :
568
  $ns[] = $datum['xmlns'][$xmlns];
@@ -576,18 +580,60 @@ class SyndicatedPost {
576
  return array_unique($ns);
577
  } /* SyndicatedPost::xpath_possible_namespaces() */
578
 
579
- function content () {
 
 
 
 
 
 
 
 
 
 
 
 
580
  $content = NULL;
 
 
 
 
 
 
 
 
 
 
581
  if (isset($this->item['atom_content'])) :
582
  $content = $this->item['atom_content'];
 
 
 
 
 
 
 
583
  elseif (isset($this->item['xhtml']['body'])) :
584
  $content = $this->item['xhtml']['body'];
585
  elseif (isset($this->item['xhtml']['div'])) :
586
  $content = $this->item['xhtml']['div'];
 
 
 
587
  elseif (isset($this->item['content']['encoded']) and $this->item['content']['encoded']):
588
  $content = $this->item['content']['encoded'];
589
- elseif (isset($this->item['description'])) :
590
- $content = $this->item['description'];
 
 
 
 
 
 
 
 
 
 
591
  endif;
592
  return $content;
593
  } /* SyndicatedPost::content() */
@@ -595,13 +641,13 @@ class SyndicatedPost {
595
  function excerpt () {
596
  # Identify and sanitize excerpt: atom:summary, or rss:description
597
  $excerpt = $this->entry->get_description();
598
-
599
  # Many RSS feeds use rss:description, inadvisably, to
600
  # carry the entire post (typically with escaped HTML).
601
  # If that's what happened, we don't want the full
602
  # content for the excerpt.
603
  $content = $this->content();
604
-
605
  // Ignore whitespace, case, and tag cruft.
606
  $theExcerpt = preg_replace('/\s+/', '', strtolower(strip_tags($excerpt)));
607
  $theContent = preg_replace('/\s+/', '', strtolower(strip_tags($content)));
@@ -628,7 +674,7 @@ class SyndicatedPost {
628
  function created ($params = array()) {
629
  $unfiltered = false; $default = NULL;
630
  extract($params);
631
-
632
  $date = '';
633
  if (isset($this->item['dc']['created'])) :
634
  $date = $this->item['dc']['created'];
@@ -653,7 +699,7 @@ class SyndicatedPost {
653
  else : // New style
654
  extract($params);
655
  endif;
656
-
657
  $date = '';
658
  $ts = null;
659
 
@@ -672,14 +718,14 @@ class SyndicatedPost {
672
  elseif (isset($this->item['pubdate'])): // RSS 2.0
673
  $date = $this->item['pubdate'];
674
  endif;
675
-
676
  if (strlen($date) > 0) :
677
  $time = new FeedTime($date);
678
  $ts = $time->timestamp();
679
  elseif ($fallback) : // Fall back to <updated> / <modified> if present
680
  $ts = $this->updated(/*fallback=*/ false, /*default=*/ $default);
681
  endif;
682
-
683
  # If everything failed, then default to the current time.
684
  if (is_null($ts)) :
685
  if (-1 == $default) :
@@ -688,7 +734,7 @@ class SyndicatedPost {
688
  $ts = $default;
689
  endif;
690
  endif;
691
-
692
  if (!$unfiltered) :
693
  $ts = apply_filters('syndicated_item_published', $ts, $this);
694
  endif;
@@ -718,14 +764,14 @@ class SyndicatedPost {
718
  elseif (isset($this->item['updated'])): // Atom 1.0
719
  $date = $this->item['updated'];
720
  endif;
721
-
722
  if (strlen($date) > 0) :
723
  $time = new FeedTime($date);
724
  $ts = $time->timestamp();
725
  elseif ($fallback) : // Fall back to issued / dc:date
726
  $ts = $this->published(/*fallback=*/ false, /*default=*/ $default);
727
  endif;
728
-
729
  # If everything failed, then default to the current time.
730
  if (is_null($ts)) :
731
  if (-1 == $default) :
@@ -766,19 +812,19 @@ class SyndicatedPost {
766
  "content" => $this->content(),
767
  "excerpt" => $this->excerpt(),
768
  );
769
-
770
  if ($hashed) :
771
  $hash = md5(serialize($hash));
772
  endif;
773
-
774
  return $hash;
775
  } /* SyndicatedPost::update_hash() */
776
 
777
- /*static*/ function normalize_guid_prefix () {
778
  return trailingslashit(get_bloginfo('url')).'?guid=';
779
  }
780
-
781
- /*static*/ function normalize_guid ($guid) {
782
  $guid = trim($guid);
783
  if (preg_match('/^[0-9a-z]{32}$/i', $guid)) : // MD5
784
  $guid = SyndicatedPost::normalize_guid_prefix().strtolower($guid);
@@ -788,7 +834,7 @@ class SyndicatedPost {
788
  $guid = trim($guid);
789
  return $guid;
790
  } /* SyndicatedPost::normalize_guid() */
791
-
792
  function guid () {
793
  $guid = null;
794
  if (isset($this->item['id'])): // Atom 0.3 / 1.0
@@ -800,12 +846,12 @@ class SyndicatedPost {
800
  elseif (isset($this->item['dc']['identifier'])) : // yeah, right
801
  $guid = $this->item['dc']['identifier'];
802
  endif;
803
-
804
  // Un-set or too long to use as-is. Generate a tag: URI.
805
  if (is_null($guid) or strlen($guid) > 250) :
806
  // In case we need to check this again
807
  $original_guid = $guid;
808
-
809
  // The feed does not seem to have provided us with a
810
  // usable unique identifier, so we'll have to cobble
811
  // together a tag: URI that might work for us. The base
@@ -823,7 +869,7 @@ class SyndicatedPost {
823
  // are hashed down into a nice, manageable tag: URI.
824
  if (!is_null($original_guid)) :
825
  $guid .= ',2010-12-03:id.'.md5($original_guid);
826
-
827
  // If we have a date of creation, then we can use that
828
  // to uniquely identify the item. (On the other hand, if
829
  // the feed producer was consicentious enough to
@@ -831,7 +877,7 @@ class SyndicatedPost {
831
  // conscientious enough to generate unique identifiers.)
832
  elseif (!is_null($this->created())) :
833
  $guid .= '://post.'.date('YmdHis', $this->created());
834
-
835
  // Otherwise, use both the URI of the item, *and* the
836
  // item's title. We have to use both because titles are
837
  // often not unique, and sometimes links aren't unique
@@ -847,10 +893,10 @@ class SyndicatedPost {
847
  endif;
848
  return $guid;
849
  } /* SyndicatedPost::guid() */
850
-
851
  function author () {
852
  $author = array ();
853
-
854
  $aa = $this->entry->get_authors();
855
  if (count($aa) > 0) :
856
  $a = reset($aa);
@@ -881,7 +927,7 @@ class SyndicatedPost {
881
  // e-mail address, but lots of people don't use
882
  // it that way. So let's make of it what we can.
883
  $author = parse_email_with_realname($this->item['author']);
884
-
885
  if (!isset($author['name'])) :
886
  if (isset($author['email'])) :
887
  $author['name'] = $author['email'];
@@ -891,7 +937,7 @@ class SyndicatedPost {
891
  endif;
892
  endif;
893
  endif;
894
-
895
  if (!isset($author['name']) or is_null($author['name'])) :
896
  // Nothing found. Try some crappy defaults.
897
  if ($this->link->name()) :
@@ -901,14 +947,14 @@ class SyndicatedPost {
901
  $author['name'] = $url['host'];
902
  endif;
903
  endif;
904
-
905
  if (FEEDWORDPRESS_COMPATIBILITY) :
906
  if (isset($this->item['author_email'])):
907
  $author['email'] = $this->item['author_email'];
908
  elseif (isset($this->feed->channel['author_email'])) :
909
  $author['email'] = $this->feed->channel['author_email'];
910
  endif;
911
-
912
  if (isset($this->item['author_uri'])):
913
  $author['uri'] = $this->item['author_uri'];
914
  elseif (isset($this->item['author_url'])):
@@ -921,7 +967,7 @@ class SyndicatedPost {
921
  $author['uri'] = $this->feed->channel['link'];
922
  endif;
923
  endif;
924
-
925
  return $author;
926
  } /* SyndicatedPost::author() */
927
 
@@ -945,7 +991,7 @@ class SyndicatedPost {
945
  endif;
946
  return $tags;
947
  }
948
-
949
  /**
950
  * SyndicatedPost::isTaggedAs: Test whether a feed item is
951
  * tagged / categorized with a given string. Case and leading and
@@ -953,7 +999,7 @@ class SyndicatedPost {
953
  *
954
  * @param string $tag Tag to check for
955
  *
956
- * @return bool Whether or not at least one of the categories / tags on
957
  * $this->item is set to $tag (modulo case and leading and trailing
958
  * whitespace)
959
  */
@@ -968,7 +1014,7 @@ class SyndicatedPost {
968
  // on this item is stored under index "category#".
969
  if (isset($this->item['category#'])) :
970
  $numberOfCategories = (int) $this->item['category#'];
971
-
972
  // We REALLY shouldn't have the old and busted MagpieRSS, but in
973
  // case we do, it doesn't support multiple categories, but there
974
  // might still be a single value under the "category" index.
@@ -1027,7 +1073,7 @@ class SyndicatedPost {
1027
  endif;
1028
  endfor;
1029
  endif;
1030
- return $enclosures;
1031
  } /* SyndicatedPost::enclosures() */
1032
 
1033
  function source ($what = NULL) {
@@ -1038,7 +1084,7 @@ class SyndicatedPost {
1038
  $ret['title'] = $source->get_title();
1039
  $ret['uri'] = $source->get_link();
1040
  $ret['feed'] = $source->get_link(0, 'self');
1041
-
1042
  if ($id_tags = $source->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id')) :
1043
  $ret['id'] = $id_tags[0]['data'];
1044
  elseif ($id_tags = $source->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id')) :
@@ -1051,16 +1097,16 @@ class SyndicatedPost {
1051
  $ret['id'] = $id_tags[0]['data'];
1052
  endif;
1053
  endif;
1054
-
1055
  if (!is_null($what) and is_scalar($what)) :
1056
  $ret = $ret[$what];
1057
  endif;
1058
  return $ret;
1059
  }
1060
-
1061
  function comment_link () {
1062
  $url = null;
1063
-
1064
  // RSS 2.0 has a standard <comments> element:
1065
  // "<comments> is an optional sub-element of <item>. If present,
1066
  // it is the url of the comments page for the item."
@@ -1073,13 +1119,13 @@ class SyndicatedPost {
1073
  // element with @rel="replies" and @type="text/html".
1074
  // Unfortunately, SimplePie_Item::get_links() allows us to filter
1075
  // by the value of @rel, but not by the value of @type. *sigh*
1076
-
1077
  // Try Atom 1.0 first
1078
  $linkElements = $this->entry->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link');
1079
-
1080
  // Fall back and try Atom 0.3
1081
  if (is_null($linkElements)) : $linkElements = $this->entry->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'); endif;
1082
-
1083
  // Now loop through the elements, screening by @rel and @type
1084
  if (is_array($linkElements)) : foreach ($linkElements as $link) :
1085
  $rel = (isset($link['attribs']['']['rel']) ? $link['attribs']['']['rel'] : 'alternate');
@@ -1170,9 +1216,9 @@ class SyndicatedPost {
1170
  return $tag['prefix'] . $url . $tag['suffix'];
1171
  } /* function SyndicatedPost::resolve_single_relative_uri() */
1172
 
1173
- function resolve_relative_uris ($content, $obj) {
1174
  $set = $obj->link->setting('resolve relative', 'resolve_relative', 'yes');
1175
- if ($set and $set != 'no') :
1176
  // Fallback: if we don't have anything better, use the
1177
  // item link from the feed
1178
  $obj->_base = $obj->permalink(); // Reset the base for resolving relative URIs
@@ -1194,7 +1240,7 @@ class SyndicatedPost {
1194
  );
1195
  endforeach;
1196
  endif;
1197
-
1198
  return $content;
1199
  } /* function SyndicatedPost::resolve_relative_uris () */
1200
 
@@ -1209,7 +1255,7 @@ class SyndicatedPost {
1209
  return $tag['before_attribute'].$tag['after_attribute'];
1210
  }
1211
 
1212
- function sanitize_content ($content, $obj) {
1213
  # This kind of sucks. I intend to replace it with
1214
  # lib_filter sometime soon.
1215
  foreach ($obj->strip_attrs as $pair):
@@ -1246,50 +1292,69 @@ class SyndicatedPost {
1246
  * still up-to-date.
1247
  *
1248
  * @return int A status code representing the freshness of the post
 
1249
  * 0 = post already syndicated; no update needed
1250
  * 1 = post already syndicated, but needs to be updated to latest
1251
  * 2 = post has not yet been syndicated; needs to be created
1252
  */
1253
- function freshness () {
1254
  global $wpdb;
1255
 
1256
  if ($this->filtered()) : // This should never happen.
1257
  FeedWordPress::critical_bug('SyndicatedPost', $this, __LINE__, __FILE__);
1258
  endif;
1259
-
1260
  if (is_null($this->_freshness)) : // Not yet checked and cached.
1261
  $guid = $this->post['guid'];
1262
- $eguid = $wpdb->escape($this->post['guid']);
1263
 
1264
  $q = new WP_Query(array(
1265
  'fields' => '_synfresh', // id, guid, post_modified_gmt
1266
  'ignore_sticky_posts' => true,
1267
  'guid' => $guid,
1268
  ));
1269
-
1270
  $old_post = NULL;
1271
  if ($q->have_posts()) :
1272
  while ($q->have_posts()) : $q->the_post();
1273
  $old_post = $q->post;
1274
  endwhile;
1275
  endif;
1276
-
1277
  if (is_null($old_post)) : // No post with this guid
1278
  FeedWordPress::diagnostic('feed_items:freshness', 'Item ['.$guid.'] "'.$this->entry->get_title().'" is a NEW POST.');
1279
  $this->_wp_id = NULL;
1280
  $this->_freshness = 2; // New content
1281
  else :
1282
- preg_match('/([0-9]+)-([0-9]+)-([0-9]+) ([0-9]+):([0-9]+):([0-9]+)/', $old_post->post_modified_gmt, $backref);
 
 
 
 
 
 
 
 
 
 
1283
 
1284
- $last_rev_ts = gmmktime($backref[4], $backref[5], $backref[6], $backref[2], $backref[3], $backref[1]);
 
1285
  $updated_ts = $this->updated(/*fallback=*/ true, /*default=*/ NULL);
1286
 
1287
- // Check timestamps...
1288
- $updated = (
1289
- !is_null($updated_ts)
1290
- and ($updated_ts > $last_rev_ts)
1291
- );
 
 
 
 
 
1292
 
 
 
1293
  $updatedReason = NULL;
1294
  if ($updated) :
1295
  $updatedReason = preg_replace(
@@ -1300,6 +1365,9 @@ class SyndicatedPost {
1300
  .date('Y-m-d H:i:s', $last_rev_ts)
1301
  .')'
1302
  );
 
 
 
1303
  else :
1304
  // Or the hash...
1305
  $hash = $this->update_hash();
@@ -1309,24 +1377,31 @@ class SyndicatedPost {
1309
  else :
1310
  $updated = true; // Can't find syndication meta-data
1311
  endif;
1312
-
1313
  if ($updated and FeedWordPress::diagnostic_on('feed_items:freshness:reasons')) :
 
 
 
 
 
 
 
1314
  $updatedReason = ' has a not-yet-seen update hash: '
1315
- .FeedWordPress::val($hash)
1316
  .' not in {'
1317
  .implode(", ", array_map(array('FeedWordPress', 'val'), $seen))
1318
  .'}. Basis: '
1319
- .FeedWordPress::val(array_keys($this->update_hash(false)));
1320
  endif;
1321
  endif;
1322
-
1323
  $frozen = false;
1324
  if ($updated) : // Ignore if the post is frozen
1325
  $frozen = ('yes' == $this->link->setting('freeze updates', 'freeze_updates', NULL));
1326
  if (!$frozen) :
1327
  $frozen_values = get_post_custom_values('_syndication_freeze_updates', $old_post->ID);
1328
  $frozen = (count($frozen_values) > 0 and 'yes' == $frozen_values[0]);
1329
-
1330
  if ($frozen) :
1331
  $updatedReason = ' IS BLOCKED FROM BEING UPDATED BY A UPDATE LOCK ON THIS POST, EVEN THOUGH IT '.$updatedReason;
1332
  endif;
@@ -1334,7 +1409,7 @@ class SyndicatedPost {
1334
  $updatedReason = ' IS BLOCKED FROM BEING UPDATED BY A FEEDWORDPRESS UPDATE LOCK, EVEN THOUGH IT '.$updatedReason;
1335
  endif;
1336
  endif;
1337
- $updated = ($updated and !$frozen);
1338
 
1339
  if ($updated) :
1340
  FeedWordPress::diagnostic('feed_items:freshness', 'Item ['.$guid.'] "'.$this->entry->get_title().'" is an update of an existing post.');
@@ -1342,7 +1417,9 @@ class SyndicatedPost {
1342
  $updatedReason = preg_replace('/\s+/', ' ', $updatedReason);
1343
  FeedWordPress::diagnostic('feed_items:freshness:reasons', 'Item ['.$guid.'] "'.$this->entry->get_title().'" '.$updatedReason);
1344
  endif;
1345
- $this->_freshness = 1; // Updated content
 
 
1346
  $this->_wp_id = $old_post->ID;
1347
  $this->_wp_post = $old_post;
1348
 
@@ -1359,9 +1436,88 @@ class SyndicatedPost {
1359
  endif;
1360
  endif;
1361
  endif;
1362
- return $this->_freshness;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1363
  }
1364
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1365
  #################################################
1366
  #### INTERNAL STORAGE AND MANAGEMENT METHODS ####
1367
  #################################################
@@ -1370,7 +1526,7 @@ class SyndicatedPost {
1370
  if ($this->filtered()) : // This should never happen.
1371
  FeedWordPress::critical_bug('SyndicatedPost', $this, __LINE__, __FILE__);
1372
  endif;
1373
-
1374
  if (is_null($this->_wp_id) and is_null($this->_freshness)) :
1375
  $fresh = $this->freshness(); // sets WP DB id in the process
1376
  endif;
@@ -1383,9 +1539,9 @@ class SyndicatedPost {
1383
  if ($this->filtered()) : // This should never happen.
1384
  FeedWordPress::critical_bug('SyndicatedPost', $this, __LINE__, __FILE__);
1385
  endif;
1386
-
1387
  $freshness = $this->freshness();
1388
- if ($freshness > 0) :
1389
  # -- Look up, or create, numeric ID for author
1390
  $this->post['post_author'] = $this->author_id (
1391
  $this->link->setting('unfamiliar author', 'unfamiliar_author', 'create')
@@ -1396,8 +1552,10 @@ class SyndicatedPost {
1396
  $this->post = NULL;
1397
  endif;
1398
  endif;
1399
-
1400
- if (!$this->filtered() and $freshness > 0) :
 
 
1401
  $consider = array(
1402
  'category' => array('abbr' => 'cats', 'domain' => array('category', 'post_tag')),
1403
  'post_tag' => array('abbr' => 'tags', 'domain' => array('post_tag')),
@@ -1408,10 +1566,10 @@ class SyndicatedPost {
1408
  if (!is_null($this->post)) : // Not filtered out yet
1409
  # -- Look up, or create, numeric ID for categories
1410
  $taxonomies = $this->link->setting("match/".$taxes['abbr'], 'match_'.$taxes['abbr'], $taxes['domain']);
1411
-
1412
  // Eliminate dummy variables
1413
  $taxonomies = array_filter($taxonomies, 'remove_dummy_zero');
1414
-
1415
  $terms = $this->category_ids (
1416
  $this->feed_terms[$what],
1417
  $this->link->setting("unfamiliar {$what}", "unfamiliar_{$what}", 'create:'.$what),
@@ -1421,7 +1579,7 @@ class SyndicatedPost {
1421
  'filters' => true,
1422
  )
1423
  );
1424
-
1425
  if (is_null($terms) or is_null($termSet)) :
1426
  // filtered out -- no matches
1427
  else :
@@ -1457,7 +1615,7 @@ class SyndicatedPost {
1457
  if (!isset($this->post['tax_input'][$tax])) :
1458
  $this->post['tax_input'][$tax] = array();
1459
  endif;
1460
-
1461
  $this->post['tax_input'][$tax] = array_merge (
1462
  $this->post['tax_input'][$tax],
1463
  $this->category_ids (
@@ -1471,23 +1629,25 @@ class SyndicatedPost {
1471
  endforeach;
1472
  endif;
1473
  endif;
1474
-
1475
- if (!$this->filtered() and $freshness > 0) :
 
 
1476
  // Filter some individual fields
1477
-
1478
  // If there already is a post slug (from syndication or by manual
1479
  // editing) don't cause WP to overwrite it by sending in a NULL
1480
  // post_name. Props Chris Fritz 2012-11-28.
1481
- $post_name = (is_null($this->_wp_post) ? NULL : $this->_wp_post->post_name);
1482
 
1483
  // Allow filters to set post slug. Props niska.
1484
  $post_name = apply_filters('syndicated_post_slug', $post_name, $this);
1485
  if (!empty($post_name)) :
1486
  $this->post['post_name'] = $post_name;
1487
  endif;
1488
-
1489
  $this->post = apply_filters('syndicated_post', $this->post, $this);
1490
-
1491
  // Allow for feed-specific syndicated_post filters.
1492
  $this->post = apply_filters(
1493
  "syndicated_post_".$this->link->uri(),
@@ -1495,7 +1655,7 @@ class SyndicatedPost {
1495
  $this
1496
  );
1497
  endif;
1498
-
1499
  // Hook in early to make sure these get inserted if at all possible
1500
  add_action(
1501
  /*hook=*/ 'transition_post_status',
@@ -1503,39 +1663,42 @@ class SyndicatedPost {
1503
  /*priority=*/ -10000, /* very early */
1504
  /*arguments=*/ 3
1505
  );
1506
-
1507
- $retval = array(1 => 'updated', 2 => 'new');
1508
 
1509
  $ret = false;
1510
- if (!$this->filtered() and isset($retval[$freshness])) :
1511
- $diag = array(
1512
- 1 => 'Updating existing post # '.$this->wp_id().', "'.$this->post['post_title'].'"',
1513
- 2 => 'Inserting new post "'.$this->post['post_title'].'"',
1514
- );
1515
- FeedWordPress::diagnostic('syndicated_posts', $diag[$freshness]);
1516
-
1517
- $this->insert_post(/*update=*/ ($freshness == 1));
1518
 
1519
- $hook = array( 1 => 'update_syndicated_item', 2 => 'post_syndicated_item' );
1520
- do_action($hook[$freshness], $this->wp_id(), $this);
1521
 
1522
- $ret = $retval[$freshness];
 
 
 
 
 
1523
  endif;
1524
 
1525
- // If this is a legit, non-filtered post, tag it as found on the feed
1526
- // regardless of fresh or stale status
1527
  if (!$this->filtered()) :
1528
  $key = '_feedwordpress_retire_me_' . $this->link->id;
1529
  delete_post_meta($this->wp_id(), $key);
1530
-
1531
  $status = get_post_field('post_status', $this->wp_id());
1532
- if ('fwpretired'==$status and $this->link->is_incremental()) :
1533
- FeedWordPress::diagnostic('syndicated_posts', "Un-retiring previously retired post # ".$this->wp_id()." due to re-appearance on non-incremental feed.");
1534
  set_post_field('post_status', $this->post['post_status'], $this->wp_id());
1535
- wp_transition_post_status($this->post['post_status'], $status, $old_status, $this->post);
 
 
 
 
1536
  endif;
1537
  endif;
1538
-
1539
  // Remove add_rss_meta hook
1540
  remove_action(
1541
  /*hook=*/ 'transition_post_status',
@@ -1546,17 +1709,18 @@ class SyndicatedPost {
1546
 
1547
  return $ret;
1548
  } /* function SyndicatedPost::store () */
1549
-
1550
- function insert_post ($update = false) {
1551
  global $wpdb;
1552
 
1553
  $dbpost = $this->normalize_post(/*new=*/ true);
 
1554
  if (!is_null($dbpost)) :
1555
  $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
1556
-
1557
  // This is a ridiculous fucking kludge necessitated by WordPress 2.6 munging authorship meta-data
1558
  add_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1559
-
1560
  // Kludge to prevent kses filters from stripping the
1561
  // content of posts when updating without a logged in
1562
  // user who has `unfiltered_html` capability.
@@ -1568,17 +1732,17 @@ class SyndicatedPost {
1568
  $removed[] = $munger;
1569
  endif;
1570
  endforeach;
1571
-
1572
  if ($update and function_exists('get_post_field')) :
1573
  // Don't munge status fields that the user may
1574
  // have reset manually
1575
  $doNotMunge = array('post_status', 'comment_status', 'ping_status');
1576
-
1577
  foreach ($doNotMunge as $field) :
1578
  $dbpost[$field] = get_post_field($field, $this->wp_id());
1579
  endforeach;
1580
  endif;
1581
-
1582
  // WP3's wp_insert_post scans current_user_can() for the
1583
  // tax_input, with no apparent way to override. Ugh.
1584
  add_action(
@@ -1587,7 +1751,7 @@ class SyndicatedPost {
1587
  /*priority=*/ -10001, /* very early */
1588
  /*arguments=*/ 3
1589
  );
1590
-
1591
  // WP3 appears to override whatever you give it for
1592
  // post_modified. Ugh.
1593
  add_action(
@@ -1601,8 +1765,44 @@ class SyndicatedPost {
1601
  $this->post['ID'] = $this->wp_id();
1602
  $dbpost['ID'] = $this->post['ID'];
1603
  endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1604
 
1605
- $this->_wp_id = wp_insert_post($dbpost, /*return wp_error=*/ true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1606
 
1607
  remove_action(
1608
  /*hook=*/ 'transition_post_status',
@@ -1623,17 +1823,17 @@ class SyndicatedPost {
1623
  foreach ($removed as $filter) :
1624
  add_filter('content_save_pre', $filter);
1625
  endforeach;
1626
-
1627
  $this->validate_post_id($dbpost, $update, array(__CLASS__, __FUNCTION__));
1628
  endif;
1629
  } /* function SyndicatedPost::insert_post () */
1630
-
1631
  function insert_new () {
1632
- $this->insert_post(/*update=*/ false);
1633
  } /* SyndicatedPost::insert_new() */
1634
 
1635
  function update_existing () {
1636
- $this->insert_post(/*update=*/ true);
1637
  } /* SyndicatedPost::update_existing() */
1638
 
1639
  /**
@@ -1660,7 +1860,7 @@ class SyndicatedPost {
1660
  $feed_url = parse_url($this->post['meta']['syndication_feed']);
1661
  $source_title = $feed_url['host'];
1662
  endif;
1663
-
1664
  $out['post_title'] = $source_title
1665
  .' '.gmdate('Y-m-d H:i:s', $this->published() + $offset);
1666
  // FIXME: Option for what to fill a blank title with...
@@ -1669,18 +1869,29 @@ class SyndicatedPost {
1669
  // Normalize the guid if necessary.
1670
  $out['guid'] = SyndicatedPost::normalize_guid($out['guid']);
1671
 
1672
- // Why the fuck doesn't wp_insert_post already do this?
1673
- foreach ($out as $key => $value) :
1674
- if (is_string($value)) :
1675
- $out[$key] = $wpdb->escape($value);
1676
- else :
1677
- $out[$key] = $value;
1678
- endif;
1679
- endforeach;
1680
-
1681
  return $out;
1682
  }
1683
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1684
  /**
1685
  * SyndicatedPost::validate_post_id()
1686
  *
@@ -1702,8 +1913,9 @@ class SyndicatedPost {
1702
  // notice if we are in debug mode.
1703
  $mesg = "Failed to $verb item [$guid]. WordPress API returned no valid post ID.\n"
1704
  ."\t\tID = ".serialize($this->_wp_id)."\n"
1705
- ."\t\tURL = ".FeedWordPress::val($url)
1706
- ."\t\tFeed = ".FeedWordPress::val($feed);
 
1707
  FeedWordPress::diagnostic('updated_feeds:errors', "WordPress API error: $mesg");
1708
  FeedWordPress::diagnostic('feed_items:rejected', $mesg);
1709
 
@@ -1711,9 +1923,9 @@ class SyndicatedPost {
1711
  The WordPress API returned an invalid post ID
1712
  when FeedWordPress tried to $verb item $guid
1713
  [URL: $url]
1714
- from the feed at $feed
1715
 
1716
- $ns::_wp_id
1717
  EOM;
1718
  FeedWordPress::noncritical_bug(
1719
  /*message=*/ $mesg,
@@ -1725,16 +1937,16 @@ EOM;
1725
  );
1726
  endif;
1727
  } /* SyndicatedPost::validate_post_id() */
1728
-
1729
  /**
1730
- * SyndicatedPost::fix_revision_meta() - Fixes the way WP 2.6+ fucks up
1731
- * meta-data (authorship, etc.) when storing revisions of an updated
1732
- * syndicated post.
1733
  *
1734
- * In their infinite wisdom, the WordPress coders have made it completely
1735
- * impossible for a plugin that uses wp_insert_post() to set certain
1736
- * meta-data (such as the author) when you store an old revision of an
1737
- * updated post. Instead, it uses the WordPress defaults (= currently
1738
  * active user ID if the process is running with a user logged in, or
1739
  * = #0 if there is no user logged in). This results in bogus authorship
1740
  * data for revisions that are syndicated from off the feed, unless we
@@ -1745,17 +1957,22 @@ EOM;
1745
  */
1746
  function fix_revision_meta ($revision_id) {
1747
  global $wpdb;
1748
-
1749
  $post_author = (int) $this->post['post_author'];
1750
-
1751
  $revision_id = (int) $revision_id;
1752
- $wpdb->query("
1753
- UPDATE $wpdb->posts
1754
- SET post_author={$this->post['post_author']}
1755
- WHERE post_type = 'revision' AND ID='$revision_id'
1756
- ");
 
 
 
 
 
1757
  } /* SyndicatedPost::fix_revision_meta () */
1758
-
1759
  /**
1760
  * SyndicatedPost::add_terms() -- if FeedWordPress is processing an
1761
  * automatic update, that generally means that wp_insert_post() is being
@@ -1774,18 +1991,35 @@ EOM;
1774
  * @param object $post The database record for the post just inserted.
1775
  */
1776
  function add_terms ($new_status, $old_status, $post) {
 
1777
  if ($new_status!='inherit') : // Bail if we are creating a revision.
1778
  if ( is_array($this->post) and isset($this->post['tax_input']) and is_array($this->post['tax_input']) ) :
1779
  foreach ($this->post['tax_input'] as $taxonomy => $terms) :
1780
  if (is_array($terms)) :
1781
  $terms = array_filter($terms); // strip out empties
1782
  endif;
1783
- wp_set_post_terms($post->ID, $terms, $taxonomy);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1784
  endforeach;
1785
  endif;
1786
  endif;
 
1787
  } /* SyndicatedPost::add_terms () */
1788
-
1789
  /**
1790
  * SyndicatedPost::fix_post_modified_ts() -- We would like to set
1791
  * post_modified and post_modified_gmt to reflect the value of
@@ -1810,7 +2044,7 @@ EOM;
1810
  ), /*where=*/ array('ID' => $post->ID) );
1811
  endif;
1812
  } /* SyndicatedPost::fix_post_modified_ts () */
1813
-
1814
  /**
1815
  * SyndicatedPost::add_rss_meta: adds interesting meta-data to each entry
1816
  * using the space for custom keys. The set of keys and values to add is
@@ -1833,7 +2067,7 @@ EOM;
1833
 
1834
  if ( is_array($this->post) and isset($this->post['meta']) and is_array($this->post['meta']) ) :
1835
  $postId = $post->ID;
1836
-
1837
  // Aggregated posts should NOT send out pingbacks.
1838
  // WordPress 2.1-2.2 claim you can tell them not to
1839
  // using $post_pingback, but they don't listen, so we
@@ -1842,21 +2076,21 @@ EOM;
1842
  DELETE FROM $wpdb->postmeta
1843
  WHERE post_id='$postId' AND meta_key='_pingme'
1844
  ");
1845
-
1846
  foreach ( $this->post['meta'] as $key => $values ) :
1847
- $eKey = $wpdb->escape($key);
1848
-
1849
  // If this is an update, clear out the old
1850
  // values to avoid duplication.
1851
  $result = $wpdb->query("
1852
  DELETE FROM $wpdb->postmeta
1853
  WHERE post_id='$postId' AND meta_key='$eKey'
1854
  ");
1855
-
1856
  // Allow for either a single value or an array
1857
  if (!is_array($values)) $values = array($values);
1858
  foreach ( $values as $value ) :
1859
- FeedWordPress::diagnostic('syndicated_posts:meta_data', "Adding post meta-datum to post [$postId]: [$key] = ".FeedWordPress::val($value, /*no newlines=*/ true));
1860
  add_post_meta($postId, $key, $value, /*unique=*/ false);
1861
  endforeach;
1862
  endforeach;
@@ -1881,7 +2115,7 @@ EOM;
1881
  $source = $this->source();
1882
  $forbidden = apply_filters('feedwordpress_forbidden_author_names',
1883
  array('admin', 'administrator', 'www', 'root'));
1884
-
1885
  // Prepare the list of candidates to try for author name: name from
1886
  // feed, original source title (if any), immediate source title live
1887
  // from feed, subscription title, prettied version of feed homepage URL,
@@ -1896,10 +2130,10 @@ EOM;
1896
  if (strlen($this->link->homepage()) > 0) : $candidates[] = feedwordpress_display_url($this->link->homepage()); endif;
1897
  $candidates[] = feedwordpress_display_url($this->link->uri());
1898
  $candidates[] = 'unknown author';
1899
-
1900
  // Pick the first one that works from the list, screening against empty
1901
  // or forbidden names.
1902
-
1903
  $author = NULL;
1904
  while (is_null($author) and ($candidate = each($candidates))) :
1905
  if (!is_null($candidate['value'])
@@ -1908,11 +2142,11 @@ EOM;
1908
  $author = $candidate['value'];
1909
  endif;
1910
  endwhile;
1911
-
1912
  $email = (isset($a['email']) ? $a['email'] : NULL);
1913
  $authorUrl = (isset($a['uri']) ? $a['uri'] : NULL);
1914
 
1915
-
1916
  $hostUrl = $this->link->homepage();
1917
  if (is_null($hostUrl) or (strlen($hostUrl) < 0)) :
1918
  $hostUrl = $this->link->uri();
@@ -1939,7 +2173,7 @@ EOM;
1939
  // Uniqueness will be guaranteed below if necessary.
1940
 
1941
  $url = parse_url($hostUrl);
1942
-
1943
  $login = sanitize_user($url['host'], /*strict=*/ true);
1944
  if (strlen($login) < 1) :
1945
  // This isn't working. Frak it.
@@ -1952,11 +2186,11 @@ EOM;
1952
  $nice_author = sanitize_title($author);
1953
  $nice_author = apply_filters('pre_user_nicename', $nice_author);
1954
 
1955
- $reg_author = $wpdb->escape(preg_quote($author));
1956
- $author = $wpdb->escape($author);
1957
- $email = $wpdb->escape($email);
1958
- $test_email = $wpdb->escape($test_email);
1959
- $authorUrl = $wpdb->escape($authorUrl);
1960
 
1961
  // Check for an existing author rule....
1962
  if (isset($this->link->settings['map authors']['name']['*'])) :
@@ -1974,7 +2208,7 @@ EOM;
1974
  // User name is filtered out
1975
  elseif ('filter' == $author_rule) :
1976
  $id = NULL;
1977
-
1978
  else :
1979
  // Check the database for an existing author record that might fit
1980
 
@@ -1987,7 +2221,7 @@ EOM;
1987
  LENGTH(TRIM(LCASE(user_email))) > 0
1988
  AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
1989
  )");
1990
-
1991
  // If that fails, look for aliases in the user meta data table
1992
  if (is_null($id)) :
1993
  $id = $wpdb->get_var(
@@ -2032,7 +2266,7 @@ EOM;
2032
  if (isset($parts[1])) : $userdata['last_name'] = $parts[1]; endif;
2033
  $userdata['display_name'] = $author;
2034
  $userdata['role'] = 'contributor';
2035
-
2036
  do { // Keep trying until you get it right. Or until PHP crashes, I guess.
2037
  $id = wp_insert_user($userdata);
2038
  if (is_wp_error($id)) :
@@ -2046,10 +2280,10 @@ EOM;
2046
  case 'existing_user_email' :
2047
  // No disassemble!
2048
  $parts = explode('@', $userdata['user_email'], 2);
2049
-
2050
  // Add a random disambiguator as a gmail-style username extension
2051
  $parts[0] .= '+'.substr(md5(uniqid(microtime())), 0, 6);
2052
-
2053
  // Reassemble
2054
  $userdata['user_email'] = $parts[0].'@'.$parts[1];
2055
  break;
@@ -2066,7 +2300,7 @@ EOM;
2066
 
2067
  if ($id) :
2068
  $this->link->settings['map authors']['name'][strtolower(trim($author))] = $id;
2069
-
2070
  // Multisite: Check whether the author has been recorded
2071
  // on *this* blog before. If not, put her down as a
2072
  // Contributor for *this* blog.
@@ -2075,128 +2309,21 @@ EOM;
2075
  $user->add_role('contributor');
2076
  endif;
2077
  endif;
2078
- return $id;
2079
  } /* function SyndicatedPost::author_id () */
2080
 
2081
  /**
2082
- * category_ids: look up (and create) category ids from a list of categories
 
2083
  *
2084
  * @param array $cats
2085
  * @param string $unfamiliar_category
2086
  * @param array|null $taxonomies
2087
  * @return array
2088
- */
2089
  function category_ids ($cats, $unfamiliar_category = 'create', $taxonomies = NULL, $params = array()) {
2090
- $singleton = (isset($params['singleton']) ? $params['singleton'] : true);
2091
- $allowFilters = (isset($params['filters']) ? $params['filters'] : false);
2092
-
2093
- $catTax = 'category';
2094
-
2095
- if (is_null($taxonomies)) :
2096
- $taxonomies = array('category');
2097
- endif;
2098
-
2099
- // We need to normalize whitespace because (1) trailing
2100
- // whitespace can cause PHP and MySQL not to see eye to eye on
2101
- // VARCHAR comparisons for some versions of MySQL (cf.
2102
- // <http://dev.mysql.com/doc/mysql/en/char.html>), and (2)
2103
- // because I doubt most people want to make a semantic
2104
- // distinction between 'Computers' and 'Computers '
2105
- $cats = array_map('trim', $cats);
2106
-
2107
- $terms = array();
2108
- foreach ($taxonomies as $tax) :
2109
- $terms[$tax] = array();
2110
- endforeach;
2111
-
2112
- foreach ($cats as $cat_name) :
2113
- if (preg_match('/^{([^#}]*)#([0-9]+)}$/', $cat_name, $backref)) :
2114
- $cat_id = (int) $backref[2];
2115
- $tax = $backref[1];
2116
- if (strlen($tax) < 1) :
2117
- $tax = $catTax;
2118
- endif;
2119
-
2120
- $term = term_exists($cat_id, $tax);
2121
- if (!is_wp_error($term) and !!$term) :
2122
- if (!isset($terms[$tax])) :
2123
- $terms[$tax] = array();
2124
- endif;
2125
- $terms[$tax][] = $cat_id;
2126
- endif;
2127
- elseif (strlen($cat_name) > 0) :
2128
- $familiar = false;
2129
- foreach ($taxonomies as $tax) :
2130
- if ($tax!='category' or strtolower($cat_name)!='uncategorized') :
2131
- $term = term_exists($cat_name, $tax);
2132
- if (!is_wp_error($term) and !!$term) :
2133
- $familiar = true;
2134
-
2135
- if (is_array($term)) :
2136
- $term_id = (int) $term['term_id'];
2137
- else :
2138
- $term_id = (int) $term;
2139
- endif;
2140
-
2141
- if (!isset($terms[$tax])) :
2142
- $terms[$tax] = array();
2143
- endif;
2144
- $terms[$tax][] = $term_id;
2145
- break; // We're done here.
2146
- endif;
2147
- endif;
2148
- endforeach;
2149
-
2150
- if (!$familiar) :
2151
- if ('tag'==$unfamiliar_category) :
2152
- $unfamiliar_category = 'create:post_tag';
2153
- endif;
2154
-
2155
- if (preg_match('/^create(:(.*))?$/i', $unfamiliar_category, $ref)) :
2156
- $tax = $catTax; // Default
2157
- if (isset($ref[2]) and strlen($ref[2]) > 2) :
2158
- $tax = $ref[2];
2159
- endif;
2160
- $term = wp_insert_term($cat_name, $tax);
2161
- if (is_wp_error($term)) :
2162
- FeedWordPress::noncritical_bug('term insertion problem', array('cat_name' => $cat_name, 'term' => $term, 'this' => $this), __LINE__, __FILE__);
2163
- else :
2164
- if (!isset($terms[$tax])) :
2165
- $terms[$tax] = array();
2166
- endif;
2167
- $terms[$tax][] = (int) $term['term_id'];
2168
- endif;
2169
- endif;
2170
- endif;
2171
- endif;
2172
- endforeach;
2173
-
2174
- $filtersOn = $allowFilters;
2175
- if ($allowFilters) :
2176
- $filters = array_filter(
2177
- $this->link->setting('match/filter', 'match_filter', array()),
2178
- 'remove_dummy_zero'
2179
- );
2180
- $filtersOn = ($filtersOn and is_array($filters) and (count($filters) > 0));
2181
- endif;
2182
-
2183
- // Check for filter conditions
2184
- foreach ($terms as $tax => $term_ids) :
2185
- if ($filtersOn
2186
- and (count($term_ids)==0)
2187
- and in_array($tax, $filters)) :
2188
- $terms = NULL; // Drop the post
2189
- break;
2190
- else :
2191
- $terms[$tax] = array_unique($term_ids);
2192
- endif;
2193
- endforeach;
2194
-
2195
- if ($singleton and count($terms)==1) : // If we only searched one, just return the term IDs
2196
- $terms = end($terms);
2197
- endif;
2198
- return $terms;
2199
- } // function SyndicatedPost::category_ids ()
2200
 
2201
  } /* class SyndicatedPost */
2202
 
1
  <?php
2
  require_once(dirname(__FILE__).'/feedtime.class.php');
3
+ require_once(dirname(__FILE__).'/syndicatedpostterm.class.php');
4
 
5
  /**
6
  * class SyndicatedPost: FeedWordPress uses to manage the conversion of
11
  * different feed formats, which may be useful to FeedWordPress users
12
  * who make use of feed data in PHP add-ons and filters.
13
  *
14
+ * @version 2013.0525
15
  */
16
  class SyndicatedPost {
17
  var $item = null; // MagpieRSS representation
20
  var $link = null;
21
  var $feed = null;
22
  var $feedmeta = null;
23
+
24
  var $xmlns = array ();
25
 
26
  var $post = array ();
28
  var $named = array ();
29
  var $preset_terms = array ();
30
  var $feed_terms = array ();
31
+
32
  var $_freshness = null;
33
  var $_wp_id = null;
34
  var $_wp_post = null;
45
  function SyndicatedPost ($item, &$source) {
46
  global $wpdb;
47
 
48
+ if ( empty($item) && empty($source) )
49
+ return;
50
+
51
  if (is_array($item)
52
  and isset($item['simplepie'])
53
  and isset($item['magpie'])) :
56
  $item = $item['magpie'];
57
  elseif (is_a($item, 'SimplePie_Item')) :
58
  $this->entry = $item;
59
+
60
  // convert to Magpie for compat purposes
61
  $mp = new MagpieFromSimplePie($source->simplepie, $this->entry);
62
  $this->item = $mp->get_item();
63
+
64
  // done with conversion object
65
  $mp = NULL; unset($mp);
66
  else :
80
  if (!isset($this->xmlns['reverse'][$ns])) :
81
  $this->xmlns['reverse'][$ns] = array();
82
  endif;
83
+ $this->xmlns['reverse'][$ns][] = $url;
84
  endforeach;
85
+
86
  // Fucking SimplePie.
87
  $this->xmlns['reverse']['rss'][] = '';
88
 
104
  // Trigger global syndicated_item filter.
105
  $changed = apply_filters('syndicated_item', $this->item, $this);
106
  $this->item = $changed;
107
+
108
  // Allow for feed-specific syndicated_item filters.
109
  $changed = apply_filters(
110
  "syndicated_item_".$source->uri(),
112
  $this
113
  );
114
  $this->item = $changed;
115
+
116
  # Filters can halt further processing by returning NULL
117
  if (is_null($this->item)) :
118
  $this->post = NULL;
119
  else :
120
+ # Note that nothing is run through esc_sql() here.
121
  # That's deliberate. The escaping is done at the point
122
  # of insertion, not here, to avoid double-escaping and
123
  # to avoid screwing with syndicated_post filters
134
  // This just gives us an alphanumeric name for the author.
135
  // We look up (or create) the numeric ID for the author
136
  // in SyndicatedPost::add().
137
+
138
  $this->post['post_content'] = apply_filters(
139
  'syndicated_item_content',
140
  $this->content(), $this
168
  // overwrite if necessary; thus preventing any munging.
169
  $postMetaIn = $this->link->postmeta(array("parsed" => true));
170
  $postMetaOut = array();
171
+
172
  foreach ($postMetaIn as $key => $meta) :
173
  $postMetaOut[$key] = $meta->do_substitutions($this);
174
  endforeach;
175
+
176
  foreach ($postMetaOut as $key => $values) :
177
  $this->post['meta'][$key] = array();
178
  foreach ($values as $value) :
179
  $this->post['meta'][$key][] = apply_filters("syndicated_post_meta_{$key}", $value, $this);
180
  endforeach;
181
  endforeach;
182
+
183
  // RSS 2.0 / Atom 1.0 enclosure support
184
  $enclosures = $this->entry->get_enclosures();
185
  if (is_array($enclosures)) : foreach ($enclosures as $enclosure) :
191
 
192
  // In case you want to point back to the blog this was
193
  // syndicated from.
194
+
195
  $sourcemeta['syndication_source'] = apply_filters(
196
  'syndicated_item_source_title',
197
  $this->link->name(),
207
  $this->link->guid(),
208
  $this
209
  );
210
+
211
  // Make use of atom:source data, if present in an aggregated feed
212
  $entry_source = $this->source();
213
  if (!is_null($entry_source)) :
217
  elseif ($what=='feed') : $key = 'syndication_feed';
218
  else : $key = "syndication_source_${what}";
219
  endif;
220
+
221
  $sourcemeta["${key}_original"] = apply_filters(
222
  'syndicated_item_original_source_'.$what,
223
  $value,
226
  endif;
227
  endforeach;
228
  endif;
229
+
230
  foreach ($sourcemeta as $meta_key => $value) :
231
  if (!is_null($value)) :
232
  $this->post['meta'][$meta_key] = $value;
234
  endforeach;
235
 
236
  // Store information on human-readable and machine-readable comment URIs
237
+
238
  // Human-readable comment URI
239
  $commentLink = apply_filters('syndicated_item_comments', $this->comment_link(), $this);
240
  if (!is_null($commentLink)) : $this->post['meta']['rss:comments'] = $commentLink; endif;
277
  $cats = array_merge($cats, $fc);
278
  endif;
279
  $this->preset_terms['category'] = $cats;
280
+
281
  // Now add categories from the post, if we have 'em
282
  $cats = array();
283
  $post_cats = $this->entry->get_categories();
284
  if (is_array($post_cats)) : foreach ($post_cats as $cat) :
285
  $cat_name = $cat->get_term();
286
  if (!$cat_name) : $cat_name = $cat->get_label(); endif;
287
+
288
  if ($this->link->setting('cat_split', NULL, NULL)) :
289
  $pcre = "\007".$this->feedmeta['cat_split']."\007";
290
  $cats = array_merge(
302
  endforeach; endif;
303
 
304
  $this->feed_terms['category'] = apply_filters('syndicated_item_categories', $cats, $this);
305
+
306
  // Tags: start with default tags, if any
307
  $tags = array();
308
  if ('no' != $this->link->setting('add/post_tag', NULL, 'yes')) :
309
  $ft = get_option("feedwordpress_syndication_tags", NULL);
310
  $tags = (is_null($ft) ? array() : explode(FEEDWORDPRESS_CAT_SEPARATOR, $ft));
311
  endif;
312
+
313
  $ft = $this->link->setting('tags', NULL, array());
314
  if (is_array($ft)) :
315
  $tags = array_merge($tags, $ft);
316
  endif;
317
  $this->preset_terms['post_tag'] = $tags;
318
+
319
  // Scan post for /a[@rel='tag'] and use as tags if present
320
  $tags = $this->inline_tags();
321
  $this->feed_terms['post_tag'] = apply_filters('syndicated_item_tags', $tags, $this);
322
+
323
  $taxonomies = $this->link->taxonomies();
324
  $feedTerms = $this->link->setting('terms', NULL, array());
325
  $globalTerms = get_option('feedwordpress_syndication_terms', array());
328
  foreach ($taxonomies as $tax) :
329
  if (!isset($specials[$tax])) :
330
  $terms = array();
331
+
332
  // See if we should get the globals
333
  if ('no' != $this->link->setting("add/$tax", NULL, 'yes')) :
334
  if (isset($globalTerms[$tax])) :
335
  $terms = $globalTerms[$tax];
336
  endif;
337
  endif;
338
+
339
  // Now merge in the locals
340
  if (isset($feedTerms[$tax])) :
341
  $terms = array_merge($terms, $feedTerms[$tax]);
356
 
357
  function substitution_function ($name) {
358
  $ret = NULL;
359
+
360
  switch ($name) :
361
  // Allowed PHP string functions
362
  case 'trim':
370
  endswitch;
371
  return $ret;
372
  }
373
+
374
  /**
375
  * SyndicatedPost::query uses an XPath-like syntax to query arbitrary
376
  * elements within the syndicated item.
387
  foreach ($match as $ref) :
388
  $urlHash[md5($ref[1])] = $ref[1];
389
  endforeach;
390
+
391
  foreach ($urlHash as $hash => $url) :
392
+ $path = str_replace('{'.$url.'}', '{#'.$hash.'}', $path);
393
  endforeach;
394
 
395
  $path = explode('/', $path);
410
  while (strlen($node)==0 and !is_null($node)) :
411
  $node = array_shift($path);
412
  endwhile;
413
+
414
  switch ($node) :
415
  case 'feed' :
416
  case 'channel' :
444
  $addenda = $elements[$element];
445
  $contexts = $elements[$element];
446
  endif;
447
+
448
  foreach ($addenda as $index => $addendum) :
449
  $context = $contexts[$index];
450
 
454
  endif;
455
  endforeach;
456
  endif;
457
+ endforeach;
458
  endif;
459
  endforeach;
460
+
461
  $data = $matches;
462
  endif;
463
  $node = array_shift($path);
464
  endwhile;
465
+
466
  $matches = array();
467
  foreach ($data as $datum) :
468
  if (is_string($datum)) :
491
  'http://backend.userland.com/RSS2',
492
  SIMPLEPIE_NAMESPACE_RSS_20,
493
  );
494
+
495
  $matches = array();
496
  foreach ($rss as $ns) :
497
  $data = $this->link->simplepie->get_feed_tags($ns, 'channel');
518
  else :
519
  $defaultNS = SIMPLEPIE_NAMESPACE_RSS_20;
520
  endif;
521
+ return $defaultNS;
522
  } /* SyndicatedPost::xpath_default_namespace() */
523
 
524
  function xpath_name_and_axis ($node) {
553
  $ns = array($ref[1]);
554
  elseif (strpos($node, ':') !== FALSE) :
555
  list($xmlns, $element) = explode(':', $node, 2);
556
+
557
  if (isset($this->xmlns['reverse'][$xmlns])) :
558
  $ns = $this->xmlns['reverse'][$xmlns];
559
  else :
560
  $ns = array($xmlns);
561
  endif;
562
+
563
  // Fucking SimplePie. For attributes in default xmlns.
564
  $defaultNS = $this->xpath_default_namespace();
565
  if (isset($this->xmlns['forward'][$defaultNS])
566
  and ($xmlns==$this->xmlns['forward'][$defaultNS])) :
567
  $ns[] = '';
568
  endif;
569
+
570
  if (isset($datum['xmlns'])) :
571
  if (isset($datum['xmlns'][$xmlns])) :
572
  $ns[] = $datum['xmlns'][$xmlns];
580
  return array_unique($ns);
581
  } /* SyndicatedPost::xpath_possible_namespaces() */
582
 
583
+ function get_categories ($params = array()) {
584
+ return $this->entry->get_categories();
585
+ }
586
+
587
+ function title ($params = array()) {
588
+ return $this->entry->get_title();
589
+ } /* SyndicatedPost::title () */
590
+
591
+ function content ($params = array()) {
592
+ $params = wp_parse_args($params, array(
593
+ "full only" => false,
594
+ ));
595
+
596
  $content = NULL;
597
+
598
+ // FIXME: This is one of the main places in the code still using
599
+ // the outmoded SimplePie - to - Magpie construction. We could
600
+ // replace using SimplePie_Item::get_tags() here. (Or if really
601
+ // ambitious we could attempt to just use
602
+ // SimplePie_Item::get_content() with content-only set to TRUE
603
+ // and some sanitization in effect. -CJ 1jul14
604
+
605
+ // atom:content, standard method of providing full HTML content
606
+ // in Atom feeds.
607
  if (isset($this->item['atom_content'])) :
608
  $content = $this->item['atom_content'];
609
+ elseif (isset($this->item['atom']['atom_content'])) :
610
+ $content = $this->item['atom']['atom_content'];
611
+
612
+ // Some exotics: back in the day, before widespread convergence
613
+ // on content:encoding, some RSS feeds took advantage of XML
614
+ // namespaces to use an inline xhtml:body or xhtml:div element
615
+ // for full-content HTML. (E.g. Sam Ruby's feed, IIRC.)
616
  elseif (isset($this->item['xhtml']['body'])) :
617
  $content = $this->item['xhtml']['body'];
618
  elseif (isset($this->item['xhtml']['div'])) :
619
  $content = $this->item['xhtml']['div'];
620
+
621
+ // content:encoded, most common method of providing full HTML in
622
+ // RSS 2.0 feeds.
623
  elseif (isset($this->item['content']['encoded']) and $this->item['content']['encoded']):
624
  $content = $this->item['content']['encoded'];
625
+
626
+ // Fall back on elements that sometimes may contain full HTML
627
+ // but sometimes not.
628
+ elseif (!$params['full only']) :
629
+
630
+ // description element is sometimes used for full HTML
631
+ // sometimes for summary text in RSS. (By the letter of
632
+ // the standard, it should just be for summary text.)
633
+ if (isset($this->item['description'])) :
634
+ $content = $this->item['description'];
635
+ endif;
636
+
637
  endif;
638
  return $content;
639
  } /* SyndicatedPost::content() */
641
  function excerpt () {
642
  # Identify and sanitize excerpt: atom:summary, or rss:description
643
  $excerpt = $this->entry->get_description();
644
+
645
  # Many RSS feeds use rss:description, inadvisably, to
646
  # carry the entire post (typically with escaped HTML).
647
  # If that's what happened, we don't want the full
648
  # content for the excerpt.
649
  $content = $this->content();
650
+
651
  // Ignore whitespace, case, and tag cruft.
652
  $theExcerpt = preg_replace('/\s+/', '', strtolower(strip_tags($excerpt)));
653
  $theContent = preg_replace('/\s+/', '', strtolower(strip_tags($content)));
674
  function created ($params = array()) {
675
  $unfiltered = false; $default = NULL;
676
  extract($params);
677
+
678
  $date = '';
679
  if (isset($this->item['dc']['created'])) :
680
  $date = $this->item['dc']['created'];
699
  else : // New style
700
  extract($params);
701
  endif;
702
+
703
  $date = '';
704
  $ts = null;
705
 
718
  elseif (isset($this->item['pubdate'])): // RSS 2.0
719
  $date = $this->item['pubdate'];
720
  endif;
721
+
722
  if (strlen($date) > 0) :
723
  $time = new FeedTime($date);
724
  $ts = $time->timestamp();
725
  elseif ($fallback) : // Fall back to <updated> / <modified> if present
726
  $ts = $this->updated(/*fallback=*/ false, /*default=*/ $default);
727
  endif;
728
+
729
  # If everything failed, then default to the current time.
730
  if (is_null($ts)) :
731
  if (-1 == $default) :
734
  $ts = $default;
735
  endif;
736
  endif;
737
+
738
  if (!$unfiltered) :
739
  $ts = apply_filters('syndicated_item_published', $ts, $this);
740
  endif;
764
  elseif (isset($this->item['updated'])): // Atom 1.0
765
  $date = $this->item['updated'];
766
  endif;
767
+
768
  if (strlen($date) > 0) :
769
  $time = new FeedTime($date);
770
  $ts = $time->timestamp();
771
  elseif ($fallback) : // Fall back to issued / dc:date
772
  $ts = $this->published(/*fallback=*/ false, /*default=*/ $default);
773
  endif;
774
+
775
  # If everything failed, then default to the current time.
776
  if (is_null($ts)) :
777
  if (-1 == $default) :
812
  "content" => $this->content(),
813
  "excerpt" => $this->excerpt(),
814
  );
815
+
816
  if ($hashed) :
817
  $hash = md5(serialize($hash));
818
  endif;
819
+
820
  return $hash;
821
  } /* SyndicatedPost::update_hash() */
822
 
823
+ static function normalize_guid_prefix () {
824
  return trailingslashit(get_bloginfo('url')).'?guid=';
825
  }
826
+
827
+ static function normalize_guid ($guid) {
828
  $guid = trim($guid);
829
  if (preg_match('/^[0-9a-z]{32}$/i', $guid)) : // MD5
830
  $guid = SyndicatedPost::normalize_guid_prefix().strtolower($guid);
834
  $guid = trim($guid);
835
  return $guid;
836
  } /* SyndicatedPost::normalize_guid() */
837
+
838
  function guid () {
839
  $guid = null;
840
  if (isset($this->item['id'])): // Atom 0.3 / 1.0
846
  elseif (isset($this->item['dc']['identifier'])) : // yeah, right
847
  $guid = $this->item['dc']['identifier'];
848
  endif;
849
+
850
  // Un-set or too long to use as-is. Generate a tag: URI.
851
  if (is_null($guid) or strlen($guid) > 250) :
852
  // In case we need to check this again
853
  $original_guid = $guid;
854
+
855
  // The feed does not seem to have provided us with a
856
  // usable unique identifier, so we'll have to cobble
857
  // together a tag: URI that might work for us. The base
869
  // are hashed down into a nice, manageable tag: URI.
870
  if (!is_null($original_guid)) :
871
  $guid .= ',2010-12-03:id.'.md5($original_guid);
872
+
873
  // If we have a date of creation, then we can use that
874
  // to uniquely identify the item. (On the other hand, if
875
  // the feed producer was consicentious enough to
877
  // conscientious enough to generate unique identifiers.)
878
  elseif (!is_null($this->created())) :
879
  $guid .= '://post.'.date('YmdHis', $this->created());
880
+
881
  // Otherwise, use both the URI of the item, *and* the
882
  // item's title. We have to use both because titles are
883
  // often not unique, and sometimes links aren't unique
893
  endif;
894
  return $guid;
895
  } /* SyndicatedPost::guid() */
896
+
897
  function author () {
898
  $author = array ();
899
+
900
  $aa = $this->entry->get_authors();
901
  if (count($aa) > 0) :
902
  $a = reset($aa);
927
  // e-mail address, but lots of people don't use
928
  // it that way. So let's make of it what we can.
929
  $author = parse_email_with_realname($this->item['author']);
930
+
931
  if (!isset($author['name'])) :
932
  if (isset($author['email'])) :
933
  $author['name'] = $author['email'];
937
  endif;
938
  endif;
939
  endif;
940
+
941
  if (!isset($author['name']) or is_null($author['name'])) :
942
  // Nothing found. Try some crappy defaults.
943
  if ($this->link->name()) :
947
  $author['name'] = $url['host'];
948
  endif;
949
  endif;
950
+
951
  if (FEEDWORDPRESS_COMPATIBILITY) :
952
  if (isset($this->item['author_email'])):
953
  $author['email'] = $this->item['author_email'];
954
  elseif (isset($this->feed->channel['author_email'])) :
955
  $author['email'] = $this->feed->channel['author_email'];
956
  endif;
957
+
958
  if (isset($this->item['author_uri'])):
959
  $author['uri'] = $this->item['author_uri'];
960
  elseif (isset($this->item['author_url'])):
967
  $author['uri'] = $this->feed->channel['link'];
968
  endif;
969
  endif;
970
+
971
  return $author;
972
  } /* SyndicatedPost::author() */
973
 
991
  endif;
992
  return $tags;
993
  }
994
+
995
  /**
996
  * SyndicatedPost::isTaggedAs: Test whether a feed item is
997
  * tagged / categorized with a given string. Case and leading and
999
  *
1000
  * @param string $tag Tag to check for
1001
  *
1002
+ * @return bool Whether or not at least one of the categories / tags on
1003
  * $this->item is set to $tag (modulo case and leading and trailing
1004
  * whitespace)
1005
  */
1014
  // on this item is stored under index "category#".
1015
  if (isset($this->item['category#'])) :
1016
  $numberOfCategories = (int) $this->item['category#'];
1017
+
1018
  // We REALLY shouldn't have the old and busted MagpieRSS, but in
1019
  // case we do, it doesn't support multiple categories, but there
1020
  // might still be a single value under the "category" index.
1073
  endif;
1074
  endfor;
1075
  endif;
1076
+ return $enclosures;
1077
  } /* SyndicatedPost::enclosures() */
1078
 
1079
  function source ($what = NULL) {
1084
  $ret['title'] = $source->get_title();
1085
  $ret['uri'] = $source->get_link();
1086
  $ret['feed'] = $source->get_link(0, 'self');
1087
+
1088
  if ($id_tags = $source->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id')) :
1089
  $ret['id'] = $id_tags[0]['data'];
1090
  elseif ($id_tags = $source->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id')) :
1097
  $ret['id'] = $id_tags[0]['data'];
1098
  endif;
1099
  endif;
1100
+
1101
  if (!is_null($what) and is_scalar($what)) :
1102
  $ret = $ret[$what];
1103
  endif;
1104
  return $ret;
1105
  }
1106
+
1107
  function comment_link () {
1108
  $url = null;
1109
+
1110
  // RSS 2.0 has a standard <comments> element:
1111
  // "<comments> is an optional sub-element of <item>. If present,
1112
  // it is the url of the comments page for the item."
1119
  // element with @rel="replies" and @type="text/html".
1120
  // Unfortunately, SimplePie_Item::get_links() allows us to filter
1121
  // by the value of @rel, but not by the value of @type. *sigh*
1122
+
1123
  // Try Atom 1.0 first
1124
  $linkElements = $this->entry->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link');
1125
+
1126
  // Fall back and try Atom 0.3
1127
  if (is_null($linkElements)) : $linkElements = $this->entry->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'); endif;
1128
+
1129
  // Now loop through the elements, screening by @rel and @type
1130
  if (is_array($linkElements)) : foreach ($linkElements as $link) :
1131
  $rel = (isset($link['attribs']['']['rel']) ? $link['attribs']['']['rel'] : 'alternate');
1216
  return $tag['prefix'] . $url . $tag['suffix'];
1217
  } /* function SyndicatedPost::resolve_single_relative_uri() */
1218
 
1219
+ static function resolve_relative_uris ($content, $obj) {
1220
  $set = $obj->link->setting('resolve relative', 'resolve_relative', 'yes');
1221
+ if ($set and $set != 'no') :
1222
  // Fallback: if we don't have anything better, use the
1223
  // item link from the feed
1224
  $obj->_base = $obj->permalink(); // Reset the base for resolving relative URIs
1240
  );
1241
  endforeach;
1242
  endif;
1243
+
1244
  return $content;
1245
  } /* function SyndicatedPost::resolve_relative_uris () */
1246
 
1255
  return $tag['before_attribute'].$tag['after_attribute'];
1256
  }
1257
 
1258
+ static function sanitize_content ($content, $obj) {
1259
  # This kind of sucks. I intend to replace it with
1260
  # lib_filter sometime soon.
1261
  foreach ($obj->strip_attrs as $pair):
1292
  * still up-to-date.
1293
  *
1294
  * @return int A status code representing the freshness of the post
1295
+ * -1 = post already syndicated; has a revision that needs to be stored, but not updated to
1296
  * 0 = post already syndicated; no update needed
1297
  * 1 = post already syndicated, but needs to be updated to latest
1298
  * 2 = post has not yet been syndicated; needs to be created
1299
  */
1300
+ function freshness ($format = 'number') {
1301
  global $wpdb;
1302
 
1303
  if ($this->filtered()) : // This should never happen.
1304
  FeedWordPress::critical_bug('SyndicatedPost', $this, __LINE__, __FILE__);
1305
  endif;
1306
+
1307
  if (is_null($this->_freshness)) : // Not yet checked and cached.
1308
  $guid = $this->post['guid'];
1309
+ $eguid = esc_sql($this->post['guid']);
1310
 
1311
  $q = new WP_Query(array(
1312
  'fields' => '_synfresh', // id, guid, post_modified_gmt
1313
  'ignore_sticky_posts' => true,
1314
  'guid' => $guid,
1315
  ));
1316
+
1317
  $old_post = NULL;
1318
  if ($q->have_posts()) :
1319
  while ($q->have_posts()) : $q->the_post();
1320
  $old_post = $q->post;
1321
  endwhile;
1322
  endif;
1323
+
1324
  if (is_null($old_post)) : // No post with this guid
1325
  FeedWordPress::diagnostic('feed_items:freshness', 'Item ['.$guid.'] "'.$this->entry->get_title().'" is a NEW POST.');
1326
  $this->_wp_id = NULL;
1327
  $this->_freshness = 2; // New content
1328
  else :
1329
+ // Presume there is nothing new until we find
1330
+ // something new.
1331
+ $updated = false;
1332
+ $live = false;
1333
+
1334
+ // Pull the list of existing revisions to get
1335
+ // timestamps.
1336
+ $revisions = wp_get_post_revisions($old_post->ID);
1337
+ foreach ($revisions as $rev) :
1338
+ $revisions_ts[] = mysql2date('G', $rev->post_modified_gmt);
1339
+ endforeach;
1340
 
1341
+ $revisions_ts[] = mysql2date('G', $old_post->post_modified_gmt);
1342
+ $last_rev_ts = end($revisions_ts);
1343
  $updated_ts = $this->updated(/*fallback=*/ true, /*default=*/ NULL);
1344
 
1345
+ // If we have an explicit updated timestamp,
1346
+ // check that against existing stamps.
1347
+ if (!is_null($updated_ts)) :
1348
+ $updated = !in_array($updated_ts, $revisions_ts);
1349
+
1350
+ // If this a newer revision, make it go
1351
+ // live. If an older one, just record
1352
+ // the contents.
1353
+ $live = ($updated and ($updated_ts > $last_rev_ts));
1354
+ endif;
1355
 
1356
+ // This is a revision we haven't seen before, judging by the date.
1357
+
1358
  $updatedReason = NULL;
1359
  if ($updated) :
1360
  $updatedReason = preg_replace(
1365
  .date('Y-m-d H:i:s', $last_rev_ts)
1366
  .')'
1367
  );
1368
+
1369
+ // The date does not indicate a new revision, so
1370
+ // let's check the hash.
1371
  else :
1372
  // Or the hash...
1373
  $hash = $this->update_hash();
1377
  else :
1378
  $updated = true; // Can't find syndication meta-data
1379
  endif;
1380
+
1381
  if ($updated and FeedWordPress::diagnostic_on('feed_items:freshness:reasons')) :
1382
+ // In the absence of definitive
1383
+ // timestamp information, we
1384
+ // just have to assume that a
1385
+ // hash we haven't seen before
1386
+ // is a newer version.
1387
+ $live = true;
1388
+
1389
  $updatedReason = ' has a not-yet-seen update hash: '
1390
+ .MyPHP::val($hash)
1391
  .' not in {'
1392
  .implode(", ", array_map(array('FeedWordPress', 'val'), $seen))
1393
  .'}. Basis: '
1394
+ .MyPHP::val(array_keys($this->update_hash(false)));
1395
  endif;
1396
  endif;
1397
+
1398
  $frozen = false;
1399
  if ($updated) : // Ignore if the post is frozen
1400
  $frozen = ('yes' == $this->link->setting('freeze updates', 'freeze_updates', NULL));
1401
  if (!$frozen) :
1402
  $frozen_values = get_post_custom_values('_syndication_freeze_updates', $old_post->ID);
1403
  $frozen = (count($frozen_values) > 0 and 'yes' == $frozen_values[0]);
1404
+
1405
  if ($frozen) :
1406
  $updatedReason = ' IS BLOCKED FROM BEING UPDATED BY A UPDATE LOCK ON THIS POST, EVEN THOUGH IT '.$updatedReason;
1407
  endif;
1409
  $updatedReason = ' IS BLOCKED FROM BEING UPDATED BY A FEEDWORDPRESS UPDATE LOCK, EVEN THOUGH IT '.$updatedReason;
1410
  endif;
1411
  endif;
1412
+ $live = ($live and !$frozen);
1413
 
1414
  if ($updated) :
1415
  FeedWordPress::diagnostic('feed_items:freshness', 'Item ['.$guid.'] "'.$this->entry->get_title().'" is an update of an existing post.');
1417
  $updatedReason = preg_replace('/\s+/', ' ', $updatedReason);
1418
  FeedWordPress::diagnostic('feed_items:freshness:reasons', 'Item ['.$guid.'] "'.$this->entry->get_title().'" '.$updatedReason);
1419
  endif;
1420
+
1421
+ $this->_freshness = apply_filters('syndicated_item_freshness', ($live ? 1 : -1), $updated, $frozen, $updated_ts, $last_rev_ts, $this);
1422
+
1423
  $this->_wp_id = $old_post->ID;
1424
  $this->_wp_post = $old_post;
1425
 
1436
  endif;
1437
  endif;
1438
  endif;
1439
+
1440
+ switch ($format) :
1441
+ case 'status' :
1442
+ switch ($this->_freshness) :
1443
+ case -1:
1444
+ $ret = 'stored';
1445
+ break;
1446
+ case 0:
1447
+ $ret = NULL;
1448
+ break;
1449
+ case 1:
1450
+ $ret = 'updated';
1451
+ break;
1452
+ case 2:
1453
+ default:
1454
+ $ret = 'new';
1455
+ break;
1456
+ endswitch;
1457
+ break;
1458
+ case 'number' :
1459
+ default :
1460
+ $ret = $this->_freshness;
1461
+ endswitch;
1462
+
1463
+
1464
+ return $ret;
1465
+ } /* SyndicatedPost::freshness () */
1466
+
1467
+ function has_fresh_content () {
1468
+ return ( ! $this->filtered() and $this->freshness() != 0 );
1469
+ } /* SyndicatedPost::has_fresh_content () */
1470
+
1471
+ function this_revision_needs_original_post ($freshness = NULL) {
1472
+ if (is_null($freshness)) :
1473
+ $freshness = $this->freshness();
1474
+ endif;
1475
+ return ( $freshness >= 2 );
1476
  }
1477
+
1478
+ function this_revision_is_current ($freshness = NULL) {
1479
+ if (is_null($freshness)) :
1480
+ $freshness = $this->freshness();
1481
+ endif;
1482
+ return ( $freshness >= 1 );
1483
+ } /* SyndicatedPost::this_revision_is_current () */
1484
+
1485
+ function fresh_content_is_update () {
1486
+ return ($this->freshness() < 2);
1487
+ } /* SyndicatedPost::fresh_content_is_update () */
1488
+
1489
+ function fresh_storage_diagnostic () {
1490
+ $ret = NULL;
1491
+ switch ($this->freshness()) :
1492
+ case -1 :
1493
+ $ret = 'Storing alternate revision of existing post # '.$this->wp_id().', "'.$this->post['post_title'].'"';
1494
+ break;
1495
+ case 1 :
1496
+ $ret = 'Updating existing post # '.$this->wp_id().', "'.$this->post['post_title'].'"';
1497
+ break;
1498
+ case 2 :
1499
+ default :
1500
+ $ret = 'Inserting new post "'.$this->post['post_title'].'"';
1501
+ break;
1502
+ endswitch;
1503
+ return $ret;
1504
+ } /* SyndicatedPost::fresh_storage_diagnostic() */
1505
+
1506
+ function fresh_storage_hook () {
1507
+ $ret = NULL;
1508
+ switch ($this->freshness()) :
1509
+ case -1 :
1510
+ case 1 :
1511
+ $ret = 'update_syndicated_item';
1512
+ break;
1513
+ case 2 :
1514
+ default :
1515
+ $ret = 'post_syndicated_item';
1516
+ break;
1517
+ endswitch;
1518
+ return $ret;
1519
+ } /* SyndicatedPost::fresh_storage_hook () */
1520
+
1521
  #################################################
1522
  #### INTERNAL STORAGE AND MANAGEMENT METHODS ####
1523
  #################################################
1526
  if ($this->filtered()) : // This should never happen.
1527
  FeedWordPress::critical_bug('SyndicatedPost', $this, __LINE__, __FILE__);
1528
  endif;
1529
+
1530
  if (is_null($this->_wp_id) and is_null($this->_freshness)) :
1531
  $fresh = $this->freshness(); // sets WP DB id in the process
1532
  endif;
1539
  if ($this->filtered()) : // This should never happen.
1540
  FeedWordPress::critical_bug('SyndicatedPost', $this, __LINE__, __FILE__);
1541
  endif;
1542
+
1543
  $freshness = $this->freshness();
1544
+ if ($this->has_fresh_content()) :
1545
  # -- Look up, or create, numeric ID for author
1546
  $this->post['post_author'] = $this->author_id (
1547
  $this->link->setting('unfamiliar author', 'unfamiliar_author', 'create')
1552
  $this->post = NULL;
1553
  endif;
1554
  endif;
1555
+
1556
+ // We have to check again in case post has been filtered during
1557
+ // the author_id lookup
1558
+ if ($this->has_fresh_content()) :
1559
  $consider = array(
1560
  'category' => array('abbr' => 'cats', 'domain' => array('category', 'post_tag')),
1561
  'post_tag' => array('abbr' => 'tags', 'domain' => array('post_tag')),
1566
  if (!is_null($this->post)) : // Not filtered out yet
1567
  # -- Look up, or create, numeric ID for categories
1568
  $taxonomies = $this->link->setting("match/".$taxes['abbr'], 'match_'.$taxes['abbr'], $taxes['domain']);
1569
+
1570
  // Eliminate dummy variables
1571
  $taxonomies = array_filter($taxonomies, 'remove_dummy_zero');
1572
+
1573
  $terms = $this->category_ids (
1574
  $this->feed_terms[$what],
1575
  $this->link->setting("unfamiliar {$what}", "unfamiliar_{$what}", 'create:'.$what),
1579
  'filters' => true,
1580
  )
1581
  );
1582
+
1583
  if (is_null($terms) or is_null($termSet)) :
1584
  // filtered out -- no matches
1585
  else :
1615
  if (!isset($this->post['tax_input'][$tax])) :
1616
  $this->post['tax_input'][$tax] = array();
1617
  endif;
1618
+
1619
  $this->post['tax_input'][$tax] = array_merge (
1620
  $this->post['tax_input'][$tax],
1621
  $this->category_ids (
1629
  endforeach;
1630
  endif;
1631
  endif;
1632
+
1633
+ // We have to check again in case the post has been filtered
1634
+ // during the category/tags/taxonomy terms lookup
1635
+ if ($this->has_fresh_content()) :
1636
  // Filter some individual fields
1637
+
1638
  // If there already is a post slug (from syndication or by manual
1639
  // editing) don't cause WP to overwrite it by sending in a NULL
1640
  // post_name. Props Chris Fritz 2012-11-28.
1641
+ $post_name = (is_null($this->_wp_post) ? NULL : $this->_wp_post->post_name);
1642
 
1643
  // Allow filters to set post slug. Props niska.
1644
  $post_name = apply_filters('syndicated_post_slug', $post_name, $this);
1645
  if (!empty($post_name)) :
1646
  $this->post['post_name'] = $post_name;
1647
  endif;
1648
+
1649
  $this->post = apply_filters('syndicated_post', $this->post, $this);
1650
+
1651
  // Allow for feed-specific syndicated_post filters.
1652
  $this->post = apply_filters(
1653
  "syndicated_post_".$this->link->uri(),
1655
  $this
1656
  );
1657
  endif;
1658
+
1659
  // Hook in early to make sure these get inserted if at all possible
1660
  add_action(
1661
  /*hook=*/ 'transition_post_status',
1663
  /*priority=*/ -10000, /* very early */
1664
  /*arguments=*/ 3
1665
  );
 
 
1666
 
1667
  $ret = false;
1668
+ if ($this->has_fresh_content()) :
1669
+ $diag = $this->fresh_storage_diagnostic();
1670
+ if (!is_null($diag)) :
1671
+ FeedWordPress::diagnostic('syndicated_posts', $diag);
1672
+ endif;
 
 
 
1673
 
1674
+ $this->insert_post(/*update=*/ $this->fresh_content_is_update(), $this->freshness());
 
1675
 
1676
+ $hook = $this->fresh_storage_hook();
1677
+ if (!is_null($hook)) :
1678
+ do_action($hook, $this->wp_id(), $this);
1679
+ endif;
1680
+
1681
+ $ret = $this->freshness('status');
1682
  endif;
1683
 
1684
+ // If this is a legit, non-filtered post, tag it as found on the
1685
+ // feed regardless of fresh or stale status
1686
  if (!$this->filtered()) :
1687
  $key = '_feedwordpress_retire_me_' . $this->link->id;
1688
  delete_post_meta($this->wp_id(), $key);
1689
+
1690
  $status = get_post_field('post_status', $this->wp_id());
1691
+ if ('fwpretired'==$status and $this->link->is_non_incremental()) :
1692
+ FeedWordPress::diagnostic('syndicated_posts', "Un-retiring previously retired post # ".$this->wp_id()." due to re-appearance on non-incremental feed.");
1693
  set_post_field('post_status', $this->post['post_status'], $this->wp_id());
1694
+ wp_transition_post_status($this->post['post_status'], $status, $this->post);
1695
+ elseif ('fwpzapped'==$status) :
1696
+ // Set this new revision up to be
1697
+ // blanked on the next update.
1698
+ add_post_meta($this->wp_id(), '_feedwordpress_zapped_blank_me', 2, /*single=*/ true);
1699
  endif;
1700
  endif;
1701
+
1702
  // Remove add_rss_meta hook
1703
  remove_action(
1704
  /*hook=*/ 'transition_post_status',
1709
 
1710
  return $ret;
1711
  } /* function SyndicatedPost::store () */
1712
+
1713
+ function insert_post ($update = false, $freshness = 2) {
1714
  global $wpdb;
1715
 
1716
  $dbpost = $this->normalize_post(/*new=*/ true);
1717
+
1718
  if (!is_null($dbpost)) :
1719
  $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
1720
+
1721
  // This is a ridiculous fucking kludge necessitated by WordPress 2.6 munging authorship meta-data
1722
  add_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1723
+
1724
  // Kludge to prevent kses filters from stripping the
1725
  // content of posts when updating without a logged in
1726
  // user who has `unfiltered_html` capability.
1732
  $removed[] = $munger;
1733
  endif;
1734
  endforeach;
1735
+
1736
  if ($update and function_exists('get_post_field')) :
1737
  // Don't munge status fields that the user may
1738
  // have reset manually
1739
  $doNotMunge = array('post_status', 'comment_status', 'ping_status');
1740
+
1741
  foreach ($doNotMunge as $field) :
1742
  $dbpost[$field] = get_post_field($field, $this->wp_id());
1743
  endforeach;
1744
  endif;
1745
+
1746
  // WP3's wp_insert_post scans current_user_can() for the
1747
  // tax_input, with no apparent way to override. Ugh.
1748
  add_action(
1751
  /*priority=*/ -10001, /* very early */
1752
  /*arguments=*/ 3
1753
  );
1754
+
1755
  // WP3 appears to override whatever you give it for
1756
  // post_modified. Ugh.
1757
  add_action(
1765
  $this->post['ID'] = $this->wp_id();
1766
  $dbpost['ID'] = $this->post['ID'];
1767
  endif;
1768
+
1769
+ // O.K., is this a new post? If so, we need to create
1770
+ // the basic post record before we do anything else.
1771
+ if ($this->this_revision_needs_original_post()) :
1772
+ // *sigh*, for handling inconsistent slash expectations < 3.6
1773
+ $sdbpost = $this->db_sanitize_post($dbpost);
1774
+
1775
+ // Go ahead and insert the first post record to
1776
+ // anchor the revision history.
1777
+ $this->_wp_id = wp_insert_post($sdbpost, /*return wp_error=*/ true);
1778
+
1779
+ $dbpost['ID'] = $this->_wp_id;
1780
+ endif;
1781
+
1782
+ // Now that we've made sure the original exists, insert
1783
+ // this version here as a revision.
1784
+ $revision_id = _wp_put_post_revision($dbpost, /*autosave=*/ false);
1785
+
1786
+ if (!$this->this_revision_needs_original_post()) :
1787
 
1788
+ if ($this->this_revision_is_current()) :
1789
+
1790
+ wp_restore_post_revision($revision_id);
1791
+
1792
+ else :
1793
+
1794
+ // If we do not activate this revision, then the
1795
+ // add_rss_meta will not be called, which is
1796
+ // more or less as it should be, but that means
1797
+ // we have to actively record this revision's
1798
+ // update hash from here.
1799
+ $postId = $this->post['ID'];
1800
+ $key = 'syndication_item_hash';
1801
+ $hash = $this->update_hash();
1802
+ FeedWordPress::diagnostic('syndicated_posts:meta_data', "Adding post meta-datum to post [$postId]: [$key] = ".FeedWordPress::val($hash, /*no newlines=*/ true));
1803
+ add_post_meta( $postId, $key, $hash, /*unique=*/ false );
1804
+ endif;
1805
+ endif;
1806
 
1807
  remove_action(
1808
  /*hook=*/ 'transition_post_status',
1823
  foreach ($removed as $filter) :
1824
  add_filter('content_save_pre', $filter);
1825
  endforeach;
1826
+
1827
  $this->validate_post_id($dbpost, $update, array(__CLASS__, __FUNCTION__));
1828
  endif;
1829
  } /* function SyndicatedPost::insert_post () */
1830
+
1831
  function insert_new () {
1832
+ $this->insert_post(/*update=*/ false, 1);
1833
  } /* SyndicatedPost::insert_new() */
1834
 
1835
  function update_existing () {
1836
+ $this->insert_post(/*update=*/ true, 2);
1837
  } /* SyndicatedPost::update_existing() */
1838
 
1839
  /**
1860
  $feed_url = parse_url($this->post['meta']['syndication_feed']);
1861
  $source_title = $feed_url['host'];
1862
  endif;
1863
+
1864
  $out['post_title'] = $source_title
1865
  .' '.gmdate('Y-m-d H:i:s', $this->published() + $offset);
1866
  // FIXME: Option for what to fill a blank title with...
1869
  // Normalize the guid if necessary.
1870
  $out['guid'] = SyndicatedPost::normalize_guid($out['guid']);
1871
 
 
 
 
 
 
 
 
 
 
1872
  return $out;
1873
  }
1874
 
1875
+ function db_sanitize_post ($out) {
1876
+ // < 3.6. Core API, including wp_insert_post(), will expect
1877
+ // properly slashed data. If wp_slash() exists, then this is
1878
+ // after the big change-over, and wp_insert_post() etc. will
1879
+ // expect *un*-slashed data.
1880
+ if (!function_exists('wp_slash')) :
1881
+
1882
+ foreach ($out as $key => $value) :
1883
+ if (is_string($value)) :
1884
+ $out[$key] = esc_sql($value);
1885
+ else :
1886
+ $out[$key] = $value;
1887
+ endif;
1888
+ endforeach;
1889
+
1890
+ endif;
1891
+
1892
+ return $out;
1893
+ }
1894
+
1895
  /**
1896
  * SyndicatedPost::validate_post_id()
1897
  *
1913
  // notice if we are in debug mode.
1914
  $mesg = "Failed to $verb item [$guid]. WordPress API returned no valid post ID.\n"
1915
  ."\t\tID = ".serialize($this->_wp_id)."\n"
1916
+ ."\t\tURL = ".MyPHP::val($url)
1917
+ ."\t\tFeed = ".MyPHP::val($feed);
1918
+
1919
  FeedWordPress::diagnostic('updated_feeds:errors', "WordPress API error: $mesg");
1920
  FeedWordPress::diagnostic('feed_items:rejected', $mesg);
1921
 
1923
  The WordPress API returned an invalid post ID
1924
  when FeedWordPress tried to $verb item $guid
1925
  [URL: $url]
1926
+ from the feed at $feed
1927
 
1928
+ $ns::_wp_id
1929
  EOM;
1930
  FeedWordPress::noncritical_bug(
1931
  /*message=*/ $mesg,
1937
  );
1938
  endif;
1939
  } /* SyndicatedPost::validate_post_id() */
1940
+
1941
  /**
1942
+ * SyndicatedPost::fix_revision_meta() - Ensures that we get the meta
1943
+ * data (authorship, guid, etc.) that we want when storing revisions of
1944
+ * a syndicated post.
1945
  *
1946
+ * In their infinite wisdom, the WordPress coders seem to have made it
1947
+ * completely impossible for a plugin that uses wp_insert_post() to set
1948
+ * certain meta-data (such as the author) when you store an old revision
1949
+ * of an updated post. Instead, it uses the WordPress defaults (= cur.
1950
  * active user ID if the process is running with a user logged in, or
1951
  * = #0 if there is no user logged in). This results in bogus authorship
1952
  * data for revisions that are syndicated from off the feed, unless we
1957
  */
1958
  function fix_revision_meta ($revision_id) {
1959
  global $wpdb;
1960
+
1961
  $post_author = (int) $this->post['post_author'];
1962
+
1963
  $revision_id = (int) $revision_id;
1964
+
1965
+ // Let's fix the author.
1966
+ set_post_field('post_author', $this->post['post_author'], $revision_id);
1967
+
1968
+ // Let's fix the GUID to a dummy URL with the update hash.
1969
+ set_post_field('guid', 'http://feedwordpress.radgeek.com/?rev='.$this->update_hash(), $revision_id);
1970
+
1971
+ // Let's fire an event for add-ons and filters
1972
+ do_action('syndicated_post_fix_revision_meta', $revision_id, $this);
1973
+
1974
  } /* SyndicatedPost::fix_revision_meta () */
1975
+
1976
  /**
1977
  * SyndicatedPost::add_terms() -- if FeedWordPress is processing an
1978
  * automatic update, that generally means that wp_insert_post() is being
1991
  * @param object $post The database record for the post just inserted.
1992
  */
1993
  function add_terms ($new_status, $old_status, $post) {
1994
+
1995
  if ($new_status!='inherit') : // Bail if we are creating a revision.
1996
  if ( is_array($this->post) and isset($this->post['tax_input']) and is_array($this->post['tax_input']) ) :
1997
  foreach ($this->post['tax_input'] as $taxonomy => $terms) :
1998
  if (is_array($terms)) :
1999
  $terms = array_filter($terms); // strip out empties
2000
  endif;
2001
+
2002
+ $res = wp_set_post_terms(
2003
+ /*post_id=*/ $post->ID,
2004
+ /*terms=*/ $terms,
2005
+ /*taxonomy=*/ $taxonomy
2006
+ );
2007
+
2008
+ FeedWordPress::diagnostic(
2009
+ 'syndicated_posts:categories',
2010
+ 'Category: post('.json_encode($post->ID).') '.$taxonomy
2011
+ .' := '
2012
+ .json_encode($terms)
2013
+ .' / result: '
2014
+ .json_encode($res)
2015
+ );
2016
+
2017
  endforeach;
2018
  endif;
2019
  endif;
2020
+
2021
  } /* SyndicatedPost::add_terms () */
2022
+
2023
  /**
2024
  * SyndicatedPost::fix_post_modified_ts() -- We would like to set
2025
  * post_modified and post_modified_gmt to reflect the value of
2044
  ), /*where=*/ array('ID' => $post->ID) );
2045
  endif;
2046
  } /* SyndicatedPost::fix_post_modified_ts () */
2047
+
2048
  /**
2049
  * SyndicatedPost::add_rss_meta: adds interesting meta-data to each entry
2050
  * using the space for custom keys. The set of keys and values to add is
2067
 
2068
  if ( is_array($this->post) and isset($this->post['meta']) and is_array($this->post['meta']) ) :
2069
  $postId = $post->ID;
2070
+
2071
  // Aggregated posts should NOT send out pingbacks.
2072
  // WordPress 2.1-2.2 claim you can tell them not to
2073
  // using $post_pingback, but they don't listen, so we
2076
  DELETE FROM $wpdb->postmeta
2077
  WHERE post_id='$postId' AND meta_key='_pingme'
2078
  ");
2079
+
2080
  foreach ( $this->post['meta'] as $key => $values ) :
2081
+ $eKey = esc_sql($key);
2082
+
2083
  // If this is an update, clear out the old
2084
  // values to avoid duplication.
2085
  $result = $wpdb->query("
2086
  DELETE FROM $wpdb->postmeta
2087
  WHERE post_id='$postId' AND meta_key='$eKey'
2088
  ");
2089
+
2090
  // Allow for either a single value or an array
2091
  if (!is_array($values)) $values = array($values);
2092
  foreach ( $values as $value ) :
2093
+ FeedWordPress::diagnostic('syndicated_posts:meta_data', "Adding post meta-datum to post [$postId]: [$key] = ".MyPHP::val($value, /*no newlines=*/ true));
2094
  add_post_meta($postId, $key, $value, /*unique=*/ false);
2095
  endforeach;
2096
  endforeach;
2115
  $source = $this->source();
2116
  $forbidden = apply_filters('feedwordpress_forbidden_author_names',
2117
  array('admin', 'administrator', 'www', 'root'));
2118
+
2119
  // Prepare the list of candidates to try for author name: name from
2120
  // feed, original source title (if any), immediate source title live
2121
  // from feed, subscription title, prettied version of feed homepage URL,
2130
  if (strlen($this->link->homepage()) > 0) : $candidates[] = feedwordpress_display_url($this->link->homepage()); endif;
2131
  $candidates[] = feedwordpress_display_url($this->link->uri());
2132
  $candidates[] = 'unknown author';
2133
+
2134
  // Pick the first one that works from the list, screening against empty
2135
  // or forbidden names.
2136
+
2137
  $author = NULL;
2138
  while (is_null($author) and ($candidate = each($candidates))) :
2139
  if (!is_null($candidate['value'])
2142
  $author = $candidate['value'];
2143
  endif;
2144
  endwhile;
2145
+
2146
  $email = (isset($a['email']) ? $a['email'] : NULL);
2147
  $authorUrl = (isset($a['uri']) ? $a['uri'] : NULL);
2148
 
2149
+
2150
  $hostUrl = $this->link->homepage();
2151
  if (is_null($hostUrl) or (strlen($hostUrl) < 0)) :
2152
  $hostUrl = $this->link->uri();
2173
  // Uniqueness will be guaranteed below if necessary.
2174
 
2175
  $url = parse_url($hostUrl);
2176
+
2177
  $login = sanitize_user($url['host'], /*strict=*/ true);
2178
  if (strlen($login) < 1) :
2179
  // This isn't working. Frak it.
2186
  $nice_author = sanitize_title($author);
2187
  $nice_author = apply_filters('pre_user_nicename', $nice_author);
2188
 
2189
+ $reg_author = esc_sql(preg_quote($author));
2190
+ $author = esc_sql($author);
2191
+ $email = esc_sql($email);
2192
+ $test_email = esc_sql($test_email);
2193
+ $authorUrl = esc_sql($authorUrl);
2194
 
2195
  // Check for an existing author rule....
2196
  if (isset($this->link->settings['map authors']['name']['*'])) :
2208
  // User name is filtered out
2209
  elseif ('filter' == $author_rule) :
2210
  $id = NULL;
2211
+
2212
  else :
2213
  // Check the database for an existing author record that might fit
2214
 
2221
  LENGTH(TRIM(LCASE(user_email))) > 0
2222
  AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
2223
  )");
2224
+
2225
  // If that fails, look for aliases in the user meta data table
2226
  if (is_null($id)) :
2227
  $id = $wpdb->get_var(
2266
  if (isset($parts[1])) : $userdata['last_name'] = $parts[1]; endif;
2267
  $userdata['display_name'] = $author;
2268
  $userdata['role'] = 'contributor';
2269
+
2270
  do { // Keep trying until you get it right. Or until PHP crashes, I guess.
2271
  $id = wp_insert_user($userdata);
2272
  if (is_wp_error($id)) :
2280
  case 'existing_user_email' :
2281
  // No disassemble!
2282
  $parts = explode('@', $userdata['user_email'], 2);
2283
+
2284
  // Add a random disambiguator as a gmail-style username extension
2285
  $parts[0] .= '+'.substr(md5(uniqid(microtime())), 0, 6);
2286
+
2287
  // Reassemble
2288
  $userdata['user_email'] = $parts[0].'@'.$parts[1];
2289
  break;
2300
 
2301
  if ($id) :
2302
  $this->link->settings['map authors']['name'][strtolower(trim($author))] = $id;
2303
+
2304
  // Multisite: Check whether the author has been recorded
2305
  // on *this* blog before. If not, put her down as a
2306
  // Contributor for *this* blog.
2309
  $user->add_role('contributor');
2310
  endif;
2311
  endif;
2312
+ return $id;
2313
  } /* function SyndicatedPost::author_id () */
2314
 
2315
  /**
2316
+ * category_ids: look up (and create) category ids from a list of
2317
+ * categories
2318
  *
2319
  * @param array $cats
2320
  * @param string $unfamiliar_category
2321
  * @param array|null $taxonomies
2322
  * @return array
2323
+ */
2324
  function category_ids ($cats, $unfamiliar_category = 'create', $taxonomies = NULL, $params = array()) {
2325
+ return $this->link->category_ids($this, $cats, $unfamiliar_category, $taxonomies, $params);
2326
+ } /* SyndicatedPost::category_ids () */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2327
 
2328
  } /* class SyndicatedPost */
2329
 
syndicatedpostterm.class.php ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class SyndicatedPostTerm {
3
+ private $term, $tax, $exists, $exists_in, $post;
4
+
5
+ public function __construct ($term, $taxonomies, $post) {
6
+ $catTax = 'category';
7
+
8
+ $this->post = $post;
9
+
10
+ // Default to these
11
+ $this->term = NULL;
12
+ $this->tax = NULL;
13
+ $this->exists = NULL;
14
+ $this->exists_in = NULL;
15
+
16
+ if (preg_match('/^{([^#}]*)#([0-9]+)}$/', $term, $backref)) :
17
+ $cat_id = (int) $backref[2];
18
+ $tax = $backref[1];
19
+ if (strlen($tax) < 1) :
20
+ $tax = $catTax;
21
+ endif;
22
+
23
+ $aTerm = get_term($cat_id, $tax);
24
+ if (!is_wp_error($aTerm) and !!$aTerm) :
25
+ $this->exists = (array) $aTerm;
26
+ $this->exists_in = $this->exists['taxonomy'];
27
+
28
+ $this->term = $this->exists['name'];
29
+ $this->tax = array($this->exists['taxonomy']);
30
+ endif;
31
+
32
+ else :
33
+ $this->term = $term;
34
+ $this->tax = $taxonomies;
35
+
36
+ // Leave exists/exists_in empty until we search()
37
+
38
+ endif;
39
+
40
+ if (is_null($this->tax)) :
41
+ $this->tax = array($catTax);
42
+ endif;
43
+ } /* SyndicatedPostTerm constructor */
44
+
45
+ public function is_familiar () {
46
+ $ex = $this->exists;
47
+ if (is_null($this->exists)) :
48
+ $ex = $this->search();
49
+ endif;
50
+
51
+ FeedWordPress::diagnostic(
52
+ 'syndicated_posts:categories',
53
+ 'Assigned category '.json_encode($this->term)
54
+ .' by feed; checking '.json_encode($this->tax)
55
+ . ' with result: '.json_encode($ex)
56
+ );
57
+ return (!is_wp_error($ex) and !!$ex);
58
+ } /* SyndicatedPostTerm::familiar () */
59
+
60
+ protected function search () {
61
+
62
+ // Either this is a numbered term code, which supplies the ID
63
+ // and the taxonomy explicitly (e.g.: {category#2}; in which
64
+ // case we have set $this->tax to a unit array containing only
65
+ // the correct taxonomy, or else we have a term name and an
66
+ // ordered array of taxonomies to search for that term name. In
67
+ // either case, loop through and check each pair of term
68
+
69
+ foreach ($this->tax as $tax) :
70
+
71
+ if (!$this->is_forbidden_in($tax)) :
72
+
73
+ $found = $this->fetch_record_in($tax);
74
+ if ($found) :
75
+ // When TRUE, the term has been found
76
+ // and is now stored in $this->exists
77
+
78
+ // Save the taxonomy we found this in.
79
+ $this->exists_in = $tax;
80
+
81
+ break;
82
+ endif;
83
+
84
+ endif;
85
+
86
+ endforeach;
87
+
88
+ FeedWordPress::diagnostic(
89
+ 'syndicated_posts:categories:test',
90
+ 'CHECKED familiarity of term '
91
+ .json_encode($this->term)
92
+ .' across '.json_encode($this->tax)
93
+ . ' with result: '.json_encode($record)
94
+ );
95
+
96
+ return $this->exists;
97
+
98
+ } /* SyndicatedPostTerm::search () */
99
+
100
+ protected function fetch_record_in ($tax) {
101
+ $record = term_exists($this->term, $tax);
102
+
103
+ FeedWordPress::diagnostic(
104
+ 'syndicated_posts:categories:test',
105
+ 'CHECK existence of '.$tax.': '
106
+ .json_encode($this->term)
107
+ .' with result: '.json_encode($record)
108
+ );
109
+
110
+ $found = (!is_wp_error($record) and !!$record);
111
+
112
+ if ($found) :
113
+ $this->exists = $record;
114
+ endif;
115
+
116
+ return $found;
117
+ } /* SyndicatedPostTerm::fetch_record_in() */
118
+
119
+ public function is_forbidden_in ($tax = NULL) {
120
+ $forbid = false; // Innocent until proven guilty.
121
+
122
+ $term = $this->term;
123
+ if (is_null($tax) and (count($this->tax) > 0)) :
124
+ $tax = $this->tax[0];
125
+ endif;
126
+
127
+ if ($tax=='category' and strtolower($term)=='uncategorized') :
128
+ $forbid = true;
129
+ endif;
130
+
131
+ // Run it through a filter.
132
+ return apply_filters('syndicated_post_forbidden_term', $forbid, $term, $tax, $this->post);
133
+ } /* SyndicatedPostTerm::is_forbidden_in () */
134
+
135
+ public function taxonomy () {
136
+ if (is_null($this->exists_in)) :
137
+ $this->search();
138
+ endif;
139
+
140
+ return $this->exists_in;
141
+ } /* SyndicatedPostTerm::taxonomy () */
142
+
143
+ public function id () {
144
+ $term_id = NULL;
145
+
146
+ if (is_null($this->exists)) :
147
+ $this->search();
148
+ endif;
149
+
150
+ $term = $this->exists;
151
+ if (is_array($term) or is_object($term)) :
152
+
153
+ // For hash tables of any sort, use the term_id member
154
+ $term = (array) $term;
155
+ $term_id = intval($term['term_id']);
156
+
157
+ elseif (is_numeric($term)) :
158
+
159
+ // For a straight numeric response, just return number
160
+ $term_id = intval($term);
161
+
162
+ endif;
163
+
164
+ return $term_id;
165
+ } /* SyndicatedPostTerm::id () */
166
+
167
+ public function insert ($tax = NULL) {
168
+ $ret = NULL;
169
+
170
+ if (is_null($tax)) :
171
+ if (count($this->tax) > 0) :
172
+ $tax = $this->tax[0];
173
+ endif;
174
+ endif;
175
+
176
+ if (!$this->is_forbidden_in($tax)) :
177
+ $aTerm = wp_insert_term($this->term, $tax);
178
+ if (is_wp_error($aTerm)) :
179
+
180
+ // If debug mode is ON, this will halt us here.
181
+ FeedWordPress::noncritical_bug(
182
+ 'term insertion problem', array(
183
+ 'term' => $this->term,
184
+ 'result' => $aTerm,
185
+ 'post' => $post,
186
+ 'this' => $this
187
+ ), __LINE__, __FILE__
188
+ );
189
+
190
+ // Otherwise, we'll continue & return NULL...
191
+
192
+ else :
193
+ $this->exists = $aTerm;
194
+ $this->exists_in = $tax;
195
+
196
+ $ret = $this->id();
197
+ endif;
198
+
199
+ FeedWordPress::diagnostic(
200
+ 'syndicated_posts:categories',
201
+ 'CREATED unfamiliar '.$tax.': '.json_encode($this->term).' with result: '.json_encode($aTerm)
202
+ );
203
+ else :
204
+ FeedWordPress::diagnostic(
205
+ 'syndicated_posts:categories',
206
+ 'Category: DID NOT CREATE unfamiliar '.$tax.': '.json_encode($this->term).':'
207
+ .' that '.$tax.' name is filtered out.'
208
+ );
209
+ endif;
210
+
211
+ return $ret;
212
+ } /* SyndicatedPostTerm::insert () */
213
+
214
+ } /* class SyndicatedPostTerm */
215
+
syndicationdataqueries.class.php CHANGED
@@ -1,10 +1,8 @@
1
  <?php
2
- define('FEEDWORDPRESS_OPTIMIZE_IN_CLAUSES', get_option('feedwordpress_optimize_in_clauses', false));
3
 
4
  class SyndicationDataQueries {
5
  function SyndicationDataQueries () {
6
  add_action('init', array($this, 'init'));
7
- add_filter('query', array($this, 'optimize_in_clauses'));
8
  add_action('parse_query', array($this, 'parse_query'), 10, 1);
9
  add_filter('posts_search', array($this, 'posts_search'), 10, 2);
10
  add_filter('posts_where', array($this, 'posts_where'), 10, 2);
@@ -17,44 +15,22 @@ class SyndicationDataQueries {
17
  $wp->add_query_var('guid');
18
  }
19
 
20
- function optimize_in_clauses ($q) {
21
- // This is kind of a dicey, low-level thing to do, and Christ,
22
- // this is something WordPress should be doing on its own,
23
- // so it's disabled by default. But you can enable it in
24
- // Performance --> Optimize IN clauses
25
- if (FEEDWORDPRESS_OPTIMIZE_IN_CLAUSES) :
26
- if (preg_match_all('/ \s+ IN \s* \((\s*([0-9]+)\s*)\)/x', $q, $r, PREG_OFFSET_CAPTURE)) :
27
- $from = 0; $nq = '';
28
- foreach ($r[0] as $idx => $ref) :
29
- $len = $ref[1] - $from;
30
- $nq .= substr($q, $from, $len);
31
- $nq .= ' = ' . $r[1][$idx][0];
32
- $from = $ref[1] + strlen($ref[0]);
33
- endforeach;
34
-
35
- $q = $nq;
36
- endif;
37
- endif;
38
-
39
- return $q;
40
- }
41
-
42
  function parse_query (&$q) {
43
  if ($q->get('guid')) :
44
  $q->is_single = false; // Causes nasty side-effects.
45
  $q->is_singular = true; // Doesn't?
46
  endif;
47
-
48
  $ff = $q->get('fields');
49
  if ($ff == '_synfresh' or $ff == '_synfrom') :
50
  $q->query_vars['cache_results'] = false; // Not suitable.
51
  endif;
52
  } /* SyndicationDataQueries::parse_query () */
53
-
54
  function pre_get_posts (&$q) {
55
- //
56
  }
57
-
58
  function posts_request ($sql, &$query) {
59
  if ($query->get('fields') == '_synfresh') :
60
  FeedWordPress::diagnostic('feed_items:freshness:sql', "SQL: ".$sql);
@@ -67,7 +43,7 @@ class SyndicationDataQueries {
67
  if ($guid = $query->get('guid')) :
68
  if (strlen(trim($guid)) > 0) :
69
  $seek = array($guid);
70
-
71
  // MD5 hashes
72
  if (preg_match('/^[0-9a-f]{32}$/i', $guid)) :
73
  $seek[] = SyndicatedPost::normalize_guid_prefix().$guid;
@@ -79,43 +55,43 @@ class SyndicationDataQueries {
79
  if ($guid != $nGuid) :
80
  $seek[] = $nGuid;
81
  endif;
82
-
83
  // Escape to prevent frak-ups, injections, etc.
84
  $seek = array_map('esc_sql', $seek);
85
-
86
  // Assemble
87
  $guidMatch = "(guid = '".implode("') OR (guid = '", $seek)."')";
88
  $search .= " AND ($guidMatch)";
89
  endif;
90
  endif;
91
-
92
  if ($query->get('fields')=='_synfresh') :
93
  // Ugly hack to ensure we ONLY check by guid in syndicated freshness
94
  // checks -- for reasons of both performance and correctness. Pitch:
95
  $search .= " -- '";
96
  elseif ($query->get('fields')=='_synfrom') :
97
- $search .= " AND ({$wpdb->postmeta}.meta_key = '".$query->get('meta_key')."' AND {$wpdb->postmeta}.meta_value = '".$query->get('meta_value')."') -- '";
98
  endif;
99
  return $search;
100
  } /* SyndicationDataQueries::posts_search () */
101
-
102
  function posts_where ($where, &$q) {
103
  global $wpdb;
104
-
105
  // Ugly hack to ensure we ONLY check by guid in syndicated freshness
106
  // checks -- for reasons of both performance and correctness. Catch:
107
  if (strpos($where, " -- '") !== false) :
108
  $bits = explode(" -- '", $where, 2);
109
  $where = $bits[0];
110
  endif;
111
-
112
  if ($psn = $q->get('post_status__not')) :
113
- $where .= " AND ({$wpdb->posts}.post_status <> '".$wpdb->escape($psn)."')";
114
  endif;
115
-
116
  return $where;
117
  } /* SyndicationDataQueries::post_where () */
118
-
119
  function posts_fields ($fields, &$query) {
120
  global $wpdb;
121
  if ($f = $query->get('fields')) :
1
  <?php
 
2
 
3
  class SyndicationDataQueries {
4
  function SyndicationDataQueries () {
5
  add_action('init', array($this, 'init'));
 
6
  add_action('parse_query', array($this, 'parse_query'), 10, 1);
7
  add_filter('posts_search', array($this, 'posts_search'), 10, 2);
8
  add_filter('posts_where', array($this, 'posts_where'), 10, 2);
15
  $wp->add_query_var('guid');
16
  }
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  function parse_query (&$q) {
19
  if ($q->get('guid')) :
20
  $q->is_single = false; // Causes nasty side-effects.
21
  $q->is_singular = true; // Doesn't?
22
  endif;
23
+
24
  $ff = $q->get('fields');
25
  if ($ff == '_synfresh' or $ff == '_synfrom') :
26
  $q->query_vars['cache_results'] = false; // Not suitable.
27
  endif;
28
  } /* SyndicationDataQueries::parse_query () */
29
+
30
  function pre_get_posts (&$q) {
31
+ //
32
  }
33
+
34
  function posts_request ($sql, &$query) {
35
  if ($query->get('fields') == '_synfresh') :
36
  FeedWordPress::diagnostic('feed_items:freshness:sql', "SQL: ".$sql);
43
  if ($guid = $query->get('guid')) :
44
  if (strlen(trim($guid)) > 0) :
45
  $seek = array($guid);
46
+
47
  // MD5 hashes
48
  if (preg_match('/^[0-9a-f]{32}$/i', $guid)) :
49
  $seek[] = SyndicatedPost::normalize_guid_prefix().$guid;
55
  if ($guid != $nGuid) :
56
  $seek[] = $nGuid;
57
  endif;
58
+
59
  // Escape to prevent frak-ups, injections, etc.
60
  $seek = array_map('esc_sql', $seek);
61
+
62
  // Assemble
63
  $guidMatch = "(guid = '".implode("') OR (guid = '", $seek)."')";
64
  $search .= " AND ($guidMatch)";
65
  endif;
66
  endif;
67
+
68
  if ($query->get('fields')=='_synfresh') :
69
  // Ugly hack to ensure we ONLY check by guid in syndicated freshness
70
  // checks -- for reasons of both performance and correctness. Pitch:
71
  $search .= " -- '";
72
  elseif ($query->get('fields')=='_synfrom') :
73
+ $search .= " AND ({$wpdb->postmeta}.meta_key = '".$query->get('meta_key')."' AND {$wpdb->postmeta}.meta_value = '".$query->get('meta_value')."') -- '";
74
  endif;
75
  return $search;
76
  } /* SyndicationDataQueries::posts_search () */
77
+
78
  function posts_where ($where, &$q) {
79
  global $wpdb;
80
+
81
  // Ugly hack to ensure we ONLY check by guid in syndicated freshness
82
  // checks -- for reasons of both performance and correctness. Catch:
83
  if (strpos($where, " -- '") !== false) :
84
  $bits = explode(" -- '", $where, 2);
85
  $where = $bits[0];
86
  endif;
87
+
88
  if ($psn = $q->get('post_status__not')) :
89
+ $where .= " AND ({$wpdb->posts}.post_status <> '".esc_sql($psn)."')";
90
  endif;
91
+
92
  return $where;
93
  } /* SyndicationDataQueries::post_where () */
94
+
95
  function posts_fields ($fields, &$query) {
96
  global $wpdb;
97
  if ($f = $query->get('fields')) :