WP RSS Aggregator - Version 4.8.1

Version Description

(2016-02-02) = * Fixed bug: Some exceptions used to cause fatal errors. * Fixed bug: Requests made by image caching used to always have an infinite timeout. * Fixed bug: Licensing algorithm used to use constants of inactive plugins, causing fatal error. * Enhanced: Visual improvements. * Enhanced: Included new Object Oriented code.

Download this release

Release Info

Developer markzahra
Plugin Icon 128x128 WP RSS Aggregator
Version 4.8.1
Comparing to
See all releases

Code changes from version 4.8 to 4.8.1

Files changed (58) hide show
  1. css/admin-styles.css +6 -6
  2. includes/Aventura/Wprss/Core/Component/EventManager.php +13 -0
  3. includes/Aventura/Wprss/Core/Component/Logger.php +126 -0
  4. includes/Aventura/Wprss/Core/ComponentFactory.php +49 -0
  5. includes/Aventura/Wprss/Core/DataObject.php +871 -0
  6. includes/Aventura/Wprss/Core/DataObjectInterface.php +36 -0
  7. includes/Aventura/Wprss/Core/Exception.php +12 -0
  8. includes/Aventura/Wprss/Core/Factory.php +23 -0
  9. includes/Aventura/Wprss/Core/Licensing/Api/Exception.php +14 -0
  10. includes/Aventura/Wprss/Core/Licensing/Api/RequestException.php +11 -0
  11. includes/Aventura/Wprss/Core/Licensing/Api/ResponseException.php +12 -0
  12. includes/Aventura/Wprss/Core/Licensing/Exception.php +14 -0
  13. includes/Aventura/Wprss/Core/Licensing/Manager.php +44 -21
  14. includes/Aventura/Wprss/Core/Licensing/Plugin/Exception.php +15 -0
  15. includes/Aventura/Wprss/Core/Licensing/Plugin/UpdaterException.php +12 -0
  16. includes/Aventura/Wprss/Core/Model/AssetsAbstract.php +610 -0
  17. includes/Aventura/Wprss/Core/Model/AssetsInterface.php +39 -0
  18. includes/Aventura/Wprss/Core/Model/Command.php +15 -0
  19. includes/Aventura/Wprss/Core/Model/CommandAbstract.php +138 -0
  20. includes/Aventura/Wprss/Core/Model/CommandException.php +14 -0
  21. includes/Aventura/Wprss/Core/Model/CommandInterface.php +20 -0
  22. includes/Aventura/Wprss/Core/Model/Event/Event.php +11 -0
  23. includes/Aventura/Wprss/Core/Model/Event/EventAbstract.php +83 -0
  24. includes/Aventura/Wprss/Core/Model/Event/EventInterface.php +33 -0
  25. includes/Aventura/Wprss/Core/Model/Event/EventManagerAbstract.php +168 -0
  26. includes/Aventura/Wprss/Core/Model/Event/EventManagerInterface.php +33 -0
  27. includes/Aventura/Wprss/Core/Model/LoggerAbstract.php +364 -0
  28. includes/Aventura/Wprss/Core/Model/LoggerInterface.php +118 -0
  29. includes/Aventura/Wprss/Core/Model/ModelAbstract.php +362 -0
  30. includes/Aventura/Wprss/Core/Model/ModelInterface.php +72 -0
  31. includes/Aventura/Wprss/Core/Model/SettingsAbstract.php +862 -0
  32. includes/Aventura/Wprss/Core/Model/SettingsInterface.php +17 -0
  33. includes/Aventura/Wprss/Core/Model/SpinnerAbstract.php +24 -0
  34. includes/Aventura/Wprss/Core/Model/SpinnerApiAbstract.php +86 -0
  35. includes/Aventura/Wprss/Core/Model/SpinnerApiInterface.php +20 -0
  36. includes/Aventura/Wprss/Core/Model/SpinnerInterface.php +18 -0
  37. includes/Aventura/Wprss/Core/Plugin.php +15 -0
  38. includes/Aventura/Wprss/Core/Plugin/AddonAbstract.php +130 -0
  39. includes/Aventura/Wprss/Core/Plugin/AddonFactoryAbstract.php +12 -0
  40. includes/Aventura/Wprss/Core/Plugin/AddonFactoryInterface.php +28 -0
  41. includes/Aventura/Wprss/Core/Plugin/AddonInterface.php +18 -0
  42. includes/Aventura/Wprss/Core/Plugin/ComponentAbstract.php +168 -0
  43. includes/Aventura/Wprss/Core/Plugin/ComponentFactoryAbstract.php +64 -0
  44. includes/Aventura/Wprss/Core/Plugin/ComponentFactoryInterface.php +17 -0
  45. includes/Aventura/Wprss/Core/Plugin/ComponentInterface.php +67 -0
  46. includes/Aventura/Wprss/Core/Plugin/Exception.php +15 -0
  47. includes/Aventura/Wprss/Core/Plugin/FactoryAbstract.php +50 -0
  48. includes/Aventura/Wprss/Core/Plugin/FactoryInterface.php +19 -0
  49. includes/Aventura/Wprss/Core/Plugin/PluginAbstract.php +359 -0
  50. includes/Aventura/Wprss/Core/Plugin/PluginInterface.php +138 -0
  51. includes/admin-addons.php +70 -69
  52. includes/admin-dashboard.php +30 -2
  53. includes/admin-help.php +28 -12
  54. includes/functions.php +159 -0
  55. includes/image-caching.php +1 -1
  56. includes/system-info.php +4 -1
  57. readme.txt +69 -772
  58. wp-rss-aggregator.php +56 -3
css/admin-styles.css CHANGED
@@ -8,6 +8,10 @@ body.post-type-wprss_feed q:after {
8
  content: '"';
9
  }
10
 
 
 
 
 
11
  .wprss-input {
12
  background: none repeat scroll 0 0 #EAF2FA;
13
  margin-bottom: 20px;
@@ -509,17 +513,13 @@ i.wprss-updating-feed-icon.wprss-show {
509
  #add-ons .add-on {
510
  float: left;
511
  width: 220px;
512
- margin: 10px;
513
- background: #FFFFFF;
514
  border: 1px solid #E5E5E5;
515
  position: relative;
516
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
517
  }
518
 
519
- #add-ons .add-on:first-child {
520
- margin-left: 0px;
521
- }
522
-
523
  #add-ons .add-on h3 {
524
  margin-top: 0.5em;
525
  }
8
  content: '"';
9
  }
10
 
11
+ span.wp-rss-footer-text {
12
+ font-style: italic;
13
+ }
14
+
15
  .wprss-input {
16
  background: none repeat scroll 0 0 #EAF2FA;
17
  margin-bottom: 20px;
513
  #add-ons .add-on {
514
  float: left;
515
  width: 220px;
516
+ margin: 10px 20px 10px 0;
517
+ background: #FFFFFF;
518
  border: 1px solid #E5E5E5;
519
  position: relative;
520
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
521
  }
522
 
 
 
 
 
523
  #add-ons .add-on h3 {
524
  margin-top: 0.5em;
525
  }
includes/Aventura/Wprss/Core/Component/EventManager.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Component;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * @since 4.8.1
9
+ */
10
+ class EventManager extends Core\Model\Event\EventManagerAbstract implements Core\Plugin\ComponentInterface
11
+ {
12
+ // All functionality is in most cases reusable from the ancestor
13
+ }
includes/Aventura/Wprss/Core/Component/Logger.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Component;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * A WPRSS-specific implementation, ready to use.
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ class Logger extends Core\Model\LoggerAbstract
13
+ {
14
+ const WPRA_LEVEL_PREFIX = 'WPRSS_LOG_LEVEL_';
15
+
16
+ /**
17
+ * {@inheritdoc}
18
+ *
19
+ * Adds an aditional 'SYSTEM' > 'DEBUG' level conversion.
20
+ *
21
+ * @since 4.8.1
22
+ * @param string $level
23
+ * @return int
24
+ */
25
+ public static function toMonologLevel($level)
26
+ {
27
+ // For compatibility with WPRA
28
+ if (strtoupper($level) === 'SYSTEM') {
29
+ $level = 'DEBUG';
30
+ }
31
+ return parent::toMonologLevel($level);
32
+ }
33
+
34
+ /**
35
+ * {@inheritdoc}
36
+ *
37
+ * @since 4.8.1
38
+ */
39
+ public function shouldAddRecord($level, $message, array $context = array())
40
+ {
41
+ return $this->shouldLogLevel($level);
42
+ }
43
+
44
+ /**
45
+ * {@inheritdoc}
46
+ *
47
+ * @since 4.8.1
48
+ * @see getLevelThreshold()
49
+ * @param int|string $level A Monolog level to check.
50
+ * @return boolean True if the level should be logged; false otherwise.
51
+ */
52
+ public function shouldLogLevel($level)
53
+ {
54
+ $level = static::monologToWpraLevel($level);
55
+ $threshold = $this->getLevelThreshold();
56
+ if (is_null($threshold)) {
57
+ return true;
58
+ }
59
+
60
+ $threshold = intval($threshold);
61
+ if ($threshold === 0) {
62
+ return false;
63
+ }
64
+
65
+ $thisLevelOnly = $threshold > 0;
66
+ $threshold = abs($threshold);
67
+
68
+ return $thisLevelOnly
69
+ ? $level === $threshold
70
+ : $level <= $threshold;
71
+ }
72
+
73
+ /**
74
+ * Converts a WPRA level to a Monolog one.
75
+ *
76
+ * @since 4.8.1
77
+ * @param int"string $level A numeric or string representation of a WPRA level.
78
+ * If is WPRA-prefixed, i.e. a full constant name, the prefix will be removed.
79
+ * @return int The numeric representation of the corresponding Monolog level.
80
+ * @throws \InvalidArgumentException If no such Monolog level defined.
81
+ */
82
+ public static function wpraToMonologLevel($level)
83
+ {
84
+ $wpraPrefix = static::WPRA_LEVEL_PREFIX;
85
+ if (!is_numeric($level) && stripos($level, $wpraPrefix)) {
86
+ $level = substr($level, strlen($wpraPrefix));
87
+ }
88
+
89
+ if (is_string($level) || $level > 50) {
90
+ return static::toMonologLevel($level);
91
+ }
92
+
93
+ $levels = wprss_log_get_levels();
94
+ if (!isset($levels[$level])) {
95
+ throw new \InvalidArgumentException(sprintf('Monolog Level "%1$s" is not defined', $level));
96
+ }
97
+
98
+ $level = $levels[$level];
99
+ return static::toMonologLevel($level);
100
+ }
101
+
102
+ /**
103
+ * Converts a Monolog level to a WPRA one.
104
+ *
105
+ * @since 4.8.1
106
+ * @param string|int $level A Monolog level's string or numeric representation.
107
+ * @return int The WPRA level's numeric representation that corresponds to the specified Monolog one.
108
+ * @throws \InvalidArgumentException If no such WPRA level defined.
109
+ */
110
+ public static function monologToWpraLevel($level)
111
+ {
112
+ if (is_numeric($level)) {
113
+ $level = static::getLevelName($level);
114
+ }
115
+ if ($level === 'DEBUG') {
116
+ $level = 'SYSTEM';
117
+ }
118
+
119
+ $constName = static::WPRA_LEVEL_PREFIX . $level;
120
+ if (!defined($constName)) {
121
+ throw new \InvalidArgumentException(sprintf('WPRA Level "%1$s" is not defined', $level));
122
+ }
123
+
124
+ return constant($constName);
125
+ }
126
+ }
includes/Aventura/Wprss/Core/ComponentFactory.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // This whole namespace is a temporary one, until there's a real Core add-on
4
+ namespace Aventura\Wprss\Core;
5
+
6
+ /**
7
+ * A dummy factory of Core components.
8
+ *
9
+ * This is to be used with the Core plugin.
10
+ *
11
+ * @todo Create a real Core factory of Core components in the Core plugin.
12
+ * @since 4.8.1
13
+ */
14
+ class ComponentFactory extends Plugin\ComponentFactoryAbstract
15
+ {
16
+ /**
17
+ * @since 4.8.1
18
+ */
19
+ protected function _construct()
20
+ {
21
+ parent::_construct();
22
+ $this->setBaseNamespace(__NAMESPACE__ . '\\Component');
23
+ }
24
+
25
+ public function createLogger($data = array())
26
+ {
27
+ $logger = $this->createComponent('Logger', $this->getPlugin());
28
+ if (!isset($data['log_file_path'])) {
29
+ $data['log_file_path'] = WPRSS_LOG_FILE . '-' . get_current_blog_id() . WPRSS_LOG_FILE_EXT;
30
+ }
31
+ if (!isset($data['level_threshold'])) {
32
+ $data['level_threshold'] = wprss_log_get_level();
33
+ }
34
+ $logger->addData($data);
35
+
36
+ return $logger;
37
+ }
38
+
39
+ /**
40
+ * @since 4.8.1
41
+ * @param array $data
42
+ * @return Model\Event\EventManagerInterface
43
+ */
44
+ public function createEventManager($data = array())
45
+ {
46
+ $events = $this->createComponent('EventManager', $this->getPlugin(), $data);
47
+ return $events;
48
+ }
49
+ }
includes/Aventura/Wprss/Core/DataObject.php ADDED
@@ -0,0 +1,871 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core;
4
+
5
+ /**
6
+ * An object with dynamic getter and setter functionality, as well as array access.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ class DataObject implements \ArrayAccess, DataObjectInterface {
11
+
12
+ /**
13
+ * Object attributes
14
+ *
15
+ * @since 4.8.1
16
+ * @var array
17
+ */
18
+ protected $_data = array();
19
+
20
+ /**
21
+ * Data changes flag (true after setData|unsetData call)
22
+ * @since 4.8.1
23
+ * @var $_hasDataChange bool
24
+ */
25
+ protected $_hasDataChanges = false;
26
+
27
+ /**
28
+ * Original data that was loaded
29
+ *
30
+ * @since 4.8.1
31
+ * @var array
32
+ */
33
+ protected $_origData;
34
+
35
+ /**
36
+ * Name of object id field
37
+ *
38
+ * @since 4.8.1
39
+ * @var string
40
+ */
41
+ protected $_idFieldName = null;
42
+
43
+ /**
44
+ * Setter/Getter underscore transformation cache
45
+ *
46
+ * @since 4.8.1
47
+ * @var array
48
+ */
49
+ protected static $_underscoreCache = array();
50
+
51
+ /**
52
+ * Object delete flag
53
+ *
54
+ * @since 4.8.1
55
+ * @var boolean
56
+ */
57
+ protected $_isDeleted = false;
58
+
59
+ /**
60
+ * Constructor
61
+ *
62
+ * By default is looking for first argument as array and assignes it as object attributes
63
+ * This behaviour may change in child classes
64
+ *
65
+ * @since 4.8.1
66
+ */
67
+ public function __construct() {
68
+ $args = func_get_args();
69
+ if (empty($args[0])) {
70
+ $args[0] = array();
71
+ }
72
+ $this->_data = $args[0];
73
+
74
+ $this->_construct();
75
+ }
76
+
77
+ /**
78
+ * Internal constructor not depended on params. Can be used for object initialization.
79
+ *
80
+ * If you want to add some procedures that happen on instantiation,
81
+ * you probably want to override this.
82
+ *
83
+ * @since 4.8.1
84
+ */
85
+ protected function _construct() {}
86
+
87
+ /**
88
+ * Set _isDeleted flag value (if $isDeleted param is defined) and return current flag value
89
+ *
90
+ * @since 4.8.1
91
+ * @param boolean $isDeleted
92
+ * @return boolean
93
+ */
94
+ public function isDeleted($isDeleted=null)
95
+ {
96
+ $result = $this->_isDeleted;
97
+ if (!is_null($isDeleted)) {
98
+ $this->_isDeleted = $isDeleted;
99
+ }
100
+ return $result;
101
+ }
102
+
103
+ /**
104
+ * Get data change status
105
+ *
106
+ * @since 4.8.1
107
+ * @return bool
108
+ */
109
+ public function hasDataChanges()
110
+ {
111
+ return $this->_hasDataChanges;
112
+ }
113
+
114
+ /**
115
+ * set name of object id field
116
+ *
117
+ * @since 4.8.1
118
+ * @param string $name
119
+ * @return Wp_Rss_SpinnerChief_Data_Object
120
+ */
121
+ public function setIdFieldName($name)
122
+ {
123
+ $this->_idFieldName = $name;
124
+ return $this;
125
+ }
126
+
127
+ /**
128
+ * Retrieve name of object id field
129
+ *
130
+ * @since 4.8.1
131
+ * @param string $name
132
+ * @return Wp_Rss_SpinnerChief_Data_Object
133
+ */
134
+ public function getIdFieldName()
135
+ {
136
+ return $this->_idFieldName;
137
+ }
138
+
139
+ /**
140
+ * Retrieve object id
141
+ *
142
+ * @since 4.8.1
143
+ * @return mixed
144
+ */
145
+ public function getId()
146
+ {
147
+ if ($this->getIdFieldName()) {
148
+ return $this->_getData($this->getIdFieldName());
149
+ }
150
+ return $this->_getData('id');
151
+ }
152
+
153
+ /**
154
+ * Set object id field value
155
+ *
156
+ * @since 4.8.1
157
+ * @param mixed $value
158
+ * @return Wp_Rss_SpinnerChief_Data_Object
159
+ */
160
+ public function setId($value)
161
+ {
162
+ if ($this->getIdFieldName()) {
163
+ $this->setData($this->getIdFieldName(), $value);
164
+ } else {
165
+ $this->setData('id', $value);
166
+ }
167
+ return $this;
168
+ }
169
+
170
+ /**
171
+ * Add data to the object.
172
+ *
173
+ * Retains previous data in the object.
174
+ *
175
+ * @since 4.8.1
176
+ * @param array $arr
177
+ * @return Wp_Rss_SpinnerChief_Data_Object
178
+ */
179
+ public function addData(array $arr)
180
+ {
181
+ foreach($arr as $index=>$value) {
182
+ $this->setData($index, $value);
183
+ }
184
+ return $this;
185
+ }
186
+
187
+ /**
188
+ * Overwrite data in the object.
189
+ *
190
+ * $key can be string or array.
191
+ * If $key is string, the attribute value will be overwritten by $value
192
+ *
193
+ * If $key is an array, it will overwrite all the data in the object.
194
+ *
195
+ * @since 4.8.1
196
+ * @param string|array $key
197
+ * @param mixed $value
198
+ * @return Wp_Rss_SpinnerChief_Data_Object
199
+ */
200
+ public function setData($key, $value=null)
201
+ {
202
+ $this->_hasDataChanges = true;
203
+ // http://www.php.net/manual/en/function.is-array.php#48083
204
+ if(is_array($key)) {
205
+ $this->_data = $key;
206
+ } else {
207
+ $this->_data[$key] = $value;
208
+ }
209
+ return $this;
210
+ }
211
+
212
+ /**
213
+ * Unset data from the object.
214
+ *
215
+ * $key can be a string only. Array will be ignored.
216
+ *
217
+ * @since 4.8.1
218
+ * @param string $key
219
+ * @return Wp_Rss_SpinnerChief_Data_Object
220
+ */
221
+ public function unsetData($key=null)
222
+ {
223
+ $this->_hasDataChanges = true;
224
+ if (is_null($key)) {
225
+ $this->_data = array();
226
+ } else {
227
+ unset($this->_data[$key]);
228
+ }
229
+ return $this;
230
+ }
231
+
232
+ /**
233
+ * Retrieves data from the object
234
+ *
235
+ * If $key is empty will return all the data as an array
236
+ * Otherwise it will return value of the attribute specified by $key
237
+ *
238
+ * If $index is specified it will assume that attribute data is an array
239
+ * and retrieve corresponding member.
240
+ *
241
+ * @since 4.8.1
242
+ * @param string $key
243
+ * @param string|int $index
244
+ * @return mixed
245
+ */
246
+ public function getData($key='', $index=null)
247
+ {
248
+ if (''===$key) {
249
+ return $this->_data;
250
+ }
251
+
252
+ if (is_array($key)) {
253
+ return array_pick($this->_data, $key);
254
+ }
255
+
256
+ $default = null;
257
+
258
+ // accept a/b/c as ['a']['b']['c']
259
+ if (strpos($key,'/')) {
260
+ $keyArr = explode('/', $key);
261
+ $data = $this->_data;
262
+ foreach ($keyArr as $i=>$k) {
263
+ if ($k==='') {
264
+ return $default;
265
+ }
266
+ if (is_array($data)) {
267
+ if (!isset($data[$k])) {
268
+ return $default;
269
+ }
270
+ $data = $data[$k];
271
+ } elseif ($data instanceof Wp_Rss_SpinnerChief_Data_Object) {
272
+ $data = $data->getData($k);
273
+ } else {
274
+ return $default;
275
+ }
276
+ }
277
+ return $data;
278
+ }
279
+
280
+ // legacy functionality for $index
281
+ if (isset($this->_data[$key])) {
282
+ if (is_null($index)) {
283
+ return $this->_data[$key];
284
+ }
285
+
286
+ $value = $this->_data[$key];
287
+ if (is_array($value)) {
288
+ //if (isset($value[$index]) && (!empty($value[$index]) || strlen($value[$index]) > 0)) {
289
+ /**
290
+ * If we have any data, even if it empty - we should use it, anyway
291
+ */
292
+ if (isset($value[$index])) {
293
+ return $value[$index];
294
+ }
295
+ return null;
296
+ } elseif (is_string($value)) {
297
+ $arr = explode("\n", $value);
298
+ return (isset($arr[$index]) && (!empty($arr[$index]) || strlen($arr[$index]) > 0)) ? $arr[$index] : null;
299
+ } elseif ($value instanceof Wp_Rss_SpinnerChief_Data_Object) {
300
+ return $value->getData($index);
301
+ }
302
+ return $default;
303
+ }
304
+ return $default;
305
+ }
306
+
307
+ /**
308
+ * Get value from _data array without parse key
309
+ *
310
+ * @since 4.8.1
311
+ * @param string $key
312
+ * @return mixed
313
+ */
314
+ protected function _getData($key)
315
+ {
316
+ return isset($this->_data[$key]) ? $this->_data[$key] : null;
317
+ }
318
+
319
+ /**
320
+ * Set object data with calling setter method
321
+ *
322
+ * @since 4.8.1
323
+ * @param string $key
324
+ * @param mixed $args
325
+ * @return Wp_Rss_SpinnerChief_Data_Object
326
+ */
327
+ public function setDataUsingMethod($key, $args=array())
328
+ {
329
+ $method = 'set'.$this->_camelize($key);
330
+ $this->$method($args);
331
+ return $this;
332
+ }
333
+
334
+ /**
335
+ * Get object data by key with calling getter method
336
+ *
337
+ * @since 4.8.1
338
+ * @param string $key
339
+ * @param mixed $args
340
+ * @return mixed
341
+ */
342
+ public function getDataUsingMethod($key, $args=null)
343
+ {
344
+ $method = 'get'.$this->_camelize($key);
345
+ return $this->$method($args);
346
+ }
347
+
348
+ /**
349
+ * Fast get data or set default if value is not available
350
+ *
351
+ * @since 4.8.1
352
+ * @param string $key
353
+ * @param mixed $default
354
+ * @return mixed
355
+ */
356
+ public function getDataSetDefault($key, $default)
357
+ {
358
+ if (!isset($this->_data[$key])) {
359
+ $this->_data[$key] = $default;
360
+ }
361
+ return $this->_data[$key];
362
+ }
363
+
364
+ /**
365
+ * If $key is empty, checks whether there's any data in the object
366
+ * Otherwise checks if the specified attribute is set.
367
+ *
368
+ * @since 4.8.1
369
+ * @param string $key
370
+ * @return boolean
371
+ */
372
+ public function hasData($key='')
373
+ {
374
+ if (empty($key) || !is_string($key)) {
375
+ return !empty($this->_data);
376
+ }
377
+ return array_key_exists($key, $this->_data);
378
+ }
379
+
380
+ /**
381
+ * Convert object attributes to array
382
+ *
383
+ * @since 4.8.1
384
+ * @param array $arrAttributes array of required attributes
385
+ * @return array
386
+ */
387
+ public function __toArray(array $arrAttributes = array())
388
+ {
389
+ if (empty($arrAttributes)) {
390
+ return $this->_data;
391
+ }
392
+
393
+ $arrRes = array();
394
+ foreach ($arrAttributes as $attribute) {
395
+ if (isset($this->_data[$attribute])) {
396
+ $arrRes[$attribute] = $this->_data[$attribute];
397
+ }
398
+ else {
399
+ $arrRes[$attribute] = null;
400
+ }
401
+ }
402
+ return $arrRes;
403
+ }
404
+
405
+ /**
406
+ * Public wrapper for __toArray
407
+ *
408
+ * @since 4.8.1
409
+ * @param array $arrAttributes
410
+ * @return array
411
+ */
412
+ public function toArray(array $arrAttributes = array())
413
+ {
414
+ return $this->__toArray($arrAttributes);
415
+ }
416
+
417
+ /**
418
+ * Set required array elements
419
+ *
420
+ * @since 4.8.1
421
+ * @param array $arr
422
+ * @param array $elements
423
+ * @return array
424
+ */
425
+ protected function _prepareArray(&$arr, array $elements=array())
426
+ {
427
+ foreach ($elements as $element) {
428
+ if (!isset($arr[$element])) {
429
+ $arr[$element] = null;
430
+ }
431
+ }
432
+ return $arr;
433
+ }
434
+
435
+ /**
436
+ * Convert object attributes to XML
437
+ *
438
+ * @since 4.8.1
439
+ * @param array $arrAttributes array of required attributes
440
+ * @param string $rootName name of the root element
441
+ * @return string
442
+ */
443
+ protected function __toXml(array $arrAttributes = array(), $rootName = 'item', $addOpenTag=false, $addCdata=true)
444
+ {
445
+ $xml = '';
446
+ if ($addOpenTag) {
447
+ $xml.= '<?xml version="1.0" encoding="UTF-8"?>'."\n";
448
+ }
449
+ if (!empty($rootName)) {
450
+ $xml.= '<'.$rootName.'>'."\n";
451
+ }
452
+ $xmlModel = new Varien_Simplexml_Element('<node></node>');
453
+ $arrData = $this->toArray($arrAttributes);
454
+ foreach ($arrData as $fieldName => $fieldValue) {
455
+ if ($addCdata === true) {
456
+ $fieldValue = "<![CDATA[$fieldValue]]>";
457
+ } else {
458
+ $fieldValue = $xmlModel->xmlentities($fieldValue);
459
+ }
460
+ $xml.= "<$fieldName>$fieldValue</$fieldName>"."\n";
461
+ }
462
+ if (!empty($rootName)) {
463
+ $xml.= '</'.$rootName.'>'."\n";
464
+ }
465
+ return $xml;
466
+ }
467
+
468
+ /**
469
+ * Public wrapper for __toXml
470
+ *
471
+ * @since 4.8.1
472
+ * @param array $arrAttributes
473
+ * @param string $rootName
474
+ * @return string
475
+ */
476
+ public function toXml(array $arrAttributes = array(), $rootName = 'item', $addOpenTag=false, $addCdata=true)
477
+ {
478
+ return $this->__toXml($arrAttributes, $rootName, $addOpenTag, $addCdata);
479
+ }
480
+
481
+ /**
482
+ * Convert object attributes to JSON
483
+ *
484
+ * @since 4.8.1
485
+ * @param array $arrAttributes array of required attributes
486
+ * @return string
487
+ */
488
+ protected function __toJson(array $arrAttributes = array())
489
+ {
490
+ $arrData = $this->toArray($arrAttributes);
491
+ $json = Zend_Json::encode($arrData);
492
+ return $json;
493
+ }
494
+
495
+ /**
496
+ * Public wrapper for __toJson
497
+ *
498
+ * @since 4.8.1
499
+ * @param array $arrAttributes
500
+ * @return string
501
+ */
502
+ public function toJson(array $arrAttributes = array())
503
+ {
504
+ return $this->__toJson($arrAttributes);
505
+ }
506
+
507
+ /**
508
+ * Convert object attributes to string
509
+ *
510
+ * @since 4.8.1
511
+ * @param array $arrAttributes array of required attributes
512
+ * @param string $valueSeparator
513
+ * @return string
514
+ */
515
+ // public function __toString(array $arrAttributes = array(), $valueSeparator=',')
516
+ // {
517
+ // $arrData = $this->toArray($arrAttributes);
518
+ // return implode($valueSeparator, $arrData);
519
+ // }
520
+
521
+ /**
522
+ * Public wrapper for __toString
523
+ *
524
+ * Will use $format as an template and substitute {{key}} for attributes
525
+ *
526
+ * @since 4.8.1
527
+ * @param string $format
528
+ * @return string
529
+ */
530
+ public function toString($format='')
531
+ {
532
+ if (empty($format)) {
533
+ $str = implode(', ', $this->getData());
534
+ } else {
535
+ preg_match_all('/\{\{([a-z0-9_]+)\}\}/is', $format, $matches);
536
+ foreach ($matches[1] as $var) {
537
+ $format = str_replace('{{'.$var.'}}', $this->getData($var), $format);
538
+ }
539
+ $str = $format;
540
+ }
541
+ return $str;
542
+ }
543
+
544
+ /**
545
+ * Set/Get attribute wrapper
546
+ *
547
+ * @since 4.8.1
548
+ * @param string $method
549
+ * @param array $args
550
+ * @return mixed
551
+ */
552
+ public function __call( $method, $args ) {
553
+ switch (substr($method, 0, 3)) {
554
+ case 'get' :
555
+ $key = $this->_underscore(substr($method,3));
556
+ $data = $this->getData($key, isset($args[0]) ? $args[0] : null);
557
+ return $data;
558
+
559
+ case 'set' :
560
+ $key = $this->_underscore(substr($method,3));
561
+ $result = $this->setData($key, isset($args[0]) ? $args[0] : null);
562
+ return $result;
563
+
564
+ case 'uns' :
565
+ $key = $this->_underscore(substr($method,3));
566
+ $result = $this->unsetData($key);
567
+ return $result;
568
+
569
+ case 'has' :
570
+ $key = $this->_underscore(substr($method,3));
571
+ return isset($this->_data[$key]);
572
+ }
573
+ throw new Exception("Invalid method ".get_class($this)."::".$method."(".print_r($args,1).")");
574
+ }
575
+
576
+ /**
577
+ * Attribute getter (deprecated)
578
+ *
579
+ * @since 4.8.1
580
+ * @param string $var
581
+ * @return mixed
582
+ */
583
+
584
+ public function __get($var)
585
+ {
586
+ $var = $this->_underscore($var);
587
+ return $this->getData($var);
588
+ }
589
+
590
+ /**
591
+ * Attribute setter (deprecated)
592
+ *
593
+ * @since 4.8.1
594
+ * @param string $var
595
+ * @param mixed $value
596
+ */
597
+ public function __set($var, $value)
598
+ {
599
+ $var = $this->_underscore($var);
600
+ $this->setData($var, $value);
601
+ }
602
+
603
+ /**
604
+ * checks whether the object is empty
605
+ *
606
+ * @since 4.8.1
607
+ * @return boolean
608
+ */
609
+ public function isEmpty()
610
+ {
611
+ if (empty($this->_data)) {
612
+ return true;
613
+ }
614
+ return false;
615
+ }
616
+
617
+ /**
618
+ * Converts field names for setters and geters
619
+ *
620
+ * $this->setMyField($value) === $this->setData('my_field', $value)
621
+ * Uses cache to eliminate unneccessary preg_replace
622
+ *
623
+ * @since 4.8.1
624
+ * @param string $name
625
+ * @return string
626
+ */
627
+ protected function _underscore($name)
628
+ {
629
+ if (isset(self::$_underscoreCache[$name])) {
630
+ return self::$_underscoreCache[$name];
631
+ }
632
+ #Varien_Profiler::start('underscore');
633
+ $result = strtolower(preg_replace('/(.)([A-Z])/', "$1_$2", $name));
634
+ #Varien_Profiler::stop('underscore');
635
+ self::$_underscoreCache[$name] = $result;
636
+ return $result;
637
+ }
638
+
639
+ protected function _camelize($name)
640
+ {
641
+ return uc_words($name, '');
642
+ }
643
+
644
+ /**
645
+ * serialize object attributes
646
+ *
647
+ * @since 4.8.1
648
+ * @param array $attributes
649
+ * @param string $valueSeparator
650
+ * @param string $fieldSeparator
651
+ * @param string $quote
652
+ * @return string
653
+ */
654
+ public function serialize($attributes = array(), $valueSeparator='=', $fieldSeparator=' ', $quote='"')
655
+ {
656
+ $res = '';
657
+ $data = array();
658
+ if (empty($attributes)) {
659
+ $attributes = array_keys($this->_data);
660
+ }
661
+
662
+ foreach ($this->_data as $key => $value) {
663
+ if (in_array($key, $attributes)) {
664
+ $data[] = $key . $valueSeparator . $quote . $value . $quote;
665
+ }
666
+ }
667
+ $res = implode($fieldSeparator, $data);
668
+ return $res;
669
+ }
670
+
671
+ /**
672
+ * Get object loaded data (original data)
673
+ *
674
+ * @since 4.8.1
675
+ * @param string $key
676
+ * @return mixed
677
+ */
678
+ public function getOrigData($key=null)
679
+ {
680
+ if (is_null($key)) {
681
+ return $this->_origData;
682
+ }
683
+ return isset($this->_origData[$key]) ? $this->_origData[$key] : null;
684
+ }
685
+
686
+ /**
687
+ * Initialize object original data
688
+ *
689
+ * @since 4.8.1
690
+ * @param string $key
691
+ * @param mixed $data
692
+ * @return Wp_Rss_SpinnerChief_Data_Object
693
+ */
694
+ public function setOrigData($key=null, $data=null)
695
+ {
696
+ if (is_null($key)) {
697
+ $this->_origData = $this->_data;
698
+ } else {
699
+ $this->_origData[$key] = $data;
700
+ }
701
+ return $this;
702
+ }
703
+
704
+ /**
705
+ * Compare object data with original data
706
+ *
707
+ * @since 4.8.1
708
+ * @param string $field
709
+ * @return boolean
710
+ */
711
+ public function dataHasChangedFor($field)
712
+ {
713
+ $newData = $this->getData($field);
714
+ $origData = $this->getOrigData($field);
715
+ return $newData!=$origData;
716
+ }
717
+
718
+ /**
719
+ * Clears data changes status
720
+ *
721
+ * @since 4.8.1
722
+ * @param boolean $value
723
+ * @return Wp_Rss_SpinnerChief_Data_Object
724
+ */
725
+ public function setDataChanges($value)
726
+ {
727
+ $this->_hasDataChanges = (bool)$value;
728
+ return $this;
729
+ }
730
+
731
+ /**
732
+ * Present object data as string in debug mode
733
+ *
734
+ * @since 4.8.1
735
+ * @param mixed $data
736
+ * @param array $objects
737
+ * @return string
738
+ */
739
+ public function debugSelf($data=null, &$objects=array())
740
+ {
741
+ if (is_null($data)) {
742
+ $hash = spl_object_hash($this);
743
+ if (!empty($objects[$hash])) {
744
+ return '*** RECURSION ***';
745
+ }
746
+ $objects[$hash] = true;
747
+ $data = $this->getData();
748
+ }
749
+ $debug = array();
750
+ foreach ($data as $key=>$value) {
751
+ if (is_scalar($value)) {
752
+ $debug[$key] = $value;
753
+ } elseif (is_array($value)) {
754
+ $debug[$key] = $this->debug($value, $objects);
755
+ } elseif ($value instanceof Wp_Rss_SpinnerChief_Data_Object) {
756
+ $debug[$key.' ('.get_class($value).')'] = $value->debug(null, $objects);
757
+ }
758
+ }
759
+ return $debug;
760
+ }
761
+
762
+ /**
763
+ * Implementation of ArrayAccess::offsetSet()
764
+ *
765
+ * @since 4.8.1
766
+ * @link http://www.php.net/manual/en/arrayaccess.offsetset.php
767
+ * @param string $offset
768
+ * @param mixed $value
769
+ */
770
+ public function offsetSet($offset, $value)
771
+ {
772
+ $this->_data[$offset] = $value;
773
+ }
774
+
775
+ /**
776
+ * Implementation of ArrayAccess::offsetExists()
777
+ *
778
+ * @since 4.8.1
779
+ * @link http://www.php.net/manual/en/arrayaccess.offsetexists.php
780
+ * @param string $offset
781
+ * @return boolean
782
+ */
783
+ public function offsetExists($offset)
784
+ {
785
+ return isset($this->_data[$offset]);
786
+ }
787
+
788
+ /**
789
+ * Implementation of ArrayAccess::offsetUnset()
790
+ *
791
+ * @since 4.8.1
792
+ * @link http://www.php.net/manual/en/arrayaccess.offsetunset.php
793
+ * @param string $offset
794
+ */
795
+ public function offsetUnset($offset)
796
+ {
797
+ unset($this->_data[$offset]);
798
+ }
799
+
800
+ /**
801
+ * Implementation of ArrayAccess::offsetGet()
802
+ *
803
+ * @since 4.8.1
804
+ * @link http://www.php.net/manual/en/arrayaccess.offsetget.php
805
+ * @param string $offset
806
+ * @return mixed
807
+ */
808
+ public function offsetGet($offset)
809
+ {
810
+ return isset($this->_data[$offset]) ? $this->_data[$offset] : null;
811
+ }
812
+
813
+
814
+ /**
815
+ * Enter description here...
816
+ *
817
+ * @since 4.8.1
818
+ * @param string $field
819
+ * @return boolean
820
+ */
821
+ public function isDirty($field=null)
822
+ {
823
+ if (empty($this->_dirty)) {
824
+ return false;
825
+ }
826
+ if (is_null($field)) {
827
+ return true;
828
+ }
829
+ return isset($this->_dirty[$field]);
830
+ }
831
+
832
+ /**
833
+ * Enter description here...
834
+ *
835
+ * @since 4.8.1
836
+ * @param string $field
837
+ * @param boolean $flag
838
+ * @return Wp_Rss_SpinnerChief_Data_Object
839
+ */
840
+ public function flagDirty($field, $flag=true)
841
+ {
842
+ if (is_null($field)) {
843
+ foreach ($this->getData() as $field=>$value) {
844
+ $this->flagDirty($field, $flag);
845
+ }
846
+ } else {
847
+ if ($flag) {
848
+ $this->_dirty[$field] = true;
849
+ } else {
850
+ unset($this->_dirty[$field]);
851
+ }
852
+ }
853
+ return $this;
854
+ }
855
+ }
856
+
857
+
858
+ /**
859
+ * Tiny function to enhance functionality of ucwords
860
+ *
861
+ * Will capitalize first letters and convert separators if needed
862
+ *
863
+ * @since 4.8.1
864
+ * @param string $str
865
+ * @param string $destSep
866
+ * @param string $srcSep
867
+ * @return string
868
+ */
869
+ function uc_words($str, $destSep='_', $srcSep='_') {
870
+ return str_replace(' ', $destSep, ucwords(str_replace($srcSep, ' ', $str)));
871
+ }
includes/Aventura/Wprss/Core/DataObjectInterface.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core;
4
+
5
+ /**
6
+ * An interface for something that can hold and manipulate arbitrary internal data.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ interface DataObjectInterface
11
+ {
12
+ /**
13
+ * @since 4.8.1
14
+ */
15
+ public function getData($key = null);
16
+
17
+ /**
18
+ * @since 4.8.1
19
+ */
20
+ public function hasData($key = null);
21
+
22
+ /**
23
+ * @since 4.8.1
24
+ */
25
+ public function unsetData($key = null);
26
+
27
+ /**
28
+ * @since 4.8.1
29
+ */
30
+ public function setData($key, $value = null);
31
+
32
+ /**
33
+ * @since 4.8.1
34
+ */
35
+ public function setDataUsingMethod($key);
36
+ }
includes/Aventura/Wprss/Core/Exception.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core;
4
+
5
+ /**
6
+ * Base class for all WPRA exceptions.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ class Exception extends \Exception
11
+ {
12
+ }
includes/Aventura/Wprss/Core/Factory.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core;
4
+
5
+ /**
6
+ * @since 4.8.1
7
+ */
8
+ class Factory extends Plugin\FactoryAbstract
9
+ {
10
+ public function _create($data = array())
11
+ {
12
+ $plugin = new Plugin($data);
13
+ $factory = new ComponentFactory($plugin);
14
+ $plugin->setFactory($factory);
15
+
16
+ $plugin->setLogger($factory->createLogger());
17
+ $plugin->setEventManager($factory->createEventManager());
18
+
19
+ $plugin->hook();
20
+
21
+ return $plugin;
22
+ }
23
+ }
includes/Aventura/Wprss/Core/Licensing/Api/Exception.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Licensing\Api;
4
+
5
+ use Aventura\Wprss\Core\Licensing;
6
+
7
+ /**
8
+ * When something goes wrong in the WPRSS Licensing API.
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ class Exception extends Licensing\Exception
13
+ {
14
+ }
includes/Aventura/Wprss/Core/Licensing/Api/RequestException.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Licensing\Api;
4
+
5
+ /**
6
+ * Thrown when the Licensing API encounters an error related to the HTTP request.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ class RequestException extends Exception {
11
+ }
includes/Aventura/Wprss/Core/Licensing/Api/ResponseException.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Licensing\Api;
4
+
5
+ /**
6
+ * Exception class, thrown when the Licensing API responds with an invalid response.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ class ResponseException extends Exception
11
+ {
12
+ }
includes/Aventura/Wprss/Core/Licensing/Exception.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Licensing;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * When something goes wrong with WPRA licensing.
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ class Exception extends Core\Exception
13
+ {
14
+ }
includes/Aventura/Wprss/Core/Licensing/Manager.php CHANGED
@@ -1,7 +1,11 @@
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.
@@ -430,9 +434,16 @@ class Manager {
430
 
431
  // Addon Uppercase ID
432
  $addonUid = strtoupper( $addonId );
433
- // Prepare constants
434
- $itemName = constant( "WPRSS_{$addonUid}_SL_ITEM_NAME" );
435
- $storeUrl = constant( "WPRSS_{$addonUid}_SL_STORE_URL" );
 
 
 
 
 
 
 
436
 
437
  try {
438
  $licenseData = $this->api($storeUrl, array(
@@ -440,10 +451,15 @@ class Manager {
440
  'license' => $license,
441
  'item_name' => $itemName,
442
  ));
443
- } catch ( Exception $e ) {
 
444
  wprss_log( sprintf( 'Could not retrieve licensing data from "%1$s": %2$s', $storeUrl, $e->getMessage() ), __FUNCTION__, WPRSS_LOG_LEVEL_WARNING );
445
  return $license->getStatus();
446
  }
 
 
 
 
447
 
448
  // Update the DB option
449
  $license->setStatus( $licenseData->license );
@@ -469,7 +485,8 @@ class Manager {
469
  * 'item_name' are required for a successful call. 'license' can also be
470
  * an instance of {@link Aventura\Wprss\Core\Licensing\License}.
471
  * @return object License data as properties of an stdClass instance.
472
- * @throws Exception If request fails, or returns empty response, or response cannot be decoded.
 
473
  */
474
  public function api($storeUrl, $params) {
475
  $defaultParams = array(
@@ -493,16 +510,16 @@ class Manager {
493
 
494
  // Request failed
495
  if ( is_wp_error( $response ) ) {
496
- throw new Exception( sprintf( 'Licensing API request failed: %1$s', $response->get_error_message() ) );
497
  }
498
 
499
  $body = wp_remote_retrieve_body( $response );
500
  if ( empty( $body ) ) {
501
- throw new Exception( sprintf( 'Licensing API response returned empty' ) );
502
  }
503
 
504
  if ( ($licenseData = json_decode( $body )) === null ) {
505
- throw new Exception( sprintf( 'Licensing API response could not be decoded' ) );
506
  }
507
 
508
  return $licenseData;
@@ -540,18 +557,23 @@ class Manager {
540
  return false;
541
  }
542
 
543
- // Create an updater
544
- $updater = $this->newUpdater($storeUrl, $path, array(
545
- 'version' => $version, // current version number
546
- 'license' => $license, // license key (used get_option above to retrieve from DB)
547
- 'item_name' => $itemName, // name of this plugin
548
- ));
549
-
550
- // Register the updater
551
- $this->_setUpdaterInstance($id, $updater);
552
-
553
- // Return true to indicate success
554
- return true;
 
 
 
 
 
555
  }
556
 
557
 
@@ -566,6 +588,7 @@ class Manager {
566
  * @param string $path Plugin file.
567
  * @param array $params Params to requests.
568
  * @return \Aventura\Wprss\Core\Licensing\Plugin\UpdaterInterface
 
569
  */
570
  public function newUpdater($url, $path, $params = array()) {
571
  // Get the updater class
@@ -580,7 +603,7 @@ class Manager {
580
 
581
  $updater = new $updaterClass($url, $path, $params);
582
  if ( !($updater instanceof Plugin\UpdaterInterface) ) {
583
- throw new Exception( sprintf( 'Could not create new updater: class "%1$s" is not an updater', get_class( $updater ) ) );
584
  }
585
 
586
  return $updater;
1
  <?php
2
 
3
  namespace Aventura\Wprss\Core\Licensing;
4
+
5
  use \Aventura\Wprss\Core\Licensing\License\Status;
6
+ use \Aventura\Wprss\Core\Licensing\Api\RequestException;
7
+ use \Aventura\Wprss\Core\Licensing\Api\ResponseException;
8
+ use \Aventura\Wprss\Core\Licensing\Plugin\UpdaterException;
9
 
10
  /**
11
  * Manager class for license handling.
434
 
435
  // Addon Uppercase ID
436
  $addonUid = strtoupper( $addonId );
437
+ // Prepare constants names
438
+ $itemNameConstant = sprintf( 'WPRSS_%s_SL_ITEM_NAME', $addonUid );
439
+ $storeUrlConstant = sprintf( 'WPRSS_%s_SL_STORE_URL', $addonUid );
440
+ // Check for existence of constants
441
+ if ( !defined($itemNameConstant) || !defined($storeUrlConstant) ) {
442
+ return null;
443
+ }
444
+ // Get constant values
445
+ $itemName = constant( $itemNameConstant );
446
+ $storeUrl = constant( $storeUrlConstant );
447
 
448
  try {
449
  $licenseData = $this->api($storeUrl, array(
451
  'license' => $license,
452
  'item_name' => $itemName,
453
  ));
454
+ }
455
+ catch ( RequestException $e ) {
456
  wprss_log( sprintf( 'Could not retrieve licensing data from "%1$s": %2$s', $storeUrl, $e->getMessage() ), __FUNCTION__, WPRSS_LOG_LEVEL_WARNING );
457
  return $license->getStatus();
458
  }
459
+ catch ( ResponseException $e ) {
460
+ wprss_log( sprintf( 'Received invalid licensing data from "%1$s": %2$s', $storeUrl, $e->getMessage() ), __FUNCTION__, WPRSS_LOG_LEVEL_WARNING );
461
+ return $license->getStatus();
462
+ }
463
 
464
  // Update the DB option
465
  $license->setStatus( $licenseData->license );
485
  * 'item_name' are required for a successful call. 'license' can also be
486
  * an instance of {@link Aventura\Wprss\Core\Licensing\License}.
487
  * @return object License data as properties of an stdClass instance.
488
+ * @throws RequestException If request fails or a response is not received.
489
+ * @throws ResponseException If the response is empty or cannot be decoded.
490
  */
491
  public function api($storeUrl, $params) {
492
  $defaultParams = array(
510
 
511
  // Request failed
512
  if ( is_wp_error( $response ) ) {
513
+ throw new RequestException( $response->get_error_message() );
514
  }
515
 
516
  $body = wp_remote_retrieve_body( $response );
517
  if ( empty( $body ) ) {
518
+ throw new ResponseException( 'Response body is empty' );
519
  }
520
 
521
  if ( ($licenseData = json_decode( $body )) === null ) {
522
+ throw new ResponseException( sprintf( 'Response body could not be decoded: %1$s', $body ) );
523
  }
524
 
525
  return $licenseData;
557
  return false;
558
  }
559
 
560
+ try {
561
+ // Create an updater
562
+ $updater = $this->newUpdater($storeUrl, $path, array(
563
+ 'version' => $version, // current version number
564
+ 'license' => $license, // license key (used get_option above to retrieve from DB)
565
+ 'item_name' => $itemName, // name of this plugin
566
+ ));
567
+
568
+ // Register the updater
569
+ $this->_setUpdaterInstance($id, $updater);
570
+
571
+ // Return true to indicate success
572
+ return true;
573
+ } catch ( UpdaterException $e ) {
574
+ wprss_log( sprintf( 'Could not create new updater:: %1$s', $e->getMessage() ), __FUNCTION__, WPRSS_LOG_LEVEL_WARNING );
575
+ return false;
576
+ }
577
  }
578
 
579
 
588
  * @param string $path Plugin file.
589
  * @param array $params Params to requests.
590
  * @return \Aventura\Wprss\Core\Licensing\Plugin\UpdaterInterface
591
+ * @throws \Aventura\Wprss\Core\Licensing\Plugin\Updater\InstanceException If the updater instance class is not a valid updater class.
592
  */
593
  public function newUpdater($url, $path, $params = array()) {
594
  // Get the updater class
603
 
604
  $updater = new $updaterClass($url, $path, $params);
605
  if ( !($updater instanceof Plugin\UpdaterInterface) ) {
606
+ throw new UpdaterException(sprintf('Could not create updater instance: class "%1$s" is not a valid updater', get_class($updater)));
607
  }
608
 
609
  return $updater;
includes/Aventura/Wprss/Core/Licensing/Plugin/Exception.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Licensing\Plugin;
4
+
5
+ use Aventura\Wprss\Core\Licensing;
6
+
7
+ /**
8
+ * Description of Exception
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ class Exception extends Licensing\Exception
13
+ {
14
+ //put your code here
15
+ }
includes/Aventura/Wprss/Core/Licensing/Plugin/UpdaterException.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Licensing\Plugin;
4
+
5
+ /**
6
+ * Thrown when there's an issue with the updater.
7
+ *
8
+ * @since 4.8.1
9
+ * @see Aventura\Wprss\Core\Licensing\Plugin\UpdaterInterface
10
+ */
11
+ class UpdaterException extends Exception {
12
+ }
includes/Aventura/Wprss/Core/Model/AssetsAbstract.php ADDED
@@ -0,0 +1,610 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * Something that can be used as an assets controller.
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ abstract class AssetsAbstract extends Core\Plugin\ComponentAbstract implements AssetsInterface
13
+ {
14
+ /** @since 4.8.1 */
15
+ const HANDLE_PREFIX = '';
16
+
17
+ /** @since 4.8.1 */
18
+ const ASSET_TYPE_STYLE = 'style';
19
+ /** @since 4.8.1 */
20
+ const ASSET_TYPE_SCRIPT = 'script';
21
+
22
+ /** @since 4.8.1 */
23
+ protected static $_assetTypes = array(
24
+ self::ASSET_TYPE_STYLE => self::ASSET_TYPE_STYLE,
25
+ self::ASSET_TYPE_SCRIPT => self::ASSET_TYPE_SCRIPT
26
+ );
27
+
28
+ /** @since 4.8.1 */
29
+ protected $_assets = array();
30
+
31
+ /**
32
+ * @since 4.8.1
33
+ */
34
+ public function hook()
35
+ {
36
+ $this->_hook();
37
+ parent::hook();
38
+ }
39
+
40
+ /**
41
+ * @since 4.8.1
42
+ */
43
+ protected function _hook() {
44
+ $this->on('!wp_enqueue_scripts', array($this, 'enqueuePublicStyles'));
45
+ $this->on('!wp_enqueue_scripts', array($this, 'enqueuePublicScripts'));
46
+ $this->on('!admin_enqueue_scripts', array($this, 'enqueueAdminStyles'));
47
+ $this->on('!admin_enqueue_scripts', array($this, 'enqueueAdminScripts'));
48
+ return $this;
49
+ }
50
+
51
+ /**
52
+ * Regisger a stylesheet.
53
+ *
54
+ * @since 4.8.1
55
+ * @see wp_enqueue_style()
56
+ * @param string $handle The resource handle of the style.
57
+ * @param string $url The stylesheet URL. If not absolute will be relative to the base CSS URI;
58
+ * See {@see getCssUri()}.
59
+ * @param array|null $dependencies One or many handles of other resources, on which this style depends.
60
+ * @param string|null $version The version number of this stylesheet. Changing version number will cause the
61
+ * user agents to flush the resource's cache.
62
+ * Default: The version of the plugin, to which this component belongs.
63
+ * @param string|null $media The media, on which this stylesheed should have effect.
64
+ * Default: 'all'.
65
+ * @return AssetsAbstract
66
+ */
67
+ protected function _registerStyle($handle, $url, $dependencies = null, $version = null, $media = null, $allowOverwrite = false)
68
+ {
69
+ return $this->register(self::ASSET_TYPE_STYLE, array(
70
+ 'handle' => $handle,
71
+ 'version' => $version,
72
+ 'uri' => $url,
73
+ 'media' => $media
74
+ ), $dependencies, $allowOverwrite);
75
+ }
76
+
77
+ /**
78
+ * Register a script.
79
+ *
80
+ * @since 4.8.1
81
+ * @see wp_enqueue_script()
82
+ * @param string $handle The resource handle of the script.
83
+ * @param string $url The script URL. If not absolute will be relative to the base JS URI;
84
+ * See {@see getJsUri()}.
85
+ * @param array|null $dependencies One or many handles of other resources, on which this script depends.
86
+ * @param string|null $version The version number of this script. Changing version number will cause the
87
+ * user agents to flush the resource's cache.
88
+ * Default: The version of the plugin, to which this component belongs.
89
+ * @param bool|null $inFooter Whether or not the script should be in the footer.
90
+ * @param bool $allowOverwrite Whether or not the asset should still be enqueued even if this handle is already registered.
91
+ * @return AssetsAbstract
92
+ */
93
+ protected function _registerScript($handle, $url, $dependencies = null, $version = null, $inFooter = false, $allowOverwrite = false)
94
+ {
95
+ return $this->register(self::ASSET_TYPE_SCRIPT, array(
96
+ 'handle' => $handle,
97
+ 'version' => $version,
98
+ 'uri' => $url,
99
+ 'in_footer' => $inFooter
100
+ ), $dependencies, $allowOverwrite);
101
+ }
102
+
103
+ /**
104
+ * Registers an asset.
105
+ *
106
+ * @since 4.8.1
107
+ * @param string $type The type of the asset.
108
+ * @param array $data Data of the asset. Following keys supported:
109
+ * 'handle'*, 'uri'*, 'version', 'in_footer' (SCRIPT), 'media'(STYLE)
110
+ * The 'handle' value will be prefixed, unless overridden/
111
+ * The 'uri' value will be made absolute, unless already absolute.
112
+ * @param array|null $dependencies Handles of asset that this asset depends on, if any.
113
+ * @throws Core\Exception If invalid 'type' value, or 'handle' or 'uri' not supplied.
114
+ */
115
+ public function register($type, $data, $dependencies = null, $allowOverwrite = false)
116
+ {
117
+ $type = trim($type);
118
+ if (!static::hasAssetType($type)) {
119
+ throw $this->exception(array('Could not register asset of type "%1$s": Type is invalid, please use one of [%2$s]',
120
+ $type,
121
+ implode(', ', static::getAssetTypes())));
122
+ }
123
+
124
+ // Default version
125
+ if (is_null($data['version'])) {
126
+ $data['version'] = $this->getPlugin()->getVersion();
127
+ }
128
+ // Default dependencies
129
+ if (is_null($dependencies)) {
130
+ $dependencies = array();
131
+ }
132
+ $dependencies = (array)$dependencies;
133
+ // Must provide handle
134
+ if (!isset($data['handle'])) {
135
+ throw $this->exception(array('Could not register asset of type "%1$s": Handle must be provided', $type));
136
+ }
137
+ // Must provide uri
138
+ if (!isset($data['uri'])) {
139
+ throw $this->exception(array('Could not register asset "%2$s" of type "%1$s": URI must be provided', $type, $data['handle']));
140
+ }
141
+
142
+ // Normalizing handle
143
+ if (!static::stringHadPrefix($data['handle'])) {
144
+ $data['handle'] = $this->getHandlePrefix($data['handle']);
145
+ }
146
+ // Normalizing stylesheet
147
+ if (!static::isUriAbsolute($data['uri'])) {
148
+ switch ($type) {
149
+ case static::ASSET_TYPE_STYLE:
150
+ $data['uri'] = $this->getCssUri($data['uri']);
151
+ break;
152
+
153
+ case static::ASSET_TYPE_SCRIPT:
154
+ $data['uri'] = $this->getJsUri($data['uri']);
155
+ break;
156
+ }
157
+ }
158
+
159
+ return $this->_register($type, $data, $dependencies, $allowOverwrite);
160
+ }
161
+
162
+ /**
163
+ * Registers an asset.
164
+ *
165
+ * @since 4.8.1
166
+ * @param string $type The type of the asset.
167
+ * @param array $data Data of the asset. Following keys supported:
168
+ * 'handle'*, 'uri'*, 'version', 'in_footer' (SCRIPT), 'media'(STYLE)
169
+ * The 'handle' value will be prefixed, unless overridden/
170
+ * The 'uri' value will be made absolute, unless already absolute.
171
+ * @param array|null $dependencies Handles of asset that this asset depends on, if any.
172
+ * @throws Core\Exception If invalid 'type' value, or 'handle' or 'uri' not supplied.
173
+ */
174
+ protected function _register($type, $data, array $dependencies, $allowOverwrite = false)
175
+ {
176
+ switch ($type) {
177
+ case static::ASSET_TYPE_SCRIPT:
178
+ // Default value
179
+ if (!isset($data['in_footer'])) {
180
+ $data['in_footer'] = false;
181
+ }
182
+
183
+ return $this->_addAsset($type, $data, $dependencies, $allowOverwrite);
184
+ break;
185
+
186
+ case static::ASSET_TYPE_STYLE:
187
+ // Default value
188
+ if (!isset($data['media'])) {
189
+ $data['media'] = 'all';
190
+ }
191
+
192
+ return $this->_addAsset($type, $data, $dependencies, $allowOverwrite);
193
+ break;
194
+ }
195
+
196
+ return null;
197
+ }
198
+
199
+ /**
200
+ * Add an asset to asset list.
201
+ *
202
+ * @param string $type The type of the asset.
203
+ * @param array $data The asset data.
204
+ * @param array $dependencies The dependencies of the asset, if any.
205
+ * @param bool $allowOverride If true, and the handle already registered, it will be replaced.
206
+ * @return string The handle of the added asset.
207
+ */
208
+ protected function _addAsset($type, $data, array $dependencies, $allowOverride = false)
209
+ {
210
+ if (isset($this->_assets[$type]) && $allowOverride) {
211
+ return null;
212
+ }
213
+
214
+ $handle = isset($data['handle']) ? $data['handle'] : $this->_getUniqueHandle();
215
+ $data['type'] = $type;
216
+ $data['dependencies'] = $dependencies;
217
+ $this->_assets[$handle] = $data;
218
+ return $handle;
219
+ }
220
+
221
+ /**
222
+ * Generate a unique asset handle.
223
+ *
224
+ * @since 4.8.1
225
+ * @return string A unique, prefixed asset handle.
226
+ */
227
+ protected function _getUniqueHandle($uri = null)
228
+ {
229
+ if (is_null($uri)) {
230
+ return uniqid($this->getHandlePrefix(), true);
231
+ }
232
+
233
+ return $this->getHandlePrefix(md5($uri));
234
+ }
235
+
236
+ /**
237
+ * Retrieve asset data by handle.
238
+ *
239
+ * @since 4.8.1
240
+ * @param string $handle The handle of the asset to get.
241
+ * @return array The asset data if exists, null otherwise.
242
+ */
243
+ public function getAsset($handle)
244
+ {
245
+ return $this->hasAsset($handle) ? $this->_assets[$handle] : null;
246
+ }
247
+
248
+ /**
249
+ * Get all registered assets.
250
+ *
251
+ * @since 4.8.1
252
+ * @return array All assets, by handle.
253
+ */
254
+ public function getAssets() {
255
+ return $this->_assets;
256
+ }
257
+
258
+ /**
259
+ * Whether or not an asset is registered.
260
+ *
261
+ * @since 4.8.1
262
+ * @param string $handle An asset handle.
263
+ * @return bool True if asset with specified handle exists; false otherwise.
264
+ */
265
+ public function hasAsset($handle)
266
+ {
267
+ return isset($this->_assets[$handle]);
268
+ }
269
+
270
+ /**
271
+ * Register an asset.
272
+ *
273
+ * @since 4.8.1
274
+ * @param array $asset An array with asset data.
275
+ * @return bool True if registered, false otherwise.
276
+ */
277
+ protected function _registerAsset($asset)
278
+ {
279
+
280
+ $type = $asset['type'];
281
+ switch ($type) {
282
+ case static::ASSET_TYPE_SCRIPT:
283
+ wp_register_script(
284
+ (string)$asset['handle'],
285
+ (string)$asset['uri'],
286
+ (array)$asset['dependencies'],
287
+ (string)$asset['version'],
288
+ (bool)$asset['in_footer']
289
+ );
290
+ return true;
291
+ break;
292
+
293
+ case static::ASSET_TYPE_STYLE:
294
+ wp_register_style(
295
+ (string)$asset['handle'],
296
+ (string)$asset['uri'],
297
+ (array)$asset['dependencies'],
298
+ (string)$asset['version'],
299
+ (string)$asset['media']
300
+ );
301
+ return true;
302
+ break;
303
+ }
304
+
305
+ return false;
306
+ }
307
+
308
+ /**
309
+ * Enqueue an asset by handle.
310
+ *
311
+ * @since 4.8.1
312
+ * @param string $asset The asset handle.
313
+ * @return bool True if enqueued, false otherwise.
314
+ * @throws Core\Exception If no handle provided, or no asset registered for handle.
315
+ */
316
+ protected function _enqueueAsset($asset)
317
+ {
318
+ if(!is_string($asset)) {
319
+ throw $this->exception('Cannot enqueue asset: An asset handle must be provided');
320
+ }
321
+
322
+ if (!($asset = $this->getAsset($asset))) {
323
+ throw $this->exception(array('Could not enqueue asset "%1$s": No asset registered with that handle'));
324
+ }
325
+ $type = $asset['type'];
326
+
327
+ switch ($type) {
328
+ case static::ASSET_TYPE_SCRIPT:
329
+ wp_enqueue_script(
330
+ (string)$asset['handle'],
331
+ (string)$asset['uri'],
332
+ (array)$asset['dependencies'],
333
+ (string)$asset['version'],
334
+ (bool)$asset['in_footer']
335
+ );
336
+ return true;
337
+ break;
338
+
339
+ case static::ASSET_TYPE_STYLE:
340
+ wp_enqueue_style(
341
+ (string)$asset['handle'],
342
+ (string)$asset['uri'],
343
+ (array)$asset['dependencies'],
344
+ (string)$asset['version'],
345
+ (string)$asset['media']
346
+ );
347
+ return true;
348
+ break;
349
+ }
350
+
351
+ return false;
352
+ }
353
+
354
+ /**
355
+ * Register a stylesheet.
356
+ *
357
+ * @since 4.8.1
358
+ * @param string $handle The unique asset handle.
359
+ * @param string $uri The URI of the asset. If relative, it will be appended to the value of {@see getCssUri()}.
360
+ * @param array|null $dependencies List of dependencies for the assed. If null, empty array will be used.
361
+ * @param string|null $version The version of the asset. If null, the plugin version will be used.
362
+ * @param string|null $media The CSS media type.
363
+ * If null, 'all' will be used.
364
+ * @param bool|null $allowOverwrite If true, and the handle already exists, it will be overwritten.
365
+ * @return string|null The asset handle if regisered; otherwise null.
366
+ */
367
+ public function registerStyle($handle, $uri, $dependencies = null, $version = null, $media = null, $allowOverwrite = false)
368
+ {
369
+ return $this->_registerStyle($handle, $uri, $dependencies, $version, $media, $allowOverwrite);
370
+ }
371
+
372
+ /**
373
+ * Enqueue a registered style by handle.
374
+ *
375
+ * @since 4.8.1
376
+ * @param string $handle The handle of the style to enqueue.
377
+ * @return AssetsAbstract This instance.
378
+ * @throws Core\Exception If the handle isn't registered, the handle type is not registered or is not of a style.
379
+ */
380
+ public function enqueueStyle($handle)
381
+ {
382
+ // Normalizing handle
383
+ if (!static::stringHadPrefix($handle)) {
384
+ $handle = $this->getHandlePrefix($handle);
385
+ }
386
+ if (!($asset = $this->getAsset($handle))) {
387
+ throw $this->exception(array('Could not enqueue script "%1$s": Register the script first', $handle));
388
+ }
389
+ if (!$this->hasAssetType($asset['type'])) {
390
+ throw $this->exception(array('Could not enqueue style "%1$s": "%2$s" is not a registered asset type', $handle, $asset['type']));
391
+ }
392
+ if ($asset['type'] !== static::ASSET_TYPE_STYLE) {
393
+ throw $this->exception(array('Could not enqueue style "%1$s": "%2$s" is not a style type', $handle, $asset['type']));
394
+ }
395
+ $this->_enqueueAsset($handle);
396
+
397
+ return $this;
398
+ }
399
+
400
+ /**
401
+ * Register a script.
402
+ *
403
+ * @since 4.8.1
404
+ * @param string $handle The unique asset handle.
405
+ * @param string $uri The URI of the asset. If relative, it will be appended to the value of {@see getJSUri()}.
406
+ * @param array|null $dependencies List of dependencies for the assed. If null, empty array will be used.
407
+ * @param string|null $version The version of the asset. If null, the plugin version will be used.
408
+ * @param bool $inFooter Whether or not the script should go in the footer.
409
+ * @param bool|null $allowOverwrite If true, and the handle already exists, it will be overwritten.
410
+ * @return string|null The asset handle if regisered; otherwise null.
411
+ */
412
+ public function registerScript($handle, $uri, $dependencies = null, $version = null, $inFooter = false, $allowOverwrite = false)
413
+ {
414
+ $this->_registerScript($handle, $uri, $dependencies, $version, $inFooter, $allowOverwrite);
415
+ }
416
+
417
+ /**
418
+ * Enqueue a registered script by handle.
419
+ *
420
+ * @since 4.8.1
421
+ * @param string $handle The handle of the script to enqueue.
422
+ * @return AssetsAbstract This instance.
423
+ * @throws Core\Exception If the handle isn't registered, the handle type is not registered or is not of a script.
424
+ */
425
+ public function enqueueScript($handle)
426
+ {
427
+ // Normalizing handle
428
+ if (!static::stringHadPrefix($handle)) {
429
+ $handle = $this->getHandlePrefix($handle);
430
+ }
431
+ if (!($asset = $this->getAsset($handle))) {
432
+ throw $this->exception(array('Could not enqueue script "%1$s": Register the script first', $handle));
433
+ }
434
+ if (!$this->hasAssetType($asset['type'])) {
435
+ throw $this->exception(array('Could not enqueue script "%1$s": "%2$s" is not a registered asset type', $handle, $asset['type']));
436
+ }
437
+ if ($asset['type'] !== static::ASSET_TYPE_SCRIPT) {
438
+ throw $this->exception(array('Could not enqueue style "%1$s": "%2$s" is not a script type', $handle, $asset['type']));
439
+ }
440
+ $this->_enqueueAsset($handle);
441
+
442
+ return $this;
443
+ }
444
+
445
+ /**
446
+ * Get all asset types of this class.
447
+ *
448
+ * @since 4.8.1
449
+ * @return array The asset type, where keys are the type code.
450
+ */
451
+ public static function getAssetTypes()
452
+ {
453
+ return static::$_assetTypes;
454
+ }
455
+
456
+ /**
457
+ * Whether or not an asset type exists.
458
+ *
459
+ * @since 4.8.1
460
+ * @param string $type The asset type.
461
+ * @return bool True if exists; false otherwise.
462
+ */
463
+ public static function hasAssetType($type)
464
+ {
465
+ $types = static::getAssetTypes();
466
+ return isset($types[$type]);
467
+ }
468
+
469
+ /**
470
+ * Gets the optionally suffixed prefix for resource handles configured for this instance.
471
+ *
472
+ * A resource handle is a unique ID that identifies resources enqueued with functions such as `wp_enqueue_script()`
473
+ * and `wp_enqueue_style()`.
474
+ *
475
+ * @since 4.8.1
476
+ * @param string|null $handle If speficied, the prefix will be suffixed with this.
477
+ * @return string|null The prefix for resource handles that is configured for this instance, optionally suffixed
478
+ * with $handle.
479
+ */
480
+ public function getHandlePrefix($handle = null)
481
+ {
482
+ $prefix = $this->_getHandlePrefix();
483
+ return is_null($handle)
484
+ ? $prefix
485
+ : static::stringHadPrefix($handle) ? $handle : "{$prefix}{$handle}";
486
+ }
487
+
488
+ /**
489
+ * Gets the prefix for resource handles configured for this instance.
490
+ *
491
+ * A resource handle is a unique ID that identifies resources enqueued with functions such as `wp_enqueue_script()`
492
+ * and `wp_enqueue_style()`.
493
+ *
494
+ * If the 'handle_prefix' data member is not set, falls back to the `HANDLE_PREFIX` class constant, then to `null`.
495
+ *
496
+ * @since 4.8.1
497
+ * @return string|null The prefix for resource handles that is configured for this instance.
498
+ */
499
+ public function _getHandlePrefix()
500
+ {
501
+ $pluginCode = $this->getPlugin()->getCode();
502
+ return $this->_getDataOrConst('handle_prefix', $pluginCode ? sprintf('%1$s-', $pluginCode) : '');
503
+ }
504
+
505
+ /**
506
+ * Gets and optionally suffixes the base CSS URI for this instance.
507
+ *
508
+ * @since 4.8.1
509
+ * @param string|null $path If specified and not null, the base CSS UR will be suffixed with this.
510
+ * @return string The base CSS URI configured for this instance, optionally suffixed with the $path.
511
+ */
512
+ public function getCssUri($path = null)
513
+ {
514
+ $base = untrailingslashit($this->_getDataOrConst('css_uri'));
515
+ return is_null($path)
516
+ ? $base
517
+ : "{$base}/{$path}";
518
+ }
519
+
520
+ /**
521
+ * Gets and optionally suffixes the base JS URI for this instance.
522
+ *
523
+ * @since 4.8.1
524
+ * @param string|null $path If specified and not null, the base JS UR will be suffixed with this.
525
+ * @return string The base JS URI configured for this instance, optionally suffixed with the $path.
526
+ */
527
+ public function getJsUri($path = null)
528
+ {
529
+ $base = untrailingslashit($this->_getDataOrConst('js_uri'));
530
+ return is_null($path)
531
+ ? $base
532
+ : "{$base}/{$path}";
533
+ }
534
+
535
+ /**
536
+ * Gets the base CSS URI configured for this instance.
537
+ *
538
+ * If the 'css_uri' data member is not set, falls back to the `CSS_URL` class constant, then to `null`.
539
+ *
540
+ * @since 4.8.1
541
+ * @return string|null The base CSS URI configured for this instance.
542
+ */
543
+ protected function _getCssUri()
544
+ {
545
+ // Allowing override via data
546
+ $key = 'css_uri';
547
+ if ($this->hasData($key)) {
548
+ return $this->getData($key);
549
+ }
550
+ // Falling back to constant
551
+ $class = get_class($this);
552
+ $const = "{$class}::CSS_URI";
553
+ if (defined($const)) {
554
+ return constant($const);
555
+ }
556
+
557
+ return null;
558
+ }
559
+
560
+ /**
561
+ * Checks if a URI is absolute.
562
+ *
563
+ * @since 4.8.1
564
+ * @see uri_is_absolute()
565
+ */
566
+ public static function isUriAbsolute($uri)
567
+ {
568
+ return uri_is_absolute($uri);
569
+ }
570
+
571
+ /**
572
+ * {@inheritdoc}
573
+ *
574
+ * @since 4.8.1
575
+ */
576
+ public function enqueuePublicStyles()
577
+ {
578
+ return $this;
579
+ }
580
+
581
+ /**
582
+ * {@inheritdoc}
583
+ *
584
+ * @since 4.8.1
585
+ */
586
+ public function enqueuePublicScripts()
587
+ {
588
+ return $this;
589
+ }
590
+
591
+ /**
592
+ * {@inheritdoc}
593
+ *
594
+ * @since 4.8.1
595
+ */
596
+ public function enqueueAdminStyles()
597
+ {
598
+ return $this;
599
+ }
600
+
601
+ /**
602
+ * {@inheritdoc}
603
+ *
604
+ * @since 4.8.1
605
+ */
606
+ public function enqueueAdminScripts()
607
+ {
608
+ return $this;
609
+ }
610
+ }
includes/Aventura/Wprss/Core/Model/AssetsInterface.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ /**
6
+ * Something that can be used as an assets controller.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ interface AssetsInterface
11
+ {
12
+ /**
13
+ * Enqueues the styles for the front-end.
14
+ *
15
+ * @since 4.8.1
16
+ */
17
+ public function enqueuePublicStyles();
18
+
19
+ /**
20
+ * Enqueues the scripts for the front-end.
21
+ *
22
+ * @since 4.8.1
23
+ */
24
+ public function enqueuePublicScripts();
25
+
26
+ /**
27
+ * Enqueues the styles for the front-end.
28
+ *
29
+ * @since 4.8.1
30
+ */
31
+ public function enqueueAdminStyles();
32
+
33
+ /**
34
+ * Enqueues the scripts for the front-end.
35
+ *
36
+ * @since 4.8.1
37
+ */
38
+ public function enqueueAdminScripts();
39
+ }
includes/Aventura/Wprss/Core/Model/Command.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ /**
6
+ * A single command.
7
+ *
8
+ * Possible to instantiate and use right away.
9
+ *
10
+ * @since [*next-version]
11
+ */
12
+ class Command extends CommandAbstract
13
+ {
14
+
15
+ }
includes/Aventura/Wprss/Core/Model/CommandAbstract.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ /**
6
+ * Common functionality for all commands.
7
+ *
8
+ * @since [*next-version]
9
+ */
10
+ abstract class CommandAbstract extends ModelAbstract implements CommandInterface
11
+ {
12
+ protected $_callable;
13
+ protected $_args = array();
14
+
15
+
16
+ /**
17
+ * @since 4.8.1
18
+ * @param callable $data The {@link set_function() function} to give to the command.
19
+ */
20
+ public function __construct( $data = array() )
21
+ {
22
+ if (is_callable($data, true)) {
23
+ $data = array('function' => $data);
24
+ }
25
+
26
+ if (isset($data['function'])) {
27
+ $this->setFunction($data['function']);
28
+ unset($data['function']);
29
+ }
30
+
31
+ if (isset($data['args'])) {
32
+ $this->setArgs($data['args']);
33
+ unset($data['args']);
34
+ }
35
+
36
+ parent::__construct($data);
37
+ }
38
+
39
+
40
+ /**
41
+ * Sets the function to be called with this command.
42
+ *
43
+ * @since 4.8.1
44
+ * @param callable $function The function or method to be called.
45
+ * @return CommandAbstract This instance.
46
+ * @throws CommandException If passed function is not a valid callable.
47
+ */
48
+ public function setFunction( $function ) {
49
+ if ( !is_callable( $function, true ) )
50
+ throw $this->exception( 'Could not set function: function is not a valid callable', array(__NAMESPACE__, 'CommandException') );
51
+
52
+ $this->_callable = $function;
53
+ return $this;
54
+ }
55
+
56
+
57
+ /**
58
+ * Sets the argument or arguments for this command.
59
+ *
60
+ * If index is null or omitted, all arguments will be set to the value of $args.
61
+ * If in this case $args is not an array, args will be an array where $args is
62
+ * the only element.
63
+ * In any case, the indexes of $args do not matter, but the order does.
64
+ *
65
+ * @since 4.8.1
66
+ * @param array $args The argument or arguments to set for this command.
67
+ * @param int $index The index, at which to set the argument.
68
+ * @return CommandAbstract This instance.
69
+ */
70
+ public function setArgs( $args, $index = null ) {
71
+ if ( is_null( $index ) ) {
72
+ $this->_args = array_values( (array) $args );
73
+ return $this;
74
+ }
75
+
76
+ $index = (int) $index;
77
+ $this->_args[ $index ] = $args;
78
+
79
+ return $this;
80
+ }
81
+
82
+
83
+ /**
84
+ * @since 4.8.1
85
+ * @return callable The function of the command.
86
+ */
87
+ public function getFunction() {
88
+ return $this->_callable;
89
+ }
90
+
91
+
92
+ /**
93
+ * Gets the argument or arguments for this command.
94
+ *
95
+ * @since 4.8.1
96
+ * @param int|null $index The index of the argument to return.
97
+ * @return array|mixed|null The argument, or arguments, or null if not found.
98
+ */
99
+ public function getArgs( $index = null ) {
100
+ if ( is_null( $index ) )
101
+ return $this->_args;
102
+
103
+ $index = (int) $index;
104
+ return isset( $this->_args[ $index ] ) ? $this->_args[ $index ] : null;
105
+ }
106
+
107
+
108
+ /**
109
+ * Calls the function of this command with the given arguments.
110
+ *
111
+ * @since 4.8.1
112
+ * @param array $args_override A different set of arguments that will override the original.
113
+ * @return mixed The return value of the function of the command.
114
+ * @throws CommandException If the function of the command is not callable.
115
+ */
116
+ public function call($args_override = array()) {
117
+ $args = $this->getArgs();
118
+ $args = array_merge_recursive_distinct( $args, $args_override );
119
+
120
+ if ( !is_callable( $callable = $this->getFunction() ) )
121
+ throw $this->exception( 'Could not call function: function must be callable', array(__NAMESPACE__, 'CommandException') );
122
+
123
+ $result = call_user_func_array( $callable, $args);
124
+ return $result;
125
+ }
126
+
127
+ /**
128
+ * Allows instances of this class and its descendants to be called like a function.
129
+ *
130
+ * @since 4.8.1
131
+ * @return type
132
+ */
133
+ public function __invoke()
134
+ {
135
+ $args = func_get_args();
136
+ return $this->call($args);
137
+ }
138
+ }
includes/Aventura/Wprss/Core/Model/CommandException.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * An exception that occurs when doing something related to a command.
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ class CommandException extends Core\Exception
13
+ {
14
+ }
includes/Aventura/Wprss/Core/Model/CommandInterface.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ /**
6
+ * An interface of something that can be a command.
7
+ *
8
+ * @since [*next-version]
9
+ */
10
+ interface CommandInterface
11
+ {
12
+ /**
13
+ * Makes it possible to invoke an instance of the implementing class
14
+ * as if it was a function.
15
+ *
16
+ * @since 4.8.1
17
+ * @return mixed The result of the call
18
+ */
19
+ public function __invoke();
20
+ }
includes/Aventura/Wprss/Core/Model/Event/Event.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model\Event;
4
+
5
+ /**
6
+ * @since 4.8.1
7
+ */
8
+ class Event extends EventAbstract
9
+ {
10
+
11
+ }
includes/Aventura/Wprss/Core/Model/Event/EventAbstract.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model\Event;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * @since 4.8.1
9
+ */
10
+ abstract class EventAbstract extends Core\DataObject implements EventInterface
11
+ {
12
+ /** @since 4.8.1 */
13
+ protected $_name;
14
+
15
+ /**
16
+ * @since 4.8.1
17
+ * @param array|string $data The event's data. Must have a 'name' index.
18
+ * If string, will be used as 'name'.
19
+ */
20
+ public function __construct($data)
21
+ {
22
+ if (!is_array($data)) {
23
+ $data = array('name' => $data);
24
+ }
25
+
26
+ parent::__construct($data);
27
+ }
28
+
29
+ /**
30
+ * @since 4.8.1
31
+ * @throws Core\Exception If 'name' index is not present.
32
+ */
33
+ protected function _construct()
34
+ {
35
+ parent::_construct();
36
+
37
+ if (!$this->hasData('name')) {
38
+ throw new Exception('Could not create event: Name must be specified');
39
+ }
40
+
41
+ $this->_setName($this->getData('name'));
42
+ }
43
+
44
+ /**
45
+ * Get the name of this event
46
+ *
47
+ * @since 4.8.1
48
+ * @return string
49
+ */
50
+ public function getName()
51
+ {
52
+ return $this->_name;
53
+ }
54
+
55
+ /**
56
+ * Blocks setting name from outside.
57
+ *
58
+ * If used, a notice will be emitted.
59
+ *
60
+ * @since 4.8.1
61
+ * @access protected
62
+ * @param string $name
63
+ * @return EventAbstract This instance.
64
+ */
65
+ public function setName($name)
66
+ {
67
+ trigger_error('Event name can only be set upon creation', E_USER_NOTICE);
68
+ return $this;
69
+ }
70
+
71
+ /**
72
+ * Set this event's name.
73
+ *
74
+ * @since 4.8.1
75
+ * @param string $name
76
+ * @return EventAbstract This instance.
77
+ */
78
+ protected function _setName($name)
79
+ {
80
+ $this->_name = trim($name);
81
+ return $this;
82
+ }
83
+ }
includes/Aventura/Wprss/Core/Model/Event/EventInterface.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model\Event;
4
+
5
+ /**
6
+ * @since 4.8.1
7
+ */
8
+ interface EventInterface
9
+ {
10
+ /**
11
+ * Get the event name.
12
+ *
13
+ * @since 4.8.1
14
+ */
15
+ public function getName();
16
+
17
+ /**
18
+ * Get event data.
19
+ *
20
+ * @since 4.8.1
21
+ * @param string|null $key All event data, or data at a specific index.\
22
+ */
23
+ public function getData($key = null);
24
+
25
+ /**
26
+ * Set event data.
27
+ *
28
+ * @since 4.8.1
29
+ * @param array|string $key The key to set the value for, or an array of data to replace.
30
+ * @param mixed|null $value The value to set for the data key.
31
+ */
32
+ public function setData($key, $value = null);
33
+ }
includes/Aventura/Wprss/Core/Model/Event/EventManagerAbstract.php ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model\Event;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * @since 4.8.1
9
+ */
10
+ class EventManagerAbstract extends Core\Plugin\ComponentAbstract implements EventManagerInterface
11
+ {
12
+ /** @since 4.8.1 */
13
+ const DEFAULT_PRIORITY = 10;
14
+
15
+ /** @since 4.8.1 */
16
+ const DEFAULT_ACCEPTED_ARGS = 1;
17
+
18
+ /**
19
+ * The array of actions registered with WordPress.
20
+ *
21
+ * @since 4.8.1
22
+ * @var array $actions The actions registered with WordPress to fire when the plugin loads.
23
+ */
24
+ protected $_events = array();
25
+ protected $_isRan;
26
+
27
+ protected function _construct()
28
+ {
29
+ parent::_construct();
30
+ $this->setIsKeepRecords(true);
31
+ }
32
+
33
+ /**
34
+ * Registers an event listener.
35
+ *
36
+ * @since 4.8.1
37
+ * @param string $name The name of the event that a listener is being registered for.
38
+ * @param callable $listener The listener.
39
+ * @param int|null $priority The priority at which the listener should be invoked.
40
+ * Default: {@link EventManagerAbstract::DEFAULT_PRIORITY}.
41
+ * @param array|null $data
42
+ * @param int|null $acceptedArgs The number of arguments that should be passed to the listener.
43
+ * Default: {@link EventManagerAbstract::DEFAULT_ACCEPTED_ARGS}.
44
+ * You don't really need to specify this with events fired via this class.
45
+ * @param bool $now Whether or not to add the event right now, now when run().
46
+ * @return EventManagerAbstract This instance.
47
+ */
48
+ public function on($name, $listener, $data = null, $priority = null, $acceptedArgs = null)
49
+ {
50
+ if (is_null($priority)) {
51
+ $priority = static::DEFAULT_PRIORITY;
52
+ }
53
+ if (is_null($acceptedArgs)) {
54
+ $acceptedArgs = static::DEFAULT_ACCEPTED_ARGS;
55
+ }
56
+ if (is_null($data)) {
57
+ $data = array();
58
+ }
59
+
60
+ $listener = $this->_normalizeCallback($listener);
61
+ $eventInfo = array(
62
+ 'name' => $name,
63
+ 'listener' => $listener,
64
+ 'args' => $data,
65
+ 'priority' => $priority,
66
+ 'accepted_args' => $acceptedArgs
67
+ );
68
+ if ($this->getIsKeepRecords()) {
69
+ $this->_events[] = $eventInfo;
70
+ }
71
+ $this->_register($eventInfo);
72
+
73
+ return $name;
74
+ }
75
+
76
+ /**
77
+ * Registers an event with the environment.
78
+ *
79
+ * @since 4.8.1
80
+ * @param array $eventInfo Data of the event.
81
+ * @return EventManagerAbstract This instance.
82
+ */
83
+ protected function _register($eventInfo)
84
+ {
85
+ $proxy = function() use ($eventInfo) {
86
+ $args = func_get_args();
87
+
88
+ // Adding registration time arguments
89
+ $event = isset($args[0]) ? $args[0] : null;
90
+ $argsOverride = isset($eventInfo['args']) ? $eventInfo['args'] : array();
91
+ if ($event instanceof EventInterface) {
92
+ foreach ($argsOverride as $_arg => $_argVal) {
93
+ if (!$event->hasData($_arg)) {
94
+ $event->setData($_arg, $_argVal);
95
+ }
96
+ }
97
+ }
98
+
99
+ return call_user_func_array($eventInfo['listener'], $args);
100
+ };
101
+
102
+ add_filter($eventInfo['name'], $proxy, $eventInfo['priority'], $eventInfo['accepted_args']);
103
+ return $this;
104
+ }
105
+
106
+ /**
107
+ * Normalizes a callback.
108
+ *
109
+ * @since 4.8.1
110
+ * @param callable $callback The callback to normalize
111
+ * @return If array is given, makes sure that the result is a numeric array with correct order of valuesl
112
+ * Otherwise, returns the callback unmodified.
113
+ */
114
+ protected function _normalizeCallback($callback)
115
+ {
116
+ if (is_array($callback)) {
117
+ $callback = array_values($callback);
118
+ $component = $callback[0];
119
+ $callback = $callback[1];
120
+ $callback = array($component, $callback);
121
+ }
122
+
123
+ return $callback;
124
+ }
125
+
126
+ /**
127
+ * {@inheritdoc}
128
+ *
129
+ * @since 4.8.1
130
+ */
131
+ public function event($name, $data = array())
132
+ {
133
+ if (is_object($data)) {
134
+ $data = (array) $data;
135
+ }
136
+ $event = $this->_createEvent($name, $data);
137
+ return $this->_dispatch($event);
138
+ }
139
+
140
+ /**
141
+ * Dispatches the actual event.
142
+ *
143
+ * @since 4.8.1
144
+ * @param EventInterface $event The event to dispatch.
145
+ * @return mixed The event object, possibly modified.
146
+ */
147
+ protected function _dispatch(EventInterface $event)
148
+ {
149
+ return apply_filters($event->getName(), $event);
150
+ }
151
+
152
+ /**
153
+ * Creates a new event.
154
+ *
155
+ * @since 4.8.1
156
+ * @param string $name The name of the event.
157
+ * @param array $args An array of arguments.
158
+ * @return EventInterface
159
+ */
160
+ protected function _createEvent($name, $args = array())
161
+ {
162
+ $event = new Event($name);
163
+ foreach($args as $_key => $_val) {
164
+ $event->setData($_key, $_val);
165
+ }
166
+ return $event;
167
+ }
168
+ }
includes/Aventura/Wprss/Core/Model/Event/EventManagerInterface.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model\Event;
4
+
5
+ /**
6
+ * An interface for something that can manage events.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ interface EventManagerInterface
11
+ {
12
+ /**
13
+ * Add an event listener.
14
+ *
15
+ * @since 4.8.1
16
+ * @param string $name The name of the event.
17
+ * @param callable $listener The listener of the event.
18
+ * @param null|int $priority Priority of the listener. If null, implementation-default will be used.
19
+ * @param null|int $numArgs Number of arguments to pass to the listener. If null, implementation-default will be used.
20
+ */
21
+ public function on($name, $listener, $args = null, $priority = null, $numArgs = null);
22
+
23
+ /**
24
+ * Raises an event.
25
+ *
26
+ * @since 4.8.1
27
+ * @param string $name Name of the event.
28
+ * @param array|object $data The event data.
29
+ * @return EventInterface An event object that is the result of this event.
30
+ * This object will contain the data passed, and possibly modified.
31
+ */
32
+ public function event($name, $data = array());
33
+ }
includes/Aventura/Wprss/Core/Model/LoggerAbstract.php ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * @since 4.8.1
9
+ */
10
+ abstract class LoggerAbstract extends Core\Plugin\ComponentAbstract implements LoggerInterface
11
+ {
12
+ /**
13
+ * Detailed debug information
14
+ *
15
+ * @since 4.8.1
16
+ */
17
+ const DEBUG = 100;
18
+
19
+ /**
20
+ * Interesting events
21
+ *
22
+ * Examples: User logs in, SQL logs.
23
+ *
24
+ * @since 4.8.1
25
+ */
26
+ const INFO = 200;
27
+
28
+ /**
29
+ * Uncommon events
30
+ *
31
+ * @since 4.8.1
32
+ */
33
+ const NOTICE = 250;
34
+
35
+ /**
36
+ * Exceptional occurrences that are not errors
37
+ *
38
+ * Examples: Use of deprecated APIs, poor use of an API,
39
+ * undesirable things that are not necessarily wrong.
40
+ *
41
+ * @since 4.8.1
42
+ */
43
+ const WARNING = 300;
44
+
45
+ /**
46
+ * Runtime errors
47
+ *
48
+ * @since 4.8.1
49
+ */
50
+ const ERROR = 400;
51
+
52
+ /**
53
+ * Critical conditions
54
+ *
55
+ * Example: Application component unavailable, unexpected exception.
56
+ *
57
+ * @since 4.8.1
58
+ */
59
+ const CRITICAL = 500;
60
+
61
+ /**
62
+ * Action must be taken immediately
63
+ *
64
+ * Example: Entire website down, database unavailable, etc.
65
+ * This should trigger the SMS alerts and wake you up.
66
+ *
67
+ * @since 4.8.1
68
+ */
69
+ const ALERT = 550;
70
+
71
+ /**
72
+ * Urgent alert.
73
+ *
74
+ * @since 4.8.1
75
+ */
76
+ const EMERGENCY = 600;
77
+
78
+ /**
79
+ * Logging levels from syslog protocol defined in RFC 5424
80
+ *
81
+ * @since 4.8.1
82
+ * @var array $levels Logging levels
83
+ */
84
+ protected static $_levels = array(
85
+ self::DEBUG => 'DEBUG',
86
+ self::INFO => 'INFO',
87
+ self::NOTICE => 'NOTICE',
88
+ self::WARNING => 'WARNING',
89
+ self::ERROR => 'ERROR',
90
+ self::CRITICAL => 'CRITICAL',
91
+ self::ALERT => 'ALERT',
92
+ self::EMERGENCY => 'EMERGENCY',
93
+ );
94
+
95
+ /**
96
+ * @since 4.8.1
97
+ */
98
+ protected function _construct()
99
+ {
100
+ if (!$this->hasName()) {
101
+ $this->setName('default');
102
+ }
103
+
104
+ parent::_construct();
105
+ }
106
+
107
+ /**
108
+ * Add a log entry.
109
+ *
110
+ * @since 4.8.1
111
+ * @param int $level The level of the log entry. See {@link LoggerAbstract::getLevels()}.
112
+ * @param string $message The message of the entry. Something that can be converted to string.
113
+ * @param array $context The context of the entry. Additional data about the environment.
114
+ * @return LoggerAbstract This instance.
115
+ */
116
+ public function addRecord($level, $message, array $context = array())
117
+ {
118
+ $this->_addRecord($level, $message, $context);
119
+ return $this;
120
+ }
121
+
122
+ /**
123
+ * Add a log entry.
124
+ *
125
+ * @since 4.8.1
126
+ * @param int $level The level of the log entry. See {@link LoggerAbstract::getLevels()}.
127
+ * @param string $message The message of the entry. Something that can be converted to string.
128
+ * @param array $context The context of the entry. Additional data about the environment.
129
+ * @return LoggerAbstract This instance.
130
+ */
131
+ protected function _addRecord($level, $message, array $context = array())
132
+ {
133
+ if (!$this->shouldAddRecord($level, $message, $context)) {
134
+ return false;
135
+ }
136
+
137
+ $levelName = static::getLevelName($level);
138
+ $date = date('Y-m-d H:i:s');
139
+ // $format = '[%datetime%] %channel%.%level_name%: %message% %context% %extra%'; // Default format
140
+ $format = '[%1$s] %2$s.%3$s (%5$s): '."\n".'%4$s'."\n";
141
+ $str = sprintf($format, $date, // Date
142
+ $this->getName(), // Channel
143
+ $levelName, // Level Name
144
+ $message, // Message
145
+ isset($context['source']) ? $context['source'] : '' // Context
146
+ );
147
+
148
+ if (!($path = $this->getLogFilePath())) {
149
+ throw $this->exception('Could not add log record: Log path must be set');
150
+ }
151
+ file_put_contents($path, $str, FILE_APPEND);
152
+ }
153
+
154
+ /**
155
+ * Gets the name of the logging level.
156
+ *
157
+ * @since 4.8.1
158
+ * @param int $level
159
+ * @return string
160
+ */
161
+ public static function getLevelName($level)
162
+ {
163
+ if (!isset(static::$_levels[$level])) {
164
+ throw new \InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ',
165
+ array_keys(static::$levels)));
166
+ }
167
+ return static::$_levels[$level];
168
+ }
169
+
170
+ /**
171
+ * Get the value of the log level.
172
+ *
173
+ * @since 4.8.1
174
+ * @param string $logLevel The string representation of the log level, case-insensitive.
175
+ * @return int The numeric representation of the log level.
176
+ */
177
+ public static function getLogLevelValue($logLevel)
178
+ {
179
+ $constName = static::WPRSS_LOG_LEVEL_PREFIX.strtoupper($logLevel);
180
+ return defined($constName) ? constant($constName) : null;
181
+ }
182
+
183
+ /**
184
+ * All levels available.
185
+ *
186
+ * @since 4.8.1
187
+ * @return array An array of all levels of this logger, where keys are numeric
188
+ * level values, and values are their string representations.
189
+ */
190
+ public static function getLevels()
191
+ {
192
+ return array_flip(static::$_levels);
193
+ }
194
+
195
+ /**
196
+ * Converts PSR-3 levels to Monolog ones if necessary
197
+ *
198
+ * @since 4.8.1
199
+ * @param string|int Level number (monolog) or name (PSR-3)
200
+ * @return int
201
+ */
202
+ public static function toMonologLevel($level)
203
+ {
204
+ if (is_string($level)) {
205
+
206
+ if (defined(get_called_class().'::'.strtoupper($level))) {
207
+ return constant(get_called_class().'::'.strtoupper($level));
208
+ }
209
+ throw new \InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ',
210
+ array_keys(static::$levels)));
211
+ }
212
+ return $level;
213
+ }
214
+
215
+ /**
216
+ * Adds a log record at an arbitrary level.
217
+ *
218
+ * This method allows for compatibility with common interfaces.
219
+ *
220
+ * @since 4.8.1
221
+ * @param mixed $level The log level
222
+ * @param string $message The log message
223
+ * @param array $context The log context
224
+ * @return bool Whether the record has been processed
225
+ */
226
+ public function log($level, $message, array $context = array())
227
+ {
228
+ $level = static::toMonologLevel($level);
229
+ return $this->addRecord($level, (string) $message, $context);
230
+ }
231
+
232
+ /**
233
+ * Adds a log record at the DEBUG level.
234
+ *
235
+ * This method allows for compatibility with common interfaces.
236
+ *
237
+ * @since 4.8.1
238
+ * @param string $message The log message
239
+ * @param array $context The log context
240
+ * @return bool Whether the record has been processed
241
+ */
242
+ public function debug($message, array $context = array())
243
+ {
244
+ return $this->addRecord(static::DEBUG, (string) $message, $context);
245
+ }
246
+
247
+ /**
248
+ * Adds a log record at the INFO level.
249
+ *
250
+ * This method allows for compatibility with common interfaces.
251
+ *
252
+ * @since 4.8.1
253
+ * @param string $message The log message
254
+ * @param array $context The log context
255
+ * @return bool Whether the record has been processed
256
+ */
257
+ public function info($message, array $context = array())
258
+ {
259
+ return $this->addRecord(static::INFO, (string) $message, $context);
260
+ }
261
+
262
+ /**
263
+ * Adds a log record at the NOTICE level.
264
+ *
265
+ * This method allows for compatibility with common interfaces.
266
+ *
267
+ * @since 4.8.1
268
+ * @param string $message The log message
269
+ * @param array $context The log context
270
+ * @return bool Whether the record has been processed
271
+ */
272
+ public function notice($message, array $context = array())
273
+ {
274
+ return $this->addRecord(static::NOTICE, (string) $message, $context);
275
+ }
276
+
277
+ /**
278
+ * Adds a log record at the WARNING level.
279
+ *
280
+ * This method allows for compatibility with common interfaces.
281
+ *
282
+ * @since 4.8.1
283
+ * @param string $message The log message
284
+ * @param array $context The log context
285
+ * @return bool Whether the record has been processed
286
+ */
287
+ public function warning($message, array $context = array())
288
+ {
289
+ return $this->addRecord(static::WARNING, (string) $message, $context);
290
+ }
291
+
292
+ /**
293
+ * Adds a log record at the ERROR level.
294
+ *
295
+ * This method allows for compatibility with common interfaces.
296
+ *
297
+ * @since 4.8.1
298
+ * @param string $message The log message
299
+ * @param array $context The log context
300
+ * @return bool Whether the record has been processed
301
+ */
302
+ public function error($message, array $context = array())
303
+ {
304
+ return $this->addRecord(static::ERROR, (string) $message, $context);
305
+ }
306
+
307
+ /**
308
+ * Adds a log record at the CRITICAL level.
309
+ *
310
+ * This method allows for compatibility with common interfaces.
311
+ *
312
+ * @since 4.8.1
313
+ * @param string $message The log message
314
+ * @param array $context The log context
315
+ * @return bool Whether the record has been processed
316
+ */
317
+ public function critical($message, array $context = array())
318
+ {
319
+ return $this->addRecord(static::CRITICAL, (string) $message, $context);
320
+ }
321
+
322
+ /**
323
+ * Adds a log record at the ALERT level.
324
+ *
325
+ * This method allows for compatibility with common interfaces.
326
+ *
327
+ * @since 4.8.1
328
+ * @param string $message The log message
329
+ * @param array $context The log context
330
+ * @return bool Whether the record has been processed
331
+ */
332
+ public function alert($message, array $context = array())
333
+ {
334
+ return $this->addRecord(static::ALERT, (string) $message, $context);
335
+ }
336
+
337
+ /**
338
+ * Adds a log record at the EMERGENCY level.
339
+ *
340
+ * This method allows for compatibility with common interfaces.
341
+ *
342
+ * @since 4.8.1
343
+ * @param string $message The log message
344
+ * @param array $context The log context
345
+ * @return bool Whether the record has been processed
346
+ */
347
+ public function emergency($message, array $context = array())
348
+ {
349
+ return $this->addRecord(static::EMERGENCY, (string) $message, $context);
350
+ }
351
+
352
+ /**
353
+ * Whether or not to add the record described by specified arguments.
354
+ *
355
+ * @since 4.8.1
356
+ * @param mixed $level The log level
357
+ * @param string $message The log message
358
+ * @param array $context The log context
359
+ */
360
+ public function shouldAddRecord($level, $message, array $context = array())
361
+ {
362
+ return true;
363
+ }
364
+ }
includes/Aventura/Wprss/Core/Model/LoggerInterface.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ /**
6
+ * This is actually taken from here:
7
+ * https://github.com/php-fig/log/blob/master/Psr/Log/LoggerInterface.php
8
+ *
9
+ * This is done for forward-compatibility with monolog/monolog, or any other PSR-compatible logger.
10
+ *
11
+ * @todo When possible, declare Psr\Log as a dependency. Consider using monolog/monolog.
12
+ * @since 4.8.1
13
+ */
14
+ interface LoggerInterface
15
+ {
16
+
17
+ /**
18
+ * System is unusable.
19
+ *
20
+ * @param string $message
21
+ * @param array $context
22
+ *
23
+ * @return null
24
+ */
25
+ public function emergency($message, array $context = array());
26
+
27
+ /**
28
+ * Action must be taken immediately.
29
+ *
30
+ * Example: Entire website down, database unavailable, etc. This should
31
+ * trigger the SMS alerts and wake you up.
32
+ *
33
+ * @param string $message
34
+ * @param array $context
35
+ *
36
+ * @return null
37
+ */
38
+ public function alert($message, array $context = array());
39
+
40
+ /**
41
+ * Critical conditions.
42
+ *
43
+ * Example: Application component unavailable, unexpected exception.
44
+ *
45
+ * @param string $message
46
+ * @param array $context
47
+ *
48
+ * @return null
49
+ */
50
+ public function critical($message, array $context = array());
51
+
52
+ /**
53
+ * Runtime errors that do not require immediate action but should typically
54
+ * be logged and monitored.
55
+ *
56
+ * @param string $message
57
+ * @param array $context
58
+ *
59
+ * @return null
60
+ */
61
+ public function error($message, array $context = array());
62
+
63
+ /**
64
+ * Exceptional occurrences that are not errors.
65
+ *
66
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
67
+ * that are not necessarily wrong.
68
+ *
69
+ * @param string $message
70
+ * @param array $context
71
+ *
72
+ * @return null
73
+ */
74
+ public function warning($message, array $context = array());
75
+
76
+ /**
77
+ * Normal but significant events.
78
+ *
79
+ * @param string $message
80
+ * @param array $context
81
+ *
82
+ * @return null
83
+ */
84
+ public function notice($message, array $context = array());
85
+
86
+ /**
87
+ * Interesting events.
88
+ *
89
+ * Example: User logs in, SQL logs.
90
+ *
91
+ * @param string $message
92
+ * @param array $context
93
+ *
94
+ * @return null
95
+ */
96
+ public function info($message, array $context = array());
97
+
98
+ /**
99
+ * Detailed debug information.
100
+ *
101
+ * @param string $message
102
+ * @param array $context
103
+ *
104
+ * @return null
105
+ */
106
+ public function debug($message, array $context = array());
107
+
108
+ /**
109
+ * Logs with an arbitrary level.
110
+ *
111
+ * @param mixed $level
112
+ * @param string $message
113
+ * @param array $context
114
+ *
115
+ * @return null
116
+ */
117
+ public function log($level, $message, array $context = array());
118
+ }
includes/Aventura/Wprss/Core/Model/ModelAbstract.php ADDED
@@ -0,0 +1,362 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * @since 4.8.1
9
+ */
10
+ abstract class ModelAbstract extends Core\DataObject implements ModelInterface
11
+ {
12
+ const PREFIX_OVERRIDE = '!';
13
+
14
+ /**
15
+ * @since 4.8.1
16
+ */
17
+ protected function _construct()
18
+ {
19
+ // Default depth
20
+ if (!$this->hasBaseNamespaceDepth()) {
21
+ $this->setBaseNamespaceDepth(3);
22
+ }
23
+ parent::_construct();
24
+ }
25
+
26
+ /**
27
+ * Translates a string of text.
28
+ *
29
+ * If text is an array, it will be used as an array to a format function,
30
+ * such as {@see sprintf()}.
31
+ * Formatting always takes place after translation; only the first element
32
+ * of the text array will be translated.
33
+ * If the text is a scalar value other than string, it will be returned unmodified.
34
+ *
35
+ * @since 4.8.1
36
+ * @param string|array $text The text to translate, or an array of arguments to a format function.
37
+ * @param string|mixed $translator A translator instance or some kind of identifier.
38
+ * @return string Translated string.
39
+ * @throws \InvalidArgumentException If trying to translate an untranslatable value.
40
+ */
41
+ public function __($text, $translator = null)
42
+ {
43
+ // Allowing array to designate message formatting
44
+ $args = (array)$text;
45
+ $text = array_shift($args);
46
+ $isString = is_string($text);
47
+ $isScalar = is_scalar($text);
48
+ $canStringify = $isString || $isScalar;
49
+
50
+ if (!$canStringify) {
51
+ throw new \InvalidArgumentException('Could not process text: Text must be a string, or at least of a scalar type');
52
+ }
53
+
54
+ $text = (string)$text;
55
+ if (!$isString) {
56
+ return $text;
57
+ }
58
+
59
+ // Allowing to skip message translation
60
+ if ($translator !== false) {
61
+ $text = $this->_translate($text, $translator);
62
+ }
63
+
64
+ array_unshift($args, $text);
65
+
66
+ if (count($args) > 1) {
67
+ // Formatting message
68
+ $result = call_user_func_array('sprintf', $args);
69
+
70
+ // Detecting format error
71
+ if (!strlen($result) && strlen($text)) {
72
+ error_log($text);
73
+ throw new \InvalidArgumentException(sprintf('Could not process text: It seems there was an error with formatting, '
74
+ .'perhaps wrong parameter count (string should contain %1$d).', count($args) - 1));
75
+ }
76
+ }
77
+ else {
78
+ $result = $args[0];
79
+ }
80
+
81
+
82
+ return $result;
83
+ }
84
+
85
+ /**
86
+ * Translates a string.
87
+ *
88
+ * @since 4.8.1
89
+ * @param string $text The text to translate.
90
+ * @param string|mixed $translator A translator instance or some kind of identifier.
91
+ * @return string Translated string.
92
+ */
93
+ protected function _translate($text, $translator = null) {
94
+ return $text;
95
+ }
96
+
97
+ /**
98
+ * Get the namespace of this or other class
99
+ *
100
+ * @since 4.8.1
101
+ * @see wprss_get_namespace()
102
+ * @param int|null $depth The depth of the namespace to retrieve.
103
+ * If omitted, the whole namespace will be retrieved.
104
+ * @param string|object|null $class The class name or instance, for which to get the namespace.
105
+ * If omitted, the current class will be used.
106
+ * @param bool $asString If true, the result will be a string; otherwise, array with namespace parts.
107
+ * @return array|string The namespace of the class.
108
+ */
109
+ public static function getNamespace($depth = null, $class = null,
110
+ $asString = false)
111
+ {
112
+ // Default to this class
113
+ if (is_null($class)) {
114
+ $className = trim(get_called_class(), $ns);
115
+ }
116
+ return wprss_get_namespace($class, $depth, $asString);
117
+ }
118
+
119
+ /**
120
+ * Check if a namespace is a root namespace.
121
+ *
122
+ * @since 4.8.1
123
+ * @see wprss_is_root_namespace()
124
+ * @param string $namespace The namespace to check.
125
+ * @param bool $isCheckClass If true, and a class or interface with the name of the specified namespace exists,
126
+ * will make this function return true. Otherwise, the result depends purely on the namespace string.
127
+ * @return boolean True if the namespace is a root namespace; false otherwise.
128
+ */
129
+ public static function isRootNamespace($namespace, $isCheckClass = true)
130
+ {
131
+ return wprss_is_root_namespace($namespace, $isCheckClass);
132
+ }
133
+
134
+ /**
135
+ * Get the base namespace of this plugin.
136
+ *
137
+ * At least most of the classes in a plugin will be relative to that plugin's namespace.
138
+ * The default namespace is the namespace of this class, of an optional depth which is determined by
139
+ * {@see getBaseNamespaceDepth()}.
140
+ *
141
+ * @since 4.8.1
142
+ * @return string The base namespace of this plugin.
143
+ */
144
+ public function getBaseNamespace()
145
+ {
146
+ if ($namespace = $this->getData('base_namespace')) {
147
+ return $namespace;
148
+ }
149
+
150
+ // Fall back to auto namespace
151
+ return static::getNamespace($this->getBaseNamespaceDepth(), $this, true);
152
+ }
153
+
154
+ /**
155
+ * Creates an exception instance.
156
+ *
157
+ * @since 4.8.1
158
+ * @param string|array $text The text to translate.
159
+ * If array, then the result will be formatted with `sprintf()`, using
160
+ * the first argument as the format string, and any that follow as arguments.
161
+ * @param string $className The name of the exception's class.
162
+ * If it doesn't start with a backslash '\', will be treated as relative to
163
+ * the plugin base namespace.
164
+ * Defaults to 'Exception', which results in class [base_namespace]\Exception.
165
+ * {@see getExceptionClassName()}
166
+ * @param string|bool|null $translate The text domain to use for translation.
167
+ * If false, no translation will be made.
168
+ * Defaults to the current plugin's text domain.
169
+ * {@see __()}
170
+ * @return \Exception The new exception instance.
171
+ * @throws Aventura\Wprss\SpinnerChief\Plugin\Exception If the exception class does not exist.
172
+ */
173
+ public function exception($text, $className = null, $translate = null)
174
+ {
175
+ $text = $this->__($text, $translate);
176
+ $className = $this->getExceptionClassName($className);
177
+ if (!class_exists($className)) {
178
+ throw new Exception(sprintf('Could not create exception: Class "%1$s" does not exist'));
179
+ }
180
+
181
+ $exception = new $className($text);
182
+ return $exception;
183
+ }
184
+
185
+ /**
186
+ * Get a class name of an exception.
187
+ *
188
+ * This will be based on its absolute or relative class name, or potentially
189
+ * any other identifier that could be mapped to a class name.
190
+ *
191
+ * @since 4.8.1
192
+ * @see getExceptionClassRoot()
193
+ * @param string|array $className A name of the exception class, or array with namespace parts.
194
+ * If array, assumed to be root namespace.
195
+ * @return string The fully qualified name of the exception class.
196
+ */
197
+ public function getExceptionClassName($className = null)
198
+ {
199
+ $defaultClassName = 'Exception';
200
+ // Defaults to this namespace's root exception
201
+ if (is_null($className)) {
202
+ $className = $defaultClassName;
203
+ }
204
+
205
+ // Namespace specified as array of parts; assume root namespace
206
+ if (is_array($className)) {
207
+ $className = '\\' . trim(implode('\\', $className), '\\');
208
+ }
209
+
210
+ // Allowing explicit class name
211
+ if (static::isRootNamespace($className, $className !== $defaultClassName)) {
212
+ return $className;
213
+ }
214
+
215
+ // Relative to this class's root
216
+ $rootNamespace = $this->getExceptionClassRoot();
217
+ return sprintf('%1$s\\%2$s', $rootNamespace, $className);
218
+ }
219
+
220
+ /**
221
+ * Get the root namespace for exception classes.
222
+ *
223
+ * Unless altered, {@see getExceptionClassName} will process class names
224
+ * relative to the value returned by this method.
225
+ *
226
+ * @since 4.8.1
227
+ * @return string The root namespace of exception class names.
228
+ */
229
+ public function getExceptionClassRoot()
230
+ {
231
+ $key = 'exception_class_root';
232
+ if (!$this->hasData($key)) {
233
+ $this->setData($key, $this->getBaseNamespace());
234
+ }
235
+
236
+ return $this->getData($key);
237
+ }
238
+
239
+ /**
240
+ *
241
+ * @since 4.8.1
242
+ * @param string $string The string to check.
243
+ * @return bool True if the string had a prefix override, and it was removed;
244
+ * false otherwise;
245
+ */
246
+ public static function stringHadPrefix(&$string)
247
+ {
248
+ return string_had_prefix($string, static::PREFIX_OVERRIDE);
249
+ }
250
+
251
+ public static function classImplements($class, $interface = null, $autoload = true)
252
+ {
253
+ $interfaces = class_implements($class, $autoload);
254
+ if (is_null($interface)) {
255
+ return $interfaces;
256
+ }
257
+
258
+ return in_array($interface, $interfaces);
259
+ }
260
+
261
+ /**
262
+ * Gets the data member with the specified key, or a corresponding constant if that key is not defined.
263
+ *
264
+ * Useful for accessing data, the default value of which was defined as a class constants.
265
+ *
266
+ * @since 4.8.1
267
+ * @param string $key The data key to get.
268
+ * @param mixed|null $default What to return if neither the data key or the constant are defined.
269
+ * @return mixed|null The value of the data key or constant.
270
+ */
271
+ protected function _getDataOrConst($key, $default = null)
272
+ {
273
+ if ($this->hasData($key)) {
274
+ return $this->getData();
275
+ }
276
+
277
+ $const = $this->constant($key);
278
+ return empty($const)
279
+ ? $default
280
+ : $const;
281
+ }
282
+
283
+ /**
284
+ * Gets the value of a constant with the specified name from this object's class.
285
+ *
286
+ * @since 4.8.1
287
+ * @param string $key The key of the constant, which corresponds to it's name.
288
+ * @param mixed|null $default What to return if the constant with the specified key is not defined.
289
+ * @param bool $toUpper Whether or not to convert the key to uppercase.
290
+ * @return int|string|null The value of the constant, or `null` if no such constant defined.
291
+ */
292
+ public function constant($key, $default = null, $toUpper = true)
293
+ {
294
+ if ($toUpper) {
295
+ $key = strtoupper($key);
296
+ }
297
+
298
+ $constName = sprintf('%1$s::%2$s', get_class($this), $key);
299
+ return defined($constName)
300
+ ? constant($constName)
301
+ : $default;
302
+ }
303
+
304
+ public function log($level, $message, array $context = array())
305
+ {
306
+ return false;
307
+ }
308
+
309
+ /**
310
+ * Get this instance's event prefix, or a prefixed event name.
311
+ *
312
+ * An event prefix is a prefix that will by default be added to names of events
313
+ * that are listened to or raised by this instance.
314
+ *
315
+ * The event prefix is by default the plugin code followed by an underscore "_", unless the code is
316
+ * not set, in which case the prefix is empty.
317
+ *
318
+ * Override with setEventPrefix().
319
+ *
320
+ * @since 4.8.1
321
+ * @param string|null $name An event name to prefix.
322
+ * @return string This instance's event prefix, or a prefixed name.
323
+ */
324
+ public function getEventPrefix($name = null)
325
+ {
326
+ $prefix = $this->_getEventPrefix();
327
+ return static::stringHadPrefix($name)
328
+ ? $name
329
+ : "{$prefix}{$name}";
330
+ }
331
+
332
+ /**
333
+ * Get the actual event prefix, only.
334
+ *
335
+ * @since 4.8.1
336
+ * @return string
337
+ */
338
+ protected function _getEventPrefix()
339
+ {
340
+ return $this->getData('event_prefix');
341
+ }
342
+
343
+ /**
344
+ * {@inheritdoc}
345
+ *
346
+ * @since 4.8.1
347
+ */
348
+ public function on($name, $listener, $data = null, $priority = null, $acceptedArgs = null)
349
+ {
350
+ return false;
351
+ }
352
+
353
+ /**
354
+ * {@inheritdoc}
355
+ *
356
+ * @since 4.8.1
357
+ */
358
+ public function event($name, $data = array())
359
+ {
360
+ return null;
361
+ }
362
+ }
includes/Aventura/Wprss/Core/Model/ModelInterface.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ /**
6
+ * Anything that can be a model.
7
+ *
8
+ * A model is something that solves a particular problem, e.g. represents a problem domain.
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ interface ModelInterface
13
+ {
14
+ /**
15
+ *
16
+ * @param string $text The text to translate.
17
+ * @param mixed $translator Something that determines how to translate the text.
18
+ */
19
+ public function __($text, $translator = null);
20
+
21
+ /**
22
+ * Logs a message
23
+ *
24
+ * @since 4.8.1
25
+ * @see LoggerAbstract
26
+ * @return bool True if log entry was processed; false otherwise.
27
+ */
28
+ public function log($level, $message, array $context = array());
29
+
30
+ /**
31
+ * Add an event listener.
32
+ *
33
+ * @since 4.8.1
34
+ * @param string $name Event name.
35
+ * @param callable $listener The event listener.
36
+ * @param null|array $data Additional data to be passed to event handlers. May not work on native system events.
37
+ * If the event gets passed data with same names when raised, they will override data passed here.
38
+ * @param int|null $priority Order priority of the listener. If null, implementation-specific default will be assumed.
39
+ * @param int|null $acceptedArgs The number of arguments to be passed to the handler. If null,
40
+ * implementation-specific default will be assumed.
41
+ * @return string|bool The eventual name of the event that was used on success; false if listener not registered.
42
+ */
43
+ public function on($name, $listener, $data = null, $priority = null, $acceptedArgs = null);
44
+
45
+ /**
46
+ * Raise an event.
47
+ *
48
+ * This triggers all event handlers.
49
+ *
50
+ * @since 4.8.1
51
+ * @param string $name Name of the event to raise
52
+ * @param array $data The data to pass to the event handlers. This will be passed as the first and only argument.
53
+ * If additional data members were passed with {@see ModelInterface::on()}, members passed here will override.
54
+ * @return Core\Model\Event\EventInterface
55
+ */
56
+ public function event($name, $data = array());
57
+
58
+ /**
59
+ * Get this instance's event prefix, or a prefixed event name.
60
+ *
61
+ * An event prefix is a prefix that will by default be added to names of events
62
+ * that are listened to or raised by this instance.
63
+ *
64
+ * The event prefix is by default the plugin code followed by an underscore "_", unless the code is
65
+ * not set, in which case the prefix is empty.
66
+ *
67
+ * @since 4.8.1
68
+ * @param string|null $name An event name to prefix.
69
+ * @return string This instance's event prefix, or a prefixed name.
70
+ */
71
+ public function getEventPrefix($name = null);
72
+ }
includes/Aventura/Wprss/Core/Model/SettingsAbstract.php ADDED
@@ -0,0 +1,862 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * Common functionality for objects that handle settings.
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ abstract class SettingsAbstract extends Core\Plugin\ComponentAbstract implements SettingsInterface
13
+ {
14
+ const MAIN_OPTION_NAME = '';
15
+ const TRUE_VALUE = '1';
16
+ const FALSE_VALUE = '0';
17
+
18
+ protected $_sectionsFields;
19
+ protected $_fieldRenderers;
20
+ protected $_defaultValues;
21
+
22
+ protected $_isValuesLoaded;
23
+ // Purely to avoid recursion during values loading
24
+ protected $_isValuesLoading;
25
+
26
+ /**
27
+ * Gets the name of the main option, where the settings are stored.
28
+ *
29
+ * The settings are stored as a serialized array.
30
+ * The name defaults to '_settings', prefixed with the plugin code.
31
+ *
32
+ * @since 4.8.1
33
+ * @return string The name of the main option in the database.
34
+ */
35
+ public function getMainOptionName()
36
+ {
37
+ return $this->_getDataOrConst('main_option_name',
38
+ sprintf('%1$s_settings', $this->getPluginCode()));
39
+ }
40
+
41
+ /**
42
+ * Get the slug of the settings subpage or tab.
43
+ *
44
+ * @since 4.8.1
45
+ * @return string The slug
46
+ */
47
+ public function getTabSlug()
48
+ {
49
+ return $this->_getDataOrConst('tab_slug', $this->getMainOptionName());
50
+ }
51
+
52
+ /**
53
+ * Get the values from the database.
54
+ *
55
+ * No cache used here.
56
+ *
57
+ * @since 4.8.1
58
+ * @return array The array of settings as retrieved from the database.
59
+ */
60
+ public function getValuesDb()
61
+ {
62
+ $default = array();
63
+ $option = static::getOption($this->getMainOptionName(), $default);
64
+ if (is_string($option)) {
65
+ $option = $default;
66
+ }
67
+
68
+ return $option;
69
+ }
70
+
71
+ /**
72
+ * Gets the default values for settings.
73
+ *
74
+ * The load will only be performed once, fildered with a prefixed `settings_defaults` hook,
75
+ * and then cached.
76
+ *
77
+ * @since 4.8.1
78
+ * @return array An array of default values, where keys correspond to the setting IDs.
79
+ */
80
+ public function getDefaultValues()
81
+ {
82
+ if (is_null($this->_defaultValues)) {
83
+ $this->_defaultValues = $this->event('settings_defaults', array('values' => $this->_getDefaultValues()))
84
+ ->getValues();
85
+ }
86
+
87
+ return $this->_defaultValues;
88
+ }
89
+
90
+ /**
91
+ * Gets the default values for settings.
92
+ *
93
+ * @since 4.8.1
94
+ * @return array A raw array of default values. Keys should correspond to setting IDs.
95
+ */
96
+ abstract protected function _getDefaultValues();
97
+
98
+ /**
99
+ * Loads the values from the database.
100
+ *
101
+ * @since 4.8.1
102
+ * @return array The loaded values.
103
+ */
104
+ protected function _loadValues()
105
+ {
106
+ $this->_isValuesLoading = true;
107
+ $dbValues = $this->getValuesDb();
108
+ $defaults = $this->getDefaultValues();
109
+ $options = array_merge_recursive_distinct($defaults, $dbValues);
110
+ foreach ($options as $key => $value) {
111
+ $this->setDataUsingMethod($key, $value);
112
+ }
113
+
114
+ $this->_isValuesLoaded = true;
115
+ $this->_isValuesLoading = false;
116
+ return $this;
117
+ }
118
+
119
+ /**
120
+ * Whether or not the setting values have been loaded.
121
+ *
122
+ * @since 4.8.1
123
+ * @return bool True if values have been loaded; false otherwise.
124
+ */
125
+ public function isValuesLoaded()
126
+ {
127
+ return (bool)$this->_isValuesLoaded;
128
+ }
129
+
130
+ /**
131
+ * Whether or not values are currently loading.
132
+ *
133
+ * This is needed to avoid recursion while loading values.
134
+ *
135
+ * @since 4.8.1
136
+ * @return bool True if the values are currently loading; false otherwise.
137
+ */
138
+ protected function _isValuesLoading()
139
+ {
140
+ return (bool)$this->_isValuesLoading;
141
+ }
142
+
143
+ /**
144
+ * {@inheritdoc}
145
+ *
146
+ * @since 4.8.1
147
+ * @param type $key
148
+ * @param type $index
149
+ * @return type
150
+ */
151
+ public function getData($key = '', $index = null)
152
+ {
153
+ if (!$this->isValuesLoaded() && !$this->_isValuesLoading()) {
154
+ $this->_loadValues();
155
+ }
156
+
157
+ return parent::getData($key, $index);
158
+ }
159
+
160
+ /**
161
+ * Gets the data for a settings tab.
162
+ *
163
+ * @since 4.8.1
164
+ * @return array Data for the settings tab.
165
+ */
166
+ public function getTabData()
167
+ {
168
+ return array(
169
+ 'label' => $this->getPlugin()->getName(),
170
+ 'slug' => $this->getTabSlug()
171
+ );
172
+ }
173
+
174
+
175
+ /**
176
+ * A hook handler, typically intended for `wprss_options_tabs`.
177
+ *
178
+ * Adds the data about this settings page's tab to the list of tabs.
179
+ *
180
+ * @since 4.8.1
181
+ * @param array $tabs An array of registered tabs.
182
+ * @return array The array of registered tabs, now also containing an entry for this addon's tab.
183
+ */
184
+ public function addTab($tabs)
185
+ {
186
+ $tabs[$this->getPluginCode()] = $this->getTabData();
187
+ return $tabs;
188
+ }
189
+
190
+ /**
191
+ * Does the registration of the main setting.
192
+ *
193
+ * @since 4.8.1
194
+ * @return SettingsAbstract
195
+ */
196
+ protected function _registerSetting()
197
+ {
198
+ $optionName = $this->getMainOptionName();
199
+ register_setting(
200
+ $optionName, // Settings group name
201
+ $optionName, // Name of setting to save in db and sanitize
202
+ array($this, 'validate') // Validation callback
203
+ );
204
+
205
+ return $this;
206
+ }
207
+
208
+ /**
209
+ * Registeres a section and its settings.
210
+ *
211
+ * @since 4.8.1
212
+ * @param array|Core\DataObjectInterface $section Section data.
213
+ * Should contain information about the section, as well as the array of fields in the 'fields' index.
214
+ */
215
+ protected function _registerSection($section)
216
+ {
217
+ $fields = null;
218
+ if ($section instanceof Core\DataObjectInterface) {
219
+ $fields = $section->getFields();
220
+ $section = $section->getData();
221
+ }
222
+
223
+ add_settings_section(
224
+ $this->getSectionId($section['id']),
225
+ $section['label'],
226
+ $this->createCommand(array($this, '_renderSectionHeader'), array($section)),
227
+ $this->getMainOptionName()
228
+ );
229
+
230
+ if (is_null($fields) && isset($section['fields'])) {
231
+ $fields = $section['fields'];
232
+ }
233
+
234
+ if (!is_array($fields)) {
235
+ $fields = array();
236
+ }
237
+
238
+ foreach ($fields as $_fieldId => $_field) {
239
+ if (!is_array($_field)) {
240
+ $_field = array('label' => $_field);
241
+ }
242
+ $_field['id'] = $_fieldId;
243
+ $_field['section_id'] = $section['id'];
244
+ $this->_registerField($_field);
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Registers a single field.
250
+ *
251
+ * @since 4.8.1
252
+ * @param array|Core\DataObjectInterface $field Data of a field.
253
+ */
254
+ protected function _registerField($field)
255
+ {
256
+ if ($field instanceof Core\DataObjectInterface) {
257
+ $field = $field->getData();
258
+ }
259
+
260
+ /**
261
+ * @var This will be passed to the field callback as the only argument
262
+ * @see http://codex.wordpress.org/Function_Reference/add_settings_field#Parameters
263
+ */
264
+ $callbackArgs = $field;
265
+ if (!isset($callbackArgs['label'])) {
266
+ $callbackArgs['label'] = null;
267
+ }
268
+ if (!isset($callbackArgs['tooltip'])) {
269
+ $callbackArgs['tooltip'] = null;
270
+ }
271
+ if (!isset($callbackArgs['value'])) {
272
+ $callbackArgs['value'] = $this->createLocalDataSource($field['id']);
273
+ }
274
+
275
+ add_settings_field(
276
+ $this->getIdPrefix($field['id']),
277
+ $field['label'],
278
+ array($this, 'renderField'),
279
+ $this->getMainOptionName(),
280
+ $this->getSectionId($field['section_id']),
281
+ $callbackArgs
282
+ );
283
+ }
284
+
285
+ /**
286
+ * Registers the settings page for these settings.
287
+ *
288
+ * @since 4.8.1
289
+ */
290
+ abstract protected function _registerSettingsPage();
291
+
292
+ /**
293
+ * Renders a header of a section.
294
+ *
295
+ * This is intended to be a callback for {@see add_settings_section()}.
296
+ *
297
+ * @since 4.8.1
298
+ * @param array $data Has 3 elmenets: 'id', 'title', 'callback'.
299
+ */
300
+ public function _renderSectionHeader($data)
301
+ {
302
+ echo isset($data['header'])
303
+ ? $this->resolveDataSource($data['header'])
304
+ : '';
305
+ }
306
+
307
+ /**
308
+ * Renders and outputs a field.
309
+ *
310
+ * @since 4.8.1
311
+ * @param array|Core\DataObjectInterface $field Data of a field.
312
+ */
313
+ public function renderField($field)
314
+ {
315
+ echo $this->getFieldHtml($field);
316
+ }
317
+
318
+ /**
319
+ * Renders and gets HTML of a field.
320
+ *
321
+ * The output will depend on the data of the field, and also on its 'type'.
322
+ *
323
+ * @since 4.8.1
324
+ * @see getFieldRenderers()
325
+ * @param array|Core\DataObjectInterface $field Data of a field.
326
+ * @return string The output of the rendered field.
327
+ * @throws \Aventura\Wprss\SpinnerChief\Exception If no renderer is defined for the field type.
328
+ */
329
+ public function getFieldHtml($field)
330
+ {
331
+ if ($field instanceof Core\DataObjectInterface) {
332
+ $field = $field->getData();
333
+ }
334
+
335
+ // Defaults
336
+ if (!isset($field['type'])) {
337
+ $field['type'] = 'text';
338
+ }
339
+ // Get actual data
340
+ if (isset($field['data'])) {
341
+ $field['data'] = $this->resolveDataSource($field['data']);
342
+ }
343
+ if (isset($field['value'])) {
344
+ $field['value'] = $this->resolveDataSource($field['value']);
345
+ }
346
+
347
+ // Choose rendering algo
348
+ if (!($renderer = $this->getFieldRenderers($field['type']))) {
349
+ throw $this->exception(array('Could not render field "%1$s": A renderer for field type "%1$s" must be defined', $field['id'], $field['type']));
350
+ }
351
+
352
+ return $this->resolveDataSource($renderer, array($field));
353
+ }
354
+
355
+ /**
356
+ * Gets one or all field type renderers.
357
+ *
358
+ * Essentially, a renderer is a callback that receives information about a field,
359
+ * and returns the output of that field rendered.
360
+ *
361
+ * The renderers will be loaded once, then filtered with a prefixed `settings_field_renderers` hook,
362
+ * and cached.
363
+ *
364
+ * @since 4.8.1
365
+ * @param string $type A type, for which to get the renderer.
366
+ * @return array|callable All field renderers available, or one renderer.
367
+ */
368
+ public function getFieldRenderers($type = null)
369
+ {
370
+ if (is_null($this->_fieldRenderers)) {
371
+ $this->_fieldRenderers = $this->event('settings_field_renderers', array('renderers' => $this->_getFieldRenderers()))
372
+ ->getRenderers();
373
+ }
374
+
375
+ if (is_null($type)) {
376
+ return $this->_fieldRenderers;
377
+ }
378
+
379
+ return isset($this->_fieldRenderers[$type])
380
+ ? $this->_fieldRenderers[$type]
381
+ : null;
382
+ }
383
+
384
+ /**
385
+ * Gets all available field renderers.
386
+ *
387
+ * Override this method to add more renderers to an instance from within itself.
388
+ *
389
+ * @since 4.8.1
390
+ * @return array An array of callables, each of which is a field renderer.
391
+ */
392
+ protected function _getFieldRenderers()
393
+ {
394
+ return array(
395
+ 'text' => $this->createCommand(array($this, 'renderTextField')),
396
+ 'checkbox' => $this->createCommand(array($this, 'renderCheckboxField')),
397
+ 'select' => $this->createCommand(array($this, 'renderSelectField')),
398
+ 'number' => $this->createCommand(array($this, 'renderNumberField')),
399
+ );
400
+ }
401
+
402
+ /**
403
+ * Renders a text field.
404
+ *
405
+ * Normally, the output would be an <input> element of type 'text'.
406
+ *
407
+ * @since 4.8.1
408
+ * @param array|Core\DataObjectInterface $field Data of a field.
409
+ * @return string The text field HTML.
410
+ */
411
+ public function renderTextField($field)
412
+ {
413
+ if ($field instanceof Core\DataObjectInterface) {
414
+ $field = $field->getData();
415
+ }
416
+
417
+ $id = $field['id'];
418
+ $htmlAttributes = array(
419
+ 'id' => $this->getIdPrefix($id),
420
+ 'name' => static::getNameHtml(array($this->getMainOptionName(), $id)),
421
+ );
422
+ $field = array_merge_recursive_distinct($field, $htmlAttributes);
423
+ return static::getTextHtml($field['value'], $field) .
424
+ $this->getPlugin()->getTooltips()->doTooltip($id);
425
+ }
426
+
427
+ /**
428
+ * Renders a number field.
429
+ *
430
+ * Normally, the output would be an <input> element of type 'number'.
431
+ *
432
+ * @since 4.8.1
433
+ * @param array|Core\DataObjectInterface $field Data of a field.
434
+ * @return string The number field HTML.
435
+ */
436
+ public function renderNumberField($field)
437
+ {
438
+ if ($field instanceof Core\DataObjectInterface) {
439
+ $field = $field->getData();
440
+ }
441
+
442
+ $id = $field['id'];
443
+ $htmlAttributes = array(
444
+ 'id' => $this->getIdPrefix($id),
445
+ 'name' => static::getNameHtml(array($this->getMainOptionName(), $id)),
446
+ );
447
+ $field = array_merge_recursive_distinct($field, $htmlAttributes);
448
+ return static::getNumberHtml($field['value'], $field) .
449
+ $this->getPlugin()->getTooltips()->doTooltip($id);
450
+ }
451
+
452
+ /**
453
+ * Renders a checkbox field.
454
+ *
455
+ * Normally, the output would be an <input> element of type 'checkbox'.
456
+ *
457
+ * @since 4.8.1
458
+ * @param array|Core\DataObjectInterface $field Data of a field.
459
+ * @return string The checkbox field HTML.
460
+ */
461
+ public function renderCheckboxField($field)
462
+ {
463
+ if ($field instanceof Core\DataObjectInterface) {
464
+ $field = $field->getData();
465
+ }
466
+
467
+ $id = $field['id'];
468
+ $trueValue = isset($field['true_value'])
469
+ ? $field['true_value']
470
+ : static::getTrueValue();
471
+ $falseValue = isset($field['false_value'])
472
+ ? $field['false_value']
473
+ : static::getFalseValue();
474
+ return static::getCheckboxHtml($field['value'], array(
475
+ 'id' => $this->getIdPrefix($id),
476
+ 'name' => static::getNameHtml(array($this->getMainOptionName(), $id)),
477
+ 'value' => $trueValue,
478
+ 'false_value' => $falseValue
479
+ )) .
480
+ $this->getPlugin()->getTooltips()->doTooltip($id);
481
+ }
482
+
483
+ /**
484
+ * Renders a checkbox field.
485
+ *
486
+ * Normally, the output would be an <select> element.
487
+ *
488
+ * @since 4.8.1
489
+ * @param array|Core\DataObjectInterface $field Data of a field.
490
+ * @return string The select field HTML.
491
+ */
492
+ public function renderSelectField($field)
493
+ {
494
+ if ($field instanceof Core\DataObjectInterface) {
495
+ $field = $field->getData();
496
+ }
497
+
498
+ $options = $field['data'];
499
+ $id = $field['id'];
500
+ return static::getSelectHtml( array_combine($options, $options), array(
501
+ 'id' => $this->getIdPrefix($id),
502
+ 'name' => static::getNameHtml(array($this->getMainOptionName(), $id)),
503
+ 'selected' => $field['value']
504
+ )) .
505
+ $this->getPlugin()->getTooltips()->doTooltip($id);
506
+ }
507
+
508
+
509
+ /**
510
+ * Add settings fields and sections
511
+ *
512
+ * @since 4.8.1
513
+ * @param string $activeTab The slug of the active wprss settings tab.
514
+ */
515
+ public function _renderSettingsPage($activeTab)
516
+ {
517
+ $optionName = $this->getMainOptionName();
518
+ if ($activeTab !== $this->getTabSlug()) return;
519
+ // Render all sections for this page
520
+ settings_fields($optionName);
521
+ do_settings_sections($optionName);
522
+ }
523
+
524
+ /**
525
+ * Gets the ID prefix, or a prefixed ID.
526
+ *
527
+ * IDs are something that can be used in HTML's "id" attributes, or
528
+ * other internal IDs.
529
+ *
530
+ * This can be set via the ID_PREFIX class constant, overridden with the 'id_prefix' data member,
531
+ * and defaults to the plugin code, followed by an underscore '_'.
532
+ *
533
+ * @since 4.8.1
534
+ * @param string|null $id An ID to prefix.
535
+ * @return string The prefix, or prefixed ID.
536
+ */
537
+ public function getIdPrefix($id = null)
538
+ {
539
+ $prefix = $this->_getDataOrConst('id_prefix', sprintf('%1$s_', $this->getPluginCode()));
540
+ return is_null($id)
541
+ ? $prefix
542
+ : "{$prefix}{$id}";
543
+ }
544
+
545
+
546
+ /**
547
+ * Gets the slug prefix, or a prefixed slug.
548
+ *
549
+ * Slugs are something that can be used in HTML's "class" or other attributes, or URLs.
550
+ *
551
+ * This can be set via the SLUG_PREFIX class constant, overridden with the 'slug_prefix' data member,
552
+ * and defaults to the plugin code, followed by a dash underscore '-'.
553
+ *
554
+ * @since 4.8.1
555
+ * @param string|null $id A slug to prefix.
556
+ * @return string The prefix, or prefixed slug.
557
+ */
558
+ public function getSlugPrefix($id = null)
559
+ {
560
+ $prefix = $this->_getDataOrConst('slug_prefix', sprintf('%1$s-', $this->getPluginCode()));
561
+ return is_null($id)
562
+ ? $prefix
563
+ : "{$prefix}{$id}";
564
+ }
565
+
566
+ /**
567
+ * Gets a section ID from a section code.
568
+ *
569
+ * A section code is something that uniquely identifies a section internally.
570
+ * A section ID, on the other hand, may contain other characters, and is typically
571
+ * used on the frontend.
572
+ *
573
+ * @since 4.8.1
574
+ * @param string $code The section code.
575
+ * @return string The section ID.
576
+ */
577
+ public function getSectionId($code)
578
+ {
579
+ $pluginCode = $this->getPluginCode();
580
+ return "settings_{$pluginCode}_{$code}_section";
581
+ }
582
+
583
+ /**
584
+ * Gets the code of the plugin.
585
+ *
586
+ * @since 4.8.1
587
+ * @see Core\Plugin\PluginInterface::getCode()
588
+ * @return string The plugin code.
589
+ */
590
+ public function getPluginCode()
591
+ {
592
+ return $this->getPlugin()->getCode();
593
+ }
594
+
595
+ /**
596
+ * Registers the settings section and fields.
597
+ *
598
+ * This should be hooked to something in WP.
599
+ *
600
+ * @since 4.8.1
601
+ */
602
+ public function register()
603
+ {
604
+ $this->_registerSetting();
605
+ $sections = $this->getSectionsFields();
606
+
607
+ foreach ($sections as $sectionId => $section) {
608
+ $section['id'] = $sectionId;
609
+ $this->_registerSection($section);
610
+ }
611
+
612
+ $this->_registerSettingsPage();
613
+ }
614
+
615
+ /**
616
+ * Retrieves all raw data for all sections.
617
+ *
618
+ * @since 4.8.1
619
+ * @return array All sections, together with their fields.
620
+ */
621
+ abstract protected function _getSectionsFields();
622
+
623
+ /**
624
+ * Retrieves all data for all sections, and their fields.
625
+ *
626
+ * This is done once, filtered with prefixed 'settings_fields', and cashed.
627
+ *
628
+ * @since 4.8.1
629
+ * @return array All sections, together with their fields.
630
+ */
631
+ public function getSectionsFields()
632
+ {
633
+ if (is_null($this->_sectionsFields)) {
634
+ $this->_sectionsFields = $this->event('settings_fields', array('sections' => $this->_getSectionsFields()))
635
+ ->getSections();
636
+ }
637
+
638
+ return $this->_sectionsFields;
639
+ }
640
+
641
+ /**
642
+ * A shortcut for creating callables to use as data sources.
643
+ *
644
+ * @since 4.8.1
645
+ * @param callable $callable The callback that the command represents.
646
+ * @param array $args The arguments for the callback.
647
+ * @return \Aventura\Wprss\Core\Model\CommandInterface A new command.
648
+ */
649
+ public function createCommand($callable, $args = array())
650
+ {
651
+ return new Command(array(
652
+ 'function' => $callable,
653
+ 'args' => $args
654
+ ));
655
+ }
656
+
657
+ /**
658
+ * Resolves a command by executing it, and returning the result.
659
+ *
660
+ * @since 4.8.1
661
+ * @param CommandInterface $command The command to resolve.
662
+ * @return mixed Result of the command.
663
+ * @throws \Aventura\Wprss\SpinnerChief\Exception
664
+ */
665
+ public function resolveCommand($command, $args = array())
666
+ {
667
+ if (!is_callable($command)) {
668
+ throw $this->exception('Cannot resolve command: Command must be callable');
669
+ }
670
+
671
+ return call_user_func_array($command, $args);
672
+ }
673
+
674
+ /**
675
+ * Retrieves the value of a datasource, or if not a datasource just returns it.
676
+ *
677
+ * @since 4.8.1
678
+ * @param callable $source The datasource.
679
+ * @param array $args Additional arguments for the datasource.
680
+ * @return mixed The resolved datasource value.
681
+ */
682
+ public function resolveDataSource($source, $args = array())
683
+ {
684
+ if (is_callable($source)) {
685
+ return $this->resolveCommand($source, $args);
686
+ }
687
+
688
+ return $source;
689
+ }
690
+
691
+ /**
692
+ * Cretes a datasource for retrieving data from this instance.
693
+ *
694
+ * @since 4.8.1
695
+ * @param string $key The key of the data member to retrieve.
696
+ * @return CommandInterface A command that retrieves data from this instance.
697
+ */
698
+ public function createLocalDataSource($key)
699
+ {
700
+ return $this->createCommand(array($this, 'getData'), array($key));
701
+ }
702
+
703
+ /**
704
+ * Generates HTML of a checkbox based on the passed parameters.
705
+ *
706
+ * @since 4.8.1
707
+ * @see PRSS_FTP_Utils::boolean_to_checkbox()
708
+ * @param bool|mixed $isChecked Whether or not this checkbox should be ticked.
709
+ * @param array $args Additional checkbox params.
710
+ * @param bool $autoEval If true, the first value will be evaluated and compared to known 'true' values.
711
+ * @return string The HTML of a checkbox.
712
+ */
713
+ static public function getCheckboxHtml($isChecked, $args, $autoEval = true)
714
+ {
715
+ if ($autoEval) {
716
+ $isChecked = static::isTrue($isChecked);
717
+ }
718
+ return \WPRSS_FTP_Utils::boolean_to_checkbox($isChecked, $args);
719
+ }
720
+
721
+ /**
722
+ * Get the HTML output of a <select> element.
723
+ *
724
+ * @since 4.8.1
725
+ * @param array $values The select element's options.
726
+ * @param array $args Data for the select element.
727
+ * @return string The select element HTML.
728
+ */
729
+ static public function getSelectHtml($values, $args = array())
730
+ {
731
+ return \WPRSS_FTP_Utils::array_to_select($values, $args);
732
+ }
733
+
734
+ /**
735
+ * Get the HTML output of an <input> element of type 'text' or 'password'.
736
+ *
737
+ * @since 4.8.1
738
+ * @param string|int $value The input element's value.
739
+ * @param array $args Data for the input element.
740
+ * @return string The input element HTML.
741
+ */
742
+ static public function getTextHtml($value, $args = array())
743
+ {
744
+ $defaults = array(
745
+ 'type' => 'text',
746
+ 'class' => '',
747
+ 'placeholder' => isset($args['label']) ? $args['label'] : ''
748
+ );
749
+ $args = array_merge_recursive_distinct($defaults, $args);
750
+
751
+ return sprintf('<input id="%1$s" type="%2$s" name="%3$s" value="%4$s" class="%5$s" placeholder="%6$s" />',
752
+ esc_attr($args['id']),
753
+ $args['type'],
754
+ $args['name'],
755
+ esc_attr($value),
756
+ $args['class'],
757
+ $args['placeholder']
758
+ );
759
+ }
760
+
761
+ /**
762
+ * Get the HTML output of an <input> element of type 'number'.
763
+ *
764
+ * @since 4.8.1
765
+ * @param string|int $value The input element's value.
766
+ * @param array $args Data for the input element.
767
+ * @return string The input element HTML.
768
+ */
769
+ static public function getNumberHtml($value, $args = array())
770
+ {
771
+ $defaults = array(
772
+ 'type' => 'number',
773
+ 'class' => '',
774
+ 'placeholder' => isset($args['label']) ? $args['label'] : '',
775
+ 'min' => 0,
776
+ 'max' => '',
777
+ 'step' => 1
778
+ );
779
+ $args = array_merge_recursive_distinct($defaults, $args);
780
+
781
+ return sprintf('<input id="%1$s" type="%2$s" name="%3$s" value="%4$s" class="%5$s" placeholder="%6$s" min="%7$s" max="%8$s" step="%9$s" />',
782
+ esc_attr($args['id']),
783
+ $args['type'],
784
+ $args['name'],
785
+ esc_attr($value),
786
+ $args['class'],
787
+ $args['placeholder'],
788
+ $args['min'],
789
+ $args['max'],
790
+ $args['step']
791
+ );
792
+ }
793
+
794
+ /**
795
+ * Gets a value for HTML elements' "name" attribute.
796
+ *
797
+ * This attribute can have multiple nested names, or levels, such as:
798
+ * name[subName][subSubName]
799
+ *
800
+ * Given all the levels, it will return the correct value for the attribute.
801
+ *
802
+ * @since 4.8.1
803
+ * @param string|array $name A name with levels separated by '/', or an array of levels.
804
+ * @return string A value used in HTML elements' "name" attribute.
805
+ */
806
+ static public function getNameHtml($name)
807
+ {
808
+ if (!is_array($name)) {
809
+ $name = explode('/', $name);
810
+ }
811
+
812
+ $mainName = array_shift($name);
813
+ return $mainName . '[' . implode('][', $name) . ']';
814
+ }
815
+
816
+ /**
817
+ * Checks whether a value is considered to be 'true' by this class.
818
+ *
819
+ * @since 4.8.1
820
+ * @param mixed $value The value to check.
821
+ * @return bool True if the value is considered by this class to represent 'true'; false otherwise.
822
+ */
823
+ static public function isTrue($value)
824
+ {
825
+ return \WPRSS_FTP_Utils::multiboolean($value) || (trim($value) === static::getTrueValue());
826
+ }
827
+
828
+ /**
829
+ * Get a value that is considered by this class to be 'true'.
830
+ *
831
+ * @since 4.8.1
832
+ * @return string Returns a string representation of a value that is considered to be 'true' by this class.
833
+ */
834
+ static public function getTrueValue()
835
+ {
836
+ return static::TRUE_VALUE;
837
+ }
838
+
839
+ /**
840
+ * Get a value that is considered by this class to be 'false'.
841
+ *
842
+ * @since 4.8.1
843
+ * @return string Returns a string representation of a value that is considered to be 'false' by this class.
844
+ */
845
+ static public function getFalseValue()
846
+ {
847
+ return static::FALSE_VALUE;
848
+ }
849
+
850
+ /**
851
+ * Retrieve a raw option by name from the database.
852
+ *
853
+ * @since 4.8.1
854
+ * @param string $name The name of the option.
855
+ * @param bool|mixed $default What to return if the option is not found.
856
+ * @return mixed The option value.
857
+ */
858
+ static public function getOption($name, $default = false)
859
+ {
860
+ return get_option($name, $default);
861
+ }
862
+ }
includes/Aventura/Wprss/Core/Model/SettingsInterface.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ /**
6
+ * Something that can represent settings.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ interface SettingsInterface
11
+ {
12
+ public function validate($settings);
13
+
14
+ public function getSectionsFields();
15
+
16
+ public function getData();
17
+ }
includes/Aventura/Wprss/Core/Model/SpinnerAbstract.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * Common functionality for spinners.
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ abstract class SpinnerAbstract extends Core\Plugin\ComponentAbstract implements SpinnerInterface
13
+ {
14
+ public function spin($content, $options = array())
15
+ {
16
+ $this->getApi()->spin($content, $options);
17
+ }
18
+
19
+ /**
20
+ * @since 4.8.1
21
+ * @return SpinnerApiInterface
22
+ */
23
+ abstract public function getApi();
24
+ }
includes/Aventura/Wprss/Core/Model/SpinnerApiAbstract.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * @since 4.8.1
9
+ */
10
+ abstract class SpinnerApiAbstract extends Core\Plugin\ComponentAbstract implements SpinnerApiInterface
11
+ {
12
+ /**
13
+ * Spins content using a remote API.
14
+ *
15
+ * @since 4.8.1
16
+ * @param mixed $content
17
+ * @param array $options Options for spinning.
18
+ * @return mixed
19
+ */
20
+ public function spin($content, $options = array())
21
+ {
22
+ $uri = $this->getQueryUri($options);
23
+ $response = $this->query($uri, $content, $options);
24
+
25
+ return $response;
26
+ }
27
+
28
+ /**
29
+ * Happens immediately before the spin request is sent to the remote API.
30
+ *
31
+ * @since 4.8.1
32
+ * @param mixed $request The request that is about to be sent.
33
+ * @param string $uri The URI, to which the request is about to be sent.
34
+ * @return mixed The new request, possibly modified
35
+ */
36
+ protected function _beforeQuery($request, $uri = null)
37
+ {
38
+ return $request;
39
+ }
40
+
41
+ /**
42
+ * Happens immediately after the spin request is sent to the remote API.
43
+ *
44
+ * @since 4.8.1
45
+ * @param mixed $response The response that was received.
46
+ * @param string $uri The URI, to which the request was sent.
47
+ * @return mixed The new response, possibly modified
48
+ */
49
+ protected function _afterQuery($response, $uri = null)
50
+ {
51
+ return $response;
52
+ }
53
+
54
+ /**
55
+ * Sends the spinning query to the remote API.
56
+ *
57
+ * @since 4.8.1
58
+ * @param string $uri The URI to send the query to.
59
+ * @param mixed $request The request to send.
60
+ * @return mixed The query response.
61
+ */
62
+ public function query($uri, $request, $options = array())
63
+ {
64
+ $request = $this->_beforeQuery($request, $uri);
65
+ $response = $this->_sendRequest($uri, $request);
66
+ $response = $this->_afterQuery($response, $uri);
67
+
68
+ return $response;
69
+ }
70
+
71
+ /**
72
+ * Does the actual sending of the request.
73
+ *
74
+ * @since 4.8.1
75
+ * @return mixed The low-level API response.
76
+ */
77
+ abstract protected function _sendRequest($uri, $request);
78
+
79
+ /**
80
+ * Get the actual URI, to which the spin request will be sent.
81
+ *
82
+ * @since 4.8.1
83
+ * @return string The complete URI, to which a spin request should be sent.
84
+ */
85
+ abstract public function getQueryUri($options = array());
86
+ }
includes/Aventura/Wprss/Core/Model/SpinnerApiInterface.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ /**
6
+ * Something that can spin content, usually using a remote service.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ interface SpinnerApiInterface
11
+ {
12
+ /**
13
+ * Spins the content using the remote API.
14
+ *
15
+ * @since 4.8.1
16
+ * @param mixed $content The content to spin.
17
+ * @param array $options Options for spinning.
18
+ */
19
+ public function spin($content, $options = array());
20
+ }
includes/Aventura/Wprss/Core/Model/SpinnerInterface.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Model;
4
+
5
+ /**
6
+ * An interface of something that can spin post data.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ interface SpinnerInterface
11
+ {
12
+ /**
13
+ *
14
+ * @since 4.8.1
15
+ * @param string $content
16
+ */
17
+ public function spin($content);
18
+ }
includes/Aventura/Wprss/Core/Plugin.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core;
4
+
5
+ /**
6
+ * A dummy plugin for the Core plugin.
7
+ *
8
+ * @since 4.8.1
9
+ * @todo Create real Core plugin in the Core plugin.
10
+ */
11
+ class Plugin extends Plugin\PluginAbstract
12
+ {
13
+ const CODE = 'wprss';
14
+ const VERSION = WPRSS_VERSION;
15
+ }
includes/Aventura/Wprss/Core/Plugin/AddonAbstract.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ /**
6
+ * A base class for SpinnerChief add-ons.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ abstract class AddonAbstract extends PluginAbstract implements AddonInterface, ComponentInterface
11
+ {
12
+ /** @since 4.8.1 */
13
+ protected $_parent;
14
+
15
+ /**
16
+ * {@inheritdoc}
17
+ *
18
+ * @since 4.8.1
19
+ */
20
+ public function __construct($data, PluginInterface $parent, ComponentFactoryInterface $factory = null)
21
+ {
22
+ parent::__construct($data, $factory);
23
+ $this->_setParent($parent);
24
+ }
25
+
26
+ /**
27
+ * {@inheritdoc}
28
+ *
29
+ * @since 4.8.1
30
+ */
31
+ public function getPlugin()
32
+ {
33
+ return $this->getParent();
34
+ }
35
+
36
+ /**
37
+ * {@inheritdoc}
38
+ *
39
+ * @since 4.8.1
40
+ */
41
+ public function getParent() {
42
+ return $this->_parent;
43
+ }
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ *
48
+ * @since 4.8.1
49
+ */
50
+ protected function _setParent(PluginInterface $parent) {
51
+ $this->_parent = $parent;
52
+ return $this;
53
+ }
54
+
55
+ /**
56
+ * {@inheritdoc}
57
+ *
58
+ * @since 4.8.1
59
+ */
60
+ public function getLogger()
61
+ {
62
+ if ($logger = parent::getLogger()) {
63
+ return $logger;
64
+ }
65
+
66
+ return $this->getParent()->getLogger();
67
+ }
68
+
69
+ /**
70
+ * {@inheritdoc}
71
+ *
72
+ * @since 4.8.1
73
+ */
74
+ public function getEventManager()
75
+ {
76
+ if ($events = parent::getEventManager()) {
77
+ return $events;
78
+ }
79
+
80
+ return $this->getParent()->getEventManager();
81
+ }
82
+
83
+ /**
84
+ * {@inheritdoc}
85
+ *
86
+ * @since 4.8.1
87
+ */
88
+ public function getEventPrefix($name = null)
89
+ {
90
+ $prefix = '';
91
+ $prefix .= $this->getParent()->getEventPrefix();
92
+ $prefix .= parent::getEventPrefix();
93
+ if (is_null($name)) {
94
+ return $prefix;
95
+ }
96
+ $prefix = static::stringHadPrefix($name)
97
+ ? $name
98
+ : "{$prefix}{$name}";
99
+
100
+ return $prefix;
101
+ }
102
+
103
+ /**
104
+ * {@inheritdoc}
105
+ *
106
+ * @since 4.8.1
107
+ */
108
+ public function on($name, $listener, $data = null, $priority = null, $acceptedArgs = null)
109
+ {
110
+ if (is_string($listener) && !is_object($listener)) {
111
+ $listener = array($this, $listener);
112
+ }
113
+
114
+ return parent::on($name, $listener, $data, $priority, $acceptedArgs);
115
+ }
116
+
117
+ /**
118
+ * {@inheritdoc}
119
+ *
120
+ * @since 4.8.1
121
+ */
122
+ public function event($name, $data = array())
123
+ {
124
+ if (!isset($data['caller'])) {
125
+ $data['caller'] = $this;
126
+ }
127
+
128
+ return parent::event($name, $data);
129
+ }
130
+ }
includes/Aventura/Wprss/Core/Plugin/AddonFactoryAbstract.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ /**
6
+ * Common functionality for add-on factories.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ abstract class AddonFactoryAbstract extends FactoryAbstract implements AddonFactoryInterface
11
+ {
12
+ }
includes/Aventura/Wprss/Core/Plugin/AddonFactoryInterface.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ /**
6
+ * An interface for something that creates add-ons.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ interface AddonFactoryInterface extends FactoryInterface
11
+ {
12
+
13
+ /**
14
+ * {@inheritdoc}
15
+ *
16
+ * @since 4.8.1
17
+ * @return AddonInterface
18
+ */
19
+ static public function create();
20
+
21
+ /**
22
+ * Get the parent of the add-ons created by this interface.
23
+ *
24
+ * @since 4.8.1
25
+ * @return PluginInterface
26
+ */
27
+ public function getParent();
28
+ }
includes/Aventura/Wprss/Core/Plugin/AddonInterface.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ /**
6
+ * @since 4.8.1
7
+ */
8
+ interface AddonInterface extends PluginInterface
9
+ {
10
+
11
+ /**
12
+ * Get the plugin, for which this is an add-on.
13
+ *
14
+ * @since 4.8.1
15
+ * @return PluginInterface The parent plugin instance.
16
+ */
17
+ public function getParent();
18
+ }
includes/Aventura/Wprss/Core/Plugin/ComponentAbstract.php ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * A base class for all SpinnerChief add-on components.
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ abstract class ComponentAbstract extends Core\Model\ModelAbstract implements ComponentInterface
13
+ {
14
+ /**
15
+ * @var PluginInterface The plugin, to which this component belongs
16
+ * @since 4.8.1
17
+ */
18
+ protected $_plugin;
19
+
20
+ /**
21
+ *
22
+ * @since 4.8.1
23
+ * @param PluginInterface|array $data The instance of the
24
+ * add-on, of which this is to be a component. Alternatively, an array with data, which must have the 'plugin'
25
+ * index set to that instance.
26
+ */
27
+ public function __construct($data)
28
+ {
29
+ // Allowing specifying parent as the only argument
30
+ if (!is_array($data)) {
31
+ $data = array('plugin' => $data);
32
+ }
33
+ // Making sure the parent is specified
34
+ if (!isset($data['plugin']) || !($data['plugin'] instanceof PluginInterface)) {
35
+ throw $this->exception(array('Could not create component: The "%1$s" index must be a plugin instance'), array(__NAMESPACE__, 'Exception'));
36
+ }
37
+ $plugin = $data['plugin'];
38
+ unset($data['plugin']);
39
+
40
+ $this->_plugin = $plugin;
41
+ parent::__construct($data);
42
+ }
43
+
44
+ /**
45
+ * {@inheritdoc}
46
+ *
47
+ * @since 4.8.1
48
+ * @return PluginInterface
49
+ */
50
+ public function getPlugin()
51
+ {
52
+ return $this->_plugin;
53
+ }
54
+
55
+ /**
56
+ * Sets the parent plugin for this component.
57
+ *
58
+ * @since 4.8.1
59
+ * @param PluginInterface $plugin The plugin to set.
60
+ * @return ComponentAbstract This instance.
61
+ */
62
+ protected function _setPlugin(PluginInterface $plugin) {
63
+ $this->_plugin = $plugin;
64
+ return $this;
65
+ }
66
+
67
+ /**
68
+ * Get the text domain of this component.
69
+ *
70
+ * @since 4.8.1
71
+ * @return string The text domain.
72
+ */
73
+ public function getTextDomain() {
74
+ return $this->getPlugin()->getTextDomain();
75
+ }
76
+
77
+ /**
78
+ * Creates an exception, the root of which is the parent plugin.
79
+ *
80
+ * @since 4.8.1
81
+ * @return Core\Exception
82
+ */
83
+ public function exception($text, $className = null, $translate = null)
84
+ {
85
+ return $this->getPlugin()->exception($text, $className, $translate);
86
+ }
87
+
88
+ /**
89
+ * Hooks this component into the environment.
90
+ *
91
+ * Typically, this is done by a factory upon creation, but not necessarily.
92
+ * Override this to hook in your component.
93
+ *
94
+ * @since 4.8.1
95
+ */
96
+ public function hook() {}
97
+
98
+ /**
99
+ * Gets a hook name prefix, or a prefixed hook name.
100
+ *
101
+ * A hook prefix is used by all abstracted methods for adding hooks.
102
+ * The prefix defaults to the plugin's prefix. If none set, the plugin code followed by an underscore '_'.
103
+ * If can be additionally defined as the HOOK_PREFIX class constant, and overridden
104
+ * with the 'hook_prefix' data member.
105
+ *
106
+ * @since 4.8.1
107
+ * @param string $code A hook name to prefix.
108
+ * @return string The hook prefix, or prefixed string.
109
+ */
110
+ public function getEventPrefix($code = null)
111
+ {
112
+ $prefix = $this->_getDataOrConst('hook_prefix');
113
+ if (is_null($prefix)) {
114
+ $prefix = $this->getPlugin()->getHookPrefix();
115
+ }
116
+ if (is_null($prefix)) {
117
+ $prefix = sprintf('%1$s_', $this->getPluginCode());
118
+ }
119
+
120
+ return is_null($code)
121
+ ? $prefix
122
+ : "{$prefix}{$code}";
123
+ }
124
+
125
+ /**
126
+ * {@inheritdoc}
127
+ *
128
+ * @since 4.8.1
129
+ * @see Core\Model\LoggerInterface
130
+ * @param string|int $level
131
+ * @param string $message
132
+ * @param array $context Particularly, the 'source' index should point to the function/method,
133
+ * where the message is sent from.
134
+ * @return bool True if log entry was processed; false otherwise.
135
+ */
136
+ public function log($level, $message, array $context = array())
137
+ {
138
+ return $this->getPlugin()->log($level, $message, $context);
139
+ }
140
+
141
+ /**
142
+ * {@inheritdoc}
143
+ *
144
+ * @since 4.8.1
145
+ */
146
+ public function on($name, $listener, $data = null, $priority = null, $acceptedArgs = null)
147
+ {
148
+ if (is_string($listener) && !is_object($listener)) {
149
+ $listener = array($this, $listener);
150
+ }
151
+
152
+ return $this->getPlugin()->on($name, $listener, $data, $priority, $acceptedArgs);
153
+ }
154
+
155
+ /**
156
+ * {@inheritdoc}
157
+ *
158
+ * @since 4.8.1
159
+ */
160
+ public function event($name, $data = array())
161
+ {
162
+ if (!isset($data['caller'])) {
163
+ $data['caller'] = $this;
164
+ }
165
+
166
+ return $this->getPlugin()->event($name, $data);
167
+ }
168
+ }
includes/Aventura/Wprss/Core/Plugin/ComponentFactoryAbstract.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ /**
6
+ * Common functionality of component factories.
7
+ * A component factory is also a component ;P
8
+ *
9
+ * @since 4.8.1
10
+ */
11
+ abstract class ComponentFactoryAbstract extends ComponentAbstract implements ComponentFactoryInterface
12
+ {
13
+ /**
14
+ * Creates a new component instance.
15
+ *
16
+ * @since 4.8.1
17
+ * @param string $class The classname of the component to create.
18
+ * Can be relative to the base namespace of this factory.
19
+ * @param PluginInterface $parent The parent plugin for the new component.
20
+ * @return ComponentInterface A new component.
21
+ * @throws Exception If class does not exist, or is not a component class.
22
+ */
23
+ public function createComponent($class, PluginInterface $parent, array $data = array())
24
+ {
25
+ $className = $this->getComponentClassName($class);
26
+ $componentBase = 'Aventura\Wprss\Core\Plugin\ComponentInterface';
27
+ if (!static::classImplements($className, $componentBase)) {
28
+ throw $this->exception(array('Could not create component: "%1$s" is not a component class as it does not implement "%2$s"', $className, $componentBase), array(__NAMESPACE__, 'Exception'));
29
+ }
30
+
31
+ if (!class_exists($className)) {
32
+ throw $this->exception(array('Could not create component: component class"%1$s" does not exist', $className), array(__NAMESPACE__, 'Exception'));
33
+ }
34
+
35
+ $data['plugin'] = $parent;
36
+ $component = new $className($data);
37
+ $component->hook();
38
+
39
+ return $component;
40
+ }
41
+
42
+ /**
43
+ * Get the name of a component class, based on it's relative or absolute name, or mapped ID.
44
+ *
45
+ * @since 4.8.1
46
+ * @param string $className A relative or absolute class name, or some other class identifier that is mapped
47
+ * to a class name. If relative, then relative to the {@see getBaseNamespace()}.
48
+ * @return string Name of the component class.
49
+ */
50
+ public function getComponentClassName($className)
51
+ {
52
+ // Namespace specified as array of parts; assume root namespace
53
+ if (is_array($className)) {
54
+ $className = '\\' . trim(implode('\\', $className), '\\');
55
+ }
56
+
57
+ if (static::isRootNamespace($className)) {
58
+ return $className;
59
+ }
60
+
61
+ $rootNamespace = $this->getBaseNamespace();
62
+ return sprintf('%1$s\\%2$s', $rootNamespace, $className);
63
+ }
64
+ }
includes/Aventura/Wprss/Core/Plugin/ComponentFactoryInterface.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ /**
6
+ * Something that allows creation and initialization of SpinnerChief classes.
7
+ */
8
+ interface ComponentFactoryInterface
9
+ {
10
+ public function createComponent($class, PluginInterface $parent);
11
+
12
+ /**
13
+ * @return string The base namespace, to which components created by this factory will belong.
14
+ */
15
+ public function getBaseNamespace();
16
+
17
+ }
includes/Aventura/Wprss/Core/Plugin/ComponentInterface.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * Something that can be a plugin component.
9
+ *
10
+ * A plugin component is something that is a part of a plugin, and therefore
11
+ * interacts with the plugin's main class, i.e. depends on it.
12
+ *
13
+ * @since 4.8.1
14
+ */
15
+ interface ComponentInterface
16
+ {
17
+
18
+ /**
19
+ * Get this component's plugin;
20
+ *
21
+ * @since 4.8.1
22
+ * @return \Aventura\Wprss\Core\Plugin\PluginInterface The instance of the add-on,
23
+ * of which this is a component.
24
+ */
25
+ public function getPlugin();
26
+
27
+ /**
28
+ * Allows the environment to cause this plugin to hook itself into the environment.
29
+ *
30
+ * Called by the environment at a time that is determined to be suitable for the environment.
31
+ *
32
+ * @since 4.8.1
33
+ */
34
+ public function hook();
35
+
36
+ /**
37
+ * @since 4.8.1
38
+ * @see Core\Model\LoggerInterface
39
+ */
40
+ public function log($level, $message, array $context = array());
41
+
42
+ /**
43
+ * Listen to an event.
44
+ *
45
+ * @since 4.8.1
46
+ * @param string $name The name of the event to listen for.
47
+ * @param callable|string $listener The listener for the event. If string given, the method of this instane
48
+ * with that name will be used.
49
+ * @param array|null $data Additional arguments to pass to the event.
50
+ * @param int|null $priority Priority of the listener. If null, implementation-default will be used.
51
+ * @param int|null $acceptedArgs Number of the args passed to the listener. If null, implementation-default is used.
52
+ * @return bool True if listener registered; false otherwise.
53
+ */
54
+ public function on($name, $listener, $data = null, $priority = null, $acceptedArgs = null);
55
+
56
+ /**
57
+ * Raise an event.
58
+ *
59
+ * @since 4.8.1
60
+ * @param string $name Name of the event.
61
+ * @param array|object $data The event data.
62
+ * @return EventInterface|null An event object that is the result of this event.
63
+ * This object will contain the data passed, and possibly modified.
64
+ * If event cannot be raised, null is returned.
65
+ */
66
+ public function event($name, $data = array());
67
+ }
includes/Aventura/Wprss/Core/Plugin/Exception.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * The base class for all WP plugins.
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ class Exception extends Core\Exception
13
+ {
14
+ //put your code here
15
+ }
includes/Aventura/Wprss/Core/Plugin/FactoryAbstract.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * @since 4.8.1
9
+ */
10
+ abstract class FactoryAbstract extends Core\Model\ModelAbstract implements FactoryInterface
11
+ {
12
+ /**
13
+ * Creates an instance of this class.
14
+ *
15
+ * @since 4.8.1
16
+ * @param array $data Data for the new instance.
17
+ * @return FactoryAbstract
18
+ */
19
+ static protected function _getInstance($data = array())
20
+ {
21
+ return new static($data);
22
+ }
23
+
24
+ /**
25
+ * {@inheritdoc}
26
+ *
27
+ * @since 4.8.1
28
+ * @param type $parent
29
+ * @param array|string $data Data for the new plugin. If string given, it will be assumed the value of the
30
+ * 'basename' index.
31
+ * @return PluginInterface
32
+ */
33
+ static public function create($data = array())
34
+ {
35
+ $me = static::_getInstance();
36
+ do_action('wprss_plugin_factory_create_plugin_before', $me);
37
+ $addon = $me->_create($data);
38
+ do_action('wprss_plugin_factory_create_plugin_after', $addon, $me);
39
+
40
+ return $addon;
41
+ }
42
+
43
+ /**
44
+ * Does the actual creation.
45
+ *
46
+ * @since 4.8.1
47
+ * @return PluginInterface
48
+ */
49
+ abstract protected function _create($data);
50
+ }
includes/Aventura/Wprss/Core/Plugin/FactoryInterface.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ /**
6
+ * An interface for something that creates plugins.
7
+ *
8
+ * @since 4.8.1
9
+ */
10
+ interface FactoryInterface
11
+ {
12
+ /**
13
+ * Create a plugin.
14
+ *
15
+ * @since 4.8.1
16
+ * @return PluginInterface
17
+ */
18
+ static public function create();
19
+ }
includes/Aventura/Wprss/Core/Plugin/PluginAbstract.php ADDED
@@ -0,0 +1,359 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * The base class for all WP plugins.
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ class PluginAbstract extends Core\Model\ModelAbstract implements PluginInterface
13
+ {
14
+ const CODE = '';
15
+ const VERSION = '';
16
+
17
+ /** @since 4.8.1 */
18
+ protected $_factory;
19
+ /** @since 4.8.1 */
20
+ protected $_logger;
21
+ /** @since 4.8.1 */
22
+ protected $_eventManager;
23
+
24
+ /**
25
+ *
26
+ * @param array|string $data Data that describes the plugin.
27
+ * The following indices are required:
28
+ * * `basename` - The plugin basename, or full path to plugin's main file. See {@see getBasename()}.
29
+ * Other indices explicitly handled by this class:
30
+ * * `component_factory` - Instance or name of a component factory class.
31
+ * * `text_domain` - The text domain used for translation by this plugin. See {@see getTextDomain}.
32
+ * * `name` - The human-readable name of the plugin. See {@see getName()}.
33
+ * Any other data will just be added to this instances internal data.
34
+ * @param ComponentFactoryInterface A factory that will create components for this plugin.
35
+ *
36
+ * @throws Exception If required fields are not specified.
37
+ */
38
+ public function __construct($data, ComponentFactoryInterface $factory = null)
39
+ {
40
+ if (!is_array($data)) {
41
+ $data = array('basename' => $data);
42
+ }
43
+
44
+ // Handling basename
45
+ if (!isset($data['basename'])) {
46
+ throw $this->exception('Could not create plugin instance: "basename" must be specified', array(__NAMESPACE__, 'Exception'));
47
+ }
48
+ $basename = trim($data['basename']);
49
+
50
+ // Account for full path to main file.
51
+ if (substr($basename, 0, 1) === '/' || substr_count($basename, '/') >= 2) {
52
+ $basename = static::getPluginBasename($basename);
53
+ }
54
+ $data['basename'] = $basename;
55
+
56
+ // Normalizing and setting component factory
57
+ if (is_null($factory) && isset($data['component_factory'])) {
58
+ $factory = $data['component_factory'];
59
+ }
60
+
61
+ if ($factory) {
62
+ $this->setFactory($factory);
63
+ }
64
+ $this->setBasename($basename);
65
+
66
+ parent::__construct($data);
67
+ }
68
+
69
+ public function getBasename()
70
+ {
71
+ return $this->getData('basename');
72
+ }
73
+
74
+ public function getTextDomain()
75
+ {
76
+ return $this->getData('text_domain');
77
+ }
78
+
79
+ public function getName()
80
+ {
81
+ return $this->getData('name');
82
+ }
83
+
84
+ public function getCode()
85
+ {
86
+ return $this->_getDataOrConst('code');
87
+ }
88
+
89
+ public function getVersion()
90
+ {
91
+ return $this->_getDataOrConst('version');
92
+ }
93
+
94
+ /**
95
+ * @since 4.8.1
96
+ * @return ComponentFactoryInterface
97
+ */
98
+ public function getFactory()
99
+ {
100
+ return $this->_factory;
101
+ }
102
+
103
+ public function setFactory(ComponentFactoryInterface $factory)
104
+ {
105
+ $this->_setFactory($factory);
106
+ return $this;
107
+ }
108
+
109
+ public function isActive()
110
+ {
111
+ return static::isPluginActive($this);
112
+ }
113
+
114
+ public function deactivate()
115
+ {
116
+ static::deactivatePlugin($this);
117
+ return $this;
118
+ }
119
+
120
+ /**
121
+ * Checks if a plugin is active.
122
+ *
123
+ * @since 4.8.1
124
+ * @param PluginInterface|string $plugin A plugin instance or basename.
125
+ * @return bool True if the plugin is active; false otherwise.
126
+ */
127
+ static public function isPluginActive($plugin)
128
+ {
129
+ static::_ensurePluginFunctionsExist();
130
+
131
+ if ($plugin instanceof PluginInterface) {
132
+ $plugin = $plugin->getBasename();
133
+ }
134
+
135
+ return is_plugin_active($plugin);
136
+ }
137
+
138
+ static public function deactivatePlugin($plugin)
139
+ {
140
+ static::_ensurePluginFunctionsExist();
141
+
142
+ if ($plugin instanceof PluginInterface) {
143
+ $plugin = $plugin->getBasename();
144
+ }
145
+
146
+ deactivate_plugins($plugin);
147
+ }
148
+
149
+ static protected function _ensurePluginFunctionsExist()
150
+ {
151
+ // Making sure there are the functions we need
152
+ if (!function_exists( 'is_plugin_active' )) {
153
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Sets the component factory instance.
159
+ *
160
+ * If class name given instead, it will be instantiated.
161
+ *
162
+ * @since 4.8.1
163
+ * @param ComponentFactoryInterface|string $factory The component factory instance or class name.
164
+ * @return PluginInterface This instance.
165
+ * @throws Exception If factory class specified as classname string does not exist, or is not a factory.
166
+ */
167
+ protected function _setFactory(ComponentFactoryInterface $factory) {
168
+ // Factory could be a classname
169
+ if (is_string($factory)) {
170
+ // Making sure it exists
171
+ $factory = trim($factory);
172
+ if (!class_exists($factory)) {
173
+ throw $this->exception(array('Could not set component factory: Factory class "%1$s" does not exist', $factory), array(__NAMESPACE__, 'Exception'));
174
+ }
175
+ // Making sure it's a factory
176
+ if (!is_a($factory, __NAMESPACE__ . '\ComponentFactoryInterface')) {
177
+ throw $this->exception(array('Could not set component factory: Factory class "%1$s" is not a factory', $factory), array(__NAMESPACE__, 'Exception'));
178
+ }
179
+
180
+ $factory = new $factory();
181
+ /* @var $factory Aventura\Wprss\Core\Plugin\ComponentFactoryInterface */
182
+ }
183
+
184
+ $this->_factory = $factory;
185
+ return $this;
186
+ }
187
+
188
+ /**
189
+ * Translates some text.
190
+ *
191
+ * @since [*next-version*]s
192
+ * @param string $text The text to translate.
193
+ * @param string|null The text domain to use for translation.
194
+ * Defaults to this plugin's text domain.
195
+ * @return string Translated text
196
+ */
197
+ protected function _translate($text, $translator = null)
198
+ {
199
+ if (!is_null($translator)) {
200
+ $translator = $this->getTextDomain();
201
+ }
202
+
203
+ return __($text, $translator);
204
+ }
205
+
206
+ /**
207
+ * Gets a plugin basename from its absolute path.
208
+ *
209
+ * @since 4.8.1
210
+ * @param string $path Absolute path to a plugin's main file.
211
+ * @return string The path to the plugin's main file, relative to the plugins directory.
212
+ */
213
+ public static function getPluginBasename($path) {
214
+ return plugin_basename($path);
215
+ }
216
+
217
+ /**
218
+ * Gets the logger instance used by this plugin.
219
+ *
220
+ * @since 4.8.1
221
+ * @return Core\Model\LoggerInterface|null
222
+ */
223
+ public function getLogger()
224
+ {
225
+ return $this->_logger;
226
+ }
227
+
228
+ /**
229
+ * Sets the logger instance to be used by this plugin.
230
+ *
231
+ * @since 4.8.1
232
+ * @param Core\Model\LoggerInterface $logger
233
+ * @return Core\Plugin\PluginAbstract
234
+ */
235
+ public function setLogger(Core\Model\LoggerInterface $logger)
236
+ {
237
+ $this->_logger = $logger;
238
+ return $this;
239
+ }
240
+
241
+ public function log($level, $message, array $context = array())
242
+ {
243
+ $isFormattable = is_array($message) && isset($message[0]) && is_string($message[0]);
244
+ if (is_object($message) || empty($message) || (!is_string($message) && !$isFormattable)) {
245
+ return $this->logObject($level, $message, $context);
246
+ }
247
+
248
+ if ($logger = $this->getLogger()) {
249
+ try {
250
+ $message = $this->__($message);
251
+ } catch (\InvalidArgumentException $e) {
252
+ return $this->logObject($level, $message, $context);
253
+ }
254
+ return $logger->log($level, $message, $context);
255
+ }
256
+
257
+ return false;
258
+ }
259
+
260
+ public function logObject($level, $object, array $context = array())
261
+ {
262
+ if (empty($object)) {
263
+ ob_start();
264
+ var_dump($object);
265
+ $dump = ob_get_contents();
266
+ ob_end_clean();
267
+ }
268
+ else {
269
+ $dump = print_r($object, true);
270
+ }
271
+
272
+ return $this->log($level, $dump, $context);
273
+ }
274
+
275
+ /**
276
+ * A default no-op implementation. Does nothing. Override in descendants.
277
+ *
278
+ * @since 4.8.1
279
+ */
280
+ public function hook() {}
281
+
282
+ /**
283
+ * {@inheritdoc}
284
+ *
285
+ * @since 4.8.1
286
+ */
287
+ protected function _getEventPrefix($name = null)
288
+ {
289
+ $prefix = $this->hasData('event_prefix')
290
+ ? $this->getData('event_prefix')
291
+ : ($code = $this->getCode()) ? sprintf('%1$s_', $code) : '';
292
+
293
+ return string_had_prefix($name, $this->getPrefixOverride())
294
+ ? $name
295
+ : "{$prefix}{$name}";
296
+ }
297
+
298
+ /**
299
+ * Sets the event manager for this instance.
300
+ *
301
+ * @since 4.8.1
302
+ * @param Core\Model\Event\EventManagerInterface $manager An event manager.
303
+ * @return PluginAbstract This instance.
304
+ */
305
+ public function setEventManager(Core\Model\Event\EventManagerInterface $manager)
306
+ {
307
+ $this->_eventManager = $manager;
308
+ return $this;
309
+ }
310
+
311
+ /**
312
+ * Retrieves this instance's event manager.
313
+ *
314
+ * @since 4.8.1
315
+ * @return Core\Model\Event\EventManagerInterface|null The event manager of this instance, or null if not set.
316
+ */
317
+ public function getEventManager()
318
+ {
319
+ return $this->_eventManager;
320
+ }
321
+
322
+ /**
323
+ * {@inheritdoc}
324
+ *
325
+ * @since 4.8.1
326
+ */
327
+ public function on($name, $listener, $data = null, $priority = null, $acceptedArgs = null)
328
+ {
329
+ if (is_string($listener) && !is_object($listener)) {
330
+ $listener = array($this, $listener);
331
+ }
332
+
333
+ if ($events = $this->getEventManager()) {
334
+ $name = $this->getEventPrefix($name);
335
+ return $events->on($name, $listener, $data, $priority, $acceptedArgs);
336
+ }
337
+
338
+ return false;
339
+ }
340
+
341
+ /**
342
+ * {@inheritdoc}
343
+ *
344
+ * @since 4.8.1
345
+ */
346
+ public function event($name, $data = array())
347
+ {
348
+ if (!isset($data['caller'])) {
349
+ $data['caller'] = $this;
350
+ }
351
+
352
+ if ($events = $this->getEventManager()) {
353
+ $name = $this->getEventPrefix($name);
354
+ return $events->event($name, $data);
355
+ }
356
+
357
+ return null;
358
+ }
359
+ }
includes/Aventura/Wprss/Core/Plugin/PluginInterface.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Aventura\Wprss\Core\Plugin;
4
+
5
+ use Aventura\Wprss\Core;
6
+
7
+ /**
8
+ * Something that can represent a WP plugin.
9
+ *
10
+ * @since 4.8.1
11
+ */
12
+ interface PluginInterface
13
+ {
14
+ /**
15
+ * The plugin's basename, e.g. 'my-plugin/my-plugin.php'.
16
+ *
17
+ * @since 4.8.1
18
+ */
19
+ public function getBasename();
20
+
21
+ /**
22
+ * The plugin's text domain.
23
+ *
24
+ * This will be used for translation.
25
+ *
26
+ * @since 4.8.1
27
+ */
28
+ public function getTextDomain();
29
+
30
+ /**
31
+ * The human-readable name of the plugin.
32
+ *
33
+ * @since 4.8.1
34
+ */
35
+ public function getName();
36
+
37
+ /**
38
+ * The unique identifier of the plugin.
39
+ *
40
+ * @since 4.8.1
41
+ */
42
+ public function getCode();
43
+
44
+ /**
45
+ * The version number of the plugin.
46
+ *
47
+ * @since 4.8.1
48
+ */
49
+ public function getVersion();
50
+
51
+ /**
52
+ * @since 4.8.1
53
+ * @return ComponentFactoryInterface The factory used by this add-on to create component instances.
54
+ */
55
+ public function getFactory();
56
+
57
+ /**
58
+ * @since 4.8.1
59
+ * @return bool Whether or not the log entry has been processed
60
+ */
61
+ public function log($level, $message, array $context = array());
62
+
63
+ /**
64
+ * @since 4.8.1
65
+ * @return Core\Model\LoggerInterface
66
+ */
67
+ public function getLogger();
68
+
69
+ /**
70
+ * Creates an exception instance.
71
+ *
72
+ * @since 4.8.1
73
+ * @param string $text The message text.
74
+ * @param string $class The class name of the exception to throw.
75
+ * @param string|null $translate Something that would be used to translate the message.
76
+ * @return \Exception An exception instance.
77
+ */
78
+ public function exception($text, $class = null, $translate = null);
79
+
80
+ /**
81
+ * Override this, and inside this method hook into the environment
82
+ *
83
+ * @since 4.8.1
84
+ */
85
+ public function hook();
86
+
87
+
88
+ /**
89
+ * Add an event listener.
90
+ *
91
+ * @since 4.8.1
92
+ * @param string $name Event name.
93
+ * @param callable $listener The event listener.
94
+ * @param null|array $data Additional data to be passed to event handlers. May not work on native system events.
95
+ * If the event gets passed data with same names when raised, they will override data passed here.
96
+ * @param int|null $priority Order priority of the listener. If null, implementation-specific default will be assumed.
97
+ * @param int|null $acceptedArgs The number of arguments to be passed to the handler. If null,
98
+ * implementation-specific default will be assumed.
99
+ */
100
+ public function on($name, $listener, $data = null, $priority = null, $acceptedArgs = null);
101
+
102
+ /**
103
+ * Raise an event.
104
+ *
105
+ * This triggers all event handlers.
106
+ *
107
+ * @since 4.8.1
108
+ * @param string $name Name of the event to raise
109
+ * @param array $data The data to pass to the event handlers. This will be passed as the first and only argument.
110
+ * If additional data members were passed with {@see PluginInterface::on()}, members passed here will override.
111
+ * @return Core\Model\Event\EventInterface
112
+ */
113
+ public function event($name, $data = array());
114
+
115
+ /**
116
+ * Get the instance of the event manager that the plugin uses.
117
+ *
118
+ * @since 4.8.1
119
+ * @return Core\Model\Event\EventManagerInterface
120
+ */
121
+ public function getEventManager();
122
+
123
+
124
+ /**
125
+ * Get this instance's event prefix, or a prefixed event name.
126
+ *
127
+ * An event prefix is a prefix that will by default be added to names of events
128
+ * that are listened to or raised by this instance.
129
+ *
130
+ * The event prefix is by default the plugin code followed by an underscore "_", unless the code is
131
+ * not set, in which case the prefix is empty.
132
+ *
133
+ * @since 4.8.1
134
+ * @param string|null $name An event name to prefix.
135
+ * @return string This instance's event prefix, or a prefixed name.
136
+ */
137
+ public function getEventPrefix($name = null);
138
+ }
includes/admin-addons.php CHANGED
@@ -8,70 +8,7 @@
8
  */
9
  function wprss_addons_page_display() {
10
 
11
- $premium = array();
12
- $premium[] = array(
13
- 'title' => __( "Excerpts & Thumbnails", WPRSS_TEXT_DOMAIN ),
14
- 'description' => __( "Adds the ability to display thumbnails and excerpts. Perfect for adding some life and color to your feed item display. For more flexibility Feed to Post is a better option.", WPRSS_TEXT_DOMAIN ),
15
- 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
16
- 'active' => is_plugin_active( 'wp-rss-excerpts-thumbnails/wp-rss-excerpts-thumbnails.php' ),
17
- 'installed_inactive' => wprss_is_plugin_inactive( 'wp-rss-excerpts-thumbnails/wp-rss-excerpts-thumbnails.php' ),
18
- 'path' => 'wp-rss-excerpts-thumbnails/wp-rss-excerpts-thumbnails.php',
19
- 'url' => 'http://www.wprssaggregator.com/extension/excerpts-thumbnails/'
20
- );
21
- $premium[] = array(
22
- 'title' => __( "Categories", WPRSS_TEXT_DOMAIN ),
23
- 'description' => __( "Assign categories to your feed sources. Then display a particular category or multiple categories on a post or page via shortcodes.", WPRSS_TEXT_DOMAIN ),
24
- 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
25
- 'active' => is_plugin_active( 'wp-rss-categories/wp-rss-categories.php' ),
26
- 'installed_inactive' => wprss_is_plugin_inactive( 'wp-rss-categories/wp-rss-categories.php' ),
27
- 'path' => 'wp-rss-categories/wp-rss-categories.php',
28
- 'url' => 'http://www.wprssaggregator.com/extension/categories/'
29
- );
30
- $premium[] = array(
31
- 'title' => __( "Keyword Filtering", WPRSS_TEXT_DOMAIN ),
32
- 'description' => __( "Import feeds that contain specific keywords in either the title or their content. Control what gets imported to your blog. You can use keywords, keyphrases and categories.", WPRSS_TEXT_DOMAIN ),
33
- 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
34
- 'active' => is_plugin_active( 'wp-rss-keyword-filtering/wp-rss-keyword-filtering.php' ),
35
- 'installed_inactive' => wprss_is_plugin_inactive( 'wp-rss-keyword-filtering/wp-rss-keyword-filtering.php' ),
36
- 'path' => 'wp-rss-keyword-filtering/wp-rss-keyword-filtering.php',
37
- 'url' => 'http://www.wprssaggregator.com/extension/keyword-filtering/'
38
- );
39
- $premium[] = array(
40
- 'title' => __( "Feed to Post", WPRSS_TEXT_DOMAIN ),
41
- 'description' => __( "Allows you to import feed items into posts or any other custom post type that you have created. Takes WP RSS Aggregator to a whole new level of flexibility.", WPRSS_TEXT_DOMAIN ),
42
- 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
43
- 'active' => is_plugin_active( 'wp-rss-feed-to-post/wp-rss-feed-to-post.php' ),
44
- 'installed_inactive' => wprss_is_plugin_inactive( 'wp-rss-feed-to-post/wp-rss-feed-to-post.php' ),
45
- 'path' => 'wp-rss-feed-to-post/wp-rss-feed-to-post.php',
46
- 'url' => 'http://www.wprssaggregator.com/extension/feed-to-post/'
47
- );
48
- $premium[] = array(
49
- 'title' => __( "Full Text RSS Feeds", WPRSS_TEXT_DOMAIN ),
50
- 'description' => __( "This add-ons provides the connectivity to our Full Text Premium service, which gives you unlimited feed items returned per feed source.", WPRSS_TEXT_DOMAIN ),
51
- 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
52
- 'active' => is_plugin_active( 'wp-rss-full-text-feeds/wp-rss-full-text.php' ),
53
- 'installed_inactive' => wprss_is_plugin_inactive( 'wp-rss-full-text-feeds/wp-rss-full-text.php' ),
54
- 'path' => 'wp-rss-full-text-feeds/wp-rss-full-text.php',
55
- 'url' => 'http://www.wprssaggregator.com/extension/full-text-rss-feeds/'
56
- );
57
- $premium[] = array(
58
- 'title' => __( "WordAi", WPRSS_TEXT_DOMAIN ),
59
- 'description' => __( "Allows you to spin the content for posts imported by Feed to Post using WordAi. Cleverly rewrite your posts without changing their meaning and maintaining human readability.", WPRSS_TEXT_DOMAIN ),
60
- 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
61
- 'active' => is_plugin_active( 'wp-rss-wordai/wp-rss-wordai.php' ),
62
- 'installed_inactive' => wprss_is_plugin_inactive( 'wp-rss-wordai/wp-rss-wordai.php' ),
63
- 'path' => 'wp-rss-wordai/wp-rss-wordai.php',
64
- 'url' => 'http://www.wprssaggregator.com/extension/wordai/'
65
- );
66
- $premium[] = array(
67
- 'title' => __( "Widget", WPRSS_TEXT_DOMAIN ),
68
- 'description' => __( "An add-on for WP RSS Aggregator that displays your imported feed items in a widget on your site. Intergrates well with Excerpts &amp; Thumbnails", WPRSS_TEXT_DOMAIN ),
69
- 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
70
- 'active' => is_plugin_active( 'wp-rss-widget/wp-rss-widget.php' ),
71
- 'installed_inactive' => wprss_is_plugin_inactive( 'wp-rss-widget/wp-rss-widget.php' ),
72
- 'path' => 'wp-rss-widget/wp-rss-widget.php',
73
- 'url' => 'http://www.wprssaggregator.com/extension/widget/'
74
- );
75
 
76
  ?>
77
  <div class="wrap">
@@ -84,8 +21,10 @@
84
  <div id="add-ons" class="clearfix">
85
 
86
  <div class="add-on-group clearfix">
87
- <?php foreach( $premium as $addon ): ?>
88
- <div class="add-on wp-box <?php if( $addon['active'] ): ?>add-on-active<?php endif; ?>">
 
 
89
  <!-- <a target="_blank" href="<?php echo $addon['url']; ?>">
90
  <img src="<?php echo $addon['thumbnail']; ?>" />
91
  </a> -->
@@ -94,10 +33,10 @@
94
  <p><?php echo $addon['description']; ?></p>
95
  </div>
96
  <div class="footer">
97
- <?php if( $addon['active'] ): ?>
98
  <a class="button button-disabled"><span class="wprss-sprite-tick"></span><?php _e( "Installed", WPRSS_TEXT_DOMAIN ); ?></a>
99
- <?php elseif( $addon['installed_inactive'] ): ?>
100
- <a class="button" href="<?php echo wp_nonce_url('plugins.php?action=activate&amp;plugin='.$addon['path'], 'activate-plugin_'.$addon['path'] ) ?>"><?php _e( "Activate", WPRSS_TEXT_DOMAIN ); ?></a>
101
  <?php else: ?>
102
  <a target="_blank" href="<?php echo $addon['url']; ?>" class="button"><?php _e( "Purchase & Install", WPRSS_TEXT_DOMAIN ); ?></a>
103
  <?php endif; ?>
@@ -113,6 +52,68 @@
113
  <?php
114
 
115
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
  /**
118
  * Check if plugin file exists but plugin is inactive
8
  */
9
  function wprss_addons_page_display() {
10
 
11
+ $premium = wprss_addons_get_extra();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  ?>
14
  <div class="wrap">
21
  <div id="add-ons" class="clearfix">
22
 
23
  <div class="add-on-group clearfix">
24
+ <?php foreach( $premium as $_code => $addon ): ?>
25
+ <?php $isActive = is_plugin_active($addon['basename']) ?>
26
+ <?php $isInstalledInactive = wprss_is_plugin_inactive($addon['basename']) ?>
27
+ <div class="add-on wp-box<?php if( $isActive ): ?> add-on-active<?php endif; ?> <?php echo sprintf('add-on-code-%1$s', $_code) ?>">
28
  <!-- <a target="_blank" href="<?php echo $addon['url']; ?>">
29
  <img src="<?php echo $addon['thumbnail']; ?>" />
30
  </a> -->
33
  <p><?php echo $addon['description']; ?></p>
34
  </div>
35
  <div class="footer">
36
+ <?php if( $isActive ): ?>
37
  <a class="button button-disabled"><span class="wprss-sprite-tick"></span><?php _e( "Installed", WPRSS_TEXT_DOMAIN ); ?></a>
38
+ <?php elseif( $isInstalledInactive ): ?>
39
+ <a class="button" href="<?php echo wp_nonce_url('plugins.php?action=activate&amp;plugin='.$addon['basename'], 'activate-plugin_'.$addon['basename'] ) ?>"><?php _e( "Activate", WPRSS_TEXT_DOMAIN ); ?></a>
40
  <?php else: ?>
41
  <a target="_blank" href="<?php echo $addon['url']; ?>" class="button"><?php _e( "Purchase & Install", WPRSS_TEXT_DOMAIN ); ?></a>
42
  <?php endif; ?>
52
  <?php
53
 
54
  }
55
+
56
+ function wprss_addons_get_extra()
57
+ {
58
+ return apply_filters('wprss_extra_addons', array(
59
+ 'et' => array(
60
+ 'title' => 'Excerpts & Thumbnails',
61
+ 'description' => __("Adds the ability to display thumbnails and excerpts. Perfect for adding some life and color to your feed item display. For more flexibility Feed to Post is a better option.", WPRSS_TEXT_DOMAIN),
62
+ 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
63
+ 'basename' => 'wp-rss-excerpts-thumbnails/wp-rss-excerpts-thumbnails.php',
64
+ 'url' => 'http://www.wprssaggregator.com/extension/excerpts-thumbnails/'
65
+ ),
66
+ 'c' => array(
67
+ 'title' => 'Categories',
68
+ 'description' => __("Assign categories to your feed sources. Then display a particular category or multiple categories on a post or page via shortcodes.", WPRSS_TEXT_DOMAIN),
69
+ 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
70
+ 'basename' => 'wp-rss-categories/wp-rss-categories.php',
71
+ 'url' => 'http://www.wprssaggregator.com/extension/categories/'
72
+ ),
73
+ 'kf' => array(
74
+ 'title' => 'Keyword Filtering',
75
+ 'description' => __("Import feeds that contain specific keywords in either the title or their content. Control what gets imported to your blog. You can use keywords, keyphrases and categories.", WPRSS_TEXT_DOMAIN),
76
+ 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
77
+ 'basename' => 'wp-rss-keyword-filtering/wp-rss-keyword-filtering.php',
78
+ 'url' => 'http://www.wprssaggregator.com/extension/keyword-filtering/'
79
+ ),
80
+ 'ftp' => array(
81
+ 'title' => 'Feed to Post',
82
+ 'description' => __("Allows you to import feed items into posts or any other custom post type that you have created. Takes WP RSS Aggregator to a whole new level of flexibility.", WPRSS_TEXT_DOMAIN),
83
+ 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
84
+ 'basename' => 'wp-rss-feed-to-post/wp-rss-feed-to-post.php',
85
+ 'url' => 'http://www.wprssaggregator.com/extension/feed-to-post/'
86
+ ),
87
+ 'ftr' => array(
88
+ 'title' => 'Full Text RSS Feeds',
89
+ 'description' => __("This add-ons provides the connectivity to our Full Text Premium service, which gives you unlimited feed items returned per feed source.", WPRSS_TEXT_DOMAIN),
90
+ 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
91
+ 'basename' => 'wp-rss-full-text-feeds/wp-rss-full-text.php',
92
+ 'url' => 'http://www.wprssaggregator.com/extension/full-text-rss-feeds/'
93
+ ),
94
+ 'wai' => array(
95
+ 'title' => 'WordAi',
96
+ 'description' => __("Allows you to spin the content for posts imported by Feed to Post using WordAi. Cleverly rewrite your posts without changing their meaning and maintaining human readability.", WPRSS_TEXT_DOMAIN),
97
+ 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
98
+ 'basename' => 'wp-rss-wordai/wp-rss-wordai.php',
99
+ 'url' => 'http://www.wprssaggregator.com/extension/wordai/'
100
+ ),
101
+ 'widget' => array(
102
+ 'title' => 'Widget',
103
+ 'description' => __("An add-on for WP RSS Aggregator that displays your imported feed items in a widget on your site. Intergrates well with Excerpts &amp; Thumbnails", WPRSS_TEXT_DOMAIN),
104
+ 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
105
+ 'basename' => 'wp-rss-widget/wp-rss-widget.php',
106
+ 'url' => 'http://www.wprssaggregator.com/extension/widget/'
107
+ ),
108
+ 'spc' => array(
109
+ 'title' => 'SpinnerChief',
110
+ 'description' => __("An extension for Feed to Post that allows you to integrate the SpinnerChief article spinner so that the imported content is both completely unique and completely readable.", WPRSS_TEXT_DOMAIN),
111
+ 'thumbnail' => WPRSS_IMG . 'add-ons/wprss.jpg',
112
+ 'basename' => 'wp-rss-spinnerchief/wp-rss-spinnerchief.php',
113
+ 'url' => 'http://www.wprssaggregator.com/extension/spinnerchief/'
114
+ )
115
+ ));
116
+ }
117
 
118
  /**
119
  * Check if plugin file exists but plugin is inactive
includes/admin-dashboard.php CHANGED
@@ -28,7 +28,7 @@
28
  'wprss-welcome',
29
  'wprss_show_welcome_screen'
30
  );
31
-
32
  }
33
 
34
 
@@ -96,4 +96,32 @@
96
  /*]]>*/
97
  </style>
98
  <?php
99
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  'wprss-welcome',
29
  'wprss_show_welcome_screen'
30
  );
31
+
32
  }
33
 
34
 
96
  /*]]>*/
97
  </style>
98
  <?php
99
+ }
100
+
101
+ add_filter( 'admin_footer_text', 'wprss_admin_footer' );
102
+ /**
103
+ * Adds footer text on the plugin pages.
104
+ *
105
+ * @param string $footer The footer text to filter
106
+ * @return string The filtered footer text with added plugin text, or the param
107
+ * value if the page is not specific to the plugin.
108
+ */
109
+ function wprss_admin_footer( $footer ) {
110
+ // Current post type
111
+ global $typenow;
112
+ // Check if type is a plugin type. If not, stop
113
+ // Plugin type is in the form 'wprss_*'' where * is 'feed', 'blacklist', etc)
114
+ if ( stripos( $typenow, 'wprss_' ) !== 0 )
115
+ return $footer;
116
+ // Prepare fragments of the message
117
+ $thank_you = sprintf(
118
+ __( 'Thank you for using <a href="%1$s" target="_blank">WP RSS Aggregator</a>!', WPRSS_TEXT_DOMAIN ),
119
+ 'http://www.wprssaggregator.com/'
120
+ );
121
+ $rate_us = sprintf(
122
+ __( 'Please <a href="%1$s" target="_blank">rate us</a>!', WPRSS_TEXT_DOMAIN ),
123
+ 'https://wordpress.org/support/view/plugin-reviews/wp-rss-aggregator?filter=5#postform'
124
+ );
125
+ // Return the final text
126
+ return sprintf( '%1$s | <span class="wp-rss-footer-text">%2$s %3$s</span>', $footer, $thank_you, $rate_us );
127
+ }
includes/admin-help.php CHANGED
@@ -57,28 +57,44 @@
57
  * @since 4.7
58
  */
59
  function wprss_premium_help_display() {
60
- // Get the first valid license.
61
- $addon = '';
 
 
 
62
  $statuses = get_option( 'wprss_settings_license_statuses', array() );
63
- foreach ( $statuses as $key => $value ) {
64
- // If we're looking at a license status key...
65
- if ( strpos($key, '_license_status') !== FALSE ) {
66
- // ...and the license is valid...
67
- if ($value === 'valid') {
68
- $addon = substr( $key, 0, strpos( $key, '_license_status' ) );
69
- break;
70
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  }
72
  }
73
 
74
  // If we didn't find an add-on with a valid license, show the free help text.
75
- if ( $addon === '' ) {
76
  wprss_free_help_display();
77
  return;
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
 
57
  * @since 4.7
58
  */
59
  function wprss_premium_help_display() {
60
+ // Addon and license object, both detected in the below algorithm that searches for a
61
+ // premium addon that is activated with a valid license
62
+ $addon = null;
63
+ $license = null;
64
+ // Get license statuses option
65
  $statuses = get_option( 'wprss_settings_license_statuses', array() );
66
+ // Iterate all statuses
67
+ foreach ( $statuses as $_key => $_value ) {
68
+ // If not a license status key, continue to next
69
+ $_keyPos = strpos($_key, '_license_status');
70
+ if ( $_keyPos === FALSE ) {
71
+ continue;
72
+ }
73
+ // If the status is not valid, contine to next
74
+ if ($_value !== 'valid') {
75
+ continue;
76
+ }
77
+ // Get the addon ID
78
+ $_addonId = substr( $_key, 0, $_keyPos );
79
+ // Get the license
80
+ $_license = wprss_licensing_get_manager()->checkLicense( $_addonId, 'ALL' );
81
+ // If the license is not null
82
+ if ($_license !== null) {
83
+ // Save its details
84
+ $addon = $_addonId;
85
+ $license = $_license;
86
+ // And stop iterating
87
+ break;
88
  }
89
  }
90
 
91
  // If we didn't find an add-on with a valid license, show the free help text.
92
+ if ( $addon === null || $license === null ) {
93
  wprss_free_help_display();
94
  return;
95
  }
96
 
97
  // Get the full license info so we can prefill the name and email
 
98
  $customer_name = is_object($license) ? $license->customer_name : '';
99
  $customer_email = is_object($license) ? $license->customer_email : '';
100
 
includes/functions.php ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Helper and misc functions.
4
+ *
5
+ * @todo Make this part of Core instead
6
+ */
7
+
8
+ if (!function_exists('wprss_get_namespace')) {
9
+
10
+ /**
11
+ * Get the namespace of a class
12
+ *
13
+ * @since 1.0
14
+ * @param string|object|null $class The class name or instance, for which to get the namespace.
15
+ * @param int|null $depth The depth of the namespace to retrieve.
16
+ * If omitted, the whole namespace will be retrieved.
17
+ * @param bool $asString If true, the result will be a string; otherwise, array with namespace parts.
18
+ * @return array|string The namespace of the class.
19
+ */
20
+ function wprss_get_namespace($class, $depth = null, $asString = false)
21
+ {
22
+ $ns = '\\';
23
+
24
+ // Can accept an instance
25
+ if (is_object($class)) {
26
+ $class = get_class($class);
27
+ }
28
+
29
+ $namespace = explode($ns, (string) $class);
30
+
31
+ // This was a root class name, no namespace
32
+ array_pop($namespace);
33
+ if (!count($namespace)) {
34
+ return null;
35
+ }
36
+
37
+ $namespace = array_slice($namespace, 0, $depth);
38
+
39
+ return $asString ? implode($ns, $namespace) : $namespace;
40
+ }
41
+ }
42
+
43
+ if (!function_exists('wprss_is_root_namespace')) {
44
+
45
+ /**
46
+ * Check if a namespace is a root namespace.
47
+ *
48
+ * @since 1.0
49
+ * @param string $namespace The namespace to check.
50
+ * @param bool $checkClass If true, and a class or interface with the name of the specified namespace exists,
51
+ * will make this function return true. Otherwise, the result depends purely on the namespace string.
52
+ * @return boolean True if the namespace is a root namespace; false otherwise.
53
+ */
54
+ function wprss_is_root_namespace($namespace, $checkClass = true) {
55
+ $isRoot = substr($namespace, 0, 1) === '\\';
56
+ return $checkClass
57
+ ? $isRoot || class_exists($namespace)
58
+ : $isRoot;
59
+ }
60
+ }
61
+
62
+ if (!function_exists('string_had_prefix')) {
63
+
64
+ /**
65
+ * Check for and possibly remove a prefix from a string.
66
+ *
67
+ * @since 1.0
68
+ * @param string $string The string to check and normalize.
69
+ * @param string $prefix The prefix to check for.
70
+ * @return string Checks if a string starts with the specified prefix.
71
+ * If yes, removes it and returns true; otherwise, false;
72
+ */
73
+ function string_had_prefix(&$string, $prefix)
74
+ {
75
+ $prefixLength = strlen($prefix);
76
+ if (substr($string, 0, $prefixLength) === $prefix) {
77
+ $string = substr($string, $prefixLength);
78
+ return true;
79
+ }
80
+
81
+ return false;
82
+ }
83
+ }
84
+
85
+ if (!function_exists('uri_is_absolute')) {
86
+
87
+ /**
88
+ * Check if the URI is absolute.
89
+ *
90
+ * Check is made based on whether or not there's a '//' sequence
91
+ * somewhere in the beginning.
92
+ *
93
+ * @since 1.0
94
+ * @param string $uri The URI to check.
95
+ * @return boolean True of the given string contains '//' within the first 10 chars;
96
+ * otherwise, false.
97
+ */
98
+ function uri_is_absolute($uri)
99
+ {
100
+ $beginning = substr($uri, 0, 10);
101
+ return strpos($beginning, '//') !== false;
102
+ }
103
+ }
104
+
105
+ if ( ! function_exists('array_merge_recursive_distinct') ) {
106
+ /**
107
+ * array_merge_recursive does indeed merge arrays, but it converts values with duplicate
108
+ * keys to arrays rather than overwriting the value in the first array with the duplicate
109
+ * value in the second array, as array_merge does. I.e., with array_merge_recursive,
110
+ * this happens (documented behavior):
111
+ *
112
+ * array_merge_recursive(array('key' => 'org value'), array('key' => 'new value'));
113
+ * => array('key' => array('org value', 'new value'));
114
+ *
115
+ * array_merge_recursive_distinct does not change the datatypes of the values in the arrays.
116
+ * Matching keys' values in the second array overwrite those in the first array, as is the
117
+ * case with array_merge, i.e.:
118
+ *
119
+ * array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value'));
120
+ * => array('key' => array('new value'));
121
+ *
122
+ * Parameters are passed by reference, though only for performance reasons. They're not
123
+ * altered by this function.
124
+ *
125
+ * @since 1.0
126
+ * @param array $array1
127
+ * @param array $array2
128
+ * @return array
129
+ * @author Daniel <daniel (at) danielsmedegaardbuus (dot) dk>
130
+ * @author Gabriel Sobrinho <gabriel (dot) sobrinho (at) gmail (dot) com>
131
+ */
132
+ function array_merge_recursive_distinct ( array &$array1, array &$array2 ) {
133
+ $merged = $array1;
134
+ foreach ( $array2 as $key => &$value ) {
135
+ if ( is_array ( $value ) && isset ( $merged [$key] ) && is_array ( $merged [$key] ) ) {
136
+ $merged [$key] = array_merge_recursive_distinct ( $merged [$key], $value );
137
+ }
138
+ else $merged [$key] = $value;
139
+ }
140
+ return $merged;
141
+ }
142
+ }
143
+
144
+ if (!function_exists('array_pick')) {
145
+
146
+ /**
147
+ * Picks values with certain keys from an array.
148
+ *
149
+ * @since 1.0
150
+ * @param array $array An array, from which to pick. Will not be modified; passed by refrence for efficiency.
151
+ * @param string|int|array $keys A key or array of keys to pick.
152
+ * @return array
153
+ */
154
+ function array_pick($array, $keys)
155
+ {
156
+ $keys = (array)$keys;
157
+ return array_intersect_key($array, array_flip($keys));
158
+ }
159
+ }
includes/image-caching.php CHANGED
@@ -481,7 +481,7 @@ class WPRSS_Image_Cache {
481
  if ( !is_null( $target_path ) )
482
  $path = $target_path;
483
 
484
- if ( is_null( $request_timeout ) )
485
  $timeout = $request_timeout;
486
 
487
  // Absolute path to the cache file
481
  if ( !is_null( $target_path ) )
482
  $path = $target_path;
483
 
484
+ if ( !is_null( $request_timeout ) )
485
  $timeout = $request_timeout;
486
 
487
  // Absolute path to the cache file
includes/system-info.php CHANGED
@@ -30,7 +30,10 @@
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
 
30
  </textarea>
31
  <p class="submit">
32
  <input type="hidden" name="wprss-action" value="download_sysinfo" />
33
+ <button type="submit" class="button button-primary" id="wprss-download-sysinfo">
34
+ <i class="fa fa-download"></i>
35
+ <?php _e( 'Download System Info File', WPRSS_TEXT_DOMAIN ) ?>
36
+ </button>
37
  </p>
38
  </form>
39
 
readme.txt CHANGED
@@ -3,79 +3,79 @@ 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.4
7
- Stable tag: 4.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
 
@@ -87,31 +87,24 @@ Instructions for plugin usage are available on the plugin's [documentation page]
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(
@@ -153,7 +146,7 @@ No, our plugin does not currently import from JSON, it only imports from RSS and
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
 
@@ -169,11 +162,11 @@ Yes, along with the [Feed to Post](http://www.wprssaggregator.com/extensions/fee
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 ==
@@ -193,6 +186,13 @@ The full documentation section can be found on the [WP RSS Aggregator website](h
193
 
194
  == Changelog ==
195
 
 
 
 
 
 
 
 
196
  = 4.8 (2015-12-30) =
197
  * Fixed bug: Licensing notices will now be displayed again.
198
  * Enhanced: Major licensing system improvements.
@@ -709,708 +709,5 @@ Fixed bug: Broken links in the "Add-ons" page, to add-on pages on our site.
709
  * Code refactoring
710
  * Changes in file and folder structure
711
 
712
- = Version 1.0 (2012-01-06) =
713
- === WP RSS Aggregator ===
714
- Contributors: jeangalea, Mekku, xedin.unknown, markzahra, doytch, chiragswadia
715
- Plugin URI: http://www.wprssaggregator.com
716
- 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
717
- Requires at least: 4.0
718
- Tested up to: 4.3.1
719
- Stable tag: 4.7.7
720
- License: GPLv2 or later
721
- The no.1 RSS feed importer for WordPress. Premium add-ons available for more functionality.
722
-
723
-
724
- == Description ==
725
-
726
- WP RSS Aggregator is the most comprehensive and elegant RSS feed solution for WordPress.
727
-
728
- The original and premier plugin for importing, merging and displaying RSS and Atom feeds on your WordPress site.
729
-
730
- With WP RSS Aggregator, you can:
731
-
732
- * Display feeds from one or more sites on your blog
733
- * Aggregate feeds from multiple sites
734
-
735
- 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.
736
-
737
- 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.
738
-
739
- = Highlighted Features =
740
-
741
- * Export a custom RSS feed based on your feed sources
742
- * Pagination
743
- * Set the feed import time interval
744
- * Scheduling of feed imports by feed source
745
- * Various shortcode parameters you can use to further customize the output
746
- * Choose whether to show/hide sources and dates
747
- * Choose the date format
748
- * Set the links as no-follow or not, or add no follow to meta tag
749
- * Select how you would like the links to open (in a Lightbox, a new window, or the current window)
750
- * Set the name of the feed source
751
- * Select number of posts per feed you want to show and store
752
- * Opens YouTube, DailyMotion and Vimeo videos directly
753
- * Limit number of feed items stored in the database
754
- * Feed autodiscovery, which lets you add feeds without even knowing the exact URL.
755
- * Extendable via action and filter hooks
756
- * 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.
757
-
758
- = Premium Add-Ons =
759
- Add-Ons that add more functionality to the core plugin are [available for purchase](http://www.wprssaggregator.com/extensions/).
760
-
761
- * [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.
762
- * [Keyword Filtering](http://www.wprssaggregator.com/extensions/keyword-filtering) - filter imported feeds based on keywords, so you only get items you're interested in.
763
- * [Excerpts & Thumbnails](http://www.wprssaggregator.com/extensions/excerpts-thumbnails) - display excerpts and thumbnails together with the title, date and source.
764
- * [Categories](http://www.wprssaggregator.com/extensions/categories) - categorise your feed sources and display items from a particular category at will within your site.
765
- * [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.
766
- * [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.
767
- * [Widget](http://www.wprssaggregator.com/extension/widget/) - Add a widget that displays imported feed items.
768
-
769
- 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.
770
-
771
- = Demo =
772
- The core plugin can be seen in use on the [demo page](http://www.wprssaggregator.com/demo/).
773
-
774
- = Video Walkthrough =
775
- [youtube http://www.youtube.com/watch?v=fcENPsmJbvc]
776
-
777
- = Documentation =
778
- Instructions for plugin usage are available on the plugin's [documentation page](http://www.wprssaggregator.com/documentation/).
779
-
780
- = As featured on =
781
- * [Latest WP](http://www.latestwp.com/2015/03/15/wp-rss-aggregator-plugin-review/)
782
- * [WP Beginner](http://www.wpbeginner.com/plugins/how-to-fetch-feeds-in-wordpress-using-wp-rss-aggregator/)
783
- * [WPEXplorer](http://www.wpexplorer.com/custom-rss-aggregator-plugin/)
784
- * [WP Kube](http://www.wpkube.com/wp-rss-aggregator-wordpress-review/)
785
- * [Torquemag](http://torquemag.io/wp-rss-aggregator-review-do-more-with-rss-feeds/)
786
- * [MyWPExpert](http://www.mywpexpert.com/wordpress-rss-aggregator-plugin)
787
- * [Kikolani](http://kikolani.com/create-latest-posts-portfolio-page-wp-rss-aggregator.html)
788
- * [ManageWP Plugins of the Month](http://managewp.com/free-wordpress-plugins-march-2014)
789
- * [TidyRepo](http://tidyrepo.com/wp-rss-aggregator/)
790
- * [WP Eka](http://www.wpeka.com/wp-rss-aggregators-plugin.html)
791
- * [IndexWP](www.indexwp.com/wp-rss-aggregator-plugin-review/)
792
- * [WPulsar](http://www.wpulsar.com/wp-rss-aggregator-plugin-feed-to-posts-keyword-filtering-review/)
793
- * [Kevin Muldoon](http://www.kevinmuldoon.com/wp-rss-aggregator-wordpress-plugin/)
794
-
795
- = Translations =
796
- * Italian - Davide De Maestri
797
- * Spanish - Andrew Kurtis
798
- * Brazilian Portugese - Bruno Calheira
799
- * Dutch - Erick Suiker
800
-
801
- == Installation ==
802
-
803
- 1. Upload the `wp-rss-aggregator` folder to the `/wp-content/plugins/` directory
804
- 2. Activate the WP RSS Aggregator plugin through the 'Plugins' menu in WordPress
805
- 3. Configure the plugin by going to the `RSS Aggregator` menu item that appears in your dashboard menu.
806
- 3. Use the shortcode in your posts or pages: `[wp-rss-aggregator]`
807
-
808
- The parameters accepted are:
809
-
810
- * links_before
811
- * links_after
812
- * link_before
813
- * link_after
814
- * limit
815
- * source
816
- * exclude
817
- * pagination
818
-
819
- An example of a shortcode with parameters:
820
- `[wp_rss_aggregator link_before='<li class="feed-link">' link_after='</li>']`
821
- It is advisable to use the 'HTML' view of the editor when inserting the shortcode with paramters.
822
-
823
- For a full list of shortcode parameters and usage guide please refer to the [documentation](http://www.wprssaggregator.com/docs/shortcodes/).
824
-
825
- __Usage within theme files__
826
-
827
- An example of a function call from within the theme's files:
828
- `
829
- <?php
830
- wprss_display_feed_items( $args = array(
831
- 'links_before' => '<ul>',
832
- 'links_after' => '</ul>',
833
- 'link_before' => '<li>',
834
- 'link_after' => '</li>',
835
- 'limit' => '8',
836
- 'source' => '5,9'
837
- ));
838
- ?>
839
- `
840
-
841
- OR
842
-
843
- `<?php do_shortcode('[wp-rss-aggregator]'); ?>`
844
-
845
-
846
- == Frequently Asked Questions ==
847
- = How do I display the imported feed items? =
848
-
849
- You can either use the shortcode in your posts and pages:
850
- `[wp-rss-aggregator]`
851
-
852
- or you can call the function directly within your theme:
853
- `<?php wprss_display_feed_items(); ?>`
854
-
855
- = Is there a limit on the number of feed sources I can use? =
856
-
857
- There is no limit in place for the number of feed sources. Having many (50+) feed sources should not present any problems in itself.
858
-
859
- 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.
860
-
861
- Check out our dedicated page for hosting recommendations.
862
-
863
- = Does WP RSS Aggregator work using JSON as the source? =
864
-
865
- No, our plugin does not currently import from JSON, it only imports from RSS and Atom structured XML.
866
-
867
- = Why do I get “No feed items found” when I insert the shortcode on a page or post? =
868
-
869
- Try adding a few more feed sources and make sure they are valid by using the RSS Feed validator.
870
-
871
- 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.
872
-
873
- = Can I store imported feed items as posts? =
874
-
875
- 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.
876
-
877
- = Some RSS feeds only give a short excerpt. Any way around that? =
878
-
879
- 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.
880
-
881
- = I’m not sure which premium add-ons are right for me. Can you help me out? =
882
-
883
- 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.
884
-
885
- If you need any further help you can contact our support team [here](http://www.wprssaggregator.com/contact/).
886
-
887
- = Where can I find the documentation for the plugin? =
888
-
889
- 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.
890
-
891
-
892
- == Screenshots ==
893
-
894
- 1. Feed items imported by WP RSS Aggregator displayed on the front-end using the shortcode.
895
-
896
- 2. Feed Items imported by WP RSS Aggregator and displayed with the [Excerpts & Thumbnails](http://www.wprssaggregator.com/extensions/excerpts-thumbnails) add-on installed.
897
-
898
- 3. Adding/Editing a feed source.
899
-
900
- 4. The feed sources.
901
-
902
- 5. The imported feeds items.
903
-
904
- 6. WP RSS Aggregator's Settings page.
905
-
906
-
907
- == Changelog ==
908
-
909
- = 4.7.7 (2015-10-19) =
910
- * Enhanced: Optimized checking for plugin updates.
911
-
912
- = 4.7.6 (2015-10-07) =
913
- * Enhanced: Feeds that fail to validate due to whitespace at the beginning are now supported by the plugin.
914
- * Fixed bug: Undefined variables in the System Info section in the Debugging page.
915
- * Fixed bug: Add-on license expiration notices could not be dismissed.
916
-
917
- = 4.7.5 (2015-09-02) =
918
- * Usage tracking now disabled.
919
- * Fixed bug: error related to undefined `ajaxurl` JS variable gone from frontend.
920
- * Enhanced: Licensing errors will be output to debug log.
921
- * Enhanced: Improved compatibility with plugins that allow AJAX searching in the backend.
922
-
923
- = 4.7.4 (2015-08-20) =
924
- * Requirement: WordPress 4.0 or greater now required.
925
- * Fixed bug in image caching
926
- * Fixed bug in admin interface due to incorrectly translated IDs
927
-
928
- = 4.7.3 (2015-08-04) =
929
- * Enhanced: Core now implements an image cache logic.
930
- * Enhanced: Add-ons on the "Add-ons" page now have an installed-but-inactive status.
931
- * Enhanced: Google Alerts permalinks will now be normalized.
932
- * Enhanced: Russian translation added.
933
- * Fixed bug: Inline help (tooltips) translations now work.
934
- * Fixed bug: Link to the Feed to Post add-on on the welcome page is no longer broken.
935
-
936
- = 4.7.2 (2015-06-30) =
937
- * Enhanced: Copyright updated.
938
- * Fixed bug: Word trimming no longer adds extra closing tags at the end.
939
- * Fixed bug: Presence of `idna_convert` class no longer causes infinite redirects on some servers.
940
- * Fixed bug: Warning of unterminated comment no longer thrown in PHP 5.5.
941
- * Fixed bug: Added default value for "Unique Titles" option.
942
- * 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.
943
- * Fixed bug: Nested options of inline help controller no longer cause a fatal error.
944
- * Fixed bug: Notices will no longer be displayed during rendering of feed items due to absence of required default values.
945
-
946
- = 4.7.1 (2015-04-23) =
947
- * Fixed bug: No warning will be thrown when fetching feeds.
948
-
949
- = 4.7 (2015-04-21) =
950
- * New: Optionally import only items with titles that don't already exist.
951
- * Enhanced: Accessing feeds over HTTPS is now possible.
952
- * Enhanced: Added support for multibyte strings in some places.
953
- * Enhanced: Increased JS compatibility with other plugins.
954
- * Enhanced: Increased UI support for mobile devices.
955
- * Fixed bug: Having no mysqli extension no longer causes an error to appear in the debug info.
956
- * Fixed bug: Saving an empty license key no longer results in a warning.
957
-
958
- = 4.6.13 (2015-03-20) =
959
- * Fixed bug: The "Force feed" option wasn't being correctly used.
960
-
961
- = 4.6.12 (2015-03-09) =
962
- * Fixed bug: The "Force feed" option was being removed by the Feed to Post add-on.
963
-
964
- = 4.6.11 (2015-03-04) =
965
- * Enhanced: The Help page now includes a support form if a premium add-on is detected.
966
- * Enhanced: Updated some translations for admin options.
967
- * Fixed bug: Help tooltips are now optimized for iPad screens.
968
- * Fixed bug: Errors on the licensing page when a license code has not yet been entered.
969
-
970
- = 4.6.10 (2015-02-10) =
971
- * Enhanced: AJAX license activation.
972
- * Enhanced: License form more reliable.
973
- * Enhanced: license-related UI improvements
974
- * New: Markdown library added. Changelog now read from readme.
975
- * Fixed bug: Saving license keys not longer triggers error in some cases.
976
-
977
- = 4.6.9 (2015-01-21) =
978
- * Enhanced: Admin user will now be warned about invalid or expiring licenses.
979
- * Enhanced: Admin notices logic centralized in this plugin.
980
- * Fixed: Multiple small-scale security vulnerabilities.
981
- * Fixed: Ampersand in feed URL no longer causes the product of generated feeds to be invalidated by W3C Validator.
982
-
983
- = 4.6.8 (2015-01-07) =
984
- * Enhanced: Added more logging during feed importing.
985
- * Enhanced: Irrelevent metaboxes added by other plugins are now removed from the Add/Edit Feed Source page.
986
- * Fixed bug: Valid feed URLS were being invalidated.
987
- * Fixed bug: The Blacklist feature was being hidden when the Feed to Post add-on was enabled.
988
- * Fixed bug: Patched a vulnerability where any user on the site can issue a feed fetch.
989
- * Fixed bug: The "Activate" and "Pause" actions are not shown in the bulk actions dropdown in WordPress v4.1.
990
-
991
- = 4.6.7 (2014-12-17) =
992
- * Enhanced: Some minor interface updates.
993
- * Enhanced: Added filters for use by the premium add-ons.
994
-
995
- = 4.6.6 (2014-12-06) =
996
- * Enhanced: Added output layouts for feed sources and feed items.
997
- * Enhanced: Updated EDD updater class to version 1.5.
998
- * Enhanced: Added time limit extending to prevent script from exhausting its execution time limit while importing.
999
- * Fixed bug: The "Delete and Re-import" button was deleting items but not re-importing.
1000
- * Fixed bug: Non-object errors when a feed source is deleted while importing.
1001
-
1002
- = 4.6.5 (2014-11-17) =
1003
- * Enhanced: Improved the logging.
1004
- * Enhanced: Improved the licensing fields.
1005
- * Enhanced: Updated the EDD updater class to the latest version.
1006
- * Fixed bug: Small random error when viewing the licenses page.
1007
-
1008
- = 4.6.4 (2014-11-10) =
1009
- * Enhanced: Added filters to the custom feed.
1010
- * Enhanced: Updated some styles to improve the user interface.
1011
- * Fixed bug: The "Remove selected from Blacklist" button had no nonce associated with it.
1012
- * Fixed bug: The Blacklist menu entry was not always being shown.
1013
-
1014
- = 4.6.3 (2014-11-3) =
1015
- Enhanced: Re-added the "Add New" link in the plugin's menu.
1016
- Enhanced: Improved error logging.
1017
- Enhanced: Bulk actions in the Feed Sources page are now also included in the bottom dropdown menu.
1018
- Fixed bug: Add-on updater was prone to conflicts. Now enclosed in an action.
1019
- Fixed bug: The Full Text RSS Feeds add-on was not showing as active in the "Add-ons" page.
1020
- Fixed bug: Broken links in the "Add-ons" page, to add-on pages on our site.
1021
-
1022
- = 4.6.2 (2014-10-15) =
1023
- * Enhanced: Improved plugin responsiveness.
1024
- * Enhanced: Updated some help text in tooltips with better explainations and added clarity.
1025
- * Enhanced: Optimized some old SQL queries.
1026
- * Enhanced: Added better debug logging.
1027
- * Enhanced: Added a new filter to modify the text shown before author names.
1028
- * Fixed bug: Licenses were not showing as active, even though they were activated.
1029
-
1030
- = 4.6.1 (2014-10-06) =
1031
- * Enhanced: Improved internationalization in the plugin, for better translations.
1032
- * Fixed bug: If the feed source age limit was left empty, the global setting was used instead of ignoring the limit.
1033
-
1034
- = 4.6 (2014-09-22) =
1035
- * Enhanced: Improved the user interface, with better responsiveness and tooltips.
1036
- * Enhanced: Removes the ID column. The ID is now shown fixed in row actions.
1037
- * Enhanced: Feed Preview indicates if feed items have no dates.
1038
- * Fixed bug: If a feed item has no date, the date and time it was imported is used.
1039
-
1040
- = 4.5.3 (2014-09-15) =
1041
- * New Featured: Added filter to allow adding RSS feeds to the head of your site's pages for CPTs.
1042
- * Enhanced: Columns in the feed sources table are now sortable.
1043
- * Enhanced: Removed the ID column in the feed sources table. The ID has been moved as a row action.
1044
- * Enhanced: Improved various interface elements.
1045
- * Enhanced: Better responsiveness for smaller screen.
1046
- * Fixed bug: The importing spinning icon would get stuck and spin for a very long time.
1047
- * Fixed bug: Removed an old description meta field.
1048
- * Fixed bug: Plugin was not removing all scheduled cron jobs when deactivated.
1049
-
1050
- = 4.5.2 (2014-09-09) =
1051
- * Enhanced: Optimized plugin for WordPress 4.0.
1052
- * Enhanced: Improved template and added filters for add-on hooking.
1053
- * Fixed bug: Editor toolbar visible over the WP RSS shortcode dialog.
1054
-
1055
- = 4.5.1 (2014-08-26) =
1056
- * Fixed bug: Last import feed item count stays at zero.
1057
- * Fixed bug: Datetime::setTimestamp error when using PHP 5.2 or earlier.
1058
- * Fixed bug: The display limit was not working.
1059
- * Fixed bug: Minor bug in licensing.
1060
-
1061
- = 4.5 (2014-08-25) =
1062
- * New Feature: Bulk importer allows you to create multiple feed sources at once.
1063
- * Enhanced: Improved OPML importer with added hooks.
1064
- * Enhanced: Centralized add-on licensing, fixing multiple bugs.
1065
- * Fixed bug: Undefined `feed_limit` errors when using the shortcode.
1066
-
1067
- = 4.4.4 (2014-08-19) =
1068
- * Fixed bug: Errors when using older PHP versions 5.3 or lower.
1069
-
1070
- = 4.4.3 (2014-08-19) =
1071
- * Fixed bug: Errors when using older PHP versions 5.3 or lower.
1072
-
1073
- = 4.4.2 (2014-08-19) =
1074
- * Fixed bug: Errors when using older PHP versions 5.3 or lower.
1075
-
1076
- = 4.4.1 (2014-08-18) =
1077
- * Enhanced: Various improvements to the plugin interface and texts.
1078
- * Enhanced: Moved the restore default settings button farther down the Debugging page, to avoid confusion with the delete button.
1079
- * Fixed bug: Feed item dates were not being adjusted to the timezone when using a GMT offset.
1080
- * Fixed bug: Feed item dates are now adjusted according to daylight savings time.
1081
-
1082
- = 4.4 (2014-08-11) =
1083
- * New Feature: Blacklist - delete items and blacklist them to never import them again.
1084
- * Enhanced: Added a button in the Debugging page to reset the plugin settings to default.
1085
- * Enhanced: WordPress Yoast SEO metaboxes and custom columns will no longer appear.
1086
-
1087
- = 4.3.1 (2014-08-08) =
1088
- * Enhanced: Better wording on settings page.
1089
- * Fixed bug: The Links Behaviour option in the settings was not working.
1090
- * Fixed bug: The wrong feed items were being shown for some sources when using the "View Items" row action.
1091
-
1092
- = 4.3 (2014-08-04) =
1093
- * New Feature: Feed items now also import authors.
1094
- * Enhanced: Custom feed is now in RSS 2.0 format.
1095
- * Enhanced: Improved the display template for feed items.
1096
- * Fixed bug: Custom feed was not working in Firefox.
1097
- * Fixed bug: Some feed items were showing items from another feed source.
1098
- * Fixed bug: The feed limit in the global settings was not working.
1099
-
1100
- = 4.2.3 (2014-07-29) =
1101
- * Enhanced: Added an option to choose between the current pagination type, and numbered pagination.
1102
- * Enhanced: The Feed Preview now also shows the total number of items in the feed.
1103
- * Fixed bug: A PHP warning error was being shown in the System Info.
1104
- * Fixed bug: Language files were not always being referenced correctly.
1105
- * Fixed bug: Manually fetching a feed fails if the feed is scheduled to update in the next 10 minutes.
1106
- * Fixed bug: Bing RSS feeds were importing duplicates on every update.
1107
-
1108
- = 4.2.2 (2014-07-23) =
1109
- * Enhanced: Facebook page feeds are now changed into RSS 2.0 feeds, rather than Atom 1.0 feeds.
1110
- * Enhanced: Improved live updating performace on the Feed Sources page.
1111
-
1112
- = 4.2.1 (2014-07-17) =
1113
- * Enhanced: Feed Sources page is now more responsive.
1114
-
1115
- = 4.2 (2014-07-17) =
1116
- * New Feature: Can now view each feed source's imported feed items separate from other feed sources' feed items.
1117
- * Enhanced: Major visual update to the Feed Sources page with new live updates.
1118
- * Enhanced: The custom feed now includes the feed source.
1119
- * Fixed bug: Google News feeds were importing duplicate items on every update.
1120
- * Fixed bug: Multiple minor bug fixes with old filters.
1121
-
1122
- = 4.1.6 (2014-06-28) =
1123
- * Fixed bug: Results returned by wprss_get_feed_items_for_source() will no longer be affected by filters.
1124
- * Fixed bug: Charset issue in titles
1125
-
1126
- = 4.1.5 (2014-06-19) =
1127
- * Enhanced: The Feed Sources table now indicates which feed sources encountered errors during the last import.
1128
- * Fixed bug: Feed titles were not being decoded for HTML entities.
1129
-
1130
- = 4.1.4 (2014-05-16) =
1131
- * Enhanced: Minor improvements to feed importing and handling.
1132
- * Fixed bug: HTML entities were not being decoded in feed item titles.
1133
-
1134
- = 4.1.3 (2014-04-28) =
1135
- * Enhanced: Added a force feed option, for valid RSS feeds with incorrect header content types.
1136
- * Fixed bug: HTML entities in feed item titles are now being decoded.
1137
-
1138
- = 4.1.2 (2014-04-22) =
1139
- * Enhanced: Improved the custom feed, by allowing a custom title.
1140
- * Enhanced: Improved shortcode, by adding the "pagination" parameter.
1141
- * Enhanced: Modified a filter to fix some bugs in the add-ons.
1142
-
1143
- = 4.1.1 (2014-04-09) =
1144
- * Enhanced: Tracking notices only appear for admin users.
1145
- * Fixed bug: Auto Feed Discovery was not working.
1146
-
1147
- = 4.1 (2014-04-03) =
1148
- * New Feature: Feed items can now link to enclosure links in the feed.
1149
- * Enhanced: Added a filter to allow add-ons to modify feed item queries.
1150
-
1151
- = 4.0.9 (2014-03-27) =
1152
- * Enhanced: Added a filter to modify the feeds template.
1153
- * Fixed bug: Nested lists in feeds template.
1154
-
1155
- = 4.0.8 (2014-03-20) =
1156
- * Fixed bug: Using the shortcode makes the comments section always open.
1157
-
1158
- = 4.0.7 (2014-03-08) =
1159
- * Fixed bug: The plugin prevented uploading of header images.
1160
-
1161
- = 4.0.6 (2014-03-05) =
1162
- * Fixed bug: Hook change in last version suspected reason for some installations having non-updated feed items.
1163
-
1164
- = 4.0.5 (2014-03-03) =
1165
- * New Feature: Time ago added as an option.
1166
- * Enhanced: The plugin now allows the use of RSS and Atom feeds that do not specify the correct MIME type.
1167
- * Enhanced: Better performance due to better hook usage.
1168
- * Fixed bug: Facebook page feed URL conversion was not being triggered for new feed sources.
1169
- * Fixed bug: Styles fix for pagination.
1170
- * Fixed bug: Removed empty spaces in logging.
1171
-
1172
- = 4.0.4 (2014-02-17) =
1173
- * Enhanced: Added Activate/Pause bulk actions in the Feed Sources page.
1174
- * Enhanced: Feed Sources page table has been re-designed.
1175
- * Enhanced: Logging is now site dependant on multisite.
1176
- * Fixed bug: Undefined display settings where appearing on the front end.
1177
-
1178
- = 4.0.3 (2014-02-12) =
1179
- * Fixed bug: The general setting for deleting feed items by age was not working.
1180
-
1181
- = 4.0.2 (2014-02-10) =
1182
- * Enhanced: Added a filter to change the html tags allowed in feed item content.
1183
-
1184
- = 4.0.1 (2014-02-08) =
1185
- * Fixed bug: Empty array of feed items bug caused importing problems.
1186
-
1187
- = 4.0 (2014-02-04) =
1188
- * Enhanced: Improved some internal queries, for better performance.
1189
- * Fixed bug: Feed limits were not working properly.
1190
-
1191
- = 3.9.9 (2014-02-03) =
1192
- * Enhanced: The custom feed can now be extended by add-ons.
1193
-
1194
- = 3.9.8 (2014-01-20) =
1195
- * Fixed bug: Removed excessive logging from Debugging Error Log.
1196
-
1197
- = 3.9.7 (2014-01-17) =
1198
- * Fixed bug: Bug in admin-debugging.php causing trouble with admin login
1199
-
1200
- = 3.9.6 (2014-01-17) =
1201
- * Enhanced: Added error logging.
1202
-
1203
- = 3.9.5 (2014-01-02) =
1204
- * Enhanced: Added a feed validator link in the New/Edit Feed Sources page.
1205
- * Enhanced: The Next Update column also shows the time remaining for next update, for feed source on the global update interval.
1206
- * Enhanced: The custom feed has been improved, and is now identical to the feeds displayed with the shortcode.
1207
- * Enhanced: License notifications only appear on the main site when using WordPress multisite.
1208
- * Enhanced: Updated Colorbox script to 1.4.33
1209
- * Fixed bug: The Imported Items column was always showing zero.
1210
- * Fixed bug: Feed items not being imported with limit set to zero. Should be unlimited.
1211
- * Fixed bug: Fat header in Feed Sources page
1212
-
1213
- = 3.9.4 (2013-12-24) =
1214
- * Enhanced: Added a column in the Feed Sources page that shows the number of feed items imported for each feed source.
1215
- * Fixed bug: Leaving the delete old feed items empty did not ignore the delete.
1216
-
1217
- = 3.9.3 (2013-12-23) =
1218
- * Fixed bug: Fixed tracking pointer appearing on saving settings.
1219
-
1220
- = 3.9.2 (2013-12-21) =
1221
- * Fixed bug: Incorrect file include call.
1222
-
1223
- = 3.9.1 (2013-12-12) =
1224
- * Enhanced: Improved date and time handling for imported feed items.
1225
- * Fixed bug: Incorrect values being shown in the Feed Processing metabox.
1226
- * Fixed bug: Feed limits set to zero were causing feeds to not be imported.
1227
-
1228
- = 3.9 (2013-12-12) =
1229
- * New Feature: Feed sources can have their own update interval.
1230
- * New Feature: The time remaining until the next update has been added to the Feed Source table.
1231
-
1232
- = 3.8 (2013-12-05) =
1233
- * New Feature: Feed items can be limited and deleted by their age.
1234
- * Enhanced: Added utility functions for shorter filters.
1235
- * Fixed bug: License codes were being erased when add-ons were deactivated.
1236
- * Fixed bug: Some feed sources could not be set to active from the table controls.
1237
- * Fixed bug: str_pos errors appear when custom feed url is left empty.
1238
- * Fixed bug: Some options were producing undefined index errors.
1239
-
1240
- = 3.7 (2013-11-28) =
1241
- * New Feature: State system - Feed sources can be activated/paused.
1242
- * New Feature: State system - Feed sources can be set to activate or pause themselves at a specific date and time.
1243
- * Enhanced: Added compatibility with nested outline elements in OPML files.
1244
- * Enhanced: Admin menu icon image will change into a Dashicon, when WordPress is updated to 3.8 (Decemeber 2013).
1245
- * Fixed bug: Custom Post types were breaking when the plugin is activated.
1246
-
1247
- = 3.6.1 (2013-11-17) =
1248
- * Fixed bug: Missing 2nd argument for wprss_shorten_title()
1249
-
1250
- = 3.6 (2013-11-16) =
1251
- * New Feature: Can set the maximum length for titles. Long titles get trimmed.
1252
- * Fixed bug: Fixed errors with undefined indexes for unchecked checkboxes in the settings page.
1253
- * Fixed bug: Pagination on front static page was not working.
1254
-
1255
- = 3.5.2 (2013-11-11) =
1256
- * Fixed bug: Invalid feed source url was producing an Undefined method notice.
1257
- * Fixed bug: Custom feed was producing a 404 page.
1258
- * Fixed bug: Presstrends code firing on admin_init, opt-in implementation coming soon
1259
-
1260
- = 3.5.1 (2013-11-09) =
1261
- * Enhanced: Increased compatibility with RSS sources.
1262
- * Fixed bug: Pagination not working on home page
1263
-
1264
- = 3.5 (2013-11-6) =
1265
- * New Feature: Can delete feed items for a particular source
1266
- * Enhanced: the 'Fetch feed items' row action for feed sources resets itself after 3.5 seconds.
1267
- * Enhanced: The feed image is saved for each url.
1268
- * Fixed bug: Link to source now links to correct url. Previously linked to site's feed.
1269
-
1270
- = 3.4.6 (2013-11-1) =
1271
- * Enhanced: Added more hooks to debugging page for the Feed to Post add-on.
1272
- * Fixed bug: Uninitialized loop index
1273
-
1274
- = 3.4.5 (2013-10-30) =
1275
- * Bug Fix: Feed items were not being imported while the WPML plugin was active.
1276
-
1277
- = 3.4.4 (2013-10-26) =
1278
- * New feature: Pagination
1279
- * New feature: First implementation of editor button for easy shortcode creation
1280
- * Enhanced: Feed items and sources don't show up in link manager
1281
- * Enhanced: Included Presstrends code for plugin usage monitoring
1282
-
1283
- = 3.4.3 (2013-10-20) =
1284
- * Fixed bug: Removed anonymous functions for backwards PHP compatibility
1285
- * Bug fix: Added suppress_filters in feed-display.php to prevent a user reported error
1286
- * Bug fix: Missing <li> in certain feed displays
1287
-
1288
- = 3.4.2 (2013-9-19) =
1289
- * Enhanced: Added some hooks for Feed to Post compatibility
1290
- * Enhanced: Moved date settings to a more appropriate location
1291
-
1292
- = 3.4.1 (2013-9-16) =
1293
- * Fixed Bug: Minor issue with options page - PHP notice
1294
-
1295
- = 3.4 (2013-9-15) =
1296
- * New Feature: Saving/Updating a feed source triggers an update for that source's feed items.
1297
- * New Feature: Option to change Youtube, Vimeo and Dailymotion feed item URLs to embedded video players URLs
1298
- * New Feature: Facebook Pages URLs are automatically detected and changed into Atom Feed URLs using FB's Graph
1299
- * Enhanced: Updated jQuery Colorbox library to 1.4.29
1300
- * Fixed Bug: Some settings did not have a default value set, and were throwing an 'Undefined Index' error
1301
- * Fixed Bug: Admin notices do not disappear immediately when dismissed.
1302
-
1303
- = Version 3.3.3 (2013-09-08) =
1304
- * Fixed bug: Better function handling on uninstall, should remove uninstall issues
1305
-
1306
- = Version 3.3.2 (2013-09-07) =
1307
- * New feature: Added exclude parameter to shortcode
1308
- * Enhanced: Added metabox links to documentation and add-ons
1309
- * Fixed bug: Custom feed linking to post on user site rather than original source
1310
- * Fixed bug: Custom post types issues when activitating the plugin
1311
-
1312
- = Version 3.3.1 (2013-08-09) =
1313
- * Fixed Bug: Roles and Capabilities file had not been included
1314
- * Fixed Bug: Error on install, function not found
1315
-
1316
- = Version 3.3 (2013-08-08) =
1317
- * New feature: OPML importer
1318
- * New feature: Feed item limits for individual Feed Sources
1319
- * New feature: Custom feed URL
1320
- * New feature: Feed limit on custom feed
1321
- * New feature: New 'Fetch feed items' action for each Feed Source in listing display
1322
- * New feature: Option to enable link to source
1323
- * Enhanced: Date strings now change according to locale being used (i.e. compatible with WPML)
1324
- * Enhanced: Capabilities implemented
1325
- * Enhanced: Feed Sources row action 'View' removed
1326
- * Fixed Bug: Proxy feed URLs resulting in the permalink: example.com/url
1327
-
1328
- = Version 3.2 (2013-07-06) =
1329
- * New feature: Parameter to limit number of feeds displayed
1330
- * New feature: Paramter to limit feeds displayed to particular sources (via ID)
1331
- * Enhanced: Better feed import handling to handle large number of feed sources
1332
-
1333
- = Version 3.1.1 (2013-06-06) =
1334
- * Fixed bug: Incompatibility with some other plugins due to function missing namespace
1335
-
1336
- = Version 3.1 (2013-06-06) =
1337
- * New feature: Option to set the number of feed items imported from every feed (default 5)
1338
- * New feature: Import and Export aggregator settings and feed sources
1339
- * New feature: Debugging page allowing manual feed refresh and feed reset
1340
- * Enhanced: Faster handling of restoring sources from trash when feed limit is 0
1341
- * Fixed bug: Limiter on number of overall feeds stored not working
1342
- * Fixed bug: Incompatibility issue with Foobox plugin fixed
1343
- * Fixed bug: Duplicate feeds sometimes imported
1344
-
1345
- = Version 3.0 (2013-03-16) =
1346
- * New feature: Option to select cron frequency
1347
- * New feature: Code extensibility added to be compatible with add-ons
1348
- * New feature: Option to set a limit to the number of feeds stored (previously 50, hard coded)
1349
- * New feature: Option to define the format of the date shown below each feed item
1350
- * New feature: Option to show or hide source of feed item
1351
- * New feature: Option to show or hide publish date of feed item
1352
- * New feature: Option to set text preceding publish date
1353
- * New feature: Option to set text preceding source of feed item
1354
- * New feature: Option to link title or not
1355
- * New feature: Limit of 5 items imported for each source instead of 10
1356
- * Enhanced: Performance improvement when publishing * New feeds in admin
1357
- * Enhanced: Query tuning for better performance
1358
- * Enhanced: Major code rewrite, refactoring and inclusion of hooks
1359
- * Enhanced: Updated Colorbox to v1.4.1
1360
- * Enhanced: Better security implementations
1361
- * Enhanced: Better feed preview display
1362
- * Fixed bug: Deletion of items upon source deletion not working properly
1363
- * Requires: WordPress 3.3
1364
-
1365
- = Version 2.2.3 (2012-11-01) =
1366
- * Fixed bug: Tab navigation preventing typing in input boxes
1367
- * Removed: Feeds showing up in internal linking pop up
1368
-
1369
- = Version 2.2.2 (2012-10-30) =
1370
- * Removed: Feeds showing up in site search results
1371
- * Enhanced: Better tab button navigation when adding a new feed
1372
- * Enhanced: Better guidance when a feed URL is invalid
1373
-
1374
- = Version 2.2.1 (2012-10-17) =
1375
- * Fixed bug: wprss_feed_source_order assumes everyone is an admin
1376
-
1377
- = Version 2.2 (2012-10-01) =
1378
- * Italian translation added
1379
- * Feed source order changed to alphabetical
1380
- * Fixed bug - repeated entries when having a non-valid feed source
1381
- * Fixed bug - all imported feeds deleted upon trashing a single feed source
1382
-
1383
- = Version 2.1 (2012-09-27) =
1384
- * Now localised for translations
1385
- * Fixed bug with date string
1386
- * Fixed $link_before and $link_after, now working
1387
- * Added backwards compatibility for wp_rss_aggregator() function
1388
-
1389
- = Version 2.0 (2012-09-21) =
1390
- * Bulk of code rewritten and refactored
1391
- * Added install and upgrade functions
1392
- * Added DB version setting
1393
- * Feed sources now stored as Custom Post Types
1394
- * Feed source list sortable ascending or descending by name
1395
- * Removed days subsections in feed display
1396
- * Ability to limit total number of feeds displayed
1397
- * Feeds now fetched via Cron
1398
- * Cron job to delete old feed items, keeps max of 50 items in DB
1399
- * Now requires WordPress 3.2
1400
- * Updated colorbox to v1.3.20.1
1401
- * Limit of 15 items max imported for each source
1402
- * Fixed issue of page content displaying incorrectly after feeds
1403
-
1404
- = Version 1.1 (2012-08-13) =
1405
- * Now requires WordPress 3.0
1406
- * More flexible fetching of images directory
1407
- * Has its own top level menu item
1408
- * Added settings section
1409
- * Ability to open in lightbox, new window or default browser behaviour
1410
- * Ability to set links as follow or no follow
1411
- * Using constants for oftenly used locations
1412
- * Code refactoring
1413
- * Changes in file and folder structure
1414
-
1415
  = Version 1.0 (2012-01-06) =
1416
  * Initial release.
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.4.1
7
+ Stable tag: 4.8.1
8
  License: GPLv2 or later
9
+ WP RSS Aggregator is the No.1 RSS feed importer and autoblogging plugin for WordPress. It provides the most comprehensive and elegant solution to import RSS feeds with premium add-ons available for additional functionality.
10
 
11
 
12
  == Description ==
13
 
14
+ WP RSS Aggregator is the original and best plugin for importing, merging and displaying RSS and Atom feeds on your WordPress site. It’s the most comprehensive and elegant RSS feed solution for WordPress.
15
 
16
+ With this free core version of WP RSS Aggregator you’ll be able to aggregate as many RSS feeds from as many sources as you'd like. Using the [shortcodes](http://docs.wprssaggregator.com/shortcodes/) you can then display the imported feed items from one or more sources directly on your website.
 
 
 
 
 
 
 
 
 
17
 
18
  = Highlighted Features =
19
 
20
+ * Set a name for each feed source.
21
+ * Import any number of feed items from multiple RSS Feeds.
22
+ * Display feed items using the [shortcodes](http://docs.wprssaggregator.com/shortcodes/) or by [calling the display function from within your theme](http://docs.wprssaggregator.com/shortcodes/#using-shortcodes-directly-in-templates).
23
+ * Limit the age of the feed items stored in the database.
24
+ * Set the number of feed items per feed source that you want to show and store.
25
+ * Set the pagination for the displayed feed items.
26
+ * Set a general feed import time interval.
27
+ * Schedule feed imports for each individual feed source.
28
+ * Choose whether to show/hide feed sources and dates, and set the date format.
29
+ * Set the links as no-follow or not, or add no follow to the meta tag.
30
+ * Customise the output using various [shortcode parameters](http://docs.wprssaggregator.com/shortcodes/#core-parameters).
31
+ * Set the open link behaviour (lightbox, new window or current window).
32
+ * Opens YouTube, DailyMotion and Vimeo videos directly.
33
+ * Export a custom RSS feed based on your feed sources.
34
+ * Extendable via [action and filter hooks](http://docs.wprssaggregator.com/category/developer-documentation/filters/).
35
+ * Incorporates feed auto-discovery, which lets you add feed sources without knowing the exact URL.
36
+ * Integrated with the Simplepie library that comes with WordPress. This includes RSS 0.91 and RSS 1.0 formats, the popular RSS 2.0 format, Atom etc.
37
 
38
  = Premium Add-Ons =
39
+ WP RSS Aggregator also has a number of premium add-ons that add more functionality to the core plugin. They provide the means to create autoblogging websites, display job listings, import YouTube videos and a lot more. Take a look at our [Use Cases](http://www.wprssaggregator.com/use-cases/) and our [Showcase](http://www.wprssaggregator.com/showcase/) for more ideas. Here are the add-ons currently available:
40
 
41
+ * [Feed to Post](http://www.wprssaggregator.com/extension/feed-to-post/) is an advanced importer that lets you import RSS feeds directly into WordPress posts or any other custom post type. You can use it to populate a website in minutes (autoblog). This is the most popular and feature-filled extension.
42
+ * [Keyword Filtering](http://www.wprssaggregator.com/extension/keyword-filtering/) filters the feed items to be imported based on keywords, key phrases or tags, so you only get the items you're interested in.
43
+ * [Excerpts & Thumbnails](http://www.wprssaggregator.com/extension/excerpts-thumbnails/) displays an excerpt and thumbnail image (taken from within the RSS feed) together with the title, date and source of each feed item.
44
+ * [Categories](http://www.wprssaggregator.com/extension/categories/) categorises your feed sources and allows you to display feed items from a particular category within your site using the [shortcode parameters](http://docs.wprssaggregator.com/shortcodes/#categories-parameters).
45
+ * [Full Text RSS Feeds](http://www.wprssaggregator.com/extension/full-text-rss-feeds/) adds connectivity to our Full Text Premium service, which allows you to import the full post content for an unlimited number of feed items per feed source, even when the feed itself doesn’t provide it. (Requires [Feed to Post](http://www.wprssaggregator.com/extension/feed-to-post/))
46
+ * [WordAi](http://www.wprssaggregator.com/extension/wordai/) allows you to take an RSS feed and turn it into new content that is both completely unique and completely readable. (Requires [Feed to Post](http://www.wprssaggregator.com/extension/feed-to-post/) and a [WordAi account](https://wordai.com/))
47
+ * [Widget](http://www.wprssaggregator.com/extension/widget/) adds a widget to your website that displays the imported feed items. It can also display excerpts and thumbnail images when used in conjunction with the [Excerpts & Thumbnails](http://www.wprssaggregator.com/extension/excerpts-thumbnails/) add-on.
48
+ * [SpinnerChief](http://www.wprssaggregator.com/extension/spinnerchief/) An extension for [Feed to Post](http://www.wprssaggregator.com/extension/feed-to-post/) that allows you to integrate the SpinnerChief article spinner so that the imported content is both completely unique and completely readable.
49
 
50
+ [View a comparison of our three most popular add-ons here](http://www.wprssaggregator.com/product-comparison/). If you're unsure as to which add-ons you need, [we put together this post to help you out](http://www.wprssaggregator.com/add-ons-purchase/).
51
+
52
+ There are also two premium bundles available, the [Simple Feeds Bundle](http://www.wprssaggregator.com/extension/simple-feeds-bundle/) and the [Advanced Feeds Bundle](http://www.wprssaggregator.com/extension/advanced-feeds-bundle/). [View a quick comparison of these bundles here](http://www.wprssaggregator.com/bundle-comparison/).
53
+
54
+ 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.
55
 
56
  = Demo =
57
+ The core plugin can be seen in use [on our website's demo page](http://www.wprssaggregator.com/demo/). There are also a number of [other demos](http://www.wprssaggregator.com/) available for our premium add-ons.
58
 
59
  = Video Walkthrough =
60
+ Have a look at the core version of WP RSS Aggregator below, or [go here to view our introductory videos for the premium add-ons](http://docs.wprssaggregator.com/introductory-videos/).
61
  [youtube http://www.youtube.com/watch?v=fcENPsmJbvc]
62
 
63
  = Documentation =
64
+ Our [comprehensive documentation](http://docs.wprssaggregator.com/) provides you with everything you need to install, set up and customize the plugin to your needs. You can also browse through [a large number of FAQs](http://docs.wprssaggregator.com/category/faqs/) that cover almost everything there is to ask.
65
 
66
  = As featured on =
67
+ * [WP Mayor](http://www.wpmayor.com/rss-feeds-review-wp-rss-aggregator/)
68
+ * [LatestWP](http://www.latestwp.com/2015/03/15/wp-rss-aggregator-plugin-review/)
69
+ * [WPBeginner](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
+ * [WPKube](http://www.wpkube.com/wp-rss-aggregator-wordpress-review/)
72
+ * [Torque](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 Plugin of the Month](http://managewp.com/free-wordpress-plugins-march-2014)
76
+ * [Tidy Repo](http://tidyrepo.com/wp-rss-aggregator/)
77
+ * [WPEka](http://www.wpeka.com/wp-rss-aggregators-plugin.html)
78
+ * [IndexWP](http://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
 
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 from the 'Plugins' section in your dashboard.
92
  3. Configure the plugin by going to the `RSS Aggregator` menu item that appears in your dashboard menu.
93
+ 4. Use the shortcode in your posts or pages: `[wp-rss-aggregator]`
94
+
95
+ You can easily select the source for your feeds and also insert a limit via [shortcode parameters](http://docs.wprssaggregator.com/shortcodes/#core-parameters) as shown below. To get your feed source ID please refer to the ID column in your feed source listing page.
96
 
97
+ `[wp-rss-aggregator source=”<ID>” limit=”<num>”]`
98
 
99
+ An example of a shortcode parameter in use could be:
 
 
 
 
 
 
 
100
 
 
101
  `[wp_rss_aggregator link_before='<li class="feed-link">' link_after='</li>']`
 
102
 
103
+ It is advisable to use the 'HTML' view of the editor when inserting shortcodes with parameters.
104
 
105
  __Usage within theme files__
106
 
107
+ Here are two examples of a function call from within the theme's files:
108
  `
109
  <?php
110
  wprss_display_feed_items( $args = array(
146
 
147
  = Why do I get “No feed items found” when I insert the shortcode on a page or post? =
148
 
149
+ Try adding a few more feed sources and make sure they are valid by using the RSS Feed Validator.
150
 
151
  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.
152
 
162
 
163
  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.
164
 
165
+ If you need any further help you can [contact our support team](http://www.wprssaggregator.com/contact/).
166
 
167
  = Where can I find the documentation for the plugin? =
168
 
169
+ Our complete documentation with FAQs included can be found on [our dedicated documentation website](http://docs.wprssaggregator.com/).
170
 
171
 
172
  == Screenshots ==
186
 
187
  == Changelog ==
188
 
189
+ = 4.8.1 (2016-02-02) =
190
+ * Fixed bug: Some exceptions used to cause fatal errors.
191
+ * Fixed bug: Requests made by image caching used to always have an infinite timeout.
192
+ * Fixed bug: Licensing algorithm used to use constants of inactive plugins, causing fatal error.
193
+ * Enhanced: Visual improvements.
194
+ * Enhanced: Included new Object Oriented code.
195
+
196
  = 4.8 (2015-12-30) =
197
  * Fixed bug: Licensing notices will now be displayed again.
198
  * Enhanced: Major licensing system improvements.
709
  * Code refactoring
710
  * Changes in file and folder structure
711
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
712
  = Version 1.0 (2012-01-06) =
713
  * 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.8
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.8
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.8', true );
47
 
48
  if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
49
  define( 'WPRSS_WP_MIN_VERSION', '4.0', true );
@@ -246,6 +246,59 @@
246
  register_deactivation_hook( __FILE__ , 'wprss_deactivate' );
247
 
248
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
 
250
 
251
  add_action( 'init', 'wprss_init' );
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.8.1
7
  Author: Jean Galea
8
  Author URI: http://www.wprssaggregator.com
9
  License: GPLv2
29
 
30
  /**
31
  * @package WPRSSAggregator
32
+ * @version 4.8.1
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.8.1', true );
47
 
48
  if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
49
  define( 'WPRSS_WP_MIN_VERSION', '4.0', true );
246
  register_deactivation_hook( __FILE__ , 'wprss_deactivate' );
247
 
248
 
249
+ /**
250
+ * Returns the Spinnerchief Addon class singleton instance.
251
+ *
252
+ * @since 4.8.1
253
+ * @return Aventura\Wprss\Core\Plugin
254
+ */
255
+ function wprss() {
256
+ static $plugin = null;
257
+
258
+
259
+ // One time initialization
260
+ if (is_null($plugin)) {
261
+ static $timesCalled = 0;
262
+ if ($timesCalled) {
263
+ throw new Exception('WP RSS Aggregator has been initialized recursively');
264
+ }
265
+ $timesCalled++;
266
+
267
+ /**
268
+ * Basically, we could just do this here:
269
+ * Factory::create();
270
+ *
271
+ * However, the actual setup allows for even further customization.
272
+ * In fact, the factory can be substituted by some entirely different factory,
273
+ * that creates and initializes a different plugin in a different way.
274
+ */
275
+
276
+ $factoryClassName = apply_filters('wprss_core_plugin_factory_class_name',
277
+ 'Aventura\\Wprss\\Core\\Factory');
278
+
279
+ if (!class_exists($factoryClassName)) {
280
+ throw new Aventura\Wprss\Exception(
281
+ sprintf('Could not initialize add-on: Factory class "%1$s" does not exist', $factoryClassName));
282
+ }
283
+
284
+ $plugin = call_user_func_array(array($factoryClassName, 'create'), array(array(
285
+ 'basename' => __FILE__,
286
+ 'name' => 'WP RSS Aggregator'
287
+ )));
288
+ }
289
+
290
+ return $plugin;
291
+ }
292
+
293
+ require_once(WPRSS_INC . 'functions.php');
294
+ try {
295
+ $instance = wprss();
296
+ } catch (Exception $e) {
297
+ if (WP_DEBUG && WP_DEBUG_DISPLAY) {
298
+ throw $e;
299
+ }
300
+ wp_die( $e->getMessage() );
301
+ }
302
 
303
 
304
  add_action( 'init', 'wprss_init' );