WP RSS Aggregator - Version 4.16

Version Description

(2019-10-31) =

Changed - Overhauled the data set system with a more robust entity system. - Various database optimizations for better performance.

Fixed - Incompatibility with other plugins that use similar import/export mechanisms. - Incompatibility with PolyLang, causing the block and shortcode to show no feed items. - Timeout and infinite loop when saving a feed source.

Download this release

Release Info

Developer Mekku
Plugin Icon 128x128 WP RSS Aggregator
Version 4.16
Comparing to
See all releases

Code changes from version 4.15.2 to 4.16

Files changed (69) hide show
  1. CHANGELOG.md +11 -1
  2. README.md +24 -0
  3. images/add-ons/wprss.jpg +0 -0
  4. images/wp-rss-aggregator-support-beacon.png +0 -0
  5. includes/admin-import-export.php +42 -19
  6. lib/Entities/Api/EntityInterface.php +56 -0
  7. lib/Entities/Api/PropertyInterface.php +39 -0
  8. lib/Entities/Api/SchemaInterface.php +25 -0
  9. lib/Entities/Api/StoreInterface.php +44 -0
  10. lib/Entities/Entity.php +148 -0
  11. lib/Entities/Properties/AbstractDecoratorProperty.php +83 -0
  12. lib/Entities/Properties/CallbackDecoratorProperty.php +81 -0
  13. lib/Entities/Properties/CallbackProperty.php +63 -0
  14. lib/Entities/Properties/DefaultingProperty.php +85 -0
  15. lib/Entities/Properties/Property.php +53 -0
  16. lib/Entities/Schemas/Schema.php +62 -0
  17. lib/Entities/Stores/ArrayStore.php +73 -0
  18. lib/Entities/Stores/EntityStore.php +73 -0
  19. readme.txt +7 -16
  20. src/Data/Collections/WpPostCollection.php +2 -469
  21. src/Data/EntityDataSet.php +146 -0
  22. src/Entities/{Feeds/Items/WpPostFeedItemCollection.php → Collections/FeedItemCollection.php} +8 -29
  23. src/Entities/Collections/FeedSourceCollection.php +56 -0
  24. src/Entities/{Feeds/Templates/WpPostFeedTemplateCollection.php → Collections/FeedTemplateCollection.php} +39 -37
  25. src/Entities/{Feeds/Items → Collections}/ImportedItemsCollection.php +7 -6
  26. src/Entities/Collections/WpEntityCollection.php +509 -0
  27. src/Entities/Feeds/Items/WpPostFeedItem.php +0 -236
  28. src/Entities/Feeds/Sources/WpPostFeedSource.php +0 -94
  29. src/Entities/Feeds/Sources/WpPostFeedSourceCollection.php +0 -75
  30. src/Entities/Feeds/Templates/BuiltInFeedTemplate.php +0 -189
  31. src/Entities/Feeds/Templates/WpPostFeedTemplate.php +0 -63
  32. src/Entities/Properties/SanitizedProperty.php +58 -0
  33. src/Entities/Properties/TimestampProperty.php +58 -0
  34. src/Entities/Properties/WpFtImageUrlProperty.php +63 -0
  35. src/Entities/Properties/WpPostEntityProperty.php +101 -0
  36. src/Entities/Properties/WpraSourceDefaultProperty.php +81 -0
  37. src/Entities/Stores/BuiltInTemplateStore.php +158 -0
  38. src/Entities/Stores/WpOptionsArrayStore.php +80 -0
  39. src/Entities/Stores/WpPostStore.php +94 -0
  40. src/Handlers/FeedSources/FeedSourceSaveMetaHandler.php +42 -3
  41. src/Handlers/FeedTemplates/RenderTemplateContentHandler.php +23 -9
  42. src/Handlers/Images/RenderItemsImageColumnHandler.php +5 -5
  43. src/Logger/ProblemLogger.php +1 -1
  44. src/Logger/WpraLogger.php +6 -6
  45. src/Modules/FeedItemsModule.php +91 -3
  46. src/Modules/FeedSourcesModule.php +114 -7
  47. src/Modules/FeedTemplatesModule.php +76 -5
  48. src/Modules/ImagesModule.php +4 -3
  49. src/Modules/ImporterModule.php +7 -3
  50. src/Modules/PolyLangCompatModule.php +63 -0
  51. src/RestApi/EndPoints/FeedTemplates/GetTemplatesEndPoint.php +2 -2
  52. src/Util/CallbackIterator.php +103 -0
  53. src/Util/PaginatedIterator.php +12 -2
  54. src/Util/SanitizerInterface.php +22 -0
  55. src/Util/Sanitizers/BoolSanitizer.php +23 -0
  56. src/Util/Sanitizers/CallbackSanitizer.php +43 -0
  57. src/Util/Sanitizers/EquivalenceSanitizer.php +52 -0
  58. src/Util/Sanitizers/IntSanitizer.php +68 -0
  59. src/Util/Sanitizers/PhpFilterSanitizer.php +85 -0
  60. test/bootstrap.php +21 -0
  61. vendor/autoload.php +1 -1
  62. vendor/composer/autoload_classmap.php +35 -9
  63. vendor/composer/autoload_psr4.php +1 -0
  64. vendor/composer/autoload_real.php +7 -7
  65. vendor/composer/autoload_static.php +45 -14
  66. vendor/composer/installed.json +17 -17
  67. vendor/php-di/phpdoc-reader/src/PhpDocReader/PhpDocReader.php +1 -0
  68. vendor/symfony/polyfill-ctype/composer.json +1 -1
  69. wp-rss-aggregator.php +4 -2
CHANGELOG.md CHANGED
@@ -4,13 +4,23 @@ All notable changes to this project will be documented in this file.
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
 
 
 
 
 
 
 
 
 
 
 
7
  ## [4.15.2] - 2019-10-03
8
  ### Added
9
  * Links and integrations with Lorem for custom developer work.
10
 
11
  ### Changed
12
  * The default logging type is now "debug".
13
- - Feeds are now sorted alphabetically by default.
14
 
15
  ### Fixed
16
  * Multisite installations only allowed the main site to have activated licenses.
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
 
7
+ ## [4.16] - 2019-10-31
8
+ ### Changed
9
+ * Overhauled the data set system with a more robust entity system.
10
+ * Various database optimizations for better performance.
11
+
12
+ ### Fixed
13
+ * Incompatibility with other plugins that use similar import/export mechanisms.
14
+ * Incompatibility with PolyLang, causing the block and shortcode to show no feed items.
15
+ * Timeout and infinite loop when saving a feed source.
16
+
17
  ## [4.15.2] - 2019-10-03
18
  ### Added
19
  * Links and integrations with Lorem for custom developer work.
20
 
21
  ### Changed
22
  * The default logging type is now "debug".
23
+ * Feeds are now sorted alphabetically by default.
24
 
25
  ### Fixed
26
  * Multisite installations only allowed the main site to have activated licenses.
README.md ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ![](https://repository-images.githubusercontent.com/15269888/73ca9400-669f-11e9-9e18-5662f7b5bd68)
2
+
3
+ ## Requirements
4
+
5
+ **Recommended**
6
+ * PHP 7+
7
+ * PHP `curl` extension
8
+ * PHP `simplexml` extension
9
+ * PHP `mbstring` extension
10
+ * PHP `gd` extension
11
+ * WordPress 5.0+
12
+
13
+ **Minimum**
14
+ * PHP 5.4+
15
+ * PHP `curl` extension
16
+ * PHP `simplexml` extension
17
+ * WordPress 4.8+
18
+
19
+ ## Links
20
+
21
+ * [Website](https://wprssaggregator.com)
22
+ * [Premium Addons](https://wprssaggregator.com/pricing)
23
+ * [Knowledge Base](https://kb.wprssaggregator.com)
24
+ * [WordPress.org Page](https://wordpress.org/plugins/wp-rss-aggregator)
images/add-ons/wprss.jpg DELETED
Binary file
images/wp-rss-aggregator-support-beacon.png DELETED
Binary file
includes/admin-import-export.php CHANGED
@@ -44,17 +44,30 @@ use Aventura\Wprss\Core\Model\BulkSourceImport\ServiceProvider;
44
  * @since 3.1
45
  */
46
  function wp_rss_aggregator_export() {
47
- if ( isset( $_POST['export'] ) && check_admin_referer( 'wprss-settings-export' ) ) {
48
- $blogname = str_replace( " ", "", get_option( 'blogname' ) );
49
- $date = date( "m-d-Y" );
50
- $json_name = $blogname . "-" . $date; // Naming the filename that will be generated.
51
-
52
- header( 'Content-Description: File Transfer' );
53
- header( "Content-Type: text/json; charset=" . get_option( 'blog_charset' ) );
54
- header( "Content-Disposition: attachment; filename=$json_name.json" );
55
- wp_rss_set_export_data();
56
- die();
 
 
 
57
  }
 
 
 
 
 
 
 
 
 
 
58
  }
59
 
60
 
@@ -126,16 +139,20 @@ use Aventura\Wprss\Core\Model\BulkSourceImport\ServiceProvider;
126
  return;
127
  }
128
  elseif ( $pagenow == 'edit.php' ) {
129
- if ( isset( $_FILES['import'] ) && check_admin_referer( 'wprss-settings-import' ) ) {
130
- if ( $_FILES['import']['error'] > 0) {
131
- wp_die( "Error during import" );
 
 
 
 
132
  } else {
133
- $file_name = $_FILES['import']['name'];
134
  $file_name_parts = explode( ".", $file_name );
135
  $file_ext = strtolower( end( $file_name_parts ) );
136
- $file_size = $_FILES['import']['size'];
137
  if ( ( $file_ext == "json" ) && ( $file_size < 500000 ) ) {
138
- $encode_options = file_get_contents( $_FILES['import']['tmp_name'] );
139
  $options = json_decode( $encode_options, true );
140
  foreach ( $options as $key => $value ) {
141
  update_option( $key, $value );
@@ -184,7 +201,10 @@ use Aventura\Wprss\Core\Model\BulkSourceImport\ServiceProvider;
184
  <form method="post">
185
  <p class="submit">
186
  <?php wp_nonce_field( 'wprss-settings-export' ); ?>
187
- <input type="submit" name="export" value="<?php _e( 'Export Settings', WPRSS_TEXT_DOMAIN ); ?>" class="button" />
 
 
 
188
  </p>
189
  </form>
190
 
@@ -195,8 +215,11 @@ use Aventura\Wprss\Core\Model\BulkSourceImport\ServiceProvider;
195
  <form method='post' enctype='multipart/form-data'>
196
  <p class="submit">
197
  <?php wp_nonce_field( 'wprss-settings-import' ); ?>
198
- <input type='file' name='import' />
199
- <input type='submit' name='import' value="<?php _e( 'Import Settings', WPRSS_TEXT_DOMAIN ); ?>" class="button" />
 
 
 
200
  </p>
201
  </form>
202
 
44
  * @since 3.1
45
  */
46
  function wp_rss_aggregator_export() {
47
+ if (!isset($_POST['wpra-export'])) {
48
+ return;
49
+ }
50
+
51
+ $adminurl = strtolower( admin_url() );
52
+ $referer = strtolower( wp_get_referer() );
53
+ $nonce = 'wprss-settings-export';
54
+ $result = isset($_POST['_wpnonce'])
55
+ ? wp_verify_nonce($_POST['_wpnonce'], 'wprss-settings-export')
56
+ : false;
57
+
58
+ if ($result === false) {
59
+ return;
60
  }
61
+
62
+ $blogname = str_replace( " ", "", get_option( 'blogname' ) );
63
+ $date = date( "m-d-Y" );
64
+ $json_name = $blogname . "-" . $date; // Naming the filename that will be generated.
65
+
66
+ header( 'Content-Description: File Transfer' );
67
+ header( "Content-Type: text/json; charset=" . get_option( 'blog_charset' ) );
68
+ header( "Content-Disposition: attachment; filename=$json_name.json" );
69
+ wp_rss_set_export_data();
70
+ die();
71
  }
72
 
73
 
139
  return;
140
  }
141
  elseif ( $pagenow == 'edit.php' ) {
142
+ if (isset($_POST['wpra-import']) && isset($_FILES['wpra-import-file'])) {
143
+ check_admin_referer( 'wprss-settings-import' );
144
+
145
+ $import = $_FILES['wpra-import-file'];
146
+
147
+ if ( $import['error'] > 0) {
148
+ wp_die( __('Error during import. Please upload a file', 'wprss') );
149
  } else {
150
+ $file_name = $import['name'];
151
  $file_name_parts = explode( ".", $file_name );
152
  $file_ext = strtolower( end( $file_name_parts ) );
153
+ $file_size = $import['size'];
154
  if ( ( $file_ext == "json" ) && ( $file_size < 500000 ) ) {
155
+ $encode_options = file_get_contents( $import['tmp_name'] );
156
  $options = json_decode( $encode_options, true );
157
  foreach ( $options as $key => $value ) {
158
  update_option( $key, $value );
201
  <form method="post">
202
  <p class="submit">
203
  <?php wp_nonce_field( 'wprss-settings-export' ); ?>
204
+ <input type="submit"
205
+ name="wpra-export"
206
+ value="<?php _e( 'Export Settings', WPRSS_TEXT_DOMAIN); ?>"
207
+ class="button" />
208
  </p>
209
  </form>
210
 
215
  <form method='post' enctype='multipart/form-data'>
216
  <p class="submit">
217
  <?php wp_nonce_field( 'wprss-settings-import' ); ?>
218
+ <input type='file' name='wpra-import-file' />
219
+ <input type='submit'
220
+ name='wpra-import'
221
+ value="<?php _e( 'Import Settings', WPRSS_TEXT_DOMAIN ); ?>"
222
+ class="button" />
223
  </p>
224
  </form>
225
 
lib/Entities/Api/EntityInterface.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities\Api;
4
+
5
+ use OutOfBoundsException;
6
+
7
+ /**
8
+ * Represents a data entity.
9
+ *
10
+ * @since [*next-version*]
11
+ */
12
+ interface EntityInterface
13
+ {
14
+ /**
15
+ * @since [*next-version*]
16
+ *
17
+ * @param string $key
18
+ *
19
+ * @return mixed
20
+ *
21
+ * @throws OutOfBoundsException
22
+ */
23
+ public function get($key);
24
+
25
+ /**
26
+ * @since [*next-version*]
27
+ *
28
+ * @param array $data
29
+ *
30
+ * @return EntityInterface
31
+ *
32
+ * @throws OutOfBoundsException
33
+ */
34
+ public function set(array $data);
35
+
36
+ /**
37
+ * @since [*next-version*]
38
+ *
39
+ * @return StoreInterface
40
+ */
41
+ public function getStore();
42
+
43
+ /**
44
+ * @since [*next-version*]
45
+ *
46
+ * @return SchemaInterface
47
+ */
48
+ public function getSchema();
49
+
50
+ /**
51
+ * @since [*next-version*]
52
+ *
53
+ * @return array
54
+ */
55
+ public function export();
56
+ }
lib/Entities/Api/PropertyInterface.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities\Api;
4
+
5
+ use OutOfBoundsException;
6
+
7
+ /**
8
+ * The interface for entity properties.
9
+ *
10
+ * A property is an object that is responsible for reading and writing data from and to a store, as well as performing
11
+ * any necessary sanitization or parsing before or after any read or write operations.
12
+ *
13
+ * @since [*next-version*]
14
+ */
15
+ interface PropertyInterface
16
+ {
17
+ /**
18
+ * @since [*next-version*]
19
+ *
20
+ * @param EntityInterface $entity
21
+ *
22
+ * @return mixed
23
+ *
24
+ * @throws OutOfBoundsException
25
+ */
26
+ public function getValue(EntityInterface $entity);
27
+
28
+ /**
29
+ * @since [*next-version*]
30
+ *
31
+ * @param EntityInterface $entity
32
+ * @param mixed $value
33
+ *
34
+ * @return array The commit to be given to a data store.
35
+ *
36
+ * @throws OutOfBoundsException
37
+ */
38
+ public function setValue(EntityInterface $entity, $value);
39
+ }
lib/Entities/Api/SchemaInterface.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities\Api;
4
+
5
+ /**
6
+ * Interface for an entity schema, which describes the data configuration for entities.
7
+ *
8
+ * @since [*next-version*]
9
+ */
10
+ interface SchemaInterface
11
+ {
12
+ /**
13
+ * @since [*next-version*]
14
+ *
15
+ * @return PropertyInterface[]
16
+ */
17
+ public function getProperties();
18
+
19
+ /**
20
+ * @since [*next-version*]
21
+ *
22
+ * @return array
23
+ */
24
+ public function getDefaults();
25
+ }
lib/Entities/Api/StoreInterface.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities\Api;
4
+
5
+ use OutOfBoundsException;
6
+
7
+ /**
8
+ * Interface for a data store, which is a simple abstraction for the storage of raw entity data.
9
+ *
10
+ * @since [*next-version*]
11
+ */
12
+ interface StoreInterface
13
+ {
14
+ /**
15
+ * @since [*next-version*]
16
+ *
17
+ * @param string $key
18
+ *
19
+ * @return mixed
20
+ *
21
+ * @throws OutOfBoundsException
22
+ */
23
+ public function get($key);
24
+
25
+ /**
26
+ * @since [*next-version*]
27
+ *
28
+ * @param string $key
29
+ *
30
+ * @return bool
31
+ */
32
+ public function has($key);
33
+
34
+ /**
35
+ * @since [*next-version*]
36
+ *
37
+ * @param array $data
38
+ *
39
+ * @return StoreInterface
40
+ *
41
+ * @throws OutOfBoundsException
42
+ */
43
+ public function set(array $data);
44
+ }
lib/Entities/Entity.php ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities;
4
+
5
+ use Exception;
6
+ use OutOfBoundsException;
7
+ use RebelCode\Entities\Api\EntityInterface;
8
+ use RebelCode\Entities\Api\PropertyInterface;
9
+ use RebelCode\Entities\Api\SchemaInterface;
10
+ use RebelCode\Entities\Api\StoreInterface;
11
+
12
+ /**
13
+ * The standard implementation for an entity, that uses a schema for its configuration and a store for its raw storage.
14
+ *
15
+ * @since [*next-version*]
16
+ */
17
+ class Entity implements EntityInterface
18
+ {
19
+ /**
20
+ * @since [*next-version*]
21
+ *
22
+ * @var SchemaInterface
23
+ */
24
+ protected $schema;
25
+
26
+ /**
27
+ * @since [*next-version*]
28
+ *
29
+ * @var StoreInterface
30
+ */
31
+ protected $store;
32
+
33
+ /**
34
+ * @since [*next-version*]
35
+ *
36
+ * @var PropertyInterface[]
37
+ */
38
+ protected $props;
39
+
40
+ /**
41
+ * @since [*next-version*]
42
+ *
43
+ * @var array
44
+ */
45
+ protected $defaults;
46
+
47
+ /**
48
+ * Constructor.
49
+ *
50
+ * @since [*next-version*]
51
+ *
52
+ * @param SchemaInterface $schema
53
+ * @param StoreInterface $store
54
+ */
55
+ public function __construct(SchemaInterface $schema, StoreInterface $store)
56
+ {
57
+ $this->schema = $schema;
58
+ $this->store = $store;
59
+ $this->props = $schema->getProperties();
60
+ $this->defaults = $schema->getDefaults();
61
+ }
62
+
63
+ /**
64
+ * @inheritdoc
65
+ *
66
+ * @since [*next-version*]
67
+ */
68
+ public function get($key)
69
+ {
70
+ if (!array_key_exists($key, $this->props)) {
71
+ throw new OutOfBoundsException();
72
+ }
73
+
74
+ try {
75
+ return $this->props[$key]->getValue($this);
76
+ } catch (OutOfBoundsException $exception) {
77
+ return array_key_exists($key, $this->defaults)
78
+ ? $this->defaults[$key]
79
+ : null;
80
+ }
81
+ }
82
+
83
+ /**
84
+ * @inheritdoc
85
+ *
86
+ * @since [*next-version*]
87
+ */
88
+ public function set(array $data)
89
+ {
90
+ $changeSet = [];
91
+
92
+ foreach ($data as $key => $value) {
93
+ if (!array_key_exists($key, $this->props)) {
94
+ throw new OutOfBoundsException();
95
+ }
96
+
97
+ try {
98
+ $commit = $this->props[$key]->setValue($this, $value);
99
+ } catch (Exception $exception) {
100
+ continue;
101
+ }
102
+
103
+ $changeSet = array_merge($changeSet, $commit);
104
+ }
105
+
106
+ // Create a new instance
107
+ $newEntity = clone $this;
108
+ // Set the changes and update the store instance
109
+ $newEntity->store = $this->store->set($changeSet);
110
+
111
+ return $newEntity;
112
+ }
113
+
114
+ /**
115
+ * @since [*next-version*]
116
+ *
117
+ * @return StoreInterface
118
+ */
119
+ public function getStore()
120
+ {
121
+ return $this->store;
122
+ }
123
+
124
+ /**
125
+ * @since [*next-version*]
126
+ *
127
+ * @return SchemaInterface
128
+ */
129
+ public function getSchema()
130
+ {
131
+ return $this->schema;
132
+ }
133
+
134
+ /**
135
+ * @since [*next-version*]
136
+ *
137
+ * @return array
138
+ */
139
+ public function export()
140
+ {
141
+ $result = [];
142
+ foreach ($this->props as $key => $prop) {
143
+ $result[$key] = $this->get($key);
144
+ }
145
+
146
+ return $result;
147
+ }
148
+ }
lib/Entities/Properties/AbstractDecoratorProperty.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities\Properties;
4
+
5
+ use OutOfBoundsException;
6
+ use RebelCode\Entities\Api\EntityInterface;
7
+ use RebelCode\Entities\Api\PropertyInterface;
8
+
9
+ /**
10
+ * Abstract implementation of a property that decorates another property.
11
+ *
12
+ * Implementations will need to implement the {@link getter()} and {@link setter()} methods. The getter is invoked
13
+ * _after_ the original property's value is retrieved, giving this instance a chance to modify the outgoing value.
14
+ * The setter is invoked _before_ the original property's {@link PropertyInterface::setValue()}, giving this instance
15
+ * a chance to modify in value that is given to the original property.
16
+ *
17
+ * @since [*next-version*]
18
+ */
19
+ abstract class AbstractDecoratorProperty implements PropertyInterface
20
+ {
21
+ /**
22
+ * @since [*next-version*]
23
+ *
24
+ * @var PropertyInterface
25
+ */
26
+ protected $property;
27
+
28
+ /**
29
+ * Constructor.
30
+ *
31
+ * @since [*next-version*]
32
+ *
33
+ * @param PropertyInterface $property The property instance to decorate.
34
+ */
35
+ public function __construct(PropertyInterface $property)
36
+ {
37
+ $this->property = $property;
38
+ }
39
+
40
+ /**
41
+ * @inheritdoc
42
+ *
43
+ * @since [*next-version*]
44
+ */
45
+ public function getValue(EntityInterface $entity)
46
+ {
47
+ return $this->getter($entity, $this->property->getValue($entity));
48
+ }
49
+
50
+ /**
51
+ * @inheritdoc
52
+ *
53
+ * @since [*next-version*]
54
+ */
55
+ public function setValue(EntityInterface $entity, $value)
56
+ {
57
+ return $this->property->setValue($entity, $this->setter($entity, $value));
58
+ }
59
+
60
+ /**
61
+ * Retrieves the actual value for the value returned by the original property.
62
+ *
63
+ * @since [*next-version*]
64
+ *
65
+ * @param EntityInterface $entity The entity instance.
66
+ * @param mixed $value The value returned by the original property.
67
+ *
68
+ * @return mixed The value.
69
+ */
70
+ abstract protected function getter(EntityInterface $entity, $value);
71
+
72
+ /**
73
+ * Retrieves the actual value to set to the original property.
74
+ *
75
+ * @since [*next-version*]
76
+ *
77
+ * @param EntityInterface $entity The entity instance.
78
+ * @param mixed $value The value being set.
79
+ *
80
+ * @return mixed The value.
81
+ */
82
+ abstract protected function setter(EntityInterface $entity, $value);
83
+ }
lib/Entities/Properties/CallbackDecoratorProperty.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities\Properties;
4
+
5
+ use RebelCode\Entities\Api\EntityInterface;
6
+ use RebelCode\Entities\Api\PropertyInterface;
7
+
8
+ /**
9
+ * A generic callback-based decorator property.
10
+ *
11
+ * @since [*next-version*]
12
+ */
13
+ class CallbackDecoratorProperty implements PropertyInterface
14
+ {
15
+ /**
16
+ * @since [*next-version*]
17
+ *
18
+ * @var PropertyInterface
19
+ */
20
+ protected $property;
21
+
22
+ /**
23
+ * @since [*next-version*]
24
+ *
25
+ * @var callable|null
26
+ */
27
+ protected $getter;
28
+
29
+ /**
30
+ * @since [*next-version*]
31
+ *
32
+ * @var callable|null
33
+ */
34
+ protected $setter;
35
+
36
+ /**
37
+ * Constructor.
38
+ *
39
+ * @since [*next-version*]
40
+ *
41
+ * @param PropertyInterface $property The property instance to decorate.
42
+ * @param callable|null $getter The getter callback. Recieves the entity instance and value as arguments and
43
+ * should return a value. Invoked after the decorated instance's getter.
44
+ * @param callable|null $setter The setter callback. Receives the entity instance and value as arguments and
45
+ * should return a commit array. Invoked after the decorated instance's setter.
46
+ */
47
+ public function __construct(PropertyInterface $property, callable $getter = null, callable $setter = null)
48
+ {
49
+ $this->property = $property;
50
+ $this->getter = $getter;
51
+ $this->setter = $setter;
52
+ }
53
+
54
+ /**
55
+ * @inheritdoc
56
+ *
57
+ * @since [*next-version*]
58
+ */
59
+ public function getValue(EntityInterface $entity)
60
+ {
61
+ $value = $this->property->getValue($entity);
62
+
63
+ return is_callable($this->getter)
64
+ ? call_user_func_array($this->getter, [$entity, $value])
65
+ : $value;
66
+ }
67
+
68
+ /**
69
+ * @inheritdoc
70
+ *
71
+ * @since [*next-version*]
72
+ */
73
+ public function setValue(EntityInterface $entity, $value)
74
+ {
75
+ $commit = $this->property->setValue($entity, $value);
76
+
77
+ return is_callable($this->setter)
78
+ ? call_user_func_array($this->setter, [$entity, $value, $commit])
79
+ : $commit;
80
+ }
81
+ }
lib/Entities/Properties/CallbackProperty.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities\Properties;
4
+
5
+ use RebelCode\Entities\Api\EntityInterface;
6
+ use RebelCode\Entities\Api\PropertyInterface;
7
+
8
+ /**
9
+ * Implementation of a property that uses callbacks for reading and writing values.
10
+ *
11
+ * @since [*next-version*]
12
+ */
13
+ class CallbackProperty implements PropertyInterface
14
+ {
15
+ /**
16
+ * @since [*next-version*]
17
+ *
18
+ * @var callable
19
+ */
20
+ protected $getter;
21
+
22
+ /**
23
+ * @since [*next-version*]
24
+ *
25
+ * @var callable
26
+ */
27
+ protected $setter;
28
+
29
+ /**
30
+ * Constructor.
31
+ *
32
+ * @since [*next-version*]
33
+ *
34
+ * @param callable $getter The getter callback. Receives the entity instance as arguments and should return a value.
35
+ * @param callable $setter The setter callback. Receives the entity instance and value as arguments and should
36
+ * return a commit array.
37
+ */
38
+ public function __construct(callable $getter, callable $setter)
39
+ {
40
+ $this->getter = $getter;
41
+ $this->setter = $setter;
42
+ }
43
+
44
+ /**
45
+ * @inheritdoc
46
+ *
47
+ * @since [*next-version*]
48
+ */
49
+ public function getValue(EntityInterface $entity)
50
+ {
51
+ return call_user_func_array($this->getter, [$entity]);
52
+ }
53
+
54
+ /**
55
+ * @inheritdoc
56
+ *
57
+ * @since [*next-version*]
58
+ */
59
+ public function setValue(EntityInterface $entity, $value)
60
+ {
61
+ return call_user_func_array($this->setter, [$entity, $value]);
62
+ }
63
+ }
lib/Entities/Properties/DefaultingProperty.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities\Properties;
4
+
5
+ use OutOfBoundsException;
6
+ use RebelCode\Entities\Api\EntityInterface;
7
+ use RebelCode\Entities\Api\PropertyInterface;
8
+
9
+ /**
10
+ * An implementation of a property that will default to a series of data store keys until a valid value is found.
11
+ *
12
+ * @since [*next-version*]
13
+ */
14
+ class DefaultingProperty implements PropertyInterface
15
+ {
16
+ /**
17
+ * @since [*next-version*]
18
+ *
19
+ * @var array
20
+ */
21
+ protected $keys;
22
+
23
+ /**
24
+ * @since [*next-version*]
25
+ *
26
+ * @var callable
27
+ */
28
+ protected $fn;
29
+
30
+ /**
31
+ * Constructor.
32
+ *
33
+ * @since [*next-version*]
34
+ *
35
+ * @param array $keys
36
+ * @param callable $fn
37
+ */
38
+ public function __construct(array $keys, callable $fn = null)
39
+ {
40
+ $this->keys = $keys;
41
+ $this->fn = is_callable($fn)
42
+ ? $fn
43
+ : function ($v) {
44
+ return empty($v);
45
+ };
46
+ }
47
+
48
+ /**
49
+ * @inheritdoc
50
+ *
51
+ * @since [*next-version*]
52
+ */
53
+ public function getValue(EntityInterface $entity)
54
+ {
55
+ $store = $entity->getStore();
56
+
57
+ foreach ($this->keys as $key) {
58
+ try {
59
+ $value = $store->get($key);
60
+
61
+ if (call_user_func_array($this->fn, [$value])) {
62
+ continue;
63
+ }
64
+ } catch (OutOfBoundsException $exception) {
65
+ continue;
66
+ }
67
+
68
+ return $value;
69
+ }
70
+
71
+ throw new OutOfBoundsException('No value exists for: ' . implode(', ', $this->keys));
72
+ }
73
+
74
+ /**
75
+ * @inheritdoc
76
+ *
77
+ * @since [*next-version*]
78
+ */
79
+ public function setValue(EntityInterface $entity, $value)
80
+ {
81
+ $key = reset($this->keys);
82
+
83
+ return [$key => $value];
84
+ }
85
+ }
lib/Entities/Properties/Property.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities\Properties;
4
+
5
+ use RebelCode\Entities\Api\EntityInterface;
6
+ use RebelCode\Entities\Api\PropertyInterface;
7
+
8
+ /**
9
+ * A simple implementation of a property that just reads and writes values to/from the data store.
10
+ *
11
+ * @since [*next-version*]
12
+ */
13
+ class Property implements PropertyInterface
14
+ {
15
+ /**
16
+ * @since [*next-version*]
17
+ *
18
+ * @var string
19
+ */
20
+ protected $key;
21
+
22
+ /**
23
+ * Constructor.
24
+ *
25
+ * @since [*next-version*]
26
+ *
27
+ * @param string $key The data store key to read from and write to.
28
+ */
29
+ public function __construct($key)
30
+ {
31
+ $this->key = $key;
32
+ }
33
+
34
+ /**
35
+ * @inheritdoc
36
+ *
37
+ * @since [*next-version*]
38
+ */
39
+ public function getValue(EntityInterface $entity)
40
+ {
41
+ return $entity->getStore()->get($this->key);
42
+ }
43
+
44
+ /**
45
+ * @inheritdoc
46
+ *
47
+ * @since [*next-version*]
48
+ */
49
+ public function setValue(EntityInterface $entity, $value)
50
+ {
51
+ return [$this->key => $value];
52
+ }
53
+ }
lib/Entities/Schemas/Schema.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities\Schemas;
4
+
5
+ use RebelCode\Entities\Api\PropertyInterface;
6
+ use RebelCode\Entities\Api\SchemaInterface;
7
+
8
+ /**
9
+ * A simple implementation for a generic schema.
10
+ *
11
+ * @since [*next-version*]
12
+ */
13
+ class Schema implements SchemaInterface
14
+ {
15
+ /**
16
+ * @since [*next-version*]
17
+ *
18
+ * @var PropertyInterface[]
19
+ */
20
+ protected $properties;
21
+
22
+ /**
23
+ * @since [*next-version*]
24
+ *
25
+ * @var array
26
+ */
27
+ protected $defaults;
28
+
29
+ /**
30
+ * Constructor.
31
+ *
32
+ * @since [*next-version*]
33
+ *
34
+ * @param PropertyInterface[] $properties A map of property keys to property instances.
35
+ * @param array $defaults A map of property keys to their default values.
36
+ */
37
+ public function __construct(array $properties, array $defaults)
38
+ {
39
+ $this->properties = $properties;
40
+ $this->defaults = $defaults;
41
+ }
42
+
43
+ /**
44
+ * @inheritdoc
45
+ *
46
+ * @since [*next-version*]
47
+ */
48
+ public function getProperties()
49
+ {
50
+ return $this->properties;
51
+ }
52
+
53
+ /**
54
+ * @inheritdoc
55
+ *
56
+ * @since [*next-version*]
57
+ */
58
+ public function getDefaults()
59
+ {
60
+ return $this->defaults;
61
+ }
62
+ }
lib/Entities/Stores/ArrayStore.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities\Stores;
4
+
5
+ use OutOfBoundsException;
6
+ use RebelCode\Entities\Api\StoreInterface;
7
+
8
+ /**
9
+ * A simple implementation of a data store that keeps the data in an internal array.
10
+ *
11
+ * @since [*next-version*]
12
+ */
13
+ class ArrayStore implements StoreInterface
14
+ {
15
+ /**
16
+ * @since [*next-version*]
17
+ *
18
+ * @var array
19
+ */
20
+ protected $data;
21
+
22
+ /**
23
+ * Constructor.
24
+ *
25
+ * @since [*next-version*]
26
+ *
27
+ * @param array $data
28
+ */
29
+ public function __construct(array $data)
30
+ {
31
+ $this->data = $data;
32
+ }
33
+
34
+ /**
35
+ * @inheritdoc
36
+ *
37
+ * @since [*next-version*]
38
+ */
39
+ public function get($key)
40
+ {
41
+ if (!array_key_exists($key, $this->data)) {
42
+ throw new OutOfBoundsException();
43
+ }
44
+
45
+ return $this->data[$key];
46
+ }
47
+
48
+ /**
49
+ * @inheritdoc
50
+ *
51
+ * @since [*next-version*]
52
+ */
53
+ public function has($key)
54
+ {
55
+ return array_key_exists($key, $this->data);
56
+ }
57
+
58
+ /**
59
+ * @inheritdoc
60
+ *
61
+ * @since [*next-version*]
62
+ */
63
+ public function set(array $data)
64
+ {
65
+ $instance = clone $this;
66
+
67
+ foreach ($data as $key => $value) {
68
+ $instance->data[$key] = $value;
69
+ }
70
+
71
+ return $instance;
72
+ }
73
+ }
lib/Entities/Stores/EntityStore.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Entities\Stores;
4
+
5
+ use OutOfBoundsException;
6
+ use RebelCode\Entities\Api\EntityInterface;
7
+ use RebelCode\Entities\Api\StoreInterface;
8
+
9
+ /**
10
+ * A data store implementation that uses an entity as its storage medium.
11
+ *
12
+ * @since [*next-version*]
13
+ */
14
+ class EntityStore implements StoreInterface
15
+ {
16
+ /**
17
+ * @since [*next-version*]
18
+ *
19
+ * @var EntityInterface
20
+ */
21
+ protected $entity;
22
+
23
+ /**
24
+ * Constructor.
25
+ *
26
+ * @since [*next-version*]
27
+ *
28
+ * @param EntityInterface $entity
29
+ */
30
+ public function __construct(EntityInterface $entity)
31
+ {
32
+ $this->entity = $entity;
33
+ }
34
+
35
+ /**
36
+ * @inheritdoc
37
+ *
38
+ * @since [*next-version*]
39
+ */
40
+ public function get($key)
41
+ {
42
+ return $this->entity->get($key);
43
+ }
44
+
45
+ /**
46
+ * @inheritdoc
47
+ *
48
+ * @since [*next-version*]
49
+ */
50
+ public function has($key)
51
+ {
52
+ try {
53
+ $this->entity->get($key);
54
+
55
+ return true;
56
+ } catch (OutOfBoundsException $exception) {
57
+ return false;
58
+ }
59
+ }
60
+
61
+ /**
62
+ * @inheritdoc
63
+ *
64
+ * @since [*next-version*]
65
+ */
66
+ public function set(array $data)
67
+ {
68
+ $instance = clone $this;
69
+ $instance->entity = $this->entity->set($data);
70
+
71
+ return $instance;
72
+ }
73
+ }
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: RSS import, RSS aggregator, feed import, content curation, feed to post
5
  Requires at least: 4.0 or higher
6
  Tested up to: 5.2.2
7
  Requires PHP: 5.4
8
- Stable tag: 4.15.2
9
  License: GPLv3
10
 
11
  WP RSS Aggregator is the original & most popular WordPress solution for importing RSS feeds, auto-blogging, content curation & aggregation.
@@ -259,22 +259,13 @@ Our complete Knowledge Base with FAQs can be found [here](https://kb.wprssaggreg
259
 
260
  == Changelog ==
261
 
262
- = 4.15.2 (2019-10-03) =
263
-
264
- **Added**
265
- - Links and integrations with Lorem for custom developer work.
266
 
267
  **Changed**
268
- - The default logging type is now "debug".
269
- - Feeds are now sorted alphabetically by default.
270
 
271
  **Fixed**
272
- - Multisite installations only allowed the main site to have activated licenses.
273
- - License notices now only appear on the main site if the site is a multisite network.
274
- - Blacklist items would occassionally be saved without a permalink.
275
- - Older versions of add-ons triggered errors when trying to log messages with the default log type.
276
- - Fixed checkbox legacy display options not saving correctly.
277
- - A saved empty useragent string in the settings caused the internal default to not be used.
278
- - The certificate path option was not defaulting correctly.
279
- - Media thumbnail images were not being detected properly.
280
- - An invalid feed would trigger false positive errors on fetch.
5
  Requires at least: 4.0 or higher
6
  Tested up to: 5.2.2
7
  Requires PHP: 5.4
8
+ Stable tag: 4.16
9
  License: GPLv3
10
 
11
  WP RSS Aggregator is the original & most popular WordPress solution for importing RSS feeds, auto-blogging, content curation & aggregation.
259
 
260
  == Changelog ==
261
 
262
+ = 4.16 (2019-10-31) =
 
 
 
263
 
264
  **Changed**
265
+ - Overhauled the data set system with a more robust entity system.
266
+ - Various database optimizations for better performance.
267
 
268
  **Fixed**
269
+ - Incompatibility with other plugins that use similar import/export mechanisms.
270
+ - Incompatibility with PolyLang, causing the block and shortcode to show no feed items.
271
+ - Timeout and infinite loop when saving a feed source.
 
 
 
 
 
 
src/Data/Collections/WpPostCollection.php CHANGED
@@ -2,472 +2,5 @@
2
 
3
  namespace RebelCode\Wpra\Core\Data\Collections;
4
 
5
- use ArrayAccess;
6
- use ArrayIterator;
7
- use Dhii\Exception\CreateInvalidArgumentExceptionCapableTrait;
8
- use Dhii\I18n\StringTranslatingTrait;
9
- use Dhii\Util\Normalization\NormalizeArrayCapableTrait;
10
- use InvalidArgumentException;
11
- use OutOfRangeException;
12
- use RebelCode\Wpra\Core\Data\AbstractDataSet;
13
- use RebelCode\Wpra\Core\Data\DataSetInterface;
14
- use RebelCode\Wpra\Core\Data\Wp\WpPostDataSet;
15
- use RuntimeException;
16
- use stdClass;
17
- use Traversable;
18
- use WP_Error;
19
- use WP_Post;
20
-
21
- /**
22
- * A data set implementation that acts as a wrapper for a collection of posts.
23
- *
24
- * @since 4.13
25
- */
26
- class WpPostCollection extends AbstractDataSet implements CollectionInterface
27
- {
28
- /* @since 4.13 */
29
- use NormalizeArrayCapableTrait;
30
-
31
- /* @since 4.13 */
32
- use CreateInvalidArgumentExceptionCapableTrait;
33
-
34
- /* @since 4.13 */
35
- use StringTranslatingTrait;
36
-
37
- /**
38
- * The post type.
39
- *
40
- * @since 4.13
41
- *
42
- * @var string
43
- */
44
- protected $postType;
45
-
46
- /**
47
- * The meta query.
48
- *
49
- * @since 4.13
50
- *
51
- * @var array
52
- */
53
- protected $metaQuery;
54
-
55
- /**
56
- * The ID of the last inserted post.
57
- *
58
- * @since 4.13
59
- *
60
- * @var int|string
61
- */
62
- protected $lastInsertedId;
63
-
64
- /**
65
- * Optional filter to restrict the collection query.
66
- *
67
- * @since 4.13
68
- *
69
- * @var array|null
70
- */
71
- protected $filter;
72
-
73
- /**
74
- * Constructor.
75
- *
76
- * @since 4.13
77
- *
78
- * @param string $postType The post type.
79
- * @param array $metaQuery The meta query.
80
- * @param array|null $filter Optional filter to restrict the collection query.
81
- */
82
- public function __construct($postType, $metaQuery = [], $filter = null)
83
- {
84
- $this->postType = $postType;
85
- $this->metaQuery = $metaQuery;
86
- $this->filter = $filter;
87
- }
88
-
89
- /**
90
- * {@inheritdoc}
91
- *
92
- * @since 4.13
93
- */
94
- public function offsetGet($key)
95
- {
96
- return $this->get($key);
97
- }
98
-
99
- /**
100
- * {@inheritdoc}
101
- *
102
- * @since 4.13
103
- */
104
- protected function get($key)
105
- {
106
- if ($key === null && $this->lastInsertedId !== null) {
107
- return $this->offsetGet($this->lastInsertedId);
108
- }
109
-
110
- $posts = $this->queryPosts($key);
111
-
112
- if (count($posts) === 0) {
113
- throw new OutOfRangeException(
114
- sprintf(__('Post "%s" was not found', 'wprss'), $key)
115
- );
116
- }
117
-
118
- $post = reset($posts);
119
- $result = $this->createModel($post);
120
-
121
- return $result;
122
- }
123
-
124
- /**
125
- * {@inheritdoc}
126
- *
127
- * @since 4.13
128
- */
129
- protected function has($key)
130
- {
131
- if ($key === null) {
132
- return false;
133
- }
134
-
135
- $posts = $this->queryPosts($key);
136
-
137
- return count($posts) === 1;
138
- }
139
-
140
- /**
141
- * {@inheritdoc}
142
- *
143
- * @since 4.13
144
- */
145
- protected function set($key, $data)
146
- {
147
- if ($key === null) {
148
- $this->createPost($data);
149
-
150
- return;
151
- }
152
-
153
- $this->updatePost($key, $data);
154
- }
155
-
156
- /**
157
- * {@inheritdoc}
158
- *
159
- * @since 4.13
160
- */
161
- protected function delete($key)
162
- {
163
- wp_delete_post($key, true);
164
- }
165
-
166
- /**
167
- * {@inheritdoc}
168
- *
169
- * @since 4.13
170
- */
171
- public function filter($filter)
172
- {
173
- if (!is_array($filter)) {
174
- throw new InvalidArgumentException('Collection filter argument is not an array');
175
- }
176
-
177
- if (empty($filter)) {
178
- return $this;
179
- }
180
-
181
- $currFilter = empty($this->filter) ? [] : $this->filter;
182
- $newFilter = array_merge_recursive_distinct($currFilter, $filter);
183
-
184
- return $this->createSelfWithFilter($newFilter);
185
- }
186
-
187
- /**
188
- * {@inheritdoc}
189
- *
190
- * @since 4.13
191
- */
192
- public function getCount()
193
- {
194
- return count($this->queryPosts(null));
195
- }
196
-
197
- /**
198
- * {@inheritdoc}
199
- *
200
- * @since 4.13
201
- */
202
- public function clear()
203
- {
204
- foreach ($this->getIterator() as $post) {
205
- $this->delete($post->ID);
206
- }
207
- }
208
-
209
- /**
210
- * Creates a new post using the given data.
211
- *
212
- * @since 4.13
213
- *
214
- * @param array $data The data to create the post with.
215
- */
216
- protected function createPost($data)
217
- {
218
- $post = $this->getNewPostData($data);
219
- $result = wp_insert_post($post, true);
220
-
221
- if ($result instanceof WP_Error) {
222
- throw new RuntimeException($result->get_error_message());
223
- }
224
-
225
- $this->lastInsertedId = $result;
226
-
227
- // Temporarily disable the filter
228
- $tFilter = $this->filter;
229
- $this->filter = [];
230
-
231
- $this->updatePost($result, $data);
232
-
233
- // Restore the filter
234
- $this->filter = $tFilter;
235
- }
236
-
237
- /**
238
- * Updates a post.
239
- *
240
- * @since 4.13
241
- *
242
- * @param int|string $key The post's key (ID or slug).
243
- * @param array $data The data to update the post with.
244
- */
245
- protected function updatePost($key, $data)
246
- {
247
- $post = $this->get($key);
248
- $data = $this->getUpdatePostData($key, $data);
249
-
250
- foreach ($data as $k => $v) {
251
- $post[$k] = $v;
252
- }
253
- }
254
-
255
- /**
256
- * Retrieves the data to use for creating a new post.
257
- *
258
- * @since 4.13
259
- *
260
- * @param array $data The data being used to create the post.
261
- *
262
- * @return array The actual data to use with {@link wp_insert_post}.
263
- */
264
- protected function getNewPostData($data)
265
- {
266
- return [
267
- 'post_type' => $this->postType,
268
- ];
269
- }
270
-
271
- /**
272
- * Retrieves the data to use for updating a post.
273
- *
274
- * @since 4.13
275
- *
276
- * @param int|string $key The post key (ID or slug).
277
- * @param array $data The data being used to update the post.
278
- *
279
- * @return array The actual data to update the post with.
280
- */
281
- protected function getUpdatePostData($key, $data)
282
- {
283
- return $data;
284
- }
285
-
286
- /**
287
- * Normalizes a variable into a post array,
288
- *
289
- * @since 4.13
290
- *
291
- * @param array|stdClass|Traversable|WP_Post $post Post data array, object or iterable, or a WP_Post instance.
292
- *
293
- * @return array The post data array.
294
- */
295
- protected function toPostArray($post)
296
- {
297
- if ($post instanceof WP_Post) {
298
- return $post->to_array();
299
- }
300
-
301
- return $this->_normalizeArray($post);
302
- }
303
-
304
- /**
305
- * Recursively patches a subject with every entry in a given patch data array.
306
- *
307
- * @since 4.13
308
- *
309
- * @param array|ArrayAccess $subject The subject to patch.
310
- * @param array|stdClass|Traversable $patch The data to patch the subject with.
311
- *
312
- * @return array|ArrayAccess The patched subject.
313
- */
314
- protected function recursivePatch($subject, $patch)
315
- {
316
- foreach ($patch as $key => $value) {
317
- $subject[$key] = $value;
318
- }
319
-
320
- return $subject;
321
- }
322
-
323
- /**
324
- * {@inheritdoc}
325
- *
326
- * @since 4.13
327
- */
328
- protected function getIterator()
329
- {
330
- return new ArrayIterator($this->queryPosts(null));
331
- }
332
-
333
- /**
334
- * {@inheritdoc}
335
- *
336
- * @since 4.13
337
- */
338
- protected function recursiveUnpackIterators()
339
- {
340
- return true;
341
- }
342
-
343
- /**
344
- * {@inheritdoc}
345
- *
346
- * @since 4.13
347
- */
348
- protected function createIterationValue($value)
349
- {
350
- return $this->createModel($value);
351
- }
352
-
353
- /**
354
- * Creates the resulting dataset model.
355
- *
356
- * @since 4.13
357
- *
358
- * @param WP_Post $post The post.
359
- *
360
- * @return DataSetInterface The dataset model.
361
- */
362
- protected function createModel(WP_Post $post)
363
- {
364
- return new WpPostDataSet($post);
365
- }
366
-
367
- /**
368
- * Queries the posts.
369
- *
370
- * @since 4.13
371
- *
372
- * @param int|string|null $key Optional ID or slug which, if not null, narrows down the query to only that post.
373
- *
374
- * @return WP_Post[] An array of posts objects.
375
- */
376
- protected function queryPosts($key = null)
377
- {
378
- $queryArgs = $this->getBasePostQueryArgs();
379
-
380
- if ($key !== null && is_numeric($key)) {
381
- $queryArgs['p'] = $key;
382
- }
383
-
384
- if ($key !== null && is_string($key) && !is_numeric($key)) {
385
- $queryArgs['name'] = $key;
386
- }
387
-
388
- $filter = is_array($this->filter) ? $this->filter : [];
389
-
390
- foreach ($filter as $fKey => $fVal) {
391
- $handled = $this->handleFilter($queryArgs, $fKey, $fVal);
392
-
393
- if (!$handled) {
394
- $queryArgs[$fKey] = $fVal;
395
- }
396
- }
397
-
398
- return get_posts($queryArgs);
399
- }
400
-
401
- /**
402
- * Retrieves the base (bare minimum) post query args.
403
- *
404
- * @since 4.13
405
- *
406
- * @return array
407
- */
408
- protected function getBasePostQueryArgs()
409
- {
410
- return [
411
- 'post_type' => $this->postType,
412
- 'post_status' => array_keys(get_post_statuses()),
413
- 'suppress_filters' => true,
414
- 'cache_results' => false,
415
- 'posts_per_page' => -1,
416
- 'meta_query' => $this->metaQuery,
417
- ];
418
- }
419
-
420
- /**
421
- * Handles the processing of a filter.
422
- *
423
- * @since 4.13
424
- *
425
- * @param array $queryArgs The query arguments to modify, passed by reference.
426
- * @param string $key The filter key.
427
- * @param mixed $value The filter value.
428
- *
429
- * @return bool True if the filter was handled, false if it wasn't.
430
- */
431
- protected function handleFilter(&$queryArgs, $key, $value)
432
- {
433
- if ($key === 'id') {
434
- $queryArgs['post__in'] = is_array($value) ? $value : [$value];
435
-
436
- return true;
437
- }
438
-
439
- if ($key === 's') {
440
- $queryArgs['s'] = $value;
441
-
442
- return true;
443
- }
444
-
445
- if ($key === 'num_items') {
446
- $queryArgs['posts_per_page'] = (!$value) ? -1 : $value;
447
-
448
- return true;
449
- }
450
-
451
- if ($key === 'page') {
452
- $queryArgs['paged'] = $value;
453
-
454
- return true;
455
- }
456
-
457
- return false;
458
- }
459
-
460
- /**
461
- * Creates a new collection of this type with an added filter.
462
- *
463
- * @since 4.13
464
- *
465
- * @param array $filter The filter for restricting the collection query.
466
- *
467
- * @return CollectionInterface
468
- */
469
- protected function createSelfWithFilter($filter)
470
- {
471
- return new static($this->postType, $this->metaQuery, $filter);
472
- }
473
- }
2
 
3
  namespace RebelCode\Wpra\Core\Data\Collections;
4
 
5
+ // Autoload the new class
6
+ class_exists('RebelCode\Wpra\Core\Entities\Collections\WpEntityCollection');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/Data/EntityDataSet.php ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Data;
4
+
5
+ use ArrayIterator;
6
+ use OutOfBoundsException;
7
+ use RebelCode\Entities\Api\EntityInterface;
8
+ use RebelCode\Wpra\Core\Util\IteratorDelegateTrait;
9
+
10
+ /**
11
+ * A data set adapter for entity instances.
12
+ *
13
+ * @since 4.16
14
+ */
15
+ class EntityDataSet implements DataSetInterface, EntityInterface
16
+ {
17
+ /**
18
+ * @since 4.16
19
+ */
20
+ use IteratorDelegateTrait;
21
+
22
+ /**
23
+ * @since 4.16
24
+ *
25
+ * @var EntityInterface
26
+ */
27
+ protected $entity;
28
+
29
+ /**
30
+ * Constructor.
31
+ *
32
+ * @since 4.16
33
+ *
34
+ * @param EntityInterface $entity The entity instance.
35
+ */
36
+ public function __construct(EntityInterface $entity)
37
+ {
38
+ $this->entity = $entity;
39
+ }
40
+
41
+ /**
42
+ * @inheritdoc
43
+ *
44
+ * @since 4.16
45
+ */
46
+ public function offsetExists($offset)
47
+ {
48
+ try {
49
+ $this->entity->get($offset);
50
+
51
+ return true;
52
+ } catch (OutOfBoundsException $exception) {
53
+ return false;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * @inheritdoc
59
+ *
60
+ * @since 4.16
61
+ */
62
+ public function offsetGet($offset)
63
+ {
64
+ return $this->entity->get($offset);
65
+ }
66
+
67
+ /**
68
+ * @inheritdoc
69
+ *
70
+ * @since 4.16
71
+ */
72
+ public function offsetSet($offset, $value)
73
+ {
74
+ $this->entity = $this->entity->set([$offset => $value]);
75
+ }
76
+
77
+ /**
78
+ * @inheritdoc
79
+ *
80
+ * @since 4.16
81
+ */
82
+ public function offsetUnset($offset)
83
+ {
84
+ $this->entity = $this->entity->set([$offset => '']);
85
+ }
86
+
87
+ /**
88
+ * @inheritdoc
89
+ *
90
+ * @since 4.16
91
+ */
92
+ protected function getIterator()
93
+ {
94
+ return new ArrayIterator($this->entity->export());
95
+ }
96
+
97
+ /**
98
+ * @inheritdoc
99
+ *
100
+ * @since 4.16
101
+ */
102
+ public function get($key)
103
+ {
104
+ return $this->entity->get($key);
105
+ }
106
+
107
+ /**
108
+ * @inheritdoc
109
+ *
110
+ * @since 4.16
111
+ */
112
+ public function set(array $data)
113
+ {
114
+ return $this->entity->set($data);
115
+ }
116
+
117
+ /**
118
+ * @inheritdoc
119
+ *
120
+ * @since 4.16
121
+ */
122
+ public function getStore()
123
+ {
124
+ return $this->entity->getStore();
125
+ }
126
+
127
+ /**
128
+ * @inheritdoc
129
+ *
130
+ * @since 4.16
131
+ */
132
+ public function getSchema()
133
+ {
134
+ return $this->entity->getSchema();
135
+ }
136
+
137
+ /**
138
+ * @inheritdoc
139
+ *
140
+ * @since 4.16
141
+ */
142
+ public function export()
143
+ {
144
+ return $this->entity->export();
145
+ }
146
+ }
src/Entities/{Feeds/Items/WpPostFeedItemCollection.php → Collections/FeedItemCollection.php} RENAMED
@@ -1,38 +1,27 @@
1
  <?php
2
 
3
- namespace RebelCode\Wpra\Core\Entities\Feeds\Items;
4
 
5
- use RebelCode\Wpra\Core\Data\Collections\WpPostCollection;
6
- use WP_Post;
7
 
8
  /**
9
  * A collection implementation that is specific to WP RSS Aggregator feed items.
10
  *
11
  * @since 4.13
12
  */
13
- class WpPostFeedItemCollection extends WpPostCollection
14
  {
15
  /**
16
  * Constructor.
17
  *
18
- * @since 4.13
19
- *
20
- * @param string $postType The name of the post type.
21
- * @param array|null $filter Optional filter to restrict the collection query.
22
- */
23
- public function __construct($postType, $filter = null)
24
- {
25
- parent::__construct($postType, [], $filter);
26
- }
27
-
28
- /**
29
- * {@inheritdoc}
30
  *
31
- * @since 4.13
 
32
  */
33
- protected function createModel(WP_Post $post)
34
  {
35
- return new WpPostFeedItem($post);
36
  }
37
 
38
  /**
@@ -96,14 +85,4 @@ class WpPostFeedItemCollection extends WpPostCollection
96
 
97
  return $r;
98
  }
99
-
100
- /**
101
- * {@inheritdoc}
102
- *
103
- * @since 4.13
104
- */
105
- protected function createSelfWithFilter($filter)
106
- {
107
- return new static($this->postType, $filter);
108
- }
109
  }
1
  <?php
2
 
3
+ namespace RebelCode\Wpra\Core\Entities\Collections;
4
 
5
+ use RebelCode\Entities\Api\SchemaInterface;
 
6
 
7
  /**
8
  * A collection implementation that is specific to WP RSS Aggregator feed items.
9
  *
10
  * @since 4.13
11
  */
12
+ class FeedItemCollection extends WpEntityCollection
13
  {
14
  /**
15
  * Constructor.
16
  *
17
+ * @since 4.14
 
 
 
 
 
 
 
 
 
 
 
18
  *
19
+ * @param string $postType The name of the post type.
20
+ * @param SchemaInterface $schema The schema for feed item entities.
21
  */
22
+ public function __construct($postType, SchemaInterface $schema)
23
  {
24
+ parent::__construct($postType, $schema);
25
  }
26
 
27
  /**
85
 
86
  return $r;
87
  }
 
 
 
 
 
 
 
 
 
 
88
  }
src/Entities/Collections/FeedSourceCollection.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Entities\Collections;
4
+
5
+ use RebelCode\Entities\Api\SchemaInterface;
6
+
7
+ /**
8
+ * A collection implementation that is specific to WP RSS Aggregator feed sources.
9
+ *
10
+ * @since 4.14
11
+ */
12
+ class FeedSourceCollection extends WpEntityCollection
13
+ {
14
+ /**
15
+ * Constructor.
16
+ *
17
+ * @since 4.14
18
+ *
19
+ * @param string $postType The name of the post type.
20
+ * @param SchemaInterface $schema The entity schema to use for created entities.
21
+ */
22
+ public function __construct($postType, SchemaInterface $schema)
23
+ {
24
+ parent::__construct($postType, $schema);
25
+ }
26
+
27
+ /**
28
+ * {@inheritdoc}
29
+ *
30
+ * Overridden to ensure that only "published" feed sources are queried.
31
+ *
32
+ * @since 4.14
33
+ */
34
+ protected function getBasePostQueryArgs()
35
+ {
36
+ $args = parent::getBasePostQueryArgs();
37
+ $args['post_status'] = 'publish';
38
+
39
+ return $args;
40
+ }
41
+
42
+ /**
43
+ * {@inheritdoc}
44
+ *
45
+ * Overridden to ensure that new feed sources are "published".
46
+ *
47
+ * @since 4.14
48
+ */
49
+ protected function getNewPostData($data)
50
+ {
51
+ $postData = parent::getNewPostData($data);
52
+ $postData['post_status'] = 'publish';
53
+
54
+ return $postData;
55
+ }
56
+ }
src/Entities/{Feeds/Templates/WpPostFeedTemplateCollection.php → Collections/FeedTemplateCollection.php} RENAMED
@@ -1,8 +1,10 @@
1
  <?php
2
 
3
- namespace RebelCode\Wpra\Core\Entities\Feeds\Templates;
4
 
5
- use RebelCode\Wpra\Core\Data\Collections\WpPostCollection;
 
 
6
  use WP_Post;
7
 
8
  /**
@@ -10,7 +12,7 @@ use WP_Post;
10
  *
11
  * @since 4.13
12
  */
13
- class WpPostFeedTemplateCollection extends WpPostCollection
14
  {
15
  /**
16
  * The default template's type.
@@ -22,35 +24,28 @@ class WpPostFeedTemplateCollection extends WpPostCollection
22
  protected $defType;
23
 
24
  /**
25
- * Constructor.
26
- *
27
- * @since 4.13
28
  *
29
- * @param string $postType The name of the post type.
30
- * @param string $defType The default template's type.
31
- * @param array|null $filter Optional filter to restrict the collection query.
32
  */
33
- public function __construct($postType, $defType, $filter = null)
34
- {
35
- parent::__construct($postType, [], $filter);
36
-
37
- $this->defType = $defType;
38
- }
39
 
40
  /**
41
- * {@inheritdoc}
42
  *
43
  * @since 4.13
 
 
 
 
 
44
  */
45
- protected function createModel(WP_Post $post)
46
  {
47
- $model = new WpPostFeedTemplate($post);
48
 
49
- if (isset($model['type']) && $model['type'] === $this->defType) {
50
- return new BuiltInFeedTemplate($post);
51
- }
52
-
53
- return $model;
54
  }
55
 
56
  /**
@@ -72,7 +67,7 @@ class WpPostFeedTemplateCollection extends WpPostCollection
72
  /**
73
  * {@inheritdoc}
74
  *
75
- * Overridden to ensure that the slug updates with the title and that the status is still "publish".
76
  *
77
  * @since 4.13
78
  */
@@ -80,8 +75,7 @@ class WpPostFeedTemplateCollection extends WpPostCollection
80
  {
81
  $post = parent::getUpdatePostData($key, $data);
82
  // Clear the slug so WordPress re-generates it
83
- $post['post_name'] = '';
84
- $post['post_status'] = 'publish';
85
 
86
  return $post;
87
  }
@@ -89,7 +83,7 @@ class WpPostFeedTemplateCollection extends WpPostCollection
89
  /**
90
  * {@inheritdoc}
91
  *
92
- * Overridden to sort the templates by title, with builtin templates served at the very top of the list.
93
  *
94
  * @since 4.13
95
  */
@@ -97,16 +91,16 @@ class WpPostFeedTemplateCollection extends WpPostCollection
97
  {
98
  $posts = parent::queryPosts($key);
99
 
100
- usort($posts, function (WP_Post $a, WP_Post $b) {
101
- if ($a->wprss_template_type === '__built_in') {
102
  return -1;
103
  }
104
 
105
- if ($b->wprss_template_type === '__built_in') {
106
  return 1;
107
  }
108
 
109
- return strcmp($a->post_title, $b->post_title);
110
  });
111
 
112
  return $posts;
@@ -122,12 +116,12 @@ class WpPostFeedTemplateCollection extends WpPostCollection
122
  $r = parent::handleFilter($queryArgs, $key, $value);
123
 
124
  if ($key === 'type') {
125
- $subQuery = [
126
  'relation' => 'or',
127
  [
128
  'key' => 'wprss_template_type',
129
  'value' => $value,
130
- ]
131
  ];
132
  if ($value === 'list') {
133
  $subQuery[] = [
@@ -145,12 +139,20 @@ class WpPostFeedTemplateCollection extends WpPostCollection
145
  }
146
 
147
  /**
148
- * {@inheritdoc}
149
  *
150
- * @since 4.13
151
  */
152
- protected function createSelfWithFilter($filter)
153
  {
154
- return new static($this->postType, $this->defType, $filter);
 
 
 
 
 
 
 
 
155
  }
156
  }
1
  <?php
2
 
3
+ namespace RebelCode\Wpra\Core\Entities\Collections;
4
 
5
+ use RebelCode\Entities\Api\EntityInterface;
6
+ use RebelCode\Entities\Api\SchemaInterface;
7
+ use RebelCode\Entities\Entity;
8
  use WP_Post;
9
 
10
  /**
12
  *
13
  * @since 4.13
14
  */
15
+ class FeedTemplateCollection extends WpEntityCollection
16
  {
17
  /**
18
  * The default template's type.
24
  protected $defType;
25
 
26
  /**
27
+ * @since 4.16
 
 
28
  *
29
+ * @var callable
 
 
30
  */
31
+ protected $builtInStoreFactory;
 
 
 
 
 
32
 
33
  /**
34
+ * Constructor.
35
  *
36
  * @since 4.13
37
+ *
38
+ * @param string $postType The name of the post type.
39
+ * @param string $defType The default template's type.
40
+ * @param SchemaInterface $schema The schema for feed template entities.
41
+ * @param callable $builtInStoreFactory The factory that creates stores for builtin templates.
42
  */
43
+ public function __construct($postType, SchemaInterface $schema, $defType, callable $builtInStoreFactory)
44
  {
45
+ parent::__construct($postType, $schema);
46
 
47
+ $this->defType = $defType;
48
+ $this->builtInStoreFactory = $builtInStoreFactory;
 
 
 
49
  }
50
 
51
  /**
67
  /**
68
  * {@inheritdoc}
69
  *
70
+ * Overridden to ensure that the slug updates with the title.
71
  *
72
  * @since 4.13
73
  */
75
  {
76
  $post = parent::getUpdatePostData($key, $data);
77
  // Clear the slug so WordPress re-generates it
78
+ $post['slug'] = '';
 
79
 
80
  return $post;
81
  }
83
  /**
84
  * {@inheritdoc}
85
  *
86
+ * Overridden to sort the templates by title, with built in templates at the very top of the list.
87
  *
88
  * @since 4.13
89
  */
91
  {
92
  $posts = parent::queryPosts($key);
93
 
94
+ usort($posts, function (EntityInterface $a, EntityInterface $b) {
95
+ if ($a->get('type') === '__built_in') {
96
  return -1;
97
  }
98
 
99
+ if ($b->get('type') === '__built_in') {
100
  return 1;
101
  }
102
 
103
+ return strcmp($a->get('name'), $b->get('name'));
104
  });
105
 
106
  return $posts;
116
  $r = parent::handleFilter($queryArgs, $key, $value);
117
 
118
  if ($key === 'type') {
119
+ $subQuery = [
120
  'relation' => 'or',
121
  [
122
  'key' => 'wprss_template_type',
123
  'value' => $value,
124
+ ],
125
  ];
126
  if ($value === 'list') {
127
  $subQuery[] = [
139
  }
140
 
141
  /**
142
+ * @inheritdoc
143
  *
144
+ * @since 4.16
145
  */
146
+ protected function createEntity(WP_Post $post)
147
  {
148
+ $type = get_post_meta($post->ID, 'wprss_template_type', true);
149
+
150
+ if ($type === $this->defType) {
151
+ $store = call_user_func_array($this->builtInStoreFactory, [$post]);
152
+
153
+ return new Entity($this->schema, $store);
154
+ }
155
+
156
+ return parent::createEntity($post);
157
  }
158
  }
src/Entities/{Feeds/Items → Collections}/ImportedItemsCollection.php RENAMED
@@ -1,7 +1,8 @@
1
  <?php
2
 
3
- namespace RebelCode\Wpra\Core\Entities\Feeds\Items;
4
 
 
5
  use RuntimeException;
6
 
7
  /**
@@ -9,19 +10,19 @@ use RuntimeException;
9
  *
10
  * @since 4.13
11
  */
12
- class ImportedItemsCollection extends WpPostFeedItemCollection
13
  {
14
  /**
15
  * Constructor.
16
  *
17
  * @since 4.13
18
  *
19
- * @param array $metaQuery The meta query.
20
- * @param array|null $filter Optional filter to restrict the collection query.
21
  */
22
- public function __construct($metaQuery = [], $filter = null)
23
  {
24
- parent::__construct(null, $filter);
25
 
26
  $this->metaQuery = $metaQuery;
27
  }
1
  <?php
2
 
3
+ namespace RebelCode\Wpra\Core\Entities\Collections;
4
 
5
+ use RebelCode\Entities\Api\SchemaInterface;
6
  use RuntimeException;
7
 
8
  /**
10
  *
11
  * @since 4.13
12
  */
13
+ class ImportedItemsCollection extends FeedItemCollection
14
  {
15
  /**
16
  * Constructor.
17
  *
18
  * @since 4.13
19
  *
20
+ * @param array $metaQuery The meta query.
21
+ * @param SchemaInterface $schema The schema for imported item entities.
22
  */
23
+ public function __construct($metaQuery, SchemaInterface $schema)
24
  {
25
+ parent::__construct(null, $schema);
26
 
27
  $this->metaQuery = $metaQuery;
28
  }
src/Entities/Collections/WpEntityCollection.php ADDED
@@ -0,0 +1,509 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Entities\Collections;
4
+
5
+ use ArrayAccess;
6
+ use ArrayIterator;
7
+ use Dhii\Exception\CreateInvalidArgumentExceptionCapableTrait;
8
+ use Dhii\I18n\StringTranslatingTrait;
9
+ use Dhii\Util\Normalization\NormalizeArrayCapableTrait;
10
+ use InvalidArgumentException;
11
+ use OutOfRangeException;
12
+ use RebelCode\Entities\Api\EntityInterface;
13
+ use RebelCode\Entities\Api\SchemaInterface;
14
+ use RebelCode\Entities\Entity;
15
+ use RebelCode\Wpra\Core\Data\AbstractDataSet;
16
+ use RebelCode\Wpra\Core\Data\Collections\CollectionInterface;
17
+ use RebelCode\Wpra\Core\Data\DataSetInterface;
18
+ use RebelCode\Wpra\Core\Data\EntityDataSet;
19
+ use RebelCode\Wpra\Core\Entities\Stores\WpPostStore;
20
+ use RuntimeException;
21
+ use stdClass;
22
+ use Traversable;
23
+ use WP_Error;
24
+ use WP_Post;
25
+
26
+ /**
27
+ * An entity collection for WP entities.
28
+ *
29
+ * @since 4.13
30
+ */
31
+ class WpEntityCollection extends AbstractDataSet implements CollectionInterface
32
+ {
33
+ /* @since 4.13 */
34
+ use NormalizeArrayCapableTrait;
35
+
36
+ /* @since 4.13 */
37
+ use CreateInvalidArgumentExceptionCapableTrait;
38
+
39
+ /* @since 4.13 */
40
+ use StringTranslatingTrait;
41
+
42
+ /**
43
+ * The post type.
44
+ *
45
+ * @since 4.13
46
+ *
47
+ * @var string
48
+ */
49
+ protected $postType;
50
+
51
+ /**
52
+ * The meta query.
53
+ *
54
+ * @since 4.13
55
+ *
56
+ * @var array
57
+ */
58
+ protected $metaQuery;
59
+
60
+ /**
61
+ * The entity schema.
62
+ *
63
+ * @since 4.16
64
+ *
65
+ * @var SchemaInterface
66
+ */
67
+ protected $schema;
68
+
69
+ /**
70
+ * The ID of the last inserted post.
71
+ *
72
+ * @since 4.13
73
+ *
74
+ * @var int|string
75
+ */
76
+ protected $lastInsertedId;
77
+
78
+ /**
79
+ * Optional filter to restrict the collection query.
80
+ *
81
+ * @since 4.13
82
+ *
83
+ * @var array|null
84
+ */
85
+ protected $filter;
86
+
87
+ /**
88
+ * Constructor.
89
+ *
90
+ * @since 4.13
91
+ *
92
+ * @param string $postType The post type.
93
+ * @param SchemaInterface $schema The entity schema to use for created entities.
94
+ * @param array $metaQuery The meta query.
95
+ */
96
+ public function __construct($postType, SchemaInterface $schema, $metaQuery = [])
97
+ {
98
+ $this->postType = $postType;
99
+ $this->schema = $schema;
100
+ $this->metaQuery = $metaQuery;
101
+ $this->filter = [];
102
+ }
103
+
104
+ /**
105
+ * {@inheritdoc}
106
+ *
107
+ * @since 4.13
108
+ */
109
+ public function offsetGet($key)
110
+ {
111
+ return $this->get($key);
112
+ }
113
+
114
+ /**
115
+ * {@inheritdoc}
116
+ *
117
+ * @since 4.13
118
+ */
119
+ protected function get($key)
120
+ {
121
+ if ($key === null && $this->lastInsertedId !== null) {
122
+ return $this->offsetGet($this->lastInsertedId);
123
+ }
124
+
125
+ $posts = $this->queryPosts($key);
126
+
127
+ if (count($posts) === 0) {
128
+ throw new OutOfRangeException(
129
+ sprintf(__('Post "%s" was not found', 'wprss'), $key)
130
+ );
131
+ }
132
+
133
+ return reset($posts);
134
+ }
135
+
136
+ /**
137
+ * {@inheritdoc}
138
+ *
139
+ * @since 4.13
140
+ */
141
+ protected function has($key)
142
+ {
143
+ if ($key === null) {
144
+ return false;
145
+ }
146
+
147
+ $posts = $this->doWpQuery($key);
148
+
149
+ return count($posts) === 1;
150
+ }
151
+
152
+ /**
153
+ * {@inheritdoc}
154
+ *
155
+ * @since 4.13
156
+ */
157
+ protected function set($key, $data)
158
+ {
159
+ if ($key === null) {
160
+ $this->createPost($data);
161
+
162
+ return;
163
+ }
164
+
165
+ $this->updatePost($key, $data);
166
+ }
167
+
168
+ /**
169
+ * {@inheritdoc}
170
+ *
171
+ * @since 4.13
172
+ */
173
+ protected function delete($key)
174
+ {
175
+ wp_delete_post($key, true);
176
+ }
177
+
178
+ /**
179
+ * {@inheritdoc}
180
+ *
181
+ * @since 4.13
182
+ */
183
+ public function filter($filter)
184
+ {
185
+ if (!is_array($filter)) {
186
+ throw new InvalidArgumentException('Collection filter argument is not an array');
187
+ }
188
+
189
+ if (empty($filter)) {
190
+ return $this;
191
+ }
192
+
193
+ $currFilter = empty($this->filter) ? [] : $this->filter;
194
+ $newFilter = array_merge_recursive_distinct($currFilter, $filter);
195
+
196
+ return $this->createSelfWithFilter($newFilter);
197
+ }
198
+
199
+ /**
200
+ * {@inheritdoc}
201
+ *
202
+ * @since 4.13
203
+ */
204
+ public function getCount()
205
+ {
206
+ return count($this->doWpQuery(null));
207
+ }
208
+
209
+ /**
210
+ * {@inheritdoc}
211
+ *
212
+ * @since 4.13
213
+ */
214
+ public function clear()
215
+ {
216
+ foreach ($this->getIterator() as $post) {
217
+ $this->delete($post->ID);
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Creates a new post using the given data.
223
+ *
224
+ * @since 4.13
225
+ *
226
+ * @param array $data The data to create the post with.
227
+ */
228
+ protected function createPost($data)
229
+ {
230
+ $post = $this->getNewPostData($data);
231
+ $result = wp_insert_post($post, true);
232
+
233
+ if ($result instanceof WP_Error) {
234
+ throw new RuntimeException($result->get_error_message());
235
+ }
236
+
237
+ $this->lastInsertedId = $result;
238
+
239
+ // Temporarily disable the filter
240
+ $tFilter = $this->filter;
241
+ $this->filter = [];
242
+
243
+ $this->updatePost($result, $data);
244
+
245
+ // Restore the filter
246
+ $this->filter = $tFilter;
247
+ }
248
+
249
+ /**
250
+ * Updates a post.
251
+ *
252
+ * @since 4.13
253
+ *
254
+ * @param int|string $key The post's key (ID or slug).
255
+ * @param array $data The data to update the post with.
256
+ */
257
+ protected function updatePost($key, $data)
258
+ {
259
+ $post = $this->get($key);
260
+ $data = $this->getUpdatePostData($key, $data);
261
+
262
+ foreach ($data as $k => $v) {
263
+ $post[$k] = $v;
264
+ }
265
+ }
266
+
267
+ /**
268
+ * Retrieves the data to use for creating a new post.
269
+ *
270
+ * @since 4.13
271
+ *
272
+ * @param array $data The data being used to create the post.
273
+ *
274
+ * @return array The actual data to use with {@link wp_insert_post}.
275
+ */
276
+ protected function getNewPostData($data)
277
+ {
278
+ return [
279
+ 'post_type' => $this->postType,
280
+ ];
281
+ }
282
+
283
+ /**
284
+ * Retrieves the data to use for updating a post.
285
+ *
286
+ * @since 4.13
287
+ *
288
+ * @param int|string $key The post key (ID or slug).
289
+ * @param array $data The data being used to update the post.
290
+ *
291
+ * @return array The actual data to update the post with.
292
+ */
293
+ protected function getUpdatePostData($key, $data)
294
+ {
295
+ return $data;
296
+ }
297
+
298
+ /**
299
+ * Normalizes a variable into a post array,
300
+ *
301
+ * @since 4.13
302
+ *
303
+ * @param array|stdClass|Traversable|WP_Post $post Post data array, object or iterable, or a WP_Post instance.
304
+ *
305
+ * @return array The post data array.
306
+ */
307
+ protected function toPostArray($post)
308
+ {
309
+ if ($post instanceof WP_Post) {
310
+ return $post->to_array();
311
+ }
312
+
313
+ return $this->_normalizeArray($post);
314
+ }
315
+
316
+ /**
317
+ * Recursively patches a subject with every entry in a given patch data array.
318
+ *
319
+ * @since 4.13
320
+ *
321
+ * @param array|ArrayAccess $subject The subject to patch.
322
+ * @param array|stdClass|Traversable $patch The data to patch the subject with.
323
+ *
324
+ * @return array|ArrayAccess The patched subject.
325
+ */
326
+ protected function recursivePatch($subject, $patch)
327
+ {
328
+ foreach ($patch as $key => $value) {
329
+ $subject[$key] = $value;
330
+ }
331
+
332
+ return $subject;
333
+ }
334
+
335
+ /**
336
+ * {@inheritdoc}
337
+ *
338
+ * @since 4.13
339
+ */
340
+ protected function getIterator()
341
+ {
342
+ return new ArrayIterator($this->queryPosts(null));
343
+ }
344
+
345
+ /**
346
+ * Queries posts from the database and creates the data sets.
347
+ *
348
+ * @since 4.16
349
+ *
350
+ * @param int|string|null $key Optional ID or slug which, if not null, narrows down the query to only that post.
351
+ *
352
+ * @return DataSetInterface[] An array of posts objects.
353
+ */
354
+ protected function queryPosts($key = null)
355
+ {
356
+ $posts = $this->doWpQuery($key);
357
+
358
+ $results = [];
359
+ foreach ($posts as $post) {
360
+ $results[] = new EntityDataSet($this->createEntity($post));
361
+ }
362
+
363
+ return $results;
364
+ }
365
+
366
+ /**
367
+ * Creates an entity instance for a given WordPress post.
368
+ *
369
+ * @since 4.16
370
+ *
371
+ * @param WP_Post $post The WordPress post instance.
372
+ *
373
+ * @return EntityInterface The created entity instance.
374
+ */
375
+ protected function createEntity(WP_Post $post)
376
+ {
377
+ return new Entity($this->schema, new WpPostStore($post));
378
+ }
379
+
380
+ /**
381
+ * Queries the posts.
382
+ *
383
+ * Not recommended to be called directly. Use only for fast existence checks or counting.
384
+ *
385
+ * @since 4.13
386
+ *
387
+ * @see WpEntityCollection::queryPosts()
388
+ *
389
+ * @param int|string|null $key Optional ID or slug which, if not null, narrows down the query to only that post.
390
+ *
391
+ * @return WP_Post[] An array of posts objects.
392
+ */
393
+ protected function doWpQuery($key = null)
394
+ {
395
+ $queryArgs = $this->getBasePostQueryArgs();
396
+
397
+ if ($key !== null && is_numeric($key)) {
398
+ $queryArgs['p'] = $key;
399
+ }
400
+
401
+ if ($key !== null && is_string($key) && !is_numeric($key)) {
402
+ $queryArgs['name'] = $key;
403
+ }
404
+
405
+ $filter = is_array($this->filter) ? $this->filter : [];
406
+
407
+ foreach ($filter as $fKey => $fVal) {
408
+ $handled = $this->handleFilter($queryArgs, $fKey, $fVal);
409
+
410
+ if (!$handled) {
411
+ $queryArgs[$fKey] = $fVal;
412
+ }
413
+ }
414
+
415
+ return get_posts($queryArgs);
416
+ }
417
+
418
+ /**
419
+ * Retrieves the base (bare minimum) post query args.
420
+ *
421
+ * @since 4.13
422
+ *
423
+ * @return array
424
+ */
425
+ protected function getBasePostQueryArgs()
426
+ {
427
+ return [
428
+ 'post_type' => $this->postType,
429
+ 'post_status' => array_keys(get_post_statuses()),
430
+ 'suppress_filters' => true,
431
+ 'cache_results' => false,
432
+ 'posts_per_page' => -1,
433
+ 'meta_query' => $this->metaQuery,
434
+ ];
435
+ }
436
+
437
+ /**
438
+ * Handles the processing of a filter.
439
+ *
440
+ * @since 4.13
441
+ *
442
+ * @param array $queryArgs The query arguments to modify, passed by reference.
443
+ * @param string $key The filter key.
444
+ * @param mixed $value The filter value.
445
+ *
446
+ * @return bool True if the filter was handled, false if it wasn't.
447
+ */
448
+ protected function handleFilter(&$queryArgs, $key, $value)
449
+ {
450
+ if ($key === 'id') {
451
+ $queryArgs['post__in'] = is_array($value) ? $value : [$value];
452
+
453
+ return true;
454
+ }
455
+
456
+ if ($key === 's') {
457
+ $queryArgs['s'] = $value;
458
+
459
+ return true;
460
+ }
461
+
462
+ if ($key === 'num_items') {
463
+ $queryArgs['posts_per_page'] = (!$value) ? -1 : $value;
464
+
465
+ return true;
466
+ }
467
+
468
+ if ($key === 'page') {
469
+ $queryArgs['paged'] = $value;
470
+
471
+ return true;
472
+ }
473
+
474
+ return false;
475
+ }
476
+
477
+ /**
478
+ * {@inheritdoc}
479
+ *
480
+ * @since 4.13
481
+ */
482
+ protected function recursiveUnpackIterators()
483
+ {
484
+ return true;
485
+ }
486
+
487
+ /**
488
+ * Creates a new collection of this type with an added filter.
489
+ *
490
+ * @since 4.13
491
+ *
492
+ * @param array $filter The filter for restricting the collection query.
493
+ *
494
+ * @return CollectionInterface
495
+ */
496
+ protected function createSelfWithFilter($filter)
497
+ {
498
+ $instance = clone $this;
499
+ $instance->filter = $filter;
500
+
501
+ return $instance;
502
+ }
503
+ }
504
+
505
+ // Alias for the old WpPostCollection class.
506
+ class_alias(
507
+ 'RebelCode\Wpra\Core\Entities\Collections\WpEntityCollection',
508
+ 'RebelCode\Wpra\Core\Data\Collections\WpPostCollection'
509
+ );
src/Entities/Feeds/Items/WpPostFeedItem.php DELETED
@@ -1,236 +0,0 @@
1
- <?php
2
-
3
- namespace RebelCode\Wpra\Core\Entities\Feeds\Items;
4
-
5
- use LogicException;
6
- use OutOfRangeException;
7
- use RebelCode\Wpra\Core\Data\AliasingDataSet;
8
- use RebelCode\Wpra\Core\Data\ArrayDataSet;
9
- use RebelCode\Wpra\Core\Data\DataSetInterface;
10
- use RebelCode\Wpra\Core\Data\MergedDataSet;
11
- use RebelCode\Wpra\Core\Data\PrefixingDataSet;
12
- use RebelCode\Wpra\Core\Data\Wp\WpCptDataSet;
13
- use RebelCode\Wpra\Core\Entities\Feeds\Sources\WpPostFeedSource;
14
- use WP_Post;
15
-
16
- /**
17
- * An implementation of a data set for WP RSS Aggregator imported feed items.
18
- *
19
- * @since 4.13
20
- */
21
- class WpPostFeedItem extends WpCptDataSet
22
- {
23
- /**
24
- * The meta key prefix.
25
- *
26
- * @since 4.13
27
- */
28
- const META_PREFIX = 'wprss_';
29
-
30
- /**
31
- * The second item-specific meta key prefix.
32
- *
33
- * @since 4.14
34
- */
35
- const SECOND_META_PREFIX = 'wprss_item_';
36
-
37
- /**
38
- * The key to which to map the feed source dataset.
39
- *
40
- * @since 4.13
41
- */
42
- const SOURCE_KEY = 'source';
43
-
44
- /**
45
- * The key to which to map the feed item author.
46
- *
47
- * @since 4.13
48
- */
49
- const AUTHOR_KEY = 'author';
50
-
51
- /**
52
- * The key to which to map the feed item URL.
53
- *
54
- * @since 4.13
55
- */
56
- const URL_KEY = 'url';
57
-
58
- /**
59
- * The key to which to map the feed item timestamp.
60
- *
61
- * @since 4.13
62
- */
63
- const TIMESTAMP_KEY = 'timestamp';
64
-
65
- /**
66
- * The key to which to map the item featured image.
67
- *
68
- * @since 4.14
69
- */
70
- const FT_IMAGE_KEY = 'ft_image_url';
71
-
72
- /**
73
- * Constructor.
74
- *
75
- * @since 4.13
76
- *
77
- * @param int|string|WP_Post $post The WordPress Post object or post ID.
78
- *
79
- * @throws OutOfRangeException If the post does not exist.
80
- */
81
- public function __construct($post)
82
- {
83
- parent::__construct($post, static::META_PREFIX, [
84
- 'ID',
85
- 'post_title',
86
- 'post_content',
87
- 'post_excerpt',
88
- 'post_date'
89
- ]);
90
- }
91
-
92
- /**
93
- * {@inheritdoc}
94
- *
95
- * @since 4.13
96
- */
97
- protected function createPostDataSet($postOrId)
98
- {
99
- $postData = parent::createPostDataSet($postOrId);
100
- $prefixed = new PrefixingDataSet($postData, 'post_');
101
- $aliased = new AliasingDataSet($prefixed, ['id' => 'ID']);
102
-
103
- return $aliased;
104
- }
105
-
106
- /**
107
- * {@inheritdoc}
108
- *
109
- * @since 4.13
110
- */
111
- protected function createMetaDataSet($postOrId)
112
- {
113
- // Add the second meta prefix
114
- $prefixed = new PrefixingDataSet(parent::createMetaDataSet($postOrId), static::SECOND_META_PREFIX);
115
-
116
- // Alias some of the meta data
117
- $aliased = new AliasingDataSet($prefixed, [
118
- 'source_id' => 'feed_id',
119
- ]);
120
-
121
- $post = $this->normalizeWpPost($postOrId);
122
- $wrapped = $this->wrapPostMetaDataSet($post, $aliased);
123
-
124
- return $wrapped;
125
- }
126
-
127
- /**
128
- * Wraps the post meta dataset with an additional layer that contains virtual data.
129
- *
130
- * @since 4.13
131
- *
132
- * @param WP_Post $post The post instance for the feed item.
133
- * @param DataSetInterface $meta The post meta dataset.
134
- *
135
- * @return DataSetInterface The wrapped post meta dataset.
136
- */
137
- protected function wrapPostMetaDataSet(WP_Post $post, DataSetInterface $meta)
138
- {
139
- $source = new WpPostFeedSource($meta['source_id']);
140
- $importSource = filter_var($source['import_source'], FILTER_VALIDATE_BOOLEAN);
141
-
142
- $wrapperData = [
143
- static::SOURCE_KEY => $source,
144
- static::TIMESTAMP_KEY => strtotime($post->post_date_gmt),
145
- static::FT_IMAGE_KEY => $this->getFtImageUrl($post),
146
- static::URL_KEY => $this->getItemUrl($post, $meta, $source),
147
- 'source_name' => $importSource ? $meta['source_name'] : $source['title'],
148
- 'source_url' => $importSource ? $meta['source_url'] : $source['site_url'],
149
- ];
150
-
151
- // For non-WPRSS feed items, use the real WordPress post author if the meta author does not exist
152
- if ($post->post_type !== 'wprss_feed_item' && empty($meta[static::AUTHOR_KEY])) {
153
- $wrapperData[static::AUTHOR_KEY] = get_the_author_meta('display_name', $post->post_author);
154
- }
155
-
156
- // Create a copy of the wrapper data with all the values replaced with `true`
157
- // This will be used as the override map for the merged data set
158
- $overrides = array_map('__return_true', $wrapperData);
159
-
160
- // Merge the real meta data with the wrapper dataset,
161
- // and explicitly set the secondary dataset to override to wrapper's entries
162
- $wrapper = new ArrayDataSet($wrapperData);
163
- $merged = new MergedDataSet($meta, $wrapper, $overrides);
164
-
165
- return $merged;
166
- }
167
-
168
- /**
169
- * {@inheritdoc}
170
- *
171
- * @since 4.13
172
- */
173
- protected function set($key, $value)
174
- {
175
- if ($key === static::SOURCE_KEY) {
176
- throw new LogicException(
177
- sprintf('Cannot modify a feed item\'s "%s" data directly. Use "source_id" instead.', static::SOURCE_KEY)
178
- );
179
- }
180
-
181
- return parent::set($key, $value);
182
- }
183
-
184
- /**
185
- * Retrieves the featured image URL for the feed item.
186
- *
187
- * @since 4.14
188
- *
189
- * @param WP_Post $post The post for the feed item.
190
- *
191
- * @return string|null The URL of the featured image or null if the item has no featured image.
192
- */
193
- protected function getFtImageUrl($post)
194
- {
195
- // Fetch the featured image first
196
- $attachment = wp_get_attachment_image_url(get_post_thumbnail_id($post->ID), '');
197
- if ($attachment !== false) {
198
- return $attachment;
199
- }
200
-
201
- // Then try the old E&T meta key
202
- $etThumbnail = get_post_meta($post->ID, 'wprss_item_thumbnail', true);
203
- if (!empty($etThumbnail)) {
204
- return $etThumbnail;
205
- }
206
-
207
- return null;
208
- }
209
-
210
- /**
211
- * Retrieves the item URL to use for a feed item.
212
- *
213
- * @since 4.14
214
- *
215
- * @param WP_Post $post The post object.
216
- * @param DataSetInterface $meta The meta data set.
217
- * @param DataSetInterface $source The feed source data set.
218
- *
219
- * @return string
220
- */
221
- protected function getItemUrl($post, $meta, $source)
222
- {
223
- // If not a WPRSS feed item, use its WordPress post permalink
224
- if ($post->post_type !== 'wprss_feed_item') {
225
- return get_permalink($post);
226
- }
227
-
228
- // Use the enclosure if the feed source option is enabled and the item has an enclosure link
229
- if (!empty($source['enclosure']) && filter_var($source['enclosure'], FILTER_VALIDATE_BOOLEAN) && !empty($meta['enclosure'])) {
230
- return $meta['enclosure'];
231
- }
232
-
233
- // Use the permalink in the meta data
234
- return $meta['permalink'];
235
- }
236
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/Entities/Feeds/Sources/WpPostFeedSource.php DELETED
@@ -1,94 +0,0 @@
1
- <?php
2
-
3
- namespace RebelCode\Wpra\Core\Entities\Feeds\Sources;
4
-
5
- use OutOfRangeException;
6
- use RebelCode\Wpra\Core\Data\AliasingDataSet;
7
- use RebelCode\Wpra\Core\Data\ArrayDataSet;
8
- use RebelCode\Wpra\Core\Data\DataSetInterface;
9
- use RebelCode\Wpra\Core\Data\MergedDataSet;
10
- use RebelCode\Wpra\Core\Data\Wp\WpCptDataSet;
11
- use WP_Post;
12
-
13
- /**
14
- * Model class for posts of the WP RSS Aggregator feed source custom post type.
15
- *
16
- * @since 4.13
17
- */
18
- class WpPostFeedSource extends WpCptDataSet
19
- {
20
- /**
21
- * The meta prefix.
22
- *
23
- * @since 4.13
24
- */
25
- const META_PREFIX = 'wprss_';
26
-
27
- /**
28
- * Constructor.
29
- *
30
- * @since 4.13
31
- *
32
- * @param int|string|WP_Post $post The post instance or ID.
33
- *
34
- * @throws OutOfRangeException If the post does not exist.
35
- */
36
- public function __construct($post)
37
- {
38
- parent::__construct($post, static::META_PREFIX, ['ID', 'post_title']);
39
- }
40
-
41
- /**
42
- * {@inheritdoc}
43
- *
44
- * @since 4.13
45
- */
46
- protected function createPostDataSet($postOrId)
47
- {
48
- return new AliasingDataSet(parent::createPostDataSet($postOrId), [
49
- 'id' => 'ID',
50
- 'title' => 'post_title'
51
- ]);
52
- }
53
-
54
- /**
55
- * {@inheritdoc}
56
- *
57
- * @since 4.14
58
- */
59
- protected function createMetaDataSet($postOrId)
60
- {
61
- $meta = parent::createMetaDataSet($postOrId);
62
- $url = isset($meta['url']) ? $meta['url'] : '';
63
-
64
- $defaults = $this->getDefaultMetaData($meta);
65
- $fullMeta = new MergedDataSet($meta, $defaults);
66
-
67
- return new MergedDataSet($fullMeta, new ArrayDataSet([
68
- 'def_ft_image_id' => $defFtImage = get_post_thumbnail_id($postOrId),
69
- 'def_ft_image_url' => wp_get_attachment_image_url($defFtImage, ''),
70
- ]));
71
- }
72
-
73
- /**
74
- * Retrieves the default meta data.
75
- *
76
- * @since 4.14
77
- *
78
- * @param DataSetInterface $meta The existing meta data.
79
- *
80
- * @return ArrayDataSet The data set containing the default meta data.
81
- */
82
- protected function getDefaultMetaData($meta)
83
- {
84
- return new ArrayDataSet([
85
- 'import_source' => '0',
86
- 'import_ft_images' => '',
87
- 'download_images' => '0',
88
- 'siphon_ft_image' => '0',
89
- 'must_have_ft_image' => '0',
90
- 'image_min_width' => 150,
91
- 'image_min_height' => 150,
92
- ]);
93
- }
94
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/Entities/Feeds/Sources/WpPostFeedSourceCollection.php DELETED
@@ -1,75 +0,0 @@
1
- <?php
2
-
3
- namespace RebelCode\Wpra\Core\Entities\Feeds\Sources;
4
-
5
- use RebelCode\Wpra\Core\Data\Collections\WpPostCollection;
6
- use WP_Post;
7
-
8
- /**
9
- * A collection implementation that is specific to WP RSS Aggregator feed sources.
10
- *
11
- * @since 4.14
12
- */
13
- class WpPostFeedSourceCollection extends WpPostCollection
14
- {
15
- /**
16
- * Constructor.
17
- *
18
- * @since @since 4.14
19
- *
20
- * @param string $postType The name of the post type.
21
- * @param array|null $filter Optional filter to restrict the collection query.
22
- */
23
- public function __construct($postType, $filter = null)
24
- {
25
- parent::__construct($postType, [], $filter);
26
- }
27
-
28
- /**
29
- * {@inheritdoc}
30
- *
31
- * @since 4.14
32
- */
33
- protected function createModel(WP_Post $post)
34
- {
35
- return new WpPostFeedSource($post);
36
- }
37
-
38
- /**
39
- * {@inheritdoc}
40
- *
41
- * @since 4.14
42
- */
43
- protected function getBasePostQueryArgs()
44
- {
45
- $args = parent::getBasePostQueryArgs();
46
- $args['post_status'] = 'publish';
47
-
48
- return $args;
49
- }
50
-
51
- /**
52
- * {@inheritdoc}
53
- *
54
- * Overridden to ensure that the status is "publish".
55
- *
56
- * @since 4.14
57
- */
58
- protected function getNewPostData($data)
59
- {
60
- $post = parent::getNewPostData($data);
61
- $post['post_status'] = 'publish';
62
-
63
- return $post;
64
- }
65
-
66
- /**
67
- * {@inheritdoc}
68
- *
69
- * @since 4.14
70
- */
71
- protected function createSelfWithFilter($filter)
72
- {
73
- return new static($this->postType, $filter);
74
- }
75
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/Entities/Feeds/Templates/BuiltInFeedTemplate.php DELETED
@@ -1,189 +0,0 @@
1
- <?php
2
-
3
- namespace RebelCode\Wpra\Core\Entities\Feeds\Templates;
4
-
5
- use RebelCode\Wpra\Core\Data\AbstractDelegateDataSet;
6
- use RebelCode\Wpra\Core\Data\AliasingDataSet;
7
- use RebelCode\Wpra\Core\Data\ArrayDataSet;
8
- use RebelCode\Wpra\Core\Data\DataSetInterface;
9
- use RebelCode\Wpra\Core\Data\DelegatorDataSet;
10
- use RebelCode\Wpra\Core\Data\MaskingDataSet;
11
- use RebelCode\Wpra\Core\Data\MergedDataSet;
12
- use RebelCode\Wpra\Core\Data\Wp\WpCptDataSet;
13
- use RebelCode\Wpra\Core\Data\Wp\WpPostArrayMetaDataSet;
14
- use WP_Post;
15
-
16
- /**
17
- * A specialized feed template model implementation that uses the old WP RSS Aggregator display settings as the
18
- * template options.
19
- *
20
- * @since 4.13
21
- */
22
- class BuiltInFeedTemplate extends AbstractDelegateDataSet
23
- {
24
- /**
25
- * The name of the option from which to retrieve the template settings.
26
- *
27
- * @since 4.13
28
- */
29
- const WP_OPTION_NAME = 'wprss_settings_general';
30
-
31
- /**
32
- * The key to which to map the settings options.
33
- *
34
- * @since 4.13
35
- */
36
- const OPTIONS_KEY = 'options';
37
-
38
- /**
39
- * The meta prefix.
40
- *
41
- * @since 4.14
42
- */
43
- const META_PREFIX = 'wprss_template_';
44
-
45
- /**
46
- * Constructor.
47
- *
48
- * @since 4.13
49
- *
50
- * @param int|string|WP_Post $postOrId The post instance or ID.
51
- */
52
- public function __construct($postOrId)
53
- {
54
- parent::__construct($this->createDataSet($postOrId));
55
- }
56
-
57
- /**
58
- * Creates the internal data set.
59
- *
60
- * @since 4.14
61
- *
62
- * @param int|WP_Post $postOrId The post instance or ID.
63
- *
64
- * @return DataSetInterface
65
- */
66
- protected function createDataSet($postOrId)
67
- {
68
- // Create the CPT data set, which only includes the required wp_post fields, which are aliased
69
- $cptDataSet = new AliasingDataSet(
70
- new WpCptDataSet(
71
- $postOrId,
72
- static::META_PREFIX,
73
- ['ID', 'post_title', 'post_name']
74
- ),
75
- [
76
- 'id' => 'ID',
77
- 'name' => 'post_title',
78
- 'slug' => 'post_name',
79
- ]
80
- );
81
-
82
- // Create the data set for the template options (the "options" key)
83
- {
84
- // Create the data set for the "options" sub-meta
85
- $metaOptsDataSet = new WpPostArrayMetaDataSet($postOrId, static::META_PREFIX . 'options');
86
- // Create the data set for the "options" stored in the settings
87
- // And wrap it to be able to use the aliases instead of the old settings keys
88
- // And mask it to prevent other settings from being read or written to
89
- $settingOptsDataSet = new MaskingDataSet(
90
- new AliasingDataSet(
91
- wpra_container()->get('wpra/settings/general/dataset'),
92
- $this->getSettingsAliases()
93
- ),
94
- $this->getSettingsMask(),
95
- false
96
- );
97
-
98
- // Create the template options delegator data set for the options in meta and settings
99
- // This is used to determine which keys are stored in which which data set
100
- $optsDelegatorDataSet = new DelegatorDataSet(
101
- [
102
- 'settings' => $settingOptsDataSet,
103
- 'meta' => $metaOptsDataSet,
104
- ],
105
- DelegatorDataSet::fixedMap($this->getKeyMapping(), 'meta')
106
- );
107
- }
108
-
109
- // Wrap the opts delegator data set to nest it under the "options" key, with recursive writing
110
- // This consists of the post data set, and the meta and settings combined under an "options" key
111
- $optsDataSet = new ArrayDataSet(
112
- [
113
- 'options' => $optsDelegatorDataSet,
114
- ],
115
- true
116
- );
117
-
118
- // Create the full data set, explicitly forwarding the options key to the second data set
119
- $dataSet = new MergedDataSet(
120
- $cptDataSet,
121
- $optsDataSet,
122
- ['options' => true],
123
- MergedDataSet::ITERATE_BOTH
124
- );
125
-
126
- return $dataSet;
127
- }
128
-
129
- /**
130
- * Retrieves the settings options aliases.
131
- *
132
- * @since 4.14
133
- *
134
- * @return string[]
135
- */
136
- protected function getSettingsAliases()
137
- {
138
- return [
139
- 'title_is_link' => 'title_link',
140
- 'title_max_length' => 'title_limit',
141
- 'limit' => 'feed_limit',
142
- 'date_enabled' => 'date_enable',
143
- 'date_prefix' => 'text_preceding_date',
144
- 'date_format' => 'date_format',
145
- 'date_use_time_ago' => 'time_ago_format_enable',
146
- 'source_enabled' => 'source_enable',
147
- 'source_prefix' => 'text_preceding_source',
148
- 'source_is_link' => 'source_link',
149
- 'author_enabled' => 'authors_enable',
150
- 'pagination_type' => 'pagination',
151
- 'links_nofollow' => 'follow_dd',
152
- 'links_behavior' => 'open_dd',
153
- 'links_video_embed_page' => 'video_link',
154
- ];
155
- }
156
-
157
- /**
158
- * Retrieves the mapping of data keys to the key of the corresponding data set.
159
- *
160
- * The settings aliases are used to construct this mapping, since the only explicit mapping we need are for
161
- * settings keys. Any other keys will default to the meta data set.
162
- *
163
- * @since 4.14
164
- *
165
- * @return array
166
- */
167
- protected function getKeyMapping()
168
- {
169
- $keys = array_keys($this->getSettingsAliases());
170
- $values = array_fill(0, count($keys), 'settings');
171
-
172
- return array_combine($keys, $values);
173
- }
174
-
175
- /**
176
- * Retrieves the mask for which settings option keys to retain in the dataset.
177
- *
178
- * @since 4.14
179
- *
180
- * @return bool[]
181
- */
182
- protected function getSettingsMask()
183
- {
184
- $keys = array_keys($this->getSettingsAliases());
185
- $values = array_fill(0, count($keys), true);
186
-
187
- return array_combine($keys, $values);
188
- }
189
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/Entities/Feeds/Templates/WpPostFeedTemplate.php DELETED
@@ -1,63 +0,0 @@
1
- <?php
2
-
3
- namespace RebelCode\Wpra\Core\Entities\Feeds\Templates;
4
-
5
- use RebelCode\Wpra\Core\Data\AliasingDataSet;
6
- use RebelCode\Wpra\Core\Data\Wp\WpCptDataSet;
7
- use WP_Post;
8
-
9
- /**
10
- * A feed template model implementation for standard WP RSS Aggregator templates that are stored as a CPT.
11
- *
12
- * @since 4.13
13
- */
14
- class WpPostFeedTemplate extends WpCptDataSet
15
- {
16
- /**
17
- * The meta prefix.
18
- *
19
- * @since 4.13
20
- */
21
- const META_PREFIX = 'wprss_template_';
22
-
23
- /**
24
- * Constructor.
25
- *
26
- * @since 4.13
27
- *
28
- * @param int|string|WP_Post $postOrId The post instance or ID.
29
- */
30
- public function __construct($postOrId)
31
- {
32
- parent::__construct($postOrId, static::META_PREFIX, $this->getPostDataMask());
33
- }
34
-
35
- /**
36
- * {@inheritdoc}
37
- *
38
- * @since 4.13
39
- */
40
- protected function createPostDataSet($postOrId)
41
- {
42
- return new AliasingDataSet(
43
- parent::createPostDataSet($postOrId),
44
- [
45
- 'id' => 'ID',
46
- 'name' => 'post_title',
47
- 'slug' => 'post_name',
48
- ]
49
- );
50
- }
51
-
52
- /**
53
- * Retrieves the list of post fields to retain in the dataset.
54
- *
55
- * @since 4.13
56
- *
57
- * @return string[]
58
- */
59
- protected function getPostDataMask()
60
- {
61
- return ['ID', 'post_title', 'post_name'];
62
- }
63
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/Entities/Properties/SanitizedProperty.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Entities\Properties;
4
+
5
+ use RebelCode\Entities\Api\EntityInterface;
6
+ use RebelCode\Entities\Api\PropertyInterface;
7
+ use RebelCode\Entities\Properties\AbstractDecoratorProperty;
8
+ use RebelCode\Wpra\Core\Util\SanitizerInterface;
9
+
10
+ /**
11
+ * An implementation of a property that decorates another property and uses a sanitizer.
12
+ *
13
+ * @since 4.16
14
+ */
15
+ class SanitizedProperty extends AbstractDecoratorProperty
16
+ {
17
+ /**
18
+ * @since 4.16
19
+ *
20
+ * @var SanitizerInterface
21
+ */
22
+ protected $sanitizer;
23
+
24
+ /**
25
+ * Constructor.
26
+ *
27
+ * @since 4.16
28
+ *
29
+ * @param PropertyInterface $property The original property instance.
30
+ * @param SanitizerInterface $sanitizer The sanitizer to use after reading and before writing.
31
+ */
32
+ public function __construct(PropertyInterface $property, SanitizerInterface $sanitizer)
33
+ {
34
+ parent::__construct($property);
35
+
36
+ $this->sanitizer = $sanitizer;
37
+ }
38
+
39
+ /**
40
+ * @inheritdoc
41
+ *
42
+ * @since 4.16
43
+ */
44
+ public function getter(EntityInterface $entity, $prev)
45
+ {
46
+ return $this->sanitizer->sanitize($prev);
47
+ }
48
+
49
+ /**
50
+ * @inheritdoc
51
+ *
52
+ * @since 4.16
53
+ */
54
+ public function setter(EntityInterface $entity, $value)
55
+ {
56
+ return $this->sanitizer->sanitize($value);
57
+ }
58
+ }
src/Entities/Properties/TimestampProperty.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Entities\Properties;
4
+
5
+ use RebelCode\Entities\Api\EntityInterface;
6
+ use RebelCode\Entities\Api\PropertyInterface;
7
+ use RebelCode\Entities\Properties\AbstractDecoratorProperty;
8
+
9
+ /**
10
+ * A decorator property that translates a datetime string property into a timestamp when reading and writes timestamps
11
+ * as date time strings.
12
+ *
13
+ * @since 4.16
14
+ */
15
+ class TimestampProperty extends AbstractDecoratorProperty
16
+ {
17
+ /**
18
+ * @since 4.16
19
+ *
20
+ * @var string
21
+ */
22
+ protected $format;
23
+
24
+ /**
25
+ * Constructor.
26
+ *
27
+ * @since 4.16
28
+ *
29
+ * @param PropertyInterface $property The property instance to decorate.
30
+ * @param string $format The datetime format to use when writing to the data store.
31
+ */
32
+ public function __construct(PropertyInterface $property, $format)
33
+ {
34
+ parent::__construct($property);
35
+
36
+ $this->format = $format;
37
+ }
38
+
39
+ /**
40
+ * @inheritdoc
41
+ *
42
+ * @since 4.16
43
+ */
44
+ protected function getter(EntityInterface $entity, $prev)
45
+ {
46
+ return strtotime($prev);
47
+ }
48
+
49
+ /**
50
+ * @inheritdoc
51
+ *
52
+ * @since 4.16
53
+ */
54
+ protected function setter(EntityInterface $entity, $value)
55
+ {
56
+ return gmdate($this->format, $value);
57
+ }
58
+ }
src/Entities/Properties/WpFtImageUrlProperty.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Entities\Properties;
4
+
5
+ use RebelCode\Entities\Api\EntityInterface;
6
+ use RebelCode\Entities\Api\PropertyInterface;
7
+
8
+ /**
9
+ * An implementation of a property that transforms a WordPress featured image ID into a URL when reading, and
10
+ * vice-versa when writing.
11
+ *
12
+ * @since 4.16
13
+ */
14
+ class WpFtImageUrlProperty implements PropertyInterface
15
+ {
16
+ /**
17
+ * @since 4.16
18
+ *
19
+ * @var string
20
+ */
21
+ protected $ftImageIdKey;
22
+
23
+ /**
24
+ * Constructor.
25
+ *
26
+ * @since 4.16
27
+ *
28
+ * @param string $ftImageIdKey The data store key where the featured image ID is stored.
29
+ */
30
+ public function __construct($ftImageIdKey)
31
+ {
32
+ $this->ftImageIdKey = $ftImageIdKey;
33
+ }
34
+
35
+ /**
36
+ * @inheritdoc
37
+ *
38
+ * @since 4.16
39
+ */
40
+ public function getValue(EntityInterface $entity)
41
+ {
42
+ $ftImageId = $entity->getStore()->get($this->ftImageIdKey);
43
+ $ftImageUrl = wp_get_attachment_image_url($ftImageId, '');
44
+
45
+ return $ftImageUrl;
46
+ }
47
+
48
+ /**
49
+ * @inheritdoc
50
+ *
51
+ * @since 4.16
52
+ */
53
+ public function setValue(EntityInterface $entity, $value)
54
+ {
55
+ $id = wpra_get_attachment_id_from_url($value);
56
+
57
+ if (is_numeric($id) && $id > 0) {
58
+ return [$this->ftImageIdKey => $id];
59
+ }
60
+
61
+ return [];
62
+ }
63
+ }
src/Entities/Properties/WpPostEntityProperty.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Entities\Properties;
4
+
5
+ use RebelCode\Entities\Api\EntityInterface;
6
+ use RebelCode\Entities\Api\PropertyInterface;
7
+ use RebelCode\Entities\Api\SchemaInterface;
8
+ use RebelCode\Entities\Entity;
9
+ use RebelCode\Entities\Stores\ArrayStore;
10
+ use RebelCode\Wpra\Core\Entities\Stores\WpPostStore;
11
+ use WP_Post;
12
+
13
+ /**
14
+ * A property implementation that transforms a post ID into an entity instance when reading, and vice-versa when
15
+ * writing.
16
+ *
17
+ * @since 4.16
18
+ */
19
+ class WpPostEntityProperty implements PropertyInterface
20
+ {
21
+ /**
22
+ * @since 4.16
23
+ *
24
+ * @var string
25
+ */
26
+ protected $idKey;
27
+
28
+ /**
29
+ * @since 4.16
30
+ *
31
+ * @var SchemaInterface
32
+ */
33
+ protected $schema;
34
+
35
+ /**
36
+ * @since 4.16
37
+ *
38
+ * @var callable|null
39
+ */
40
+ protected $factory;
41
+
42
+ /**
43
+ * Constructor.
44
+ *
45
+ * @since 4.16
46
+ *
47
+ * @param string $idKey The data store key where the post ID is stored.
48
+ * @param SchemaInterface $schema The schema to use for created entities.
49
+ * @param callable|null $factory Optional factory function to use for created entities. If null, {@link Entity}
50
+ * instances will be created. The function will receive the schema and store as
51
+ * arguments.
52
+ */
53
+ public function __construct($idKey, SchemaInterface $schema, callable $factory = null)
54
+ {
55
+ $this->idKey = $idKey;
56
+ $this->schema = $schema;
57
+ $this->factory = $factory;
58
+ }
59
+
60
+ /**
61
+ * @inheritdoc
62
+ *
63
+ * @since 4.16
64
+ */
65
+ public function getValue(EntityInterface $entity)
66
+ {
67
+ $id = $entity->getStore()->get($this->idKey);
68
+ $post = get_post($id);
69
+ $store = ($post instanceof WP_Post)
70
+ ? new WpPostStore($post)
71
+ : new ArrayStore([]);
72
+
73
+ if ($this->factory === null) {
74
+ return new Entity($this->schema, $store);
75
+ }
76
+
77
+ return call_user_func_array($this->factory, [$this->schema, $store]);
78
+ }
79
+
80
+ /**
81
+ * @inheritdoc
82
+ *
83
+ * @since 4.16
84
+ */
85
+ public function setValue(EntityInterface $entity, $value)
86
+ {
87
+ if (is_numeric($value)) {
88
+ return [$this->idKey => $value];
89
+ }
90
+
91
+ if ($value instanceof WP_Post) {
92
+ return [$this->idKey => $value->ID];
93
+ }
94
+
95
+ if ($value instanceof EntityInterface) {
96
+ return [$this->idKey => $value->getStore()->get('ID')];
97
+ }
98
+
99
+ return [];
100
+ }
101
+ }
src/Entities/Properties/WpraSourceDefaultProperty.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Entities\Properties;
4
+
5
+ use OutOfBoundsException;
6
+ use RebelCode\Entities\Api\EntityInterface;
7
+ use RebelCode\Entities\Api\PropertyInterface;
8
+
9
+ /**
10
+ * A property implementation built specifically for feed items that defaults to a value from the item's feed source.
11
+ *
12
+ * The defaulting mechanism only works for read operations. All write operations are made to the feed item's property.
13
+ *
14
+ * @since 4.16
15
+ */
16
+ class WpraSourceDefaultProperty implements PropertyInterface
17
+ {
18
+ /**
19
+ * @since 4.16
20
+ *
21
+ * @var string
22
+ */
23
+ protected $key;
24
+
25
+ /**
26
+ * @since 4.16
27
+ *
28
+ * @var string
29
+ */
30
+ protected $feedKey;
31
+
32
+ /**
33
+ * Constructor.
34
+ *
35
+ * @since 4.16
36
+ *
37
+ * @param string $key The data store key to read from and write to.
38
+ * @param string $feedKey The key in feed source entities to default to.
39
+ */
40
+ public function __construct($key, $feedKey)
41
+ {
42
+ $this->key = $key;
43
+ $this->feedKey = $feedKey;
44
+ }
45
+
46
+ /**
47
+ * @inheritdoc
48
+ *
49
+ * @since 4.16
50
+ */
51
+ public function getValue(EntityInterface $entity)
52
+ {
53
+ try {
54
+ $value = $entity->getStore()->get($this->key);
55
+
56
+ if (!empty($value)) {
57
+ return $value;
58
+ }
59
+ } catch (OutOfBoundsException $exception) {
60
+ // Do nothing
61
+ }
62
+
63
+ $feed = get_post($entity->get('source_id'));
64
+
65
+ if (!property_exists($feed, $this->feedKey)) {
66
+ throw new OutOfBoundsException("Item's feed source does not have property \"{$this->feedKey}\"");
67
+ }
68
+
69
+ return $feed->{$this->feedKey};
70
+ }
71
+
72
+ /**
73
+ * @inheritdoc
74
+ *
75
+ * @since 4.16
76
+ */
77
+ public function setValue(EntityInterface $entity, $value)
78
+ {
79
+ return [$this->key => $value];
80
+ }
81
+ }
src/Entities/Stores/BuiltInTemplateStore.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Entities\Stores;
4
+
5
+ use RebelCode\Wpra\Core\Data\DataSetInterface;
6
+ use RebelCode\Wpra\Core\Util\SanitizerInterface;
7
+ use RebelCode\Wpra\Core\Util\Sanitizers\BoolSanitizer;
8
+ use RebelCode\Wpra\Core\Util\Sanitizers\CallbackSanitizer;
9
+ use WP_Post;
10
+
11
+ /**
12
+ * A custom store implementation built specifically for builtin templates. This implementation intercerpts read and
13
+ * write operations for the template's "options" key to store redundant information in the legacy display settings.
14
+ *
15
+ * @since 4.16
16
+ */
17
+ class BuiltInTemplateStore extends WpPostStore
18
+ {
19
+ /**
20
+ * @since 4.16
21
+ *
22
+ * @var DataSetInterface
23
+ */
24
+ protected $settings;
25
+
26
+ /**
27
+ * Constructor.
28
+ *
29
+ * @since 4.16
30
+ *
31
+ * @param WP_Post $wpPost The post instance.
32
+ * @param DataSetInterface $settings The settings dataset.
33
+ */
34
+ public function __construct(WP_Post $wpPost, DataSetInterface $settings)
35
+ {
36
+ parent::__construct($wpPost);
37
+
38
+ $this->settings = $settings;
39
+ }
40
+
41
+ /**
42
+ * @inheritdoc
43
+ *
44
+ * @since 4.16
45
+ */
46
+ public function get($key)
47
+ {
48
+ if ($key !== 'wprss_template_options') {
49
+ return parent::get($key);
50
+ }
51
+
52
+ $aliases = $this->getSettingsAliases();
53
+ $sanitizers = $this->getSettingsSanitizers();
54
+
55
+ // Get the options from the post's meta
56
+ $options = parent::has($key)
57
+ ? parent::get($key)
58
+ : [];
59
+
60
+ foreach ($aliases as $alias => $key) {
61
+ if (!isset($this->settings[$key])) {
62
+ continue;
63
+ }
64
+
65
+ $value = $this->settings[$key];
66
+
67
+ if (array_key_exists($key, $sanitizers)) {
68
+ $value = $sanitizers[$key]->sanitize($value);
69
+ }
70
+
71
+ $options[$alias] = $value;
72
+ }
73
+
74
+ return $options;
75
+ }
76
+
77
+ /**
78
+ * @inheritdoc
79
+ *
80
+ * @since 4.16
81
+ */
82
+ public function set(array $data)
83
+ {
84
+ if (array_key_exists('wprss_template_options', $data)) {
85
+ $options = $data['wprss_template_options'];
86
+
87
+ $aliases = $this->getSettingsAliases();
88
+ foreach ($aliases as $alias => $key) {
89
+ if (!array_key_exists($alias, $options)) {
90
+ continue;
91
+ }
92
+
93
+ $this->settings[$key] = $options[$alias];
94
+ }
95
+ }
96
+
97
+ return parent::set($data);
98
+ }
99
+
100
+ /**
101
+ * Retrieves the settings options aliases.
102
+ *
103
+ * @since 4.16
104
+ *
105
+ * @return string[]
106
+ */
107
+ protected function getSettingsAliases()
108
+ {
109
+ static $cache = null;
110
+
111
+ return ($cache !== null)
112
+ ? $cache
113
+ : $cache = [
114
+ 'title_is_link' => 'title_link',
115
+ 'title_max_length' => 'title_limit',
116
+ 'limit' => 'feed_limit',
117
+ 'date_enabled' => 'date_enable',
118
+ 'date_prefix' => 'text_preceding_date',
119
+ 'date_format' => 'date_format',
120
+ 'date_use_time_ago' => 'time_ago_format_enable',
121
+ 'source_enabled' => 'source_enable',
122
+ 'source_prefix' => 'text_preceding_source',
123
+ 'source_is_link' => 'source_link',
124
+ 'author_enabled' => 'authors_enable',
125
+ 'pagination_type' => 'pagination',
126
+ 'links_nofollow' => 'follow_dd',
127
+ 'links_behavior' => 'open_dd',
128
+ 'links_video_embed_page' => 'video_link',
129
+ ];
130
+ }
131
+
132
+ /**
133
+ * Retrieves the sanitizers for the settings options.
134
+ *
135
+ * @since 4.16
136
+ *
137
+ * @return SanitizerInterface[]
138
+ */
139
+ protected function getSettingsSanitizers()
140
+ {
141
+ static $cache = null;
142
+
143
+ return ($cache !== null)
144
+ ? $cache
145
+ : $cache = [
146
+ 'title_link' => new BoolSanitizer(),
147
+ 'date_enable' => new BoolSanitizer(),
148
+ 'time_ago_format_enable' => new BoolSanitizer(),
149
+ 'source_enable' => new BoolSanitizer(),
150
+ 'source_link' => new BoolSanitizer(),
151
+ 'authors_enable' => new BoolSanitizer(),
152
+ 'video_link' => new BoolSanitizer(),
153
+ 'follow_dd' => new CallbackSanitizer(function ($value) {
154
+ return $value === 'no_follow' || $value === true;
155
+ }),
156
+ ];
157
+ }
158
+ }
src/Entities/Stores/WpOptionsArrayStore.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Entities\Stores;
4
+
5
+ use OutOfBoundsException;
6
+ use RebelCode\Entities\Api\StoreInterface;
7
+
8
+ /**
9
+ * A store implementation for an array stored in WordPress' wp_options table.
10
+ *
11
+ * @since 4.16
12
+ */
13
+ class WpOptionsArrayStore implements StoreInterface
14
+ {
15
+ /**
16
+ * @since 4.16
17
+ *
18
+ * @var string
19
+ */
20
+ protected $option;
21
+
22
+ /**
23
+ * @since 4.16
24
+ *
25
+ * @var array
26
+ */
27
+ protected $data;
28
+
29
+ /**
30
+ * Constructor.
31
+ *
32
+ * @since 4.16
33
+ *
34
+ * @param string $option The name of the option.
35
+ */
36
+ public function __construct($option)
37
+ {
38
+ $this->option = $option;
39
+ $this->data = get_option($option, []);
40
+ }
41
+
42
+ /**
43
+ * @inheritdoc
44
+ *
45
+ * @since 4.16
46
+ */
47
+ public function get($key)
48
+ {
49
+ if (!array_key_exists($key, $this->data)) {
50
+ throw new OutOfBoundsException(sprintf('Option "%s" does not have key "%s"', $this->option, $key));
51
+ }
52
+
53
+ return $this->data[$key];
54
+ }
55
+
56
+ /**
57
+ * @inheritdoc
58
+ *
59
+ * @since 4.16
60
+ */
61
+ public function has($key)
62
+ {
63
+ return array_key_exists($key, $this->data);
64
+ }
65
+
66
+ /**
67
+ * @inheritdoc
68
+ *
69
+ * @since 4.16
70
+ */
71
+ public function set(array $data)
72
+ {
73
+ $instance = clone $this;
74
+ $instance->data = array_merge($this->data, $data);
75
+
76
+ update_option($this->option, $instance->data);
77
+
78
+ return $instance;
79
+ }
80
+ }
src/Entities/Stores/WpPostStore.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Entities\Stores;
4
+
5
+ use OutOfBoundsException;
6
+ use RebelCode\Entities\Api\StoreInterface;
7
+ use WP_Post;
8
+
9
+ /**
10
+ * An implementation of a store that uses a WordPress post instance for storage. Supports both post data and meta data.
11
+ *
12
+ * @since 4.16
13
+ */
14
+ class WpPostStore implements StoreInterface
15
+ {
16
+ /**
17
+ * @since 4.16
18
+ *
19
+ * @var array
20
+ */
21
+ protected $post;
22
+
23
+ /**
24
+ * Constructor.
25
+ *
26
+ * @since 4.16
27
+ *
28
+ * @param WP_Post $wpPost The post instance.
29
+ */
30
+ public function __construct(WP_Post $wpPost)
31
+ {
32
+ $this->post = $wpPost->to_array();
33
+ }
34
+
35
+ /**
36
+ * @inheritdoc
37
+ *
38
+ * @since 4.16
39
+ */
40
+ public function get($key)
41
+ {
42
+ if (array_key_exists($key, $this->post)) {
43
+ return $this->post[$key];
44
+ }
45
+
46
+ $meta = get_post_meta($this->post['ID'], $key);
47
+
48
+ if (count($meta) > 0) {
49
+ return reset($meta);
50
+ }
51
+
52
+ throw new OutOfBoundsException(sprintf('Post "%s" has no "%s" property or meta data', $this->post['ID'], $key));
53
+ }
54
+
55
+ /**
56
+ * @inheritdoc
57
+ *
58
+ * @since 4.16
59
+ */
60
+ public function has($key)
61
+ {
62
+ return array_key_exists($key, $this->post) || count(get_post_meta($this->post['ID'], $key)) > 0;
63
+ }
64
+
65
+ /**
66
+ * @inheritdoc
67
+ *
68
+ * @since 4.16
69
+ */
70
+ public function set(array $data)
71
+ {
72
+ $update = [];
73
+ $meta = [];
74
+
75
+ foreach ($data as $key => $value) {
76
+ if (array_key_exists($key, $this->post)) {
77
+ $update[$key] = $value;
78
+ continue;
79
+ }
80
+
81
+ update_post_meta($this->post['ID'], $key, $value);
82
+ }
83
+
84
+ if (!empty($update)) {
85
+ $update['ID'] = $this->post['ID'];
86
+ wp_update_post($update);
87
+ }
88
+
89
+ $instance = clone $this;
90
+ $instance->post = get_post($this->post['ID'])->to_array();
91
+
92
+ return $instance;
93
+ }
94
+ }
src/Handlers/FeedSources/FeedSourceSaveMetaHandler.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  namespace RebelCode\Wpra\Core\Handlers\FeedSources;
4
 
5
- use RebelCode\Wpra\Core\Entities\Feeds\Sources\WpPostFeedSource;
6
  use WP_Post;
7
 
8
  /**
@@ -12,6 +12,33 @@ use WP_Post;
12
  */
13
  class FeedSourceSaveMetaHandler
14
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  /**
16
  * @inheritdoc
17
  *
@@ -19,6 +46,11 @@ class FeedSourceSaveMetaHandler
19
  */
20
  public function __invoke($postId, WP_Post $post)
21
  {
 
 
 
 
 
22
  // Verify the nonce to ensure that the data is coming from the feed source edit page
23
  $nonce = filter_input(INPUT_POST, 'wprss_meta_box_nonce');
24
  if (!wp_verify_nonce($nonce, 'wpra_feed_source')) {
@@ -44,11 +76,18 @@ class FeedSourceSaveMetaHandler
44
  return;
45
  }
46
 
 
 
 
47
  // Get the feed source model object
48
- $feed = new WpPostFeedSource($post);
49
  // Save the meta to the feed
50
  foreach ($meta as $key => $value) {
51
- $feed[$key] = $value;
 
 
52
  }
 
 
53
  }
54
  }
2
 
3
  namespace RebelCode\Wpra\Core\Handlers\FeedSources;
4
 
5
+ use RebelCode\Wpra\Core\Data\Collections\CollectionInterface;
6
  use WP_Post;
7
 
8
  /**
12
  */
13
  class FeedSourceSaveMetaHandler
14
  {
15
+ /**
16
+ * @since [*some-version*]
17
+ *
18
+ * @var CollectionInterface
19
+ */
20
+ protected $collection;
21
+
22
+ /**
23
+ * @since [*some-version*]
24
+ *
25
+ * @var bool
26
+ */
27
+ protected $locked;
28
+
29
+ /**
30
+ * Constructor.
31
+ *
32
+ * @since [*some-version*]
33
+ *
34
+ * @param CollectionInterface $collection The feed sources collection.
35
+ */
36
+ public function __construct(CollectionInterface $collection)
37
+ {
38
+ $this->collection = $collection;
39
+ $this->locked = false;
40
+ }
41
+
42
  /**
43
  * @inheritdoc
44
  *
46
  */
47
  public function __invoke($postId, WP_Post $post)
48
  {
49
+ // If the handler is locked (already running), stop to prevent an infinite loop
50
+ if ($this->locked) {
51
+ return;
52
+ }
53
+
54
  // Verify the nonce to ensure that the data is coming from the feed source edit page
55
  $nonce = filter_input(INPUT_POST, 'wprss_meta_box_nonce');
56
  if (!wp_verify_nonce($nonce, 'wpra_feed_source')) {
76
  return;
77
  }
78
 
79
+ // Prevent infinite loop
80
+ $this->locked = true;
81
+
82
  // Get the feed source model object
83
+ $feed = $this->collection[$post->ID];
84
  // Save the meta to the feed
85
  foreach ($meta as $key => $value) {
86
+ if (isset($feed[$key])) {
87
+ $feed[$key] = $value;
88
+ }
89
  }
90
+
91
+ $this->locked = false;
92
  }
93
  }
src/Handlers/FeedTemplates/RenderTemplateContentHandler.php CHANGED
@@ -3,7 +3,7 @@
3
  namespace RebelCode\Wpra\Core\Handlers\FeedTemplates;
4
 
5
  use Dhii\Output\TemplateInterface;
6
- use RebelCode\Wpra\Core\Entities\Feeds\Templates\WpPostFeedTemplate;
7
 
8
  /**
9
  * The handler that renders the template content, by rendering the template itself as would be done through normal
@@ -40,20 +40,35 @@ class RenderTemplateContentHandler
40
  */
41
  protected $previewTemplate;
42
 
 
 
 
 
 
 
 
 
 
43
  /**
44
  * Constructor.
45
  *
46
  * @since 4.13
47
  *
48
- * @param string $cpt The name of the templates CPT.
49
- * @param TemplateInterface $template The master template to use for rendering.
50
- * @param TemplateInterface $previewTemplate The template to use for rendering previews.
 
51
  */
52
- public function __construct($cpt, TemplateInterface $template, TemplateInterface $previewTemplate)
53
- {
 
 
 
 
54
  $this->cpt = $cpt;
55
  $this->masterTemplate = $template;
56
  $this->previewTemplate = $previewTemplate;
 
57
  }
58
 
59
  /**
@@ -75,7 +90,7 @@ class RenderTemplateContentHandler
75
  }
76
 
77
  // Get the template instance
78
- $template = new WpPostFeedTemplate($post);
79
 
80
  // Check if this is a preview, determined by serialized options in the GET param
81
  $options = filter_input(INPUT_GET, 'options', FILTER_DEFAULT);
@@ -84,11 +99,10 @@ class RenderTemplateContentHandler
84
  $options = json_decode(base64_decode($options), true);
85
  $options = empty($options) ? [] : (array) $options;
86
 
87
-
88
  // Render the preview
89
  return $this->previewTemplate->render([
90
  'type' => $template['type'],
91
- 'options' => $options
92
  ]);
93
  }
94
 
3
  namespace RebelCode\Wpra\Core\Handlers\FeedTemplates;
4
 
5
  use Dhii\Output\TemplateInterface;
6
+ use RebelCode\Wpra\Core\Data\Collections\CollectionInterface;
7
 
8
  /**
9
  * The handler that renders the template content, by rendering the template itself as would be done through normal
40
  */
41
  protected $previewTemplate;
42
 
43
+ /**
44
+ * The collection of templates.
45
+ *
46
+ * @since [*some-version*]
47
+ *
48
+ * @var CollectionInterface
49
+ */
50
+ protected $collection;
51
+
52
  /**
53
  * Constructor.
54
  *
55
  * @since 4.13
56
  *
57
+ * @param string $cpt The name of the templates CPT.
58
+ * @param TemplateInterface $template The master template to use for rendering.
59
+ * @param TemplateInterface $previewTemplate The template to use for rendering previews.
60
+ * @param CollectionInterface $collection The collection of templates.
61
  */
62
+ public function __construct(
63
+ $cpt,
64
+ TemplateInterface $template,
65
+ TemplateInterface $previewTemplate,
66
+ CollectionInterface $collection
67
+ ) {
68
  $this->cpt = $cpt;
69
  $this->masterTemplate = $template;
70
  $this->previewTemplate = $previewTemplate;
71
+ $this->collection = $collection;
72
  }
73
 
74
  /**
90
  }
91
 
92
  // Get the template instance
93
+ $template = $this->collection[$post->ID];
94
 
95
  // Check if this is a preview, determined by serialized options in the GET param
96
  $options = filter_input(INPUT_GET, 'options', FILTER_DEFAULT);
99
  $options = json_decode(base64_decode($options), true);
100
  $options = empty($options) ? [] : (array) $options;
101
 
 
102
  // Render the preview
103
  return $this->previewTemplate->render([
104
  'type' => $template['type'],
105
+ 'options' => $options,
106
  ]);
107
  }
108
 
src/Handlers/Images/RenderItemsImageColumnHandler.php CHANGED
@@ -51,17 +51,17 @@ class RenderItemsImageColumnHandler
51
  }
52
 
53
  $feedItem = $this->feedItems[$postId];
54
- $image = isset($feedItem['ft_image_url'])
55
- ? $feedItem['ft_image_url']
56
- : null;
57
 
58
- if (empty($image)) {
 
 
59
  return;
60
  }
61
 
62
  printf(
63
  '<div><img src="%1$s" alt="%2$s" title="%2$s" class="wpra-item-ft-image" /></div>',
64
- $feedItem['ft_image_url'],
65
  __('Feed item image', 'wprss')
66
  );
67
  }
51
  }
52
 
53
  $feedItem = $this->feedItems[$postId];
54
+ $ftImageId = $feedItem['ft_image'];
 
 
55
 
56
+ $url = wp_get_attachment_url($ftImageId, '');
57
+
58
+ if (empty($url)) {
59
  return;
60
  }
61
 
62
  printf(
63
  '<div><img src="%1$s" alt="%2$s" title="%2$s" class="wpra-item-ft-image" /></div>',
64
+ $url,
65
  __('Feed item image', 'wprss')
66
  );
67
  }
src/Logger/ProblemLogger.php CHANGED
@@ -23,7 +23,7 @@ class ProblemLogger extends NullLogger implements LogReaderInterface, ClearableL
23
  /**
24
  * Constructor.
25
  *
26
- * @since [*next-version*]
27
  *
28
  * @param string $error The error.
29
  */
23
  /**
24
  * Constructor.
25
  *
26
+ * @since 4.15
27
  *
28
  * @param string $error The error.
29
  */
src/Logger/WpraLogger.php CHANGED
@@ -11,7 +11,7 @@ use RebelCode\Wpra\Core\Database\TableInterface;
11
  * By implementing the {@link FeedLoggerInterface}, it is able to yield new instances that log messages spefific to
12
  * that feed source.
13
  *
14
- * @since [*next-version*]
15
  *
16
  * @see WpdbLogger
17
  * @see FeedLoggerInterface
@@ -21,14 +21,14 @@ class WpraLogger extends WpdbLogger implements FeedLoggerInterface
21
  /**
22
  * The key of the extra feed ID column in the logs table.
23
  *
24
- * @since [*next-version*]
25
  */
26
  CONST LOG_FEED_ID = 'feed_id';
27
 
28
  /**
29
  * The ID of the feed for which messages are being logged.
30
  *
31
- * @since [*next-version*]
32
  *
33
  * @var string
34
  */
@@ -37,7 +37,7 @@ class WpraLogger extends WpdbLogger implements FeedLoggerInterface
37
  /**
38
  * @inheritdoc
39
  *
40
- * @since [*next-version*]
41
  */
42
  public function __construct(TableInterface $table, $columns = [], $extra = [])
43
  {
@@ -50,7 +50,7 @@ class WpraLogger extends WpdbLogger implements FeedLoggerInterface
50
  /**
51
  * @inheritdoc
52
  *
53
- * @since [*next-version*]
54
  */
55
  public function forFeedSource($feedId)
56
  {
@@ -65,7 +65,7 @@ class WpraLogger extends WpdbLogger implements FeedLoggerInterface
65
  *
66
  * Also updates the callback for the extra feed ID table column.
67
  *
68
- * @since [*next-version*]
69
  *
70
  * @param int $feedId The ID of the feed source.
71
  */
11
  * By implementing the {@link FeedLoggerInterface}, it is able to yield new instances that log messages spefific to
12
  * that feed source.
13
  *
14
+ * @since 4.15.1
15
  *
16
  * @see WpdbLogger
17
  * @see FeedLoggerInterface
21
  /**
22
  * The key of the extra feed ID column in the logs table.
23
  *
24
+ * @since 4.15.1
25
  */
26
  CONST LOG_FEED_ID = 'feed_id';
27
 
28
  /**
29
  * The ID of the feed for which messages are being logged.
30
  *
31
+ * @since 4.15.1
32
  *
33
  * @var string
34
  */
37
  /**
38
  * @inheritdoc
39
  *
40
+ * @since 4.15.1
41
  */
42
  public function __construct(TableInterface $table, $columns = [], $extra = [])
43
  {
50
  /**
51
  * @inheritdoc
52
  *
53
+ * @since 4.15.1
54
  */
55
  public function forFeedSource($feedId)
56
  {
65
  *
66
  * Also updates the callback for the extra feed ID table column.
67
  *
68
+ * @since 4.15.1
69
  *
70
  * @param int $feedId The ID of the feed source.
71
  */
src/Modules/FeedItemsModule.php CHANGED
@@ -3,7 +3,16 @@
3
  namespace RebelCode\Wpra\Core\Modules;
4
 
5
  use Psr\Container\ContainerInterface;
6
- use RebelCode\Wpra\Core\Entities\Feeds\Items\WpPostFeedItemCollection;
 
 
 
 
 
 
 
 
 
7
  use RebelCode\Wpra\Core\Handlers\AddCptMetaCapsHandler;
8
  use RebelCode\Wpra\Core\Handlers\NullHandler;
9
  use RebelCode\Wpra\Core\Handlers\RegisterCptHandler;
@@ -23,6 +32,82 @@ class FeedItemsModule implements ModuleInterface
23
  public function getFactories()
24
  {
25
  return [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  /*
27
  * The name of the feed items CPT.
28
  *
@@ -88,7 +173,7 @@ class FeedItemsModule implements ModuleInterface
88
  'capability_type' => $c->get('wpra/feeds/items/cpt/capability'),
89
  'map_meta_cap' => true,
90
  'labels' => $c->get('wpra/feeds/items/cpt/labels'),
91
- 'supports' => ['title', 'editor', 'excerpt']
92
  ];
93
  },
94
  /*
@@ -97,7 +182,10 @@ class FeedItemsModule implements ModuleInterface
97
  * @since 4.13
98
  */
99
  'wpra/feeds/items/collection' => function (ContainerInterface $c) {
100
- return new WpPostFeedItemCollection($c->get('wpra/feeds/items/cpt/name'));
 
 
 
101
  },
102
  /*
103
  * The handler that registers the feed items CPT.
3
  namespace RebelCode\Wpra\Core\Modules;
4
 
5
  use Psr\Container\ContainerInterface;
6
+ use RebelCode\Entities\Entity;
7
+ use RebelCode\Entities\Properties\DefaultingProperty;
8
+ use RebelCode\Entities\Properties\Property;
9
+ use RebelCode\Entities\Schemas\Schema;
10
+ use RebelCode\Wpra\Core\Data\EntityDataSet;
11
+ use RebelCode\Wpra\Core\Entities\Collections\FeedItemCollection;
12
+ use RebelCode\Wpra\Core\Entities\Properties\TimestampProperty;
13
+ use RebelCode\Wpra\Core\Entities\Properties\WpFtImageUrlProperty;
14
+ use RebelCode\Wpra\Core\Entities\Properties\WpPostEntityProperty;
15
+ use RebelCode\Wpra\Core\Entities\Properties\WpraSourceDefaultProperty;
16
  use RebelCode\Wpra\Core\Handlers\AddCptMetaCapsHandler;
17
  use RebelCode\Wpra\Core\Handlers\NullHandler;
18
  use RebelCode\Wpra\Core\Handlers\RegisterCptHandler;
32
  public function getFactories()
33
  {
34
  return [
35
+ /*
36
+ * The properties for feed item entities.
37
+ *
38
+ * @since 4.16
39
+ */
40
+ 'wpra/feeds/items/properties' => function (ContainerInterface $c) {
41
+ $sourceSchema = $c->get('wpra/feeds/sources/schema');
42
+
43
+ return [
44
+ 'id' => new Property('ID'),
45
+ 'title' => new Property('post_title'),
46
+ 'content' => new DefaultingProperty(['post_content', 'post_excerpt']),
47
+ 'excerpt' => new DefaultingProperty(['post_excerpt', 'post_content']),
48
+ 'url' => new Property('wprss_item_permalink'),
49
+ 'permalink' => new Property('wprss_item_permalink'),
50
+ 'enclosure' => new Property('wprss_item_enclosure'),
51
+ 'author' => new Property('wprss_item_author'),
52
+ 'date' => new Property('wprss_item_date'),
53
+ 'timestamp' => new TimestampProperty(new Property('post_date_gmt'), 'Y-m-d H:i:s'),
54
+ 'source_id' => new Property('wprss_feed_id'),
55
+ 'source_name' => new WpraSourceDefaultProperty('wprss_source_name', 'post_title'),
56
+ 'source_url' => new WpraSourceDefaultProperty('wprss_source_url', 'wprss_url'),
57
+ 'ft_image' => new Property('_thumbnail_id'),
58
+ 'ft_image_url' => new WpFtImageUrlProperty('_thumbnail_id'),
59
+ 'is_using_def_image' => new Property('wprss_item_is_using_def_image'),
60
+ 'images' => new Property('wprss_images'),
61
+ 'best_image' => new Property('wprss_best_image'),
62
+ 'embed_url' => new Property('wprss_item_embed_url'),
63
+ 'is_yt' => new Property('wprss_item_is_yt'),
64
+ 'yt_embed_url' => new Property('wprss_item_yt_embed_url'),
65
+ // @todo remove after templates 0.2
66
+ 'source' => new WpPostEntityProperty('wprss_feed_id', $sourceSchema, function ($schema, $store) {
67
+ return new EntityDataSet(new Entity($schema, $store));
68
+ }),
69
+ ];
70
+ },
71
+ /*
72
+ * The default values for feed item entities.
73
+ *
74
+ * @since 4.16
75
+ */
76
+ 'wpra/feeds/items/defaults' => function (ContainerInterface $c) {
77
+ return [
78
+ 'id' => null,
79
+ 'title' => '',
80
+ 'content' => '',
81
+ 'excerpt' => '',
82
+ 'url' => '',
83
+ 'permalink' => '',
84
+ 'enclosure' => '',
85
+ 'author' => '',
86
+ 'date' => '',
87
+ 'timestamp' => 0,
88
+ 'source_id' => null,
89
+ 'source_name' => '',
90
+ 'source_url' => '',
91
+ 'ft_image' => null,
92
+ 'ft_image_url' => '',
93
+ 'images' => [],
94
+ 'best_image' => null,
95
+ 'embed_url' => '',
96
+ 'is_yt' => false,
97
+ 'yt_embed_url' => '',
98
+ ];
99
+ },
100
+ /*
101
+ * The schema for feed items.
102
+ *
103
+ * @since 4.16
104
+ */
105
+ 'wpra/feeds/items/schema' => function (ContainerInterface $c) {
106
+ return new Schema(
107
+ $c->get('wpra/feeds/items/properties'),
108
+ $c->get('wpra/feeds/items/defaults')
109
+ );
110
+ },
111
  /*
112
  * The name of the feed items CPT.
113
  *
173
  'capability_type' => $c->get('wpra/feeds/items/cpt/capability'),
174
  'map_meta_cap' => true,
175
  'labels' => $c->get('wpra/feeds/items/cpt/labels'),
176
+ 'supports' => ['title', 'editor', 'excerpt'],
177
  ];
178
  },
179
  /*
182
  * @since 4.13
183
  */
184
  'wpra/feeds/items/collection' => function (ContainerInterface $c) {
185
+ return new FeedItemCollection(
186
+ $c->get('wpra/feeds/items/cpt/name'),
187
+ $c->get('wpra/feeds/items/schema')
188
+ );
189
  },
190
  /*
191
  * The handler that registers the feed items CPT.
src/Modules/FeedSourcesModule.php CHANGED
@@ -3,7 +3,10 @@
3
  namespace RebelCode\Wpra\Core\Modules;
4
 
5
  use Psr\Container\ContainerInterface;
6
- use RebelCode\Wpra\Core\Entities\Feeds\Sources\WpPostFeedSourceCollection;
 
 
 
7
  use RebelCode\Wpra\Core\Handlers\AddCapabilitiesHandler;
8
  use RebelCode\Wpra\Core\Handlers\AddCptMetaCapsHandler;
9
  use RebelCode\Wpra\Core\Handlers\FeedSources\FeedSourceSaveMetaHandler;
@@ -12,6 +15,9 @@ use RebelCode\Wpra\Core\Handlers\MultiHandler;
12
  use RebelCode\Wpra\Core\Handlers\NullHandler;
13
  use RebelCode\Wpra\Core\Handlers\RegisterCptHandler;
14
  use RebelCode\Wpra\Core\Templates\NullTemplate;
 
 
 
15
 
16
  /**
17
  * The feed sources module for WP RSS Aggregator.
@@ -29,12 +35,100 @@ class FeedSourcesModule implements ModuleInterface
29
  {
30
  return [
31
  /*
32
- * The name of the feed sources CPT.
33
  *
34
- * @since 4.13
35
  */
36
- 'wpra/feeds/sources/cpt/name' => function () {
37
- return 'wprss_feed';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  },
39
  /*
40
  * The collection for feed sources.
@@ -42,7 +136,18 @@ class FeedSourcesModule implements ModuleInterface
42
  * @since 4.14
43
  */
44
  'wpra/feeds/sources/collection' => function (ContainerInterface $c) {
45
- return new WpPostFeedSourceCollection($c->get('wpra/feeds/sources/cpt/name'));
 
 
 
 
 
 
 
 
 
 
 
46
  },
47
  /*
48
  * The labels for the feed sources CPT.
@@ -201,7 +306,9 @@ class FeedSourcesModule implements ModuleInterface
201
  * @since 4.14
202
  */
203
  'wpra/feeds/sources/meta_box/save_handler' => function (ContainerInterface $c) {
204
- return new FeedSourceSaveMetaHandler();
 
 
205
  },
206
  ];
207
  }
3
  namespace RebelCode\Wpra\Core\Modules;
4
 
5
  use Psr\Container\ContainerInterface;
6
+ use RebelCode\Entities\Properties\Property;
7
+ use RebelCode\Entities\Schemas\Schema;
8
+ use RebelCode\Wpra\Core\Entities\Collections\FeedSourceCollection;
9
+ use RebelCode\Wpra\Core\Entities\Properties\SanitizedProperty;
10
  use RebelCode\Wpra\Core\Handlers\AddCapabilitiesHandler;
11
  use RebelCode\Wpra\Core\Handlers\AddCptMetaCapsHandler;
12
  use RebelCode\Wpra\Core\Handlers\FeedSources\FeedSourceSaveMetaHandler;
15
  use RebelCode\Wpra\Core\Handlers\NullHandler;
16
  use RebelCode\Wpra\Core\Handlers\RegisterCptHandler;
17
  use RebelCode\Wpra\Core\Templates\NullTemplate;
18
+ use RebelCode\Wpra\Core\Util\Sanitizers\BoolSanitizer;
19
+ use RebelCode\Wpra\Core\Util\Sanitizers\CallbackSanitizer;
20
+ use RebelCode\Wpra\Core\Util\Sanitizers\IntSanitizer;
21
 
22
  /**
23
  * The feed sources module for WP RSS Aggregator.
35
  {
36
  return [
37
  /*
38
+ * The properties for feed source entities.
39
  *
40
+ * @since 4.16
41
  */
42
+ 'wpra/feeds/sources/properties' => function (ContainerInterface $c) {
43
+ return [
44
+ // == Basic info ==
45
+ 'id' => new Property('ID'),
46
+ 'name' => new Property('post_title'),
47
+ 'active' => new SanitizedProperty(
48
+ new Property('wprss_state'),
49
+ new CallbackSanitizer(function ($state) {
50
+ return empty($state) || strtolower($state) === 'active';
51
+ })
52
+ ),
53
+ // == Import options ==
54
+ 'url' => new Property('wprss_url'),
55
+ 'import_source' => new SanitizedProperty(
56
+ new Property('wprss_import_source'),
57
+ new BoolSanitizer()
58
+ ),
59
+ 'import_limit' => new SanitizedProperty(
60
+ new Property('wprss_limit'),
61
+ new IntSanitizer(0, 0)
62
+ ),
63
+ 'unique_titles_only' => new SanitizedProperty(
64
+ new Property('wprss_unique_titles'),
65
+ new BoolSanitizer()
66
+ ),
67
+ // == Image options ==
68
+ 'def_ft_image' => new Property('_thumbnail_id'),
69
+ 'import_ft_images' => new Property('wprss_import_ft_images'),
70
+ 'download_images' => new SanitizedProperty(
71
+ new Property('wprss_download_images'),
72
+ new BoolSanitizer()
73
+ ),
74
+ 'download_srcset' => new SanitizedProperty(
75
+ new Property('wprss_download_srcset'),
76
+ new BoolSanitizer()
77
+ ),
78
+ 'siphon_ft_image' => new SanitizedProperty(
79
+ new Property('wprss_siphon_ft_image'),
80
+ new BoolSanitizer()
81
+ ),
82
+ 'must_have_ft_image' => new SanitizedProperty(
83
+ new Property('wprss_must_have_ft_image'),
84
+ new BoolSanitizer()
85
+ ),
86
+ 'image_min_width' => new SanitizedProperty(
87
+ new Property('wprss_image_min_width'),
88
+ new IntSanitizer(0, 0)
89
+ ),
90
+ 'image_min_height' => new SanitizedProperty(
91
+ new Property('wprss_image_min_height'),
92
+ new IntSanitizer(0, 0)
93
+ ),
94
+ // @todo remove after templates 0.2
95
+ 'title' => new Property('post_title'),
96
+ ];
97
+ },
98
+ /*
99
+ * The default values for feed source entities.
100
+ *
101
+ * @since 4.16
102
+ */
103
+ 'wpra/feeds/sources/defaults' => function (ContainerInterface $c) {
104
+ return [
105
+ 'id' => null,
106
+ 'name' => '',
107
+ 'active' => true,
108
+ 'url' => '',
109
+ 'import_source' => false,
110
+ 'import_limit' => 0,
111
+ 'unique_titles_only' => false,
112
+ 'def_ft_image' => null,
113
+ 'import_ft_images' => '',
114
+ 'download_images' => false,
115
+ 'download_srcset' => false,
116
+ 'siphon_ft_image' => false,
117
+ 'must_have_ft_image' => false,
118
+ 'image_min_width' => 150,
119
+ 'image_min_height' => 150,
120
+ ];
121
+ },
122
+ /*
123
+ * The schema for feed source entities.
124
+ *
125
+ * @since 4.16
126
+ */
127
+ 'wpra/feeds/sources/schema' => function (ContainerInterface $c) {
128
+ return new Schema(
129
+ $c->get('wpra/feeds/sources/properties'),
130
+ $c->get('wpra/feeds/sources/defaults')
131
+ );
132
  },
133
  /*
134
  * The collection for feed sources.
136
  * @since 4.14
137
  */
138
  'wpra/feeds/sources/collection' => function (ContainerInterface $c) {
139
+ return new FeedSourceCollection(
140
+ $c->get('wpra/feeds/sources/cpt/name'),
141
+ $c->get('wpra/feeds/sources/schema')
142
+ );
143
+ },
144
+ /*
145
+ * The name of the feed sources CPT.
146
+ *
147
+ * @since 4.13
148
+ */
149
+ 'wpra/feeds/sources/cpt/name' => function () {
150
+ return 'wprss_feed';
151
  },
152
  /*
153
  * The labels for the feed sources CPT.
306
  * @since 4.14
307
  */
308
  'wpra/feeds/sources/meta_box/save_handler' => function (ContainerInterface $c) {
309
+ return new FeedSourceSaveMetaHandler(
310
+ $c->get('wpra/feeds/sources/collection')
311
+ );
312
  },
313
  ];
314
  }
src/Modules/FeedTemplatesModule.php CHANGED
@@ -4,8 +4,12 @@ namespace RebelCode\Wpra\Core\Modules;
4
 
5
  use Psr\Container\ContainerInterface;
6
  use Psr\Log\NullLogger;
 
 
 
7
  use RebelCode\Wpra\Core\Data\Collections\NullCollection;
8
- use RebelCode\Wpra\Core\Entities\Feeds\Templates\WpPostFeedTemplateCollection;
 
9
  use RebelCode\Wpra\Core\Handlers\AddCptMetaCapsHandler;
10
  use RebelCode\Wpra\Core\Handlers\FeedTemplates\AjaxRenderFeedsTemplateHandler;
11
  use RebelCode\Wpra\Core\Handlers\FeedTemplates\CreateDefaultFeedTemplateHandler;
@@ -28,6 +32,7 @@ use RebelCode\Wpra\Core\Templates\Feeds\TemplateTypeTemplate;
28
  use RebelCode\Wpra\Core\Templates\Feeds\Types\ListTemplateType;
29
  use RebelCode\Wpra\Core\Wp\Asset\ScriptAsset;
30
  use RebelCode\Wpra\Core\Wp\Asset\StyleAsset;
 
31
 
32
  /**
33
  * The templates module for WP RSS Aggregator.
@@ -44,6 +49,69 @@ class FeedTemplatesModule implements ModuleInterface
44
  public function getFactories()
45
  {
46
  return [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  /*
48
  * The name of the feeds template CPT.
49
  *
@@ -295,9 +363,11 @@ class FeedTemplatesModule implements ModuleInterface
295
  * @since 4.13
296
  */
297
  'wpra/feeds/templates/collection' => function (ContainerInterface $c) {
298
- return new WpPostFeedTemplateCollection(
299
  $c->get('wpra/feeds/templates/cpt/name'),
300
- $c->get('wpra/feeds/templates/default_template_type')
 
 
301
  );
302
  },
303
  /*
@@ -564,7 +634,8 @@ class FeedTemplatesModule implements ModuleInterface
564
  return new RenderTemplateContentHandler(
565
  $c->get('wpra/feeds/templates/cpt/name'),
566
  $c->get('wpra/feeds/templates/master_template'),
567
- $c->get('wpra/feeds/templates/generic_template')
 
568
  );
569
  },
570
  /*
@@ -710,7 +781,7 @@ class FeedTemplatesModule implements ModuleInterface
710
  '/templates(?:/(?P<id>[^/]+))?',
711
  ['GET'],
712
  $c->get('wpra/feeds/templates/rest_api/v1/get_endpoint'),
713
- $c->get('wpra/rest_api/v1/auth/user_is_admin')
714
  );
715
  $endPoints['patch_templates'] = new EndPoint(
716
  '/templates/(?P<id>[^/]+)',
4
 
5
  use Psr\Container\ContainerInterface;
6
  use Psr\Log\NullLogger;
7
+ use RebelCode\Entities\Properties\Property;
8
+ use RebelCode\Entities\Schemas\Schema;
9
+ use RebelCode\Wpra\Core\Data\ArrayDataSet;
10
  use RebelCode\Wpra\Core\Data\Collections\NullCollection;
11
+ use RebelCode\Wpra\Core\Entities\Collections\FeedTemplateCollection;
12
+ use RebelCode\Wpra\Core\Entities\Stores\BuiltInTemplateStore;
13
  use RebelCode\Wpra\Core\Handlers\AddCptMetaCapsHandler;
14
  use RebelCode\Wpra\Core\Handlers\FeedTemplates\AjaxRenderFeedsTemplateHandler;
15
  use RebelCode\Wpra\Core\Handlers\FeedTemplates\CreateDefaultFeedTemplateHandler;
32
  use RebelCode\Wpra\Core\Templates\Feeds\Types\ListTemplateType;
33
  use RebelCode\Wpra\Core\Wp\Asset\ScriptAsset;
34
  use RebelCode\Wpra\Core\Wp\Asset\StyleAsset;
35
+ use WP_Post;
36
 
37
  /**
38
  * The templates module for WP RSS Aggregator.
49
  public function getFactories()
50
  {
51
  return [
52
+ /*
53
+ * The properties for feed template entities.
54
+ *
55
+ * @since 4.16
56
+ */
57
+ 'wpra/feeds/templates/properties' => function () {
58
+ return [
59
+ 'id' => new Property('ID'),
60
+ 'name' => new Property('post_title'),
61
+ 'slug' => new Property('post_name'),
62
+ 'type' => new Property('wprss_template_type'),
63
+ 'options' => new Property('wprss_template_options'),
64
+ ];
65
+ },
66
+ /*
67
+ * The default values for feed template entities.
68
+ *
69
+ * @since 4.16
70
+ */
71
+ 'wpra/feeds/templates/defaults' => function () {
72
+ return [
73
+ 'id' => null,
74
+ 'name' => '',
75
+ 'slug' => '',
76
+ 'type' => '',
77
+ 'options' => [],
78
+ ];
79
+ },
80
+ /*
81
+ * The schema for feed templates.
82
+ *
83
+ * @since 4.16
84
+ */
85
+ 'wpra/feeds/templates/schema' => function (ContainerInterface $c) {
86
+ return new Schema(
87
+ $c->get('wpra/feeds/templates/properties'),
88
+ $c->get('wpra/feeds/templates/defaults')
89
+ );
90
+ },
91
+ /*
92
+ * The store to use for built in templates.
93
+ *
94
+ * @since 4.16
95
+ */
96
+ 'wpra/feeds/templates/builtin_store_factory' => function (ContainerInterface $c) {
97
+ $settings = $c->get('wpra/feeds/templates/display_settings');
98
+
99
+ return function(WP_Post $post) use ($settings) {
100
+ return new BuiltInTemplateStore($post, $settings);
101
+ };
102
+ },
103
+ /*
104
+ * The data set that contains the legacy display settings.
105
+ *
106
+ * @since 4.16
107
+ */
108
+ 'wpra/feeds/templates/display_settings' => function (ContainerInterface $c) {
109
+ if ($c->has('wpra/settings/general/dataset')) {
110
+ return $c->get('wpra/settings/general/dataset');
111
+ }
112
+
113
+ return new ArrayDataSet([]);
114
+ },
115
  /*
116
  * The name of the feeds template CPT.
117
  *
363
  * @since 4.13
364
  */
365
  'wpra/feeds/templates/collection' => function (ContainerInterface $c) {
366
+ return new FeedTemplateCollection(
367
  $c->get('wpra/feeds/templates/cpt/name'),
368
+ $c->get('wpra/feeds/templates/schema'),
369
+ $c->get('wpra/feeds/templates/default_template_type'),
370
+ $c->get('wpra/feeds/templates/builtin_store_factory')
371
  );
372
  },
373
  /*
634
  return new RenderTemplateContentHandler(
635
  $c->get('wpra/feeds/templates/cpt/name'),
636
  $c->get('wpra/feeds/templates/master_template'),
637
+ $c->get('wpra/feeds/templates/generic_template'),
638
+ $c->get('wpra/feeds/templates/collection')
639
  );
640
  },
641
  /*
781
  '/templates(?:/(?P<id>[^/]+))?',
782
  ['GET'],
783
  $c->get('wpra/feeds/templates/rest_api/v1/get_endpoint'),
784
+ null //$c->get('wpra/rest_api/v1/auth/user_is_admin')
785
  );
786
  $endPoints['patch_templates'] = new EndPoint(
787
  '/templates/(?P<id>[^/]+)',
src/Modules/ImagesModule.php CHANGED
@@ -276,15 +276,16 @@ class ImagesModule implements ModuleInterface
276
  * @since 4.14
277
  */
278
  'wpra/images/items/dev_meta_box/handler' => function (ContainerInterface $c) {
279
- $templates = $c->get('wpra/twig/collection');
 
280
 
281
  return new RegisterMetaBoxHandler(
282
  'wpra-dev-items-images',
283
  __('Images', 'wprss'),
284
- new RenderTemplateHandler($templates['admin/items/images-meta-box.twig'], function () {
285
  global $post;
286
  return [
287
- 'item' => new WpPostFeedItem($post),
288
  ];
289
  }, true),
290
  'wprss_feed_item'
276
  * @since 4.14
277
  */
278
  'wpra/images/items/dev_meta_box/handler' => function (ContainerInterface $c) {
279
+ $items = $c->get('wpra/feeds/items/collection');
280
+ $template = $c->get('wpra/twig/collection')['admin/items/images-meta-box.twig'];
281
 
282
  return new RegisterMetaBoxHandler(
283
  'wpra-dev-items-images',
284
  __('Images', 'wprss'),
285
+ new RenderTemplateHandler($template, function () use ($items) {
286
  global $post;
287
  return [
288
+ 'item' => $items[$post->ID],
289
  ];
290
  }, true),
291
  'wprss_feed_item'
src/Modules/ImporterModule.php CHANGED
@@ -3,7 +3,7 @@
3
  namespace RebelCode\Wpra\Core\Modules;
4
 
5
  use Psr\Container\ContainerInterface;
6
- use RebelCode\Wpra\Core\Entities\Feeds\Items\ImportedItemsCollection;
7
 
8
  /**
9
  * The WP RSS Aggregator importer module.
@@ -20,8 +20,8 @@ class ImporterModule implements ModuleInterface
20
  public function getFactories()
21
  {
22
  return [
23
- 'wpra/importer/items/collection' => function () {
24
- return new ImportedItemsCollection(
25
  [
26
  'relation' => 'AND',
27
  [
@@ -29,6 +29,10 @@ class ImporterModule implements ModuleInterface
29
  'compare' => 'EXISTS',
30
  ],
31
  ],
 
 
 
 
32
  [
33
  'order_by' => 'date',
34
  'order' => 'DESC',
3
  namespace RebelCode\Wpra\Core\Modules;
4
 
5
  use Psr\Container\ContainerInterface;
6
+ use RebelCode\Wpra\Core\Entities\Collections\ImportedItemsCollection;
7
 
8
  /**
9
  * The WP RSS Aggregator importer module.
20
  public function getFactories()
21
  {
22
  return [
23
+ 'wpra/importer/items/collection' => function (ContainerInterface $c) {
24
+ $collection = new ImportedItemsCollection(
25
  [
26
  'relation' => 'AND',
27
  [
29
  'compare' => 'EXISTS',
30
  ],
31
  ],
32
+ $c->get('wpra/feeds/items/schema')
33
+ );
34
+
35
+ return $collection->filter(
36
  [
37
  'order_by' => 'date',
38
  'order' => 'DESC',
src/Modules/PolyLangCompatModule.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Modules;
4
+
5
+ use Psr\Container\ContainerInterface;
6
+
7
+ /**
8
+ * A module that adds compatibility with the PolyLang plugin.
9
+ *
10
+ * @since 4.16
11
+ */
12
+ class PolyLangCompatModule implements ModuleInterface
13
+ {
14
+ /**
15
+ * @inheritdoc
16
+ *
17
+ * @since 4.16
18
+ */
19
+ public function getFactories()
20
+ {
21
+ return [
22
+ /*
23
+ * The filter handler that registers the feed item CPT.
24
+ *
25
+ * @since 4.16
26
+ */
27
+ 'wpra/polylang/handlers/register_feed_item_cpt' => function (ContainerInterface $c) {
28
+ return function ($postTypes) use ($c) {
29
+ // Stop if the feed items CPT name is not available
30
+ if (!$c->has('wpra/feeds/items/cpt/name')) {
31
+ return $postTypes;
32
+ }
33
+
34
+ $cpt = $c->get('wpra/feeds/items/cpt/name');
35
+
36
+ $postTypes[$cpt] = $cpt;
37
+
38
+ return $postTypes;
39
+ };
40
+ },
41
+ ];
42
+ }
43
+
44
+ /**
45
+ * @inheritdoc
46
+ *
47
+ * @since 4.16
48
+ */
49
+ public function getExtensions()
50
+ {
51
+ return [];
52
+ }
53
+
54
+ /**
55
+ * @inheritdoc
56
+ *
57
+ * @since 4.16
58
+ */
59
+ public function run(ContainerInterface $c)
60
+ {
61
+ add_filter('pll_get_post_types', $c->get('wpra/polylang/handlers/register_feed_item_cpt'));
62
+ }
63
+ }
src/RestApi/EndPoints/FeedTemplates/GetTemplatesEndPoint.php CHANGED
@@ -2,10 +2,10 @@
2
 
3
  namespace RebelCode\Wpra\Core\RestApi\EndPoints\FeedTemplates;
4
 
 
5
  use RebelCode\Wpra\Core\Data\Collections\CollectionInterface;
6
  use RebelCode\Wpra\Core\RestApi\EndPoints\AbstractRestApiEndPoint;
7
  use RebelCode\Wpra\Core\Util\PaginatedIterator;
8
- use Traversable;
9
  use WP_REST_Request;
10
  use WP_REST_Response;
11
 
@@ -119,7 +119,7 @@ class GetTemplatesEndPoint extends AbstractRestApiEndPoint
119
  * @param WP_REST_Request $request The request.
120
  * @param CollectionInterface $collection The collection to paginate.
121
  *
122
- * @return Traversable The pagination collection iterable.
123
  */
124
  protected function paginateCollection(WP_REST_Request $request, CollectionInterface $collection)
125
  {
2
 
3
  namespace RebelCode\Wpra\Core\RestApi\EndPoints\FeedTemplates;
4
 
5
+ use Iterator;
6
  use RebelCode\Wpra\Core\Data\Collections\CollectionInterface;
7
  use RebelCode\Wpra\Core\RestApi\EndPoints\AbstractRestApiEndPoint;
8
  use RebelCode\Wpra\Core\Util\PaginatedIterator;
 
9
  use WP_REST_Request;
10
  use WP_REST_Response;
11
 
119
  * @param WP_REST_Request $request The request.
120
  * @param CollectionInterface $collection The collection to paginate.
121
  *
122
+ * @return Iterator The pagination collection iterator.
123
  */
124
  protected function paginateCollection(WP_REST_Request $request, CollectionInterface $collection)
125
  {
src/Util/CallbackIterator.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Util;
4
+
5
+ use Iterator;
6
+ use OuterIterator;
7
+
8
+ /**
9
+ * A decorator iterator that passes each value yielded from the inner iterator through a callback before yielding.
10
+ *
11
+ * @since 4.16
12
+ */
13
+ class CallbackIterator implements OuterIterator
14
+ {
15
+ /**
16
+ * @since 4.16
17
+ *
18
+ * @var Iterator
19
+ */
20
+ protected $inner;
21
+
22
+ /**
23
+ * @since 4.16
24
+ *
25
+ * @var callable
26
+ */
27
+ protected $callback;
28
+
29
+ /**
30
+ * Constructor.
31
+ *
32
+ * @since 4.16
33
+ *
34
+ * @param Iterator $inner The inner iterator.
35
+ * @param callable $callback The callback function to run for each element. Receives the original element from the
36
+ * inner iterator and the corresponding key as arguments.
37
+ */
38
+ public function __construct(Iterator $inner, callable $callback)
39
+ {
40
+ $this->inner = $inner;
41
+ $this->callback = $callback;
42
+ }
43
+
44
+ /**
45
+ * @inheritdoc
46
+ *
47
+ * @since 4.16
48
+ */
49
+ public function getInnerIterator()
50
+ {
51
+ return $this->inner;
52
+ }
53
+
54
+ /**
55
+ * @inheritdoc
56
+ *
57
+ * @since 4.16
58
+ */
59
+ public function rewind()
60
+ {
61
+ $this->inner->rewind();
62
+ }
63
+
64
+ /**
65
+ * @inheritdoc
66
+ *
67
+ * @since 4.16
68
+ */
69
+ public function key()
70
+ {
71
+ return $this->inner->key();
72
+ }
73
+
74
+ /**
75
+ * @inheritdoc
76
+ *
77
+ * @since 4.16
78
+ */
79
+ public function current()
80
+ {
81
+ return call_user_func_array($this->callback, [$this->inner->current(), $this->inner->key()]);
82
+ }
83
+
84
+ /**
85
+ * @inheritdoc
86
+ *
87
+ * @since 4.16
88
+ */
89
+ public function next()
90
+ {
91
+ $this->inner->next();
92
+ }
93
+
94
+ /**
95
+ * @inheritdoc
96
+ *
97
+ * @since 4.16
98
+ */
99
+ public function valid()
100
+ {
101
+ return $this->inner->valid();
102
+ }
103
+ }
src/Util/PaginatedIterator.php CHANGED
@@ -71,8 +71,18 @@ class PaginatedIterator extends LimitIterator
71
  ? parent::key()
72
  : $this->keyCount;
73
 
74
- $this->keyCount++;
75
-
76
  return $key;
77
  }
 
 
 
 
 
 
 
 
 
 
 
 
78
  }
71
  ? parent::key()
72
  : $this->keyCount;
73
 
 
 
74
  return $key;
75
  }
76
+
77
+ /**
78
+ * @inheritdoc
79
+ *
80
+ * @since 4.16
81
+ */
82
+ public function next()
83
+ {
84
+ parent::next();
85
+
86
+ $this->keyCount++;
87
+ }
88
  }
src/Util/SanitizerInterface.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Util;
4
+
5
+ /**
6
+ * Interface for objects that can sanitize values.
7
+ *
8
+ * @since 4.16
9
+ */
10
+ interface SanitizerInterface
11
+ {
12
+ /**
13
+ * Sanitizes a given value.
14
+ *
15
+ * @since 4.16
16
+ *
17
+ * @param mixed $value The value to sanitize.
18
+ *
19
+ * @return mixed The sanitized value.
20
+ */
21
+ public function sanitize($value);
22
+ }
src/Util/Sanitizers/BoolSanitizer.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Util\Sanitizers;
4
+
5
+ use RebelCode\Wpra\Core\Util\SanitizerInterface;
6
+
7
+ /**
8
+ * A sanitizer implementation that sanitizes boolean values.
9
+ *
10
+ * @since 4.16
11
+ */
12
+ class BoolSanitizer implements SanitizerInterface
13
+ {
14
+ /**
15
+ * @inheritdoc
16
+ *
17
+ * @since 4.16
18
+ */
19
+ public function sanitize($value)
20
+ {
21
+ return filter_var($value, FILTER_VALIDATE_BOOLEAN);
22
+ }
23
+ }
src/Util/Sanitizers/CallbackSanitizer.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Util\Sanitizers;
4
+
5
+ use RebelCode\Wpra\Core\Util\SanitizerInterface;
6
+
7
+ /**
8
+ * A sanitizer implementation that uses callbacks for sanitization.
9
+ *
10
+ * @since 4.16
11
+ */
12
+ class CallbackSanitizer implements SanitizerInterface
13
+ {
14
+ /**
15
+ * @since 4.16
16
+ *
17
+ * @var callable
18
+ */
19
+ protected $callback;
20
+
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @since 4.16
25
+ *
26
+ * @param callable $callback The callback function. Recieves the value as argument and should return the
27
+ * sanitized value.
28
+ */
29
+ public function __construct(callable $callback)
30
+ {
31
+ $this->callback = $callback;
32
+ }
33
+
34
+ /**
35
+ * @inheritdoc
36
+ *
37
+ * @since 4.16
38
+ */
39
+ public function sanitize($value)
40
+ {
41
+ return call_user_func_array($this->callback, [$value]);
42
+ }
43
+ }
src/Util/Sanitizers/EquivalenceSanitizer.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Util\Sanitizers;
4
+
5
+ use RebelCode\Wpra\Core\Util\SanitizerInterface;
6
+
7
+ /**
8
+ * A sanitizer that compares values against another static literal value and yields booleans, with support for negated
9
+ * equivalence checking.
10
+ *
11
+ * @since 4.16
12
+ */
13
+ class EquivalenceSanitizer implements SanitizerInterface
14
+ {
15
+ /**
16
+ * @since 4.16
17
+ *
18
+ * @var mixed
19
+ */
20
+ protected $value;
21
+
22
+ /**
23
+ * @since 4.16
24
+ *
25
+ * @var bool
26
+ */
27
+ protected $notEqual;
28
+
29
+ /**
30
+ * Constructor.
31
+ *
32
+ * @since 4.16
33
+ *
34
+ * @param mixed $value The value to compare against.
35
+ * @param bool $notEqual Whether to use negated equivalence.
36
+ */
37
+ public function __construct($value, $notEqual = false)
38
+ {
39
+ $this->value = $value;
40
+ $this->notEqual = $notEqual;
41
+ }
42
+
43
+ /**
44
+ * @inheritdoc
45
+ *
46
+ * @since 4.16
47
+ */
48
+ public function sanitize($value)
49
+ {
50
+ return $value === $this->value xor $this->notEqual;
51
+ }
52
+ }
src/Util/Sanitizers/IntSanitizer.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Util\Sanitizers;
4
+
5
+ use RebelCode\Wpra\Core\Util\SanitizerInterface;
6
+
7
+ /**
8
+ * A sanitizer implementation that sanitizes integer values, with configuration for range control and a default value.
9
+ *
10
+ * @since 4.16
11
+ */
12
+ class IntSanitizer implements SanitizerInterface
13
+ {
14
+ /**
15
+ * @since 4.16
16
+ *
17
+ * @var int
18
+ */
19
+ protected $default;
20
+
21
+ /**
22
+ * @since 4.16
23
+ *
24
+ * @var int|null
25
+ */
26
+ protected $min;
27
+
28
+ /**
29
+ * @since 4.16
30
+ *
31
+ * @var int|null
32
+ */
33
+ protected $max;
34
+
35
+ /**
36
+ * Constructor.
37
+ *
38
+ * @since 4.16
39
+ *
40
+ * @param int $default The default value to return if a value is not an integer or is not inside the range.
41
+ * @param int|null $min Optional minimum value for range control.
42
+ * @param int|null $max Optional maximum value for range control.
43
+ */
44
+ public function __construct($default = 0, $min = null, $max = null)
45
+ {
46
+ $this->default = $default;
47
+ $this->min = $min;
48
+ $this->max = $max;
49
+ }
50
+
51
+ /**
52
+ * @inheritdoc
53
+ *
54
+ * @since 4.16
55
+ */
56
+ public function sanitize($value)
57
+ {
58
+ if (!is_int($value) && !is_numeric($value)) {
59
+ return $this->default;
60
+ }
61
+
62
+ $int = (int) $value;
63
+ $int = ($this->min !== null) ? max($this->min, $int) : $int;
64
+ $int = ($this->max !== null) ? min($this->max, $int) : $int;
65
+
66
+ return $int;
67
+ }
68
+ }
src/Util/Sanitizers/PhpFilterSanitizer.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace RebelCode\Wpra\Core\Util\Sanitizers;
4
+
5
+ use RebelCode\Wpra\Core\Util\SanitizerInterface;
6
+
7
+ /**
8
+ * A sanitizer implementation for any native PHP filters.
9
+ *
10
+ * @since 4.16
11
+ */
12
+ class PhpFilterSanitizer implements SanitizerInterface
13
+ {
14
+ /**
15
+ * @since 4.16
16
+ *
17
+ * @var int
18
+ */
19
+ protected $filter;
20
+
21
+ /**
22
+ * @since 4.16
23
+ *
24
+ * @var int
25
+ */
26
+ protected $flags;
27
+
28
+ /**
29
+ * @since 4.16
30
+ *
31
+ * @var array
32
+ */
33
+ protected $options;
34
+
35
+ /**
36
+ * Constructor.
37
+ *
38
+ * @since 4.16
39
+ *
40
+ * @param int $filter The filter.
41
+ * @param int $flags The filter flags.
42
+ * @param array $options The filter options.
43
+ */
44
+ public function __construct($filter, $flags = 0, array $options = [])
45
+ {
46
+ $this->filter = $filter;
47
+ $this->flags = $flags;
48
+ $this->options = $options;
49
+ }
50
+
51
+ /**
52
+ * @inheritdoc
53
+ *
54
+ * @since 4.16
55
+ */
56
+ public function sanitize($value)
57
+ {
58
+ return filter_var($value, $this->filter, [
59
+ 'flags' => $this->flags,
60
+ 'options' => $this->options,
61
+ ]);
62
+ }
63
+
64
+ public static function validateInt($min = null, $max = null, $default = 0)
65
+ {
66
+ $options = [
67
+ 'default' => $default,
68
+ ];
69
+
70
+ if (is_int($min)) {
71
+ $options['min_range'] = $min;
72
+ }
73
+
74
+ if (is_int($max)) {
75
+ $options['max_range'] = $max;
76
+ }
77
+
78
+ return new static(FILTER_VALIDATE_INT, 0, $options);
79
+ }
80
+
81
+ public static function validateBool()
82
+ {
83
+ return new static(FILTER_VALIDATE_BOOLEAN);
84
+ }
85
+ }
test/bootstrap.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ global $vendorDir;
4
+ $vendorDir = __DIR__ . '/../vendor/';
5
+
6
+ require_once $vendorDir . 'autoload.php';
7
+
8
+ /**
9
+ * Loads a WordPress file.
10
+ *
11
+ * @since [*next-version*]
12
+ *
13
+ * @param string $relPath The path relative to a WordPress installation's root directory.
14
+ */
15
+ function wpraTestLoadWpFile($relPath)
16
+ {
17
+ global $vendorDir;
18
+
19
+ require_once $vendorDir . 'johnpbloch/wordpress-core/' . $relPath;
20
+ }
21
+
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit0a9906e044288a89ce7d4c5685e9efc0::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit78c9546730fedf778e75f7ce2d8c83db::getLoader();
vendor/composer/autoload_classmap.php CHANGED
@@ -280,6 +280,19 @@ return array(
280
  'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/psr/log/Psr/Log/Test/TestLogger.php',
281
  'RebelCode\\Composer\\CleanupPlugin' => $vendorDir . '/rebelcode/composer-cleanup-plugin/src/CleanupPlugin.php',
282
  'RebelCode\\Composer\\CleanupRules' => $vendorDir . '/rebelcode/composer-cleanup-plugin/src/CleanupRules.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
283
  'RebelCode\\Wpra\\Core\\Container\\ModuleContainer' => $baseDir . '/src/Container/ModuleContainer.php',
284
  'RebelCode\\Wpra\\Core\\Container\\WpFilterContainer' => $baseDir . '/src/Container/WpFilterContainer.php',
285
  'RebelCode\\Wpra\\Core\\Container\\WpraContainer' => $baseDir . '/src/Container/WpraContainer.php',
@@ -291,11 +304,11 @@ return array(
291
  'RebelCode\\Wpra\\Core\\Data\\Collections\\CollectionInterface' => $baseDir . '/src/Data/Collections/CollectionInterface.php',
292
  'RebelCode\\Wpra\\Core\\Data\\Collections\\NullCollection' => $baseDir . '/src/Data/Collections/NullCollection.php',
293
  'RebelCode\\Wpra\\Core\\Data\\Collections\\TwigTemplateCollection' => $baseDir . '/src/Data/Collections/TwigTemplateCollection.php',
294
- 'RebelCode\\Wpra\\Core\\Data\\Collections\\WpPostCollection' => $baseDir . '/src/Data/Collections/WpPostCollection.php',
295
  'RebelCode\\Wpra\\Core\\Data\\CompositeDataSet' => $baseDir . '/src/Data/CompositeDataSet.php',
296
  'RebelCode\\Wpra\\Core\\Data\\DataSetInterface' => $baseDir . '/src/Data/DataSetInterface.php',
297
  'RebelCode\\Wpra\\Core\\Data\\DelegatorDataSet' => $baseDir . '/src/Data/DelegatorDataSet.php',
298
  'RebelCode\\Wpra\\Core\\Data\\DeprefixingDataSet' => $baseDir . '/src/Data/DeprefixingDataSet.php',
 
299
  'RebelCode\\Wpra\\Core\\Data\\MaskingDataSet' => $baseDir . '/src/Data/MaskingDataSet.php',
300
  'RebelCode\\Wpra\\Core\\Data\\MergedDataSet' => $baseDir . '/src/Data/MergedDataSet.php',
301
  'RebelCode\\Wpra\\Core\\Data\\PrefixingDataSet' => $baseDir . '/src/Data/PrefixingDataSet.php',
@@ -310,14 +323,19 @@ return array(
310
  'RebelCode\\Wpra\\Core\\Database\\NullTable' => $baseDir . '/src/Database/NullTable.php',
311
  'RebelCode\\Wpra\\Core\\Database\\TableInterface' => $baseDir . '/src/Database/TableInterface.php',
312
  'RebelCode\\Wpra\\Core\\Database\\WpdbTable' => $baseDir . '/src/Database/WpdbTable.php',
313
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Items\\ImportedItemsCollection' => $baseDir . '/src/Entities/Feeds/Items/ImportedItemsCollection.php',
314
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Items\\WpPostFeedItem' => $baseDir . '/src/Entities/Feeds/Items/WpPostFeedItem.php',
315
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Items\\WpPostFeedItemCollection' => $baseDir . '/src/Entities/Feeds/Items/WpPostFeedItemCollection.php',
316
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Sources\\WpPostFeedSource' => $baseDir . '/src/Entities/Feeds/Sources/WpPostFeedSource.php',
317
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Sources\\WpPostFeedSourceCollection' => $baseDir . '/src/Entities/Feeds/Sources/WpPostFeedSourceCollection.php',
318
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Templates\\BuiltInFeedTemplate' => $baseDir . '/src/Entities/Feeds/Templates/BuiltInFeedTemplate.php',
319
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Templates\\WpPostFeedTemplate' => $baseDir . '/src/Entities/Feeds/Templates/WpPostFeedTemplate.php',
320
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Templates\\WpPostFeedTemplateCollection' => $baseDir . '/src/Entities/Feeds/Templates/WpPostFeedTemplateCollection.php',
 
 
 
 
 
321
  'RebelCode\\Wpra\\Core\\ErrorHandler' => $baseDir . '/src/ErrorHandler.php',
322
  'RebelCode\\Wpra\\Core\\Handlers\\AbstractSavePostHandler' => $baseDir . '/src/Handlers/AbstractSavePostHandler.php',
323
  'RebelCode\\Wpra\\Core\\Handlers\\AddCapabilitiesHandler' => $baseDir . '/src/Handlers/AddCapabilitiesHandler.php',
@@ -389,6 +407,7 @@ return array(
389
  'RebelCode\\Wpra\\Core\\Modules\\LoremModule' => $baseDir . '/src/Modules/LoremModule.php',
390
  'RebelCode\\Wpra\\Core\\Modules\\ModuleInterface' => $baseDir . '/src/Modules/ModuleInterface.php',
391
  'RebelCode\\Wpra\\Core\\Modules\\ParsedownModule' => $baseDir . '/src/Modules/ParsedownModule.php',
 
392
  'RebelCode\\Wpra\\Core\\Modules\\RestApiModule' => $baseDir . '/src/Modules/RestApiModule.php',
393
  'RebelCode\\Wpra\\Core\\Modules\\SettingsModule' => $baseDir . '/src/Modules/SettingsModule.php',
394
  'RebelCode\\Wpra\\Core\\Modules\\TwigModule' => $baseDir . '/src/Modules/TwigModule.php',
@@ -424,6 +443,7 @@ return array(
424
  'RebelCode\\Wpra\\Core\\Twig\\Extensions\\I18n\\I18nTransTokenParser' => $baseDir . '/src/Twig/Extensions/I18n/I18nTransTokenParser.php',
425
  'RebelCode\\Wpra\\Core\\Twig\\Extensions\\I18n\\WpI18nExtension' => $baseDir . '/src/Twig/Extensions/I18n/WpI18nExtension.php',
426
  'RebelCode\\Wpra\\Core\\Twig\\Extensions\\WpraExtension' => $baseDir . '/src/Twig/Extensions/WpraExtension.php',
 
427
  'RebelCode\\Wpra\\Core\\Util\\IteratorDelegateTrait' => $baseDir . '/src/Util/IteratorDelegateTrait.php',
428
  'RebelCode\\Wpra\\Core\\Util\\MergedIterator' => $baseDir . '/src/Util/MergedIterator.php',
429
  'RebelCode\\Wpra\\Core\\Util\\NormalizeWpPostCapableTrait' => $baseDir . '/src/Util/NormalizeWpPostCapableTrait.php',
@@ -431,6 +451,12 @@ return array(
431
  'RebelCode\\Wpra\\Core\\Util\\PaginatedIterator' => $baseDir . '/src/Util/PaginatedIterator.php',
432
  'RebelCode\\Wpra\\Core\\Util\\ParseArgsWithSchemaCapableTrait' => $baseDir . '/src/Util/ParseArgsWithSchemaCapableTrait.php',
433
  'RebelCode\\Wpra\\Core\\Util\\SanitizeIdCommaListCapableTrait' => $baseDir . '/src/Util/SanitizeIdCommaListCapableTrait.php',
 
 
 
 
 
 
434
  'RebelCode\\Wpra\\Core\\Wp\\Asset\\AbstractAsset' => $baseDir . '/src/Wp/Asset/AbstractAsset.php',
435
  'RebelCode\\Wpra\\Core\\Wp\\Asset\\AssetInterface' => $baseDir . '/src/Wp/Asset/AssetInterface.php',
436
  'RebelCode\\Wpra\\Core\\Wp\\Asset\\ScriptAsset' => $baseDir . '/src/Wp/Asset/ScriptAsset.php',
280
  'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/psr/log/Psr/Log/Test/TestLogger.php',
281
  'RebelCode\\Composer\\CleanupPlugin' => $vendorDir . '/rebelcode/composer-cleanup-plugin/src/CleanupPlugin.php',
282
  'RebelCode\\Composer\\CleanupRules' => $vendorDir . '/rebelcode/composer-cleanup-plugin/src/CleanupRules.php',
283
+ 'RebelCode\\Entities\\Api\\EntityInterface' => $baseDir . '/lib/Entities/Api/EntityInterface.php',
284
+ 'RebelCode\\Entities\\Api\\PropertyInterface' => $baseDir . '/lib/Entities/Api/PropertyInterface.php',
285
+ 'RebelCode\\Entities\\Api\\SchemaInterface' => $baseDir . '/lib/Entities/Api/SchemaInterface.php',
286
+ 'RebelCode\\Entities\\Api\\StoreInterface' => $baseDir . '/lib/Entities/Api/StoreInterface.php',
287
+ 'RebelCode\\Entities\\Entity' => $baseDir . '/lib/Entities/Entity.php',
288
+ 'RebelCode\\Entities\\Properties\\AbstractDecoratorProperty' => $baseDir . '/lib/Entities/Properties/AbstractDecoratorProperty.php',
289
+ 'RebelCode\\Entities\\Properties\\CallbackDecoratorProperty' => $baseDir . '/lib/Entities/Properties/CallbackDecoratorProperty.php',
290
+ 'RebelCode\\Entities\\Properties\\CallbackProperty' => $baseDir . '/lib/Entities/Properties/CallbackProperty.php',
291
+ 'RebelCode\\Entities\\Properties\\DefaultingProperty' => $baseDir . '/lib/Entities/Properties/DefaultingProperty.php',
292
+ 'RebelCode\\Entities\\Properties\\Property' => $baseDir . '/lib/Entities/Properties/Property.php',
293
+ 'RebelCode\\Entities\\Schemas\\Schema' => $baseDir . '/lib/Entities/Schemas/Schema.php',
294
+ 'RebelCode\\Entities\\Stores\\ArrayStore' => $baseDir . '/lib/Entities/Stores/ArrayStore.php',
295
+ 'RebelCode\\Entities\\Stores\\EntityStore' => $baseDir . '/lib/Entities/Stores/EntityStore.php',
296
  'RebelCode\\Wpra\\Core\\Container\\ModuleContainer' => $baseDir . '/src/Container/ModuleContainer.php',
297
  'RebelCode\\Wpra\\Core\\Container\\WpFilterContainer' => $baseDir . '/src/Container/WpFilterContainer.php',
298
  'RebelCode\\Wpra\\Core\\Container\\WpraContainer' => $baseDir . '/src/Container/WpraContainer.php',
304
  'RebelCode\\Wpra\\Core\\Data\\Collections\\CollectionInterface' => $baseDir . '/src/Data/Collections/CollectionInterface.php',
305
  'RebelCode\\Wpra\\Core\\Data\\Collections\\NullCollection' => $baseDir . '/src/Data/Collections/NullCollection.php',
306
  'RebelCode\\Wpra\\Core\\Data\\Collections\\TwigTemplateCollection' => $baseDir . '/src/Data/Collections/TwigTemplateCollection.php',
 
307
  'RebelCode\\Wpra\\Core\\Data\\CompositeDataSet' => $baseDir . '/src/Data/CompositeDataSet.php',
308
  'RebelCode\\Wpra\\Core\\Data\\DataSetInterface' => $baseDir . '/src/Data/DataSetInterface.php',
309
  'RebelCode\\Wpra\\Core\\Data\\DelegatorDataSet' => $baseDir . '/src/Data/DelegatorDataSet.php',
310
  'RebelCode\\Wpra\\Core\\Data\\DeprefixingDataSet' => $baseDir . '/src/Data/DeprefixingDataSet.php',
311
+ 'RebelCode\\Wpra\\Core\\Data\\EntityDataSet' => $baseDir . '/src/Data/EntityDataSet.php',
312
  'RebelCode\\Wpra\\Core\\Data\\MaskingDataSet' => $baseDir . '/src/Data/MaskingDataSet.php',
313
  'RebelCode\\Wpra\\Core\\Data\\MergedDataSet' => $baseDir . '/src/Data/MergedDataSet.php',
314
  'RebelCode\\Wpra\\Core\\Data\\PrefixingDataSet' => $baseDir . '/src/Data/PrefixingDataSet.php',
323
  'RebelCode\\Wpra\\Core\\Database\\NullTable' => $baseDir . '/src/Database/NullTable.php',
324
  'RebelCode\\Wpra\\Core\\Database\\TableInterface' => $baseDir . '/src/Database/TableInterface.php',
325
  'RebelCode\\Wpra\\Core\\Database\\WpdbTable' => $baseDir . '/src/Database/WpdbTable.php',
326
+ 'RebelCode\\Wpra\\Core\\Entities\\Collections\\FeedItemCollection' => $baseDir . '/src/Entities/Collections/FeedItemCollection.php',
327
+ 'RebelCode\\Wpra\\Core\\Entities\\Collections\\FeedSourceCollection' => $baseDir . '/src/Entities/Collections/FeedSourceCollection.php',
328
+ 'RebelCode\\Wpra\\Core\\Entities\\Collections\\FeedTemplateCollection' => $baseDir . '/src/Entities/Collections/FeedTemplateCollection.php',
329
+ 'RebelCode\\Wpra\\Core\\Entities\\Collections\\ImportedItemsCollection' => $baseDir . '/src/Entities/Collections/ImportedItemsCollection.php',
330
+ 'RebelCode\\Wpra\\Core\\Entities\\Collections\\WpEntityCollection' => $baseDir . '/src/Entities/Collections/WpEntityCollection.php',
331
+ 'RebelCode\\Wpra\\Core\\Entities\\Properties\\SanitizedProperty' => $baseDir . '/src/Entities/Properties/SanitizedProperty.php',
332
+ 'RebelCode\\Wpra\\Core\\Entities\\Properties\\TimestampProperty' => $baseDir . '/src/Entities/Properties/TimestampProperty.php',
333
+ 'RebelCode\\Wpra\\Core\\Entities\\Properties\\WpFtImageUrlProperty' => $baseDir . '/src/Entities/Properties/WpFtImageUrlProperty.php',
334
+ 'RebelCode\\Wpra\\Core\\Entities\\Properties\\WpPostEntityProperty' => $baseDir . '/src/Entities/Properties/WpPostEntityProperty.php',
335
+ 'RebelCode\\Wpra\\Core\\Entities\\Properties\\WpraSourceDefaultProperty' => $baseDir . '/src/Entities/Properties/WpraSourceDefaultProperty.php',
336
+ 'RebelCode\\Wpra\\Core\\Entities\\Stores\\BuiltInTemplateStore' => $baseDir . '/src/Entities/Stores/BuiltInTemplateStore.php',
337
+ 'RebelCode\\Wpra\\Core\\Entities\\Stores\\WpOptionsArrayStore' => $baseDir . '/src/Entities/Stores/WpOptionsArrayStore.php',
338
+ 'RebelCode\\Wpra\\Core\\Entities\\Stores\\WpPostStore' => $baseDir . '/src/Entities/Stores/WpPostStore.php',
339
  'RebelCode\\Wpra\\Core\\ErrorHandler' => $baseDir . '/src/ErrorHandler.php',
340
  'RebelCode\\Wpra\\Core\\Handlers\\AbstractSavePostHandler' => $baseDir . '/src/Handlers/AbstractSavePostHandler.php',
341
  'RebelCode\\Wpra\\Core\\Handlers\\AddCapabilitiesHandler' => $baseDir . '/src/Handlers/AddCapabilitiesHandler.php',
407
  'RebelCode\\Wpra\\Core\\Modules\\LoremModule' => $baseDir . '/src/Modules/LoremModule.php',
408
  'RebelCode\\Wpra\\Core\\Modules\\ModuleInterface' => $baseDir . '/src/Modules/ModuleInterface.php',
409
  'RebelCode\\Wpra\\Core\\Modules\\ParsedownModule' => $baseDir . '/src/Modules/ParsedownModule.php',
410
+ 'RebelCode\\Wpra\\Core\\Modules\\PolyLangCompatModule' => $baseDir . '/src/Modules/PolyLangCompatModule.php',
411
  'RebelCode\\Wpra\\Core\\Modules\\RestApiModule' => $baseDir . '/src/Modules/RestApiModule.php',
412
  'RebelCode\\Wpra\\Core\\Modules\\SettingsModule' => $baseDir . '/src/Modules/SettingsModule.php',
413
  'RebelCode\\Wpra\\Core\\Modules\\TwigModule' => $baseDir . '/src/Modules/TwigModule.php',
443
  'RebelCode\\Wpra\\Core\\Twig\\Extensions\\I18n\\I18nTransTokenParser' => $baseDir . '/src/Twig/Extensions/I18n/I18nTransTokenParser.php',
444
  'RebelCode\\Wpra\\Core\\Twig\\Extensions\\I18n\\WpI18nExtension' => $baseDir . '/src/Twig/Extensions/I18n/WpI18nExtension.php',
445
  'RebelCode\\Wpra\\Core\\Twig\\Extensions\\WpraExtension' => $baseDir . '/src/Twig/Extensions/WpraExtension.php',
446
+ 'RebelCode\\Wpra\\Core\\Util\\CallbackIterator' => $baseDir . '/src/Util/CallbackIterator.php',
447
  'RebelCode\\Wpra\\Core\\Util\\IteratorDelegateTrait' => $baseDir . '/src/Util/IteratorDelegateTrait.php',
448
  'RebelCode\\Wpra\\Core\\Util\\MergedIterator' => $baseDir . '/src/Util/MergedIterator.php',
449
  'RebelCode\\Wpra\\Core\\Util\\NormalizeWpPostCapableTrait' => $baseDir . '/src/Util/NormalizeWpPostCapableTrait.php',
451
  'RebelCode\\Wpra\\Core\\Util\\PaginatedIterator' => $baseDir . '/src/Util/PaginatedIterator.php',
452
  'RebelCode\\Wpra\\Core\\Util\\ParseArgsWithSchemaCapableTrait' => $baseDir . '/src/Util/ParseArgsWithSchemaCapableTrait.php',
453
  'RebelCode\\Wpra\\Core\\Util\\SanitizeIdCommaListCapableTrait' => $baseDir . '/src/Util/SanitizeIdCommaListCapableTrait.php',
454
+ 'RebelCode\\Wpra\\Core\\Util\\SanitizerInterface' => $baseDir . '/src/Util/SanitizerInterface.php',
455
+ 'RebelCode\\Wpra\\Core\\Util\\Sanitizers\\BoolSanitizer' => $baseDir . '/src/Util/Sanitizers/BoolSanitizer.php',
456
+ 'RebelCode\\Wpra\\Core\\Util\\Sanitizers\\CallbackSanitizer' => $baseDir . '/src/Util/Sanitizers/CallbackSanitizer.php',
457
+ 'RebelCode\\Wpra\\Core\\Util\\Sanitizers\\EquivalenceSanitizer' => $baseDir . '/src/Util/Sanitizers/EquivalenceSanitizer.php',
458
+ 'RebelCode\\Wpra\\Core\\Util\\Sanitizers\\IntSanitizer' => $baseDir . '/src/Util/Sanitizers/IntSanitizer.php',
459
+ 'RebelCode\\Wpra\\Core\\Util\\Sanitizers\\PhpFilterSanitizer' => $baseDir . '/src/Util/Sanitizers/PhpFilterSanitizer.php',
460
  'RebelCode\\Wpra\\Core\\Wp\\Asset\\AbstractAsset' => $baseDir . '/src/Wp/Asset/AbstractAsset.php',
461
  'RebelCode\\Wpra\\Core\\Wp\\Asset\\AssetInterface' => $baseDir . '/src/Wp/Asset/AssetInterface.php',
462
  'RebelCode\\Wpra\\Core\\Wp\\Asset\\ScriptAsset' => $baseDir . '/src/Wp/Asset/ScriptAsset.php',
vendor/composer/autoload_psr4.php CHANGED
@@ -10,6 +10,7 @@ return array(
10
  'Twig\\' => array($vendorDir . '/twig/twig/src'),
11
  'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
12
  'RebelCode\\Wpra\\Core\\' => array($baseDir . '/src'),
 
13
  'RebelCode\\Composer\\' => array($vendorDir . '/rebelcode/composer-cleanup-plugin/src'),
14
  'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
15
  'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
10
  'Twig\\' => array($vendorDir . '/twig/twig/src'),
11
  'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
12
  'RebelCode\\Wpra\\Core\\' => array($baseDir . '/src'),
13
+ 'RebelCode\\Entities\\' => array($baseDir . '/lib/Entities'),
14
  'RebelCode\\Composer\\' => array($vendorDir . '/rebelcode/composer-cleanup-plugin/src'),
15
  'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
16
  'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit0a9906e044288a89ce7d4c5685e9efc0
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit0a9906e044288a89ce7d4c5685e9efc0
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit0a9906e044288a89ce7d4c5685e9efc0', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit0a9906e044288a89ce7d4c5685e9efc0', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
@@ -48,19 +48,19 @@ class ComposerAutoloaderInit0a9906e044288a89ce7d4c5685e9efc0
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
- $includeFiles = Composer\Autoload\ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
- composerRequire0a9906e044288a89ce7d4c5685e9efc0($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
- function composerRequire0a9906e044288a89ce7d4c5685e9efc0($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit78c9546730fedf778e75f7ce2d8c83db
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit78c9546730fedf778e75f7ce2d8c83db', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit78c9546730fedf778e75f7ce2d8c83db', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit78c9546730fedf778e75f7ce2d8c83db::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
+ $includeFiles = Composer\Autoload\ComposerStaticInit78c9546730fedf778e75f7ce2d8c83db::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequire78c9546730fedf778e75f7ce2d8c83db($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
+ function composerRequire78c9546730fedf778e75f7ce2d8c83db($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0
8
  {
9
  public static $files = array (
10
  '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
@@ -24,6 +24,7 @@ class ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0
24
  'R' =>
25
  array (
26
  'RebelCode\\Wpra\\Core\\' => 20,
 
27
  'RebelCode\\Composer\\' => 19,
28
  ),
29
  'P' =>
@@ -73,6 +74,10 @@ class ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0
73
  array (
74
  0 => __DIR__ . '/../..' . '/src',
75
  ),
 
 
 
 
76
  'RebelCode\\Composer\\' =>
77
  array (
78
  0 => __DIR__ . '/..' . '/rebelcode/composer-cleanup-plugin/src',
@@ -463,6 +468,19 @@ class ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0
463
  'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/TestLogger.php',
464
  'RebelCode\\Composer\\CleanupPlugin' => __DIR__ . '/..' . '/rebelcode/composer-cleanup-plugin/src/CleanupPlugin.php',
465
  'RebelCode\\Composer\\CleanupRules' => __DIR__ . '/..' . '/rebelcode/composer-cleanup-plugin/src/CleanupRules.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
466
  'RebelCode\\Wpra\\Core\\Container\\ModuleContainer' => __DIR__ . '/../..' . '/src/Container/ModuleContainer.php',
467
  'RebelCode\\Wpra\\Core\\Container\\WpFilterContainer' => __DIR__ . '/../..' . '/src/Container/WpFilterContainer.php',
468
  'RebelCode\\Wpra\\Core\\Container\\WpraContainer' => __DIR__ . '/../..' . '/src/Container/WpraContainer.php',
@@ -474,11 +492,11 @@ class ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0
474
  'RebelCode\\Wpra\\Core\\Data\\Collections\\CollectionInterface' => __DIR__ . '/../..' . '/src/Data/Collections/CollectionInterface.php',
475
  'RebelCode\\Wpra\\Core\\Data\\Collections\\NullCollection' => __DIR__ . '/../..' . '/src/Data/Collections/NullCollection.php',
476
  'RebelCode\\Wpra\\Core\\Data\\Collections\\TwigTemplateCollection' => __DIR__ . '/../..' . '/src/Data/Collections/TwigTemplateCollection.php',
477
- 'RebelCode\\Wpra\\Core\\Data\\Collections\\WpPostCollection' => __DIR__ . '/../..' . '/src/Data/Collections/WpPostCollection.php',
478
  'RebelCode\\Wpra\\Core\\Data\\CompositeDataSet' => __DIR__ . '/../..' . '/src/Data/CompositeDataSet.php',
479
  'RebelCode\\Wpra\\Core\\Data\\DataSetInterface' => __DIR__ . '/../..' . '/src/Data/DataSetInterface.php',
480
  'RebelCode\\Wpra\\Core\\Data\\DelegatorDataSet' => __DIR__ . '/../..' . '/src/Data/DelegatorDataSet.php',
481
  'RebelCode\\Wpra\\Core\\Data\\DeprefixingDataSet' => __DIR__ . '/../..' . '/src/Data/DeprefixingDataSet.php',
 
482
  'RebelCode\\Wpra\\Core\\Data\\MaskingDataSet' => __DIR__ . '/../..' . '/src/Data/MaskingDataSet.php',
483
  'RebelCode\\Wpra\\Core\\Data\\MergedDataSet' => __DIR__ . '/../..' . '/src/Data/MergedDataSet.php',
484
  'RebelCode\\Wpra\\Core\\Data\\PrefixingDataSet' => __DIR__ . '/../..' . '/src/Data/PrefixingDataSet.php',
@@ -493,14 +511,19 @@ class ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0
493
  'RebelCode\\Wpra\\Core\\Database\\NullTable' => __DIR__ . '/../..' . '/src/Database/NullTable.php',
494
  'RebelCode\\Wpra\\Core\\Database\\TableInterface' => __DIR__ . '/../..' . '/src/Database/TableInterface.php',
495
  'RebelCode\\Wpra\\Core\\Database\\WpdbTable' => __DIR__ . '/../..' . '/src/Database/WpdbTable.php',
496
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Items\\ImportedItemsCollection' => __DIR__ . '/../..' . '/src/Entities/Feeds/Items/ImportedItemsCollection.php',
497
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Items\\WpPostFeedItem' => __DIR__ . '/../..' . '/src/Entities/Feeds/Items/WpPostFeedItem.php',
498
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Items\\WpPostFeedItemCollection' => __DIR__ . '/../..' . '/src/Entities/Feeds/Items/WpPostFeedItemCollection.php',
499
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Sources\\WpPostFeedSource' => __DIR__ . '/../..' . '/src/Entities/Feeds/Sources/WpPostFeedSource.php',
500
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Sources\\WpPostFeedSourceCollection' => __DIR__ . '/../..' . '/src/Entities/Feeds/Sources/WpPostFeedSourceCollection.php',
501
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Templates\\BuiltInFeedTemplate' => __DIR__ . '/../..' . '/src/Entities/Feeds/Templates/BuiltInFeedTemplate.php',
502
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Templates\\WpPostFeedTemplate' => __DIR__ . '/../..' . '/src/Entities/Feeds/Templates/WpPostFeedTemplate.php',
503
- 'RebelCode\\Wpra\\Core\\Entities\\Feeds\\Templates\\WpPostFeedTemplateCollection' => __DIR__ . '/../..' . '/src/Entities/Feeds/Templates/WpPostFeedTemplateCollection.php',
 
 
 
 
 
504
  'RebelCode\\Wpra\\Core\\ErrorHandler' => __DIR__ . '/../..' . '/src/ErrorHandler.php',
505
  'RebelCode\\Wpra\\Core\\Handlers\\AbstractSavePostHandler' => __DIR__ . '/../..' . '/src/Handlers/AbstractSavePostHandler.php',
506
  'RebelCode\\Wpra\\Core\\Handlers\\AddCapabilitiesHandler' => __DIR__ . '/../..' . '/src/Handlers/AddCapabilitiesHandler.php',
@@ -572,6 +595,7 @@ class ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0
572
  'RebelCode\\Wpra\\Core\\Modules\\LoremModule' => __DIR__ . '/../..' . '/src/Modules/LoremModule.php',
573
  'RebelCode\\Wpra\\Core\\Modules\\ModuleInterface' => __DIR__ . '/../..' . '/src/Modules/ModuleInterface.php',
574
  'RebelCode\\Wpra\\Core\\Modules\\ParsedownModule' => __DIR__ . '/../..' . '/src/Modules/ParsedownModule.php',
 
575
  'RebelCode\\Wpra\\Core\\Modules\\RestApiModule' => __DIR__ . '/../..' . '/src/Modules/RestApiModule.php',
576
  'RebelCode\\Wpra\\Core\\Modules\\SettingsModule' => __DIR__ . '/../..' . '/src/Modules/SettingsModule.php',
577
  'RebelCode\\Wpra\\Core\\Modules\\TwigModule' => __DIR__ . '/../..' . '/src/Modules/TwigModule.php',
@@ -607,6 +631,7 @@ class ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0
607
  'RebelCode\\Wpra\\Core\\Twig\\Extensions\\I18n\\I18nTransTokenParser' => __DIR__ . '/../..' . '/src/Twig/Extensions/I18n/I18nTransTokenParser.php',
608
  'RebelCode\\Wpra\\Core\\Twig\\Extensions\\I18n\\WpI18nExtension' => __DIR__ . '/../..' . '/src/Twig/Extensions/I18n/WpI18nExtension.php',
609
  'RebelCode\\Wpra\\Core\\Twig\\Extensions\\WpraExtension' => __DIR__ . '/../..' . '/src/Twig/Extensions/WpraExtension.php',
 
610
  'RebelCode\\Wpra\\Core\\Util\\IteratorDelegateTrait' => __DIR__ . '/../..' . '/src/Util/IteratorDelegateTrait.php',
611
  'RebelCode\\Wpra\\Core\\Util\\MergedIterator' => __DIR__ . '/../..' . '/src/Util/MergedIterator.php',
612
  'RebelCode\\Wpra\\Core\\Util\\NormalizeWpPostCapableTrait' => __DIR__ . '/../..' . '/src/Util/NormalizeWpPostCapableTrait.php',
@@ -614,6 +639,12 @@ class ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0
614
  'RebelCode\\Wpra\\Core\\Util\\PaginatedIterator' => __DIR__ . '/../..' . '/src/Util/PaginatedIterator.php',
615
  'RebelCode\\Wpra\\Core\\Util\\ParseArgsWithSchemaCapableTrait' => __DIR__ . '/../..' . '/src/Util/ParseArgsWithSchemaCapableTrait.php',
616
  'RebelCode\\Wpra\\Core\\Util\\SanitizeIdCommaListCapableTrait' => __DIR__ . '/../..' . '/src/Util/SanitizeIdCommaListCapableTrait.php',
 
 
 
 
 
 
617
  'RebelCode\\Wpra\\Core\\Wp\\Asset\\AbstractAsset' => __DIR__ . '/../..' . '/src/Wp/Asset/AbstractAsset.php',
618
  'RebelCode\\Wpra\\Core\\Wp\\Asset\\AssetInterface' => __DIR__ . '/../..' . '/src/Wp/Asset/AssetInterface.php',
619
  'RebelCode\\Wpra\\Core\\Wp\\Asset\\ScriptAsset' => __DIR__ . '/../..' . '/src/Wp/Asset/ScriptAsset.php',
@@ -1032,10 +1063,10 @@ class ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0
1032
  public static function getInitializer(ClassLoader $loader)
1033
  {
1034
  return \Closure::bind(function () use ($loader) {
1035
- $loader->prefixLengthsPsr4 = ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0::$prefixLengthsPsr4;
1036
- $loader->prefixDirsPsr4 = ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0::$prefixDirsPsr4;
1037
- $loader->prefixesPsr0 = ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0::$prefixesPsr0;
1038
- $loader->classMap = ComposerStaticInit0a9906e044288a89ce7d4c5685e9efc0::$classMap;
1039
 
1040
  }, null, ClassLoader::class);
1041
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit78c9546730fedf778e75f7ce2d8c83db
8
  {
9
  public static $files = array (
10
  '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
24
  'R' =>
25
  array (
26
  'RebelCode\\Wpra\\Core\\' => 20,
27
+ 'RebelCode\\Entities\\' => 19,
28
  'RebelCode\\Composer\\' => 19,
29
  ),
30
  'P' =>
74
  array (
75
  0 => __DIR__ . '/../..' . '/src',
76
  ),
77
+ 'RebelCode\\Entities\\' =>
78
+ array (
79
+ 0 => __DIR__ . '/../..' . '/lib/Entities',
80
+ ),
81
  'RebelCode\\Composer\\' =>
82
  array (
83
  0 => __DIR__ . '/..' . '/rebelcode/composer-cleanup-plugin/src',
468
  'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/TestLogger.php',
469
  'RebelCode\\Composer\\CleanupPlugin' => __DIR__ . '/..' . '/rebelcode/composer-cleanup-plugin/src/CleanupPlugin.php',
470
  'RebelCode\\Composer\\CleanupRules' => __DIR__ . '/..' . '/rebelcode/composer-cleanup-plugin/src/CleanupRules.php',
471
+ 'RebelCode\\Entities\\Api\\EntityInterface' => __DIR__ . '/../..' . '/lib/Entities/Api/EntityInterface.php',
472
+ 'RebelCode\\Entities\\Api\\PropertyInterface' => __DIR__ . '/../..' . '/lib/Entities/Api/PropertyInterface.php',
473
+ 'RebelCode\\Entities\\Api\\SchemaInterface' => __DIR__ . '/../..' . '/lib/Entities/Api/SchemaInterface.php',
474
+ 'RebelCode\\Entities\\Api\\StoreInterface' => __DIR__ . '/../..' . '/lib/Entities/Api/StoreInterface.php',
475
+ 'RebelCode\\Entities\\Entity' => __DIR__ . '/../..' . '/lib/Entities/Entity.php',
476
+ 'RebelCode\\Entities\\Properties\\AbstractDecoratorProperty' => __DIR__ . '/../..' . '/lib/Entities/Properties/AbstractDecoratorProperty.php',
477
+ 'RebelCode\\Entities\\Properties\\CallbackDecoratorProperty' => __DIR__ . '/../..' . '/lib/Entities/Properties/CallbackDecoratorProperty.php',
478
+ 'RebelCode\\Entities\\Properties\\CallbackProperty' => __DIR__ . '/../..' . '/lib/Entities/Properties/CallbackProperty.php',
479
+ 'RebelCode\\Entities\\Properties\\DefaultingProperty' => __DIR__ . '/../..' . '/lib/Entities/Properties/DefaultingProperty.php',
480
+ 'RebelCode\\Entities\\Properties\\Property' => __DIR__ . '/../..' . '/lib/Entities/Properties/Property.php',
481
+ 'RebelCode\\Entities\\Schemas\\Schema' => __DIR__ . '/../..' . '/lib/Entities/Schemas/Schema.php',
482
+ 'RebelCode\\Entities\\Stores\\ArrayStore' => __DIR__ . '/../..' . '/lib/Entities/Stores/ArrayStore.php',
483
+ 'RebelCode\\Entities\\Stores\\EntityStore' => __DIR__ . '/../..' . '/lib/Entities/Stores/EntityStore.php',
484
  'RebelCode\\Wpra\\Core\\Container\\ModuleContainer' => __DIR__ . '/../..' . '/src/Container/ModuleContainer.php',
485
  'RebelCode\\Wpra\\Core\\Container\\WpFilterContainer' => __DIR__ . '/../..' . '/src/Container/WpFilterContainer.php',
486
  'RebelCode\\Wpra\\Core\\Container\\WpraContainer' => __DIR__ . '/../..' . '/src/Container/WpraContainer.php',
492
  'RebelCode\\Wpra\\Core\\Data\\Collections\\CollectionInterface' => __DIR__ . '/../..' . '/src/Data/Collections/CollectionInterface.php',
493
  'RebelCode\\Wpra\\Core\\Data\\Collections\\NullCollection' => __DIR__ . '/../..' . '/src/Data/Collections/NullCollection.php',
494
  'RebelCode\\Wpra\\Core\\Data\\Collections\\TwigTemplateCollection' => __DIR__ . '/../..' . '/src/Data/Collections/TwigTemplateCollection.php',
 
495
  'RebelCode\\Wpra\\Core\\Data\\CompositeDataSet' => __DIR__ . '/../..' . '/src/Data/CompositeDataSet.php',
496
  'RebelCode\\Wpra\\Core\\Data\\DataSetInterface' => __DIR__ . '/../..' . '/src/Data/DataSetInterface.php',
497
  'RebelCode\\Wpra\\Core\\Data\\DelegatorDataSet' => __DIR__ . '/../..' . '/src/Data/DelegatorDataSet.php',
498
  'RebelCode\\Wpra\\Core\\Data\\DeprefixingDataSet' => __DIR__ . '/../..' . '/src/Data/DeprefixingDataSet.php',
499
+ 'RebelCode\\Wpra\\Core\\Data\\EntityDataSet' => __DIR__ . '/../..' . '/src/Data/EntityDataSet.php',
500
  'RebelCode\\Wpra\\Core\\Data\\MaskingDataSet' => __DIR__ . '/../..' . '/src/Data/MaskingDataSet.php',
501
  'RebelCode\\Wpra\\Core\\Data\\MergedDataSet' => __DIR__ . '/../..' . '/src/Data/MergedDataSet.php',
502
  'RebelCode\\Wpra\\Core\\Data\\PrefixingDataSet' => __DIR__ . '/../..' . '/src/Data/PrefixingDataSet.php',
511
  'RebelCode\\Wpra\\Core\\Database\\NullTable' => __DIR__ . '/../..' . '/src/Database/NullTable.php',
512
  'RebelCode\\Wpra\\Core\\Database\\TableInterface' => __DIR__ . '/../..' . '/src/Database/TableInterface.php',
513
  'RebelCode\\Wpra\\Core\\Database\\WpdbTable' => __DIR__ . '/../..' . '/src/Database/WpdbTable.php',
514
+ 'RebelCode\\Wpra\\Core\\Entities\\Collections\\FeedItemCollection' => __DIR__ . '/../..' . '/src/Entities/Collections/FeedItemCollection.php',
515
+ 'RebelCode\\Wpra\\Core\\Entities\\Collections\\FeedSourceCollection' => __DIR__ . '/../..' . '/src/Entities/Collections/FeedSourceCollection.php',
516
+ 'RebelCode\\Wpra\\Core\\Entities\\Collections\\FeedTemplateCollection' => __DIR__ . '/../..' . '/src/Entities/Collections/FeedTemplateCollection.php',
517
+ 'RebelCode\\Wpra\\Core\\Entities\\Collections\\ImportedItemsCollection' => __DIR__ . '/../..' . '/src/Entities/Collections/ImportedItemsCollection.php',
518
+ 'RebelCode\\Wpra\\Core\\Entities\\Collections\\WpEntityCollection' => __DIR__ . '/../..' . '/src/Entities/Collections/WpEntityCollection.php',
519
+ 'RebelCode\\Wpra\\Core\\Entities\\Properties\\SanitizedProperty' => __DIR__ . '/../..' . '/src/Entities/Properties/SanitizedProperty.php',
520
+ 'RebelCode\\Wpra\\Core\\Entities\\Properties\\TimestampProperty' => __DIR__ . '/../..' . '/src/Entities/Properties/TimestampProperty.php',
521
+ 'RebelCode\\Wpra\\Core\\Entities\\Properties\\WpFtImageUrlProperty' => __DIR__ . '/../..' . '/src/Entities/Properties/WpFtImageUrlProperty.php',
522
+ 'RebelCode\\Wpra\\Core\\Entities\\Properties\\WpPostEntityProperty' => __DIR__ . '/../..' . '/src/Entities/Properties/WpPostEntityProperty.php',
523
+ 'RebelCode\\Wpra\\Core\\Entities\\Properties\\WpraSourceDefaultProperty' => __DIR__ . '/../..' . '/src/Entities/Properties/WpraSourceDefaultProperty.php',
524
+ 'RebelCode\\Wpra\\Core\\Entities\\Stores\\BuiltInTemplateStore' => __DIR__ . '/../..' . '/src/Entities/Stores/BuiltInTemplateStore.php',
525
+ 'RebelCode\\Wpra\\Core\\Entities\\Stores\\WpOptionsArrayStore' => __DIR__ . '/../..' . '/src/Entities/Stores/WpOptionsArrayStore.php',
526
+ 'RebelCode\\Wpra\\Core\\Entities\\Stores\\WpPostStore' => __DIR__ . '/../..' . '/src/Entities/Stores/WpPostStore.php',
527
  'RebelCode\\Wpra\\Core\\ErrorHandler' => __DIR__ . '/../..' . '/src/ErrorHandler.php',
528
  'RebelCode\\Wpra\\Core\\Handlers\\AbstractSavePostHandler' => __DIR__ . '/../..' . '/src/Handlers/AbstractSavePostHandler.php',
529
  'RebelCode\\Wpra\\Core\\Handlers\\AddCapabilitiesHandler' => __DIR__ . '/../..' . '/src/Handlers/AddCapabilitiesHandler.php',
595
  'RebelCode\\Wpra\\Core\\Modules\\LoremModule' => __DIR__ . '/../..' . '/src/Modules/LoremModule.php',
596
  'RebelCode\\Wpra\\Core\\Modules\\ModuleInterface' => __DIR__ . '/../..' . '/src/Modules/ModuleInterface.php',
597
  'RebelCode\\Wpra\\Core\\Modules\\ParsedownModule' => __DIR__ . '/../..' . '/src/Modules/ParsedownModule.php',
598
+ 'RebelCode\\Wpra\\Core\\Modules\\PolyLangCompatModule' => __DIR__ . '/../..' . '/src/Modules/PolyLangCompatModule.php',
599
  'RebelCode\\Wpra\\Core\\Modules\\RestApiModule' => __DIR__ . '/../..' . '/src/Modules/RestApiModule.php',
600
  'RebelCode\\Wpra\\Core\\Modules\\SettingsModule' => __DIR__ . '/../..' . '/src/Modules/SettingsModule.php',
601
  'RebelCode\\Wpra\\Core\\Modules\\TwigModule' => __DIR__ . '/../..' . '/src/Modules/TwigModule.php',
631
  'RebelCode\\Wpra\\Core\\Twig\\Extensions\\I18n\\I18nTransTokenParser' => __DIR__ . '/../..' . '/src/Twig/Extensions/I18n/I18nTransTokenParser.php',
632
  'RebelCode\\Wpra\\Core\\Twig\\Extensions\\I18n\\WpI18nExtension' => __DIR__ . '/../..' . '/src/Twig/Extensions/I18n/WpI18nExtension.php',
633
  'RebelCode\\Wpra\\Core\\Twig\\Extensions\\WpraExtension' => __DIR__ . '/../..' . '/src/Twig/Extensions/WpraExtension.php',
634
+ 'RebelCode\\Wpra\\Core\\Util\\CallbackIterator' => __DIR__ . '/../..' . '/src/Util/CallbackIterator.php',
635
  'RebelCode\\Wpra\\Core\\Util\\IteratorDelegateTrait' => __DIR__ . '/../..' . '/src/Util/IteratorDelegateTrait.php',
636
  'RebelCode\\Wpra\\Core\\Util\\MergedIterator' => __DIR__ . '/../..' . '/src/Util/MergedIterator.php',
637
  'RebelCode\\Wpra\\Core\\Util\\NormalizeWpPostCapableTrait' => __DIR__ . '/../..' . '/src/Util/NormalizeWpPostCapableTrait.php',
639
  'RebelCode\\Wpra\\Core\\Util\\PaginatedIterator' => __DIR__ . '/../..' . '/src/Util/PaginatedIterator.php',
640
  'RebelCode\\Wpra\\Core\\Util\\ParseArgsWithSchemaCapableTrait' => __DIR__ . '/../..' . '/src/Util/ParseArgsWithSchemaCapableTrait.php',
641
  'RebelCode\\Wpra\\Core\\Util\\SanitizeIdCommaListCapableTrait' => __DIR__ . '/../..' . '/src/Util/SanitizeIdCommaListCapableTrait.php',
642
+ 'RebelCode\\Wpra\\Core\\Util\\SanitizerInterface' => __DIR__ . '/../..' . '/src/Util/SanitizerInterface.php',
643
+ 'RebelCode\\Wpra\\Core\\Util\\Sanitizers\\BoolSanitizer' => __DIR__ . '/../..' . '/src/Util/Sanitizers/BoolSanitizer.php',
644
+ 'RebelCode\\Wpra\\Core\\Util\\Sanitizers\\CallbackSanitizer' => __DIR__ . '/../..' . '/src/Util/Sanitizers/CallbackSanitizer.php',
645
+ 'RebelCode\\Wpra\\Core\\Util\\Sanitizers\\EquivalenceSanitizer' => __DIR__ . '/../..' . '/src/Util/Sanitizers/EquivalenceSanitizer.php',
646
+ 'RebelCode\\Wpra\\Core\\Util\\Sanitizers\\IntSanitizer' => __DIR__ . '/../..' . '/src/Util/Sanitizers/IntSanitizer.php',
647
+ 'RebelCode\\Wpra\\Core\\Util\\Sanitizers\\PhpFilterSanitizer' => __DIR__ . '/../..' . '/src/Util/Sanitizers/PhpFilterSanitizer.php',
648
  'RebelCode\\Wpra\\Core\\Wp\\Asset\\AbstractAsset' => __DIR__ . '/../..' . '/src/Wp/Asset/AbstractAsset.php',
649
  'RebelCode\\Wpra\\Core\\Wp\\Asset\\AssetInterface' => __DIR__ . '/../..' . '/src/Wp/Asset/AssetInterface.php',
650
  'RebelCode\\Wpra\\Core\\Wp\\Asset\\ScriptAsset' => __DIR__ . '/../..' . '/src/Wp/Asset/ScriptAsset.php',
1063
  public static function getInitializer(ClassLoader $loader)
1064
  {
1065
  return \Closure::bind(function () use ($loader) {
1066
+ $loader->prefixLengthsPsr4 = ComposerStaticInit78c9546730fedf778e75f7ce2d8c83db::$prefixLengthsPsr4;
1067
+ $loader->prefixDirsPsr4 = ComposerStaticInit78c9546730fedf778e75f7ce2d8c83db::$prefixDirsPsr4;
1068
+ $loader->prefixesPsr0 = ComposerStaticInit78c9546730fedf778e75f7ce2d8c83db::$prefixesPsr0;
1069
+ $loader->classMap = ComposerStaticInit78c9546730fedf778e75f7ce2d8c83db::$classMap;
1070
 
1071
  }, null, ClassLoader::class);
1072
  }
vendor/composer/installed.json CHANGED
@@ -1425,17 +1425,17 @@
1425
  },
1426
  {
1427
  "name": "php-di/phpdoc-reader",
1428
- "version": "2.1.0",
1429
- "version_normalized": "2.1.0.0",
1430
  "source": {
1431
  "type": "git",
1432
  "url": "https://github.com/PHP-DI/PhpDocReader.git",
1433
- "reference": "7d0de60b9341933c8afd172a6255cd7557601e0e"
1434
  },
1435
  "dist": {
1436
  "type": "zip",
1437
- "url": "https://api.github.com/repos/PHP-DI/PhpDocReader/zipball/7d0de60b9341933c8afd172a6255cd7557601e0e",
1438
- "reference": "7d0de60b9341933c8afd172a6255cd7557601e0e",
1439
  "shasum": ""
1440
  },
1441
  "require": {
@@ -1444,7 +1444,7 @@
1444
  "require-dev": {
1445
  "phpunit/phpunit": "~4.6"
1446
  },
1447
- "time": "2018-02-18T17:39:01+00:00",
1448
  "type": "library",
1449
  "installation-source": "dist",
1450
  "autoload": {
@@ -1612,17 +1612,17 @@
1612
  },
1613
  {
1614
  "name": "symfony/polyfill-ctype",
1615
- "version": "v1.11.0",
1616
- "version_normalized": "1.11.0.0",
1617
  "source": {
1618
  "type": "git",
1619
  "url": "https://github.com/symfony/polyfill-ctype.git",
1620
- "reference": "82ebae02209c21113908c229e9883c419720738a"
1621
  },
1622
  "dist": {
1623
  "type": "zip",
1624
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
1625
- "reference": "82ebae02209c21113908c229e9883c419720738a",
1626
  "shasum": ""
1627
  },
1628
  "require": {
@@ -1631,11 +1631,11 @@
1631
  "suggest": {
1632
  "ext-ctype": "For best performance"
1633
  },
1634
- "time": "2019-02-06T07:57:58+00:00",
1635
  "type": "library",
1636
  "extra": {
1637
  "branch-alias": {
1638
- "dev-master": "1.11-dev"
1639
  }
1640
  },
1641
  "installation-source": "dist",
@@ -1652,13 +1652,13 @@
1652
  "MIT"
1653
  ],
1654
  "authors": [
1655
- {
1656
- "name": "Symfony Community",
1657
- "homepage": "https://symfony.com/contributors"
1658
- },
1659
  {
1660
  "name": "Gert de Pagter",
1661
  "email": "BackEndTea@gmail.com"
 
 
 
 
1662
  }
1663
  ],
1664
  "description": "Symfony polyfill for ctype functions",
1425
  },
1426
  {
1427
  "name": "php-di/phpdoc-reader",
1428
+ "version": "2.1.1",
1429
+ "version_normalized": "2.1.1.0",
1430
  "source": {
1431
  "type": "git",
1432
  "url": "https://github.com/PHP-DI/PhpDocReader.git",
1433
+ "reference": "15678f7451c020226807f520efb867ad26fbbfcf"
1434
  },
1435
  "dist": {
1436
  "type": "zip",
1437
+ "url": "https://api.github.com/repos/PHP-DI/PhpDocReader/zipball/15678f7451c020226807f520efb867ad26fbbfcf",
1438
+ "reference": "15678f7451c020226807f520efb867ad26fbbfcf",
1439
  "shasum": ""
1440
  },
1441
  "require": {
1444
  "require-dev": {
1445
  "phpunit/phpunit": "~4.6"
1446
  },
1447
+ "time": "2019-09-26T11:24:58+00:00",
1448
  "type": "library",
1449
  "installation-source": "dist",
1450
  "autoload": {
1612
  },
1613
  {
1614
  "name": "symfony/polyfill-ctype",
1615
+ "version": "v1.12.0",
1616
+ "version_normalized": "1.12.0.0",
1617
  "source": {
1618
  "type": "git",
1619
  "url": "https://github.com/symfony/polyfill-ctype.git",
1620
+ "reference": "550ebaac289296ce228a706d0867afc34687e3f4"
1621
  },
1622
  "dist": {
1623
  "type": "zip",
1624
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4",
1625
+ "reference": "550ebaac289296ce228a706d0867afc34687e3f4",
1626
  "shasum": ""
1627
  },
1628
  "require": {
1631
  "suggest": {
1632
  "ext-ctype": "For best performance"
1633
  },
1634
+ "time": "2019-08-06T08:03:45+00:00",
1635
  "type": "library",
1636
  "extra": {
1637
  "branch-alias": {
1638
+ "dev-master": "1.12-dev"
1639
  }
1640
  },
1641
  "installation-source": "dist",
1652
  "MIT"
1653
  ],
1654
  "authors": [
 
 
 
 
1655
  {
1656
  "name": "Gert de Pagter",
1657
  "email": "BackEndTea@gmail.com"
1658
+ },
1659
+ {
1660
+ "name": "Symfony Community",
1661
+ "homepage": "https://symfony.com/contributors"
1662
  }
1663
  ],
1664
  "description": "Symfony polyfill for ctype functions",
vendor/php-di/phpdoc-reader/src/PhpDocReader/PhpDocReader.php CHANGED
@@ -34,6 +34,7 @@ class PhpDocReader
34
  'callable',
35
  'resource',
36
  'mixed',
 
37
  );
38
 
39
  /**
34
  'callable',
35
  'resource',
36
  'mixed',
37
+ 'iterable',
38
  );
39
 
40
  /**
vendor/symfony/polyfill-ctype/composer.json CHANGED
@@ -28,7 +28,7 @@
28
  "minimum-stability": "dev",
29
  "extra": {
30
  "branch-alias": {
31
- "dev-master": "1.11-dev"
32
  }
33
  }
34
  }
28
  "minimum-stability": "dev",
29
  "extra": {
30
  "branch-alias": {
31
+ "dev-master": "1.12-dev"
32
  }
33
  }
34
  }
wp-rss-aggregator.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin Name: WP RSS Aggregator
5
  * Plugin URI: https://www.wprssaggregator.com/#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wpraplugin
6
  * Description: Imports and aggregates multiple RSS Feeds.
7
- * Version: 4.15.2
8
  * Author: RebelCode
9
  * Author URI: https://www.wprssaggregator.com
10
  * Text Domain: wprss
@@ -56,6 +56,7 @@ use RebelCode\Wpra\Core\Modules\LoggerModule;
56
  use RebelCode\Wpra\Core\Modules\LoremModule;
57
  use RebelCode\Wpra\Core\Modules\ModuleInterface;
58
  use RebelCode\Wpra\Core\Modules\ParsedownModule;
 
59
  use RebelCode\Wpra\Core\Modules\RestApiModule;
60
  use RebelCode\Wpra\Core\Modules\SettingsModule;
61
  use RebelCode\Wpra\Core\Modules\TwigModule;
@@ -69,7 +70,7 @@ use RebelCode\Wpra\Core\Plugin;
69
 
70
  // Set the version number of the plugin.
71
  if( !defined( 'WPRSS_VERSION' ) )
72
- define( 'WPRSS_VERSION', '4.15.2' );
73
 
74
  if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
75
  define( 'WPRSS_WP_MIN_VERSION', '4.8' );
@@ -403,6 +404,7 @@ function wpra_modules()
403
  'i18n' => new I18nModule(),
404
  'twig' => new TwigModule(),
405
  'parsedown' => new ParsedownModule(),
 
406
  ]);
407
  }
408
 
4
  * Plugin Name: WP RSS Aggregator
5
  * Plugin URI: https://www.wprssaggregator.com/#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wpraplugin
6
  * Description: Imports and aggregates multiple RSS Feeds.
7
+ * Version: 4.16
8
  * Author: RebelCode
9
  * Author URI: https://www.wprssaggregator.com
10
  * Text Domain: wprss
56
  use RebelCode\Wpra\Core\Modules\LoremModule;
57
  use RebelCode\Wpra\Core\Modules\ModuleInterface;
58
  use RebelCode\Wpra\Core\Modules\ParsedownModule;
59
+ use RebelCode\Wpra\Core\Modules\PolyLangCompatModule;
60
  use RebelCode\Wpra\Core\Modules\RestApiModule;
61
  use RebelCode\Wpra\Core\Modules\SettingsModule;
62
  use RebelCode\Wpra\Core\Modules\TwigModule;
70
 
71
  // Set the version number of the plugin.
72
  if( !defined( 'WPRSS_VERSION' ) )
73
+ define( 'WPRSS_VERSION', '4.16' );
74
 
75
  if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
76
  define( 'WPRSS_WP_MIN_VERSION', '4.8' );
404
  'i18n' => new I18nModule(),
405
  'twig' => new TwigModule(),
406
  'parsedown' => new ParsedownModule(),
407
+ 'polylang_compat' => new PolyLangCompatModule(),
408
  ]);
409
  }
410