Skip to content

Commit 7f68abd

Browse files
dev: track first import creation/run
1 parent 527dfe7 commit 7f68abd

4 files changed

Lines changed: 265 additions & 53 deletions

File tree

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

Lines changed: 74 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,45 @@ public function get_usage_data( $data ) {
8888
// imports.
8989
$imports = array();
9090
$license = 'free';
91+
92+
$imports = array(
93+
// how many active imports are created.
94+
'publish' => count(
95+
get_posts(
96+
array(
97+
'post_type' => 'feedzy_imports',
98+
'post_status' => 'publish',
99+
'numberposts' => 99,
100+
'fields' => 'ids',
101+
)
102+
)
103+
),
104+
// how many draft imports are created.
105+
'draft' => count(
106+
get_posts(
107+
array(
108+
'post_type' => 'feedzy_imports',
109+
'post_status' => 'draft',
110+
'numberposts' => 99,
111+
'fields' => 'ids',
112+
)
113+
)
114+
),
115+
// how many posts were imported by the imports.
116+
'imported' => count(
117+
get_posts(
118+
array(
119+
'post_type' => 'post',
120+
'post_status' => array( 'publish', 'private', 'draft', 'trash' ),
121+
'numberposts' => 2999, //phpcs:ignore WordPress.WP.PostsPerPage.posts_per_page_numberposts
122+
'fields' => 'ids',
123+
'meta_key' => 'feedzy', //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
124+
'meta_value' => 1, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
125+
)
126+
)
127+
),
128+
);
129+
91130
if ( feedzy_is_pro() ) {
92131
$license = 'pro';
93132
if ( apply_filters( 'feedzy_is_license_of_type', false, 'agency' ) ) {
@@ -107,69 +146,51 @@ public function get_usage_data( $data ) {
107146
}
108147
}
109148

110-
$imports = apply_filters(
111-
'feedzy_usage_data',
112-
array(
113-
// how many active imports are created.
114-
'publish' => count(
115-
get_posts(
116-
array(
117-
'post_type' => 'feedzy_imports',
118-
'post_status' => 'publish',
119-
'numberposts' => 99,
120-
'fields' => 'ids',
121-
)
122-
)
123-
),
124-
// how many draft imports are created
125-
'draft' => count(
126-
get_posts(
127-
array(
128-
'post_type' => 'feedzy_imports',
129-
'post_status' => 'draft',
130-
'numberposts' => 99,
131-
'fields' => 'ids',
132-
)
133-
)
134-
),
135-
// how many posts were imported by the imports
136-
'imported' => count(
137-
get_posts(
138-
array(
139-
'post_type' => 'post',
140-
'post_status' => array( 'publish', 'private', 'draft', 'trash' ),
141-
'numberposts' => 2999, //phpcs:ignore WordPress.WP.PostsPerPage.posts_per_page_numberposts
142-
'fields' => 'ids',
143-
'meta_key' => 'feedzy', //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
144-
'meta_value' => 1, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
145-
)
146-
)
147-
),
148-
// integrations
149-
'integrations' => $integrations,
150-
)
151-
);
149+
$imports['integrations'] = $integrations;
152150
}
153151

152+
$imports = wp_parse_args( Feedzy_Rss_Feeds_Usage::get_instance()->get_usage_stats(), $imports );
153+
$imports = apply_filters( 'feedzy_usage_data', $imports );
154+
155+
// how many posts contain the shortcode
156+
global $wpdb;
157+
$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
158+
159+
$data = array(
160+
'categories' => $categories,
161+
'imports' => $imports,
162+
'shortcodes' => $shortcodes,
163+
'license' => $license,
164+
);
165+
154166
$settings = apply_filters( 'feedzy_get_settings', null );
155167
$config = array();
156168
if ( $settings ) {
157169
$proxy = isset( $settings['proxy'] ) && is_array( $settings['proxy'] ) && ! empty( $settings['proxy'] ) ? array_filter( $settings['proxy'] ) : array();
158170
if ( ! empty( $proxy ) ) {
159171
$config[] = 'proxy';
160172
}
161-
}
162173

163-
// how many posts contain the shortcode
164-
global $wpdb;
165-
$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
166-
$data = array(
167-
'categories' => $categories,
168-
'imports' => $imports,
169-
'shortcodes' => $shortcodes,
170-
'license' => $license,
171-
'config' => $config,
172-
);
174+
if ( isset( $settings['header'], $settings['header']['user-agent'] ) && ! empty( $settings['header']['user-agent'] ) ) {
175+
$config[] = 'custom-user-agent';
176+
}
177+
178+
if ( ! empty( $config ) ) {
179+
$data['config'] = $config;
180+
}
181+
182+
if ( is_array( $settings['general'] ) && ! empty( $settings['general'] ) ) {
183+
foreach ( $settings['general'] as $key => $value ) {
184+
if ( ! empty( $value ) ) {
185+
$general_settings[ $key ] = $value;
186+
}
187+
}
188+
189+
if ( ! empty( $general_settings ) ) {
190+
$data['general'] = $general_settings;
191+
}
192+
}
193+
}
173194

174195
return $data;
175196
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,12 @@ public function save_feedzy_post_type_meta( $post_id, $post ) {
769769
$feedzy_category_feed = preg_replace( '/\s*,\s*|\R/', ',', $feedzy_category_feed );
770770
$category_meta['feedzy_category_feed'] = $feedzy_category_feed;
771771
}
772+
773+
if ( empty( get_post_meta( $post_id, 'usage_counted', true ) ) ) {
774+
Feedzy_Rss_Feeds_Usage::get_instance()->track_import_creation();
775+
update_post_meta( $post_id, 'usage_counted', 'yes' );
776+
}
777+
772778
if ( $post->post_type === 'revision' ) {
773779
return true;
774780
} else {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,8 @@ public function run_cron( $max = 100, $job_id = 0 ) {
13871387
* @access private
13881388
*/
13891389
private function run_job( $job, $max ) {
1390+
Feedzy_Rss_Feeds_Usage::get_instance()->track_rss_import();
1391+
13901392
global $themeisle_log_event;
13911393
$source = get_post_meta( $job->ID, 'source', true );
13921394
$inc_key = get_post_meta( $job->ID, 'inc_key', true );
@@ -3352,6 +3354,7 @@ private function wizard_import_feed() {
33523354
'post_status' => 'publish',
33533355
)
33543356
);
3357+
Feedzy_Rss_Feeds_Usage::get_instance()->track_import_creation();
33553358
}
33563359

33573360
if ( ! is_wp_error( $job_id ) ) {
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
<?php
2+
/**
3+
* Track the usage of the plugin.
4+
*
5+
* @link https://themeisle.com
6+
* @since 3.0.0
7+
*
8+
* @package feedzy-rss-feeds
9+
* @subpackage feedzy-rss-feeds/includes/admin
10+
*/
11+
12+
/**
13+
* Track the usage of the plugin.
14+
*
15+
* @package feedzy-rss-feeds
16+
* @subpackage feedzy-rss-feeds/includes/admin
17+
* @author Themeisle <friends@themeisle.com>
18+
*/
19+
class Feedzy_Rss_Feeds_Usage {
20+
21+
/**
22+
* Option name in wp_options table.
23+
*/
24+
const OPTION_NAME = 'feedzy_usage';
25+
26+
/**
27+
* The single instance of the class.
28+
*
29+
* @var Feedzy_Rss_Feeds_Usage|null
30+
*/
31+
private static $instance = null;
32+
33+
/**
34+
* Default usage data structure.
35+
*
36+
* @var array
37+
*/
38+
private $default_data = array(
39+
'first_import_run_datetime' => null,
40+
'imports_runs' => 0,
41+
'first_import_created_datetime' => null,
42+
);
43+
44+
/**
45+
* Private constructor to prevent direct instantiation.
46+
*/
47+
private function __construct() {
48+
$this->init();
49+
}
50+
51+
/**
52+
* Prevent cloning of the instance.
53+
*/
54+
public function __clone() {}
55+
56+
/**
57+
* Prevent unserialization of the instance.
58+
*/
59+
public function __wakeup() {}
60+
61+
/**
62+
* Get the single instance of the class.
63+
*
64+
* @return Feedzy_Rss_Feeds_Usage
65+
*/
66+
public static function get_instance() {
67+
if (null === self::$instance) {
68+
self::$instance = new self();
69+
}
70+
return self::$instance;
71+
}
72+
73+
/**
74+
* Initialize the usage tracking.
75+
* Creates the option if it doesn't exist.
76+
*/
77+
private function init() {
78+
if ( false === get_option(self::OPTION_NAME) ) {
79+
add_option(self::OPTION_NAME, $this->default_data);
80+
}
81+
}
82+
83+
/**
84+
* Get all usage data.
85+
*
86+
* @return array Usage data array.
87+
*/
88+
public function get_usage_data() {
89+
$data = get_option(self::OPTION_NAME, $this->default_data);
90+
return wp_parse_args($data, $this->default_data);
91+
}
92+
93+
/**
94+
* Update usage data.
95+
*
96+
* @param array $new_data Data to update.
97+
* @return bool True if the option was updated, false otherwise.
98+
*/
99+
private function update_usage_data($new_data) {
100+
$current_data = $this->get_usage_data();
101+
$updated_data = array_merge($current_data, $new_data);
102+
return update_option(self::OPTION_NAME, $updated_data);
103+
}
104+
105+
106+
107+
/**
108+
* Track RSS feed import.
109+
* Sets first import timestamp if it's the first import, always increments counter.
110+
*
111+
* @return void
112+
*/
113+
public function track_rss_import() {
114+
$data = $this->get_usage_data();
115+
116+
if ( PHP_INT_MAX <= $data['imports_runs'] ) {
117+
return;
118+
}
119+
120+
$update_data = array();
121+
122+
$update_data['imports_runs'] = $data['imports_runs'] + 1;
123+
124+
if ( empty( $data['first_import_run_datetime'] ) ) {
125+
$update_data['first_import_run_datetime'] = current_time('mysql');
126+
}
127+
128+
$this->update_usage_data($update_data);
129+
}
130+
131+
/**
132+
* Track settings page creation.
133+
* Sets first settings page timestamp if it's the first page, always increments counter.
134+
*
135+
* @return void
136+
*/
137+
public function track_import_creation() {
138+
$data = $this->get_usage_data();
139+
140+
if ( ! empty( $data['first_import_created_datetime'] ) ) {
141+
return;
142+
}
143+
144+
$this->update_usage_data( array( 'first_import_created_datetime' => current_time('mysql') ) );
145+
}
146+
147+
/**
148+
* Delete the usage data option.
149+
* Useful for plugin uninstall.
150+
*
151+
* @return bool True if the option was deleted, false otherwise.
152+
*/
153+
public function delete_usage_data() {
154+
return delete_option(self::OPTION_NAME);
155+
}
156+
157+
/**
158+
* Get usage statistics in a formatted array.
159+
*
160+
* @return array<string, mixed> Formatted usage statistics.
161+
*/
162+
public function get_usage_stats() {
163+
$data = $this->get_usage_data();
164+
165+
$stats = array(
166+
'first_import_run_datetime' => !empty( $data['first_import_run_datetime'] ) ? $data['first_import_run_datetime'] : 'Never',
167+
'import_runs' => $data['imports_runs'],
168+
'first_import_created_datetime' => !empty( $data['first_import_created_datetime'] ) ? $data['first_import_created_datetime'] : 'Never',
169+
);
170+
171+
// Calculate time between first import run and first import created if applicable.
172+
if ( ! empty( $data['first_import_run_datetime'] ) && ! empty( $data['first_import_created_datetime'] ) ) {
173+
$import_time = strtotime( $data['first_import_run_datetime'] );
174+
$settings_time = strtotime( $data['first_import_created_datetime'] );
175+
if ( $settings_time < $import_time ) {
176+
$stats['time_between_first_import_created_and_run'] = $import_time - $settings_time;
177+
}
178+
}
179+
180+
return $stats;
181+
}
182+
}

0 commit comments

Comments
 (0)