PluginProbe
Extendify / 3.0.4
Extendify v3.0.4
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / app / Insights.php

Insights.php in Extendify 3.0.4, at app/Insights.php

211 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Insights setup
5 */
6
7 namespace Extendify;
8
9 defined('ABSPATH') || die('No direct access.');
10
11 use Extendify\Shared\Services\Sanitizer;
12 use Extendify\PartnerData;
13
14 /**
15 * Controller for handling various Insights related things.
16 * WP code reviewers: This is used in another plugin and not invoked here.
17 */
18
19 class Insights
20 {
21 /**
22 * An array of active tests. 'A' should be the control.
23 * For weighted tests, try ['A', 'A', 'A', 'A', 'B']
24 *
25 * @var array
26 */
27 protected $activeTests = [];
28
29 /**
30 * Process the readme file to get version and name
31 *
32 * @return void
33 */
34 public function __construct()
35 {
36 // If there isn't a siteId, then create one.
37 if (!\get_option('extendify_site_id', false)) {
38 \update_option('extendify_site_id', \wp_generate_uuid4());
39 }
40
41 if (
42 defined('EXTENDIFY_INSIGHTS_URL')
43 && class_exists('ExtendifyInsights')
44 && !\get_option('extendify_insights_checkedin_once', 0)
45 ) {
46 \update_option('extendify_insights_checkedin_once', gmdate('Y-m-d H:i:s'));
47 // WP code reviewers: This job is defined in another plugin (i.e. it's opt-in).
48 \add_action('init', function () {
49 // Run this once but wait 10 minutes.
50 \wp_schedule_single_event((time() + 10 * MINUTE_IN_SECONDS), 'extendify_insights');
51 \spawn_cron();
52 });
53 }
54
55 $this->setUpActiveTests();
56 $this->filterExternalInsights();
57 $this->setupAdminLoginInsights();
58 }
59
60 /**
61 * Returns the active tests for the user, and sets up tests as needed.
62 *
63 * @return void
64 */
65 public function setUpActiveTests()
66 {
67 // Make sure that the active tests are set.
68 $currentTests = \get_option('extendify_active_tests', []);
69 $newTests = array_map(function ($test) {
70 // Pick from value randomly.
71 return $test[array_rand($test)];
72 }, array_diff_key($this->activeTests, $currentTests));
73 $testsCombined = array_merge($currentTests, $newTests);
74 if ($newTests) {
75 \update_option('extendify_active_tests', Sanitizer::sanitizeArray($testsCombined));
76 }
77 }
78
79 /**
80 * Add additional data to the opt-in insights
81 *
82 * @return void
83 */
84 public function filterExternalInsights()
85 {
86 add_filter('extendify_insights_data', function ($data) {
87 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
88 $readme = file_get_contents(EXTENDIFY_PATH . 'readme.txt');
89 preg_match('/Stable tag: ([0-9.:]+)/', $readme, $version);
90
91 $insights = array_merge($data, [
92 'launch' => Config::$showLaunch,
93 'launchRedirectedAt' => \get_option('extendify_attempted_redirect', null),
94 'launchLoadedAt' => \get_option('extendify_launch_loaded', null),
95 'partner' => defined('EXTENDIFY_PARTNER_ID') ? constant('EXTENDIFY_PARTNER_ID') : null,
96 'siteCreatedAt' => SiteSettings::getSiteCreatedAt(),
97 'assistRouterData' => \get_option('extendify_assist_router', null),
98 'libraryData' => \get_option('extendify_library_site_data', null),
99 'draftSettingsData' => \get_option('extendify_draft_settings', null),
100 'activity' => \get_option('extendify_shared_activity', null),
101 'domainsActivities' => \get_option('extendify_domains_recommendations_activities', null),
102 'extendifyVersion' => ($version[1] ?? null),
103 'siteProfile' => \get_option('extendify_site_profile', null),
104 'pluginSearchTerms' => \get_option('extendify_plugin_search_terms', []),
105 'blockSearchTerms' => \get_option('extendify_block_search_terms', []),
106 'phpVersion' => PHP_VERSION,
107 'themeSearchTerms' => \get_option('extendify_theme_search_terms', []),
108 'license' => PartnerData::setting('license'),
109 'pagesCount' => $this->getPostsCount('page'),
110 'postsCount' => $this->getPostsCount('post'),
111 'lastUpdatedPage' => $this->getLastUpdatedPost('page'),
112 'lastUpdatedPost' => $this->getLastUpdatedPost('post'),
113 'lastLoginAdmin' => $this->getLastAdminLogin(),
114 'hasImprint' => $this->hasImprint(),
115 ]);
116 return $insights;
117 });
118 }
119
120 /**
121 * Get the number of posts/pages
122 *
123 * @param string $type The type of post/page to get the count for (post or page)
124 * @return int The number of posts/pages
125 */
126 protected function getPostsCount($type = 'post')
127 {
128 $count = wp_count_posts($type);
129 return isset($count->publish) ? (int) $count->publish : 0;
130 }
131
132 /**
133 * Set up admin login insights to monitor when admin users log in
134 *
135 * @return void
136 */
137 protected function setupAdminLoginInsights()
138 {
139 add_action('wp_login', function ($user_login, $user) {
140 // Only get insights for admin users
141 if (user_can($user, 'manage_options')) {
142 update_user_meta($user->ID, 'extendify_last_login', gmdate('Y-m-d H:i:s'));
143 }
144 }, 10, 2);
145 }
146
147 /**
148 * Get the last time a post/page was updated
149 *
150 * @return string|null The last updated post timestamp or null if no posts found
151 */
152 protected function getLastUpdatedPost($type = 'post')
153 {
154 $posts = get_posts([
155 'post_type' => $type,
156 'post_status' => 'publish',
157 'orderby' => 'modified',
158 'order' => 'DESC',
159 'numberposts' => 1,
160 'fields' => 'ids'
161 ]);
162
163 if (!empty($posts)) {
164 $post = get_post($posts[0]);
165 return $post ? $post->post_modified : null;
166 }
167 return null;
168 }
169
170 /**
171 * Get the last time an admin user logged in
172 *
173 * @return string|null The most recent admin login timestamp or null if no data found
174 */
175 protected function getLastAdminLogin()
176 {
177 $admins = get_users([
178 'role' => 'administrator',
179 'meta_key' => 'extendify_last_login',
180 'orderby' => 'meta_value',
181 'order' => 'DESC',
182 'number' => 1
183 ]);
184
185 if (!empty($admins)) {
186 return get_user_meta($admins[0]->ID, 'extendify_last_login', true);
187 }
188 return null;
189 }
190
191 /**
192 * Check if the site has an imprint based on the site profile and language settings
193 *
194 * @return bool True if the site has an imprint, false otherwise
195 */
196 protected function hasImprint()
197 {
198 $siteProfile = \get_option('extendify_site_profile', []);
199 if (empty($siteProfile)) {
200 return false;
201 }
202
203 $imprintLanguages = array_filter(PartnerData::setting('showImprint') ?? [], function ($value) {
204 return $value === get_locale();
205 });
206
207 return !empty($imprintLanguages) && (strtolower($siteProfile['aiSiteCategory']) === 'business' ||
208 strtolower($siteProfile['category']) === 'business');
209 }
210 }
211