Version Description
(2015-11-18) = * Fixed bug: Sticky posts no longer get deleted when truncating, unless imported from a feed source. * Enhanced: Added autoloading and refactored licensing. * Enhanced: Added button to download error log. * Enhanced: Cosmetic changes and fixes.
Download this release
Release Info
Developer | markzahra |
Plugin | WP RSS Aggregator |
Version | 4.7.8 |
Comparing to | |
See all releases |
Code changes from version 4.7.7 to 4.7.8
- css/admin-styles.css +7 -0
- includes/Aventura/Wprss/Core/Caching/ImageCache.php +18 -0
- includes/Aventura/Wprss/Core/Caching/ImageCache/Image.php +14 -0
- includes/Aventura/Wprss/Core/Licensing/AjaxController.php +192 -0
- includes/Aventura/Wprss/Core/Licensing/License.php +177 -0
- includes/Aventura/Wprss/Core/Licensing/License/Status.php +13 -0
- includes/Aventura/Wprss/Core/Licensing/Manager.php +768 -0
- includes/Aventura/Wprss/Core/Licensing/Plugin/Updater.php +15 -0
- includes/Aventura/Wprss/Core/Licensing/Plugin/UpdaterInterface.php +16 -0
- includes/Aventura/Wprss/Core/Licensing/Settings.php +382 -0
- includes/Aventura/Wprss/Core/Loader.php +285 -0
- includes/admin-ajax-notice.php +30 -15
- includes/admin-debugging.php +56 -11
- includes/admin-help.php +237 -211
- includes/admin-log.php +24 -0
- includes/admin-options.php +6 -1
- includes/autoload.php +26 -0
- includes/feed-importing.php +41 -41
- includes/feed-processing.php +29 -28
- includes/image-caching.php +4 -0
- includes/libraries/browser.php +1024 -1003
- includes/licensing.php +53 -750
- includes/scripts.php +1 -0
- includes/system-info.php +3 -4
- includes/update.php +51 -48
- readme.txt +1412 -703
- wp-rss-aggregator.php +14 -8
css/admin-styles.css
CHANGED
@@ -259,6 +259,13 @@ input#thumbnails-width {
|
|
259 |
display: block;
|
260 |
}
|
261 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
|
263 |
@media screen and (min-width: 782px) {
|
264 |
#custom_feed_title {
|
259 |
display: block;
|
260 |
}
|
261 |
|
262 |
+
form.wprss-error-log-action {
|
263 |
+
display: inline-block;
|
264 |
+
margin: 15px 5px 15px 0;
|
265 |
+
}
|
266 |
+
form.wprss-error-log-action input[type="submit"]:active {
|
267 |
+
vertical-align: baseline;
|
268 |
+
}
|
269 |
|
270 |
@media screen and (min-width: 782px) {
|
271 |
#custom_feed_title {
|
includes/Aventura/Wprss/Core/Caching/ImageCache.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Caching;
|
4 |
+
|
5 |
+
if (!class_exists('\\WPRSS_Image_Cache')) {
|
6 |
+
require WPRSS_INC . 'image-caching.php';
|
7 |
+
}
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Image caching class.
|
11 |
+
*/
|
12 |
+
class ImageCache extends \WPRSS_Image_Cache {
|
13 |
+
|
14 |
+
protected function _construct() {
|
15 |
+
$this->set_image_class_name( __NAMESPACE__ . '\\ImageCache\\Image' );
|
16 |
+
}
|
17 |
+
|
18 |
+
}
|
includes/Aventura/Wprss/Core/Caching/ImageCache/Image.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Caching\ImageCache;
|
4 |
+
|
5 |
+
if (!class_exists('\\WPRSS_Image_Cache_Image')) {
|
6 |
+
require WPRSS_INC . 'image-caching.php';
|
7 |
+
}
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Image class for ImageCache module.
|
11 |
+
*/
|
12 |
+
class Image extends \WPRSS_Image_Cache_Image {
|
13 |
+
|
14 |
+
}
|
includes/Aventura/Wprss/Core/Licensing/AjaxController.php
ADDED
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Licensing;
|
4 |
+
use \Aventura\Wprss\Core\Licensing\License\Status;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* AJAX controller class for licensing AJAX operations.
|
8 |
+
*/
|
9 |
+
class AjaxController {
|
10 |
+
|
11 |
+
// Pattern for ajax handler methods
|
12 |
+
const AJAX_MANAGE_LICENSE_METHOD_PATTERN = 'handleAjaxLicense%s';
|
13 |
+
|
14 |
+
protected $_manager;
|
15 |
+
protected $_settings;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Constructor.
|
19 |
+
*/
|
20 |
+
public function __construct() {
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Sets the settings controller to be used by this instance.
|
25 |
+
*
|
26 |
+
* @param \Aventura\Wprss\Core\Licensing\Settings $settings The settings controller.
|
27 |
+
* @return \Aventura\Wprss\Core\Licensing\AjaxController This instance.
|
28 |
+
*/
|
29 |
+
public function setSettingsController( Settings $settings ) {
|
30 |
+
$this->_settings = $settings;
|
31 |
+
return $this;
|
32 |
+
}
|
33 |
+
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Gets the settings controller used by this instance.
|
37 |
+
*
|
38 |
+
* @return \Aventura\Wprss\Core\Licensing\Settings The settings controller used by this instance.
|
39 |
+
*/
|
40 |
+
public function getSettingsController() {
|
41 |
+
return $this->_settings;
|
42 |
+
}
|
43 |
+
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Sets the license manager to be used by this instance.
|
47 |
+
*
|
48 |
+
* @param \Aventura\Wprss\Core\Licensing\Manager $manager The license manager to use.
|
49 |
+
* @return \Aventura\Wprss\Core\Licensing\AjaxController This instance.
|
50 |
+
*/
|
51 |
+
public function setManager(Manager $manager) {
|
52 |
+
$this->_manager = $manager;
|
53 |
+
return $this;
|
54 |
+
}
|
55 |
+
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Gets the license manager used by this instance.
|
59 |
+
*
|
60 |
+
* @return \Aventura\Wprss\Core\Licensing\Manager The lisence manager.
|
61 |
+
*/
|
62 |
+
public function getManager() {
|
63 |
+
return $this->_manager;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Echoes an AJAX error response along with activate/deactivate license button HTML markup and then dies.
|
68 |
+
*
|
69 |
+
* @param string $message The error message to send.
|
70 |
+
* @param string $addonId Optional addon ID related to the error, used for sending the activate/deactivate license button.
|
71 |
+
*/
|
72 |
+
protected function _sendErrorResponse( $message, $addonId = '' ) {
|
73 |
+
$response = array(
|
74 |
+
'error' => $message,
|
75 |
+
'html' => $this->getSettingsController()->getActivateLicenseButtonHtml($addonId)
|
76 |
+
);
|
77 |
+
|
78 |
+
echo json_encode( $response );
|
79 |
+
die();
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Handles AJAX requests for managing licenses (activation, deactivation, etc..)
|
84 |
+
*/
|
85 |
+
public function handleAjaxManageLicense() {
|
86 |
+
// Get data from request
|
87 |
+
$nonce = empty( $_GET['nonce'] )? null : sanitize_text_field( $_GET['nonce'] );
|
88 |
+
$addon = empty( $_GET['addon'] )? null : sanitize_text_field( $_GET['addon'] );
|
89 |
+
$event = empty( $_GET['event'] )? null : sanitize_text_field( $_GET['event'] );
|
90 |
+
$licenseKey = empty( $_GET['license'] )? null : sanitize_text_field( $_GET['license'] );
|
91 |
+
|
92 |
+
// If no nonce, stop
|
93 |
+
if ( $nonce === null ) $this->_sendErrorResponse( __( 'No nonce', WPRSS_TEXT_DOMAIN ), $addon );
|
94 |
+
// Generate the nonce id
|
95 |
+
$nonce_id = sprintf( 'wprss_%s_license_nonce', $addon );
|
96 |
+
// Verify the nonce. If verification fails, stop
|
97 |
+
if ( ! wp_verify_nonce( $nonce, $nonce_id ) ) {
|
98 |
+
$this->_sendErrorResponse( __( 'Bad nonce', WPRSS_TEXT_DOMAIN ), $addon );
|
99 |
+
}
|
100 |
+
|
101 |
+
// Check addon, event and license
|
102 |
+
if ( $addon === null ) $this->_sendErrorResponse( __( 'No addon ID', WPRSS_TEXT_DOMAIN ) );
|
103 |
+
if ( $event === null ) $this->_sendErrorResponse( __( 'No event specified', WPRSS_TEXT_DOMAIN ), $addon );
|
104 |
+
if ( $licenseKey === null ) $this->_sendErrorResponse( __( 'No license', WPRSS_TEXT_DOMAIN ), $addon );
|
105 |
+
|
106 |
+
$settings = $this->getSettingsController();
|
107 |
+
$manager = $this->getManager();
|
108 |
+
|
109 |
+
// Check if the license key was obfuscated on the client's end.
|
110 |
+
if ( $settings->isLicenseKeyObfuscated( $licenseKey ) ) {
|
111 |
+
// If so, use the stored license key since obfuscation signifies that the key was not modified
|
112 |
+
// and is equal to the one saved in db
|
113 |
+
$licenseKey = $manager->getLicense( $addon );
|
114 |
+
} else {
|
115 |
+
// Otherwise, update the value in db
|
116 |
+
$license = $manager->getLicense( $addon );
|
117 |
+
if ( $license === null ) {
|
118 |
+
$license = $manager->createLicense( $addon );
|
119 |
+
}
|
120 |
+
$license->setKey( $licenseKey );
|
121 |
+
$manager->saveLicenseKeys();
|
122 |
+
}
|
123 |
+
|
124 |
+
// uppercase first letter of event
|
125 |
+
$event = ucfirst( $event );
|
126 |
+
// Generate method name
|
127 |
+
$eventMethod = sprintf( self::AJAX_MANAGE_LICENSE_METHOD_PATTERN, $event );
|
128 |
+
// check if the event is handle-able
|
129 |
+
if ( ! method_exists( $this, $eventMethod ) ) {
|
130 |
+
$this->_sendErrorResponse( __( 'Invalid event specified', WPRSS_TEXT_DOMAIN ), $addon);
|
131 |
+
}
|
132 |
+
|
133 |
+
// Call the appropriate handler method
|
134 |
+
$returnValue = call_user_func_array( array( $this, $eventMethod ), array( $addon ) );
|
135 |
+
|
136 |
+
// Prepare the response
|
137 |
+
$partialResponse = array(
|
138 |
+
'addon' => $addon,
|
139 |
+
'html' => $settings->getActivateLicenseButtonHtml( $addon ),
|
140 |
+
'licensedAddons' => array_keys( $manager->getLicensesWithStatus( Status::VALID ) )
|
141 |
+
);
|
142 |
+
// Merge the returned value(s) from the handler method to generate the final resposne
|
143 |
+
$response = array_merge( $partialResponse, $returnValue );
|
144 |
+
|
145 |
+
// Return the JSON data.
|
146 |
+
echo json_encode( $response );
|
147 |
+
die();
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Handles the AJAX request to fetch license information.
|
152 |
+
*/
|
153 |
+
public function handleAjaxFetchLicense() {
|
154 |
+
// If not addon ID in the request, stop
|
155 |
+
if ( empty( $_GET['addon']) )
|
156 |
+
$this->_sendErrorResponse( __( 'No addon ID', WPRSS_TEXT_DOMAIN ) );
|
157 |
+
// Get and sanitize the addon ID
|
158 |
+
$addon = sanitize_text_field( $_GET['addon'] );
|
159 |
+
// Get the license information from EDD
|
160 |
+
$response = $this->getManager()->checkLicense( $addon, 'ALL' );
|
161 |
+
// Send response as JSON
|
162 |
+
echo json_encode( $response );
|
163 |
+
die();
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Handles the activation AJAX request to activate the license for the given addon.
|
168 |
+
*
|
169 |
+
* @param string $addonId The addon ID.
|
170 |
+
* @return array The data to add to the AJAX response, containing the license status after activation.
|
171 |
+
*/
|
172 |
+
public function handleAjaxLicenseActivate( $addonId ) {
|
173 |
+
$manager = $this->getManager();
|
174 |
+
return array(
|
175 |
+
'validity' => $manager->normalizeLicenseApiStatus( $manager->activateLicense( $addonId ) )
|
176 |
+
);
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Handles the deactivation AJAX request to deactivate the license for the given addon.
|
181 |
+
*
|
182 |
+
* @param string $addonId The addon ID.
|
183 |
+
* @return array The data to add to the AJAX response, containing the license status after activation.
|
184 |
+
*/
|
185 |
+
public function handleAjaxLicenseDeactivate( $addonId ) {
|
186 |
+
$manager = $this->getManager();
|
187 |
+
return array(
|
188 |
+
'validity' => $manager->normalizeLicenseApiStatus( $manager->deactivateLicense( $addonId ) )
|
189 |
+
);
|
190 |
+
}
|
191 |
+
|
192 |
+
}
|
includes/Aventura/Wprss/Core/Licensing/License.php
ADDED
@@ -0,0 +1,177 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Licensing;
|
4 |
+
use \Aventura\Wprss\Core\Licensing\License\Status;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* This class represents a single license object.
|
8 |
+
*
|
9 |
+
* IMPORTANT!
|
10 |
+
* This version is still untested
|
11 |
+
*
|
12 |
+
* @version 1.0-alpha
|
13 |
+
* @since 4.7.8
|
14 |
+
*/
|
15 |
+
class License {
|
16 |
+
|
17 |
+
// Default values for license properties
|
18 |
+
const KEY_DEFAULT = false;
|
19 |
+
const STATUS_DEFAULT = Status::INVALID;
|
20 |
+
const EXPIRY_DEFAULT = null;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* License key.
|
24 |
+
*
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
+
protected $_key;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* License status.
|
31 |
+
*
|
32 |
+
* @see Aventura\Wprss\Licensing\License\Status;
|
33 |
+
* @var string
|
34 |
+
*/
|
35 |
+
protected $_status;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* License expiry date.
|
39 |
+
*
|
40 |
+
* @var integer
|
41 |
+
*/
|
42 |
+
protected $_expiry;
|
43 |
+
|
44 |
+
/** @var string Code of the add-on this license belongs to. */
|
45 |
+
protected $_addonCode;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Constructs a new instance, using the given params or an array of properties if only the first param is given.
|
49 |
+
*
|
50 |
+
* @param string $key The license key, or an array containing the license data. Default: array()
|
51 |
+
* @param string $status The license status. Default: null
|
52 |
+
* @param integer $expiry The expiry date of this license. Default: null
|
53 |
+
* @see Aventura\Wprss\Licensing\License\Status
|
54 |
+
*/
|
55 |
+
public function __construct( $key = array(), $status = null, $expiry = null, $addonCode = null ) {
|
56 |
+
// If first arg is an array,
|
57 |
+
if ( is_array( $key ) ) {
|
58 |
+
// Get values from the appropriate keys
|
59 |
+
$data = array_merge( self::getDefaultSettings(), $key );
|
60 |
+
$key = $data['key'];
|
61 |
+
$status = $data['status'];
|
62 |
+
$expiry = $data['expires'];
|
63 |
+
$addonCode = $data['addon_code'];
|
64 |
+
}
|
65 |
+
|
66 |
+
$this
|
67 |
+
// Set fields
|
68 |
+
->setKey( $key )
|
69 |
+
->setStatus( $status )
|
70 |
+
->setExpiry( $expiry )
|
71 |
+
->setAddonCode( $addonCode )
|
72 |
+
// Call secondary constructor
|
73 |
+
->_construct();
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Internal secondary constructor, for use when class is extended.
|
78 |
+
*/
|
79 |
+
protected function _construct() {}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Gets the license key.
|
83 |
+
*
|
84 |
+
* @return string
|
85 |
+
*/
|
86 |
+
public function getKey() {
|
87 |
+
return $this->_key;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Sets the license key.
|
92 |
+
*
|
93 |
+
* @param string $key The license key.
|
94 |
+
* @return self
|
95 |
+
*/
|
96 |
+
public function setKey( $key ) {
|
97 |
+
$this->_key = $key;
|
98 |
+
return $this;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Gets the license status.
|
103 |
+
*
|
104 |
+
* @see Aventura\Wprss\Licensing\License\Status
|
105 |
+
* @return string
|
106 |
+
*/
|
107 |
+
public function getStatus() {
|
108 |
+
return $this->_status;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Sets the license status.
|
113 |
+
*
|
114 |
+
* @see Aventura\Wprss\Licensing\License\Status
|
115 |
+
*
|
116 |
+
* @param string $status The license status.
|
117 |
+
* @return self
|
118 |
+
*/
|
119 |
+
public function setStatus( $status ) {
|
120 |
+
$this->_status = $status;
|
121 |
+
return $this;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Gets the license expiry date.
|
126 |
+
*
|
127 |
+
* @return integer
|
128 |
+
*/
|
129 |
+
public function getExpiry() {
|
130 |
+
return $this->_expiry;
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Sets the license expiry date.
|
135 |
+
*
|
136 |
+
* @param integer $expiry The license expiry date
|
137 |
+
*/
|
138 |
+
public function setExpiry( $expiry ) {
|
139 |
+
$this->_expiry = $expiry;
|
140 |
+
return $this;
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Set the code of the add-on that this license belongs to.
|
145 |
+
*
|
146 |
+
* @param string $code Code of the addon that this license belongs to.
|
147 |
+
* @return \Aventura\Wprss\Core\Licensing\License This instance.
|
148 |
+
*/
|
149 |
+
public function setAddonCode($code) {
|
150 |
+
$this->_addonCode = $code;
|
151 |
+
return $this;
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Get the code of the add-on that this license belongs to.
|
156 |
+
*
|
157 |
+
* @return string Code of the addon that this license belongs to.
|
158 |
+
*/
|
159 |
+
public function getAddonCode() {
|
160 |
+
return $this->_addonCode;
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Gets the default values for all properties of the license.
|
165 |
+
*
|
166 |
+
* @return array
|
167 |
+
*/
|
168 |
+
public static function getDefaultSettings() {
|
169 |
+
return array(
|
170 |
+
'key' => '',
|
171 |
+
'status' => Status::INVALID,
|
172 |
+
'expires' => null,
|
173 |
+
'addon_code'=> null,
|
174 |
+
);
|
175 |
+
}
|
176 |
+
|
177 |
+
}
|
includes/Aventura/Wprss/Core/Licensing/License/Status.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Licensing\License;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Enum-style abstract class for license statuses.
|
7 |
+
*/
|
8 |
+
abstract class Status {
|
9 |
+
const VALID = 'valid';
|
10 |
+
const INVALID = 'invalid';
|
11 |
+
const INACTIVE = 'inactive';
|
12 |
+
const EXPIRED = 'expired';
|
13 |
+
}
|
includes/Aventura/Wprss/Core/Licensing/Manager.php
ADDED
@@ -0,0 +1,768 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Licensing;
|
4 |
+
use \Aventura\Wprss\Core\Licensing\License\Status;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Manager class for license handling.
|
8 |
+
*
|
9 |
+
* @version 1.0
|
10 |
+
* @since 4.7.8
|
11 |
+
*/
|
12 |
+
class Manager {
|
13 |
+
|
14 |
+
// The default updater class
|
15 |
+
const DEFAULT_UPDATER_CLASS = '\\Aventura\\Wprss\\Core\\Licensing\\Plugin\\Updater';
|
16 |
+
|
17 |
+
// Name of license keys option in DB
|
18 |
+
const DB_LICENSE_KEYS_OPTION_NAME = 'wprss_settings_license_keys';
|
19 |
+
// Name of license statuses option in DB
|
20 |
+
const DB_LICENSE_STATUSES_OPTION_NAME = 'wprss_settings_license_statuses';
|
21 |
+
// Regex pattern for keys in license option
|
22 |
+
const DB_LICENSE_KEYS_OPTION_PATTERN = '%s_license_key';
|
23 |
+
// Regex pattern for statuses in license option
|
24 |
+
const DB_LICENSE_STATUSES_OPTION_PATTERN = '%s_license_%s';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* License instance.
|
28 |
+
*
|
29 |
+
* @var array
|
30 |
+
*/
|
31 |
+
protected $_licenses;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* The class to use for updating addons.
|
35 |
+
*
|
36 |
+
* @var string
|
37 |
+
*/
|
38 |
+
protected $_updaterClass;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* The updater instances for the addons.
|
42 |
+
*
|
43 |
+
* @var array
|
44 |
+
*/
|
45 |
+
protected $_updaterInstances;
|
46 |
+
|
47 |
+
protected $_licenseKeysOptionName;
|
48 |
+
protected $_licenseStatusesOptionName;
|
49 |
+
protected $_expirationNoticePeriod;
|
50 |
+
protected $_defaultAuthorName;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Constructor.
|
54 |
+
*/
|
55 |
+
public function __construct() {
|
56 |
+
// Reset the updater instances
|
57 |
+
$this->_updaterInstances = array();
|
58 |
+
$this->_loadLicenses();
|
59 |
+
$this->_construct();
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Internal secondary constructor, used by classes that extend this class.
|
64 |
+
*/
|
65 |
+
protected function _construct() {}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Gets the name of the class used to update the addons.
|
69 |
+
*
|
70 |
+
* @return string
|
71 |
+
*/
|
72 |
+
public function getUpdaterClass() {
|
73 |
+
if ( is_null($this->_updaterClass) ) {
|
74 |
+
return self::DEFAULT_UPDATER_CLASS;
|
75 |
+
}
|
76 |
+
|
77 |
+
return $this->_updaterClass;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Sets the class used to update the addons.
|
82 |
+
*
|
83 |
+
* @param string $updaterClass The name of the updater class.
|
84 |
+
* @return self
|
85 |
+
*/
|
86 |
+
public function setUpdaterClass( $updaterClass ) {
|
87 |
+
$this->_updaterClass = $updaterClass;
|
88 |
+
return self;
|
89 |
+
}
|
90 |
+
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Get the period before license expiration, for which a notice should be displayed.
|
94 |
+
*
|
95 |
+
* @return int|string An integer, representing the number of secods before license expiry.
|
96 |
+
* or a string, representing a time offset that can be used with strtotime().
|
97 |
+
*/
|
98 |
+
public function getExpirationNoticePeriod() {
|
99 |
+
$period = $this->_expirationNoticePeriod;
|
100 |
+
if ( is_numeric( $period ) ) {
|
101 |
+
$period = intval( $period );
|
102 |
+
}
|
103 |
+
|
104 |
+
return $period;
|
105 |
+
}
|
106 |
+
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Set the period before license expiration, for which a notice should be displayed.
|
110 |
+
*
|
111 |
+
* @param int|string $period An integer, representing the number of secods before license expiry.
|
112 |
+
* @return \Aventura\Wprss\Core\Licensing\Manager This instance.
|
113 |
+
*/
|
114 |
+
public function setExpirationNoticePeriod( $period ) {
|
115 |
+
$this->_expirationNoticePeriod = trim($period);
|
116 |
+
return $this;
|
117 |
+
}
|
118 |
+
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Gets the name of the plugin author that is used by default.
|
122 |
+
*
|
123 |
+
* @return string Nae of the plugin author that is sent to EDD API by default.
|
124 |
+
*/
|
125 |
+
public function getDefaultAuthorName() {
|
126 |
+
return $this->_defaultAuthorName;
|
127 |
+
}
|
128 |
+
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Sets the name of the plugin author that will be used by default.
|
132 |
+
*
|
133 |
+
* @param string $name Name of the plugin author that will be sent to EDD API by default.
|
134 |
+
* @return \Aventura\Wprss\Core\Licensing\Manager This instance.
|
135 |
+
*/
|
136 |
+
public function setDefaultAuthorName($name) {
|
137 |
+
$this->_defaultAuthorName = $name;
|
138 |
+
return $this;
|
139 |
+
}
|
140 |
+
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Gets a list of registered addons.
|
144 |
+
*
|
145 |
+
* @return array An assoc array containing addon IDs as array keys and the addon names as array values.
|
146 |
+
*/
|
147 |
+
public function getAddons() {
|
148 |
+
return wprss_get_addons();
|
149 |
+
}
|
150 |
+
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Gets all of the updater instances.
|
154 |
+
*
|
155 |
+
* Alias for self#getUpdaterInstance()
|
156 |
+
*
|
157 |
+
* @see self::getUpdaterInstance
|
158 |
+
* @uses self::getUpdaterInstance
|
159 |
+
* @return array
|
160 |
+
*/
|
161 |
+
public function getUpdaterInstances() {
|
162 |
+
return $this->getUpdaterInstance();
|
163 |
+
}
|
164 |
+
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Gets the updater instance for a single addon, or all the updater instances if no param or null is passed.#
|
168 |
+
*
|
169 |
+
* @param mixed $addonId The addon ID for which to return the updater instance, or null to return all instances. Default: null
|
170 |
+
* @return mixed An instance of \Aventura\Wprss\Core\Licensing\Plugin\UpdaterInterface if an addon ID is given, or an array of instances is null is given.
|
171 |
+
*/
|
172 |
+
public function getUpdaterInstance( $addonId = null ) {
|
173 |
+
return is_null($addonId)
|
174 |
+
? $this->_updaterInstances
|
175 |
+
: $this->_getUpdaterInstance($addonId);
|
176 |
+
}
|
177 |
+
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Internally used to get a single updater instance for a particular addon.
|
181 |
+
*
|
182 |
+
* @param string $addonId The addon ID.
|
183 |
+
* @return \Aventura\Wprss\Core\Licensing\Plugin\UpdaterInterface
|
184 |
+
*/
|
185 |
+
protected function _getUpdaterInstance( $addonId ) {
|
186 |
+
return $this->hasUpdaterInsantance($addonId)
|
187 |
+
? $this->_updaterInstances[$addonId]
|
188 |
+
: null;
|
189 |
+
}
|
190 |
+
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Checks if an updater instance exists for a specific addon.
|
194 |
+
*
|
195 |
+
* @param string $addonId The addon ID.
|
196 |
+
* @return boolean True if the updater instance exists, false if not.
|
197 |
+
*/
|
198 |
+
public function hasUpdaterInsantance($addonId) {
|
199 |
+
return isset($this->_updaterInstances[$addonId]);
|
200 |
+
}
|
201 |
+
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Sets the updater instance for an addon.
|
205 |
+
*
|
206 |
+
* @param string $addonId The addon ID.
|
207 |
+
* @param \Aventura\Wprss\Core\Licensing\Plugin\UpdaterInterface The updater instance.
|
208 |
+
*/
|
209 |
+
protected function _setUpdaterInstance($addonId, $instance) {
|
210 |
+
$this->_updaterInstances[ $addonId ] = $instance;
|
211 |
+
return $this;
|
212 |
+
}
|
213 |
+
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Creates a new license.
|
217 |
+
*
|
218 |
+
* This does not save the license to the database. You will need to call Manager::saveLicenses() to save to db.
|
219 |
+
*
|
220 |
+
* @param string $addonId The addon ID
|
221 |
+
* @return License The created license
|
222 |
+
*/
|
223 |
+
public function createLicense( $addonId ) {
|
224 |
+
return $this->_licenses[ $addonId ] = new License( array('addon_code' => $addonId) );
|
225 |
+
}
|
226 |
+
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Gets all license key settings.
|
230 |
+
*
|
231 |
+
* @return array
|
232 |
+
*/
|
233 |
+
public function getLicenses() {
|
234 |
+
return $this->_licenses;
|
235 |
+
}
|
236 |
+
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Gets the license key for a specific addon.
|
240 |
+
*
|
241 |
+
* @param string $addonId The addon id.
|
242 |
+
* @return array
|
243 |
+
*/
|
244 |
+
public function getLicense( $addonId ) {
|
245 |
+
if ( ! $this->licenseExists( $addonId ) ) {
|
246 |
+
return null;
|
247 |
+
}
|
248 |
+
return $this->_licenses[ $addonId ];
|
249 |
+
}
|
250 |
+
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Checks if an addon license key
|
254 |
+
*
|
255 |
+
* @param string $addonId The addon id
|
256 |
+
* @return boolean True if the license key for the given addon id exists, false if not.
|
257 |
+
*/
|
258 |
+
public function licenseExists( $addonId ) {
|
259 |
+
return isset( $this->_licenses[ $addonId ] );
|
260 |
+
}
|
261 |
+
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Gets all licenses with the given status.
|
265 |
+
*
|
266 |
+
* @param string $status The status to search for.
|
267 |
+
* @param boolean $negation If true, the method will search for licenses that do NOT have the given status.
|
268 |
+
* If false, the method will search for licenses with the given status.
|
269 |
+
* Default: false
|
270 |
+
* @return array An array of matching licenses. Array keys contain the addon IDs and array values contain the license objects.
|
271 |
+
*/
|
272 |
+
public function getLicensesWithStatus( $status, $negation = false ) {
|
273 |
+
$licenses = array();
|
274 |
+
foreach ( $this->_licenses as $_addonId => $_license ) {
|
275 |
+
if ( $_license->getStatus() === $status xor $negation === true ) {
|
276 |
+
$licenses[ $_addonId ] = $_license;
|
277 |
+
}
|
278 |
+
}
|
279 |
+
return $licenses;
|
280 |
+
}
|
281 |
+
|
282 |
+
|
283 |
+
/**
|
284 |
+
* Checks if a license with the given status exists, stopping at the first match.
|
285 |
+
*
|
286 |
+
* @param string $status The status to search for.
|
287 |
+
* @param boolean $negation If true, the method will search for licenses that do NOT have the given status.
|
288 |
+
* If false, the method will search for licenses with the given status.
|
289 |
+
* Default: false
|
290 |
+
* @return boolean True if a license with or without (depending on $negation) the given status exists, false otherwise.
|
291 |
+
*/
|
292 |
+
public function licenseWithStatusExists( $status, $negation = false ) {
|
293 |
+
return count( $this->getLicensesWithStatus( $status, $negation ) ) > 0;
|
294 |
+
}
|
295 |
+
|
296 |
+
|
297 |
+
/**
|
298 |
+
* Gets the licenses that are soon to be expired.
|
299 |
+
*
|
300 |
+
* @uses self::_calculateSteTimestamp To calculate the minimum date for classifying licenses as "soon-to-expire".
|
301 |
+
*
|
302 |
+
* @return array An assoc array with addon IDs as array keys and License instances as array values.
|
303 |
+
*/
|
304 |
+
public function getExpiringLicenses() {
|
305 |
+
// Calculate soon-to-expiry (ste) date
|
306 |
+
$ste = $this->getSteTimestamp();
|
307 |
+
// Prepare the list
|
308 |
+
$expiringLicences = array();
|
309 |
+
// Iterate all licenses
|
310 |
+
foreach ( $this->_licenses as $addonId => $license ) {
|
311 |
+
// Get expiry
|
312 |
+
$expires = $license->getExpiry();
|
313 |
+
// Split using space and get first part only (date only)
|
314 |
+
$parts = explode( ' ', $expires );
|
315 |
+
$dateOnly = strtotime( $parts[0] );
|
316 |
+
// Check if the expiry date is zero, or is within the expiration notice period
|
317 |
+
if ( $dateOnly == 0 || $dateOnly < $ste ) {
|
318 |
+
$expiringLicences[ $addonId ] = $license;
|
319 |
+
}
|
320 |
+
}
|
321 |
+
return $expiringLicences;
|
322 |
+
}
|
323 |
+
|
324 |
+
|
325 |
+
/**
|
326 |
+
* Checks if there are licenses that will soon expire.
|
327 |
+
*
|
328 |
+
* @uses self::_calculateSteTimestamp To calculate the minimum date for classifying licenses as "soon-to-expire".
|
329 |
+
*
|
330 |
+
* @return bool True if there are licenses that will soon expire, false otherwise.
|
331 |
+
*/
|
332 |
+
public function expiringLicensesExist() {
|
333 |
+
return count( $this->getExpiringLicenses() ) > 0;
|
334 |
+
}
|
335 |
+
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Activates an add-on's license.
|
339 |
+
*
|
340 |
+
* @uses self::sendApiRequest() Sends the request with $action set as 'activate_license'.
|
341 |
+
*
|
342 |
+
* @param string $addonId The ID of the addon.
|
343 |
+
* @param string $return What to return from the response.
|
344 |
+
* @return mixed
|
345 |
+
*/
|
346 |
+
public function activateLicense( $addonId, $return = 'license') {
|
347 |
+
return $this->sendApiRequest( $addonId, 'activate_license', $return );
|
348 |
+
}
|
349 |
+
|
350 |
+
|
351 |
+
/**
|
352 |
+
* Deactivates an add-on's license.
|
353 |
+
*
|
354 |
+
* @uses self::sendApiRequest() Sends the request with $action set as 'deactivate_license'.
|
355 |
+
*
|
356 |
+
* @param string $addonId The ID of the addon.
|
357 |
+
* @param string $return What to return from the response.
|
358 |
+
* @return mixed
|
359 |
+
*/
|
360 |
+
public function deactivateLicense( $addonId, $return = 'license') {
|
361 |
+
return $this->sendApiRequest( $addonId, 'deactivate_license', $return );
|
362 |
+
}
|
363 |
+
|
364 |
+
|
365 |
+
/**
|
366 |
+
* Checks an add-on's license's status with the server.
|
367 |
+
*
|
368 |
+
* @uses self::sendApiRequest() Sends the request with $action set as 'check_license'.
|
369 |
+
*
|
370 |
+
* @param string $addonId The ID of the addon.
|
371 |
+
* @param string $return What to return from the response.
|
372 |
+
* @return mixed
|
373 |
+
*/
|
374 |
+
public function checkLicense( $addonId, $return = 'license') {
|
375 |
+
return $this->sendApiRequest( $addonId, 'check_license', $return );
|
376 |
+
}
|
377 |
+
|
378 |
+
|
379 |
+
/**
|
380 |
+
* Calls the EDD Software Licensing API to perform licensing tasks on the addon's store server.
|
381 |
+
*
|
382 |
+
* @param string $addonId The ID of the addon
|
383 |
+
* @param string $action The action to perform on the license.
|
384 |
+
* @param string $return What to return from the response. If 'ALL', the entire license status object is returned,
|
385 |
+
* Otherwise, the property with name $return will be returned, or null if it doesn't exist.
|
386 |
+
* @return mixed
|
387 |
+
*/
|
388 |
+
public function sendApiRequest( $addonId, $action = 'check_license', $return = 'license' ) {
|
389 |
+
// Get the license for the addon
|
390 |
+
$license = $this->getLicense( $addonId );
|
391 |
+
// Use blank license if addon license does not exist
|
392 |
+
if ( $license === null ) {
|
393 |
+
$license = new License();
|
394 |
+
}
|
395 |
+
|
396 |
+
// Addon Uppercase ID
|
397 |
+
$addonUid = strtoupper( $addonId );
|
398 |
+
// Prepare constants
|
399 |
+
$itemName = constant( "WPRSS_{$addonUid}_SL_ITEM_NAME" );
|
400 |
+
$storeUrl = constant( "WPRSS_{$addonUid}_SL_STORE_URL" );
|
401 |
+
|
402 |
+
try {
|
403 |
+
$licenseData = $this->api($storeUrl, array(
|
404 |
+
'edd_action' => $action,
|
405 |
+
'license' => $license,
|
406 |
+
'item_name' => $itemName,
|
407 |
+
));
|
408 |
+
} catch ( Exception $e ) {
|
409 |
+
wprss_log( sprintf( 'Could not retrieve licensing data from "%1$s": %2$s', $storeUrl, $e->getMessage() ), __FUNCTION__, WPRSS_LOG_LEVEL_WARNING );
|
410 |
+
return $license->getStatus();
|
411 |
+
}
|
412 |
+
|
413 |
+
// Update the DB option
|
414 |
+
$license->setStatus( $licenseData->license );
|
415 |
+
$license->setExpiry( $licenseData->expires );
|
416 |
+
$this->saveLicenseStatuses();
|
417 |
+
|
418 |
+
// Return the data
|
419 |
+
if ( strtoupper( $return ) === 'ALL' ) {
|
420 |
+
return $licenseData;
|
421 |
+
} else {
|
422 |
+
return isset( $licenseData->{$return} ) ? $licenseData->{$return} : null;
|
423 |
+
}
|
424 |
+
}
|
425 |
+
|
426 |
+
|
427 |
+
/**
|
428 |
+
* Low-level method for sending API requests to an EDD license server.
|
429 |
+
*
|
430 |
+
* Will normalize parameters for the request as needed, and return the decoded response.
|
431 |
+
*
|
432 |
+
* @param string $storeUrl The URL, to which to send the request. The EDD API endpoint.
|
433 |
+
* @param array $params Params of the request. 'license', 'edd_action' and
|
434 |
+
* 'item_name' are required for a successful call. 'license' can also be
|
435 |
+
* an instance of {@link Aventura\Wprss\Core\Licensing\License}.
|
436 |
+
* @return object License data as properties of an stdClass instance.
|
437 |
+
* @throws Exception If request fails, or returns empty response, or response cannot be decoded.
|
438 |
+
*/
|
439 |
+
public function api($storeUrl, $params) {
|
440 |
+
$defaultParams = array(
|
441 |
+
'edd_action' => null,
|
442 |
+
'license' => null,
|
443 |
+
'item_name' => null,
|
444 |
+
'url' => network_site_url(),
|
445 |
+
'time' => time(),
|
446 |
+
);
|
447 |
+
|
448 |
+
// Prepare params
|
449 |
+
$params = array_merge($defaultParams, $params);
|
450 |
+
array_walk($params, array($this, 'sanitizeApiParams'));
|
451 |
+
if ( $params['license'] instanceof License ) $params['license'] = $params['license']->getKey();
|
452 |
+
if ( $params['license'] ) $params['license'] = sanitize_text_field ( $params['license']);
|
453 |
+
if ( $params['item_name'] ) $params['item_name'] = sanitize_text_field ( $params['item_name']);
|
454 |
+
if ( $params['url'] ) $params['url'] = urlencode ( $params['url']);
|
455 |
+
|
456 |
+
// Send the request to the API
|
457 |
+
$response = wp_remote_post( add_query_arg( $params, $storeUrl ) );
|
458 |
+
|
459 |
+
// Request failed
|
460 |
+
if ( is_wp_error( $response ) ) {
|
461 |
+
throw new Exception( sprintf( 'Licensing API request failed: %1$s', $response->get_error_message() ) );
|
462 |
+
}
|
463 |
+
|
464 |
+
$body = wp_remote_retrieve_body( $response );
|
465 |
+
if ( empty( $body ) ) {
|
466 |
+
throw new Exception( sprintf( 'Licensing API response returned empty' ) );
|
467 |
+
}
|
468 |
+
|
469 |
+
if ( ($licenseData = json_decode( $body )) === null ) {
|
470 |
+
throw new Exception( sprintf( 'Licensing API response could not be decoded' ) );
|
471 |
+
}
|
472 |
+
|
473 |
+
return $licenseData;
|
474 |
+
}
|
475 |
+
|
476 |
+
|
477 |
+
/**
|
478 |
+
* Sanitizes the API params, prior to sending them.
|
479 |
+
*
|
480 |
+
* @param mixed $value The param value
|
481 |
+
* @param string $key The param ID
|
482 |
+
* @return mixed The sanitized param value.
|
483 |
+
*/
|
484 |
+
public function sanitizeApiParams( &$value, $key ) {
|
485 |
+
$value = is_string($value)? urlencode($value) : $value;
|
486 |
+
}
|
487 |
+
|
488 |
+
|
489 |
+
/**
|
490 |
+
* Sets up the EDD updater for all registered add-ons.
|
491 |
+
*
|
492 |
+
* @since 4.6.3
|
493 |
+
*/
|
494 |
+
public function initUpdaterInstances() {
|
495 |
+
// Stop if doing autosave or ajax
|
496 |
+
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) return;
|
497 |
+
|
498 |
+
// Get all registered addons
|
499 |
+
$addons = $this->getAddons();
|
500 |
+
|
501 |
+
// Iterate the addons
|
502 |
+
foreach( $addons as $id => $name ) {
|
503 |
+
// Prepare the data
|
504 |
+
$license = $this->getLicense( $id );
|
505 |
+
// If the addon doesn't have a license or the license is not valid, skip this addon
|
506 |
+
if ( $license === null || $license->getStatus() !== Status::VALID ) continue;
|
507 |
+
$uid = strtoupper( $id );
|
508 |
+
$name = constant("WPRSS_{$uid}_SL_ITEM_NAME");
|
509 |
+
$version = constant("WPRSS_{$uid}_VERSION");
|
510 |
+
$path = constant("WPRSS_{$uid}_PATH");
|
511 |
+
$storeUrl = defined( "WPRSS_{$uid}_SL_STORE_URL")
|
512 |
+
? constant( "WPRSS_{$uid}_SL_STORE_URL" )
|
513 |
+
: WPRSS_SL_STORE_URL;
|
514 |
+
|
515 |
+
// Set up an updater and register the instance
|
516 |
+
$this->_setUpdaterInstance(
|
517 |
+
$id,
|
518 |
+
$this->newUpdater($storeUrl, $path, array(
|
519 |
+
'version' => $version, // current version number
|
520 |
+
'license' => $license, // license key (used get_option above to retrieve from DB)
|
521 |
+
'item_name' => $name, // name of this plugin
|
522 |
+
))
|
523 |
+
);
|
524 |
+
}
|
525 |
+
}
|
526 |
+
|
527 |
+
|
528 |
+
/**
|
529 |
+
* Creates a new instance of the updater class, as configured.
|
530 |
+
*
|
531 |
+
* Guaranteed to return an updater.
|
532 |
+
*
|
533 |
+
* @see getUpdaterClass()
|
534 |
+
* @see Plugin\UpdaterInterface::__construct();
|
535 |
+
* @param string $url Endpoint URL.
|
536 |
+
* @param string $path Plugin file.
|
537 |
+
* @param array $params Params to requests.
|
538 |
+
* @return \Aventura\Wprss\Core\Licensing\Plugin\UpdaterInterface
|
539 |
+
*/
|
540 |
+
public function newUpdater($url, $path, $params = array()) {
|
541 |
+
// Get the updater class
|
542 |
+
$updaterClass = $this->getUpdaterClass();
|
543 |
+
|
544 |
+
$defaultParams = array(
|
545 |
+
'author' => $this->getDefaultAuthorName(),
|
546 |
+
'license' => null,
|
547 |
+
);
|
548 |
+
$params = array_merge($defaultParams, $params);
|
549 |
+
if ( $params['license'] instanceof License ) $params['license'] = $params['license']->getKey();
|
550 |
+
|
551 |
+
$updater = new $updaterClass($url, $path, $params);
|
552 |
+
if ( !($updater instanceof Plugin\UpdaterInterface) ) {
|
553 |
+
throw new Exception( sprintf( 'Could not create new updater: class "%1$s" is not an updater', get_class( $updater ) ) );
|
554 |
+
}
|
555 |
+
|
556 |
+
return $updater;
|
557 |
+
}
|
558 |
+
|
559 |
+
|
560 |
+
/**
|
561 |
+
* Normalizes the license status received by the API into the license statuses that we use locally in our code.
|
562 |
+
*
|
563 |
+
* @param string $status The status to normalize.
|
564 |
+
* @return string The normalized status.
|
565 |
+
*/
|
566 |
+
public function normalizeLicenseApiStatus( $status ) {
|
567 |
+
if ( $status === 'site_inactive' ) $status = 'inactive';
|
568 |
+
if ( $status === 'item_name_mismatch' ) $status = 'invalid';
|
569 |
+
return $status;
|
570 |
+
}
|
571 |
+
|
572 |
+
|
573 |
+
/**
|
574 |
+
* Loads the licenses from db and prepares the internal licenses array
|
575 |
+
*/
|
576 |
+
protected function _loadLicenses() {
|
577 |
+
$this->_licenses = array();
|
578 |
+
$options = self::_normalizeLicenseOptions( $this->getLicenseKeysDbOption(), $this->getLicenseStatusesDbOption() );
|
579 |
+
foreach ( $options as $addonId => $_data ) {
|
580 |
+
$this->_licenses[ $addonId ] = new License( $_data );
|
581 |
+
}
|
582 |
+
|
583 |
+
return $this;
|
584 |
+
}
|
585 |
+
|
586 |
+
|
587 |
+
/**
|
588 |
+
* Saves the licenses and their statuses to the db.
|
589 |
+
*/
|
590 |
+
public function saveLicenses() {
|
591 |
+
$this->saveLicenseKeys();
|
592 |
+
$this->saveLicenseStatuses();
|
593 |
+
|
594 |
+
return $this;
|
595 |
+
}
|
596 |
+
|
597 |
+
|
598 |
+
/**
|
599 |
+
* Saves the license keys to the db.
|
600 |
+
*/
|
601 |
+
public function saveLicenseKeys() {
|
602 |
+
$keys = array();
|
603 |
+
foreach ( $this->_licenses as $_addonId => $_license ) {
|
604 |
+
$_key = sprintf( self::DB_LICENSE_KEYS_OPTION_PATTERN, $_addonId );
|
605 |
+
$keys[ $_key ] = $_license->getKey();
|
606 |
+
}
|
607 |
+
update_option( self::DB_LICENSE_KEYS_OPTION_NAME, $keys );
|
608 |
+
|
609 |
+
return $this;
|
610 |
+
}
|
611 |
+
|
612 |
+
|
613 |
+
/**
|
614 |
+
* Saves the license statuses (and expirations) to the db.
|
615 |
+
*/
|
616 |
+
public function saveLicenseStatuses() {
|
617 |
+
$statuses = array();
|
618 |
+
foreach ( $this->_licenses as $_addonId => $_license ) {
|
619 |
+
$_status = sprintf( self::DB_LICENSE_STATUSES_OPTION_PATTERN, $_addonId, 'status' );
|
620 |
+
$_expires = sprintf( self::DB_LICENSE_STATUSES_OPTION_PATTERN, $_addonId, 'expires' );
|
621 |
+
$statuses[ $_status ] = $_license->getStatus();
|
622 |
+
$statuses[ $_expires ] = $_license->getExpiry();
|
623 |
+
}
|
624 |
+
update_option( self::DB_LICENSE_STATUSES_OPTION_NAME, $statuses );
|
625 |
+
|
626 |
+
return $this;
|
627 |
+
}
|
628 |
+
|
629 |
+
|
630 |
+
/**
|
631 |
+
* Retrieves the licenses keys db option.
|
632 |
+
*
|
633 |
+
* @return array
|
634 |
+
*/
|
635 |
+
public function getLicenseKeysDbOption() {
|
636 |
+
return get_option( $this->getLicenseKeysOptionName(), array() );
|
637 |
+
}
|
638 |
+
|
639 |
+
|
640 |
+
/**
|
641 |
+
* Retrieves the licenses statuses db option.
|
642 |
+
*
|
643 |
+
* @return array
|
644 |
+
*/
|
645 |
+
public function getLicenseStatusesDbOption() {
|
646 |
+
return get_option( $this->getLicenseStatusesOptionName(), array() );
|
647 |
+
}
|
648 |
+
|
649 |
+
|
650 |
+
/**
|
651 |
+
* @param string $optionName The name of the option where license keys should be stored.
|
652 |
+
* @return \Aventura\Wprss\Core\Licensing\Manager This instance.
|
653 |
+
*/
|
654 |
+
public function setLicenseKeysOptionName($optionName) {
|
655 |
+
$this->_licenseKeysOptionName = $optionName;
|
656 |
+
return $this;
|
657 |
+
}
|
658 |
+
|
659 |
+
|
660 |
+
/**
|
661 |
+
* @return string The name of the option where license keys are stored.
|
662 |
+
*/
|
663 |
+
public function getLicenseKeysOptionName() {
|
664 |
+
if ( is_null( $this->_licenseKeysOptionName ) ) {
|
665 |
+
return self::DB_LICENSE_KEYS_OPTION_NAME;
|
666 |
+
}
|
667 |
+
|
668 |
+
return $this->_licenseKeysOptionName;
|
669 |
+
}
|
670 |
+
|
671 |
+
|
672 |
+
/**
|
673 |
+
* @param string $optionName The name of the option where license statuses should be stored.
|
674 |
+
* @return \Aventura\Wprss\Core\Licensing\Manager This instance.
|
675 |
+
*/
|
676 |
+
public function setLicenseStatusesOptionName($optionName) {
|
677 |
+
$this->_licenseStatusesOptionName = $optionName;
|
678 |
+
return $this;
|
679 |
+
}
|
680 |
+
|
681 |
+
|
682 |
+
/**
|
683 |
+
* @return string The name of the option where license statuses are stored.
|
684 |
+
*/
|
685 |
+
public function getLicenseStatusesOptionName() {
|
686 |
+
if ( is_null( $this->_licenseStatusesOptionName ) ) {
|
687 |
+
return self::DB_LICENSE_STATUSES_OPTION_NAME;
|
688 |
+
}
|
689 |
+
|
690 |
+
return $this->_licenseStatusesOptionName;
|
691 |
+
}
|
692 |
+
|
693 |
+
|
694 |
+
/**
|
695 |
+
* Normalizes the given db options into a format that the Manager can use to compile a list of License instances.
|
696 |
+
*
|
697 |
+
* @return array
|
698 |
+
*/
|
699 |
+
protected static function _normalizeLicenseOptions( $keys, $statuses ) {
|
700 |
+
// Prepare result array
|
701 |
+
$normalized = array();
|
702 |
+
// Prepare regex pattern outside of iterations
|
703 |
+
$licenseKeysOptionPattern = self::_formatStringToDbOptionPattern( self::DB_LICENSE_KEYS_OPTION_PATTERN );
|
704 |
+
$licenseStatusesOptionPattern = self::_formatStringToDbOptionPattern( self::DB_LICENSE_STATUSES_OPTION_PATTERN );
|
705 |
+
|
706 |
+
// Prepare the license keys into the normalized array
|
707 |
+
foreach ( $keys as $_key => $_value ) {
|
708 |
+
// Regex match for pattern of array keys
|
709 |
+
preg_match( $licenseKeysOptionPattern, $_key, $_matches );
|
710 |
+
if ( count( $_matches ) < 2 ) continue;
|
711 |
+
// Addon id is the first match (excluding whole string match at $_matches[0])
|
712 |
+
$_addonId = $_matches[1];
|
713 |
+
// check if entry for add-on exists in normalized array, otherwise create it
|
714 |
+
if ( ! isset( $normalized[ $_addonId ] ) )
|
715 |
+
$normalized[ $_addonId ] = array();
|
716 |
+
// Insert the license key inot the normalized array
|
717 |
+
$normalized[ $_addonId ]['key'] = $_value;
|
718 |
+
$normalized[ $_addonId ]['addon_code'] = $_addonId;
|
719 |
+
}
|
720 |
+
// Now iterate and insert the statuses
|
721 |
+
foreach ( $statuses as $_key => $_value ) {
|
722 |
+
// Regex match for pattern of array keys
|
723 |
+
preg_match( $licenseStatusesOptionPattern, $_key, $_matches );
|
724 |
+
// continue to next iteration if there are no matches
|
725 |
+
if ( count( $_matches ) < 3 ) continue;
|
726 |
+
// The addon ID: first match
|
727 |
+
$_addonId = $_matches[1];
|
728 |
+
// Property name: second match
|
729 |
+
$_property = $_matches[2];
|
730 |
+
// if entry for add-on doesn't exist in normalized array, continue
|
731 |
+
if ( ! isset( $normalized[ $_addonId ] ) ) continue;
|
732 |
+
// Add the property to the normalized array for the addon's entry
|
733 |
+
$normalized[ $_addonId ][ $_property ] = $_value;
|
734 |
+
}
|
735 |
+
|
736 |
+
return $normalized;
|
737 |
+
}
|
738 |
+
|
739 |
+
|
740 |
+
/**
|
741 |
+
* Converts the given format string into a regex pattern, replacing all instances of '%s' with
|
742 |
+
* '([^_]+)'. The pattern can be used by PHP regex functions to match db license options.
|
743 |
+
*
|
744 |
+
* @param string $formatString
|
745 |
+
* @return string
|
746 |
+
*/
|
747 |
+
protected static function _formatStringToDbOptionPattern( $formatString ) {
|
748 |
+
return sprintf( '/\\A%s\\Z/', str_replace( '%s', '([^_\s]+)', $formatString ) );
|
749 |
+
}
|
750 |
+
|
751 |
+
|
752 |
+
/**
|
753 |
+
* Calculates the "soon-to-expire" timestamp.
|
754 |
+
*
|
755 |
+
* @return integer The timestamp for a future date, for which addons whose license's expiry lies between this date and the present are considered "soon-to-expire".
|
756 |
+
*/
|
757 |
+
public function getSteTimestamp() {
|
758 |
+
$period = $this->getExpirationNoticePeriod();
|
759 |
+
if ( is_null( $period ) ) {
|
760 |
+
return null;
|
761 |
+
}
|
762 |
+
|
763 |
+
return is_numeric( $period )
|
764 |
+
? time() + $period
|
765 |
+
: strtotime( sprintf( '+%s', $period ) );
|
766 |
+
}
|
767 |
+
|
768 |
+
}
|
includes/Aventura/Wprss/Core/Licensing/Plugin/Updater.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Licensing\Plugin;
|
4 |
+
|
5 |
+
// Load Easy Digital Downloads - Software Licensing updater class file
|
6 |
+
if ( ! class_exists('EDD_SL_Plugin_Updater') ) {
|
7 |
+
require_once( WPRSS_INC . 'libraries/EDD_licensing/EDD_SL_Plugin_Updater.php' );
|
8 |
+
}
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Updater class, extending the Software Licensing updater and implementing the updater interface.
|
12 |
+
*/
|
13 |
+
class Updater extends \EDD_SL_Plugin_Updater implements UpdaterInterface {
|
14 |
+
|
15 |
+
}
|
includes/Aventura/Wprss/Core/Licensing/Plugin/UpdaterInterface.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Licensing\Plugin;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Interface for a plugin updater class.
|
7 |
+
*/
|
8 |
+
interface UpdaterInterface {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @param type $apiUrl The URL pointing to the custom API endpoint.
|
12 |
+
* @param type $pluginFile Path to the plugin file.
|
13 |
+
* @param type $apiData Optional data to send with API calls.
|
14 |
+
*/
|
15 |
+
public function __construct($apiUrl, $pluginFile, $apiData = array());
|
16 |
+
}
|
includes/Aventura/Wprss/Core/Licensing/Settings.php
ADDED
@@ -0,0 +1,382 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core\Licensing;
|
4 |
+
use \Aventura\Wprss\Core\Licensing\License\Status;
|
5 |
+
use \WPRSS_MBString;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* The licensing settings class.
|
9 |
+
*
|
10 |
+
* Manages registraion, rendering and validation of the licensing settings as well as handling AJAX requests
|
11 |
+
* from the client. This class uses the Manager class internally to retrieve, update and manage licenses.
|
12 |
+
*/
|
13 |
+
class Settings {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* What to print in place of license code chars.
|
17 |
+
* This must not be a symbol that is considered to be a valid license key char.
|
18 |
+
*
|
19 |
+
* @since 4.6.10
|
20 |
+
*/
|
21 |
+
const LICENSE_KEY_MASK_CHAR = '•';
|
22 |
+
|
23 |
+
/**
|
24 |
+
* How many characters of the license code to print as is.
|
25 |
+
* Use negative value to indicate that characters at the end of the key are excluded.
|
26 |
+
*
|
27 |
+
* @since 4.6.10
|
28 |
+
*/
|
29 |
+
const LICENSE_KEY_MASK_EXCLUDE_AMOUNT = -4;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The Licensing Manager instance.
|
33 |
+
*
|
34 |
+
* @var Manager
|
35 |
+
*/
|
36 |
+
protected $_manager;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Constructor.
|
40 |
+
*/
|
41 |
+
public function __construct() {
|
42 |
+
$this->_setManager( wprss_licensing_get_manager() );
|
43 |
+
// Only load notices if on admin side
|
44 |
+
if ( is_admin() ) {
|
45 |
+
$this->_initNotices();
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Sets the license manager for this settings controller to use.
|
51 |
+
*
|
52 |
+
* @param \Aventura\Wprss\Core\Licensing\Manager $manager An instance of the license manager.
|
53 |
+
* @return \Aventura\Wprss\Core\Licensing\Settings This instance.
|
54 |
+
*/
|
55 |
+
protected function _setManager(Manager $manager) {
|
56 |
+
$this->_manager = $manager;
|
57 |
+
return $this;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Gets the license manager for this settings controller.
|
62 |
+
*
|
63 |
+
* @return \Aventura\Wprss\Core\Licensing\Manager The license manager used by this settings controller.
|
64 |
+
*/
|
65 |
+
public function getManager() {
|
66 |
+
return $this->_manager;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Initializes the admin notices.
|
71 |
+
*
|
72 |
+
* @return \Aventura\Wprss\Core\Licensing\Settings
|
73 |
+
*/
|
74 |
+
protected function _initNotices() {
|
75 |
+
$noticesCollection = wprss_admin_notice_get_collection();
|
76 |
+
foreach ( $this->getManager()->getAddons() as $_addonId => $_addonName ) {
|
77 |
+
$_notice = array(
|
78 |
+
'id' => sprintf( 'invalid_licenses_exist_%s', $_addonId ),
|
79 |
+
'notice_type' => 'error',
|
80 |
+
'content' => $this->getInvalidLicenseNoticeContent( $_addonId ),
|
81 |
+
'condition' => array( array( $this, 'invalidLicensesNoticeCondition' ) ),
|
82 |
+
'addon' => $_addonId
|
83 |
+
);
|
84 |
+
$noticesCollection->add_notice( $_notice );
|
85 |
+
}
|
86 |
+
|
87 |
+
return $this;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Condition callback for the "invalid license notice".
|
92 |
+
*
|
93 |
+
* @return boolean True if the notice is to be shown, false if not.
|
94 |
+
*/
|
95 |
+
public function invalidLicensesNoticeCondition( $args ) {
|
96 |
+
if ( isset( $args['addon'] ) ) return false;
|
97 |
+
$license = $this->getManager()->getLicense( $args['addon'] );
|
98 |
+
return $license !== null && $license->getStatus() !== Status::VALID;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Gets the content of the notice that informs the user of invalid licenses.
|
103 |
+
*
|
104 |
+
* @param string $addonId The ID of addon that has the invalid license.
|
105 |
+
* @return string
|
106 |
+
*/
|
107 |
+
public function getInvalidLicenseNoticeContent( $addonId ) {
|
108 |
+
$addons = $this->getManager()->getAddons();
|
109 |
+
$addonName = $addons[ $addonId ];
|
110 |
+
return sprintf(
|
111 |
+
__( '<p>Remember to <a href="%s">enter your plugin license code</a> for the WP RSS Aggregator <strong>%s</strong> add-on to benefit from updates and support.</p>', WPRSS_TEXT_DOMAIN ),
|
112 |
+
esc_attr( admin_url( 'edit.php?post_type=wprss_feed&page=wprss-aggregator-settings&tab=licenses_settings' ) ),
|
113 |
+
$addonName
|
114 |
+
);
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Registers the WordPress settings.
|
119 |
+
*/
|
120 |
+
public function registerSettings() {
|
121 |
+
// Iterate all addon IDs and register a settings section with 2 fields for each.
|
122 |
+
foreach( $this->getManager()->getAddons() as $_addonId => $_addonName ) {
|
123 |
+
// Settings Section
|
124 |
+
add_settings_section(
|
125 |
+
sprintf( 'wprss_settings_%s_licenses_section', $_addonId ),
|
126 |
+
sprintf( '%s %s', $_addonName, __( 'License', WPRSS_TEXT_DOMAIN ) ),
|
127 |
+
'__return_empty_string',
|
128 |
+
'wprss_settings_license_keys'
|
129 |
+
);
|
130 |
+
// License key field
|
131 |
+
add_settings_field(
|
132 |
+
sprintf( 'wprss_settings_%s_license', $_addonId ),
|
133 |
+
__( 'License Key', WPRSS_TEXT_DOMAIN ),
|
134 |
+
array( $this, 'renderLicenseKeyField' ),
|
135 |
+
'wprss_settings_license_keys',
|
136 |
+
sprintf( 'wprss_settings_%s_licenses_section', $_addonId ),
|
137 |
+
array( $_addonId )
|
138 |
+
);
|
139 |
+
// Activate license button
|
140 |
+
add_settings_field(
|
141 |
+
sprintf( 'wprss_settings_%s_activate_license', $_addonId ),
|
142 |
+
__( 'Activate License', WPRSS_TEXT_DOMAIN ),
|
143 |
+
array( $this, 'renderActivateLicenseButton' ),
|
144 |
+
'wprss_settings_license_keys',
|
145 |
+
sprintf( 'wprss_settings_%s_licenses_section', $_addonId ),
|
146 |
+
array( $_addonId )
|
147 |
+
);
|
148 |
+
}
|
149 |
+
|
150 |
+
return $this;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Renders the license field for a particular add-on.
|
155 |
+
*
|
156 |
+
* @since 4.4.5
|
157 |
+
*/
|
158 |
+
public function renderLicenseKeyField( $args ) {
|
159 |
+
if ( count( $args ) < 1 ) return;
|
160 |
+
// Addon ID is the first arg
|
161 |
+
$addonId = $args[0];
|
162 |
+
// Get the addon's license
|
163 |
+
$license = $this->getManager()->getLicense( $addonId );
|
164 |
+
// Mask it - if the license exists
|
165 |
+
$displayedKey = is_null( $license )? '' : self::obfuscateLicenseKey( $license->getKey() );
|
166 |
+
// Render the markup ?>
|
167 |
+
<input id="wprss-<?php echo $addonId ?>-license-key" name="wprss_settings_license_keys[<?php echo $addonId ?>_license_key]"
|
168 |
+
type="text" value="<?php echo esc_attr( $displayedKey ) ?>" style="width: 300px;"
|
169 |
+
/>
|
170 |
+
<label class="description" for="wprss-<?php echo $addonId ?>-license-key">
|
171 |
+
<?php _e( 'Enter your license key', WPRSS_TEXT_DOMAIN ) ?>
|
172 |
+
</label><?php
|
173 |
+
}
|
174 |
+
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Masks a license key.
|
178 |
+
*
|
179 |
+
* @param string $licenseKey The license key to mask
|
180 |
+
* @param string $maskChar The masking character(s)
|
181 |
+
* @param integer $maskExcludeAmount The amount of characyers to exclude from the mask. If negative, the exluded characters will begin from the end of the string
|
182 |
+
* @return string The masked license key
|
183 |
+
*/
|
184 |
+
public static function obfuscateLicenseKey( $licenseKey, $maskChar = self::LICENSE_KEY_MASK_CHAR, $maskExcludeAmount = self::LICENSE_KEY_MASK_EXCLUDE_AMOUNT ) {
|
185 |
+
// Pre-calculate license key length
|
186 |
+
$licenseKeyLength = strlen( $licenseKey );
|
187 |
+
// In case the mask exclude amount is greater than the license key length
|
188 |
+
$actualMaskExcludeAmount = abs( $maskExcludeAmount ) > ( $licenseKeyLength - 1 )
|
189 |
+
? ( $licenseKeyLength - 1 ) * ( $maskExcludeAmount < 0 ? -1 : 1 ) // Making sure to preserve position of mask
|
190 |
+
: $maskExcludeAmount;
|
191 |
+
// How many chars to mask. Always at least one char will be masked.
|
192 |
+
$maskLength = $licenseKeyLength - abs( $actualMaskExcludeAmount );
|
193 |
+
// Create the mask
|
194 |
+
$mask = $maskLength > 0 ? str_repeat( $maskChar, $maskLength ) : '';
|
195 |
+
// The starting index: if negative mask exclude amount, start from the back. otherwise start from 0
|
196 |
+
$startIndex = $actualMaskExcludeAmount < 0 ? $maskLength : 0;
|
197 |
+
// Extract the excluded characters
|
198 |
+
$excludedChars = WPRSS_MBString::mb_substr( $licenseKey, $startIndex, abs( $actualMaskExcludeAmount ) );
|
199 |
+
// Generate the displayed key and return it
|
200 |
+
return sprintf( $actualMaskExcludeAmount > 0 ? '%1$s%2$s' : '%2$s%1$s', $excludedChars, $mask );
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Determines whether or not the license key in question is obfuscated.
|
205 |
+
*
|
206 |
+
* This is achieved by searching for the mask character in the key. Because the
|
207 |
+
* mask character cannot be a valid license character, the presence of at least
|
208 |
+
* one such character indicates that the key is obfuscated.
|
209 |
+
*
|
210 |
+
* @param string $key The license key in question.
|
211 |
+
* @param string $maskChar The masking character(s).
|
212 |
+
* @return bool Whether or not this key is obfuscated.
|
213 |
+
*/
|
214 |
+
public function isLicenseKeyObfuscated( $key, $maskChar = self::LICENSE_KEY_MASK_CHAR ) {
|
215 |
+
return WPRSS_MBString::mb_strpos( $key, $maskChar ) !== false;
|
216 |
+
}
|
217 |
+
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Invalidates the key if it is obfuscated, causing the saved version to be used.
|
221 |
+
* This meanst that the new key will not be saved, as it is considered then to be unchanged.
|
222 |
+
*
|
223 |
+
* @since 4.6.10
|
224 |
+
* @param bool $is_valid Indicates whether the key is currently considered to be valid.
|
225 |
+
* @param string $key The license key in question
|
226 |
+
* @return Whether or not the key is still to be considered valid.
|
227 |
+
*/
|
228 |
+
public function validateLicenseKeyForSave( $is_valid, $key ) {
|
229 |
+
if ( $this->isLicenseKeyObfuscated( $key ) )
|
230 |
+
return false;
|
231 |
+
|
232 |
+
return $is_valid;
|
233 |
+
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Renders the activate/deactivate license button for a particular add-on.
|
237 |
+
*
|
238 |
+
* @since 4.4.5
|
239 |
+
*/
|
240 |
+
public function renderActivateLicenseButton( $args ) {
|
241 |
+
$addonId = $args[0];
|
242 |
+
$manager = $this->getManager();
|
243 |
+
$data = $manager->checkLicense( $addonId, 'ALL' );
|
244 |
+
$status = is_string( $data ) ? $data : $data->license;
|
245 |
+
if ( $status === 'site_inactive' ) $status = 'inactive';
|
246 |
+
if ( $status === 'item_name_mismatch' ) $status = 'invalid';
|
247 |
+
|
248 |
+
$valid = $status == 'valid';
|
249 |
+
$btnText = $valid ? 'Deactivate License' : 'Activate License';
|
250 |
+
$btnName = "wprss_{$addonId}_license_" . ( $valid? 'deactivate' : 'activate' );
|
251 |
+
$btnClass = "button-" . ( $valid ? 'deactivate' : 'activate' ) . "-license";
|
252 |
+
wp_nonce_field( "wprss_{$addonId}_license_nonce", "wprss_{$addonId}_license_nonce", false ); ?>
|
253 |
+
|
254 |
+
<input type="button" class="<?php echo $btnClass; ?> button-process-license button-secondary" name="<?php echo $btnName; ?>" value="<?php _e( $btnText, WPRSS_TEXT_DOMAIN ); ?>" />
|
255 |
+
<span id="wprss-<?php echo $addonId; ?>-license-status-text">
|
256 |
+
<strong><?php _e('Status', WPRSS_TEXT_DOMAIN); ?>:
|
257 |
+
<span class="wprss-<?php echo $addonId; ?>-license-<?php echo $status; ?>">
|
258 |
+
<?php _e( ucfirst($status), WPRSS_TEXT_DOMAIN ); ?>
|
259 |
+
<?php if ( $status === 'valid' ) : ?>
|
260 |
+
<i class="fa fa-check"></i>
|
261 |
+
<?php elseif( $status === 'invalid' || $status === 'expired' ): ?>
|
262 |
+
<i class="fa fa-times"></i>
|
263 |
+
<?php elseif( $status === 'inactive' ): ?>
|
264 |
+
<i class="fa fa-warning"></i>
|
265 |
+
<?php endif; ?>
|
266 |
+
</strong>
|
267 |
+
</span>
|
268 |
+
</span>
|
269 |
+
|
270 |
+
<p>
|
271 |
+
<?php
|
272 |
+
$license = $manager->getLicense( $addonId );
|
273 |
+
if ( $license !== null && ($licenseKey = $license->getKey()) && !empty( $licenseKey ) ) :
|
274 |
+
if ( is_object( $data ) ) :
|
275 |
+
$currentActivations = $data->site_count;
|
276 |
+
$activationsLeft = $data->activations_left;
|
277 |
+
$activationsLimit = $data->license_limit;
|
278 |
+
$expires = $data->expires;
|
279 |
+
$expires = substr( $expires, 0, strpos( $expires, " " ) );
|
280 |
+
|
281 |
+
// If the license key is garbage, don't show any of the data.
|
282 |
+
if ( !empty($data->payment_id) && !empty($data->license_limit ) ) :
|
283 |
+
?>
|
284 |
+
<small>
|
285 |
+
<?php if ( $status !== 'valid' && $activationsLeft === 0 ) : ?>
|
286 |
+
<?php $accountUrl = 'https://www.wprssaggregator.com/account/?action=manage_licenses&payment_id=' . $data->payment_id; ?>
|
287 |
+
<a href="<?php echo $accountUrl; ?>"><?php _e("No activations left. Click here to manage the sites you've activated licenses on.", WPRSS_TEXT_DOMAIN); ?></a>
|
288 |
+
<br/>
|
289 |
+
<?php endif; ?>
|
290 |
+
<?php if ( strtotime($expires) < strtotime("+2 weeks") ) : ?>
|
291 |
+
<?php $renewalUrl = esc_attr(WPRSS_SL_STORE_URL . '/checkout/?edd_license_key=' . $licenseKey); ?>
|
292 |
+
<a href="<?php echo $renewalUrl; ?>"><?php _e('Renew your license to continue receiving updates and support.', WPRSS_TEXT_DOMAIN); ?></a>
|
293 |
+
<br/>
|
294 |
+
<?php endif; ?>
|
295 |
+
<strong><?php _e('Activations', WPRSS_TEXT_DOMAIN); ?>:</strong>
|
296 |
+
<?php echo $currentActivations.'/'.$activationsLimit; ?> (<?php echo $activationsLeft; ?> left)
|
297 |
+
<br/>
|
298 |
+
<strong><?php _e('Expires on', WPRSS_TEXT_DOMAIN); ?>:</strong>
|
299 |
+
<code><?php echo $expires; ?></code>
|
300 |
+
<br/>
|
301 |
+
<strong><?php _e('Registered to', WPRSS_TEXT_DOMAIN); ?>:</strong>
|
302 |
+
<?php echo $data->customer_name; ?> (<code><?php echo $data->customer_email; ?></code>)
|
303 |
+
</small>
|
304 |
+
<?php endif; ?>
|
305 |
+
<?php else: ?>
|
306 |
+
<small><?php _e('Failed to get license information. This is a temporary problem. Check your internet connection and try again later.', WPRSS_TEXT_DOMAIN); ?></small>
|
307 |
+
<?php endif; ?>
|
308 |
+
<?php endif;
|
309 |
+
?>
|
310 |
+
</p>
|
311 |
+
|
312 |
+
<style type="text/css">
|
313 |
+
.wprss-<?php echo $addonId; ?>-license-valid {
|
314 |
+
color: green;
|
315 |
+
}
|
316 |
+
.wprss-<?php echo $addonId; ?>-license-invalid, .wprss-<?php echo $addonId; ?>-license-expired {
|
317 |
+
color: #b71919;
|
318 |
+
}
|
319 |
+
.wprss-<?php echo $addonId; ?>-license-inactive {
|
320 |
+
color: #d19e5b;
|
321 |
+
}
|
322 |
+
#wprss-<?php echo $addonId; ?>-license-status-text {
|
323 |
+
margin-left: 8px;
|
324 |
+
line-height: 27px;
|
325 |
+
vertical-align: middle;
|
326 |
+
}
|
327 |
+
</style>
|
328 |
+
<?php
|
329 |
+
}
|
330 |
+
|
331 |
+
/**
|
332 |
+
* Handles the activation/deactivation process
|
333 |
+
*
|
334 |
+
* @since 1.0
|
335 |
+
*/
|
336 |
+
public function handleLicenseStatusChange() {
|
337 |
+
$manager = $this->getManager();
|
338 |
+
$addons = $manager->getAddons();
|
339 |
+
|
340 |
+
// Get for each registered addon
|
341 |
+
foreach( $addons as $id => $name ) {
|
342 |
+
// listen for our activate button to be clicked
|
343 |
+
if( isset( $_POST["wprss_{$id}_license_activate"] ) || isset( $_POST["wprss_{$id}_license_deactivate"] ) ) {
|
344 |
+
// run a quick security check
|
345 |
+
if ( ! check_admin_referer( "wprss_{$id}_license_nonce", "wprss_{$id}_license_nonce" ) )
|
346 |
+
continue; // get out if we didn't click the Activate/Deactivate button
|
347 |
+
}
|
348 |
+
|
349 |
+
// retrieve the license
|
350 |
+
$license = $manager->getLicense( $id );
|
351 |
+
|
352 |
+
// If the license is not saved in DB, but is included in POST
|
353 |
+
if ( $license == '' && ! empty( $_POST['wprss_settings_license_keys'][$id.'_license_key'] ) ) {
|
354 |
+
// Use the license given in POST
|
355 |
+
$license->setKey( $_POST['wprss_settings_license_keys'][ $id.'_license_key' ] );
|
356 |
+
}
|
357 |
+
|
358 |
+
// Prepare the action to take
|
359 |
+
if ( isset( $_POST["wprss_{$id}_license_activate"] ) ) {
|
360 |
+
$manager->activateLicense( $id );
|
361 |
+
}
|
362 |
+
elseif ( isset( $_POST["wprss_{$id}_license_deactivate"] ) ) {
|
363 |
+
$manager->deactivateLicense( $id );
|
364 |
+
}
|
365 |
+
}
|
366 |
+
|
367 |
+
return $this;
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* Gets the HTML markup for the activate license button.
|
372 |
+
*
|
373 |
+
* @param string $addonId The ID of the addon for which the button will be related to.
|
374 |
+
* @return string The HTML markup of the button.
|
375 |
+
*/
|
376 |
+
public function getActivateLicenseButtonHtml( $addonId ) {
|
377 |
+
ob_start();
|
378 |
+
$this->renderActivateLicenseButton( array( $addonId ) );
|
379 |
+
return ob_get_clean();
|
380 |
+
}
|
381 |
+
|
382 |
+
}
|
includes/Aventura/Wprss/Core/Loader.php
ADDED
@@ -0,0 +1,285 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Aventura\Wprss\Core;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Responsible for autoloading classes.
|
7 |
+
*/
|
8 |
+
class Loader {
|
9 |
+
|
10 |
+
const WHITESPACE_CHARS = " \t\n\r\0\x0B";
|
11 |
+
|
12 |
+
protected $_psr4 = array();
|
13 |
+
protected $_isRegistered = false;
|
14 |
+
protected $_ext = array();
|
15 |
+
|
16 |
+
public function __construct() {
|
17 |
+
$this->_construct();
|
18 |
+
}
|
19 |
+
|
20 |
+
protected function _construct() {
|
21 |
+
$this->addExtension('php');
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Registers this instance for handling autoloading, if not already registered.
|
26 |
+
*
|
27 |
+
* @return \Aventura\Wprss\Core\Loader This instance.
|
28 |
+
*/
|
29 |
+
public function register() {
|
30 |
+
if (!$this->isRegistered()) {
|
31 |
+
$this->_register();
|
32 |
+
}
|
33 |
+
|
34 |
+
return $this;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Low level method for registering the autoload function.
|
39 |
+
*
|
40 |
+
* No checks performed.
|
41 |
+
*
|
42 |
+
* @see spl_autoload_register()
|
43 |
+
* @return \Aventura\Wprss\Core\Loader This instance.
|
44 |
+
*/
|
45 |
+
protected function _register() {
|
46 |
+
spl_autoload_register(array($this, 'autoload'));
|
47 |
+
return $this;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Checks whether or not this class is already registered for handling autoloading.
|
52 |
+
*
|
53 |
+
* @see register()
|
54 |
+
* @return boolean True if already registered; false otherwise.
|
55 |
+
*/
|
56 |
+
public function isRegistered() {
|
57 |
+
return (bool)$this->_isRegistered;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Implementation of an autoloading function.
|
62 |
+
*
|
63 |
+
* @see spl_autoload()
|
64 |
+
* @param string $class Name of the class to load.
|
65 |
+
*/
|
66 |
+
public function autoload($class) {
|
67 |
+
if (!($basePath = $this->match($class))) {
|
68 |
+
return;
|
69 |
+
}
|
70 |
+
|
71 |
+
$relativePath = $this->getClassRelativePath($class);
|
72 |
+
if ($path = $this->findClassFile($relativePath, $basePath)) {
|
73 |
+
include_once($path);
|
74 |
+
}
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Alias of addPsr4().
|
79 |
+
*
|
80 |
+
* @see addPsr4
|
81 |
+
* @return \Aventura\Wprss\Core\Loader This instance.
|
82 |
+
*/
|
83 |
+
public function add($namespace, $basePath) {
|
84 |
+
$this->addPsr4($namespace, $basePath);
|
85 |
+
return $this;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Tells the loader to load classes in specified namespace from specified directory.
|
90 |
+
*
|
91 |
+
* This is according to the PSR-4 standard.
|
92 |
+
*
|
93 |
+
* @param string $namespace The namespace, files for which should be loaded from the path.
|
94 |
+
* @param string $basePath Path to the directory, which is the base directory for class files.
|
95 |
+
* @return \Aventura\Wprss\Core\Loader This instance.
|
96 |
+
*/
|
97 |
+
public function addPsr4($namespace, $basePath) {
|
98 |
+
$namespace = $this->normalizeClassName($namespace);
|
99 |
+
$basePath = $this->normalizeBasePath($basePath);
|
100 |
+
|
101 |
+
$this->_psr4[$namespace] = $basePath;
|
102 |
+
return $this;
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Matches the class name with all registered namespaces.
|
107 |
+
*
|
108 |
+
* Used to find the base path, where the class should be loaded from.
|
109 |
+
*
|
110 |
+
* @param string $class Name of the class to find the base path for.
|
111 |
+
* @return string|null The basepath that corresponds to the registered namespace of the class, if such a namespace is found.
|
112 |
+
* Otherwise, null.
|
113 |
+
*/
|
114 |
+
public function match($class) {
|
115 |
+
if ($basePath = $this->matchPsr4($class)) {
|
116 |
+
return $basePath;
|
117 |
+
}
|
118 |
+
|
119 |
+
return null;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Matches the class agains the registered PSR-4 namespaces.
|
124 |
+
*
|
125 |
+
* @see match()
|
126 |
+
* @param string $class Class name to match.
|
127 |
+
* @return string|null Basepath for PSR-4 namespace, or null if no match.
|
128 |
+
*/
|
129 |
+
public function matchPsr4($class) {
|
130 |
+
foreach ($this->getPsr4Namespaces() as $_ns => $_basePath) {
|
131 |
+
if ( $this->matchNamespace( $_ns, $class ) ) {
|
132 |
+
return $_basePath;
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
return null;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Get all registered PSR-4 namespaces.
|
141 |
+
*
|
142 |
+
* They will be sorted by longest first. This allows to avoid instances, where
|
143 |
+
* class `My\Namespace\Cool\Class` will be loaded from the basepath that
|
144 |
+
* corresponds to `My\Namespace` even if `My\Namespace\Cool` is registered.
|
145 |
+
*
|
146 |
+
* @see sortNamespaces()
|
147 |
+
* @return array Array of registered PSR-4 namespaces, sorted by longest first.
|
148 |
+
*/
|
149 |
+
public function getPsr4Namespaces() {
|
150 |
+
return $this->sortNamespaces($this->_psr4);
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Sorts an array of strings by longest first.
|
155 |
+
*
|
156 |
+
* @param array $namespaces The array to sort.
|
157 |
+
* @return array Array of strings, sorted by longest first.
|
158 |
+
*/
|
159 |
+
public function sortNamespaces($namespaces) {
|
160 |
+
uasort($namespaces, function($a, $b) {
|
161 |
+
return strlen($b) - strlen($a);
|
162 |
+
});
|
163 |
+
|
164 |
+
return $namespaces;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Determines whether a class belongs to a namespace.
|
169 |
+
*
|
170 |
+
* @param string $namespace Namespace to match the class against.
|
171 |
+
* @param string $class Name of the class to match.
|
172 |
+
* @return boolean True if the specified class belongs to the specified namespace.
|
173 |
+
*/
|
174 |
+
public function matchNamespace($namespace, $class) {
|
175 |
+
$namespace = $this->normalizeClassName($namespace);
|
176 |
+
$class = $this->normalizeClassName($class);
|
177 |
+
return strpos( $class, $namespace ) === 0;
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Normalizes a class name.
|
182 |
+
*
|
183 |
+
* @param string $className Class name to normalize.
|
184 |
+
* @return string The class name with whitespace and namespace separators removed from beginning and end.
|
185 |
+
*/
|
186 |
+
public function normalizeClassName($className) {
|
187 |
+
return trim($className, self::WHITESPACE_CHARS . '\\');
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Normalizes a path in a way that is independent of platform's directory separator.
|
192 |
+
*
|
193 |
+
* @param string $path Path to normalize.
|
194 |
+
* @return string The path with whitespace and directory separators removed from end.
|
195 |
+
* Whitespace will be removed from beginning as well.
|
196 |
+
*/
|
197 |
+
public function normalizeBasePath($path) {
|
198 |
+
$path = ltrim($path);
|
199 |
+
return rtrim($path, self::WHITESPACE_CHARS . '\\/' . DIRECTORY_SEPARATOR);
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Normalizes a file extension.
|
204 |
+
*
|
205 |
+
* @param string $extension The extension to normalize.
|
206 |
+
* @return string The file extension with whitespace and period trimmed.
|
207 |
+
*/
|
208 |
+
public function normalizeExtension($extension) {
|
209 |
+
return trim($extension, self::WHITESPACE_CHARS . '.');
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Deduces the relative path to the file of a PSR-0 or PSR-4 class.
|
214 |
+
*
|
215 |
+
* @param string $class Name of the class.
|
216 |
+
* @return string The relative path deduced from the class name, without extension.
|
217 |
+
*/
|
218 |
+
public function getClassRelativePath($class) {
|
219 |
+
$class = $this->normalizeClassName($class);
|
220 |
+
$path = str_replace(array('\\', '_'), DIRECTORY_SEPARATOR, $class);
|
221 |
+
|
222 |
+
return $path;
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Looks for a file with all registered extensions in all specified paths.
|
227 |
+
*
|
228 |
+
* @see getClassRelativePath()
|
229 |
+
* @param string $path Relative path to a class file, without extension.
|
230 |
+
* @param string|array $basePath Path or array of paths to the base directory in which to search for the file.
|
231 |
+
* @return string|null Path to the class file, if found; otherwise, null.
|
232 |
+
*/
|
233 |
+
public function findClassFile($path, $basePath) {
|
234 |
+
$basePath = (array)$basePath;
|
235 |
+
$extensions = $this->getAllowedExtensions();
|
236 |
+
foreach ($basePath as $_path) {
|
237 |
+
foreach ($extensions as $_ext) {
|
238 |
+
$classPath = implode(DIRECTORY_SEPARATOR, array($_path, "{$path}.{$_ext}"));
|
239 |
+
if (file_exists($classPath)) {
|
240 |
+
return $classPath;
|
241 |
+
}
|
242 |
+
}
|
243 |
+
}
|
244 |
+
|
245 |
+
return null;
|
246 |
+
}
|
247 |
+
|
248 |
+
/**
|
249 |
+
* Retrieves the list of all extensions, for which this loader will autoload class files.
|
250 |
+
*
|
251 |
+
* @return array Array of registered extensions.
|
252 |
+
*/
|
253 |
+
public function getAllowedExtensions() {
|
254 |
+
return array_keys($this->_ext);
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Allows an extension for class files.
|
259 |
+
*
|
260 |
+
* @param string $extension Extension to allow.
|
261 |
+
* @return \Aventura\Wprss\Core\Loader This instance.
|
262 |
+
*
|
263 |
+
*/
|
264 |
+
public function addExtension($extension) {
|
265 |
+
$extension = $this->normalizeExtension($extension);
|
266 |
+
$this->_ext[$extension] = true;
|
267 |
+
|
268 |
+
return $this;
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* Disallows an extension for class files.
|
273 |
+
*
|
274 |
+
* @param string $extension Extension to disallow.
|
275 |
+
* @return \Aventura\Wprss\Core\Loader This instance.
|
276 |
+
*/
|
277 |
+
public function removeExtension($extension) {
|
278 |
+
$extension = $this->normalizeExtension($extension);
|
279 |
+
if (isset($this->_ext[$extension])) {
|
280 |
+
unset($this->_ext[$extension]);
|
281 |
+
}
|
282 |
+
|
283 |
+
return $this;
|
284 |
+
}
|
285 |
+
}
|
includes/admin-ajax-notice.php
CHANGED
@@ -1127,8 +1127,7 @@ add_action( 'init', 'wprss_admin_notice_get_collection', 9 );
|
|
1127 |
* @since 4.7.4
|
1128 |
* @uses-filter wprss_admin_notice_collection_before_init To modify collection before initialization.
|
1129 |
* @uses-filter wprss_admin_notice_collection_after_init To modify collection after initialization.
|
1130 |
-
* @uses-
|
1131 |
-
* @uses-action wprss_admin_notice_collection_after_enqueue_scripts To access list of enqueued script handles.
|
1132 |
* @uses-filter wprss_admin_notice_collection_before_localize_vars To modify list of vars to expose to the frontend.
|
1133 |
* @uses-action wprss_admin_notice_collection_after_localize_vars To access list of vars exposed to the frontend.
|
1134 |
* @staticvar WPRSS_Admin_Notices $collection The singleton instance.
|
@@ -1148,24 +1147,40 @@ function wprss_admin_notice_get_collection() {
|
|
1148 |
$collection->init();
|
1149 |
$collection = apply_filters( 'wprss_admin_notice_collection_after_init', $collection );
|
1150 |
|
1151 |
-
|
1152 |
-
foreach ( $script_handles as $_idx => $_handle ) wp_enqueue_script( $_handle );
|
1153 |
-
do_action( 'wprss_admin_notice_collection_after_enqueue_scripts', $script_handles, $collection );
|
1154 |
-
|
1155 |
-
// Frontend settings
|
1156 |
-
$settings = apply_filters( 'wprss_admin_notice_collection_before_localize_vars', array(
|
1157 |
-
'notice_class' => $collection->get_notice_base_class(),
|
1158 |
-
'nonce_class' => $collection->get_nonce_base_class(),
|
1159 |
-
'btn_close_class' => $collection->get_btn_close_base_class(),
|
1160 |
-
'action_code' => wprss_admin_notice_get_action_code()
|
1161 |
-
), $collection );
|
1162 |
-
wp_localize_script( 'aventura', 'adminNoticeGlobalVars', $settings);
|
1163 |
-
do_action( 'wprss_admin_notice_collection_after_localize_vars', $settings, $collection );
|
1164 |
}
|
1165 |
|
1166 |
return $collection;
|
1167 |
}
|
1168 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1169 |
|
1170 |
/**
|
1171 |
* Centralizes access to the name of the AJAX action handler for dismissing admin notices.
|
1127 |
* @since 4.7.4
|
1128 |
* @uses-filter wprss_admin_notice_collection_before_init To modify collection before initialization.
|
1129 |
* @uses-filter wprss_admin_notice_collection_after_init To modify collection after initialization.
|
1130 |
+
* @uses-action admin_enqueue_scripts To enqueue the scripts for the collection.
|
|
|
1131 |
* @uses-filter wprss_admin_notice_collection_before_localize_vars To modify list of vars to expose to the frontend.
|
1132 |
* @uses-action wprss_admin_notice_collection_after_localize_vars To access list of vars exposed to the frontend.
|
1133 |
* @staticvar WPRSS_Admin_Notices $collection The singleton instance.
|
1147 |
$collection->init();
|
1148 |
$collection = apply_filters( 'wprss_admin_notice_collection_after_init', $collection );
|
1149 |
|
1150 |
+
add_action( 'admin_enqueue_scripts', 'wprss_admin_notices_collection_enqueue_scripts' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1151 |
}
|
1152 |
|
1153 |
return $collection;
|
1154 |
}
|
1155 |
|
1156 |
+
/**
|
1157 |
+
* Enqueues the scripts for a notice collection.
|
1158 |
+
*
|
1159 |
+
* @since 4.7.8
|
1160 |
+
* @uses-filter wprss_admin_notice_collection_before_enqueue_scripts To modify list of script handles to enqueue.
|
1161 |
+
* @uses-action wprss_admin_notice_collection_after_enqueue_scripts To access list of enqueued script handles.
|
1162 |
+
*/
|
1163 |
+
function wprss_admin_notices_collection_enqueue_scripts() {
|
1164 |
+
// Get singleton collection
|
1165 |
+
$collection = wprss_admin_notice_get_collection();
|
1166 |
+
|
1167 |
+
// Get script handles via filter
|
1168 |
+
$script_handles = apply_filters( 'wprss_admin_notice_collection_before_enqueue_scripts', array( 'wprss-admin-notifications' ), $collection );
|
1169 |
+
// Iterate and enqueue scripts
|
1170 |
+
foreach ( $script_handles as $_idx => $_handle ) wp_enqueue_script( $_handle );
|
1171 |
+
// Post-enqueueing action
|
1172 |
+
do_action( 'wprss_admin_notice_collection_after_enqueue_scripts', $script_handles, $collection );
|
1173 |
+
|
1174 |
+
// Frontend settings
|
1175 |
+
$settings = apply_filters( 'wprss_admin_notice_collection_before_localize_vars', array(
|
1176 |
+
'notice_class' => $collection->get_notice_base_class(),
|
1177 |
+
'nonce_class' => $collection->get_nonce_base_class(),
|
1178 |
+
'btn_close_class' => $collection->get_btn_close_base_class(),
|
1179 |
+
'action_code' => wprss_admin_notice_get_action_code()
|
1180 |
+
), $collection );
|
1181 |
+
wp_localize_script( 'aventura', 'adminNoticeGlobalVars', $settings);
|
1182 |
+
do_action( 'wprss_admin_notice_collection_after_localize_vars', $settings, $collection );
|
1183 |
+
}
|
1184 |
|
1185 |
/**
|
1186 |
* Centralizes access to the name of the AJAX action handler for dismissing admin notices.
|
includes/admin-debugging.php
CHANGED
@@ -6,8 +6,8 @@
|
|
6 |
* @subpackage Includes
|
7 |
* @since 3.0
|
8 |
* @author Jean Galea <info@jeangalea.com>
|
9 |
-
* @copyright Copyright(c) 2012-
|
10 |
-
* @link http://www.
|
11 |
* @license http://www.gnu.org/licenses/gpl.html
|
12 |
*/
|
13 |
|
@@ -45,7 +45,27 @@
|
|
45 |
)
|
46 |
);
|
47 |
|
48 |
-
$operations['error-log'] = apply_filters(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
'wprss_debug_error_log_operation',
|
50 |
array(
|
51 |
'nonce' => 'wprss-clear-error-log',
|
@@ -157,23 +177,48 @@
|
|
157 |
<?php
|
158 |
}
|
159 |
|
160 |
-
|
161 |
/**
|
162 |
-
* Renders the
|
163 |
-
*
|
164 |
-
* @since 3.9.6
|
165 |
*/
|
166 |
-
function
|
167 |
?>
|
168 |
<h3><?php _e( 'Error Log', WPRSS_TEXT_DOMAIN ); ?></h3>
|
169 |
|
170 |
<textarea readonly="readonly" id="wprss-error-log-textarea"><?php echo wprss_get_log(); ?></textarea>
|
|
|
|
|
171 |
|
172 |
-
|
173 |
-
|
174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
</form>
|
|
|
|
|
176 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
<?php
|
178 |
}
|
179 |
|
6 |
* @subpackage Includes
|
7 |
* @since 3.0
|
8 |
* @author Jean Galea <info@jeangalea.com>
|
9 |
+
* @copyright Copyright(c) 2012-2015, Jean Galea
|
10 |
+
* @link http://www.wprssaggregator.com
|
11 |
* @license http://www.gnu.org/licenses/gpl.html
|
12 |
*/
|
13 |
|
45 |
)
|
46 |
);
|
47 |
|
48 |
+
$operations['render-error-log'] = apply_filters(
|
49 |
+
'wprss_render_error_log_operation',
|
50 |
+
array(
|
51 |
+
'nonce' => null,
|
52 |
+
'run' => null,
|
53 |
+
'redirect' => 'edit.php?post_type=wprss_feed&page=wprss-debugging',
|
54 |
+
'render' => 'wprss_debug_render_error_log'
|
55 |
+
)
|
56 |
+
);
|
57 |
+
|
58 |
+
$operations['download-error-log'] = apply_filters(
|
59 |
+
'wprss_debug_download_error_log_operation',
|
60 |
+
array(
|
61 |
+
'nonce' => 'wprss-download-error-log',
|
62 |
+
'run' => 'wprss_download_log',
|
63 |
+
'redirect' => 'edit.php?post_type=wprss_feed&page=wprss-debugging',
|
64 |
+
'render' => 'wprss_debug_download_log_button'
|
65 |
+
)
|
66 |
+
);
|
67 |
+
|
68 |
+
$operations['clear-error-log'] = apply_filters(
|
69 |
'wprss_debug_error_log_operation',
|
70 |
array(
|
71 |
'nonce' => 'wprss-clear-error-log',
|
177 |
<?php
|
178 |
}
|
179 |
|
|
|
180 |
/**
|
181 |
+
* Renders the Error Log.
|
|
|
|
|
182 |
*/
|
183 |
+
function wprss_debug_render_error_log() {
|
184 |
?>
|
185 |
<h3><?php _e( 'Error Log', WPRSS_TEXT_DOMAIN ); ?></h3>
|
186 |
|
187 |
<textarea readonly="readonly" id="wprss-error-log-textarea"><?php echo wprss_get_log(); ?></textarea>
|
188 |
+
<?php
|
189 |
+
}
|
190 |
|
191 |
+
/**
|
192 |
+
* Renders the "Clear log" button
|
193 |
+
*
|
194 |
+
* @since 3.9.6
|
195 |
+
*/
|
196 |
+
function wprss_debug_clear_log_button() {
|
197 |
+
$form_url = admin_url( 'edit.php?post_type=wprss_feed&page=wprss-debugging' ); ?>
|
198 |
+
<form id="wprss-clear-error-log-form" action="<?php echo $form_url; ?>" method="POST" class="wprss-error-log-action">
|
199 |
+
<?php wp_nonce_field( 'wprss-clear-error-log' ); ?>
|
200 |
+
<button type="submit" for="wprss-clear-error-log-form" name="clear-error-log" class="button button-red">
|
201 |
+
<i class="fa fa-trash-o"></i>
|
202 |
+
<?php _e( 'Clear log', WPRSS_TEXT_DOMAIN ); ?>
|
203 |
+
</button>
|
204 |
</form>
|
205 |
+
<?php
|
206 |
+
}
|
207 |
|
208 |
+
/**
|
209 |
+
* Renders the "Download Error Log" button
|
210 |
+
*
|
211 |
+
* @since 4.7.8
|
212 |
+
*/
|
213 |
+
function wprss_debug_download_log_button() {
|
214 |
+
$form_url = admin_url( 'edit.php?post_type=wprss_feed&page=wprss-debugging' ); ?>
|
215 |
+
<form id="wprss-download-error-log-form" action="<?php echo $form_url; ?>" method="POST" class="wprss-error-log-action">
|
216 |
+
<?php wp_nonce_field( 'wprss-download-error-log' ); ?>
|
217 |
+
<button type="submit" for="wprss-download-error-log-form" name="download-error-log" class="button button-primary">
|
218 |
+
<i class="fa fa-download"></i>
|
219 |
+
<?php _e( 'Download log', WPRSS_TEXT_DOMAIN ); ?>
|
220 |
+
</button>
|
221 |
+
</form>
|
222 |
<?php
|
223 |
}
|
224 |
|
includes/admin-help.php
CHANGED
@@ -1,9 +1,12 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/**
|
3 |
* Build the Help page
|
4 |
-
*
|
5 |
* @since 4.2
|
6 |
-
*/
|
7 |
function wprss_help_page_display() {
|
8 |
?>
|
9 |
|
@@ -12,14 +15,32 @@
|
|
12 |
|
13 |
<h2><?php _e( 'Help & Support', WPRSS_TEXT_DOMAIN ); ?></h2>
|
14 |
<h3><?php _e( 'Documentation', WPRSS_TEXT_DOMAIN ) ?></h3>
|
15 |
-
<?php
|
16 |
-
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
<h3><?php _e( 'Frequently Asked Questions (FAQ)', WPRSS_TEXT_DOMAIN ) ?></h3>
|
19 |
-
<?php echo wpautop( __('If after going through the documentation you still have questions, please take a look at the <a href="http://www.wprssaggregator.com/faq/">FAQ page</a> on the site, we set this up purposely to answer the most commonly asked questions by our users.', WPRSS_TEXT_DOMAIN) ) ?>
|
20 |
-
|
21 |
<?php
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
wprss_premium_help_display();
|
24 |
} else {
|
25 |
wprss_free_help_display();
|
@@ -32,9 +53,9 @@
|
|
32 |
|
33 |
/**
|
34 |
* Print the premium help section with inline support form.
|
35 |
-
*
|
36 |
* @since 4.7
|
37 |
-
*/
|
38 |
function wprss_premium_help_display() {
|
39 |
// Get the first valid license.
|
40 |
$addon = '';
|
@@ -57,7 +78,7 @@
|
|
57 |
}
|
58 |
|
59 |
// Get the full license info so we can prefill the name and email
|
60 |
-
$license =
|
61 |
$customer_name = is_object($license) ? $license->customer_name : '';
|
62 |
$customer_email = is_object($license) ? $license->customer_email : '';
|
63 |
|
@@ -89,11 +110,11 @@
|
|
89 |
<td colspan="3"><input type='checkbox' name='support-include-log' value='checked' checked><?php _e('WP RSS Aggregator log file', WPRSS_TEXT_DOMAIN); ?></td>
|
90 |
</tr>
|
91 |
<tr>
|
92 |
-
<td colspan="3"><input type='checkbox' name='support-include-sys' value='checked' checked><?php _e('WordPress information', WPRSS_TEXT_DOMAIN); ?></td>
|
93 |
</tr>
|
94 |
</table>
|
95 |
</form>
|
96 |
-
<div style='line-height:2.3em;'>
|
97 |
<button id='send-message-btn' class='button button-primary'><?php _e('Send Message', WPRSS_TEXT_DOMAIN); ?></button>
|
98 |
<span id='support-error'></span>
|
99 |
</div>
|
@@ -103,12 +124,17 @@
|
|
103 |
|
104 |
/**
|
105 |
* Print the free help section with link to forums.
|
106 |
-
*
|
107 |
* @since 4.7
|
108 |
-
*/
|
109 |
function wprss_free_help_display() {
|
110 |
echo '<h3>' . __( 'Support Forums', WPRSS_TEXT_DOMAIN ) . '</h3>';
|
111 |
-
|
|
|
|
|
|
|
|
|
|
|
112 |
}
|
113 |
|
114 |
|
@@ -137,8 +163,8 @@
|
|
137 |
// Send the email.
|
138 |
$sent = wp_mail( "support@wprssaggregator.com", $subject, $message, $headers );
|
139 |
|
140 |
-
// NB, the retval is a best-guess about email sending. According to the WP Codex it
|
141 |
-
// doesn't mean the user received the email, it "only means that the method used
|
142 |
// was able to process the request without any errors."
|
143 |
if ($sent === FALSE) {
|
144 |
$ret['error'] = sprintf(__('There was an error sending the form. Please use the <a href="%s" target="_blank">contact form on our site.</a>'), esc_attr('http://www.wprssaggregator.com/contact/'));
|
@@ -153,10 +179,10 @@
|
|
153 |
|
154 |
|
155 |
/**
|
156 |
-
* Ensures that all support form fields have been filled out. Returns TRUE
|
157 |
*
|
158 |
* @since 4.7
|
159 |
-
* @return FALSE when all fields are valid, or a string containing an error they aren't.
|
160 |
*/
|
161 |
function wprss_validate_support_request() {
|
162 |
$fields = array(
|
@@ -171,7 +197,7 @@
|
|
171 |
if (!isset($_GET[$field]) || $_GET[$field] === "") {
|
172 |
|
173 |
return sprintf(
|
174 |
-
__('Please fill out all the fields in the form, including the <strong>%s</strong> field.', WPRSS_TEXT_DOMAIN),
|
175 |
ucfirst(substr($field, strpos($field, '-') + 1))
|
176 |
);
|
177 |
}
|
@@ -245,44 +271,44 @@
|
|
245 |
return $headers;
|
246 |
}
|
247 |
|
248 |
-
|
249 |
/**
|
250 |
* Encapsulates features for providing inline help in the admin interface.
|
251 |
-
*
|
252 |
* The following filters are introduced:
|
253 |
-
*
|
254 |
* - `wprss_help_default_options` - The default options to be extended.
|
255 |
-
*
|
256 |
* 1. The array of options
|
257 |
-
*
|
258 |
* - `wprss_help_template_path` - The path of template retrieved by WPRSS_Help::get_template().
|
259 |
-
*
|
260 |
* 1. The path to the template.
|
261 |
* 2. The array of variables passed.
|
262 |
-
*
|
263 |
* - `wprss_help_template_vars` - The variables for the template, received by WPRSS_Help::get_template().
|
264 |
*
|
265 |
* 1. The variables array.
|
266 |
* 2. The path to the template, filtered by `wprss_help_template_path`.
|
267 |
-
*
|
268 |
* - `wprss_help_tooltip_options` - Options that are in effect when adding tooltips with WPRSS_Help::add_tooltip().
|
269 |
* - `wprss_help_tooltip_handle_html_options` - Options that are in effect when retrieving tooltip handle HTML with WPRSS_Help::wprss_help_tooltip_handle_html_options.
|
270 |
-
*
|
271 |
-
*
|
272 |
* Also, the following options are available:
|
273 |
-
*
|
274 |
* - `tooltip_id_prefix` - The HTML element ID prefix that will be used for tooltips.
|
275 |
* - `tooltip_handle_text` - The text that will appear inside the handle HTML elements.
|
276 |
* - `tooltip_handle_class` - The CSS class that will be assigned to tooltip handles.
|
277 |
* - `tooltip_content_class` - The CSS class that will be assigned to tooltip content HTML elements.
|
278 |
* - `enqueue_tooltip_content` - Whether or not content is to be enqueued, instead of being output directly.
|
279 |
-
*
|
280 |
* 1. The absolute path to the core plugin directory
|
281 |
*/
|
282 |
class WPRSS_Help {
|
283 |
|
284 |
static $_instance;
|
285 |
-
|
286 |
protected $_options;
|
287 |
protected $_enqueued_tooltip_content = array();
|
288 |
protected $_tooltips = array();
|
@@ -293,14 +319,14 @@ class WPRSS_Help {
|
|
293 |
const TEXT_DOMAIN = WPRSS_TEXT_DOMAIN;
|
294 |
const HASHING_CONCATENATOR = '|';
|
295 |
const OPTIONS_FILTER_SUFFIX = '_options';
|
296 |
-
|
297 |
const TOOLTIP_DATA_KEY_ID = 'id';
|
298 |
const TOOLTIP_DATA_KEY_TEXT = 'text';
|
299 |
const TOOLTIP_DATA_KEY_OPTIONS = 'options';
|
300 |
|
301 |
/**
|
302 |
* Retrieve the singleton instance
|
303 |
-
*
|
304 |
* @return WPRSS_Help
|
305 |
*/
|
306 |
public static function get_instance() {
|
@@ -311,20 +337,20 @@ class WPRSS_Help {
|
|
311 |
|
312 |
return self::$_instance;
|
313 |
}
|
314 |
-
|
315 |
|
316 |
public static function init() {
|
317 |
// Actions
|
318 |
add_action( 'admin_enqueue_scripts', array( self::get_instance(), '_admin_enqueue_scripts' ) );
|
319 |
add_action( 'admin_footer', array( self::get_instance(), '_admin_footer' ) );
|
320 |
}
|
321 |
-
|
322 |
|
323 |
/**
|
324 |
* Filters used:
|
325 |
-
*
|
326 |
* - `wprss_help_default_options`
|
327 |
-
*
|
328 |
* @param array $options Options that will overwrite defaults.
|
329 |
*/
|
330 |
public function __construct( $options = array() ) {
|
@@ -347,21 +373,21 @@ class WPRSS_Help {
|
|
347 |
|
348 |
$this->_construct();
|
349 |
}
|
350 |
-
|
351 |
|
352 |
/**
|
353 |
* Used for parameter-less extension of constructor logic
|
354 |
*/
|
355 |
protected function _construct() {
|
356 |
-
|
357 |
}
|
358 |
-
|
359 |
|
360 |
/**
|
361 |
* Return an option value, or the whole array of internal options.
|
362 |
* These options are a product of the defaults, the database, and anything
|
363 |
* set later on, applied on top of eachother and overwriting in that order.
|
364 |
-
*
|
365 |
* @param null|string $key The key of the option to return.
|
366 |
* @param null|mixed $default What to return if options with the specified key not found.
|
367 |
* @return array|mixed|null The option value, or an array of options.
|
@@ -372,20 +398,20 @@ class WPRSS_Help {
|
|
372 |
if ( is_null( $key ) ) {
|
373 |
return $options;
|
374 |
}
|
375 |
-
|
376 |
if( is_array( $key ) ) {
|
377 |
return $this->array_merge_recursive_distinct( $options, $key );
|
378 |
}
|
379 |
|
380 |
return isset( $options[ $key ] ) ? $options[ $key ] : $default;
|
381 |
}
|
382 |
-
|
383 |
|
384 |
/**
|
385 |
* Set the value of an internal option or options.
|
386 |
* Existing options will be overwritten. New options will be added.
|
387 |
* Database options will not be modified.
|
388 |
-
*
|
389 |
* @param string|array $key The key of the option to set, or an array of options.
|
390 |
* @param null|mixed $value The value of the option to set.
|
391 |
* @return WPRSS_Help This instance.
|
@@ -401,12 +427,12 @@ class WPRSS_Help {
|
|
401 |
|
402 |
$this->_set_options( $key, $value );
|
403 |
}
|
404 |
-
|
405 |
|
406 |
/**
|
407 |
* Set an option value, or all options.
|
408 |
* In latter case completely overrides the whole options array.
|
409 |
-
*
|
410 |
* @param string|array $key The key of the option to set, or the whole options array.
|
411 |
* @param null|mixed $value Value of the option to set.
|
412 |
* @return WPRSS_Help This instance.
|
@@ -420,11 +446,11 @@ class WPRSS_Help {
|
|
420 |
$this->_options[ $key ] = $value;
|
421 |
return $this;
|
422 |
}
|
423 |
-
|
424 |
|
425 |
/**
|
426 |
* Returns a WPRSS_Help option or options from the database.
|
427 |
-
*
|
428 |
* @param string $key The key of the option to return.
|
429 |
* @param null|mixed $default What to return if option identified by $key is not found.
|
430 |
* @return null|array|mixed The options or option value.
|
@@ -438,16 +464,16 @@ class WPRSS_Help {
|
|
438 |
|
439 |
return isset( $options[ $key ] ) ? $options[ $key ] : $default;
|
440 |
}
|
441 |
-
|
442 |
|
443 |
/**
|
444 |
* Get content of a template.
|
445 |
-
*
|
446 |
* Filters used
|
447 |
-
*
|
448 |
* - `wprss_help_template_path`
|
449 |
* - `wprss_help_template_vars`
|
450 |
-
*
|
451 |
* @param string $path Full path to the template
|
452 |
* @param array $vars This will be passed to the template
|
453 |
*/
|
@@ -465,68 +491,68 @@ class WPRSS_Help {
|
|
465 |
|
466 |
return $content;
|
467 |
}
|
468 |
-
|
469 |
|
470 |
/**
|
471 |
* This is called during the `admin_enqueue_scripts` action, and will
|
472 |
* enqueue scripts needed for the backend.
|
473 |
-
*
|
474 |
* Filters used:
|
475 |
-
*
|
476 |
* - `wprss_help_admin_scripts`
|
477 |
-
*
|
478 |
* @return WPRSS_Help This instance.
|
479 |
*/
|
480 |
public function _admin_enqueue_scripts() {
|
481 |
$scripts = $this->apply_filters( 'admin_scripts', array(
|
482 |
'jquery-ui-tooltip' => array()
|
483 |
));
|
484 |
-
|
485 |
foreach ( $scripts as $_handle => $_args ) {
|
486 |
// Allows numeric array with handles as values
|
487 |
if ( is_numeric( $_handle ) ) {
|
488 |
$_handle = $_args;
|
489 |
}
|
490 |
-
|
491 |
// Allows specifying null as value to simply enqueue handle
|
492 |
if ( empty( $_args ) ){
|
493 |
$_args = array();
|
494 |
}
|
495 |
-
|
496 |
array_unshift( $_args, $_handle );
|
497 |
call_user_func_array( 'wp_enqueue_script', $_args );
|
498 |
}
|
499 |
-
|
500 |
return $this;
|
501 |
}
|
502 |
-
|
503 |
-
|
504 |
public function _admin_footer() {
|
505 |
$html = '';
|
506 |
$html .= $this->get_enqueued_tooltip_content_html() . "\n";
|
507 |
$html .= $this->get_admin_footer_js_html();
|
508 |
$html = $this->apply_filters( 'admin_footer', $html );
|
509 |
-
|
510 |
echo $html;
|
511 |
}
|
512 |
-
|
513 |
-
|
514 |
public function is_overrides_default_prefix( $string ) {
|
515 |
return strpos( $string, self::OVERRIDE_DEFAULT_PREFIX ) === 0;
|
516 |
}
|
517 |
-
|
518 |
-
|
519 |
/**
|
520 |
* @return string This class's text domain
|
521 |
*/
|
522 |
public function get_text_domain() {
|
523 |
return self::TEXT_DOMAIN;
|
524 |
}
|
525 |
-
|
526 |
/**
|
527 |
* Format this string, replacing placeholders with values, and translate it
|
528 |
* in the class's text domain.
|
529 |
-
*
|
530 |
* @see sprintf()
|
531 |
* @param string $string The string to translate.
|
532 |
* @param mixed $argN,.. Additional arguments.
|
@@ -534,18 +560,18 @@ class WPRSS_Help {
|
|
534 |
public function __( $string, $argN = null ) {
|
535 |
$args = func_get_args();
|
536 |
$args[0] = $string = __( $string, $this->get_text_domain() );
|
537 |
-
|
538 |
$string = call_user_func_array( 'sprintf', $args );
|
539 |
-
|
540 |
return $string;
|
541 |
}
|
542 |
-
|
543 |
/**
|
544 |
* Hashes all the given values into a single hash.
|
545 |
* Accepts an infinite number of parameters, all of which will be first
|
546 |
* glued together by a separator, then hashed.
|
547 |
* Non-scalar values will be serialized.
|
548 |
-
*
|
549 |
* @param mixed $value The value to hash.
|
550 |
* @param mixed $argN Other values to hash.
|
551 |
* @return string The hash.
|
@@ -553,33 +579,33 @@ class WPRSS_Help {
|
|
553 |
public function get_hash( $value ) {
|
554 |
$args = func_get_args();
|
555 |
$glue = self::HASHING_CONCATENATOR;
|
556 |
-
|
557 |
$blob = '';
|
558 |
foreach ( $args as $_idx => $_arg ) {
|
559 |
$blob .= is_scalar( $_arg ) ? $_arg : serialize( $_arg );
|
560 |
$blob .= $glue;
|
561 |
}
|
562 |
-
|
563 |
$blob = substr( $blob, 0, -1 );
|
564 |
-
|
565 |
return sha1( $blob );
|
566 |
}
|
567 |
-
|
568 |
/**
|
569 |
* Get the class code prefix, or the specified prefixed with it.
|
570 |
-
*
|
571 |
* @param string $string A string to prefix.
|
572 |
* @return string The code prefix or the prefixed string.
|
573 |
*/
|
574 |
public function get_code_prefix( $string = '' ) {
|
575 |
return self::CODE_PREFIX . (string)$string;
|
576 |
}
|
577 |
-
|
578 |
/**
|
579 |
* Optionally prefix a string with the class code prefix, unless it
|
580 |
* contains the "!" character in the very beginning, in which case it will
|
581 |
* simply be removed.
|
582 |
-
*
|
583 |
* @param string $string The string to consider for prefixing.
|
584 |
* @return string The prefixed or clean string.
|
585 |
*/
|
@@ -588,11 +614,11 @@ class WPRSS_Help {
|
|
588 |
? substr( $string, 1 )
|
589 |
: $this->get_code_prefix( $string );
|
590 |
}
|
591 |
-
|
592 |
/**
|
593 |
* Applies filters, but prefixes the filter name with 'wprss_help_',
|
594 |
* unless '!' is specified as the first character of the filter.
|
595 |
-
*
|
596 |
* @param string $filter_name Name or "tag" of the filter.
|
597 |
* @param mixed $subject The value to apply filters to.
|
598 |
* @param mixed $argN,.. Additional filter arguments
|
@@ -600,46 +626,46 @@ class WPRSS_Help {
|
|
600 |
*/
|
601 |
public function apply_filters( $filter_name, $subject, $argN = null ) {
|
602 |
$args = func_get_args();
|
603 |
-
|
604 |
$args[0] = $filter_name = $this->prefix( $filter_name );
|
605 |
-
|
606 |
return call_user_func_array( 'apply_filters', $args );
|
607 |
}
|
608 |
-
|
609 |
-
|
610 |
/**
|
611 |
* Applies a filters with the specified name to the options that were
|
612 |
* applied on top of defaults.
|
613 |
* The name will be prefixed with the class prefix 'wprss_help_', and
|
614 |
* suffixed with '_options'.
|
615 |
-
*
|
616 |
* @param string $filter_name Name of the filter to apply to the options
|
617 |
* @param array $options The options to filter
|
618 |
* @param mixed $filter_argN,.. Other filter arguments to be passed to filter
|
619 |
*/
|
620 |
public function apply_options_filters( $filter_name, $options = array(), $filter_argN = null ) {
|
621 |
$args = func_get_args();
|
622 |
-
|
623 |
// Adding sufix
|
624 |
$args[0] = $filter_name .= self::OPTIONS_FILTER_SUFFIX;
|
625 |
-
|
626 |
// Applying defaults
|
627 |
$args[1] = $options = $this->get_options( $options );
|
628 |
-
|
629 |
// Entry point. Order of args is already correct.
|
630 |
$options = call_user_func_array( array( $this, 'apply_filters' ), $args );
|
631 |
-
|
632 |
return $options;
|
633 |
}
|
634 |
-
|
635 |
-
|
636 |
/**
|
637 |
* Parses the tooltip handle template path for placeholders.
|
638 |
-
*
|
639 |
* Filters used:
|
640 |
-
*
|
641 |
* - `wprss_help_admin_footer_js_html_template`
|
642 |
-
*
|
643 |
* @param null|string $path Optional path to parse and retrieve. Default: value of the 'admin_footer_js_template' option.
|
644 |
* @return string Path to the template.
|
645 |
*/
|
@@ -648,40 +674,40 @@ class WPRSS_Help {
|
|
648 |
if ( is_null( $path ) ) {
|
649 |
$path = $this->get_options( 'admin_footer_js_template' );
|
650 |
}
|
651 |
-
|
652 |
// Entry point
|
653 |
$path = $this->apply_filters( 'admin_footer_js_html_template', $path );
|
654 |
-
|
655 |
return $this->parse_path( $path );
|
656 |
}
|
657 |
-
|
658 |
-
|
659 |
/**
|
660 |
* Get the HTML of the JavaScript for the footer in Admin Panel.
|
661 |
-
*
|
662 |
* Filters used:
|
663 |
-
*
|
664 |
* - `wprss_help_admin_footer_js_html`
|
665 |
-
*
|
666 |
* @param array $options Any additional options to be used with defaults.
|
667 |
* @return string The HTML.
|
668 |
*/
|
669 |
public function get_admin_footer_js_html( $options = array() ) {
|
670 |
$options = $this->apply_options_filters( 'admin_footer_js_html', $options);
|
671 |
-
|
672 |
$templatePath = $this->get_admin_footer_js_html_template( $options['admin_footer_js_template'] );
|
673 |
-
|
674 |
return $this->get_template($templatePath, $options);
|
675 |
}
|
676 |
-
|
677 |
-
|
678 |
/**
|
679 |
* Parses the tooltip handle template path for placeholders.
|
680 |
-
*
|
681 |
* Filters used:
|
682 |
-
*
|
683 |
* - `wprss_help_tooltip_handle_html_template`
|
684 |
-
*
|
685 |
* @param null|string $path Optional path to parse and retrieve. Default: value of the 'tooltip_handle_template' option.
|
686 |
* @return string Path to the template.
|
687 |
*/
|
@@ -690,21 +716,21 @@ class WPRSS_Help {
|
|
690 |
if ( is_null( $path ) ) {
|
691 |
$path = $this->get_options( 'tooltip_handle_template' );
|
692 |
}
|
693 |
-
|
694 |
// Entry point
|
695 |
$path = $this->apply_filters( 'tooltip_handle_html_template', $path );
|
696 |
-
|
697 |
return $this->parse_path( $path );
|
698 |
}
|
699 |
-
|
700 |
-
|
701 |
/**
|
702 |
* Get the HTML of the tooltip handle.
|
703 |
-
*
|
704 |
* Filters used:
|
705 |
-
*
|
706 |
* - `wprss_help_tooltip_handle_html_options`
|
707 |
-
*
|
708 |
* @param string $text Content of the tooltip text.
|
709 |
* @param string $id ID of the tooltip.
|
710 |
* @param array $options Any additional options to be used with defaults.
|
@@ -716,20 +742,20 @@ class WPRSS_Help {
|
|
716 |
// Add template varialbes
|
717 |
$options['tooltip_id'] = $id;
|
718 |
$options['tooltip_text'] = $text;
|
719 |
-
|
720 |
$templatePath = $this->get_tooltip_handle_html_template( $options['tooltip_handle_template'] );
|
721 |
-
|
722 |
return $this->get_template($templatePath, $options);
|
723 |
}
|
724 |
-
|
725 |
-
|
726 |
/**
|
727 |
* Parses the tooltip content template path for placeholders.
|
728 |
-
*
|
729 |
* Filters used:
|
730 |
-
*
|
731 |
* - `wprss_help_tooltip_content_html_template`
|
732 |
-
*
|
733 |
* @param null|string $path Optional path to parse and retrieve. Default: value of the 'tooltip_handle_template' option.
|
734 |
* @return string Path to the template.
|
735 |
*/
|
@@ -738,21 +764,21 @@ class WPRSS_Help {
|
|
738 |
if ( is_null( $path ) ) {
|
739 |
$path = $this->get_options( 'tooltip_content_template' );
|
740 |
}
|
741 |
-
|
742 |
// Entry point
|
743 |
$path = $this->apply_filters( 'tooltip_content_html_template', $path );
|
744 |
-
|
745 |
return $this->parse_path( $path );
|
746 |
}
|
747 |
-
|
748 |
-
|
749 |
/**
|
750 |
* Get the HTML of the tooltip content.
|
751 |
-
*
|
752 |
* Filters used:
|
753 |
-
*
|
754 |
* - `wprss_help_tooltip_content_html_options`
|
755 |
-
*
|
756 |
* @param string $text Content of the tooltip text.
|
757 |
* @param string $id ID of the tooltip.
|
758 |
* @param array $options Any additional options to be used with defaults.
|
@@ -760,23 +786,23 @@ class WPRSS_Help {
|
|
760 |
*/
|
761 |
public function get_tooltip_content_html( $text, $id, $options = array() ) {
|
762 |
$options = $this->apply_options_filters( 'tooltip_content_html', $options, $text, $id );
|
763 |
-
|
764 |
// Add template varialbes
|
765 |
$options['tooltip_id'] = $id;
|
766 |
$options['tooltip_text'] = $text;
|
767 |
-
|
768 |
$templatePath = $this->get_tooltip_content_html_template( $options['tooltip_content_template'] );
|
769 |
-
|
770 |
return $this->get_template( $templatePath, $options );
|
771 |
}
|
772 |
-
|
773 |
-
|
774 |
/**
|
775 |
* Add tooltip and get tooltip HTML.
|
776 |
* If $text is null, just get the HTML of tooltip with specified ID.
|
777 |
* The `is_enqueue_tooltip_content` option determines whether to enqueue
|
778 |
* the content, instead of outputting it after the handle.
|
779 |
-
*
|
780 |
* @param string $id ID for this tooltip
|
781 |
* @param string|null $text Text of this tooltip. If null, tooltip will not be added, but only retrieved.
|
782 |
* @param array|bool $options The options for this operation, or a boolean indicating whether or not content is to be enqueued
|
@@ -786,11 +812,11 @@ class WPRSS_Help {
|
|
786 |
$this->add_tooltip( $id, $text, $options );
|
787 |
return $this->do_tooltip( $id );
|
788 |
}
|
789 |
-
|
790 |
-
|
791 |
/**
|
792 |
* Add tooltips in a batch, with optionally prefixed ID.
|
793 |
-
*
|
794 |
* @param array $tooltips An array where key is tooltip ID and value is tooltip text.
|
795 |
* @param string $prefix A prefix to add to all tooltip IDs.
|
796 |
* @param array $options Arra of options for all the tooltips to add.
|
@@ -799,20 +825,20 @@ class WPRSS_Help {
|
|
799 |
public function add_tooltips( $tooltips, $prefix = null, $options = array() ) {
|
800 |
$prefix = (string) $prefix;
|
801 |
if ( !is_array($options) ) $options = array();
|
802 |
-
|
803 |
foreach ( $tooltips as $_id => $_text ) {
|
804 |
$this->add_tooltip( $prefix . $_id, $_text, $options );
|
805 |
}
|
806 |
-
|
807 |
return $this;
|
808 |
}
|
809 |
-
|
810 |
-
|
811 |
/**
|
812 |
* Add a tooltip for later display.
|
813 |
* Text and options will be replaced by existing text and options, if they
|
814 |
* are empty, and a tooltip with the same ID is already registered.
|
815 |
-
*
|
816 |
* @param string $id The ID of this tooltip
|
817 |
* @param string $text Text for this tooltip
|
818 |
* @param array $options Options for this tooltip.
|
@@ -823,16 +849,16 @@ class WPRSS_Help {
|
|
823 |
if ( is_null( $text ) ) $text = isset( $tooltip[ self::TOOLTIP_DATA_KEY_TEXT ] ) ? $tooltip[ self::TOOLTIP_DATA_KEY_TEXT ] : $text;
|
824 |
if ( empty( $options ) ) $options = isset( $tooltip[ self::TOOLTIP_DATA_KEY_OPTIONS ] ) ? $tooltip[ self::TOOLTIP_DATA_KEY_OPTIONS ] : $options;
|
825 |
}
|
826 |
-
|
827 |
$this->set_tooltip( $id, $text, $options );
|
828 |
-
|
829 |
return $this;
|
830 |
}
|
831 |
-
|
832 |
-
|
833 |
/**
|
834 |
* Set a tooltip, existing or not.
|
835 |
-
*
|
836 |
* @param string $id The ID of this tooltip
|
837 |
* @param string $text Text for this tooltip
|
838 |
* @param array $options Options for this tooltip.
|
@@ -844,14 +870,14 @@ class WPRSS_Help {
|
|
844 |
self::TOOLTIP_DATA_KEY_TEXT => $text,
|
845 |
self::TOOLTIP_DATA_KEY_OPTIONS => $options
|
846 |
);
|
847 |
-
|
848 |
return $this;
|
849 |
}
|
850 |
-
|
851 |
-
|
852 |
/**
|
853 |
* Retrieve one tooltip, or an array containing all tooltips.
|
854 |
-
*
|
855 |
* @param string|null $id The ID of the tooltip to retrieve.
|
856 |
* @param mixed|null $default What to return if tooltip with specified ID not found.
|
857 |
* @return array An array that contains the following indexes: 'id', 'text', 'options'. See {@link add_tooltip()} for details.
|
@@ -860,28 +886,28 @@ class WPRSS_Help {
|
|
860 |
if ( is_null( $id ) ) {
|
861 |
return $this->_tooltips;
|
862 |
}
|
863 |
-
|
864 |
return $this->has_tooltip( $id ) ? $this->_tooltips[ $id ] : $default;
|
865 |
}
|
866 |
-
|
867 |
-
|
868 |
/**
|
869 |
* Check whether a tooltip with the specified ID exists.
|
870 |
-
*
|
871 |
* @param string $id ID of the tooltip to check for.
|
872 |
* @return boolean True if a tooltip with the specified ID exists; false otherwise.
|
873 |
*/
|
874 |
public function has_tooltip( $id ) {
|
875 |
return isset( $this->_tooltips[ $id ] );
|
876 |
}
|
877 |
-
|
878 |
/**
|
879 |
* Get registered tooltip HTML.
|
880 |
-
*
|
881 |
* Filters used:
|
882 |
-
*
|
883 |
* - `wprss_help_tooltip_options` - Filters options used for tooltip
|
884 |
-
*
|
885 |
* @param string $id ID for this tooltip
|
886 |
* @param string $text Text of this tooltip
|
887 |
* @param array|bool $options The options for this operation, or a boolean indicating whether or not content is to be enqueued
|
@@ -889,40 +915,40 @@ class WPRSS_Help {
|
|
889 |
*/
|
890 |
public function do_tooltip( $id ) {
|
891 |
$options = $this->get_options();
|
892 |
-
|
893 |
if ( !($tooltip = $this->get_tooltip( $id )) || !isset($tooltip[ self::TOOLTIP_DATA_KEY_TEXT ]) || !$tooltip[ self::TOOLTIP_DATA_KEY_TEXT ] ) {
|
894 |
return isset( $options['tooltip_not_found_handle_html'] )
|
895 |
? $options['tooltip_not_found_handle_html']
|
896 |
: null;
|
897 |
}
|
898 |
-
|
899 |
$options = isset( $tooltip[ self::TOOLTIP_DATA_KEY_OPTIONS ] ) ? $tooltip[ self::TOOLTIP_DATA_KEY_OPTIONS ] : null;
|
900 |
$text = isset( $tooltip[ self::TOOLTIP_DATA_KEY_TEXT ] ) ? $tooltip[ self::TOOLTIP_DATA_KEY_TEXT ] : null;
|
901 |
-
|
902 |
if ( !is_array( $options ) ) {
|
903 |
$options = array( 'is_enqueue_tooltip_content' => $options );
|
904 |
}
|
905 |
-
|
906 |
// Entry point
|
907 |
$options = $this->apply_options_filters( 'tooltip', $options, $id, $text );
|
908 |
-
|
909 |
// Get handle HTML
|
910 |
$output = $this->get_tooltip_handle_html( $text, $id, $options );
|
911 |
-
|
912 |
if ( $this->evaluate_boolean( $options['is_enqueue_tooltip_content'] ) ) {
|
913 |
$this->enqueue_tooltip_content($text, $id, $options);
|
914 |
}
|
915 |
else {
|
916 |
$output .= $this->get_tooltip_content_html( $text, $id, $options );
|
917 |
}
|
918 |
-
|
919 |
return $output;
|
920 |
}
|
921 |
-
|
922 |
-
|
923 |
/**
|
924 |
* Enqueue tooltip content to be displayed in another part of the page.
|
925 |
-
*
|
926 |
* @param string $text The text of the tooltip content to enqueue.
|
927 |
* @param string $id ID of the tooltip, the content of which to enqueue.
|
928 |
* @param array $options This tooltip's options.
|
@@ -930,7 +956,7 @@ class WPRSS_Help {
|
|
930 |
*/
|
931 |
public function enqueue_tooltip_content( $text, $id, $options = array() ) {
|
932 |
$queue_method = $this->apply_filters( 'enqueue_tooltip_content_method', array( $this, '_enqueue_tooltip_content' ), $options, $id, $text );
|
933 |
-
|
934 |
// "Error handling" WP style
|
935 |
if ( !is_callable( $queue_method ) ) {
|
936 |
return new WP_Error( $this->prefix( 'invalid_queue_method' ), $this->__( 'Could not enqueue tooltip content: the queue method is not a valid callable.' ), array(
|
@@ -940,13 +966,13 @@ class WPRSS_Help {
|
|
940 |
'options' => $options
|
941 |
));
|
942 |
}
|
943 |
-
|
944 |
call_user_func_array( $queue_method, array( $text, $id, $options ) );
|
945 |
-
|
946 |
return $this;
|
947 |
}
|
948 |
-
|
949 |
-
|
950 |
public function _enqueue_tooltip_content( $text, $id, $options = array() ) {
|
951 |
$hash = $this->get_hash( $text, $id, $options );
|
952 |
$this->_enqueued_tooltip_content[ $hash ] = array(
|
@@ -954,31 +980,31 @@ class WPRSS_Help {
|
|
954 |
self::TOOLTIP_DATA_KEY_ID => $id,
|
955 |
self::TOOLTIP_DATA_KEY_OPTIONS => $options
|
956 |
);
|
957 |
-
|
958 |
return $this;
|
959 |
}
|
960 |
-
|
961 |
-
|
962 |
public function get_enqueued_tooltip_content() {
|
963 |
return $this->_enqueued_tooltip_content;
|
964 |
}
|
965 |
-
|
966 |
-
|
967 |
public function get_enqueued_tooltip_content_html() {
|
968 |
$output = '';
|
969 |
foreach ( $this->get_enqueued_tooltip_content() as $_hash => $_vars ) {
|
970 |
$options = is_array( $_vars[ self::TOOLTIP_DATA_KEY_OPTIONS ] ) ? $_vars[ self::TOOLTIP_DATA_KEY_OPTIONS ] : array();
|
971 |
$output = $this->get_tooltip_content_html( $_vars[ self::TOOLTIP_DATA_KEY_ID ], $_vars[ self::TOOLTIP_DATA_KEY_ID ], $options );
|
972 |
}
|
973 |
-
|
974 |
echo $output;
|
975 |
}
|
976 |
-
|
977 |
-
|
978 |
/**
|
979 |
* Check whether or not the given value is false.
|
980 |
* False values are all {@link empty()} values, and also strings 'false' and 'no'.
|
981 |
-
*
|
982 |
* @param mixed $value The value to check.
|
983 |
* @return boolean Whether or not the value is considered to be false.
|
984 |
*/
|
@@ -987,12 +1013,12 @@ class WPRSS_Help {
|
|
987 |
? false
|
988 |
: true;
|
989 |
}
|
990 |
-
|
991 |
|
992 |
/**
|
993 |
* Merge two arrays in an intuitive way.
|
994 |
* Input arrays remain unchanged.
|
995 |
-
*
|
996 |
* @see http://php.net/manual/en/function.array-merge-recursive.php#92195
|
997 |
* @param array $array1 The array to merge.
|
998 |
* @param array $array2 The array to merge into.
|
@@ -1011,54 +1037,54 @@ class WPRSS_Help {
|
|
1011 |
|
1012 |
return $merged;
|
1013 |
}
|
1014 |
-
|
1015 |
-
|
1016 |
/**
|
1017 |
* Converts an array to a numeric array.
|
1018 |
* If $map is empty, assumes that the array keys are already in order.
|
1019 |
* If $map is a number, assumes it's the amount of elements to return.
|
1020 |
* If $map is an array, assumes it is the map of intended numeric indexes to their value in the input array.
|
1021 |
-
*
|
1022 |
* @param array $array The array to convert to a numeric array
|
1023 |
* @param false|null|array $map The map of the array indexes, or number of array elements to slice, or nothing.
|
1024 |
* @return array The resulting numeric array.
|
1025 |
*/
|
1026 |
public function array_to_numeric( $array, $map = null ) {
|
1027 |
$result = array();
|
1028 |
-
|
1029 |
// If map is not an array, assume it's an indicator
|
1030 |
if ( !is_array( $map ) ) {
|
1031 |
$array = array_values( $array );
|
1032 |
}
|
1033 |
-
|
1034 |
// If map is empty, assume keys are in order
|
1035 |
if ( empty( $map ) ) {
|
1036 |
return $array;
|
1037 |
}
|
1038 |
-
|
1039 |
// If map is a number, assume it's the amount of elements to return
|
1040 |
if ( is_numeric( $map ) ) {
|
1041 |
$map = intval( $map );
|
1042 |
return array_slice( $array, 0, $map );
|
1043 |
}
|
1044 |
-
|
1045 |
foreach( $map as $_idx => $_key ) {
|
1046 |
$result[ $_idx ] = $array[ $_key ];
|
1047 |
}
|
1048 |
-
|
1049 |
return $result;
|
1050 |
}
|
1051 |
-
|
1052 |
-
|
1053 |
/**
|
1054 |
* Parses the template and replaces placeholders with their values.
|
1055 |
* This function uses {@see sprintf()} to format the template string using
|
1056 |
* the values provided in $data.
|
1057 |
* It is also possible for $data to be an associative array of key-value pairs.
|
1058 |
-
* To achieve the same result, a map can be provided, mapping data keys to
|
1059 |
* their placeholder positions.
|
1060 |
-
* If no map is provided,
|
1061 |
-
*
|
1062 |
* @param string $string The template string.
|
1063 |
* @param array $data The key-value pairs of template data.
|
1064 |
* @param false|null|array $map {@see array_to_numeric()} The template value map.
|
@@ -1069,18 +1095,18 @@ class WPRSS_Help {
|
|
1069 |
array_unshift( $data, $string );
|
1070 |
return call_user_func_array( 'sprintf', $data );
|
1071 |
}
|
1072 |
-
|
1073 |
-
|
1074 |
/**
|
1075 |
* Parses a path template specifically with WPRSS_Help path placeholders.
|
1076 |
-
*
|
1077 |
* Filters used (in order):
|
1078 |
-
*
|
1079 |
* 1. `parse_path_data_default`;
|
1080 |
* 2. `parse_path_data`;
|
1081 |
* 3. `parse_path_map`;
|
1082 |
* 4. `parse_path_path`.
|
1083 |
-
*
|
1084 |
* @see WPRSS_Help::parse_template()
|
1085 |
* @param string $path The path to parse.
|
1086 |
* @param null|array $data Any additional data. Will be merged with defaults.
|
@@ -1091,7 +1117,7 @@ class WPRSS_Help {
|
|
1091 |
if( is_null( $data ) ) {
|
1092 |
$data = array();
|
1093 |
}
|
1094 |
-
|
1095 |
$defaults = $this->apply_filters( 'parse_path_data_default', array(
|
1096 |
'wprss_templates_dir' => wprss_get_templates_dir()
|
1097 |
));
|
@@ -1099,7 +1125,7 @@ class WPRSS_Help {
|
|
1099 |
$data = $this->apply_filters( 'parse_path_data', $data, $path, $map );
|
1100 |
$map = $this->apply_filters( 'parse_path_map', $map, $data, $path );
|
1101 |
$path = $this->apply_filters( 'parse_path_path', $path, $data, $map );
|
1102 |
-
|
1103 |
return $this->parse_template( $path, $data, $map );
|
1104 |
}
|
1105 |
}
|
1 |
<?php
|
2 |
+
|
3 |
+
use Aventura\Wprss\Core\Licensing\License\Status as License_Status;
|
4 |
+
|
5 |
/**
|
6 |
* Build the Help page
|
7 |
+
*
|
8 |
* @since 4.2
|
9 |
+
*/
|
10 |
function wprss_help_page_display() {
|
11 |
?>
|
12 |
|
15 |
|
16 |
<h2><?php _e( 'Help & Support', WPRSS_TEXT_DOMAIN ); ?></h2>
|
17 |
<h3><?php _e( 'Documentation', WPRSS_TEXT_DOMAIN ) ?></h3>
|
18 |
+
<?php
|
19 |
+
printf(
|
20 |
+
wpautop(
|
21 |
+
__( 'In the <a href="%s">documentation area</a> on the WP RSS Aggregator website you will find comprehensive details on how to use the core plugin and all the add-ons.
|
22 |
+
|
23 |
+
There are also some videos to help you make a quick start to setting up and enjoying this plugin.',
|
24 |
+
WPRSS_TEXT_DOMAIN
|
25 |
+
)
|
26 |
+
),
|
27 |
+
'http://docs.wprssaggregator.com/'
|
28 |
+
);
|
29 |
+
?>
|
30 |
<h3><?php _e( 'Frequently Asked Questions (FAQ)', WPRSS_TEXT_DOMAIN ) ?></h3>
|
|
|
|
|
31 |
<?php
|
32 |
+
printf(
|
33 |
+
wpautop(
|
34 |
+
__( 'If after going through the documentation you still have questions, please take a look at the <a href="%s">FAQ page</a> on the site. We set this up purposely to answer the most commonly asked questions by our users.',
|
35 |
+
WPRSS_TEXT_DOMAIN
|
36 |
+
)
|
37 |
+
),
|
38 |
+
'http://docs.wprssaggregator.com/category/faqs/'
|
39 |
+
)
|
40 |
+
?>
|
41 |
+
|
42 |
+
<?php
|
43 |
+
if ( wprss_licensing_get_manager()->licenseWithStatusExists( License_Status::VALID ) ) {
|
44 |
wprss_premium_help_display();
|
45 |
} else {
|
46 |
wprss_free_help_display();
|
53 |
|
54 |
/**
|
55 |
* Print the premium help section with inline support form.
|
56 |
+
*
|
57 |
* @since 4.7
|
58 |
+
*/
|
59 |
function wprss_premium_help_display() {
|
60 |
// Get the first valid license.
|
61 |
$addon = '';
|
78 |
}
|
79 |
|
80 |
// Get the full license info so we can prefill the name and email
|
81 |
+
$license = wprss_licensing_get_manager()->checkLicense( $addon, 'ALL' );
|
82 |
$customer_name = is_object($license) ? $license->customer_name : '';
|
83 |
$customer_email = is_object($license) ? $license->customer_email : '';
|
84 |
|
110 |
<td colspan="3"><input type='checkbox' name='support-include-log' value='checked' checked><?php _e('WP RSS Aggregator log file', WPRSS_TEXT_DOMAIN); ?></td>
|
111 |
</tr>
|
112 |
<tr>
|
113 |
+
<td colspan="3"><input type='checkbox' name='support-include-sys' value='checked' checked><?php _e('WordPress debugging information', WPRSS_TEXT_DOMAIN); ?></td>
|
114 |
</tr>
|
115 |
</table>
|
116 |
</form>
|
117 |
+
<div style='line-height:2.3em; margin-top:10px;'>
|
118 |
<button id='send-message-btn' class='button button-primary'><?php _e('Send Message', WPRSS_TEXT_DOMAIN); ?></button>
|
119 |
<span id='support-error'></span>
|
120 |
</div>
|
124 |
|
125 |
/**
|
126 |
* Print the free help section with link to forums.
|
127 |
+
*
|
128 |
* @since 4.7
|
129 |
+
*/
|
130 |
function wprss_free_help_display() {
|
131 |
echo '<h3>' . __( 'Support Forums', WPRSS_TEXT_DOMAIN ) . '</h3>';
|
132 |
+
printf(
|
133 |
+
wpautop(
|
134 |
+
__( 'Users of the free version of WP RSS Aggregator can ask questions on the <a href="%s">support forum</a>.', WPRSS_TEXT_DOMAIN )
|
135 |
+
),
|
136 |
+
'http://wordpress.org/support/plugin/wp-rss-aggregator'
|
137 |
+
);
|
138 |
}
|
139 |
|
140 |
|
163 |
// Send the email.
|
164 |
$sent = wp_mail( "support@wprssaggregator.com", $subject, $message, $headers );
|
165 |
|
166 |
+
// NB, the retval is a best-guess about email sending. According to the WP Codex it
|
167 |
+
// doesn't mean the user received the email, it "only means that the method used
|
168 |
// was able to process the request without any errors."
|
169 |
if ($sent === FALSE) {
|
170 |
$ret['error'] = sprintf(__('There was an error sending the form. Please use the <a href="%s" target="_blank">contact form on our site.</a>'), esc_attr('http://www.wprssaggregator.com/contact/'));
|
179 |
|
180 |
|
181 |
/**
|
182 |
+
* Ensures that all support form fields have been filled out. Returns TRUE
|
183 |
*
|
184 |
* @since 4.7
|
185 |
+
* @return FALSE when all fields are valid, or a string containing an error they aren't.
|
186 |
*/
|
187 |
function wprss_validate_support_request() {
|
188 |
$fields = array(
|
197 |
if (!isset($_GET[$field]) || $_GET[$field] === "") {
|
198 |
|
199 |
return sprintf(
|
200 |
+
__('Please fill out all the fields in the form, including the <strong>%s</strong> field.', WPRSS_TEXT_DOMAIN),
|
201 |
ucfirst(substr($field, strpos($field, '-') + 1))
|
202 |
);
|
203 |
}
|
271 |
return $headers;
|
272 |
}
|
273 |
|
274 |
+
|
275 |
/**
|
276 |
* Encapsulates features for providing inline help in the admin interface.
|
277 |
+
*
|
278 |
* The following filters are introduced:
|
279 |
+
*
|
280 |
* - `wprss_help_default_options` - The default options to be extended.
|
281 |
+
*
|
282 |
* 1. The array of options
|
283 |
+
*
|
284 |
* - `wprss_help_template_path` - The path of template retrieved by WPRSS_Help::get_template().
|
285 |
+
*
|
286 |
* 1. The path to the template.
|
287 |
* 2. The array of variables passed.
|
288 |
+
*
|
289 |
* - `wprss_help_template_vars` - The variables for the template, received by WPRSS_Help::get_template().
|
290 |
*
|
291 |
* 1. The variables array.
|
292 |
* 2. The path to the template, filtered by `wprss_help_template_path`.
|
293 |
+
*
|
294 |
* - `wprss_help_tooltip_options` - Options that are in effect when adding tooltips with WPRSS_Help::add_tooltip().
|
295 |
* - `wprss_help_tooltip_handle_html_options` - Options that are in effect when retrieving tooltip handle HTML with WPRSS_Help::wprss_help_tooltip_handle_html_options.
|
296 |
+
*
|
297 |
+
*
|
298 |
* Also, the following options are available:
|
299 |
+
*
|
300 |
* - `tooltip_id_prefix` - The HTML element ID prefix that will be used for tooltips.
|
301 |
* - `tooltip_handle_text` - The text that will appear inside the handle HTML elements.
|
302 |
* - `tooltip_handle_class` - The CSS class that will be assigned to tooltip handles.
|
303 |
* - `tooltip_content_class` - The CSS class that will be assigned to tooltip content HTML elements.
|
304 |
* - `enqueue_tooltip_content` - Whether or not content is to be enqueued, instead of being output directly.
|
305 |
+
*
|
306 |
* 1. The absolute path to the core plugin directory
|
307 |
*/
|
308 |
class WPRSS_Help {
|
309 |
|
310 |
static $_instance;
|
311 |
+
|
312 |
protected $_options;
|
313 |
protected $_enqueued_tooltip_content = array();
|
314 |
protected $_tooltips = array();
|
319 |
const TEXT_DOMAIN = WPRSS_TEXT_DOMAIN;
|
320 |
const HASHING_CONCATENATOR = '|';
|
321 |
const OPTIONS_FILTER_SUFFIX = '_options';
|
322 |
+
|
323 |
const TOOLTIP_DATA_KEY_ID = 'id';
|
324 |
const TOOLTIP_DATA_KEY_TEXT = 'text';
|
325 |
const TOOLTIP_DATA_KEY_OPTIONS = 'options';
|
326 |
|
327 |
/**
|
328 |
* Retrieve the singleton instance
|
329 |
+
*
|
330 |
* @return WPRSS_Help
|
331 |
*/
|
332 |
public static function get_instance() {
|
337 |
|
338 |
return self::$_instance;
|
339 |
}
|
340 |
+
|
341 |
|
342 |
public static function init() {
|
343 |
// Actions
|
344 |
add_action( 'admin_enqueue_scripts', array( self::get_instance(), '_admin_enqueue_scripts' ) );
|
345 |
add_action( 'admin_footer', array( self::get_instance(), '_admin_footer' ) );
|
346 |
}
|
347 |
+
|
348 |
|
349 |
/**
|
350 |
* Filters used:
|
351 |
+
*
|
352 |
* - `wprss_help_default_options`
|
353 |
+
*
|
354 |
* @param array $options Options that will overwrite defaults.
|
355 |
*/
|
356 |
public function __construct( $options = array() ) {
|
373 |
|
374 |
$this->_construct();
|
375 |
}
|
376 |
+
|
377 |
|
378 |
/**
|
379 |
* Used for parameter-less extension of constructor logic
|
380 |
*/
|
381 |
protected function _construct() {
|
382 |
+
|
383 |
}
|
384 |
+
|
385 |
|
386 |
/**
|
387 |
* Return an option value, or the whole array of internal options.
|
388 |
* These options are a product of the defaults, the database, and anything
|
389 |
* set later on, applied on top of eachother and overwriting in that order.
|
390 |
+
*
|
391 |
* @param null|string $key The key of the option to return.
|
392 |
* @param null|mixed $default What to return if options with the specified key not found.
|
393 |
* @return array|mixed|null The option value, or an array of options.
|
398 |
if ( is_null( $key ) ) {
|
399 |
return $options;
|
400 |
}
|
401 |
+
|
402 |
if( is_array( $key ) ) {
|
403 |
return $this->array_merge_recursive_distinct( $options, $key );
|
404 |
}
|
405 |
|
406 |
return isset( $options[ $key ] ) ? $options[ $key ] : $default;
|
407 |
}
|
408 |
+
|
409 |
|
410 |
/**
|
411 |
* Set the value of an internal option or options.
|
412 |
* Existing options will be overwritten. New options will be added.
|
413 |
* Database options will not be modified.
|
414 |
+
*
|
415 |
* @param string|array $key The key of the option to set, or an array of options.
|
416 |
* @param null|mixed $value The value of the option to set.
|
417 |
* @return WPRSS_Help This instance.
|
427 |
|
428 |
$this->_set_options( $key, $value );
|
429 |
}
|
430 |
+
|
431 |
|
432 |
/**
|
433 |
* Set an option value, or all options.
|
434 |
* In latter case completely overrides the whole options array.
|
435 |
+
*
|
436 |
* @param string|array $key The key of the option to set, or the whole options array.
|
437 |
* @param null|mixed $value Value of the option to set.
|
438 |
* @return WPRSS_Help This instance.
|
446 |
$this->_options[ $key ] = $value;
|
447 |
return $this;
|
448 |
}
|
449 |
+
|
450 |
|
451 |
/**
|
452 |
* Returns a WPRSS_Help option or options from the database.
|
453 |
+
*
|
454 |
* @param string $key The key of the option to return.
|
455 |
* @param null|mixed $default What to return if option identified by $key is not found.
|
456 |
* @return null|array|mixed The options or option value.
|
464 |
|
465 |
return isset( $options[ $key ] ) ? $options[ $key ] : $default;
|
466 |
}
|
467 |
+
|
468 |
|
469 |
/**
|
470 |
* Get content of a template.
|
471 |
+
*
|
472 |
* Filters used
|
473 |
+
*
|
474 |
* - `wprss_help_template_path`
|
475 |
* - `wprss_help_template_vars`
|
476 |
+
*
|
477 |
* @param string $path Full path to the template
|
478 |
* @param array $vars This will be passed to the template
|
479 |
*/
|
491 |
|
492 |
return $content;
|
493 |
}
|
494 |
+
|
495 |
|
496 |
/**
|
497 |
* This is called during the `admin_enqueue_scripts` action, and will
|
498 |
* enqueue scripts needed for the backend.
|
499 |
+
*
|
500 |
* Filters used:
|
501 |
+
*
|
502 |
* - `wprss_help_admin_scripts`
|
503 |
+
*
|
504 |
* @return WPRSS_Help This instance.
|
505 |
*/
|
506 |
public function _admin_enqueue_scripts() {
|
507 |
$scripts = $this->apply_filters( 'admin_scripts', array(
|
508 |
'jquery-ui-tooltip' => array()
|
509 |
));
|
510 |
+
|
511 |
foreach ( $scripts as $_handle => $_args ) {
|
512 |
// Allows numeric array with handles as values
|
513 |
if ( is_numeric( $_handle ) ) {
|
514 |
$_handle = $_args;
|
515 |
}
|
516 |
+
|
517 |
// Allows specifying null as value to simply enqueue handle
|
518 |
if ( empty( $_args ) ){
|
519 |
$_args = array();
|
520 |
}
|
521 |
+
|
522 |
array_unshift( $_args, $_handle );
|
523 |
call_user_func_array( 'wp_enqueue_script', $_args );
|
524 |
}
|
525 |
+
|
526 |
return $this;
|
527 |
}
|
528 |
+
|
529 |
+
|
530 |
public function _admin_footer() {
|
531 |
$html = '';
|
532 |
$html .= $this->get_enqueued_tooltip_content_html() . "\n";
|
533 |
$html .= $this->get_admin_footer_js_html();
|
534 |
$html = $this->apply_filters( 'admin_footer', $html );
|
535 |
+
|
536 |
echo $html;
|
537 |
}
|
538 |
+
|
539 |
+
|
540 |
public function is_overrides_default_prefix( $string ) {
|
541 |
return strpos( $string, self::OVERRIDE_DEFAULT_PREFIX ) === 0;
|
542 |
}
|
543 |
+
|
544 |
+
|
545 |
/**
|
546 |
* @return string This class's text domain
|
547 |
*/
|
548 |
public function get_text_domain() {
|
549 |
return self::TEXT_DOMAIN;
|
550 |
}
|
551 |
+
|
552 |
/**
|
553 |
* Format this string, replacing placeholders with values, and translate it
|
554 |
* in the class's text domain.
|
555 |
+
*
|
556 |
* @see sprintf()
|
557 |
* @param string $string The string to translate.
|
558 |
* @param mixed $argN,.. Additional arguments.
|
560 |
public function __( $string, $argN = null ) {
|
561 |
$args = func_get_args();
|
562 |
$args[0] = $string = __( $string, $this->get_text_domain() );
|
563 |
+
|
564 |
$string = call_user_func_array( 'sprintf', $args );
|
565 |
+
|
566 |
return $string;
|
567 |
}
|
568 |
+
|
569 |
/**
|
570 |
* Hashes all the given values into a single hash.
|
571 |
* Accepts an infinite number of parameters, all of which will be first
|
572 |
* glued together by a separator, then hashed.
|
573 |
* Non-scalar values will be serialized.
|
574 |
+
*
|
575 |
* @param mixed $value The value to hash.
|
576 |
* @param mixed $argN Other values to hash.
|
577 |
* @return string The hash.
|
579 |
public function get_hash( $value ) {
|
580 |
$args = func_get_args();
|
581 |
$glue = self::HASHING_CONCATENATOR;
|
582 |
+
|
583 |
$blob = '';
|
584 |
foreach ( $args as $_idx => $_arg ) {
|
585 |
$blob .= is_scalar( $_arg ) ? $_arg : serialize( $_arg );
|
586 |
$blob .= $glue;
|
587 |
}
|
588 |
+
|
589 |
$blob = substr( $blob, 0, -1 );
|
590 |
+
|
591 |
return sha1( $blob );
|
592 |
}
|
593 |
+
|
594 |
/**
|
595 |
* Get the class code prefix, or the specified prefixed with it.
|
596 |
+
*
|
597 |
* @param string $string A string to prefix.
|
598 |
* @return string The code prefix or the prefixed string.
|
599 |
*/
|
600 |
public function get_code_prefix( $string = '' ) {
|
601 |
return self::CODE_PREFIX . (string)$string;
|
602 |
}
|
603 |
+
|
604 |
/**
|
605 |
* Optionally prefix a string with the class code prefix, unless it
|
606 |
* contains the "!" character in the very beginning, in which case it will
|
607 |
* simply be removed.
|
608 |
+
*
|
609 |
* @param string $string The string to consider for prefixing.
|
610 |
* @return string The prefixed or clean string.
|
611 |
*/
|
614 |
? substr( $string, 1 )
|
615 |
: $this->get_code_prefix( $string );
|
616 |
}
|
617 |
+
|
618 |
/**
|
619 |
* Applies filters, but prefixes the filter name with 'wprss_help_',
|
620 |
* unless '!' is specified as the first character of the filter.
|
621 |
+
*
|
622 |
* @param string $filter_name Name or "tag" of the filter.
|
623 |
* @param mixed $subject The value to apply filters to.
|
624 |
* @param mixed $argN,.. Additional filter arguments
|
626 |
*/
|
627 |
public function apply_filters( $filter_name, $subject, $argN = null ) {
|
628 |
$args = func_get_args();
|
629 |
+
|
630 |
$args[0] = $filter_name = $this->prefix( $filter_name );
|
631 |
+
|
632 |
return call_user_func_array( 'apply_filters', $args );
|
633 |
}
|
634 |
+
|
635 |
+
|
636 |
/**
|
637 |
* Applies a filters with the specified name to the options that were
|
638 |
* applied on top of defaults.
|
639 |
* The name will be prefixed with the class prefix 'wprss_help_', and
|
640 |
* suffixed with '_options'.
|
641 |
+
*
|
642 |
* @param string $filter_name Name of the filter to apply to the options
|
643 |
* @param array $options The options to filter
|
644 |
* @param mixed $filter_argN,.. Other filter arguments to be passed to filter
|
645 |
*/
|
646 |
public function apply_options_filters( $filter_name, $options = array(), $filter_argN = null ) {
|
647 |
$args = func_get_args();
|
648 |
+
|
649 |
// Adding sufix
|
650 |
$args[0] = $filter_name .= self::OPTIONS_FILTER_SUFFIX;
|
651 |
+
|
652 |
// Applying defaults
|
653 |
$args[1] = $options = $this->get_options( $options );
|
654 |
+
|
655 |
// Entry point. Order of args is already correct.
|
656 |
$options = call_user_func_array( array( $this, 'apply_filters' ), $args );
|
657 |
+
|
658 |
return $options;
|
659 |
}
|
660 |
+
|
661 |
+
|
662 |
/**
|
663 |
* Parses the tooltip handle template path for placeholders.
|
664 |
+
*
|
665 |
* Filters used:
|
666 |
+
*
|
667 |
* - `wprss_help_admin_footer_js_html_template`
|
668 |
+
*
|
669 |
* @param null|string $path Optional path to parse and retrieve. Default: value of the 'admin_footer_js_template' option.
|
670 |
* @return string Path to the template.
|
671 |
*/
|
674 |
if ( is_null( $path ) ) {
|
675 |
$path = $this->get_options( 'admin_footer_js_template' );
|
676 |
}
|
677 |
+
|
678 |
// Entry point
|
679 |
$path = $this->apply_filters( 'admin_footer_js_html_template', $path );
|
680 |
+
|
681 |
return $this->parse_path( $path );
|
682 |
}
|
683 |
+
|
684 |
+
|
685 |
/**
|
686 |
* Get the HTML of the JavaScript for the footer in Admin Panel.
|
687 |
+
*
|
688 |
* Filters used:
|
689 |
+
*
|
690 |
* - `wprss_help_admin_footer_js_html`
|
691 |
+
*
|
692 |
* @param array $options Any additional options to be used with defaults.
|
693 |
* @return string The HTML.
|
694 |
*/
|
695 |
public function get_admin_footer_js_html( $options = array() ) {
|
696 |
$options = $this->apply_options_filters( 'admin_footer_js_html', $options);
|
697 |
+
|
698 |
$templatePath = $this->get_admin_footer_js_html_template( $options['admin_footer_js_template'] );
|
699 |
+
|
700 |
return $this->get_template($templatePath, $options);
|
701 |
}
|
702 |
+
|
703 |
+
|
704 |
/**
|
705 |
* Parses the tooltip handle template path for placeholders.
|
706 |
+
*
|
707 |
* Filters used:
|
708 |
+
*
|
709 |
* - `wprss_help_tooltip_handle_html_template`
|
710 |
+
*
|
711 |
* @param null|string $path Optional path to parse and retrieve. Default: value of the 'tooltip_handle_template' option.
|
712 |
* @return string Path to the template.
|
713 |
*/
|
716 |
if ( is_null( $path ) ) {
|
717 |
$path = $this->get_options( 'tooltip_handle_template' );
|
718 |
}
|
719 |
+
|
720 |
// Entry point
|
721 |
$path = $this->apply_filters( 'tooltip_handle_html_template', $path );
|
722 |
+
|
723 |
return $this->parse_path( $path );
|
724 |
}
|
725 |
+
|
726 |
+
|
727 |
/**
|
728 |
* Get the HTML of the tooltip handle.
|
729 |
+
*
|
730 |
* Filters used:
|
731 |
+
*
|
732 |
* - `wprss_help_tooltip_handle_html_options`
|
733 |
+
*
|
734 |
* @param string $text Content of the tooltip text.
|
735 |
* @param string $id ID of the tooltip.
|
736 |
* @param array $options Any additional options to be used with defaults.
|
742 |
// Add template varialbes
|
743 |
$options['tooltip_id'] = $id;
|
744 |
$options['tooltip_text'] = $text;
|
745 |
+
|
746 |
$templatePath = $this->get_tooltip_handle_html_template( $options['tooltip_handle_template'] );
|
747 |
+
|
748 |
return $this->get_template($templatePath, $options);
|
749 |
}
|
750 |
+
|
751 |
+
|
752 |
/**
|
753 |
* Parses the tooltip content template path for placeholders.
|
754 |
+
*
|
755 |
* Filters used:
|
756 |
+
*
|
757 |
* - `wprss_help_tooltip_content_html_template`
|
758 |
+
*
|
759 |
* @param null|string $path Optional path to parse and retrieve. Default: value of the 'tooltip_handle_template' option.
|
760 |
* @return string Path to the template.
|
761 |
*/
|
764 |
if ( is_null( $path ) ) {
|
765 |
$path = $this->get_options( 'tooltip_content_template' );
|
766 |
}
|
767 |
+
|
768 |
// Entry point
|
769 |
$path = $this->apply_filters( 'tooltip_content_html_template', $path );
|
770 |
+
|
771 |
return $this->parse_path( $path );
|
772 |
}
|
773 |
+
|
774 |
+
|
775 |
/**
|
776 |
* Get the HTML of the tooltip content.
|
777 |
+
*
|
778 |
* Filters used:
|
779 |
+
*
|
780 |
* - `wprss_help_tooltip_content_html_options`
|
781 |
+
*
|
782 |
* @param string $text Content of the tooltip text.
|
783 |
* @param string $id ID of the tooltip.
|
784 |
* @param array $options Any additional options to be used with defaults.
|
786 |
*/
|
787 |
public function get_tooltip_content_html( $text, $id, $options = array() ) {
|
788 |
$options = $this->apply_options_filters( 'tooltip_content_html', $options, $text, $id );
|
789 |
+
|
790 |
// Add template varialbes
|
791 |
$options['tooltip_id'] = $id;
|
792 |
$options['tooltip_text'] = $text;
|
793 |
+
|
794 |
$templatePath = $this->get_tooltip_content_html_template( $options['tooltip_content_template'] );
|
795 |
+
|
796 |
return $this->get_template( $templatePath, $options );
|
797 |
}
|
798 |
+
|
799 |
+
|
800 |
/**
|
801 |
* Add tooltip and get tooltip HTML.
|
802 |
* If $text is null, just get the HTML of tooltip with specified ID.
|
803 |
* The `is_enqueue_tooltip_content` option determines whether to enqueue
|
804 |
* the content, instead of outputting it after the handle.
|
805 |
+
*
|
806 |
* @param string $id ID for this tooltip
|
807 |
* @param string|null $text Text of this tooltip. If null, tooltip will not be added, but only retrieved.
|
808 |
* @param array|bool $options The options for this operation, or a boolean indicating whether or not content is to be enqueued
|
812 |
$this->add_tooltip( $id, $text, $options );
|
813 |
return $this->do_tooltip( $id );
|
814 |
}
|
815 |
+
|
816 |
+
|
817 |
/**
|
818 |
* Add tooltips in a batch, with optionally prefixed ID.
|
819 |
+
*
|
820 |
* @param array $tooltips An array where key is tooltip ID and value is tooltip text.
|
821 |
* @param string $prefix A prefix to add to all tooltip IDs.
|
822 |
* @param array $options Arra of options for all the tooltips to add.
|
825 |
public function add_tooltips( $tooltips, $prefix = null, $options = array() ) {
|
826 |
$prefix = (string) $prefix;
|
827 |
if ( !is_array($options) ) $options = array();
|
828 |
+
|
829 |
foreach ( $tooltips as $_id => $_text ) {
|
830 |
$this->add_tooltip( $prefix . $_id, $_text, $options );
|
831 |
}
|
832 |
+
|
833 |
return $this;
|
834 |
}
|
835 |
+
|
836 |
+
|
837 |
/**
|
838 |
* Add a tooltip for later display.
|
839 |
* Text and options will be replaced by existing text and options, if they
|
840 |
* are empty, and a tooltip with the same ID is already registered.
|
841 |
+
*
|
842 |
* @param string $id The ID of this tooltip
|
843 |
* @param string $text Text for this tooltip
|
844 |
* @param array $options Options for this tooltip.
|
849 |
if ( is_null( $text ) ) $text = isset( $tooltip[ self::TOOLTIP_DATA_KEY_TEXT ] ) ? $tooltip[ self::TOOLTIP_DATA_KEY_TEXT ] : $text;
|
850 |
if ( empty( $options ) ) $options = isset( $tooltip[ self::TOOLTIP_DATA_KEY_OPTIONS ] ) ? $tooltip[ self::TOOLTIP_DATA_KEY_OPTIONS ] : $options;
|
851 |
}
|
852 |
+
|
853 |
$this->set_tooltip( $id, $text, $options );
|
854 |
+
|
855 |
return $this;
|
856 |
}
|
857 |
+
|
858 |
+
|
859 |
/**
|
860 |
* Set a tooltip, existing or not.
|
861 |
+
*
|
862 |
* @param string $id The ID of this tooltip
|
863 |
* @param string $text Text for this tooltip
|
864 |
* @param array $options Options for this tooltip.
|
870 |
self::TOOLTIP_DATA_KEY_TEXT => $text,
|
871 |
self::TOOLTIP_DATA_KEY_OPTIONS => $options
|
872 |
);
|
873 |
+
|
874 |
return $this;
|
875 |
}
|
876 |
+
|
877 |
+
|
878 |
/**
|
879 |
* Retrieve one tooltip, or an array containing all tooltips.
|
880 |
+
*
|
881 |
* @param string|null $id The ID of the tooltip to retrieve.
|
882 |
* @param mixed|null $default What to return if tooltip with specified ID not found.
|
883 |
* @return array An array that contains the following indexes: 'id', 'text', 'options'. See {@link add_tooltip()} for details.
|
886 |
if ( is_null( $id ) ) {
|
887 |
return $this->_tooltips;
|
888 |
}
|
889 |
+
|
890 |
return $this->has_tooltip( $id ) ? $this->_tooltips[ $id ] : $default;
|
891 |
}
|
892 |
+
|
893 |
+
|
894 |
/**
|
895 |
* Check whether a tooltip with the specified ID exists.
|
896 |
+
*
|
897 |
* @param string $id ID of the tooltip to check for.
|
898 |
* @return boolean True if a tooltip with the specified ID exists; false otherwise.
|
899 |
*/
|
900 |
public function has_tooltip( $id ) {
|
901 |
return isset( $this->_tooltips[ $id ] );
|
902 |
}
|
903 |
+
|
904 |
/**
|
905 |
* Get registered tooltip HTML.
|
906 |
+
*
|
907 |
* Filters used:
|
908 |
+
*
|
909 |
* - `wprss_help_tooltip_options` - Filters options used for tooltip
|
910 |
+
*
|
911 |
* @param string $id ID for this tooltip
|
912 |
* @param string $text Text of this tooltip
|
913 |
* @param array|bool $options The options for this operation, or a boolean indicating whether or not content is to be enqueued
|
915 |
*/
|
916 |
public function do_tooltip( $id ) {
|
917 |
$options = $this->get_options();
|
918 |
+
|
919 |
if ( !($tooltip = $this->get_tooltip( $id )) || !isset($tooltip[ self::TOOLTIP_DATA_KEY_TEXT ]) || !$tooltip[ self::TOOLTIP_DATA_KEY_TEXT ] ) {
|
920 |
return isset( $options['tooltip_not_found_handle_html'] )
|
921 |
? $options['tooltip_not_found_handle_html']
|
922 |
: null;
|
923 |
}
|
924 |
+
|
925 |
$options = isset( $tooltip[ self::TOOLTIP_DATA_KEY_OPTIONS ] ) ? $tooltip[ self::TOOLTIP_DATA_KEY_OPTIONS ] : null;
|
926 |
$text = isset( $tooltip[ self::TOOLTIP_DATA_KEY_TEXT ] ) ? $tooltip[ self::TOOLTIP_DATA_KEY_TEXT ] : null;
|
927 |
+
|
928 |
if ( !is_array( $options ) ) {
|
929 |
$options = array( 'is_enqueue_tooltip_content' => $options );
|
930 |
}
|
931 |
+
|
932 |
// Entry point
|
933 |
$options = $this->apply_options_filters( 'tooltip', $options, $id, $text );
|
934 |
+
|
935 |
// Get handle HTML
|
936 |
$output = $this->get_tooltip_handle_html( $text, $id, $options );
|
937 |
+
|
938 |
if ( $this->evaluate_boolean( $options['is_enqueue_tooltip_content'] ) ) {
|
939 |
$this->enqueue_tooltip_content($text, $id, $options);
|
940 |
}
|
941 |
else {
|
942 |
$output .= $this->get_tooltip_content_html( $text, $id, $options );
|
943 |
}
|
944 |
+
|
945 |
return $output;
|
946 |
}
|
947 |
+
|
948 |
+
|
949 |
/**
|
950 |
* Enqueue tooltip content to be displayed in another part of the page.
|
951 |
+
*
|
952 |
* @param string $text The text of the tooltip content to enqueue.
|
953 |
* @param string $id ID of the tooltip, the content of which to enqueue.
|
954 |
* @param array $options This tooltip's options.
|
956 |
*/
|
957 |
public function enqueue_tooltip_content( $text, $id, $options = array() ) {
|
958 |
$queue_method = $this->apply_filters( 'enqueue_tooltip_content_method', array( $this, '_enqueue_tooltip_content' ), $options, $id, $text );
|
959 |
+
|
960 |
// "Error handling" WP style
|
961 |
if ( !is_callable( $queue_method ) ) {
|
962 |
return new WP_Error( $this->prefix( 'invalid_queue_method' ), $this->__( 'Could not enqueue tooltip content: the queue method is not a valid callable.' ), array(
|
966 |
'options' => $options
|
967 |
));
|
968 |
}
|
969 |
+
|
970 |
call_user_func_array( $queue_method, array( $text, $id, $options ) );
|
971 |
+
|
972 |
return $this;
|
973 |
}
|
974 |
+
|
975 |
+
|
976 |
public function _enqueue_tooltip_content( $text, $id, $options = array() ) {
|
977 |
$hash = $this->get_hash( $text, $id, $options );
|
978 |
$this->_enqueued_tooltip_content[ $hash ] = array(
|
980 |
self::TOOLTIP_DATA_KEY_ID => $id,
|
981 |
self::TOOLTIP_DATA_KEY_OPTIONS => $options
|
982 |
);
|
983 |
+
|
984 |
return $this;
|
985 |
}
|
986 |
+
|
987 |
+
|
988 |
public function get_enqueued_tooltip_content() {
|
989 |
return $this->_enqueued_tooltip_content;
|
990 |
}
|
991 |
+
|
992 |
+
|
993 |
public function get_enqueued_tooltip_content_html() {
|
994 |
$output = '';
|
995 |
foreach ( $this->get_enqueued_tooltip_content() as $_hash => $_vars ) {
|
996 |
$options = is_array( $_vars[ self::TOOLTIP_DATA_KEY_OPTIONS ] ) ? $_vars[ self::TOOLTIP_DATA_KEY_OPTIONS ] : array();
|
997 |
$output = $this->get_tooltip_content_html( $_vars[ self::TOOLTIP_DATA_KEY_ID ], $_vars[ self::TOOLTIP_DATA_KEY_ID ], $options );
|
998 |
}
|
999 |
+
|
1000 |
echo $output;
|
1001 |
}
|
1002 |
+
|
1003 |
+
|
1004 |
/**
|
1005 |
* Check whether or not the given value is false.
|
1006 |
* False values are all {@link empty()} values, and also strings 'false' and 'no'.
|
1007 |
+
*
|
1008 |
* @param mixed $value The value to check.
|
1009 |
* @return boolean Whether or not the value is considered to be false.
|
1010 |
*/
|
1013 |
? false
|
1014 |
: true;
|
1015 |
}
|
1016 |
+
|
1017 |
|
1018 |
/**
|
1019 |
* Merge two arrays in an intuitive way.
|
1020 |
* Input arrays remain unchanged.
|
1021 |
+
*
|
1022 |
* @see http://php.net/manual/en/function.array-merge-recursive.php#92195
|
1023 |
* @param array $array1 The array to merge.
|
1024 |
* @param array $array2 The array to merge into.
|
1037 |
|
1038 |
return $merged;
|
1039 |
}
|
1040 |
+
|
1041 |
+
|
1042 |
/**
|
1043 |
* Converts an array to a numeric array.
|
1044 |
* If $map is empty, assumes that the array keys are already in order.
|
1045 |
* If $map is a number, assumes it's the amount of elements to return.
|
1046 |
* If $map is an array, assumes it is the map of intended numeric indexes to their value in the input array.
|
1047 |
+
*
|
1048 |
* @param array $array The array to convert to a numeric array
|
1049 |
* @param false|null|array $map The map of the array indexes, or number of array elements to slice, or nothing.
|
1050 |
* @return array The resulting numeric array.
|
1051 |
*/
|
1052 |
public function array_to_numeric( $array, $map = null ) {
|
1053 |
$result = array();
|
1054 |
+
|
1055 |
// If map is not an array, assume it's an indicator
|
1056 |
if ( !is_array( $map ) ) {
|
1057 |
$array = array_values( $array );
|
1058 |
}
|
1059 |
+
|
1060 |
// If map is empty, assume keys are in order
|
1061 |
if ( empty( $map ) ) {
|
1062 |
return $array;
|
1063 |
}
|
1064 |
+
|
1065 |
// If map is a number, assume it's the amount of elements to return
|
1066 |
if ( is_numeric( $map ) ) {
|
1067 |
$map = intval( $map );
|
1068 |
return array_slice( $array, 0, $map );
|
1069 |
}
|
1070 |
+
|
1071 |
foreach( $map as $_idx => $_key ) {
|
1072 |
$result[ $_idx ] = $array[ $_key ];
|
1073 |
}
|
1074 |
+
|
1075 |
return $result;
|
1076 |
}
|
1077 |
+
|
1078 |
+
|
1079 |
/**
|
1080 |
* Parses the template and replaces placeholders with their values.
|
1081 |
* This function uses {@see sprintf()} to format the template string using
|
1082 |
* the values provided in $data.
|
1083 |
* It is also possible for $data to be an associative array of key-value pairs.
|
1084 |
+
* To achieve the same result, a map can be provided, mapping data keys to
|
1085 |
* their placeholder positions.
|
1086 |
+
* If no map is provided,
|
1087 |
+
*
|
1088 |
* @param string $string The template string.
|
1089 |
* @param array $data The key-value pairs of template data.
|
1090 |
* @param false|null|array $map {@see array_to_numeric()} The template value map.
|
1095 |
array_unshift( $data, $string );
|
1096 |
return call_user_func_array( 'sprintf', $data );
|
1097 |
}
|
1098 |
+
|
1099 |
+
|
1100 |
/**
|
1101 |
* Parses a path template specifically with WPRSS_Help path placeholders.
|
1102 |
+
*
|
1103 |
* Filters used (in order):
|
1104 |
+
*
|
1105 |
* 1. `parse_path_data_default`;
|
1106 |
* 2. `parse_path_data`;
|
1107 |
* 3. `parse_path_map`;
|
1108 |
* 4. `parse_path_path`.
|
1109 |
+
*
|
1110 |
* @see WPRSS_Help::parse_template()
|
1111 |
* @param string $path The path to parse.
|
1112 |
* @param null|array $data Any additional data. Will be merged with defaults.
|
1117 |
if( is_null( $data ) ) {
|
1118 |
$data = array();
|
1119 |
}
|
1120 |
+
|
1121 |
$defaults = $this->apply_filters( 'parse_path_data_default', array(
|
1122 |
'wprss_templates_dir' => wprss_get_templates_dir()
|
1123 |
));
|
1125 |
$data = $this->apply_filters( 'parse_path_data', $data, $path, $map );
|
1126 |
$map = $this->apply_filters( 'parse_path_map', $map, $data, $path );
|
1127 |
$path = $this->apply_filters( 'parse_path_path', $path, $data, $map );
|
1128 |
+
|
1129 |
return $this->parse_template( $path, $data, $map );
|
1130 |
}
|
1131 |
}
|
includes/admin-log.php
CHANGED
@@ -203,6 +203,30 @@
|
|
203 |
}
|
204 |
|
205 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
/**
|
207 |
* Adds an empty line at the end of the log file.
|
208 |
*
|
203 |
}
|
204 |
|
205 |
|
206 |
+
/**
|
207 |
+
* Downloads the log file.
|
208 |
+
*
|
209 |
+
* @since 4.7.8
|
210 |
+
*/
|
211 |
+
function wprss_download_log() {
|
212 |
+
if ( !file_exists( wprss_log_file() ) ) {
|
213 |
+
wprss_clear_log();
|
214 |
+
}
|
215 |
+
else {
|
216 |
+
$file = wprss_log_file();
|
217 |
+
header( 'Content-Description: File Transfer' );
|
218 |
+
header( 'Content-type: text/plain' );
|
219 |
+
header( 'Content-Disposition: attachment; filename="error-log.txt"' );
|
220 |
+
header( 'Expires: 0' );
|
221 |
+
header( 'Cache-Control: must-revalidate' );
|
222 |
+
header( 'Pragma: public' );
|
223 |
+
header( 'Content-Length: ' . filesize( $file ) );
|
224 |
+
readfile( $file );
|
225 |
+
exit;
|
226 |
+
}
|
227 |
+
}
|
228 |
+
|
229 |
+
|
230 |
/**
|
231 |
* Adds an empty line at the end of the log file.
|
232 |
*
|
includes/admin-options.php
CHANGED
@@ -258,7 +258,12 @@
|
|
258 |
);
|
259 |
*/
|
260 |
|
261 |
-
|
|
|
|
|
|
|
|
|
|
|
262 |
|
263 |
do_action( 'wprss_admin_init' );
|
264 |
}
|
258 |
);
|
259 |
*/
|
260 |
|
261 |
+
//If user requested to download system info, generate the download.
|
262 |
+
if ( isset( $_POST['wprss-sysinfo'] ) )
|
263 |
+
do_action( 'wprss_download_sysinfo' );
|
264 |
+
if ( isset( $_POST['wprss-sysinfo'] ) ) {
|
265 |
+
// do_action( 'wprss_download_log' );
|
266 |
+
}
|
267 |
|
268 |
do_action( 'wprss_admin_init' );
|
269 |
}
|
includes/autoload.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if (!function_exists('wprss_autoloader')) {
|
4 |
+
/**
|
5 |
+
*
|
6 |
+
* @return Aventura\Wprss\Core\Loader The loader singleton instance
|
7 |
+
*/
|
8 |
+
function wprss_autoloader() {
|
9 |
+
static $loader = null;
|
10 |
+
$className = 'Aventura\\Wprss\\Core\\Loader';
|
11 |
+
if (!class_exists($className)){
|
12 |
+
$dir = dirname(__FILE__);
|
13 |
+
$classPath = str_replace('\\', DIRECTORY_SEPARATOR, $className);
|
14 |
+
$classPath = "{$dir}/{$classPath}.php";
|
15 |
+
require_once($classPath);
|
16 |
+
}
|
17 |
+
|
18 |
+
if ($loader === null) {
|
19 |
+
$loader = new $className();
|
20 |
+
/* @var $loader Aventura\Wprss\Core\Loader */
|
21 |
+
$loader->register();
|
22 |
+
}
|
23 |
+
|
24 |
+
return $loader;
|
25 |
+
}
|
26 |
+
}
|
includes/feed-importing.php
CHANGED
@@ -4,14 +4,14 @@
|
|
4 |
*
|
5 |
* @package WPRSSAggregator
|
6 |
*/
|
7 |
-
|
8 |
|
9 |
// Warning: Order may be important
|
10 |
add_filter('wprss_normalize_permalink', 'wprss_google_news_url_fix', 8);
|
11 |
add_filter('wprss_normalize_permalink', 'wprss_bing_news_url_fix', 9);
|
12 |
add_filter('wprss_normalize_permalink', 'wprss_google_alerts_url_fix', 10);
|
13 |
add_filter('wprss_normalize_permalink', 'wprss_convert_video_permalink', 100);
|
14 |
-
|
15 |
|
16 |
add_action( 'wprss_fetch_single_feed_hook', 'wprss_fetch_insert_single_feed_items' );
|
17 |
/**
|
@@ -40,7 +40,7 @@
|
|
40 |
delete_post_meta( $feed_ID, 'wprss_force_next_fetch' );
|
41 |
wprss_log( 'Force feed flag removed', null, WPRSS_LOG_LEVEL_SYSTEM );
|
42 |
}
|
43 |
-
|
44 |
$start_of_update = wprss_flag_feed_as_updating( $feed_ID );
|
45 |
wprss_log_obj( 'Start of import time updated', date( 'Y-m-d H:i:s', $start_of_update), null, WPRSS_LOG_LEVEL_SYSTEM );
|
46 |
|
@@ -53,7 +53,7 @@
|
|
53 |
// Get the feed limit from post meta
|
54 |
$feed_limit = get_post_meta( $feed_ID, 'wprss_limit', true );
|
55 |
wprss_log_obj( 'Feed limit value is', $feed_limit, null, WPRSS_LOG_LEVEL_SYSTEM );
|
56 |
-
|
57 |
// If the feed has no individual limit
|
58 |
if ( $feed_limit === '' || intval( $feed_limit ) <= 0 ) {
|
59 |
wprss_log_obj( 'Using global limit', $feed_limit, null, WPRSS_LOG_LEVEL_NOTICE );
|
@@ -141,17 +141,17 @@
|
|
141 |
} else {
|
142 |
wprss_log( 'Items to import remained untouched. Not items already exist or are blacklisted.', null, WPRSS_LOG_LEVEL_SYSTEM );
|
143 |
}
|
144 |
-
|
145 |
$items_to_insert = $new_items;
|
146 |
|
147 |
// If using a limit - delete any excess items to make room for the new items
|
148 |
if ( $feed_limit !== NULL ) {
|
149 |
wprss_log_obj( 'Some items may be deleted due to limit', $feed_limit, null, WPRSS_LOG_LEVEL_SYSTEM );
|
150 |
-
|
151 |
// Get the number of feed items in DB, and their count
|
152 |
$db_feed_items = wprss_get_feed_items_for_source( $feed_ID );
|
153 |
$num_db_feed_items = $db_feed_items->post_count;
|
154 |
-
|
155 |
// Get the number of feed items we can store until we reach the limit
|
156 |
$num_can_insert = $feed_limit - $num_db_feed_items;
|
157 |
// Calculate how many feed items we must delete before importing, to keep to the limit
|
@@ -170,11 +170,11 @@
|
|
170 |
foreach ( $feed_items_to_delete as $key => $post ) {
|
171 |
wp_delete_post( $post->ID, TRUE );
|
172 |
}
|
173 |
-
|
174 |
if ( $deleted_items_count = count( $feed_items_to_delete ) )
|
175 |
wprss_log_obj( 'Items deleted due to limit', $deleted_items_count, null, WPRSS_LOG_LEVEL_NOTICE );
|
176 |
}
|
177 |
-
|
178 |
update_post_meta( $feed_ID, 'wprss_last_update', $last_update_time = time() );
|
179 |
update_post_meta( $feed_ID, 'wprss_last_update_items', 0 );
|
180 |
wprss_log_obj( 'Last import time updated', $last_update_time, null, WPRSS_LOG_LEVEL_SYSTEM );
|
@@ -187,9 +187,9 @@
|
|
187 |
} else {
|
188 |
wprss_log_obj('The feed URL is not valid! Please recheck', $feed_url);
|
189 |
}
|
190 |
-
|
191 |
$next_scheduled = get_post_meta( $feed_ID, 'wprss_reschedule_event', TRUE );
|
192 |
-
|
193 |
if ( $next_scheduled !== '' ) {
|
194 |
wprss_feed_source_update_start_schedule( $feed_ID );
|
195 |
delete_post_meta( $feed_ID, 'wprss_reschedule_event' );
|
@@ -219,7 +219,7 @@
|
|
219 |
// Remove previously added filters and actions
|
220 |
remove_action( 'wp_feed_options', 'wprss_do_not_cache_feeds' );
|
221 |
remove_filter( 'wp_feed_cache_transient_lifetime' , 'wprss_feed_cache_lifetime' );
|
222 |
-
|
223 |
if ( !is_wp_error( $feed ) ) {
|
224 |
// Return the items in the feed.
|
225 |
return $feed->get_items();
|
@@ -260,7 +260,7 @@
|
|
260 |
$feed->force_feed( TRUE );
|
261 |
}
|
262 |
}
|
263 |
-
|
264 |
// Set timeout limit
|
265 |
$fetch_time_limit = wprss_get_feed_fetch_time_limit();
|
266 |
$feed->set_timeout( $fetch_time_limit );
|
@@ -277,11 +277,11 @@
|
|
277 |
$feed->strip_htmltags( $tags_to_strip );
|
278 |
|
279 |
do_action( 'wprss_fetch_feed_before', $feed );
|
280 |
-
|
281 |
// Fetch the feed
|
282 |
$feed->init();
|
283 |
$feed->handle_content_type();
|
284 |
-
|
285 |
do_action( 'wprss_fetch_feed_after', $feed );
|
286 |
|
287 |
// Convert the feed error into a WP_Error, if applicable
|
@@ -312,33 +312,33 @@
|
|
312 |
// Return the normalized permalink
|
313 |
return $permalink;
|
314 |
}
|
315 |
-
|
316 |
-
|
317 |
/**
|
318 |
* Extracts the actual URL from a Google News permalink
|
319 |
-
*
|
320 |
* @param string $permalink The permalink to normalize.
|
321 |
* @since 4.2.3
|
322 |
*/
|
323 |
function wprss_google_news_url_fix($permalink) {
|
324 |
return wprss_tracking_url_fix($permalink, '!^(https?:\/\/)?' . preg_quote('news.google.com', '!') . '.*!');
|
325 |
}
|
326 |
-
|
327 |
-
|
328 |
/**
|
329 |
* Extracts the actual URL from a Google Alerts permalink
|
330 |
-
*
|
331 |
* @param string $permalink The permalink to normalize.
|
332 |
* @since 4.7.3
|
333 |
*/
|
334 |
function wprss_google_alerts_url_fix($permalink) {
|
335 |
return wprss_tracking_url_fix($permalink, '!^(https?:\/\/)?(www\.)?' . preg_quote('google.com/url', '!') . '.*!');
|
336 |
}
|
337 |
-
|
338 |
|
339 |
/**
|
340 |
* Extracts the actual URL from a Bing permalink
|
341 |
-
*
|
342 |
* @param string $permalink The permalink to normalize.
|
343 |
* @since 4.2.3
|
344 |
*/
|
@@ -355,7 +355,7 @@
|
|
355 |
* Fixes the issue with equivalent Google News etc. items having
|
356 |
* different URLs, that contain randomly generated GET parameters.
|
357 |
* Example:
|
358 |
-
*
|
359 |
* http://news.google.com/news/url?sa=t&fd=R&ct2=us&ei=V3e9U6izMMnm1QaB1YHoDA&url=http://abcd...
|
360 |
* http://news.google.com/news/url?sa=t&fd=R&ct2=us&ei=One9U-HQLsTp1Aal-oDQBQ&url=http://abcd...
|
361 |
*
|
@@ -370,7 +370,7 @@
|
|
370 |
// Parse the url
|
371 |
$parsed = parse_url( urldecode( html_entity_decode( $permalink ) ) );
|
372 |
$patterns = is_array($patterns) ? $patterns :array($patterns);
|
373 |
-
|
374 |
// If parsing failed, return the permalink
|
375 |
if ( $parsed === FALSE || $parsed === NULL ) return $permalink;
|
376 |
|
@@ -382,19 +382,19 @@
|
|
382 |
break;
|
383 |
}
|
384 |
}
|
385 |
-
|
386 |
if( !$isMatch ) return $permalink;
|
387 |
-
|
388 |
// Check if the url GET query string is present
|
389 |
if ( !isset( $parsed['query'] ) ) return $permalink;
|
390 |
-
|
391 |
// Parse the query string
|
392 |
$query = array();
|
393 |
parse_str( $parsed['query'], $query );
|
394 |
-
|
395 |
// Check if the url GET parameter is present in the query string
|
396 |
if ( !is_array($query) || !isset( $query[$argName] ) ) return $permalink;
|
397 |
-
|
398 |
return urldecode( $query[$argName] );
|
399 |
}
|
400 |
|
@@ -415,12 +415,12 @@
|
|
415 |
|
416 |
// If video host was found
|
417 |
if ( $found_video_host !== 0 && $found_video_host !== FALSE ) {
|
418 |
-
|
419 |
// Get general options
|
420 |
$options = get_option( 'wprss_settings_general' );
|
421 |
// Get the video link option entry, or false if it does not exist
|
422 |
$video_link = ( isset($options['video_link']) )? $options['video_link'] : 'false';
|
423 |
-
|
424 |
// If the video link option is true, change the video URL to its repective host's embedded
|
425 |
// video player URL. Otherwise, leave the permalink as is.
|
426 |
if ( strtolower( $video_link ) === 'true' ) {
|
@@ -454,7 +454,7 @@
|
|
454 |
function wprss_items_insert_post( $items, $feed_ID ) {
|
455 |
update_post_meta( $feed_ID, 'wprss_feed_is_updating', $update_started_at = time() );
|
456 |
wprss_log_obj( 'Starting import of items for feed ' . $feed_ID, $update_started_at, null, WPRSS_LOG_LEVEL_INFO );
|
457 |
-
|
458 |
// Gather the permalinks of existing feed item's related to this feed source
|
459 |
$existing_permalinks = wprss_get_existing_permalinks( $feed_ID );
|
460 |
|
@@ -505,7 +505,7 @@
|
|
505 |
// If the item is not NULL, continue to inserting the feed item post into the DB
|
506 |
if ( $item !== NULL && !is_bool($item) ) {
|
507 |
wprss_log( 'Using core logic', null, WPRSS_LOG_LEVEL_SYSTEM );
|
508 |
-
|
509 |
// Get the date and GTM date and normalize if not valid dor not present
|
510 |
$format = 'Y-m-d H:i:s';
|
511 |
$has_date = $item->get_date( 'U' ) ? TRUE : FALSE;
|
@@ -520,20 +520,20 @@
|
|
520 |
'post_content' => '',
|
521 |
'post_status' => 'publish',
|
522 |
'post_type' => 'wprss_feed_item',
|
523 |
-
'post_date' => $date,
|
524 |
'post_date_gmt' => $date_gmt
|
525 |
),
|
526 |
$item
|
527 |
);
|
528 |
wprss_log( 'Post data filters applied', null, WPRSS_LOG_LEVEL_SYSTEM );
|
529 |
-
|
530 |
if ( defined('ICL_SITEPRESS_VERSION') )
|
531 |
@include_once( WP_PLUGIN_DIR . '/sitepress-multilingual-cms/inc/wpml-api.php' );
|
532 |
if ( defined('ICL_LANGUAGE_CODE') ) {
|
533 |
$_POST['icl_post_language'] = $language_code = ICL_LANGUAGE_CODE;
|
534 |
wprss_log_obj( 'WPML detected. Language code determined', $language_code, null, WPRSS_LOG_LEVEL_SYSTEM );
|
535 |
}
|
536 |
-
|
537 |
// Create and insert post object into the DB
|
538 |
$inserted_ID = wp_insert_post( $feed_item );
|
539 |
|
@@ -572,7 +572,7 @@
|
|
572 |
else {
|
573 |
wprss_log( 'Item already exists and will be skipped', null, WPRSS_LOG_LEVEL_NOTICE );
|
574 |
}
|
575 |
-
|
576 |
wprss_log_obj( 'Finished importing item', $permalink, null, WPRSS_LOG_LEVEL_INFO );
|
577 |
}
|
578 |
|
@@ -591,12 +591,12 @@
|
|
591 |
function wprss_items_insert_post_meta( $inserted_ID, $item, $feed_ID, $permalink, $enclosure_url ) {
|
592 |
update_post_meta( $inserted_ID, 'wprss_item_permalink', $permalink );
|
593 |
update_post_meta( $inserted_ID, 'wprss_item_enclosure', $enclosure_url );
|
594 |
-
|
595 |
$author = $item->get_author();
|
596 |
if ( $author ) {
|
597 |
update_post_meta( $inserted_ID, 'wprss_item_author', $author->get_name() );
|
598 |
}
|
599 |
-
|
600 |
update_post_meta( $inserted_ID, 'wprss_feed_id', $feed_ID);
|
601 |
do_action( 'wprss_items_create_post_meta', $inserted_ID, $item, $feed_ID );
|
602 |
}
|
@@ -662,7 +662,7 @@
|
|
662 |
|
663 |
/**
|
664 |
* Runs the above function with parameter FALSE
|
665 |
-
*
|
666 |
* @since 3.9
|
667 |
*/
|
668 |
function wprss_fetch_insert_all_feed_items_from_cron() {
|
4 |
*
|
5 |
* @package WPRSSAggregator
|
6 |
*/
|
7 |
+
|
8 |
|
9 |
// Warning: Order may be important
|
10 |
add_filter('wprss_normalize_permalink', 'wprss_google_news_url_fix', 8);
|
11 |
add_filter('wprss_normalize_permalink', 'wprss_bing_news_url_fix', 9);
|
12 |
add_filter('wprss_normalize_permalink', 'wprss_google_alerts_url_fix', 10);
|
13 |
add_filter('wprss_normalize_permalink', 'wprss_convert_video_permalink', 100);
|
14 |
+
|
15 |
|
16 |
add_action( 'wprss_fetch_single_feed_hook', 'wprss_fetch_insert_single_feed_items' );
|
17 |
/**
|
40 |
delete_post_meta( $feed_ID, 'wprss_force_next_fetch' );
|
41 |
wprss_log( 'Force feed flag removed', null, WPRSS_LOG_LEVEL_SYSTEM );
|
42 |
}
|
43 |
+
|
44 |
$start_of_update = wprss_flag_feed_as_updating( $feed_ID );
|
45 |
wprss_log_obj( 'Start of import time updated', date( 'Y-m-d H:i:s', $start_of_update), null, WPRSS_LOG_LEVEL_SYSTEM );
|
46 |
|
53 |
// Get the feed limit from post meta
|
54 |
$feed_limit = get_post_meta( $feed_ID, 'wprss_limit', true );
|
55 |
wprss_log_obj( 'Feed limit value is', $feed_limit, null, WPRSS_LOG_LEVEL_SYSTEM );
|
56 |
+
|
57 |
// If the feed has no individual limit
|
58 |
if ( $feed_limit === '' || intval( $feed_limit ) <= 0 ) {
|
59 |
wprss_log_obj( 'Using global limit', $feed_limit, null, WPRSS_LOG_LEVEL_NOTICE );
|
141 |
} else {
|
142 |
wprss_log( 'Items to import remained untouched. Not items already exist or are blacklisted.', null, WPRSS_LOG_LEVEL_SYSTEM );
|
143 |
}
|
144 |
+
|
145 |
$items_to_insert = $new_items;
|
146 |
|
147 |
// If using a limit - delete any excess items to make room for the new items
|
148 |
if ( $feed_limit !== NULL ) {
|
149 |
wprss_log_obj( 'Some items may be deleted due to limit', $feed_limit, null, WPRSS_LOG_LEVEL_SYSTEM );
|
150 |
+
|
151 |
// Get the number of feed items in DB, and their count
|
152 |
$db_feed_items = wprss_get_feed_items_for_source( $feed_ID );
|
153 |
$num_db_feed_items = $db_feed_items->post_count;
|
154 |
+
|
155 |
// Get the number of feed items we can store until we reach the limit
|
156 |
$num_can_insert = $feed_limit - $num_db_feed_items;
|
157 |
// Calculate how many feed items we must delete before importing, to keep to the limit
|
170 |
foreach ( $feed_items_to_delete as $key => $post ) {
|
171 |
wp_delete_post( $post->ID, TRUE );
|
172 |
}
|
173 |
+
|
174 |
if ( $deleted_items_count = count( $feed_items_to_delete ) )
|
175 |
wprss_log_obj( 'Items deleted due to limit', $deleted_items_count, null, WPRSS_LOG_LEVEL_NOTICE );
|
176 |
}
|
177 |
+
|
178 |
update_post_meta( $feed_ID, 'wprss_last_update', $last_update_time = time() );
|
179 |
update_post_meta( $feed_ID, 'wprss_last_update_items', 0 );
|
180 |
wprss_log_obj( 'Last import time updated', $last_update_time, null, WPRSS_LOG_LEVEL_SYSTEM );
|
187 |
} else {
|
188 |
wprss_log_obj('The feed URL is not valid! Please recheck', $feed_url);
|
189 |
}
|
190 |
+
|
191 |
$next_scheduled = get_post_meta( $feed_ID, 'wprss_reschedule_event', TRUE );
|
192 |
+
|
193 |
if ( $next_scheduled !== '' ) {
|
194 |
wprss_feed_source_update_start_schedule( $feed_ID );
|
195 |
delete_post_meta( $feed_ID, 'wprss_reschedule_event' );
|
219 |
// Remove previously added filters and actions
|
220 |
remove_action( 'wp_feed_options', 'wprss_do_not_cache_feeds' );
|
221 |
remove_filter( 'wp_feed_cache_transient_lifetime' , 'wprss_feed_cache_lifetime' );
|
222 |
+
|
223 |
if ( !is_wp_error( $feed ) ) {
|
224 |
// Return the items in the feed.
|
225 |
return $feed->get_items();
|
260 |
$feed->force_feed( TRUE );
|
261 |
}
|
262 |
}
|
263 |
+
|
264 |
// Set timeout limit
|
265 |
$fetch_time_limit = wprss_get_feed_fetch_time_limit();
|
266 |
$feed->set_timeout( $fetch_time_limit );
|
277 |
$feed->strip_htmltags( $tags_to_strip );
|
278 |
|
279 |
do_action( 'wprss_fetch_feed_before', $feed );
|
280 |
+
|
281 |
// Fetch the feed
|
282 |
$feed->init();
|
283 |
$feed->handle_content_type();
|
284 |
+
|
285 |
do_action( 'wprss_fetch_feed_after', $feed );
|
286 |
|
287 |
// Convert the feed error into a WP_Error, if applicable
|
312 |
// Return the normalized permalink
|
313 |
return $permalink;
|
314 |
}
|
315 |
+
|
316 |
+
|
317 |
/**
|
318 |
* Extracts the actual URL from a Google News permalink
|
319 |
+
*
|
320 |
* @param string $permalink The permalink to normalize.
|
321 |
* @since 4.2.3
|
322 |
*/
|
323 |
function wprss_google_news_url_fix($permalink) {
|
324 |
return wprss_tracking_url_fix($permalink, '!^(https?:\/\/)?' . preg_quote('news.google.com', '!') . '.*!');
|
325 |
}
|
326 |
+
|
327 |
+
|
328 |
/**
|
329 |
* Extracts the actual URL from a Google Alerts permalink
|
330 |
+
*
|
331 |
* @param string $permalink The permalink to normalize.
|
332 |
* @since 4.7.3
|
333 |
*/
|
334 |
function wprss_google_alerts_url_fix($permalink) {
|
335 |
return wprss_tracking_url_fix($permalink, '!^(https?:\/\/)?(www\.)?' . preg_quote('google.com/url', '!') . '.*!');
|
336 |
}
|
337 |
+
|
338 |
|
339 |
/**
|
340 |
* Extracts the actual URL from a Bing permalink
|
341 |
+
*
|
342 |
* @param string $permalink The permalink to normalize.
|
343 |
* @since 4.2.3
|
344 |
*/
|
355 |
* Fixes the issue with equivalent Google News etc. items having
|
356 |
* different URLs, that contain randomly generated GET parameters.
|
357 |
* Example:
|
358 |
+
*
|
359 |
* http://news.google.com/news/url?sa=t&fd=R&ct2=us&ei=V3e9U6izMMnm1QaB1YHoDA&url=http://abcd...
|
360 |
* http://news.google.com/news/url?sa=t&fd=R&ct2=us&ei=One9U-HQLsTp1Aal-oDQBQ&url=http://abcd...
|
361 |
*
|
370 |
// Parse the url
|
371 |
$parsed = parse_url( urldecode( html_entity_decode( $permalink ) ) );
|
372 |
$patterns = is_array($patterns) ? $patterns :array($patterns);
|
373 |
+
|
374 |
// If parsing failed, return the permalink
|
375 |
if ( $parsed === FALSE || $parsed === NULL ) return $permalink;
|
376 |
|
382 |
break;
|
383 |
}
|
384 |
}
|
385 |
+
|
386 |
if( !$isMatch ) return $permalink;
|
387 |
+
|
388 |
// Check if the url GET query string is present
|
389 |
if ( !isset( $parsed['query'] ) ) return $permalink;
|
390 |
+
|
391 |
// Parse the query string
|
392 |
$query = array();
|
393 |
parse_str( $parsed['query'], $query );
|
394 |
+
|
395 |
// Check if the url GET parameter is present in the query string
|
396 |
if ( !is_array($query) || !isset( $query[$argName] ) ) return $permalink;
|
397 |
+
|
398 |
return urldecode( $query[$argName] );
|
399 |
}
|
400 |
|
415 |
|
416 |
// If video host was found
|
417 |
if ( $found_video_host !== 0 && $found_video_host !== FALSE ) {
|
418 |
+
|
419 |
// Get general options
|
420 |
$options = get_option( 'wprss_settings_general' );
|
421 |
// Get the video link option entry, or false if it does not exist
|
422 |
$video_link = ( isset($options['video_link']) )? $options['video_link'] : 'false';
|
423 |
+
|
424 |
// If the video link option is true, change the video URL to its repective host's embedded
|
425 |
// video player URL. Otherwise, leave the permalink as is.
|
426 |
if ( strtolower( $video_link ) === 'true' ) {
|
454 |
function wprss_items_insert_post( $items, $feed_ID ) {
|
455 |
update_post_meta( $feed_ID, 'wprss_feed_is_updating', $update_started_at = time() );
|
456 |
wprss_log_obj( 'Starting import of items for feed ' . $feed_ID, $update_started_at, null, WPRSS_LOG_LEVEL_INFO );
|
457 |
+
|
458 |
// Gather the permalinks of existing feed item's related to this feed source
|
459 |
$existing_permalinks = wprss_get_existing_permalinks( $feed_ID );
|
460 |
|
505 |
// If the item is not NULL, continue to inserting the feed item post into the DB
|
506 |
if ( $item !== NULL && !is_bool($item) ) {
|
507 |
wprss_log( 'Using core logic', null, WPRSS_LOG_LEVEL_SYSTEM );
|
508 |
+
|
509 |
// Get the date and GTM date and normalize if not valid dor not present
|
510 |
$format = 'Y-m-d H:i:s';
|
511 |
$has_date = $item->get_date( 'U' ) ? TRUE : FALSE;
|
520 |
'post_content' => '',
|
521 |
'post_status' => 'publish',
|
522 |
'post_type' => 'wprss_feed_item',
|
523 |
+
'post_date' => $date,
|
524 |
'post_date_gmt' => $date_gmt
|
525 |
),
|
526 |
$item
|
527 |
);
|
528 |
wprss_log( 'Post data filters applied', null, WPRSS_LOG_LEVEL_SYSTEM );
|
529 |
+
|
530 |
if ( defined('ICL_SITEPRESS_VERSION') )
|
531 |
@include_once( WP_PLUGIN_DIR . '/sitepress-multilingual-cms/inc/wpml-api.php' );
|
532 |
if ( defined('ICL_LANGUAGE_CODE') ) {
|
533 |
$_POST['icl_post_language'] = $language_code = ICL_LANGUAGE_CODE;
|
534 |
wprss_log_obj( 'WPML detected. Language code determined', $language_code, null, WPRSS_LOG_LEVEL_SYSTEM );
|
535 |
}
|
536 |
+
|
537 |
// Create and insert post object into the DB
|
538 |
$inserted_ID = wp_insert_post( $feed_item );
|
539 |
|
572 |
else {
|
573 |
wprss_log( 'Item already exists and will be skipped', null, WPRSS_LOG_LEVEL_NOTICE );
|
574 |
}
|
575 |
+
|
576 |
wprss_log_obj( 'Finished importing item', $permalink, null, WPRSS_LOG_LEVEL_INFO );
|
577 |
}
|
578 |
|
591 |
function wprss_items_insert_post_meta( $inserted_ID, $item, $feed_ID, $permalink, $enclosure_url ) {
|
592 |
update_post_meta( $inserted_ID, 'wprss_item_permalink', $permalink );
|
593 |
update_post_meta( $inserted_ID, 'wprss_item_enclosure', $enclosure_url );
|
594 |
+
|
595 |
$author = $item->get_author();
|
596 |
if ( $author ) {
|
597 |
update_post_meta( $inserted_ID, 'wprss_item_author', $author->get_name() );
|
598 |
}
|
599 |
+
|
600 |
update_post_meta( $inserted_ID, 'wprss_feed_id', $feed_ID);
|
601 |
do_action( 'wprss_items_create_post_meta', $inserted_ID, $item, $feed_ID );
|
602 |
}
|
662 |
|
663 |
/**
|
664 |
* Runs the above function with parameter FALSE
|
665 |
+
*
|
666 |
* @since 3.9
|
667 |
*/
|
668 |
function wprss_fetch_insert_all_feed_items_from_cron() {
|
includes/feed-processing.php
CHANGED
@@ -11,7 +11,7 @@
|
|
11 |
/**
|
12 |
* Returns whether or not the feed source will forcefully fetch the next fetch,
|
13 |
* ignoring whether or not it is paused or not.
|
14 |
-
*
|
15 |
* @param $source_id The ID of the feed soruce
|
16 |
* @return boolean
|
17 |
* @since 3.7
|
@@ -74,13 +74,14 @@
|
|
74 |
$args = apply_filters(
|
75 |
'wprss_get_feed_items_for_source_args',
|
76 |
array(
|
77 |
-
'post_type'
|
78 |
-
'cache_results'
|
79 |
-
'no_found_rows'
|
80 |
-
'posts_per_page'=> -1,
|
81 |
-
'
|
82 |
-
'
|
83 |
-
'
|
|
|
84 |
array(
|
85 |
'key' => 'wprss_feed_id',
|
86 |
'value' => $source_id,
|
@@ -195,11 +196,11 @@
|
|
195 |
* Returns the image of the feed.
|
196 |
* The reason this function exists is for add-ons to be able to detect if the plugin core
|
197 |
* supports feed image functionality through a simple function_exists() call.
|
198 |
-
*
|
199 |
* @param $source_id The ID of the feed source
|
200 |
* @return string The link to the feed image
|
201 |
* @since 1.0
|
202 |
-
*/
|
203 |
function wprss_get_feed_image( $source_id ) {
|
204 |
return get_post_meta( $source_id, 'wprss_feed_image', true );
|
205 |
}
|
@@ -215,7 +216,7 @@
|
|
215 |
*/
|
216 |
function wprss_updated_feed_source( $post_ID, $post_after, $post_before ) {
|
217 |
// Check if the post is a feed source and is published
|
218 |
-
|
219 |
if ( ( $post_after->post_type == 'wprss_feed' ) && ( $post_after->post_status == 'publish' ) ) {
|
220 |
|
221 |
if ( isset( $_POST['wprss_url'] ) && !empty( $_POST['wprss_url'] ) ) {
|
@@ -305,7 +306,7 @@
|
|
305 |
if ( isset( $json['id'] ) ) {
|
306 |
# Generate the final URL for this feed and update the post meta
|
307 |
$final_url = "http://www.facebook.com/feeds/page.php?format=rss20&id=" . $json['id'];
|
308 |
-
update_post_meta( $post_id, 'wprss_url', $final_url, $url );
|
309 |
}
|
310 |
}
|
311 |
}
|
@@ -389,7 +390,7 @@
|
|
389 |
function wprss_flag_feed_as_idle( $feed_ID ) {
|
390 |
delete_post_meta( $feed_ID, 'wprss_feed_is_updating' );
|
391 |
}
|
392 |
-
|
393 |
|
394 |
/**
|
395 |
* Returns whether or not the feed source is updating.
|
@@ -401,7 +402,7 @@
|
|
401 |
function wprss_is_feed_source_updating( $id ) {
|
402 |
// Get the 'updating' meta field
|
403 |
$is_updating_meta = get_post_meta( $id, 'wprss_feed_is_updating', TRUE );
|
404 |
-
|
405 |
// Check if the feed has the 'updating' meta field set
|
406 |
if ( $is_updating_meta === '' ) {
|
407 |
// If not, then the feed is not updating
|
@@ -449,7 +450,7 @@
|
|
449 |
if ( $is_deleting_meta === '' ) {
|
450 |
return FALSE;
|
451 |
}
|
452 |
-
|
453 |
$diff = time() - $is_deleting_meta;
|
454 |
|
455 |
$items = wprss_get_feed_items_for_source( $id );
|
@@ -476,7 +477,7 @@
|
|
476 |
/**
|
477 |
* Returns true if the feed item is older than the given timestamp,
|
478 |
* false otherwise;
|
479 |
-
*
|
480 |
* @since 3.8
|
481 |
*/
|
482 |
function wprss_is_feed_item_older_than( $id, $timestamp ) {
|
@@ -492,7 +493,7 @@
|
|
492 |
|
493 |
/**
|
494 |
* Returns the maximum age setting for a feed source.
|
495 |
-
*
|
496 |
* @since 3.8
|
497 |
*/
|
498 |
function wprss_get_max_age_for_feed_source( $source_id ) {
|
@@ -546,7 +547,7 @@
|
|
546 |
if ( $feed_items-> have_posts() ) {
|
547 |
// Extend the timeout time limit for the deletion of the feed items
|
548 |
$time_limit = wprss_get_item_import_time_limit();
|
549 |
-
wprss_log( "Extended execution time limit by {$time_limit}s for imported items truncation.", null,
|
550 |
set_time_limit( $time_limit );
|
551 |
// For each feed item
|
552 |
while ( $feed_items->have_posts() ) {
|
@@ -555,7 +556,7 @@
|
|
555 |
if ( wprss_is_feed_item_older_than( get_the_ID(), $max_age ) === TRUE ){
|
556 |
// Delete the post
|
557 |
wp_delete_post( get_the_ID(), true );
|
558 |
-
}
|
559 |
}
|
560 |
// Reset feed items query data
|
561 |
wp_reset_postdata();
|
@@ -590,7 +591,7 @@
|
|
590 |
$threshold = $general_settings['limit_feed_items_db'];
|
591 |
$post_types = apply_filters( 'wprss_truncation_post_types', array( 'wprss_feed_item' ) );
|
592 |
$post_types_str = array_map( 'wprss_return_as_string', $post_types );
|
593 |
-
|
594 |
$post_type_list = implode( ',' , $post_types_str );
|
595 |
|
596 |
// Query post type
|
@@ -601,7 +602,7 @@
|
|
601 |
AND post_status = 'publish'
|
602 |
ORDER BY post_modified DESC
|
603 |
";
|
604 |
-
|
605 |
$results = $wpdb->get_results( $query );
|
606 |
|
607 |
// Check if there are any results
|
@@ -624,8 +625,8 @@
|
|
624 |
add_filter( 'wprss_insert_post_item_conditionals', 'wprss_check_feed_item_date_on_import', 2, 3 );
|
625 |
/**
|
626 |
* When a feed item is imported, it's date is compared against the max age of it's feed source.
|
627 |
-
*
|
628 |
-
*
|
629 |
* @since 3.8
|
630 |
*/
|
631 |
function wprss_check_feed_item_date_on_import( $item, $source, $permalink ){
|
@@ -642,7 +643,7 @@
|
|
642 |
|
643 |
// Calculate the age difference
|
644 |
$difference = $age - $max_age;
|
645 |
-
|
646 |
if ( $difference <= 0 ) {
|
647 |
return NULL;
|
648 |
} else {
|
@@ -660,13 +661,13 @@
|
|
660 |
wp_schedule_single_event( time(), 'wprss_delete_all_feed_items_hook' );
|
661 |
set_transient( WPRSS_TRANSIENT_NAME_IS_REIMPORTING, true );
|
662 |
}
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
function wprss_schedule_reimport_all($deleted_ids) {
|
667 |
if( !get_transient( WPRSS_TRANSIENT_NAME_IS_REIMPORTING ) )
|
668 |
return;
|
669 |
-
|
670 |
wprss_log( 'Re-import scheduled...', __FUNCTION__, WPRSS_LOG_LEVEL_SYSTEM);
|
671 |
delete_transient( WPRSS_TRANSIENT_NAME_IS_REIMPORTING );
|
672 |
wprss_fetch_insert_all_feed_items( TRUE );
|
11 |
/**
|
12 |
* Returns whether or not the feed source will forcefully fetch the next fetch,
|
13 |
* ignoring whether or not it is paused or not.
|
14 |
+
*
|
15 |
* @param $source_id The ID of the feed soruce
|
16 |
* @return boolean
|
17 |
* @since 3.7
|
74 |
$args = apply_filters(
|
75 |
'wprss_get_feed_items_for_source_args',
|
76 |
array(
|
77 |
+
'post_type' => 'wprss_feed_item',
|
78 |
+
'cache_results' => false, // Disable caching, used for one-off queries
|
79 |
+
'no_found_rows' => true, // We don't need pagination, so disable it
|
80 |
+
'posts_per_page' => -1,
|
81 |
+
'ignore_sticky_posts' => 'true',
|
82 |
+
'orderby' => 'date',
|
83 |
+
'order' => 'DESC',
|
84 |
+
'meta_query' => array(
|
85 |
array(
|
86 |
'key' => 'wprss_feed_id',
|
87 |
'value' => $source_id,
|
196 |
* Returns the image of the feed.
|
197 |
* The reason this function exists is for add-ons to be able to detect if the plugin core
|
198 |
* supports feed image functionality through a simple function_exists() call.
|
199 |
+
*
|
200 |
* @param $source_id The ID of the feed source
|
201 |
* @return string The link to the feed image
|
202 |
* @since 1.0
|
203 |
+
*/
|
204 |
function wprss_get_feed_image( $source_id ) {
|
205 |
return get_post_meta( $source_id, 'wprss_feed_image', true );
|
206 |
}
|
216 |
*/
|
217 |
function wprss_updated_feed_source( $post_ID, $post_after, $post_before ) {
|
218 |
// Check if the post is a feed source and is published
|
219 |
+
|
220 |
if ( ( $post_after->post_type == 'wprss_feed' ) && ( $post_after->post_status == 'publish' ) ) {
|
221 |
|
222 |
if ( isset( $_POST['wprss_url'] ) && !empty( $_POST['wprss_url'] ) ) {
|
306 |
if ( isset( $json['id'] ) ) {
|
307 |
# Generate the final URL for this feed and update the post meta
|
308 |
$final_url = "http://www.facebook.com/feeds/page.php?format=rss20&id=" . $json['id'];
|
309 |
+
update_post_meta( $post_id, 'wprss_url', $final_url, $url );
|
310 |
}
|
311 |
}
|
312 |
}
|
390 |
function wprss_flag_feed_as_idle( $feed_ID ) {
|
391 |
delete_post_meta( $feed_ID, 'wprss_feed_is_updating' );
|
392 |
}
|
393 |
+
|
394 |
|
395 |
/**
|
396 |
* Returns whether or not the feed source is updating.
|
402 |
function wprss_is_feed_source_updating( $id ) {
|
403 |
// Get the 'updating' meta field
|
404 |
$is_updating_meta = get_post_meta( $id, 'wprss_feed_is_updating', TRUE );
|
405 |
+
|
406 |
// Check if the feed has the 'updating' meta field set
|
407 |
if ( $is_updating_meta === '' ) {
|
408 |
// If not, then the feed is not updating
|
450 |
if ( $is_deleting_meta === '' ) {
|
451 |
return FALSE;
|
452 |
}
|
453 |
+
|
454 |
$diff = time() - $is_deleting_meta;
|
455 |
|
456 |
$items = wprss_get_feed_items_for_source( $id );
|
477 |
/**
|
478 |
* Returns true if the feed item is older than the given timestamp,
|
479 |
* false otherwise;
|
480 |
+
*
|
481 |
* @since 3.8
|
482 |
*/
|
483 |
function wprss_is_feed_item_older_than( $id, $timestamp ) {
|
493 |
|
494 |
/**
|
495 |
* Returns the maximum age setting for a feed source.
|
496 |
+
*
|
497 |
* @since 3.8
|
498 |
*/
|
499 |
function wprss_get_max_age_for_feed_source( $source_id ) {
|
547 |
if ( $feed_items-> have_posts() ) {
|
548 |
// Extend the timeout time limit for the deletion of the feed items
|
549 |
$time_limit = wprss_get_item_import_time_limit();
|
550 |
+
wprss_log( "Extended execution time limit by {$time_limit}s for imported items truncation.", null, WPRSS_LOG_LEVEL_SYSTEM );
|
551 |
set_time_limit( $time_limit );
|
552 |
// For each feed item
|
553 |
while ( $feed_items->have_posts() ) {
|
556 |
if ( wprss_is_feed_item_older_than( get_the_ID(), $max_age ) === TRUE ){
|
557 |
// Delete the post
|
558 |
wp_delete_post( get_the_ID(), true );
|
559 |
+
}
|
560 |
}
|
561 |
// Reset feed items query data
|
562 |
wp_reset_postdata();
|
591 |
$threshold = $general_settings['limit_feed_items_db'];
|
592 |
$post_types = apply_filters( 'wprss_truncation_post_types', array( 'wprss_feed_item' ) );
|
593 |
$post_types_str = array_map( 'wprss_return_as_string', $post_types );
|
594 |
+
|
595 |
$post_type_list = implode( ',' , $post_types_str );
|
596 |
|
597 |
// Query post type
|
602 |
AND post_status = 'publish'
|
603 |
ORDER BY post_modified DESC
|
604 |
";
|
605 |
+
|
606 |
$results = $wpdb->get_results( $query );
|
607 |
|
608 |
// Check if there are any results
|
625 |
add_filter( 'wprss_insert_post_item_conditionals', 'wprss_check_feed_item_date_on_import', 2, 3 );
|
626 |
/**
|
627 |
* When a feed item is imported, it's date is compared against the max age of it's feed source.
|
628 |
+
*
|
629 |
+
*
|
630 |
* @since 3.8
|
631 |
*/
|
632 |
function wprss_check_feed_item_date_on_import( $item, $source, $permalink ){
|
643 |
|
644 |
// Calculate the age difference
|
645 |
$difference = $age - $max_age;
|
646 |
+
|
647 |
if ( $difference <= 0 ) {
|
648 |
return NULL;
|
649 |
} else {
|
661 |
wp_schedule_single_event( time(), 'wprss_delete_all_feed_items_hook' );
|
662 |
set_transient( WPRSS_TRANSIENT_NAME_IS_REIMPORTING, true );
|
663 |
}
|
664 |
+
|
665 |
+
|
666 |
+
|
667 |
function wprss_schedule_reimport_all($deleted_ids) {
|
668 |
if( !get_transient( WPRSS_TRANSIENT_NAME_IS_REIMPORTING ) )
|
669 |
return;
|
670 |
+
|
671 |
wprss_log( 'Re-import scheduled...', __FUNCTION__, WPRSS_LOG_LEVEL_SYSTEM);
|
672 |
delete_transient( WPRSS_TRANSIENT_NAME_IS_REIMPORTING );
|
673 |
wprss_fetch_insert_all_feed_items( TRUE );
|
includes/image-caching.php
CHANGED
@@ -20,8 +20,12 @@ class WPRSS_Image_Cache {
|
|
20 |
* @since 4.6.10
|
21 |
*/
|
22 |
public function __construct() {
|
|
|
23 |
}
|
24 |
|
|
|
|
|
|
|
25 |
|
26 |
/**
|
27 |
* Retrieve the singleton instance of this class.
|
20 |
* @since 4.6.10
|
21 |
*/
|
22 |
public function __construct() {
|
23 |
+
$this->_construct();
|
24 |
}
|
25 |
|
26 |
+
protected function _construct() {
|
27 |
+
|
28 |
+
}
|
29 |
|
30 |
/**
|
31 |
* Retrieve the singleton instance of this class.
|
includes/libraries/browser.php
CHANGED
@@ -1,1082 +1,1103 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
/**
|
3 |
-
*
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
*
|
19 |
-
* @version 1.9
|
20 |
-
* @package PegasusPHP
|
21 |
-
*
|
22 |
-
* Copyright (C) 2008-2010 Chris Schuld (chris@chrisschuld.com)
|
23 |
-
*
|
24 |
-
* This program is free software; you can redistribute it and/or
|
25 |
-
* modify it under the terms of the GNU General Public License as
|
26 |
-
* published by the Free Software Foundation; either version 2 of
|
27 |
-
* the License, or (at your option) any later version.
|
28 |
-
*
|
29 |
-
* This program is distributed in the hope that it will be useful,
|
30 |
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
31 |
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
32 |
-
* GNU General Public License for more details at:
|
33 |
-
* http://www.gnu.org/copyleft/gpl.html
|
34 |
-
*
|
35 |
-
*
|
36 |
-
* Typical Usage:
|
37 |
-
*
|
38 |
-
* $browser = new Browser();
|
39 |
-
* if( $browser->getBrowser() == Browser::BROWSER_FIREFOX && $browser->getVersion() >= 2 ) {
|
40 |
-
* echo 'You have FireFox version 2 or greater';
|
41 |
-
* }
|
42 |
-
*
|
43 |
-
* User Agents Sampled from: http://www.useragentstring.com/
|
44 |
-
*
|
45 |
-
* This implementation is based on the original work from Gary White
|
46 |
-
* http://apptools.com/phptools/browser/
|
47 |
*
|
48 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
*
|
50 |
-
*
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
*
|
55 |
*
|
56 |
-
*
|
57 |
-
|
|
|
|
|
|
|
58 |
*
|
59 |
-
*
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
*
|
64 |
-
* + Added OpenBSD Platform
|
65 |
-
* + Added NetBSD Platform
|
66 |
-
* + Added SunOS Platform
|
67 |
-
* + Added OpenSolaris Platform
|
68 |
-
* + Added support of the Iceweazel Browser
|
69 |
-
* + Added isChromeFrame() call to check if chromeframe is in use
|
70 |
-
* + Moved the Opera check in front of the Firefox check due to legacy Opera User Agents
|
71 |
-
* + Added the __toString() method (Thanks Deano)
|
72 |
*
|
73 |
-
*
|
74 |
-
|
75 |
-
|
76 |
-
|
|
|
77 |
*
|
78 |
-
*
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
*
|
83 |
-
* + Added support for isRobot() and isMobile()
|
84 |
-
* + Added support for Opera version 10
|
85 |
-
* + Added support for deprecated Netscape Navigator version 9
|
86 |
-
* + Added support for IceCat
|
87 |
-
* + Added support for Shiretoko
|
88 |
*
|
89 |
-
*
|
90 |
-
|
|
|
|
|
|
|
91 |
*
|
92 |
-
*
|
93 |
-
|
94 |
-
|
|
|
|
|
95 |
*
|
96 |
-
*
|
97 |
-
|
|
|
|
|
|
|
98 |
*
|
99 |
-
*
|
100 |
-
|
101 |
-
|
102 |
-
|
|
|
103 |
*
|
104 |
-
*
|
105 |
-
|
106 |
-
|
107 |
-
|
|
|
108 |
*
|
109 |
-
*
|
110 |
-
|
|
|
|
|
|
|
111 |
*
|
112 |
-
*
|
113 |
-
|
|
|
|
|
|
|
114 |
*
|
115 |
-
*
|
116 |
-
|
117 |
-
|
118 |
-
|
|
|
119 |
*
|
|
|
|
|
|
|
|
|
|
|
120 |
*
|
121 |
-
*
|
122 |
-
|
123 |
-
|
124 |
-
|
|
|
125 |
*
|
126 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
*
|
128 |
-
*
|
129 |
-
*
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
*
|
136 |
-
* Updated the version detection for OmniWeb
|
137 |
-
* Updated the version detection for iCab
|
138 |
-
* Updated the version detection for Safari
|
139 |
-
* Updated Safari to remove mobile devices (iPhone)
|
140 |
-
* Added detection for iPhone
|
141 |
-
* Added detection for robots
|
142 |
-
* Added detection for mobile devices
|
143 |
-
* Added detection for BlackBerry
|
144 |
-
* Removed Netscape checks (matches heavily with firefox & mozilla)
|
145 |
*
|
|
|
146 |
*/
|
147 |
-
|
148 |
-
class Browser {
|
149 |
-
public $_agent = '';
|
150 |
-
public $_browser_name = '';
|
151 |
-
public $_version = '';
|
152 |
-
public $_platform = '';
|
153 |
-
public $_os = '';
|
154 |
-
public $_is_aol = false;
|
155 |
-
public $_is_mobile = false;
|
156 |
-
public $_is_robot = false;
|
157 |
-
public $_aol_version = '';
|
158 |
-
|
159 |
-
public $BROWSER_UNKNOWN = 'unknown';
|
160 |
-
public $VERSION_UNKNOWN = 'unknown';
|
161 |
-
|
162 |
-
public $BROWSER_OPERA = 'Opera'; // Http://www.opera.com/
|
163 |
-
public $BROWSER_OPERA_MINI = 'Opera Mini'; // Http://www.opera.com/mini/
|
164 |
-
public $BROWSER_WEBTV = 'WebTV'; // Http://www.webtv.net/pc/
|
165 |
-
public $BROWSER_IE = 'Internet Explorer'; // Http://www.microsoft.com/ie/
|
166 |
-
public $BROWSER_POCKET_IE = 'Pocket Internet Explorer'; // Http://en.wikipedia.org/wiki/Internet_Explorer_Mobile
|
167 |
-
public $BROWSER_KONQUEROR = 'Konqueror'; // Http://www.konqueror.org/
|
168 |
-
public $BROWSER_ICAB = 'iCab'; // Http://www.icab.de/
|
169 |
-
public $BROWSER_OMNIWEB = 'OmniWeb'; // Http://www.omnigroup.com/applications/omniweb/
|
170 |
-
public $BROWSER_FIREBIRD = 'Firebird'; // Http://www.ibphoenix.com/
|
171 |
-
public $BROWSER_FIREFOX = 'Firefox'; // Http://www.mozilla.com/en-US/firefox/firefox.html
|
172 |
-
public $BROWSER_ICEWEASEL = 'Iceweasel'; // Http://www.geticeweasel.org/
|
173 |
-
public $BROWSER_SHIRETOKO = 'Shiretoko'; // Http://wiki.mozilla.org/Projects/shiretoko
|
174 |
-
public $BROWSER_MOZILLA = 'Mozilla'; // Http://www.mozilla.com/en-US/
|
175 |
-
public $BROWSER_AMAYA = 'Amaya'; // Http://www.w3.org/Amaya/
|
176 |
-
public $BROWSER_LYNX = 'Lynx'; // Http://en.wikipedia.org/wiki/Lynx
|
177 |
-
public $BROWSER_SAFARI = 'Safari'; // Http://apple.com
|
178 |
-
public $BROWSER_IPHONE = 'iPhone'; // Http://apple.com
|
179 |
-
public $BROWSER_IPOD = 'iPod'; // Http://apple.com
|
180 |
-
public $BROWSER_IPAD = 'iPad'; // Http://apple.com
|
181 |
-
public $BROWSER_CHROME = 'Chrome'; // Http://www.google.com/chrome
|
182 |
-
public $BROWSER_ANDROID = 'Android'; // Http://www.android.com/
|
183 |
-
public $BROWSER_GOOGLEBOT = 'GoogleBot'; // Http://en.wikipedia.org/wiki/Googlebot
|
184 |
-
public $BROWSER_SLURP = 'Yahoo! Slurp'; // Http://en.wikipedia.org/wiki/Yahoo!_Slurp
|
185 |
-
public $BROWSER_W3CVALIDATOR = 'W3C Validator'; // Http://validator.w3.org/
|
186 |
-
public $BROWSER_BLACKBERRY = 'BlackBerry'; // Http://www.blackberry.com/
|
187 |
-
public $BROWSER_ICECAT = 'IceCat'; // Http://en.wikipedia.org/wiki/GNU_IceCat
|
188 |
-
public $BROWSER_NOKIA_S60 = 'Nokia S60 OSS Browser'; // Http://en.wikipedia.org/wiki/Web_Browser_for_S60
|
189 |
-
public $BROWSER_NOKIA = 'Nokia Browser'; // * all other WAP-based browsers on the Nokia Platform
|
190 |
-
public $BROWSER_MSN = 'MSN Browser'; // Http://explorer.msn.com/
|
191 |
-
public $BROWSER_MSNBOT = 'MSN Bot'; // Http://search.msn.com/msnbot.htm
|
192 |
-
// Http://en.wikipedia.org/wiki/Msnbot (used for Bing as well)
|
193 |
-
|
194 |
-
public $BROWSER_NETSCAPE_NAVIGATOR = 'Netscape Navigator'; // Http://browser.netscape.com/ (DEPRECATED)
|
195 |
-
public $BROWSER_GALEON = 'Galeon'; // Http://galeon.sourceforge.net/ (DEPRECATED)
|
196 |
-
public $BROWSER_NETPOSITIVE = 'NetPositive'; // Http://en.wikipedia.org/wiki/NetPositive (DEPRECATED)
|
197 |
-
public $BROWSER_PHOENIX = 'Phoenix'; // Http://en.wikipedia.org/wiki/History_of_Mozilla_Firefox (DEPRECATED)
|
198 |
-
|
199 |
-
public $PLATFORM_UNKNOWN = 'unknown';
|
200 |
-
public $PLATFORM_WINDOWS = 'Windows';
|
201 |
-
public $PLATFORM_WINDOWS_CE = 'Windows CE';
|
202 |
-
public $PLATFORM_APPLE = 'Apple';
|
203 |
-
public $PLATFORM_LINUX = 'Linux';
|
204 |
-
public $PLATFORM_OS2 = 'OS/2';
|
205 |
-
public $PLATFORM_BEOS = 'BeOS';
|
206 |
-
public $PLATFORM_IPHONE = 'iPhone';
|
207 |
-
public $PLATFORM_IPOD = 'iPod';
|
208 |
-
public $PLATFORM_IPAD = 'iPad';
|
209 |
-
public $PLATFORM_BLACKBERRY = 'BlackBerry';
|
210 |
-
public $PLATFORM_NOKIA = 'Nokia';
|
211 |
-
public $PLATFORM_FREEBSD = 'FreeBSD';
|
212 |
-
public $PLATFORM_OPENBSD = 'OpenBSD';
|
213 |
-
public $PLATFORM_NETBSD = 'NetBSD';
|
214 |
-
public $PLATFORM_SUNOS = 'SunOS';
|
215 |
-
public $PLATFORM_OPENSOLARIS = 'OpenSolaris';
|
216 |
-
public $PLATFORM_ANDROID = 'Android';
|
217 |
-
|
218 |
-
public $OPERATING_SYSTEM_UNKNOWN = 'unknown';
|
219 |
-
|
220 |
-
function Browser($useragent="") {
|
221 |
-
$this->reset();
|
222 |
-
if( $useragent != "" ) {
|
223 |
-
$this->setUserAgent($useragent);
|
224 |
-
}
|
225 |
-
else {
|
226 |
-
$this->determine();
|
227 |
-
}
|
228 |
-
}
|
229 |
-
|
230 |
-
/**
|
231 |
-
* Reset all properties
|
232 |
-
*/
|
233 |
-
function reset() {
|
234 |
-
$this->_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : "";
|
235 |
-
$this->_browser_name = $this->BROWSER_UNKNOWN;
|
236 |
-
$this->_version = $this->VERSION_UNKNOWN;
|
237 |
-
$this->_platform = $this->PLATFORM_UNKNOWN;
|
238 |
-
$this->_os = $this->OPERATING_SYSTEM_UNKNOWN;
|
239 |
-
$this->_is_aol = false;
|
240 |
-
$this->_is_mobile = false;
|
241 |
-
$this->_is_robot = false;
|
242 |
-
$this->_aol_version = $this->VERSION_UNKNOWN;
|
243 |
-
}
|
244 |
-
|
245 |
-
/**
|
246 |
-
* Check to see if the specific browser is valid
|
247 |
-
* @param string $browserName
|
248 |
-
* @return True if the browser is the specified browser
|
249 |
-
*/
|
250 |
-
function isBrowser($browserName) { return( 0 == strcasecmp($this->_browser_name, trim($browserName))); }
|
251 |
-
|
252 |
-
/**
|
253 |
-
* The name of the browser. All return types are from the class contants
|
254 |
-
* @return string Name of the browser
|
255 |
-
*/
|
256 |
-
function getBrowser() { return $this->_browser_name; }
|
257 |
-
/**
|
258 |
-
* Set the name of the browser
|
259 |
-
* @param $browser The name of the Browser
|
260 |
-
*/
|
261 |
-
function setBrowser($browser) { return $this->_browser_name = $browser; }
|
262 |
-
/**
|
263 |
-
* The name of the platform. All return types are from the class contants
|
264 |
-
* @return string Name of the browser
|
265 |
-
*/
|
266 |
-
function getPlatform() { return $this->_platform; }
|
267 |
-
/**
|
268 |
-
* Set the name of the platform
|
269 |
-
* @param $platform The name of the Platform
|
270 |
-
*/
|
271 |
-
function setPlatform($platform) { return $this->_platform = $platform; }
|
272 |
-
/**
|
273 |
-
* The version of the browser.
|
274 |
-
* @return string Version of the browser (will only contain alpha-numeric characters and a period)
|
275 |
-
*/
|
276 |
-
function getVersion() { return $this->_version; }
|
277 |
-
/**
|
278 |
-
* Set the version of the browser
|
279 |
-
* @param $version The version of the Browser
|
280 |
-
*/
|
281 |
-
function setVersion($version) { $this->_version = preg_replace('/[^0-9,.,a-z,A-Z-]/','',$version); }
|
282 |
-
/**
|
283 |
-
* The version of AOL.
|
284 |
-
* @return string Version of AOL (will only contain alpha-numeric characters and a period)
|
285 |
-
*/
|
286 |
-
function getAolVersion() { return $this->_aol_version; }
|
287 |
-
/**
|
288 |
-
* Set the version of AOL
|
289 |
-
* @param $version The version of AOL
|
290 |
-
*/
|
291 |
-
function setAolVersion($version) { $this->_aol_version = preg_replace('/[^0-9,.,a-z,A-Z]/','',$version); }
|
292 |
-
/**
|
293 |
-
* Is the browser from AOL?
|
294 |
-
* @return boolean True if the browser is from AOL otherwise false
|
295 |
-
*/
|
296 |
-
function isAol() { return $this->_is_aol; }
|
297 |
-
/**
|
298 |
-
* Is the browser from a mobile device?
|
299 |
-
* @return boolean True if the browser is from a mobile device otherwise false
|
300 |
-
*/
|
301 |
-
function isMobile() { return $this->_is_mobile; }
|
302 |
-
/**
|
303 |
-
* Is the browser from a robot (ex Slurp,GoogleBot)?
|
304 |
-
* @return boolean True if the browser is from a robot otherwise false
|
305 |
-
*/
|
306 |
-
function isRobot() { return $this->_is_robot; }
|
307 |
-
/**
|
308 |
-
* Set the browser to be from AOL
|
309 |
-
* @param $isAol
|
310 |
-
*/
|
311 |
-
function setAol($isAol) { $this->_is_aol = $isAol; }
|
312 |
-
/**
|
313 |
-
* Set the Browser to be mobile
|
314 |
-
* @param boolean $value is the browser a mobile brower or not
|
315 |
-
*/
|
316 |
-
function setMobile($value=true) { $this->_is_mobile = $value; }
|
317 |
-
/**
|
318 |
-
* Set the Browser to be a robot
|
319 |
-
* @param boolean $value is the browser a robot or not
|
320 |
-
*/
|
321 |
-
function setRobot($value=true) { $this->_is_robot = $value; }
|
322 |
-
/**
|
323 |
-
* Get the user agent value in use to determine the browser
|
324 |
-
* @return string The user agent from the HTTP header
|
325 |
-
*/
|
326 |
-
function getUserAgent() { return $this->_agent; }
|
327 |
-
/**
|
328 |
-
* Set the user agent value (the construction will use the HTTP header value - this will overwrite it)
|
329 |
-
* @param $agent_string The value for the User Agent
|
330 |
-
*/
|
331 |
-
function setUserAgent($agent_string) {
|
332 |
-
$this->reset();
|
333 |
-
$this->_agent = $agent_string;
|
334 |
-
$this->determine();
|
335 |
-
}
|
336 |
-
/**
|
337 |
-
* Used to determine if the browser is actually "chromeframe"
|
338 |
-
* @since 1.7
|
339 |
-
* @return boolean True if the browser is using chromeframe
|
340 |
-
*/
|
341 |
-
function isChromeFrame() {
|
342 |
-
return( strpos($this->_agent,"chromeframe") !== false );
|
343 |
-
}
|
344 |
-
/**
|
345 |
-
* Returns a formatted string with a summary of the details of the browser.
|
346 |
-
* @return string formatted string with a summary of the browser
|
347 |
-
*/
|
348 |
-
function __toString() {
|
349 |
$text1 = $this->getUserAgent(); //grabs the UA (user agent) string
|
350 |
-
$UAline1 = substr($text1, 0, 32); //the first line we print should only be the first 32 characters of the UA string
|
351 |
$text2 = $this->getUserAgent();//now we grab it again and save it to a string
|
352 |
-
$towrapUA = str_replace($UAline1, '', $text2);//the rest of the printoff (other than first line) is equivolent
|
353 |
// To the whole string minus the part we printed off. IE
|
354 |
// User Agent: thefirst32charactersfromUAline1
|
355 |
// the rest of it is now stored in
|
356 |
// $text2 to be printed off
|
357 |
// But we need to add spaces before each line that is split other than line 1
|
358 |
$space = '';
|
359 |
-
for($i = 0; $i < 25; $i++) {
|
360 |
-
|
361 |
}
|
362 |
// Now we split the remaining string of UA ($text2) into lines that are prefixed by spaces for formatting
|
363 |
-
$wordwrapped = chunk_split($towrapUA, 32, "\n $space");
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
|
|
404 |
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
|
418 |
-
|
419 |
-
|
420 |
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
|
|
452 |
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
|
|
460 |
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
|
|
485 |
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
return false;
|
500 |
}
|
|
|
|
|
501 |
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
|
|
542 |
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
|
|
548 |
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
557 |
return true;
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
$this->setVersion(str_replace(array('(',')',';'),'',$aresult[1]));
|
571 |
-
return true;
|
572 |
-
}
|
573 |
-
// Test for Pocket IE
|
574 |
-
else if( stripos($this->_agent,'mspie') !== false || stripos($this->_agent,'pocket') !== false ) {
|
575 |
-
$aresult = explode(' ',stristr($this->_agent,'mspie'));
|
576 |
-
$this->setPlatform( $this->PLATFORM_WINDOWS_CE );
|
577 |
-
$this->setBrowser( $this->BROWSER_POCKET_IE );
|
578 |
-
$this->setMobile(true);
|
579 |
-
|
580 |
-
if( stripos($this->_agent,'mspie') !== false ) {
|
581 |
-
$this->setVersion($aresult[1]);
|
582 |
-
}
|
583 |
-
else {
|
584 |
-
$aversion = explode('/',$this->_agent);
|
585 |
-
$this->setVersion($aversion[1]);
|
586 |
-
}
|
587 |
-
return true;
|
588 |
-
}
|
589 |
-
return false;
|
590 |
-
}
|
591 |
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
$this->setVersion($aversion[0]);
|
603 |
-
}
|
604 |
-
else {
|
605 |
-
$aversion = explode(' ',stristr($resultant,'opera mini'));
|
606 |
-
$this->setVersion($aversion[1]);
|
607 |
-
}
|
608 |
-
$this->_browser_name = $this->BROWSER_OPERA_MINI;
|
609 |
-
$this->setMobile(true);
|
610 |
-
return true;
|
611 |
-
}
|
612 |
-
else if( stripos($this->_agent,'opera') !== false ) {
|
613 |
-
$resultant = stristr($this->_agent, 'opera');
|
614 |
-
if( preg_match('/Version\/(10.*)$/',$resultant,$matches) ) {
|
615 |
-
$this->setVersion($matches[1]);
|
616 |
-
}
|
617 |
-
else if( preg_match('/\//',$resultant) ) {
|
618 |
-
$aresult = explode('/',str_replace("("," ",$resultant));
|
619 |
-
$aversion = explode(' ',$aresult[1]);
|
620 |
-
$this->setVersion($aversion[0]);
|
621 |
-
}
|
622 |
-
else {
|
623 |
-
$aversion = explode(' ',stristr($resultant,'opera'));
|
624 |
-
$this->setVersion(isset($aversion[1])?$aversion[1]:"");
|
625 |
-
}
|
626 |
-
$this->_browser_name = $this->BROWSER_OPERA;
|
627 |
-
return true;
|
628 |
-
}
|
629 |
-
return false;
|
630 |
-
}
|
631 |
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
646 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
647 |
|
648 |
-
/**
|
649 |
-
* Determine if the browser is WebTv or not (last updated 1.7)
|
650 |
-
* @return boolean True if the browser is WebTv otherwise false
|
651 |
-
*/
|
652 |
-
function checkBrowserWebTv() {
|
653 |
-
if( stripos($this->_agent,'webtv') !== false ) {
|
654 |
-
$aresult = explode('/',stristr($this->_agent,'webtv'));
|
655 |
-
$aversion = explode(' ',$aresult[1]);
|
656 |
-
$this->setVersion($aversion[0]);
|
657 |
-
$this->setBrowser($this->BROWSER_WEBTV);
|
658 |
-
return true;
|
659 |
-
}
|
660 |
-
return false;
|
661 |
-
}
|
662 |
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
|
|
677 |
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
|
|
692 |
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
|
|
707 |
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
|
|
|
|
721 |
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
|
|
|
|
750 |
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
|
|
764 |
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
return true;
|
780 |
-
}
|
781 |
-
return false;
|
782 |
-
}
|
783 |
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
796 |
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
|
|
809 |
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
$this->setMobile(true);
|
824 |
-
return true;
|
825 |
-
}
|
826 |
-
return false;
|
827 |
-
}
|
828 |
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
$this->setVersion("");
|
842 |
-
$this->setBrowser($this->BROWSER_FIREFOX);
|
843 |
-
return true;
|
844 |
-
}
|
845 |
}
|
846 |
-
|
847 |
-
|
|
|
|
|
|
|
848 |
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
$this->setVersion($
|
858 |
-
$this->setBrowser($this->
|
|
|
|
|
|
|
|
|
859 |
return true;
|
860 |
}
|
861 |
-
return false;
|
862 |
}
|
863 |
-
|
864 |
-
|
865 |
-
* @return boolean True if the browser is Mozilla otherwise false
|
866 |
-
*/
|
867 |
-
function checkBrowserMozilla() {
|
868 |
-
if( stripos($this->_agent,'mozilla') !== false && preg_match('/rv:[0-9].[0-9][a-b]?/i',$this->_agent) && stripos($this->_agent,'netscape') === false) {
|
869 |
-
$aversion = explode(' ',stristr($this->_agent,'rv:'));
|
870 |
-
preg_match('/rv:[0-9].[0-9][a-b]?/i',$this->_agent,$aversion);
|
871 |
-
$this->setVersion(str_replace('rv:','',$aversion[0]));
|
872 |
-
$this->setBrowser($this->BROWSER_MOZILLA);
|
873 |
-
return true;
|
874 |
-
}
|
875 |
-
else if( stripos($this->_agent,'mozilla') !== false && preg_match('/rv:[0-9]\.[0-9]/i',$this->_agent) && stripos($this->_agent,'netscape') === false ) {
|
876 |
-
$aversion = explode('',stristr($this->_agent,'rv:'));
|
877 |
-
$this->setVersion(str_replace('rv:','',$aversion[0]));
|
878 |
-
$this->setBrowser($this->BROWSER_MOZILLA);
|
879 |
-
return true;
|
880 |
-
}
|
881 |
-
else if( stripos($this->_agent,'mozilla') !== false && preg_match('/mozilla\/([^ ]*)/i',$this->_agent,$matches) && stripos($this->_agent,'netscape') === false ) {
|
882 |
-
$this->setVersion($matches[1]);
|
883 |
-
$this->setBrowser($this->BROWSER_MOZILLA);
|
884 |
-
return true;
|
885 |
-
}
|
886 |
-
return false;
|
887 |
-
}
|
888 |
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
903 |
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
|
|
918 |
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
return true;
|
935 |
-
}
|
936 |
-
return false;
|
937 |
-
}
|
938 |
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
}
|
959 |
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
|
1010 |
-
|
1011 |
-
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
1043 |
-
$this->_platform = $this->PLATFORM_ANDROID;
|
1044 |
-
}
|
1045 |
-
elseif( stripos($this->_agent, 'linux') !== false ) {
|
1046 |
-
$this->_platform = $this->PLATFORM_LINUX;
|
1047 |
-
}
|
1048 |
-
else if( stripos($this->_agent, 'Nokia') !== false ) {
|
1049 |
-
$this->_platform = $this->PLATFORM_NOKIA;
|
1050 |
-
}
|
1051 |
-
else if( stripos($this->_agent, 'BlackBerry') !== false ) {
|
1052 |
-
$this->_platform = $this->PLATFORM_BLACKBERRY;
|
1053 |
-
}
|
1054 |
-
elseif( stripos($this->_agent,'FreeBSD') !== false ) {
|
1055 |
-
$this->_platform = $this->PLATFORM_FREEBSD;
|
1056 |
-
}
|
1057 |
-
elseif( stripos($this->_agent,'OpenBSD') !== false ) {
|
1058 |
-
$this->_platform = $this->PLATFORM_OPENBSD;
|
1059 |
-
}
|
1060 |
-
elseif( stripos($this->_agent,'NetBSD') !== false ) {
|
1061 |
-
$this->_platform = $this->PLATFORM_NETBSD;
|
1062 |
-
}
|
1063 |
-
elseif( stripos($this->_agent, 'OpenSolaris') !== false ) {
|
1064 |
-
$this->_platform = $this->PLATFORM_OPENSOLARIS;
|
1065 |
-
}
|
1066 |
-
elseif( stripos($this->_agent, 'SunOS') !== false ) {
|
1067 |
-
$this->_platform = $this->PLATFORM_SUNOS;
|
1068 |
-
}
|
1069 |
-
elseif( stripos($this->_agent, 'OS\/2') !== false ) {
|
1070 |
-
$this->_platform = $this->PLATFORM_OS2;
|
1071 |
-
}
|
1072 |
-
elseif( stripos($this->_agent, 'BeOS') !== false ) {
|
1073 |
-
$this->_platform = $this->PLATFORM_BEOS;
|
1074 |
-
}
|
1075 |
-
elseif( stripos($this->_agent, 'win') !== false ) {
|
1076 |
-
$this->_platform = $this->PLATFORM_WINDOWS;
|
1077 |
-
}
|
1078 |
|
1079 |
-
|
1080 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1081 |
|
1082 |
-
|
|
1 |
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Modified to remove var
|
8 |
+
* Chris Christoff on 12/26/2012
|
9 |
+
* Changes: Changes vars to publics
|
10 |
+
*
|
11 |
+
* Modified to work for EDD by
|
12 |
+
* Chris Christoff on 12/23/2012
|
13 |
+
* Changes: Removed the browser string return and added spacing. Also removed return HTML formatting.
|
14 |
+
*
|
15 |
+
* Modified to add formatted User Agent string for EDD System Info by
|
16 |
+
* Chris Christoff on 12/23/2012
|
17 |
+
* Changes: Split user string and add formatting so we can print a nicely
|
18 |
+
* formatted user agent string on the EDD System Info
|
19 |
+
*
|
20 |
+
* File: Browser.php
|
21 |
+
* Author: Chris Schuld (http://chrisschuld.com/)
|
22 |
+
* Last Modified: August 20th, 2010
|
23 |
+
*
|
24 |
+
* @version 1.9
|
25 |
+
* @package PegasusPHP
|
26 |
+
*
|
27 |
+
* Copyright (C) 2008-2010 Chris Schuld (chris@chrisschuld.com)
|
28 |
+
*
|
29 |
+
* This program is free software; you can redistribute it and/or
|
30 |
+
* modify it under the terms of the GNU General Public License as
|
31 |
+
* published by the Free Software Foundation; either version 2 of
|
32 |
+
* the License, or (at your option) any later version.
|
33 |
+
*
|
34 |
+
* This program is distributed in the hope that it will be useful,
|
35 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
36 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
37 |
+
* GNU General Public License for more details at:
|
38 |
+
* http://www.gnu.org/copyleft/gpl.html
|
39 |
+
*
|
40 |
+
*
|
41 |
+
* Typical Usage:
|
42 |
+
*
|
43 |
+
* $browser = new Browser();
|
44 |
+
* if( $browser->getBrowser() == Browser::BROWSER_FIREFOX && $browser->getVersion() >= 2 ) {
|
45 |
+
* echo 'You have FireFox version 2 or greater';
|
46 |
+
* }
|
47 |
+
*
|
48 |
+
* User Agents Sampled from: http://www.useragentstring.com/
|
49 |
+
*
|
50 |
+
* This implementation is based on the original work from Gary White
|
51 |
+
* http://apptools.com/phptools/browser/
|
52 |
+
*
|
53 |
+
* UPDATES:
|
54 |
+
*
|
55 |
+
* 2010-08-20 (v1.9):
|
56 |
+
* + Added MSN Explorer Browser (legacy)
|
57 |
+
* + Added Bing/MSN Robot (Thanks Rob MacDonald)
|
58 |
+
* + Added the Android Platform (PLATFORM_ANDROID)
|
59 |
+
* + Fixed issue with Android 1.6/2.2 (Thanks Tom Hirashima)
|
60 |
+
*
|
61 |
+
* 2010-04-27 (v1.8):
|
62 |
+
* + Added iPad Support
|
63 |
+
*
|
64 |
+
* 2010-03-07 (v1.7):
|
65 |
+
* + *MAJOR* Rebuild (preg_match and other "slow" routine removal(s))
|
66 |
+
* + Almost allof Gary's original code has been replaced
|
67 |
+
* + Large PHPUNIT testing environment created to validate new releases and additions
|
68 |
+
* + Added FreeBSD Platform
|
69 |
+
* + Added OpenBSD Platform
|
70 |
+
* + Added NetBSD Platform
|
71 |
+
* + Added SunOS Platform
|
72 |
+
* + Added OpenSolaris Platform
|
73 |
+
* + Added support of the Iceweazel Browser
|
74 |
+
* + Added isChromeFrame() call to check if chromeframe is in use
|
75 |
+
* + Moved the Opera check in front of the Firefox check due to legacy Opera User Agents
|
76 |
+
* + Added the __toString() method (Thanks Deano)
|
77 |
+
*
|
78 |
+
* 2009-11-15:
|
79 |
+
* + Updated the checkes for Firefox
|
80 |
+
* + Added the NOKIA platform
|
81 |
+
* + Added Checks for the NOKIA brower(s)
|
82 |
+
*
|
83 |
+
* 2009-11-08:
|
84 |
+
* + PHP 5.3 Support
|
85 |
+
* + Added support for BlackBerry OS and BlackBerry browser
|
86 |
+
* + Added support for the Opera Mini browser
|
87 |
+
* + Added additional documenation
|
88 |
+
* + Added support for isRobot() and isMobile()
|
89 |
+
* + Added support for Opera version 10
|
90 |
+
* + Added support for deprecated Netscape Navigator version 9
|
91 |
+
* + Added support for IceCat
|
92 |
+
* + Added support for Shiretoko
|
93 |
+
*
|
94 |
+
* 2010-04-27 (v1.8):
|
95 |
+
* + Added iPad Support
|
96 |
+
*
|
97 |
+
* 2009-08-18:
|
98 |
+
* + Updated to support PHP 5.3 - removed all deprecated function calls
|
99 |
+
* + Updated to remove all double quotes (") -- converted to single quotes (')
|
100 |
+
*
|
101 |
+
* 2009-04-27:
|
102 |
+
* + Updated the IE check to remove a typo and bug (thanks John)
|
103 |
+
*
|
104 |
+
* 2009-04-22:
|
105 |
+
* + Added detection for GoogleBot
|
106 |
+
* + Added detection for the W3C Validator.
|
107 |
+
* + Added detection for Yahoo! Slurp
|
108 |
+
*
|
109 |
+
* 2009-03-14:
|
110 |
+
* + Added detection for iPods.
|
111 |
+
* + Added Platform detection for iPhones
|
112 |
+
* + Added Platform detection for iPods
|
113 |
+
*
|
114 |
+
* 2009-02-16: (Rick Hale)
|
115 |
+
* + Added version detection for Android phones.
|
116 |
+
*
|
117 |
+
* 2008-12-09:
|
118 |
+
* + Removed unused constant
|
119 |
+
*
|
120 |
+
* 2008-11-07:
|
121 |
+
* + Added Google's Chrome to the detection list
|
122 |
+
* + Added isBrowser(string) to the list of functions special thanks to
|
123 |
+
* Daniel 'mavrick' Lang for the function concept (http://mavrick.id.au)
|
124 |
+
*
|
125 |
+
*
|
126 |
+
* Gary White noted: "Since browser detection is so unreliable, I am
|
127 |
+
* no longer maintaining this script. You are free to use and or
|
128 |
+
* modify/update it as you want, however the author assumes no
|
129 |
+
* responsibility for the accuracy of the detected values."
|
130 |
+
*
|
131 |
+
* Anyone experienced with Gary's script might be interested in these notes:
|
132 |
+
*
|
133 |
+
* Added class constants
|
134 |
+
* Added detection and version detection for Google's Chrome
|
135 |
+
* Updated the version detection for Amaya
|
136 |
+
* Updated the version detection for Firefox
|
137 |
+
* Updated the version detection for Lynx
|
138 |
+
* Updated the version detection for WebTV
|
139 |
+
* Updated the version detection for NetPositive
|
140 |
+
* Updated the version detection for IE
|
141 |
+
* Updated the version detection for OmniWeb
|
142 |
+
* Updated the version detection for iCab
|
143 |
+
* Updated the version detection for Safari
|
144 |
+
* Updated Safari to remove mobile devices (iPhone)
|
145 |
+
* Added detection for iPhone
|
146 |
+
* Added detection for robots
|
147 |
+
* Added detection for mobile devices
|
148 |
+
* Added detection for BlackBerry
|
149 |
+
* Removed Netscape checks (matches heavily with firefox & mozilla)
|
150 |
+
*
|
151 |
+
*/
|
152 |
+
|
153 |
+
class Browser {
|
154 |
+
public $_agent = '';
|
155 |
+
public $_browser_name = '';
|
156 |
+
public $_version = '';
|
157 |
+
public $_platform = '';
|
158 |
+
public $_os = '';
|
159 |
+
public $_is_aol = false;
|
160 |
+
public $_is_mobile = false;
|
161 |
+
public $_is_robot = false;
|
162 |
+
public $_aol_version = '';
|
163 |
+
|
164 |
+
public $BROWSER_UNKNOWN = 'unknown';
|
165 |
+
public $VERSION_UNKNOWN = 'unknown';
|
166 |
+
|
167 |
+
public $BROWSER_OPERA = 'Opera'; // Http://www.opera.com/
|
168 |
+
public $BROWSER_OPERA_MINI = 'Opera Mini'; // Http://www.opera.com/mini/
|
169 |
+
public $BROWSER_WEBTV = 'WebTV'; // Http://www.webtv.net/pc/
|
170 |
+
public $BROWSER_IE = 'Internet Explorer'; // Http://www.microsoft.com/ie/
|
171 |
+
public $BROWSER_POCKET_IE = 'Pocket Internet Explorer'; // Http://en.wikipedia.org/wiki/Internet_Explorer_Mobile
|
172 |
+
public $BROWSER_KONQUEROR = 'Konqueror'; // Http://www.konqueror.org/
|
173 |
+
public $BROWSER_ICAB = 'iCab'; // Http://www.icab.de/
|
174 |
+
public $BROWSER_OMNIWEB = 'OmniWeb'; // Http://www.omnigroup.com/applications/omniweb/
|
175 |
+
public $BROWSER_FIREBIRD = 'Firebird'; // Http://www.ibphoenix.com/
|
176 |
+
public $BROWSER_FIREFOX = 'Firefox'; // Http://www.mozilla.com/en-US/firefox/firefox.html
|
177 |
+
public $BROWSER_ICEWEASEL = 'Iceweasel'; // Http://www.geticeweasel.org/
|
178 |
+
public $BROWSER_SHIRETOKO = 'Shiretoko'; // Http://wiki.mozilla.org/Projects/shiretoko
|
179 |
+
public $BROWSER_MOZILLA = 'Mozilla'; // Http://www.mozilla.com/en-US/
|
180 |
+
public $BROWSER_AMAYA = 'Amaya'; // Http://www.w3.org/Amaya/
|
181 |
+
public $BROWSER_LYNX = 'Lynx'; // Http://en.wikipedia.org/wiki/Lynx
|
182 |
+
public $BROWSER_SAFARI = 'Safari'; // Http://apple.com
|
183 |
+
public $BROWSER_IPHONE = 'iPhone'; // Http://apple.com
|
184 |
+
public $BROWSER_IPOD = 'iPod'; // Http://apple.com
|
185 |
+
public $BROWSER_IPAD = 'iPad'; // Http://apple.com
|
186 |
+
public $BROWSER_CHROME = 'Chrome'; // Http://www.google.com/chrome
|
187 |
+
public $BROWSER_ANDROID = 'Android'; // Http://www.android.com/
|
188 |
+
public $BROWSER_GOOGLEBOT = 'GoogleBot'; // Http://en.wikipedia.org/wiki/Googlebot
|
189 |
+
public $BROWSER_SLURP = 'Yahoo! Slurp'; // Http://en.wikipedia.org/wiki/Yahoo!_Slurp
|
190 |
+
public $BROWSER_W3CVALIDATOR = 'W3C Validator'; // Http://validator.w3.org/
|
191 |
+
public $BROWSER_BLACKBERRY = 'BlackBerry'; // Http://www.blackberry.com/
|
192 |
+
public $BROWSER_ICECAT = 'IceCat'; // Http://en.wikipedia.org/wiki/GNU_IceCat
|
193 |
+
public $BROWSER_NOKIA_S60 = 'Nokia S60 OSS Browser'; // Http://en.wikipedia.org/wiki/Web_Browser_for_S60
|
194 |
+
public $BROWSER_NOKIA = 'Nokia Browser'; // * all other WAP-based browsers on the Nokia Platform
|
195 |
+
public $BROWSER_MSN = 'MSN Browser'; // Http://explorer.msn.com/
|
196 |
+
public $BROWSER_MSNBOT = 'MSN Bot'; // Http://search.msn.com/msnbot.htm
|
197 |
+
// Http://en.wikipedia.org/wiki/Msnbot (used for Bing as well)
|
198 |
+
|
199 |
+
public $BROWSER_NETSCAPE_NAVIGATOR = 'Netscape Navigator'; // Http://browser.netscape.com/ (DEPRECATED)
|
200 |
+
public $BROWSER_GALEON = 'Galeon'; // Http://galeon.sourceforge.net/ (DEPRECATED)
|
201 |
+
public $BROWSER_NETPOSITIVE = 'NetPositive'; // Http://en.wikipedia.org/wiki/NetPositive (DEPRECATED)
|
202 |
+
public $BROWSER_PHOENIX = 'Phoenix'; // Http://en.wikipedia.org/wiki/History_of_Mozilla_Firefox (DEPRECATED)
|
203 |
+
|
204 |
+
public $PLATFORM_UNKNOWN = 'unknown';
|
205 |
+
public $PLATFORM_WINDOWS = 'Windows';
|
206 |
+
public $PLATFORM_WINDOWS_CE = 'Windows CE';
|
207 |
+
public $PLATFORM_APPLE = 'Apple';
|
208 |
+
public $PLATFORM_LINUX = 'Linux';
|
209 |
+
public $PLATFORM_OS2 = 'OS/2';
|
210 |
+
public $PLATFORM_BEOS = 'BeOS';
|
211 |
+
public $PLATFORM_IPHONE = 'iPhone';
|
212 |
+
public $PLATFORM_IPOD = 'iPod';
|
213 |
+
public $PLATFORM_IPAD = 'iPad';
|
214 |
+
public $PLATFORM_BLACKBERRY = 'BlackBerry';
|
215 |
+
public $PLATFORM_NOKIA = 'Nokia';
|
216 |
+
public $PLATFORM_FREEBSD = 'FreeBSD';
|
217 |
+
public $PLATFORM_OPENBSD = 'OpenBSD';
|
218 |
+
public $PLATFORM_NETBSD = 'NetBSD';
|
219 |
+
public $PLATFORM_SUNOS = 'SunOS';
|
220 |
+
public $PLATFORM_OPENSOLARIS = 'OpenSolaris';
|
221 |
+
public $PLATFORM_ANDROID = 'Android';
|
222 |
+
|
223 |
+
public $OPERATING_SYSTEM_UNKNOWN = 'unknown';
|
224 |
+
|
225 |
+
function Browser( $useragent="" ) {
|
226 |
+
$this->reset();
|
227 |
+
if ( $useragent != "" ) {
|
228 |
+
$this->setUserAgent( $useragent );
|
229 |
+
} else {
|
230 |
+
$this->determine();
|
231 |
+
}
|
232 |
+
}
|
233 |
+
|
234 |
/**
|
235 |
+
* Reset all properties
|
236 |
+
*/
|
237 |
+
function reset() {
|
238 |
+
$this->_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : "";
|
239 |
+
$this->_browser_name = $this->BROWSER_UNKNOWN;
|
240 |
+
$this->_version = $this->VERSION_UNKNOWN;
|
241 |
+
$this->_platform = $this->PLATFORM_UNKNOWN;
|
242 |
+
$this->_os = $this->OPERATING_SYSTEM_UNKNOWN;
|
243 |
+
$this->_is_aol = false;
|
244 |
+
$this->_is_mobile = false;
|
245 |
+
$this->_is_robot = false;
|
246 |
+
$this->_aol_version = $this->VERSION_UNKNOWN;
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Check to see if the specific browser is valid
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
251 |
*
|
252 |
+
* @param string $browserName
|
253 |
+
* @return True if the browser is the specified browser
|
254 |
+
*/
|
255 |
+
function isBrowser( $browserName ) { return 0 == strcasecmp( $this->_browser_name, trim( $browserName ) ); }
|
256 |
+
|
257 |
+
/**
|
258 |
+
* The name of the browser. All return types are from the class contants
|
259 |
*
|
260 |
+
* @return string Name of the browser
|
261 |
+
*/
|
262 |
+
function getBrowser() { return $this->_browser_name; }
|
263 |
+
/**
|
264 |
+
* Set the name of the browser
|
265 |
*
|
266 |
+
* @param unknown $browser The name of the Browser
|
267 |
+
*/
|
268 |
+
function setBrowser( $browser ) { return $this->_browser_name = $browser; }
|
269 |
+
/**
|
270 |
+
* The name of the platform. All return types are from the class contants
|
271 |
*
|
272 |
+
* @return string Name of the browser
|
273 |
+
*/
|
274 |
+
function getPlatform() { return $this->_platform; }
|
275 |
+
/**
|
276 |
+
* Set the name of the platform
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
277 |
*
|
278 |
+
* @param unknown $platform The name of the Platform
|
279 |
+
*/
|
280 |
+
function setPlatform( $platform ) { return $this->_platform = $platform; }
|
281 |
+
/**
|
282 |
+
* The version of the browser.
|
283 |
*
|
284 |
+
* @return string Version of the browser (will only contain alpha-numeric characters and a period)
|
285 |
+
*/
|
286 |
+
function getVersion() { return $this->_version; }
|
287 |
+
/**
|
288 |
+
* Set the version of the browser
|
|
|
|
|
|
|
|
|
|
|
289 |
*
|
290 |
+
* @param unknown $version The version of the Browser
|
291 |
+
*/
|
292 |
+
function setVersion( $version ) { $this->_version = preg_replace( '/[^0-9,.,a-z,A-Z-]/', '', $version ); }
|
293 |
+
/**
|
294 |
+
* The version of AOL.
|
295 |
*
|
296 |
+
* @return string Version of AOL (will only contain alpha-numeric characters and a period)
|
297 |
+
*/
|
298 |
+
function getAolVersion() { return $this->_aol_version; }
|
299 |
+
/**
|
300 |
+
* Set the version of AOL
|
301 |
*
|
302 |
+
* @param unknown $version The version of AOL
|
303 |
+
*/
|
304 |
+
function setAolVersion( $version ) { $this->_aol_version = preg_replace( '/[^0-9,.,a-z,A-Z]/', '', $version ); }
|
305 |
+
/**
|
306 |
+
* Is the browser from AOL?
|
307 |
*
|
308 |
+
* @return boolean True if the browser is from AOL otherwise false
|
309 |
+
*/
|
310 |
+
function isAol() { return $this->_is_aol; }
|
311 |
+
/**
|
312 |
+
* Is the browser from a mobile device?
|
313 |
*
|
314 |
+
* @return boolean True if the browser is from a mobile device otherwise false
|
315 |
+
*/
|
316 |
+
function isMobile() { return $this->_is_mobile; }
|
317 |
+
/**
|
318 |
+
* Is the browser from a robot (ex Slurp,GoogleBot)?
|
319 |
*
|
320 |
+
* @return boolean True if the browser is from a robot otherwise false
|
321 |
+
*/
|
322 |
+
function isRobot() { return $this->_is_robot; }
|
323 |
+
/**
|
324 |
+
* Set the browser to be from AOL
|
325 |
*
|
326 |
+
* @param unknown $isAol
|
327 |
+
*/
|
328 |
+
function setAol( $isAol ) { $this->_is_aol = $isAol; }
|
329 |
+
/**
|
330 |
+
* Set the Browser to be mobile
|
331 |
*
|
332 |
+
* @param boolean $value is the browser a mobile brower or not
|
333 |
+
*/
|
334 |
+
function setMobile( $value=true ) { $this->_is_mobile = $value; }
|
335 |
+
/**
|
336 |
+
* Set the Browser to be a robot
|
337 |
*
|
338 |
+
* @param boolean $value is the browser a robot or not
|
339 |
+
*/
|
340 |
+
function setRobot( $value=true ) { $this->_is_robot = $value; }
|
341 |
+
/**
|
342 |
+
* Get the user agent value in use to determine the browser
|
343 |
*
|
344 |
+
* @return string The user agent from the HTTP header
|
345 |
+
*/
|
346 |
+
function getUserAgent() { return $this->_agent; }
|
347 |
+
/**
|
348 |
+
* Set the user agent value (the construction will use the HTTP header value - this will overwrite it)
|
349 |
*
|
350 |
+
* @param unknown $agent_string The value for the User Agent
|
351 |
+
*/
|
352 |
+
function setUserAgent( $agent_string ) {
|
353 |
+
$this->reset();
|
354 |
+
$this->_agent = $agent_string;
|
355 |
+
$this->determine();
|
356 |
+
}
|
357 |
+
/**
|
358 |
+
* Used to determine if the browser is actually "chromeframe"
|
359 |
*
|
360 |
+
* @since 1.7
|
361 |
+
* @return boolean True if the browser is using chromeframe
|
362 |
+
*/
|
363 |
+
function isChromeFrame() {
|
364 |
+
return strpos( $this->_agent, "chromeframe" ) !== false;
|
365 |
+
}
|
366 |
+
/**
|
367 |
+
* Returns a formatted string with a summary of the details of the browser.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
368 |
*
|
369 |
+
* @return string formatted string with a summary of the browser
|
370 |
*/
|
371 |
+
function __toString() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
372 |
$text1 = $this->getUserAgent(); //grabs the UA (user agent) string
|
373 |
+
$UAline1 = substr( $text1, 0, 32 ); //the first line we print should only be the first 32 characters of the UA string
|
374 |
$text2 = $this->getUserAgent();//now we grab it again and save it to a string
|
375 |
+
$towrapUA = str_replace( $UAline1, '', $text2 );//the rest of the printoff (other than first line) is equivolent
|
376 |
// To the whole string minus the part we printed off. IE
|
377 |
// User Agent: thefirst32charactersfromUAline1
|
378 |
// the rest of it is now stored in
|
379 |
// $text2 to be printed off
|
380 |
// But we need to add spaces before each line that is split other than line 1
|
381 |
$space = '';
|
382 |
+
for ( $i = 0; $i < 25; $i++ ) {
|
383 |
+
$space .= ' ';
|
384 |
}
|
385 |
// Now we split the remaining string of UA ($text2) into lines that are prefixed by spaces for formatting
|
386 |
+
$wordwrapped = chunk_split( $towrapUA, 32, "\n $space" );
|
387 |
+
return "Platform: {$this->getPlatform()} \n".
|
388 |
+
"Browser Name: {$this->getBrowser()} \n" .
|
389 |
+
"Browser Version: {$this->getVersion()} \n" .
|
390 |
+
"User Agent String: $UAline1 \n\t\t\t " .
|
391 |
+
"$wordwrapped";
|
392 |
+
}
|
393 |
+
/**
|
394 |
+
* Protected routine to calculate and determine what the browser is in use (including platform)
|
395 |
+
*/
|
396 |
+
function determine() {
|
397 |
+
$this->checkPlatform();
|
398 |
+
$this->checkBrowsers();
|
399 |
+
$this->checkForAol();
|
400 |
+
}
|
401 |
+
/**
|
402 |
+
* Protected routine to determine the browser type
|
403 |
+
*
|
404 |
+
* @return boolean True if the browser was detected otherwise false
|
405 |
+
*/
|
406 |
+
function checkBrowsers() {
|
407 |
+
return (
|
408 |
+
// Well-known, well-used
|
409 |
+
// Special Notes:
|
410 |
+
// (1) Opera must be checked before FireFox due to the odd
|
411 |
+
// user agents used in some older versions of Opera
|
412 |
+
// (2) WebTV is strapped onto Internet Explorer so we must
|
413 |
+
// check for WebTV before IE
|
414 |
+
// (3) (deprecated) Galeon is based on Firefox and needs to be
|
415 |
+
// tested before Firefox is tested
|
416 |
+
// (4) OmniWeb is based on Safari so OmniWeb check must occur
|
417 |
+
// before Safari
|
418 |
+
// (5) Netscape 9+ is based on Firefox so Netscape checks
|
419 |
+
// before FireFox are necessary
|
420 |
+
$this->checkBrowserWebTv() ||
|
421 |
+
$this->checkBrowserInternetExplorer() ||
|
422 |
+
$this->checkBrowserOpera() ||
|
423 |
+
$this->checkBrowserGaleon() ||
|
424 |
+
$this->checkBrowserNetscapeNavigator9Plus() ||
|
425 |
+
$this->checkBrowserFirefox() ||
|
426 |
+
$this->checkBrowserChrome() ||
|
427 |
+
$this->checkBrowserOmniWeb() ||
|
428 |
|
429 |
+
// Common mobile
|
430 |
+
$this->checkBrowserAndroid() ||
|
431 |
+
$this->checkBrowseriPad() ||
|
432 |
+
$this->checkBrowseriPod() ||
|
433 |
+
$this->checkBrowseriPhone() ||
|
434 |
+
$this->checkBrowserBlackBerry() ||
|
435 |
+
$this->checkBrowserNokia() ||
|
436 |
|
437 |
+
// Common bots
|
438 |
+
$this->checkBrowserGoogleBot() ||
|
439 |
+
$this->checkBrowserMSNBot() ||
|
440 |
+
$this->checkBrowserSlurp() ||
|
441 |
|
442 |
+
// WebKit base check (post mobile and others)
|
443 |
+
$this->checkBrowserSafari() ||
|
444 |
|
445 |
+
// Everyone else
|
446 |
+
$this->checkBrowserNetPositive() ||
|
447 |
+
$this->checkBrowserFirebird() ||
|
448 |
+
$this->checkBrowserKonqueror() ||
|
449 |
+
$this->checkBrowserIcab() ||
|
450 |
+
$this->checkBrowserPhoenix() ||
|
451 |
+
$this->checkBrowserAmaya() ||
|
452 |
+
$this->checkBrowserLynx() ||
|
453 |
|
454 |
+
$this->checkBrowserShiretoko() ||
|
455 |
+
$this->checkBrowserIceCat() ||
|
456 |
+
$this->checkBrowserW3CValidator() ||
|
457 |
+
$this->checkBrowserMozilla() /* Mozilla is such an open standard that you must check it last */
|
458 |
+
);
|
459 |
+
}
|
460 |
|
461 |
+
/**
|
462 |
+
* Determine if the user is using a BlackBerry (last updated 1.7)
|
463 |
+
*
|
464 |
+
* @return boolean True if the browser is the BlackBerry browser otherwise false
|
465 |
+
*/
|
466 |
+
function checkBrowserBlackBerry() {
|
467 |
+
if ( stripos( $this->_agent, 'blackberry' ) !== false ) {
|
468 |
+
$aresult = explode( "/", stristr( $this->_agent, "BlackBerry" ) );
|
469 |
+
$aversion = explode( ' ', $aresult[1] );
|
470 |
+
$this->setVersion( $aversion[0] );
|
471 |
+
$this->_browser_name = $this->BROWSER_BLACKBERRY;
|
472 |
+
$this->setMobile( true );
|
473 |
+
return true;
|
474 |
+
}
|
475 |
+
return false;
|
476 |
+
}
|
477 |
|
478 |
+
/**
|
479 |
+
* Determine if the user is using an AOL User Agent (last updated 1.7)
|
480 |
+
*
|
481 |
+
* @return boolean True if the browser is from AOL otherwise false
|
482 |
+
*/
|
483 |
+
function checkForAol() {
|
484 |
+
$this->setAol( false );
|
485 |
+
$this->setAolVersion( $this->VERSION_UNKNOWN );
|
486 |
|
487 |
+
if ( stripos( $this->_agent, 'aol' ) !== false ) {
|
488 |
+
$aversion = explode( ' ', stristr( $this->_agent, 'AOL' ) );
|
489 |
+
$this->setAol( true );
|
490 |
+
$this->setAolVersion( preg_replace( '/[^0-9\.a-z]/i', '', $aversion[1] ) );
|
491 |
+
return true;
|
492 |
+
}
|
493 |
+
return false;
|
494 |
+
}
|
495 |
|
496 |
+
/**
|
497 |
+
* Determine if the browser is the GoogleBot or not (last updated 1.7)
|
498 |
+
*
|
499 |
+
* @return boolean True if the browser is the GoogletBot otherwise false
|
500 |
+
*/
|
501 |
+
function checkBrowserGoogleBot() {
|
502 |
+
if ( stripos( $this->_agent, 'googlebot' ) !== false ) {
|
503 |
+
$aresult = explode( '/', stristr( $this->_agent, 'googlebot' ) );
|
504 |
+
$aversion = explode( ' ', $aresult[1] );
|
505 |
+
$this->setVersion( str_replace( ';', '', $aversion[0] ) );
|
506 |
+
$this->_browser_name = $this->BROWSER_GOOGLEBOT;
|
507 |
+
$this->setRobot( true );
|
508 |
+
return true;
|
509 |
+
}
|
510 |
+
return false;
|
511 |
+
}
|
512 |
|
513 |
+
/**
|
514 |
+
* Determine if the browser is the MSNBot or not (last updated 1.9)
|
515 |
+
*
|
516 |
+
* @return boolean True if the browser is the MSNBot otherwise false
|
517 |
+
*/
|
518 |
+
function checkBrowserMSNBot() {
|
519 |
+
if ( stripos( $this->_agent, "msnbot" ) !== false ) {
|
520 |
+
$aresult = explode( "/", stristr( $this->_agent, "msnbot" ) );
|
521 |
+
$aversion = explode( " ", $aresult[1] );
|
522 |
+
$this->setVersion( str_replace( ";", "", $aversion[0] ) );
|
523 |
+
$this->_browser_name = $this->BROWSER_MSNBOT;
|
524 |
+
$this->setRobot( true );
|
525 |
+
return true;
|
|
|
526 |
}
|
527 |
+
return false;
|
528 |
+
}
|
529 |
|
530 |
+
/**
|
531 |
+
* Determine if the browser is the W3C Validator or not (last updated 1.7)
|
532 |
+
*
|
533 |
+
* @return boolean True if the browser is the W3C Validator otherwise false
|
534 |
+
*/
|
535 |
+
function checkBrowserW3CValidator() {
|
536 |
+
if ( stripos( $this->_agent, 'W3C-checklink' ) !== false ) {
|
537 |
+
$aresult = explode( '/', stristr( $this->_agent, 'W3C-checklink' ) );
|
538 |
+
$aversion = explode( ' ', $aresult[1] );
|
539 |
+
$this->setVersion( $aversion[0] );
|
540 |
+
$this->_browser_name = $this->BROWSER_W3CVALIDATOR;
|
541 |
+
return true;
|
542 |
+
} else if ( stripos( $this->_agent, 'W3C_Validator' ) !== false ) {
|
543 |
+
// Some of the Validator versions do not delineate w/ a slash - add it back in
|
544 |
+
$ua = str_replace( "W3C_Validator ", "W3C_Validator/", $this->_agent );
|
545 |
+
$aresult = explode( '/', stristr( $ua, 'W3C_Validator' ) );
|
546 |
+
$aversion = explode( ' ', $aresult[1] );
|
547 |
+
$this->setVersion( $aversion[0] );
|
548 |
+
$this->_browser_name = $this->BROWSER_W3CVALIDATOR;
|
549 |
+
return true;
|
550 |
+
}
|
551 |
+
return false;
|
552 |
+
}
|
553 |
|
554 |
+
/**
|
555 |
+
* Determine if the browser is the Yahoo! Slurp Robot or not (last updated 1.7)
|
556 |
+
*
|
557 |
+
* @return boolean True if the browser is the Yahoo! Slurp Robot otherwise false
|
558 |
+
*/
|
559 |
+
function checkBrowserSlurp() {
|
560 |
+
if ( stripos( $this->_agent, 'slurp' ) !== false ) {
|
561 |
+
$aresult = explode( '/', stristr( $this->_agent, 'Slurp' ) );
|
562 |
+
$aversion = explode( ' ', $aresult[1] );
|
563 |
+
$this->setVersion( $aversion[0] );
|
564 |
+
$this->_browser_name = $this->BROWSER_SLURP;
|
565 |
+
$this->setRobot( true );
|
566 |
+
$this->setMobile( false );
|
567 |
+
return true;
|
568 |
+
}
|
569 |
+
return false;
|
570 |
+
}
|
571 |
|
572 |
+
/**
|
573 |
+
* Determine if the browser is Internet Explorer or not (last updated 1.7)
|
574 |
+
*
|
575 |
+
* @return boolean True if the browser is Internet Explorer otherwise false
|
576 |
+
*/
|
577 |
+
function checkBrowserInternetExplorer() {
|
578 |
|
579 |
+
// Test for v1 - v1.5 IE
|
580 |
+
if ( stripos( $this->_agent, 'microsoft internet explorer' ) !== false ) {
|
581 |
+
$this->setBrowser( $this->BROWSER_IE );
|
582 |
+
$this->setVersion( '1.0' );
|
583 |
+
$aresult = stristr( $this->_agent, '/' );
|
584 |
+
if ( preg_match( '/308|425|426|474|0b1/i', $aresult ) ) {
|
585 |
+
$this->setVersion( '1.5' );
|
586 |
+
}
|
587 |
+
return true;
|
588 |
+
}
|
589 |
+
// Test for versions > 1.5
|
590 |
+
else if ( stripos( $this->_agent, 'msie' ) !== false && stripos( $this->_agent, 'opera' ) === false ) {
|
591 |
+
// See if the browser is the odd MSN Explorer
|
592 |
+
if ( stripos( $this->_agent, 'msnb' ) !== false ) {
|
593 |
+
$aresult = explode( ' ', stristr( str_replace( ';', '; ', $this->_agent ), 'MSN' ) );
|
594 |
+
$this->setBrowser( $this->BROWSER_MSN );
|
595 |
+
$this->setVersion( str_replace( array( '(', ')', ';' ), '', $aresult[1] ) );
|
596 |
return true;
|
597 |
+
}
|
598 |
+
$aresult = explode( ' ', stristr( str_replace( ';', '; ', $this->_agent ), 'msie' ) );
|
599 |
+
$this->setBrowser( $this->BROWSER_IE );
|
600 |
+
$this->setVersion( str_replace( array( '(', ')', ';' ), '', $aresult[1] ) );
|
601 |
+
return true;
|
602 |
+
}
|
603 |
+
// Test for Pocket IE
|
604 |
+
else if ( stripos( $this->_agent, 'mspie' ) !== false || stripos( $this->_agent, 'pocket' ) !== false ) {
|
605 |
+
$aresult = explode( ' ', stristr( $this->_agent, 'mspie' ) );
|
606 |
+
$this->setPlatform( $this->PLATFORM_WINDOWS_CE );
|
607 |
+
$this->setBrowser( $this->BROWSER_POCKET_IE );
|
608 |
+
$this->setMobile( true );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
609 |
|
610 |
+
if ( stripos( $this->_agent, 'mspie' ) !== false ) {
|
611 |
+
$this->setVersion( $aresult[1] );
|
612 |
+
} else {
|
613 |
+
$aversion = explode( '/', $this->_agent );
|
614 |
+
$this->setVersion( $aversion[1] );
|
615 |
+
}
|
616 |
+
return true;
|
617 |
+
}
|
618 |
+
return false;
|
619 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
620 |
|
621 |
+
/**
|
622 |
+
* Determine if the browser is Opera or not (last updated 1.7)
|
623 |
+
*
|
624 |
+
* @return boolean True if the browser is Opera otherwise false
|
625 |
+
*/
|
626 |
+
function checkBrowserOpera() {
|
627 |
+
if ( stripos( $this->_agent, 'opera mini' ) !== false ) {
|
628 |
+
$resultant = stristr( $this->_agent, 'opera mini' );
|
629 |
+
if ( preg_match( '/\//', $resultant ) ) {
|
630 |
+
$aresult = explode( '/', $resultant );
|
631 |
+
$aversion = explode( ' ', $aresult[1] );
|
632 |
+
$this->setVersion( $aversion[0] );
|
633 |
+
} else {
|
634 |
+
$aversion = explode( ' ', stristr( $resultant, 'opera mini' ) );
|
635 |
+
$this->setVersion( $aversion[1] );
|
636 |
+
}
|
637 |
+
$this->_browser_name = $this->BROWSER_OPERA_MINI;
|
638 |
+
$this->setMobile( true );
|
639 |
+
return true;
|
640 |
+
} else if ( stripos( $this->_agent, 'opera' ) !== false ) {
|
641 |
+
$resultant = stristr( $this->_agent, 'opera' );
|
642 |
+
if ( preg_match( '/Version\/(10.*)$/', $resultant, $matches ) ) {
|
643 |
+
$this->setVersion( $matches[1] );
|
644 |
+
} else if ( preg_match( '/\//', $resultant ) ) {
|
645 |
+
$aresult = explode( '/', str_replace( "(", " ", $resultant ) );
|
646 |
+
$aversion = explode( ' ', $aresult[1] );
|
647 |
+
$this->setVersion( $aversion[0] );
|
648 |
+
} else {
|
649 |
+
$aversion = explode( ' ', stristr( $resultant, 'opera' ) );
|
650 |
+
$this->setVersion( isset( $aversion[1] )?$aversion[1]:"" );
|
651 |
+
}
|
652 |
+
$this->_browser_name = $this->BROWSER_OPERA;
|
653 |
+
return true;
|
654 |
+
}
|
655 |
+
return false;
|
656 |
+
}
|
657 |
|
658 |
+
/**
|
659 |
+
* Determine if the browser is Chrome or not (last updated 1.7)
|
660 |
+
*
|
661 |
+
* @return boolean True if the browser is Chrome otherwise false
|
662 |
+
*/
|
663 |
+
function checkBrowserChrome() {
|
664 |
+
if ( stripos( $this->_agent, 'Chrome' ) !== false ) {
|
665 |
+
$aresult = explode( '/', stristr( $this->_agent, 'Chrome' ) );
|
666 |
+
$aversion = explode( ' ', $aresult[1] );
|
667 |
+
$this->setVersion( $aversion[0] );
|
668 |
+
$this->setBrowser( $this->BROWSER_CHROME );
|
669 |
+
return true;
|
670 |
+
}
|
671 |
+
return false;
|
672 |
+
}
|
673 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
674 |
|
675 |
+
/**
|
676 |
+
* Determine if the browser is WebTv or not (last updated 1.7)
|
677 |
+
*
|
678 |
+
* @return boolean True if the browser is WebTv otherwise false
|
679 |
+
*/
|
680 |
+
function checkBrowserWebTv() {
|
681 |
+
if ( stripos( $this->_agent, 'webtv' ) !== false ) {
|
682 |
+
$aresult = explode( '/', stristr( $this->_agent, 'webtv' ) );
|
683 |
+
$aversion = explode( ' ', $aresult[1] );
|
684 |
+
$this->setVersion( $aversion[0] );
|
685 |
+
$this->setBrowser( $this->BROWSER_WEBTV );
|
686 |
+
return true;
|
687 |
+
}
|
688 |
+
return false;
|
689 |
+
}
|
690 |
|
691 |
+
/**
|
692 |
+
* Determine if the browser is NetPositive or not (last updated 1.7)
|
693 |
+
*
|
694 |
+
* @return boolean True if the browser is NetPositive otherwise false
|
695 |
+
*/
|
696 |
+
function checkBrowserNetPositive() {
|
697 |
+
if ( stripos( $this->_agent, 'NetPositive' ) !== false ) {
|
698 |
+
$aresult = explode( '/', stristr( $this->_agent, 'NetPositive' ) );
|
699 |
+
$aversion = explode( ' ', $aresult[1] );
|
700 |
+
$this->setVersion( str_replace( array( '(', ')', ';' ), '', $aversion[0] ) );
|
701 |
+
$this->setBrowser( $this->BROWSER_NETPOSITIVE );
|
702 |
+
return true;
|
703 |
+
}
|
704 |
+
return false;
|
705 |
+
}
|
706 |
|
707 |
+
/**
|
708 |
+
* Determine if the browser is Galeon or not (last updated 1.7)
|
709 |
+
*
|
710 |
+
* @return boolean True if the browser is Galeon otherwise false
|
711 |
+
*/
|
712 |
+
function checkBrowserGaleon() {
|
713 |
+
if ( stripos( $this->_agent, 'galeon' ) !== false ) {
|
714 |
+
$aresult = explode( ' ', stristr( $this->_agent, 'galeon' ) );
|
715 |
+
$aversion = explode( '/', $aresult[0] );
|
716 |
+
$this->setVersion( $aversion[1] );
|
717 |
+
$this->setBrowser( $this->BROWSER_GALEON );
|
718 |
+
return true;
|
719 |
+
}
|
720 |
+
return false;
|
721 |
+
}
|
722 |
|
723 |
+
/**
|
724 |
+
* Determine if the browser is Konqueror or not (last updated 1.7)
|
725 |
+
*
|
726 |
+
* @return boolean True if the browser is Konqueror otherwise false
|
727 |
+
*/
|
728 |
+
function checkBrowserKonqueror() {
|
729 |
+
if ( stripos( $this->_agent, 'Konqueror' ) !== false ) {
|
730 |
+
$aresult = explode( ' ', stristr( $this->_agent, 'Konqueror' ) );
|
731 |
+
$aversion = explode( '/', $aresult[0] );
|
732 |
+
$this->setVersion( $aversion[1] );
|
733 |
+
$this->setBrowser( $this->BROWSER_KONQUEROR );
|
734 |
+
return true;
|
735 |
+
}
|
736 |
+
return false;
|
737 |
+
}
|
738 |
|
739 |
+
/**
|
740 |
+
* Determine if the browser is iCab or not (last updated 1.7)
|
741 |
+
*
|
742 |
+
* @return boolean True if the browser is iCab otherwise false
|
743 |
+
*/
|
744 |
+
function checkBrowserIcab() {
|
745 |
+
if ( stripos( $this->_agent, 'icab' ) !== false ) {
|
746 |
+
$aversion = explode( ' ', stristr( str_replace( '/', ' ', $this->_agent ), 'icab' ) );
|
747 |
+
$this->setVersion( $aversion[1] );
|
748 |
+
$this->setBrowser( $this->BROWSER_ICAB );
|
749 |
+
return true;
|
750 |
+
}
|
751 |
+
return false;
|
752 |
+
}
|
753 |
|
754 |
+
/**
|
755 |
+
* Determine if the browser is OmniWeb or not (last updated 1.7)
|
756 |
+
*
|
757 |
+
* @return boolean True if the browser is OmniWeb otherwise false
|
758 |
+
*/
|
759 |
+
function checkBrowserOmniWeb() {
|
760 |
+
if ( stripos( $this->_agent, 'omniweb' ) !== false ) {
|
761 |
+
$aresult = explode( '/', stristr( $this->_agent, 'omniweb' ) );
|
762 |
+
$aversion = explode( ' ', isset( $aresult[1] )?$aresult[1]:"" );
|
763 |
+
$this->setVersion( $aversion[0] );
|
764 |
+
$this->setBrowser( $this->BROWSER_OMNIWEB );
|
765 |
+
return true;
|
766 |
+
}
|
767 |
+
return false;
|
768 |
+
}
|
769 |
|
770 |
+
/**
|
771 |
+
* Determine if the browser is Phoenix or not (last updated 1.7)
|
772 |
+
*
|
773 |
+
* @return boolean True if the browser is Phoenix otherwise false
|
774 |
+
*/
|
775 |
+
function checkBrowserPhoenix() {
|
776 |
+
if ( stripos( $this->_agent, 'Phoenix' ) !== false ) {
|
777 |
+
$aversion = explode( '/', stristr( $this->_agent, 'Phoenix' ) );
|
778 |
+
$this->setVersion( $aversion[1] );
|
779 |
+
$this->setBrowser( $this->BROWSER_PHOENIX );
|
780 |
+
return true;
|
781 |
+
}
|
782 |
+
return false;
|
783 |
+
}
|
784 |
|
785 |
+
/**
|
786 |
+
* Determine if the browser is Firebird or not (last updated 1.7)
|
787 |
+
*
|
788 |
+
* @return boolean True if the browser is Firebird otherwise false
|
789 |
+
*/
|
790 |
+
function checkBrowserFirebird() {
|
791 |
+
if ( stripos( $this->_agent, 'Firebird' ) !== false ) {
|
792 |
+
$aversion = explode( '/', stristr( $this->_agent, 'Firebird' ) );
|
793 |
+
$this->setVersion( $aversion[1] );
|
794 |
+
$this->setBrowser( $this->BROWSER_FIREBIRD );
|
795 |
+
return true;
|
796 |
+
}
|
797 |
+
return false;
|
798 |
+
}
|
|
|
|
|
|
|
|
|
799 |
|
800 |
+
/**
|
801 |
+
* Determine if the browser is Netscape Navigator 9+ or not (last updated 1.7)
|
802 |
+
* NOTE: (http://browser.netscape.com/ - Official support ended on March 1st, 2008)
|
803 |
+
*
|
804 |
+
* @return boolean True if the browser is Netscape Navigator 9+ otherwise false
|
805 |
+
*/
|
806 |
+
function checkBrowserNetscapeNavigator9Plus() {
|
807 |
+
if ( stripos( $this->_agent, 'Firefox' ) !== false && preg_match( '/Navigator\/([^ ]*)/i', $this->_agent, $matches ) ) {
|
808 |
+
$this->setVersion( $matches[1] );
|
809 |
+
$this->setBrowser( $this->BROWSER_NETSCAPE_NAVIGATOR );
|
810 |
+
return true;
|
811 |
+
} else if ( stripos( $this->_agent, 'Firefox' ) === false && preg_match( '/Netscape6?\/([^ ]*)/i', $this->_agent, $matches ) ) {
|
812 |
+
$this->setVersion( $matches[1] );
|
813 |
+
$this->setBrowser( $this->BROWSER_NETSCAPE_NAVIGATOR );
|
814 |
+
return true;
|
815 |
+
}
|
816 |
+
return false;
|
817 |
+
}
|
818 |
|
819 |
+
/**
|
820 |
+
* Determine if the browser is Shiretoko or not (https://wiki.mozilla.org/Projects/shiretoko) (last updated 1.7)
|
821 |
+
*
|
822 |
+
* @return boolean True if the browser is Shiretoko otherwise false
|
823 |
+
*/
|
824 |
+
function checkBrowserShiretoko() {
|
825 |
+
if ( stripos( $this->_agent, 'Mozilla' ) !== false && preg_match( '/Shiretoko\/([^ ]*)/i', $this->_agent, $matches ) ) {
|
826 |
+
$this->setVersion( $matches[1] );
|
827 |
+
$this->setBrowser( $this->BROWSER_SHIRETOKO );
|
828 |
+
return true;
|
829 |
+
}
|
830 |
+
return false;
|
831 |
+
}
|
832 |
|
833 |
+
/**
|
834 |
+
* Determine if the browser is Ice Cat or not (http://en.wikipedia.org/wiki/GNU_IceCat) (last updated 1.7)
|
835 |
+
*
|
836 |
+
* @return boolean True if the browser is Ice Cat otherwise false
|
837 |
+
*/
|
838 |
+
function checkBrowserIceCat() {
|
839 |
+
if ( stripos( $this->_agent, 'Mozilla' ) !== false && preg_match( '/IceCat\/([^ ]*)/i', $this->_agent, $matches ) ) {
|
840 |
+
$this->setVersion( $matches[1] );
|
841 |
+
$this->setBrowser( $this->BROWSER_ICECAT );
|
842 |
+
return true;
|
843 |
+
}
|
844 |
+
return false;
|
845 |
+
}
|
|
|
|
|
|
|
|
|
|
|
846 |
|
847 |
+
/**
|
848 |
+
* Determine if the browser is Nokia or not (last updated 1.7)
|
849 |
+
*
|
850 |
+
* @return boolean True if the browser is Nokia otherwise false
|
851 |
+
*/
|
852 |
+
function checkBrowserNokia() {
|
853 |
+
if ( preg_match( "/Nokia([^\/]+)\/([^ SP]+)/i", $this->_agent, $matches ) ) {
|
854 |
+
$this->setVersion( $matches[2] );
|
855 |
+
if ( stripos( $this->_agent, 'Series60' ) !== false || strpos( $this->_agent, 'S60' ) !== false ) {
|
856 |
+
$this->setBrowser( $this->BROWSER_NOKIA_S60 );
|
857 |
+
} else {
|
858 |
+
$this->setBrowser( $this->BROWSER_NOKIA );
|
|
|
|
|
|
|
|
|
859 |
}
|
860 |
+
$this->setMobile( true );
|
861 |
+
return true;
|
862 |
+
}
|
863 |
+
return false;
|
864 |
+
}
|
865 |
|
866 |
+
/**
|
867 |
+
* Determine if the browser is Firefox or not (last updated 1.7)
|
868 |
+
*
|
869 |
+
* @return boolean True if the browser is Firefox otherwise false
|
870 |
+
*/
|
871 |
+
function checkBrowserFirefox() {
|
872 |
+
if ( stripos( $this->_agent, 'safari' ) === false ) {
|
873 |
+
if ( preg_match( "/Firefox[\/ \(]([^ ;\)]+)/i", $this->_agent, $matches ) ) {
|
874 |
+
$this->setVersion( $matches[1] );
|
875 |
+
$this->setBrowser( $this->BROWSER_FIREFOX );
|
876 |
+
return true;
|
877 |
+
} else if ( preg_match( "/Firefox$/i", $this->_agent, $matches ) ) {
|
878 |
+
$this->setVersion( "" );
|
879 |
+
$this->setBrowser( $this->BROWSER_FIREFOX );
|
880 |
return true;
|
881 |
}
|
|
|
882 |
}
|
883 |
+
return false;
|
884 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
885 |
|
886 |
+
/**
|
887 |
+
* Determine if the browser is Firefox or not (last updated 1.7)
|
888 |
+
*
|
889 |
+
* @return boolean True if the browser is Firefox otherwise false
|
890 |
+
*/
|
891 |
+
function checkBrowserIceweasel() {
|
892 |
+
if ( stripos( $this->_agent, 'Iceweasel' ) !== false ) {
|
893 |
+
$aresult = explode( '/', stristr( $this->_agent, 'Iceweasel' ) );
|
894 |
+
$aversion = explode( ' ', $aresult[1] );
|
895 |
+
$this->setVersion( $aversion[0] );
|
896 |
+
$this->setBrowser( $this->BROWSER_ICEWEASEL );
|
897 |
+
return true;
|
898 |
+
}
|
899 |
+
return false;
|
900 |
+
}
|
901 |
+
/**
|
902 |
+
* Determine if the browser is Mozilla or not (last updated 1.7)
|
903 |
+
*
|
904 |
+
* @return boolean True if the browser is Mozilla otherwise false
|
905 |
+
*/
|
906 |
+
function checkBrowserMozilla() {
|
907 |
+
if ( stripos( $this->_agent, 'mozilla' ) !== false && preg_match( '/rv:[0-9].[0-9][a-b]?/i', $this->_agent ) && stripos( $this->_agent, 'netscape' ) === false ) {
|
908 |
+
$aversion = explode( ' ', stristr( $this->_agent, 'rv:' ) );
|
909 |
+
preg_match( '/rv:[0-9].[0-9][a-b]?/i', $this->_agent, $aversion );
|
910 |
+
$this->setVersion( str_replace( 'rv:', '', $aversion[0] ) );
|
911 |
+
$this->setBrowser( $this->BROWSER_MOZILLA );
|
912 |
+
return true;
|
913 |
+
} else if ( stripos( $this->_agent, 'mozilla' ) !== false && preg_match( '/rv:[0-9]\.[0-9]/i', $this->_agent ) && stripos( $this->_agent, 'netscape' ) === false ) {
|
914 |
+
$aversion = explode( '', stristr( $this->_agent, 'rv:' ) );
|
915 |
+
$this->setVersion( str_replace( 'rv:', '', $aversion[0] ) );
|
916 |
+
$this->setBrowser( $this->BROWSER_MOZILLA );
|
917 |
+
return true;
|
918 |
+
} else if ( stripos( $this->_agent, 'mozilla' ) !== false && preg_match( '/mozilla\/([^ ]*)/i', $this->_agent, $matches ) && stripos( $this->_agent, 'netscape' ) === false ) {
|
919 |
+
$this->setVersion( $matches[1] );
|
920 |
+
$this->setBrowser( $this->BROWSER_MOZILLA );
|
921 |
+
return true;
|
922 |
+
}
|
923 |
+
return false;
|
924 |
+
}
|
925 |
|
926 |
+
/**
|
927 |
+
* Determine if the browser is Lynx or not (last updated 1.7)
|
928 |
+
*
|
929 |
+
* @return boolean True if the browser is Lynx otherwise false
|
930 |
+
*/
|
931 |
+
function checkBrowserLynx() {
|
932 |
+
if ( stripos( $this->_agent, 'lynx' ) !== false ) {
|
933 |
+
$aresult = explode( '/', stristr( $this->_agent, 'Lynx' ) );
|
934 |
+
$aversion = explode( ' ', ( isset( $aresult[1] )?$aresult[1]:"" ) );
|
935 |
+
$this->setVersion( $aversion[0] );
|
936 |
+
$this->setBrowser( $this->BROWSER_LYNX );
|
937 |
+
return true;
|
938 |
+
}
|
939 |
+
return false;
|
940 |
+
}
|
941 |
|
942 |
+
/**
|
943 |
+
* Determine if the browser is Amaya or not (last updated 1.7)
|
944 |
+
*
|
945 |
+
* @return boolean True if the browser is Amaya otherwise false
|
946 |
+
*/
|
947 |
+
function checkBrowserAmaya() {
|
948 |
+
if ( stripos( $this->_agent, 'amaya' ) !== false ) {
|
949 |
+
$aresult = explode( '/', stristr( $this->_agent, 'Amaya' ) );
|
950 |
+
$aversion = explode( ' ', $aresult[1] );
|
951 |
+
$this->setVersion( $aversion[0] );
|
952 |
+
$this->setBrowser( $this->BROWSER_AMAYA );
|
953 |
+
return true;
|
954 |
+
}
|
955 |
+
return false;
|
956 |
+
}
|
|
|
|
|
|
|
|
|
957 |
|
958 |
+
/**
|
959 |
+
* Determine if the browser is Safari or not (last updated 1.7)
|
960 |
+
*
|
961 |
+
* @return boolean True if the browser is Safari otherwise false
|
962 |
+
*/
|
963 |
+
function checkBrowserSafari() {
|
964 |
+
if ( stripos( $this->_agent, 'Safari' ) !== false && stripos( $this->_agent, 'iPhone' ) === false && stripos( $this->_agent, 'iPod' ) === false ) {
|
965 |
+
$aresult = explode( '/', stristr( $this->_agent, 'Version' ) );
|
966 |
+
if ( isset( $aresult[1] ) ) {
|
967 |
+
$aversion = explode( ' ', $aresult[1] );
|
968 |
+
$this->setVersion( $aversion[0] );
|
969 |
+
} else {
|
970 |
+
$this->setVersion( $this->VERSION_UNKNOWN );
|
971 |
+
}
|
972 |
+
$this->setBrowser( $this->BROWSER_SAFARI );
|
973 |
+
return true;
|
974 |
+
}
|
975 |
+
return false;
|
976 |
+
}
|
|
|
977 |
|
978 |
+
/**
|
979 |
+
* Determine if the browser is iPhone or not (last updated 1.7)
|
980 |
+
*
|
981 |
+
* @return boolean True if the browser is iPhone otherwise false
|
982 |
+
*/
|
983 |
+
function checkBrowseriPhone() {
|
984 |
+
if ( stripos( $this->_agent, 'iPhone' ) !== false ) {
|
985 |
+
$aresult = explode( '/', stristr( $this->_agent, 'Version' ) );
|
986 |
+
if ( isset( $aresult[1] ) ) {
|
987 |
+
$aversion = explode( ' ', $aresult[1] );
|
988 |
+
$this->setVersion( $aversion[0] );
|
989 |
+
} else {
|
990 |
+
$this->setVersion( $this->VERSION_UNKNOWN );
|
991 |
+
}
|
992 |
+
$this->setMobile( true );
|
993 |
+
$this->setBrowser( $this->BROWSER_IPHONE );
|
994 |
+
return true;
|
995 |
+
}
|
996 |
+
return false;
|
997 |
+
}
|
998 |
|
999 |
+
/**
|
1000 |
+
* Determine if the browser is iPod or not (last updated 1.7)
|
1001 |
+
*
|
1002 |
+
* @return boolean True if the browser is iPod otherwise false
|
1003 |
+
*/
|
1004 |
+
function checkBrowseriPad() {
|
1005 |
+
if ( stripos( $this->_agent, 'iPad' ) !== false ) {
|
1006 |
+
$aresult = explode( '/', stristr( $this->_agent, 'Version' ) );
|
1007 |
+
if ( isset( $aresult[1] ) ) {
|
1008 |
+
$aversion = explode( ' ', $aresult[1] );
|
1009 |
+
$this->setVersion( $aversion[0] );
|
1010 |
+
} else {
|
1011 |
+
$this->setVersion( $this->VERSION_UNKNOWN );
|
1012 |
+
}
|
1013 |
+
$this->setMobile( true );
|
1014 |
+
$this->setBrowser( $this->BROWSER_IPAD );
|
1015 |
+
return true;
|
1016 |
+
}
|
1017 |
+
return false;
|
1018 |
+
}
|
1019 |
|
1020 |
+
/**
|
1021 |
+
* Determine if the browser is iPod or not (last updated 1.7)
|
1022 |
+
*
|
1023 |
+
* @return boolean True if the browser is iPod otherwise false
|
1024 |
+
*/
|
1025 |
+
function checkBrowseriPod() {
|
1026 |
+
if ( stripos( $this->_agent, 'iPod' ) !== false ) {
|
1027 |
+
$aresult = explode( '/', stristr( $this->_agent, 'Version' ) );
|
1028 |
+
if ( isset( $aresult[1] ) ) {
|
1029 |
+
$aversion = explode( ' ', $aresult[1] );
|
1030 |
+
$this->setVersion( $aversion[0] );
|
1031 |
+
} else {
|
1032 |
+
$this->setVersion( $this->VERSION_UNKNOWN );
|
1033 |
+
}
|
1034 |
+
$this->setMobile( true );
|
1035 |
+
$this->setBrowser( $this->BROWSER_IPOD );
|
1036 |
+
return true;
|
1037 |
+
}
|
1038 |
+
return false;
|
1039 |
+
}
|
1040 |
|
1041 |
+
/**
|
1042 |
+
* Determine if the browser is Android or not (last updated 1.7)
|
1043 |
+
*
|
1044 |
+
* @return boolean True if the browser is Android otherwise false
|
1045 |
+
*/
|
1046 |
+
function checkBrowserAndroid() {
|
1047 |
+
if ( stripos( $this->_agent, 'Android' ) !== false ) {
|
1048 |
+
$aresult = explode( ' ', stristr( $this->_agent, 'Android' ) );
|
1049 |
+
if ( isset( $aresult[1] ) ) {
|
1050 |
+
$aversion = explode( ' ', $aresult[1] );
|
1051 |
+
$this->setVersion( $aversion[0] );
|
1052 |
+
} else {
|
1053 |
+
$this->setVersion( $this->VERSION_UNKNOWN );
|
1054 |
+
}
|
1055 |
+
$this->setMobile( true );
|
1056 |
+
$this->setBrowser( $this->BROWSER_ANDROID );
|
1057 |
+
return true;
|
1058 |
+
}
|
1059 |
+
return false;
|
1060 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1061 |
|
1062 |
+
/**
|
1063 |
+
* Determine the user's platform (last updated 1.7)
|
1064 |
+
*/
|
1065 |
+
function checkPlatform() {
|
1066 |
+
if ( stripos( $this->_agent, 'windows' ) !== false ) {
|
1067 |
+
$this->_platform = $this->PLATFORM_WINDOWS;
|
1068 |
+
} else if ( stripos( $this->_agent, 'iPad' ) !== false ) {
|
1069 |
+
$this->_platform = $this->PLATFORM_IPAD;
|
1070 |
+
} else if ( stripos( $this->_agent, 'iPod' ) !== false ) {
|
1071 |
+
$this->_platform = $this->PLATFORM_IPOD;
|
1072 |
+
} else if ( stripos( $this->_agent, 'iPhone' ) !== false ) {
|
1073 |
+
$this->_platform = $this->PLATFORM_IPHONE;
|
1074 |
+
} elseif ( stripos( $this->_agent, 'mac' ) !== false ) {
|
1075 |
+
$this->_platform = $this->PLATFORM_APPLE;
|
1076 |
+
} elseif ( stripos( $this->_agent, 'android' ) !== false ) {
|
1077 |
+
$this->_platform = $this->PLATFORM_ANDROID;
|
1078 |
+
} elseif ( stripos( $this->_agent, 'linux' ) !== false ) {
|
1079 |
+
$this->_platform = $this->PLATFORM_LINUX;
|
1080 |
+
} else if ( stripos( $this->_agent, 'Nokia' ) !== false ) {
|
1081 |
+
$this->_platform = $this->PLATFORM_NOKIA;
|
1082 |
+
} else if ( stripos( $this->_agent, 'BlackBerry' ) !== false ) {
|
1083 |
+
$this->_platform = $this->PLATFORM_BLACKBERRY;
|
1084 |
+
} elseif ( stripos( $this->_agent, 'FreeBSD' ) !== false ) {
|
1085 |
+
$this->_platform = $this->PLATFORM_FREEBSD;
|
1086 |
+
} elseif ( stripos( $this->_agent, 'OpenBSD' ) !== false ) {
|
1087 |
+
$this->_platform = $this->PLATFORM_OPENBSD;
|
1088 |
+
} elseif ( stripos( $this->_agent, 'NetBSD' ) !== false ) {
|
1089 |
+
$this->_platform = $this->PLATFORM_NETBSD;
|
1090 |
+
} elseif ( stripos( $this->_agent, 'OpenSolaris' ) !== false ) {
|
1091 |
+
$this->_platform = $this->PLATFORM_OPENSOLARIS;
|
1092 |
+
} elseif ( stripos( $this->_agent, 'SunOS' ) !== false ) {
|
1093 |
+
$this->_platform = $this->PLATFORM_SUNOS;
|
1094 |
+
} elseif ( stripos( $this->_agent, 'OS\/2' ) !== false ) {
|
1095 |
+
$this->_platform = $this->PLATFORM_OS2;
|
1096 |
+
} elseif ( stripos( $this->_agent, 'BeOS' ) !== false ) {
|
1097 |
+
$this->_platform = $this->PLATFORM_BEOS;
|
1098 |
+
} elseif ( stripos( $this->_agent, 'win' ) !== false ) {
|
1099 |
+
$this->_platform = $this->PLATFORM_WINDOWS;
|
1100 |
+
}
|
1101 |
|
1102 |
+
}
|
1103 |
+
}
|
includes/licensing.php
CHANGED
@@ -1,783 +1,86 @@
|
|
1 |
<?php
|
2 |
|
3 |
/**
|
4 |
-
*
|
5 |
-
* This must not be a symbol that is considered to be a valid license key char.
|
6 |
*
|
7 |
-
* @since 4.
|
|
|
8 |
*/
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
* @since 4.6.10
|
15 |
-
*/
|
16 |
-
define( 'WPRSS_LICENSE_KEY_MASK_EXCLUDE_AMOUNT', -4 );
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Returns all registered addons.
|
20 |
-
*
|
21 |
-
* @since 4.4.5
|
22 |
-
*/
|
23 |
-
function wprss_get_addons() {
|
24 |
-
return apply_filters( 'wprss_register_addon', array() );
|
25 |
-
}
|
26 |
-
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Calls the EDD Software Licensing API to perform licensing tasks on the addon's store server.
|
30 |
-
*
|
31 |
-
* @since 4.4.5
|
32 |
-
*/
|
33 |
-
function wprss_edd_licensing_api( $addon, $license_key = NULL, $action = 'check_license', $return = 'license' ) {
|
34 |
-
// If no license argument was given
|
35 |
-
if ( $license_key === NULL ) {
|
36 |
-
// Get the license key
|
37 |
-
$license_key = wprss_get_license_key( $addon );
|
38 |
-
}
|
39 |
-
// Get the license status from the DB
|
40 |
-
$license_status = wprss_get_license_status( $addon );
|
41 |
-
|
42 |
-
// Prepare constants
|
43 |
-
$item_name = strtoupper( $addon );
|
44 |
-
$item_name_constant = constant( "WPRSS_{$item_name}_SL_ITEM_NAME" );
|
45 |
-
$store_url_constant = constant( "WPRSS_{$item_name}_SL_STORE_URL" );
|
46 |
-
|
47 |
-
// data to send in our API request
|
48 |
-
$api_params = array(
|
49 |
-
'edd_action' => $action,
|
50 |
-
'license' => sanitize_text_field( $license_key ),
|
51 |
-
'item_name' => urlencode( $item_name_constant ),
|
52 |
-
'url' => urlencode( network_site_url() ),
|
53 |
-
'time' => time(),
|
54 |
-
);
|
55 |
-
|
56 |
-
// Send the request to the API
|
57 |
-
$response = wp_remote_get( add_query_arg( $api_params, $store_url_constant ) );
|
58 |
-
|
59 |
-
// If the response is an error, return the value in the DB
|
60 |
-
if ( is_wp_error( $response ) ) {
|
61 |
-
wprss_log( sprintf( 'Licensing API request failed: %1$s', $response->get_error_message() ), __FUNCTION__, WPRSS_LOG_LEVEL_WARNING );
|
62 |
-
return $license_status;
|
63 |
-
}
|
64 |
-
|
65 |
-
// decode the license data
|
66 |
-
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
|
67 |
-
|
68 |
-
// Could not decode response JSON
|
69 |
-
if ( is_null( $license_data ) ) {
|
70 |
-
wprss_log( sprintf( 'Licensing API: Failed to decode response JSON' ), __FUNCTION__, WPRSS_LOG_LEVEL_WARNING );
|
71 |
-
return $license_status;
|
72 |
-
}
|
73 |
-
|
74 |
-
// Update the DB option
|
75 |
-
$license_statuses = get_option( 'wprss_settings_license_statuses' );
|
76 |
-
$license_statuses["{$addon}_license_status"] = $license_data->license;
|
77 |
-
$license_statuses["{$addon}_license_expires"] = $license_data->expires;
|
78 |
-
update_option( 'wprss_settings_license_statuses', $license_statuses );
|
79 |
-
|
80 |
-
// Return the data
|
81 |
-
if ( strtoupper( $return ) === 'ALL' ) {
|
82 |
-
return $license_data;
|
83 |
-
} else {
|
84 |
-
return isset( $license_data->{$return} ) ? $license_data->{$return} : null;
|
85 |
-
}
|
86 |
-
}
|
87 |
-
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Returns the license status. Also updates the status in the DB.
|
91 |
-
*
|
92 |
-
* @since 4.4.5
|
93 |
-
*/
|
94 |
-
function wprss_edd_check_license( $addon, $license_key = NULL, $return = 'license' ) {
|
95 |
-
return wprss_edd_licensing_api( $addon, $license_key, 'check_license', $return );
|
96 |
-
}
|
97 |
-
|
98 |
-
|
99 |
-
/**
|
100 |
-
* Activates an addon's license.
|
101 |
-
*
|
102 |
-
* @since 4.4.5
|
103 |
-
*/
|
104 |
-
function wprss_edd_activate_license( $addon, $license_key = NULL ) {
|
105 |
-
return wprss_edd_licensing_api( $addon, $license_key, 'activate_license' );
|
106 |
-
}
|
107 |
-
|
108 |
-
|
109 |
-
/**
|
110 |
-
* Deactivates an addon's license.
|
111 |
-
*
|
112 |
-
* @since 4.4.5
|
113 |
-
*/
|
114 |
-
function wprss_edd_deactivate_license( $addon, $license_key = NULL ) {
|
115 |
-
return wprss_edd_licensing_api( $addon, $license_key, 'deactivate_license' );
|
116 |
-
}
|
117 |
-
|
118 |
-
|
119 |
-
/**
|
120 |
-
* Returns an array of the default license settings. Used for plugin activation.
|
121 |
-
*
|
122 |
-
* @since 4.4.5
|
123 |
-
*
|
124 |
-
*/
|
125 |
-
function wprss_default_license_settings( $addon ) {
|
126 |
-
// Set up the default license settings
|
127 |
-
$settings = apply_filters(
|
128 |
-
'wprss_default_license_settings',
|
129 |
-
array(
|
130 |
-
"{$addon}_license_key" => FALSE,
|
131 |
-
"{$addon}_license_status" => 'invalid',
|
132 |
-
"{$addon}_license_expires" => NULL
|
133 |
-
)
|
134 |
-
);
|
135 |
-
|
136 |
-
// Return the default settings
|
137 |
-
return $settings;
|
138 |
-
}
|
139 |
-
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Returns the saved license code.
|
143 |
-
*
|
144 |
-
* @since 4.4.5
|
145 |
-
*/
|
146 |
-
function wprss_get_license_key( $addon ) {
|
147 |
-
// Get default and current options
|
148 |
-
$defaults = wprss_default_license_settings( $addon );
|
149 |
-
$keys = get_option( 'wprss_settings_license_keys', array() );
|
150 |
-
// Prepare the array key and target
|
151 |
-
$k = "{$addon}_license_key";
|
152 |
-
// Return the appropriate value
|
153 |
-
return isset( $keys["{$addon}_license_key"] )? $keys[$k] : $defaults[$k];
|
154 |
-
}
|
155 |
-
|
156 |
-
|
157 |
-
/**
|
158 |
-
* Returns the saved license code.
|
159 |
-
*
|
160 |
-
* @since 4.4.5
|
161 |
-
*/
|
162 |
-
function wprss_get_license_status( $addon ) {
|
163 |
-
// Get the default and current options
|
164 |
-
$defaults = wprss_default_license_settings( $addon );
|
165 |
-
$statuses = get_option( 'wprss_settings_license_statuses', array() );
|
166 |
-
// Prepare the key
|
167 |
-
$k = "{$addon}_license_status";
|
168 |
-
// Return the appropriate value
|
169 |
-
return isset( $statuses["{$addon}_license_status"] )? $statuses[$k] : $defaults[$k];
|
170 |
-
}
|
171 |
-
|
172 |
-
|
173 |
-
/**
|
174 |
-
* Returns the saved license expiry.
|
175 |
-
*
|
176 |
-
* @since 4.6.7
|
177 |
-
*/
|
178 |
-
function wprss_get_license_expiry( $addon ) {
|
179 |
-
// Get default and current options
|
180 |
-
$defaults = wprss_default_license_settings( $addon );
|
181 |
-
$statuses = get_option( 'wprss_settings_license_statuses', array() );
|
182 |
-
// Prepare the key
|
183 |
-
$k = "{$addon}_license_expires";
|
184 |
-
// Return the appropriate value
|
185 |
-
return isset( $statuses[$k] ) ? $statuses[$k] : $defaults[$k];
|
186 |
-
}
|
187 |
-
|
188 |
-
|
189 |
-
add_action( 'admin_init', 'wprss_check_to_show_license_notice');
|
190 |
-
/**
|
191 |
-
* Checks whether there are any invalid or expired licenses.
|
192 |
-
*
|
193 |
-
* @since 4.6.10
|
194 |
-
* @return BOOL which is TRUE if any addons are unlicensed, FALSE otherwise.
|
195 |
-
*/
|
196 |
-
function wprss_unlicensed_addons_exist() {
|
197 |
-
// Get the license statuses including expiry dates.
|
198 |
-
$statuses = get_option( 'wprss_settings_license_statuses', array() );
|
199 |
-
|
200 |
-
foreach ($statuses as $key => $value) {
|
201 |
-
if ( strpos($key, '_license_status') > 0 ) {
|
202 |
-
if ( $value !== 'valid') {
|
203 |
-
return TRUE;
|
204 |
-
}
|
205 |
-
} else if ( strpos($key, '_license_expires') > 0 ) {
|
206 |
-
// Check invalid expiry dates.
|
207 |
-
$expires = strtotime( substr( $value, 0, strpos( $value, " " ) ) );
|
208 |
-
|
209 |
-
if ( $expires == 0 || ( $expires < strtotime("+2 weeks") ) ) {
|
210 |
-
return TRUE;
|
211 |
-
}
|
212 |
-
}
|
213 |
-
}
|
214 |
-
|
215 |
-
return FALSE;
|
216 |
-
}
|
217 |
-
|
218 |
-
/**
|
219 |
-
* Check if any add-ons have a valid license and return a boolean.
|
220 |
-
*
|
221 |
-
* @since 4.6.8
|
222 |
-
*/
|
223 |
-
function wprss_is_premium_user() {
|
224 |
-
// Iterate through license statuses looking for a valid one.
|
225 |
-
$statuses = get_option('wprss_settings_license_statuses', array());
|
226 |
-
foreach ($statuses as $key => $value) {
|
227 |
-
// If we're looking at a license status key...
|
228 |
-
if (strpos($key, '_license_status') !== FALSE) {
|
229 |
-
// ...and the license is valid...
|
230 |
-
if ($value === 'valid') {
|
231 |
-
return TRUE;
|
232 |
-
}
|
233 |
-
}
|
234 |
-
}
|
235 |
-
|
236 |
-
return FALSE;
|
237 |
-
}
|
238 |
-
|
239 |
-
/**
|
240 |
-
* Returns an array of addon IDs that are licensed.
|
241 |
-
*
|
242 |
-
* @since 4.6.10
|
243 |
-
* @return Array of addon ID strings that have a valid license status.
|
244 |
-
*/
|
245 |
-
function wprss_get_licensed_addons() {
|
246 |
-
$addons = array();
|
247 |
-
|
248 |
-
// Get the license statuses.
|
249 |
-
$statuses = get_option( 'wprss_settings_license_statuses', array() );
|
250 |
-
|
251 |
-
foreach ($statuses as $key => $value) {
|
252 |
-
if ( strpos($key, '_license_status') > 0 ) {
|
253 |
-
if ( $value === 'valid') {
|
254 |
-
$addons[] = strtoupper( substr( $key, 0, strpos( $key, "_" ) ) );
|
255 |
-
}
|
256 |
-
}
|
257 |
-
}
|
258 |
-
|
259 |
-
return $addons;
|
260 |
-
|
261 |
-
}
|
262 |
-
|
263 |
-
|
264 |
-
/**
|
265 |
-
* Checks whether we should show the invalid/expired license notices.
|
266 |
-
*
|
267 |
-
* @since 4.6.10
|
268 |
-
*/
|
269 |
-
function wprss_check_to_show_license_notice() {
|
270 |
-
// Check if we found any of the licenses to be invalid, expiring or expired
|
271 |
-
// so that we can show the appropriate license nag.
|
272 |
-
if (wprss_unlicensed_addons_exist()) {
|
273 |
-
add_action( 'all_admin_notices', 'wprss_show_license_notice' );
|
274 |
-
}
|
275 |
-
}
|
276 |
-
|
277 |
-
|
278 |
-
/**
|
279 |
-
* Shows an admin notice for any invalid/expired licenses.
|
280 |
-
*
|
281 |
-
* @since 4.6.9
|
282 |
-
*/
|
283 |
-
function wprss_show_license_notice() {
|
284 |
-
// Get the license statuses including expiry dates.
|
285 |
-
$statuses = get_option( 'wprss_settings_license_statuses', array() );
|
286 |
-
|
287 |
-
// Array of notices to show.
|
288 |
-
$notices = array();
|
289 |
-
|
290 |
-
foreach ($statuses as $key => $value) {
|
291 |
-
if ( strpos($key, '_license_status') > 0 ) {
|
292 |
-
if ( $value === 'expired' ) {
|
293 |
-
// License is expired, but we'll show the notice for this when checking the *_license_expires key.
|
294 |
-
|
295 |
-
continue;
|
296 |
-
|
297 |
-
} else if ( $value !== 'valid' ) {
|
298 |
-
// The license is invalid or unactivated.
|
299 |
-
|
300 |
-
$uid = strtoupper( substr( $key, 0, strpos( $key, "_" ) ) );
|
301 |
-
|
302 |
-
// Check if the plugin is currently activated.
|
303 |
-
if ( !defined("WPRSS_{$uid}_SL_ITEM_NAME") ) {
|
304 |
-
continue;
|
305 |
-
} else {
|
306 |
-
$plugin = constant("WPRSS_{$uid}_SL_ITEM_NAME");
|
307 |
-
}
|
308 |
-
|
309 |
-
$msg = sprintf(
|
310 |
-
__( 'Remember to <a href="%s">enter your plugin license code</a> for the WP RSS Aggregator <b>%s</b> add-on to benefit from updates and support.', WPRSS_TEXT_DOMAIN ),
|
311 |
-
esc_attr(admin_url( 'edit.php?post_type=wprss_feed&page=wprss-aggregator-settings&tab=licenses_settings' )),
|
312 |
-
$plugin
|
313 |
-
);
|
314 |
-
|
315 |
-
// Save the notice we're going to display
|
316 |
-
$notices[$uid] = '<div id="wprss-license-notice-' . $uid . '" class="error wprss-license-notice"><p>' . $msg . '</p></div>';
|
317 |
-
}
|
318 |
-
} else if ( strpos($key, '_license_expires') > 0 ) {
|
319 |
-
// Check for expired licenses
|
320 |
-
|
321 |
-
$expires = strtotime( substr( $value, 0, strpos( $value, " " ) ) );
|
322 |
-
$id = substr( $key, 0, strpos( $key, "_" ) );
|
323 |
-
$uid = strtoupper($id);
|
324 |
-
|
325 |
-
$addon_notices = get_option('wprss_addon_notices');
|
326 |
-
|
327 |
-
// Check if the plugin is currently activated.
|
328 |
-
if ( !defined("WPRSS_{$uid}_SL_ITEM_NAME") ) {
|
329 |
-
continue;
|
330 |
-
} else {
|
331 |
-
$plugin = constant("WPRSS_{$uid}_SL_ITEM_NAME");
|
332 |
-
}
|
333 |
-
|
334 |
-
if ( $expires < strtotime("+2 weeks") && empty ( $addon_notices[$id]['expiry'] ) ) {
|
335 |
-
// The license is expired or expiring soon.
|
336 |
-
$license_key = wprss_get_license_key($id);
|
337 |
-
$msg = sprintf(
|
338 |
-
__('<a href="%s">Save 30%% on your license renewal</a> for the WP RSS Aggregator <b>%s</b> add-on and continue receiving updates and support.', WPRSS_TEXT_DOMAIN),
|
339 |
-
esc_attr(WPRSS_SL_STORE_URL . '/checkout/?edd_license_key=' . $license_key),
|
340 |
-
$plugin
|
341 |
-
);
|
342 |
-
|
343 |
-
// User can hide expiring/expired license messages.
|
344 |
-
$hide = '<a href="#" class="ajax-close-addon-notice" style="float:right;" data-addon="'. $id .'" data-notice="expiry">' .
|
345 |
-
__('Dismiss this notification', WPRSS_TEXT_DOMAIN) . '</a>';
|
346 |
-
|
347 |
-
// Only show this notice if there isn't already a notice to show for this add-on.
|
348 |
-
if ( !isset($notices[$uid]) ) {
|
349 |
-
$notices[$uid] = '<div class="error wprss-license-notice"><p>' . $msg . $hide . '</p></div>';
|
350 |
-
}
|
351 |
-
}
|
352 |
-
}
|
353 |
-
}
|
354 |
-
|
355 |
-
// Display the notices
|
356 |
-
foreach ($notices as $notice) {
|
357 |
-
echo $notice;
|
358 |
-
}
|
359 |
}
|
360 |
|
361 |
|
362 |
-
add_action( 'wp_ajax_wprss_ajax_manage_license', 'wprss_ajax_manage_license' );
|
363 |
/**
|
364 |
-
*
|
365 |
*
|
366 |
-
* @since 4.7
|
|
|
367 |
*/
|
368 |
-
function
|
369 |
-
|
370 |
-
if ( isset($_GET['addon']) ) {
|
371 |
-
$addon = sanitize_text_field($_GET['addon']);
|
372 |
-
} else {
|
373 |
-
wprss_echo_error_and_die( __('No addon ID', WPRSS_TEXT_DOMAIN ));
|
374 |
-
}
|
375 |
-
|
376 |
-
// Check what we've been asked to do with the license.
|
377 |
-
if ( isset($_GET['event']) ) {
|
378 |
-
$event = sanitize_text_field($_GET['event']);
|
379 |
-
|
380 |
-
if ($event !== 'activate' && $event !== 'deactivate') {
|
381 |
-
wprss_echo_error_and_die( __('Invalid event specified', WPRSS_TEXT_DOMAIN), $addon);
|
382 |
-
}
|
383 |
-
} else {
|
384 |
-
wprss_echo_error_and_die( __('No event specified', WPRSS_TEXT_DOMAIN), $addon);
|
385 |
-
}
|
386 |
-
|
387 |
-
// Get and sanitize the license that was entered.
|
388 |
-
if ( isset($_GET['license']) ) {
|
389 |
-
$license = sanitize_text_field($_GET['license']);
|
390 |
-
} else {
|
391 |
-
wprss_echo_error_and_die( __('No license', WPRSS_TEXT_DOMAIN), $addon);
|
392 |
-
}
|
393 |
-
|
394 |
-
// Check the nonce for this particular add-on's validation button.
|
395 |
-
if ( isset($_GET['nonce']) ) {
|
396 |
-
$nonce = sanitize_text_field($_GET['nonce']);
|
397 |
-
$nonce_id = "wprss_{$addon}_license_nonce";
|
398 |
-
|
399 |
-
if ( !wp_verify_nonce($nonce, $nonce_id) ) {
|
400 |
-
wprss_echo_error_and_die( __('Bad nonce', WPRSS_TEXT_DOMAIN), $addon);
|
401 |
-
}
|
402 |
-
} else {
|
403 |
-
wprss_echo_error_and_die( __('No nonce', WPRSS_TEXT_DOMAIN), $addon);
|
404 |
-
}
|
405 |
-
|
406 |
-
$license_keys = get_option('wprss_settings_license_keys', array());
|
407 |
-
// Check if the license key was obfuscated on the client's end.
|
408 |
-
if ( wprss_license_key_is_obfuscated( $license ) ) {
|
409 |
-
// If so, use the stored license key for de/activation.
|
410 |
-
$license = $license_keys[$addon . '_license_key'];
|
411 |
-
} else {
|
412 |
-
// Otherwise, update the license key stored in the DB.
|
413 |
-
$license_keys[$addon . '_license_key'] = $license;
|
414 |
-
update_option('wprss_settings_license_keys', $license_keys);
|
415 |
-
}
|
416 |
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
} else {
|
423 |
-
wprss_echo_error_and_die( __('Invalid event specified', WPRSS_TEXT_DOMAIN), $addon);
|
424 |
-
}
|
425 |
|
426 |
-
|
427 |
-
$ret = array();
|
428 |
-
|
429 |
-
// Set the validity of the license.
|
430 |
-
if ( $status === 'site_inactive' ) $status = 'inactive';
|
431 |
-
if ( $status === 'item_name_mismatch' ) $status = 'invalid';
|
432 |
-
$ret['validity'] = $status;
|
433 |
-
|
434 |
-
// Set the addon ID for use in the callback.
|
435 |
-
$ret['addon'] = $addon;
|
436 |
-
|
437 |
-
// Set the HTML markup for the new button and validity display.
|
438 |
-
$ret['html'] = wprss_get_activate_license_button($addon);
|
439 |
-
|
440 |
-
$ret['licensedAddons'] = wprss_get_licensed_addons();
|
441 |
-
|
442 |
-
// Return the JSON data.
|
443 |
-
echo json_encode($ret);
|
444 |
-
die();
|
445 |
}
|
446 |
|
447 |
-
|
448 |
-
add_action( 'wp_ajax_wprss_ajax_fetch_license', 'wprss_ajax_fetch_license' );
|
449 |
/**
|
450 |
-
*
|
451 |
*
|
452 |
-
* @since 4.7
|
|
|
453 |
*/
|
454 |
-
function
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
wprss_echo_error_and_die( __('No addon ID', WPRSS_TEXT_DOMAIN ));
|
460 |
-
}
|
461 |
-
|
462 |
-
// Get the license information from EDD
|
463 |
-
$ret = wprss_edd_check_license( $addon, NULL, 'ALL' );
|
464 |
-
|
465 |
-
echo json_encode($ret);
|
466 |
-
die();
|
467 |
}
|
468 |
|
469 |
-
|
470 |
/**
|
471 |
-
*
|
472 |
-
* activate/deactivate license button HTML markup and then die()s.
|
473 |
-
*
|
474 |
-
* @since 4.7
|
475 |
-
*/
|
476 |
-
function wprss_echo_error_and_die($msg, $addon = '') {
|
477 |
-
$ret = array(
|
478 |
-
'error' => $msg,
|
479 |
-
'html' => wprss_get_activate_license_button($addon)
|
480 |
-
);
|
481 |
-
|
482 |
-
echo json_encode($ret);
|
483 |
-
die();
|
484 |
-
}
|
485 |
-
|
486 |
-
|
487 |
-
add_action( 'wprss_admin_init', 'wprss_license_settings', 100 );
|
488 |
-
/**
|
489 |
-
* Adds the license sections and settings for registered add-ons.
|
490 |
-
*
|
491 |
-
* @since 4.4.5
|
492 |
-
*/
|
493 |
-
function wprss_license_settings() {
|
494 |
-
$addons = wprss_get_addons();
|
495 |
-
foreach( $addons as $addon_id => $addon_name ) {
|
496 |
-
// Settings Section
|
497 |
-
add_settings_section(
|
498 |
-
"wprss_settings_{$addon_id}_licenses_section",
|
499 |
-
$addon_name .' '. __( 'License', WPRSS_TEXT_DOMAIN ),
|
500 |
-
'__return_empty_string',
|
501 |
-
'wprss_settings_license_keys'
|
502 |
-
);
|
503 |
-
// License key field
|
504 |
-
add_settings_field(
|
505 |
-
"wprss_settings_{$addon_id}_license",
|
506 |
-
__( 'License Key', WPRSS_TEXT_DOMAIN ),
|
507 |
-
'wprss_license_key_field',
|
508 |
-
'wprss_settings_license_keys',
|
509 |
-
"wprss_settings_{$addon_id}_licenses_section",
|
510 |
-
array( $addon_id )
|
511 |
-
);
|
512 |
-
// Activate license button
|
513 |
-
add_settings_field(
|
514 |
-
"wprss_settings_{$addon_id}_activate_license",
|
515 |
-
__( 'Activate License', WPRSS_TEXT_DOMAIN ),
|
516 |
-
'wprss_activate_license_button',
|
517 |
-
'wprss_settings_license_keys',
|
518 |
-
"wprss_settings_{$addon_id}_licenses_section",
|
519 |
-
array( $addon_id )
|
520 |
-
);
|
521 |
-
}
|
522 |
-
}
|
523 |
-
|
524 |
-
|
525 |
-
/**
|
526 |
-
* Renders the license field for a particular add-on.
|
527 |
-
*
|
528 |
-
* @since 4.4.5
|
529 |
-
*/
|
530 |
-
function wprss_license_key_field( $args ) {
|
531 |
-
$addon_id = $args[0];
|
532 |
-
$license_key = wprss_get_license_key( $addon_id );
|
533 |
-
$license_key_length = strlen( $license_key );
|
534 |
-
$mask_char = WPRSS_LICENSE_KEY_MASK_CHAR;
|
535 |
-
// How many chars to show
|
536 |
-
$mask_exclude_amount = WPRSS_LICENSE_KEY_MASK_EXCLUDE_AMOUNT;
|
537 |
-
$mask_exclude_amount = abs( $mask_exclude_amount ) > ($license_key_length - 1)
|
538 |
-
? ($license_key_length - 1) * ( $mask_exclude_amount < 0 ? -1 : 1 ) // Making sure to preserve position of mask
|
539 |
-
: $mask_exclude_amount;
|
540 |
-
// How many chars to mask. Always at least one char will be masked.
|
541 |
-
$mask_length = $license_key_length - abs( $mask_exclude_amount );
|
542 |
-
$mask = $mask_length > 0 ? str_repeat( $mask_char, $mask_length ) : '';
|
543 |
-
$excluded_chars = WPRSS_MBString::mb_substr( $license_key, $mask_exclude_amount < 0 ? $mask_length : 0, abs( $mask_exclude_amount ) );
|
544 |
-
$displayed_key = sprintf( $mask_exclude_amount > 0 ? '%1$s%2$s' : '%2$s%1$s', $excluded_chars, $mask); ?>
|
545 |
-
<input id="wprss-<?php echo $addon_id ?>-license-key" name="wprss_settings_license_keys[<?php echo $addon_id ?>_license_key]"
|
546 |
-
type="text" value="<?php echo esc_attr( $displayed_key ) ?>" style="width: 300px;"
|
547 |
-
/>
|
548 |
-
<label class="description" for="wprss-<?php echo $addon_id ?>-license-key">
|
549 |
-
<?php _e( 'Enter your license key', WPRSS_TEXT_DOMAIN ) ?>
|
550 |
-
</label><?php
|
551 |
-
}
|
552 |
-
|
553 |
-
|
554 |
-
/**
|
555 |
-
* Renders the activate/deactivate license button for a particular add-on.
|
556 |
*
|
557 |
* @since 4.4.5
|
|
|
|
|
558 |
*/
|
559 |
-
function
|
560 |
-
$
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
if ( $status === 'item_name_mismatch' ) $status = 'invalid';
|
565 |
-
|
566 |
-
$valid = $status == 'valid';
|
567 |
-
$btn_text = $valid ? 'Deactivate License' : 'Activate License';
|
568 |
-
$btn_name = "wprss_{$addon_id}_license_" . ( $valid? 'deactivate' : 'activate' );
|
569 |
-
$btn_class = "button-" . ( $valid ? 'deactivate' : 'activate' ) . "-license";
|
570 |
-
wp_nonce_field( "wprss_{$addon_id}_license_nonce", "wprss_{$addon_id}_license_nonce", false ); ?>
|
571 |
-
|
572 |
-
<input type="button" class="<?php echo $btn_class; ?> button-process-license button-secondary" name="<?php echo $btn_name; ?>" value="<?php _e( $btn_text, WPRSS_TEXT_DOMAIN ); ?>" />
|
573 |
-
<span id="wprss-<?php echo $addon_id; ?>-license-status-text">
|
574 |
-
<strong><?php _e('Status', WPRSS_TEXT_DOMAIN); ?>:
|
575 |
-
<span class="wprss-<?php echo $addon_id; ?>-license-<?php echo $status; ?>">
|
576 |
-
<?php _e( ucfirst($status), WPRSS_TEXT_DOMAIN ); ?>
|
577 |
-
<?php if ( $status === 'valid' ) : ?>
|
578 |
-
<i class="fa fa-check"></i>
|
579 |
-
<?php elseif( $status === 'invalid' || $status === 'expired' ): ?>
|
580 |
-
<i class="fa fa-times"></i>
|
581 |
-
<?php elseif( $status === 'inactive' ): ?>
|
582 |
-
<i class="fa fa-warning"></i>
|
583 |
-
<?php endif; ?>
|
584 |
-
</strong>
|
585 |
-
</span>
|
586 |
-
</span>
|
587 |
-
|
588 |
-
<p>
|
589 |
-
<?php
|
590 |
-
$license_key = wprss_get_license_key( $addon_id );
|
591 |
-
if ( ! empty( $license_key ) ) :
|
592 |
-
if ( is_object( $data ) ) :
|
593 |
-
$acts_current = $data->site_count;
|
594 |
-
$acts_left = $data->activations_left;
|
595 |
-
$acts_limit = $data->license_limit;
|
596 |
-
$expires = $data->expires;
|
597 |
-
$expires = substr( $expires, 0, strpos( $expires, " " ) );
|
598 |
-
|
599 |
-
// If the license key is garbage, don't show any of the data.
|
600 |
-
if ( !empty($data->payment_id) && !empty($data->license_limit ) ) :
|
601 |
-
?>
|
602 |
-
<small>
|
603 |
-
<?php if ( $status !== 'valid' && $acts_left === 0 ) : ?>
|
604 |
-
<?php $account_url = 'https://www.wprssaggregator.com/account/?action=manage_licenses&payment_id=' . $data->payment_id; ?>
|
605 |
-
<a href="<?php echo $account_url; ?>"><?php _e("No activations left. Click here to manage the sites you've activated licenses on.", WPRSS_TEXT_DOMAIN); ?></a>
|
606 |
-
<br/>
|
607 |
-
<?php endif; ?>
|
608 |
-
<?php if ( strtotime($expires) < strtotime("+2 weeks") ) : ?>
|
609 |
-
<?php $renewal_url = esc_attr(WPRSS_SL_STORE_URL . '/checkout/?edd_license_key=' . $license_key); ?>
|
610 |
-
<a href="<?php echo $renewal_url; ?>"><?php _e('Renew your license to continue receiving updates and support.', WPRSS_TEXT_DOMAIN); ?></a>
|
611 |
-
<br/>
|
612 |
-
<?php endif; ?>
|
613 |
-
<strong><?php _e('Activations', WPRSS_TEXT_DOMAIN); ?>:</strong>
|
614 |
-
<?php echo $acts_current.'/'.$acts_limit; ?> (<?php echo $acts_left; ?> left)
|
615 |
-
<br/>
|
616 |
-
<strong><?php _e('Expires on', WPRSS_TEXT_DOMAIN); ?>:</strong>
|
617 |
-
<code><?php echo $expires; ?></code>
|
618 |
-
<br/>
|
619 |
-
<strong><?php _e('Registered to', WPRSS_TEXT_DOMAIN); ?>:</strong>
|
620 |
-
<?php echo $data->customer_name; ?> (<code><?php echo $data->customer_email; ?></code>)
|
621 |
-
</small>
|
622 |
-
<?php endif; ?>
|
623 |
-
<?php else: ?>
|
624 |
-
<small><?php _e('Failed to get license information. This is a temporary problem. Check your internet connection and try again later.', WPRSS_TEXT_DOMAIN); ?></small>
|
625 |
-
<?php endif; ?>
|
626 |
-
<?php endif;
|
627 |
-
?>
|
628 |
-
</p>
|
629 |
-
|
630 |
-
<style type="text/css">
|
631 |
-
.wprss-<?php echo $addon_id; ?>-license-valid {
|
632 |
-
color: green;
|
633 |
-
}
|
634 |
-
.wprss-<?php echo $addon_id; ?>-license-invalid, .wprss-<?php echo $addon_id; ?>-license-expired {
|
635 |
-
color: #b71919;
|
636 |
-
}
|
637 |
-
.wprss-<?php echo $addon_id; ?>-license-inactive {
|
638 |
-
color: #d19e5b;
|
639 |
-
}
|
640 |
-
#wprss-<?php echo $addon_id; ?>-license-status-text {
|
641 |
-
margin-left: 8px;
|
642 |
-
line-height: 27px;
|
643 |
-
vertical-align: middle;
|
644 |
-
}
|
645 |
-
</style>
|
646 |
-
|
647 |
-
|
648 |
-
<?php
|
649 |
-
}
|
650 |
-
|
651 |
-
|
652 |
-
/**
|
653 |
-
* Returns the activate/deactivate license button markup for a particular add-on.
|
654 |
-
*
|
655 |
-
* @since 4.7
|
656 |
-
*/
|
657 |
-
function wprss_get_activate_license_button( $addon ) {
|
658 |
-
// Buffer the output from the rendering function.
|
659 |
-
ob_start();
|
660 |
-
|
661 |
-
wprss_activate_license_button(array($addon));
|
662 |
-
$ret = ob_get_contents();
|
663 |
-
|
664 |
-
ob_end_clean();
|
665 |
-
|
666 |
-
return $ret;
|
667 |
-
}
|
668 |
-
|
669 |
-
|
670 |
-
add_action( 'admin_init', 'wprss_process_addon_license', 10 );
|
671 |
-
/**
|
672 |
-
* Handles the activation/deactivation process
|
673 |
-
*
|
674 |
-
* @since 1.0
|
675 |
-
*/
|
676 |
-
function wprss_process_addon_license() {
|
677 |
-
$addons = wprss_get_addons();
|
678 |
-
|
679 |
-
// Get for each registered addon
|
680 |
-
foreach( $addons as $id => $name ) {
|
681 |
-
|
682 |
-
// listen for our activate button to be clicked
|
683 |
-
if( isset( $_POST["wprss_{$id}_license_activate"] ) || isset( $_POST["wprss_{$id}_license_deactivate"] ) ) {
|
684 |
-
// run a quick security check
|
685 |
-
if( ! check_admin_referer( "wprss_{$id}_license_nonce", "wprss_{$id}_license_nonce" ) )
|
686 |
-
continue; // get out if we didn't click the Activate/Deactivate button
|
687 |
-
}
|
688 |
-
|
689 |
-
// retrieve the license keys and statuses from the database
|
690 |
-
$license = wprss_get_license_key( $id );
|
691 |
-
$license_statuses = get_option( 'wprss_settings_license_statuses' );
|
692 |
-
|
693 |
-
// If the license is not saved in DB, but is included in POST
|
694 |
-
if ( $license == '' && !empty($_POST['wprss_settings_license_keys'][$id.'_license_key']) ) {
|
695 |
-
// Use the license given in POST
|
696 |
-
$license = $_POST['wprss_settings_license_keys'][$id.'_license_key'];
|
697 |
-
}
|
698 |
-
|
699 |
-
// Prepare the action to take
|
700 |
-
if ( isset( $_POST["wprss_{$id}_license_activate"] ) ) {
|
701 |
-
wprss_edd_activate_license( $id, $license );
|
702 |
-
}
|
703 |
-
elseif ( isset( $_POST["wprss_{$id}_license_deactivate"] ) ) {
|
704 |
-
wprss_edd_deactivate_license( $id, $license );
|
705 |
-
}
|
706 |
-
}
|
707 |
}
|
708 |
|
709 |
-
|
710 |
-
add_action( 'admin_init', 'wprss_setup_edd_updater' );
|
711 |
/**
|
712 |
-
*
|
713 |
-
*
|
714 |
-
* @since 4.6.3
|
715 |
*/
|
716 |
-
function
|
717 |
-
|
|
|
|
|
|
|
718 |
|
719 |
-
|
720 |
-
|
|
|
721 |
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
// setup the updater
|
726 |
-
if ( !class_exists( 'EDD_SL_Plugin_Updater' ) ) {
|
727 |
-
// load our custom updater
|
728 |
-
include ( WPRSS_INC . 'libraries/EDD_licensing/EDD_SL_Plugin_Updater.php' );
|
729 |
-
}
|
730 |
-
|
731 |
-
// Iterate the addons
|
732 |
-
foreach( $addons as $id => $name ) {
|
733 |
-
// Prepare the data
|
734 |
-
$license = wprss_get_license_key( $id );
|
735 |
-
$uid = strtoupper( $id );
|
736 |
-
$name = constant("WPRSS_{$uid}_SL_ITEM_NAME");
|
737 |
-
$version = constant("WPRSS_{$uid}_VERSION");
|
738 |
-
$path = constant("WPRSS_{$uid}_PATH");
|
739 |
-
// Set up an updater
|
740 |
-
$edd_updater = new EDD_SL_Plugin_Updater( WPRSS_SL_STORE_URL, $path, array(
|
741 |
-
'version' => $version, // current version number
|
742 |
-
'license' => $license, // license key (used get_option above to retrieve from DB)
|
743 |
-
'item_name' => $name, // name of this plugin
|
744 |
-
'author' => 'Jean Galea' // author of this plugin
|
745 |
-
));
|
746 |
-
}
|
747 |
-
}
|
748 |
|
|
|
|
|
|
|
749 |
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
*
|
755 |
-
* @since 4.6.10
|
756 |
-
* @param bool $is_valid Indicates whether the key is currently considered to be valid.
|
757 |
-
* @param string $key The license key in question
|
758 |
-
* @return Whether or not the key is still to be considered valid.
|
759 |
-
*/
|
760 |
-
function wprss_license_validate_key_for_save( $is_valid, $key ) {
|
761 |
-
if ( wprss_license_key_is_obfuscated( $key ) )
|
762 |
-
return false;
|
763 |
-
|
764 |
-
return $is_valid;
|
765 |
-
}
|
766 |
-
|
767 |
-
|
768 |
-
/**
|
769 |
-
* Determines whether or not the license key in question is obfuscated.
|
770 |
-
*
|
771 |
-
* This is achieved by searching for the mask character in the key. Because the
|
772 |
-
* mask character cannot be a valid license character, the presence of at least
|
773 |
-
* one such character indicates that the key is obfuscated.
|
774 |
-
*
|
775 |
-
* @since 4.6.10
|
776 |
-
* @param string $key The license key in question.
|
777 |
-
* @return bool Whether or not this key is obfuscated.
|
778 |
-
*/
|
779 |
-
function wprss_license_key_is_obfuscated( $key ) {
|
780 |
-
$char = WPRSS_LICENSE_KEY_MASK_CHAR;
|
781 |
-
|
782 |
-
return WPRSS_MBString::mb_strpos( $key, $char ) !== false;
|
783 |
}
|
1 |
<?php
|
2 |
|
3 |
/**
|
4 |
+
* Gets the singleton instance of the Settings class, creating it if it doesn't exist.
|
|
|
5 |
*
|
6 |
+
* @since 4.7.8
|
7 |
+
* @return Aventura\Wprss\Core\Licensing\Settings
|
8 |
*/
|
9 |
+
function wprss_licensing_get_settings_controller() {
|
10 |
+
static $instance = null;
|
11 |
+
return is_null( $instance )
|
12 |
+
? $instance = new Aventura\Wprss\Core\Licensing\Settings()
|
13 |
+
: $instance;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
}
|
15 |
|
16 |
|
|
|
17 |
/**
|
18 |
+
* Gets the singleton instance of the Manager class, creating it if it doesn't exist.
|
19 |
*
|
20 |
+
* @since 4.7.8
|
21 |
+
* @return Aventura\Wprss\Core\Licensing\Manager
|
22 |
*/
|
23 |
+
function wprss_licensing_get_manager() {
|
24 |
+
static $manager = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
26 |
+
if ( is_null( $manager ) ) {
|
27 |
+
$manager = new Aventura\Wprss\Core\Licensing\Manager();
|
28 |
+
$manager->setExpirationNoticePeriod( wprss_get_general_setting( 'expiration_notice_period' ) );
|
29 |
+
$manager->setDefaultAuthorName( 'Jean Galea' );
|
30 |
+
}
|
|
|
|
|
|
|
31 |
|
32 |
+
return $manager;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
}
|
34 |
|
|
|
|
|
35 |
/**
|
36 |
+
* Gets the singleton instance of the AjaxController class, creating it if it doesn't exist.
|
37 |
*
|
38 |
+
* @since 4.7.8
|
39 |
+
* @return Aventura\Wprss\Core\Licensing\AjaxController
|
40 |
*/
|
41 |
+
function wprss_licensing_get_ajax_controller() {
|
42 |
+
static $instance = null;
|
43 |
+
return is_null( $instance )
|
44 |
+
? $instance = new Aventura\Wprss\Core\Licensing\AjaxController()
|
45 |
+
: $instance;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
}
|
47 |
|
|
|
48 |
/**
|
49 |
+
* Returns all registered addons.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
*
|
51 |
* @since 4.4.5
|
52 |
+
* @param bool $noCache If true, the add-ons filter will be ran again; if false, it will only be ran if not ran before.
|
53 |
+
* @return array Array of add-on codes.
|
54 |
*/
|
55 |
+
function wprss_get_addons($noCache = false) {
|
56 |
+
static $addons = null;
|
57 |
+
return is_null( $addons ) || $noCache
|
58 |
+
? $addons = apply_filters( 'wprss_register_addon', array() )
|
59 |
+
: $addons;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
}
|
61 |
|
|
|
|
|
62 |
/**
|
63 |
+
* Hooks the licensing system into WordPress.
|
|
|
|
|
64 |
*/
|
65 |
+
function wprss_init_licensing() {
|
66 |
+
// Get licensing class instances
|
67 |
+
$manager = wprss_licensing_get_manager();
|
68 |
+
$settingsController = wprss_licensing_get_settings_controller();
|
69 |
+
$ajaxController = wprss_licensing_get_ajax_controller();
|
70 |
|
71 |
+
// Set up Ajax Controller pointers
|
72 |
+
$ajaxController->setManager( $manager );
|
73 |
+
$ajaxController->setSettingsController( $settingsController );
|
74 |
|
75 |
+
// Licensing Manager hooks
|
76 |
+
add_action( 'admin_init', array( $manager, 'initUpdaterInstances' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
+
// Licensing Ajax Controller hooks
|
79 |
+
add_action( 'wp_ajax_wprss_ajax_manage_license', array( $ajaxController, 'handleAjaxManageLicense' ) );
|
80 |
+
add_action( 'wp_ajax_wprss_ajax_fetch_license', array( $ajaxController, 'handleAjaxFetchLicense' ) );
|
81 |
|
82 |
+
// Licensing Settings Controller hooks
|
83 |
+
add_action( 'wprss_admin_init', array( $settingsController, 'registerSettings' ), 100 );
|
84 |
+
add_action( 'admin_init', array( $settingsController, 'handleLicenseStatusChange' ), 10 );
|
85 |
+
add_action( 'wprss_settings_license_key_is_valid', array( $settingsController, 'validateLicenseKeyForSave' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
}
|
includes/scripts.php
CHANGED
@@ -29,6 +29,7 @@
|
|
29 |
if ( isset( $_GET['page'] ) && ( $_GET['page'] == 'wprss-aggregator' || $_GET['page'] == 'wprss-aggregator-settings'
|
30 |
|| $_GET['page'] == 'wprss-import-export-settings' || $_GET['page'] == 'wprss-debugging' || $_GET['page'] == 'wprss-addons' ) ) {
|
31 |
wp_enqueue_style( 'wprss-styles', WPRSS_CSS . 'admin-styles.css' );
|
|
|
32 |
}
|
33 |
|
34 |
if ( is_admin() ) {
|
29 |
if ( isset( $_GET['page'] ) && ( $_GET['page'] == 'wprss-aggregator' || $_GET['page'] == 'wprss-aggregator-settings'
|
30 |
|| $_GET['page'] == 'wprss-import-export-settings' || $_GET['page'] == 'wprss-debugging' || $_GET['page'] == 'wprss-addons' ) ) {
|
31 |
wp_enqueue_style( 'wprss-styles', WPRSS_CSS . 'admin-styles.css' );
|
32 |
+
wp_enqueue_style( 'wprss-fa', WPRSS_CSS . 'font-awesome.min.css' );
|
33 |
}
|
34 |
|
35 |
if ( is_admin() ) {
|
includes/system-info.php
CHANGED
@@ -26,12 +26,11 @@
|
|
26 |
$nonce_url = wp_nonce_url( $form_url, 'wprss-sysinfo' );
|
27 |
?>
|
28 |
<form action="<?php echo esc_url( $nonce_url ); ?>" method="post">
|
29 |
-
<textarea readonly="readonly" onclick="this.focus();this.select()" id="system-info-textarea" name="wprss-sysinfo" title="<?php _e( 'To copy the system info, click below then press Ctrl + C (PC) or Cmd + C (Mac).', WPRSS_TEXT_DOMAIN ); ?>"
|
30 |
-
<?php wprss_print_system_info(); ?>
|
31 |
</textarea>
|
32 |
<p class="submit">
|
33 |
-
|
34 |
-
|
35 |
</p>
|
36 |
</form>
|
37 |
|
26 |
$nonce_url = wp_nonce_url( $form_url, 'wprss-sysinfo' );
|
27 |
?>
|
28 |
<form action="<?php echo esc_url( $nonce_url ); ?>" method="post">
|
29 |
+
<textarea readonly="readonly" onclick="this.focus();this.select()" id="system-info-textarea" name="wprss-sysinfo" title="<?php _e( 'To copy the system info, click below then press Ctrl + C (PC) or Cmd + C (Mac).', WPRSS_TEXT_DOMAIN ); ?>"><?php wprss_print_system_info(); ?>
|
|
|
30 |
</textarea>
|
31 |
<p class="submit">
|
32 |
+
<input type="hidden" name="wprss-action" value="download_sysinfo" />
|
33 |
+
<?php submit_button( __( 'Download System Info File', WPRSS_TEXT_DOMAIN ), 'primary', 'wprss-download-sysinfo', false ); ?>
|
34 |
</p>
|
35 |
</form>
|
36 |
|
includes/update.php
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
<?php
|
2 |
-
/**
|
3 |
* Contains all the functions related to updating the plugin from
|
4 |
* one version to another
|
5 |
-
*
|
6 |
* @package WP RSS Aggregator
|
7 |
*/
|
8 |
|
9 |
-
add_action( 'init', 'wprss_version_check' );
|
10 |
/**
|
11 |
* Checks the version number and runs install or update functions if needed.
|
12 |
*
|
@@ -16,15 +16,15 @@
|
|
16 |
|
17 |
// Get the old database version.
|
18 |
$old_db_version = get_option( 'wprss_db_version' );
|
19 |
-
|
20 |
-
// Get the plugin settings.
|
21 |
$settings = get_option( 'wprss_settings' );
|
22 |
|
23 |
-
// Get the plugin options
|
24 |
-
$options = get_option( 'wprss_options' );
|
25 |
|
26 |
// For fresh installs
|
27 |
-
// If there is no old database version and no settings, run the install.
|
28 |
if ( empty( $old_db_version ) && false === $settings && false === $options ) {
|
29 |
wprss_install();
|
30 |
}
|
@@ -34,30 +34,30 @@
|
|
34 |
elseif ( empty( $old_db_version ) && false === $settings && !empty( $options ) ) {
|
35 |
wp_clear_scheduled_hook( 'wprss_generate_hook' );
|
36 |
wprss_install();
|
37 |
-
wprss_migrate();
|
38 |
-
wprss_fetch_insert_all_feed_items();
|
39 |
}
|
40 |
|
41 |
-
// For version 1.1 to 3.0
|
42 |
// If there is no old database version, but only settings and options
|
43 |
elseif ( empty( $old_db_version ) && !empty( $settings ) && !empty( $options ) ) {
|
44 |
wp_clear_scheduled_hook( 'wprss_generate_hook' );
|
45 |
wprss_update();
|
46 |
wprss_migrate();
|
47 |
-
wprss_fetch_insert_all_feed_items();
|
48 |
}
|
49 |
|
50 |
// For version 2+ to 3.0
|
51 |
// We check if wprss_settings option exists, as this only exists prior to version 3.0
|
52 |
// Settings field changed, and another added
|
53 |
-
elseif ( intval( $old_db_version ) < intval( WPRSS_DB_VERSION ) && ( FALSE != get_option( 'wprss_settings' ) ) ) {
|
54 |
wprss_upgrade_30();
|
55 |
wprss_update();
|
56 |
-
wprss_fetch_insert_all_feed_items();
|
57 |
}
|
58 |
|
59 |
-
// For any future versions where DB changes
|
60 |
-
// If the old version is less than the new version, run the update.
|
61 |
elseif ( intval( $old_db_version ) < intval( WPRSS_DB_VERSION ) ) {
|
62 |
wprss_update();
|
63 |
wprss_fetch_insert_all_feed_items();
|
@@ -70,7 +70,7 @@
|
|
70 |
$options['follow_dd'] = 'follow';
|
71 |
}
|
72 |
}
|
73 |
-
|
74 |
}
|
75 |
|
76 |
|
@@ -81,7 +81,7 @@
|
|
81 |
*/
|
82 |
function wprss_install() {
|
83 |
|
84 |
-
// Add the database version setting.
|
85 |
add_option( 'wprss_db_version', WPRSS_DB_VERSION );
|
86 |
|
87 |
// Add the default plugin settings.
|
@@ -96,11 +96,11 @@
|
|
96 |
*/
|
97 |
function wprss_update() {
|
98 |
|
99 |
-
// Update the database version setting.
|
100 |
update_option( 'wprss_db_version', WPRSS_DB_VERSION );
|
101 |
// Initialize settings
|
102 |
wprss_settings_initialize();
|
103 |
-
|
104 |
// Open Link Behavior Name Fix
|
105 |
$settings = get_option( 'wprss_settings_general' );
|
106 |
|
@@ -111,7 +111,7 @@
|
|
111 |
}else if( $settings['open_dd'] === 'Self' || $settings['open_dd'] === __( 'Self', WPRSS_TEXT_DOMAIN ) ){
|
112 |
$settings['open_dd'] = 'self';
|
113 |
}
|
114 |
-
|
115 |
// At version 4.7.5 tracking was disabled
|
116 |
$settings['tracking'] = '0';
|
117 |
update_option( 'wprss_settings_general', $settings );
|
@@ -130,35 +130,35 @@
|
|
130 |
// Get the default plugin settings.
|
131 |
$default_settings = wprss_get_default_settings_general();
|
132 |
|
133 |
-
// Loop through each of the default plugin settings.
|
134 |
foreach ( $default_settings as $setting_key => $setting_value ) {
|
135 |
|
136 |
-
// If the setting didn't previously exist, add the default value to the $settings array.
|
137 |
if ( ! isset( $settings[ $setting_key ] ) )
|
138 |
$settings[ $setting_key ] = $setting_value;
|
139 |
}
|
140 |
|
141 |
// Update the plugin settings.
|
142 |
-
update_option( 'wprss_settings_general', $settings );
|
143 |
}
|
144 |
-
|
145 |
|
146 |
/**
|
147 |
* Takes care of cron and DB changes between versions 2+ and 3
|
148 |
*
|
149 |
* @since 3.0
|
150 |
-
*/
|
151 |
function wprss_upgrade_30() {
|
152 |
-
wp_clear_scheduled_hook( 'wprss_fetch_feeds_hook' );
|
153 |
|
154 |
-
// Get the settings from the database.
|
155 |
$settings = get_option( 'wprss_settings' );
|
156 |
|
157 |
// Put them into our new field
|
158 |
update_option( 'wprss_settings_general', $settings );
|
159 |
|
160 |
// Remove old options field, we are now using wprss_settings_general
|
161 |
-
delete_option( 'wprss_settings' );
|
162 |
}
|
163 |
|
164 |
|
@@ -166,30 +166,30 @@
|
|
166 |
* Migrates the feed sources from the wprss_options field to the wp_posts table (for older versions)
|
167 |
*
|
168 |
* @since 2.0
|
169 |
-
*/
|
170 |
function wprss_migrate() {
|
171 |
-
|
172 |
-
// Get the plugin options
|
173 |
-
$options = get_option( 'wprss_options' );
|
174 |
|
175 |
$feed_sources = array_chunk( $options, 2 );
|
176 |
-
|
177 |
-
foreach ( $feed_sources as $feed_source ) {
|
178 |
$feed_title = $feed_source[0];
|
179 |
$feed_url = $feed_source[1];
|
180 |
-
|
181 |
// Create post object
|
182 |
$feed_item = array(
|
183 |
'post_title' => $feed_title,
|
184 |
'post_content' => '',
|
185 |
'post_status' => 'publish',
|
186 |
'post_type' => 'wprss_feed'
|
187 |
-
);
|
188 |
-
|
189 |
-
$inserted_ID = wp_insert_post( $feed_item, $wp_error );
|
190 |
// insert post meta
|
191 |
-
update_post_meta( $inserted_ID, 'wprss_url', $feed_url );
|
192 |
-
}
|
193 |
// delete unneeded option
|
194 |
delete_option( 'wprss_options' );
|
195 |
}
|
@@ -209,10 +209,10 @@
|
|
209 |
// from version 1.1
|
210 |
'open_dd' => 'blank',
|
211 |
'follow_dd' => 'no_follow',
|
212 |
-
|
213 |
// from version 2.0
|
214 |
-
'feed_limit' => 15,
|
215 |
-
|
216 |
// from version 3.0
|
217 |
'date_format' => 'Y-m-d',
|
218 |
'limit_feed_items_db' => 200,
|
@@ -232,7 +232,7 @@
|
|
232 |
'custom_feed_url' => 'wprss',
|
233 |
'custom_feed_limit' => '',
|
234 |
'source_link' => 0,
|
235 |
-
|
236 |
// from version 3.4
|
237 |
'video_link' => 'false',
|
238 |
|
@@ -248,15 +248,18 @@
|
|
248 |
|
249 |
// from version 4.1.2
|
250 |
'custom_feed_title' => 'Latest imported feed items on ' . get_bloginfo('name'),
|
251 |
-
|
252 |
// From version 4.2.3
|
253 |
'pagination' => 'default',
|
254 |
|
255 |
// From 4.2.4
|
256 |
'authors_enable' => 0,
|
257 |
-
|
258 |
// From 4.7.2
|
259 |
'unique_titles' => 0,
|
|
|
|
|
|
|
260 |
)
|
261 |
);
|
262 |
|
@@ -268,7 +271,7 @@
|
|
268 |
|
269 |
/**
|
270 |
* Returns the default tracking settings.
|
271 |
-
*
|
272 |
* @since 3.6
|
273 |
*/
|
274 |
function wprss_get_default_tracking_settings() {
|
1 |
<?php
|
2 |
+
/**
|
3 |
* Contains all the functions related to updating the plugin from
|
4 |
* one version to another
|
5 |
+
*
|
6 |
* @package WP RSS Aggregator
|
7 |
*/
|
8 |
|
9 |
+
add_action( 'init', 'wprss_version_check' );
|
10 |
/**
|
11 |
* Checks the version number and runs install or update functions if needed.
|
12 |
*
|
16 |
|
17 |
// Get the old database version.
|
18 |
$old_db_version = get_option( 'wprss_db_version' );
|
19 |
+
|
20 |
+
// Get the plugin settings.
|
21 |
$settings = get_option( 'wprss_settings' );
|
22 |
|
23 |
+
// Get the plugin options
|
24 |
+
$options = get_option( 'wprss_options' );
|
25 |
|
26 |
// For fresh installs
|
27 |
+
// If there is no old database version and no settings, run the install.
|
28 |
if ( empty( $old_db_version ) && false === $settings && false === $options ) {
|
29 |
wprss_install();
|
30 |
}
|
34 |
elseif ( empty( $old_db_version ) && false === $settings && !empty( $options ) ) {
|
35 |
wp_clear_scheduled_hook( 'wprss_generate_hook' );
|
36 |
wprss_install();
|
37 |
+
wprss_migrate();
|
38 |
+
wprss_fetch_insert_all_feed_items();
|
39 |
}
|
40 |
|
41 |
+
// For version 1.1 to 3.0
|
42 |
// If there is no old database version, but only settings and options
|
43 |
elseif ( empty( $old_db_version ) && !empty( $settings ) && !empty( $options ) ) {
|
44 |
wp_clear_scheduled_hook( 'wprss_generate_hook' );
|
45 |
wprss_update();
|
46 |
wprss_migrate();
|
47 |
+
wprss_fetch_insert_all_feed_items();
|
48 |
}
|
49 |
|
50 |
// For version 2+ to 3.0
|
51 |
// We check if wprss_settings option exists, as this only exists prior to version 3.0
|
52 |
// Settings field changed, and another added
|
53 |
+
elseif ( intval( $old_db_version ) < intval( WPRSS_DB_VERSION ) && ( FALSE != get_option( 'wprss_settings' ) ) ) {
|
54 |
wprss_upgrade_30();
|
55 |
wprss_update();
|
56 |
+
wprss_fetch_insert_all_feed_items();
|
57 |
}
|
58 |
|
59 |
+
// For any future versions where DB changes
|
60 |
+
// If the old version is less than the new version, run the update.
|
61 |
elseif ( intval( $old_db_version ) < intval( WPRSS_DB_VERSION ) ) {
|
62 |
wprss_update();
|
63 |
wprss_fetch_insert_all_feed_items();
|
70 |
$options['follow_dd'] = 'follow';
|
71 |
}
|
72 |
}
|
73 |
+
|
74 |
}
|
75 |
|
76 |
|
81 |
*/
|
82 |
function wprss_install() {
|
83 |
|
84 |
+
// Add the database version setting.
|
85 |
add_option( 'wprss_db_version', WPRSS_DB_VERSION );
|
86 |
|
87 |
// Add the default plugin settings.
|
96 |
*/
|
97 |
function wprss_update() {
|
98 |
|
99 |
+
// Update the database version setting.
|
100 |
update_option( 'wprss_db_version', WPRSS_DB_VERSION );
|
101 |
// Initialize settings
|
102 |
wprss_settings_initialize();
|
103 |
+
|
104 |
// Open Link Behavior Name Fix
|
105 |
$settings = get_option( 'wprss_settings_general' );
|
106 |
|
111 |
}else if( $settings['open_dd'] === 'Self' || $settings['open_dd'] === __( 'Self', WPRSS_TEXT_DOMAIN ) ){
|
112 |
$settings['open_dd'] = 'self';
|
113 |
}
|
114 |
+
|
115 |
// At version 4.7.5 tracking was disabled
|
116 |
$settings['tracking'] = '0';
|
117 |
update_option( 'wprss_settings_general', $settings );
|
130 |
// Get the default plugin settings.
|
131 |
$default_settings = wprss_get_default_settings_general();
|
132 |
|
133 |
+
// Loop through each of the default plugin settings.
|
134 |
foreach ( $default_settings as $setting_key => $setting_value ) {
|
135 |
|
136 |
+
// If the setting didn't previously exist, add the default value to the $settings array.
|
137 |
if ( ! isset( $settings[ $setting_key ] ) )
|
138 |
$settings[ $setting_key ] = $setting_value;
|
139 |
}
|
140 |
|
141 |
// Update the plugin settings.
|
142 |
+
update_option( 'wprss_settings_general', $settings );
|
143 |
}
|
144 |
+
|
145 |
|
146 |
/**
|
147 |
* Takes care of cron and DB changes between versions 2+ and 3
|
148 |
*
|
149 |
* @since 3.0
|
150 |
+
*/
|
151 |
function wprss_upgrade_30() {
|
152 |
+
wp_clear_scheduled_hook( 'wprss_fetch_feeds_hook' );
|
153 |
|
154 |
+
// Get the settings from the database.
|
155 |
$settings = get_option( 'wprss_settings' );
|
156 |
|
157 |
// Put them into our new field
|
158 |
update_option( 'wprss_settings_general', $settings );
|
159 |
|
160 |
// Remove old options field, we are now using wprss_settings_general
|
161 |
+
delete_option( 'wprss_settings' );
|
162 |
}
|
163 |
|
164 |
|
166 |
* Migrates the feed sources from the wprss_options field to the wp_posts table (for older versions)
|
167 |
*
|
168 |
* @since 2.0
|
169 |
+
*/
|
170 |
function wprss_migrate() {
|
171 |
+
|
172 |
+
// Get the plugin options
|
173 |
+
$options = get_option( 'wprss_options' );
|
174 |
|
175 |
$feed_sources = array_chunk( $options, 2 );
|
176 |
+
|
177 |
+
foreach ( $feed_sources as $feed_source ) {
|
178 |
$feed_title = $feed_source[0];
|
179 |
$feed_url = $feed_source[1];
|
180 |
+
|
181 |
// Create post object
|
182 |
$feed_item = array(
|
183 |
'post_title' => $feed_title,
|
184 |
'post_content' => '',
|
185 |
'post_status' => 'publish',
|
186 |
'post_type' => 'wprss_feed'
|
187 |
+
);
|
188 |
+
|
189 |
+
$inserted_ID = wp_insert_post( $feed_item, $wp_error );
|
190 |
// insert post meta
|
191 |
+
update_post_meta( $inserted_ID, 'wprss_url', $feed_url );
|
192 |
+
}
|
193 |
// delete unneeded option
|
194 |
delete_option( 'wprss_options' );
|
195 |
}
|
209 |
// from version 1.1
|
210 |
'open_dd' => 'blank',
|
211 |
'follow_dd' => 'no_follow',
|
212 |
+
|
213 |
// from version 2.0
|
214 |
+
'feed_limit' => 15,
|
215 |
+
|
216 |
// from version 3.0
|
217 |
'date_format' => 'Y-m-d',
|
218 |
'limit_feed_items_db' => 200,
|
232 |
'custom_feed_url' => 'wprss',
|
233 |
'custom_feed_limit' => '',
|
234 |
'source_link' => 0,
|
235 |
+
|
236 |
// from version 3.4
|
237 |
'video_link' => 'false',
|
238 |
|
248 |
|
249 |
// from version 4.1.2
|
250 |
'custom_feed_title' => 'Latest imported feed items on ' . get_bloginfo('name'),
|
251 |
+
|
252 |
// From version 4.2.3
|
253 |
'pagination' => 'default',
|
254 |
|
255 |
// From 4.2.4
|
256 |
'authors_enable' => 0,
|
257 |
+
|
258 |
// From 4.7.2
|
259 |
'unique_titles' => 0,
|
260 |
+
|
261 |
+
// From 4.7.8
|
262 |
+
'expiration_notice_period' => '2 weeks',
|
263 |
)
|
264 |
);
|
265 |
|
271 |
|
272 |
/**
|
273 |
* Returns the default tracking settings.
|
274 |
+
*
|
275 |
* @since 3.6
|
276 |
*/
|
277 |
function wprss_get_default_tracking_settings() {
|
readme.txt
CHANGED
@@ -1,703 +1,1412 @@
|
|
1 |
-
=== WP RSS Aggregator ===
|
2 |
-
Contributors: jeangalea, Mekku, xedin.unknown, markzahra, doytch, chiragswadia
|
3 |
-
Plugin URI: http://www.wprssaggregator.com
|
4 |
-
Tags: rss,
|
5 |
-
Requires at least: 4.0
|
6 |
-
Tested up to: 4.3.1
|
7 |
-
Stable tag: 4.7.
|
8 |
-
License: GPLv2 or later
|
9 |
-
The no.1 RSS feed importer for WordPress. Premium add-ons available for more functionality.
|
10 |
-
|
11 |
-
|
12 |
-
== Description ==
|
13 |
-
|
14 |
-
WP RSS Aggregator is the most comprehensive and elegant RSS feed solution for WordPress.
|
15 |
-
|
16 |
-
The original and
|
17 |
-
|
18 |
-
With WP RSS Aggregator, you can:
|
19 |
-
|
20 |
-
* Display feeds from one or more sites on your blog
|
21 |
-
* Aggregate feeds from multiple sites
|
22 |
-
|
23 |
-
You can add any number of feeds through an administration panel, the plugin will then pull feed items from these sites, merge them and display them in date order.
|
24 |
-
|
25 |
-
To [display your imported feed items](http://wordpress.org/plugins/wp-rss-aggregator/screenshots/), you can use a shortcode or call the display function directly from within your theme.
|
26 |
-
|
27 |
-
= Highlighted Features =
|
28 |
-
|
29 |
-
* Export a custom RSS feed based on your feed sources
|
30 |
-
* Pagination
|
31 |
-
* Set the feed import time interval
|
32 |
-
* Scheduling of feed imports by feed source
|
33 |
-
* Various shortcode parameters you can use to further customize the output
|
34 |
-
* Choose whether to show/hide sources and dates
|
35 |
-
* Choose the date format
|
36 |
-
* Set the links as no-follow or not, or add no follow to meta tag
|
37 |
-
* Select how you would like the links to open (in a Lightbox, a new window, or the current window)
|
38 |
-
* Set the name of the feed source
|
39 |
-
* Select number of posts per feed you want to show and store
|
40 |
-
* Opens YouTube, DailyMotion and Vimeo videos directly
|
41 |
-
* Limit number of feed items stored in the database
|
42 |
-
* Feed autodiscovery, which lets you add feeds without even knowing the exact URL.
|
43 |
-
* Extendable via action and filter hooks
|
44 |
-
* Integrated with the Simplepie library that come with WordPress. This includes RSS 0.91 and RSS 1.0 formats, the popular RSS 2.0 format, Atom etc.
|
45 |
-
|
46 |
-
= Premium Add-Ons =
|
47 |
-
Add-Ons that add more functionality to the core plugin are [available for purchase](http://www.wprssaggregator.com/extensions/).
|
48 |
-
|
49 |
-
* [Feed to Post](http://www.wprssaggregator.com/extensions/feed-to-post) - an advanced importer that lets you import RSS to posts or custom post types. Populate a website in minutes (autoblog). This is the most popular extension.
|
50 |
-
* [Keyword Filtering](http://www.wprssaggregator.com/extensions/keyword-filtering) - filter imported feeds based on keywords, so you only get items you're interested in.
|
51 |
-
* [Excerpts & Thumbnails](http://www.wprssaggregator.com/extensions/excerpts-thumbnails) - display excerpts and thumbnails together with the title, date and source.
|
52 |
-
* [Categories](http://www.wprssaggregator.com/extensions/categories) - categorise your feed sources and display items from a particular category at will within your site.
|
53 |
-
* [WordAi](http://www.wprssaggregator.com/extension/wordai/) - WordAi allows users to take an RSS feed and turn it into new content that is both completely unique and completely readable.
|
54 |
-
* [Full Text RSS Feeds](http://www.wprssaggregator.com/extension/full-text-rss-feeds/) - connectivity to our Full Text Premium service, which gives you unlimited feed items returned per feed source.
|
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 the [demo page](http://www.wprssaggregator.com/demo/).
|
60 |
-
|
61 |
-
= Video Walkthrough =
|
62 |
-
[youtube http://www.youtube.com/watch?v=fcENPsmJbvc]
|
63 |
-
|
64 |
-
= Documentation =
|
65 |
-
Instructions for plugin usage are available on the plugin's [documentation page](http://www.wprssaggregator.com/documentation/).
|
66 |
-
|
67 |
-
= As featured on =
|
68 |
-
* [Latest WP](http://www.latestwp.com/2015/03/15/wp-rss-aggregator-plugin-review/)
|
69 |
-
* [WP Beginner](http://www.wpbeginner.com/plugins/how-to-fetch-feeds-in-wordpress-using-wp-rss-aggregator/)
|
70 |
-
* [WPEXplorer](http://www.wpexplorer.com/custom-rss-aggregator-plugin/)
|
71 |
-
* [WP Kube](http://www.wpkube.com/wp-rss-aggregator-wordpress-review/)
|
72 |
-
* [Torquemag](http://torquemag.io/wp-rss-aggregator-review-do-more-with-rss-feeds/)
|
73 |
-
* [MyWPExpert](http://www.mywpexpert.com/wordpress-rss-aggregator-plugin)
|
74 |
-
* [Kikolani](http://kikolani.com/create-latest-posts-portfolio-page-wp-rss-aggregator.html)
|
75 |
-
* [ManageWP Plugins of the Month](http://managewp.com/free-wordpress-plugins-march-2014)
|
76 |
-
* [TidyRepo](http://tidyrepo.com/wp-rss-aggregator/)
|
77 |
-
* [WP Eka](http://www.wpeka.com/wp-rss-aggregators-plugin.html)
|
78 |
-
* [IndexWP](www.indexwp.com/wp-rss-aggregator-plugin-review/)
|
79 |
-
* [WPulsar](http://www.wpulsar.com/wp-rss-aggregator-plugin-feed-to-posts-keyword-filtering-review/)
|
80 |
-
* [Kevin Muldoon](http://www.kevinmuldoon.com/wp-rss-aggregator-wordpress-plugin/)
|
81 |
-
|
82 |
-
= Translations =
|
83 |
-
* Italian - Davide De Maestri
|
84 |
-
* Spanish - Andrew Kurtis
|
85 |
-
* Brazilian Portugese - Bruno Calheira
|
86 |
-
* Dutch - Erick Suiker
|
87 |
-
|
88 |
-
== Installation ==
|
89 |
-
|
90 |
-
1. Upload the `wp-rss-aggregator` folder to the `/wp-content/plugins/` directory
|
91 |
-
2. Activate the WP RSS Aggregator plugin through the 'Plugins' menu in WordPress
|
92 |
-
3. Configure the plugin by going to the `RSS Aggregator` menu item that appears in your dashboard menu.
|
93 |
-
3. Use the shortcode in your posts or pages: `[wp-rss-aggregator]`
|
94 |
-
|
95 |
-
The parameters accepted are:
|
96 |
-
|
97 |
-
* links_before
|
98 |
-
* links_after
|
99 |
-
* link_before
|
100 |
-
* link_after
|
101 |
-
* limit
|
102 |
-
* source
|
103 |
-
* exclude
|
104 |
-
* pagination
|
105 |
-
|
106 |
-
An example of a shortcode with parameters:
|
107 |
-
`[wp_rss_aggregator link_before='<li class="feed-link">' link_after='</li>']`
|
108 |
-
It is advisable to use the 'HTML' view of the editor when inserting the shortcode with paramters.
|
109 |
-
|
110 |
-
For a full list of shortcode parameters and usage guide please refer to the [documentation](http://www.wprssaggregator.com/docs/shortcodes/).
|
111 |
-
|
112 |
-
__Usage within theme files__
|
113 |
-
|
114 |
-
An example of a function call from within the theme's files:
|
115 |
-
`
|
116 |
-
<?php
|
117 |
-
wprss_display_feed_items( $args = array(
|
118 |
-
'links_before' => '<ul>',
|
119 |
-
'links_after' => '</ul>',
|
120 |
-
'link_before' => '<li>',
|
121 |
-
'link_after' => '</li>',
|
122 |
-
'limit' => '8',
|
123 |
-
'source' => '5,9'
|
124 |
-
));
|
125 |
-
?>
|
126 |
-
`
|
127 |
-
|
128 |
-
OR
|
129 |
-
|
130 |
-
`<?php do_shortcode('[wp-rss-aggregator]'); ?>`
|
131 |
-
|
132 |
-
|
133 |
-
== Frequently Asked Questions ==
|
134 |
-
= How do I display the imported feed items? =
|
135 |
-
|
136 |
-
You can either use the shortcode in your posts and pages:
|
137 |
-
`[wp-rss-aggregator]`
|
138 |
-
|
139 |
-
or you can call the function directly within your theme:
|
140 |
-
`<?php wprss_display_feed_items(); ?>`
|
141 |
-
|
142 |
-
= Is there a limit on the number of feed sources I can use? =
|
143 |
-
|
144 |
-
There is no limit in place for the number of feed sources. Having many (50+) feed sources should not present any problems in itself.
|
145 |
-
|
146 |
-
However, pulling in posts from many sites is bound to put your server under some stress, so you might want to consider using a hosting solution that goes beyond your typical shared host.
|
147 |
-
|
148 |
-
Check out our dedicated page
|
149 |
-
|
150 |
-
= Does WP RSS Aggregator work using JSON as the source? =
|
151 |
-
|
152 |
-
No, our plugin does not currently import from JSON, it only imports from RSS and Atom structured XML.
|
153 |
-
|
154 |
-
= Why do I get “No feed items found” when I insert the shortcode on a page or post? =
|
155 |
-
|
156 |
-
Try adding a few more feed sources and make sure they are valid by using the RSS Feed validator.
|
157 |
-
|
158 |
-
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.
|
159 |
-
|
160 |
-
= Can I store imported feed items as posts? =
|
161 |
-
|
162 |
-
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.
|
163 |
-
|
164 |
-
= Some RSS feeds only give a short excerpt. Any way around that? =
|
165 |
-
|
166 |
-
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.
|
167 |
-
|
168 |
-
= I’m not sure which premium add-ons are right for me. Can you help me out? =
|
169 |
-
|
170 |
-
Sure! We wrote a post 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.
|
171 |
-
|
172 |
-
If you need any further help you can contact our support team [here](http://www.wprssaggregator.com/contact/).
|
173 |
-
|
174 |
-
= Where can I find the documentation for the plugin? =
|
175 |
-
|
176 |
-
The full documentation section can be found on the [WP RSS Aggregator website](
|
177 |
-
|
178 |
-
|
179 |
-
== Screenshots ==
|
180 |
-
|
181 |
-
1. Feed items imported by WP RSS Aggregator displayed on the front-end using the shortcode.
|
182 |
-
|
183 |
-
2. Feed Items imported by WP RSS Aggregator and displayed with the [Excerpts & Thumbnails](http://www.wprssaggregator.com/extensions/excerpts-thumbnails) add-on installed.
|
184 |
-
|
185 |
-
3. Adding/Editing a feed source.
|
186 |
-
|
187 |
-
4. The feed sources.
|
188 |
-
|
189 |
-
5. The imported feeds items.
|
190 |
-
|
191 |
-
6. WP RSS Aggregator's Settings page.
|
192 |
-
|
193 |
-
|
194 |
-
== Changelog ==
|
195 |
-
|
196 |
-
= 4.7.
|
197 |
-
*
|
198 |
-
|
199 |
-
|
200 |
-
* Enhanced:
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
*
|
207 |
-
*
|
208 |
-
*
|
209 |
-
|
210 |
-
= 4.7.
|
211 |
-
*
|
212 |
-
* Fixed bug
|
213 |
-
*
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
*
|
218 |
-
*
|
219 |
-
*
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
* Enhanced:
|
225 |
-
*
|
226 |
-
* Fixed bug:
|
227 |
-
* Fixed bug:
|
228 |
-
|
229 |
-
|
230 |
-
*
|
231 |
-
* Fixed bug:
|
232 |
-
|
233 |
-
|
234 |
-
* Fixed bug:
|
235 |
-
|
236 |
-
|
237 |
-
*
|
238 |
-
|
239 |
-
|
240 |
-
*
|
241 |
-
|
242 |
-
|
243 |
-
*
|
244 |
-
|
245 |
-
|
246 |
-
*
|
247 |
-
|
248 |
-
|
249 |
-
* Fixed bug:
|
250 |
-
|
251 |
-
= 4.6.
|
252 |
-
*
|
253 |
-
|
254 |
-
|
255 |
-
* Fixed bug:
|
256 |
-
|
257 |
-
= 4.6.
|
258 |
-
* Enhanced:
|
259 |
-
* Enhanced:
|
260 |
-
*
|
261 |
-
*
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
* Enhanced:
|
266 |
-
* Enhanced:
|
267 |
-
*
|
268 |
-
* Fixed:
|
269 |
-
|
270 |
-
= 4.6.
|
271 |
-
* Enhanced:
|
272 |
-
* Enhanced:
|
273 |
-
* Fixed
|
274 |
-
* Fixed
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
*
|
280 |
-
*
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
* Enhanced:
|
286 |
-
*
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
* Enhanced:
|
291 |
-
* Enhanced:
|
292 |
-
*
|
293 |
-
* Fixed bug:
|
294 |
-
|
295 |
-
= 4.6.
|
296 |
-
* Enhanced:
|
297 |
-
* Enhanced:
|
298 |
-
*
|
299 |
-
* Fixed bug:
|
300 |
-
|
301 |
-
= 4.6.
|
302 |
-
Enhanced:
|
303 |
-
Enhanced:
|
304 |
-
|
305 |
-
Fixed bug:
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
* Enhanced:
|
319 |
-
*
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
* Enhanced:
|
325 |
-
* Fixed bug: If
|
326 |
-
|
327 |
-
= 4.
|
328 |
-
*
|
329 |
-
* Enhanced:
|
330 |
-
* Enhanced:
|
331 |
-
*
|
332 |
-
|
333 |
-
|
334 |
-
*
|
335 |
-
*
|
336 |
-
|
337 |
-
|
338 |
-
* Enhanced:
|
339 |
-
*
|
340 |
-
* Fixed bug:
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
*
|
345 |
-
*
|
346 |
-
* Fixed bug:
|
347 |
-
|
348 |
-
= 4.5 (2014-08-
|
349 |
-
*
|
350 |
-
*
|
351 |
-
*
|
352 |
-
* Fixed bug:
|
353 |
-
|
354 |
-
= 4.
|
355 |
-
*
|
356 |
-
|
357 |
-
|
358 |
-
* Fixed bug:
|
359 |
-
|
360 |
-
= 4.4.
|
361 |
-
* Fixed bug: Errors when using older PHP versions 5.3 or lower.
|
362 |
-
|
363 |
-
= 4.4.
|
364 |
-
*
|
365 |
-
|
366 |
-
|
367 |
-
* Fixed bug:
|
368 |
-
|
369 |
-
= 4.4 (2014-08-
|
370 |
-
*
|
371 |
-
* Enhanced:
|
372 |
-
*
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
*
|
377 |
-
*
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
* Enhanced:
|
382 |
-
*
|
383 |
-
* Fixed bug:
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
* Enhanced:
|
389 |
-
*
|
390 |
-
* Fixed bug:
|
391 |
-
* Fixed bug:
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
*
|
397 |
-
*
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
*
|
404 |
-
|
405 |
-
|
406 |
-
*
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
*
|
411 |
-
*
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
* Enhanced:
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
*
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
* Fixed bug:
|
447 |
-
|
448 |
-
= 4.0.
|
449 |
-
* Fixed bug:
|
450 |
-
|
451 |
-
= 4.0.
|
452 |
-
*
|
453 |
-
|
454 |
-
|
455 |
-
* Fixed bug:
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
* Enhanced:
|
461 |
-
*
|
462 |
-
*
|
463 |
-
* Fixed bug:
|
464 |
-
|
465 |
-
= 4.0.
|
466 |
-
*
|
467 |
-
|
468 |
-
|
469 |
-
*
|
470 |
-
|
471 |
-
= 4.0.
|
472 |
-
* Fixed bug:
|
473 |
-
|
474 |
-
= 4.0 (2014-02-
|
475 |
-
* Enhanced:
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
* Fixed bug:
|
483 |
-
|
484 |
-
= 3.9.
|
485 |
-
*
|
486 |
-
|
487 |
-
= 3.9.
|
488 |
-
*
|
489 |
-
|
490 |
-
= 3.9.
|
491 |
-
*
|
492 |
-
|
493 |
-
|
494 |
-
* Enhanced:
|
495 |
-
|
496 |
-
|
497 |
-
*
|
498 |
-
*
|
499 |
-
|
500 |
-
|
501 |
-
* Enhanced:
|
502 |
-
* Fixed bug:
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
* Fixed bug:
|
509 |
-
|
510 |
-
= 3.9.
|
511 |
-
*
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
*
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
*
|
523 |
-
*
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
*
|
529 |
-
*
|
530 |
-
*
|
531 |
-
*
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
*
|
536 |
-
|
537 |
-
|
538 |
-
*
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
*
|
545 |
-
* Fixed bug:
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
* Fixed bug:
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
* Enhanced:
|
555 |
-
* Fixed bug:
|
556 |
-
|
557 |
-
= 3.
|
558 |
-
*
|
559 |
-
*
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
*
|
566 |
-
|
567 |
-
|
568 |
-
*
|
569 |
-
|
570 |
-
= 3.4.
|
571 |
-
*
|
572 |
-
*
|
573 |
-
*
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
*
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
*
|
584 |
-
|
585 |
-
|
586 |
-
*
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
*
|
592 |
-
|
593 |
-
|
594 |
-
*
|
595 |
-
|
596 |
-
|
597 |
-
* Fixed bug:
|
598 |
-
|
599 |
-
= Version 3.3.
|
600 |
-
*
|
601 |
-
*
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
*
|
607 |
-
*
|
608 |
-
|
609 |
-
|
610 |
-
*
|
611 |
-
*
|
612 |
-
*
|
613 |
-
*
|
614 |
-
|
615 |
-
|
616 |
-
*
|
617 |
-
*
|
618 |
-
* Enhanced:
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
*
|
625 |
-
|
626 |
-
|
627 |
-
*
|
628 |
-
|
629 |
-
|
630 |
-
*
|
631 |
-
|
632 |
-
|
633 |
-
*
|
634 |
-
*
|
635 |
-
*
|
636 |
-
*
|
637 |
-
|
638 |
-
|
639 |
-
* New feature: Option to
|
640 |
-
* New feature:
|
641 |
-
* New feature: Option to
|
642 |
-
* New feature:
|
643 |
-
*
|
644 |
-
*
|
645 |
-
*
|
646 |
-
*
|
647 |
-
*
|
648 |
-
*
|
649 |
-
*
|
650 |
-
*
|
651 |
-
|
652 |
-
|
653 |
-
*
|
654 |
-
*
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
*
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
*
|
666 |
-
|
667 |
-
|
668 |
-
* Fixed bug
|
669 |
-
|
670 |
-
= Version 2.
|
671 |
-
*
|
672 |
-
*
|
673 |
-
* Fixed
|
674 |
-
*
|
675 |
-
|
676 |
-
= Version 2.
|
677 |
-
*
|
678 |
-
*
|
679 |
-
*
|
680 |
-
*
|
681 |
-
|
682 |
-
|
683 |
-
*
|
684 |
-
*
|
685 |
-
*
|
686 |
-
*
|
687 |
-
*
|
688 |
-
*
|
689 |
-
*
|
690 |
-
|
691 |
-
|
692 |
-
* Now requires WordPress 3.
|
693 |
-
*
|
694 |
-
*
|
695 |
-
*
|
696 |
-
|
697 |
-
|
698 |
-
*
|
699 |
-
*
|
700 |
-
*
|
701 |
-
|
702 |
-
|
703 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== WP RSS Aggregator ===
|
2 |
+
Contributors: jeangalea, Mekku, xedin.unknown, markzahra, doytch, chiragswadia
|
3 |
+
Plugin URI: http://www.wprssaggregator.com
|
4 |
+
Tags: rss, aggregation, autoblog, autoblog aggregator, autoblogger, autoblogging, autopost, content curation, feed aggregation, feed aggregator, feed import, feed reader, feed to post, feeds, multi feed import, multi feed importer, multi rss feeds, multiple feed import, multiple rss feeds,rss aggregator, rss feader, RSS Feed, rss feed to post, rss feeder, RSS import, rss multi importer, rss post importer, rss retriever, rss to post, syndication
|
5 |
+
Requires at least: 4.0
|
6 |
+
Tested up to: 4.3.1
|
7 |
+
Stable tag: 4.7.8
|
8 |
+
License: GPLv2 or later
|
9 |
+
The no.1 RSS feed importer for WordPress. Premium add-ons available for more functionality.
|
10 |
+
|
11 |
+
|
12 |
+
== Description ==
|
13 |
+
|
14 |
+
WP RSS Aggregator is the most comprehensive and elegant RSS feed solution for WordPress.
|
15 |
+
|
16 |
+
The original and best plugin for importing, merging and displaying RSS and Atom feeds on your WordPress site.
|
17 |
+
|
18 |
+
With WP RSS Aggregator, you can:
|
19 |
+
|
20 |
+
* Display feeds from one or more sites on your blog
|
21 |
+
* Aggregate feeds from multiple sites
|
22 |
+
|
23 |
+
You can add any number of feeds through an administration panel, the plugin will then pull feed items from these sites, merge them and display them in date order.
|
24 |
+
|
25 |
+
To [display your imported feed items](http://wordpress.org/plugins/wp-rss-aggregator/screenshots/), you can use a shortcode or call the display function directly from within your theme.
|
26 |
+
|
27 |
+
= Highlighted Features =
|
28 |
+
|
29 |
+
* Export a custom RSS feed based on your feed sources
|
30 |
+
* Pagination
|
31 |
+
* Set the feed import time interval
|
32 |
+
* Scheduling of feed imports by feed source
|
33 |
+
* Various shortcode parameters you can use to further customize the output
|
34 |
+
* Choose whether to show/hide sources and dates
|
35 |
+
* Choose the date format
|
36 |
+
* Set the links as no-follow or not, or add no follow to meta tag
|
37 |
+
* Select how you would like the links to open (in a Lightbox, a new window, or the current window)
|
38 |
+
* Set the name of the feed source
|
39 |
+
* Select number of posts per feed you want to show and store
|
40 |
+
* Opens YouTube, DailyMotion and Vimeo videos directly
|
41 |
+
* Limit number of feed items stored in the database
|
42 |
+
* Feed autodiscovery, which lets you add feeds without even knowing the exact URL.
|
43 |
+
* Extendable via action and filter hooks
|
44 |
+
* Integrated with the Simplepie library that come with WordPress. This includes RSS 0.91 and RSS 1.0 formats, the popular RSS 2.0 format, Atom etc.
|
45 |
+
|
46 |
+
= Premium Add-Ons =
|
47 |
+
Add-Ons that add more functionality to the core plugin are [available for purchase](http://www.wprssaggregator.com/extensions/).
|
48 |
+
|
49 |
+
* [Feed to Post](http://www.wprssaggregator.com/extensions/feed-to-post) - an advanced importer that lets you import RSS to posts or custom post types. Populate a website in minutes (autoblog). This is the most popular extension.
|
50 |
+
* [Keyword Filtering](http://www.wprssaggregator.com/extensions/keyword-filtering) - filter imported feeds based on keywords, so you only get items you're interested in.
|
51 |
+
* [Excerpts & Thumbnails](http://www.wprssaggregator.com/extensions/excerpts-thumbnails) - display excerpts and thumbnails together with the title, date and source.
|
52 |
+
* [Categories](http://www.wprssaggregator.com/extensions/categories) - categorise your feed sources and display items from a particular category at will within your site.
|
53 |
+
* [WordAi](http://www.wprssaggregator.com/extension/wordai/) - WordAi allows users to take an RSS feed and turn it into new content that is both completely unique and completely readable.
|
54 |
+
* [Full Text RSS Feeds](http://www.wprssaggregator.com/extension/full-text-rss-feeds/) - connectivity to our Full Text Premium service, which gives you unlimited feed items returned per feed source.
|
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 the [demo page](http://www.wprssaggregator.com/demo/).
|
60 |
+
|
61 |
+
= Video Walkthrough =
|
62 |
+
[youtube http://www.youtube.com/watch?v=fcENPsmJbvc]
|
63 |
+
|
64 |
+
= Documentation =
|
65 |
+
Instructions for plugin usage are available on the plugin's [documentation page](http://www.wprssaggregator.com/documentation/).
|
66 |
+
|
67 |
+
= As featured on =
|
68 |
+
* [Latest WP](http://www.latestwp.com/2015/03/15/wp-rss-aggregator-plugin-review/)
|
69 |
+
* [WP Beginner](http://www.wpbeginner.com/plugins/how-to-fetch-feeds-in-wordpress-using-wp-rss-aggregator/)
|
70 |
+
* [WPEXplorer](http://www.wpexplorer.com/custom-rss-aggregator-plugin/)
|
71 |
+
* [WP Kube](http://www.wpkube.com/wp-rss-aggregator-wordpress-review/)
|
72 |
+
* [Torquemag](http://torquemag.io/wp-rss-aggregator-review-do-more-with-rss-feeds/)
|
73 |
+
* [MyWPExpert](http://www.mywpexpert.com/wordpress-rss-aggregator-plugin)
|
74 |
+
* [Kikolani](http://kikolani.com/create-latest-posts-portfolio-page-wp-rss-aggregator.html)
|
75 |
+
* [ManageWP Plugins of the Month](http://managewp.com/free-wordpress-plugins-march-2014)
|
76 |
+
* [TidyRepo](http://tidyrepo.com/wp-rss-aggregator/)
|
77 |
+
* [WP Eka](http://www.wpeka.com/wp-rss-aggregators-plugin.html)
|
78 |
+
* [IndexWP](www.indexwp.com/wp-rss-aggregator-plugin-review/)
|
79 |
+
* [WPulsar](http://www.wpulsar.com/wp-rss-aggregator-plugin-feed-to-posts-keyword-filtering-review/)
|
80 |
+
* [Kevin Muldoon](http://www.kevinmuldoon.com/wp-rss-aggregator-wordpress-plugin/)
|
81 |
+
|
82 |
+
= Translations =
|
83 |
+
* Italian - Davide De Maestri
|
84 |
+
* Spanish - Andrew Kurtis
|
85 |
+
* Brazilian Portugese - Bruno Calheira
|
86 |
+
* Dutch - Erick Suiker
|
87 |
+
|
88 |
+
== Installation ==
|
89 |
+
|
90 |
+
1. Upload the `wp-rss-aggregator` folder to the `/wp-content/plugins/` directory
|
91 |
+
2. Activate the WP RSS Aggregator plugin through the 'Plugins' menu in WordPress
|
92 |
+
3. Configure the plugin by going to the `RSS Aggregator` menu item that appears in your dashboard menu.
|
93 |
+
3. Use the shortcode in your posts or pages: `[wp-rss-aggregator]`
|
94 |
+
|
95 |
+
The parameters accepted are:
|
96 |
+
|
97 |
+
* links_before
|
98 |
+
* links_after
|
99 |
+
* link_before
|
100 |
+
* link_after
|
101 |
+
* limit
|
102 |
+
* source
|
103 |
+
* exclude
|
104 |
+
* pagination
|
105 |
+
|
106 |
+
An example of a shortcode with parameters:
|
107 |
+
`[wp_rss_aggregator link_before='<li class="feed-link">' link_after='</li>']`
|
108 |
+
It is advisable to use the 'HTML' view of the editor when inserting the shortcode with paramters.
|
109 |
+
|
110 |
+
For a full list of shortcode parameters and usage guide please refer to the [documentation](http://www.wprssaggregator.com/docs/shortcodes/).
|
111 |
+
|
112 |
+
__Usage within theme files__
|
113 |
+
|
114 |
+
An example of a function call from within the theme's files:
|
115 |
+
`
|
116 |
+
<?php
|
117 |
+
wprss_display_feed_items( $args = array(
|
118 |
+
'links_before' => '<ul>',
|
119 |
+
'links_after' => '</ul>',
|
120 |
+
'link_before' => '<li>',
|
121 |
+
'link_after' => '</li>',
|
122 |
+
'limit' => '8',
|
123 |
+
'source' => '5,9'
|
124 |
+
));
|
125 |
+
?>
|
126 |
+
`
|
127 |
+
|
128 |
+
OR
|
129 |
+
|
130 |
+
`<?php do_shortcode('[wp-rss-aggregator]'); ?>`
|
131 |
+
|
132 |
+
|
133 |
+
== Frequently Asked Questions ==
|
134 |
+
= How do I display the imported feed items? =
|
135 |
+
|
136 |
+
You can either use the shortcode in your posts and pages:
|
137 |
+
`[wp-rss-aggregator]`
|
138 |
+
|
139 |
+
or you can call the function directly within your theme:
|
140 |
+
`<?php wprss_display_feed_items(); ?>`
|
141 |
+
|
142 |
+
= Is there a limit on the number of feed sources I can use? =
|
143 |
+
|
144 |
+
There is no limit in place for the number of feed sources. Having many (50+) feed sources should not present any problems in itself.
|
145 |
+
|
146 |
+
However, pulling in posts from many sites is bound to put your server under some stress, so you might want to consider using a hosting solution that goes beyond your typical shared host.
|
147 |
+
|
148 |
+
Check out our dedicated page on [WordPress hosting](http://www.wprssaggregator.com/recommended-web-hosts/) recommendations.
|
149 |
+
|
150 |
+
= Does WP RSS Aggregator work using JSON as the source? =
|
151 |
+
|
152 |
+
No, our plugin does not currently import from JSON, it only imports from RSS and Atom structured XML.
|
153 |
+
|
154 |
+
= Why do I get “No feed items found” when I insert the shortcode on a page or post? =
|
155 |
+
|
156 |
+
Try adding a few more feed sources and make sure they are valid by using the RSS Feed validator.
|
157 |
+
|
158 |
+
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.
|
159 |
+
|
160 |
+
= Can I store imported feed items as posts? =
|
161 |
+
|
162 |
+
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.
|
163 |
+
|
164 |
+
= Some RSS feeds only give a short excerpt. Any way around that? =
|
165 |
+
|
166 |
+
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.
|
167 |
+
|
168 |
+
= I’m not sure which premium add-ons are right for me. Can you help me out? =
|
169 |
+
|
170 |
+
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.
|
171 |
+
|
172 |
+
If you need any further help you can contact our support team [here](http://www.wprssaggregator.com/contact/).
|
173 |
+
|
174 |
+
= Where can I find the documentation for the plugin? =
|
175 |
+
|
176 |
+
The full documentation section can be found on the [WP RSS Aggregator website](http://docs.wprssaggregator.com/), the documentation also includes an extensive FAQ list.
|
177 |
+
|
178 |
+
|
179 |
+
== Screenshots ==
|
180 |
+
|
181 |
+
1. Feed items imported by WP RSS Aggregator displayed on the front-end using the shortcode.
|
182 |
+
|
183 |
+
2. Feed Items imported by WP RSS Aggregator and displayed with the [Excerpts & Thumbnails](http://www.wprssaggregator.com/extensions/excerpts-thumbnails) add-on installed.
|
184 |
+
|
185 |
+
3. Adding/Editing a feed source.
|
186 |
+
|
187 |
+
4. The feed sources.
|
188 |
+
|
189 |
+
5. The imported feeds items.
|
190 |
+
|
191 |
+
6. WP RSS Aggregator's Settings page.
|
192 |
+
|
193 |
+
|
194 |
+
== Changelog ==
|
195 |
+
|
196 |
+
= 4.7.8 (2015-11-18) =
|
197 |
+
* Fixed bug: Sticky posts no longer get deleted when truncating, unless imported from a feed source.
|
198 |
+
* Enhanced: Added autoloading and refactored licensing.
|
199 |
+
* Enhanced: Added button to download error log.
|
200 |
+
* Enhanced: Cosmetic changes and fixes.
|
201 |
+
|
202 |
+
= 4.7.7 (2015-10-19) =
|
203 |
+
* Enhanced: Optimized checking for plugin updates.
|
204 |
+
|
205 |
+
= 4.7.6 (2015-10-07) =
|
206 |
+
* Enhanced: Feeds that fail to validate due to whitespace at the beginning are now supported by the plugin.
|
207 |
+
* Fixed bug: Undefined variables in the System Info section in the Debugging page.
|
208 |
+
* Fixed bug: Add-on license expiration notices could not be dismissed.
|
209 |
+
|
210 |
+
= 4.7.5 (2015-09-02) =
|
211 |
+
* Usage tracking now disabled.
|
212 |
+
* Fixed bug: error related to undefined `ajaxurl` JS variable gone from frontend.
|
213 |
+
* Enhanced: Licensing errors will be output to debug log.
|
214 |
+
* Enhanced: Improved compatibility with plugins that allow AJAX searching in the backend.
|
215 |
+
|
216 |
+
= 4.7.4 (2015-08-20) =
|
217 |
+
* Requirement: WordPress 4.0 or greater now required.
|
218 |
+
* Fixed bug in image caching
|
219 |
+
* Fixed bug in admin interface due to incorrectly translated IDs
|
220 |
+
|
221 |
+
= 4.7.3 (2015-08-04) =
|
222 |
+
* Enhanced: Core now implements an image cache logic.
|
223 |
+
* Enhanced: Add-ons on the "Add-ons" page now have an installed-but-inactive status.
|
224 |
+
* Enhanced: Google Alerts permalinks will now be normalized.
|
225 |
+
* Enhanced: Russian translation added.
|
226 |
+
* Fixed bug: Inline help (tooltips) translations now work.
|
227 |
+
* Fixed bug: Link to the Feed to Post add-on on the welcome page is no longer broken.
|
228 |
+
|
229 |
+
= 4.7.2 (2015-06-30) =
|
230 |
+
* Enhanced: Copyright updated.
|
231 |
+
* Fixed bug: Word trimming no longer adds extra closing tags at the end.
|
232 |
+
* Fixed bug: Presence of `idna_convert` class no longer causes infinite redirects on some servers.
|
233 |
+
* Fixed bug: Warning of unterminated comment no longer thrown in PHP 5.5.
|
234 |
+
* Fixed bug: Added default value for "Unique Titles" option.
|
235 |
+
* Fixed bug: Having a the port number specified with the database host no longer causes issues with the `mysqli` adapter in System Info on some servers.
|
236 |
+
* Fixed bug: Nested options of inline help controller no longer cause a fatal error.
|
237 |
+
* Fixed bug: Notices will no longer be displayed during rendering of feed items due to absence of required default values.
|
238 |
+
|
239 |
+
= 4.7.1 (2015-04-23) =
|
240 |
+
* Fixed bug: No warning will be thrown when fetching feeds.
|
241 |
+
|
242 |
+
= 4.7 (2015-04-21) =
|
243 |
+
* New: Optionally import only items with titles that don't already exist.
|
244 |
+
* Enhanced: Accessing feeds over HTTPS is now possible.
|
245 |
+
* Enhanced: Added support for multibyte strings in some places.
|
246 |
+
* Enhanced: Increased JS compatibility with other plugins.
|
247 |
+
* Enhanced: Increased UI support for mobile devices.
|
248 |
+
* Fixed bug: Having no mysqli extension no longer causes an error to appear in the debug info.
|
249 |
+
* Fixed bug: Saving an empty license key no longer results in a warning.
|
250 |
+
|
251 |
+
= 4.6.13 (2015-03-20) =
|
252 |
+
* Fixed bug: The "Force feed" option wasn't being correctly used.
|
253 |
+
|
254 |
+
= 4.6.12 (2015-03-09) =
|
255 |
+
* Fixed bug: The "Force feed" option was being removed by the Feed to Post add-on.
|
256 |
+
|
257 |
+
= 4.6.11 (2015-03-04) =
|
258 |
+
* Enhanced: The Help page now includes a support form if a premium add-on is detected.
|
259 |
+
* Enhanced: Updated some translations for admin options.
|
260 |
+
* Fixed bug: Help tooltips are now optimized for iPad screens.
|
261 |
+
* Fixed bug: Errors on the licensing page when a license code has not yet been entered.
|
262 |
+
|
263 |
+
= 4.6.10 (2015-02-10) =
|
264 |
+
* Enhanced: AJAX license activation.
|
265 |
+
* Enhanced: License form more reliable.
|
266 |
+
* Enhanced: license-related UI improvements
|
267 |
+
* New: Markdown library added. Changelog now read from readme.
|
268 |
+
* Fixed bug: Saving license keys not longer triggers error in some cases.
|
269 |
+
|
270 |
+
= 4.6.9 (2015-01-21) =
|
271 |
+
* Enhanced: Admin user will now be warned about invalid or expiring licenses.
|
272 |
+
* Enhanced: Admin notices logic centralized in this plugin.
|
273 |
+
* Fixed: Multiple small-scale security vulnerabilities.
|
274 |
+
* Fixed: Ampersand in feed URL no longer causes the product of generated feeds to be invalidated by W3C Validator.
|
275 |
+
|
276 |
+
= 4.6.8 (2015-01-07) =
|
277 |
+
* Enhanced: Added more logging during feed importing.
|
278 |
+
* Enhanced: Irrelevent metaboxes added by other plugins are now removed from the Add/Edit Feed Source page.
|
279 |
+
* Fixed bug: Valid feed URLS were being invalidated.
|
280 |
+
* Fixed bug: The Blacklist feature was being hidden when the Feed to Post add-on was enabled.
|
281 |
+
* Fixed bug: Patched a vulnerability where any user on the site can issue a feed fetch.
|
282 |
+
* Fixed bug: The "Activate" and "Pause" actions are not shown in the bulk actions dropdown in WordPress v4.1.
|
283 |
+
|
284 |
+
= 4.6.7 (2014-12-17) =
|
285 |
+
* Enhanced: Some minor interface updates.
|
286 |
+
* Enhanced: Added filters for use by the premium add-ons.
|
287 |
+
|
288 |
+
= 4.6.6 (2014-12-06) =
|
289 |
+
* Enhanced: Added output layouts for feed sources and feed items.
|
290 |
+
* Enhanced: Updated EDD updater class to version 1.5.
|
291 |
+
* Enhanced: Added time limit extending to prevent script from exhausting its execution time limit while importing.
|
292 |
+
* Fixed bug: The "Delete and Re-import" button was deleting items but not re-importing.
|
293 |
+
* Fixed bug: Non-object errors when a feed source is deleted while importing.
|
294 |
+
|
295 |
+
= 4.6.5 (2014-11-17) =
|
296 |
+
* Enhanced: Improved the logging.
|
297 |
+
* Enhanced: Improved the licensing fields.
|
298 |
+
* Enhanced: Updated the EDD updater class to the latest version.
|
299 |
+
* Fixed bug: Small random error when viewing the licenses page.
|
300 |
+
|
301 |
+
= 4.6.4 (2014-11-10) =
|
302 |
+
* Enhanced: Added filters to the custom feed.
|
303 |
+
* Enhanced: Updated some styles to improve the user interface.
|
304 |
+
* Fixed bug: The "Remove selected from Blacklist" button had no nonce associated with it.
|
305 |
+
* Fixed bug: The Blacklist menu entry was not always being shown.
|
306 |
+
|
307 |
+
= 4.6.3 (2014-11-3) =
|
308 |
+
Enhanced: Re-added the "Add New" link in the plugin's menu.
|
309 |
+
Enhanced: Improved error logging.
|
310 |
+
Enhanced: Bulk actions in the Feed Sources page are now also included in the bottom dropdown menu.
|
311 |
+
Fixed bug: Add-on updater was prone to conflicts. Now enclosed in an action.
|
312 |
+
Fixed bug: The Full Text RSS Feeds add-on was not showing as active in the "Add-ons" page.
|
313 |
+
Fixed bug: Broken links in the "Add-ons" page, to add-on pages on our site.
|
314 |
+
|
315 |
+
= 4.6.2 (2014-10-15) =
|
316 |
+
* Enhanced: Improved plugin responsiveness.
|
317 |
+
* Enhanced: Updated some help text in tooltips with better explainations and added clarity.
|
318 |
+
* Enhanced: Optimized some old SQL queries.
|
319 |
+
* Enhanced: Added better debug logging.
|
320 |
+
* Enhanced: Added a new filter to modify the text shown before author names.
|
321 |
+
* Fixed bug: Licenses were not showing as active, even though they were activated.
|
322 |
+
|
323 |
+
= 4.6.1 (2014-10-06) =
|
324 |
+
* Enhanced: Improved internationalization in the plugin, for better translations.
|
325 |
+
* Fixed bug: If the feed source age limit was left empty, the global setting was used instead of ignoring the limit.
|
326 |
+
|
327 |
+
= 4.6 (2014-09-22) =
|
328 |
+
* Enhanced: Improved the user interface, with better responsiveness and tooltips.
|
329 |
+
* Enhanced: Removes the ID column. The ID is now shown fixed in row actions.
|
330 |
+
* Enhanced: Feed Preview indicates if feed items have no dates.
|
331 |
+
* Fixed bug: If a feed item has no date, the date and time it was imported is used.
|
332 |
+
|
333 |
+
= 4.5.3 (2014-09-15) =
|
334 |
+
* New Featured: Added filter to allow adding RSS feeds to the head of your site's pages for CPTs.
|
335 |
+
* Enhanced: Columns in the feed sources table are now sortable.
|
336 |
+
* Enhanced: Removed the ID column in the feed sources table. The ID has been moved as a row action.
|
337 |
+
* Enhanced: Improved various interface elements.
|
338 |
+
* Enhanced: Better responsiveness for smaller screen.
|
339 |
+
* Fixed bug: The importing spinning icon would get stuck and spin for a very long time.
|
340 |
+
* Fixed bug: Removed an old description meta field.
|
341 |
+
* Fixed bug: Plugin was not removing all scheduled cron jobs when deactivated.
|
342 |
+
|
343 |
+
= 4.5.2 (2014-09-09) =
|
344 |
+
* Enhanced: Optimized plugin for WordPress 4.0.
|
345 |
+
* Enhanced: Improved template and added filters for add-on hooking.
|
346 |
+
* Fixed bug: Editor toolbar visible over the WP RSS shortcode dialog.
|
347 |
+
|
348 |
+
= 4.5.1 (2014-08-26) =
|
349 |
+
* Fixed bug: Last import feed item count stays at zero.
|
350 |
+
* Fixed bug: Datetime::setTimestamp error when using PHP 5.2 or earlier.
|
351 |
+
* Fixed bug: The display limit was not working.
|
352 |
+
* Fixed bug: Minor bug in licensing.
|
353 |
+
|
354 |
+
= 4.5 (2014-08-25) =
|
355 |
+
* New Feature: Bulk importer allows you to create multiple feed sources at once.
|
356 |
+
* Enhanced: Improved OPML importer with added hooks.
|
357 |
+
* Enhanced: Centralized add-on licensing, fixing multiple bugs.
|
358 |
+
* Fixed bug: Undefined `feed_limit` errors when using the shortcode.
|
359 |
+
|
360 |
+
= 4.4.4 (2014-08-19) =
|
361 |
+
* Fixed bug: Errors when using older PHP versions 5.3 or lower.
|
362 |
+
|
363 |
+
= 4.4.3 (2014-08-19) =
|
364 |
+
* Fixed bug: Errors when using older PHP versions 5.3 or lower.
|
365 |
+
|
366 |
+
= 4.4.2 (2014-08-19) =
|
367 |
+
* Fixed bug: Errors when using older PHP versions 5.3 or lower.
|
368 |
+
|
369 |
+
= 4.4.1 (2014-08-18) =
|
370 |
+
* Enhanced: Various improvements to the plugin interface and texts.
|
371 |
+
* Enhanced: Moved the restore default settings button farther down the Debugging page, to avoid confusion with the delete button.
|
372 |
+
* Fixed bug: Feed item dates were not being adjusted to the timezone when using a GMT offset.
|
373 |
+
* Fixed bug: Feed item dates are now adjusted according to daylight savings time.
|
374 |
+
|
375 |
+
= 4.4 (2014-08-11) =
|
376 |
+
* New Feature: Blacklist - delete items and blacklist them to never import them again.
|
377 |
+
* Enhanced: Added a button in the Debugging page to reset the plugin settings to default.
|
378 |
+
* Enhanced: WordPress Yoast SEO metaboxes and custom columns will no longer appear.
|
379 |
+
|
380 |
+
= 4.3.1 (2014-08-08) =
|
381 |
+
* Enhanced: Better wording on settings page.
|
382 |
+
* Fixed bug: The Links Behaviour option in the settings was not working.
|
383 |
+
* Fixed bug: The wrong feed items were being shown for some sources when using the "View Items" row action.
|
384 |
+
|
385 |
+
= 4.3 (2014-08-04) =
|
386 |
+
* New Feature: Feed items now also import authors.
|
387 |
+
* Enhanced: Custom feed is now in RSS 2.0 format.
|
388 |
+
* Enhanced: Improved the display template for feed items.
|
389 |
+
* Fixed bug: Custom feed was not working in Firefox.
|
390 |
+
* Fixed bug: Some feed items were showing items from another feed source.
|
391 |
+
* Fixed bug: The feed limit in the global settings was not working.
|
392 |
+
|
393 |
+
= 4.2.3 (2014-07-29) =
|
394 |
+
* Enhanced: Added an option to choose between the current pagination type, and numbered pagination.
|
395 |
+
* Enhanced: The Feed Preview now also shows the total number of items in the feed.
|
396 |
+
* Fixed bug: A PHP warning error was being shown in the System Info.
|
397 |
+
* Fixed bug: Language files were not always being referenced correctly.
|
398 |
+
* Fixed bug: Manually fetching a feed fails if the feed is scheduled to update in the next 10 minutes.
|
399 |
+
* Fixed bug: Bing RSS feeds were importing duplicates on every update.
|
400 |
+
|
401 |
+
= 4.2.2 (2014-07-23) =
|
402 |
+
* Enhanced: Facebook page feeds are now changed into RSS 2.0 feeds, rather than Atom 1.0 feeds.
|
403 |
+
* Enhanced: Improved live updating performace on the Feed Sources page.
|
404 |
+
|
405 |
+
= 4.2.1 (2014-07-17) =
|
406 |
+
* Enhanced: Feed Sources page is now more responsive.
|
407 |
+
|
408 |
+
= 4.2 (2014-07-17) =
|
409 |
+
* New Feature: Can now view each feed source's imported feed items separate from other feed sources' feed items.
|
410 |
+
* Enhanced: Major visual update to the Feed Sources page with new live updates.
|
411 |
+
* Enhanced: The custom feed now includes the feed source.
|
412 |
+
* Fixed bug: Google News feeds were importing duplicate items on every update.
|
413 |
+
* Fixed bug: Multiple minor bug fixes with old filters.
|
414 |
+
|
415 |
+
= 4.1.6 (2014-06-28) =
|
416 |
+
* Fixed bug: Results returned by wprss_get_feed_items_for_source() will no longer be affected by filters.
|
417 |
+
* Fixed bug: Charset issue in titles
|
418 |
+
|
419 |
+
= 4.1.5 (2014-06-19) =
|
420 |
+
* Enhanced: The Feed Sources table now indicates which feed sources encountered errors during the last import.
|
421 |
+
* Fixed bug: Feed titles were not being decoded for HTML entities.
|
422 |
+
|
423 |
+
= 4.1.4 (2014-05-16) =
|
424 |
+
* Enhanced: Minor improvements to feed importing and handling.
|
425 |
+
* Fixed bug: HTML entities were not being decoded in feed item titles.
|
426 |
+
|
427 |
+
= 4.1.3 (2014-04-28) =
|
428 |
+
* Enhanced: Added a force feed option, for valid RSS feeds with incorrect header content types.
|
429 |
+
* Fixed bug: HTML entities in feed item titles are now being decoded.
|
430 |
+
|
431 |
+
= 4.1.2 (2014-04-22) =
|
432 |
+
* Enhanced: Improved the custom feed, by allowing a custom title.
|
433 |
+
* Enhanced: Improved shortcode, by adding the "pagination" parameter.
|
434 |
+
* Enhanced: Modified a filter to fix some bugs in the add-ons.
|
435 |
+
|
436 |
+
= 4.1.1 (2014-04-09) =
|
437 |
+
* Enhanced: Tracking notices only appear for admin users.
|
438 |
+
* Fixed bug: Auto Feed Discovery was not working.
|
439 |
+
|
440 |
+
= 4.1 (2014-04-03) =
|
441 |
+
* New Feature: Feed items can now link to enclosure links in the feed.
|
442 |
+
* Enhanced: Added a filter to allow add-ons to modify feed item queries.
|
443 |
+
|
444 |
+
= 4.0.9 (2014-03-27) =
|
445 |
+
* Enhanced: Added a filter to modify the feeds template.
|
446 |
+
* Fixed bug: Nested lists in feeds template.
|
447 |
+
|
448 |
+
= 4.0.8 (2014-03-20) =
|
449 |
+
* Fixed bug: Using the shortcode makes the comments section always open.
|
450 |
+
|
451 |
+
= 4.0.7 (2014-03-08) =
|
452 |
+
* Fixed bug: The plugin prevented uploading of header images.
|
453 |
+
|
454 |
+
= 4.0.6 (2014-03-05) =
|
455 |
+
* Fixed bug: Hook change in last version suspected reason for some installations having non-updated feed items.
|
456 |
+
|
457 |
+
= 4.0.5 (2014-03-03) =
|
458 |
+
* New Feature: Time ago added as an option.
|
459 |
+
* Enhanced: The plugin now allows the use of RSS and Atom feeds that do not specify the correct MIME type.
|
460 |
+
* Enhanced: Better performance due to better hook usage.
|
461 |
+
* Fixed bug: Facebook page feed URL conversion was not being triggered for new feed sources.
|
462 |
+
* Fixed bug: Styles fix for pagination.
|
463 |
+
* Fixed bug: Removed empty spaces in logging.
|
464 |
+
|
465 |
+
= 4.0.4 (2014-02-17) =
|
466 |
+
* Enhanced: Added Activate/Pause bulk actions in the Feed Sources page.
|
467 |
+
* Enhanced: Feed Sources page table has been re-designed.
|
468 |
+
* Enhanced: Logging is now site dependant on multisite.
|
469 |
+
* Fixed bug: Undefined display settings where appearing on the front end.
|
470 |
+
|
471 |
+
= 4.0.3 (2014-02-12) =
|
472 |
+
* Fixed bug: The general setting for deleting feed items by age was not working.
|
473 |
+
|
474 |
+
= 4.0.2 (2014-02-10) =
|
475 |
+
* Enhanced: Added a filter to change the html tags allowed in feed item content.
|
476 |
+
|
477 |
+
= 4.0.1 (2014-02-08) =
|
478 |
+
* Fixed bug: Empty array of feed items bug caused importing problems.
|
479 |
+
|
480 |
+
= 4.0 (2014-02-04) =
|
481 |
+
* Enhanced: Improved some internal queries, for better performance.
|
482 |
+
* Fixed bug: Feed limits were not working properly.
|
483 |
+
|
484 |
+
= 3.9.9 (2014-02-03) =
|
485 |
+
* Enhanced: The custom feed can now be extended by add-ons.
|
486 |
+
|
487 |
+
= 3.9.8 (2014-01-20) =
|
488 |
+
* Fixed bug: Removed excessive logging from Debugging Error Log.
|
489 |
+
|
490 |
+
= 3.9.7 (2014-01-17) =
|
491 |
+
* Fixed bug: Bug in admin-debugging.php causing trouble with admin login
|
492 |
+
|
493 |
+
= 3.9.6 (2014-01-17) =
|
494 |
+
* Enhanced: Added error logging.
|
495 |
+
|
496 |
+
= 3.9.5 (2014-01-02) =
|
497 |
+
* Enhanced: Added a feed validator link in the New/Edit Feed Sources page.
|
498 |
+
* Enhanced: The Next Update column also shows the time remaining for next update, for feed source on the global update interval.
|
499 |
+
* Enhanced: The custom feed has been improved, and is now identical to the feeds displayed with the shortcode.
|
500 |
+
* Enhanced: License notifications only appear on the main site when using WordPress multisite.
|
501 |
+
* Enhanced: Updated Colorbox script to 1.4.33
|
502 |
+
* Fixed bug: The Imported Items column was always showing zero.
|
503 |
+
* Fixed bug: Feed items not being imported with limit set to zero. Should be unlimited.
|
504 |
+
* Fixed bug: Fat header in Feed Sources page
|
505 |
+
|
506 |
+
= 3.9.4 (2013-12-24) =
|
507 |
+
* Enhanced: Added a column in the Feed Sources page that shows the number of feed items imported for each feed source.
|
508 |
+
* Fixed bug: Leaving the delete old feed items empty did not ignore the delete.
|
509 |
+
|
510 |
+
= 3.9.3 (2013-12-23) =
|
511 |
+
* Fixed bug: Fixed tracking pointer appearing on saving settings.
|
512 |
+
|
513 |
+
= 3.9.2 (2013-12-21) =
|
514 |
+
* Fixed bug: Incorrect file include call.
|
515 |
+
|
516 |
+
= 3.9.1 (2013-12-12) =
|
517 |
+
* Enhanced: Improved date and time handling for imported feed items.
|
518 |
+
* Fixed bug: Incorrect values being shown in the Feed Processing metabox.
|
519 |
+
* Fixed bug: Feed limits set to zero were causing feeds to not be imported.
|
520 |
+
|
521 |
+
= 3.9 (2013-12-12) =
|
522 |
+
* New Feature: Feed sources can have their own update interval.
|
523 |
+
* New Feature: The time remaining until the next update has been added to the Feed Source table.
|
524 |
+
|
525 |
+
= 3.8 (2013-12-05) =
|
526 |
+
* New Feature: Feed items can be limited and deleted by their age.
|
527 |
+
* Enhanced: Added utility functions for shorter filters.
|
528 |
+
* Fixed bug: License codes were being erased when add-ons were deactivated.
|
529 |
+
* Fixed bug: Some feed sources could not be set to active from the table controls.
|
530 |
+
* Fixed bug: str_pos errors appear when custom feed url is left empty.
|
531 |
+
* Fixed bug: Some options were producing undefined index errors.
|
532 |
+
|
533 |
+
= 3.7 (2013-11-28) =
|
534 |
+
* New Feature: State system - Feed sources can be activated/paused.
|
535 |
+
* New Feature: State system - Feed sources can be set to activate or pause themselves at a specific date and time.
|
536 |
+
* Enhanced: Added compatibility with nested outline elements in OPML files.
|
537 |
+
* Enhanced: Admin menu icon image will change into a Dashicon, when WordPress is updated to 3.8 (Decemeber 2013).
|
538 |
+
* Fixed bug: Custom Post types were breaking when the plugin is activated.
|
539 |
+
|
540 |
+
= 3.6.1 (2013-11-17) =
|
541 |
+
* Fixed bug: Missing 2nd argument for wprss_shorten_title()
|
542 |
+
|
543 |
+
= 3.6 (2013-11-16) =
|
544 |
+
* New Feature: Can set the maximum length for titles. Long titles get trimmed.
|
545 |
+
* Fixed bug: Fixed errors with undefined indexes for unchecked checkboxes in the settings page.
|
546 |
+
* Fixed bug: Pagination on front static page was not working.
|
547 |
+
|
548 |
+
= 3.5.2 (2013-11-11) =
|
549 |
+
* Fixed bug: Invalid feed source url was producing an Undefined method notice.
|
550 |
+
* Fixed bug: Custom feed was producing a 404 page.
|
551 |
+
* Fixed bug: Presstrends code firing on admin_init, opt-in implementation coming soon
|
552 |
+
|
553 |
+
= 3.5.1 (2013-11-09) =
|
554 |
+
* Enhanced: Increased compatibility with RSS sources.
|
555 |
+
* Fixed bug: Pagination not working on home page
|
556 |
+
|
557 |
+
= 3.5 (2013-11-6) =
|
558 |
+
* New Feature: Can delete feed items for a particular source
|
559 |
+
* Enhanced: the 'Fetch feed items' row action for feed sources resets itself after 3.5 seconds.
|
560 |
+
* Enhanced: The feed image is saved for each url.
|
561 |
+
* Fixed bug: Link to source now links to correct url. Previously linked to site's feed.
|
562 |
+
|
563 |
+
= 3.4.6 (2013-11-1) =
|
564 |
+
* Enhanced: Added more hooks to debugging page for the Feed to Post add-on.
|
565 |
+
* Fixed bug: Uninitialized loop index
|
566 |
+
|
567 |
+
= 3.4.5 (2013-10-30) =
|
568 |
+
* Bug Fix: Feed items were not being imported while the WPML plugin was active.
|
569 |
+
|
570 |
+
= 3.4.4 (2013-10-26) =
|
571 |
+
* New feature: Pagination
|
572 |
+
* New feature: First implementation of editor button for easy shortcode creation
|
573 |
+
* Enhanced: Feed items and sources don't show up in link manager
|
574 |
+
* Enhanced: Included Presstrends code for plugin usage monitoring
|
575 |
+
|
576 |
+
= 3.4.3 (2013-10-20) =
|
577 |
+
* Fixed bug: Removed anonymous functions for backwards PHP compatibility
|
578 |
+
* Bug fix: Added suppress_filters in feed-display.php to prevent a user reported error
|
579 |
+
* Bug fix: Missing <li> in certain feed displays
|
580 |
+
|
581 |
+
= 3.4.2 (2013-9-19) =
|
582 |
+
* Enhanced: Added some hooks for Feed to Post compatibility
|
583 |
+
* Enhanced: Moved date settings to a more appropriate location
|
584 |
+
|
585 |
+
= 3.4.1 (2013-9-16) =
|
586 |
+
* Fixed Bug: Minor issue with options page - PHP notice
|
587 |
+
|
588 |
+
= 3.4 (2013-9-15) =
|
589 |
+
* New Feature: Saving/Updating a feed source triggers an update for that source's feed items.
|
590 |
+
* New Feature: Option to change Youtube, Vimeo and Dailymotion feed item URLs to embedded video players URLs
|
591 |
+
* New Feature: Facebook Pages URLs are automatically detected and changed into Atom Feed URLs using FB's Graph
|
592 |
+
* Enhanced: Updated jQuery Colorbox library to 1.4.29
|
593 |
+
* Fixed Bug: Some settings did not have a default value set, and were throwing an 'Undefined Index' error
|
594 |
+
* Fixed Bug: Admin notices do not disappear immediately when dismissed.
|
595 |
+
|
596 |
+
= Version 3.3.3 (2013-09-08) =
|
597 |
+
* Fixed bug: Better function handling on uninstall, should remove uninstall issues
|
598 |
+
|
599 |
+
= Version 3.3.2 (2013-09-07) =
|
600 |
+
* New feature: Added exclude parameter to shortcode
|
601 |
+
* Enhanced: Added metabox links to documentation and add-ons
|
602 |
+
* Fixed bug: Custom feed linking to post on user site rather than original source
|
603 |
+
* Fixed bug: Custom post types issues when activitating the plugin
|
604 |
+
|
605 |
+
= Version 3.3.1 (2013-08-09) =
|
606 |
+
* Fixed Bug: Roles and Capabilities file had not been included
|
607 |
+
* Fixed Bug: Error on install, function not found
|
608 |
+
|
609 |
+
= Version 3.3 (2013-08-08) =
|
610 |
+
* New feature: OPML importer
|
611 |
+
* New feature: Feed item limits for individual Feed Sources
|
612 |
+
* New feature: Custom feed URL
|
613 |
+
* New feature: Feed limit on custom feed
|
614 |
+
* New feature: New 'Fetch feed items' action for each Feed Source in listing display
|
615 |
+
* New feature: Option to enable link to source
|
616 |
+
* Enhanced: Date strings now change according to locale being used (i.e. compatible with WPML)
|
617 |
+
* Enhanced: Capabilities implemented
|
618 |
+
* Enhanced: Feed Sources row action 'View' removed
|
619 |
+
* Fixed Bug: Proxy feed URLs resulting in the permalink: example.com/url
|
620 |
+
|
621 |
+
= Version 3.2 (2013-07-06) =
|
622 |
+
* New feature: Parameter to limit number of feeds displayed
|
623 |
+
* New feature: Paramter to limit feeds displayed to particular sources (via ID)
|
624 |
+
* Enhanced: Better feed import handling to handle large number of feed sources
|
625 |
+
|
626 |
+
= Version 3.1.1 (2013-06-06) =
|
627 |
+
* Fixed bug: Incompatibility with some other plugins due to function missing namespace
|
628 |
+
|
629 |
+
= Version 3.1 (2013-06-06) =
|
630 |
+
* New feature: Option to set the number of feed items imported from every feed (default 5)
|
631 |
+
* New feature: Import and Export aggregator settings and feed sources
|
632 |
+
* New feature: Debugging page allowing manual feed refresh and feed reset
|
633 |
+
* Enhanced: Faster handling of restoring sources from trash when feed limit is 0
|
634 |
+
* Fixed bug: Limiter on number of overall feeds stored not working
|
635 |
+
* Fixed bug: Incompatibility issue with Foobox plugin fixed
|
636 |
+
* Fixed bug: Duplicate feeds sometimes imported
|
637 |
+
|
638 |
+
= Version 3.0 (2013-03-16) =
|
639 |
+
* New feature: Option to select cron frequency
|
640 |
+
* New feature: Code extensibility added to be compatible with add-ons
|
641 |
+
* New feature: Option to set a limit to the number of feeds stored (previously 50, hard coded)
|
642 |
+
* New feature: Option to define the format of the date shown below each feed item
|
643 |
+
* New feature: Option to show or hide source of feed item
|
644 |
+
* New feature: Option to show or hide publish date of feed item
|
645 |
+
* New feature: Option to set text preceding publish date
|
646 |
+
* New feature: Option to set text preceding source of feed item
|
647 |
+
* New feature: Option to link title or not
|
648 |
+
* New feature: Limit of 5 items imported for each source instead of 10
|
649 |
+
* Enhanced: Performance improvement when publishing * New feeds in admin
|
650 |
+
* Enhanced: Query tuning for better performance
|
651 |
+
* Enhanced: Major code rewrite, refactoring and inclusion of hooks
|
652 |
+
* Enhanced: Updated Colorbox to v1.4.1
|
653 |
+
* Enhanced: Better security implementations
|
654 |
+
* Enhanced: Better feed preview display
|
655 |
+
* Fixed bug: Deletion of items upon source deletion not working properly
|
656 |
+
* Requires: WordPress 3.3
|
657 |
+
|
658 |
+
= Version 2.2.3 (2012-11-01) =
|
659 |
+
* Fixed bug: Tab navigation preventing typing in input boxes
|
660 |
+
* Removed: Feeds showing up in internal linking pop up
|
661 |
+
|
662 |
+
= Version 2.2.2 (2012-10-30) =
|
663 |
+
* Removed: Feeds showing up in site search results
|
664 |
+
* Enhanced: Better tab button navigation when adding a new feed
|
665 |
+
* Enhanced: Better guidance when a feed URL is invalid
|
666 |
+
|
667 |
+
= Version 2.2.1 (2012-10-17) =
|
668 |
+
* Fixed bug: wprss_feed_source_order assumes everyone is an admin
|
669 |
+
|
670 |
+
= Version 2.2 (2012-10-01) =
|
671 |
+
* Italian translation added
|
672 |
+
* Feed source order changed to alphabetical
|
673 |
+
* Fixed bug - repeated entries when having a non-valid feed source
|
674 |
+
* Fixed bug - all imported feeds deleted upon trashing a single feed source
|
675 |
+
|
676 |
+
= Version 2.1 (2012-09-27) =
|
677 |
+
* Now localised for translations
|
678 |
+
* Fixed bug with date string
|
679 |
+
* Fixed $link_before and $link_after, now working
|
680 |
+
* Added backwards compatibility for wp_rss_aggregator() function
|
681 |
+
|
682 |
+
= Version 2.0 (2012-09-21) =
|
683 |
+
* Bulk of code rewritten and refactored
|
684 |
+
* Added install and upgrade functions
|
685 |
+
* Added DB version setting
|
686 |
+
* Feed sources now stored as Custom Post Types
|
687 |
+
* Feed source list sortable ascending or descending by name
|
688 |
+
* Removed days subsections in feed display
|
689 |
+
* Ability to limit total number of feeds displayed
|
690 |
+
* Feeds now fetched via Cron
|
691 |
+
* Cron job to delete old feed items, keeps max of 50 items in DB
|
692 |
+
* Now requires WordPress 3.2
|
693 |
+
* Updated colorbox to v1.3.20.1
|
694 |
+
* Limit of 15 items max imported for each source
|
695 |
+
* Fixed issue of page content displaying incorrectly after feeds
|
696 |
+
|
697 |
+
= Version 1.1 (2012-08-13) =
|
698 |
+
* Now requires WordPress 3.0
|
699 |
+
* More flexible fetching of images directory
|
700 |
+
* Has its own top level menu item
|
701 |
+
* Added settings section
|
702 |
+
* Ability to open in lightbox, new window or default browser behaviour
|
703 |
+
* Ability to set links as follow or no follow
|
704 |
+
* Using constants for oftenly used locations
|
705 |
+
* Code refactoring
|
706 |
+
* Changes in file and folder structure
|
707 |
+
|
708 |
+
= Version 1.0 (2012-01-06) =
|
709 |
+
=== WP RSS Aggregator ===
|
710 |
+
Contributors: jeangalea, Mekku, xedin.unknown, markzahra, doytch, chiragswadia
|
711 |
+
Plugin URI: http://www.wprssaggregator.com
|
712 |
+
Tags: rss, aggregation, autoblog, autoblog aggregator, autoblogger, autoblogging, autopost, content curation, feed aggregation, feed aggregator, feed import, feed reader, feed to post, feeds, multi feed import, multi feed importer, multi rss feeds, multiple feed import, multiple rss feeds,rss aggregator, rss feader, RSS Feed, rss feed to post, rss feeder, RSS import, rss multi importer, rss post importer, rss retriever, rss to post, syndication
|
713 |
+
Requires at least: 4.0
|
714 |
+
Tested up to: 4.3.1
|
715 |
+
Stable tag: 4.7.7
|
716 |
+
License: GPLv2 or later
|
717 |
+
The no.1 RSS feed importer for WordPress. Premium add-ons available for more functionality.
|
718 |
+
|
719 |
+
|
720 |
+
== Description ==
|
721 |
+
|
722 |
+
WP RSS Aggregator is the most comprehensive and elegant RSS feed solution for WordPress.
|
723 |
+
|
724 |
+
The original and premier plugin for importing, merging and displaying RSS and Atom feeds on your WordPress site.
|
725 |
+
|
726 |
+
With WP RSS Aggregator, you can:
|
727 |
+
|
728 |
+
* Display feeds from one or more sites on your blog
|
729 |
+
* Aggregate feeds from multiple sites
|
730 |
+
|
731 |
+
You can add any number of feeds through an administration panel, the plugin will then pull feed items from these sites, merge them and display them in date order.
|
732 |
+
|
733 |
+
To [display your imported feed items](http://wordpress.org/plugins/wp-rss-aggregator/screenshots/), you can use a shortcode or call the display function directly from within your theme.
|
734 |
+
|
735 |
+
= Highlighted Features =
|
736 |
+
|
737 |
+
* Export a custom RSS feed based on your feed sources
|
738 |
+
* Pagination
|
739 |
+
* Set the feed import time interval
|
740 |
+
* Scheduling of feed imports by feed source
|
741 |
+
* Various shortcode parameters you can use to further customize the output
|
742 |
+
* Choose whether to show/hide sources and dates
|
743 |
+
* Choose the date format
|
744 |
+
* Set the links as no-follow or not, or add no follow to meta tag
|
745 |
+
* Select how you would like the links to open (in a Lightbox, a new window, or the current window)
|
746 |
+
* Set the name of the feed source
|
747 |
+
* Select number of posts per feed you want to show and store
|
748 |
+
* Opens YouTube, DailyMotion and Vimeo videos directly
|
749 |
+
* Limit number of feed items stored in the database
|
750 |
+
* Feed autodiscovery, which lets you add feeds without even knowing the exact URL.
|
751 |
+
* Extendable via action and filter hooks
|
752 |
+
* Integrated with the Simplepie library that come with WordPress. This includes RSS 0.91 and RSS 1.0 formats, the popular RSS 2.0 format, Atom etc.
|
753 |
+
|
754 |
+
= Premium Add-Ons =
|
755 |
+
Add-Ons that add more functionality to the core plugin are [available for purchase](http://www.wprssaggregator.com/extensions/).
|
756 |
+
|
757 |
+
* [Feed to Post](http://www.wprssaggregator.com/extensions/feed-to-post) - an advanced importer that lets you import RSS to posts or custom post types. Populate a website in minutes (autoblog). This is the most popular extension.
|
758 |
+
* [Keyword Filtering](http://www.wprssaggregator.com/extensions/keyword-filtering) - filter imported feeds based on keywords, so you only get items you're interested in.
|
759 |
+
* [Excerpts & Thumbnails](http://www.wprssaggregator.com/extensions/excerpts-thumbnails) - display excerpts and thumbnails together with the title, date and source.
|
760 |
+
* [Categories](http://www.wprssaggregator.com/extensions/categories) - categorise your feed sources and display items from a particular category at will within your site.
|
761 |
+
* [WordAi](http://www.wprssaggregator.com/extension/wordai/) - WordAi allows users to take an RSS feed and turn it into new content that is both completely unique and completely readable.
|
762 |
+
* [Full Text RSS Feeds](http://www.wprssaggregator.com/extension/full-text-rss-feeds/) - connectivity to our Full Text Premium service, which gives you unlimited feed items returned per feed source.
|
763 |
+
* [Widget](http://www.wprssaggregator.com/extension/widget/) - Add a widget that displays imported feed items.
|
764 |
+
|
765 |
+
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.
|
766 |
+
|
767 |
+
= Demo =
|
768 |
+
The core plugin can be seen in use on the [demo page](http://www.wprssaggregator.com/demo/).
|
769 |
+
|
770 |
+
= Video Walkthrough =
|
771 |
+
[youtube http://www.youtube.com/watch?v=fcENPsmJbvc]
|
772 |
+
|
773 |
+
= Documentation =
|
774 |
+
Instructions for plugin usage are available on the plugin's [documentation page](http://www.wprssaggregator.com/documentation/).
|
775 |
+
|
776 |
+
= As featured on =
|
777 |
+
* [Latest WP](http://www.latestwp.com/2015/03/15/wp-rss-aggregator-plugin-review/)
|
778 |
+
* [WP Beginner](http://www.wpbeginner.com/plugins/how-to-fetch-feeds-in-wordpress-using-wp-rss-aggregator/)
|
779 |
+
* [WPEXplorer](http://www.wpexplorer.com/custom-rss-aggregator-plugin/)
|
780 |
+
* [WP Kube](http://www.wpkube.com/wp-rss-aggregator-wordpress-review/)
|
781 |
+
* [Torquemag](http://torquemag.io/wp-rss-aggregator-review-do-more-with-rss-feeds/)
|
782 |
+
* [MyWPExpert](http://www.mywpexpert.com/wordpress-rss-aggregator-plugin)
|
783 |
+
* [Kikolani](http://kikolani.com/create-latest-posts-portfolio-page-wp-rss-aggregator.html)
|
784 |
+
* [ManageWP Plugins of the Month](http://managewp.com/free-wordpress-plugins-march-2014)
|
785 |
+
* [TidyRepo](http://tidyrepo.com/wp-rss-aggregator/)
|
786 |
+
* [WP Eka](http://www.wpeka.com/wp-rss-aggregators-plugin.html)
|
787 |
+
* [IndexWP](www.indexwp.com/wp-rss-aggregator-plugin-review/)
|
788 |
+
* [WPulsar](http://www.wpulsar.com/wp-rss-aggregator-plugin-feed-to-posts-keyword-filtering-review/)
|
789 |
+
* [Kevin Muldoon](http://www.kevinmuldoon.com/wp-rss-aggregator-wordpress-plugin/)
|
790 |
+
|
791 |
+
= Translations =
|
792 |
+
* Italian - Davide De Maestri
|
793 |
+
* Spanish - Andrew Kurtis
|
794 |
+
* Brazilian Portugese - Bruno Calheira
|
795 |
+
* Dutch - Erick Suiker
|
796 |
+
|
797 |
+
== Installation ==
|
798 |
+
|
799 |
+
1. Upload the `wp-rss-aggregator` folder to the `/wp-content/plugins/` directory
|
800 |
+
2. Activate the WP RSS Aggregator plugin through the 'Plugins' menu in WordPress
|
801 |
+
3. Configure the plugin by going to the `RSS Aggregator` menu item that appears in your dashboard menu.
|
802 |
+
3. Use the shortcode in your posts or pages: `[wp-rss-aggregator]`
|
803 |
+
|
804 |
+
The parameters accepted are:
|
805 |
+
|
806 |
+
* links_before
|
807 |
+
* links_after
|
808 |
+
* link_before
|
809 |
+
* link_after
|
810 |
+
* limit
|
811 |
+
* source
|
812 |
+
* exclude
|
813 |
+
* pagination
|
814 |
+
|
815 |
+
An example of a shortcode with parameters:
|
816 |
+
`[wp_rss_aggregator link_before='<li class="feed-link">' link_after='</li>']`
|
817 |
+
It is advisable to use the 'HTML' view of the editor when inserting the shortcode with paramters.
|
818 |
+
|
819 |
+
For a full list of shortcode parameters and usage guide please refer to the [documentation](http://www.wprssaggregator.com/docs/shortcodes/).
|
820 |
+
|
821 |
+
__Usage within theme files__
|
822 |
+
|
823 |
+
An example of a function call from within the theme's files:
|
824 |
+
`
|
825 |
+
<?php
|
826 |
+
wprss_display_feed_items( $args = array(
|
827 |
+
'links_before' => '<ul>',
|
828 |
+
'links_after' => '</ul>',
|
829 |
+
'link_before' => '<li>',
|
830 |
+
'link_after' => '</li>',
|
831 |
+
'limit' => '8',
|
832 |
+
'source' => '5,9'
|
833 |
+
));
|
834 |
+
?>
|
835 |
+
`
|
836 |
+
|
837 |
+
OR
|
838 |
+
|
839 |
+
`<?php do_shortcode('[wp-rss-aggregator]'); ?>`
|
840 |
+
|
841 |
+
|
842 |
+
== Frequently Asked Questions ==
|
843 |
+
= How do I display the imported feed items? =
|
844 |
+
|
845 |
+
You can either use the shortcode in your posts and pages:
|
846 |
+
`[wp-rss-aggregator]`
|
847 |
+
|
848 |
+
or you can call the function directly within your theme:
|
849 |
+
`<?php wprss_display_feed_items(); ?>`
|
850 |
+
|
851 |
+
= Is there a limit on the number of feed sources I can use? =
|
852 |
+
|
853 |
+
There is no limit in place for the number of feed sources. Having many (50+) feed sources should not present any problems in itself.
|
854 |
+
|
855 |
+
However, pulling in posts from many sites is bound to put your server under some stress, so you might want to consider using a hosting solution that goes beyond your typical shared host.
|
856 |
+
|
857 |
+
Check out our dedicated page for hosting recommendations.
|
858 |
+
|
859 |
+
= Does WP RSS Aggregator work using JSON as the source? =
|
860 |
+
|
861 |
+
No, our plugin does not currently import from JSON, it only imports from RSS and Atom structured XML.
|
862 |
+
|
863 |
+
= Why do I get “No feed items found” when I insert the shortcode on a page or post? =
|
864 |
+
|
865 |
+
Try adding a few more feed sources and make sure they are valid by using the RSS Feed validator.
|
866 |
+
|
867 |
+
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.
|
868 |
+
|
869 |
+
= Can I store imported feed items as posts? =
|
870 |
+
|
871 |
+
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.
|
872 |
+
|
873 |
+
= Some RSS feeds only give a short excerpt. Any way around that? =
|
874 |
+
|
875 |
+
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.
|
876 |
+
|
877 |
+
= I’m not sure which premium add-ons are right for me. Can you help me out? =
|
878 |
+
|
879 |
+
Sure! We wrote a post 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.
|
880 |
+
|
881 |
+
If you need any further help you can contact our support team [here](http://www.wprssaggregator.com/contact/).
|
882 |
+
|
883 |
+
= Where can I find the documentation for the plugin? =
|
884 |
+
|
885 |
+
The full documentation section can be found on the [WP RSS Aggregator website](www.wprssaggregator.com/documentation/), the documentation also includes an extensive FAQ list.
|
886 |
+
|
887 |
+
|
888 |
+
== Screenshots ==
|
889 |
+
|
890 |
+
1. Feed items imported by WP RSS Aggregator displayed on the front-end using the shortcode.
|
891 |
+
|
892 |
+
2. Feed Items imported by WP RSS Aggregator and displayed with the [Excerpts & Thumbnails](http://www.wprssaggregator.com/extensions/excerpts-thumbnails) add-on installed.
|
893 |
+
|
894 |
+
3. Adding/Editing a feed source.
|
895 |
+
|
896 |
+
4. The feed sources.
|
897 |
+
|
898 |
+
5. The imported feeds items.
|
899 |
+
|
900 |
+
6. WP RSS Aggregator's Settings page.
|
901 |
+
|
902 |
+
|
903 |
+
== Changelog ==
|
904 |
+
|
905 |
+
= 4.7.7 (2015-10-19) =
|
906 |
+
* Enhanced: Optimized checking for plugin updates.
|
907 |
+
|
908 |
+
= 4.7.6 (2015-10-07) =
|
909 |
+
* Enhanced: Feeds that fail to validate due to whitespace at the beginning are now supported by the plugin.
|
910 |
+
* Fixed bug: Undefined variables in the System Info section in the Debugging page.
|
911 |
+
* Fixed bug: Add-on license expiration notices could not be dismissed.
|
912 |
+
|
913 |
+
= 4.7.5 (2015-09-02) =
|
914 |
+
* Usage tracking now disabled.
|
915 |
+
* Fixed bug: error related to undefined `ajaxurl` JS variable gone from frontend.
|
916 |
+
* Enhanced: Licensing errors will be output to debug log.
|
917 |
+
* Enhanced: Improved compatibility with plugins that allow AJAX searching in the backend.
|
918 |
+
|
919 |
+
= 4.7.4 (2015-08-20) =
|
920 |
+
* Requirement: WordPress 4.0 or greater now required.
|
921 |
+
* Fixed bug in image caching
|
922 |
+
* Fixed bug in admin interface due to incorrectly translated IDs
|
923 |
+
|
924 |
+
= 4.7.3 (2015-08-04) =
|
925 |
+
* Enhanced: Core now implements an image cache logic.
|
926 |
+
* Enhanced: Add-ons on the "Add-ons" page now have an installed-but-inactive status.
|
927 |
+
* Enhanced: Google Alerts permalinks will now be normalized.
|
928 |
+
* Enhanced: Russian translation added.
|
929 |
+
* Fixed bug: Inline help (tooltips) translations now work.
|
930 |
+
* Fixed bug: Link to the Feed to Post add-on on the welcome page is no longer broken.
|
931 |
+
|
932 |
+
= 4.7.2 (2015-06-30) =
|
933 |
+
* Enhanced: Copyright updated.
|
934 |
+
* Fixed bug: Word trimming no longer adds extra closing tags at the end.
|
935 |
+
* Fixed bug: Presence of `idna_convert` class no longer causes infinite redirects on some servers.
|
936 |
+
* Fixed bug: Warning of unterminated comment no longer thrown in PHP 5.5.
|
937 |
+
* Fixed bug: Added default value for "Unique Titles" option.
|
938 |
+
* Fixed bug: Having a the port number specified with the database host no longer causes issues with the `mysqli` adapter in System Info on some servers.
|
939 |
+
* Fixed bug: Nested options of inline help controller no longer cause a fatal error.
|
940 |
+
* Fixed bug: Notices will no longer be displayed during rendering of feed items due to absence of required default values.
|
941 |
+
|
942 |
+
= 4.7.1 (2015-04-23) =
|
943 |
+
* Fixed bug: No warning will be thrown when fetching feeds.
|
944 |
+
|
945 |
+
= 4.7 (2015-04-21) =
|
946 |
+
* New: Optionally import only items with titles that don't already exist.
|
947 |
+
* Enhanced: Accessing feeds over HTTPS is now possible.
|
948 |
+
* Enhanced: Added support for multibyte strings in some places.
|
949 |
+
* Enhanced: Increased JS compatibility with other plugins.
|
950 |
+
* Enhanced: Increased UI support for mobile devices.
|
951 |
+
* Fixed bug: Having no mysqli extension no longer causes an error to appear in the debug info.
|
952 |
+
* Fixed bug: Saving an empty license key no longer results in a warning.
|
953 |
+
|
954 |
+
= 4.6.13 (2015-03-20) =
|
955 |
+
* Fixed bug: The "Force feed" option wasn't being correctly used.
|
956 |
+
|
957 |
+
= 4.6.12 (2015-03-09) =
|
958 |
+
* Fixed bug: The "Force feed" option was being removed by the Feed to Post add-on.
|
959 |
+
|
960 |
+
= 4.6.11 (2015-03-04) =
|
961 |
+
* Enhanced: The Help page now includes a support form if a premium add-on is detected.
|
962 |
+
* Enhanced: Updated some translations for admin options.
|
963 |
+
* Fixed bug: Help tooltips are now optimized for iPad screens.
|
964 |
+
* Fixed bug: Errors on the licensing page when a license code has not yet been entered.
|
965 |
+
|
966 |
+
= 4.6.10 (2015-02-10) =
|
967 |
+
* Enhanced: AJAX license activation.
|
968 |
+
* Enhanced: License form more reliable.
|
969 |
+
* Enhanced: license-related UI improvements
|
970 |
+
* New: Markdown library added. Changelog now read from readme.
|
971 |
+
* Fixed bug: Saving license keys not longer triggers error in some cases.
|
972 |
+
|
973 |
+
= 4.6.9 (2015-01-21) =
|
974 |
+
* Enhanced: Admin user will now be warned about invalid or expiring licenses.
|
975 |
+
* Enhanced: Admin notices logic centralized in this plugin.
|
976 |
+
* Fixed: Multiple small-scale security vulnerabilities.
|
977 |
+
* Fixed: Ampersand in feed URL no longer causes the product of generated feeds to be invalidated by W3C Validator.
|
978 |
+
|
979 |
+
= 4.6.8 (2015-01-07) =
|
980 |
+
* Enhanced: Added more logging during feed importing.
|
981 |
+
* Enhanced: Irrelevent metaboxes added by other plugins are now removed from the Add/Edit Feed Source page.
|
982 |
+
* Fixed bug: Valid feed URLS were being invalidated.
|
983 |
+
* Fixed bug: The Blacklist feature was being hidden when the Feed to Post add-on was enabled.
|
984 |
+
* Fixed bug: Patched a vulnerability where any user on the site can issue a feed fetch.
|
985 |
+
* Fixed bug: The "Activate" and "Pause" actions are not shown in the bulk actions dropdown in WordPress v4.1.
|
986 |
+
|
987 |
+
= 4.6.7 (2014-12-17) =
|
988 |
+
* Enhanced: Some minor interface updates.
|
989 |
+
* Enhanced: Added filters for use by the premium add-ons.
|
990 |
+
|
991 |
+
= 4.6.6 (2014-12-06) =
|
992 |
+
* Enhanced: Added output layouts for feed sources and feed items.
|
993 |
+
* Enhanced: Updated EDD updater class to version 1.5.
|
994 |
+
* Enhanced: Added time limit extending to prevent script from exhausting its execution time limit while importing.
|
995 |
+
* Fixed bug: The "Delete and Re-import" button was deleting items but not re-importing.
|
996 |
+
* Fixed bug: Non-object errors when a feed source is deleted while importing.
|
997 |
+
|
998 |
+
= 4.6.5 (2014-11-17) =
|
999 |
+
* Enhanced: Improved the logging.
|
1000 |
+
* Enhanced: Improved the licensing fields.
|
1001 |
+
* Enhanced: Updated the EDD updater class to the latest version.
|
1002 |
+
* Fixed bug: Small random error when viewing the licenses page.
|
1003 |
+
|
1004 |
+
= 4.6.4 (2014-11-10) =
|
1005 |
+
* Enhanced: Added filters to the custom feed.
|
1006 |
+
* Enhanced: Updated some styles to improve the user interface.
|
1007 |
+
* Fixed bug: The "Remove selected from Blacklist" button had no nonce associated with it.
|
1008 |
+
* Fixed bug: The Blacklist menu entry was not always being shown.
|
1009 |
+
|
1010 |
+
= 4.6.3 (2014-11-3) =
|
1011 |
+
Enhanced: Re-added the "Add New" link in the plugin's menu.
|
1012 |
+
Enhanced: Improved error logging.
|
1013 |
+
Enhanced: Bulk actions in the Feed Sources page are now also included in the bottom dropdown menu.
|
1014 |
+
Fixed bug: Add-on updater was prone to conflicts. Now enclosed in an action.
|
1015 |
+
Fixed bug: The Full Text RSS Feeds add-on was not showing as active in the "Add-ons" page.
|
1016 |
+
Fixed bug: Broken links in the "Add-ons" page, to add-on pages on our site.
|
1017 |
+
|
1018 |
+
= 4.6.2 (2014-10-15) =
|
1019 |
+
* Enhanced: Improved plugin responsiveness.
|
1020 |
+
* Enhanced: Updated some help text in tooltips with better explainations and added clarity.
|
1021 |
+
* Enhanced: Optimized some old SQL queries.
|
1022 |
+
* Enhanced: Added better debug logging.
|
1023 |
+
* Enhanced: Added a new filter to modify the text shown before author names.
|
1024 |
+
* Fixed bug: Licenses were not showing as active, even though they were activated.
|
1025 |
+
|
1026 |
+
= 4.6.1 (2014-10-06) =
|
1027 |
+
* Enhanced: Improved internationalization in the plugin, for better translations.
|
1028 |
+
* Fixed bug: If the feed source age limit was left empty, the global setting was used instead of ignoring the limit.
|
1029 |
+
|
1030 |
+
= 4.6 (2014-09-22) =
|
1031 |
+
* Enhanced: Improved the user interface, with better responsiveness and tooltips.
|
1032 |
+
* Enhanced: Removes the ID column. The ID is now shown fixed in row actions.
|
1033 |
+
* Enhanced: Feed Preview indicates if feed items have no dates.
|
1034 |
+
* Fixed bug: If a feed item has no date, the date and time it was imported is used.
|
1035 |
+
|
1036 |
+
= 4.5.3 (2014-09-15) =
|
1037 |
+
* New Featured: Added filter to allow adding RSS feeds to the head of your site's pages for CPTs.
|
1038 |
+
* Enhanced: Columns in the feed sources table are now sortable.
|
1039 |
+
* Enhanced: Removed the ID column in the feed sources table. The ID has been moved as a row action.
|
1040 |
+
* Enhanced: Improved various interface elements.
|
1041 |
+
* Enhanced: Better responsiveness for smaller screen.
|
1042 |
+
* Fixed bug: The importing spinning icon would get stuck and spin for a very long time.
|
1043 |
+
* Fixed bug: Removed an old description meta field.
|
1044 |
+
* Fixed bug: Plugin was not removing all scheduled cron jobs when deactivated.
|
1045 |
+
|
1046 |
+
= 4.5.2 (2014-09-09) =
|
1047 |
+
* Enhanced: Optimized plugin for WordPress 4.0.
|
1048 |
+
* Enhanced: Improved template and added filters for add-on hooking.
|
1049 |
+
* Fixed bug: Editor toolbar visible over the WP RSS shortcode dialog.
|
1050 |
+
|
1051 |
+
= 4.5.1 (2014-08-26) =
|
1052 |
+
* Fixed bug: Last import feed item count stays at zero.
|
1053 |
+
* Fixed bug: Datetime::setTimestamp error when using PHP 5.2 or earlier.
|
1054 |
+
* Fixed bug: The display limit was not working.
|
1055 |
+
* Fixed bug: Minor bug in licensing.
|
1056 |
+
|
1057 |
+
= 4.5 (2014-08-25) =
|
1058 |
+
* New Feature: Bulk importer allows you to create multiple feed sources at once.
|
1059 |
+
* Enhanced: Improved OPML importer with added hooks.
|
1060 |
+
* Enhanced: Centralized add-on licensing, fixing multiple bugs.
|
1061 |
+
* Fixed bug: Undefined `feed_limit` errors when using the shortcode.
|
1062 |
+
|
1063 |
+
= 4.4.4 (2014-08-19) =
|
1064 |
+
* Fixed bug: Errors when using older PHP versions 5.3 or lower.
|
1065 |
+
|
1066 |
+
= 4.4.3 (2014-08-19) =
|
1067 |
+
* Fixed bug: Errors when using older PHP versions 5.3 or lower.
|
1068 |
+
|
1069 |
+
= 4.4.2 (2014-08-19) =
|
1070 |
+
* Fixed bug: Errors when using older PHP versions 5.3 or lower.
|
1071 |
+
|
1072 |
+
= 4.4.1 (2014-08-18) =
|
1073 |
+
* Enhanced: Various improvements to the plugin interface and texts.
|
1074 |
+
* Enhanced: Moved the restore default settings button farther down the Debugging page, to avoid confusion with the delete button.
|
1075 |
+
* Fixed bug: Feed item dates were not being adjusted to the timezone when using a GMT offset.
|
1076 |
+
* Fixed bug: Feed item dates are now adjusted according to daylight savings time.
|
1077 |
+
|
1078 |
+
= 4.4 (2014-08-11) =
|
1079 |
+
* New Feature: Blacklist - delete items and blacklist them to never import them again.
|
1080 |
+
* Enhanced: Added a button in the Debugging page to reset the plugin settings to default.
|
1081 |
+
* Enhanced: WordPress Yoast SEO metaboxes and custom columns will no longer appear.
|
1082 |
+
|
1083 |
+
= 4.3.1 (2014-08-08) =
|
1084 |
+
* Enhanced: Better wording on settings page.
|
1085 |
+
* Fixed bug: The Links Behaviour option in the settings was not working.
|
1086 |
+
* Fixed bug: The wrong feed items were being shown for some sources when using the "View Items" row action.
|
1087 |
+
|
1088 |
+
= 4.3 (2014-08-04) =
|
1089 |
+
* New Feature: Feed items now also import authors.
|
1090 |
+
* Enhanced: Custom feed is now in RSS 2.0 format.
|
1091 |
+
* Enhanced: Improved the display template for feed items.
|
1092 |
+
* Fixed bug: Custom feed was not working in Firefox.
|
1093 |
+
* Fixed bug: Some feed items were showing items from another feed source.
|
1094 |
+
* Fixed bug: The feed limit in the global settings was not working.
|
1095 |
+
|
1096 |
+
= 4.2.3 (2014-07-29) =
|
1097 |
+
* Enhanced: Added an option to choose between the current pagination type, and numbered pagination.
|
1098 |
+
* Enhanced: The Feed Preview now also shows the total number of items in the feed.
|
1099 |
+
* Fixed bug: A PHP warning error was being shown in the System Info.
|
1100 |
+
* Fixed bug: Language files were not always being referenced correctly.
|
1101 |
+
* Fixed bug: Manually fetching a feed fails if the feed is scheduled to update in the next 10 minutes.
|
1102 |
+
* Fixed bug: Bing RSS feeds were importing duplicates on every update.
|
1103 |
+
|
1104 |
+
= 4.2.2 (2014-07-23) =
|
1105 |
+
* Enhanced: Facebook page feeds are now changed into RSS 2.0 feeds, rather than Atom 1.0 feeds.
|
1106 |
+
* Enhanced: Improved live updating performace on the Feed Sources page.
|
1107 |
+
|
1108 |
+
= 4.2.1 (2014-07-17) =
|
1109 |
+
* Enhanced: Feed Sources page is now more responsive.
|
1110 |
+
|
1111 |
+
= 4.2 (2014-07-17) =
|
1112 |
+
* New Feature: Can now view each feed source's imported feed items separate from other feed sources' feed items.
|
1113 |
+
* Enhanced: Major visual update to the Feed Sources page with new live updates.
|
1114 |
+
* Enhanced: The custom feed now includes the feed source.
|
1115 |
+
* Fixed bug: Google News feeds were importing duplicate items on every update.
|
1116 |
+
* Fixed bug: Multiple minor bug fixes with old filters.
|
1117 |
+
|
1118 |
+
= 4.1.6 (2014-06-28) =
|
1119 |
+
* Fixed bug: Results returned by wprss_get_feed_items_for_source() will no longer be affected by filters.
|
1120 |
+
* Fixed bug: Charset issue in titles
|
1121 |
+
|
1122 |
+
= 4.1.5 (2014-06-19) =
|
1123 |
+
* Enhanced: The Feed Sources table now indicates which feed sources encountered errors during the last import.
|
1124 |
+
* Fixed bug: Feed titles were not being decoded for HTML entities.
|
1125 |
+
|
1126 |
+
= 4.1.4 (2014-05-16) =
|
1127 |
+
* Enhanced: Minor improvements to feed importing and handling.
|
1128 |
+
* Fixed bug: HTML entities were not being decoded in feed item titles.
|
1129 |
+
|
1130 |
+
= 4.1.3 (2014-04-28) =
|
1131 |
+
* Enhanced: Added a force feed option, for valid RSS feeds with incorrect header content types.
|
1132 |
+
* Fixed bug: HTML entities in feed item titles are now being decoded.
|
1133 |
+
|
1134 |
+
= 4.1.2 (2014-04-22) =
|
1135 |
+
* Enhanced: Improved the custom feed, by allowing a custom title.
|
1136 |
+
* Enhanced: Improved shortcode, by adding the "pagination" parameter.
|
1137 |
+
* Enhanced: Modified a filter to fix some bugs in the add-ons.
|
1138 |
+
|
1139 |
+
= 4.1.1 (2014-04-09) =
|
1140 |
+
* Enhanced: Tracking notices only appear for admin users.
|
1141 |
+
* Fixed bug: Auto Feed Discovery was not working.
|
1142 |
+
|
1143 |
+
= 4.1 (2014-04-03) =
|
1144 |
+
* New Feature: Feed items can now link to enclosure links in the feed.
|
1145 |
+
* Enhanced: Added a filter to allow add-ons to modify feed item queries.
|
1146 |
+
|
1147 |
+
= 4.0.9 (2014-03-27) =
|
1148 |
+
* Enhanced: Added a filter to modify the feeds template.
|
1149 |
+
* Fixed bug: Nested lists in feeds template.
|
1150 |
+
|
1151 |
+
= 4.0.8 (2014-03-20) =
|
1152 |
+
* Fixed bug: Using the shortcode makes the comments section always open.
|
1153 |
+
|
1154 |
+
= 4.0.7 (2014-03-08) =
|
1155 |
+
* Fixed bug: The plugin prevented uploading of header images.
|
1156 |
+
|
1157 |
+
= 4.0.6 (2014-03-05) =
|
1158 |
+
* Fixed bug: Hook change in last version suspected reason for some installations having non-updated feed items.
|
1159 |
+
|
1160 |
+
= 4.0.5 (2014-03-03) =
|
1161 |
+
* New Feature: Time ago added as an option.
|
1162 |
+
* Enhanced: The plugin now allows the use of RSS and Atom feeds that do not specify the correct MIME type.
|
1163 |
+
* Enhanced: Better performance due to better hook usage.
|
1164 |
+
* Fixed bug: Facebook page feed URL conversion was not being triggered for new feed sources.
|
1165 |
+
* Fixed bug: Styles fix for pagination.
|
1166 |
+
* Fixed bug: Removed empty spaces in logging.
|
1167 |
+
|
1168 |
+
= 4.0.4 (2014-02-17) =
|
1169 |
+
* Enhanced: Added Activate/Pause bulk actions in the Feed Sources page.
|
1170 |
+
* Enhanced: Feed Sources page table has been re-designed.
|
1171 |
+
* Enhanced: Logging is now site dependant on multisite.
|
1172 |
+
* Fixed bug: Undefined display settings where appearing on the front end.
|
1173 |
+
|
1174 |
+
= 4.0.3 (2014-02-12) =
|
1175 |
+
* Fixed bug: The general setting for deleting feed items by age was not working.
|
1176 |
+
|
1177 |
+
= 4.0.2 (2014-02-10) =
|
1178 |
+
* Enhanced: Added a filter to change the html tags allowed in feed item content.
|
1179 |
+
|
1180 |
+
= 4.0.1 (2014-02-08) =
|
1181 |
+
* Fixed bug: Empty array of feed items bug caused importing problems.
|
1182 |
+
|
1183 |
+
= 4.0 (2014-02-04) =
|
1184 |
+
* Enhanced: Improved some internal queries, for better performance.
|
1185 |
+
* Fixed bug: Feed limits were not working properly.
|
1186 |
+
|
1187 |
+
= 3.9.9 (2014-02-03) =
|
1188 |
+
* Enhanced: The custom feed can now be extended by add-ons.
|
1189 |
+
|
1190 |
+
= 3.9.8 (2014-01-20) =
|
1191 |
+
* Fixed bug: Removed excessive logging from Debugging Error Log.
|
1192 |
+
|
1193 |
+
= 3.9.7 (2014-01-17) =
|
1194 |
+
* Fixed bug: Bug in admin-debugging.php causing trouble with admin login
|
1195 |
+
|
1196 |
+
= 3.9.6 (2014-01-17) =
|
1197 |
+
* Enhanced: Added error logging.
|
1198 |
+
|
1199 |
+
= 3.9.5 (2014-01-02) =
|
1200 |
+
* Enhanced: Added a feed validator link in the New/Edit Feed Sources page.
|
1201 |
+
* Enhanced: The Next Update column also shows the time remaining for next update, for feed source on the global update interval.
|
1202 |
+
* Enhanced: The custom feed has been improved, and is now identical to the feeds displayed with the shortcode.
|
1203 |
+
* Enhanced: License notifications only appear on the main site when using WordPress multisite.
|
1204 |
+
* Enhanced: Updated Colorbox script to 1.4.33
|
1205 |
+
* Fixed bug: The Imported Items column was always showing zero.
|
1206 |
+
* Fixed bug: Feed items not being imported with limit set to zero. Should be unlimited.
|
1207 |
+
* Fixed bug: Fat header in Feed Sources page
|
1208 |
+
|
1209 |
+
= 3.9.4 (2013-12-24) =
|
1210 |
+
* Enhanced: Added a column in the Feed Sources page that shows the number of feed items imported for each feed source.
|
1211 |
+
* Fixed bug: Leaving the delete old feed items empty did not ignore the delete.
|
1212 |
+
|
1213 |
+
= 3.9.3 (2013-12-23) =
|
1214 |
+
* Fixed bug: Fixed tracking pointer appearing on saving settings.
|
1215 |
+
|
1216 |
+
= 3.9.2 (2013-12-21) =
|
1217 |
+
* Fixed bug: Incorrect file include call.
|
1218 |
+
|
1219 |
+
= 3.9.1 (2013-12-12) =
|
1220 |
+
* Enhanced: Improved date and time handling for imported feed items.
|
1221 |
+
* Fixed bug: Incorrect values being shown in the Feed Processing metabox.
|
1222 |
+
* Fixed bug: Feed limits set to zero were causing feeds to not be imported.
|
1223 |
+
|
1224 |
+
= 3.9 (2013-12-12) =
|
1225 |
+
* New Feature: Feed sources can have their own update interval.
|
1226 |
+
* New Feature: The time remaining until the next update has been added to the Feed Source table.
|
1227 |
+
|
1228 |
+
= 3.8 (2013-12-05) =
|
1229 |
+
* New Feature: Feed items can be limited and deleted by their age.
|
1230 |
+
* Enhanced: Added utility functions for shorter filters.
|
1231 |
+
* Fixed bug: License codes were being erased when add-ons were deactivated.
|
1232 |
+
* Fixed bug: Some feed sources could not be set to active from the table controls.
|
1233 |
+
* Fixed bug: str_pos errors appear when custom feed url is left empty.
|
1234 |
+
* Fixed bug: Some options were producing undefined index errors.
|
1235 |
+
|
1236 |
+
= 3.7 (2013-11-28) =
|
1237 |
+
* New Feature: State system - Feed sources can be activated/paused.
|
1238 |
+
* New Feature: State system - Feed sources can be set to activate or pause themselves at a specific date and time.
|
1239 |
+
* Enhanced: Added compatibility with nested outline elements in OPML files.
|
1240 |
+
* Enhanced: Admin menu icon image will change into a Dashicon, when WordPress is updated to 3.8 (Decemeber 2013).
|
1241 |
+
* Fixed bug: Custom Post types were breaking when the plugin is activated.
|
1242 |
+
|
1243 |
+
= 3.6.1 (2013-11-17) =
|
1244 |
+
* Fixed bug: Missing 2nd argument for wprss_shorten_title()
|
1245 |
+
|
1246 |
+
= 3.6 (2013-11-16) =
|
1247 |
+
* New Feature: Can set the maximum length for titles. Long titles get trimmed.
|
1248 |
+
* Fixed bug: Fixed errors with undefined indexes for unchecked checkboxes in the settings page.
|
1249 |
+
* Fixed bug: Pagination on front static page was not working.
|
1250 |
+
|
1251 |
+
= 3.5.2 (2013-11-11) =
|
1252 |
+
* Fixed bug: Invalid feed source url was producing an Undefined method notice.
|
1253 |
+
* Fixed bug: Custom feed was producing a 404 page.
|
1254 |
+
* Fixed bug: Presstrends code firing on admin_init, opt-in implementation coming soon
|
1255 |
+
|
1256 |
+
= 3.5.1 (2013-11-09) =
|
1257 |
+
* Enhanced: Increased compatibility with RSS sources.
|
1258 |
+
* Fixed bug: Pagination not working on home page
|
1259 |
+
|
1260 |
+
= 3.5 (2013-11-6) =
|
1261 |
+
* New Feature: Can delete feed items for a particular source
|
1262 |
+
* Enhanced: the 'Fetch feed items' row action for feed sources resets itself after 3.5 seconds.
|
1263 |
+
* Enhanced: The feed image is saved for each url.
|
1264 |
+
* Fixed bug: Link to source now links to correct url. Previously linked to site's feed.
|
1265 |
+
|
1266 |
+
= 3.4.6 (2013-11-1) =
|
1267 |
+
* Enhanced: Added more hooks to debugging page for the Feed to Post add-on.
|
1268 |
+
* Fixed bug: Uninitialized loop index
|
1269 |
+
|
1270 |
+
= 3.4.5 (2013-10-30) =
|
1271 |
+
* Bug Fix: Feed items were not being imported while the WPML plugin was active.
|
1272 |
+
|
1273 |
+
= 3.4.4 (2013-10-26) =
|
1274 |
+
* New feature: Pagination
|
1275 |
+
* New feature: First implementation of editor button for easy shortcode creation
|
1276 |
+
* Enhanced: Feed items and sources don't show up in link manager
|
1277 |
+
* Enhanced: Included Presstrends code for plugin usage monitoring
|
1278 |
+
|
1279 |
+
= 3.4.3 (2013-10-20) =
|
1280 |
+
* Fixed bug: Removed anonymous functions for backwards PHP compatibility
|
1281 |
+
* Bug fix: Added suppress_filters in feed-display.php to prevent a user reported error
|
1282 |
+
* Bug fix: Missing <li> in certain feed displays
|
1283 |
+
|
1284 |
+
= 3.4.2 (2013-9-19) =
|
1285 |
+
* Enhanced: Added some hooks for Feed to Post compatibility
|
1286 |
+
* Enhanced: Moved date settings to a more appropriate location
|
1287 |
+
|
1288 |
+
= 3.4.1 (2013-9-16) =
|
1289 |
+
* Fixed Bug: Minor issue with options page - PHP notice
|
1290 |
+
|
1291 |
+
= 3.4 (2013-9-15) =
|
1292 |
+
* New Feature: Saving/Updating a feed source triggers an update for that source's feed items.
|
1293 |
+
* New Feature: Option to change Youtube, Vimeo and Dailymotion feed item URLs to embedded video players URLs
|
1294 |
+
* New Feature: Facebook Pages URLs are automatically detected and changed into Atom Feed URLs using FB's Graph
|
1295 |
+
* Enhanced: Updated jQuery Colorbox library to 1.4.29
|
1296 |
+
* Fixed Bug: Some settings did not have a default value set, and were throwing an 'Undefined Index' error
|
1297 |
+
* Fixed Bug: Admin notices do not disappear immediately when dismissed.
|
1298 |
+
|
1299 |
+
= Version 3.3.3 (2013-09-08) =
|
1300 |
+
* Fixed bug: Better function handling on uninstall, should remove uninstall issues
|
1301 |
+
|
1302 |
+
= Version 3.3.2 (2013-09-07) =
|
1303 |
+
* New feature: Added exclude parameter to shortcode
|
1304 |
+
* Enhanced: Added metabox links to documentation and add-ons
|
1305 |
+
* Fixed bug: Custom feed linking to post on user site rather than original source
|
1306 |
+
* Fixed bug: Custom post types issues when activitating the plugin
|
1307 |
+
|
1308 |
+
= Version 3.3.1 (2013-08-09) =
|
1309 |
+
* Fixed Bug: Roles and Capabilities file had not been included
|
1310 |
+
* Fixed Bug: Error on install, function not found
|
1311 |
+
|
1312 |
+
= Version 3.3 (2013-08-08) =
|
1313 |
+
* New feature: OPML importer
|
1314 |
+
* New feature: Feed item limits for individual Feed Sources
|
1315 |
+
* New feature: Custom feed URL
|
1316 |
+
* New feature: Feed limit on custom feed
|
1317 |
+
* New feature: New 'Fetch feed items' action for each Feed Source in listing display
|
1318 |
+
* New feature: Option to enable link to source
|
1319 |
+
* Enhanced: Date strings now change according to locale being used (i.e. compatible with WPML)
|
1320 |
+
* Enhanced: Capabilities implemented
|
1321 |
+
* Enhanced: Feed Sources row action 'View' removed
|
1322 |
+
* Fixed Bug: Proxy feed URLs resulting in the permalink: example.com/url
|
1323 |
+
|
1324 |
+
= Version 3.2 (2013-07-06) =
|
1325 |
+
* New feature: Parameter to limit number of feeds displayed
|
1326 |
+
* New feature: Paramter to limit feeds displayed to particular sources (via ID)
|
1327 |
+
* Enhanced: Better feed import handling to handle large number of feed sources
|
1328 |
+
|
1329 |
+
= Version 3.1.1 (2013-06-06) =
|
1330 |
+
* Fixed bug: Incompatibility with some other plugins due to function missing namespace
|
1331 |
+
|
1332 |
+
= Version 3.1 (2013-06-06) =
|
1333 |
+
* New feature: Option to set the number of feed items imported from every feed (default 5)
|
1334 |
+
* New feature: Import and Export aggregator settings and feed sources
|
1335 |
+
* New feature: Debugging page allowing manual feed refresh and feed reset
|
1336 |
+
* Enhanced: Faster handling of restoring sources from trash when feed limit is 0
|
1337 |
+
* Fixed bug: Limiter on number of overall feeds stored not working
|
1338 |
+
* Fixed bug: Incompatibility issue with Foobox plugin fixed
|
1339 |
+
* Fixed bug: Duplicate feeds sometimes imported
|
1340 |
+
|
1341 |
+
= Version 3.0 (2013-03-16) =
|
1342 |
+
* New feature: Option to select cron frequency
|
1343 |
+
* New feature: Code extensibility added to be compatible with add-ons
|
1344 |
+
* New feature: Option to set a limit to the number of feeds stored (previously 50, hard coded)
|
1345 |
+
* New feature: Option to define the format of the date shown below each feed item
|
1346 |
+
* New feature: Option to show or hide source of feed item
|
1347 |
+
* New feature: Option to show or hide publish date of feed item
|
1348 |
+
* New feature: Option to set text preceding publish date
|
1349 |
+
* New feature: Option to set text preceding source of feed item
|
1350 |
+
* New feature: Option to link title or not
|
1351 |
+
* New feature: Limit of 5 items imported for each source instead of 10
|
1352 |
+
* Enhanced: Performance improvement when publishing * New feeds in admin
|
1353 |
+
* Enhanced: Query tuning for better performance
|
1354 |
+
* Enhanced: Major code rewrite, refactoring and inclusion of hooks
|
1355 |
+
* Enhanced: Updated Colorbox to v1.4.1
|
1356 |
+
* Enhanced: Better security implementations
|
1357 |
+
* Enhanced: Better feed preview display
|
1358 |
+
* Fixed bug: Deletion of items upon source deletion not working properly
|
1359 |
+
* Requires: WordPress 3.3
|
1360 |
+
|
1361 |
+
= Version 2.2.3 (2012-11-01) =
|
1362 |
+
* Fixed bug: Tab navigation preventing typing in input boxes
|
1363 |
+
* Removed: Feeds showing up in internal linking pop up
|
1364 |
+
|
1365 |
+
= Version 2.2.2 (2012-10-30) =
|
1366 |
+
* Removed: Feeds showing up in site search results
|
1367 |
+
* Enhanced: Better tab button navigation when adding a new feed
|
1368 |
+
* Enhanced: Better guidance when a feed URL is invalid
|
1369 |
+
|
1370 |
+
= Version 2.2.1 (2012-10-17) =
|
1371 |
+
* Fixed bug: wprss_feed_source_order assumes everyone is an admin
|
1372 |
+
|
1373 |
+
= Version 2.2 (2012-10-01) =
|
1374 |
+
* Italian translation added
|
1375 |
+
* Feed source order changed to alphabetical
|
1376 |
+
* Fixed bug - repeated entries when having a non-valid feed source
|
1377 |
+
* Fixed bug - all imported feeds deleted upon trashing a single feed source
|
1378 |
+
|
1379 |
+
= Version 2.1 (2012-09-27) =
|
1380 |
+
* Now localised for translations
|
1381 |
+
* Fixed bug with date string
|
1382 |
+
* Fixed $link_before and $link_after, now working
|
1383 |
+
* Added backwards compatibility for wp_rss_aggregator() function
|
1384 |
+
|
1385 |
+
= Version 2.0 (2012-09-21) =
|
1386 |
+
* Bulk of code rewritten and refactored
|
1387 |
+
* Added install and upgrade functions
|
1388 |
+
* Added DB version setting
|
1389 |
+
* Feed sources now stored as Custom Post Types
|
1390 |
+
* Feed source list sortable ascending or descending by name
|
1391 |
+
* Removed days subsections in feed display
|
1392 |
+
* Ability to limit total number of feeds displayed
|
1393 |
+
* Feeds now fetched via Cron
|
1394 |
+
* Cron job to delete old feed items, keeps max of 50 items in DB
|
1395 |
+
* Now requires WordPress 3.2
|
1396 |
+
* Updated colorbox to v1.3.20.1
|
1397 |
+
* Limit of 15 items max imported for each source
|
1398 |
+
* Fixed issue of page content displaying incorrectly after feeds
|
1399 |
+
|
1400 |
+
= Version 1.1 (2012-08-13) =
|
1401 |
+
* Now requires WordPress 3.0
|
1402 |
+
* More flexible fetching of images directory
|
1403 |
+
* Has its own top level menu item
|
1404 |
+
* Added settings section
|
1405 |
+
* Ability to open in lightbox, new window or default browser behaviour
|
1406 |
+
* Ability to set links as follow or no follow
|
1407 |
+
* Using constants for oftenly used locations
|
1408 |
+
* Code refactoring
|
1409 |
+
* Changes in file and folder structure
|
1410 |
+
|
1411 |
+
= Version 1.0 (2012-01-06) =
|
1412 |
+
* Initial release.
|
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.
|
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.7.
|
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.7.
|
47 |
|
48 |
if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
|
49 |
define( 'WPRSS_WP_MIN_VERSION', '4.0', true );
|
@@ -114,6 +114,11 @@
|
|
114 |
* Load required files.
|
115 |
*/
|
116 |
|
|
|
|
|
|
|
|
|
|
|
117 |
/* Load install, upgrade and migration code. */
|
118 |
require_once ( WPRSS_INC . 'update.php' );
|
119 |
|
@@ -234,11 +239,16 @@
|
|
234 |
/* Load the fallbacks for mbstring */
|
235 |
require_once ( WPRSS_INC . 'fallback-mbstring.php' );
|
236 |
|
|
|
|
|
|
|
237 |
|
238 |
register_activation_hook( __FILE__ , 'wprss_activate' );
|
239 |
register_deactivation_hook( __FILE__ , 'wprss_deactivate' );
|
240 |
|
241 |
|
|
|
|
|
242 |
add_action( 'init', 'wprss_init' );
|
243 |
/**
|
244 |
* Initialise the plugin
|
@@ -247,11 +257,6 @@
|
|
247 |
* @return void
|
248 |
*/
|
249 |
function wprss_init() {
|
250 |
-
//If user requested to download system info, generate the download.
|
251 |
-
if ( isset( $_POST['wprss-sysinfo'] ) ) {
|
252 |
-
do_action( 'wprss_download_sysinfo' );
|
253 |
-
}
|
254 |
-
|
255 |
do_action( 'wprss_init' );
|
256 |
}
|
257 |
|
@@ -410,6 +415,7 @@
|
|
410 |
WPRSS_TEXT_DOMAIN ), WPRSS_WP_MIN_VERSION ),
|
411 |
'notice_type' => 'error'
|
412 |
));
|
|
|
413 |
}
|
414 |
|
415 |
|
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.8
|
7 |
Author: Jean Galea
|
8 |
Author URI: http://www.wprssaggregator.com
|
9 |
License: GPLv2
|
29 |
|
30 |
/**
|
31 |
* @package WPRSSAggregator
|
32 |
+
* @version 4.7.8
|
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.7.8', true );
|
47 |
|
48 |
if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
|
49 |
define( 'WPRSS_WP_MIN_VERSION', '4.0', true );
|
114 |
* Load required files.
|
115 |
*/
|
116 |
|
117 |
+
/* Autoloader for this plugin */
|
118 |
+
require_once ( WPRSS_INC . 'autoload.php' );
|
119 |
+
// Adding autoload paths
|
120 |
+
wprss_autoloader()->add('Aventura\\Wprss\\Core', WPRSS_INC);
|
121 |
+
|
122 |
/* Load install, upgrade and migration code. */
|
123 |
require_once ( WPRSS_INC . 'update.php' );
|
124 |
|
239 |
/* Load the fallbacks for mbstring */
|
240 |
require_once ( WPRSS_INC . 'fallback-mbstring.php' );
|
241 |
|
242 |
+
// Initializes licensing
|
243 |
+
// Needs autoloading
|
244 |
+
// add_action( 'plugins_loaded', 'wprss_init_licensing' );
|
245 |
|
246 |
register_activation_hook( __FILE__ , 'wprss_activate' );
|
247 |
register_deactivation_hook( __FILE__ , 'wprss_deactivate' );
|
248 |
|
249 |
|
250 |
+
|
251 |
+
|
252 |
add_action( 'init', 'wprss_init' );
|
253 |
/**
|
254 |
* Initialise the plugin
|
257 |
* @return void
|
258 |
*/
|
259 |
function wprss_init() {
|
|
|
|
|
|
|
|
|
|
|
260 |
do_action( 'wprss_init' );
|
261 |
}
|
262 |
|
415 |
WPRSS_TEXT_DOMAIN ), WPRSS_WP_MIN_VERSION ),
|
416 |
'notice_type' => 'error'
|
417 |
));
|
418 |
+
|
419 |
}
|
420 |
|
421 |
|