PluginProbe
FeedWordPress / 2017.0913
FeedWordPress v2017.0913
trunk 0.8 0.9 0.91 0.95 0.96 0.97 0.98 0.981 0.99 0.991 0.992 0.993 2008.1030 2008.1101 2008.1105 2008.1214 2009.0612 2009.0613 2009.0618 2009.0707 2009.1111 2009.1112 2010.0127 2010.0528 All 65 releases
← All changes | feeds-page.php +870 -388 2009.11112017.0913 View file →
@@ -1,8 +1,9 @@
1 1 <?php
2 2 require_once(dirname(__FILE__) . '/admin-ui.php');
3 3 require_once(dirname(__FILE__) . '/magpiemocklink.class.php');
4 4 require_once(dirname(__FILE__) . '/feedfinder.class.php');
5 +require_once(dirname(__FILE__) . '/updatedpostscontrol.class.php');
5 6
6 7 class FeedWordPressFeedsPage extends FeedWordPressAdminPage {
7 8 var $HTTPStatusMessages = array (
8 9 200 => 'OK. FeedWordPress had no problems retrieving the content at this URL but the content does not seem to be a feed, and does not seem to include links to any feeds.',
@@ -43,166 +44,148 @@
43 44 503 => 'Service Unavailable. The server is currently unable to handle the request due to a temporary overloading or maintenance of the server that hosts this URL. This is probably a temporary condition and you should try again later to see if the issue has been resolved.',
44 45 504 => 'Gateway Timeout',
45 46 505 => 'HTTP Version Not Supported',
46 47 );
48 + var $updatedPosts = NULL;
47 49
48 - /**
49 - * Constructs the Feeds page object
50 - *
51 - * @param mixed $link An object of class {@link SyndicatedLink} if created for one feed's settings, NULL if created for global default settings
52 - */
53 - function FeedWordPressFeedsPage ($link = -1) {
54 - if (is_numeric($link) and -1 == $link) :
55 - $link = FeedWordPressAdminPage::submitted_link();
56 - endif;
57 -
58 - FeedWordPressAdminPage::FeedWordPressAdminPage('feedwordpressfeeds', $link);
59 -
60 - $this->dispatch = get_class($this);
61 - $this->filename = __FILE__;
62 - } /* FeedWordPressFeedsPage constructor */
63 -
64 50 var $special_settings = array ( /* Regular expression syntax is OK here */
65 51 'cats',
66 52 'cat_split',
53 + 'fetch timeout',
54 + 'freeze updates',
67 55 'hardcode name',
68 56 'hardcode url',
69 57 'hardcode description',
70 58 'hardcode categories', /* Deprecated */
71 - 'post status',
72 59 'comment status',
60 + 'terms',
61 + 'map authors',
62 + 'munge permalink',
73 63 'ping status',
64 + 'post status',
65 + 'postmeta',
66 + 'query parameters',
67 + 'resolve relative',
68 + 'syndicated post type',
69 + 'tags',
74 70 'unfamiliar author',
75 71 'unfamliar categories', /* Deprecated */
76 72 'unfamiliar category',
77 - 'map authors',
78 - 'tags',
79 - 'postmeta',
73 + 'unfamiliar post_tag',
74 + 'add/.*',
80 75 'update/.*',
81 76 'feed/.*',
82 77 'link/.*',
78 + 'match/.*',
83 79 );
84 80
81 + /**
82 + * Constructs the Feeds page object
83 + *
84 + * @param mixed $link An object of class {@link SyndicatedLink} if created for one feed's settings, NULL if created for global default settings
85 + */
86 + public function __construct( $link = -1 ) {
87 + if (is_numeric($link) and -1 == $link) :
88 + $link = $this->submitted_link();
89 + endif;
90 +
91 + parent::__construct('feedwordpressfeeds', $link);
92 +
93 + $this->dispatch = 'feedwordpress_admin_page_feeds';
94 + $this->pagenames = array(
95 + 'default' => 'Feeds',
96 + 'settings-update' => 'Syndicated feed',
97 + 'open-sheet' => 'Feed and Update',
98 + );
99 + $this->filename = __FILE__;
100 + $this->updatedPosts = new UpdatedPostsControl($this);
101 +
102 + $this->special_settings = apply_filters('syndicated_feed_special_settings', $this->special_settings, $this);
103 + } /* FeedWordPressFeedsPage constructor */
104 +
85 105 function display () {
86 - global $wpdb;
87 106 global $fwp_post;
88 107 global $post_source;
89 -
90 - if (FeedWordPress::needs_upgrade()) :
91 - fwp_upgrade_page();
92 - return;
93 - endif;
94 108
109 + $this->boxes_by_methods = array(
110 + 'feed_information_box' => __('Feed Information'),
111 + 'global_feeds_box' => __('Update Scheduling'),
112 + 'updated_posts_box' => __('Updated Posts'),
113 + 'custom_settings_box' => __('Custom Feed Settings (for use in templates)'),
114 + 'advanced_settings_box' => __('Advanced Settings'),
115 + );
116 + if ($this->for_default_settings()) :
117 + unset($this->boxes_by_methods['custom_settings_box']);
118 + endif;
119 +
95 120 // Allow overriding of normal source for FeedFinder, which may
96 121 // be called from multiple points.
97 122 if (isset($post_source) and !is_null($post_source)) :
98 123 $source = $post_source;
99 124 else :
100 - $source = get_class($this);
125 + $source = $this->dispatch;
101 126 endif;
102 127
103 - // If this is a POST, validate source and user credentials
104 - FeedWordPressCompatibility::validate_http_request(/*action=*/ $source, /*capability=*/ 'manage_links');
105 -
106 128 if (isset($_REQUEST['feedfinder'])
107 129 or (isset($_REQUEST['action']) and $_REQUEST['action']=='feedfinder')
108 130 or (isset($_REQUEST['action']) and $_REQUEST['action']==FWP_SYNDICATE_NEW)) :
131 + // If this is a POST, validate source and user credentials
132 + FeedWordPressCompatibility::validate_http_request(/*action=*/ $source, /*capability=*/ 'manage_links');
133 +
109 134 return $this->display_feedfinder(); // re-route to Feed Finder page
110 - else :
111 - if (strtoupper($_SERVER['REQUEST_METHOD'])=='POST') :
112 - $this->accept_POST($fwp_post);
113 - do_action('feedwordpress_admin_page_feeds_save', $GLOBALS['fwp_post'], $this);
114 - endif;
115 -
116 - ////////////////////////////////////////////////
117 - // Prepare settings page ///////////////////////
118 - ////////////////////////////////////////////////
119 -
120 - $this->ajax_interface_js();
121 - $this->display_update_notice_if_updated('Syndicated feed');
122 - $this->open_sheet('Feed and Update');
123 - ?>
124 - <div id="post-body">
125 - <?php
126 - ////////////////////////////////////////////////
127 - // Display settings boxes //////////////////////
128 - ////////////////////////////////////////////////
129 -
130 - $boxes_by_methods = array(
131 - 'feed_information_box' => __('Feed Information'),
132 - 'global_feeds_box' => __('Update Scheduling'),
133 - 'posts_box' => __('Syndicated Posts, Links, Comments & Pings'),
134 - 'authors_box' => __('Syndicated Authors'),
135 - 'categories_box' => __('Categories'.FEEDWORDPRESS_AND_TAGS),
136 - 'custom_settings_box' => __('Custom Feed Settings (for use in templates)'),
137 - );
138 - if ($this->for_default_settings()) :
139 - unset($boxes_by_methods['custom_settings_box']);
140 - endif;
141 -
142 - foreach ($boxes_by_methods as $method => $row) :
143 - if (is_array($row)) :
144 - $id = $row['id'];
145 - $title = $row['title'];
146 - else :
147 - $id = 'feedwordpress_'.$method;
148 - $title = $row;
149 - endif;
150 -
151 - fwp_add_meta_box(
152 - /*id=*/ $id,
153 - /*title=*/ $title,
154 - /*callback=*/ array(get_class($this), $method),
155 - /*page=*/ $this->meta_box_context(),
156 - /*context=*/ $this->meta_box_context()
157 - );
158 - endforeach;
159 - do_action('feedwordpress_admin_page_feeds_meta_boxes', $this);
160 - ?>
161 - <div class="metabox-holder">
162 - <?php
163 - fwp_do_meta_boxes($this->meta_box_context(), $this->meta_box_context(), $this);
164 - ?>
165 - </div> <!-- class="metabox-holder" -->
166 - </div> <!-- id="post-body" -->
167 - <?php $this->close_sheet(); ?>
135 + endif;
168 136
169 - <script type="text/javascript">
170 - var els = ['name', 'description', 'url'];
171 - for (var i = 0; i < els.length; i++) {
172 - contextual_appearance(
173 - /*item=*/ 'basics-hardcode-'+els[i],
174 - /*appear=*/ 'basics-'+els[i]+'-view',
175 - /*disappear=*/ 'basics-'+els[i]+'-edit',
176 - /*value=*/ 'no',
177 - /*visibleStyle=*/ 'block',
178 - /*checkbox=*/ true
179 - );
180 - } /* for */
181 - </script>
182 - <?php
183 - endif;
137 + parent::display();
184 138 return false; // Don't continue
185 139 } /* FeedWordPressFeedsPage::display() */
186 140
187 - /*static*/ function global_feeds_box ($page, $box = NULL) {
188 - global $wpdb;
141 + function ajax_interface_js () {
142 + parent::ajax_interface_js();
143 + ?>
189 144
190 - $defaultUpdateWindow = get_option('feedwordpress_update_window');
191 - if (!is_numeric($defaultUpdateWindow)) :
192 - $defaultUpdateWindow = DEFAULT_UPDATE_PERIOD;
193 - else :
194 - $defaultUpdateWindow = (int) $defaultUpdateWindow;
195 - endif;
145 + jQuery(document).ready( function () {
146 + contextual_appearance('automatic-updates-selector', 'cron-job-explanation', null, 'no');
147 + contextual_appearance('time-limit', 'time-limit-box', null, 'yes');
148 + contextual_appearance('use-default-update-window-no', 'update-scheduling-note', null, null, 'block', true);
149 + jQuery('#use-default-update-window-yes, #use-default-update-window-no').click( function () {
150 + contextual_appearance('use-default-update-window-no', 'update-scheduling-note', null, null, 'block', true);
151 + } );
152 +
153 + var els = ['name', 'description', 'url'];
154 + for (var i = 0; i < els.length; i++) {
155 + contextual_appearance(
156 + /*item=*/ 'basics-hardcode-'+els[i],
157 + /*appear=*/ 'basics-'+els[i]+'-view',
158 + /*disappear=*/ 'basics-'+els[i]+'-edit',
159 + /*value=*/ 'no',
160 + /*visibleStyle=*/ 'block',
161 + /*checkbox=*/ true
162 + );
163 + } /* for */
164 + } );
165 +
166 + <?php
167 + }
168 +
169 + /*static*/ function updated_posts_box ($page, $box = NULL) {
196 170 ?>
197 -
198 171 <table class="edit-form">
172 + <?php $page->updatedPosts->display(); ?>
173 + </table>
199 174 <?php
200 - if ($page->for_default_settings()) :
201 - $automatic_updates = get_option('feedwordpress_automatic_updates');
202 - $update_time_limit = (int) get_option('feedwordpress_update_time_limit');
175 + } /* FeedWordPressFeedsPage::updated_posts_box() */
176 +
177 + /*static*/ function global_feeds_box ($page, $box = NULL) {
178 + global $feedwordpress;
179 + $automatic_updates = $feedwordpress->automatic_update_hook(array('setting only' => true));
180 + $update_time_limit = (int) get_option('feedwordpress_update_time_limit');
181 +
182 + // Hey, ho, let's go...
203 183 ?>
204 184
185 + <table class="edit-form">
186 + <?php if ($page->for_default_settings()) : ?>
187 +
205 188 <tr>
206 189 <th scope="row">Updates:</th>
207 190 <td><select id="automatic-updates-selector" name="automatic_updates" size="1" onchange="contextual_appearance('automatic-updates-selector', 'cron-job-explanation', null, 'no');">
208 191 <option value="shutdown"<?php echo ($automatic_updates=='shutdown')?' selected="selected"':''; ?>>automatically check for updates after pages load</option>
@@ -209,13 +192,36 @@
209 192 <option value="init"<?php echo ($automatic_updates=='init')?' selected="selected"':''; ?>>automatically check for updates before pages load</option>
210 193 <option value="no"<?php echo (!$automatic_updates)?' selected="selected"':''; ?>>cron job or manual updates</option>
211 194 </select>
212 195 <div id="cron-job-explanation" class="setting-description">
213 - <p>If you want to use a cron job,
196 + <p><?php
197 + // Do we have shell_exec() available from here, or is it disabled for security reasons?
198 + // If it's available, use it to execute `which` to try to get a realistic path to curl,
199 + // or to wget. If everything fails or shell_exec() isn't available, then just make
200 + // up something for the sake of example.
201 + $shellExecAvailable = (is_callable('shell_exec') && false === stripos(ini_get('disable_functions'), 'shell_exec'));
202 +
203 + if ($shellExecAvailable) :
204 + $path = `which curl`; $opts = '--silent %s';
205 + endif;
206 +
207 + if ($shellExecAvailable and (is_null($path) or strlen(trim($path))==0)) :
208 + $path = `which wget`; $opts = '-q -O - %s';
209 + endif;
210 +
211 + if (is_null($path) or strlen(trim($path))==0) :
212 + $path = '/usr/bin/curl'; $opts = '--silent %s';
213 + endif;
214 +
215 + $path = preg_replace('/\n+$/', '', $path);
216 +
217 + $cmdline = $path . ' ' . sprintf($opts, get_bloginfo('url').'?update_feedwordpress=1');
218 +
219 + ?>If you want to use a cron job,
214 220 you can perform scheduled updates by sending regularly-scheduled
215 - requests to <a href="<?php bloginfo('home'); ?>?update_feedwordpress=1"><code><?php bloginfo('home') ?>?update_feedwordpress=1</code></a>
221 + requests to <a href="<?php bloginfo('url'); ?>?update_feedwordpress=1"><code><?php bloginfo('url') ?>?update_feedwordpress=1</code></a>
216 222 For example, inserting the following line in your crontab:</p>
217 - <pre style="font-size: 0.80em"><code>*/10 * * * * /usr/bin/curl --silent <?php bloginfo('home'); ?>?update_feedwordpress=1</code></pre>
223 + <pre style="font-size: 0.80em"><code>*/10 * * * * <?php print esc_html($cmdline); ?></code></pre>
218 224 <p class="setting-description">will check in every 10 minutes
219 225 and check for updates on any feeds that are ready to be polled for updates.</p>
220 226 </div>
221 227 </td>
@@ -220,39 +226,10 @@
220 226 </div>
221 227 </td>
222 228 </tr>
223 229
224 - <tr>
225 - <th scope="row"><?php print __('Update scheduling:') ?></th>
226 - <td><p style="margin-top:0px">How long should FeedWordPress wait between updates before it considers a feed ready to be polled for updates again?</p>
227 - <p style="font-style: italic; margin-left: 2.0em"><label>Wait <input type="text" name="update_window" value="<?php print $defaultUpdateWindow; ?>" size="4" /> minutes between polling.</label></p>
228 - <div class="setting-description">
229 - <p<?php if ($defaultUpdateWindow<50) : ?> style="color: white; background-color: #703030; padding: 1.0em;"<?php endif; ?>><strong>Recommendation.</strong> Unless you are positive that you have the webmaster's permission, you generally should not set FeedWordPress to poll feeds more frequently than once every 60 minutes. Many webmasters consider more frequent automated polling to be abusive, and may complain to your web host, or ban your IP address, as retaliation for hammering their servers too hard.</p>
230 - <p><strong>Note.</strong> This is a default setting that FeedWordPress uses to schedule updates when the feed does not provide any scheduling requests. If a feed does provide update scheduling information (through elements such as <code>&lt;rss:ttl&gt;</code> or <code>&lt;sy:updateFrequency&gt;</code>), FeedWordPress will respect the feed's request.</p>
231 - </div></td>
232 - </tr>
233 -
234 - <tr>
235 - <th scope="row"><?php print __('Time limit on updates'); ?>:</th>
236 - <td><select id="time-limit" name="update_time_limit" size="1" onchange="contextual_appearance('time-limit', 'time-limit-box', null, 'yes');">
237 - <option value="no"<?php echo ($update_time_limit>0)?'':' selected="selected"'; ?>>no time limit on updates</option>
238 - <option value="yes"<?php echo ($update_time_limit>0)?' selected="selected"':''; ?>>limit updates to no more than...</option>
239 - </select>
240 - <span id="time-limit-box"><label><input type="text" name="time_limit_seconds" value="<?php print $update_time_limit; ?>" size="5" /> seconds</label></span>
241 - </tr>
230 + <?php else : /* Feed-specific settings */ ?>
242 231
243 - <?php else :
244 - $useDefaultUpdateWindow = !(isset($page->link->settings['update/window']));
245 -
246 - $updateWindow = (isset($page->link->settings['update/window']) ? $page->link->settings['update/window'] : null);
247 - if (!is_numeric($updateWindow)) :
248 - $updateWindow = 60;
249 - else :
250 - $updateWindow = (int) $updateWindow;
251 - endif;
252 -
253 - ?>
254 -
255 232 <tr>
256 233 <th scope="row"><?php _e('Last update') ?>:</th>
257 234 <td><?php
258 235 if (isset($page->link->settings['update/last'])) :
@@ -287,39 +264,240 @@
287 264 ?></option>
288 265 <option value="next"<?php echo ($holdem=='next')?' selected="selected"':''; ?>>update ASAP</option>
289 266 <option value="ping"<?php echo ($holdem=='ping')?' selected="selected"':''; ?>>update only when pinged</option>
290 267 </select></td></tr>
291 -
268 +
269 + <?php endif; ?>
270 +
292 271 <tr>
293 272 <th scope="row"><?php print __('Update scheduling:') ?></th>
294 273 <td><p style="margin-top:0px">How long should FeedWordPress wait between updates before it considers this feed ready to be polled for updates again?</p>
295 - <ul>
296 - <li><label><input type="radio" name="use_default_update_window" value="Yes" <?php if ($useDefaultUpdateWindow) : ?>checked="checked"<?php endif; ?> /> Use site-wide setting (currently <?php print $defaultUpdateWindow; ?> minutes)</li>
297 - <li><label><input type="radio" name="use_default_update_window" value="No" <?php if (!$useDefaultUpdateWindow) : ?>checked="checked"<?php endif; ?> /> Wait <input type="text" name="update_window" value="<?php print $updateWindow; ?>" size="4" /> minutes between polling.</label></li>
298 - </ul>
274 + <?php
275 +
276 + $this->setting_radio_control(
277 + 'update/window', 'update_window',
278 + array($this, 'update_window_edit_box'),
279 + array(
280 + 'global-setting-default' => DEFAULT_UPDATE_PERIOD,
281 + 'default-input-name' => 'use_default_update_window',
282 + 'default-input-id' => 'use-default-update-window-yes',
283 + 'default-input-id-no' => 'use-default-update-window-no',
284 + 'labels' => array($this, 'update_window_currently'),
285 + )
286 + );
287 + ?></td>
288 + </tr>
289 +
290 + <tr>
291 + <th scope="row"><?php print __('Minimum Interval:'); ?></th>
292 + <td><p style="margin-top:0px">Some feeds include standard elements that
293 + request a specific update schedule. If the interval requested by the
294 + feed provider is <em>longer</em> than FeedWordPress's normal scheduling,
295 + FeedWordPress will always respect their request to slow down. But what
296 + should it do if the update interval is <em>shorter</em> than the schedule set above?</p>
297 + <?php
298 + $this->setting_radio_control(
299 + 'update/minimum', 'update_minimum',
300 + /*options=*/ array(
301 + 'no' => 'Speed up and accept the interval from the feed provider',
302 + 'yes' => 'Keep pace and use the longer scheduling from FeedWordPress',
303 + ),
304 + /*params=*/ array(
305 + 'setting-default' => NULL,
306 + 'global-setting-default' => 'no',
307 + 'default-input-value' => 'default',
308 + )
309 + );
310 + ?>
311 + </td>
312 + </tr>
299 313
300 - <div class="setting-description">
314 + <?php if ($this->for_default_settings()) : ?>
315 +
316 + <tr>
317 + <th scope="row"><?php print __('Time limit on updates'); ?>:</th>
318 + <td><select id="time-limit" name="update_time_limit" size="1" onchange="contextual_appearance('time-limit', 'time-limit-box', null, 'yes');">
319 + <option value="no"<?php echo ($update_time_limit>0)?'':' selected="selected"'; ?>>no time limit on updates</option>
320 + <option value="yes"<?php echo ($update_time_limit>0)?' selected="selected"':''; ?>>limit updates to no more than...</option>
321 + </select>
322 + <span id="time-limit-box"><label><input type="text" name="time_limit_seconds" value="<?php print $update_time_limit; ?>" size="5" /> seconds</label></span>
323 + </tr>
324 +
325 + <?php endif; ?>
326 +
327 + </table>
328 +
329 + <?php
330 + } /* FeedWordPressFeedsPage::global_feeds_box() */
331 +
332 + function update_window_edit_box ($updateWindow, $defaulted, $params) {
333 + if (!is_numeric($updateWindow)) :
334 + $updateWindow = DEFAULT_UPDATE_PERIOD;
335 + endif;
336 + ?>
337 + <p>Wait <input type="text" name="update_window" value="<?php print $updateWindow; ?>" size="4" /> minutes between polling.</p>
338 + <div class="setting-description" id="update-scheduling-note">
301 339 <p<?php if ($updateWindow<50) : ?> style="color: white; background-color: #703030; padding: 1.0em;"<?php endif; ?>><strong>Recommendation.</strong> Unless you are positive that you have the webmaster's permission, you generally should not set FeedWordPress to poll feeds more frequently than once every 60 minutes. Many webmasters consider more frequent automated polling to be abusive, and may complain to your web host, or ban your IP address, as retaliation for hammering their servers too hard.</p>
302 340 <p><strong>Note.</strong> This is a default setting that FeedWordPress uses to schedule updates when the feed does not provide any scheduling requests. If this feed does provide update scheduling information (through elements such as <code>&lt;rss:ttl&gt;</code> or <code>&lt;sy:updateFrequency&gt;</code>), FeedWordPress will respect the feed's request.</p>
303 - </div></td>
341 + </div>
342 + <?php
343 + } /* FeedWordPressFeedsPage::update_window_edit_box () */
344 +
345 + function update_window_currently ($updateWindow, $defaulted, $params) {
346 + $updateWindow = (int) $updateWindow;
347 + if (1==$updateWindow) :
348 + $caption = 'wait %d minute between polling';
349 + else :
350 + $caption = 'wait %d minutes between polling';
351 + endif;
352 + return sprintf(__($caption), $updateWindow);
353 + } /* FeedWordPressFeedsPage::update_window_currently () */
354 +
355 + function fetch_timeout_setting ($setting, $defaulted, $params) {
356 + $timeout = intval($this->setting('fetch timeout', FEEDWORDPRESS_FETCH_TIMEOUT_DEFAULT));
357 +
358 + if ($this->for_feed_settings()) :
359 + $article = 'this';
360 + else :
361 + $article = 'a';
362 + endif;
363 + ?>
364 + <p>Wait no more than
365 + than <input name="fetch_timeout" type="number" min="0" size="3" value="<?php print $timeout; ?>" />
366 + second(s) when trying to fetch <?php print $article; ?> feed to check for updates.</p>
367 + <p>If <?php print $article; ?> source's web server does not respond before time runs
368 + out, FeedWordPress will skip over the source and try again during
369 + the next update cycle.</p>
370 + <?php
371 + }
372 + function fetch_timeout_setting_value ($setting, $defaulted, $params) {
373 + print number_format(intval($setting)) . " " . (($setting==1) ? "second" : "seconds");
374 + }
375 +
376 + function advanced_settings_box ($page, $box = NULL) {
377 + ?>
378 + <table class="edit-form">
379 + <tr>
380 + <th>Fetch Timeout:</th>
381 + <td>
382 + <?php
383 + $this->setting_radio_control(
384 + 'fetch timeout', 'fetch_timeout',
385 + array($this, 'fetch_timeout_setting'),
386 + array(
387 + 'global-setting-default' => FEEDWORDPRESS_FETCH_TIMEOUT_DEFAULT,
388 + 'input-name' => 'fetch_timeout',
389 + 'default-input-name' => 'fetch_timeout_default',
390 + 'labels' => array($this, 'fetch_timeout_setting_value'),
391 + )
392 + );
393 + ?>
394 + </td>
304 395 </tr>
305 - <?php endif; ?>
396 + <tr>
397 + <th>Feed Update Type:</th>
398 + <td><?php
399 + $this->setting_radio_control('update_incremental', 'update_incremental',
400 + /*options=*/ array(
401 + 'incremental' => '<strong>Incremental.</strong> When items no longer appear on the feed, keep them in the WordPress posts table.',
402 + 'complete' => '<strong>Complete.</strong> When items no longer appear on the feed, they are obsolete; retire them from the WordPress posts table.',
403 + ),
404 + /*params=*/ array(
405 + 'setting-default' => NULL,
406 + 'global-setting-default' => 'incremental',
407 + 'default-input-value' => 'default',
408 + )
409 + ); ?></td>
410 + </tr>
411 + <tr>
412 + <th>Allow Feeds to Delete Posts:</th>
413 + <td><?php
414 + $this->setting_radio_control('tombstones', 'tombstones',
415 + /*options=*/ array(
416 + 'yes' => 'Yes. If a feed indicates that one of its posts has been deleted, delete the local copy syndicated to this website.',
417 + 'no' => 'No. Even if a feed indicates that one of its posts has been deleted, retain the local copy on this website.',
418 + ),
419 + /*params=*/ array(
420 + 'setting-default' => NULL,
421 + 'global-setting-default' => 'yes',
422 + 'default-input-value' => 'default',
423 + )
424 + ); ?></td>
425 + </tr>
426 + </table>
427 + <?php
428 + } /* FeedWordPressFeedsPage::advanced_settings_box () */
429 +
430 + function display_authentication_credentials_box ($params = array()) {
431 + static $count = 0;
306 432
433 + $params = wp_parse_args($params, array(
434 + 'username' => NULL,
435 + 'password' => NULL,
436 + 'method' => '-',
437 + ));
438 +
439 + // Equivalents
440 + if (is_null($params['method'])) : $params['method'] = '-'; endif;
441 +
442 + $count++;
443 + $slug = ($count > 1 ? '-'.$count : '');
444 +
445 + global $feedwordpress;
446 + $authMethods = apply_filters(
447 + 'feedwordpress_http_auth_methods',
448 + $feedwordpress->httpauth->methods_available()
449 + );
307 450
308 -</table>
309 -<script type="text/javascript">
310 -contextual_appearance('automatic-updates-selector', 'cron-job-explanation', null, 'no');
311 -contextual_appearance('time-limit', 'time-limit-box', null, 'yes');
312 -</script>
313 -<?php
314 - } /* FeedWordPressFeedsPage::global_feeds_box() */
315 -
451 + if (count($authMethods) > 1) : /* More than '-' */
452 + ?>
453 + <div class="link-rss-authentication" id="link-rss-authentication<?php print $slug; ?>">
454 + <table>
455 + <tbody>
456 + <tr class="link-rss-authentication-credentials" id="link-rss-authentication-credentials<?php print $slug; ?>">
457 + <td><label>user: <input type="text" name="link_rss_username"
458 + value="<?php print esc_attr($params['username']); ?>" size="16"
459 + placeholder="username to access this feed" /></label></td>
460 + <td><label>pass: <input type="text" name="link_rss_password"
461 + value="<?php print esc_attr($params['password']); ?>" size="16"
462 + placeholder="password to access this feed" /></label></td>
463 + <td class="link-rss-authentication-method" id="link-rss-authentication-method<?php print $slug; ?>"><label>method: <select class="link-rss-auth-method" id="link-rss-auth-method" name="link_rss_auth_method" size="1">
464 +<?php foreach ($authMethods as $value => $label) : ?>
465 + <option value="<?php print esc_attr($value); ?>"<?php
466 + if ($value == $params['method']) : ?> selected="selected"<?php
467 + endif; ?>><?php print esc_html($label); ?></option>
468 +<?php endforeach; ?>
469 + </select></label></td>
470 + </tr>
471 + </tbody>
472 + </table>
473 + </div>
474 +
475 + <script type="text/javascript">
476 + jQuery('<td><a class="add-remove remove-it" id="link-rss-userpass-remove<?php print $slug; ?>" href="#"><span class="x">(X)</span> Remove</a></td>')
477 + .appendTo('#link-rss-authentication-credentials<?php print $slug; ?>')
478 + .click( feedAuthenticationMethodUnPress );
479 + jQuery('#link-rss-auth-method<?php print $slug; ?>').change( feedAuthenticationMethod );
480 + feedAuthenticationMethod({
481 + init: true,
482 + node: jQuery('#link-rss-authentication<?php print $slug; ?>') });
483 + </script>
484 +
485 + <?php
486 + endif;
487 + }
488 +
316 489 function feed_information_box ($page, $box = NULL) {
317 490 global $wpdb;
491 + $link_rss_params = maybe_unserialize($page->setting('query parameters', ''));
492 + if (!is_array($link_rss_params)) :
493 + $link_rss_params = array();
494 + endif;
495 +
318 496 if ($page->for_feed_settings()) :
319 - $info['name'] = wp_specialchars($page->link->link->link_name, 1);
320 - $info['description'] = wp_specialchars($page->link->link->link_description, 'both');
321 - $info['url'] = wp_specialchars($page->link->link->link_url, 1);
497 + $info['name'] = esc_html($page->link->link->link_name);
498 + $info['description'] = esc_html($page->link->link->link_description);
499 + $info['url'] = esc_html($page->link->link->link_url);
322 500 $rss_url = $page->link->link->link_rss;
323 501
324 502 $hardcode['name'] = $page->link->hardcode('name');
325 503 $hardcode['description'] = $page->link->hardcode('description');
@@ -325,26 +503,29 @@
325 503 $hardcode['description'] = $page->link->hardcode('description');
326 504 $hardcode['url'] = $page->link->hardcode('url');
327 505 else :
328 506 $cat_id = FeedWordPress::link_category_id();
329 - if (FeedWordPressCompatibility::test_version(FWP_SCHEMA_21)) :
330 - $results = get_categories(array(
331 - "type" => 'link',
332 - "hide_empty" => false,
333 - ));
507 +
508 + $params = array();
509 + if (FeedWordPressCompatibility::test_version(FWP_SCHEMA_USES_ARGS_TAXONOMY)) :
510 + $params['taxonomy'] = 'link_category';
511 + else :
512 + $params['type'] = 'link';
513 + endif;
514 + $params['hide_empty'] = false;
515 + $results = get_categories($params);
334 516
335 - // Guarantee that the Contributors category will be in the drop-down chooser, even if it is empty.
336 - $found_link_category_id = false;
337 - foreach ($results as $row) :
338 - // Normalize case
339 - if (!isset($row->cat_id)) : $row->cat_id = $row->cat_ID; endif;
517 + // Guarantee that the Contributors category will be in the drop-down chooser, even if it is empty.
518 + $found_link_category_id = false;
519 + foreach ($results as $row) :
520 + // Normalize case
521 + if (!isset($row->cat_id)) : $row->cat_id = $row->cat_ID; endif;
340 522
341 - if ($row->cat_id == $cat_id) : $found_link_category_id = true; endif;
342 - endforeach;
343 -
344 - if (!$found_link_category_id) : $results[] = get_category($cat_id); endif;
345 - else :
346 - $results = $wpdb->get_results("SELECT cat_id, cat_name, auto_toggle FROM $wpdb->linkcategories ORDER BY cat_id");
523 + if ($row->cat_id == $cat_id) : $found_link_category_id = true; endif;
524 + endforeach;
525 +
526 + if (!$found_link_category_id) :
527 + $results[] = get_category($cat_id);
347 528 endif;
348 529
349 530 $info = array();
350 531 $rss_url = null;
@@ -353,17 +534,34 @@
353 534 $hardcode['description'] = get_option('feedwordpress_hardcode_description');
354 535 $hardcode['url'] = get_option('feedwordpress_hardcode_url');
355 536 endif;
356 537
538 + $hideAuth = false;
539 +
540 + $username = $this->setting('http username', NULL);
541 +
542 + if (is_null($username)) :
543 + $username = '';
544 + $hideAuth = true;
545 + endif;
546 +
547 + $password = $this->setting('http password', NULL);
548 + if (is_null($password)) :
549 + $password = '';
550 + endif;
551 +
552 + $auth = $this->setting('http auth method', NULL);
553 +
554 + global $feedwordpress;
555 +
556 + if (is_null($auth) or (strlen($auth)==0)) :
557 + $auth = '-';
558 + $hideAuth = true;
559 + endif;
560 +
357 561 // Hey ho, let's go
562 +
358 563 ?>
359 - <style type="text/css">
360 - table.edit-form { width: 100%; }
361 - table.edit-form th { width: 25%; vertical-align: top; text-align: right; padding: 0.5em; }
362 - table.edit-form td { width: 75%; vertical-align: top; padding: 0.5em; }
363 - table.edit-form td ul.options { margin: 0; padding: 0; list-style: none; }
364 - </style>
365 -
366 564 <table class="edit-form">
367 565
368 566 <?php if ($page->for_feed_settings()) : ?>
369 567
@@ -368,14 +566,82 @@
368 566 <?php if ($page->for_feed_settings()) : ?>
369 567
370 568 <tr>
371 569 <th scope="row"><?php _e('Feed URL:') ?></th>
372 - <td><a href="<?php echo wp_specialchars($rss_url, 'both'); ?>"><?php echo wp_specialchars($rss_url, 'both'); ?></a>
570 + <td><a href="<?php echo esc_html($rss_url); ?>"><?php echo esc_html($rss_url); ?></a>
373 571 (<a href="<?php echo FEEDVALIDATOR_URI; ?>?url=<?php echo urlencode($rss_url); ?>"
374 - title="Check feed &lt;<?php echo wp_specialchars($rss_url, 'both'); ?>&gt; for validity">validate</a>)
375 - <input type="submit" name="feedfinder" value="switch &rarr;" style="font-size:smaller" /></td>
572 + title="Check feed &lt;<?php echo esc_html($rss_url); ?>&gt; for validity">validate</a>)
573 + <input type="submit" name="feedfinder" value="switch &rarr;" style="font-size:smaller" />
574 +
575 + <?php $this->display_authentication_credentials_box(array(
576 + 'username' => $username,
577 + 'password' => $password,
578 + 'method' => $auth,
579 + )); ?>
580 +
581 + <table id="link-rss-params">
582 + <tbody>
583 + <?php
584 + $link_rss_params['new'] = array('', '');
585 + $i = 0;
586 + foreach ($link_rss_params as $index => $pair) :
587 + ?>
588 + <tr class="link-rss-params-row" id="link-rss-params-<?php print $index; ?>">
589 + <td><label>Parameter: <input type="text" class="link_params_key"
590 + name="link_rss_params_key[<?php print $index; ?>]" value="<?php print esc_html($pair[0]); ?>"
591 + size="5" style="width: 5em" placeholder="name" /></label></td>
592 + <td class="link-rss-params-value-cell"><label class="link_params_value_label">= <input type="text" class="link_params_value"
593 + name="link_rss_params_value[<?php print $index; ?>]" value="<?php print esc_html($pair[1]); ?>"
594 + size="8" placeholder="value" /></label></td>
376 595 </tr>
596 + <?php
597 + $i++;
598 + endforeach;
599 + ?>
600 + </tbody>
601 + </table>
602 +
603 + <div><input type="hidden" id="link-rss-params-num" name="link_rss_params_num" value="<?php print $i; ?>" /></div>
604 +
605 + <script type="text/javascript">
606 + function linkParamsRowRemove (element) {
607 + jQuery(element).closest('tr').fadeOut('slow', function () {
608 + jQuery(this).remove();
609 + } );
610 + }
377 611
612 + jQuery('<td><a href="#" class="add-remove link-rss-params-remove"><span class="x">(X)</span> Remove</a></td>').insertAfter('.link-rss-params-value-cell');
613 +
614 + jQuery('#link-rss-params-new').hide();
615 + jQuery('<a class="add-remove" id="link-rss-params-add" href="#">+ Add a query parameter</a>').insertAfter('#link-rss-params');
616 + jQuery('#link-rss-params-add').click( function () {
617 + var next = jQuery('#link-rss-params-num').val();
618 + var newRow = jQuery('#link-rss-params-new').clone().attr('id', 'link-rss-params-'+next);
619 + newRow.find('.link_params_key').attr('name', 'link_rss_params_key['+next+']');
620 + newRow.find('.link_params_value').attr('name', 'link_rss_params_value['+next+']');
621 +
622 + newRow.find('.link-rss-params-remove').click( function () {
623 + linkParamsRowRemove(this);
624 + return false;
625 + } );
626 +
627 + newRow.appendTo('#link-rss-params');
628 + newRow.show();
629 +
630 + // Update counter for next row.
631 + next++;
632 + jQuery('#link-rss-params-num').val(next);
633 +
634 + return false;
635 + } );
636 + jQuery('.link-rss-params-remove').click( function () {
637 + linkParamsRowRemove(this);
638 + return false;
639 + } );
640 + </script>
641 + </td>
642 + </tr>
643 +
378 644 <?php
379 645 $rows = array(
380 646 "name" => __('Link Name'),
381 647 "description" => __('Short Description'),
@@ -423,9 +689,9 @@
423 689 echo "\n\t<option value=\"$row->cat_id\"";
424 690 if ($row->cat_id == $cat_id) :
425 691 echo " selected='selected'";
426 692 endif;
427 - echo ">$row->cat_id: ".wp_specialchars($row->cat_name);
693 + echo ">$row->cat_id: ".esc_html($row->cat_name);
428 694 echo "</option>\n";
429 695 endforeach;
430 696 ?></select></p>
431 697 <p class="setting-description">FeedWordPress will syndicate the
@@ -453,26 +719,15 @@
453 719 </table>
454 720 <?php
455 721 } /* FeedWordPressFeedsPage::feed_information_box() */
456 722
457 - function posts_box ($page, $box = NULL) {
458 - FeedWordPressSettingsUI::instead_of_posts_box($page->link->id);
459 - } /* FeedWordPressFeedsPage::posts_box() */
460 -
461 - function authors_box ($page, $box = NULL) {
462 - FeedWordPressSettingsUI::instead_of_authors_box($page->link->id);
463 - } /* FeedWordPressFeedsPage::authors_box() */
464 -
465 - function categories_box ($page, $box = NULL) {
466 - FeedWordPressSettingsUI::instead_of_categories_box($page->link->id);
467 - } /* FeedWordPressFeedsPage::categories_box() */
468 -
469 723 function custom_settings_box ($page, $box = NULL) {
724 + $postsSettings = $this->admin_page_href('posts-page.php', array(), $page->link);
470 725 ?>
471 726 <p class="setting-description">These custom settings are special fields for the <strong>feed</strong> you are
472 727 syndicating, to be retrieved in templates using the <code>get_feed_meta()</code> function. They do not create
473 728 custom fields on syndicated <strong>posts</strong>. If you want to create custom fields that are applied to each
474 - individual post from this feed, set up the settings in <a href="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/posts-page.php&amp;link_id=<?php print $page->link->id; ?>">Syndicated Posts</a>.</p>
729 + individual post from this feed, set up the settings in <a href="<?php print $postsSettings; ?>">Syndicated Posts</a>.</p>
475 730
476 731 <div id="postcustomstuff">
477 732 <table id="meta-list" cellpadding="3">
478 733 <tr>
@@ -486,11 +741,11 @@
486 741 foreach ($page->link->settings as $key => $value) :
487 742 if (!preg_match("\007^((".implode(')|(', $page->special_settings)."))$\007i", $key)) :
488 743 ?>
489 744 <tr style="vertical-align:top">
490 - <th width="30%" scope="row"><input type="hidden" name="notes[<?php echo $i; ?>][key0]" value="<?php echo wp_specialchars($key, 'both'); ?>" />
491 - <input id="notes-<?php echo $i; ?>-key" name="notes[<?php echo $i; ?>][key1]" value="<?php echo wp_specialchars($key, 'both'); ?>" /></th>
492 - <td width="60%"><textarea rows="2" cols="40" id="notes-<?php echo $i; ?>-value" name="notes[<?php echo $i; ?>][value]"><?php echo wp_specialchars($value, 'both'); ?></textarea></td>
745 + <th width="30%" scope="row"><input type="hidden" name="notes[<?php echo $i; ?>][key0]" value="<?php echo esc_html($key); ?>" />
746 + <input id="notes-<?php echo $i; ?>-key" name="notes[<?php echo $i; ?>][key1]" value="<?php echo esc_html($key); ?>" /></th>
747 + <td width="60%"><textarea rows="2" cols="40" id="notes-<?php echo $i; ?>-value" name="notes[<?php echo $i; ?>][value]"><?php echo esc_html($value); ?></textarea></td>
493 748 <td width="10%"><select name="notes[<?php echo $i; ?>][action]">
494 749 <option value="update">save changes</option>
495 750 <option value="delete">delete this setting</option>
496 751 </select></td>
@@ -509,71 +764,171 @@
509 764 </div> <!-- id="postcustomstuff" -->
510 765 <?php
511 766 }
512 767
768 + function url_for_401 ($err) {
769 + $ret = NULL;
770 + if (is_wp_error($err)) :
771 + if ($err->get_error_code()=='http_request_failed') :
772 + $data = $err->get_error_data('http_request_failed');
773 +
774 + if (is_array($data) and isset($data['status'])) :
775 + if (401==$data['status']) :
776 + $ret = $data['uri'];
777 + endif;
778 + endif;
779 + endif;
780 + endif;
781 + return $ret;
782 + }
783 +
513 784 function display_feedfinder () {
514 785 global $wpdb;
515 786
516 787 $lookup = (isset($_REQUEST['lookup']) ? $_REQUEST['lookup'] : NULL);
788 +
789 + $auth = MyPHP::request('link_rss_auth_method');
790 + $username = MyPHP::request('link_rss_username');
791 + $password = MyPHP::request('link_rss_password');
792 + $credentials = array(
793 + "authentication" => $auth,
794 + "username" => $username,
795 + "password" => $password,
796 + );
517 797
798 + $feeds = array(); $feedSwitch = false; $current = null;
518 799 if ($this->for_feed_settings()) : // Existing feed?
519 - if (is_null($lookup)) : $lookup = $this->link->link->link_url; endif;
520 - $name = wp_specialchars($this->link->link->link_name, 'both');
800 + $feedSwitch = true;
801 + if (is_null($lookup)) :
802 + // Switch Feed without a specific feed yet suggested
803 + // Go to the human-readable homepage to look for
804 + // auto-detection links
805 +
806 + $lookup = $this->link->link->link_url;
807 + $auth = $this->link->setting('http auth method');
808 + $username = $this->link->setting('http username');
809 + $password = $this->link->setting('http password');
810 +
811 + // Guarantee that you at least have the option to
812 + // stick with what works.
813 + $current = $this->link->link->link_rss;
814 + $feeds[] = $current;
815 + endif;
816 + $name = esc_html($this->link->link->link_name);
521 817 else: // Or a new subscription to add?
522 - $name = "Subscribe to <code>".wp_specialchars(feedwordpress_display_url($lookup))."</code>";
818 + $name = "Subscribe to <code>".esc_html(feedwordpress_display_url($lookup))."</code>";
523 819 endif;
524 820 ?>
525 - <style type="text/css">
526 - form.fieldset {
527 - clear: both;
528 - }
529 - .feed-sample {
530 - float: right;
531 - background-color: #D0D0D0;
532 - color: black;
533 - width: 45%;
534 - font-size: 70%;
535 - border-left: 1px dotted #A0A0A0;
536 - margin-left: 1.0em;
537 - }
538 - .feed-sample p, .feed-sample h3 {
539 - padding-left: 0.5em;
540 - padding-right: 0.5em;
541 - }
542 - .feed-sample .feed-problem {
543 - background-color: #ffd0d0;
544 - border-bottom: 1px dotted black;
545 - padding-bottom: 0.5em;
546 - margin-bottom: 0.5em;
547 - }
548 - </style>
549 -
550 - <div class="wrap">
821 + <div class="wrap" id="feed-finder">
551 822 <h2>Feed Finder: <?php echo $name; ?></h2>
552 823
553 824 <?php
554 - $f =& new FeedFinder($lookup);
555 - $feeds = $f->find();
825 + if ($feedSwitch) :
826 + $this->display_alt_feed_box($lookup);
827 + endif;
828 +
829 + $finder = array();
830 + if (!is_null($current)) :
831 + $finder[$current] = new FeedFinder($current);
832 + endif;
833 + $finder[$lookup] = new FeedFinder($lookup);
834 +
835 + foreach ($finder as $url => $ff) :
836 + $feeds = array_merge($feeds, $ff->find(
837 + /*url=*/ NULL,
838 + /*params=*/ $credentials));
839 + endforeach;
840 +
841 + $feeds = array_values( // Renumber from 0..(N-1)
842 + $feeds
843 + );
844 +
845 + // Allow for some simple FeedFinder results filtering
846 + $feeds = apply_filters(
847 + 'feedwordpress_feedfinder_results',
848 + $feeds,
849 + array(
850 + "url" => $lookup,
851 + "auth" => $auth,
852 + "username" => $username,
853 + "password" => $password,
854 + "finder" => $finder,
855 + ),
856 + $this
857 + );
858 +
556 859 if (count($feeds) > 0):
860 + if ($feedSwitch) :
861 + ?>
862 + <h3>Feeds Found</h3>
863 + <?php
864 + endif;
865 +
866 + if (count($feeds) > 1) :
867 + $option_template = 'Option %d: ';
868 + $form_class = ' class="multi"';
869 + ?>
870 + <p><strong>This web page provides at least <?php print count($feeds); ?> different feeds.</strong> These feeds may provide the same information
871 + in different formats, or may track different items. (You can check the Feed Information and the
872 + Sample Item for each feed to get an idea of what the feed provides.) Please select the feed that you'd like to subscribe to.</p>
873 + <?php
874 + else :
875 + $option_template = '';
876 + $form_class = '';
877 + endif;
878 +
879 + global $fwp_credentials;
880 +
557 881 foreach ($feeds as $key => $f):
558 - $rss = @fetch_rss($f);
559 - if ($rss):
560 - $feed_title = isset($rss->channel['title'])?$rss->channel['title']:$rss->channel['link'];
561 - $feed_link = isset($rss->channel['link'])?$rss->channel['link']:'';
882 + $ofc = $fwp_credentials;
883 + $fwp_credentials = $credentials; // Set
884 + $pie = FeedWordPress::fetch($f, array("cache" => false));
885 + $fwp_credentials = $ofc; // Re-Set
886 +
887 + $rss = (is_wp_error($pie) ? $pie : new MagpieFromSimplePie($pie));
888 +
889 + if ($this->url_for_401($pie)) :
890 + $this->display_alt_feed_box($lookup, array(
891 + "err" => $pie,
892 + "auth" => $auth,
893 + "username" => $username,
894 + "password" => $password
895 + ));
896 + continue;
897 + endif;
898 +
899 + if ($rss and !is_wp_error($rss)):
900 + $feed_link = (isset($rss->channel['link'])?$rss->channel['link']:'');
901 + $feed_title = (isset($rss->channel['title'])?$rss->channel['title']:$feed_link);
562 902 $feed_type = ($rss->feed_type ? $rss->feed_type : 'Unknown');
903 + $feed_version_template = '%.1f';
904 + $feed_version = $rss->feed_version;
563 905 else :
564 906 // Give us some sucky defaults
565 907 $feed_title = feedwordpress_display_url($lookup);
566 908 $feed_link = $lookup;
567 909 $feed_type = 'Unknown';
910 + $feed_version_template = '';
911 + $feed_version = '';
568 912 endif;
569 913 ?>
570 - <form action="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/syndication.php" method="post">
571 - <div><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_switchfeed'); ?></div>
572 - <fieldset>
573 - <legend><?php echo $feed_type; ?> <?php echo $rss->feed_version; ?> feed</legend>
914 + <form<?php print $form_class; ?> action="<?php print $this->form_action('syndication.php'); ?>" method="post">
915 + <div class="inside"><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_switchfeed'); ?>
574 916
575 917 <?php
918 + $classes = array('feed-found'); $currentFeed = '';
919 + if (!is_null($current) and $current==$f) :
920 + $classes[] = 'current';
921 + $currentFeed = ' (currently subscribed)';
922 + endif;
923 + if ($key%2) :
924 + $classes[] = 'alt';
925 + endif;
926 + ?>
927 + <fieldset class="<?php print implode(" ", $classes); ?>">
928 + <legend><?php printf($option_template, ($key+1)); print $feed_type." "; printf($feed_version_template, $feed_version); ?> feed<?php print $currentFeed; ?></legend>
929 +
930 + <?php
576 931 $this->stamp_link_id();
577 932
578 933 // No feed specified = add new feed; we
579 934 // need to pass along a starting title
@@ -579,25 +934,26 @@
579 934 // need to pass along a starting title
580 935 // and homepage URL for the new Link.
581 936 if (!$this->for_feed_settings()):
582 937 ?>
583 - <input type="hidden" name="feed_title" value="<?php echo wp_specialchars($feed_title, 'both'); ?>" />
584 - <input type="hidden" name="feed_link" value="<?php echo wp_specialchars($feed_link, 'both'); ?>" />
938 + <input type="hidden" name="feed_title" value="<?php echo esc_html($feed_title); ?>" />
939 + <input type="hidden" name="feed_link" value="<?php echo esc_html($feed_link); ?>" />
585 940 <?php
586 941 endif;
587 942 ?>
588 943
589 - <input type="hidden" name="feed" value="<?php echo wp_specialchars($f, 'both'); ?>" />
944 + <input type="hidden" name="feed" value="<?php echo esc_html($f); ?>" />
590 945 <input type="hidden" name="action" value="switchfeed" />
591 946
592 947 <div>
593 948 <div class="feed-sample">
594 -
595 949 <?php
596 - if (count($rss->items) > 0):
950 + $link = NULL;
951 + $post = NULL;
952 + if (!is_wp_error($rss) and count($rss->items) > 0):
597 953 // Prepare to display Sample Item
598 - $link =& new MagpieMockLink($rss, $f);
599 - $post =& new SyndicatedPost($rss->items[0], $link);
954 + $link = new MagpieMockLink(array('simplepie' => $pie, 'magpie' => $rss), $f);
955 + $post = new SyndicatedPost(array('simplepie' => $rss->originals[0], 'magpie' => $rss->items[0]), $link);
600 956 ?>
601 957 <h3>Sample Item</h3>
602 958 <ul>
603 959 <li><strong>Title:</strong> <a href="<?php echo $post->post['meta']['syndication_permalink']; ?>"><?php echo $post->post['post_title']; ?></a></li>
@@ -606,15 +962,16 @@
606 962 <div class="entry">
607 963 <?php print $post->post['post_content']; ?>
608 964 </div>
609 965 <?php
966 + do_action('feedwordpress_feed_finder_sample_item', $f, $post, $link);
610 967 else:
611 - if (magpie_error()) :
968 + if (is_wp_error($rss)) :
612 969 print '<div class="feed-problem">';
613 970 print "<h3>Problem:</h3>\n";
614 971 print "<p>FeedWordPress encountered the following error
615 972 when trying to retrieve this feed:</p>";
616 - print '<p style="margin: 1.0em 3.0em"><code>'.magpie_error().'</code></p>';
973 + print '<p style="margin: 1.0em 3.0em"><code>'.$rss->get_error_message().'</code></p>';
617 974 print "<p>If you think this is a temporary problem, you can still force FeedWordPress to add the subscription. FeedWordPress will not be able to find any syndicated posts until this problem is resolved.</p>";
618 975 print "</div>";
619 976 endif;
620 977 ?>
@@ -628,171 +985,296 @@
628 985 <div>
629 986 <h3>Feed Information</h3>
630 987 <ul>
631 988 <li><strong>Homepage:</strong> <a href="<?php echo $feed_link; ?>"><?php echo is_null($feed_title)?'<em>Unknown</em>':$feed_title; ?></a></li>
632 - <li><strong>Feed URL:</strong> <a href="<?php echo wp_specialchars($f, 'both'); ?>"><?php echo wp_specialchars($f, 'both'); ?></a> (<a title="Check feed &lt;<?php echo wp_specialchars($f, 'both'); ?>&gt; for validity" href="http://feedvalidator.org/check.cgi?url=<?php echo urlencode($f); ?>">validate</a>)</li>
633 - <li><strong>Encoding:</strong> <?php echo isset($rss->encoding)?wp_specialchars($rss->encoding, 'both'):"<em>Unknown</em>"; ?></li>
634 - <li><strong>Description:</strong> <?php echo isset($rss->channel['description'])?wp_specialchars($rss->channel['description'], 'both'):"<em>Unknown</em>"; ?></li>
989 + <li><strong>Feed URL:</strong> <a title="<?php echo esc_html($f); ?>" href="<?php echo esc_html($f); ?>"><?php echo esc_html(feedwordpress_display_url($f, 40, 10)); ?></a> (<a title="Check feed &lt;<?php echo esc_html($f); ?>&gt; for validity" href="http://feedvalidator.org/check.cgi?url=<?php echo urlencode($f); ?>">validate</a>)</li>
990 + <li><strong>Encoding:</strong> <?php echo isset($rss->encoding)?esc_html($rss->encoding):"<em>Unknown</em>"; ?></li>
991 + <li><strong>Description:</strong> <?php echo isset($rss->channel['description'])?esc_html($rss->channel['description']):"<em>Unknown</em>"; ?></li>
635 992 </ul>
636 - <div class="submit"><input type="submit" name="Use" value="&laquo; Use this feed" /></div>
637 - <div class="submit"><input type="submit" name="Cancel" value="&laquo; Cancel" /></div>
993 + <?php $this->display_authentication_credentials_box(array(
994 + 'username' => $username,
995 + 'password' => $password,
996 + 'method' => $auth,
997 + )); ?>
998 + <?php do_action('feedwordpress_feedfinder_form', $f, $post, $link, $this->for_feed_settings()); ?>
999 + <div class="submit"><input type="submit" class="button-primary" name="Use" value="&laquo; Use this feed" />
1000 + <input type="submit" class="button" name="Cancel" value="× Cancel" /></div>
638 1001 </div>
639 1002 </div>
640 1003 </fieldset>
1004 + </div> <!-- class="inside" -->
641 1005 </form>
642 1006 <?php
1007 + unset($link);
1008 + unset($post);
643 1009 endforeach;
644 1010 else:
645 - print "<p><strong>".__('Error').":</strong> ".__("FeedWordPress couldn't find any feeds at").' <code><a href="'.htmlspecialchars($lookup).'">'.htmlspecialchars($lookup).'</a></code>';
646 - print ". ".__('Try another URL').".</p>";
1011 + foreach ($finder as $url => $ff) :
1012 + $url = esc_html($url);
1013 + print "<h3>Searched for feeds at ${url}</h3>\n";
1014 + print "<p><strong>".__('Error').":</strong> ".__("FeedWordPress couldn't find any feeds at").' <code><a href="'.htmlspecialchars($lookup).'">'.htmlspecialchars($lookup).'</a></code>';
1015 + print ". ".__('Try another URL').".</p>";
647 1016
648 - // Diagnostics
649 - print "<div class=\"updated\" style=\"margin-left: 3.0em; margin-right: 3.0em;\">\n";
650 - print "<h3>".__('Diagnostic information')."</h3>\n";
651 - if (!is_null($f->error()) and strlen($f->error()) > 0) :
652 - print "<h4>".__('HTTP request failure')."</h4>\n";
653 - print "<p>".$f->error()."</p>\n";
654 - else :
655 - print "<h4>".__('HTTP request completed')."</h4>\n";
656 - print "<p><strong>Status ".$f->status().":</strong> ".$this->HTTPStatusMessages[(int) $f->status()]."</p>\n";
657 - endif;
1017 + // Diagnostics
1018 + print "<div class=\"updated\" style=\"margin-left: 3.0em; margin-right: 3.0em;\">\n";
1019 + print "<h3>".__('Diagnostic information')."</h3>\n";
1020 + if (!is_null($ff->error()) and strlen($ff->error()) > 0) :
1021 + print "<h4>".__('HTTP request failure')."</h4>\n";
1022 + print "<p>".$ff->error()."</p>\n";
1023 + else :
1024 + print "<h4>".__('HTTP request completed')."</h4>\n";
1025 + print "<p><strong>Status ".$ff->status().":</strong> ".$this->HTTPStatusMessages[(int) $ff->status()]."</p>\n";
1026 + endif;
658 1027
659 - // Do some more diagnostics if the API for it is available.
660 - if (function_exists('_wp_http_get_object')) :
661 - $httpObject = _wp_http_get_object();
662 - $transports = $httpObject->_getTransport();
1028 + // Do some more diagnostics if the API for it is available.
1029 + if (function_exists('_wp_http_get_object')) :
1030 + $httpObject = _wp_http_get_object();
1031 +
1032 + if (is_callable(array($httpObject, '_getTransport'))) :
1033 + $transports = $httpObject->_getTransport();
1034 +
1035 + print "<h4>".__('HTTP Transports available').":</h4>\n";
1036 + print "<ol>\n";
1037 + print "<li>".implode("</li>\n<li>", array_map('get_class', $transports))."</li>\n";
1038 + print "</ol>\n";
1039 + elseif (is_callable(array($httpObject, '_get_first_available_transport'))) :
1040 + $transport = $httpObject->_get_first_available_transport(
1041 + array(),
1042 + $url
1043 + );
1044 +
1045 + print "<h4>".__("HTTP Transport").":</h4>\n";
1046 + print "<ol>\n";
1047 + print "<li>".MyPHP::val($transport)."</li>\n";
1048 + print "</ol>\n";
1049 + endif;
1050 +
1051 + print "</div>\n";
1052 + endif;
1053 + endforeach;
1054 + endif;
1055 +
1056 + if (!$feedSwitch) :
1057 + $this->display_alt_feed_box($lookup, /*alt=*/ true);
1058 + endif;
1059 + ?>
1060 + </div> <!-- class="wrap" -->
1061 + <?php
1062 + return false; // Don't continue
1063 + } /* FeedWordPressFeedsPage::display_feedfinder() */
663 1064
664 - print "<h4>".__('HTTP Transports available').":</h4>\n";
665 - print "<ol>\n";
666 - print "<li>".implode("</li>\n<li>", array_map('get_class', $transports))."</li>\n";
667 - print "</ol>\n";
668 - print "</div>\n";
1065 + function display_alt_feed_box ($lookup, $params = false) {
1066 + global $fwp_post;
1067 +
1068 + if (is_bool($params)) :
1069 + $params = array("alt" => $params);
1070 + endif;
1071 +
1072 + $params = wp_parse_args($params, array( // Defaults
1073 + "alt" => false,
1074 + "err" => NULL,
1075 + "auth" => NULL,
1076 + "password" => NULL,
1077 + "username" => NULL,
1078 + ));
1079 + $alt = $params['alt'];
1080 +
1081 + ?>
1082 + <form action="<?php print $this->form_action('syndication.php'); ?>" method="post">
1083 + <div class="inside"><?php
1084 + FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds');
1085 + ?>
1086 + <fieldset class="alt"
1087 + <?php if (!$alt): ?>style="margin: 1.0em 3.0em; font-size: smaller;"<?php endif; ?>>
1088 + <legend><?php if ($alt) : ?>Alternative feeds<?php else: ?>Find feeds<?php endif; ?></legend>
1089 + <?php if ($alt) : ?><h3>Use a different feed</h3><?php endif; ?>
1090 + <?php if (is_wp_error($params['err'])) :
1091 + ?>
1092 + <p><em><strong>401 Not Authorized.</strong> This URL may require
1093 + a username and password to access it.</em> You may want to add login
1094 + credentials below and check it again.</p>
1095 + <?php
669 1096 endif;
1097 + ?>
1098 + <div><label>Address:
1099 + <input type="text" name="lookup" id="use-another-feed"
1100 + placeholder="URL"
1101 + <?php if (is_null($lookup)) : ?>
1102 + value="URL"
1103 + <?php else : ?>
1104 + value="<?php print esc_html($lookup); ?>"
1105 + <?php endif; ?>
1106 + size="64" style="max-width: 80%" /></label>
1107 + <?php if (is_null($lookup)) : ?>
1108 + <?php FeedWordPressSettingsUI::magic_input_tip_js('use-another-feed'); ?>
1109 + <?php endif; ?>
670 1110
671 - endif;
672 - ?>
673 - </div>
674 -
675 - <form action="admin.php?page=<?php print $GLOBALS['fwp_path'] ?>/<?php echo basename(__FILE__); ?>" method="post">
676 - <div><?php
677 - FeedWordPressCompatibility::stamp_nonce(get_class($this));
678 - ?></div>
679 - <div class="wrap">
680 - <h2>Use another feed</h2>
681 - <div><label>Feed:</label>
682 - <input type="text" name="lookup" id="use-another-feed" value="URI" />
683 - <?php FeedWordPressSettingsUI::magic_input_tip_js('use-another-feed'); ?>
684 1111 <?php $this->stamp_link_id('link_id'); ?>
685 - <input type="hidden" name="action" value="feedfinder" /></div>
686 - <div class="submit"><input type="submit" value="Use this feed &raquo;" /></div>
687 - </div>
688 - </form>
1112 + <input type="hidden" name="action" value="feedfinder" />
1113 + <input type="submit" class="button<?php if ($alt): ?>-primary<?php endif; ?>" value="Check &raquo;" /></div>
1114 +
1115 + <?php $this->display_authentication_credentials_box(array(
1116 + 'username' => $params['username'],
1117 + 'password' => $params['password'],
1118 + 'method' => $params['auth'],
1119 + )); ?>
1120 +
1121 + <p>This can be the address of a feed, or of a website. FeedWordPress
1122 + will try to automatically detect any feeds associated with a
1123 + website.</p>
1124 + </div> <!-- class="inside" -->
1125 + </fieldset></form>
1126 +
689 1127 <?php
690 - return false; // Don't continue
691 - } /* WordPressFeedsPage::display_feedfinder() */
692 -
693 - function accept_POST ($post) {
694 - global $wpdb;
1128 + } /* FeedWordPressFeedsPage::display_alt_feed_box() */
1129 +
1130 + function save_settings ($post) {
1131 + if ($this->for_feed_settings()) :
695 1132
696 - // User mashed a Save Changes button
697 - if (isset($post['save']) or isset($post['submit'])) :
698 - if ($this->for_feed_settings()) :
699 - $alter = array ();
700 -
701 - // custom feed settings first
702 - foreach ($post['notes'] as $mn) :
703 - $mn['key0'] = trim($mn['key0']);
704 - $mn['key1'] = trim($mn['key1']);
705 - if (preg_match("\007^(("
706 - .implode(')|(',$this->special_settings)
707 - ."))$\007i",
708 - $mn['key1'])) :
709 - $mn['key1'] = 'user/'.$mn['key1'];
1133 + if (isset($post['link_rss_params_key'])) :
1134 + $qp = array();
1135 + foreach ($post['link_rss_params_key'] as $index => $key) :
1136 + if (strlen($key) > 0) :
1137 + if (isset($post['link_rss_params_value'][$index])
1138 + and strlen($post['link_rss_params_value'][$index])) :
1139 + $value = $post['link_rss_params_value'][$index];
1140 + $qp[] = array($key, $value);
1141 + endif;
710 1142 endif;
711 -
712 - if (strlen($mn['key0']) > 0) :
713 - unset($this->link->settings[$mn['key0']]); // out with the old
714 - endif;
715 -
716 - if (($mn['action']=='update') and (strlen($mn['key1']) > 0)) :
717 - $this->link->settings[$mn['key1']] = $mn['value']; // in with the new
718 - endif;
719 1143 endforeach;
720 -
721 - // now stuff through the web form
722 - // hardcoded feed info
723 -
724 - foreach (array('name', 'description', 'url') as $what) :
725 - // We have a checkbox for "No," so if it's unchecked, mark as "Yes."
726 - $this->link->settings["hardcode {$what}"] = (isset($post["hardcode_{$what}"]) ? $post["hardcode_{$what}"] : 'yes');
727 - if (FeedWordPress::affirmative($this->link->settings, "hardcode {$what}")) :
728 - $alter[] = "link_{$what} = '".$wpdb->escape($post['link'.$what])."'";
729 - endif;
730 - endforeach;
731 -
732 - // Update scheduling
733 - if (isset($post['update_schedule'])) :
734 - $this->link->settings['update/hold'] = $post['update_schedule'];
1144 + $this->update_setting('query parameters', serialize($qp));
1145 + endif;
1146 +
1147 + // custom feed settings first
1148 + foreach ($post['notes'] as $mn) :
1149 + $mn['key0'] = (isset($mn['key0']) ? trim($mn['key0']) : NULL);
1150 + $mn['key1'] = trim($mn['key1']);
1151 + if (preg_match("\007^(("
1152 + .implode(')|(',$this->special_settings)
1153 + ."))$\007i",
1154 + $mn['key1'])) :
1155 + $mn['key1'] = 'user/'.$mn['key1'];
735 1156 endif;
736 1157
737 - if (isset($post['use_default_update_window']) and strtolower($post['use_default_update_window'])=='yes') :
738 - unset($this->link->settings['update/window']);
739 - elseif (isset($post['update_window'])):
740 - if ((int) $post['update_window'] > 0) :
741 - $this->link->settings['update/window'] = (int) $post['update_window'];
742 - endif;
1158 + if (strlen($mn['key0']) > 0) :
1159 + unset($this->link->settings[$mn['key0']]); // out with the old
743 1160 endif;
744 1161
745 - $alter[] = "link_notes = '".$wpdb->escape($this->link->settings_to_notes())."'";
1162 + if (($mn['action']=='update') and (strlen($mn['key1']) > 0)) :
1163 + $this->link->settings[$mn['key1']] = $mn['value']; // in with the new
1164 + endif;
1165 + endforeach;
1166 +
1167 + // now stuff through the web form
1168 + // hardcoded feed info
1169 +
1170 + foreach (array('name', 'description', 'url') as $what) :
1171 + // We have a checkbox for "No," so if it's unchecked, mark as "Yes."
1172 + $this->link->settings["hardcode {$what}"] = (isset($post["hardcode_{$what}"]) ? $post["hardcode_{$what}"] : 'yes');
1173 + if (FeedWordPress::affirmative($this->link->settings, "hardcode {$what}")) :
1174 + $this->link->link->{'link_'.$what} = $post['link'.$what];
1175 + endif;
1176 + endforeach;
1177 +
1178 + // Update scheduling
1179 + if (isset($post['update_schedule'])) :
1180 + $this->link->settings['update/hold'] = $post['update_schedule'];
1181 + endif;
746 1182
747 - $alter_set = implode(", ", $alter);
748 -
749 - // issue update query
750 - $result = $wpdb->query("
751 - UPDATE $wpdb->links
752 - SET $alter_set
753 - WHERE link_id='{$this->link->id}'
754 - ");
755 - $this->updated = true;
756 -
757 - // reload link information from DB
758 - if (function_exists('clean_bookmark_cache')) :
759 - clean_bookmark_cache($this->link->id);
1183 + if (isset($post['use_default_update_window']) and strtolower($post['use_default_update_window'])=='yes') :
1184 + unset($this->link->settings['update/window']);
1185 + elseif (isset($post['update_window'])):
1186 + if ((int) $post['update_window'] > 0) :
1187 + $this->link->settings['update/window'] = (int) $post['update_window'];
760 1188 endif;
761 - $this->link = new SyndicatedLink($this->link->id);
1189 + endif;
1190 +
1191 + else :
1192 + // Global
1193 + update_option('feedwordpress_cat_id', $post['syndication_category']);
1194 +
1195 + if (!isset($post['automatic_updates']) or !in_array($post['automatic_updates'], array('init', 'shutdown'))) :
1196 + $automatic_updates = NULL;
762 1197 else :
763 - // Global
764 - update_option('feedwordpress_cat_id', $post['syndication_category']);
765 -
766 - if (!isset($post['automatic_updates']) or !in_array($post['automatic_updates'], array('init', 'shutdown'))) :
767 - $automatic_updates = false;
768 - else :
769 - $automatic_updates = $post['automatic_updates'];
1198 + $automatic_updates = $post['automatic_updates'];
1199 + endif;
1200 + update_option('feedwordpress_automatic_updates', $automatic_updates);
1201 +
1202 + if (isset($post['update_window'])):
1203 + if ((int) $post['update_window'] > 0) :
1204 + update_option('feedwordpress_update_window', (int) $post['update_window']);
770 1205 endif;
771 - update_option('feedwordpress_automatic_updates', $automatic_updates);
1206 + endif;
772 1207
773 - if (isset($post['update_window'])):
774 - if ((int) $post['update_window'] > 0) :
775 - update_option('feedwordpress_update_window', (int) $post['update_window']);
776 - endif;
777 - endif;
1208 + update_option('feedwordpress_update_time_limit', ($post['update_time_limit']=='yes')?(int) $post['time_limit_seconds']:0);
778 1209
779 - update_option('feedwordpress_update_time_limit', ($post['update_time_limit']=='yes')?(int) $post['time_limit_seconds']:0);
1210 + foreach (array('name', 'description', 'url') as $what) :
1211 + // We have a checkbox for "No," so if it's unchecked, mark as "Yes."
1212 + $hardcode = (isset($post["hardcode_{$what}"]) ? $post["hardcode_{$what}"] : 'yes');
1213 + update_option("feedwordpress_hardcode_{$what}", $hardcode);
1214 + endforeach;
1215 +
1216 + endif;
1217 +
1218 + if (isset($post['fetch_timeout'])) :
1219 + if (isset($post['fetch_timeout_default']) and $post['fetch_timeout_default']=='yes') :
1220 + $timeout = NULL;
1221 + else :
1222 + $timeout = $post['fetch_timeout'];
1223 + endif;
780 1224
781 - foreach (array('name', 'description', 'url') as $what) :
782 - // We have a checkbox for "No," so if it's unchecked, mark as "Yes."
783 - $hardcode = (isset($post["hardcode_{$what}"]) ? $post["hardcode_{$what}"] : 'yes');
784 - update_option("feedwordpress_hardcode_{$what}", $hardcode);
785 - endforeach;
786 -
787 - $this->updated = true;
1225 + if (is_int($timeout)) :
1226 + $timeout = intval($timeout);
788 1227 endif;
1228 + $this->update_setting('fetch timeout', $timeout);
1229 + endif;
1230 +
1231 + if (isset($post['update_incremental'])) :
1232 + $this->update_setting('update_incremental', $post['update_incremental']);
1233 + endif;
789 1234
790 - // Probably a "Go" button for the drop-down
1235 + if (isset($post['tombstones'])) :
1236 + $this->update_setting('tombstones', $post['tombstones']);
1237 + endif;
1238 +
1239 + if (isset($post['update_minimum'])) :
1240 + $this->update_setting('update/minimum', $post['update_minimum']);
1241 + endif;
1242 +
1243 + if (
1244 + isset($post['link_rss_auth_method'])
1245 + and $post['link_rss_auth_method']
1246 + and ('-' != $post['link_rss_auth_method'])
1247 + ) :
1248 + $this->update_setting('http auth method', $post['link_rss_auth_method']);
791 1249 else :
792 - $this->updated = false;
1250 + $this->update_setting('http auth method', NULL);
793 1251 endif;
794 - } /* WordPressFeedsPage::accept_POST() */
1252 +
1253 + if (
1254 + isset($post['link_rss_username'])
1255 + and (strlen($post['link_rss_username']) > 0)
1256 + and ('-' != $post['link_rss_auth_method'])
1257 + ) :
1258 + $this->update_setting('http username', $post['link_rss_username']);
1259 + else :
1260 + $this->update_setting('http username', NULL);
1261 + endif;
1262 +
1263 + if (
1264 + isset($post['link_rss_password'])
1265 + and (strlen($post['link_rss_password']) > 0)
1266 + and ('-' != $post['link_rss_auth_method'])
1267 + ) :
1268 + $this->update_setting('http password', $post['link_rss_password']);
1269 + else :
1270 + $this->update_setting('http password', NULL);
1271 + endif;
1272 +
1273 + $this->updatedPosts->accept_POST($post);
1274 +
1275 + parent::save_settings($post);
1276 + } /* FeedWordPressFeedsPage::save_settings() */
795 1277
796 1278 } /* class FeedWordPressFeedsPage */
797 1279
798 1280 $feedsPage = new FeedWordPressFeedsPage;