PluginProbe
FeedWordPress / 2024.1119
FeedWordPress v2024.1119
trunk 0.8 0.9 0.91 0.95 0.96 0.97 0.98 0.981 0.99 0.991 0.992 0.993 2008.1030 2008.1101 2008.1105 2008.1214 2009.0612 2009.0613 2009.0618 2009.0707 2009.1111 2009.1112 2010.0127 2010.0528 All 65 releases
feedwordpress / feeds-page.php

feeds-page.php in FeedWordPress 2024.1119, at feeds-page.php

1,521 lines 58.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 require_once dirname(__FILE__) . '/admin-ui.php';
3 require_once dirname(__FILE__) . '/magpiemocklink.class.php';
4 require_once dirname(__FILE__) . '/feedfinder.class.php';
5 require_once dirname(__FILE__) . '/updatedpostscontrol.class.php';
6
7 /**
8 * List of feeds for FWP
9 *
10 * @extends FeedWordPressAdminPage
11 * @global $post_source
12 */
13 class FeedWordPressFeedsPage extends FeedWordPressAdminPage {
14 /**
15 * List of possible HTTP status messages.
16 *
17 * @var array
18 *
19 * @note Added a few more, renamed a few to stick to contemporary standard. (gwyneth 20230918)
20 */
21 var $HTTPStatusMessages = array(
22 100 => 'Continue',
23 101 => 'Switching Protocols',
24 102 => 'Processing', // WebDAV; RFC 2518
25 103 => 'Early Hints', // RFC 8297
26 110 => 'Response is Stale', // Obsoleted in 2022 by RFC 9111 (caching-related)
27 111 => 'Revalidation Failed', // Obsoleted in 2022 by RFC 9111 (caching-related)
28 112 => 'Disconnected Operation', // Obsoleted in 2022 by RFC 9111 (caching-related)
29 113 => 'Heuristic Expiration', // Obsoleted in 2022 by RFC 9111 (caching-related)
30 199 => 'Miscellaneous Warning', // Obsoleted in 2022 by RFC 9111 (caching-related)
31 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.',
32 201 => 'Created',
33 202 => 'Accepted',
34 203 => 'Non-Authoritative information',
35 204 => 'No Content',
36 205 => 'Reset Content',
37 206 => 'Partial Content',
38 207 => 'Multi-Status', // WebDAV; RFC 4918
39 208 => 'Already Reported', // WebDAV; RFC 5842
40 214 => 'Transformation Applied', // Obsoleted in 2022 by RFC 9111 (caching-related)
41 218 => 'This is fine', // Non-standard; used by the Apache HTTP Serve)
42 226 => 'IM Used', // RFC 3229
43 299 => 'Miscellaneous Persistent Warning', // Obsoleted in 2022 by RFC 9111 (caching-related)
44 300 => 'Multiple Choices',
45 301 => 'Moved Permanently',
46 302 => 'Found', // Previously known as 'Moved temporarily'
47 303 => 'See Other',
48 304 => 'Not Modified',
49 305 => 'Use Proxy',
50 306 => 'Switch Proxy',
51 307 => 'Temporary Redirect',
52 308 => 'Permanent Redirect',
53 400 => 'Bad Request',
54 401 => 'Unauthorized. This URL probably needs a username and password for you to access it.',
55 402 => 'Payment Required',
56 403 => 'Forbidden. The URL is not made available for the machine that FeedWordPress is running on.',
57 404 => 'Not Found. There is nothing at this URL. Have you checked the address for typos?',
58 405 => 'Method Not Allowed',
59 406 => 'Not Acceptable',
60 407 => 'Proxy Authentication Required',
61 408 => 'Request Timeout',
62 409 => 'Conflict',
63 410 => 'Gone. This URL is no longer available on this server and no forwarding address is known.',
64 411 => 'Length Required',
65 412 => 'Precondition Failed',
66 413 => 'Payload Too Large', // Previously known as 'Request Entity Too Large'
67 414 => 'URI Too Long', // Previously known as 'Request URI Too Long'
68 415 => 'Unsupported Media Type',
69 416 => 'Range Not Satisfiable', // Previously known as 'Requested Range Not Satisfiable'
70 417 => 'Expectation Failed',
71 418 => 'I\'m a teapot', // RFC 2324, RFC 7168
72 419 => 'Page Expired', // Non-standard; used by the Laravel Framework
73 420 => 'Enhance Your Calm', // Non-standard; used by version 1.0 of the Twitter API
74 421 => 'Misdirected Request',
75 422 => 'Unprocessable Entity',
76 423 => 'Locked', // WebDAV; RFC 4918
77 424 => 'Failed Dependency', // WebDAV; RFC 4918
78 425 => 'Too Early', // RFC 8470
79 426 => 'Upgrade Required',
80 428 => 'Precondition Required', // RFC 6585
81 429 => 'Too Many Requests', // RFC 6585
82 431 => 'Request Header Fields Too Large', // RFC 6585
83 440 => 'Login Time-out', // Non-standard; used by Microsoft on IIS
84 444 => 'No Response', // Non-standard; used internally by the nginx web server
85 449 => 'Retry With', // Non-standard; used by Microsoft on IIS
86 450 => 'Blocked by Windows Parental Controls', // Non-standard; used by Microsoft
87 451 => 'Unavailable For Legal Reasons', // RFC 7725; also: used by Microsoft IIS for a redirect
88 460 => 'Too Soon', // Non-standard; used by Amazon on AWS
89 463 => 'Too Many IP Addresses', // Non-standard; used by Amazon on AWS
90 464 => 'Incompatible Protocol Version', // Non-standard; used by Amazon on AWS
91 494 => 'Request Header Too Large', // Non-standard; used by the nginx web server
92 495 => 'SSL Certificate Error', // Non-standard; used by the nginx web server
93 496 => 'SSL Certificate Required', // Non-standard; used by the nginx web server
94 498 => 'Invalid Token', // Non-standard; used by Esri on their ArcGIS for Server product
95 499 => 'Token Required', // Non-standard; used by Esri on their ArcGIS for Server product; also used as 'Client Closed Request' by the nginx web server
96 500 => 'Internal Server Error. Something unexpected went wrong with the configuration of the server that hosts this URL. You might try again later to see if this issue has been resolved.',
97 501 => 'Not Implemented',
98 502 => 'Bad Gateway',
99 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.',
100 504 => 'Gateway Timeout',
101 505 => 'HTTP Version Not Supported',
102 506 => 'Variant Also Negotiates', // RFC 2295
103 507 => 'Insufficient Storage', // WebDAV; RFC 4918
104 508 => 'Loop Detected', // WebDAV; RFC 5842
105 509 => 'Bandwidth Limit Exceeded', // Non-standard; used by the Apache Web Server as well as cPanel
106 510 => 'Not Extended', // RFC 2774
107 511 => 'Network Authentication Required', // RFC 6585
108 520 => 'Web Server Returned an Unknown Error', // Non-Standard; used by Cloudflare
109 521 => 'Web Server Is Down', // Non-Standard; used by Cloudflare
110 522 => 'Connection Timed Out', // Non-Standard; used by Cloudflare
111 523 => 'Origin Is Unreachable', // Non-Standard; used by Cloudflare
112 524 => 'A Timeout Occurred', // Non-Standard; used by Cloudflare
113 525 => 'SSL Handshake Failed', // Non-Standard; used by Cloudflare
114 526 => 'Invalid SSL Certificate', // Non-Standard; used by Cloudflare
115 527 => 'Railgun Error', // Non-Standard; used by Cloudflare
116 529 => 'Site is overloaded', // Non-standard; used by Qualys on its SSLLabs server testing API
117 530 => 'Site is frozen', // Non-standard; used by the Pantheon Systems web platform
118 561 => 'Unauthorized', // Non-standard; used by Amazon on AWS
119 598 => 'Network Read Timeout Error', // Non-standard; informal convention used by some HTTP procoes
120 599 => 'Network Connect Timeout Error', // Non-standard; informal convention used by some HTTP procoes
121 );
122
123 /**
124 * List of updated posts.
125 *
126 * @var mixed
127 */
128 var $updatedPosts = NULL;
129
130 /**
131 * List of special settings.
132 *
133 * Regular expression syntax is OK here.
134 *
135 * @var Array
136 */
137 var $special_settings = array(
138 'cats',
139 'cat_split',
140 'fetch timeout',
141 'freeze updates',
142 'hardcode name',
143 'hardcode url',
144 'hardcode description',
145 'hardcode categories', /* Deprecated */
146 'comment status',
147 'terms',
148 'map authors',
149 'munge permalink',
150 'ping status',
151 'post status',
152 'postmeta',
153 'query parameters',
154 'resolve relative',
155 'syndicated post type',
156 'tags',
157 'unfamiliar author',
158 'unfamliar categories', /* Deprecated */
159 'unfamiliar category',
160 'unfamiliar post_tag',
161 'add/.*',
162 'update/.*',
163 'feed/.*',
164 'link/.*',
165 'match/.*',
166 );
167
168 /**
169 * Constructs the Feeds page object
170 *
171 * @param mixed $link An object of class {@link SyndicatedLink} if created for one feed's settings, NULL if created for global default settings
172 * @uses UpdatedPostsControl
173 */
174 public function __construct( $link = -1 ) {
175 if ( is_numeric( $link ) and -1 == $link ) :
176 $link = $this->submitted_link();
177 endif;
178
179 parent::__construct( 'feedwordpressfeeds', $link );
180
181 $this->dispatch = 'feedwordpress_admin_page_feeds';
182 $this->pagenames = array(
183 'default' => 'Feeds',
184 'settings-update' => 'Syndicated feed',
185 'open-sheet' => 'Feed and Update',
186 );
187 $this->filename = __FILE__;
188 $this->updatedPosts = new UpdatedPostsControl( $this );
189
190 $this->special_settings = apply_filters( 'syndicated_feed_special_settings', $this->special_settings, $this );
191 } /* FeedWordPressFeedsPage constructor */
192
193 /**
194 * Prints out the feeds page.
195 *
196 * @return bool TRUE to continue printing out, FALSE to stop.
197 * @uses FeedWordPress::param()
198 */
199 function display() {
200 global $post_source;
201
202 $this->boxes_by_methods = array(
203 'feed_information_box' => __( 'Feed Information' ),
204 'global_feeds_box' => __( 'Update Scheduling' ),
205 'updated_posts_box' => __( 'Updated Posts' ),
206 'custom_settings_box' => __( 'Custom Feed Settings (for use in templates)' ),
207 'advanced_settings_box' => __( 'Advanced Settings' ),
208 );
209 if ($this->for_default_settings()) :
210 unset( $this->boxes_by_methods['custom_settings_box'] );
211 endif;
212
213 // Allow overriding of normal source for FeedFinder, which may
214 // be called from multiple points.
215 if ( isset( $post_source ) and ! is_null( $post_source ) ) :
216 $source = $post_source;
217 else :
218 $source = $this->dispatch;
219 endif;
220
221 $feedfinder = FeedWordPress::param( 'feedfinder' );
222 $action = FeedWordPress::param( 'action' );
223 if ( $feedfinder || in_array( $action, array( 'feedfinder', FWP_SYNDICATE_NEW ) ) ) :
224
225 // If this is a POST, validate source and user credentials
226 FeedWordPressCompatibility::validate_http_request(/*action=*/ $source, /*capability=*/ 'manage_links');
227
228 return $this->display_feedfinder(); // re-route to Feed Finder page
229 endif;
230
231 parent::display();
232 return false; // Don't continue
233 } /* FeedWordPressFeedsPage::display() */
234
235 /**
236 * Interface with JavaScript calls.
237 *
238 */
239 function ajax_interface_js() {
240 parent::ajax_interface_js();
241 ?>
242 jQuery( document ).ready( function () {
243 contextual_appearance( 'automatic-updates-selector', 'cron-job-explanation', null, 'no' );
244 contextual_appearance( 'time-limit', 'time-limit-box', null, 'yes' );
245 contextual_appearance( 'use-default-update-window-no', 'update-scheduling-note', null, null, 'block', true );
246 jQuery( '#use-default-update-window-yes, #use-default-update-window-no' ).click( function () {
247 contextual_appearance( 'use-default-update-window-no', 'update-scheduling-note', null, null, 'block', true );
248 } );
249
250 var els = [ 'name', 'description', 'url' ];
251 for ( var i = 0; i < els.length; i++ ) {
252 contextual_appearance(
253 /*item=*/ 'basics-hardcode-' + els[i],
254 /*appear=*/ 'basics-' + els[i] + '-view',
255 /*disappear=*/ 'basics-' + els[i] + '-edit',
256 /*value=*/ 'no',
257 /*visibleStyle=*/ 'block',
258 /*checkbox=*/ true
259 );
260 } /* for */
261
262 // Let's make the interface for the PAUSE/RESUME a bit better
263 jQuery( '<tr id="reveal-pause-resume"><th></th><td><button id="pause-resume-reveal-button">&mdash; PAUSE or RESUME UPDATES &mdash;</button></td></tr>' ).insertBefore( '#pause-resume' );
264 jQuery( '#pause-resume' ).hide();
265 jQuery( '#pause-resume-reveal-button' ).click( function( ev ) {
266 ev.preventDefault();
267
268 jQuery( '#pause-resume' ).toggle();
269 return false;
270 });
271 } );
272 <?php
273 } /* FeedWordPressFeedsPage::ajax_interface_js() */
274
275 /**
276 * Displays updated feeds.
277 *
278 * @param object $page Current page object (?).
279 * @param mixed|null $box A box inside this object.
280 */
281 /*static*/ function updated_posts_box( $page, $box = NULL ) {
282 ?>
283 <table class="edit-form">
284 <?php $page->updatedPosts->display(); ?>
285 </table>
286 <?php
287 } /* FeedWordPressFeedsPage::updated_posts_box() */
288
289 /**
290 * Displays form to deal with global feeds.
291 *
292 * @param object $page Current page object (?).
293 * @param mixed|null $box A box inside this object.
294 *
295 * @uses FeedWordPress::automatic_update_hook()
296 */
297 /*static*/ function global_feeds_box( $page, $box = NULL ) {
298 global $feedwordpress;
299 $automatic_updates = $feedwordpress->automatic_update_hook( array( 'setting only' => true ) );
300 $update_time_limit = (int) get_option( 'feedwordpress_update_time_limit' );
301
302 // Hey, ho, let's go...
303 ?>
304
305 <table class="edit-form"
306 <?php if ( $page->for_default_settings() ) : ?>
307
308 <tr>
309 <th scope="row"><?php esc_html_e( 'Update Method:' ); ?></th>
310 <td><select id="automatic-updates-selector" name="automatic_updates" size="1" onchange="contextual_appearance('automatic-updates-selector', 'cron-job-explanation', null, 'no');">
311 <option value="shutdown"<?php fwp_selected_flag( 'shutdown' == $automatic_updates ); ?>><?php esc_html_e( 'automatically check for updates after pages load' ); ?></option>
312 <option value="init"<?php fwp_selected_flag( 'init' == $automatic_updates ); ?>><?php esc_html_e( 'automatically check for updates before pages load' ); ?></option>
313 <option value="no"<?php fwp_selected_flag( ! $automatic_updates ); ?>><?php esc_html_e( 'cron job or manual updates' ); ?></option>
314 </select>
315 <div id="cron-job-explanation" class="setting-description">
316 <p><?php
317 /* Do we have shell_exec() available from here, or is it disabled for security reasons?
318 * If it's available, use it to execute `which` to try to get a realistic path to curl,
319 * or to wget. If everything fails or shell_exec() isn't available, then just make
320 * up something for the sake of example.
321 */
322 /** var string|null Path to either cURL or wget executables. */
323 $curlOrWgetPath = NULL;
324
325 /** var bool True if this WP installation can call shell commands. */
326 $shellExecAvailable = ( is_callable( 'shell_exec' ) && false === stripos( ini_get( 'disable_functions' ), 'shell_exec') );
327
328 if ( $shellExecAvailable ) :
329 $curlOrWgetPath = `which curl`; $opts = '--silent %s';
330 endif;
331
332 if ( $shellExecAvailable and ( is_null( $curlOrWgetPath ) or strlen( trim( $curlOrWgetPath ) ) == 0 ) ) :
333 $curlOrWgetPath = `which wget`; $opts = '-q -O - %s';
334 endif;
335
336 if ( is_null( $curlOrWgetPath ) or strlen( trim( $curlOrWgetPath ) ) == 0 ) :
337 $curlOrWgetPath = '/usr/bin/curl'; $opts = '--silent %s';
338 endif;
339
340 $curlOrWgetPath = preg_replace( '/\n+$/', '', $curlOrWgetPath );
341
342 /** var string Constructed shell command line to call cURL/wget for updating FeedWordPress feeds. */
343 $cmdline = $curlOrWgetPath . ' ' . sprintf( $opts, get_bloginfo( 'url' ) . '?update_feedwordpress=1' );
344
345 ?><?php esc_html_e( 'If you want to use a cron job, you can perform scheduled updates by sending regularly-scheduled requests to ' ); ?><a href="<?php bloginfo('url'); ?>?update_feedwordpress=1"><code><?php bloginfo('url'); ?>?update_feedwordpress=1</code></a>
346 <?php esc_html_e( 'For example, inserting the following line in your crontab:' ); ?></p>
347 <pre style="font-size: 0.80em"><code>*/10 * * * * <?php print esc_html($cmdline); ?></code></pre>
348 <p class="setting-description"><?php esc_html_e( 'will check in every 10 minutes and check for updates on any feeds that are ready to be polled for updates.' ); ?></p>
349 </div>
350 </td>
351 </tr>
352
353 <?php else : /* Feed-specific settings */ ?>
354
355 <tr>
356 <th scope="row"><?php esc_html_e( 'Last update' ) ?>:</th>
357 <td><?php
358 if ( isset( $page->link->settings['update/last'] ) ) :
359 echo esc_html( fwp_time_elapsed( $page->link->settings['update/last'] ) . " " );
360 else :
361 esc_html_e( " none yet" );
362 endif;
363 ?></td></tr>
364
365 <tr><th><?php esc_html_e( 'Next update' ) ?>:</th>
366 <td><?php
367 $holdem = ( isset( $page->link->settings['update/hold'] ) ? $page->link->settings['update/hold'] : 'scheduled' );
368 ?>
369 <select name="update_schedule">
370 <option value="scheduled"<?php echo ( 'scheduled' == $holdem ) ? ' selected="selected"' : ''; ?>><?php esc_html_e( 'update on schedule' ); ?> <?php
371 echo " (";
372 if ( isset( $page->link->settings['update/ttl'] ) and is_numeric( $page->link->settings['update/ttl'] ) ) :
373 if ( isset( $page->link->settings['update/timed'] ) and 'automatically' == $page->link->settings['update/timed'] ) :
374 esc_html_e( 'next: ');
375 $next = $page->link->settings['update/last'] + ( (int) $page->link->settings['update/ttl'] * 60 );
376 // Note: strftime() is deprecated; use date() instead. (gwyneth 20230918)
377 if ( strftime( '%x', time() ) != strftime( '%x', $next) ) :
378 echo esc_html( strftime( '%x', $next ) . ' ' );
379 endif;
380 echo esc_html( strftime( '%X', $page->link->settings['update/last'] + ( (int) $page->link->settings['update/ttl'] * 60 ) ) );
381 else :
382 echo esc_html__( "every " ) . esc_html( $page->link->settings['update/ttl'] ) . esc_html__( " minute" )
383 . ( ( 1 != $page->link->settings['update/ttl'] ) ? esc_html__( "s" ) : "" );
384 endif;
385 else:
386 esc_html_e( "next scheduled update" );
387 endif;
388 echo ")";
389 ?></option>
390 <option value="next"<?php echo ( 'next' == $holdem ) ? ' selected="selected"' : ''; ?>><?php esc_html_e( 'update ASAP' ); ?></option>
391 <option value="ping"<?php echo ( 'ping' == $holdem ) ? ' selected="selected"' : ''; ?>><?php esc_html_e( 'update only when pinged' ); ?></option>
392 </select></td></tr>
393
394 <?php endif; ?>
395
396 <tr id="pause-resume">
397 <th scope="row"><?php esc_html_e( 'Pause/Resume:'); ?></th>
398 <td><?php
399 $this->setting_radio_control(
400 'update/pause',
401 'update_pause',
402 /*options=*/ array(
403 'no' => __( '<strong>UPDATE:</strong> import new posts as normal' ),
404 'yes' => __( '<strong>PAUSE:</strong> do not import new posts until I unpause updates' ),
405 ),
406 /*params=*/ array(
407 'setting-default' => NULL,
408 'global-setting-default' => 'no',
409 'default-input-value' => 'default',
410 ),
411 );
412 ?></td>
413 </tr>
414
415 <tr>
416 <th scope="row"><?php esc_html_e( 'Update scheduling:') ?></th>
417 <td><p style="margin-top:0px"><?php esc_html_e( 'How long should FeedWordPress wait between updates before it considers this feed ready to be polled for updates again?' ); ?></p>
418 <?php
419 $this->setting_radio_control(
420 'update/window',
421 'update_window',
422 array( $this, 'update_window_edit_box' ),
423 array(
424 'global-setting-default' => DEFAULT_UPDATE_PERIOD,
425 'default-input-name' => 'use_default_update_window',
426 'default-input-id' => 'use-default-update-window-yes',
427 'default-input-id-no' => 'use-default-update-window-no',
428 'labels' => array($this, 'update_window_currently' ),
429 )
430 );
431 ?></td>
432 </tr>
433
434 <tr>
435 <th scope="row"><?php esc_html_e( 'Minimum Interval:'); ?></th>
436 <td><p style="margin-top:0px"><?php esc_html_e( 'Some feeds include standard elements that
437 request a specific update schedule. If the interval requested by the
438 feed provider is <em>longer</em> than FeedWordPress&rsquo;s normal scheduling,
439 FeedWordPress will always respect their request to slow down. But what
440 should it do if the update interval is <em>shorter</em> than the schedule set above?' ); ?></p>
441 <?php
442 $this->setting_radio_control(
443 'update/minimum', 'update_minimum',
444 /*options=*/ array(
445 'no' => __( 'Speed up and accept the interval from the feed provider' ),
446 'yes' => __( 'Keep pace and use the longer scheduling from FeedWordPress' ),
447 ),
448 /*params=*/ array(
449 'setting-default' => NULL,
450 'global-setting-default' => 'no',
451 'default-input-value' => 'default',
452 )
453 );
454 ?>
455 </td>
456 </tr>
457
458 <?php if ($this->for_default_settings()) : ?>
459
460 <tr>
461 <th scope="row"><?php esc_html_e( 'Time limit on updates' ); ?>:</th>
462 <td><select id="time-limit" name="update_time_limit" size="1" onchange="contextual_appearance( 'time-limit', 'time-limit-box', null, 'yes' );">
463 <option value="no"<?php fwp_selected_flag( $update_time_limit <= 0 ); ?>><?php esc_html_e( 'no time limit on updates' ); ?></option>
464 <option value="yes"<?php fwp_selected_flag( $update_time_limit > 0 ); ?>><?php esc_html_e( 'limit updates to no more than...' ); ?></option>
465 </select>
466 <span id="time-limit-box"><label><input type="text" name="time_limit_seconds" value="<?php print esc_attr( $update_time_limit ); ?>" size="5" /> <?php esc_html_e( 'seconds' ); ?></label></span>
467 </tr>
468
469 <?php endif; ?>
470
471 </table>
472
473 <?php
474 } /* FeedWordPressFeedsPage::global_feeds_box() */
475
476 /**
477 * Updates the window edit box.
478 *
479 * @param int $updateWindow Minutes between polling.
480 * @param bool $defaulted Unused.
481 * @param array $params Unused.
482 */
483 function update_window_edit_box( $updateWindow, $defaulted, $params ) {
484 if ( ! is_numeric( $updateWindow) ) :
485 $updateWindow = DEFAULT_UPDATE_PERIOD;
486 endif;
487 ?>
488 <p><?php esc_html_e( 'Wait' ); ?> <input type="text" name="update_window" value="<?php print esc_attr( $updateWindow ); ?>" size="4" /> <?php esc_html_e( 'minutes between polling.' ); ?></p>
489 <div class="setting-description" id="update-scheduling-note">
490 <p<?php if ( $updateWindow < 50 ) : ?> style="color: white; background-color: #703030; padding: 1.0em;"<?php endif; ?>><?php esc_html_e( '<strong>Recommendation.</strong> Unless you are positive that you have the webmaster&rsquo;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>
491 <p><?php esc_html_e( '<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&rsquo;s request.' ); ?></p>
492 </div>
493 <?php
494 } /* FeedWordPressFeedsPage::update_window_edit_box() */
495
496 /**
497 * Auxiliary function to update the window with current polling waiting period.
498 *
499 * @param int $updateWindow Minutes between polling.
500 * @param bool $defaulted Unused.
501 * @param array $params Unused.
502 */
503 function update_window_currently( $updateWindow, $defaulted, $params ) {
504 $updateWindow = (int) $updateWindow;
505 if ( 1 == $updateWindow ) :
506 $caption = __( 'wait %d minute between polling' );
507 else :
508 $caption = __( 'wait %d minutes between polling' );
509 endif;
510 return sprintf( $caption, $updateWindow );
511 } /* FeedWordPressFeedsPage::update_window_currently() */
512
513 /**
514 * Fetches the timeout setting.
515 *
516 * Nothing is returned, this just emits the HTML.
517 *
518 * @param int $setting Unused.
519 * @param bool $defaulted Unused.
520 * @param array $params Unused.
521 */
522 function fetch_timeout_setting( $setting, $defaulted, $params ) {
523 /** var int Fetch feed timeout in seconds. */
524 $timeout = intval( $this->setting( 'fetch timeout', FEEDWORDPRESS_FETCH_TIMEOUT_DEFAULT ) );
525
526 if ( $this->for_feed_settings() ) :
527 $article = __( 'this' );
528 else :
529 $article = __( 'a' );
530 endif;
531 ?>
532 <p><?php esc_html_e( 'Wait no more than' ); ?> <input name="fetch_timeout" type="number" min="0" size="3" value="<?php print esc_attr( $timeout ); ?>" />
533 <?php esc_html_e( 'second(s) when trying to fetch '); print esc_html( $article ); esc_html_e(' feed to check for updates. '); ?></p>
534 <p><?php esc_html_e( 'If ' ); print esc_html( $article ); esc_html_e(' source&rsquo;s web server does not respond before time runs
535 out, FeedWordPress will skip over the source and try again during the next update cycle.' ); ?></p>
536 <?php
537 } /* FeedWordPressFeedsPage::fetch_timeout_setting() */
538
539 /**
540 * Properly formats the feed timeout setting, with plurals if required.
541 *
542 * Nothing is returned, this just emits the HTML.
543 *
544 * @param int $setting Value for the feed timeout, in seconds.
545 * @param bool $defaulted Unused.
546 * @param array $params Unused.
547 */
548 function fetch_timeout_setting_value( $setting, $defaulted, $params ) {
549 print number_format( intval( $setting) ) . " " . ( ( 1 == $setting ) ? "second" : "seconds" );
550 }
551
552 /**
553 * Displays the advanced settings box on the FWP dashboard page.
554 *
555 * @param FeedWordPressFeedsPage $page A page object, unused.
556 * @param mixed|null $box A box inside this object, unused.
557 */
558 function advanced_settings_box( $page, $box = NULL ) {
559 ?>
560 <table class="edit-form">
561 <tr>
562 <th><?php esc_html_e( 'Fetch Timeout:' ); ?></th>
563 <td>
564 <?php
565 $this->setting_radio_control(
566 'fetch timeout', 'fetch_timeout',
567 array($this, 'fetch_timeout_setting'),
568 array(
569 'global-setting-default' => FEEDWORDPRESS_FETCH_TIMEOUT_DEFAULT,
570 'input-name' => 'fetch_timeout',
571 'default-input-name' => 'fetch_timeout_default',
572 'labels' => array($this, 'fetch_timeout_setting_value'),
573 )
574 );
575 ?>
576 </td>
577 </tr>
578 <tr>
579 <th><?php esc_html_e( 'Feed Update Type:' ); ?></th>
580 <td><?php
581 $this->setting_radio_control( 'update_incremental', 'update_incremental',
582 /*options=*/ array(
583 'incremental' => __( '**Incremental.** When items no longer appear on the feed, keep them in the WordPress posts table.' ),
584 'complete' => __( '**Complete.** When items no longer appear on the feed, they are obsolete; retire them from the WordPress posts table.' ),
585 ),
586 /*params=*/ array(
587 'setting-default' => NULL,
588 'global-setting-default' => 'incremental',
589 'default-input-value' => 'default',
590 )
591 ); ?></td>
592 </tr>
593 <tr>
594 <th><?php esc_html_e( 'Allow Feeds to Delete Posts:' ); ?></th>
595 <td><?php
596 $this->setting_radio_control(
597 'tombstones',
598 'tombstones',
599 /*options=*/ array(
600 'yes' => __( 'Yes. If a feed indicates that one of its posts has been deleted, delete the local copy syndicated to this website.' ),
601 'no' => __( 'No. Even if a feed indicates that one of its posts has been deleted, retain the local copy on this website.' ),
602 ),
603 /*params=*/ array(
604 'setting-default' => NULL,
605 'global-setting-default' => 'yes',
606 'default-input-value' => 'default',
607 )
608 ); ?></td>
609 </tr>
610 </table>
611 <?php
612 } /* FeedWordPressFeedsPage::advanced_settings_box() */
613
614 /**
615 * Shows a box for authentication credentials for a feed.
616 *
617 * @param array $params Array of parameters to parse.
618 */
619 function display_authentication_credentials_box( $params = array() ) {
620 static $count = 0;
621
622 $params = wp_parse_args(
623 $params,
624 array(
625 'username' => NULL,
626 'password' => NULL,
627 'method' => '-',
628 ),
629 );
630
631 // Equivalents
632 if ( is_null( $params['method'] ) ) : $params['method'] = '-'; endif;
633
634 $count++;
635 /** var string Constructed slug for each feed credential. */
636 $slug = ( $count > 1 ? '-' . $count : '' );
637
638 global $feedwordpress;
639 $authMethods = apply_filters(
640 'feedwordpress_http_auth_methods',
641 $feedwordpress->httpauth->methods_available(),
642 );
643
644 $linkRssAuthId = sanitize_html_class( 'link-rss-authentication' . $slug );
645 $linkRssCredentialsId = sanitize_html_class( 'link-rss-authentication-credentials' . $slug );
646 $linkRssAuthMethodId = sanitize_html_class( 'link-rss-authentication-method' . $slug );
647
648 if ( count( $authMethods ) > 1 ) : /* More than '-' */
649 ?>
650 <div class="link-rss-authentication" id="<?php print esc_attr( $linkRssAuthId ); ?>">
651 <table>
652 <tbody>
653 <tr class="link-rss-authentication-credentials" id="<?php print esc_attr( $linkRssCredentialsId ); ?>">
654 <td><label><?php esc_html_e( 'user:' ); ?> <input type="text" name="link_rss_username"
655 value="<?php print esc_attr( $params['username'] ); ?>" size="16"
656 placeholder="username to access this feed" /></label></td>
657 <td><label><?php esc_html_e( 'pass:' ); ?> <input type="text" name="link_rss_password"
658 value="<?php print esc_attr( $params['password'] ); ?>" size="16"
659 placeholder=<?php esc_html_e( 'password to access this feed' ); ?> /></label></td>
660 <td class="link-rss-authentication-method" id="<?php print esc_attr( $linkRssAuthMethodId ); ?>"><label><?php esc_html_e( 'method' ); ?>: <select class="link-rss-auth-method" id="link-rss-auth-method" name="link_rss_auth_method" size="1">
661 <?php foreach ( $authMethods as $value => $label ) : ?>
662 <option value="<?php print esc_attr( $value ); ?>"<?php
663 fwp_selected_flag( $value == $params['method'] );
664 ?>><?php print esc_html( $label ); ?></option>
665 <?php endforeach; ?>
666 </select></label></td>
667 </tr>
668 </tbody>
669 </table>
670 </div>
671
672 <script type="text/javascript">
673 jQuery('<td><a class="add-remove remove-it" id="link-rss-userpass-remove<?php print esc_attr( $slug ); ?>" href="#"><span class="x">(X)</span> <?php esc_html_e( 'Remove' ); ?></a></td>')
674 .appendTo('#<?php print esc_attr( $linkRssCredentialsId ); ?>' )
675 .click( feedAuthenticationMethodUnPress );
676 jQuery( '#link-rss-auth-method<?php print esc_attr( $slug ); ?>' ).change( feedAuthenticationMethod );
677 feedAuthenticationMethod( {
678 init: true,
679 node: jQuery( '#<?php print esc_attr( $linkRssAuthId ); ?>' )
680 } );
681 </script>
682
683 <?php
684 endif;
685 } /* FeedWordPressFeedsPage::display_authentication_credentials_box() */
686
687 /**
688 * Displays a box with information about a feed.
689 *
690 * @param object $page Current page object (?).
691 * @param mixed|null $box A box inside this object.
692 *
693 * @uses get_categories()
694 * @uses get_category()
695 * @uses get_option()
696 * @uses maybe_unserialize()
697 * @uses FeedWordPress::link_category_id()
698 */
699 function feed_information_box( $page, $box = NULL ) {
700 $link_rss_params = maybe_unserialize( $page->setting( 'query parameters', '' ) );
701 if ( ! is_array( $link_rss_params ) ) :
702 $link_rss_params = array();
703 endif;
704
705 if ( $page->for_feed_settings() ) :
706 $info['name'] = esc_html( $page->link->link->link_name );
707 $info['description'] = esc_html( $page->link->link->link_description );
708 $info['url'] = esc_html( $page->link->link->link_url );
709 $rss_url = $page->link->link->link_rss;
710
711 $hardcode['name'] = $page->link->hardcode( 'name' );
712 $hardcode['description'] = $page->link->hardcode( 'description' );
713 $hardcode['url'] = $page->link->hardcode( 'url' );
714 else :
715 $cat_id = FeedWordPress::link_category_id();
716
717 $params = array();
718 $params['taxonomy'] = 'link_category';
719 $params['hide_empty'] = false;
720 $results = get_categories( $params );
721
722 /** var bool Guarantee that the Contributors category will be in the drop-down chooser, even if it is empty. */
723 $found_link_category_id = false;
724 foreach ( $results as $row ) :
725 // Normalize case
726 if ( ! isset( $row->cat_id ) ) : $row->cat_id = $row->cat_ID; endif;
727
728 if ( $row->cat_id == $cat_id) : $found_link_category_id = true; endif;
729 endforeach;
730
731 if ( ! $found_link_category_id ) :
732 $results[] = get_category( $cat_id );
733 endif;
734
735 $info = array();
736 $rss_url = null;
737
738 $hardcode['name'] = get_option( 'feedwordpress_hardcode_name' );
739 $hardcode['description'] = get_option( 'feedwordpress_hardcode_description' );
740 $hardcode['url'] = get_option( 'feedwordpress_hardcode_url' );
741 endif;
742
743 /** @var bool Hide authentication (unused). */
744 $hideAuth = false;
745
746 $username = $this->setting( 'http username', NULL );
747
748 if ( is_null( $username ) ) :
749 $username = '';
750 $hideAuth = true;
751 endif;
752
753 $password = $this->setting( 'http password', NULL );
754 if ( is_null( $password ) ) :
755 $password = '';
756 endif;
757
758 $auth = $this->setting( 'http auth method', NULL );
759
760 if ( is_null( $auth ) or ( strlen( $auth ) == 0 ) ) :
761 $auth = '-';
762 $hideAuth = true;
763 endif;
764
765 // Hey ho, let's go
766
767 ?>
768 <table class="edit-form">
769
770 <?php if ( $page->for_feed_settings() ) : ?>
771
772 <tr>
773 <th scope="row"><?php esc_html_e( 'Feed URL:' ) ?></th>
774 <td><a href="<?php echo esc_html( $rss_url ); ?>"><?php echo esc_html( $rss_url ); ?></a>
775 (<a href="<?php echo esc_url( FEEDVALIDATOR_URI ); ?>?url=<?php echo urlencode( $rss_url ); ?>"
776 title="<?php esc_html_e( 'Check feed' ); ?> &lt;<?php echo esc_html( $rss_url ); ?>&gt; <?php esc_html_e( 'for validity' ); ?>">validate</a>)
777 <input type="submit" name="feedfinder" value="switch &rarr;" style="font-size:smaller" />
778
779 <?php $this->display_authentication_credentials_box( array(
780 'username' => $username,
781 'password' => $password,
782 'method' => $auth,
783 )
784 );
785 ?>
786 <table id="link-rss-params">
787 <tbody>
788 <?php
789 $link_rss_params['new'] = array( '', '' );
790 $i = 0;
791 foreach ( $link_rss_params as $index => $pair ) :
792 ?>
793 <tr class="link-rss-params-row" id="link-rss-params-<?php print esc_attr($index); ?>">
794 <td><label><?php esc_html_e( 'Parameter' ); ?>: <input type="text" class="link_params_key"
795 name="link_rss_params_key[<?php print esc_attr( $index ); ?>]" value="<?php print esc_html( $pair[0] ); ?>"
796 size="5" style="width: 5em" placeholder="name" /></label></td>
797 <td class="link-rss-params-value-cell"><label class="link_params_value_label">= <input type="text" class="link_params_value"
798 name="link_rss_params_value[<?php print esc_attr( $index ); ?>]" value="<?php print esc_html( $pair[1] ); ?>"
799 size="8" placeholder="value" /></label></td>
800 </tr>
801 <?php
802 $i++;
803 endforeach;
804 ?>
805 </tbody>
806 </table>
807
808 <div><input type="hidden" id="link-rss-params-num" name="link_rss_params_num" value="<?php print esc_attr($i); ?>" /></div>
809
810 <script>
811 function linkParamsRowRemove( element ) {
812 jQuery( element ).closest( 'tr' ).fadeOut(
813 'slow',
814 function () {
815 jQuery( this ).remove();
816 }
817 );
818 }
819
820 jQuery('<td><a href="#" class="add-remove link-rss-params-remove"><span class="x">(X)</span> <?php esc_html_e( 'Remove' ); ?></a></td>' ).insertAfter( '.link-rss-params-value-cell' );
821
822 jQuery( '#link-rss-params-new' ).hide();
823 jQuery( '<a class="add-remove" id="link-rss-params-add" href="#"><span class="dashicons dashicons-plus fwp-no-underline"></span> <?php esc_html_e( 'Add a query parameter' ); ?></a>').insertAfter( '#link-rss-params' );
824 jQuery( '#link-rss-params-add' ).click( function () {
825 var next = jQuery( '#link-rss-params-num' ).val();
826 var newRow = jQuery( '#link-rss-params-new' ).clone().attr( 'id', 'link-rss-params-' + next );
827 newRow.find( '.link_params_key' ).attr( 'name', 'link_rss_params_key[' + next + ']' );
828 newRow.find( '.link_params_value' ).attr( 'name', 'link_rss_params_value[' + next + ']' );
829
830 newRow.find( '.link-rss-params-remove' ).click(
831 function () {
832 linkParamsRowRemove( this );
833 return false;
834 }
835 );
836
837 newRow.appendTo( '#link-rss-params' );
838 newRow.show();
839
840 // Update counter for next row.
841 next++;
842 jQuery( '#link-rss-params-num' ).val( next );
843
844 return false;
845 } );
846 jQuery( '.link-rss-params-remove' ).click( function () {
847 linkParamsRowRemove( this );
848 return false;
849 } );
850 </script>
851 </td>
852 </tr>
853
854 <?php
855 $rows = array(
856 "name" => __('Link Name'),
857 "description" => __('Short Description'),
858 "url" => __('Homepage'),
859 );
860 foreach ( $rows as $what => $label ) :
861 $hardcode_name = sanitize_html_class( sprintf( 'hardcode_%s', $what ) );
862 $hardcode_id = sanitize_html_class( sprintf( 'basics-hardcode-%s', $what ) );
863 $hardcode_view_id = sanitize_html_class( sprintf( 'basics-%s-view', $what ) );
864 $hardcode_edit_id = sanitize_html_class( sprintf( 'basics-%s-edit', $what ) );
865 ?>
866 <tr>
867 <th scope="row"><?php print esc_html( $label ); ?></th>
868 <td>
869 <div id="<?php print esc_attr( $hardcode_edit_id ); ?>"><input type="text" name="link<?php print esc_attr( $what ); ?>"
870 value="<?php echo esc_attr( $info[$what] ); ?>" style="width: 95%" /></div>
871 <div id="<?php print esc_attr( $hardcode_view_id ); ?>">
872 <?php if ( 'url' == $what ) : ?><a href="<?php print esc_url( $info[$what] ); ?>"><?php else : ?><strong><?php endif; ?>
873 <?php print ( strlen( trim( $info[$what] ) ) > 0 ) ? esc_attr( $info[$what] ) : esc_attr__( '(none provided)' ); ?>
874 <?php if ( 'url' == $what ) : ?></a><?php else : ?></strong><?php endif; ?></div>
875
876 <div>
877 <label><input id="<?php print esc_attr( $hardcode_id ); ?>"
878 type="radio" name="<?php print esc_attr( $hardcode_name ); ?>" value="no"
879 <?php echo ( ('yes' == $hardcode[$what] ) ? '' : ' checked="checked"');?>
880 onchange="contextual_appearance( 'basics-hardcode-<?php print esc_attr( $what ); ?>', '<?php print esc_attr( $hardcode_view_id ); ?>', '<?php print esc_attr( $hardcode_edit_id ); ?>', 'no', 'block', /*checkbox=*/ true )"
881 /> <?php esc_html_e( 'Update automatically from feed' ); ?></label>
882 <label><input type="radio" name="<?php print esc_attr( $hardcode_name ); ?>" value="yes"
883 <?php echo ( ( 'yes' != $hardcode[$what] ) ? '' : ' checked="checked"' );?>
884 onchange="contextual_appearance('<?php print esc_attr( $hardcode_id ); ?>', '<?php print esc_attr( $hardcode_view_id ); ?>', '<?php print esc_attr( $hardcode_edit_id ); ?>', 'no', 'block', /*checkbox=*/ true)"
885 /> <?php esc_html_e( 'Edit manually' ); ?></label>
886 </div>
887 </td>
888 </tr>
889 <?php
890 endforeach;
891 ?>
892
893 <?php else : ?>
894
895 <tr>
896 <th scope="row"><?php esc_html_e( 'Syndicated Link category:' ); ?></th>
897 <td><p><select name="syndication_category" size="1">
898 <?php
899 foreach ( $results as $row ) :
900 // Normalize case
901 if ( ! isset( $row->cat_id ) ) : $row->cat_id = $row->cat_ID; endif;
902
903 echo "\n\t" . '<option value="' . esc_attr( $row->cat_id ) . '"';
904 if ( $row->cat_id == $cat_id) :
905 echo ' selected="selected"';
906 endif;
907 echo '>' . esc_attr( $row->cat_id ) . ': ' . esc_html( $row->cat_name );
908 echo '</option>' . "\n";
909 endforeach;
910 ?></select></p>
911 <p class="setting-description"><?php esc_html_e( 'FeedWordPress will syndicate the
912 links placed under this link category.' ); ?></p>
913 </td>
914 </tr>
915
916 <tr>
917 <th scope="row"><?php esc_html_e( 'Link Names:' ); ?></th>
918 <td><label><input type="checkbox" name="hardcode_name" value="no"<?php echo ( ( 'yes' == $hardcode['name'] )? '' : ' checked="checked"' );?>/> <?php esc_html_e( 'Update contributor titles automatically when the feed title changes' ); ?></label></td>
919 </tr>
920
921 <tr>
922 <th scope="row"><?php esc_html_e( 'Short descriptions:' ); ?></th>
923 <td><label><input type="checkbox" name="hardcode_description" value="no"<?php echo ( ( 'yes' == $hardcode['description'] ) ? '' : ' checked="checked"' );?>/> <?php esc_html_e( 'Update contributor descriptions automatically when the feed tagline changes' ); ?></label></td>
924 </tr>
925
926 <tr>
927 <th scope="row"><?php esc_html_e( 'Homepages:' ); ?></th>
928 <td><label><input type="checkbox" name="hardcode_url" value="no"<?php echo ( ( 'yes' == $hardcode['url'] ) ? '' : ' checked="checked"' );?>/> <?php esc_html_e( 'Update contributor homepages automatically when the feed link changes' ); ?></label></td>
929 </tr>
930
931 <?php endif; ?>
932
933 </table>
934 <?php
935 } /* FeedWordPressFeedsPage::feed_information_box() */
936
937
938 function custom_settings_box( $page, $box = NULL ) {
939 $postsSettings = $this->admin_page_href('posts-page.php', array(), $page->link);
940 ?>
941 <p class="setting-description">These custom settings are special fields for the <strong>feed</strong> you are
942 syndicating, to be retrieved in templates using the <code>get_feed_meta()</code> function. They do not create
943 custom fields on syndicated <strong>posts</strong>. If you want to create custom fields that are applied to each
944 individual post from this feed, set up the settings in <a href="<?php print esc_url($postsSettings); ?>">Syndicated Posts</a>.</p>
945 <div id="postcustomstuff">
946 <table id="meta-list" cellpadding="3">
947 <tr>
948 <th>Key</th>
949 <th>Value</th>
950 <th>Action</th>
951 </tr>
952
953 <?php
954 $i = 0;
955 foreach ($page->link->settings as $key => $value) :
956 if ( !preg_match("\007^((".implode(')|(', $page->special_settings)."))$\007i", $key)) :
957 ?>
958 <tr style="vertical-align:top">
959 <th width="30%" scope="row"><input type="hidden" name="notes[<?php echo esc_attr($i); ?>][key0]" value="<?php echo esc_html($key); ?>" />
960 <input id="notes-<?php echo esc_attr($i); ?>-key" name="notes[<?php echo esc_attr($i); ?>][key1]" value="<?php echo esc_html($key); ?>" /></th>
961 <td width="60%"><textarea rows="2" cols="40" id="notes-<?php echo esc_attr($i); ?>-value" name="notes[<?php echo esc_attr($i); ?>][value]"><?php echo esc_html($value); ?></textarea></td>
962 <td width="10%"><select name="notes[<?php echo esc_attr($i); ?>][action]">
963 <option value="update">save changes</option>
964 <option value="delete">delete this setting</option>
965 </select></td>
966 </tr>
967 <?php
968 $i++;
969 endif;
970 endforeach;
971 ?>
972 <tr>
973 <th scope="row"><input type="text" size="10" name="notes[<?php echo esc_attr( $i ); ?>][key1]" value="" /></th>
974 <td><textarea name="notes[<?php echo esc_attr( $i ); ?>][value]" rows="2" cols="40"></textarea></td>
975 <td><em>add new setting...</em><input type="hidden" name="notes[<?php echo esc_attr( $i ); ?>][action]" value="update" /></td>
976 </tr>
977 </table>
978 </div> <!-- id="postcustomstuff" -->
979 <?php
980 }
981
982 function url_for_401 ($err) {
983 $ret = NULL;
984 if (is_wp_error($err)) :
985 if ($err->get_error_code()=='http_request_failed') :
986 $data = $err->get_error_data('http_request_failed');
987
988 if (is_array($data) and isset($data['status'])) :
989 if (401==$data['status']) :
990 $ret = $data['uri'];
991 endif;
992 endif;
993 endif;
994 endif;
995 return $ret;
996 }
997
998 function display_feedfinder () {
999 $lookup = FeedWordPress::param( 'lookup' );
1000
1001 $auth = FeedWordPress::param( 'link_rss_auth_method' );
1002 $username = FeedWordPress::param( 'link_rss_username' );
1003 $password = FeedWordPress::param( 'link_rss_password' );
1004 $credentials = array(
1005 "authentication" => $auth,
1006 "username" => $username,
1007 "password" => $password,
1008 );
1009
1010 $feeds = array(); $feedSwitch = false; $current = null;
1011 if ($this->for_feed_settings()) : // Existing feed?
1012 $feedSwitch = true;
1013 if (is_null($lookup)) :
1014 // Switch Feed without a specific feed yet suggested
1015 // Go to the human-readable homepage to look for
1016 // auto-detection links
1017
1018 $lookup = $this->link->link->link_url;
1019 $auth = $this->link->setting('http auth method');
1020 $username = $this->link->setting('http username');
1021 $password = $this->link->setting('http password');
1022
1023 // Guarantee that you at least have the option to
1024 // stick with what works.
1025 $current = $this->link->link->link_rss;
1026 $feeds[] = $current;
1027 endif;
1028 $name = $this->link->link->link_name;
1029 else: // Or a new subscription to add?
1030 $name = "Subscribe to ".feedwordpress_display_url($lookup);
1031 endif;
1032 ?>
1033 <div class="wrap" id="feed-finder">
1034 <h2>Feed Finder: <?php echo esc_html($name); ?></h2>
1035
1036 <?php
1037 if ($feedSwitch) :
1038 $this->display_alt_feed_box($lookup);
1039 endif;
1040
1041 $finder = array();
1042 if ( !is_null($current)) :
1043 $finder[$current] = new FeedFinder($current);
1044 endif;
1045 $finder[$lookup] = new FeedFinder($lookup);
1046
1047 foreach ($finder as $url => $ff) :
1048 $feeds = array_merge($feeds, $ff->find(
1049 /*url=*/ NULL,
1050 /*params=*/ $credentials));
1051 endforeach;
1052
1053 $feeds = array_values( // Renumber from 0..(N-1)
1054 $feeds
1055 );
1056
1057 // Allow for some simple FeedFinder results filtering
1058 $feeds = apply_filters(
1059 'feedwordpress_feedfinder_results',
1060 $feeds,
1061 array(
1062 "url" => $lookup,
1063 "auth" => $auth,
1064 "username" => $username,
1065 "password" => $password,
1066 "finder" => $finder,
1067 ),
1068 $this
1069 );
1070
1071 if (count($feeds) > 0):
1072 if ($feedSwitch) :
1073 ?>
1074 <h3>Feeds Found</h3>
1075 <?php
1076 endif;
1077
1078 if (count($feeds) > 1) :
1079 $option_template = 'Option %d: ';
1080 $form_class = 'multi';
1081 ?>
1082 <p><strong>This web page provides at least <?php print count($feeds); ?> different feeds.</strong> These feeds may provide the same information
1083 in different formats, or may track different items. (You can check the Feed Information and the
1084 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>
1085 <?php
1086 else :
1087 $option_template = '';
1088 $form_class = '';
1089 endif;
1090
1091 global $fwp_credentials;
1092
1093 foreach ($feeds as $key => $f):
1094 $ofc = $fwp_credentials;
1095 $fwp_credentials = $credentials; // Set
1096 $pie = FeedWordPress::fetch($f, array("cache" => false));
1097 $fwp_credentials = $ofc; // Re-Set
1098
1099 $rss = (is_wp_error($pie) ? $pie : new MagpieFromSimplePie($pie));
1100
1101 if ($this->url_for_401($pie)) :
1102 $this->display_alt_feed_box($lookup, array(
1103 "err" => $pie,
1104 "auth" => $auth,
1105 "username" => $username,
1106 "password" => $password
1107 ));
1108 continue;
1109 endif;
1110
1111 if ($rss and !is_wp_error($rss)):
1112 $feed_link = (isset($rss->channel['link'])?$rss->channel['link']:'');
1113 $feed_title = (isset($rss->channel['title'])?$rss->channel['title']:$feed_link);
1114 $feed_type = ($rss->feed_type ? $rss->feed_type : 'Unknown');
1115 $feed_version_template = '%.1f';
1116 $feed_version = $rss->feed_version;
1117 else :
1118 // Give us some sucky defaults
1119 $feed_title = feedwordpress_display_url($lookup);
1120 $feed_link = $lookup;
1121 $feed_type = 'Unknown';
1122 $feed_version_template = '';
1123 $feed_version = '';
1124 endif;
1125 ?>
1126 <form <?php fwp_form_class_attr($form_class); ?> action="<?php print esc_url( $this->form_action( 'syndication.php' ) ); ?>" method="post">
1127 <div class="inside"><?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_switchfeed'); ?>
1128
1129 <?php
1130 $classes = array('feed-found'); $currentFeed = '';
1131 if ( !is_null($current) and $current==$f) :
1132 $classes[] = 'current';
1133 $currentFeed = ' (currently subscribed)';
1134 endif;
1135 if ($key%2) :
1136 $classes[] = 'alt';
1137 endif;
1138 ?>
1139 <fieldset class="<?php print esc_attr( implode(" ", $classes) ); ?>">
1140 <legend><?php print esc_html( sprintf( $option_template, ( $key + 1 ) ) ); print esc_html($feed_type) . " "; print esc_html( sprintf( $feed_version_template, $feed_version ) ); ?> feed<?php print esc_html( $currentFeed ); ?></legend>
1141
1142 <?php
1143 $this->stamp_link_id();
1144
1145 // No feed specified = add new feed; we
1146 // need to pass along a starting title
1147 // and homepage URL for the new Link.
1148 if ( ! $this->for_feed_settings()):
1149 ?>
1150 <input type="hidden" name="feed_title" value="<?php echo esc_html($feed_title); ?>" />
1151 <input type="hidden" name="feed_link" value="<?php echo esc_html($feed_link); ?>" />
1152 <?php
1153 endif;
1154 ?>
1155
1156 <input type="hidden" name="feed" value="<?php echo esc_html($f); ?>" />
1157 <input type="hidden" name="action" value="switchfeed" />
1158
1159 <div>
1160 <div class="feed-sample">
1161 <?php
1162 $link = null;
1163 $post = null;
1164 if ( !is_wp_error($rss) and count($rss->items) > 0):
1165 // Prepare to display Sample Item
1166 $link = new MagpieMockLink(array('simplepie' => $pie, 'magpie' => $rss), $f);
1167 $post = new SyndicatedPost(array('simplepie' => $rss->originals[0], 'magpie' => $rss->items[0]), $link);
1168 ?>
1169 <h3>Sample Item</h3>
1170 <ul>
1171 <li><strong>Title:</strong> <a href="<?php echo esc_url( $post->post['meta']['syndication_permalink'] ); ?>"><?php echo esc_html( $post->post['post_title'] ); ?></a></li>
1172 <li><strong>Date:</strong> <?php print esc_html( date('d-M-y g:i:s a', $post->published() ) ); ?></li>
1173 </ul>
1174 <div class="entry">
1175 <?php print wp_kses( $post->post['post_content'], 'post' ); ?>
1176 </div>
1177 <?php
1178 do_action('feedwordpress_feed_finder_sample_item', $f, $post, $link);
1179 else:
1180 if (is_wp_error($rss)) :
1181 print '<div class="feed-problem">';
1182 print "<h3>Problem:</h3>\n";
1183 print "<p>FeedWordPress encountered the following error
1184 when trying to retrieve this feed:</p>";
1185 print '<p style="margin: 1.0em 3.0em"><code>' . esc_html( $rss->get_error_message() ) . '</code></p>';
1186 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>";
1187 print "</div>";
1188 endif;
1189 ?>
1190 <h3>No Items</h3>
1191 <p>FeedWordPress found no posts on this feed.</p>
1192 <?php
1193 endif;
1194 ?>
1195 </div>
1196
1197 <div>
1198 <h3>Feed Information</h3>
1199 <ul>
1200 <li><strong>Homepage:</strong> <a href="<?php echo esc_url( $feed_link ); ?>"><?php echo is_null( $feed_title )?'<em>Unknown</em>': esc_html( $feed_title ); ?></a></li>
1201 <li><strong>Feed URL:</strong> <a title="<?php echo esc_html( $f ); ?>" href="<?php echo esc_url( $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>
1202 <li><strong>Encoding:</strong> <?php echo isset($rss->encoding) ? esc_html($rss->encoding) : "<em>Unknown</em>"; ?></li>
1203 <li><strong>Description:</strong> <?php echo isset($rss->channel['description']) ? esc_html($rss->channel['description']) : "<em>Unknown</em>"; ?></li>
1204 </ul>
1205 <?php $this->display_authentication_credentials_box(array(
1206 'username' => $username,
1207 'password' => $password,
1208 'method' => $auth,
1209 )); ?>
1210 <?php do_action('feedwordpress_feedfinder_form', $f, $post, $link, $this->for_feed_settings()); ?>
1211 <div class="submit"><input type="submit" class="button-primary" name="Use" value="&laquo; Use this feed" />
1212 <input type="submit" class="button" name="Cancel" value="× Cancel" /></div>
1213 </div>
1214 </div>
1215 </fieldset>
1216 </div> <!-- class="inside" -->
1217 </form>
1218 <?php
1219 unset($link);
1220 unset($post);
1221 endforeach;
1222 else:
1223 foreach ($finder as $url => $ff) :
1224 print '<h3>Searched for feeds at '. esc_html( $url ) . '</h3>' . "\n";
1225 print '<p><strong>' . esc_html__( 'Error' ) . ':</strong> ' . esc_html__( 'FeedWordPress couldn\'t find any feeds at' ).' <code><a href="' . esc_url( $lookup ) . '">' . esc_html( $lookup ) . '</a></code>';
1226 print '. ' . esc_html__( 'Try another URL' ) . '.</p>';
1227
1228 // Diagnostics
1229 print "<div class=\"updated\" style=\"margin-left: 3.0em; margin-right: 3.0em;\">\n";
1230 print '<h3>' . esc_html__( 'Diagnostic information' ) . '</h3>' . "\n";
1231 if ( !is_null($ff->error()) and strlen($ff->error()) > 0) :
1232 print '<h4>'. esc_html__( 'HTTP request failure' ) . '</h4>' . "\n";
1233 print '<p>' . esc_html( $ff->error() ) ."</p>\n";
1234 else :
1235 print '<h4>' . esc_html__( 'HTTP request completed' ) . '</h4>' . "\n";
1236 print '<p><strong>Status ' . esc_html( $ff->status() ) . ':</strong> '. esc_html( $this->HTTPStatusMessages[ (int) $ff->status() ] ) ."</p>\n";
1237 endif;
1238
1239 // Do some more diagnostics if the API for it is available.
1240 // Note to @radgeek: consider using a hook instead: https://developer.wordpress.org/reference/hooks/http_api_transports/ (gwyneth 20230920)
1241 if ( function_exists( '_wp_http_get_object' ) ) :
1242 $httpObject = _wp_http_get_object();
1243
1244 /*
1245 // _getTransport() was totally deprecated (gwyneth 20230920)
1246 if (is_callable(array($httpObject, '_getTransport'))) :
1247
1248 $transports = $httpObject->_getTransport();
1249
1250 print "<h4>".__('HTTP Transports available').":</h4>\n";
1251 print "<ol>\n";
1252 print "<li>".implode("</li>\n<li>", array_map('get_class', $transports))."</li>\n";
1253 print "</ol>\n";
1254 else
1255 */
1256 if ( is_callable( array( $httpObject, '_get_first_available_transport' ) ) ) :
1257 $transport = $httpObject->_get_first_available_transport(
1258 array(),
1259 $url
1260 );
1261
1262 print "<h4>" . esc_html__("HTTP Transport") . ":</h4>\n";
1263 print "<ol>\n";
1264 print "<li>" . esc_html( MyPHP::val($transport) ) . "</li>\n";
1265 print "</ol>\n";
1266 endif;
1267
1268 print "</div>\n";
1269 endif;
1270 endforeach;
1271 endif;
1272
1273 if ( ! $feedSwitch) :
1274 $this->display_alt_feed_box($lookup, /*alt=*/ true);
1275 endif;
1276 ?>
1277 </div> <!-- class="wrap" -->
1278 <?php
1279 return false; // Don't continue
1280 } /* FeedWordPressFeedsPage::display_feedfinder() */
1281
1282 function display_alt_feed_box ($lookup, $params = false)
1283 {
1284 if (is_bool($params)) :
1285 $params = array("alt" => $params);
1286 endif;
1287
1288 $params = wp_parse_args($params, array( // Defaults
1289 "alt" => false,
1290 "err" => NULL,
1291 "auth" => NULL,
1292 "password" => NULL,
1293 "username" => NULL,
1294 ));
1295 $alt = $params['alt'];
1296
1297 ?>
1298 <form action="<?php print esc_url( $this->form_action('syndication.php') ); ?>" method="post">
1299 <div class="inside"><?php
1300 FeedWordPressCompatibility::stamp_nonce('feedwordpress_feeds');
1301 ?>
1302 <fieldset class="alt"
1303 <?php if ( ! $alt): ?>style="margin: 1.0em 3.0em; font-size: smaller;"<?php endif; ?>>
1304 <legend><?php if ($alt) : ?>Alternative feeds<?php else: ?>Find feeds<?php endif; ?></legend>
1305 <?php if ($alt) : ?><h3>Use a different feed</h3><?php endif; ?>
1306 <?php if (is_wp_error($params['err'])) :
1307 ?>
1308 <p><em><strong>401 Not Authorized.</strong> This URL may require
1309 a username and password to access it.</em> You may want to add login
1310 credentials below and check it again.</p>
1311 <?php
1312 endif;
1313 ?>
1314 <div><label>Address:
1315 <input type="text" name="lookup" id="use-another-feed"
1316 placeholder="URL"
1317 <?php if (is_null($lookup)) : ?>
1318 value="URL"
1319 <?php else : ?>
1320 value="<?php print esc_html($lookup); ?>"
1321 <?php endif; ?>
1322 size="64" style="max-width: 80%" /></label>
1323 <?php if (is_null($lookup)) : ?>
1324 <?php FeedWordPressSettingsUI::magic_input_tip_js('use-another-feed'); ?>
1325 <?php endif; ?>
1326
1327 <?php $this->stamp_link_id('link_id'); ?>
1328 <input type="hidden" name="action" value="feedfinder" />
1329 <input type="submit" class="button<?php if ($alt): ?>-primary<?php endif; ?>" value="Check &raquo;" /></div>
1330
1331 <?php $this->display_authentication_credentials_box(array(
1332 'username' => $params['username'],
1333 'password' => $params['password'],
1334 'method' => $params['auth'],
1335 )); ?>
1336
1337 <p>This can be the address of a feed, or of a website. FeedWordPress
1338 will try to automatically detect any feeds associated with a
1339 website.</p>
1340 </div> <!-- class="inside" -->
1341 </fieldset></form>
1342
1343 <?php
1344 } /* FeedWordPressFeedsPage::display_alt_feed_box() */
1345
1346 function save_settings () {
1347 if ($this->for_feed_settings()) :
1348 $params_key = FeedWordPress::post( 'link_rss_params_key', array() );
1349
1350 if ( is_array( $params_key ) && count($params_key) > 0 ) :
1351 $params_values = FeedWordPress::post( 'link_rss_params_value', array() );
1352 $qp = array();
1353 foreach ( $params_key as $index => $key ) :
1354 if (strlen($key) > 0) :
1355
1356 if ( isset( $params_values[ $index ] ) ) :
1357
1358 $params_value = $params_values[ $index ];
1359 if ( strlen($params_value) > 0 ) :
1360 $qp[] = array( $key, $params_value );
1361 endif;
1362 endif;
1363 endif;
1364 endforeach;
1365 $this->update_setting('query parameters', serialize($qp));
1366
1367 endif;
1368
1369 // custom feed settings first
1370 $param_notes = FeedWordPress::post( 'notes', array() );
1371 foreach ( $param_notes as $mn ) :
1372 $mn['key0'] = ( isset($mn['key0']) ? trim($mn['key0']) : null );
1373 $mn['key1'] = trim($mn['key1']);
1374 if (preg_match("\007^(("
1375 .implode(')|(',$this->special_settings)
1376 ."))$\007i",
1377 $mn['key1'])) :
1378 $mn['key1'] = 'user/'.$mn['key1'];
1379 endif;
1380
1381 if (strlen($mn['key0']) > 0) :
1382 unset($this->link->settings[$mn['key0']]); // out with the old
1383 endif;
1384
1385 if (($mn['action']=='update') and (strlen($mn['key1']) > 0)) :
1386 $this->link->settings[$mn['key1']] = $mn['value']; // in with the new
1387 endif;
1388 endforeach;
1389
1390 // now stuff through the web form
1391 // hardcoded feed info
1392
1393 foreach (array('name', 'description', 'url') as $what) :
1394 // We have a checkbox for "No," so if it's unchecked, mark as "Yes."
1395 $this->link->settings["hardcode {$what}"] = FeedWordPress::post( "hardcode_{$what}", 'yes' );
1396 if (FeedWordPress::affirmative($this->link->settings, "hardcode {$what}")) :
1397 $this->link->link->{'link_'.$what} = FeedWordPress::post( 'link' . $what );
1398 endif;
1399 endforeach;
1400
1401 // Update scheduling
1402 $update_schedule = FeedWordPress::post( 'update_schedule' );
1403 if ( ! is_null( $update_schedule ) ) :
1404 $this->link->settings['update/hold'] = $update_schedule;
1405 endif;
1406
1407 $use_default_update_window = FeedWordPress::post( 'use_default_update_window' );
1408 $update_window = FeedWordPress::post( 'update_window' );
1409 if ( FeedWordPress::affirmative( $use_default_update_window ) ) :
1410 unset($this->link->settings['update/window']);
1411 elseif ( ! is_null( $update_window ) ) :
1412 $update_window = intval( $update_window );
1413 if ( $update_window > 0 ) :
1414 $this->link->settings['update/window'] = $update_window;
1415 endif;
1416 endif;
1417
1418 else :
1419 // Global
1420 update_option('feedwordpress_cat_id', FeedWordPress::post( 'syndication_category' ) );
1421
1422 $automatic_updates = FeedWordPress::post( 'automatic_updates' );
1423 if ( ! in_array( $automatic_updates, array( 'init', 'shutdown' ) ) ) :
1424 $automatic_updates = null;
1425 endif;
1426 update_option('feedwordpress_automatic_updates', $automatic_updates);
1427
1428 $update_window = FeedWordPress::post( 'update_window' );
1429 if ( ! is_null( $update_window ) ) :
1430 $update_window = intval( $update_window );
1431 if ( $update_window > 0 ) :
1432 update_option( 'feedwordpress_update_window', $update_window );
1433 endif;
1434 endif;
1435
1436 $update_time_limit = FeedWordPress::post( 'update_time_limit' );
1437 $time_limit_seconds = 0;
1438 if ( FeedWordPress::affirmative( $update_time_limit ) ) :
1439 $time_limit_seconds = intval( FeedWordPress::post( 'time_limit_seconds' ) );
1440 endif;
1441 update_option( 'feedwordpress_update_time_limit', $time_limit_seconds );
1442
1443 foreach (array('name', 'description', 'url') as $what) :
1444 // We have a checkbox for "No," so if it's unchecked, mark as "Yes."
1445 $hardcode = FeedWordPress::post( "hardcode_{$what}", 'yes' );
1446 update_option( "feedwordpress_hardcode_{$what}", $hardcode );
1447 endforeach;
1448
1449 endif;
1450
1451 $update_pause = FeedWordPress::post( 'update_pause' );
1452 if ( ! is_null( $update_pause ) ) :
1453 $this->update_setting( 'update/pause', $update_pause );
1454 endif;
1455
1456 $fetch_timeout = FeedWordPress::post( 'fetch_timeout' );
1457 if ( ! is_null( $fetch_timeout ) ) :
1458 $fetch_timeout_default = FeedWordPress::post( 'fetch_timeout_default' );
1459 if ( FeedWordPress::affirmative( $fetch_timeout_default ) ) :
1460 $fetch_timeout = null;
1461 endif;
1462
1463 if ( is_int( $fetch_timeout ) ) :
1464 $fetch_timeout = intval( $fetch_timeout );
1465 endif;
1466 $this->update_setting( 'fetch timeout', $fetch_timeout );
1467 endif;
1468
1469 $update_incremental = FeedWordPress::post( 'update_incremental' );
1470 if ( ! is_null( $update_incremental ) ) :
1471 $this->update_setting( 'update_incremental', $update_incremental );
1472 endif;
1473
1474 $tombstones = FeedWordPress::post( 'tombstones' );
1475 if ( ! is_null( $tombstones ) ) :
1476 $this->update_setting('tombstones', $tombstones );
1477 endif;
1478
1479 $update_minimum = FeedWordPress::post( 'update_minimum' );
1480 if ( ! is_null( $update_minimum ) ) :
1481 $this->update_setting( 'update/minimum', $update_minimum );
1482 endif;
1483
1484 $link_rss_auth_method = FeedWordPress::post( 'link_rss_auth_method' );
1485 if (
1486 ! $link_rss_auth_method
1487 || '-' == $link_rss_auth_method
1488 ) :
1489 $link_rss_auth_method = null;
1490 endif;
1491 $this->update_setting( 'http auth method', $link_rss_auth_method );
1492
1493 $link_rss_username = FeedWordPress::post( 'link_rss_username' );
1494 if (
1495 ! $link_rss_username
1496 || is_null( $link_rss_auth_method )
1497 ) :
1498 $link_rss_username = null;
1499 endif;
1500 $this->update_setting( 'http username', $link_rss_username );
1501
1502 $link_rss_password = FeedWordPress::post( 'link_rss_password' );
1503 if (
1504 strlen( $link_rss_password ) == 0
1505 || is_null( $link_rss_auth_method )
1506 ) :
1507 $link_rss_password = null;
1508 endif;
1509 $this->update_setting( 'http password', $link_rss_password );
1510
1511 $this->updatedPosts->accept_POST();
1512
1513 parent::save_settings();
1514 } /* FeedWordPressFeedsPage::save_settings() */
1515
1516 } /* class FeedWordPressFeedsPage */
1517
1518 $feedsPage = new FeedWordPressFeedsPage;
1519 $feedsPage->display();
1520
1521