This commit is contained in:
Javier Casares 2026-10-12 15:30:04 +00:00
commit 1ef08bd731
27 changed files with 4854 additions and 0 deletions

View file

@ -0,0 +1,199 @@
<?php
/**
* Comarca resolution: maps incident towns to the comarques around Font del Bosc.
*
* @package Fontdelbosc_Transit
*/
defined( 'ABSPATH' ) || exit;
/**
* Town-to-comarca mapping for Alt Penedès, Anoia, Baix Llobregat and Garraf.
*/
class Fontdelbosc_Transit_Comarques {
/**
* Supported comarca keys and their labels.
*
* @var array<string, string>
*/
public const COMARQUES = array(
'altpenedes' => 'Alt Penedès',
'anoia' => 'Anoia',
'baixllobregat' => 'Baix Llobregat',
'garraf' => 'Garraf',
);
/**
* Normalized town name to comarca key.
*
* @var array<string, string>
*/
public const TOWN_COMARCA = array(
/* Alt Penedès */
'AVINYONETDELPENEDES' => 'altpenedes',
'LESCABANES' => 'altpenedes',
'CASTELLVIDELAMARCA' => 'altpenedes',
'FONTRUBI' => 'altpenedes',
'GELIDA' => 'altpenedes',
'LAGRANADA' => 'altpenedes',
'MEDIONA' => 'altpenedes',
'OLERDOLA' => 'altpenedes',
'OLESADEBONESVALLS' => 'altpenedes',
'PACSDELPENEDES' => 'altpenedes',
'PLADELPENEDES' => 'altpenedes',
'PONTONS' => 'altpenedes',
'PUIGDALBER' => 'altpenedes',
'SANTCUGATSESGARRIGUES' => 'altpenedes',
'SANTLLORENCDHORTONS' => 'altpenedes',
'SANTMARTISARROCA' => 'altpenedes',
'SANTPEREDERIUDEBITLLES' => 'altpenedes',
'SANTQUINTIDEMEDIONA' => 'altpenedes',
'SANTAFEDELPENEDES' => 'altpenedes',
'SANTSADURNIDANOIA' => 'altpenedes',
'SANTAMARGARIDAILSMONJOS' => 'altpenedes',
'SANTAMARGARIDAIELSMONJOS' => 'altpenedes',
'SUBIRATS' => 'altpenedes',
'TORRELAVIT' => 'altpenedes',
'TORRELLESDEFOIX' => 'altpenedes',
'VILAFRANCADELPENEDES' => 'altpenedes',
'VILOVIDELPENEDES' => 'altpenedes',
/* Anoia */
'IGUALADA' => 'anoia',
'ODENA' => 'anoia',
'VILANOVADELCAMI' => 'anoia',
'SANTAMARGARIDADEMONTBUI' => 'anoia',
'POBLADECLARAMUNT' => 'anoia',
'JORBA' => 'anoia',
'PIERA' => 'anoia',
'CABRERADANOIA' => 'anoia',
'CAPELLADES' => 'anoia',
'CARME' => 'anoia',
'BRUC' => 'anoia',
'CASTELLFOLLITDERIUBREGOS' => 'anoia',
'CASTELLOLI' => 'anoia',
'COPONS' => 'anoia',
'ESTARAS' => 'anoia',
'RUBIO' => 'anoia',
'SANTMARTISESGUEIOLES' => 'anoia',
'SANTPERESALLAVINERA' => 'anoia',
'PUJALT' => 'anoia',
'PRATSDEREI' => 'anoia',
'VECIANA' => 'anoia',
'MONTMANEU' => 'anoia',
'ARGENSOLA' => 'anoia',
'BELLPRAT' => 'anoia',
/* Baix Llobregat */
'CORNELLADELLOBREGAT' => 'baixllobregat',
'SANTBOIDELLOBREGAT' => 'baixllobregat',
'SANTFEIUDELLOBREGAT' => 'baixllobregat',
'SANTJUSTDESVERN' => 'baixllobregat',
'ESPLUGUESDELLOBREGAT' => 'baixllobregat',
'SANTJOANDESPI' => 'baixllobregat',
'SANTVICENSDELSHORTS' => 'baixllobregat',
'SANTACOLOMADECERVELLO' => 'baixllobregat',
'SANTCLIMENTDELLOBREGAT' => 'baixllobregat',
'TORRELLESDELLOBREGAT' => 'baixllobregat',
'VILADECANS' => 'baixllobregat',
'PRATDELLOBREGAT' => 'baixllobregat',
'HOSPITALETDELLOBREGAT' => 'baixllobregat',
'CERVELLO' => 'baixllobregat',
'CORBERADELLOBREGAT' => 'baixllobregat',
'PALMADECERVELLO' => 'baixllobregat',
'PALLEJA' => 'baixllobregat',
'PAPIOL' => 'baixllobregat',
'MOLINSDEREI' => 'baixllobregat',
'SANTANDREUDELABARCA' => 'baixllobregat',
'CASTELLDEFELS' => 'baixllobregat',
'GAVA' => 'baixllobregat',
'BEGUES' => 'baixllobregat',
'ABRERA' => 'baixllobregat',
'MARTORELL' => 'baixllobregat',
'SANTESTEVESESROVIRES' => 'baixllobregat',
'CASTELLVIDEROSANES' => 'baixllobregat',
'COLLBATO' => 'baixllobregat',
'ESPARREGUERA' => 'baixllobregat',
'OLESADEMONTSERRAT' => 'baixllobregat',
'VALLIRANA' => 'baixllobregat',
/* Garraf */
'VILANOVAILAGELTRU' => 'garraf',
'SITGES' => 'garraf',
'CUBELLES' => 'garraf',
'CANYELLES' => 'garraf',
'SANTPEREDERIBES' => 'garraf',
'OLIVELLA' => 'garraf',
'GARRAF' => 'garraf',
);
/**
* Resolve the comarca key of an incident from its town.
*
* @param array<mixed> $incident Normalized incident.
* @return string Comarca key, or '' when unknown.
*/
public static function comarca_of( array $incident ): string {
$town = Fontdelbosc_Transit_Payload::str( $incident['town'] ?? null ) ?? '';
if ( '' === $town ) {
return '';
}
return self::TOWN_COMARCA[ self::normalize_town( $town ) ] ?? '';
}
/**
* Normalize a town name for lookup: uppercase, unaccented, letters only.
*
* @param string $town Raw town name.
* @return string
*/
public static function normalize_town( string $town ): string {
$ascii = iconv( 'UTF-8', 'ASCII//TRANSLIT', $town );
if ( false === $ascii ) {
$ascii = $town;
}
return preg_replace( '/[^A-Z]/', '', strtoupper( $ascii ) ) ?? '';
}
/**
* Parse a comma-separated comarca attribute into valid, unique keys.
*
* @param string $attr Raw attribute value, e.g. "anoia, garraf".
* @return array<int, string>
*/
public static function keys_from_attr( string $attr ): array {
$keys = array();
foreach ( explode( ',', $attr ) as $part ) {
$key = sanitize_key( trim( $part ) );
if ( '' !== $key && self::is_valid( $key ) && ! in_array( $key, $keys, true ) ) {
$keys[] = $key;
}
}
return $keys;
}
/**
* Whether a comarca key is supported.
*
* @param string $key Comarca key.
* @return bool
*/
public static function is_valid( string $key ): bool {
return isset( self::COMARQUES[ $key ] );
}
/**
* Label of a comarca key.
*
* @param string $key Comarca key.
* @return string
*/
public static function label( string $key ): string {
return self::COMARQUES[ $key ] ?? '';
}
}