Version Description
(2016-06-14) = * Fixed bug: Potential security vulnerability related to triggering feed update. * Fixed bug: Error output on Feed Sources list is trimmed and cannot break the page layout. * Fixed bug: Certain notices could not be dismissed. * Fixed bug: Word trimming didn't always trim correctly with HTML. * Enhanced: Visual improvements.
Download this release
Release Info
Developer | markzahra |
Plugin | WP RSS Aggregator |
Version | 4.9 |
Comparing to | |
See all releases |
Code changes from version 4.8.2 to 4.9
- css/admin-styles.css +23 -1
- includes/Aventura/Wprss/Core/Block/AbstractBlock.php +29 -0
- includes/Aventura/Wprss/Core/Block/BlockInterface.php +20 -0
- includes/Aventura/Wprss/Core/Block/Html/AbstractHtml.php +160 -0
- includes/Aventura/Wprss/Core/Block/Html/AbstractTag.php +82 -0
- includes/Aventura/Wprss/Core/Block/Html/Anchor.php +29 -0
- includes/Aventura/Wprss/Core/Block/Html/TagInterface.php +54 -0
- includes/Aventura/Wprss/Core/DataObject.php +21 -1
- includes/Aventura/Wprss/Core/Http/Message/AbstractResponse.php +32 -0
- includes/Aventura/Wprss/Core/Http/Message/Ajax/AbstractResponse.php +90 -0
- includes/Aventura/Wprss/Core/Http/Message/Ajax/AjaxInterface.php +38 -0
- includes/Aventura/Wprss/Core/Http/Message/Ajax/Response.php +12 -0
- includes/Aventura/Wprss/Core/Http/Message/MessageInterface.php +16 -0
- includes/Aventura/Wprss/Core/Http/Message/ResponseInterface.php +12 -0
- includes/Aventura/Wprss/Core/Licensing/Manager.php +0 -1
- includes/Aventura/Wprss/Core/Model/AjaxResponse.php +68 -0
- includes/Aventura/Wprss/Core/Model/ModelAbstract.php +23 -1
- includes/Aventura/Wprss/Core/Plugin.php +127 -3
- includes/Aventura/Wprss/Core/Plugin/PluginAbstract.php +38 -8
- includes/admin-addons.php +1 -1
- includes/admin-ajax-notice.php +16 -5
- includes/admin-display.php +41 -13
- includes/admin-help.php +1 -1
- includes/custom-post-types.php +2 -1
- includes/feed-access.php +61 -55
- includes/feed-importing.php +6 -5
- includes/misc-functions.php +23 -2
- js/admin-custom.js +35 -14
- js/admin-help.js +3 -1
- nbproject/project.properties +0 -7
- nbproject/project.xml +0 -9
- readme.txt +77 -48
- wp-rss-aggregator.php +3 -3
css/admin-styles.css
CHANGED
@@ -621,6 +621,20 @@ body.post-type-wprss_blacklist .alignleft.actions.bulkactions {
|
|
621 |
margin: 0;
|
622 |
}
|
623 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
624 |
|
625 |
|
626 |
/* Admin Notifications ====================================================== */
|
@@ -710,4 +724,12 @@ body.post-type-wprss_blacklist .alignleft.actions.bulkactions {
|
|
710 |
.wprss-tr-hr th {
|
711 |
padding-top: 10px;
|
712 |
}
|
713 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
621 |
margin: 0;
|
622 |
}
|
623 |
|
624 |
+
.wprss-section-tooltip-handle,
|
625 |
+
.wprss-section-tooltip-handle:hover,
|
626 |
+
.wprss-section-tooltip-handle:active,
|
627 |
+
.wprss-section-tooltip-handle:visited,
|
628 |
+
.wprss-section-tooltip-handle:link,
|
629 |
+
.wprss-section-tooltip-handle:focus {
|
630 |
+
color: #006799;
|
631 |
+
margin-left: 5px;
|
632 |
+
text-decoration: none;
|
633 |
+
outline: none;
|
634 |
+
cursor: help;
|
635 |
+
font-size: 15px;
|
636 |
+
}
|
637 |
+
|
638 |
|
639 |
|
640 |
/* Admin Notifications ====================================================== */
|
724 |
.wprss-tr-hr th {
|
725 |
padding-top: 10px;
|
726 |
}
|
727 |
+
}
|
728 |
+
|
729 |
+
.ajax-error,
|
730 |
+
.ajax-error:hover,
|
731 |
+
.ajax-error:visited,
|
732 |
+
.ajax-error:link,
|
733 |
+
.ajax-error:active {
|
734 |
+
color: #a00;
|
735 |
+
}
|
includes/Aventura/Wprss/Core/Block/AbstractBlock.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Block;
|
4 |
+
|
5 |
+
use Aventura\Wprss\Core;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Basic functionality for all blocks.
|
9 |
+
*
|
10 |
+
* @since 4.9
|
11 |
+
*/
|
12 |
+
abstract class AbstractBlock extends Core\Model\ModelAbstract implements BlockInterface
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* {@inheritdoc}
|
16 |
+
* @since 4.9
|
17 |
+
*/
|
18 |
+
public function __toString() {
|
19 |
+
return $this->getOutput();
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* A more structured way of retrieving this block's output.
|
24 |
+
*
|
25 |
+
* @since 4.9
|
26 |
+
* @return string Output generated by this block.
|
27 |
+
*/
|
28 |
+
abstract public function getOutput();
|
29 |
+
}
|
includes/Aventura/Wprss/Core/Block/BlockInterface.php
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aventura\Wprss\Core\Block;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Something that can be a block.
|
6 |
+
*
|
7 |
+
* A block is a class that is responsible for generating output.
|
8 |
+
*
|
9 |
+
* @since 4.9
|
10 |
+
*/
|
11 |
+
interface BlockInterface {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Retrieve the string output of this block.
|
15 |
+
*
|
16 |
+
* @since 4.9
|
17 |
+
* @return string The output generated by this block.
|
18 |
+
*/
|
19 |
+
public function __toString();
|
20 |
+
}
|
includes/Aventura/Wprss/Core/Block/Html/AbstractHtml.php
ADDED
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Block\Html;
|
4 |
+
use Aventura\Wprss\Core\Block;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Something that generates HTML output.
|
8 |
+
*
|
9 |
+
* @since 4.9
|
10 |
+
*/
|
11 |
+
abstract class AbstractHtml extends Block\AbstractBlock
|
12 |
+
{
|
13 |
+
const QUOTE_SINGLE = "'";
|
14 |
+
const QUOTE_DOUBLE = '"';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Get the quote that this class will use to surround attribute values.
|
18 |
+
*
|
19 |
+
* @since 4.9
|
20 |
+
* @return string The string that will surround an HTML attribute value.
|
21 |
+
*/
|
22 |
+
public static function getAttributeQuote()
|
23 |
+
{
|
24 |
+
return static::QUOTE_DOUBLE;
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Generate an attribute-value pair string.
|
29 |
+
*
|
30 |
+
* This string is intended to be part of an HTML tag.
|
31 |
+
*
|
32 |
+
* @since 4.9
|
33 |
+
* @param string $name The attribute name.
|
34 |
+
* @param string $value The attribute value.
|
35 |
+
* @param null|string $surround The quote symbol to use to surround the
|
36 |
+
* attribute value.
|
37 |
+
* @return string A string that represents an HTML tag's attribute-value
|
38 |
+
* pair.
|
39 |
+
*/
|
40 |
+
public static function getAttributePairString($name, $value = '', $surround = null)
|
41 |
+
{
|
42 |
+
$surround = static::defaultParam($surround, static::getAttributeQuote());
|
43 |
+
return sprintf('%2$s=%1$s%3$s%1$s', $surround, $name, $value);
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Generate a string of attribute-value pairs.
|
48 |
+
*
|
49 |
+
* Intended to be used in an HTML tag.
|
50 |
+
*
|
51 |
+
* @since 4.9
|
52 |
+
* @see getAttributeQuote()
|
53 |
+
* @see getAttributeStringsArray()
|
54 |
+
* @param array $attributes An array of attributes, where key is attribute
|
55 |
+
* name, and value is attribute value.
|
56 |
+
* @param string|bool $escape If array, the values of only those attributes,
|
57 |
+
* the names of which are listed here, will be escaped.
|
58 |
+
* Othwewise, whether or not all attribute values will be escaped.
|
59 |
+
* @param string $surround The quote to use for surrounding the attribute
|
60 |
+
* value.
|
61 |
+
* One of the QUOTE_* constants.
|
62 |
+
* Default: What this class's getAttributeQuote() returns.
|
63 |
+
* @return string A string that consists of attribute-value pairs with
|
64 |
+
* spaces in between.
|
65 |
+
*/
|
66 |
+
public static function getAttributesStringFromArray($attributes = array(), $escape = true, $surround = null)
|
67 |
+
{
|
68 |
+
$surround = static::defaultParam($surround, static::getAttributeQuote());
|
69 |
+
return implode(' ', static::getAttributeStringsArray($attributes, $escape, $surround));
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Generates an array of attribute-value pair strings, by attribute name.
|
74 |
+
*
|
75 |
+
* @since 4.9
|
76 |
+
* @see getAttributeQuote()
|
77 |
+
* @see getAttributePairString()
|
78 |
+
* @see sanitizeAttributeName()
|
79 |
+
* @param array $attributes An array of attributes, where key is attribute
|
80 |
+
* name, and value is attribute value.
|
81 |
+
* @param string|bool $escape If array, the values of only those attributes,
|
82 |
+
* the names of which are listed here, will be escaped.
|
83 |
+
* Othwewise, whether or not all attribute values will be escaped.
|
84 |
+
* @param string $surround The quote to use for surrounding the attribute
|
85 |
+
* value.
|
86 |
+
* One of the QUOTE_* constants.
|
87 |
+
* Default: What this class's getAttributeQuote() returns.
|
88 |
+
* @return array An array, where keys are attribute names, and values are
|
89 |
+
* attribute-value pair strings, e.g. 'name="value"';
|
90 |
+
*/
|
91 |
+
public static function getAttributeStringsArray($attributes = array(), $escape = true, $surround = null)
|
92 |
+
{
|
93 |
+
$surround = static::defaultParam($surround, static::getAttributeQuote());
|
94 |
+
|
95 |
+
// Allow a single attribute
|
96 |
+
if (is_string($escape)) {
|
97 |
+
$escape = (array) $escape;
|
98 |
+
}
|
99 |
+
|
100 |
+
$attrStrings = array();
|
101 |
+
foreach( $attributes as $_key => $_value ) {
|
102 |
+
$key = $_key;
|
103 |
+
|
104 |
+
// Should we standardize?
|
105 |
+
$isEscape = is_array($escape)
|
106 |
+
? in_array($_key, $escape) // Array with keys to standardize
|
107 |
+
: (bool) $escape; // Same for all
|
108 |
+
|
109 |
+
// Cleaning attribute name and value
|
110 |
+
if ($isEscape) {
|
111 |
+
$key = static::sanitizeAttributeName($_key);
|
112 |
+
$_value = static::escapeAttributeValue($_value, $surround);
|
113 |
+
}
|
114 |
+
|
115 |
+
$attrStrings[$key] = static::getAttributePairString($key, $_value, $surround);
|
116 |
+
}
|
117 |
+
|
118 |
+
return $attrStrings;
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Sanitizes an HTML tag's attribute name.
|
123 |
+
*
|
124 |
+
* Result will not contain white space before or after the name.
|
125 |
+
*
|
126 |
+
* @since 4.9
|
127 |
+
* @param string $attribute The attribute name to sanitize.
|
128 |
+
* @return string A valid attribute name.
|
129 |
+
*/
|
130 |
+
public static function sanitizeAttributeName($attribute)
|
131 |
+
{
|
132 |
+
return trim($attribute);
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Escapes an HTML tag's attribute value.
|
137 |
+
*
|
138 |
+
* If single quote is used to surround the value, only single quotes in the
|
139 |
+
* value will be escaped.
|
140 |
+
* Othwewise, all quotes in the value will be escaped.
|
141 |
+
*
|
142 |
+
* @since 4.9
|
143 |
+
* @see htmlspecialchars()
|
144 |
+
* @param type $attribute
|
145 |
+
* @param string $quote The quote that is used for surrounding the attribute
|
146 |
+
* value.
|
147 |
+
* Default: What this class's getAttributeQuote() returns.
|
148 |
+
* @return string An attribute value that is valid for insertion into an
|
149 |
+
* HTML document.
|
150 |
+
*/
|
151 |
+
public static function escapeAttributeValue($attribute, $quote = null)
|
152 |
+
{
|
153 |
+
$quote = static::defaultParam($quote, static::getAttributeQuote());
|
154 |
+
|
155 |
+
$quoteStyle = $quote === static::QUOTE_SINGLE
|
156 |
+
? ENT_QUOTES
|
157 |
+
: ENT_COMPAT;
|
158 |
+
return htmlspecialchars($attribute, $quoteStyle);
|
159 |
+
}
|
160 |
+
}
|
includes/Aventura/Wprss/Core/Block/Html/AbstractTag.php
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Block\Html;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Base functionlity for HTML tags.
|
7 |
+
*
|
8 |
+
* @since 4.9
|
9 |
+
*/
|
10 |
+
abstract class AbstractTag extends AbstractHtml implements TagInterface
|
11 |
+
{
|
12 |
+
const TAG_NAME = 'div';
|
13 |
+
|
14 |
+
const K_CONTENT = 'content';
|
15 |
+
const K_BASE_NAMESPACE_DEPTH = 'base_namespace_depth';
|
16 |
+
|
17 |
+
/**
|
18 |
+
* {@inheritdoc}
|
19 |
+
*
|
20 |
+
* @since 4.9
|
21 |
+
*/
|
22 |
+
public function getAttributes($attributes = false)
|
23 |
+
{
|
24 |
+
return !empty($attributes) && is_array($attributes)
|
25 |
+
? $this->getDataForKeys($attributes)
|
26 |
+
: $this->getDataForKeys($this->_getNonAttributeKeys(), true);
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* {@inheritdoc}
|
31 |
+
*
|
32 |
+
* @since 4.9
|
33 |
+
*/
|
34 |
+
public function setAttributes($attributes)
|
35 |
+
{
|
36 |
+
$this->addData($attributes);
|
37 |
+
return $this;
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Gets names of data keys which do not count as attribute names.
|
42 |
+
*
|
43 |
+
* @since 4.9
|
44 |
+
* @return array A numeric array of key names.
|
45 |
+
*/
|
46 |
+
protected function _getNonAttributeKeys()
|
47 |
+
{
|
48 |
+
return array(static::K_CONTENT, static::K_BASE_NAMESPACE_DEPTH);
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* {@inheritdoc}
|
53 |
+
*
|
54 |
+
* @since 4.9
|
55 |
+
* @return string This tag's content.
|
56 |
+
*/
|
57 |
+
public function getContent()
|
58 |
+
{
|
59 |
+
return $this->getData(static::K_CONTENT);
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* {@inheritdoc}
|
64 |
+
*
|
65 |
+
* @since 4.9
|
66 |
+
*/
|
67 |
+
public function setContent($content)
|
68 |
+
{
|
69 |
+
$this->setData(static::K_CONTENT, $content);
|
70 |
+
return $this;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* {@inheritdoc}
|
75 |
+
*
|
76 |
+
* @since 4.9
|
77 |
+
*/
|
78 |
+
public function getTagName()
|
79 |
+
{
|
80 |
+
return static::TAG_NAME;
|
81 |
+
}
|
82 |
+
}
|
includes/Aventura/Wprss/Core/Block/Html/Anchor.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Aventura\Wprss\Core\Block\Html;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Represents an HTML anchor (link).
|
6 |
+
*
|
7 |
+
* @since 4.9
|
8 |
+
*/
|
9 |
+
class Anchor extends AbstractTag
|
10 |
+
{
|
11 |
+
const TAG_NAME = 'a';
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Renders the anchor HTML.
|
15 |
+
*
|
16 |
+
* @since 4.9
|
17 |
+
*/
|
18 |
+
public function getOutput()
|
19 |
+
{
|
20 |
+
$attributes = $this->getAttributes();
|
21 |
+
$attributes = count($attributes)
|
22 |
+
? ' '.static::getAttributesStringFromArray($attributes)
|
23 |
+
: '';
|
24 |
+
$content = $this->getContent();
|
25 |
+
$tagName = $this->getTagName();
|
26 |
+
|
27 |
+
return sprintf('<%1$s%2$s>%3$s</%1$s>', $tagName, $attributes, $content);
|
28 |
+
}
|
29 |
+
}
|
includes/Aventura/Wprss/Core/Block/Html/TagInterface.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Block\Html;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Something that can be an HTML tag.
|
7 |
+
*
|
8 |
+
* @since 4.9
|
9 |
+
*/
|
10 |
+
interface TagInterface
|
11 |
+
{
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Retrieve an array of attributes.
|
15 |
+
*
|
16 |
+
* Keys are attribute names, values are attribute values.
|
17 |
+
*
|
18 |
+
* @param array|bool If is a non-empty array, will return attribute values
|
19 |
+
* for attributes in that array; Otherwise, return all attributes.
|
20 |
+
* @since 4.9
|
21 |
+
*/
|
22 |
+
public function getAttributes($attributes);
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Set attributes.
|
26 |
+
*
|
27 |
+
* Will set attributes to those specified in this array. Existing values
|
28 |
+
* remain.
|
29 |
+
*
|
30 |
+
* @since 4.9
|
31 |
+
*/
|
32 |
+
public function setAttributes($attributes);
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Get content of the tag.
|
36 |
+
*
|
37 |
+
* @since 4.9
|
38 |
+
*/
|
39 |
+
public function getContent();
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Set content of the tag.
|
43 |
+
*
|
44 |
+
* @since 4.9
|
45 |
+
*/
|
46 |
+
public function setContent($content);
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Get name of the tag.
|
50 |
+
*
|
51 |
+
* @since 4.9
|
52 |
+
*/
|
53 |
+
public function getTagName();
|
54 |
+
}
|
includes/Aventura/Wprss/Core/DataObject.php
CHANGED
@@ -832,7 +832,7 @@ class DataObject implements \ArrayAccess, DataObjectInterface {
|
|
832 |
/**
|
833 |
* Enter description here...
|
834 |
*
|
835 |
-
|
836 |
* @param string $field
|
837 |
* @param boolean $flag
|
838 |
* @return Wp_Rss_SpinnerChief_Data_Object
|
@@ -852,6 +852,26 @@ class DataObject implements \ArrayAccess, DataObjectInterface {
|
|
852 |
}
|
853 |
return $this;
|
854 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
855 |
}
|
856 |
|
857 |
|
832 |
/**
|
833 |
* Enter description here...
|
834 |
*
|
835 |
+
* @since 4.8.1
|
836 |
* @param string $field
|
837 |
* @param boolean $flag
|
838 |
* @return Wp_Rss_SpinnerChief_Data_Object
|
852 |
}
|
853 |
return $this;
|
854 |
}
|
855 |
+
|
856 |
+
/**
|
857 |
+
* Gets data for keys that are specified.
|
858 |
+
*
|
859 |
+
* The second parameter inverts the check.
|
860 |
+
*
|
861 |
+
* @since 4.9
|
862 |
+
* @param string|array $keys A key or an array of keys to match.
|
863 |
+
* @param bool $exclude If true, returns elements which are not
|
864 |
+
* specified.
|
865 |
+
* @return array An array with elements that match the
|
866 |
+
* specified keys.
|
867 |
+
*/
|
868 |
+
public function getDataForKeys($keys, $exclude = false)
|
869 |
+
{
|
870 |
+
$keys = array_flip((array) $keys);
|
871 |
+
return $exclude
|
872 |
+
? array_diff_key($this->_data, $keys)
|
873 |
+
: array_intersect_key($this->_data, $keys);
|
874 |
+
}
|
875 |
}
|
876 |
|
877 |
|
includes/Aventura/Wprss/Core/Http/Message/AbstractResponse.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Http\Message;
|
4 |
+
|
5 |
+
use Aventura\Wprss\Core;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Base functionality for responses
|
9 |
+
*
|
10 |
+
* @since 4.9
|
11 |
+
*/
|
12 |
+
abstract class AbstractResponse extends Core\DataObject implements ResponseInterface
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* @since 4.9
|
16 |
+
*/
|
17 |
+
const K_BODY = 'body';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @since 4.9
|
21 |
+
*/
|
22 |
+
protected $body;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* {@inheritdoc}
|
26 |
+
* @since 4.9
|
27 |
+
*/
|
28 |
+
public function getBody()
|
29 |
+
{
|
30 |
+
return $this->getData(static::K_BODY);
|
31 |
+
}
|
32 |
+
}
|
includes/Aventura/Wprss/Core/Http/Message/Ajax/AbstractResponse.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Http\Message\Ajax;
|
4 |
+
|
5 |
+
use Aventura\Wprss\Core;
|
6 |
+
use Aventura\Wprss\Core\Http\Message;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* @since 4.9
|
10 |
+
*/
|
11 |
+
abstract class AbstractResponse extends Message\AbstractResponse implements Core\Http\Message\Ajax\AjaxInterface
|
12 |
+
{
|
13 |
+
/** @since 4.9 */
|
14 |
+
protected $ajaxData;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* {@inheritdoc}
|
18 |
+
*
|
19 |
+
* @since 4.9
|
20 |
+
* @see Core\DataObject::getData()
|
21 |
+
* @since 4.9
|
22 |
+
*/
|
23 |
+
public function getAjaxData($key = null) {
|
24 |
+
$this->_getAjaxData()->getData($key);
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* {@inheritdoc}
|
29 |
+
*
|
30 |
+
* @since 4.9
|
31 |
+
* @see Core\DataObject::addData()
|
32 |
+
* @param type $key
|
33 |
+
* @param type $value
|
34 |
+
* @return \Aventura\Wprss\Core\Http\Message\Ajax\AbstractResponse
|
35 |
+
*/
|
36 |
+
public function setAjaxData($key, $value = null) {
|
37 |
+
$data = $this->_getAjaxData();
|
38 |
+
is_array($key)
|
39 |
+
? $data->addData($key)
|
40 |
+
: $data->setData($key, $value);
|
41 |
+
return $this;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @since 4.9
|
46 |
+
* @return Core\DataObject
|
47 |
+
*/
|
48 |
+
protected function _getAjaxData()
|
49 |
+
{
|
50 |
+
if (is_null($this->ajaxData)) {
|
51 |
+
$this->ajaxData = new Core\DataObject();
|
52 |
+
}
|
53 |
+
|
54 |
+
return $this->ajaxData;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* {@inheritdoc}
|
59 |
+
*
|
60 |
+
* @since 4.9
|
61 |
+
* @return string
|
62 |
+
*/
|
63 |
+
public function getBody()
|
64 |
+
{
|
65 |
+
return ($body = $this->getData(static::K_BODY))
|
66 |
+
? $body
|
67 |
+
: static::convertToJson($this->_getAjaxData());
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Converts data in the passed object to a JSON representation.
|
72 |
+
*
|
73 |
+
* If a data object instance is used, will convert the object's data.
|
74 |
+
* If any other type, will convert the properties.
|
75 |
+
* If array, the array keys and values will represent the data.
|
76 |
+
*
|
77 |
+
* @since 4.9
|
78 |
+
* @param array|Core|Core\DataObjectInterface|object $object An object with data to convert.
|
79 |
+
* @return string The JSON-encoded data.
|
80 |
+
*/
|
81 |
+
public static function convertToJson($object)
|
82 |
+
{
|
83 |
+
$object = $object instanceof Core\DataObjectInterface
|
84 |
+
? $object->getData()
|
85 |
+
: (array) $object;
|
86 |
+
$json = json_encode($object);
|
87 |
+
|
88 |
+
return $json;
|
89 |
+
}
|
90 |
+
}
|
includes/Aventura/Wprss/Core/Http/Message/Ajax/AjaxInterface.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Http\Message\Ajax;
|
4 |
+
|
5 |
+
use Aventura\Wprss\Core;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @since 4.9
|
9 |
+
*/
|
10 |
+
interface AjaxInterface extends Core\Http\Message\ResponseInterface
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Set one or many AJAX data members.
|
14 |
+
*
|
15 |
+
* This is data particular to the AJAX response, and is separate from the
|
16 |
+
* message data.
|
17 |
+
*
|
18 |
+
* Existing keys will be preserved. Same keys will overwrite.
|
19 |
+
*
|
20 |
+
* @since 4.9
|
21 |
+
* @see Core\DataObjectInterface::setData()
|
22 |
+
* @param string|array $key The key to set the data for, or a data array,
|
23 |
+
* where keys are data keys, and values are data values. If array, the
|
24 |
+
* second parameter will be ignored.
|
25 |
+
* @param null|mixed $value The value to set for the key.
|
26 |
+
*/
|
27 |
+
public function setAjaxData($key, $value = null);
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Get one or all AJAX data members.
|
31 |
+
*
|
32 |
+
* @since 4.9
|
33 |
+
* @param string|null $key The key for which to get data. If null, an array
|
34 |
+
* containing all AJAX data is returned.
|
35 |
+
* @return array|mixed The data member value, or an array with all AJAX data.
|
36 |
+
*/
|
37 |
+
public function getAjaxData($key = null);
|
38 |
+
}
|
includes/Aventura/Wprss/Core/Http/Message/Ajax/Response.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Http\Message\Ajax;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* A concrete response, for easy use.
|
7 |
+
*
|
8 |
+
* @since 4.9
|
9 |
+
*/
|
10 |
+
class Response extends AbstractResponse
|
11 |
+
{
|
12 |
+
}
|
includes/Aventura/Wprss/Core/Http/Message/MessageInterface.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Http\Message;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @todo Substitute with PSR-7 interface.
|
7 |
+
* @since 4.9
|
8 |
+
* @link https://github.com/php-fig/http-message/blob/master/src/MessageInterface.php
|
9 |
+
*/
|
10 |
+
interface MessageInterface
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* @since 4.9
|
14 |
+
*/
|
15 |
+
public function getBody();
|
16 |
+
}
|
includes/Aventura/Wprss/Core/Http/Message/ResponseInterface.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Http\Message;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @todo Substitute with PSR-7 interface.
|
7 |
+
* @since 4.9
|
8 |
+
* @link https://github.com/php-fig/http-message/blob/master/src/ResponseInterface.php
|
9 |
+
*/
|
10 |
+
interface ResponseInterface
|
11 |
+
{
|
12 |
+
}
|
includes/Aventura/Wprss/Core/Licensing/Manager.php
CHANGED
@@ -503,7 +503,6 @@ class Manager {
|
|
503 |
if ( $params['license'] instanceof License ) $params['license'] = $params['license']->getKey();
|
504 |
if ( $params['license'] ) $params['license'] = sanitize_text_field ( $params['license']);
|
505 |
if ( $params['item_name'] ) $params['item_name'] = sanitize_text_field ( $params['item_name']);
|
506 |
-
if ( $params['url'] ) $params['url'] = urlencode ( $params['url']);
|
507 |
|
508 |
// Send the request to the API
|
509 |
$response = wp_remote_post( add_query_arg( $params, $storeUrl ) );
|
503 |
if ( $params['license'] instanceof License ) $params['license'] = $params['license']->getKey();
|
504 |
if ( $params['license'] ) $params['license'] = sanitize_text_field ( $params['license']);
|
505 |
if ( $params['item_name'] ) $params['item_name'] = sanitize_text_field ( $params['item_name']);
|
|
|
506 |
|
507 |
// Send the request to the API
|
508 |
$response = wp_remote_post( add_query_arg( $params, $storeUrl ) );
|
includes/Aventura/Wprss/Core/Model/AjaxResponse.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Model;
|
4 |
+
|
5 |
+
use Aventura\Wprss\Core;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @since 4.9
|
9 |
+
*/
|
10 |
+
class AjaxResponse extends Core\Http\Message\Ajax\AbstractResponse
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* A convenient way to create an instance of this class which indicates that an exception has occurred.
|
14 |
+
*
|
15 |
+
* @since 4.9
|
16 |
+
* @param \Exception $e An exception, from which to take the response data.
|
17 |
+
* @return AjaxResponse A new instance with relevant data from the exception.
|
18 |
+
*/
|
19 |
+
public static function createFromException(\Exception $e)
|
20 |
+
{
|
21 |
+
$response = static::createFromError($e->getMessage())->setAjaxData(array(
|
22 |
+
'error_code' => $e->getCode()
|
23 |
+
));
|
24 |
+
|
25 |
+
if (static::isDebug()) {
|
26 |
+
$response->setAjaxData(array(
|
27 |
+
'debug_trace' => $e->getTrace(),
|
28 |
+
'debug_file' => $e->getFile(),
|
29 |
+
'debug_line' => $e->getLine()
|
30 |
+
));
|
31 |
+
}
|
32 |
+
|
33 |
+
return $response;
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* A convenient way to create an instance of this class whic indicates that an error has occurred.
|
38 |
+
*
|
39 |
+
* @since 4.9
|
40 |
+
* @param string $error Text of the error message.
|
41 |
+
* @return AjaxResponse A new instance with relevant error data.
|
42 |
+
*/
|
43 |
+
public static function createFromError($error)
|
44 |
+
{
|
45 |
+
$response = new static();
|
46 |
+
$response->setAjaxData(array(
|
47 |
+
'is_error' => true,
|
48 |
+
'error_message' => $error
|
49 |
+
));
|
50 |
+
|
51 |
+
return $response;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Determines if this class is in debug mode.
|
56 |
+
*
|
57 |
+
* In debug mode, extended information about exceptions will be added to
|
58 |
+
* instances generated from exceptions. This data may not be safe for
|
59 |
+
* displaying in production environments.
|
60 |
+
*
|
61 |
+
* @since 4.9
|
62 |
+
* @return bool True if debug mode is on for this class; false otherwise.
|
63 |
+
*/
|
64 |
+
public static function isDebug()
|
65 |
+
{
|
66 |
+
return WP_DEBUG;
|
67 |
+
}
|
68 |
+
}
|
includes/Aventura/Wprss/Core/Model/ModelAbstract.php
CHANGED
@@ -359,4 +359,26 @@ abstract class ModelAbstract extends Core\DataObject implements ModelInterface
|
|
359 |
{
|
360 |
return null;
|
361 |
}
|
362 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
359 |
{
|
360 |
return null;
|
361 |
}
|
362 |
+
|
363 |
+
/**
|
364 |
+
* Convenient wrapper for providing a default value to a parameter.
|
365 |
+
*
|
366 |
+
* Will return the default value if the parameter matches the criteria;
|
367 |
+
* otherwise, returns the parameter unchanged.
|
368 |
+
* The comparison is made in strict mode.
|
369 |
+
*
|
370 |
+
* @since 4.9
|
371 |
+
* @param mixed $param The actual value.
|
372 |
+
* @param mixed $default The default value.
|
373 |
+
* @param mixed $criteria The condition.
|
374 |
+
* @return mixed The parameter, or the default value.
|
375 |
+
*/
|
376 |
+
public static function defaultParam($param, $default, $criteria = null)
|
377 |
+
{
|
378 |
+
if ($param === $criteria) {
|
379 |
+
return $default;
|
380 |
+
}
|
381 |
+
|
382 |
+
return $param;
|
383 |
+
}
|
384 |
+
}
|
includes/Aventura/Wprss/Core/Plugin.php
CHANGED
@@ -3,13 +3,137 @@
|
|
3 |
namespace Aventura\Wprss\Core;
|
4 |
|
5 |
/**
|
6 |
-
*
|
7 |
*
|
8 |
* @since 4.8.1
|
9 |
-
* @todo Create real Core plugin in the Core plugin.
|
10 |
*/
|
11 |
class Plugin extends Plugin\PluginAbstract
|
12 |
{
|
13 |
const CODE = 'wprss';
|
14 |
const VERSION = WPRSS_VERSION;
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
namespace Aventura\Wprss\Core;
|
4 |
|
5 |
/**
|
6 |
+
* The Core instance of WP RSS Aggregator.
|
7 |
*
|
8 |
* @since 4.8.1
|
|
|
9 |
*/
|
10 |
class Plugin extends Plugin\PluginAbstract
|
11 |
{
|
12 |
const CODE = 'wprss';
|
13 |
const VERSION = WPRSS_VERSION;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Hooks the rest of the functionality of this class.
|
17 |
+
*
|
18 |
+
* @since 4.9
|
19 |
+
*/
|
20 |
+
public function hook()
|
21 |
+
{
|
22 |
+
$this->on('!plugins_loaded', array($this, 'delayedHook'));
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Hooks in functionality after all plugins are loaded.
|
27 |
+
*
|
28 |
+
* @since 4.9
|
29 |
+
*/
|
30 |
+
public function delayedHook()
|
31 |
+
{
|
32 |
+
$this->on('!plugin_row_meta', array($this, '_addPluginRowMeta'), null, 10, 2);
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Returns all meta members that appear below a plugin row in the backend.
|
37 |
+
*
|
38 |
+
* Handles `plugin_row_meta` WP native filter.
|
39 |
+
*
|
40 |
+
* @since 4.9
|
41 |
+
* @param type $meta
|
42 |
+
* @param type $pluginBasename
|
43 |
+
* @return array Numeric array, where each element is a meta information
|
44 |
+
* piece (usually link).
|
45 |
+
*/
|
46 |
+
public function _addPluginRowMeta($meta, $pluginBasename)
|
47 |
+
{
|
48 |
+
if ($pluginBasename !== $this->getBasename()) {
|
49 |
+
return $meta;
|
50 |
+
}
|
51 |
+
|
52 |
+
$meta = array_merge($meta, array_values($this->getPluginRowMeta()));
|
53 |
+
return $meta;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Returns a list of meta members for this plugin.
|
58 |
+
*
|
59 |
+
* Raises plugin-specific event `plugin_row_meta`.
|
60 |
+
*
|
61 |
+
* @since 4.9
|
62 |
+
* @return array An array of meta members for this plugin, by key.
|
63 |
+
*/
|
64 |
+
public function getPluginRowMeta()
|
65 |
+
{
|
66 |
+
return $this->event('plugin_row_meta', array('links' => array(
|
67 |
+
'getting_started' => $this->getAnchor(array(
|
68 |
+
'target' => '_blank',
|
69 |
+
'href' => 'https://docs.wprssaggregator.com/category/getting-started/'
|
70 |
+
), $this->__('Getting Started')),
|
71 |
+
'extensions' => $this->getAnchor(array(
|
72 |
+
'target' => '_blank',
|
73 |
+
'href' => 'https://www.wprssaggregator.com/extensions/'
|
74 |
+
), $this->__('Extensions'))
|
75 |
+
)))->getData('links');
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Get a new anchor block instance.
|
80 |
+
*
|
81 |
+
* @since 4.9
|
82 |
+
* @param array|string $attributes Keys are attribute names; values are attribute
|
83 |
+
* values. These will become the attributes of the anchor tag.
|
84 |
+
* If string, this will be treated as the value of the 'href' attribute.
|
85 |
+
* @param string $content Content for the anchor tag. Usually text.
|
86 |
+
* @return Block\Html\TagInterface An anchor block instance.
|
87 |
+
*/
|
88 |
+
public function getAnchor($attributes = array(), $content = '')
|
89 |
+
{
|
90 |
+
if (is_string($attributes)) {
|
91 |
+
$attributes = array('href' => $attributes);
|
92 |
+
}
|
93 |
+
$block = $this->createAnchorBlock()
|
94 |
+
->setAttributes($attributes)
|
95 |
+
->setContent($content);
|
96 |
+
|
97 |
+
return $block;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Anchor block factory.
|
102 |
+
*
|
103 |
+
* @since 4.9
|
104 |
+
* @return Aventura\Wprss\Core\Block\Html\TagInterface
|
105 |
+
*/
|
106 |
+
public function createAnchorBlock()
|
107 |
+
{
|
108 |
+
return new \Aventura\Wprss\Core\Block\Html\Anchor();
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Create an AJAX response instance that contains error data.
|
113 |
+
*
|
114 |
+
* @since 4.9
|
115 |
+
* @param \Exception|string $error An exception, or error message.
|
116 |
+
* @return Http\Message\Ajax\Response
|
117 |
+
*/
|
118 |
+
public function createAjaxErrorResponse($error)
|
119 |
+
{
|
120 |
+
return $error instanceof \Exception
|
121 |
+
? Model\AjaxResponse::createFromException($error)
|
122 |
+
: Model\AjaxResponse::createFromError($error);
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Creates an instance of an AJAX response.
|
127 |
+
*
|
128 |
+
* @since 4.9
|
129 |
+
* @param type $data
|
130 |
+
* @return Http\Message\Ajax\Response
|
131 |
+
*/
|
132 |
+
public function createAjaxResponse($data = array())
|
133 |
+
{
|
134 |
+
$response = new Model\AjaxResponse();
|
135 |
+
$response->setAjaxData($data);
|
136 |
+
|
137 |
+
return $response;
|
138 |
+
}
|
139 |
+
}
|
includes/Aventura/Wprss/Core/Plugin/PluginAbstract.php
CHANGED
@@ -45,13 +45,7 @@ class PluginAbstract extends Core\Model\ModelAbstract implements PluginInterface
|
|
45 |
if (!isset($data['basename'])) {
|
46 |
throw $this->exception('Could not create plugin instance: "basename" must be specified', array(__NAMESPACE__, 'Exception'));
|
47 |
}
|
48 |
-
$basename =
|
49 |
-
|
50 |
-
// Account for full path to main file.
|
51 |
-
if (substr($basename, 0, 1) === '/' || substr_count($basename, '/') >= 2) {
|
52 |
-
$basename = static::getPluginBasename($basename);
|
53 |
-
}
|
54 |
-
$data['basename'] = $basename;
|
55 |
|
56 |
// Normalizing and setting component factory
|
57 |
if (is_null($factory) && isset($data['component_factory'])) {
|
@@ -61,7 +55,6 @@ class PluginAbstract extends Core\Model\ModelAbstract implements PluginInterface
|
|
61 |
if ($factory) {
|
62 |
$this->setFactory($factory);
|
63 |
}
|
64 |
-
$this->setBasename($basename);
|
65 |
|
66 |
parent::__construct($data);
|
67 |
}
|
@@ -356,4 +349,41 @@ class PluginAbstract extends Core\Model\ModelAbstract implements PluginInterface
|
|
356 |
|
357 |
return null;
|
358 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
359 |
}
|
45 |
if (!isset($data['basename'])) {
|
46 |
throw $this->exception('Could not create plugin instance: "basename" must be specified', array(__NAMESPACE__, 'Exception'));
|
47 |
}
|
48 |
+
$data['basename'] = static::standardizeBasename($data['basename']);
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
|
50 |
// Normalizing and setting component factory
|
51 |
if (is_null($factory) && isset($data['component_factory'])) {
|
55 |
if ($factory) {
|
56 |
$this->setFactory($factory);
|
57 |
}
|
|
|
58 |
|
59 |
parent::__construct($data);
|
60 |
}
|
349 |
|
350 |
return null;
|
351 |
}
|
352 |
+
|
353 |
+
/**
|
354 |
+
* Converts all directory separators into Unix-style ones.
|
355 |
+
*
|
356 |
+
* @since 4.9
|
357 |
+
* @param string $path A filesystem path.
|
358 |
+
* @return The path with standardized directory separators, and trimmed
|
359 |
+
* whitespace.
|
360 |
+
*/
|
361 |
+
public static function standardizeDirectorySeparators($path)
|
362 |
+
{
|
363 |
+
return trim(str_replace(array('\\', '/'), '/', $path));
|
364 |
+
}
|
365 |
+
|
366 |
+
/**
|
367 |
+
* Will standardize a plugin basename.
|
368 |
+
*
|
369 |
+
* A standard plugin basename is a path to the main plugin file relative
|
370 |
+
* to the plugins directory, and with Unix directory separators if
|
371 |
+
* applicable.
|
372 |
+
*
|
373 |
+
* @since 4.9
|
374 |
+
* @see standardizeDirectorySeparators()
|
375 |
+
* @param string $path An absolute or relative path to a plugin main file.
|
376 |
+
* @return string A standardized plugin basename.
|
377 |
+
*/
|
378 |
+
public static function standardizeBasename($path)
|
379 |
+
{
|
380 |
+
$path = static::standardizeDirectorySeparators($path);
|
381 |
+
|
382 |
+
// Account for full path to main file.
|
383 |
+
if (substr($path, 0, 1) === '/' || substr_count($path, '/') >= 2) {
|
384 |
+
$path = static::getPluginBasename($path);
|
385 |
+
}
|
386 |
+
|
387 |
+
return $path;
|
388 |
+
}
|
389 |
}
|
includes/admin-addons.php
CHANGED
@@ -16,7 +16,7 @@
|
|
16 |
|
17 |
<h2><?php _e( 'Add-Ons', WPRSS_TEXT_DOMAIN ); ?></h2>
|
18 |
<p><?php _e( "The following Add-ons are available to increase the functionality of the WP RSS Aggregator plugin.", WPRSS_TEXT_DOMAIN ); ?><br />
|
19 |
-
<?php _e( "Each Add-on can be installed as a separate plugin.
|
20 |
|
21 |
<div id="add-ons" class="clearfix">
|
22 |
|
16 |
|
17 |
<h2><?php _e( 'Add-Ons', WPRSS_TEXT_DOMAIN ); ?></h2>
|
18 |
<p><?php _e( "The following Add-ons are available to increase the functionality of the WP RSS Aggregator plugin.", WPRSS_TEXT_DOMAIN ); ?><br />
|
19 |
+
<?php _e( "Each Add-on can be installed as a separate plugin.", WPRSS_TEXT_DOMAIN ); ?></p>
|
20 |
|
21 |
<div id="add-ons" class="clearfix">
|
22 |
|
includes/admin-ajax-notice.php
CHANGED
@@ -144,6 +144,12 @@
|
|
144 |
/**
|
145 |
* Responsible for tracking and outputting admin notices
|
146 |
*
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
* @since 4.7.4
|
148 |
*/
|
149 |
class WPRSS_Admin_Notices {
|
@@ -493,7 +499,7 @@ class WPRSS_Admin_Notices {
|
|
493 |
|
494 |
// Auto-generate ID
|
495 |
if ( is_null( $data['id'] ) )
|
496 |
-
$data['id'] = $this->generate_unique_id( 'admin-notice-' );
|
497 |
|
498 |
// Prefix ID
|
499 |
$data['id'] = $this->prefix( $data['id'] );
|
@@ -1006,14 +1012,18 @@ class WPRSS_Admin_Notices {
|
|
1006 |
* @param string $prefix The prefix to give to the generated ID.
|
1007 |
* @return string A notice ID unique to this instance in the scope of this collection.
|
1008 |
*/
|
1009 |
-
public function generate_unique_id( $prefix = '' ) {
|
1010 |
do {
|
1011 |
-
$id = uniqid( $prefix );
|
1012 |
} while ( $this->has_notice( $id ) );
|
1013 |
|
1014 |
return apply_filters( $this->prefix( 'admin_notice_generate_unique_id' ), $id, $prefix, $this );
|
1015 |
}
|
1016 |
|
|
|
|
|
|
|
|
|
1017 |
|
1018 |
/**
|
1019 |
* Generate the HTML for all allowed notices, sequentially.
|
@@ -1094,12 +1104,13 @@ class WPRSS_Admin_Notices {
|
|
1094 |
if ( is_array( $notice ) )
|
1095 |
$notice = isset( $notice['id'] ) ? $notice['id'] : null;
|
1096 |
|
|
|
1097 |
if ( is_null( $notice ) )
|
1098 |
throw new Exception( sprintf( 'Could not hide notice: Notice ID must be specified' ) );
|
1099 |
if ( is_null( $nonce ) )
|
1100 |
throw new Exception( sprintf( 'Could not hide notice: nonce must be specified' ) );
|
1101 |
if ( !($notice = $this->get_notices( $notice ) ) )
|
1102 |
-
throw new Exception( sprintf( 'Could not hide notice: No notice found for ID "%1$s"', $
|
1103 |
|
1104 |
// Is it the right nonce?
|
1105 |
if ( $notice['nonce'] !== $nonce )
|
@@ -1207,7 +1218,7 @@ function wprss_admin_notice_add( $notice ) {
|
|
1207 |
try {
|
1208 |
if ( !($collection = wprss_admin_notice_get_collection()) )
|
1209 |
return false;
|
1210 |
-
|
1211 |
$collection->add_notice( $notice );
|
1212 |
} catch ( Exception $e ) {
|
1213 |
return new WP_Error( 'could_not_add_admin_notice', $e->getMessage() );
|
144 |
/**
|
145 |
* Responsible for tracking and outputting admin notices
|
146 |
*
|
147 |
+
* Usage:
|
148 |
+
* Initialize by calling {@see init()} early, before `admin_init`. On `plugins_loaded`
|
149 |
+
* is a good place.
|
150 |
+
* Do not add notices conditionally. Instead, add them always, but specify
|
151 |
+
* the `condition` index to {@see add_notice()}.
|
152 |
+
*
|
153 |
* @since 4.7.4
|
154 |
*/
|
155 |
class WPRSS_Admin_Notices {
|
499 |
|
500 |
// Auto-generate ID
|
501 |
if ( is_null( $data['id'] ) )
|
502 |
+
$data['id'] = $this->generate_unique_id( 'admin-notice-', $data );
|
503 |
|
504 |
// Prefix ID
|
505 |
$data['id'] = $this->prefix( $data['id'] );
|
1012 |
* @param string $prefix The prefix to give to the generated ID.
|
1013 |
* @return string A notice ID unique to this instance in the scope of this collection.
|
1014 |
*/
|
1015 |
+
public function generate_unique_id( $prefix = '', $data = null ) {
|
1016 |
do {
|
1017 |
+
$id = is_null($data) ? uniqid( $prefix ) : $prefix . $this->hash($data);
|
1018 |
} while ( $this->has_notice( $id ) );
|
1019 |
|
1020 |
return apply_filters( $this->prefix( 'admin_notice_generate_unique_id' ), $id, $prefix, $this );
|
1021 |
}
|
1022 |
|
1023 |
+
public function hash($data) {
|
1024 |
+
return md5(serialize($data));
|
1025 |
+
}
|
1026 |
+
|
1027 |
|
1028 |
/**
|
1029 |
* Generate the HTML for all allowed notices, sequentially.
|
1104 |
if ( is_array( $notice ) )
|
1105 |
$notice = isset( $notice['id'] ) ? $notice['id'] : null;
|
1106 |
|
1107 |
+
$notice_id = $notice;
|
1108 |
if ( is_null( $notice ) )
|
1109 |
throw new Exception( sprintf( 'Could not hide notice: Notice ID must be specified' ) );
|
1110 |
if ( is_null( $nonce ) )
|
1111 |
throw new Exception( sprintf( 'Could not hide notice: nonce must be specified' ) );
|
1112 |
if ( !($notice = $this->get_notices( $notice ) ) )
|
1113 |
+
throw new Exception( sprintf( 'Could not hide notice: No notice found for ID "%1$s"', $notice_id ) );
|
1114 |
|
1115 |
// Is it the right nonce?
|
1116 |
if ( $notice['nonce'] !== $nonce )
|
1218 |
try {
|
1219 |
if ( !($collection = wprss_admin_notice_get_collection()) )
|
1220 |
return false;
|
1221 |
+
|
1222 |
$collection->add_notice( $notice );
|
1223 |
} catch ( Exception $e ) {
|
1224 |
return new WP_Error( 'could_not_add_admin_notice', $e->getMessage() );
|
includes/admin-display.php
CHANGED
@@ -354,6 +354,7 @@
|
|
354 |
|
355 |
$fetch_items_row_action_text = apply_filters( 'wprss_fetch_items_row_action_text', __( 'Fetch Items', WPRSS_TEXT_DOMAIN ) );
|
356 |
$actions[ 'fetch' ] = '<a href="javascript:;" class="wprss_ajax_action" pid="'. $post->ID .'" purl="'.home_url().'/wp-admin/admin-ajax.php">' . $fetch_items_row_action_text . '</a>';
|
|
|
357 |
|
358 |
$purge_feeds_row_action_text = apply_filters( 'wprss_purge_feeds_row_action_text', __( 'Delete Items', WPRSS_TEXT_DOMAIN ) );
|
359 |
$purge_feeds_row_action_title = apply_filters( 'wprss_purge_feeds_row_action_title', __( 'Delete feed items imported by this feed source', WPRSS_TEXT_DOMAIN ) );
|
@@ -456,9 +457,26 @@
|
|
456 |
* @since 3.3
|
457 |
*/
|
458 |
function wprss_fetch_feeds_action_hook() {
|
459 |
-
|
460 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
461 |
$id = $_POST['id'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
462 |
update_post_meta( $id, 'wprss_force_next_fetch', '1' );
|
463 |
|
464 |
// Prepare the schedule args
|
@@ -467,23 +485,33 @@
|
|
467 |
// Get the current schedule - do nothing if not scheduled
|
468 |
$next_scheduled = wp_next_scheduled( 'wprss_fetch_single_feed_hook', $schedule_args );
|
469 |
if ( $next_scheduled !== FALSE ) {
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
}
|
481 |
|
482 |
// Schedule the event for 5 seconds from now
|
483 |
wp_schedule_single_event( time() + 1, 'wprss_fetch_single_feed_hook', $schedule_args );
|
484 |
wprss_flag_feed_as_updating( $id );
|
485 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
486 |
}
|
|
|
|
|
|
|
|
|
487 |
}
|
488 |
|
489 |
|
354 |
|
355 |
$fetch_items_row_action_text = apply_filters( 'wprss_fetch_items_row_action_text', __( 'Fetch Items', WPRSS_TEXT_DOMAIN ) );
|
356 |
$actions[ 'fetch' ] = '<a href="javascript:;" class="wprss_ajax_action" pid="'. $post->ID .'" purl="'.home_url().'/wp-admin/admin-ajax.php">' . $fetch_items_row_action_text . '</a>';
|
357 |
+
$actions[ 'fetch' ] .= wp_nonce_field( sprintf( 'wprss-fetch-items-for-%s', $post->ID ) );
|
358 |
|
359 |
$purge_feeds_row_action_text = apply_filters( 'wprss_purge_feeds_row_action_text', __( 'Delete Items', WPRSS_TEXT_DOMAIN ) );
|
360 |
$purge_feeds_row_action_title = apply_filters( 'wprss_purge_feeds_row_action_title', __( 'Delete feed items imported by this feed source', WPRSS_TEXT_DOMAIN ) );
|
457 |
* @since 3.3
|
458 |
*/
|
459 |
function wprss_fetch_feeds_action_hook() {
|
460 |
+
$response = wprss()->createAjaxResponse();
|
461 |
+
$wprss = wprss();
|
462 |
+
$kFeedSourceId = 'feed_source_id';
|
463 |
+
try {
|
464 |
+
$kId = 'id';
|
465 |
+
if (!isset( $_POST[$kId] ) || empty( $_POST[$kId] )) {
|
466 |
+
throw new Exception($wprss->__('Could not schedule fetch: source ID must be specified'));
|
467 |
+
}
|
468 |
$id = $_POST['id'];
|
469 |
+
$response->setAjaxData($kFeedSourceId, $id);
|
470 |
+
|
471 |
+
if (!current_user_can('edit_feed_sources')) {
|
472 |
+
throw new Exception($wprss->__(array('Could not schedule fetch for source #%1$s: user must have sufficient priviledges', $id)));
|
473 |
+
}
|
474 |
+
|
475 |
+
// Verify admin referer
|
476 |
+
if (!wprss_verify_nonce( sprintf( 'wprss-fetch-items-for-%s', $id ), 'wprss_admin_ajax_nonce' )) {
|
477 |
+
throw new Exception($wprss->__(array('Could not schedule fetch for source #%1$s: nonce is expired', $id)));
|
478 |
+
}
|
479 |
+
|
480 |
update_post_meta( $id, 'wprss_force_next_fetch', '1' );
|
481 |
|
482 |
// Prepare the schedule args
|
485 |
// Get the current schedule - do nothing if not scheduled
|
486 |
$next_scheduled = wp_next_scheduled( 'wprss_fetch_single_feed_hook', $schedule_args );
|
487 |
if ( $next_scheduled !== FALSE ) {
|
488 |
+
// If scheduled, unschedule it
|
489 |
+
wp_unschedule_event( $next_scheduled, 'wprss_fetch_single_feed_hook', $schedule_args );
|
490 |
+
|
491 |
+
// Get the interval option for the feed source
|
492 |
+
$interval = get_post_meta( $id, 'wprss_update_interval', TRUE );
|
493 |
+
// if the feed source uses its own interval
|
494 |
+
if ( $interval !== '' && $interval !== wprss_get_default_feed_source_update_interval() ) {
|
495 |
+
// Add meta in feed source. This is used to notify the source that it needs to reschedule it
|
496 |
+
update_post_meta( $id, 'wprss_reschedule_event', $next_scheduled );
|
497 |
+
}
|
498 |
}
|
499 |
|
500 |
// Schedule the event for 5 seconds from now
|
501 |
wp_schedule_single_event( time() + 1, 'wprss_fetch_single_feed_hook', $schedule_args );
|
502 |
wprss_flag_feed_as_updating( $id );
|
503 |
+
} catch (Exception $e) {
|
504 |
+
$response = wprss()->createAjaxErrorResponse($e);
|
505 |
+
if (isset($id)) {
|
506 |
+
$response->setAjaxData($kFeedSourceId, $id);
|
507 |
+
}
|
508 |
+
echo $response->getBody();
|
509 |
+
exit();
|
510 |
}
|
511 |
+
|
512 |
+
$response->setAjaxData('message', $wprss->__(array('Fetch for feed source #%1$s successfully scheduled', $id)));
|
513 |
+
echo $response->getBody();
|
514 |
+
exit();
|
515 |
}
|
516 |
|
517 |
|
includes/admin-help.php
CHANGED
@@ -132,7 +132,7 @@
|
|
132 |
</form>
|
133 |
<div style='line-height:2.3em; margin-top:10px;'>
|
134 |
<button id='send-message-btn' class='button button-primary'><?php _e('Send Message', WPRSS_TEXT_DOMAIN); ?></button>
|
135 |
-
<
|
136 |
</div>
|
137 |
|
138 |
<?php
|
132 |
</form>
|
133 |
<div style='line-height:2.3em; margin-top:10px;'>
|
134 |
<button id='send-message-btn' class='button button-primary'><?php _e('Send Message', WPRSS_TEXT_DOMAIN); ?></button>
|
135 |
+
<div id='support-error'></div>
|
136 |
</div>
|
137 |
|
138 |
<?php
|
includes/custom-post-types.php
CHANGED
@@ -54,7 +54,8 @@
|
|
54 |
'capability_type' => 'feed',
|
55 |
'map_meta_cap' => true,
|
56 |
'supports' => array( 'title' ),
|
57 |
-
'labels' => $labels
|
|
|
58 |
)
|
59 |
);
|
60 |
|
54 |
'capability_type' => 'feed',
|
55 |
'map_meta_cap' => true,
|
56 |
'supports' => array( 'title' ),
|
57 |
+
'labels' => $labels,
|
58 |
+
'menu_icon' => 'dashicons-rss'
|
59 |
)
|
60 |
);
|
61 |
|
includes/feed-access.php
CHANGED
@@ -3,18 +3,18 @@
|
|
3 |
|
4 |
/**
|
5 |
* Centralizes control over resource fetching.
|
6 |
-
*
|
7 |
* @since 4.7
|
8 |
*/
|
9 |
class WPRSS_Feed_Access {
|
10 |
-
|
11 |
protected static $_instance;
|
12 |
-
|
13 |
protected $_certificate_file_path;
|
14 |
-
|
15 |
const SETTING_KEY_CERTIFICATE_PATH = 'certificate-path';
|
16 |
const SETTING_KEY_FEED_REQUEST_USERAGENT = 'feed_request_useragent';
|
17 |
-
|
18 |
/**
|
19 |
* @since 4.7
|
20 |
* @return WPRSS_Feed_Access The singleton instance of this class.
|
@@ -24,19 +24,19 @@ class WPRSS_Feed_Access {
|
|
24 |
$class_name = __CLASS__;
|
25 |
self::$_instance = new $class_name;
|
26 |
}
|
27 |
-
|
28 |
return self::$_instance;
|
29 |
}
|
30 |
-
|
31 |
-
|
32 |
public function __construct() {
|
33 |
$this->_construct();
|
34 |
}
|
35 |
-
|
36 |
-
|
37 |
/**
|
38 |
* The parameter-less constructor.
|
39 |
-
*
|
40 |
* @since 4.7
|
41 |
*/
|
42 |
protected function _construct() {
|
@@ -44,11 +44,11 @@ class WPRSS_Feed_Access {
|
|
44 |
add_action( 'wprss_settings_array', array( $this, 'add_settings' ) );
|
45 |
add_action( 'wprss_default_settings_general', array( $this, 'add_default_settings' ) );
|
46 |
}
|
47 |
-
|
48 |
-
|
49 |
/**
|
50 |
* Sets the path to the certificate, which will be used by WPRSS to fetch remote content.
|
51 |
-
*
|
52 |
* @since 4.7
|
53 |
* @param string $path Absolute path to the certificate file.
|
54 |
* @return \WPRSS_Feed_Access This instance.
|
@@ -57,11 +57,11 @@ class WPRSS_Feed_Access {
|
|
57 |
$this->_certificate_file_path = $path;
|
58 |
return $this;
|
59 |
}
|
60 |
-
|
61 |
-
|
62 |
/**
|
63 |
* Gets the path to the certificate, which will be used by WPRSS to fetch remote content.
|
64 |
-
*
|
65 |
* @since 4.7
|
66 |
* @see get_certificate_path_setting()
|
67 |
* @return string Absolute path to the certificate file. By default will use the option.
|
@@ -72,24 +72,24 @@ class WPRSS_Feed_Access {
|
|
72 |
|
73 |
return $this->_certificate_file_path;
|
74 |
}
|
75 |
-
|
76 |
-
|
77 |
/**
|
78 |
* Gets the value of the option that stores the path to the certificate file.
|
79 |
* Relative paths will be converted to absolute, as if relative to WP root.
|
80 |
-
*
|
81 |
* @since 4.7
|
82 |
* @return string Absolute path to the certificate file.
|
83 |
*/
|
84 |
public function get_certificate_path_setting() {
|
85 |
$path = wprss_get_general_setting( self::SETTING_KEY_CERTIFICATE_PATH );
|
86 |
-
|
87 |
if ( empty( $path ) )
|
88 |
return $path;
|
89 |
-
|
90 |
if ( !path_is_absolute( $path ) )
|
91 |
$path = ABSPATH . $path;
|
92 |
-
|
93 |
return $path;
|
94 |
}
|
95 |
|
@@ -120,12 +120,12 @@ class WPRSS_Feed_Access {
|
|
120 |
? SIMPLEPIE_USERAGENT
|
121 |
: $useragent;
|
122 |
}
|
123 |
-
|
124 |
-
|
125 |
/**
|
126 |
* This happens immediately before feed initialization.
|
127 |
* Handles the `wprss_fetch_feed_before` action.
|
128 |
-
*
|
129 |
* @since 4.7
|
130 |
* @param SimplePie $feed The instance of the object that represents the feed to be fetched.
|
131 |
* @param string $url The URL, from which the feed is going to be fetched.
|
@@ -135,11 +135,11 @@ class WPRSS_Feed_Access {
|
|
135 |
$feed->set_useragent($this->get_useragent());
|
136 |
WPRSS_SimplePie_File::set_default_certificate_file_path( $this->get_certificate_file_path() );
|
137 |
}
|
138 |
-
|
139 |
-
|
140 |
/**
|
141 |
* Implements a `wprss_settings_array` filter.
|
142 |
-
*
|
143 |
* @since 4.7
|
144 |
* @param array $settings The current settings array, where 1st dimension is secion code, 2nd is setting code, 3rd is setting option(s).
|
145 |
* @return array The new settings array.
|
@@ -154,11 +154,11 @@ class WPRSS_Feed_Access {
|
|
154 |
'label' => __( 'Feed Request Useragent', WPRSS_TEXT_DOMAIN ),
|
155 |
'callback' => array( $this, 'render_feed_request_useragent_setting' )
|
156 |
);
|
157 |
-
|
158 |
return $settings;
|
159 |
}
|
160 |
-
|
161 |
-
|
162 |
/**
|
163 |
* @since 4.7
|
164 |
* @param array $settings The array of settings, where key is
|
@@ -171,11 +171,11 @@ class WPRSS_Feed_Access {
|
|
171 |
|
172 |
return $settings;
|
173 |
}
|
174 |
-
|
175 |
-
|
176 |
/**
|
177 |
* Renders the setting field for the certificate path.
|
178 |
-
*
|
179 |
* @since 4.7
|
180 |
* @see wprss_admin_init
|
181 |
* @param array $field Data of this field.
|
@@ -215,12 +215,12 @@ class WPRSS_SimplePie_File extends SimplePie_File {
|
|
215 |
|
216 |
protected static $_default_certificate_file_path;
|
217 |
protected $_certificate_file_path;
|
218 |
-
|
219 |
-
|
220 |
/**
|
221 |
* Copied from {@see SimplePie_File#__construct()}.
|
222 |
* Adds call to {@see _before_curl_exec()}.
|
223 |
-
*
|
224 |
* @since 4.7
|
225 |
*/
|
226 |
public function __construct( $url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false ) {
|
@@ -400,14 +400,14 @@ class WPRSS_SimplePie_File extends SimplePie_File {
|
|
400 |
}
|
401 |
}
|
402 |
}
|
403 |
-
|
404 |
-
|
405 |
/**
|
406 |
* Additional preparation of the curl request.
|
407 |
* Sets the {@link CURLOPT_CAINFO http://php.net/manual/en/function.curl-setopt.php}
|
408 |
* cURL option to a value determined by {@see get_default_certificate_file_path}.
|
409 |
* If the value is empty, leaves it as is.
|
410 |
-
*
|
411 |
* @since 4.7
|
412 |
* @param resource $fp Pointer to a resource created by {@see curl_init()}.
|
413 |
* @param string $url The URL, to which the cURL request is being made.
|
@@ -422,36 +422,36 @@ class WPRSS_SimplePie_File extends SimplePie_File {
|
|
422 |
|
423 |
return $this;
|
424 |
}
|
425 |
-
|
426 |
-
|
427 |
/**
|
428 |
* Gets the path to the certificate, which will be used by this instance
|
429 |
* to fetch remote content.
|
430 |
-
*
|
431 |
* @since 4.7
|
432 |
* @return string Path to the certificate file.
|
433 |
*/
|
434 |
public function get_certificate_file_path() {
|
435 |
return $this->_certificate_file_path;
|
436 |
}
|
437 |
-
|
438 |
-
|
439 |
/**
|
440 |
* Gets the path to the certificate file, which will be used by future
|
441 |
* instances of this class.
|
442 |
-
*
|
443 |
* @since 4.7
|
444 |
* @return string Path to the certificate file.
|
445 |
*/
|
446 |
public static function get_default_certificate_file_path() {
|
447 |
return self::$_default_certificate_file_path;
|
448 |
}
|
449 |
-
|
450 |
-
|
451 |
/**
|
452 |
* Sets the path to the certificate file.
|
453 |
* This path will be used by future instances of this class.
|
454 |
-
*
|
455 |
* @since 4.7
|
456 |
* @param string $path The path to the certificate file.
|
457 |
*/
|
@@ -469,20 +469,26 @@ class WPRSS_SimplePie_File extends SimplePie_File {
|
|
469 |
*/
|
470 |
protected function _afterCurlHeadersParsed($curlInfo)
|
471 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
472 |
$error = implode("\n", array(
|
473 |
'The resource could not be retrieved because of a %1$s error with code %2$d',
|
474 |
-
'Server returned %3$d characters:',
|
475 |
'%4$s'
|
476 |
));
|
477 |
|
478 |
-
$code = $this->status_code;
|
479 |
-
$body = $this->body;
|
480 |
if ($code >= 400 && $code < 500 ) { // Client error
|
481 |
-
$this->error = sprintf($error, 'client', $code,
|
482 |
$this->success = false;
|
483 |
}
|
484 |
if ($code >= 500 && $code < 600 ) { // Server error
|
485 |
-
$this->error = sprintf($error, 'server', $code,
|
486 |
$this->success = false;
|
487 |
}
|
488 |
}
|
3 |
|
4 |
/**
|
5 |
* Centralizes control over resource fetching.
|
6 |
+
*
|
7 |
* @since 4.7
|
8 |
*/
|
9 |
class WPRSS_Feed_Access {
|
10 |
+
|
11 |
protected static $_instance;
|
12 |
+
|
13 |
protected $_certificate_file_path;
|
14 |
+
|
15 |
const SETTING_KEY_CERTIFICATE_PATH = 'certificate-path';
|
16 |
const SETTING_KEY_FEED_REQUEST_USERAGENT = 'feed_request_useragent';
|
17 |
+
|
18 |
/**
|
19 |
* @since 4.7
|
20 |
* @return WPRSS_Feed_Access The singleton instance of this class.
|
24 |
$class_name = __CLASS__;
|
25 |
self::$_instance = new $class_name;
|
26 |
}
|
27 |
+
|
28 |
return self::$_instance;
|
29 |
}
|
30 |
+
|
31 |
+
|
32 |
public function __construct() {
|
33 |
$this->_construct();
|
34 |
}
|
35 |
+
|
36 |
+
|
37 |
/**
|
38 |
* The parameter-less constructor.
|
39 |
+
*
|
40 |
* @since 4.7
|
41 |
*/
|
42 |
protected function _construct() {
|
44 |
add_action( 'wprss_settings_array', array( $this, 'add_settings' ) );
|
45 |
add_action( 'wprss_default_settings_general', array( $this, 'add_default_settings' ) );
|
46 |
}
|
47 |
+
|
48 |
+
|
49 |
/**
|
50 |
* Sets the path to the certificate, which will be used by WPRSS to fetch remote content.
|
51 |
+
*
|
52 |
* @since 4.7
|
53 |
* @param string $path Absolute path to the certificate file.
|
54 |
* @return \WPRSS_Feed_Access This instance.
|
57 |
$this->_certificate_file_path = $path;
|
58 |
return $this;
|
59 |
}
|
60 |
+
|
61 |
+
|
62 |
/**
|
63 |
* Gets the path to the certificate, which will be used by WPRSS to fetch remote content.
|
64 |
+
*
|
65 |
* @since 4.7
|
66 |
* @see get_certificate_path_setting()
|
67 |
* @return string Absolute path to the certificate file. By default will use the option.
|
72 |
|
73 |
return $this->_certificate_file_path;
|
74 |
}
|
75 |
+
|
76 |
+
|
77 |
/**
|
78 |
* Gets the value of the option that stores the path to the certificate file.
|
79 |
* Relative paths will be converted to absolute, as if relative to WP root.
|
80 |
+
*
|
81 |
* @since 4.7
|
82 |
* @return string Absolute path to the certificate file.
|
83 |
*/
|
84 |
public function get_certificate_path_setting() {
|
85 |
$path = wprss_get_general_setting( self::SETTING_KEY_CERTIFICATE_PATH );
|
86 |
+
|
87 |
if ( empty( $path ) )
|
88 |
return $path;
|
89 |
+
|
90 |
if ( !path_is_absolute( $path ) )
|
91 |
$path = ABSPATH . $path;
|
92 |
+
|
93 |
return $path;
|
94 |
}
|
95 |
|
120 |
? SIMPLEPIE_USERAGENT
|
121 |
: $useragent;
|
122 |
}
|
123 |
+
|
124 |
+
|
125 |
/**
|
126 |
* This happens immediately before feed initialization.
|
127 |
* Handles the `wprss_fetch_feed_before` action.
|
128 |
+
*
|
129 |
* @since 4.7
|
130 |
* @param SimplePie $feed The instance of the object that represents the feed to be fetched.
|
131 |
* @param string $url The URL, from which the feed is going to be fetched.
|
135 |
$feed->set_useragent($this->get_useragent());
|
136 |
WPRSS_SimplePie_File::set_default_certificate_file_path( $this->get_certificate_file_path() );
|
137 |
}
|
138 |
+
|
139 |
+
|
140 |
/**
|
141 |
* Implements a `wprss_settings_array` filter.
|
142 |
+
*
|
143 |
* @since 4.7
|
144 |
* @param array $settings The current settings array, where 1st dimension is secion code, 2nd is setting code, 3rd is setting option(s).
|
145 |
* @return array The new settings array.
|
154 |
'label' => __( 'Feed Request Useragent', WPRSS_TEXT_DOMAIN ),
|
155 |
'callback' => array( $this, 'render_feed_request_useragent_setting' )
|
156 |
);
|
157 |
+
|
158 |
return $settings;
|
159 |
}
|
160 |
+
|
161 |
+
|
162 |
/**
|
163 |
* @since 4.7
|
164 |
* @param array $settings The array of settings, where key is
|
171 |
|
172 |
return $settings;
|
173 |
}
|
174 |
+
|
175 |
+
|
176 |
/**
|
177 |
* Renders the setting field for the certificate path.
|
178 |
+
*
|
179 |
* @since 4.7
|
180 |
* @see wprss_admin_init
|
181 |
* @param array $field Data of this field.
|
215 |
|
216 |
protected static $_default_certificate_file_path;
|
217 |
protected $_certificate_file_path;
|
218 |
+
|
219 |
+
|
220 |
/**
|
221 |
* Copied from {@see SimplePie_File#__construct()}.
|
222 |
* Adds call to {@see _before_curl_exec()}.
|
223 |
+
*
|
224 |
* @since 4.7
|
225 |
*/
|
226 |
public function __construct( $url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false ) {
|
400 |
}
|
401 |
}
|
402 |
}
|
403 |
+
|
404 |
+
|
405 |
/**
|
406 |
* Additional preparation of the curl request.
|
407 |
* Sets the {@link CURLOPT_CAINFO http://php.net/manual/en/function.curl-setopt.php}
|
408 |
* cURL option to a value determined by {@see get_default_certificate_file_path}.
|
409 |
* If the value is empty, leaves it as is.
|
410 |
+
*
|
411 |
* @since 4.7
|
412 |
* @param resource $fp Pointer to a resource created by {@see curl_init()}.
|
413 |
* @param string $url The URL, to which the cURL request is being made.
|
422 |
|
423 |
return $this;
|
424 |
}
|
425 |
+
|
426 |
+
|
427 |
/**
|
428 |
* Gets the path to the certificate, which will be used by this instance
|
429 |
* to fetch remote content.
|
430 |
+
*
|
431 |
* @since 4.7
|
432 |
* @return string Path to the certificate file.
|
433 |
*/
|
434 |
public function get_certificate_file_path() {
|
435 |
return $this->_certificate_file_path;
|
436 |
}
|
437 |
+
|
438 |
+
|
439 |
/**
|
440 |
* Gets the path to the certificate file, which will be used by future
|
441 |
* instances of this class.
|
442 |
+
*
|
443 |
* @since 4.7
|
444 |
* @return string Path to the certificate file.
|
445 |
*/
|
446 |
public static function get_default_certificate_file_path() {
|
447 |
return self::$_default_certificate_file_path;
|
448 |
}
|
449 |
+
|
450 |
+
|
451 |
/**
|
452 |
* Sets the path to the certificate file.
|
453 |
* This path will be used by future instances of this class.
|
454 |
+
*
|
455 |
* @since 4.7
|
456 |
* @param string $path The path to the certificate file.
|
457 |
*/
|
469 |
*/
|
470 |
protected function _afterCurlHeadersParsed($curlInfo)
|
471 |
{
|
472 |
+
$bodyMaxLength = 150;
|
473 |
+
$code = $this->status_code;
|
474 |
+
$body = $this->body;
|
475 |
+
$bodyLength = strlen($body);
|
476 |
+
$bodyOutput = strlen($body) < $bodyMaxLength
|
477 |
+
? $body
|
478 |
+
: substr($body, 0, $bodyMaxLength);
|
479 |
+
$outputLength = strlen($bodyOutput);
|
480 |
$error = implode("\n", array(
|
481 |
'The resource could not be retrieved because of a %1$s error with code %2$d',
|
482 |
+
'Server returned %3$d characters' . ($outputLength < $bodyMaxLength ? '' : ', of which ' . $outputLength . ' are below') . ':',
|
483 |
'%4$s'
|
484 |
));
|
485 |
|
|
|
|
|
486 |
if ($code >= 400 && $code < 500 ) { // Client error
|
487 |
+
$this->error = sprintf($error, 'client', $code, $bodyLength, $bodyOutput);
|
488 |
$this->success = false;
|
489 |
}
|
490 |
if ($code >= 500 && $code < 600 ) { // Server error
|
491 |
+
$this->error = sprintf($error, 'server', $code, $bodyLength, $bodyOutput);
|
492 |
$this->success = false;
|
493 |
}
|
494 |
}
|
includes/feed-importing.php
CHANGED
@@ -106,8 +106,9 @@
|
|
106 |
// Generate a list of items fetched, that are not already in the DB
|
107 |
$new_items = array();
|
108 |
foreach ( $items_to_insert as $item ) {
|
109 |
-
|
110 |
-
|
|
|
111 |
|
112 |
// Check if not blacklisted and not already imported
|
113 |
$is_blacklisted = wprss_is_blacklisted( $permalink );
|
@@ -305,10 +306,10 @@
|
|
305 |
* @return string The normalized permalink
|
306 |
* @since 4.2.3
|
307 |
*/
|
308 |
-
function wprss_normalize_permalink( $permalink ) {
|
309 |
// Apply normalization functions on the permalink
|
310 |
$permalink = trim( $permalink );
|
311 |
-
$permalink = apply_filters( 'wprss_normalize_permalink', $permalink );
|
312 |
// Return the normalized permalink
|
313 |
return $permalink;
|
314 |
}
|
@@ -464,7 +465,7 @@
|
|
464 |
foreach ( $items as $item ) {
|
465 |
|
466 |
// Normalize the URL
|
467 |
-
$permalink = wprss_normalize_permalink( $item->get_permalink() );
|
468 |
wprss_log_obj( 'Importing item', $permalink, null, WPRSS_LOG_LEVEL_INFO );
|
469 |
wprss_log_obj( 'Original permalink', $item->get_permalink(), null, WPRSS_LOG_LEVEL_SYSTEM );
|
470 |
|
106 |
// Generate a list of items fetched, that are not already in the DB
|
107 |
$new_items = array();
|
108 |
foreach ( $items_to_insert as $item ) {
|
109 |
+
|
110 |
+
$permalink = wprss_normalize_permalink( $item->get_permalink(), $item, $feed_ID );
|
111 |
+
wprss_log_obj( 'Normalized permalink', sprintf('%1$s -> %2$s', $item->get_permalink(), $permalink), null, WPRSS_LOG_LEVEL_SYSTEM );
|
112 |
|
113 |
// Check if not blacklisted and not already imported
|
114 |
$is_blacklisted = wprss_is_blacklisted( $permalink );
|
306 |
* @return string The normalized permalink
|
307 |
* @since 4.2.3
|
308 |
*/
|
309 |
+
function wprss_normalize_permalink( $permalink, $item, $feed_ID) {
|
310 |
// Apply normalization functions on the permalink
|
311 |
$permalink = trim( $permalink );
|
312 |
+
$permalink = apply_filters( 'wprss_normalize_permalink', $permalink, $item, $feed_ID);
|
313 |
// Return the normalized permalink
|
314 |
return $permalink;
|
315 |
}
|
465 |
foreach ( $items as $item ) {
|
466 |
|
467 |
// Normalize the URL
|
468 |
+
$permalink = wprss_normalize_permalink( $item->get_permalink(), $item, $feed_ID );
|
469 |
wprss_log_obj( 'Importing item', $permalink, null, WPRSS_LOG_LEVEL_INFO );
|
470 |
wprss_log_obj( 'Original permalink', $item->get_permalink(), null, WPRSS_LOG_LEVEL_SYSTEM );
|
471 |
|
includes/misc-functions.php
CHANGED
@@ -231,7 +231,7 @@ EOS;
|
|
231 |
}
|
232 |
|
233 |
// Stock trimming of words
|
234 |
-
$plain_text = wp_trim_words_wprss( $plain_text, $max_words );
|
235 |
|
236 |
/*
|
237 |
* Put the tags back, using the offsets recorded
|
@@ -373,4 +373,25 @@ function wprss_validate_url( $url ) {
|
|
373 |
')';
|
374 |
|
375 |
return preg_match('!' . $expression . '!', $url) ? $url : null;
|
376 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
}
|
232 |
|
233 |
// Stock trimming of words
|
234 |
+
$plain_text = wp_trim_words_wprss( $plain_text, $max_words, '' );
|
235 |
|
236 |
/*
|
237 |
* Put the tags back, using the offsets recorded
|
373 |
')';
|
374 |
|
375 |
return preg_match('!' . $expression . '!', $url) ? $url : null;
|
376 |
+
}
|
377 |
+
|
378 |
+
if (!function_exists('wprss_verify_nonce'))
|
379 |
+
{
|
380 |
+
/**
|
381 |
+
* Check if a WP nonce sent in a reques is valid.
|
382 |
+
*
|
383 |
+
* @since 4.9
|
384 |
+
* @see wp_verify_nonce()
|
385 |
+
* @param string $action ID of the action, for which checking the nonce.
|
386 |
+
* @param string $queryArg Name of the key in the $_REQUEST global
|
387 |
+
* which contains the nonce value.
|
388 |
+
* @return bool|int False if nonce invalid, 1 if it's the first 12 hours of
|
389 |
+
* validity, 2 if the second 12 hours.
|
390 |
+
*/
|
391 |
+
function wprss_verify_nonce($action, $queryArg)
|
392 |
+
{
|
393 |
+
return isset($_REQUEST[$queryArg])
|
394 |
+
? wp_verify_nonce($_REQUEST[$queryArg], $action)
|
395 |
+
: false;
|
396 |
+
}
|
397 |
+
}
|
js/admin-custom.js
CHANGED
@@ -1,31 +1,52 @@
|
|
1 |
// jQuery for 'Fetch Feed Items' Row Action in 'All Feed Sources' page
|
2 |
-
function fetch_items_row_action_callback(){
|
3 |
var link = jQuery(this);
|
4 |
var original_text = link.text();
|
5 |
var id = link.attr('pid');
|
6 |
var url = link.attr('purl');
|
7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
jQuery.ajax({
|
9 |
url: ajaxurl,
|
10 |
type: 'POST',
|
|
|
11 |
data: {
|
12 |
'action': 'wprss_fetch_feeds_row_action',
|
13 |
-
'id': id
|
|
|
|
|
14 |
},
|
15 |
success: function( response, status, jqXHR ){
|
16 |
-
|
17 |
-
|
|
|
|
|
|
|
|
|
18 |
jQuery('table.wp-list-table tbody tr.post-' + id + ' td.column-feed-count i.fa-spin').addClass('wprss-show');
|
19 |
-
setTimeout( function(){
|
20 |
-
link.text( original_text ).click( fetch_items_row_action_callback );
|
21 |
-
}, 3500 );
|
22 |
-
},
|
23 |
-
error: function( response, status, error ){
|
24 |
-
link.text( wprss_admin_custom.failed_to_import + ': ' + error );
|
25 |
-
setTimeout( function(){
|
26 |
-
link.text( original_text ).click( fetch_items_row_action_callback );
|
27 |
-
}, 3500 );
|
28 |
},
|
|
|
29 |
timeout: 60000 // set timeout to 1 minute
|
30 |
});
|
31 |
/*
|
@@ -43,7 +64,7 @@ function fetch_items_row_action_callback(){
|
|
43 |
}
|
44 |
);*/
|
45 |
link.text( wprss_admin_custom.please_wait );
|
46 |
-
link.
|
47 |
};
|
48 |
|
49 |
|
1 |
// jQuery for 'Fetch Feed Items' Row Action in 'All Feed Sources' page
|
2 |
+
function fetch_items_row_action_callback(e){
|
3 |
var link = jQuery(this);
|
4 |
var original_text = link.text();
|
5 |
var id = link.attr('pid');
|
6 |
var url = link.attr('purl');
|
7 |
|
8 |
+
var errorImportingHandler = function(jqXHR, status, exceptionText) {
|
9 |
+
displayResultMessage(status === 'parsererror' ? 'Error parsing response' : exceptionText, 'ajax-error');;
|
10 |
+
};
|
11 |
+
|
12 |
+
var displayResultMessage = function(message, className) {
|
13 |
+
link.text(message);
|
14 |
+
if (className)
|
15 |
+
link.addClass(className);
|
16 |
+
|
17 |
+
setTimeout(function(){
|
18 |
+
link.text(original_text);
|
19 |
+
link.removeAttr('disabled');
|
20 |
+
if (className)
|
21 |
+
link.removeClass(className);
|
22 |
+
}, 3500);
|
23 |
+
};
|
24 |
+
|
25 |
+
e.preventDefault();
|
26 |
+
if (link.attr('disabled')) {
|
27 |
+
return;
|
28 |
+
}
|
29 |
+
|
30 |
jQuery.ajax({
|
31 |
url: ajaxurl,
|
32 |
type: 'POST',
|
33 |
+
dataType: 'json',
|
34 |
data: {
|
35 |
'action': 'wprss_fetch_feeds_row_action',
|
36 |
+
'id': id,
|
37 |
+
'wprss_admin_ajax_nonce': link.next().val(), // nonce
|
38 |
+
'wprss_admin_ajax_referer': link.next().next().val() // referer
|
39 |
},
|
40 |
success: function( response, status, jqXHR ){
|
41 |
+
if (response.is_error) {
|
42 |
+
errorImportingHandler(jqXHR, status, response.error_message);
|
43 |
+
return;
|
44 |
+
}
|
45 |
+
|
46 |
+
displayResultMessage(wprss_admin_custom.items_are_importing + '!');
|
47 |
jQuery('table.wp-list-table tbody tr.post-' + id + ' td.column-feed-count i.fa-spin').addClass('wprss-show');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
},
|
49 |
+
error: errorImportingHandler,
|
50 |
timeout: 60000 // set timeout to 1 minute
|
51 |
});
|
52 |
/*
|
64 |
}
|
65 |
);*/
|
66 |
link.text( wprss_admin_custom.please_wait );
|
67 |
+
link.attr('disabled', 'disabled');
|
68 |
};
|
69 |
|
70 |
|
js/admin-help.js
CHANGED
@@ -45,7 +45,9 @@ jQuery( document ).ready( function($) {
|
|
45 |
showError(response.error);
|
46 |
} else {
|
47 |
$('#support-error').html(wprss_admin_help['sent-ok']);
|
48 |
-
$('#support-error').css('color', '
|
|
|
|
|
49 |
}
|
50 |
|
51 |
return response;
|
45 |
showError(response.error);
|
46 |
} else {
|
47 |
$('#support-error').html(wprss_admin_help['sent-ok']);
|
48 |
+
$('#support-error').css('color', 'green');
|
49 |
+
|
50 |
+
formElements.parents('form').get(0).reset();
|
51 |
}
|
52 |
|
53 |
return response;
|
nbproject/project.properties
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
include.path=${php.global.include.path}
|
2 |
-
php.version=PHP_53
|
3 |
-
source.encoding=UTF-8
|
4 |
-
src.dir=.
|
5 |
-
tags.asp=false
|
6 |
-
tags.short=false
|
7 |
-
web.root=.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nbproject/project.xml
DELETED
@@ -1,9 +0,0 @@
|
|
1 |
-
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
-
<project xmlns="http://www.netbeans.org/ns/project/1">
|
3 |
-
<type>org.netbeans.modules.php.project</type>
|
4 |
-
<configuration>
|
5 |
-
<data xmlns="http://www.netbeans.org/ns/php-project/1">
|
6 |
-
<name>WPRACORE</name>
|
7 |
-
</data>
|
8 |
-
</configuration>
|
9 |
-
</project>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
readme.txt
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
=== WP RSS Aggregator ===
|
2 |
Contributors: jeangalea, Mekku, xedin.unknown, markzahra, doytch, chiragswadia
|
3 |
Plugin URI: http://www.wprssaggregator.com
|
4 |
-
Tags: RSS feeds, aggregation, autoblog, content curation, feed reader, feed to post, RSS aggregator, RSS feeder, RSS import, RSS to post, syndication, multiple feed import
|
5 |
Requires at least: 4.0
|
6 |
-
Tested up to: 4.
|
7 |
-
Stable tag: 4.
|
8 |
License: GPLv2 or later
|
9 |
WP RSS Aggregator is the most comprehensive RSS feed importer and autoblogging plugin for WordPress with premium add-ons for additional functionality.
|
10 |
|
@@ -18,53 +18,55 @@ With this free core version of WP RSS Aggregator you’ll be able to aggregate a
|
|
18 |
Have a look at the core version of WP RSS Aggregator below, or [go here to view our introductory videos for the premium add-ons](http://docs.wprssaggregator.com/introductory-videos/).
|
19 |
[youtube http://www.youtube.com/watch?v=fcENPsmJbvc]
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
*
|
24 |
-
*
|
25 |
-
*
|
26 |
-
*
|
27 |
-
* Set the
|
28 |
-
* Set
|
29 |
-
*
|
30 |
-
*
|
31 |
-
*
|
32 |
-
*
|
33 |
-
*
|
34 |
-
*
|
35 |
-
*
|
36 |
-
*
|
37 |
-
*
|
38 |
-
*
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
* [
|
45 |
-
* [
|
46 |
-
* [
|
47 |
-
* [
|
48 |
-
* [
|
49 |
-
* [
|
50 |
-
* [Widget](http://www.wprssaggregator.com/extension/widget/) adds a widget to your website that displays the imported feed items. It can also display excerpts and thumbnail images when used in conjunction with the [Excerpts & Thumbnails](http://www.wprssaggregator.com/extension/excerpts-thumbnails/) add-on.
|
51 |
-
|
52 |
-
|
53 |
-
[View a comparison of our three most popular add-ons here](http://www.wprssaggregator.com/product-comparison/). If you're unsure as to which add-ons you need, [we put together this post to help you out](http://www.wprssaggregator.com/add-ons-purchase/).
|
54 |
|
55 |
-
There are also two premium bundles available, the [Simple Feeds Bundle](http://www.wprssaggregator.com/extension/simple-feeds-bundle/) and the [Advanced Feeds Bundle](http://www.wprssaggregator.com/extension/advanced-feeds-bundle/).
|
56 |
|
57 |
We also provide a [Feed Creator](http://createfeed.wprssaggregator.com/) service that allows you to generate RSS feeds from any webpage, even if it doesn't have its own RSS feed.
|
58 |
|
59 |
-
|
60 |
-
The core plugin can be seen in use [on our website's demo page](http://www.wprssaggregator.com/demo/). There are also a number of [other demos](http://www.wprssaggregator.com/) available for our premium add-ons.
|
61 |
|
62 |
-
|
|
|
63 |
|
64 |
-
|
65 |
-
|
|
|
|
|
66 |
|
67 |
-
|
68 |
* [WP Mayor](http://www.wpmayor.com/rss-feeds-review-wp-rss-aggregator/)
|
69 |
* [LatestWP](http://www.latestwp.com/2015/03/15/wp-rss-aggregator-plugin-review/)
|
70 |
* [WPBeginner](http://www.wpbeginner.com/plugins/how-to-fetch-feeds-in-wordpress-using-wp-rss-aggregator/)
|
@@ -81,7 +83,7 @@ Our [comprehensive documentation](http://docs.wprssaggregator.com/) provides you
|
|
81 |
* [Kevin Muldoon](http://www.kevinmuldoon.com/wp-rss-aggregator-wordpress-plugin/)
|
82 |
* [Magazine3](http://magazine3.com/blog/news-aggregator-website/)
|
83 |
|
84 |
-
|
85 |
* Italian - Davide De Maestri
|
86 |
* Spanish - Andrew Kurtis
|
87 |
* Brazilian Portugese - Bruno Calheira
|
@@ -89,10 +91,12 @@ Our [comprehensive documentation](http://docs.wprssaggregator.com/) provides you
|
|
89 |
|
90 |
== Installation ==
|
91 |
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
|
|
|
|
96 |
|
97 |
You can easily select the source for your feeds and also insert a limit via [shortcode parameters](http://docs.wprssaggregator.com/shortcodes/#core-parameters) as shown below. To get your feed source ID please refer to the ID column in your feed source listing page.
|
98 |
|
@@ -134,6 +138,8 @@ You can either use the shortcode in your posts and pages:
|
|
134 |
or you can call the function directly within your theme:
|
135 |
`<?php wprss_display_feed_items(); ?>`
|
136 |
|
|
|
|
|
137 |
= Is there a limit on the number of feed sources I can use? =
|
138 |
|
139 |
There is no limit in place for the number of feed sources. Having many (50+) feed sources should not present any problems in itself.
|
@@ -142,34 +148,50 @@ However, pulling in posts from many sites is bound to put your server under some
|
|
142 |
|
143 |
Check out our dedicated page on [WordPress hosting](http://www.wprssaggregator.com/recommended-web-hosts/) recommendations.
|
144 |
|
|
|
|
|
145 |
= Does WP RSS Aggregator work using JSON as the source? =
|
146 |
|
147 |
No, our plugin does not currently import from JSON, it only imports from RSS and Atom structured XML.
|
148 |
|
|
|
|
|
149 |
= Why do I get “No feed items found” when I insert the shortcode on a page or post? =
|
150 |
|
151 |
Try adding a few more feed sources and make sure they are valid by using the RSS Feed Validator.
|
152 |
|
153 |
Secondly make sure your WordPress cron system is working well. If not, the feeds cannot be imported. If in doubt you can go to RSS Aggregator > Debugging and hit the red button to re-import all feed items. If the problem persists contact support.
|
154 |
|
|
|
|
|
155 |
= Can I store imported feed items as posts? =
|
156 |
|
157 |
Yes! You can do that with the [Feed to Post](http://www.wprssaggregator.com/extensions/feed-to-post) add-on. You will not only be able to store items as posts, but also as other custom post types, as well as set the author, auto set tags and categories, import images into the gallery or set featured images, and much more.
|
158 |
|
|
|
|
|
159 |
= Some RSS feeds only give a short excerpt. Any way around that? =
|
160 |
|
161 |
Yes, along with the [Feed to Post](http://www.wprssaggregator.com/extensions/feed-to-post) add-on we have another add-on called [Full Text RSS Feeds](http://www.wprssaggregator.com/extension/full-text-rss-feeds/) that can get the full content of those feeds that only supply a short excerpt.
|
162 |
|
|
|
|
|
163 |
= I’m not sure which premium add-ons are right for me. Can you help me out? =
|
164 |
|
165 |
Sure! We wrote a [post](http://www.wprssaggregator.com/add-ons-purchase/) just for you. Read about which add-ons you should buy, we explain the different types of usage so you’ll know what to expect when purchasing.
|
166 |
|
167 |
If you need any further help you can [contact our support team](http://www.wprssaggregator.com/contact/).
|
168 |
|
|
|
|
|
169 |
= Where can I find the documentation for the plugin? =
|
170 |
|
171 |
Our complete documentation with FAQs included can be found on [our dedicated documentation website](http://docs.wprssaggregator.com/).
|
172 |
|
|
|
|
|
|
|
|
|
173 |
|
174 |
== Screenshots ==
|
175 |
|
@@ -188,6 +210,13 @@ Our complete documentation with FAQs included can be found on [our dedicated doc
|
|
188 |
|
189 |
== Changelog ==
|
190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
= 4.8.2 (2016-02-22) =
|
192 |
* Fixed bug: Interface methods used to conflict, causing fatal error on activation.
|
193 |
* Fixed bug: Empty feed response used to cause misleading error message in log.
|
1 |
=== WP RSS Aggregator ===
|
2 |
Contributors: jeangalea, Mekku, xedin.unknown, markzahra, doytch, chiragswadia
|
3 |
Plugin URI: http://www.wprssaggregator.com
|
4 |
+
Tags: RSS, RSS feeds, aggregation, autoblog, content curation, feed reader, feed to post, RSS aggregator, RSS feeder, RSS import, RSS to post, syndication, multiple feed import
|
5 |
Requires at least: 4.0
|
6 |
+
Tested up to: 4.5.2
|
7 |
+
Stable tag: 4.9
|
8 |
License: GPLv2 or later
|
9 |
WP RSS Aggregator is the most comprehensive RSS feed importer and autoblogging plugin for WordPress with premium add-ons for additional functionality.
|
10 |
|
18 |
Have a look at the core version of WP RSS Aggregator below, or [go here to view our introductory videos for the premium add-ons](http://docs.wprssaggregator.com/introductory-videos/).
|
19 |
[youtube http://www.youtube.com/watch?v=fcENPsmJbvc]
|
20 |
|
21 |
+
> ### Highlighted Features ###
|
22 |
+
> * Set a name for each feed source.
|
23 |
+
> * Import any number of feed items from multiple RSS Feeds.
|
24 |
+
> * Display feed items using the [shortcodes](http://docs.wprssaggregator.com/shortcodes/) or by [calling the display function from within your theme](http://docs.wprssaggregator.com/shortcodes/#using-shortcodes-directly-in-templates).
|
25 |
+
> * Limit the age of the feed items stored in the database.
|
26 |
+
> * Set the number of feed items per feed source that you want to show and store.
|
27 |
+
> * Set the pagination for the displayed feed items.
|
28 |
+
> * Set a general feed import time interval.
|
29 |
+
> * Schedule feed imports for each individual feed source.
|
30 |
+
> * Choose whether to show/hide feed sources and dates, and set the date format.
|
31 |
+
> * Set the links as no-follow or not, or add no follow to the meta tag.
|
32 |
+
> * Customise the output using various [shortcode parameters](http://docs.wprssaggregator.com/shortcodes/#core-parameters).
|
33 |
+
> * Set the open link behaviour (lightbox, new window or current window).
|
34 |
+
> * Opens YouTube, DailyMotion and Vimeo videos directly.
|
35 |
+
> * Export a custom RSS feed based on your feed sources.
|
36 |
+
> * Extendable via [action and filter hooks](http://docs.wprssaggregator.com/category/developer-documentation/filters/).
|
37 |
+
> * Incorporates feed auto-discovery, which lets you add feed sources without knowing the exact URL.
|
38 |
+
> * Integrated with the Simplepie library that comes with WordPress. This includes RSS 0.91 and RSS 1.0 formats, the popular RSS 2.0 format, Atom etc.
|
39 |
+
|
40 |
+
### Premium Add-Ons ###
|
41 |
+
WP RSS Aggregator also has a number of premium add-ons that add more functionality to the core plugin. They provide the means to create auto-blogging websites, display job listings, import YouTube videos and a lot more. Take a look at our [Use Cases](http://www.wprssaggregator.com/use-cases/) and our [Showcase](http://www.wprssaggregator.com/showcase/) for more ideas. Here are the add-ons currently available:
|
42 |
+
|
43 |
+
> * [Feed to Post](http://www.wprssaggregator.com/extension/feed-to-post/) is an advanced importer that lets you import RSS feeds directly into WordPress posts or any other custom post type. You can use it to populate a website in minutes (autoblog). This is the most popular and feature-filled extension.
|
44 |
+
> * [Keyword Filtering](http://www.wprssaggregator.com/extension/keyword-filtering/) filters the feed items to be imported based on keywords, key phrases or tags, so you only get the items you're interested in.
|
45 |
+
> * [Excerpts & Thumbnails](http://www.wprssaggregator.com/extension/excerpts-thumbnails/) displays an excerpt and thumbnail image (taken from within the RSS feed) together with the title, date and source of each feed item.
|
46 |
+
> * [Categories](http://www.wprssaggregator.com/extension/categories/) categorises your feed sources and allows you to display feed items from a particular category within your site using the [shortcode parameters](http://docs.wprssaggregator.com/shortcodes/#categories-parameters).
|
47 |
+
> * [Full Text RSS Feeds](http://www.wprssaggregator.com/extension/full-text-rss-feeds/) adds connectivity to our Full Text Premium service, which allows you to import the full post content for an unlimited number of feed items per feed source, even when the feed itself doesn’t provide it. (Requires [Feed to Post](http://www.wprssaggregator.com/extension/feed-to-post/))
|
48 |
+
> * [WordAi](http://www.wprssaggregator.com/extension/wordai/) allows you to take an RSS feed and turn it into new content that is both completely unique and completely readable. (Requires [Feed to Post](http://www.wprssaggregator.com/extension/feed-to-post/) and a [WordAi account](https://wordai.com/))
|
49 |
+
> * [SpinnerChief](http://www.wprssaggregator.com/extension/spinnerchief/) is an extension for [Feed to Post](http://www.wprssaggregator.com/extension/feed-to-post/) that allows you to integrate the SpinnerChief article spinner so that the imported content is both completely unique and completely readable.
|
50 |
+
> * [Widget](http://www.wprssaggregator.com/extension/widget/) adds a widget to your website that displays the imported feed items. It can also display excerpts and thumbnail images when used in conjunction with the [Excerpts & Thumbnails](http://www.wprssaggregator.com/extension/excerpts-thumbnails/) add-on.
|
51 |
+
|
52 |
+
View a comparison of our three most popular add-ons [here](http://www.wprssaggregator.com/product-comparison/). If you're unsure as to which add-ons you need, we put together [this comprehensive post](http://www.wprssaggregator.com/add-ons-purchase/) to help you out.
|
|
|
53 |
|
54 |
+
There are also two premium bundles available, the [Simple Feeds Bundle](http://www.wprssaggregator.com/extension/simple-feeds-bundle/) and the [Advanced Feeds Bundle](http://www.wprssaggregator.com/extension/advanced-feeds-bundle/). View a quick comparison of these bundles [here](http://www.wprssaggregator.com/bundle-comparison/).
|
55 |
|
56 |
We also provide a [Feed Creator](http://createfeed.wprssaggregator.com/) service that allows you to generate RSS feeds from any webpage, even if it doesn't have its own RSS feed.
|
57 |
|
58 |
+
> ### Demo ###
|
59 |
+
> The core plugin can be seen in use [on our website's demo page](http://www.wprssaggregator.com/demo/). There are also a number of [other demos](http://www.wprssaggregator.com/) available for our premium add-ons.
|
60 |
|
61 |
+
> ### Documentation ###
|
62 |
+
> Our [comprehensive documentation](http://docs.wprssaggregator.com/) provides you with everything you need to install, set up and customize the plugin to your needs. You can also browse through [a large number of FAQs](http://docs.wprssaggregator.com/category/faqs/) that cover almost everything there is to ask.
|
63 |
|
64 |
+
> ### Support ###
|
65 |
+
> The support section for the free version of WP RSS Aggregator can be found [here on the plugin repository](https://wordpress.org/support/plugin/wp-rss-aggregator). It’s important to read and follow the [Support Guidelines](https://wordpress.org/support/topic/support-guidelines-1?replies=4) before opening a new ticket.
|
66 |
+
>
|
67 |
+
> For support related to any of the premium add-ons you should open a [premium support ticket](https://www.wprssaggregator.com/contact/).
|
68 |
|
69 |
+
### As featured on ###
|
70 |
* [WP Mayor](http://www.wpmayor.com/rss-feeds-review-wp-rss-aggregator/)
|
71 |
* [LatestWP](http://www.latestwp.com/2015/03/15/wp-rss-aggregator-plugin-review/)
|
72 |
* [WPBeginner](http://www.wpbeginner.com/plugins/how-to-fetch-feeds-in-wordpress-using-wp-rss-aggregator/)
|
83 |
* [Kevin Muldoon](http://www.kevinmuldoon.com/wp-rss-aggregator-wordpress-plugin/)
|
84 |
* [Magazine3](http://magazine3.com/blog/news-aggregator-website/)
|
85 |
|
86 |
+
### Translations ###
|
87 |
* Italian - Davide De Maestri
|
88 |
* Spanish - Andrew Kurtis
|
89 |
* Brazilian Portugese - Bruno Calheira
|
91 |
|
92 |
== Installation ==
|
93 |
|
94 |
+
Follow these instructions to install the core WP RSS Aggregator plugin:
|
95 |
+
|
96 |
+
> 1. Upload the `wp-rss-aggregator` folder to the `/wp-content/plugins/` directory.
|
97 |
+
> 2. Activate the WP RSS Aggregator plugin from the 'Plugins' section in your dashboard.
|
98 |
+
> 3. Configure the plugin by going to the `RSS Aggregator` menu item that appears in your dashboard menu.
|
99 |
+
> 4. Use the WP RSS Aggregator shortcode in your posts or pages: `[wp-rss-aggregator]`
|
100 |
|
101 |
You can easily select the source for your feeds and also insert a limit via [shortcode parameters](http://docs.wprssaggregator.com/shortcodes/#core-parameters) as shown below. To get your feed source ID please refer to the ID column in your feed source listing page.
|
102 |
|
138 |
or you can call the function directly within your theme:
|
139 |
`<?php wprss_display_feed_items(); ?>`
|
140 |
|
141 |
+
- - -
|
142 |
+
|
143 |
= Is there a limit on the number of feed sources I can use? =
|
144 |
|
145 |
There is no limit in place for the number of feed sources. Having many (50+) feed sources should not present any problems in itself.
|
148 |
|
149 |
Check out our dedicated page on [WordPress hosting](http://www.wprssaggregator.com/recommended-web-hosts/) recommendations.
|
150 |
|
151 |
+
- - -
|
152 |
+
|
153 |
= Does WP RSS Aggregator work using JSON as the source? =
|
154 |
|
155 |
No, our plugin does not currently import from JSON, it only imports from RSS and Atom structured XML.
|
156 |
|
157 |
+
- - -
|
158 |
+
|
159 |
= Why do I get “No feed items found” when I insert the shortcode on a page or post? =
|
160 |
|
161 |
Try adding a few more feed sources and make sure they are valid by using the RSS Feed Validator.
|
162 |
|
163 |
Secondly make sure your WordPress cron system is working well. If not, the feeds cannot be imported. If in doubt you can go to RSS Aggregator > Debugging and hit the red button to re-import all feed items. If the problem persists contact support.
|
164 |
|
165 |
+
- - -
|
166 |
+
|
167 |
= Can I store imported feed items as posts? =
|
168 |
|
169 |
Yes! You can do that with the [Feed to Post](http://www.wprssaggregator.com/extensions/feed-to-post) add-on. You will not only be able to store items as posts, but also as other custom post types, as well as set the author, auto set tags and categories, import images into the gallery or set featured images, and much more.
|
170 |
|
171 |
+
- - -
|
172 |
+
|
173 |
= Some RSS feeds only give a short excerpt. Any way around that? =
|
174 |
|
175 |
Yes, along with the [Feed to Post](http://www.wprssaggregator.com/extensions/feed-to-post) add-on we have another add-on called [Full Text RSS Feeds](http://www.wprssaggregator.com/extension/full-text-rss-feeds/) that can get the full content of those feeds that only supply a short excerpt.
|
176 |
|
177 |
+
- - -
|
178 |
+
|
179 |
= I’m not sure which premium add-ons are right for me. Can you help me out? =
|
180 |
|
181 |
Sure! We wrote a [post](http://www.wprssaggregator.com/add-ons-purchase/) just for you. Read about which add-ons you should buy, we explain the different types of usage so you’ll know what to expect when purchasing.
|
182 |
|
183 |
If you need any further help you can [contact our support team](http://www.wprssaggregator.com/contact/).
|
184 |
|
185 |
+
- - -
|
186 |
+
|
187 |
= Where can I find the documentation for the plugin? =
|
188 |
|
189 |
Our complete documentation with FAQs included can be found on [our dedicated documentation website](http://docs.wprssaggregator.com/).
|
190 |
|
191 |
+
- - -
|
192 |
+
|
193 |
+
> ### Got more questions? ###
|
194 |
+
> You can find the full list of FAQs [in our documentation](https://docs.wprssaggregator.com/category/faqs/).
|
195 |
|
196 |
== Screenshots ==
|
197 |
|
210 |
|
211 |
== Changelog ==
|
212 |
|
213 |
+
= 4.9 (2016-06-14) =
|
214 |
+
* Fixed bug: Potential security vulnerability related to triggering feed update.
|
215 |
+
* Fixed bug: Error output on Feed Sources list is trimmed and cannot break the page layout.
|
216 |
+
* Fixed bug: Certain notices could not be dismissed.
|
217 |
+
* Fixed bug: Word trimming didn't always trim correctly with HTML.
|
218 |
+
* Enhanced: Visual improvements.
|
219 |
+
|
220 |
= 4.8.2 (2016-02-22) =
|
221 |
* Fixed bug: Interface methods used to conflict, causing fatal error on activation.
|
222 |
* Fixed bug: Empty feed response used to cause misleading error message in log.
|
wp-rss-aggregator.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: WP RSS Aggregator
|
4 |
Plugin URI: http://www.wprssaggregator.com
|
5 |
Description: Imports and aggregates multiple RSS Feeds using SimplePie
|
6 |
-
Version: 4.
|
7 |
Author: Jean Galea
|
8 |
Author URI: http://www.wprssaggregator.com
|
9 |
License: GPLv2
|
@@ -29,7 +29,7 @@
|
|
29 |
|
30 |
/**
|
31 |
* @package WPRSSAggregator
|
32 |
-
* @version 4.
|
33 |
* @since 1.0
|
34 |
* @author Jean Galea <info@wprssaggregator.com>
|
35 |
* @copyright Copyright (c) 2012-2015, Jean Galea
|
@@ -43,7 +43,7 @@
|
|
43 |
|
44 |
// Set the version number of the plugin.
|
45 |
if( !defined( 'WPRSS_VERSION' ) )
|
46 |
-
define( 'WPRSS_VERSION', '4.
|
47 |
|
48 |
if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
|
49 |
define( 'WPRSS_WP_MIN_VERSION', '4.0', true );
|
3 |
Plugin Name: WP RSS Aggregator
|
4 |
Plugin URI: http://www.wprssaggregator.com
|
5 |
Description: Imports and aggregates multiple RSS Feeds using SimplePie
|
6 |
+
Version: 4.9
|
7 |
Author: Jean Galea
|
8 |
Author URI: http://www.wprssaggregator.com
|
9 |
License: GPLv2
|
29 |
|
30 |
/**
|
31 |
* @package WPRSSAggregator
|
32 |
+
* @version 4.9
|
33 |
* @since 1.0
|
34 |
* @author Jean Galea <info@wprssaggregator.com>
|
35 |
* @copyright Copyright (c) 2012-2015, Jean Galea
|
43 |
|
44 |
// Set the version number of the plugin.
|
45 |
if( !defined( 'WPRSS_VERSION' ) )
|
46 |
+
define( 'WPRSS_VERSION', '4.9', true );
|
47 |
|
48 |
if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
|
49 |
define( 'WPRSS_WP_MIN_VERSION', '4.0', true );
|