Files
argus-wp-defence/includes/class-argus-charts.php
T
root df0f2fccb8 ARGUS WordPress Defence 1.0.0 — first production release
Automatic WordPress security: local firewall, malware and file-integrity
scanning, vulnerability protection, quarantine, scheduled backups, an
optional page cache, and automatic global threat intelligence.

See README.md for installation, update, and uninstall instructions.
2026-08-09 13:40:16 +00:00

142 lines
4.4 KiB
PHP

<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Argus_Charts {
const PALETTE = array( '#3987e5', '#d95926', '#199e70', '#c98500', '#d55181', '#9085e9', '#e66767', '#17a2b8' );
public static function donut( array $data, $size = 168, $stroke = 24 ) {
$total = array_sum( $data );
if ( $total <= 0 ) {
return '';
}
$r = ( $size - $stroke ) / 2;
$c = $size / 2;
$circumference = 2 * M_PI * $r;
$segments = '';
$offset = 0;
$i = 0;
foreach ( $data as $label => $value ) {
if ( $value <= 0 ) {
continue;
}
$len = ( $value / $total ) * $circumference;
$color = self::PALETTE[ $i % count( self::PALETTE ) ];
$segments .= sprintf(
'<circle cx="%1$s" cy="%1$s" r="%2$s" fill="none" stroke="%3$s" stroke-width="%4$s" stroke-dasharray="%5$s %6$s" stroke-dashoffset="%7$s" stroke-linecap="butt" transform="rotate(-90 %1$s %1$s)"><title>%8$s: %9$s</title></circle>',
esc_attr( $c ),
esc_attr( $r ),
esc_attr( $color ),
esc_attr( $stroke ),
esc_attr( round( $len, 3 ) ),
esc_attr( round( $circumference - $len, 3 ) ),
esc_attr( round( -$offset, 3 ) ),
esc_html( $label ),
esc_html( number_format_i18n( $value ) )
);
$offset += $len;
$i++;
}
return sprintf(
'<svg viewBox="0 0 %1$d %1$d" class="argus-wpd-donut-svg" role="img" aria-label="%2$s">'
. '<circle cx="%3$s" cy="%3$s" r="%4$s" fill="none" stroke="var(--panel-2)" stroke-width="%5$s"></circle>'
. '%6$s'
. '<text x="%3$s" y="%3$s" text-anchor="middle" dominant-baseline="middle" class="argus-wpd-donut-total">%7$s</text>'
. '</svg>',
$size,
esc_attr__( 'Distribution chart', 'argus-wordpress-defence' ),
esc_attr( $c ),
esc_attr( $r ),
esc_attr( $stroke ),
$segments,
esc_html( number_format_i18n( $total ) )
);
}
public static function legend( array $data ) {
$total = array_sum( $data );
if ( $total <= 0 ) {
return '';
}
$html = '<div class="argus-wpd-donut-legend">';
$i = 0;
foreach ( $data as $label => $value ) {
if ( $value <= 0 ) {
continue;
}
$color = self::PALETTE[ $i % count( self::PALETTE ) ];
$pct = round( $value / $total * 100 );
$html .= sprintf(
'<div class="argus-wpd-donut-legend-row"><span class="argus-wpd-donut-swatch" style="background:%1$s"></span><span class="argus-wpd-donut-legend-label">%2$s</span><span class="argus-wpd-donut-legend-value">%3$s <em>(%4$s%%)</em></span></div>',
esc_attr( $color ),
esc_html( $label ),
esc_html( number_format_i18n( $value ) ),
esc_html( $pct )
);
$i++;
}
$html .= '</div>';
return $html;
}
public static function area_chart( array $series, $width = 640, $height = 160 ) {
$count = count( $series );
if ( $count < 2 ) {
return '';
}
$values = wp_list_pluck( $series, 'value' );
$max = max( 1, max( $values ) );
$pad_x = 8;
$pad_y = 10;
$plot_w = $width - ( $pad_x * 2 );
$plot_h = $height - ( $pad_y * 2 );
$step = $plot_w / ( $count - 1 );
$points = array();
foreach ( array_values( $values ) as $i => $value ) {
$x = $pad_x + ( $i * $step );
$y = $pad_y + $plot_h - ( ( $value / $max ) * $plot_h );
$points[] = array( round( $x, 2 ), round( $y, 2 ) );
}
$line_path = 'M ' . implode( ' L ', array_map( function ( $p ) {
return $p[0] . ' ' . $p[1];
}, $points ) );
$fill_path = $line_path
. sprintf( ' L %s %s', round( $pad_x + $plot_w, 2 ), round( $pad_y + $plot_h, 2 ) )
. sprintf( ' L %s %s Z', $pad_x, round( $pad_y + $plot_h, 2 ) );
$last = end( $points );
return sprintf(
'<svg viewBox="0 0 %1$d %2$d" class="argus-wpd-area-svg" role="img" aria-label="%3$s" preserveAspectRatio="none">'
. '<defs><linearGradient id="argusWpdAreaFill" x1="0" y1="0" x2="0" y2="1">'
. '<stop offset="0%%" stop-color="var(--cyan)" stop-opacity="0.35"></stop>'
. '<stop offset="100%%" stop-color="var(--cyan)" stop-opacity="0"></stop>'
. '</linearGradient></defs>'
. '<path d="%4$s" fill="url(#argusWpdAreaFill)" stroke="none"></path>'
. '<path d="%5$s" fill="none" stroke="var(--cyan)" stroke-width="2" stroke-linejoin="round" stroke-linecap="round"></path>'
. '<circle cx="%6$s" cy="%7$s" r="3.5" fill="var(--cyan)"></circle>'
. '</svg>',
$width,
$height,
esc_attr__( 'Blocked requests over time', 'argus-wordpress-defence' ),
esc_attr( $fill_path ),
esc_attr( $line_path ),
esc_attr( $last[0] ),
esc_attr( $last[1] )
);
}
}