@@ -41,13 +41,15 @@ class Feedzy_Rss_Feeds_Usage {
41
41
* Default usage data structure.
42
42
*
43
43
* @since 5.0.7
44
- * @var array< string, string| int| bool>
44
+ * @var array{ first_import_run_datetime: string, first_import_created_datetime: string, import_count: int, 'can_track_first_usage': bool, imports_per_week: array<string, int> }
45
45
*/
46
46
private $ default_data = array (
47
- 'first_import_run_datetime ' => '' ,
48
- 'imports_runs ' => 0 ,
49
- 'first_import_created_datetime ' => '' ,
50
- 'can_track_first_usage ' => false ,
47
+ 'first_import_run_datetime ' => '' ,
48
+ 'import_count ' => 0 ,
49
+ 'plugin_age_on_first_import_created ' => 0 ,
50
+ 'first_import_created_datetime ' => '' ,
51
+ 'can_track_first_usage ' => false ,
52
+ 'imports_per_week ' => [],
51
53
);
52
54
53
55
/**
@@ -103,7 +105,7 @@ private function init() {
103
105
* Get usage data with defaults merged.
104
106
*
105
107
* @since 5.0.7
106
- * @return array< string, string| int| bool>
108
+ * @return array{ first_import_run_datetime: string, first_import_created_datetime: string, import_count: int, can_track_first_usage: bool, imports_per_week: array<string, int> }
107
109
*/
108
110
public function get_usage_data () {
109
111
$ data = get_option ( self ::OPTION_NAME , array () );
@@ -114,7 +116,7 @@ public function get_usage_data() {
114
116
* Update usage data.
115
117
*
116
118
* @since 5.0.7
117
- * @param array<string, string|int|bool> $new_data Data to merge.
119
+ * @param array<string, string|int|bool|array<string, int> > $new_data Data to merge.
118
120
* @return bool
119
121
*/
120
122
public function update_usage_data ( $ new_data ) {
@@ -132,14 +134,15 @@ public function update_usage_data( $new_data ) {
132
134
*/
133
135
public function track_rss_import () {
134
136
$ data = $ this ->get_usage_data ();
137
+ $ this ->record_import_per_week ();
135
138
136
- if ( PHP_INT_MAX <= $ data ['imports_runs ' ] ) {
139
+ if ( PHP_INT_MAX <= $ data ['import_count ' ] ) {
137
140
return ;
138
141
}
139
142
140
143
$ update_data = array ();
141
144
142
- $ update_data ['imports_runs ' ] = $ data ['imports_runs ' ] + 1 ;
145
+ $ update_data ['import_count ' ] = $ data ['import_count ' ] + 1 ;
143
146
144
147
if ( $ data ['can_track_first_usage ' ] && empty ( $ data ['first_import_run_datetime ' ] ) ) {
145
148
$ update_data ['first_import_run_datetime ' ] = current_time ( 'mysql ' );
@@ -179,17 +182,56 @@ public function delete_usage_data() {
179
182
* Get formatted usage statistics with calculated fields.
180
183
*
181
184
* @since 5.0.7
182
- * @return array< string, string| int>
185
+ * @return array{ first_import_run_datetime?: string, first_import_created_datetime?: string, import_count: int, imports_per_week: array<array{year: int, week: int, count: int}>, time_between_first_import_created_and_run?: int }
183
186
*/
184
187
public function get_usage_stats () {
185
188
$ data = $ this ->get_usage_data ();
186
189
187
190
$ stats = array (
188
- 'import_runs ' => $ data ['imports_runs ' ],
191
+ 'import_count ' => $ data ['import_count ' ],
192
+ 'imports_per_week ' => array (),
189
193
);
190
194
195
+ if ( ! empty ( $ data ['imports_per_week ' ] ) ) {
196
+
197
+ /**
198
+ * Format the import into friendly structure for MongoDB.
199
+ *
200
+ * @var array<array{year: int, week: int, count: int}>
201
+ */
202
+ $ formatted_imports = array ();
203
+
204
+ foreach ( $ data ['imports_per_week ' ] as $ key => $ count ) {
205
+ // Parse the ISO week format manually (e.g., "2025-W31")
206
+ if ( ! preg_match ( '/^(\d{4})-W(\d{1,2})$/ ' , $ key , $ matches ) ) {
207
+ continue ;
208
+ }
209
+
210
+ $ year = (int ) $ matches [1 ];
211
+ $ week = (int ) $ matches [2 ];
212
+
213
+ $ formatted_imports [] = array (
214
+ 'year ' => $ year ,
215
+ 'week ' => $ week ,
216
+ 'count ' => (int ) $ count ,
217
+ );
218
+ }
219
+
220
+ // Sort in chronological order by year and week.
221
+ usort (
222
+ $ formatted_imports ,
223
+ function ( $ a , $ b ) {
224
+ if ( $ a ['year ' ] !== $ b ['year ' ] ) {
225
+ return $ a ['year ' ] - $ b ['year ' ];
226
+ }
227
+ return $ a ['week ' ] - $ b ['week ' ];
228
+ }
229
+ );
230
+ $ stats ['imports_per_week ' ] = $ formatted_imports ;
231
+ }
232
+
191
233
if ( ! $ data ['can_track_first_usage ' ] ) {
192
- return $ data ;
234
+ return $ stats ;
193
235
}
194
236
195
237
$ stats ['first_import_run_datetime ' ] = ! empty ( $ data ['first_import_run_datetime ' ] ) ? $ data ['first_import_run_datetime ' ] : 'Never ' ;
@@ -213,6 +255,36 @@ public function get_usage_stats() {
213
255
return $ stats ;
214
256
}
215
257
258
+ /**
259
+ * Record the import count per year week.
260
+ *
261
+ * @return void
262
+ *
263
+ * @since 5.0.8
264
+ */
265
+ public function record_import_per_week () {
266
+ $ datetime = current_datetime ();
267
+ $ key = $ datetime ->format ( 'o-\WW ' );
268
+
269
+ $ imports_per_week = array ();
270
+ $ data = $ this ->get_usage_data ();
271
+ if ( is_array ( $ data ['imports_per_week ' ] ) ) {
272
+ $ imports_per_week = $ data ['imports_per_week ' ];
273
+ }
274
+
275
+ if ( array_key_exists ( $ key , $ imports_per_week ) ) {
276
+ $ imports_per_week [ $ key ] += 1 ;
277
+ } else {
278
+ $ imports_per_week [ $ key ] = 1 ;
279
+ }
280
+
281
+ if ( 120 < count ( $ imports_per_week ) ) {
282
+ $ imports_per_week = $ this ->remove_old_import_records ( $ imports_per_week , $ datetime );
283
+ }
284
+
285
+ $ this ->update_usage_data ( array ( 'imports_per_week ' => $ imports_per_week ) );
286
+ }
287
+
216
288
/**
217
289
* Check if user installed plugin within last day.
218
290
*
@@ -228,4 +300,35 @@ public function is_new_user() {
228
300
229
301
return DAY_IN_SECONDS >= ( time () - $ install_time );
230
302
}
303
+
304
+ /**
305
+ * Remove the records older than two years.
306
+ *
307
+ * @param array<string, int> $imports_per_week The imports per week data.
308
+ * @param DateTimeImmutable $datetime The current datetime.
309
+ * @return array<string, int>
310
+ */
311
+ public function remove_old_import_records ( $ imports_per_week , $ datetime ) {
312
+ $ cutoff_date_time = ( clone $ datetime )->modify ( '-2 years ' );
313
+
314
+ return array_filter (
315
+ $ imports_per_week ,
316
+ function ( $ key ) use ( $ cutoff_date_time ) {
317
+ // Parse the ISO week format manually (e.g., "2025-W31")
318
+ if ( ! preg_match ( '/^(\d{4})-W(\d{1,2})$/ ' , $ key , $ matches ) ) {
319
+ return false ;
320
+ }
321
+
322
+ $ year = (int ) $ matches [1 ];
323
+ $ week = (int ) $ matches [2 ];
324
+
325
+ // Create a datetime for the last day of that week (Sunday)
326
+ $ record_datetime = new DateTime ();
327
+ $ record_datetime ->setISODate ( $ year , $ week , 7 );
328
+
329
+ return $ record_datetime >= $ cutoff_date_time ;
330
+ },
331
+ ARRAY_FILTER_USE_KEY
332
+ );
333
+ }
231
334
}
0 commit comments