PluginProbe
Vigilant – 100% Free Security Suite: Firewall, 2FA, Login, Headers, Scanner… / 2.9.8
Vigilant – 100% Free Security Suite: Firewall, 2FA, Login, Headers, Scanner… v2.9.8
3.0.0 2.11.12 2.11.11 2.11.10 2.11.9 2.11.7 2.11.8 2.11.6 2.11.5 2.11.4 2.11.3 2.11.1 2.11.2 2.11.0 2.10.5 2.10.4 2.10.3 2.10.2 2.10.1 2.10.0 2.9.9 2.9.8 2.9.6 2.9.7 2.9.5 All 88 releases
vigilante / includes / security-analyzer / class-sa-check-result.php

class-sa-check-result.php in Vigilant – 100% Free Security Suite: Firewall, 2FA, Login, Headers, Scanner… 2.9.8, at includes/security-analyzer/class-sa-check-result.php

192 lines 5.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Security Analyzer — Check result value object.
4 *
5 * Represents the outcome of a single check inside the Security Analyzer.
6 * Categories return arrays of these, the orchestrator aggregates them
7 * into the scan report.
8 *
9 * @package Vigilante
10 * @since 2.1.0
11 */
12
13 // Prevent direct access.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 /**
19 * Immutable-ish value object describing a single analyzer check result.
20 *
21 * Lightweight on purpose — just a typed container so category classes
22 * don't return nested associative arrays with inconsistent keys.
23 */
24 class Vigilante_SA_Check_Result {
25
26 /**
27 * State constants.
28 */
29 const STATE_PASS = 'pass'; // Check fully passed.
30 const STATE_WARN = 'warn'; // Partial / non-critical issue.
31 const STATE_FAIL = 'fail'; // Check failed.
32 const STATE_INFO = 'info'; // Informational (no score impact, e.g. theme version).
33 const STATE_SKIP = 'skip'; // Could not evaluate (no network, permission issue).
34
35 /**
36 * Unique ID (e.g. "csp", "admin_username"). Matches catalog key.
37 *
38 * @var string
39 */
40 public $id;
41
42 /**
43 * Category slug (ssl, headers, wp_exposure, access, files, internal).
44 *
45 * @var string
46 */
47 public $category;
48
49 /**
50 * Current state (pass/warn/fail/info/skip).
51 *
52 * @var string
53 */
54 public $state;
55
56 /**
57 * Points awarded on this run (0..max).
58 *
59 * @var int
60 */
61 public $score;
62
63 /**
64 * Maximum points this check can award.
65 *
66 * @var int
67 */
68 public $max;
69
70 /**
71 * Translated short label (e.g. "HTTPS enabled").
72 *
73 * @var string
74 */
75 public $label;
76
77 /**
78 * Translated longer detail explaining the result.
79 *
80 * @var string
81 */
82 public $detail;
83
84 /**
85 * Admin URL linking to the relevant setting, or empty string if none.
86 *
87 * @var string
88 */
89 public $fix_link;
90
91 /**
92 * Optional extra payload (e.g. expiry days, current value). Serializable scalars only.
93 *
94 * @var array
95 */
96 public $data;
97
98 /**
99 * Constructor.
100 *
101 * @param array $args Keys: id, category, state, score, max, label, detail, fix_link, data.
102 */
103 public function __construct( array $args ) {
104 $this->id = isset( $args['id'] ) ? (string) $args['id'] : '';
105 $this->category = isset( $args['category'] ) ? (string) $args['category'] : '';
106 $this->state = isset( $args['state'] ) ? (string) $args['state'] : self::STATE_SKIP;
107 $this->score = isset( $args['score'] ) ? (int) $args['score'] : 0;
108 $this->max = isset( $args['max'] ) ? (int) $args['max'] : 0;
109 $this->label = isset( $args['label'] ) ? (string) $args['label'] : '';
110 $this->detail = isset( $args['detail'] ) ? (string) $args['detail'] : '';
111 $this->fix_link = isset( $args['fix_link'] ) ? (string) $args['fix_link'] : '';
112 $this->data = isset( $args['data'] ) && is_array( $args['data'] ) ? $args['data'] : array();
113
114 // Clamp score within [0, max].
115 if ( $this->score < 0 ) {
116 $this->score = 0;
117 }
118 if ( $this->max > 0 && $this->score > $this->max ) {
119 $this->score = $this->max;
120 }
121 }
122
123 /**
124 * Serialize to array for persistence/JSON.
125 *
126 * @return array
127 */
128 public function to_array() {
129 return array(
130 'id' => $this->id,
131 'category' => $this->category,
132 'state' => $this->state,
133 'score' => $this->score,
134 'max' => $this->max,
135 'label' => $this->label,
136 'detail' => $this->detail,
137 'fix_link' => $this->fix_link,
138 'data' => $this->data,
139 );
140 }
141
142 /**
143 * Whether this result should influence the aggregate score.
144 * INFO results are always excluded; SKIP results award nothing and max is ignored
145 * so they don't unfairly drag the score down when the analyzer couldn't evaluate.
146 *
147 * @return bool
148 */
149 public function counts_for_score() {
150 return self::STATE_INFO !== $this->state && self::STATE_SKIP !== $this->state;
151 }
152
153 /**
154 * Shorthand constructors keep category classes readable.
155 */
156 public static function pass( $args ) {
157 $args['state'] = self::STATE_PASS;
158 if ( ! isset( $args['score'] ) && isset( $args['max'] ) ) {
159 $args['score'] = $args['max'];
160 }
161 return new self( $args );
162 }
163
164 public static function warn( $args ) {
165 $args['state'] = self::STATE_WARN;
166 // Warn awards half points by default if not explicitly set.
167 if ( ! isset( $args['score'] ) && isset( $args['max'] ) ) {
168 $args['score'] = (int) floor( $args['max'] / 2 );
169 }
170 return new self( $args );
171 }
172
173 public static function fail( $args ) {
174 $args['state'] = self::STATE_FAIL;
175 $args['score'] = 0;
176 return new self( $args );
177 }
178
179 public static function info( $args ) {
180 $args['state'] = self::STATE_INFO;
181 $args['score'] = 0;
182 $args['max'] = 0;
183 return new self( $args );
184 }
185
186 public static function skip( $args ) {
187 $args['state'] = self::STATE_SKIP;
188 $args['score'] = 0;
189 return new self( $args );
190 }
191 }
192