Skip to content

Commit dc20f64

Browse files
dev: track the import count per week and days since install (#1102)
- Add the import run count per week for telemetry. - Add the days since install for telemetry.
1 parent 19e5e87 commit dc20f64

File tree

3 files changed

+500
-16
lines changed

3 files changed

+500
-16
lines changed

includes/abstract/feedzy-rss-feeds-admin-abstract.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,11 @@ public function get_usage_data( $data ) {
156156
$shortcodes = $wpdb->get_var( "SELECT count(*) FROM {$wpdb->prefix}posts WHERE post_status IN ('publish', 'private') AND post_content LIKE '%[feedzy-rss %'" ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
157157

158158
$data = array(
159-
'categories' => $categories,
160-
'imports' => $imports,
161-
'shortcodes' => $shortcodes,
162-
'license' => $license,
159+
'categories' => $categories,
160+
'imports' => $imports,
161+
'shortcodes' => $shortcodes,
162+
'license' => $license,
163+
'days_since_install' => round( ( time() - get_option( 'feedzy_rss_feeds_install', time() ) ) / DAY_IN_SECONDS ),
163164
);
164165

165166
$settings = apply_filters( 'feedzy_get_settings', null );

includes/admin/feedzy-rss-feeds-usage.php

Lines changed: 115 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,15 @@ class Feedzy_Rss_Feeds_Usage {
4141
* Default usage data structure.
4242
*
4343
* @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> }
4545
*/
4646
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' => [],
5153
);
5254

5355
/**
@@ -103,7 +105,7 @@ private function init() {
103105
* Get usage data with defaults merged.
104106
*
105107
* @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> }
107109
*/
108110
public function get_usage_data() {
109111
$data = get_option( self::OPTION_NAME, array() );
@@ -114,7 +116,7 @@ public function get_usage_data() {
114116
* Update usage data.
115117
*
116118
* @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.
118120
* @return bool
119121
*/
120122
public function update_usage_data( $new_data ) {
@@ -132,14 +134,15 @@ public function update_usage_data( $new_data ) {
132134
*/
133135
public function track_rss_import() {
134136
$data = $this->get_usage_data();
137+
$this->record_import_per_week();
135138

136-
if ( PHP_INT_MAX <= $data['imports_runs'] ) {
139+
if ( PHP_INT_MAX <= $data['import_count'] ) {
137140
return;
138141
}
139142

140143
$update_data = array();
141144

142-
$update_data['imports_runs'] = $data['imports_runs'] + 1;
145+
$update_data['import_count'] = $data['import_count'] + 1;
143146

144147
if ( $data['can_track_first_usage'] && empty( $data['first_import_run_datetime'] ) ) {
145148
$update_data['first_import_run_datetime'] = current_time( 'mysql' );
@@ -179,17 +182,56 @@ public function delete_usage_data() {
179182
* Get formatted usage statistics with calculated fields.
180183
*
181184
* @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 }
183186
*/
184187
public function get_usage_stats() {
185188
$data = $this->get_usage_data();
186189

187190
$stats = array(
188-
'import_runs' => $data['imports_runs'],
191+
'import_count' => $data['import_count'],
192+
'imports_per_week' => array(),
189193
);
190194

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+
191233
if ( ! $data['can_track_first_usage'] ) {
192-
return $data;
234+
return $stats;
193235
}
194236

195237
$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() {
213255
return $stats;
214256
}
215257

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+
216288
/**
217289
* Check if user installed plugin within last day.
218290
*
@@ -228,4 +300,35 @@ public function is_new_user() {
228300

229301
return DAY_IN_SECONDS >= ( time() - $install_time );
230302
}
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+
}
231334
}

0 commit comments

Comments
 (0)