PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / 3.3.1
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar v3.3.1
3.3.1 3.3.0 3.2.14 3.2.13 3.2.12 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 trunk 0.2.5.5 0.2.5.6 0.2.5.7 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 All 156 releases
notificationx / includes / Admin / Scanner / Scanner.php

Scanner.php in NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar 3.3.1, at includes/Admin/Scanner/Scanner.php

257 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace NotificationX\Admin\Scanner;
3
4 use NotificationX\Core\Helper;
5 use NotificationX\GetInstance;
6 use NotificationX\NotificationX;
7 use WP_REST_Server;
8 use WP_REST_Request;
9 use WP_REST_Response;
10
11 class Scanner
12 {
13 use GetInstance;
14 private static $_namespace = 'notificationx';
15 private static $_version = 1;
16 private static $_apiBase = "";
17 private static $is_pro = false;
18 public function __construct()
19 {
20 add_action('rest_api_init', [$this, 'rest_init']);
21 if( NotificationX::is_pro() ) {
22 self::$is_pro = true;
23 }
24 self::$_apiBase = (defined('NX_DEBUG') && NX_DEBUG)
25 ? 'https://notificationx-api.test/cookie-scanner/v1'
26 : 'https://api.notificationx.com/cookie-scanner/v1';
27 }
28
29 public static function _namespace()
30 {
31 return self::$_namespace . '/v' . self::$_version;
32 }
33
34 /**
35 * Registers custom REST API endpoints for scan initiation, scan status, and scan history.
36 *
37 * - /scan: Initiates a new scan based on the provided URL.
38 * - /scan/status: Retrieves the status of a scan using the provided scan ID.
39 * - /scan/history: Fetches the scan history based on the notification ID (nx_id).
40 *
41 * @return void
42 */
43 public function rest_init()
44 {
45 $namespace = self::_namespace();
46
47 // Register the scan initiation endpoint
48 register_rest_route($namespace, '/scan', array(
49 'methods' => WP_REST_Server::CREATABLE,
50 'callback' => array($this, 'initiate_scan'),
51 'permission_callback' => array($this, 'edit_permission'),
52 ));
53
54 // Register the scan status endpoint
55 register_rest_route($namespace, '/scan/status', array(
56 'methods' => WP_REST_Server::EDITABLE,
57 'callback' => array($this, 'check_scan_status'),
58 'permission_callback' => array($this, 'edit_permission'),
59 ));
60
61 }
62
63 /**
64 * Permission check for the scanner routes.
65 * The cookie scanner is only used from the notification builder,
66 * which requires the edit_notificationx capability.
67 *
68 * @return bool
69 */
70 public function edit_permission()
71 {
72 return current_user_can('edit_notificationx');
73 }
74
75 /**
76 * Initiates a scan process for the provided URL.
77 *
78 * Validates the URL parameter and triggers the scan if it's valid.
79 * Responds with the scan status.
80 *
81 * @param WP_REST_Request $request The REST request object containing the URL.
82 *
83 * @return WP_REST_Response The response indicating the status of the scan initiation.
84 */
85 public function initiate_scan(WP_REST_Request $request)
86 {
87 $url = $request->get_param('url');
88
89 // Check if the URL parameter is provided
90 if (empty($url)) {
91 return new WP_REST_Response(['error' => 'URL parameter is required'], 200);
92 }
93
94 // Trigger the scan process (implement this function as needed)
95 $this->trigger_scan($url);
96
97 return new WP_REST_Response(['status' => 'Scan started.'], 200);
98 }
99
100 /**
101 * Retrieves the current status of a scan based on the provided scan ID.
102 *
103 * Queries the status from an external service and returns the results.
104 * If the scan is completed, it processes the result and inserts cookie and stats entries into the database.
105 *
106 * @param WP_REST_Request $request The REST request object containing the scan ID.
107 *
108 * @return WP_REST_Response The response with the scan status or an error message.
109 */
110 public function check_scan_status(WP_REST_Request $request)
111 {
112 $scanId = $request->get_param('scan_id');
113
114 // Retrieve the scan status from the database (implement this function as needed)
115 $status = $this->get_scan_status($scanId);
116
117 // Handle invalid scan ID
118 if ($status === null && empty( $scanId )) {
119 $data = [ 'status' => 'failed', 'message' => __('Invalid scan ID','notificationx') ];
120 return new WP_REST_Response(['data' => $data ], 404);
121 }
122
123 // Process the scan result if the status is 'completed'
124 if ( is_array($status) && !empty($status['status']) && $status['status'] === 'completed') {
125 // Update scan count to the options
126 $pre_count = get_option('nx_scan_count', 0);
127 update_option('nx_scan_count', $pre_count + 1);
128 update_option('nx_scan_date', Helper::nx_get_current_datetime() );
129
130 $cookies = $status['result']; // Extract scanned cookies
131 $stats = $status['stats']; // Extract scan statistics
132
133 // Use the helper function to categorize cookies and get the category count
134 $cookieData = $this->categorizeCookiesAndCount($cookies);
135 $categoryCount = $cookieData['category_count'];
136 $categorized = $cookieData['categorized'];
137 $data = [ 'last_scan_date' => Helper::nx_get_current_datetime(), 'status' => 'completed', 'stats' => $stats, 'cookies' => $cookies, 'category_count' => $categoryCount, 'categorized' => $categorized ];
138 return new WP_REST_Response(['data' => $data], 200);
139 }
140
141 return new WP_REST_Response(['data' => $status], 200);
142 }
143
144 /**
145 * Triggers a scan process by making an HTTP GET request to an external API.
146 *
147 * Sends the provided URL to the external scan API and handles the response.
148 *
149 * @param string $url The URL to be scanned.
150 *
151 * @return WP_REST_Response The response containing the result of the scan.
152 */
153 private function trigger_scan($url)
154 {
155 // API endpoint that will process the scan
156 if( self::$is_pro ) {
157 $apiEndpoint = self::$_apiBase . "?nxpro=active&url=" . urlencode($url);
158 }else{
159 $apiEndpoint = self::$_apiBase . "?url=" . urlencode($url);
160 }
161
162 // Make an HTTP GET request
163 $response = wp_remote_get($apiEndpoint, [
164 'timeout' => 200, // Set timeout (adjust as needed)
165 'sslverify' => false, // Bypass SSL verification temporarily (for local dev)
166 ]);
167
168 // Check for errors in the response
169 if (is_wp_error($response)) {
170 return new WP_REST_Response(['error' => $response->get_error_message()], 500);
171 }
172
173 // Decode response body
174 $responseBody = json_decode(wp_remote_retrieve_body($response), true);
175
176 return wp_send_json_success($responseBody);
177 }
178
179 /**
180 * Retrieves the current status of a scan from the external scan API using the scan ID.
181 *
182 * Makes an HTTP GET request to the scan API to fetch the status of the scan.
183 *
184 * @param string $scanId The scan ID to check the status of.
185 *
186 * @return array The scan status data from the external API.
187 */
188 private function get_scan_status($scanId)
189 {
190 // API endpoint to check the scan status
191 $apiEndpoint = self::$_apiBase . "/status.php?scan_id=" . urlencode($scanId);
192
193 // Make an HTTP GET request
194 $response = wp_remote_get($apiEndpoint, [
195 'timeout' => 200, // Set timeout (adjust as needed)
196 'sslverify' => false, // Bypass SSL verification temporarily (for local dev)
197 ]);
198
199 // Check for errors in the response
200 if (is_wp_error($response)) {
201 return new WP_REST_Response(['error' => $response->get_error_message()], 500);
202 }
203
204 // Decode response body
205 $responseBody = json_decode(wp_remote_retrieve_body($response), true);
206 return $responseBody;
207 }
208
209
210 // Helper function to categorize cookies and calculate category count
211 public function categorizeCookiesAndCount($cookies) {
212 // Define cookie categories
213 $cookieCategoryPrefix = [
214 'necessary' => ['PHPSESSID', 'wordpress_logged_in', 'wp-settings', 'wp-settings-time', 'wpEmojiSettingsSupports', 'cookieyes-consent', 'elementor', 'csrftoken', 'auth', 'session', 'secure', 'cart', 'checkout', 'wp_woocommerce'],
215 'functional' => ['lang', 'preferences', 'remember_me', 'theme', 'consent', 'locale', 'user_settings', 'cookie_preference'],
216 'analytics' => ['_ga', '_gid', '_gat', 'fbp', 'utm', 'amplitude', 'mixpanel', 'hotjar', 'segment', 'ahoy', 'kissmetrics', 'analytics', 'visitor_id', 'sbjs_udata', 'sbjs_current', 'sbjs_first', 'sbjs_first_add', 'sbjs_current_add'],
217 'performance' => ['_hj', 'cf_use_ob', 'cf_clearance', 'AWSALB', 'load_balancer', 'page_speed', 'cdn_cache', 'pingdom', 'new_relic'],
218 'advertisement' => ['ads', '_fbp', '_gcl', '_dc_gtm', 'doubleclick', 'IDE', 'adroll', 'criteo', 'twitter_ads', 'bing_ads', 'remarketing', 'test_cookie'],
219 ];
220
221 // Initialize category counts
222 $categorized = [
223 'necessary' => 0,
224 'functional' => 0,
225 'analytics' => 0,
226 'performance' => 0,
227 'advertisement' => 0,
228 ];
229
230 // Categorize cookies based on partial matching of cookie names (prefixes)
231 if (!empty($cookies) && is_array($cookies)) {
232 foreach ($cookies as $cookie) {
233 foreach ($cookieCategoryPrefix as $category => $cookieNames) {
234 foreach ($cookieNames as $cookieName) {
235 if (isset($cookie['name']) && strpos($cookie['name'], $cookieName) !== false) { // Check if cookie contains the prefix
236 $categorized[$category]++;
237 break; // No need to check other prefixes for this cookie
238 }
239 }
240 }
241 }
242 }
243
244 // Calculate the category count (only categories with count > 0)
245 $categoryCount = count(array_filter($categorized, function($count) {
246 return $count > 0;
247 }));
248
249 return [
250 'category_count' => $categoryCount,
251 'categorized' => $categorized
252 ];
253 }
254
255 }
256 ?>
257