PluginProbe
404 Solution / trunk
404 Solution vtrunk
4.3.5 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.2.0 4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.1.7 4.1.6 4.1.5 4.1.4 4.1.3 trunk 2.30.0 All 109 releases
404-solution / includes / logs / LogsPrivacyService.php

LogsPrivacyService.php in 404 Solution trunk, at includes/logs/LogsPrivacyService.php

95 lines 4.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 /**
8 * GDPR privacy operations on logsv2 rows, keyed by lookup value (user name).
9 *
10 * Three operations: paginated id-lookup for a username, paginated row-lookup
11 * for export, and anonymize-by-ids for erasure. The anonymize path overwrites
12 * user_ip with the sentinel string '(Anonymized)' and nulls referrer,
13 * requested_url_detail, and username.
14 *
15 * Extracted from LogsRepository under M201. Consumed by Privacy.php via the
16 * LogsRepository facade.
17 */
18 class ABJ_404_Solution_LogsPrivacyService {
19
20 /** @var ABJ_404_Solution_DatabaseCore */
21 private $dbCore;
22
23 public function __construct(ABJ_404_Solution_DatabaseCore $dbCore) {
24 $this->dbCore = $dbCore;
25 }
26
27 /**
28 * Paginated id-only lookup. Returns logsv2 row ids whose username (via
29 * lkup) matches the given value.
30 *
31 * @param string $lkupValue
32 * @param int $page 1-indexed
33 * @param int $perPage clamped to [1, 500]
34 * @return int[]
35 */
36 public function getLogsv2IdsForLookupValue($lkupValue, $page = 1, $perPage = 100) {
37 $lkupValue = trim($lkupValue);
38 if ($lkupValue === '') { return array(); }
39 $page = max(1, absint($page));
40 $perPage = max(1, min(500, absint($perPage)));
41 $offset = ($page - 1) * $perPage;
42 $logsTable = $this->dbCore->doTableNameReplacements("{wp_abj404_logsv2}");
43 $lookupTable = $this->dbCore->doTableNameReplacements("{wp_abj404_lookup}");
44 $sql = "SELECT l.id FROM `{$logsTable}` l INNER JOIN `{$lookupTable}` u ON l.username = u.id WHERE u.lkup_value = %s ORDER BY l.id DESC LIMIT %d OFFSET %d";
45 $result = $this->dbCore->queryAndGetResults($sql, array('query_params' => array($lkupValue, $perPage, $offset)));
46 if (!empty($result['timed_out']) || (isset($result['last_error']) && $result['last_error'] != '')) { return array(); }
47 $rows = is_array($result['rows'] ?? null) ? $result['rows'] : array();
48 $ids = array();
49 foreach ($rows as $row) {
50 if (is_array($row) && isset($row['id'])) { $ids[] = absint($row['id']); }
51 }
52 return array_values(array_filter($ids));
53 }
54
55 /**
56 * Paginated row-lookup for export. Fetches a fixed projection of the
57 * logsv2 columns relevant to a GDPR export.
58 *
59 * @param string $lkupValue
60 * @param int $page
61 * @param int $perPage
62 * @return array<int, array<string, mixed>>
63 */
64 public function getLogsv2RowsForLookupValue($lkupValue, $page = 1, $perPage = 50) {
65 $ids = $this->getLogsv2IdsForLookupValue($lkupValue, $page, $perPage);
66 if (empty($ids)) { return array(); }
67 $logsTable = $this->dbCore->doTableNameReplacements("{wp_abj404_logsv2}");
68 $placeholders = implode(',', array_fill(0, count($ids), '%d'));
69 $sql = "SELECT id, timestamp, user_ip, referrer, requested_url, requested_url_detail, dest_url FROM `{$logsTable}` WHERE id IN ({$placeholders}) ORDER BY id DESC";
70 $result = $this->dbCore->queryAndGetResults($sql, array('query_params' => $ids));
71 if (!empty($result['timed_out']) || (isset($result['last_error']) && $result['last_error'] != '')) { return array(); }
72 return is_array($result['rows'] ?? null) ? $result['rows'] : array();
73 }
74
75 /**
76 * Anonymize logsv2 rows by id (GDPR erasure). Overwrites user_ip with
77 * '(Anonymized)' and nulls referrer, requested_url_detail, username.
78 *
79 * @param int[] $ids
80 * @return bool true on success, false on query error
81 */
82 public function anonymizeLogsv2RowsByIds($ids) {
83 if (!is_array($ids) || empty($ids)) { return true; }
84 $ids = array_values(array_filter(array_map('absint', $ids)));
85 if (empty($ids)) { return true; }
86 $logsTable = $this->dbCore->doTableNameReplacements("{wp_abj404_logsv2}");
87 $placeholders = implode(',', array_fill(0, count($ids), '%d'));
88 $sql = "UPDATE `{$logsTable}` SET user_ip = %s, referrer = NULL, requested_url_detail = NULL, username = NULL WHERE id IN ({$placeholders})";
89 $params = array_merge(array('(Anonymized)'), $ids);
90 $result = $this->dbCore->queryAndGetResults($sql, array('query_params' => $params));
91 if (!empty($result['timed_out']) || (isset($result['last_error']) && $result['last_error'] != '')) { return false; }
92 return true;
93 }
94 }
95