PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.12.0
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.12.0
2.13.0 2.13.1 2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 All 80 releases
ablocks / addons / cookie-consent / report.php

report.php in aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder 2.12.0, at addons/cookie-consent/report.php

114 lines 3.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace ABlocksCookieConsent;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 /**
9 * What the gating layers saw on the last pages that were rendered.
10 *
11 * Two audiences. In dry run it answers "what would you have blocked?" before
12 * anything is blocked. With gating live it answers the harder question — "what
13 * third-party script is running that you have no rule for?" — which is the one
14 * that decides whether the configuration is actually complete.
15 *
16 * Kept in a transient rather than a table: it is diagnostic, it is
17 * regenerable by loading a page, and it should expire on its own.
18 */
19 class Report {
20
21 const KEY = 'ablocks_cc_scan';
22 const LIMIT = 120;
23
24 /**
25 * Entries collected during this request, flushed once on shutdown so a
26 * page with forty scripts writes the option once and not forty times.
27 *
28 * @var array
29 */
30 private static $pending = [];
31
32 /**
33 * @param string $subject Script URL or handle.
34 * @param string $category Matched category, '' when unclassified.
35 * @param string $source 'enqueued' or 'inline'.
36 */
37 public static function add( $subject, $category, $source ) {
38 $subject = (string) $subject;
39 if ( '' === $subject ) {
40 return;
41 }
42 // Inline snippets can be kilobytes; the report only needs a fingerprint.
43 if ( 'inline' === $source && strlen( $subject ) > 120 ) {
44 $subject = trim( preg_replace( '/\s+/', ' ', substr( $subject, 0, 120 ) ) ) . '';
45 }
46
47 $key = md5( $source . '|' . $subject );
48 if ( isset( self::$pending[ $key ] ) ) {
49 return;
50 }
51
52 self::$pending[ $key ] = [
53 'subject' => $subject,
54 'category' => (string) $category,
55 'source' => $source,
56 'url' => self::current_url(),
57 'seen' => time(),
58 ];
59
60 if ( 1 === count( self::$pending ) ) {
61 add_action( 'shutdown', [ __CLASS__, 'flush' ], 99 );
62 }
63 }
64
65 public static function flush() {
66 if ( empty( self::$pending ) ) {
67 return;
68 }
69 $stored = get_transient( self::KEY );
70 $stored = is_array( $stored ) ? $stored : [];
71 $stored = array_merge( $stored, self::$pending );
72
73 // Newest wins when the report is full — an old entry has already been
74 // read, and the entries that matter are from the page just loaded.
75 if ( count( $stored ) > self::LIMIT ) {
76 uasort(
77 $stored,
78 function ( $a, $b ) {
79 return $b['seen'] <=> $a['seen'];
80 }
81 );
82 $stored = array_slice( $stored, 0, self::LIMIT, true );
83 }
84
85 set_transient( self::KEY, $stored, DAY_IN_SECONDS );
86 self::$pending = [];
87 }
88
89 /**
90 * @return array Entries, newest first.
91 */
92 public static function get() {
93 $stored = get_transient( self::KEY );
94 $stored = is_array( $stored ) ? $stored : [];
95 uasort(
96 $stored,
97 function ( $a, $b ) {
98 return $b['seen'] <=> $a['seen'];
99 }
100 );
101 return array_values( $stored );
102 }
103
104 public static function clear() {
105 delete_transient( self::KEY );
106 }
107
108 private static function current_url() {
109 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
110 $path = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
111 return $path ? substr( $path, 0, 190 ) : '';
112 }
113 }
114