fontdelbosc-transit/includes/class-fontdelbosc-transit-widget.php
2026-10-12 15:30:04 +00:00

205 lines
6.9 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Sidebar widget: compact incidents or ZBE summary.
*
* @package Fontdelbosc_Transit
*/
defined( 'ABSPATH' ) || exit;
/**
* Transit widget.
*/
class Fontdelbosc_Transit_Widget extends WP_Widget {
/**
* Constructor.
*/
public function __construct() {
parent::__construct(
'fontdelbosc_transit',
__( 'Font del Bosc — Trànsit', 'fontdelbosc-transit' ),
array(
'classname' => 'fdbt-widget',
'description' => __( 'C-15 incidents or a Low Emission Zones summary.', 'fontdelbosc-transit' ),
)
);
}
/**
* Render the widget.
*
* @param array<string, mixed> $args Sidebar arguments.
* @param array<string, mixed> $instance Widget settings.
*/
public function widget( $args, $instance ): void {
$title = Fontdelbosc_Transit_Payload::str( apply_filters( 'widget_title', Fontdelbosc_Transit_Payload::str( Fontdelbosc_Transit_Payload::get( $instance, 'title' ) ) ?? '' ) ) ?? '';
$view = Fontdelbosc_Transit_Payload::str( Fontdelbosc_Transit_Payload::get( $instance, 'view' ) ) ?? 'c15';
$before_widget = Fontdelbosc_Transit_Payload::str( Fontdelbosc_Transit_Payload::get( $args, 'before_widget' ) ) ?? '';
$after_widget = Fontdelbosc_Transit_Payload::str( Fontdelbosc_Transit_Payload::get( $args, 'after_widget' ) ) ?? '';
$before_title = Fontdelbosc_Transit_Payload::str( Fontdelbosc_Transit_Payload::get( $args, 'before_title' ) ) ?? '';
$after_title = Fontdelbosc_Transit_Payload::str( Fontdelbosc_Transit_Payload::get( $args, 'after_title' ) ) ?? '';
echo wp_kses_post( $before_widget );
if ( '' !== $title ) {
echo wp_kses_post( $before_title . esc_html( $title ) . $after_title );
}
if ( 'zbe' === $view ) {
$this->render_zbe_summary();
} else {
$this->render_incidents();
}
echo wp_kses_post( $after_widget );
}
/**
* Render the compact C-15 incident list.
*/
private function render_incidents(): void {
$data = Fontdelbosc_Transit_Data_Manager::get_incidents();
if ( null === $data ) {
echo '<p class="fdbt-widget__empty">' . esc_html__( 'Data unavailable.', 'fontdelbosc-transit' ) . '</p>';
return;
}
$incidents = array_filter(
$data['incidents'],
static fn( array $incident ): bool => Fontdelbosc_Transit_Maps::is_c15( $incident )
);
$incidents = array_slice( array_values( $incidents ), 0, 5 );
if ( array() === $incidents ) {
echo '<p class="fdbt-widget__empty">' . esc_html__( 'No incidents on C-15.', 'fontdelbosc-transit' ) . '</p>';
return;
}
echo '<ul class="fdbt-widget__list">';
foreach ( $incidents as $incident ) {
$type_key = Fontdelbosc_Transit_Maps::type_key( Fontdelbosc_Transit_Payload::str( $incident['type'] ?? null ) ?? '' );
echo '<li class="fdbt-widget__item">';
echo '<span class="fdbt-badge fdbt-badge--' . esc_attr( $type_key ) . '">' . esc_html( Fontdelbosc_Transit_Maps::type_label( Fontdelbosc_Transit_Payload::str( $incident['type'] ?? null ) ?? '' ) ) . '</span>';
echo '<span class="fdbt-widget__text">' . esc_html( $this->incident_summary( $incident ) ) . '</span>';
echo '</li>';
}
echo '</ul>';
}
/**
* Build the one-line summary of an incident for the widget.
*
* @param array<mixed> $incident Normalized incident.
* @return string
*/
private function incident_summary( array $incident ): string {
$parts = array();
$km = Fontdelbosc_Transit_Payload::str( $incident['km'] ?? null );
if ( null !== $km && '' !== $km ) {
$parts[] = sprintf(
/* translators: %s: kilometre point. */
__( 'km %s', 'fontdelbosc-transit' ),
$km
);
}
$town = Fontdelbosc_Transit_Payload::str( $incident['town'] ?? null );
if ( null !== $town && '' !== $town ) {
$parts[] = $town;
}
$title = Fontdelbosc_Transit_Payload::str( $incident['title'] ?? null );
if ( null !== $title && '' !== $title ) {
$parts[] = $title;
}
if ( array() === $parts ) {
return Fontdelbosc_Transit_Payload::str( $incident['road_name'] ?? null ) ?? '';
}
return implode( ' — ', $parts );
}
/**
* Render the compact ZBE summary.
*/
private function render_zbe_summary(): void {
$zones = Fontdelbosc_Transit_Data_Manager::get_zbes();
if ( array() === $zones ) {
echo '<p class="fdbt-widget__empty">' . esc_html__( 'Data unavailable.', 'fontdelbosc-transit' ) . '</p>';
return;
}
echo '<ul class="fdbt-widget__list">';
foreach ( $zones as $zone ) {
echo '<li class="fdbt-widget__item"><strong>' . esc_html( Fontdelbosc_Transit_Payload::str( $zone['name'] ?? null ) ?? '' ) . '</strong>';
$periods = Fontdelbosc_Transit_Payload::arr( $zone['periods'] ?? null );
$first = $periods[0] ?? null;
if ( is_array( $first ) ) {
$start = Fontdelbosc_Transit_Payload::str( $first['start'] ?? null ) ?? '';
$end = Fontdelbosc_Transit_Payload::str( $first['end'] ?? null ) ?? '';
$label = $start . '–' . $end;
if ( '' !== $start && '' !== $end ) {
echo '<span class="fdbt-widget__text"> ' . esc_html( $label ) . '</span>';
}
}
echo '</li>';
}
echo '</ul>';
}
/**
* Widget settings form.
*
* @param array<string, mixed> $instance Widget settings.
*/
public function form( $instance ): ?string {
$title = Fontdelbosc_Transit_Payload::str( Fontdelbosc_Transit_Payload::get( $instance, 'title' ) ) ?? __( 'Traffic on C-15', 'fontdelbosc-transit' );
$view = Fontdelbosc_Transit_Payload::str( Fontdelbosc_Transit_Payload::get( $instance, 'view' ) ) ?? 'c15';
echo '<p>';
echo '<label for="' . esc_attr( $this->get_field_id( 'title' ) ) . '">' . esc_html__( 'Title:', 'fontdelbosc-transit' ) . ' </label>';
echo '<input class="widefat" id="' . esc_attr( $this->get_field_id( 'title' ) ) . '" name="' . esc_attr( $this->get_field_name( 'title' ) ) . '" type="text" value="' . esc_attr( $title ) . '" />';
echo '</p>';
echo '<p>';
echo '<label for="' . esc_attr( $this->get_field_id( 'view' ) ) . '">' . esc_html__( 'View:', 'fontdelbosc-transit' ) . ' </label>';
echo '<select class="widefat" id="' . esc_attr( $this->get_field_id( 'view' ) ) . '" name="' . esc_attr( $this->get_field_name( 'view' ) ) . '">';
echo '<option value="c15"' . selected( $view, 'c15', false ) . '>' . esc_html__( 'Traffic on C-15', 'fontdelbosc-transit' ) . '</option>';
echo '<option value="zbe"' . selected( $view, 'zbe', false ) . '>' . esc_html__( 'Low Emission Zones (ZBE)', 'fontdelbosc-transit' ) . '</option>';
echo '</select>';
echo '</p>';
return null;
}
/**
* Save widget settings.
*
* @param array<string, mixed> $new_instance New settings.
* @param array<string, mixed> $old_instance Old settings.
* @return array<string, mixed>
*/
public function update( $new_instance, $old_instance ): array {
$instance = $old_instance;
$instance['title'] = sanitize_text_field( Fontdelbosc_Transit_Payload::str( Fontdelbosc_Transit_Payload::get( $new_instance, 'title' ) ) ?? '' );
$instance['view'] = 'zbe' === Fontdelbosc_Transit_Payload::str( Fontdelbosc_Transit_Payload::get( $new_instance, 'view' ) ) ? 'zbe' : 'c15';
return $instance;
}
}