Version Description
WORDPRESS 5.5 COMPATIBILITY FIXES, RESOLVES WARNING NOTICES OR WP-ADMIN LOCKOUT. WordPress 5.5 incorporated a newer release of SimplePie, version 1.5.5, which is pretty rad, but FeedWordPress classes that relied on SimplePie 1.3.1's method signatures would then produce PHP warning notices. That should be pretty innocuous, but depending on web server configurations, some users could get locked out of their own wp-admin interface by the display of error notices in the browser at inopportune times. In any case, I have
PHP 7.4 COMPATIBILITY FIX: Magic quotes were deprecated and then removed back in PHP 5.x, and in PHP 7.4 the vestigial
get_magic_quotes_gpc()
function has been deprecated. We don't need to worry about it anymore for versions of PHP still supported by WordPress. The reference to the function in the MyPHP utility class caused PHP warnings in more recent versions of PHP; so it has now been removed.DIVERS BUG FIXES AND PHP WARNING NOTICES RESOLVED, thanks to @oppiansteve's fixes and pull requests. (Thanks!)
JQUERY COMPATIBILITY FIXES, RESOLVES MYSTERIOUS VANISHING FEED SELECTOR IN WP-ADMIN. An upgrade to WordPress's packaged jQuery caused the drop-down box for feed settings (in Syndication > Feeds & Updates, Syndication > Posts & Links, etc.) to vanish shortly after pageload. That was awkward, so I disabled the now-incompatible interface chrome that was causing it to vanish.
Release Info
Developer | radgeek |
Plugin | FeedWordPress |
Version | 2020.0818 |
Comparing to | |
See all releases |
Code changes from version 2020.0118 to 2020.0818
- btc-qr-64px.png +0 -0
- compatability.php +28 -0
- diagnostics-page.php +62 -10
- feedwordpie_item.class.php → extend/SimplePie/1.3.1/feedwordpie_item.class.php +1 -0
- feedwordpress_parser.class.php → extend/SimplePie/1.3.1/feedwordpie_parser.class.php +61 -44
- extend/SimplePie/default/feedwordpie_item.class.php +56 -0
- extend/SimplePie/default/feedwordpie_parser.class.php +562 -0
- feedwordpie.class.php → extend/SimplePie/feedwordpie.class.php +0 -0
- feedwordpress-content-type-sniffer.class.php → extend/SimplePie/feedwordpie_content_type_sniffer.class.php +3 -3
- feedwordpress_file.class.php → extend/SimplePie/feedwordpie_file.class.php +3 -3
- extend/SimplePie/feedwordpie_item.class.php +12 -0
- extend/SimplePie/feedwordpie_parser.class.php +12 -0
- externals/myphp/myphp.class.php +6 -6
- feedwordpress-elements.js +2 -2
- feedwordpress.php +233 -537
- feedwordpress.pings.functions.php +86 -0
- feedwordpress.wp-admin.post-edit.functions.php +104 -0
- feedwordpressboilerplatereformatter.class.php +122 -0
- feedwordpressboilerplatereformatter.shortcode.functions.php +126 -0
- performance-page.php +3 -1
- posts-page.php +3 -1
- readme.txt +22 -2
- syndicatedlink.class.php +37 -22
- syndicatedpost.class.php +7 -4
- template-functions.php +11 -0
Binary file
|
@@ -135,6 +135,34 @@ if (!function_exists('set_post_field')) {
|
|
135 |
|
136 |
} /* if */
|
137 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
require_once(dirname(__FILE__).'/feedwordpress-walker-category-checklist.class.php');
|
139 |
|
140 |
function fwp_category_checklist ($post_id = 0, $descendents_and_self = 0, $selected_cats = false, $params = array()) {
|
135 |
|
136 |
} /* if */
|
137 |
|
138 |
+
if (!function_exists('is_countable')) {
|
139 |
+
|
140 |
+
// Copied from WordPress 5.3.2 wp-includes/compat.php pursuant to terms
|
141 |
+
// of GPL. Provide support for is_countable() for versions of PHP < 7.3
|
142 |
+
// and for versions of WordPress < 4.9.6. -C.J. 2020/01/24
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Polyfill for is_countable() function added in PHP 7.3.
|
146 |
+
*
|
147 |
+
* Verify that the content of a variable is an array or an object
|
148 |
+
* implementing the Countable interface.
|
149 |
+
*
|
150 |
+
* @since 4.9.6
|
151 |
+
*
|
152 |
+
* @param mixed $var The value to check.
|
153 |
+
*
|
154 |
+
* @return bool True if `$var` is countable, false otherwise.
|
155 |
+
*/
|
156 |
+
function is_countable( $var ) {
|
157 |
+
return ( is_array( $var )
|
158 |
+
|| $var instanceof Countable
|
159 |
+
|| $var instanceof SimpleXMLElement
|
160 |
+
|| $var instanceof ResourceBundle
|
161 |
+
);
|
162 |
+
}
|
163 |
+
|
164 |
+
} /* if */
|
165 |
+
|
166 |
require_once(dirname(__FILE__).'/feedwordpress-walker-category-checklist.class.php');
|
167 |
|
168 |
function fwp_category_checklist ($post_id = 0, $descendents_and_self = 0, $selected_cats = false, $params = array()) {
|
@@ -1,5 +1,6 @@
|
|
1 |
<?php
|
2 |
require_once(dirname(__FILE__) . '/admin-ui.php');
|
|
|
3 |
|
4 |
class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
|
5 |
public function __construct() {
|
@@ -41,7 +42,7 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
|
|
41 |
$boxes_by_methods = array(
|
42 |
'info_box' => __('Diagnostic Information'),
|
43 |
'diagnostics_box' => __('Display Diagnostics'),
|
44 |
-
'updates_box' => __('
|
45 |
'tests_box' => __('Diagnostic Tests'),
|
46 |
);
|
47 |
|
@@ -135,6 +136,7 @@ class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
|
|
135 |
<th scope="row">Hosting Environment:</th>
|
136 |
<td><ul style="margin-top: 0; padding-top: 0;">
|
137 |
<li><em>WordPress:</em> version <?php print $wp_version; ?></li>
|
|
|
138 |
<?php if (function_exists('phpversion')) : ?>
|
139 |
<li><em>PHP:</em> version <?php print phpversion(); ?></li>
|
140 |
<?php endif; ?>
|
@@ -263,18 +265,21 @@ testing but absolutely inappropriate for a production server.</p>
|
|
263 |
'Update Diagnostics' => array(
|
264 |
'update_schedule:check' => 'whenever a FeedWordPress checks in on the update schedule',
|
265 |
'updated_feeds' => 'as each feed is checked for updates',
|
266 |
-
'updated_feeds:errors:persistent' => 'when attempts to update a feed have resulted in errors</label> <label>for at least <input type="number" min="1" max="360" step="1" name="diagnostics_persistent_error_hours" value="'.$hours.'" /> hours',
|
267 |
-
'updated_feeds:errors' => 'any time FeedWordPress encounters any errors while checking a feed for updates',
|
268 |
-
'updated_feeds:http' => "displaying the raw HTTP data passed to and from the feed being checked for updates",
|
269 |
'syndicated_posts' => 'as each syndicated post is added to the database',
|
270 |
'feed_items' => 'as each syndicated item is considered on the feed',
|
271 |
'memory_usage' => 'indicating how much memory was used',
|
272 |
),
|
|
|
|
|
|
|
|
|
|
|
273 |
'Syndicated Post Details' => array(
|
274 |
'feed_items:freshness' => 'as FeedWordPress decides whether to treat an item as a new post, an update, or a duplicate of an existing post',
|
275 |
'feed_items:rejected' => 'when FeedWordPress rejects a post without syndicating it',
|
276 |
'syndicated_posts:categories' => 'as categories, tags, and other terms are added on the post',
|
277 |
'syndicated_posts:meta_data' => 'as syndication meta-data is added on the post',
|
|
|
278 |
),
|
279 |
'Advanced Diagnostics' => array(
|
280 |
'feed_items:freshness:reasons' => 'explaining the reason that a post was treated as an update to an existing post',
|
@@ -318,6 +323,15 @@ testing but absolutely inappropriate for a production server.</p>
|
|
318 |
} /* FeedWordPressDiagnosticsPage::updates_box () */
|
319 |
|
320 |
static function tests_box ($page, $box = NULL) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
321 |
?>
|
322 |
<script type="text/javascript">
|
323 |
function clone_http_test_args_keyvalue_prototype () {
|
@@ -334,11 +348,20 @@ function clone_http_test_args_keyvalue_prototype () {
|
|
334 |
<table class="edit-form">
|
335 |
<tr>
|
336 |
<th scope="row">HTTP:</th>
|
337 |
-
<td><div><input type="url" name="http_test_url" value="" placeholder="http://www.example.com/" size="127" style="width: 80%; max-width: 80.0em;" />
|
338 |
<input type="submit" name="feedwordpress_diagnostics_do[http_test]" value="Test »" /></div>
|
339 |
<div><select name="http_test_method" size="1">
|
340 |
-
|
341 |
-
<option value="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
342 |
</select></div>
|
343 |
<table>
|
344 |
<tr>
|
@@ -358,7 +381,7 @@ function clone_http_test_args_keyvalue_prototype () {
|
|
358 |
|
359 |
<tr>
|
360 |
<th>XPath:</th>
|
361 |
-
<td><div><input type="text" name="http_test_xpath" value="" placeholder="xpath-like query" /></div>
|
362 |
<div><p>Leave blank to test HTTP, fill in to test a query.</p></div>
|
363 |
</td>
|
364 |
</tr>
|
@@ -415,8 +438,37 @@ function clone_http_test_args_keyvalue_prototype () {
|
|
415 |
case 'wp_remote_request' :
|
416 |
$out = wp_remote_request($url, $args);
|
417 |
break;
|
418 |
-
case '
|
419 |
-
$out = new
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
420 |
break;
|
421 |
endswitch;
|
422 |
|
1 |
<?php
|
2 |
require_once(dirname(__FILE__) . '/admin-ui.php');
|
3 |
+
require_once(dirname(__FILE__) . '/magpiemocklink.class.php');
|
4 |
|
5 |
class FeedWordPressDiagnosticsPage extends FeedWordPressAdminPage {
|
6 |
public function __construct() {
|
42 |
$boxes_by_methods = array(
|
43 |
'info_box' => __('Diagnostic Information'),
|
44 |
'diagnostics_box' => __('Display Diagnostics'),
|
45 |
+
'updates_box' => __('Diagnostic Messages'),
|
46 |
'tests_box' => __('Diagnostic Tests'),
|
47 |
);
|
48 |
|
136 |
<th scope="row">Hosting Environment:</th>
|
137 |
<td><ul style="margin-top: 0; padding-top: 0;">
|
138 |
<li><em>WordPress:</em> version <?php print $wp_version; ?></li>
|
139 |
+
<li><em>SimplePie:</em> version <?php print SIMPLEPIE_VERSION; ?></li>
|
140 |
<?php if (function_exists('phpversion')) : ?>
|
141 |
<li><em>PHP:</em> version <?php print phpversion(); ?></li>
|
142 |
<?php endif; ?>
|
265 |
'Update Diagnostics' => array(
|
266 |
'update_schedule:check' => 'whenever a FeedWordPress checks in on the update schedule',
|
267 |
'updated_feeds' => 'as each feed is checked for updates',
|
|
|
|
|
|
|
268 |
'syndicated_posts' => 'as each syndicated post is added to the database',
|
269 |
'feed_items' => 'as each syndicated item is considered on the feed',
|
270 |
'memory_usage' => 'indicating how much memory was used',
|
271 |
),
|
272 |
+
'Feed Retrieval' => array(
|
273 |
+
'updated_feeds:errors:persistent' => 'when attempts to update a feed have resulted in errors</label> <label>for at least <input type="number" min="1" max="360" step="1" name="diagnostics_persistent_error_hours" value="'.$hours.'" /> hours',
|
274 |
+
'updated_feeds:errors' => 'any time FeedWordPress encounters any errors while checking a feed for updates',
|
275 |
+
'updated_feeds:http' => "displaying the raw HTTP data passed to and from the feed being checked for updates",
|
276 |
+
),
|
277 |
'Syndicated Post Details' => array(
|
278 |
'feed_items:freshness' => 'as FeedWordPress decides whether to treat an item as a new post, an update, or a duplicate of an existing post',
|
279 |
'feed_items:rejected' => 'when FeedWordPress rejects a post without syndicating it',
|
280 |
'syndicated_posts:categories' => 'as categories, tags, and other terms are added on the post',
|
281 |
'syndicated_posts:meta_data' => 'as syndication meta-data is added on the post',
|
282 |
+
'syndicated_posts:do_pings' => 'when FeedWordPress holds or releases the pings WordPress sends out when new posts are created',
|
283 |
),
|
284 |
'Advanced Diagnostics' => array(
|
285 |
'feed_items:freshness:reasons' => 'explaining the reason that a post was treated as an update to an existing post',
|
323 |
} /* FeedWordPressDiagnosticsPage::updates_box () */
|
324 |
|
325 |
static function tests_box ($page, $box = NULL) {
|
326 |
+
$url = MyPHP::request('http_test_url');
|
327 |
+
$method = MyPHP::request('http_test_method');
|
328 |
+
$xpath = MyPHP::request('http_test_xpath');
|
329 |
+
|
330 |
+
$aMethods = array(
|
331 |
+
'wp_remote_request',
|
332 |
+
'FeedWordPie_File',
|
333 |
+
'FeedWordPress::fetch',
|
334 |
+
);
|
335 |
?>
|
336 |
<script type="text/javascript">
|
337 |
function clone_http_test_args_keyvalue_prototype () {
|
348 |
<table class="edit-form">
|
349 |
<tr>
|
350 |
<th scope="row">HTTP:</th>
|
351 |
+
<td><div><input type="url" name="http_test_url" value="<?php print esc_attr($url);?>" placeholder="http://www.example.com/" size="127" style="width: 80%; max-width: 80.0em;" />
|
352 |
<input type="submit" name="feedwordpress_diagnostics_do[http_test]" value="Test »" /></div>
|
353 |
<div><select name="http_test_method" size="1">
|
354 |
+
<?php foreach ($aMethods as $sMethod) :?>
|
355 |
+
<option value="<?php
|
356 |
+
print esc_attr($sMethod);
|
357 |
+
?>"<?php
|
358 |
+
if ($method==$sMethod) :
|
359 |
+
print ' selected="selected"';
|
360 |
+
endif;
|
361 |
+
?>><?php
|
362 |
+
print $sMethod;
|
363 |
+
?></option>
|
364 |
+
<?php endforeach; ?>
|
365 |
</select></div>
|
366 |
<table>
|
367 |
<tr>
|
381 |
|
382 |
<tr>
|
383 |
<th>XPath:</th>
|
384 |
+
<td><div><input type="text" name="http_test_xpath" value="<?php print esc_attr($xpath); ?>" placeholder="xpath-like query" /></div>
|
385 |
<div><p>Leave blank to test HTTP, fill in to test a query.</p></div>
|
386 |
</td>
|
387 |
</tr>
|
438 |
case 'wp_remote_request' :
|
439 |
$out = wp_remote_request($url, $args);
|
440 |
break;
|
441 |
+
case 'FeedWordPie_File' :
|
442 |
+
$out = new FeedWordPie_File($url);
|
443 |
+
break;
|
444 |
+
case 'FeedWordPress::fetch' :
|
445 |
+
$out = FeedWordPress::fetch($url);
|
446 |
+
|
447 |
+
if (isset($post['http_test_xpath'])) :
|
448 |
+
if (strlen($post['http_test_xpath']) > 0) :
|
449 |
+
|
450 |
+
$xpath = $post['http_test_xpath'];
|
451 |
+
|
452 |
+
if ( !is_wp_error($out) ) :
|
453 |
+
$expr = new FeedWordPressParsedPostMeta($xpath);
|
454 |
+
|
455 |
+
$feed = new MagpieMockLink( $out, $url );
|
456 |
+
$posts = $feed->live_posts();
|
457 |
+
|
458 |
+
$post = new SyndicatedPost($posts[0], $feed);
|
459 |
+
$meta = $expr->do_substitutions($post);
|
460 |
+
|
461 |
+
$out = array(
|
462 |
+
"post_title" => $post->entry->get_title(),
|
463 |
+
"post_link" => $post->permalink(),
|
464 |
+
"guid" => $post->guid(),
|
465 |
+
"expression" => $xpath,
|
466 |
+
"results" => $meta,
|
467 |
+
"pie" => $out,
|
468 |
+
);
|
469 |
+
endif;
|
470 |
+
endif;
|
471 |
+
endif;
|
472 |
break;
|
473 |
endswitch;
|
474 |
|
@@ -1,4 +1,5 @@
|
|
1 |
<?php
|
|
|
2 |
class FeedWordPie_Item extends SimplePie_Item {
|
3 |
|
4 |
function get_id ($hash = false) {
|
1 |
<?php
|
2 |
+
|
3 |
class FeedWordPie_Item extends SimplePie_Item {
|
4 |
|
5 |
function get_id ($hash = false) {
|
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
class
|
3 |
function reset_parser (&$xml) {
|
4 |
// reset members
|
5 |
$this->namespace = array('');
|
@@ -67,7 +67,7 @@ class FeedWordPress_Parser extends SimplePie_Parser {
|
|
67 |
|
68 |
if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
|
69 |
{
|
70 |
-
$declaration =
|
71 |
if ($declaration->parse())
|
72 |
{
|
73 |
$data = substr($data, $pos + 2);
|
@@ -100,44 +100,21 @@ class FeedWordPress_Parser extends SimplePie_Parser {
|
|
100 |
xml_set_object($xml, $this);
|
101 |
xml_set_character_data_handler($xml, 'cdata');
|
102 |
xml_set_element_handler($xml, 'tag_open', 'tag_close');
|
103 |
-
xml_set_start_namespace_decl_handler($xml, 'start_xmlns');
|
104 |
-
|
105 |
-
// Parse!
|
106 |
-
$parseResults = xml_parse($xml, $data, true);
|
107 |
-
|
108 |
-
$endOfJunk = strpos($data, '<?xml');
|
109 |
-
if (!$parseResults and $endOfJunk > 0) :
|
110 |
-
// There is some junk before the feed prolog. Try to get rid of it.
|
111 |
-
$data = substr($data, $endOfJunk);
|
112 |
-
$data = trim($data);
|
113 |
-
$this->reset_parser($xml);
|
114 |
|
115 |
-
|
116 |
-
|
|
|
|
|
117 |
|
118 |
-
$badEntity = (xml_get_error_code($xml) == 26);
|
119 |
-
if (!$parseResults and $badEntity) :
|
120 |
-
// There was an entity that libxml couldn't understand.
|
121 |
-
// Chances are, it was a stray HTML entity. So let's try
|
122 |
-
// converting all the named HTML entities to numeric XML
|
123 |
-
// entities and starting over.
|
124 |
-
$data = $this->html_convert_entities($data);
|
125 |
-
$this->reset_parser($xml);
|
126 |
-
|
127 |
-
$parseResults = xml_parse($xml, $data, true);
|
128 |
-
endif;
|
129 |
-
|
130 |
if (!$parseResults) {
|
131 |
$this->error_code = xml_get_error_code($xml);
|
132 |
$this->error_string = xml_error_string($this->error_code);
|
133 |
$return = false;
|
134 |
}
|
135 |
-
|
136 |
$this->current_line = xml_get_current_line_number($xml);
|
137 |
$this->current_column = xml_get_current_column_number($xml);
|
138 |
$this->current_byte = xml_get_current_byte_index($xml);
|
139 |
xml_parser_free($xml);
|
140 |
-
|
141 |
return $return;
|
142 |
}
|
143 |
else
|
@@ -153,7 +130,7 @@ class FeedWordPress_Parser extends SimplePie_Parser {
|
|
153 |
case constant('XMLReader::END_ELEMENT'):
|
154 |
if ($xml->namespaceURI !== '')
|
155 |
{
|
156 |
-
$tagName =
|
157 |
}
|
158 |
else
|
159 |
{
|
@@ -165,7 +142,7 @@ class FeedWordPress_Parser extends SimplePie_Parser {
|
|
165 |
$empty = $xml->isEmptyElement;
|
166 |
if ($xml->namespaceURI !== '')
|
167 |
{
|
168 |
-
$tagName =
|
169 |
}
|
170 |
else
|
171 |
{
|
@@ -176,7 +153,7 @@ class FeedWordPress_Parser extends SimplePie_Parser {
|
|
176 |
{
|
177 |
if ($xml->namespaceURI !== '')
|
178 |
{
|
179 |
-
$attrName =
|
180 |
}
|
181 |
else
|
182 |
{
|
@@ -184,14 +161,8 @@ class FeedWordPress_Parser extends SimplePie_Parser {
|
|
184 |
}
|
185 |
$attributes[$attrName] = $xml->value;
|
186 |
}
|
187 |
-
|
188 |
-
|
189 |
-
list($ns, $local) = $this->split_ns($attr);
|
190 |
-
if ($ns=='http://www.w3.org/2000/xmlns/') :
|
191 |
-
if ('xmlns' == $local) : $local = false; endif;
|
192 |
-
$this->start_xmlns(null, $local, $value);
|
193 |
-
endif;
|
194 |
-
endforeach;
|
195 |
|
196 |
$this->tag_open(null, $tagName, $attributes);
|
197 |
if ($empty)
|
@@ -219,7 +190,52 @@ class FeedWordPress_Parser extends SimplePie_Parser {
|
|
219 |
return true;
|
220 |
}
|
221 |
}
|
222 |
-
} /*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
|
224 |
var $xmlns_stack = array();
|
225 |
var $xmlns_current = array();
|
@@ -247,8 +263,9 @@ class FeedWordPress_Parser extends SimplePie_Parser {
|
|
247 |
if ($this->current_xhtml_construct < 0) :
|
248 |
$this->xmlns_current[$prefix] = $uri;
|
249 |
endif;
|
|
|
250 |
return true;
|
251 |
-
} /*
|
252 |
|
253 |
/* html_convert_entities($string) -- convert named HTML entities to
|
254 |
* XML-compatible numeric entities. Adapted from code by @inanimatt:
|
@@ -522,8 +539,8 @@ class FeedWordPress_Parser extends SimplePie_Parser {
|
|
522 |
);
|
523 |
// Entity not found? Destroy it.
|
524 |
return isset($table[$matches[1]]) ? $table[$matches[1]] : '';
|
525 |
-
} /*
|
526 |
|
527 |
-
} /* class
|
528 |
|
529 |
|
1 |
<?php
|
2 |
+
class FeedWordPie_Parser extends SimplePie_Parser {
|
3 |
function reset_parser (&$xml) {
|
4 |
// reset members
|
5 |
$this->namespace = array('');
|
67 |
|
68 |
if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
|
69 |
{
|
70 |
+
$declaration = $this->registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5)));
|
71 |
if ($declaration->parse())
|
72 |
{
|
73 |
$data = substr($data, $pos + 2);
|
100 |
xml_set_object($xml, $this);
|
101 |
xml_set_character_data_handler($xml, 'cdata');
|
102 |
xml_set_element_handler($xml, 'tag_open', 'tag_close');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
|
104 |
+
// Parse!
|
105 |
+
$results = $this->do_xml_parse_attempt($xml, $data);
|
106 |
+
$parseResults = $results[0];
|
107 |
+
$data = $results[1];
|
108 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
if (!$parseResults) {
|
110 |
$this->error_code = xml_get_error_code($xml);
|
111 |
$this->error_string = xml_error_string($this->error_code);
|
112 |
$return = false;
|
113 |
}
|
|
|
114 |
$this->current_line = xml_get_current_line_number($xml);
|
115 |
$this->current_column = xml_get_current_column_number($xml);
|
116 |
$this->current_byte = xml_get_current_byte_index($xml);
|
117 |
xml_parser_free($xml);
|
|
|
118 |
return $return;
|
119 |
}
|
120 |
else
|
130 |
case constant('XMLReader::END_ELEMENT'):
|
131 |
if ($xml->namespaceURI !== '')
|
132 |
{
|
133 |
+
$tagName = $xml->namespaceURI . $this->separator . $xml->localName;
|
134 |
}
|
135 |
else
|
136 |
{
|
142 |
$empty = $xml->isEmptyElement;
|
143 |
if ($xml->namespaceURI !== '')
|
144 |
{
|
145 |
+
$tagName = $xml->namespaceURI . $this->separator . $xml->localName;
|
146 |
}
|
147 |
else
|
148 |
{
|
153 |
{
|
154 |
if ($xml->namespaceURI !== '')
|
155 |
{
|
156 |
+
$attrName = $xml->namespaceURI . $this->separator . $xml->localName;
|
157 |
}
|
158 |
else
|
159 |
{
|
161 |
}
|
162 |
$attributes[$attrName] = $xml->value;
|
163 |
}
|
164 |
+
|
165 |
+
$this->do_scan_attributes_namespaces($attributes);
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
|
167 |
$this->tag_open(null, $tagName, $attributes);
|
168 |
if ($empty)
|
190 |
return true;
|
191 |
}
|
192 |
}
|
193 |
+
} /* FeedWordPie_Parser::parse() */
|
194 |
+
|
195 |
+
public function do_xml_parse_attempt ($xml, $data) {
|
196 |
+
xml_set_start_namespace_decl_handler($xml, 'start_xmlns');
|
197 |
+
|
198 |
+
// Parse!
|
199 |
+
$parseResults = xml_parse($xml, $data, true);
|
200 |
+
$endOfJunk = strpos($data, '<?xml');
|
201 |
+
if (!$parseResults and $endOfJunk > 0) :
|
202 |
+
// There is some junk before the feed prolog. Try to get rid of it.
|
203 |
+
$data = substr($data, $endOfJunk);
|
204 |
+
$data = trim($data);
|
205 |
+
$this->reset_parser($xml);
|
206 |
+
|
207 |
+
$parseResults = xml_parse($xml, $data, true);
|
208 |
+
endif;
|
209 |
+
|
210 |
+
$badEntity = (xml_get_error_code($xml) == 26);
|
211 |
+
if (!$parseResults and $badEntity) :
|
212 |
+
// There was an entity that libxml couldn't understand.
|
213 |
+
// Chances are, it was a stray HTML entity. So let's try
|
214 |
+
// converting all the named HTML entities to numeric XML
|
215 |
+
// entities and starting over.
|
216 |
+
$data = $this->html_convert_entities($data);
|
217 |
+
$this->reset_parser($xml);
|
218 |
+
|
219 |
+
$parseResults = xml_parse($xml, $data, true);
|
220 |
+
endif;
|
221 |
+
|
222 |
+
$result = array(
|
223 |
+
$parseResults,
|
224 |
+
$data
|
225 |
+
);
|
226 |
+
return $result;
|
227 |
+
|
228 |
+
}
|
229 |
+
|
230 |
+
public function do_scan_attributes_namespaces ($attributes) {
|
231 |
+
foreach ($attributes as $attr => $value) :
|
232 |
+
list($ns, $local) = $this->split_ns($attr);
|
233 |
+
if ($ns=='http://www.w3.org/2000/xmlns/') :
|
234 |
+
if ('xmlns' == $local) : $local = false; endif;
|
235 |
+
$this->start_xmlns(null, $local, $value);
|
236 |
+
endif;
|
237 |
+
endforeach;
|
238 |
+
}
|
239 |
|
240 |
var $xmlns_stack = array();
|
241 |
var $xmlns_current = array();
|
263 |
if ($this->current_xhtml_construct < 0) :
|
264 |
$this->xmlns_current[$prefix] = $uri;
|
265 |
endif;
|
266 |
+
|
267 |
return true;
|
268 |
+
} /* FeedWordPie_Parser::start_xmlns() */
|
269 |
|
270 |
/* html_convert_entities($string) -- convert named HTML entities to
|
271 |
* XML-compatible numeric entities. Adapted from code by @inanimatt:
|
539 |
);
|
540 |
// Entity not found? Destroy it.
|
541 |
return isset($table[$matches[1]]) ? $table[$matches[1]] : '';
|
542 |
+
} /* FeedWordPie_Parser::convert_entity() */
|
543 |
|
544 |
+
} /* class FeedWordPie_Parser */
|
545 |
|
546 |
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class FeedWordPie_Item extends SimplePie_Item {
|
4 |
+
|
5 |
+
function get_id ($hash = false, $fn = 'md5') {
|
6 |
+
return apply_filters('feedwordpie_item_get_id', parent::get_id($hash, $fn), $hash, $this, $fn);
|
7 |
+
}
|
8 |
+
|
9 |
+
function get_title () {
|
10 |
+
return apply_filters('feedwordpie_item_get_title', parent::get_title(), $this);
|
11 |
+
}
|
12 |
+
|
13 |
+
function get_description ($description_only = false) {
|
14 |
+
return apply_filters('feedwordpie_item_get_description', parent::get_description($description_only), $description_only, $this);
|
15 |
+
}
|
16 |
+
|
17 |
+
function get_content ($content_only = false) {
|
18 |
+
return apply_filters('feedwordpie_item_get_content', parent::get_content($content_only), $content_only, $this);
|
19 |
+
}
|
20 |
+
|
21 |
+
function get_categories () {
|
22 |
+
return apply_filters('feedwordpie_item_get_categories', parent::get_categories(), $this);
|
23 |
+
}
|
24 |
+
|
25 |
+
function get_authors () {
|
26 |
+
return apply_filters('feedwordpie_item_get_authors', parent::get_authors(), $this);
|
27 |
+
}
|
28 |
+
function get_contributors () {
|
29 |
+
return apply_filters('feedwordpie_item_get_contributors', parent::get_contributors(), $this);
|
30 |
+
}
|
31 |
+
function get_copyright () {
|
32 |
+
return apply_filters('feedwordpie_item_get_copyright', parent::get_copyright(), $this);
|
33 |
+
}
|
34 |
+
function get_date ($date_format = 'j F Y, g:i a') {
|
35 |
+
return apply_filters('feedwordpie_item_get_date', parent::get_date($date_format), $date_format, $this);
|
36 |
+
}
|
37 |
+
function get_local_date ($date_format = '%c') {
|
38 |
+
return apply_filters('feedwordpie_item_get_local_date', parent::get_local_date($date_format), $date_format, $this);
|
39 |
+
}
|
40 |
+
function get_links ($rel = 'alternate') {
|
41 |
+
return apply_filters('feedwordpie_item_get_links', parent::get_links($rel), $rel, $this);
|
42 |
+
}
|
43 |
+
function get_enclosures () {
|
44 |
+
return apply_filters('feedwordpie_item_get_enclosures', parent::get_enclosures(), $this);
|
45 |
+
}
|
46 |
+
function get_latitude () {
|
47 |
+
return apply_filters('feedwordpie_item_get_lattitude', parent::get_lattitude(), $this);
|
48 |
+
}
|
49 |
+
function get_longitude () {
|
50 |
+
return apply_filters('feedwordpie_item_get_longitude', parent::get_longtidue(), $this);
|
51 |
+
}
|
52 |
+
function get_source () {
|
53 |
+
return apply_filters('feedwordpie_item_get_source', parent::get_source(), $this);
|
54 |
+
}
|
55 |
+
} /* class FeedWordPie_Item */
|
56 |
+
|
@@ -0,0 +1,562 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class FeedWordPie_Parser extends SimplePie_Parser {
|
3 |
+
function reset_parser (&$xml) {
|
4 |
+
// reset members
|
5 |
+
$this->namespace = array('');
|
6 |
+
$this->element = array('');
|
7 |
+
$this->xml_base = array('');
|
8 |
+
$this->xml_base_explicit = array(false);
|
9 |
+
$this->xml_lang = array('');
|
10 |
+
$this->data = array();
|
11 |
+
$this->datas = array(array());
|
12 |
+
$this->current_xhtml_construct = -1;
|
13 |
+
$this->xmlns_stack = array();
|
14 |
+
$this->xmlns_current = array();
|
15 |
+
|
16 |
+
// reset libxml parser
|
17 |
+
xml_parser_free($xml);
|
18 |
+
|
19 |
+
$xml = xml_parser_create_ns($this->encoding, $this->separator);
|
20 |
+
xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
|
21 |
+
xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
|
22 |
+
xml_set_object($xml, $this);
|
23 |
+
xml_set_character_data_handler($xml, 'cdata');
|
24 |
+
xml_set_element_handler($xml, 'tag_open', 'tag_close');
|
25 |
+
xml_set_start_namespace_decl_handler($xml, 'start_xmlns');
|
26 |
+
}
|
27 |
+
|
28 |
+
public function parse (&$data, $encoding, $url = '')
|
29 |
+
{
|
30 |
+
$data = apply_filters('feedwordpress_parser_parse', $data, $encoding, $this, $url);
|
31 |
+
|
32 |
+
if (class_exists('DOMXpath') && function_exists('Mf2\parse')) {
|
33 |
+
$doc = new DOMDocument();
|
34 |
+
@$doc->loadHTML($data);
|
35 |
+
$xpath = new DOMXpath($doc);
|
36 |
+
// Check for both h-feed and h-entry, as both a feed with no entries
|
37 |
+
// and a list of entries without an h-feed wrapper are both valid.
|
38 |
+
$query = '//*[contains(concat(" ", @class, " "), " h-feed ") or '.
|
39 |
+
'contains(concat(" ", @class, " "), " h-entry ")]';
|
40 |
+
$result = $xpath->query($query);
|
41 |
+
if ($result->length !== 0) {
|
42 |
+
return $this->parse_microformats($data, $url);
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
// Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
|
47 |
+
if (strtoupper($encoding) === 'US-ASCII')
|
48 |
+
{
|
49 |
+
$this->encoding = 'UTF-8';
|
50 |
+
}
|
51 |
+
else
|
52 |
+
{
|
53 |
+
$this->encoding = $encoding;
|
54 |
+
}
|
55 |
+
|
56 |
+
// Strip BOM:
|
57 |
+
// UTF-32 Big Endian BOM
|
58 |
+
if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
|
59 |
+
{
|
60 |
+
$data = substr($data, 4);
|
61 |
+
}
|
62 |
+
// UTF-32 Little Endian BOM
|
63 |
+
elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
|
64 |
+
{
|
65 |
+
$data = substr($data, 4);
|
66 |
+
}
|
67 |
+
// UTF-16 Big Endian BOM
|
68 |
+
elseif (substr($data, 0, 2) === "\xFE\xFF")
|
69 |
+
{
|
70 |
+
$data = substr($data, 2);
|
71 |
+
}
|
72 |
+
// UTF-16 Little Endian BOM
|
73 |
+
elseif (substr($data, 0, 2) === "\xFF\xFE")
|
74 |
+
{
|
75 |
+
$data = substr($data, 2);
|
76 |
+
}
|
77 |
+
// UTF-8 BOM
|
78 |
+
elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
|
79 |
+
{
|
80 |
+
$data = substr($data, 3);
|
81 |
+
}
|
82 |
+
|
83 |
+
if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
|
84 |
+
{
|
85 |
+
$declaration = $this->registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5)));
|
86 |
+
if ($declaration->parse())
|
87 |
+
{
|
88 |
+
$data = substr($data, $pos + 2);
|
89 |
+
$data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' ."\n". $this->declare_html_entities() . $data;
|
90 |
+
}
|
91 |
+
else
|
92 |
+
{
|
93 |
+
$this->error_string = 'SimplePie bug! Please report this!';
|
94 |
+
return false;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
$return = true;
|
99 |
+
|
100 |
+
static $xml_is_sane = null;
|
101 |
+
if ($xml_is_sane === null)
|
102 |
+
{
|
103 |
+
$parser_check = xml_parser_create();
|
104 |
+
xml_parse_into_struct($parser_check, '<foo>&</foo>', $values);
|
105 |
+
xml_parser_free($parser_check);
|
106 |
+
$xml_is_sane = isset($values[0]['value']);
|
107 |
+
}
|
108 |
+
|
109 |
+
// Create the parser
|
110 |
+
if ($xml_is_sane)
|
111 |
+
{
|
112 |
+
$xml = xml_parser_create_ns($this->encoding, $this->separator);
|
113 |
+
xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
|
114 |
+
xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
|
115 |
+
xml_set_object($xml, $this);
|
116 |
+
xml_set_character_data_handler($xml, 'cdata');
|
117 |
+
xml_set_element_handler($xml, 'tag_open', 'tag_close');
|
118 |
+
|
119 |
+
// Parse!
|
120 |
+
$results = $this->do_xml_parse_attempt($xml, $data);
|
121 |
+
$parseResults = $results[0];
|
122 |
+
$data = $results[1];
|
123 |
+
|
124 |
+
if (!$parseResults) {
|
125 |
+
$this->error_code = xml_get_error_code($xml);
|
126 |
+
$this->error_string = xml_error_string($this->error_code);
|
127 |
+
$return = false;
|
128 |
+
}
|
129 |
+
$this->current_line = xml_get_current_line_number($xml);
|
130 |
+
$this->current_column = xml_get_current_column_number($xml);
|
131 |
+
$this->current_byte = xml_get_current_byte_index($xml);
|
132 |
+
xml_parser_free($xml);
|
133 |
+
return $return;
|
134 |
+
}
|
135 |
+
|
136 |
+
libxml_clear_errors();
|
137 |
+
$xml = new XMLReader();
|
138 |
+
$xml->xml($data);
|
139 |
+
while (@$xml->read())
|
140 |
+
{
|
141 |
+
switch ($xml->nodeType)
|
142 |
+
{
|
143 |
+
|
144 |
+
case constant('XMLReader::END_ELEMENT'):
|
145 |
+
if ($xml->namespaceURI !== '')
|
146 |
+
{
|
147 |
+
$tagName = $xml->namespaceURI . $this->separator . $xml->localName;
|
148 |
+
}
|
149 |
+
else
|
150 |
+
{
|
151 |
+
$tagName = $xml->localName;
|
152 |
+
}
|
153 |
+
$this->tag_close(null, $tagName);
|
154 |
+
break;
|
155 |
+
case constant('XMLReader::ELEMENT'):
|
156 |
+
$empty = $xml->isEmptyElement;
|
157 |
+
if ($xml->namespaceURI !== '')
|
158 |
+
{
|
159 |
+
$tagName = $xml->namespaceURI . $this->separator . $xml->localName;
|
160 |
+
}
|
161 |
+
else
|
162 |
+
{
|
163 |
+
$tagName = $xml->localName;
|
164 |
+
}
|
165 |
+
$attributes = array();
|
166 |
+
while ($xml->moveToNextAttribute())
|
167 |
+
{
|
168 |
+
if ($xml->namespaceURI !== '')
|
169 |
+
{
|
170 |
+
$attrName = $xml->namespaceURI . $this->separator . $xml->localName;
|
171 |
+
}
|
172 |
+
else
|
173 |
+
{
|
174 |
+
$attrName = $xml->localName;
|
175 |
+
}
|
176 |
+
$attributes[$attrName] = $xml->value;
|
177 |
+
}
|
178 |
+
|
179 |
+
$this->do_scan_attributes_namespaces($attributes);
|
180 |
+
|
181 |
+
$this->tag_open(null, $tagName, $attributes);
|
182 |
+
if ($empty)
|
183 |
+
{
|
184 |
+
$this->tag_close(null, $tagName);
|
185 |
+
}
|
186 |
+
break;
|
187 |
+
case constant('XMLReader::TEXT'):
|
188 |
+
|
189 |
+
case constant('XMLReader::CDATA'):
|
190 |
+
$this->cdata(null, $xml->value);
|
191 |
+
break;
|
192 |
+
}
|
193 |
+
}
|
194 |
+
if ($error = libxml_get_last_error())
|
195 |
+
{
|
196 |
+
$this->error_code = $error->code;
|
197 |
+
$this->error_string = $error->message;
|
198 |
+
$this->current_line = $error->line;
|
199 |
+
$this->current_column = $error->column;
|
200 |
+
return false;
|
201 |
+
}
|
202 |
+
|
203 |
+
return true;
|
204 |
+
} /* FeedWordPie_Parser::parse() */
|
205 |
+
|
206 |
+
public function do_xml_parse_attempt ($xml, $data) {
|
207 |
+
xml_set_start_namespace_decl_handler($xml, 'start_xmlns');
|
208 |
+
|
209 |
+
// Parse!
|
210 |
+
$parseResults = xml_parse($xml, $data, true);
|
211 |
+
$endOfJunk = strpos($data, '<?xml');
|
212 |
+
if (!$parseResults and $endOfJunk > 0) :
|
213 |
+
// There is some junk before the feed prolog. Try to get rid of it.
|
214 |
+
$data = substr($data, $endOfJunk);
|
215 |
+
$data = trim($data);
|
216 |
+
$this->reset_parser($xml);
|
217 |
+
|
218 |
+
$parseResults = xml_parse($xml, $data, true);
|
219 |
+
endif;
|
220 |
+
|
221 |
+
$badEntity = (xml_get_error_code($xml) == 26);
|
222 |
+
if (!$parseResults and $badEntity) :
|
223 |
+
// There was an entity that libxml couldn't understand.
|
224 |
+
// Chances are, it was a stray HTML entity. So let's try
|
225 |
+
// converting all the named HTML entities to numeric XML
|
226 |
+
// entities and starting over.
|
227 |
+
$data = $this->html_convert_entities($data);
|
228 |
+
$this->reset_parser($xml);
|
229 |
+
|
230 |
+
$parseResults = xml_parse($xml, $data, true);
|
231 |
+
endif;
|
232 |
+
|
233 |
+
$result = array(
|
234 |
+
$parseResults,
|
235 |
+
$data
|
236 |
+
);
|
237 |
+
return $result;
|
238 |
+
|
239 |
+
}
|
240 |
+
|
241 |
+
public function do_scan_attributes_namespaces ($attributes) {
|
242 |
+
foreach ($attributes as $attr => $value) :
|
243 |
+
list($ns, $local) = $this->split_ns($attr);
|
244 |
+
if ($ns=='http://www.w3.org/2000/xmlns/') :
|
245 |
+
if ('xmlns' == $local) : $local = false; endif;
|
246 |
+
$this->start_xmlns(null, $local, $value);
|
247 |
+
endif;
|
248 |
+
endforeach;
|
249 |
+
}
|
250 |
+
|
251 |
+
var $xmlns_stack = array();
|
252 |
+
var $xmlns_current = array();
|
253 |
+
function tag_open ($parser, $tag, $attributes) {
|
254 |
+
$ret = parent::tag_open($parser, $tag, $attributes);
|
255 |
+
if ($this->current_xhtml_construct < 0) :
|
256 |
+
$this->data['xmlns'] = $this->xmlns_current;
|
257 |
+
$this->xmlns_stack[] = $this->xmlns_current;
|
258 |
+
endif;
|
259 |
+
return $ret;
|
260 |
+
}
|
261 |
+
|
262 |
+
function tag_close($parser, $tag) {
|
263 |
+
if ($this->current_xhtml_construct < 0) :
|
264 |
+
$this->xmlns_current = array_pop($this->xmlns_stack);
|
265 |
+
endif;
|
266 |
+
$ret = parent::tag_close($parser, $tag);
|
267 |
+
return $ret;
|
268 |
+
}
|
269 |
+
|
270 |
+
function start_xmlns ($parser, $prefix, $uri) {
|
271 |
+
if (!$prefix) :
|
272 |
+
$prefix = '';
|
273 |
+
endif;
|
274 |
+
if ($this->current_xhtml_construct < 0) :
|
275 |
+
$this->xmlns_current[$prefix] = $uri;
|
276 |
+
endif;
|
277 |
+
|
278 |
+
return true;
|
279 |
+
} /* FeedWordPie_Parser::start_xmlns() */
|
280 |
+
|
281 |
+
/* html_convert_entities($string) -- convert named HTML entities to
|
282 |
+
* XML-compatible numeric entities. Adapted from code by @inanimatt:
|
283 |
+
* https://gist.github.com/inanimatt/879249
|
284 |
+
*/
|
285 |
+
public function html_convert_entities($string) {
|
286 |
+
return preg_replace_callback('/&([a-zA-Z][a-zA-Z0-9]+);/S',
|
287 |
+
array($this, 'convert_entity'), $string);
|
288 |
+
}
|
289 |
+
|
290 |
+
/* Swap HTML named entity with its numeric equivalent. If the entity
|
291 |
+
* isn't in the lookup table, this function returns a blank, which
|
292 |
+
* destroys the character in the output - this is probably the
|
293 |
+
* desired behaviour when producing XML. Adapted from code by @inanimatt:
|
294 |
+
* https://gist.github.com/inanimatt/879249
|
295 |
+
*/
|
296 |
+
public function convert_entity($matches) {
|
297 |
+
static $table = array(
|
298 |
+
'quot' => '"',
|
299 |
+
'amp' => '&',
|
300 |
+
'lt' => '<',
|
301 |
+
'gt' => '>',
|
302 |
+
'OElig' => 'Œ',
|
303 |
+
'oelig' => 'œ',
|
304 |
+
'Scaron' => 'Š',
|
305 |
+
'scaron' => 'š',
|
306 |
+
'Yuml' => 'Ÿ',
|
307 |
+
'circ' => 'ˆ',
|
308 |
+
'tilde' => '˜',
|
309 |
+
'ensp' => ' ',
|
310 |
+
'emsp' => ' ',
|
311 |
+
'thinsp' => ' ',
|
312 |
+
'zwnj' => '‌',
|
313 |
+
'zwj' => '‍',
|
314 |
+
'lrm' => '‎',
|
315 |
+
'rlm' => '‏',
|
316 |
+
'ndash' => '–',
|
317 |
+
'mdash' => '—',
|
318 |
+
'lsquo' => '‘',
|
319 |
+
'rsquo' => '’',
|
320 |
+
'sbquo' => '‚',
|
321 |
+
'ldquo' => '“',
|
322 |
+
'rdquo' => '”',
|
323 |
+
'bdquo' => '„',
|
324 |
+
'dagger' => '†',
|
325 |
+
'Dagger' => '‡',
|
326 |
+
'permil' => '‰',
|
327 |
+
'lsaquo' => '‹',
|
328 |
+
'rsaquo' => '›',
|
329 |
+
'euro' => '€',
|
330 |
+
'fnof' => 'ƒ',
|
331 |
+
'Alpha' => 'Α',
|
332 |
+
'Beta' => 'Β',
|
333 |
+
'Gamma' => 'Γ',
|
334 |
+
'Delta' => 'Δ',
|
335 |
+
'Epsilon' => 'Ε',
|
336 |
+
'Zeta' => 'Ζ',
|
337 |
+
'Eta' => 'Η',
|
338 |
+
'Theta' => 'Θ',
|
339 |
+
'Iota' => 'Ι',
|
340 |
+
'Kappa' => 'Κ',
|
341 |
+
'Lambda' => 'Λ',
|
342 |
+
'Mu' => 'Μ',
|
343 |
+
'Nu' => 'Ν',
|
344 |
+
'Xi' => 'Ξ',
|
345 |
+
'Omicron' => 'Ο',
|
346 |
+
'Pi' => 'Π',
|
347 |
+
'Rho' => 'Ρ',
|
348 |
+
'Sigma' => 'Σ',
|
349 |
+
'Tau' => 'Τ',
|
350 |
+
'Upsilon' => 'Υ',
|
351 |
+
'Phi' => 'Φ',
|
352 |
+
'Chi' => 'Χ',
|
353 |
+
'Psi' => 'Ψ',
|
354 |
+
'Omega' => 'Ω',
|
355 |
+
'alpha' => 'α',
|
356 |
+
'beta' => 'β',
|
357 |
+
'gamma' => 'γ',
|
358 |
+
'delta' => 'δ',
|
359 |
+
'epsilon' => 'ε',
|
360 |
+
'zeta' => 'ζ',
|
361 |
+
'eta' => 'η',
|
362 |
+
'theta' => 'θ',
|
363 |
+
'iota' => 'ι',
|
364 |
+
'kappa' => 'κ',
|
365 |
+
'lambda' => 'λ',
|
366 |
+
'mu' => 'μ',
|
367 |
+
'nu' => 'ν',
|
368 |
+
'xi' => 'ξ',
|
369 |
+
'omicron' => 'ο',
|
370 |
+
'pi' => 'π',
|
371 |
+
'rho' => 'ρ',
|
372 |
+
'sigmaf' => 'ς',
|
373 |
+
'sigma' => 'σ',
|
374 |
+
'tau' => 'τ',
|
375 |
+
'upsilon' => 'υ',
|
376 |
+
'phi' => 'φ',
|
377 |
+
'chi' => 'χ',
|
378 |
+
'psi' => 'ψ',
|
379 |
+
'omega' => 'ω',
|
380 |
+
'thetasym' => 'ϑ',
|
381 |
+
'upsih' => 'ϒ',
|
382 |
+
'piv' => 'ϖ',
|
383 |
+
'bull' => '•',
|
384 |
+
'hellip' => '…',
|
385 |
+
'prime' => '′',
|
386 |
+
'Prime' => '″',
|
387 |
+
'oline' => '‾',
|
388 |
+
'frasl' => '⁄',
|
389 |
+
'weierp' => '℘',
|
390 |
+
'image' => 'ℑ',
|
391 |
+
'real' => 'ℜ',
|
392 |
+
'trade' => '™',
|
393 |
+
'alefsym' => 'ℵ',
|
394 |
+
'larr' => '←',
|
395 |
+
'uarr' => '↑',
|
396 |
+
'rarr' => '→',
|
397 |
+
'darr' => '↓',
|
398 |
+
'harr' => '↔',
|
399 |
+
'crarr' => '↵',
|
400 |
+
'lArr' => '⇐',
|
401 |
+
'uArr' => '⇑',
|
402 |
+
'rArr' => '⇒',
|
403 |
+
'dArr' => '⇓',
|
404 |
+
'hArr' => '⇔',
|
405 |
+
'forall' => '∀',
|
406 |
+
'part' => '∂',
|
407 |
+
'exist' => '∃',
|
408 |
+
'empty' => '∅',
|
409 |
+
'nabla' => '∇',
|
410 |
+
'isin' => '∈',
|
411 |
+
'notin' => '∉',
|
412 |
+
'ni' => '∋',
|
413 |
+
'prod' => '∏',
|
414 |
+
'sum' => '∑',
|
415 |
+
'minus' => '−',
|
416 |
+
'lowast' => '∗',
|
417 |
+
'radic' => '√',
|
418 |
+
'prop' => '∝',
|
419 |
+
'infin' => '∞',
|
420 |
+
'ang' => '∠',
|
421 |
+
'and' => '∧',
|
422 |
+
'or' => '∨',
|
423 |
+
'cap' => '∩',
|
424 |
+
'cup' => '∪',
|
425 |
+
'int' => '∫',
|
426 |
+
'there4' => '∴',
|
427 |
+
'sim' => '∼',
|
428 |
+
'cong' => '≅',
|
429 |
+
'asymp' => '≈',
|
430 |
+
'ne' => '≠',
|
431 |
+
'equiv' => '≡',
|
432 |
+
'le' => '≤',
|
433 |
+
'ge' => '≥',
|
434 |
+
'sub' => '⊂',
|
435 |
+
'sup' => '⊃',
|
436 |
+
'nsub' => '⊄',
|
437 |
+
'sube' => '⊆',
|
438 |
+
'supe' => '⊇',
|
439 |
+
'oplus' => '⊕',
|
440 |
+
'otimes' => '⊗',
|
441 |
+
'perp' => '⊥',
|
442 |
+
'sdot' => '⋅',
|
443 |
+
'lceil' => '⌈',
|
444 |
+
'rceil' => '⌉',
|
445 |
+
'lfloor' => '⌊',
|
446 |
+
'rfloor' => '⌋',
|
447 |
+
'lang' => '〈',
|
448 |
+
'rang' => '〉',
|
449 |
+
'loz' => '◊',
|
450 |
+
'spades' => '♠',
|
451 |
+
'clubs' => '♣',
|
452 |
+
'hearts' => '♥',
|
453 |
+
'diams' => '♦',
|
454 |
+
'nbsp' => ' ',
|
455 |
+
'iexcl' => '¡',
|
456 |
+
'cent' => '¢',
|
457 |
+
'pound' => '£',
|
458 |
+
'curren' => '¤',
|
459 |
+
'yen' => '¥',
|
460 |
+
'brvbar' => '¦',
|
461 |
+
'sect' => '§',
|
462 |
+
'uml' => '¨',
|
463 |
+
'copy' => '©',
|
464 |
+
'ordf' => 'ª',
|
465 |
+
'laquo' => '«',
|
466 |
+
'not' => '¬',
|
467 |
+
'shy' => '­',
|
468 |
+
'reg' => '®',
|
469 |
+
'macr' => '¯',
|
470 |
+
'deg' => '°',
|
471 |
+
'plusmn' => '±',
|
472 |
+
'sup2' => '²',
|
473 |
+
'sup3' => '³',
|
474 |
+
'acute' => '´',
|
475 |
+
'micro' => 'µ',
|
476 |
+
'para' => '¶',
|
477 |
+
'middot' => '·',
|
478 |
+
'cedil' => '¸',
|
479 |
+
'sup1' => '¹',
|
480 |
+
'ordm' => 'º',
|
481 |
+
'raquo' => '»',
|
482 |
+
'frac14' => '¼',
|
483 |
+
'frac12' => '½',
|
484 |
+
'frac34' => '¾',
|
485 |
+
'iquest' => '¿',
|
486 |
+
'Agrave' => 'À',
|
487 |
+
'Aacute' => 'Á',
|
488 |
+
'Acirc' => 'Â',
|
489 |
+
'Atilde' => 'Ã',
|
490 |
+
'Auml' => 'Ä',
|
491 |
+
'Aring' => 'Å',
|
492 |
+
'AElig' => 'Æ',
|
493 |
+
'Ccedil' => 'Ç',
|
494 |
+
'Egrave' => 'È',
|
495 |
+
'Eacute' => 'É',
|
496 |
+
'Ecirc' => 'Ê',
|
497 |
+
'Euml' => 'Ë',
|
498 |
+
'Igrave' => 'Ì',
|
499 |
+
'Iacute' => 'Í',
|
500 |
+
'Icirc' => 'Î',
|
501 |
+
'Iuml' => 'Ï',
|
502 |
+
'ETH' => 'Ð',
|
503 |
+
'Ntilde' => 'Ñ',
|
504 |
+
'Ograve' => 'Ò',
|
505 |
+
'Oacute' => 'Ó',
|
506 |
+
'Ocirc' => 'Ô',
|
507 |
+
'Otilde' => 'Õ',
|
508 |
+
'Ouml' => 'Ö',
|
509 |
+
'times' => '×',
|
510 |
+
'Oslash' => 'Ø',
|
511 |
+
'Ugrave' => 'Ù',
|
512 |
+
'Uacute' => 'Ú',
|
513 |
+
'Ucirc' => 'Û',
|
514 |
+
'Uuml' => 'Ü',
|
515 |
+
'Yacute' => 'Ý',
|
516 |
+
'THORN' => 'Þ',
|
517 |
+
'szlig' => 'ß',
|
518 |
+
'agrave' => 'à',
|
519 |
+
'aacute' => 'á',
|
520 |
+
'acirc' => 'â',
|
521 |
+
'atilde' => 'ã',
|
522 |
+
'auml' => 'ä',
|
523 |
+
'aring' => 'å',
|
524 |
+
'aelig' => 'æ',
|
525 |
+
'ccedil' => 'ç',
|
526 |
+
'egrave' => 'è',
|
527 |
+
'eacute' => 'é',
|
528 |
+
'ecirc' => 'ê',
|
529 |
+
'euml' => 'ë',
|
530 |
+
'igrave' => 'ì',
|
531 |
+
'iacute' => 'í',
|
532 |
+
'icirc' => 'î',
|
533 |
+
'iuml' => 'ï',
|
534 |
+
'eth' => 'ð',
|
535 |
+
'ntilde' => 'ñ',
|
536 |
+
'ograve' => 'ò',
|
537 |
+
'oacute' => 'ó',
|
538 |
+
'ocirc' => 'ô',
|
539 |
+
'otilde' => 'õ',
|
540 |
+
'ouml' => 'ö',
|
541 |
+
'divide' => '÷',
|
542 |
+
'oslash' => 'ø',
|
543 |
+
'ugrave' => 'ù',
|
544 |
+
'uacute' => 'ú',
|
545 |
+
'ucirc' => 'û',
|
546 |
+
'uuml' => 'ü',
|
547 |
+
'yacute' => 'ý',
|
548 |
+
'thorn' => 'þ',
|
549 |
+
'yuml' => 'ÿ'
|
550 |
+
);
|
551 |
+
// Entity not found? Destroy it.
|
552 |
+
return isset($table[$matches[1]]) ? $table[$matches[1]] : '';
|
553 |
+
} /* FeedWordPie_Parser::convert_entity() */
|
554 |
+
|
555 |
+
private function declare_html_entities() {
|
556 |
+
// This is required because the RSS specification says that entity-encoded
|
557 |
+
// html is allowed, but the xml specification says they must be declared.
|
558 |
+
return '<!DOCTYPE html [ <!ENTITY nbsp " "> <!ENTITY iexcl "¡"> <!ENTITY cent "¢"> <!ENTITY pound "£"> <!ENTITY curren "¤"> <!ENTITY yen "¥"> <!ENTITY brvbar "¦"> <!ENTITY sect "§"> <!ENTITY uml "¨"> <!ENTITY copy "©"> <!ENTITY ordf "ª"> <!ENTITY laquo "«"> <!ENTITY not "¬"> <!ENTITY shy "­"> <!ENTITY reg "®"> <!ENTITY macr "¯"> <!ENTITY deg "°"> <!ENTITY plusmn "±"> <!ENTITY sup2 "²"> <!ENTITY sup3 "³"> <!ENTITY acute "´"> <!ENTITY micro "µ"> <!ENTITY para "¶"> <!ENTITY middot "·"> <!ENTITY cedil "¸"> <!ENTITY sup1 "¹"> <!ENTITY ordm "º"> <!ENTITY raquo "»"> <!ENTITY frac14 "¼"> <!ENTITY frac12 "½"> <!ENTITY frac34 "¾"> <!ENTITY iquest "¿"> <!ENTITY Agrave "À"> <!ENTITY Aacute "Á"> <!ENTITY Acirc "Â"> <!ENTITY Atilde "Ã"> <!ENTITY Auml "Ä"> <!ENTITY Aring "Å"> <!ENTITY AElig "Æ"> <!ENTITY Ccedil "Ç"> <!ENTITY Egrave "È"> <!ENTITY Eacute "É"> <!ENTITY Ecirc "Ê"> <!ENTITY Euml "Ë"> <!ENTITY Igrave "Ì"> <!ENTITY Iacute "Í"> <!ENTITY Icirc "Î"> <!ENTITY Iuml "Ï"> <!ENTITY ETH "Ð"> <!ENTITY Ntilde "Ñ"> <!ENTITY Ograve "Ò"> <!ENTITY Oacute "Ó"> <!ENTITY Ocirc "Ô"> <!ENTITY Otilde "Õ"> <!ENTITY Ouml "Ö"> <!ENTITY times "×"> <!ENTITY Oslash "Ø"> <!ENTITY Ugrave "Ù"> <!ENTITY Uacute "Ú"> <!ENTITY Ucirc "Û"> <!ENTITY Uuml "Ü"> <!ENTITY Yacute "Ý"> <!ENTITY THORN "Þ"> <!ENTITY szlig "ß"> <!ENTITY agrave "à"> <!ENTITY aacute "á"> <!ENTITY acirc "â"> <!ENTITY atilde "ã"> <!ENTITY auml "ä"> <!ENTITY aring "å"> <!ENTITY aelig "æ"> <!ENTITY ccedil "ç"> <!ENTITY egrave "è"> <!ENTITY eacute "é"> <!ENTITY ecirc "ê"> <!ENTITY euml "ë"> <!ENTITY igrave "ì"> <!ENTITY iacute "í"> <!ENTITY icirc "î"> <!ENTITY iuml "ï"> <!ENTITY eth "ð"> <!ENTITY ntilde "ñ"> <!ENTITY ograve "ò"> <!ENTITY oacute "ó"> <!ENTITY ocirc "ô"> <!ENTITY otilde "õ"> <!ENTITY ouml "ö"> <!ENTITY divide "÷"> <!ENTITY oslash "ø"> <!ENTITY ugrave "ù"> <!ENTITY uacute "ú"> <!ENTITY ucirc "û"> <!ENTITY uuml "ü"> <!ENTITY yacute "ý"> <!ENTITY thorn "þ"> <!ENTITY yuml "ÿ"> <!ENTITY OElig "Œ"> <!ENTITY oelig "œ"> <!ENTITY Scaron "Š"> <!ENTITY scaron "š"> <!ENTITY Yuml "Ÿ"> <!ENTITY fnof "ƒ"> <!ENTITY circ "ˆ"> <!ENTITY tilde "˜"> <!ENTITY Alpha "Α"> <!ENTITY Beta "Β"> <!ENTITY Gamma "Γ"> <!ENTITY Epsilon "Ε"> <!ENTITY Zeta "Ζ"> <!ENTITY Eta "Η"> <!ENTITY Theta "Θ"> <!ENTITY Iota "Ι"> <!ENTITY Kappa "Κ"> <!ENTITY Lambda "Λ"> <!ENTITY Mu "Μ"> <!ENTITY Nu "Ν"> <!ENTITY Xi "Ξ"> <!ENTITY Omicron "Ο"> <!ENTITY Pi "Π"> <!ENTITY Rho "Ρ"> <!ENTITY Sigma "Σ"> <!ENTITY Tau "Τ"> <!ENTITY Upsilon "Υ"> <!ENTITY Phi "Φ"> <!ENTITY Chi "Χ"> <!ENTITY Psi "Ψ"> <!ENTITY Omega "Ω"> <!ENTITY alpha "α"> <!ENTITY beta "β"> <!ENTITY gamma "γ"> <!ENTITY delta "δ"> <!ENTITY epsilon "ε"> <!ENTITY zeta "ζ"> <!ENTITY eta "η"> <!ENTITY theta "θ"> <!ENTITY iota "ι"> <!ENTITY kappa "κ"> <!ENTITY lambda "λ"> <!ENTITY mu "μ"> <!ENTITY nu "ν"> <!ENTITY xi "ξ"> <!ENTITY omicron "ο"> <!ENTITY pi "π"> <!ENTITY rho "ρ"> <!ENTITY sigmaf "ς"> <!ENTITY sigma "σ"> <!ENTITY tau "τ"> <!ENTITY upsilon "υ"> <!ENTITY phi "φ"> <!ENTITY chi "χ"> <!ENTITY psi "ψ"> <!ENTITY omega "ω"> <!ENTITY thetasym "ϑ"> <!ENTITY upsih "ϒ"> <!ENTITY piv "ϖ"> <!ENTITY ensp " "> <!ENTITY emsp " "> <!ENTITY thinsp " "> <!ENTITY zwnj "‌"> <!ENTITY zwj "‍"> <!ENTITY lrm "‎"> <!ENTITY rlm "‏"> <!ENTITY ndash "–"> <!ENTITY mdash "—"> <!ENTITY lsquo "‘"> <!ENTITY rsquo "’"> <!ENTITY sbquo "‚"> <!ENTITY ldquo "“"> <!ENTITY rdquo "”"> <!ENTITY bdquo "„"> <!ENTITY dagger "†"> <!ENTITY Dagger "‡"> <!ENTITY bull "•"> <!ENTITY hellip "…"> <!ENTITY permil "‰"> <!ENTITY prime "′"> <!ENTITY Prime "″"> <!ENTITY lsaquo "‹"> <!ENTITY rsaquo "›"> <!ENTITY oline "‾"> <!ENTITY frasl "⁄"> <!ENTITY euro "€"> <!ENTITY image "ℑ"> <!ENTITY weierp "℘"> <!ENTITY real "ℜ"> <!ENTITY trade "™"> <!ENTITY alefsym "ℵ"> <!ENTITY larr "←"> <!ENTITY uarr "↑"> <!ENTITY rarr "→"> <!ENTITY darr "↓"> <!ENTITY harr "↔"> <!ENTITY crarr "↵"> <!ENTITY lArr "⇐"> <!ENTITY uArr "⇑"> <!ENTITY rArr "⇒"> <!ENTITY dArr "⇓"> <!ENTITY hArr "⇔"> <!ENTITY forall "∀"> <!ENTITY part "∂"> <!ENTITY exist "∃"> <!ENTITY empty "∅"> <!ENTITY nabla "∇"> <!ENTITY isin "∈"> <!ENTITY notin "∉"> <!ENTITY ni "∋"> <!ENTITY prod "∏"> <!ENTITY sum "∑"> <!ENTITY minus "−"> <!ENTITY lowast "∗"> <!ENTITY radic "√"> <!ENTITY prop "∝"> <!ENTITY infin "∞"> <!ENTITY ang "∠"> <!ENTITY and "∧"> <!ENTITY or "∨"> <!ENTITY cap "∩"> <!ENTITY cup "∪"> <!ENTITY int "∫"> <!ENTITY there4 "∴"> <!ENTITY sim "∼"> <!ENTITY cong "≅"> <!ENTITY asymp "≈"> <!ENTITY ne "≠"> <!ENTITY equiv "≡"> <!ENTITY le "≤"> <!ENTITY ge "≥"> <!ENTITY sub "⊂"> <!ENTITY sup "⊃"> <!ENTITY nsub "⊄"> <!ENTITY sube "⊆"> <!ENTITY supe "⊇"> <!ENTITY oplus "⊕"> <!ENTITY otimes "⊗"> <!ENTITY perp "⊥"> <!ENTITY sdot "⋅"> <!ENTITY lceil "⌈"> <!ENTITY rceil "⌉"> <!ENTITY lfloor "⌊"> <!ENTITY rfloor "⌋"> <!ENTITY lang "〈"> <!ENTITY rang "〉"> <!ENTITY loz "◊"> <!ENTITY spades "♠"> <!ENTITY clubs "♣"> <!ENTITY hearts "♥"> <!ENTITY diams "♦"> ]>';
|
559 |
+
}
|
560 |
+
} /* class FeedWordPie_Parser */
|
561 |
+
|
562 |
+
|
File without changes
|
@@ -3,7 +3,7 @@ if (!class_exists('SimplePie_Content_Type_Sniffer')) :
|
|
3 |
require_once(ABSPATH . WPINC . '/class-simplepie.php');
|
4 |
endif;
|
5 |
|
6 |
-
class
|
7 |
/**
|
8 |
* Get the Content-Type of the specified file
|
9 |
*
|
@@ -55,6 +55,6 @@ class FeedWordPress_Content_Type_Sniffer extends SimplePie_Content_Type_Sniffer
|
|
55 |
$this->file->headers['content-type'] = 'text/xml'; // Generic
|
56 |
endif;
|
57 |
return parent::get_type();
|
58 |
-
} /*
|
59 |
-
} /* class
|
60 |
|
3 |
require_once(ABSPATH . WPINC . '/class-simplepie.php');
|
4 |
endif;
|
5 |
|
6 |
+
class FeedWordPie_Content_Type_Sniffer extends SimplePie_Content_Type_Sniffer {
|
7 |
/**
|
8 |
* Get the Content-Type of the specified file
|
9 |
*
|
55 |
$this->file->headers['content-type'] = 'text/xml'; // Generic
|
56 |
endif;
|
57 |
return parent::get_type();
|
58 |
+
} /* FeedWordPie_Content_Type_Sniffer::get_type() */
|
59 |
+
} /* class FeedWordPie_Content_Type_Sniffer */
|
60 |
|
@@ -3,7 +3,7 @@ global $fwp_credentials;
|
|
3 |
|
4 |
$fwp_credentials = NULL;
|
5 |
|
6 |
-
class
|
7 |
public function __construct ($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) {
|
8 |
global $feedwordpress;
|
9 |
global $wp_version;
|
@@ -95,6 +95,6 @@ class FeedWordPress_File extends WP_SimplePie_File {
|
|
95 |
// to break and fall on its ass when SimplePie is getting a 304,
|
96 |
// but doesn't realize it because this member is "304" instead.
|
97 |
$this->status_code = (int) $this->status_code;
|
98 |
-
}
|
99 |
-
} /* class
|
100 |
|
3 |
|
4 |
$fwp_credentials = NULL;
|
5 |
|
6 |
+
class FeedWordPie_File extends WP_SimplePie_File {
|
7 |
public function __construct ($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) {
|
8 |
global $feedwordpress;
|
9 |
global $wp_version;
|
95 |
// to break and fall on its ass when SimplePie is getting a 304,
|
96 |
// but doesn't realize it because this member is "304" instead.
|
97 |
$this->status_code = (int) $this->status_code;
|
98 |
+
} /* FeedWordPie_File::__construct () */
|
99 |
+
} /* class FeedWordPie_File () */
|
100 |
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$subdir = dirname(__FILE__);
|
3 |
+
$ver = SIMPLEPIE_VERSION;;
|
4 |
+
$mod = basename(__FILE__);
|
5 |
+
|
6 |
+
if ( is_readable("${subdir}/${ver}/${mod}") ) :
|
7 |
+
$modClassPath = "${subdir}/${ver}/${mod}";
|
8 |
+
else :
|
9 |
+
$modClassPath = "${subdir}/default/${mod}";
|
10 |
+
endif;
|
11 |
+
|
12 |
+
require_once("${modClassPath}");
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$subdir = dirname(__FILE__);
|
3 |
+
$ver = SIMPLEPIE_VERSION;
|
4 |
+
$mod = basename(__FILE__);
|
5 |
+
|
6 |
+
if ( is_readable("${subdir}/${ver}/${mod}") ) :
|
7 |
+
$modClassPath = "${subdir}/${ver}/${mod}";
|
8 |
+
else :
|
9 |
+
$modClassPath = "${subdir}/default/${mod}";
|
10 |
+
endif;
|
11 |
+
|
12 |
+
require_once("${modClassPath}");
|
@@ -30,12 +30,12 @@ if (!class_exists('MyPHP')) :
|
|
30 |
if (isset($GLOBALS[$where]) and is_array($GLOBALS[$where])) :
|
31 |
if (isset($GLOBALS[$where][$key])) :
|
32 |
$ret = $GLOBALS[$where][$key];
|
33 |
-
|
34 |
-
// Magic quotes
|
35 |
-
// thing ever.
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
endif;
|
40 |
endif;
|
41 |
|
30 |
if (isset($GLOBALS[$where]) and is_array($GLOBALS[$where])) :
|
31 |
if (isset($GLOBALS[$where][$key])) :
|
32 |
$ret = $GLOBALS[$where][$key];
|
33 |
+
|
34 |
+
// Magic quotes were just like the stupidest
|
35 |
+
// thing ever. (<http://php.net/manual/en/security.magicquotes.php>)
|
36 |
+
// Happily they were DEPRECATED as of PHP 5.3.0,
|
37 |
+
// and REMOVED as of PHP 5.4.0, so we don't need
|
38 |
+
// to worry about them anymore.
|
39 |
endif;
|
40 |
endif;
|
41 |
|
@@ -736,10 +736,10 @@ jQuery(document).ready(function($){
|
|
736 |
tagBox.init();
|
737 |
}
|
738 |
|
739 |
-
|
740 |
function(){$('.fwpfs').removeClass('slideUp').addClass('slideDown'); setTimeout(function(){if ( $('.fwpfs').hasClass('slideDown') ) { $('.fwpfs').addClass('slide-down'); }}, 10) },
|
741 |
function(){$('.fwpfs').removeClass('slideDown').addClass('slideUp'); setTimeout(function(){if ( $('.fwpfs').hasClass('slideUp') ) { $('.fwpfs').removeClass('slide-down'); }}, 10) }
|
742 |
-
)
|
743 |
$('.fwpfs').bind(
|
744 |
'change',
|
745 |
function () { this.form.submit(); }
|
736 |
tagBox.init();
|
737 |
}
|
738 |
|
739 |
+
/*$('.fwpfs').toggle(
|
740 |
function(){$('.fwpfs').removeClass('slideUp').addClass('slideDown'); setTimeout(function(){if ( $('.fwpfs').hasClass('slideDown') ) { $('.fwpfs').addClass('slide-down'); }}, 10) },
|
741 |
function(){$('.fwpfs').removeClass('slideDown').addClass('slideUp'); setTimeout(function(){if ( $('.fwpfs').hasClass('slideUp') ) { $('.fwpfs').removeClass('slide-down'); }}, 10) }
|
742 |
+
);*/
|
743 |
$('.fwpfs').bind(
|
744 |
'change',
|
745 |
function () { this.form.submit(); }
|
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: FeedWordPress
|
4 |
Plugin URI: http://feedwordpress.radgeek.com/
|
5 |
Description: simple and flexible Atom/RSS syndication for WordPress
|
6 |
-
Version: 2020.
|
7 |
Author: C. Johnson
|
8 |
Author URI: https://feedwordpress.radgeek.com/contact/
|
9 |
License: GPL
|
@@ -11,7 +11,7 @@ License: GPL
|
|
11 |
|
12 |
/**
|
13 |
* @package FeedWordPress
|
14 |
-
* @version 2020.
|
15 |
*/
|
16 |
|
17 |
# This plugin uses code derived from:
|
@@ -22,20 +22,24 @@ License: GPL
|
|
22 |
# - WordPress Blog Tool and Publishing Platform <http://wordpress.org/>
|
23 |
# - Github contributors @Flynsarmy, @BandonRandon, @david-robinson-practiceweb,
|
24 |
# @daidais, @thegreatmichael, @stedaniels, @alexiskulash, @quassy, @zoul0813,
|
25 |
-
# @timmmmyboy, @vobornik,
|
|
|
26 |
# according to the terms of the GNU General Public License.
|
27 |
|
28 |
####################################################################################
|
29 |
## CONSTANTS & DEFAULTS ############################################################
|
30 |
####################################################################################
|
31 |
|
32 |
-
define ('FEEDWORDPRESS_VERSION', '2020.
|
33 |
define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://feedwordpress.radgeek.com/contact');
|
34 |
|
35 |
if (!defined('FEEDWORDPRESS_BLEG')) :
|
36 |
define ('FEEDWORDPRESS_BLEG', true);
|
37 |
endif;
|
38 |
-
|
|
|
|
|
|
|
39 |
define('FEEDWORDPRESS_BLEG_PAYPAL', '22PAJZZCK5Z3W');
|
40 |
|
41 |
// Defaults
|
@@ -134,13 +138,13 @@ require_once("${dir}/compatability.php"); // Legacy API
|
|
134 |
require_once("${dir}/syndicatedpost.class.php");
|
135 |
require_once("${dir}/syndicatedlink.class.php");
|
136 |
require_once("${dir}/feedwordpresshtml.class.php");
|
137 |
-
require_once("${dir}/feedwordpress-content-type-sniffer.class.php");
|
138 |
require_once("${dir}/inspectpostmeta.class.php");
|
139 |
require_once("${dir}/syndicationdataqueries.class.php");
|
140 |
-
require_once("${dir}/feedwordpie.class.php");
|
141 |
-
require_once("${dir}/feedwordpie_item.class.php");
|
142 |
-
require_once("${dir}/
|
143 |
-
require_once("${dir}/
|
|
|
144 |
require_once("${dir}/feedwordpressrpc.class.php");
|
145 |
require_once("${dir}/feedwordpresshttpauthenticator.class.php");
|
146 |
require_once("${dir}/feedwordpresslocalpost.class.php");
|
@@ -181,79 +185,7 @@ endif;
|
|
181 |
|
182 |
$feedwordpress = new FeedWordPress;
|
183 |
if (!$feedwordpress->needs_upgrade()) : // only work if the conditions are safe!
|
184 |
-
|
185 |
-
# Syndicated items are generally received in output-ready (X)HTML and
|
186 |
-
# should not be folded, crumpled, mutilated, or spindled by WordPress
|
187 |
-
# formatting filters. But we don't want to interfere with filters for
|
188 |
-
# any locally-authored posts, either.
|
189 |
-
#
|
190 |
-
# What WordPress should really have is a way for upstream filters to
|
191 |
-
# stop downstream filters from running at all. Since it doesn't, and
|
192 |
-
# since a downstream filter can't access the original copy of the text
|
193 |
-
# that is being filtered, what we will do here is (1) save a copy of the
|
194 |
-
# original text upstream, before any other filters run, and then (2)
|
195 |
-
# retrieve that copy downstream, after all the other filters run, *if*
|
196 |
-
# this is a syndicated post
|
197 |
-
|
198 |
-
add_filter('the_content', 'feedwordpress_preserve_syndicated_content', -10000);
|
199 |
-
add_filter('the_content', 'feedwordpress_restore_syndicated_content', 10000);
|
200 |
-
|
201 |
-
add_action('atom_entry', 'feedwordpress_item_feed_data');
|
202 |
-
|
203 |
-
# Filter in original permalinks if the user wants that
|
204 |
-
add_filter('post_link', 'syndication_permalink', /*priority=*/ 1, /*arguments=*/ 3);
|
205 |
-
add_filter('post_type_link', 'syndication_permalink', /*priority=*/ 1, /*arguments=*/ 4);
|
206 |
-
|
207 |
-
# When foreign URLs are used for permalinks in feeds or display
|
208 |
-
# contexts, they need to be escaped properly.
|
209 |
-
add_filter('the_permalink', 'syndication_permalink_escaped');
|
210 |
-
add_filter('the_permalink_rss', 'syndication_permalink_escaped');
|
211 |
-
|
212 |
-
add_filter('post_comments_feed_link', 'syndication_comments_feed_link');
|
213 |
-
|
214 |
-
# WTF? By default, wp_insert_link runs incoming link_url and link_rss
|
215 |
-
# URIs through default filters that include `wp_kses()`. But `wp_kses()`
|
216 |
-
# just happens to escape any occurrence of & to & -- which just
|
217 |
-
# happens to fuck up any URI with a & to separate GET parameters.
|
218 |
-
remove_filter('pre_link_rss', 'wp_filter_kses');
|
219 |
-
remove_filter('pre_link_url', 'wp_filter_kses');
|
220 |
-
|
221 |
-
# Boilerplate functionality: hook in to title, excerpt, and content to add boilerplate text
|
222 |
-
$hookOrder = get_option('feedwordpress_boilerplate_hook_order', FEEDWORDPRESS_BOILERPLATE_DEFAULT_HOOK_ORDER);
|
223 |
-
add_filter(
|
224 |
-
/*hook=*/ 'the_title',
|
225 |
-
/*function=*/ 'add_boilerplate_title',
|
226 |
-
/*priority=*/ $hookOrder,
|
227 |
-
/*arguments=*/ 2
|
228 |
-
);
|
229 |
-
add_filter(
|
230 |
-
/*hook=*/ 'get_the_excerpt',
|
231 |
-
/*function=*/ 'add_boilerplate_excerpt',
|
232 |
-
/*priority=*/ $hookOrder,
|
233 |
-
/*arguments=*/ 1
|
234 |
-
);
|
235 |
-
add_filter(
|
236 |
-
/*hook=*/ 'the_content',
|
237 |
-
/*function=*/ 'add_boilerplate_content',
|
238 |
-
/*priority=*/ $hookOrder,
|
239 |
-
/*arguments=*/ 1
|
240 |
-
);
|
241 |
-
add_filter(
|
242 |
-
/*hook=*/ 'the_content_rss',
|
243 |
-
/*function=*/ 'add_boilerplate_content',
|
244 |
-
/*priority=*/ $hookOrder,
|
245 |
-
/*arguments=*/ 1
|
246 |
-
);
|
247 |
-
|
248 |
-
# Admin menu
|
249 |
-
add_action('admin_init', array($feedwordpress, 'admin_init'));
|
250 |
-
add_action('admin_menu', 'fwp_add_pages');
|
251 |
-
add_action('admin_notices', 'fwp_check_debug');
|
252 |
-
|
253 |
-
add_action('admin_menu', 'feedwordpress_add_post_edit_controls');
|
254 |
-
add_action('save_post', 'feedwordpress_save_post_edit_controls');
|
255 |
-
|
256 |
-
add_action('admin_footer', array($feedwordpress, 'admin_footer'));
|
257 |
|
258 |
# Inbound XML-RPC update methods
|
259 |
$feedwordpressRPC = new FeedWordPressRPC;
|
@@ -268,38 +200,9 @@ if (!$feedwordpress->needs_upgrade()) : // only work if the conditions are safe!
|
|
268 |
add_action('feedwordpress_update', 'fwp_hold_pings');
|
269 |
add_action('feedwordpress_update_complete', 'fwp_release_pings');
|
270 |
|
271 |
-
add_action('syndicated_feed_error', array('FeedWordPressDiagnostic', 'feed_error'), 100, 3);
|
272 |
-
|
273 |
-
add_action('wp_footer', 'debug_out_feedwordpress_footer', -100);
|
274 |
-
add_action('admin_footer', 'debug_out_feedwordpress_footer', -100);
|
275 |
-
|
276 |
-
# Cron-less auto-update. Hooray!
|
277 |
-
$autoUpdateHook = $feedwordpress->automatic_update_hook();
|
278 |
-
if (!is_null($autoUpdateHook)) :
|
279 |
-
add_action($autoUpdateHook, array($feedwordpress, 'auto_update'));
|
280 |
-
endif;
|
281 |
-
|
282 |
-
add_action('init', array($feedwordpress, 'init'));
|
283 |
-
add_action('wp_loaded', array($feedwordpress, 'wp_loaded'));
|
284 |
-
|
285 |
-
add_action('shutdown', array($feedwordpress, 'email_diagnostic_log'));
|
286 |
-
add_action('shutdown', array($feedwordpress, 'feedwordpress_cleanup'));
|
287 |
-
add_action('wp_dashboard_setup', array($feedwordpress, 'dashboard_setup'));
|
288 |
-
|
289 |
-
# Default sanitizers
|
290 |
-
add_filter('syndicated_item_content', array('SyndicatedPost', 'resolve_relative_uris'), 0, 2);
|
291 |
-
add_filter('syndicated_item_content', array('SyndicatedPost', 'sanitize_content'), 0, 2);
|
292 |
-
|
293 |
-
add_action('plugins_loaded', array($feedwordpress, 'admin_api'));
|
294 |
-
add_action('all_admin_notices', array($feedwordpress, 'all_admin_notices'));
|
295 |
-
|
296 |
-
// Use our the cache settings that we want.
|
297 |
-
add_filter('wp_feed_cache_transient_lifetime', array('FeedWordPress', 'cache_lifetime'));
|
298 |
-
|
299 |
-
|
300 |
else :
|
301 |
# Hook in the menus, which will just point to the upgrade interface
|
302 |
-
add_action('admin_menu', '
|
303 |
endif; // if (!FeedWordPress::needs_upgrade())
|
304 |
|
305 |
register_deactivation_hook(__FILE__, 'feedwordpress_deactivate');
|
@@ -526,433 +429,16 @@ function syndication_comments_feed_link ($link) {
|
|
526 |
return $link;
|
527 |
} /* function syndication_comments_feed_link() */
|
528 |
|
529 |
-
|
530 |
-
## ADMIN MENU ADD-ONS: register Dashboard management pages #####################
|
531 |
-
################################################################################
|
532 |
-
|
533 |
-
function fwp_add_pages () {
|
534 |
-
global $feedwordpress;
|
535 |
-
|
536 |
-
$menu_cap = FeedWordPress::menu_cap();
|
537 |
-
$settings_cap = FeedWordPress::menu_cap(/*sub=*/ true);
|
538 |
-
$syndicationMenu = FeedWordPress::path('syndication.php');
|
539 |
-
|
540 |
-
add_menu_page(
|
541 |
-
'Syndicated Sites', 'Syndication',
|
542 |
-
$menu_cap,
|
543 |
-
$syndicationMenu,
|
544 |
-
NULL,
|
545 |
-
plugins_url( '/'.FeedWordPress::path('feedwordpress-tiny.png') )
|
546 |
-
);
|
547 |
-
|
548 |
-
do_action('feedwordpress_admin_menu_pre_feeds', $menu_cap, $settings_cap);
|
549 |
-
add_submenu_page(
|
550 |
-
$syndicationMenu, 'Syndicated Sites', 'Syndicated Sites',
|
551 |
-
$settings_cap, $syndicationMenu
|
552 |
-
);
|
553 |
-
|
554 |
-
do_action('feedwordpress_admin_menu_pre_feeds', $menu_cap, $settings_cap);
|
555 |
-
add_submenu_page(
|
556 |
-
$syndicationMenu, 'Syndicated Feeds & Updates', 'Feeds & Updates',
|
557 |
-
$settings_cap, FeedWordPress::path('feeds-page.php')
|
558 |
-
);
|
559 |
-
|
560 |
-
do_action('feedwordpress_admin_menu_pre_posts', $menu_cap, $settings_cap);
|
561 |
-
add_submenu_page(
|
562 |
-
$syndicationMenu, 'Syndicated Posts & Links', 'Posts & Links',
|
563 |
-
$settings_cap, FeedWordPress::path('posts-page.php')
|
564 |
-
);
|
565 |
-
|
566 |
-
do_action('feedwordpress_admin_menu_pre_authors', $menu_cap, $settings_cap);
|
567 |
-
add_submenu_page(
|
568 |
-
$syndicationMenu, 'Syndicated Authors', 'Authors',
|
569 |
-
$settings_cap, FeedWordPress::path('authors-page.php')
|
570 |
-
);
|
571 |
-
|
572 |
-
do_action('feedwordpress_admin_menu_pre_categories', $menu_cap, $settings_cap);
|
573 |
-
add_submenu_page(
|
574 |
-
$syndicationMenu, 'Categories & Tags', 'Categories & Tags',
|
575 |
-
$settings_cap, FeedWordPress::path('categories-page.php')
|
576 |
-
);
|
577 |
-
|
578 |
-
do_action('feedwordpress_admin_menu_pre_performance', $menu_cap, $settings_cap);
|
579 |
-
add_submenu_page(
|
580 |
-
$syndicationMenu, 'FeedWordPress Performance', 'Performance',
|
581 |
-
$settings_cap, FeedWordPress::path('performance-page.php')
|
582 |
-
);
|
583 |
-
|
584 |
-
do_action('feedwordpress_admin_menu_pre_diagnostics', $menu_cap, $settings_cap);
|
585 |
-
add_submenu_page(
|
586 |
-
$syndicationMenu, 'FeedWordPress Diagnostics', 'Diagnostics',
|
587 |
-
$settings_cap, FeedWordPress::path('diagnostics-page.php')
|
588 |
-
);
|
589 |
-
|
590 |
-
add_filter('page_row_actions', array($feedwordpress, 'row_actions'), 10, 2);
|
591 |
-
add_filter('post_row_actions', array($feedwordpress, 'row_actions'), 10, 2);
|
592 |
-
} /* function fwp_add_pages () */
|
593 |
-
|
594 |
-
function fwp_check_debug () {
|
595 |
-
// This is a horrible fucking kludge that I have to do because the
|
596 |
-
// admin notice code is triggered before the code that updates the
|
597 |
-
// setting.
|
598 |
-
if (isset($_POST['feedwordpress_debug'])) :
|
599 |
-
$feedwordpress_debug = $_POST['feedwordpress_debug'];
|
600 |
-
else :
|
601 |
-
$feedwordpress_debug = get_option('feedwordpress_debug');
|
602 |
-
endif;
|
603 |
-
if ($feedwordpress_debug==='yes') :
|
604 |
-
?>
|
605 |
-
<div class="error">
|
606 |
-
<p><strong>FeedWordPress warning.</strong> Debugging mode is <strong>ON</strong>.
|
607 |
-
While it remains on, FeedWordPress displays many diagnostic error messages,
|
608 |
-
warnings, and notices that are ordinarily suppressed, and also turns off all
|
609 |
-
caching of feeds. Use with caution: this setting is absolutely inappropriate
|
610 |
-
for a production server.</p>
|
611 |
-
</div>
|
612 |
-
<?php
|
613 |
-
endif;
|
614 |
-
} /* function fwp_check_debug () */
|
615 |
-
|
616 |
-
################################################################################
|
617 |
-
## fwp_hold_pings() and fwp_release_pings(): Outbound XML-RPC ping reform ####
|
618 |
-
## ... 'coz it's rude to send 500 pings the first time your aggregator runs ####
|
619 |
-
################################################################################
|
620 |
-
|
621 |
-
$fwp_held_ping = NULL; // NULL: not holding pings yet
|
622 |
-
|
623 |
-
function fwp_hold_pings () {
|
624 |
-
global $fwp_held_ping;
|
625 |
-
if (is_null($fwp_held_ping)):
|
626 |
-
$fwp_held_ping = 0; // 0: ready to hold pings; none yet received
|
627 |
-
endif;
|
628 |
-
}
|
629 |
-
|
630 |
-
function fwp_release_pings () {
|
631 |
-
global $fwp_held_ping;
|
632 |
-
if ($fwp_held_ping):
|
633 |
-
if (function_exists('wp_schedule_single_event')) :
|
634 |
-
wp_schedule_single_event(time(), 'do_pings');
|
635 |
-
else :
|
636 |
-
generic_ping($fwp_held_ping);
|
637 |
-
endif;
|
638 |
-
endif;
|
639 |
-
$fwp_held_ping = NULL; // NULL: not holding pings anymore
|
640 |
-
}
|
641 |
-
|
642 |
-
function fwp_do_pings () {
|
643 |
-
if (!is_null($fwp_held_ping) and $post_id) : // Defer until we're done updating
|
644 |
-
$fwp_held_ping = $post_id;
|
645 |
-
elseif (function_exists('do_all_pings')) :
|
646 |
-
do_all_pings();
|
647 |
-
else :
|
648 |
-
generic_ping($fwp_held_ping);
|
649 |
-
endif;
|
650 |
-
}
|
651 |
-
|
652 |
-
function fwp_publish_post_hook ($post_id) {
|
653 |
-
global $fwp_held_ping;
|
654 |
-
|
655 |
-
if (!is_null($fwp_held_ping)) : // Syndicated post. Don't mark with _pingme
|
656 |
-
if ( defined('XMLRPC_REQUEST') )
|
657 |
-
do_action('xmlrpc_publish_post', $post_id);
|
658 |
-
if ( defined('APP_REQUEST') )
|
659 |
-
do_action('app_publish_post', $post_id);
|
660 |
-
|
661 |
-
if ( defined('WP_IMPORTING') )
|
662 |
-
return;
|
663 |
-
|
664 |
-
// Defer sending out pings until we finish updating
|
665 |
-
$fwp_held_ping = $post_id;
|
666 |
-
else :
|
667 |
-
if (function_exists('_publish_post_hook')) : // WordPress 2.3
|
668 |
-
_publish_post_hook($post_id);
|
669 |
-
endif;
|
670 |
-
endif;
|
671 |
-
}
|
672 |
-
|
673 |
-
function feedwordpress_add_post_edit_controls () {
|
674 |
-
global $feedwordpress;
|
675 |
-
global $inspectPostMeta;
|
676 |
-
|
677 |
-
// Put in Manual Editing checkbox
|
678 |
-
add_action('add_meta_boxes', 'feedwordpress_post_add_meta_boxes', 10, 2);
|
679 |
-
|
680 |
-
add_filter('user_can_richedit', array($feedwordpress, 'user_can_richedit'), 1000, 1);
|
681 |
-
|
682 |
-
if (FeedWordPressDiagnostic::is_on('syndicated_posts:static_meta_data')) :
|
683 |
-
$inspectPostMeta = new InspectPostMeta;
|
684 |
-
endif;
|
685 |
-
} // function feedwordpress_add_post_edit_controls ()
|
686 |
-
|
687 |
-
function feedwordpress_post_add_meta_boxes ($post_type, $post) {
|
688 |
-
add_meta_box(
|
689 |
-
'feedwordpress-post-controls',
|
690 |
-
__('Syndication'),
|
691 |
-
'feedwordpress_post_edit_controls',
|
692 |
-
$post_type,
|
693 |
-
'side',
|
694 |
-
'high'
|
695 |
-
);
|
696 |
-
}
|
697 |
-
|
698 |
-
function feedwordpress_post_edit_controls () {
|
699 |
-
global $post;
|
700 |
-
|
701 |
-
$frozen_values = get_post_custom_values('_syndication_freeze_updates', $post->ID);
|
702 |
-
$frozen_post = ($frozen_values !== null and count($frozen_values) > 0 and 'yes' == $frozen_values[0]);
|
703 |
-
|
704 |
-
if (is_syndicated($post->ID)) :
|
705 |
-
?>
|
706 |
-
<p>This is a syndicated post, which originally appeared at
|
707 |
-
<cite><?php print esc_html(get_syndication_source(NULL, $post->ID)); ?></cite>.
|
708 |
-
<a href="<?php print esc_html(get_syndication_permalink($post->ID)); ?>">View original post</a>.</p>
|
709 |
-
|
710 |
-
<?php do_action('feedwordpress_post_edit_controls_pre', $post); ?>
|
711 |
-
|
712 |
-
<p><input type="hidden" name="feedwordpress_noncename" id="feedwordpress_noncename" value="<?php print wp_create_nonce(plugin_basename(__FILE__)); ?>" />
|
713 |
-
<label><input type="checkbox" name="freeze_updates" value="yes" <?php if ($frozen_post) : ?>checked="checked"<?php endif; ?> /> <strong>Manual editing.</strong>
|
714 |
-
If set, FeedWordPress will not overwrite the changes you make manually
|
715 |
-
to this post, if the syndicated content is updated on the
|
716 |
-
feed.</label></p>
|
717 |
-
|
718 |
-
<?php do_action('feedwordpress_post_edit_controls', $post); ?>
|
719 |
-
|
720 |
-
<?php
|
721 |
-
else :
|
722 |
-
?>
|
723 |
-
<p>This post was created locally at this website.</p>
|
724 |
-
<?php
|
725 |
-
endif;
|
726 |
-
} /* function feedwordpress_post_edit_controls () */
|
727 |
-
|
728 |
-
function feedwordpress_save_post_edit_controls ( $post_id ) {
|
729 |
-
global $post;
|
730 |
-
if (!isset($_POST['feedwordpress_noncename']) or !wp_verify_nonce($_POST['feedwordpress_noncename'], plugin_basename(__FILE__))) :
|
731 |
-
return $post_id;
|
732 |
-
endif;
|
733 |
-
|
734 |
-
// Verify if this is an auto save routine. If it is our form has
|
735 |
-
// not been submitted, so we don't want to do anything.
|
736 |
-
if ( defined('DOING_AUTOSAVE') and DOING_AUTOSAVE ) :
|
737 |
-
return $post_id;
|
738 |
-
endif;
|
739 |
-
|
740 |
-
// The data in $_POST is for applying only to the post actually
|
741 |
-
// in the edit window, i.e. $post
|
742 |
-
if ($post_id != $post->ID) :
|
743 |
-
return $post_id;
|
744 |
-
endif;
|
745 |
-
|
746 |
-
// Check permissions
|
747 |
-
$cap[0] = 'edit_post';
|
748 |
-
$cap[1] = 'edit_' . $_POST['post_type'];
|
749 |
-
if (
|
750 |
-
!current_user_can( $cap[0], $post_id )
|
751 |
-
and !current_user_can( $cap[1], $post_id )
|
752 |
-
) :
|
753 |
-
return $post_id;
|
754 |
-
endif;
|
755 |
-
|
756 |
-
// OK, we're golden. Now let's save some data.
|
757 |
-
if (isset($_POST['freeze_updates'])) :
|
758 |
-
|
759 |
-
update_post_meta($post_id, '_syndication_freeze_updates', $_POST['freeze_updates']);
|
760 |
-
$ret = $_POST['freeze_updates'];
|
761 |
-
|
762 |
-
// If you make manual edits through the WordPress editing
|
763 |
-
// UI then they should be run through normal WP formatting
|
764 |
-
// filters.
|
765 |
-
update_post_meta($post_id, '_feedwordpress_formatting_filters', 'yes');
|
766 |
-
|
767 |
-
else :
|
768 |
-
delete_post_meta($post_id, '_syndication_freeze_updates');
|
769 |
-
$ret = NULL;
|
770 |
-
endif;
|
771 |
|
772 |
-
|
773 |
-
|
774 |
-
return $ret;
|
775 |
-
} // function feedwordpress_save_edit_controls
|
776 |
|
777 |
################################################################################
|
778 |
## class FeedWordPressBoilerplateReformatter ###################################
|
779 |
################################################################################
|
780 |
|
781 |
-
class
|
782 |
-
|
783 |
-
|
784 |
-
public function __construct ($id = NULL, $element = 'post') {
|
785 |
-
$this->id = $id;
|
786 |
-
$this->element = $element;
|
787 |
-
}
|
788 |
-
|
789 |
-
function shortcode_methods () {
|
790 |
-
return array(
|
791 |
-
'source' => 'source_link',
|
792 |
-
'source-name' => 'source_name',
|
793 |
-
'source-url' => 'source_url',
|
794 |
-
'original-link' => 'original_link',
|
795 |
-
'original-url' => 'original_url',
|
796 |
-
'author' => 'source_author_link',
|
797 |
-
'author-name' => 'source_author',
|
798 |
-
'feed-setting' => 'source_setting',
|
799 |
-
);
|
800 |
-
}
|
801 |
-
function do_shortcode ($template) {
|
802 |
-
$codes = $this->shortcode_methods();
|
803 |
-
|
804 |
-
// Register shortcodes relative to this object/post ID/element.
|
805 |
-
foreach ($codes as $code => $method) :
|
806 |
-
add_shortcode($code, array($this, $method));
|
807 |
-
endforeach;
|
808 |
-
|
809 |
-
$template = do_shortcode($template);
|
810 |
-
|
811 |
-
// Unregister shortcodes.
|
812 |
-
foreach ($codes as $code => $method) :
|
813 |
-
remove_shortcode($code);
|
814 |
-
endforeach;
|
815 |
-
|
816 |
-
return $template;
|
817 |
-
}
|
818 |
-
|
819 |
-
function source_name ($atts) {
|
820 |
-
$param = shortcode_atts(array(
|
821 |
-
'original' => NULL,
|
822 |
-
), $atts);
|
823 |
-
return get_syndication_source($param['original'], $this->id);
|
824 |
-
}
|
825 |
-
function source_url ($atts) {
|
826 |
-
$param = shortcode_atts(array(
|
827 |
-
'original' => NULL,
|
828 |
-
), $atts);
|
829 |
-
return get_syndication_source_link($param['original'], $this->id);
|
830 |
-
}
|
831 |
-
function source_link ($atts) {
|
832 |
-
switch (strtolower($atts[0])) :
|
833 |
-
case '-name' :
|
834 |
-
$ret = $this->source_name($atts);
|
835 |
-
break;
|
836 |
-
case '-url' :
|
837 |
-
$ret = $this->source_url($atts);
|
838 |
-
break;
|
839 |
-
default :
|
840 |
-
$param = shortcode_atts(array(
|
841 |
-
'original' => NULL,
|
842 |
-
), $atts);
|
843 |
-
if ('title' == $this->element) :
|
844 |
-
$ret = $this->source_name($atts);
|
845 |
-
else :
|
846 |
-
$ret = '<a href="'.htmlspecialchars($this->source_url($atts)).'">'.htmlspecialchars($this->source_name($atts)).'</a>';
|
847 |
-
endif;
|
848 |
-
endswitch;
|
849 |
-
return $ret;
|
850 |
-
}
|
851 |
-
function source_setting ($atts) {
|
852 |
-
$param = shortcode_atts(array(
|
853 |
-
'key' => NULL,
|
854 |
-
), $atts);
|
855 |
-
return get_feed_meta($param['key'], $this->id);
|
856 |
-
}
|
857 |
-
function original_link ($atts, $text) {
|
858 |
-
$url = $this->original_url($atts);
|
859 |
-
return '<a href="'.esc_url($url).'">'.do_shortcode($text).'</a>';
|
860 |
-
}
|
861 |
-
function original_url ($atts) {
|
862 |
-
return get_syndication_permalink($this->id);
|
863 |
-
}
|
864 |
-
function source_author ($atts) {
|
865 |
-
return get_the_author();
|
866 |
-
}
|
867 |
-
function source_author_link ($atts) {
|
868 |
-
switch (strtolower($atts[0])) :
|
869 |
-
case '-name' :
|
870 |
-
$ret = $this->source_author($atts);
|
871 |
-
break;
|
872 |
-
default :
|
873 |
-
global $authordata; // Janky.
|
874 |
-
if ('title' == $this->element) :
|
875 |
-
$ret = $this->source_author($atts);
|
876 |
-
else :
|
877 |
-
$ret = get_the_author();
|
878 |
-
$url = get_author_posts_url((int) $authordata->ID, (int) $authordata->user_nicename);
|
879 |
-
if ($url) :
|
880 |
-
$ret = '<a href="'.$url.'" '
|
881 |
-
.'title="Read other posts by '.esc_html($authordata->display_name).'">'
|
882 |
-
.$ret
|
883 |
-
.'</a>';
|
884 |
-
endif;
|
885 |
-
endif;
|
886 |
-
endswitch;
|
887 |
-
return $ret;
|
888 |
-
}
|
889 |
-
}
|
890 |
-
|
891 |
-
function add_boilerplate_reformat ($template, $element, $id = NULL) {
|
892 |
-
if ('post' == $element and !preg_match('/< (p|div) ( \s [^>]+ )? >/xi', $template)) :
|
893 |
-
$template = '<p class="syndicated-attribution">'.$template.'</p>';
|
894 |
-
endif;
|
895 |
-
|
896 |
-
$ref = new FeedWordPressBoilerplateReformatter($id, $element);
|
897 |
-
return $ref->do_shortcode($template);
|
898 |
-
}
|
899 |
-
|
900 |
-
function add_boilerplate_simple ($element, $title, $id = NULL) {
|
901 |
-
if (is_syndicated($id)) :
|
902 |
-
$meta = get_feed_meta('boilerplate rules', $id);
|
903 |
-
if ($meta and !is_array($meta)) : $meta = unserialize($meta); endif;
|
904 |
-
|
905 |
-
if (!is_array($meta) or empty($meta)) :
|
906 |
-
$meta = get_option('feedwordpress_boilerplate');
|
907 |
-
endif;
|
908 |
-
|
909 |
-
if (is_array($meta) and !empty($meta)) :
|
910 |
-
foreach ($meta as $rule) :
|
911 |
-
if ($element==$rule['element']) :
|
912 |
-
$rule['template'] = add_boilerplate_reformat($rule['template'], $element, $id);
|
913 |
-
|
914 |
-
if ('before'==$rule['placement']) :
|
915 |
-
$title = $rule['template'] . ' ' . $title;
|
916 |
-
else :
|
917 |
-
$title = $title . ' ' . $rule['template'];
|
918 |
-
endif;
|
919 |
-
endif;
|
920 |
-
endforeach;
|
921 |
-
endif;
|
922 |
-
endif;
|
923 |
-
return $title;
|
924 |
-
}
|
925 |
-
function add_boilerplate_title ($title, $id = NULL) {
|
926 |
-
return add_boilerplate_simple('title', $title, $id);
|
927 |
-
}
|
928 |
-
function add_boilerplate_excerpt ($title, $id = NULL) {
|
929 |
-
return add_boilerplate_simple('excerpt', $title, $id);
|
930 |
-
}
|
931 |
-
function add_boilerplate_content ($content) {
|
932 |
-
if (is_syndicated()) :
|
933 |
-
$meta = get_feed_meta('boilerplate rules');
|
934 |
-
if ($meta and !is_array($meta)) : $meta = unserialize($meta); endif;
|
935 |
-
|
936 |
-
if (!is_array($meta) or empty($meta)) :
|
937 |
-
$meta = get_option('feedwordpress_boilerplate');
|
938 |
-
endif;
|
939 |
-
|
940 |
-
if (is_array($meta) and !empty($meta)) :
|
941 |
-
foreach ($meta as $rule) :
|
942 |
-
if ('post'==$rule['element']) :
|
943 |
-
$rule['template'] = add_boilerplate_reformat($rule['template'], 'post');
|
944 |
-
|
945 |
-
if ('before'==$rule['placement']) :
|
946 |
-
$content = $rule['template'] . "\n" . $content;
|
947 |
-
else :
|
948 |
-
$content = $content . "\n" . $rule['template'];
|
949 |
-
endif;
|
950 |
-
endif;
|
951 |
-
endforeach;
|
952 |
-
endif;
|
953 |
-
endif;
|
954 |
-
return $content;
|
955 |
-
}
|
956 |
|
957 |
################################################################################
|
958 |
## class FeedWordPress #########################################################
|
@@ -1025,6 +511,216 @@ class FeedWordPress {
|
|
1025 |
$this->httpauth = new FeedWordPressHTTPAuthenticator;
|
1026 |
} /* FeedWordPress::__construct () */
|
1027 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1028 |
/**
|
1029 |
* FeedWordPress::subscribed (): Check whether a feed is currently in the
|
1030 |
* subscription list for FeedWordPress.
|
@@ -2243,10 +1939,10 @@ class FeedWordPress {
|
|
2243 |
|
2244 |
$pie_class = apply_filters('feedwordpress_simplepie_class', 'FeedWordPie');
|
2245 |
$cache_class = apply_filters('feedwordpress_cache_class', 'WP_Feed_Cache');
|
2246 |
-
$file_class = apply_filters('feedwordpress_file_class', '
|
2247 |
-
$parser_class = apply_filters('feedwordpress_parser_class', '
|
2248 |
$item_class = apply_filters('feedwordpress_item_class', 'FeedWordPie_Item');
|
2249 |
-
$sniffer_class = apply_filters('feedwordpress_sniffer_class', '
|
2250 |
|
2251 |
$feed = new $pie_class;
|
2252 |
$feed->set_feed_url($url);
|
3 |
Plugin Name: FeedWordPress
|
4 |
Plugin URI: http://feedwordpress.radgeek.com/
|
5 |
Description: simple and flexible Atom/RSS syndication for WordPress
|
6 |
+
Version: 2020.0818
|
7 |
Author: C. Johnson
|
8 |
Author URI: https://feedwordpress.radgeek.com/contact/
|
9 |
License: GPL
|
11 |
|
12 |
/**
|
13 |
* @package FeedWordPress
|
14 |
+
* @version 2020.0818
|
15 |
*/
|
16 |
|
17 |
# This plugin uses code derived from:
|
22 |
# - WordPress Blog Tool and Publishing Platform <http://wordpress.org/>
|
23 |
# - Github contributors @Flynsarmy, @BandonRandon, @david-robinson-practiceweb,
|
24 |
# @daidais, @thegreatmichael, @stedaniels, @alexiskulash, @quassy, @zoul0813,
|
25 |
+
# @timmmmyboy, @vobornik, @inanimatt, @tristanleboss, @martinburchell,
|
26 |
+
# @bigalownz, and @oppiansteve
|
27 |
# according to the terms of the GNU General Public License.
|
28 |
|
29 |
####################################################################################
|
30 |
## CONSTANTS & DEFAULTS ############################################################
|
31 |
####################################################################################
|
32 |
|
33 |
+
define ('FEEDWORDPRESS_VERSION', '2020.0818');
|
34 |
define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://feedwordpress.radgeek.com/contact');
|
35 |
|
36 |
if (!defined('FEEDWORDPRESS_BLEG')) :
|
37 |
define ('FEEDWORDPRESS_BLEG', true);
|
38 |
endif;
|
39 |
+
|
40 |
+
define('FEEDWORDPRESS_BLEG_BTC_pre_2020', '15EsQ9QMZtLytsaVYZUaUCmrkSMaxZBTso');
|
41 |
+
define('FEEDWORDPRESS_BLEG_BTC', '1NB1ebYVb68Har4WijmE8gKnZ47NptCqtB'); // 2020.0201
|
42 |
+
|
43 |
define('FEEDWORDPRESS_BLEG_PAYPAL', '22PAJZZCK5Z3W');
|
44 |
|
45 |
// Defaults
|
138 |
require_once("${dir}/syndicatedpost.class.php");
|
139 |
require_once("${dir}/syndicatedlink.class.php");
|
140 |
require_once("${dir}/feedwordpresshtml.class.php");
|
|
|
141 |
require_once("${dir}/inspectpostmeta.class.php");
|
142 |
require_once("${dir}/syndicationdataqueries.class.php");
|
143 |
+
require_once("${dir}/extend/SimplePie/feedwordpie.class.php");
|
144 |
+
require_once("${dir}/extend/SimplePie/feedwordpie_item.class.php");
|
145 |
+
require_once("${dir}/extend/SimplePie/feedwordpie_file.class.php");
|
146 |
+
require_once("${dir}/extend/SimplePie/feedwordpie_parser.class.php");
|
147 |
+
require_once("${dir}/extend/SimplePie/feedwordpie_content_type_sniffer.class.php");
|
148 |
require_once("${dir}/feedwordpressrpc.class.php");
|
149 |
require_once("${dir}/feedwordpresshttpauthenticator.class.php");
|
150 |
require_once("${dir}/feedwordpresslocalpost.class.php");
|
185 |
|
186 |
$feedwordpress = new FeedWordPress;
|
187 |
if (!$feedwordpress->needs_upgrade()) : // only work if the conditions are safe!
|
188 |
+
$feedwordpress->add_filters();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
189 |
|
190 |
# Inbound XML-RPC update methods
|
191 |
$feedwordpressRPC = new FeedWordPressRPC;
|
200 |
add_action('feedwordpress_update', 'fwp_hold_pings');
|
201 |
add_action('feedwordpress_update_complete', 'fwp_release_pings');
|
202 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
else :
|
204 |
# Hook in the menus, which will just point to the upgrade interface
|
205 |
+
add_action('admin_menu', array($feedwordpress, 'add_pages'));
|
206 |
endif; // if (!FeedWordPress::needs_upgrade())
|
207 |
|
208 |
register_deactivation_hook(__FILE__, 'feedwordpress_deactivate');
|
429 |
return $link;
|
430 |
} /* function syndication_comments_feed_link() */
|
431 |
|
432 |
+
require_once("${dir}/feedwordpress.pings.functions.php");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
433 |
|
434 |
+
require_once("${dir}/feedwordpress.wp-admin.post-edit.functions.php");
|
|
|
|
|
|
|
435 |
|
436 |
################################################################################
|
437 |
## class FeedWordPressBoilerplateReformatter ###################################
|
438 |
################################################################################
|
439 |
|
440 |
+
require_once("${dir}/feedwordpressboilerplatereformatter.class.php");
|
441 |
+
require_once("${dir}/feedwordpressboilerplatereformatter.shortcode.functions.php");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
442 |
|
443 |
################################################################################
|
444 |
## class FeedWordPress #########################################################
|
511 |
$this->httpauth = new FeedWordPressHTTPAuthenticator;
|
512 |
} /* FeedWordPress::__construct () */
|
513 |
|
514 |
+
/**
|
515 |
+
* FeedWordPress::add_filters() connects FeedWordPress to WordPress lifecycle
|
516 |
+
* events by setting up action and filter hooks.
|
517 |
+
*
|
518 |
+
* @uses get_option()
|
519 |
+
* @uses add_filter()
|
520 |
+
* @uses add_action()
|
521 |
+
* @uses remove_filter()
|
522 |
+
*/
|
523 |
+
public function add_filters () {
|
524 |
+
# Syndicated items are generally received in output-ready (X)HTML and
|
525 |
+
# should not be folded, crumpled, mutilated, or spindled by WordPress
|
526 |
+
# formatting filters. But we don't want to interfere with filters for
|
527 |
+
# any locally-authored posts, either.
|
528 |
+
#
|
529 |
+
# What WordPress should really have is a way for upstream filters to
|
530 |
+
# stop downstream filters from running at all. Since it doesn't, and
|
531 |
+
# since a downstream filter can't access the original copy of the text
|
532 |
+
# that is being filtered, what we will do here is (1) save a copy of the
|
533 |
+
# original text upstream, before any other filters run, and then (2)
|
534 |
+
# retrieve that copy downstream, after all the other filters run, *if*
|
535 |
+
# this is a syndicated post
|
536 |
+
|
537 |
+
add_filter('the_content', 'feedwordpress_preserve_syndicated_content', -10000);
|
538 |
+
add_filter('the_content', 'feedwordpress_restore_syndicated_content', 10000);
|
539 |
+
|
540 |
+
add_action('atom_entry', 'feedwordpress_item_feed_data');
|
541 |
+
|
542 |
+
# Filter in original permalinks if the user wants that
|
543 |
+
add_filter('post_link', 'syndication_permalink', /*priority=*/ 1, /*arguments=*/ 3);
|
544 |
+
add_filter('post_type_link', 'syndication_permalink', /*priority=*/ 1, /*arguments=*/ 4);
|
545 |
+
|
546 |
+
# When foreign URLs are used for permalinks in feeds or display
|
547 |
+
# contexts, they need to be escaped properly.
|
548 |
+
add_filter('the_permalink', 'syndication_permalink_escaped');
|
549 |
+
add_filter('the_permalink_rss', 'syndication_permalink_escaped');
|
550 |
+
|
551 |
+
add_filter('post_comments_feed_link', 'syndication_comments_feed_link');
|
552 |
+
|
553 |
+
# WTF? By default, wp_insert_link runs incoming link_url and link_rss
|
554 |
+
# URIs through default filters that include `wp_kses()`. But `wp_kses()`
|
555 |
+
# just happens to escape any occurrence of & to & -- which just
|
556 |
+
# happens to fuck up any URI with a & to separate GET parameters.
|
557 |
+
remove_filter('pre_link_rss', 'wp_filter_kses');
|
558 |
+
remove_filter('pre_link_url', 'wp_filter_kses');
|
559 |
+
|
560 |
+
# Boilerplate functionality: hook in to title, excerpt, and content to add boilerplate text
|
561 |
+
$hookOrder = get_option('feedwordpress_boilerplate_hook_order', FEEDWORDPRESS_BOILERPLATE_DEFAULT_HOOK_ORDER);
|
562 |
+
add_filter(
|
563 |
+
/*hook=*/ 'the_title',
|
564 |
+
/*function=*/ 'add_boilerplate_title',
|
565 |
+
/*priority=*/ $hookOrder,
|
566 |
+
/*arguments=*/ 2
|
567 |
+
);
|
568 |
+
add_filter(
|
569 |
+
/*hook=*/ 'get_the_excerpt',
|
570 |
+
/*function=*/ 'add_boilerplate_excerpt',
|
571 |
+
/*priority=*/ $hookOrder,
|
572 |
+
/*arguments=*/ 1
|
573 |
+
);
|
574 |
+
add_filter(
|
575 |
+
/*hook=*/ 'the_content',
|
576 |
+
/*function=*/ 'add_boilerplate_content',
|
577 |
+
/*priority=*/ $hookOrder,
|
578 |
+
/*arguments=*/ 1
|
579 |
+
);
|
580 |
+
add_filter(
|
581 |
+
/*hook=*/ 'the_content_rss',
|
582 |
+
/*function=*/ 'add_boilerplate_content',
|
583 |
+
/*priority=*/ $hookOrder,
|
584 |
+
/*arguments=*/ 1
|
585 |
+
);
|
586 |
+
|
587 |
+
# Admin menu
|
588 |
+
add_action('admin_init', array($this, 'admin_init'));
|
589 |
+
add_action('admin_menu', array($this, 'add_pages'));
|
590 |
+
add_action('admin_notices', array($this, 'check_debug'));
|
591 |
+
|
592 |
+
add_action('admin_menu', 'feedwordpress_add_post_edit_controls');
|
593 |
+
add_action('save_post', 'feedwordpress_save_post_edit_controls');
|
594 |
+
|
595 |
+
add_action('admin_footer', array($this, 'admin_footer'));
|
596 |
+
|
597 |
+
add_action('syndicated_feed_error', array('FeedWordPressDiagnostic', 'feed_error'), 100, 3);
|
598 |
+
|
599 |
+
add_action('wp_footer', 'debug_out_feedwordpress_footer', -100);
|
600 |
+
add_action('admin_footer', 'debug_out_feedwordpress_footer', -100);
|
601 |
+
|
602 |
+
# Cron-less auto-update. Hooray!
|
603 |
+
$autoUpdateHook = $this->automatic_update_hook();
|
604 |
+
if (!is_null($autoUpdateHook)) :
|
605 |
+
add_action($autoUpdateHook, array($this, 'auto_update'));
|
606 |
+
endif;
|
607 |
+
|
608 |
+
add_action('init', array($this, 'init'));
|
609 |
+
add_action('wp_loaded', array($this, 'wp_loaded'));
|
610 |
+
|
611 |
+
add_action('shutdown', array($this, 'email_diagnostic_log'));
|
612 |
+
add_action('shutdown', array($this, 'feedwordpress_cleanup'));
|
613 |
+
add_action('wp_dashboard_setup', array($this, 'dashboard_setup'));
|
614 |
+
|
615 |
+
# Default sanitizers
|
616 |
+
add_filter('syndicated_item_content', array('SyndicatedPost', 'resolve_relative_uris'), 0, 2);
|
617 |
+
add_filter('syndicated_item_content', array('SyndicatedPost', 'sanitize_content'), 0, 2);
|
618 |
+
|
619 |
+
add_action('plugins_loaded', array($this, 'admin_api'));
|
620 |
+
add_action('all_admin_notices', array($this, 'all_admin_notices'));
|
621 |
+
|
622 |
+
// Use the cache settings that we want, from a static method
|
623 |
+
add_filter('wp_feed_cache_transient_lifetime', array(get_class($this), 'cache_lifetime'));
|
624 |
+
|
625 |
+
} /* FeedWordPress::add_filters () */
|
626 |
+
|
627 |
+
################################################################################
|
628 |
+
## ADMIN MENU ADD-ONS: register Dashboard management pages #####################
|
629 |
+
################################################################################
|
630 |
+
|
631 |
+
/**
|
632 |
+
* FeedWordPress::add_pages(): set up WordPress admin interface pages thru
|
633 |
+
* hooking in Syndication menu and submenus
|
634 |
+
*
|
635 |
+
* @uses FeedWordPress::menu_cap()
|
636 |
+
* @uses FeedWordPress::path()
|
637 |
+
* @uses add_menu_page()
|
638 |
+
* @uses add_submenu_page()
|
639 |
+
* @uses do_action()
|
640 |
+
* @uses add_filter()
|
641 |
+
*/
|
642 |
+
public function add_pages () {
|
643 |
+
|
644 |
+
$menu_cap = FeedWordPress::menu_cap();
|
645 |
+
$settings_cap = FeedWordPress::menu_cap(/*sub=*/ true);
|
646 |
+
$syndicationMenu = FeedWordPress::path('syndication.php');
|
647 |
+
|
648 |
+
add_menu_page(
|
649 |
+
'Syndicated Sites', 'Syndication',
|
650 |
+
$menu_cap,
|
651 |
+
$syndicationMenu,
|
652 |
+
NULL,
|
653 |
+
plugins_url( '/'.FeedWordPress::path('feedwordpress-tiny.png') )
|
654 |
+
);
|
655 |
+
|
656 |
+
do_action('feedwordpress_admin_menu_pre_feeds', $menu_cap, $settings_cap);
|
657 |
+
add_submenu_page(
|
658 |
+
$syndicationMenu, 'Syndicated Sites', 'Syndicated Sites',
|
659 |
+
$settings_cap, $syndicationMenu
|
660 |
+
);
|
661 |
+
|
662 |
+
do_action('feedwordpress_admin_menu_pre_feeds', $menu_cap, $settings_cap);
|
663 |
+
add_submenu_page(
|
664 |
+
$syndicationMenu, 'Syndicated Feeds & Updates', 'Feeds & Updates',
|
665 |
+
$settings_cap, FeedWordPress::path('feeds-page.php')
|
666 |
+
);
|
667 |
+
|
668 |
+
do_action('feedwordpress_admin_menu_pre_posts', $menu_cap, $settings_cap);
|
669 |
+
add_submenu_page(
|
670 |
+
$syndicationMenu, 'Syndicated Posts & Links', 'Posts & Links',
|
671 |
+
$settings_cap, FeedWordPress::path('posts-page.php')
|
672 |
+
);
|
673 |
+
|
674 |
+
do_action('feedwordpress_admin_menu_pre_authors', $menu_cap, $settings_cap);
|
675 |
+
add_submenu_page(
|
676 |
+
$syndicationMenu, 'Syndicated Authors', 'Authors',
|
677 |
+
$settings_cap, FeedWordPress::path('authors-page.php')
|
678 |
+
);
|
679 |
+
|
680 |
+
do_action('feedwordpress_admin_menu_pre_categories', $menu_cap, $settings_cap);
|
681 |
+
add_submenu_page(
|
682 |
+
$syndicationMenu, 'Categories & Tags', 'Categories & Tags',
|
683 |
+
$settings_cap, FeedWordPress::path('categories-page.php')
|
684 |
+
);
|
685 |
+
|
686 |
+
do_action('feedwordpress_admin_menu_pre_performance', $menu_cap, $settings_cap);
|
687 |
+
add_submenu_page(
|
688 |
+
$syndicationMenu, 'FeedWordPress Performance', 'Performance',
|
689 |
+
$settings_cap, FeedWordPress::path('performance-page.php')
|
690 |
+
);
|
691 |
+
|
692 |
+
do_action('feedwordpress_admin_menu_pre_diagnostics', $menu_cap, $settings_cap);
|
693 |
+
add_submenu_page(
|
694 |
+
$syndicationMenu, 'FeedWordPress Diagnostics', 'Diagnostics',
|
695 |
+
$settings_cap, FeedWordPress::path('diagnostics-page.php')
|
696 |
+
);
|
697 |
+
|
698 |
+
add_filter('page_row_actions', array($this, 'row_actions'), 10, 2);
|
699 |
+
add_filter('post_row_actions', array($this, 'row_actions'), 10, 2);
|
700 |
+
} /* function FeedWordPress::add_pages () */
|
701 |
+
|
702 |
+
public function check_debug () {
|
703 |
+
// This is a horrible fucking kludge that I have to do because the
|
704 |
+
// admin notice code is triggered before the code that updates the
|
705 |
+
// setting.
|
706 |
+
if (isset($_POST['feedwordpress_debug'])) :
|
707 |
+
$feedwordpress_debug = $_POST['feedwordpress_debug'];
|
708 |
+
else :
|
709 |
+
$feedwordpress_debug = get_option('feedwordpress_debug');
|
710 |
+
endif;
|
711 |
+
if ($feedwordpress_debug==='yes') :
|
712 |
+
?>
|
713 |
+
<div class="error">
|
714 |
+
<p><strong>FeedWordPress warning.</strong> Debugging mode is <strong>ON</strong>.
|
715 |
+
While it remains on, FeedWordPress displays many diagnostic error messages,
|
716 |
+
warnings, and notices that are ordinarily suppressed, and also turns off all
|
717 |
+
caching of feeds. Use with caution: this setting is absolutely inappropriate
|
718 |
+
for a production server.</p>
|
719 |
+
</div>
|
720 |
+
<?php
|
721 |
+
endif;
|
722 |
+
} /* function FeedWordPress::check_debug () */
|
723 |
+
|
724 |
/**
|
725 |
* FeedWordPress::subscribed (): Check whether a feed is currently in the
|
726 |
* subscription list for FeedWordPress.
|
1939 |
|
1940 |
$pie_class = apply_filters('feedwordpress_simplepie_class', 'FeedWordPie');
|
1941 |
$cache_class = apply_filters('feedwordpress_cache_class', 'WP_Feed_Cache');
|
1942 |
+
$file_class = apply_filters('feedwordpress_file_class', 'FeedWordPie_File');
|
1943 |
+
$parser_class = apply_filters('feedwordpress_parser_class', 'FeedWordPie_Parser');
|
1944 |
$item_class = apply_filters('feedwordpress_item_class', 'FeedWordPie_Item');
|
1945 |
+
$sniffer_class = apply_filters('feedwordpress_sniffer_class', 'FeedWordPie_Content_Type_Sniffer');
|
1946 |
|
1947 |
$feed = new $pie_class;
|
1948 |
$feed->set_feed_url($url);
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
################################################################################
|
3 |
+
## fwp_hold_pings() and fwp_release_pings(): Outbound XML-RPC ping reform ####
|
4 |
+
## ... 'coz it's rude to send 500 pings the first time your aggregator runs ####
|
5 |
+
################################################################################
|
6 |
+
|
7 |
+
global $fwp_held_ping;
|
8 |
+
|
9 |
+
$fwp_held_ping = NULL; // NULL: not holding pings yet
|
10 |
+
|
11 |
+
function fwp_hold_pings () {
|
12 |
+
global $fwp_held_ping;
|
13 |
+
if (is_null($fwp_held_ping)):
|
14 |
+
$fwp_held_ping = 0; // 0: ready to hold pings; none yet received
|
15 |
+
FeedWordPress::diagnostic(
|
16 |
+
'syndicated_posts:do_pings',
|
17 |
+
'FeedWordPress is set up to hold pings, fwp_held_ping='.json_encode($fwp_held_ping)
|
18 |
+
);
|
19 |
+
endif;
|
20 |
+
}
|
21 |
+
|
22 |
+
function fwp_release_pings () {
|
23 |
+
global $fwp_held_ping;
|
24 |
+
|
25 |
+
$diag_message = null;
|
26 |
+
if ($fwp_held_ping):
|
27 |
+
if (function_exists('wp_schedule_single_event')) :
|
28 |
+
wp_schedule_single_event(time(), 'do_pings');
|
29 |
+
$diag_message = 'scheduled release of pings';
|
30 |
+
else :
|
31 |
+
generic_ping($fwp_held_ping);
|
32 |
+
$diag_message = 'released pings';
|
33 |
+
endif;
|
34 |
+
endif;
|
35 |
+
|
36 |
+
$fwp_held_ping = NULL; // NULL: not holding pings anymore
|
37 |
+
|
38 |
+
if (!is_null($diag_message)) :
|
39 |
+
FeedWordPress::diagnostic(
|
40 |
+
'syndicated_posts:do_pings',
|
41 |
+
"FeedWordPress ${diag_message}, fwp_held_ping=".json_encode($fwp_held_ping)
|
42 |
+
);
|
43 |
+
endif;
|
44 |
+
}
|
45 |
+
|
46 |
+
function fwp_do_pings () {
|
47 |
+
if (!is_null($fwp_held_ping) and $post_id) : // Defer until we're done updating
|
48 |
+
$fwp_held_ping = $post_id;
|
49 |
+
|
50 |
+
FeedWordPress::diagnostic(
|
51 |
+
'syndicated_posts:do_pings',
|
52 |
+
"FeedWordPress intercepted a ping event, fwp_held_ping=".json_encode($fwp_held_ping)
|
53 |
+
);
|
54 |
+
|
55 |
+
elseif (function_exists('do_all_pings')) :
|
56 |
+
do_all_pings();
|
57 |
+
else :
|
58 |
+
generic_ping($fwp_held_ping);
|
59 |
+
endif;
|
60 |
+
}
|
61 |
+
|
62 |
+
function fwp_publish_post_hook ($post_id) {
|
63 |
+
global $fwp_held_ping;
|
64 |
+
|
65 |
+
if (!is_null($fwp_held_ping)) : // Syndicated post. Don't mark with _pingme
|
66 |
+
if ( defined('XMLRPC_REQUEST') )
|
67 |
+
do_action('xmlrpc_publish_post', $post_id);
|
68 |
+
if ( defined('APP_REQUEST') )
|
69 |
+
do_action('app_publish_post', $post_id);
|
70 |
+
|
71 |
+
if ( defined('WP_IMPORTING') )
|
72 |
+
return;
|
73 |
+
|
74 |
+
// Defer sending out pings until we finish updating
|
75 |
+
$fwp_held_ping = $post_id;
|
76 |
+
|
77 |
+
FeedWordPress::diagnostic(
|
78 |
+
'syndicated_posts:do_pings',
|
79 |
+
"FeedWordPress intercepted a post event, fwp_held_ping=".json_encode($fwp_held_ping)
|
80 |
+
);
|
81 |
+
else :
|
82 |
+
if (function_exists('_publish_post_hook')) : // WordPress 2.3
|
83 |
+
_publish_post_hook($post_id);
|
84 |
+
endif;
|
85 |
+
endif;
|
86 |
+
}
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
function feedwordpress_add_post_edit_controls () {
|
3 |
+
global $feedwordpress;
|
4 |
+
global $inspectPostMeta;
|
5 |
+
|
6 |
+
// Put in Manual Editing checkbox
|
7 |
+
add_action('add_meta_boxes', 'feedwordpress_post_add_meta_boxes', 10, 2);
|
8 |
+
|
9 |
+
add_filter('user_can_richedit', array($feedwordpress, 'user_can_richedit'), 1000, 1);
|
10 |
+
|
11 |
+
if (FeedWordPressDiagnostic::is_on('syndicated_posts:static_meta_data')) :
|
12 |
+
$inspectPostMeta = new InspectPostMeta;
|
13 |
+
endif;
|
14 |
+
} // function feedwordpress_add_post_edit_controls ()
|
15 |
+
|
16 |
+
function feedwordpress_post_add_meta_boxes ($post_type, $post) {
|
17 |
+
add_meta_box(
|
18 |
+
'feedwordpress-post-controls',
|
19 |
+
__('Syndication'),
|
20 |
+
'feedwordpress_post_edit_controls',
|
21 |
+
$post_type,
|
22 |
+
'side',
|
23 |
+
'high'
|
24 |
+
);
|
25 |
+
}
|
26 |
+
|
27 |
+
function feedwordpress_post_edit_controls () {
|
28 |
+
global $post;
|
29 |
+
|
30 |
+
$frozen_values = get_post_custom_values('_syndication_freeze_updates', $post->ID);
|
31 |
+
$frozen_post = ($frozen_values !== null and count($frozen_values) > 0 and 'yes' == $frozen_values[0]);
|
32 |
+
|
33 |
+
if (is_syndicated($post->ID)) :
|
34 |
+
?>
|
35 |
+
<p>This is a syndicated post, which originally appeared at
|
36 |
+
<cite><?php print esc_html(get_syndication_source(NULL, $post->ID)); ?></cite>.
|
37 |
+
<a href="<?php print esc_html(get_syndication_permalink($post->ID)); ?>">View original post</a>.</p>
|
38 |
+
|
39 |
+
<?php do_action('feedwordpress_post_edit_controls_pre', $post); ?>
|
40 |
+
|
41 |
+
<p><input type="hidden" name="feedwordpress_noncename" id="feedwordpress_noncename" value="<?php print wp_create_nonce(plugin_basename(__FILE__)); ?>" />
|
42 |
+
<label><input type="checkbox" name="freeze_updates" value="yes" <?php if ($frozen_post) : ?>checked="checked"<?php endif; ?> /> <strong>Manual editing.</strong>
|
43 |
+
If set, FeedWordPress will not overwrite the changes you make manually
|
44 |
+
to this post, if the syndicated content is updated on the
|
45 |
+
feed.</label></p>
|
46 |
+
|
47 |
+
<?php do_action('feedwordpress_post_edit_controls', $post); ?>
|
48 |
+
|
49 |
+
<?php
|
50 |
+
else :
|
51 |
+
?>
|
52 |
+
<p>This post was created locally at this website.</p>
|
53 |
+
<?php
|
54 |
+
endif;
|
55 |
+
} /* function feedwordpress_post_edit_controls () */
|
56 |
+
|
57 |
+
function feedwordpress_save_post_edit_controls ( $post_id ) {
|
58 |
+
global $post;
|
59 |
+
if (!isset($_POST['feedwordpress_noncename']) or !wp_verify_nonce($_POST['feedwordpress_noncename'], plugin_basename(__FILE__))) :
|
60 |
+
return $post_id;
|
61 |
+
endif;
|
62 |
+
|
63 |
+
// Verify if this is an auto save routine. If it is our form has
|
64 |
+
// not been submitted, so we don't want to do anything.
|
65 |
+
if ( defined('DOING_AUTOSAVE') and DOING_AUTOSAVE ) :
|
66 |
+
return $post_id;
|
67 |
+
endif;
|
68 |
+
|
69 |
+
// The data in $_POST is for applying only to the post actually
|
70 |
+
// in the edit window, i.e. $post
|
71 |
+
if ($post_id != $post->ID) :
|
72 |
+
return $post_id;
|
73 |
+
endif;
|
74 |
+
|
75 |
+
// Check permissions
|
76 |
+
$cap[0] = 'edit_post';
|
77 |
+
$cap[1] = 'edit_' . $_POST['post_type'];
|
78 |
+
if (
|
79 |
+
!current_user_can( $cap[0], $post_id )
|
80 |
+
and !current_user_can( $cap[1], $post_id )
|
81 |
+
) :
|
82 |
+
return $post_id;
|
83 |
+
endif;
|
84 |
+
|
85 |
+
// OK, we're golden. Now let's save some data.
|
86 |
+
if (isset($_POST['freeze_updates'])) :
|
87 |
+
|
88 |
+
update_post_meta($post_id, '_syndication_freeze_updates', $_POST['freeze_updates']);
|
89 |
+
$ret = $_POST['freeze_updates'];
|
90 |
+
|
91 |
+
// If you make manual edits through the WordPress editing
|
92 |
+
// UI then they should be run through normal WP formatting
|
93 |
+
// filters.
|
94 |
+
update_post_meta($post_id, '_feedwordpress_formatting_filters', 'yes');
|
95 |
+
|
96 |
+
else :
|
97 |
+
delete_post_meta($post_id, '_syndication_freeze_updates');
|
98 |
+
$ret = NULL;
|
99 |
+
endif;
|
100 |
+
|
101 |
+
do_action('feedwordpress_save_edit_controls', $post_id);
|
102 |
+
|
103 |
+
return $ret;
|
104 |
+
} // function feedwordpress_save_edit_controls
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class FeedWordPressBoilerplateReformatter: processes shortcodes in Boilerplate / Credits
|
4 |
+
* settings text from Syndication > Posts & Links > Boilerplate / Credits
|
5 |
+
*
|
6 |
+
* @author C. Johnson <development@fwpplugin.com>
|
7 |
+
*
|
8 |
+
* @see feedwordpressboilerplatereformatter.shortcode.functions.php
|
9 |
+
*
|
10 |
+
* @version 2020.0120
|
11 |
+
*/
|
12 |
+
|
13 |
+
class FeedWordPressBoilerplateReformatter {
|
14 |
+
var $id, $element;
|
15 |
+
|
16 |
+
public function __construct ($id = NULL, $element = 'post') {
|
17 |
+
$this->id = $id;
|
18 |
+
$this->element = $element;
|
19 |
+
}
|
20 |
+
|
21 |
+
function shortcode_methods () {
|
22 |
+
return array(
|
23 |
+
'source' => 'source_link',
|
24 |
+
'source-name' => 'source_name',
|
25 |
+
'source-url' => 'source_url',
|
26 |
+
'original-link' => 'original_link',
|
27 |
+
'original-url' => 'original_url',
|
28 |
+
'author' => 'source_author_link',
|
29 |
+
'author-name' => 'source_author',
|
30 |
+
'feed-setting' => 'source_setting',
|
31 |
+
);
|
32 |
+
}
|
33 |
+
function do_shortcode ($template) {
|
34 |
+
$codes = $this->shortcode_methods();
|
35 |
+
|
36 |
+
// Register shortcodes relative to this object/post ID/element.
|
37 |
+
foreach ($codes as $code => $method) :
|
38 |
+
add_shortcode($code, array($this, $method));
|
39 |
+
endforeach;
|
40 |
+
|
41 |
+
$template = do_shortcode($template);
|
42 |
+
|
43 |
+
// Unregister shortcodes.
|
44 |
+
foreach ($codes as $code => $method) :
|
45 |
+
remove_shortcode($code);
|
46 |
+
endforeach;
|
47 |
+
|
48 |
+
return $template;
|
49 |
+
}
|
50 |
+
|
51 |
+
function source_name ($atts) {
|
52 |
+
$param = shortcode_atts(array(
|
53 |
+
'original' => NULL,
|
54 |
+
), $atts);
|
55 |
+
return get_syndication_source($param['original'], $this->id);
|
56 |
+
}
|
57 |
+
function source_url ($atts) {
|
58 |
+
$param = shortcode_atts(array(
|
59 |
+
'original' => NULL,
|
60 |
+
), $atts);
|
61 |
+
return get_syndication_source_link($param['original'], $this->id);
|
62 |
+
}
|
63 |
+
function source_link ($atts) {
|
64 |
+
switch (strtolower($atts[0])) :
|
65 |
+
case '-name' :
|
66 |
+
$ret = $this->source_name($atts);
|
67 |
+
break;
|
68 |
+
case '-url' :
|
69 |
+
$ret = $this->source_url($atts);
|
70 |
+
break;
|
71 |
+
default :
|
72 |
+
$param = shortcode_atts(array(
|
73 |
+
'original' => NULL,
|
74 |
+
), $atts);
|
75 |
+
if ('title' == $this->element) :
|
76 |
+
$ret = $this->source_name($atts);
|
77 |
+
else :
|
78 |
+
$ret = '<a href="'.htmlspecialchars($this->source_url($atts)).'">'.htmlspecialchars($this->source_name($atts)).'</a>';
|
79 |
+
endif;
|
80 |
+
endswitch;
|
81 |
+
return $ret;
|
82 |
+
}
|
83 |
+
function source_setting ($atts) {
|
84 |
+
$param = shortcode_atts(array(
|
85 |
+
'key' => NULL,
|
86 |
+
), $atts);
|
87 |
+
return get_feed_meta($param['key'], $this->id);
|
88 |
+
}
|
89 |
+
function original_link ($atts, $text) {
|
90 |
+
$url = $this->original_url($atts);
|
91 |
+
return '<a href="'.esc_url($url).'">'.do_shortcode($text).'</a>';
|
92 |
+
}
|
93 |
+
function original_url ($atts) {
|
94 |
+
return get_syndication_permalink($this->id);
|
95 |
+
}
|
96 |
+
function source_author ($atts) {
|
97 |
+
return get_the_author();
|
98 |
+
}
|
99 |
+
function source_author_link ($atts) {
|
100 |
+
switch (strtolower($atts[0])) :
|
101 |
+
case '-name' :
|
102 |
+
$ret = $this->source_author($atts);
|
103 |
+
break;
|
104 |
+
default :
|
105 |
+
global $authordata; // Janky.
|
106 |
+
if ('title' == $this->element) :
|
107 |
+
$ret = $this->source_author($atts);
|
108 |
+
else :
|
109 |
+
$ret = get_the_author();
|
110 |
+
$url = get_author_posts_url((int) $authordata->ID, (int) $authordata->user_nicename);
|
111 |
+
if ($url) :
|
112 |
+
$ret = '<a href="'.$url.'" '
|
113 |
+
.'title="Read other posts by '.esc_html($authordata->display_name).'">'
|
114 |
+
.$ret
|
115 |
+
.'</a>';
|
116 |
+
endif;
|
117 |
+
endif;
|
118 |
+
endswitch;
|
119 |
+
return $ret;
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* function add_boilerplate_reformat: reformat boilerplate template to fit into post elements; return reformatted text
|
4 |
+
*
|
5 |
+
* @uses FeedWordPressBoilerplateReformatter
|
6 |
+
* @uses FeedWordPressBoilerplateReformatter::do_shortcode()
|
7 |
+
*
|
8 |
+
* @param string $template The boilerplate template text, mostly in text/html, with any inline [shortcode] elements
|
9 |
+
* @param string $element the wp_post element being processed, e.g. 'post' (= post_content), 'excerpt', 'title'
|
10 |
+
* @param int|null $id the numeric id of the post to be reformatted, or NULL for the current post in the WP loop
|
11 |
+
* @return string The reformatted text, in text/html format.
|
12 |
+
*/
|
13 |
+
function add_boilerplate_reformat ($template, $element, $id = NULL) {
|
14 |
+
if ('post' == $element and !preg_match('/< (p|div) ( \s [^>]+ )? >/xi', $template)) :
|
15 |
+
$template = '<p class="syndicated-attribution">'.$template.'</p>';
|
16 |
+
endif;
|
17 |
+
|
18 |
+
$ref = new FeedWordPressBoilerplateReformatter($id, $element);
|
19 |
+
return $ref->do_shortcode($template);
|
20 |
+
} /* add_boilerplate_reformat() */
|
21 |
+
|
22 |
+
/**
|
23 |
+
* function add_boilerplate_simple: look for any relevant Boilerplate / Credits template text to add
|
24 |
+
* to elements (post body, excerpt, title...) of a post being displayed in WordPress theme code.
|
25 |
+
*
|
26 |
+
* @uses is_syndicated()
|
27 |
+
* @uses get_feed_meta()
|
28 |
+
* @uses get_option()
|
29 |
+
* @uses add_boilerplate_reformat()
|
30 |
+
*
|
31 |
+
* @param string $element indicates the element of the post 'post' (= main body), 'excerpt', or 'title'
|
32 |
+
* @param string $title provides the text of the element waiting for boilerplate to be inserted
|
33 |
+
* @param int|null $id provides the numeric ID of the post being displayed (null = current post in WP loop)
|
34 |
+
* @return string provides the reformatted text, including any boilerplate text that has been inserted
|
35 |
+
*/
|
36 |
+
function add_boilerplate_simple ($element, $title, $id = NULL) {
|
37 |
+
if (is_syndicated($id)) :
|
38 |
+
$meta = get_feed_meta('boilerplate rules', $id);
|
39 |
+
if ($meta and !is_array($meta)) : $meta = unserialize($meta); endif;
|
40 |
+
|
41 |
+
if (!is_array($meta) or empty($meta)) :
|
42 |
+
$meta = get_option('feedwordpress_boilerplate');
|
43 |
+
endif;
|
44 |
+
|
45 |
+
if (is_array($meta) and !empty($meta)) :
|
46 |
+
foreach ($meta as $rule) :
|
47 |
+
if ($element==$rule['element']) :
|
48 |
+
$rule['template'] = add_boilerplate_reformat($rule['template'], $element, $id);
|
49 |
+
|
50 |
+
if ('before'==$rule['placement']) :
|
51 |
+
$title = $rule['template'] . ' ' . $title;
|
52 |
+
else :
|
53 |
+
$title = $title . ' ' . $rule['template'];
|
54 |
+
endif;
|
55 |
+
endif;
|
56 |
+
endforeach;
|
57 |
+
endif;
|
58 |
+
endif;
|
59 |
+
return $title;
|
60 |
+
} /* function add_boilerplate_simple() */
|
61 |
+
|
62 |
+
/**
|
63 |
+
* function add_boilerplate_title: filter hook for the_title to add Boilerplate / Credit text,
|
64 |
+
* if any is set, for the title of syndicated posts
|
65 |
+
*
|
66 |
+
* @uses add_boilerplate_simple()
|
67 |
+
*
|
68 |
+
* @param string $title contains the text of the title of the post being displayed
|
69 |
+
* @param int|null $id provides the numeric ID of the post being displayed (null = current post in WP loop)
|
70 |
+
* @return string provides the text of the title, reformatted to include any relevant boilerplate text
|
71 |
+
*/
|
72 |
+
function add_boilerplate_title ($title, $id = NULL) {
|
73 |
+
return add_boilerplate_simple('title', $title, $id);
|
74 |
+
} /* function add_boilerplate_title () */
|
75 |
+
|
76 |
+
/**
|
77 |
+
* function add_boilerplate_excerpt: filter hook for the_excerpt to add Boilerplate / Credit text,
|
78 |
+
* if any is set, for the excerpt of syndicated posts
|
79 |
+
*
|
80 |
+
* @uses add_boilerplate_simple()
|
81 |
+
*
|
82 |
+
* @param string $excerpt contains the text of the excerpt of the post being displayed
|
83 |
+
* @param int|null $id provides the numeric ID of the post being displayed (null = current post in WP loop)
|
84 |
+
* @return string provides the text of the excerpt, reformatted to include any relevant boilerplate text
|
85 |
+
*/
|
86 |
+
function add_boilerplate_excerpt ($title, $id = NULL) {
|
87 |
+
return add_boilerplate_simple('excerpt', $title, $id);
|
88 |
+
} /* function add_boilerplate_excerpt () */
|
89 |
+
|
90 |
+
/**
|
91 |
+
* function add_boilerplate_content: filter hook for the_content to add Boilerplate / Credit text,
|
92 |
+
* if any is set, for the excerpt of syndicated posts
|
93 |
+
*
|
94 |
+
* @uses is_syndicated()
|
95 |
+
* @uses get_feed_meta()
|
96 |
+
* @uses get_option()
|
97 |
+
* @uses add_boilerplate_reformat()
|
98 |
+
*
|
99 |
+
* @param string $content contains the text content of the post being displayed
|
100 |
+
* @return string provides the text content, reformatted to include any relevant boilerplate text
|
101 |
+
*/
|
102 |
+
function add_boilerplate_content ($content) {
|
103 |
+
if (is_syndicated()) :
|
104 |
+
$meta = get_feed_meta('boilerplate rules');
|
105 |
+
if ($meta and !is_array($meta)) : $meta = unserialize($meta); endif;
|
106 |
+
|
107 |
+
if (!is_array($meta) or empty($meta)) :
|
108 |
+
$meta = get_option('feedwordpress_boilerplate');
|
109 |
+
endif;
|
110 |
+
|
111 |
+
if (is_array($meta) and !empty($meta)) :
|
112 |
+
foreach ($meta as $rule) :
|
113 |
+
if ('post'==$rule['element']) :
|
114 |
+
$rule['template'] = add_boilerplate_reformat($rule['template'], 'post');
|
115 |
+
|
116 |
+
if ('before'==$rule['placement']) :
|
117 |
+
$content = $rule['template'] . "\n" . $content;
|
118 |
+
else :
|
119 |
+
$content = $content . "\n" . $rule['template'];
|
120 |
+
endif;
|
121 |
+
endif;
|
122 |
+
endforeach;
|
123 |
+
endif;
|
124 |
+
endif;
|
125 |
+
return $content;
|
126 |
+
} /* add_boilerplate_content () */
|
@@ -62,6 +62,8 @@ class FeedWordPressPerformancePage extends FeedWordPressAdminPage {
|
|
62 |
} /* FeedWordPressPerformancePage::display () */
|
63 |
|
64 |
function accept_POST ($post) {
|
|
|
|
|
65 |
if (isset($post['create_index'])) :
|
66 |
FeedWordPress::create_guid_index();
|
67 |
$this->updated = __('guid column index created on database table.');
|
@@ -72,7 +74,7 @@ class FeedWordPressPerformancePage extends FeedWordPressAdminPage {
|
|
72 |
endif;
|
73 |
|
74 |
if (isset($post['clear_cache'])) :
|
75 |
-
$N =
|
76 |
$feeds = (($N == 1) ? __("feed") : __("feeds"));
|
77 |
$this->updated = sprintf(__("Cleared %d cached %s from WordPress database."), $N, $feeds);
|
78 |
endif;
|
62 |
} /* FeedWordPressPerformancePage::display () */
|
63 |
|
64 |
function accept_POST ($post) {
|
65 |
+
global $feedwordpress;
|
66 |
+
|
67 |
if (isset($post['create_index'])) :
|
68 |
FeedWordPress::create_guid_index();
|
69 |
$this->updated = __('guid column index created on database table.');
|
74 |
endif;
|
75 |
|
76 |
if (isset($post['clear_cache'])) :
|
77 |
+
$N = $feedwordpress->clear_cache();
|
78 |
$feeds = (($N == 1) ? __("feed") : __("feeds"));
|
79 |
$this->updated = sprintf(__("Cleared %d cached %s from WordPress database."), $N, $feeds);
|
80 |
endif;
|
@@ -525,7 +525,9 @@ class FeedWordPressPostsPage extends FeedWordPressAdminPage {
|
|
525 |
|
526 |
public function boilerplate_box ($page, $box = NULL) {
|
527 |
if ($page->for_feed_settings()) :
|
528 |
-
$attrib =
|
|
|
|
|
529 |
$syndicatedPosts = 'this feed\'s posts';
|
530 |
else :
|
531 |
$attrib = get_option('feedwordpress_boilerplate');
|
525 |
|
526 |
public function boilerplate_box ($page, $box = NULL) {
|
527 |
if ($page->for_feed_settings()) :
|
528 |
+
$attrib = isset($page->link->settings['boilerplate rules'])
|
529 |
+
? unserialize($page->link->settings['boilerplate rules'])
|
530 |
+
: [];
|
531 |
$syndicatedPosts = 'this feed\'s posts';
|
532 |
else :
|
533 |
$attrib = get_option('feedwordpress_boilerplate');
|
@@ -3,8 +3,8 @@ Contributors: C. Johnson
|
|
3 |
Donate link: http://feedwordpress.radgeek.com/donate/
|
4 |
Tags: syndication, aggregation, feed, atom, rss
|
5 |
Requires at least: 4.5
|
6 |
-
Tested up to: 5.
|
7 |
-
Stable tag: 2020.
|
8 |
License: GPLv2 or later
|
9 |
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
@@ -65,6 +65,26 @@ FeedWordPress has many options which can be accessed through the WordPress Dashb
|
|
65 |
|
66 |
== Changelog ==
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
= 2017.1020 =
|
69 |
|
70 |
* ADD BOILERPLATE / CREDITS FEATURE AVAILABLE IN POSTS & LINKS SETTINGS PANEL. I have added a new settings panel to the off-the-shelf features of FeedWordPress, under Syndication > Posts & Links (or under the Posts settings page for any individual feed), which allows you to define boilerplate text that should appear in connection with every syndicated post, or with every post syndicated from a particular feed. So, for example, if you want each syndicated post to include a byline reading "This is a syndicated post, reprinted from (LINK TO ORIGINAL SOURCE WEBSITE).", you could set up this byline from within the FeedWordPress settings interface, by going to the Boilerplate / Credits panel, and adding a line to appear BEFORE the CONTENT of each syndicated post, using the text and shortcode "This is a syndicated post, reprinted from [source]." For those of you who have corresponded with me about this feature before, you may be familiar with it from the long-standing "experimental" add-on, FWP+: Add Attribution; I've decided that it's been enough years, and I've had enough requests, that the Add Attribution feature may as well be included in the main FeedWordPress code.
|
3 |
Donate link: http://feedwordpress.radgeek.com/donate/
|
4 |
Tags: syndication, aggregation, feed, atom, rss
|
5 |
Requires at least: 4.5
|
6 |
+
Tested up to: 5.5
|
7 |
+
Stable tag: 2020.0818
|
8 |
License: GPLv2 or later
|
9 |
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
65 |
|
66 |
== Changelog ==
|
67 |
|
68 |
+
= 2020.0818 =
|
69 |
+
|
70 |
+
* WORDPRESS 5.5 COMPATIBILITY FIXES, RESOLVES WARNING NOTICES OR WP-ADMIN LOCKOUT. WordPress 5.5 incorporated a newer release of SimplePie, version 1.5.5, which is pretty rad, but FeedWordPress classes that relied on SimplePie 1.3.1's method signatures would then produce PHP warning notices. That should be pretty innocuous, but depending on web server configurations, some users could get locked out of their own wp-admin interface by the display of error notices in the browser at inopportune times. In any case, I have
|
71 |
+
|
72 |
+
* PHP 7.4 COMPATIBILITY FIX: Magic quotes were deprecated and then removed back in PHP 5.x, and in PHP 7.4 the vestigial `get_magic_quotes_gpc()` function has been deprecated. We don't need to worry about it anymore for versions of PHP still supported by WordPress. The reference to the function in the MyPHP utility class caused PHP warnings in more recent versions of PHP; so it has now been removed.
|
73 |
+
|
74 |
+
* DIVERS BUG FIXES AND PHP WARNING NOTICES RESOLVED, thanks to @oppiansteve's fixes and pull requests. (Thanks!)
|
75 |
+
|
76 |
+
* JQUERY COMPATIBILITY FIXES, RESOLVES MYSTERIOUS VANISHING FEED SELECTOR IN WP-ADMIN. An upgrade to WordPress's packaged jQuery caused the drop-down box for feed settings (in Syndication > Feeds & Updates, Syndication > Posts & Links, etc.) to vanish shortly after pageload. That was awkward, so I disabled the now-incompatible interface chrome that was causing it to vanish.
|
77 |
+
|
78 |
+
= 2020.0118 =
|
79 |
+
|
80 |
+
* WORDPRESS COMPATIBILITY TESTING. It's been some time since a public release of FeedWordPress; so I have tested the plugin functionality with recent versions of WordPress and incorporated a number of PHP 7-compatibility related tweaks.
|
81 |
+
|
82 |
+
* FEED PARSING FAULT TOLERANCE. If FeedWordPress fails to parse a feed using normal XML functions, it will attempt to convert any named entities that may be causing a problem, and then try to parse again. Props to @inanimatt for utility functions that help make the code go.
|
83 |
+
|
84 |
+
* PAUSING UPDATES. In Syndication > Feeds & Updates, you can now instruct FeedWordPress to temporarily pause or resume updating feeds -- whatever update method you are using, you can put new updates on hold for a while so that you can fiddle with setings, run tests, or do whatever you need to do before allowing updates to resume.
|
85 |
+
|
86 |
+
* CODE MODERNIZATION, PHP 7.x COMPATIBILITY AND CLEANUP AND REORGANIZATION. I have been dusting out nooks and crannies in the code and hiving more functionality off into discrete modules. A number of FeedWordPress users have also offered pull requests to eliminate bothersome PHP notices and warnings related to PHP 7.x compatibility -- in particular removing uses of deprecated `each()` functions, and avoiding use of `count()` on null values -- which I have rolled into the main branch release. Props to @manzoorwanijk, @tristanleboss, @martinburchell and @oppiansteve
|
87 |
+
|
88 |
= 2017.1020 =
|
89 |
|
90 |
* ADD BOILERPLATE / CREDITS FEATURE AVAILABLE IN POSTS & LINKS SETTINGS PANEL. I have added a new settings panel to the off-the-shelf features of FeedWordPress, under Syndication > Posts & Links (or under the Posts settings page for any individual feed), which allows you to define boilerplate text that should appear in connection with every syndicated post, or with every post syndicated from a particular feed. So, for example, if you want each syndicated post to include a byline reading "This is a syndicated post, reprinted from (LINK TO ORIGINAL SOURCE WEBSITE).", you could set up this byline from within the FeedWordPress settings interface, by going to the Boilerplate / Credits panel, and adding a line to appear BEFORE the CONTENT of each syndicated post, using the text and shortcode "This is a syndicated post, reprinted from [source]." For those of you who have corresponded with me about this feature before, you may be familiar with it from the long-standing "experimental" add-on, FWP+: Add Attribution; I've decided that it's been enough years, and I've had enough requests, that the Add Attribution feature may as well be included in the main FeedWordPress code.
|
@@ -175,7 +175,7 @@ class SyndicatedLink {
|
|
175 |
$ttl = $this->automatic_ttl();
|
176 |
$ttl = apply_filters('syndicated_feed_ttl', $ttl, $this);
|
177 |
$ttl = apply_filters('syndicated_feed_ttl_from_error', $ttl, $this);
|
178 |
-
$this->update_setting('update/ttl', $ttl
|
179 |
$this->update_setting('update/timed', 'automatically');
|
180 |
endif;
|
181 |
|
@@ -189,7 +189,7 @@ class SyndicatedLink {
|
|
189 |
// Success; clear out error setting, if any.
|
190 |
$this->update_setting('update/error', NULL);
|
191 |
|
192 |
-
$new_count = array('new' => 0, 'updated' => 0);
|
193 |
|
194 |
# -- Update Link metadata live from feed
|
195 |
$channel = $this->magpie->channel;
|
@@ -220,24 +220,7 @@ class SyndicatedLink {
|
|
220 |
$this->merge_settings($channel, 'feed/');
|
221 |
|
222 |
$this->update_setting('update/last', time());
|
223 |
-
|
224 |
-
|
225 |
-
if (!is_null($ttl)) :
|
226 |
-
$this->update_setting('update/ttl', $ttl);
|
227 |
-
$this->update_setting('update/xml', $xml);
|
228 |
-
$this->update_setting('update/timed', 'feed');
|
229 |
-
else :
|
230 |
-
$ttl = $this->automatic_ttl();
|
231 |
-
$this->update_setting('update/ttl', $ttl);
|
232 |
-
$this->update_setting('update/xml', NULL);
|
233 |
-
$this->update_setting('update/timed', 'automatically');
|
234 |
-
endif;
|
235 |
-
$this->update_setting('update/fudge', rand(0, ($ttl/3))*60);
|
236 |
-
$this->update_setting('update/ttl', apply_filters(
|
237 |
-
'syndicated_feed_ttl',
|
238 |
-
$this->setting('update/ttl'),
|
239 |
-
$this
|
240 |
-
));
|
241 |
|
242 |
if (!$this->setting('update/hold') != 'ping') :
|
243 |
$this->update_setting('update/hold', 'scheduled');
|
@@ -371,6 +354,30 @@ class SyndicatedLink {
|
|
371 |
return $new_count;
|
372 |
} /* SyndicatedLink::poll() */
|
373 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
374 |
public function process_retirements ($delta) {
|
375 |
global $post;
|
376 |
|
@@ -1018,7 +1025,7 @@ class SyndicatedLink {
|
|
1018 |
// channel format is updated. Acceptable values are:
|
1019 |
// hourly, daily, weekly, monthly, yearly. If omitted,
|
1020 |
// daily is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
|
1021 |
-
if (isset($channel['sy']['updateperiod'])) : $period = $channel['sy']['updateperiod'];
|
1022 |
else : $period = 'daily';
|
1023 |
endif;
|
1024 |
|
@@ -1031,8 +1038,16 @@ class SyndicatedLink {
|
|
1031 |
else : $freq = 1;
|
1032 |
endif;
|
1033 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1034 |
$xml = 'sy:updateFrequency';
|
1035 |
-
$ret = (int) ($
|
|
|
1036 |
else :
|
1037 |
$xml = NULL;
|
1038 |
$ret = NULL;
|
175 |
$ttl = $this->automatic_ttl();
|
176 |
$ttl = apply_filters('syndicated_feed_ttl', $ttl, $this);
|
177 |
$ttl = apply_filters('syndicated_feed_ttl_from_error', $ttl, $this);
|
178 |
+
$this->update_setting('update/ttl', $ttl);
|
179 |
$this->update_setting('update/timed', 'automatically');
|
180 |
endif;
|
181 |
|
189 |
// Success; clear out error setting, if any.
|
190 |
$this->update_setting('update/error', NULL);
|
191 |
|
192 |
+
$new_count = array('new' => 0, 'updated' => 0, 'stored' => 0);
|
193 |
|
194 |
# -- Update Link metadata live from feed
|
195 |
$channel = $this->magpie->channel;
|
220 |
$this->merge_settings($channel, 'feed/');
|
221 |
|
222 |
$this->update_setting('update/last', time());
|
223 |
+
$this->do_update_ttl();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
|
225 |
if (!$this->setting('update/hold') != 'ping') :
|
226 |
$this->update_setting('update/hold', 'scheduled');
|
354 |
return $new_count;
|
355 |
} /* SyndicatedLink::poll() */
|
356 |
|
357 |
+
public function do_update_ttl () {
|
358 |
+
list($ttl, $xml) = $this->ttl(/*return element=*/ true);
|
359 |
+
|
360 |
+
if (!is_null($ttl)) :
|
361 |
+
$this->update_setting('update/ttl', $ttl);
|
362 |
+
$this->update_setting('update/xml', $xml);
|
363 |
+
$this->update_setting('update/timed', 'feed');
|
364 |
+
else :
|
365 |
+
$ttl = $this->automatic_ttl();
|
366 |
+
$this->update_setting('update/ttl', $ttl);
|
367 |
+
$this->update_setting('update/xml', NULL);
|
368 |
+
$this->update_setting('update/timed', 'automatically');
|
369 |
+
endif;
|
370 |
+
|
371 |
+
$this->update_setting('update/fudge', rand(0, ($ttl/3))*60);
|
372 |
+
|
373 |
+
$this->update_setting('update/ttl', apply_filters(
|
374 |
+
'syndicated_feed_ttl',
|
375 |
+
$this->setting('update/ttl'),
|
376 |
+
$this
|
377 |
+
));
|
378 |
+
|
379 |
+
} /* SyndicatedLink::do_update_ttl () */
|
380 |
+
|
381 |
public function process_retirements ($delta) {
|
382 |
global $post;
|
383 |
|
1025 |
// channel format is updated. Acceptable values are:
|
1026 |
// hourly, daily, weekly, monthly, yearly. If omitted,
|
1027 |
// daily is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
|
1028 |
+
if (isset($channel['sy']['updateperiod'])) : $period = trim($channel['sy']['updateperiod']);
|
1029 |
else : $period = 'daily';
|
1030 |
endif;
|
1031 |
|
1038 |
else : $freq = 1;
|
1039 |
endif;
|
1040 |
|
1041 |
+
// normalize the period name...
|
1042 |
+
$period = strtolower(trim($period));
|
1043 |
+
|
1044 |
+
// do we recognize the alphanumeric period name? if not, then guess
|
1045 |
+
// a responsible default, e.g. roughly hourly
|
1046 |
+
$mins = (isset($period_minutes[$period]) ? $period_minutes[$period] : 67);
|
1047 |
+
|
1048 |
$xml = 'sy:updateFrequency';
|
1049 |
+
$ret = (int) ($mins / $freq);
|
1050 |
+
|
1051 |
else :
|
1052 |
$xml = NULL;
|
1053 |
$ret = NULL;
|
@@ -163,6 +163,9 @@ class SyndicatedPost {
|
|
163 |
endforeach;
|
164 |
|
165 |
foreach ($postMetaOut as $key => $values) :
|
|
|
|
|
|
|
166 |
$this->post['meta'][$key] = array();
|
167 |
foreach ($values as $value) :
|
168 |
$this->post['meta'][$key][] = apply_filters("syndicated_post_meta_{$key}", $value, $this);
|
@@ -557,7 +560,7 @@ class SyndicatedPost {
|
|
557 |
endif;
|
558 |
|
559 |
if (!$unfiltered) :
|
560 |
-
apply_filters('syndicated_item_updated', $ts, $this);
|
561 |
endif;
|
562 |
return $ts;
|
563 |
} /* SyndicatedPost::updated() */
|
@@ -705,7 +708,7 @@ class SyndicatedPost {
|
|
705 |
$author = array ();
|
706 |
|
707 |
$aa = $this->entry->get_authors();
|
708 |
-
if (count($aa) > 0) :
|
709 |
$a = reset($aa);
|
710 |
|
711 |
$author = array(
|
@@ -903,7 +906,7 @@ class SyndicatedPost {
|
|
903 |
$content = $this->content();
|
904 |
$pattern = FeedWordPressHTML::tagWithAttributeRegex('a', 'rel', 'tag');
|
905 |
preg_match_all($pattern, $content, $refs, PREG_SET_ORDER);
|
906 |
-
if (count($refs) > 0) :
|
907 |
foreach ($refs as $ref) :
|
908 |
$tag = FeedWordPressHTML::tagWithAttributeMatch($ref);
|
909 |
$tags[] = $tag['content'];
|
@@ -1301,7 +1304,7 @@ class SyndicatedPost {
|
|
1301 |
// Or the hash...
|
1302 |
$hash = $this->update_hash();
|
1303 |
$seen = $this->stored_hashes($old_post->ID);
|
1304 |
-
if (count($seen) > 0) :
|
1305 |
$updated = !in_array($hash, $seen); // Not seen yet?
|
1306 |
else :
|
1307 |
$updated = true; // Can't find syndication meta-data
|
163 |
endforeach;
|
164 |
|
165 |
foreach ($postMetaOut as $key => $values) :
|
166 |
+
if (is_null($values)) { // have chosen to replace value with empty string
|
167 |
+
$values = [''];
|
168 |
+
}
|
169 |
$this->post['meta'][$key] = array();
|
170 |
foreach ($values as $value) :
|
171 |
$this->post['meta'][$key][] = apply_filters("syndicated_post_meta_{$key}", $value, $this);
|
560 |
endif;
|
561 |
|
562 |
if (!$unfiltered) :
|
563 |
+
$ts = apply_filters('syndicated_item_updated', $ts, $this);
|
564 |
endif;
|
565 |
return $ts;
|
566 |
} /* SyndicatedPost::updated() */
|
708 |
$author = array ();
|
709 |
|
710 |
$aa = $this->entry->get_authors();
|
711 |
+
if (is_countable($aa) and count($aa) > 0) :
|
712 |
$a = reset($aa);
|
713 |
|
714 |
$author = array(
|
906 |
$content = $this->content();
|
907 |
$pattern = FeedWordPressHTML::tagWithAttributeRegex('a', 'rel', 'tag');
|
908 |
preg_match_all($pattern, $content, $refs, PREG_SET_ORDER);
|
909 |
+
if (is_countable($refs) and count($refs) > 0) :
|
910 |
foreach ($refs as $ref) :
|
911 |
$tag = FeedWordPressHTML::tagWithAttributeMatch($ref);
|
912 |
$tags[] = $tag['content'];
|
1304 |
// Or the hash...
|
1305 |
$hash = $this->update_hash();
|
1306 |
$seen = $this->stored_hashes($old_post->ID);
|
1307 |
+
if (is_countable($seen) and count($seen) > 0) :
|
1308 |
$updated = !in_array($hash, $seen); // Not seen yet?
|
1309 |
else :
|
1310 |
$updated = true; // Can't find syndication meta-data
|
@@ -17,6 +17,17 @@ function is_syndicated ($id = NULL) {
|
|
17 |
return $p->is_syndicated();
|
18 |
} /* function is_syndicated() */
|
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
function feedwordpress_display_url ($url, $before = 60, $after = 0) {
|
21 |
$bits = parse_url($url);
|
22 |
|
17 |
return $p->is_syndicated();
|
18 |
} /* function is_syndicated() */
|
19 |
|
20 |
+
/**
|
21 |
+
* feedwordpress_display_url: format a fully-formed URL for display in the
|
22 |
+
* FeedWordPress admin interface, abbreviating it (e.g.: input of
|
23 |
+
* `http://feedwordpress.radgeek.com/feed/` will be shortened to
|
24 |
+
* `feedwordpress.radgeek.com/feed/`)
|
25 |
+
*
|
26 |
+
* @param string $url provides the URL to display
|
27 |
+
* @param int $before a number of characters to preserve from the beginning of the URL if it must be shortened
|
28 |
+
* @param int $after a number of characters to preserve from the end of the URL if it must be shortened
|
29 |
+
* @return string containing an abbreviated display form of the URL (e.g.: `feedwordpress.radgeek.net/feed`)
|
30 |
+
*/
|
31 |
function feedwordpress_display_url ($url, $before = 60, $after = 0) {
|
32 |
$bits = parse_url($url);
|
33 |
|