if($usedYear){$mode='used-ranking-year';}
?php
declare(strict_types=1);
// Dynamic HTML must be revalidated so deploys do not leave stale pages in browsers/proxies.
header('Cache-Control: no-cache, max-age=0, must-revalidate');
header('X-GB-Version: 7.8.8');
require __DIR__.'/_bootstrap.php';
require APP_ROOT.'/app/PageRepository.php';
require APP_ROOT.'/app/Router.php';
require APP_ROOT.'/app/PriceRepository.php';
require APP_ROOT.'/app/AdService.php';
require APP_ROOT.'/app/AnalyticsService.php';
require APP_ROOT.'/app/VehicleRepository.php';
require APP_ROOT.'/app/EvRepository.php';
require APP_ROOT.'/app/VehicleCatalogRepository.php';
require APP_ROOT.'/app/RegistrationRepository.php';
require APP_ROOT.'/app/VehicleInsightsRepository.php';
require APP_ROOT.'/app/FiscalRepository.php';
$pages=new PageRepository(gb_cms_db());
$prices=new PriceRepository(gb_prices_db());
$locations=new LocationIndex();
$vehicles=new VehicleRepository(gb_vehicles_db());
$vehicleReady=$vehicles->ready();
$ev=new EvRepository(gb_vehicles_db());
$evReady=$ev->ready();
$vehicleCatalog=new VehicleCatalogRepository(gb_vehicles_db());
$vehicleCatalogReady=$vehicleCatalog->ready();
$registrations=new RegistrationRepository(gb_vehicles_db());
$registrationsReady=$registrations->ready();
$insights=new VehicleInsightsRepository(gb_vehicles_db());
$insightsReady=$insights->ready();
$fiscal=new FiscalRepository(gb_vehicles_db());
$fiscalReady=$fiscal->ready();
$path=gb_request_path();
// Atajos humanos: evitan 404 si alguien omite /vehiculos/ en verticales muy buscadas.
$shortcutRedirects=[
'/matriculaciones/'=>'/vehiculos/matriculaciones/',
'/coches-mas-vendidos/'=>'/vehiculos/coches-mas-vendidos/',
'/marcas-mas-vendidas/'=>'/vehiculos/marcas-mas-vendidas/',
'/coches-electricos/'=>'/vehiculos/coches-electricos/',
'/coches-electricos-mas-vendidos/'=>'/vehiculos/coches-electricos-mas-vendidos/',
'/parque-automovilistico/'=>'/vehiculos/parque-automovilistico/',
'/coches-mas-comunes/'=>'/vehiculos/coches-mas-comunes/'
];
if(isset($shortcutRedirects[$path])){header('Location: '.gb_url($shortcutRedirects[$path]),true,301);exit;}
// Alias histórico/semántico: conservamos "electrolineras" como variante,
// pero la URL canónica prioriza la intención con más demanda: "puntos de recarga".
if($path==='/electrolineras' || str_starts_with($path,'/electrolineras/')){
$newPath=preg_replace('~^/electrolineras(?=/|$)~','/puntos-de-recarga',$path);
header('Location: '.gb_url($newPath?:'/puntos-de-recarga/'),true,301);
exit;
}
// Aliases SEO: concentramos intenciones equivalentes en una sola URL canónica.
$seoAliases=[
'/vehiculos/calculadora-valor-venal-coche/'=>'/vehiculos/valor-venal/',
'/vehiculos/valor-fiscal-coche/'=>'/vehiculos/valor-venal/',
'/vehiculos/tablas-hacienda-valor-coche/'=>'/vehiculos/valor-venal/',
'/vehiculos/cambio-titularidad-coche/'=>'/vehiculos/transferencia-coche/',
'/vehiculos/precio-transferencia-coche/'=>'/vehiculos/transferencia-coche/',
];
if(isset($seoAliases[$path])){
header('Location: '.gb_url($seoAliases[$path]),true,301);
exit;
}
function eur(mixed $n,int $dec=3):string{$x=(float)$n;return$x>0?number_format($x,$dec,',','.').' €':'—';}
function saving50(mixed $avg,mixed $price):float{$a=(float)$avg;$p=(float)$price;return($a>0&&$p>0)?($a-$p)*50:0.0;}
function fmt_date(?string $d):string{if(!$d)return'Dato sin fecha';$t=strtotime($d);return$t?date('d/m/Y H:i',$t):$d;}
function json_response(mixed $x):never{header('Content-Type: application/json; charset=utf-8');echo json_encode($x,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);exit;}
function station_url(array $s):string{return gb_url('/estacion/'.(int)$s['eess_id'].'/');}
function province_slug(LocationIndex $locations,string $province,int $community):string{$u=$locations->provinceUrl($province,$community);$p=array_values(array_filter(explode('/',trim($u,'/'))));return end($p)?:Geo::slug($province);}
function feature_url(array $scope,LocationIndex $locations,?array $community=null,?array $province=null,?array $municipality=null):string{
$prefix=match($scope['feature_kind']??null){'24h'=>'/gasolineras-24-horas/','low_cost'=>'/gasolineras-low-cost/','brand'=>'/gasolineras-'.Geo::slug((string)$scope['brand']).'/', 'fuel'=>match($scope['fuel']){'gas_licuado_petroleo'=>'/gasolineras-glp-autogas/','gn_comprimido'=>'/gasolineras-gas-natural/','biodiesel'=>'/gasolineras-biodiesel/','precio_bioetanol'=>'/gasolineras-bioetanol/',default=>'/'},default=>'/'};
if($municipality&&$province){return $prefix.province_slug($locations,(string)$province['provincia'],(int)$province['comunidad']).'/'.Geo::slug((string)$municipality['municipio']).'/';}
if($province){return $prefix.province_slug($locations,(string)$province['provincia'],(int)$province['comunidad']).'/';}
if($community){return $prefix.$community['slug'].'/';}
return $prefix;
}
function editorial_html(string $html):string{
$html=str_replace(['https://gasolinabarata.info','http://gasolinabarata.info'],rtrim((string)gb_config('base_url'),'/'),$html);
return preg_replace_callback('~]*href=["\']https://www\.circuloconductores\.es/[^"\']*idaso=35730[^"\']*["\'][^>]*)>~i',function($m){$a=$m[1];if(preg_match('~\brel=["\']([^"\']*)["\']~i',$a,$r)){$rels=preg_split('/\s+/',trim($r[1]))?:[];foreach(['sponsored','nofollow','noopener','noreferrer'] as $x)if(!in_array($x,$rels,true))$rels[]=$x;$a=preg_replace('~\brel=["\'][^"\']*["\']~i','rel="'.implode(' ',$rels).'"',$a,1);}else{$a.=' rel="sponsored nofollow noopener noreferrer"';}return'';},$html)??$html;
}
function rank_message(array $r):string{
$label=$r['label'];$cheap=(int)$r['cheap_rank'];$exp=(int)$r['expensive_rank'];$cp=(float)$r['cheap_pct'];$ep=(float)$r['expensive_pct'];
if($cheap<=25)return"Top $cheap más barata de $label";
if($cheap<=100)return"Entre las 100 más baratas de $label";
if($cp<=25)return'Entre el '.(int)ceil($cp)."% más barato de $label";
if($exp<=25)return"Top $exp más cara de $label";
if($exp<=100)return"Entre las 100 más caras de $label";
if($ep<=25)return'Entre el '.(int)ceil($ep)."% más caro de $label";
return"Precio intermedio en $label";
}
function fuel_options(string $selected='gasolina_95'):string{$o='';foreach(PriceRepository::FUELS as $k=>$m)$o.='';return$o;}
function gb_registration_table(array $rows): string{
if(!$rows)return '
';
}
function gb_period_human(string $period): string{
if(!preg_match('/^(20\d{2})-(0[1-9]|1[0-2])$/',$period,$m))return $period;
$months=[1=>'enero',2=>'febrero',3=>'marzo',4=>'abril',5=>'mayo',6=>'junio',7=>'julio',8=>'agosto',9=>'septiembre',10=>'octubre',11=>'noviembre',12=>'diciembre'];
return ($months[(int)$m[2]]??$m[2]).' de '.$m[1];
}
function gb_province_name(string $code): string{
$c=str_pad(trim($code),2,'0',STR_PAD_LEFT);
$m=['01'=>'Álava','02'=>'Albacete','03'=>'Alicante','04'=>'Almería','05'=>'Ávila','06'=>'Badajoz','07'=>'Illes Balears','08'=>'Barcelona','09'=>'Burgos','10'=>'Cáceres','11'=>'Cádiz','12'=>'Castellón','13'=>'Ciudad Real','14'=>'Córdoba','15'=>'A Coruña','16'=>'Cuenca','17'=>'Girona','18'=>'Granada','19'=>'Guadalajara','20'=>'Gipuzkoa','21'=>'Huelva','22'=>'Huesca','23'=>'Jaén','24'=>'León','25'=>'Lleida','26'=>'La Rioja','27'=>'Lugo','28'=>'Madrid','29'=>'Málaga','30'=>'Murcia','31'=>'Navarra','32'=>'Ourense','33'=>'Asturias','34'=>'Palencia','35'=>'Las Palmas','36'=>'Pontevedra','37'=>'Salamanca','38'=>'Santa Cruz de Tenerife','39'=>'Cantabria','40'=>'Segovia','41'=>'Sevilla','42'=>'Soria','43'=>'Tarragona','44'=>'Teruel','45'=>'Toledo','46'=>'Valencia','47'=>'Valladolid','48'=>'Bizkaia','49'=>'Zamora','50'=>'Zaragoza','51'=>'Ceuta','52'=>'Melilla'];
return $m[$c]??($code!==''?$code:'Sin provincia');
}
function gb_related_vehicle_cluster(string $active): string{
$items=[
'registrations'=>['/vehiculos/matriculaciones/','Matriculaciones','Evolución mensual y volumen registrado por la DGT.'],
'best-selling'=>['/vehiculos/coches-mas-vendidos/','Coches más vendidos','Ranking de modelos por matriculaciones.'],
'best-brands'=>['/vehiculos/marcas-mas-vendidas/','Marcas más vendidas','Ranking agregado por marca.'],
'electric-cars'=>['/vehiculos/coches-electricos/','Coches eléctricos','Parque eléctrico y distribución territorial.'],
'electric-best-selling'=>['/vehiculos/coches-electricos-mas-vendidos/','Eléctricos más vendidos','Ranking de matriculaciones eléctricas.'],
'park'=>['/vehiculos/parque-automovilistico/','Parque automovilístico','Edad, propulsión, etiquetas y territorio.'],
'common-cars'=>['/vehiculos/coches-mas-comunes/','Coches más comunes','Modelos con más unidades en el parque.'],
'badges'=>['/vehiculos/etiqueta-ambiental/','Distintivo ambiental','Etiquetas B, C, ECO, 0 y vehículos sin distintivo.'],
'used-market'=>['/vehiculos/segunda-mano/','Coches de segunda mano','Transferencias registradas por la DGT.'],
];
$h='';
}
function gb_bar_chart(array $rows,string $labelKey,string $valueKey,string $title,int $limit=12): string{
$rows=array_slice($rows,0,$limit); if(!$rows)return '';
$max=max(array_map(static fn($r)=>(int)($r[$valueKey]??0),$rows)?:[1]);
$h='
Gráfico interactivo
'.gb_h($title).'
GasolinaBarata.info
';
foreach($rows as $r){$v=(int)($r[$valueKey]??0);$pct=$max?max(2,$v/$max*100):0;$h.='
'.(count($rows)>$initial?'':'').'';
return $h;
}
// ---------------- APIs ----------------
$router=new Router($pages);[$page,$legacyContext]=$router->resolve($path);
$effectivePath=$path;
if(str_starts_with($path,'/mapa-comunidades/')&&$path!=='/mapa-comunidades/'){$effectivePath='/'.substr(trim($path,'/'),strlen('mapa-comunidades/')).'/';}
$scope=$prices->scopeFrom($effectivePath,$legacyContext);
if(str_starts_with($path,'/api/')){
if($path==='/api/search/'){$q=trim((string)($_GET['q']??''));$out=[];if(mb_strlen($q)>=2)foreach($prices->searchLocations($q,24) as $r){if($r['type']==='province')$out[]=['label'=>PriceRepository::pretty((string)$r['provincia']),'meta'=>'Provincia · '.number_format((int)$r['n'],0,',','.').' estaciones','type'=>'province','url'=>$locations->provinceUrl((string)$r['provincia'],(int)$r['comunidad'])];else$out[]=['label'=>PriceRepository::pretty((string)$r['municipio']),'meta'=>'Municipio · '.PriceRepository::pretty((string)$r['provincia']).' · '.number_format((int)$r['n'],0,',','.').' estaciones','type'=>'municipality','url'=>$locations->municipalityUrl((string)$r['municipio'],(string)$r['provincia'],(int)$r['comunidad'])];}json_response($out);}
if($path==='/api/brands/'){
$fuel=(string)($_GET['fuel']??'gasolina_95');$rows=$prices->brandStats($fuel);
foreach($rows as &$r)$r['url']='/'.trim((string)$r['slug'],'/').'/';unset($r);json_response($rows);
}
if($path==='/api/history/')json_response($prices->nationalHistory((string)($_GET['fuel']??'gasolina_95'),(int)($_GET['days']??365)));
if($path==='/api/station-history/')json_response($prices->stationHistory((int)($_GET['id']??0),(string)($_GET['fuel']??'gasolina_95'),(int)($_GET['days']??365)));
if($path==='/api/map/'){
$p=(string)($_GET['path']??'/');$lp=[];$s=$prices->scopeFrom($p,$lp);if(!empty($_GET['h24'])){$s['where'][]="(UPPER(horario) LIKE '%24H%' OR UPPER(horario) LIKE '%24 H%' OR UPPER(horario) LIKE '%00:00-24:00%')";}if(!empty($_GET['low'])){$low=$prices->scopeFrom('/gasolineras-low-cost/',[]);$s['where']=array_merge($s['where'],$low['where']);$s['types'].=$low['types'];$s['params']=array_merge($s['params'],$low['params']);}
if(!empty($_GET['brand']))$s=$prices->brandMapScope((string)$_GET['brand']);json_response($prices->mapPayload($s,(string)($_GET['fuel']??'gasolina_95')));
}
if($path==='/api/nearby/')json_response($prices->nearbyStations((float)($_GET['lat']??0),(float)($_GET['lng']??0),(float)($_GET['radius']??10),(string)($_GET['fuel']??'gasolina_95'),150,['24h'=>!empty($_GET['h24']),'low_cost'=>!empty($_GET['low'])]));
if($path==='/api/vehiculos/ranking-buscar/'){
$kind=(string)($_GET['kind']??'');$year=(int)($_GET['year']??0);$q=trim((string)($_GET['q']??''));$rows=[];
if($kind==='brands')$raw=$registrations->searchBrandsForYear($year,$q,100);
elseif($kind==='electric-models')$raw=$registrations->searchModelsForYear($year,$q,'Eléctrico',100);
else $raw=$registrations->searchModelsForYear($year,$q,null,100);
foreach($raw as $r){
if($kind==='brands')$rows[]=['label'=>(string)$r['marca'],'numero'=>(int)$r['numero'],'url'=>gb_url('/vehiculos/'.$r['slug'].'/')];
else $rows[]=['label'=>trim((string)$r['marca'].' '.(string)$r['modelo']),'numero'=>(int)$r['numero'],'url'=>gb_url('/vehiculos/'.$r['marca_slug'].'/'.$r['modelo_slug'].'/')];
}
json_response(['ok'=>true,'rows'=>$rows]);
}
if($path==='/api/vehiculos/year-winner/'){
$kind=(string)($_GET['kind']??'models');$year=(int)($_GET['year']??0);
if($year<2014||$year>(int)date('Y')+1)json_response(['ok'=>false,'error'=>'Año no válido']);
$key='reg-winner-'.$kind.'-'.$year.'-v785';
$row=gb_cache_remember($key,86400,function()use($registrations,$kind,$year){
if($kind==='brands')return $registrations->brandWinnerForYear($year);
if($kind==='electric')return $registrations->winnerForYear($year,'Eléctrico');
return $registrations->winnerForYear($year,null);
});
if(!$row)json_response(['ok'=>true,'row'=>null]);
if($kind==='brands')json_response(['ok'=>true,'row'=>['anio'=>(string)$year,'label'=>(string)$row['marca'],'numero'=>(int)$row['numero'],'url'=>gb_url('/vehiculos/'.(string)$row['slug'].'/')]]);
json_response(['ok'=>true,'row'=>['anio'=>(string)$year,'label'=>trim((string)$row['marca'].' '.(string)$row['modelo']),'numero'=>(int)$row['numero'],'url'=>gb_url('/vehiculos/'.(string)$row['marca_slug'].'/'.(string)$row['modelo_slug'].'/')]]);
}
if($path==='/api/vehiculos/mercado-usado/'){
$year=(int)($_GET['year']??0);$year=$year>=2014&&$year<=(int)date('Y')+1?$year:0;
$key='used-market-api-'.($year?:'12m').'-v788';
$payload=gb_cache_remember($key,86400,function()use($insights,$year){
return ['top'=>$insights->topTransferredModels($year?:null,80),'ages'=>$insights->transferAgeBands($year?:null)];
});
json_response(['ok'=>true,'year'=>$year?:null]+$payload);
}
if($path==='/api/vehiculos/valor-fiscal-buscar/'){
$q=trim((string)($_GET['q']??''));
json_response(['ok'=>true,'rows'=>mb_strlen($q)>=2?$fiscal->search($q,40):[]]);
}
if($path==='/api/vehiculos/usados-year-winner/'){
$year=(int)($_GET['year']??0);if($year<2014||$year>(int)date('Y')+1)json_response(['ok'=>false,'error'=>'Año no válido']);
$key='used-winner-'.$year.'-v789';
$row=gb_cache_remember($key,86400,fn()=>$insights->topTransferredModels($year,1)[0]??null);
json_response(['ok'=>true,'row'=>$row?['label'=>trim((string)$row['marca'].' '.(string)$row['modelo']),'numero'=>(int)$row['numero'],'url'=>gb_url('/vehiculos/'.(string)$row['marca_slug'].'/'.(string)$row['modelo_slug'].'/')]:null]);
}
if($path==='/api/vehiculos/usados-ranking/'){
$year=(int)($_GET['year']??0);if($year<2014||$year>(int)date('Y')+1)json_response(['ok'=>false,'error'=>'Año no válido']);
$key='used-ranking-'.$year.'-v789';
$rows=gb_cache_remember($key,86400,fn()=>$insights->topTransferredModels($year,80));
json_response(['ok'=>true,'year'=>$year,'rows'=>$rows]);
}
if($path==='/api/vehiculos/longevidad/'){
$months=(int)($_GET['months']??12);if(!in_array($months,[12,36,60],true))$months=12;
$key='longevity-api-'.$months.'m-v789';
$rows=gb_cache_remember($key,86400,fn()=>$insights->longestLivedModels(120,$months===12?30:100,$months));
json_response(['ok'=>true,'months'=>$months,'rows'=>$rows]);
}
if($path==='/api/vehiculos/matricula/')json_response($vehicles->estimatePlate((string)($_GET['q']??'')));
if($path==='/api/vehiculos/serie-por-fecha/'){$period=trim((string)($_GET['period']??''));$row=$vehicles->seriesForPeriod($period);json_response($row?['ok'=>true,'period'=>$period,'period_label'=>$vehicles->periodLabel($period),'ultima_serie'=>$row['ultima_serie'],'matriculaciones'=>(int)$row['matriculaciones']]:['ok'=>false,'error'=>'No tenemos datos para ese mes.']);}
if($path==='/api/electrolineras/buscar/')json_response(['ok'=>true,'rows'=>$ev->search(trim((string)($_GET['q']??'')),24)]);
if($path==='/api/electrolineras/mapa/')json_response(['ok'=>true,'rows'=>$ev->mapInstallations(15000)]);
if($path==='/api/electrolineras/cerca/'){$lat=(float)($_GET['lat']??0);$lng=(float)($_GET['lng']??0);$radius=(float)($_GET['radius']??25);$minKw=isset($_GET['min_kw'])&&$_GET['min_kw']!==''?(float)$_GET['min_kw']:null;json_response(['ok'=>true,'rows'=>$ev->nearby($lat,$lng,$radius,150,$minKw)]);}
json_response(['error'=>'not_found']);
}
// ---------------- Page resolution ----------------
$station=null;
if(preg_match('~^/estacion/(\d+)/$~',$path,$m)){$station=$prices->station((int)$m[1]);if(!$station)http_response_code(404);}
$specialRoot=in_array($path,['/gasolina-mas-barata-hoy/','/gasolineras-low-cost/','/mapa-comunidades/'],true);
if(!$page&&($specialRoot||$scope['geo_kind']!=='spain'||$scope['feature_kind']))$page=['ID'=>0,'post_type'=>'Página','post_title'=>'Gasolina Barata','meta_title'=>'','meta_description'=>'','post_url'=>$path,'post_image'=>'','post_index'=>1,'post_follow'=>1,'post_content'=>''];
if($station)$page=['ID'=>0,'post_type'=>'Página','post_title'=>($station['rotulo']?:'Gasolinera'),'meta_title'=>'','meta_description'=>'','post_url'=>$path,'post_image'=>'','post_index'=>1,'post_follow'=>1,'post_content'=>''];
$matriculaPaths=['/matriculas/','/matriculas/ultima-matricula/','/matriculas/fecha-matriculacion/','/matriculas/por-anos/','/matriculas/matricula-por-fecha/'];
$evPaths=['/puntos-de-recarga/','/puntos-de-recarga/mapa/','/puntos-de-recarga/cerca-de-mi/','/puntos-de-recarga/carga-rapida/','/puntos-de-recarga/carga-ultrarrapida/','/puntos-de-recarga/operadores/'];
$evRoute=null;
if(preg_match('~^/puntos-de-recarga/operadores/([^/]+)/?$~',$path,$em)){
$operator=$ev->operatorBySlug($em[1]);
if($operator)$evRoute=['kind'=>'operator','operator'=>$operator];
}
if(!$evRoute && preg_match('~^/puntos-de-recarga/([^/]+)/([^/]+)/?$~',$path,$em)){
$municipality=$ev->municipalityBySlugs($em[1],$em[2]);
if($municipality)$evRoute=['kind'=>'municipality','province_slug'=>$em[1],'municipality_slug'=>$em[2],'province'=>$municipality['provincia'],'municipality'=>$municipality['municipio']];
}
if(!$evRoute && preg_match('~^/puntos-de-recarga/([^/]+)/?$~',$path,$em) && !in_array($em[1],['mapa','cerca-de-mi','carga-rapida','carga-ultrarrapida','operadores'],true)){
$province=$ev->provinceBySlug($em[1]);
if($province){
$evRoute=['kind'=>'province','province_slug'=>$em[1],'province'=>$province['provincia']];
}else{
$community=$ev->communityBySlug($em[1]);
if($community)$evRoute=['kind'=>'community','community_slug'=>$em[1],'community'=>$community['comunidad']];
}
}
$usedYear=null;
if(preg_match('~^/vehiculos/coches-usados-mas-vendidos/(20\d{2})/?$~',$path,$um)){
$usedYear=(int)$um[1];
}
$vehiclePaths=['/vehiculos/','/vehiculos/marcas/','/vehiculos/matriculaciones/','/vehiculos/coches-mas-vendidos/','/vehiculos/marcas-mas-vendidas/','/vehiculos/coches-electricos/','/vehiculos/coches-electricos-mas-vendidos/','/vehiculos/valor-venal/','/vehiculos/itp-coche/','/vehiculos/transferencia-coche/','/vehiculos/contrato-compraventa-coche/','/vehiculos/etiqueta-ambiental/','/vehiculos/etiqueta-b/','/vehiculos/etiqueta-c/','/vehiculos/etiqueta-eco/','/vehiculos/etiqueta-0/','/vehiculos/sin-etiqueta/','/vehiculos/parque-automovilistico/','/vehiculos/coches-mas-comunes/','/vehiculos/segunda-mano/','/vehiculos/coches-usados-mas-vendidos/','/vehiculos/coches-que-mas-duran/','/vehiculos/coches-mas-robados/'];
$registrationYear=null;$registrationYearKind=null;
if(preg_match('~^/vehiculos/(coches-mas-vendidos|marcas-mas-vendidas|coches-electricos-mas-vendidos)/(20\d{2})/$~',$path,$rm)){
$registrationYear=(int)$rm[2];$registrationYearKind=(string)$rm[1];
}
$vehicleRoute=null;
if(preg_match('~^/vehiculos/([^/]+)/?$~',$path,$vm) && $vm[1]!=='marcas'){
$brand=$vehicleCatalog->brandBySlug($vm[1]);
if($brand)$vehicleRoute=['kind'=>'brand','brand'=>$brand];
}
if(preg_match('~^/vehiculos/([^/]+)/familia/([^/]+)/?$~',$path,$vm)){
$family=$vehicleCatalog->familyBySlugs($vm[1],$vm[2]);
if($family)$vehicleRoute=['kind'=>'family','family'=>$family,'brand'=>$family['brand']];
}
if(!$vehicleRoute && preg_match('~^/vehiculos/([^/]+)/([^/]+)/?$~',$path,$vm)){
$model=$vehicleCatalog->modelBySlugs($vm[1],$vm[2]);
if($model)$vehicleRoute=['kind'=>'model','model'=>$model,'brand'=>$model['brand']];
}
if(!$page&&in_array($path,$matriculaPaths,true))$page=['ID'=>0,'post_type'=>'Página','post_title'=>'Matrículas','meta_title'=>'','meta_description'=>'','post_url'=>$path,'post_image'=>'','post_index'=>1,'post_follow'=>1,'post_content'=>''];
if(!$page&&(in_array($path,$evPaths,true)||$evRoute))$page=['ID'=>0,'post_type'=>'Página','post_title'=>'Electrolineras','meta_title'=>'','meta_description'=>'','post_url'=>$path,'post_image'=>'','post_index'=>1,'post_follow'=>1,'post_content'=>''];
if(!$page&&(in_array($path,$vehiclePaths,true)||$vehicleRoute||$registrationYear))$page=['ID'=>0,'post_type'=>'Página','post_title'=>'Vehículos','meta_title'=>'','meta_description'=>'','post_url'=>$path,'post_image'=>'','post_index'=>1,'post_follow'=>1,'post_content'=>''];
$is404=false;
if(!$page){$is404=true;http_response_code(404);$page=['ID'=>0,'post_type'=>'Página','post_title'=>'Página no encontrada','meta_title'=>'Página no encontrada | Gasolina Barata','meta_description'=>'La página solicitada no existe.','post_url'=>$path,'post_image'=>'','post_index'=>0,'post_follow'=>1,'post_content'=>''];}
$isHome=$path==='/';$isPrices=$path==='/precio-gasolina/';$isSearch=$path==='/buscar/';$isMap=str_starts_with($path,'/mapa-comunidades/');$isBrands=$path==='/marcas-gasolineras/';$isSavings=$path==='/ahorrar-gasolina/';$isSavingsArticle=$path==='/como-ahorrar-gasolina/';$isCheapest=$path==='/gasolina-mas-barata-hoy/';$isMatriculas=in_array($path,$matriculaPaths,true);$isEv=in_array($path,$evPaths,true)||$evRoute!==null;$isVehicleCatalog=in_array($path,$vehiclePaths,true)||$vehicleRoute!==null||$registrationYear!==null;$isFeature=(bool)$scope['feature_kind'];$isTerritory=$scope['geo_kind']!=='spain'&&!$isFeature&&!$isMatriculas&&!$isEv&&!$isVehicleCatalog;$isEditorial=((string)($page['post_type']??'')==='Artículo')||$isSavingsArticle;
$matriculaMode=match($path){'/matriculas/'=>'matriculas','/matriculas/ultima-matricula/'=>'matricula-latest','/matriculas/fecha-matriculacion/'=>'matricula-date','/matriculas/por-anos/'=>'matricula-years','/matriculas/matricula-por-fecha/'=>'matricula-by-date',default=>null};
$evMode=match($path){'/puntos-de-recarga/'=>'electrolineras','/puntos-de-recarga/mapa/'=>'ev-map','/puntos-de-recarga/cerca-de-mi/'=>'ev-nearby','/puntos-de-recarga/carga-rapida/'=>'ev-fast','/puntos-de-recarga/carga-ultrarrapida/'=>'ev-ultrafast','/puntos-de-recarga/operadores/'=>'ev-operators',default=>(($evRoute['kind']??null)==='province'?'ev-province':((($evRoute['kind']??null)==='municipality')?'ev-municipality':((($evRoute['kind']??null)==='community'?'ev-community':((($evRoute['kind']??null)==='operator')?'ev-operator':null)))))};
$vehicleMode=match($path){
'/vehiculos/'=>'vehicles','/vehiculos/marcas/'=>'vehicle-brands','/vehiculos/matriculaciones/'=>'registrations','/vehiculos/coches-mas-vendidos/'=>'best-selling','/vehiculos/marcas-mas-vendidas/'=>'best-brands','/vehiculos/coches-electricos/'=>'electric-cars','/vehiculos/coches-electricos-mas-vendidos/'=>'electric-best-selling','/vehiculos/valor-venal/'=>'fiscal-value','/vehiculos/itp-coche/'=>'itp','/vehiculos/transferencia-coche/'=>'transfer-guide','/vehiculos/contrato-compraventa-coche/'=>'sale-contract','/vehiculos/etiqueta-ambiental/'=>'badges','/vehiculos/etiqueta-b/'=>'badge-b','/vehiculos/etiqueta-c/'=>'badge-c','/vehiculos/etiqueta-eco/'=>'badge-eco','/vehiculos/etiqueta-0/'=>'badge-zero','/vehiculos/sin-etiqueta/'=>'badge-none','/vehiculos/parque-automovilistico/'=>'park','/vehiculos/coches-mas-comunes/'=>'common-cars','/vehiculos/segunda-mano/'=>'used-market','/vehiculos/coches-usados-mas-vendidos/'=>'used-ranking','/vehiculos/coches-que-mas-duran/'=>'longevity','/vehiculos/coches-mas-robados/'=>'stolen-indicator',default=>($registrationYear?match($registrationYearKind){'marcas-mas-vendidas'=>'best-brands-year','coches-electricos-mas-vendidos'=>'electric-best-selling-year',default=>'best-selling-year'}:(($vehicleRoute['kind']??null)==='brand'?'vehicle-brand':((($vehicleRoute['kind']??null)==='family')?'vehicle-family':((($vehicleRoute['kind']??null)==='model')?'vehicle-model':null))))};
$mode=$is404?'notfound':($station?'station':($vehicleMode??($evMode??($matriculaMode??($isHome?'home':($isPrices?'prices':($isSearch?'search':($isMap?'map':($isBrands?'brands':($isSavings?'savings':($isCheapest?'cheapest':($isFeature?'feature':($isTerritory?'territory':($isEditorial?'editorial':'generic'))))))))))))));
$seo=Seo::copy($path,$page,$scope);$h1=$seo['h1'];$metaTitle=$seo['title'];$description=$seo['description'];
if($isVehicleCatalog){
if($vehicleMode==='vehicles'){
$h1='Coches y vehículos en España';
$metaTitle='Coches en España: marcas, modelos y datos DGT | GasolinaBarata';
$description='Consulta marcas y modelos de coches con datos del parque móvil, matriculaciones, antigüedad, transferencias y bajas a partir de fuentes oficiales DGT.';
}elseif($vehicleMode==='registrations'){
$metaTitle='Matriculaciones de coches en España: datos DGT por mes y año | GasolinaBarata';$h1='Matriculaciones de coches en España';$description='Consulta la evolución de las matriculaciones de vehículos en España con datos oficiales DGT, rankings por modelo y series históricas.';
}elseif($vehicleMode==='best-selling'){
$metaTitle='Coches más vendidos en España: ranking DGT | GasolinaBarata';$h1='Coches más vendidos en España';$description='Ranking de modelos con más matriculaciones registradas por la DGT. Consulta el último mes, el año actual y el histórico por años.';
}elseif(in_array($vehicleMode,['best-brands','best-brands-year'],true)){
$y=$vehicleMode==='best-brands-year'?(int)$registrationYear:null;
$metaTitle=$y?'Marcas de coches más matriculadas en España en '.$y.' | GasolinaBarata':'Marcas de coches más vendidas en España: ranking DGT | GasolinaBarata';
$h1=$y?'Marcas de coches más matriculadas en '.$y:'Marcas de coches más vendidas en España';
$description=$y?'Ranking de marcas por matriculaciones DGT en '.$y.'.':'Ranking anual de marcas por número de matriculaciones DGT, con cifras agregadas y metodología transparente.';
}elseif($vehicleMode==='best-selling-year'){
$metaTitle='Coches más vendidos en España en '.(int)$registrationYear.' | Matriculaciones DGT';$h1='Coches más vendidos en '.(int)$registrationYear;$description='Ranking de modelos con más matriculaciones DGT en '.(int)$registrationYear.'. Datos oficiales agregados por modelo.';
}elseif($vehicleMode==='electric-cars'){
$h1='Coches eléctricos en España';
$metaTitle='Coches eléctricos en España: cuántos hay y dónde | GasolinaBarata';
$description='Consulta cuántos coches eléctricos hay en España, su peso en el parque y las provincias con más vehículos eléctricos según los datos DGT procesados.';
}elseif(in_array($vehicleMode,['electric-best-selling','electric-best-selling-year'],true)){
$y=$vehicleMode==='electric-best-selling-year'?(int)$registrationYear:null;
$h1=$y?'Coches eléctricos más matriculados en España en '.$y:'Coches eléctricos más matriculados en España';
$metaTitle=$y?'Coches eléctricos más matriculados en '.$y.' | GasolinaBarata':'Coches eléctricos más vendidos en España: ranking DGT | GasolinaBarata';
$description=$y?'Ranking de coches eléctricos por matriculaciones DGT en '.$y.'.':'Ranking de coches eléctricos por matriculaciones DGT. Mostramos matriculaciones, no contratos de venta, y el año disponible en la base.';
}elseif($vehicleMode==='fiscal-value'){
$h1='Valor venal y valor fiscal de coches';
$metaTitle='Valor venal coche: calculadora y tablas de Hacienda | GasolinaBarata';
$description='Calcula y consulta el valor venal o fiscal de referencia de un coche buscando marca y modelo en las tablas oficiales de Hacienda importadas.';
}elseif($vehicleMode==='itp'){
$h1='ITP de un coche: cómo calcularlo';$metaTitle='ITP coche: cálculo, valor fiscal y transferencia | GasolinaBarata';$description='Calcula la base orientativa del ITP de un coche a partir del valor fiscal y entiende qué dato depende de tu comunidad autónoma.';
}elseif($vehicleMode==='transfer-guide'){
$h1='Transferencia de coche y cambio de titularidad';$metaTitle='Transferencia de coche: precio, cambio de titularidad e ITP | GasolinaBarata';$description='Guía práctica para transferir un coche: cuánto cuesta, valor fiscal, ITP, documentación y pasos del cambio de titularidad.';
}elseif($vehicleMode==='sale-contract'){
$h1='Contrato de compraventa de coche entre particulares';
$metaTitle='Contrato compraventa coche: modelo y qué debe incluir | GasolinaBarata';
$description='Modelo práctico de contrato de compraventa de vehículo entre particulares, datos imprescindibles, comprobaciones y relación con la transferencia del coche.';
}elseif($vehicleMode==='badges'){
$h1='Etiquetas ambientales de los coches en España';$metaTitle='Etiquetas B, C, ECO y 0: cuántos coches hay | GasolinaBarata';$description='Consulta cuántos vehículos hay con distintivo B, C, ECO, 0 o sin etiqueta según la fotografía del parque DGT.';
}elseif(str_starts_with((string)$vehicleMode,'badge-')){
$badgeTitle=match($vehicleMode){'badge-b'=>'Etiqueta B','badge-c'=>'Etiqueta C','badge-eco'=>'Etiqueta ECO','badge-zero'=>'Etiqueta 0 emisiones','badge-none'=>'Coches sin etiqueta',default=>'Etiqueta ambiental'};$h1=$badgeTitle.' en España';$metaTitle=$badgeTitle.': cuántos coches hay por provincia | GasolinaBarata';$description='Distribución de '.$badgeTitle.' por provincias según los datos agregados del parque de vehículos DGT.';
}elseif($vehicleMode==='park'){
$h1='Parque automovilístico de España';$metaTitle='Parque automovilístico de España: coches, edad y combustible | GasolinaBarata';$description='Cuántos vehículos hay en España, edad media, propulsiones, etiquetas y distribución territorial según el parque DGT.';
}elseif($vehicleMode==='common-cars'){
$h1='Coches más comunes en España';$metaTitle='Coches más comunes en España: modelos con más unidades | GasolinaBarata';$description='Ranking de marcas y modelos con más unidades presentes en el parque automovilístico español.';
}elseif($vehicleMode==='used-market'){
$h1='Mercado de coches de segunda mano en España';$metaTitle='Coches de segunda mano: transferencias y datos DGT | GasolinaBarata';$description='Estadísticas de transferencias de vehículos usados por modelo, antigüedad y periodo a partir de datos DGT.';
}elseif($vehicleMode==='used-ranking'){
$h1='Coches usados más transferidos en España';$metaTitle='Coches usados más vendidos: ranking de transferencias DGT | GasolinaBarata';$description='Ranking de modelos con más transferencias registradas. Usamos transferencias DGT como indicador del mercado de segunda mano.';
}elseif($vehicleMode==='longevity'){
$h1='Coches que llegan a mayor edad en España';$metaTitle='Coches que más duran: edad media al darse de baja | GasolinaBarata';$description='Modelos que alcanzan mayor edad media en los registros de baja DGT. La baja administrativa no equivale necesariamente a avería.';
}elseif($vehicleMode==='stolen-indicator'){
$h1='Vehículos con indicador de sustracción en transferencias';$metaTitle='Indicador de sustracción en transferencias DGT | GasolinaBarata';$description='Análisis experimental del indicador de sustracción presente en transferencias DGT. No equivale a un ranking oficial de robos.';
}elseif($vehicleMode==='vehicle-brands'){
$h1='Marcas de coches en España';
$metaTitle='Marcas de coches en España: modelos y parque móvil | GasolinaBarata';
$description='Explora las marcas y modelos presentes en el parque de vehículos español y consulta sus cifras oficiales.';
}elseif($vehicleMode==='vehicle-brand'){
$brandName=(string)($vehicleRoute['brand']['nombre']??'');
$h1='Coches '.$brandName.' en España';
$metaTitle=$brandName.': modelos, parque y matriculaciones | GasolinaBarata';
$description='Consulta los modelos '.$brandName.' presentes en España, cuántos vehículos hay y sus datos de matriculación y antigüedad.';
}elseif($vehicleMode==='vehicle-family'){
$brandName=(string)($vehicleRoute['brand']['nombre']??'');
$familyName=(string)($vehicleRoute['family']['familia']??'');
$h1=trim($brandName.' '.$familyName).' en España';
$metaTitle=trim($brandName.' '.$familyName).': cuántos hay, matriculaciones y versiones | GasolinaBarata';
$description='Consulta cuántos '.trim($brandName.' '.$familyName).' hay en España, sus versiones DGT, matriculaciones, provincias, antigüedad, transferencias y bajas.';
}elseif($vehicleMode==='vehicle-model'){
$brandName=(string)($vehicleRoute['brand']['nombre']??'');
$modelName=(string)($vehicleRoute['model']['modelo']??'');
$h1=$brandName.' '.$modelName.': datos en España';
$metaTitle=$brandName.' '.$modelName.': cuántos hay, matriculaciones y edad | GasolinaBarata';
$description='Datos del '.$brandName.' '.$modelName.' en España: parque actual, edad media, matriculaciones, provincias, transferencias y bajas según fuentes DGT.';
}
}
if($isEv){
if($evMode==='electrolineras'){
$h1='Puntos de recarga para coches eléctricos en España';
$metaTitle='Puntos de recarga de coches eléctricos en España | GasolinaBarata';
$description='Mapa y buscador de puntos de recarga públicos en España: potencia, conectores, operador, horario y ubicación con datos oficiales RIPREE.';
}elseif($evMode==='ev-map'){
$h1='Mapa de puntos de recarga para coches eléctricos en España';
$metaTitle='Mapa de puntos de recarga de coches eléctricos en España | GasolinaBarata';
$description='Explora en un mapa los puntos de recarga públicos de coche eléctrico en España y consulta operador, potencia, localidad y ubicación.';
}elseif($evMode==='ev-nearby'){
$h1='Cargadores de coche eléctrico cerca de mí';
$metaTitle='Cargadores de coche eléctrico cerca de mí | GasolinaBarata';
$description='Localiza puntos de recarga públicos cerca de tu ubicación y filtra por distancia y potencia.';
}elseif($evMode==='ev-fast'){
$h1='Puntos de carga rápida para coche eléctrico';
$metaTitle='Carga rápida de coche eléctrico: cargadores desde 50 kW | GasolinaBarata';
$description='Encuentra puntos de recarga rápida de 50 kW o más registrados en RIPREE.';
}elseif($evMode==='ev-ultrafast'){
$h1='Puntos de carga ultrarrápida para coche eléctrico';
$metaTitle='Carga ultrarrápida de coche eléctrico: 150 kW o más | GasolinaBarata';
$description='Encuentra puntos de recarga ultrarrápida de 150 kW o más registrados en RIPREE.';
}elseif($evMode==='ev-operators'){
$h1='Operadores de puntos de recarga en España';
$metaTitle='Operadores de recarga eléctrica en España | GasolinaBarata';
$description='Compara redes y operadores de recarga por instalaciones, puntos registrados y potencia máxima.';
}elseif($evMode==='ev-community'){
$evPlace=(string)$evRoute['community'];
$h1='Puntos de recarga de coches eléctricos en '.$evPlace;
$metaTitle='Puntos de recarga de coches eléctricos en '.$evPlace.' | GasolinaBarata';
$description='Consulta cargadores de coche eléctrico en '.$evPlace.': instalaciones, puntos, provincias, operadores y potencia con datos oficiales RIPREE.';
}elseif($evMode==='ev-province'){
$evPlace=(string)$evRoute['province'];
$h1='Puntos de recarga de coches eléctricos en '.$evPlace;
$metaTitle='Puntos de recarga de coches eléctricos en '.$evPlace.' | GasolinaBarata';
$description='Consulta cargadores de coche eléctrico en '.$evPlace.': instalaciones, puntos, operadores y potencia con datos oficiales RIPREE.';
}elseif($evMode==='ev-municipality'){
$evPlace=(string)$evRoute['municipality'];
$h1='Puntos de recarga de coche eléctrico en '.$evPlace;
$metaTitle='Cargadores de coche eléctrico en '.$evPlace.' | GasolinaBarata';
$description='Consulta puntos de recarga públicos en '.$evPlace.', '.(string)$evRoute['province'].': operador, dirección, potencia y ubicación.';
}elseif($evMode==='ev-operator'){
$evOperatorName=(string)$evRoute['operator']['nombre'];
$h1='Puntos de recarga '.$evOperatorName.' en España';
$metaTitle=$evOperatorName.': puntos de recarga y electrolineras | GasolinaBarata';
$description='Consulta la red '.$evOperatorName.' en España: instalaciones, puntos, provincias y potencia registrada en RIPREE.';
}
}
if($scope['geo_kind']==='municipality'&&!$isFeature){$h1='¿Está barato repostar en '.(string)$scope['municipality'].'?';}
if($station){$h1=($station['rotulo']?:'Gasolinera').' en '.$station['municipio'];$metaTitle=$h1.' · Precios, histórico y mapa | Gasolina Barata';$description='Consulta precios, horario, ubicación, evolución y comparación de '.($station['rotulo']?:'esta gasolinera').' en '.$station['municipio'].'.';}
$canonicalPath=$path;
$canonical=rtrim((string)gb_config('production_url'),'/').($canonicalPath===''?'/':$canonicalPath);
// Legacy CMS rows still contain historical post_index=0 values for several
// modern utility pages. Production indexability is explicitly defined here
// for canonical pages that are intentionally public.
$robots=gb_config('noindex')
? 'noindex,nofollow'
: (((int)($page['post_index']??1)?'index':'noindex').','.((int)($page['post_follow']??1)?'follow':'nofollow'));
$modernIndexablePaths=[
'/',
'/precio-gasolina/',
'/buscar/',
'/mapa-comunidades/',
'/marcas-gasolineras/',
'/ahorrar-gasolina/',
'/como-ahorrar-gasolina/',
'/gasolina-mas-barata-hoy/',
'/gasolineras-low-cost/',
'/gasolineras-24-horas/',
'/matriculas/',
'/matriculas/ultima-matricula/',
'/matriculas/fecha-matriculacion/',
'/matriculas/por-anos/',
'/matriculas/matricula-por-fecha/',
'/puntos-de-recarga/',
'/puntos-de-recarga/mapa/',
'/puntos-de-recarga/cerca-de-mi/',
'/puntos-de-recarga/carga-rapida/',
'/puntos-de-recarga/carga-ultrarrapida/',
'/puntos-de-recarga/operadores/',
'/vehiculos/',
'/vehiculos/marcas/',
'/vehiculos/matriculaciones/', '/vehiculos/coches-mas-vendidos/', '/vehiculos/marcas-mas-vendidas/', '/vehiculos/coches-electricos/', '/vehiculos/coches-electricos-mas-vendidos/',
'/vehiculos/valor-venal/', '/vehiculos/itp-coche/', '/vehiculos/transferencia-coche/', '/vehiculos/contrato-compraventa-coche/',
'/vehiculos/etiqueta-ambiental/', '/vehiculos/etiqueta-b/', '/vehiculos/etiqueta-c/', '/vehiculos/etiqueta-eco/', '/vehiculos/etiqueta-0/', '/vehiculos/sin-etiqueta/',
'/vehiculos/parque-automovilistico/', '/vehiculos/coches-mas-comunes/', '/vehiculos/segunda-mano/', '/vehiculos/coches-usados-mas-vendidos/', '/vehiculos/coches-que-mas-duran/',
];
if(!gb_config('noindex') && !$is404 && (in_array($path,$modernIndexablePaths,true)||$registrationYear!==null)){
$robots='index,follow';
}
if($isMatriculas && !$vehicleReady){$robots='noindex,follow';}
if($isEv && !$evReady){$robots='noindex,follow';}
if($isVehicleCatalog && !$vehicleCatalogReady){$robots='noindex,follow';}
if(in_array($vehicleMode,['registrations','best-selling','best-brands','best-selling-year','best-brands-year','electric-best-selling','electric-best-selling-year'],true) && !$registrationsReady){$robots='noindex,follow';}
if(in_array($vehicleMode,['park','common-cars','electric-cars','badges','badge-b','badge-c','badge-eco','badge-zero','badge-none','used-market','used-ranking','longevity','stolen-indicator'],true) && !$insightsReady){$robots='noindex,follow';}
if(in_array($vehicleMode,['fiscal-value','itp','transfer-guide'],true) && !$fiscalReady){$robots='noindex,follow';}
if($vehicleMode==='stolen-indicator' && !gb_config('noindex')){$robots='noindex,follow';}
// Base /buscar/ is a useful landing page; internal query-result variants are not.
if(!gb_config('noindex') && $isSearch && trim((string)($_GET['q']??''))!==''){
$robots='noindex,follow';
}
$baseProd=rtrim((string)gb_config('production_url'),'/');$breadcrumbs=[['name'=>'España','url'=>$baseProd.'/']];
if($station){$c=Geo::communityById((int)$station['comunidad']);$breadcrumbs[]=['name'=>$c['name'],'url'=>$baseProd.'/'.$c['slug'].'/'];$breadcrumbs[]=['name'=>PriceRepository::pretty((string)$station['provincia']),'url'=>$baseProd.$locations->provinceUrl((string)$station['provincia'],(int)$station['comunidad'])];$breadcrumbs[]=['name'=>(string)$station['municipio'],'url'=>$baseProd.$locations->municipalityUrl((string)$station['municipio'],(string)$station['provincia'],(int)$station['comunidad'])];$breadcrumbs[]=['name'=>(string)($station['rotulo']?:'Gasolinera'),'url'=>$canonical];}
elseif($scope['geo_kind']==='community')$breadcrumbs[]=['name'=>(string)$scope['community_name'],'url'=>$canonical];
elseif($scope['geo_kind']==='province'){if($scope['community_id']){$c=Geo::communityById((int)$scope['community_id']);$breadcrumbs[]=['name'=>$c['name'],'url'=>$baseProd.'/'.$c['slug'].'/'];}$breadcrumbs[]=['name'=>PriceRepository::pretty((string)$scope['province']),'url'=>$canonical];}
elseif($scope['geo_kind']==='municipality'){if($scope['community_id']){$c=Geo::communityById((int)$scope['community_id']);$breadcrumbs[]=['name'=>$c['name'],'url'=>$baseProd.'/'.$c['slug'].'/'];}$breadcrumbs[]=['name'=>PriceRepository::pretty((string)$scope['province']),'url'=>$baseProd.$locations->provinceUrl((string)$scope['province'],(int)$scope['community_id'])];$breadcrumbs[]=['name'=>(string)$scope['municipality'],'url'=>$canonical];}
if($isMatriculas){$breadcrumbs=[['name'=>'España','url'=>$baseProd.'/'],['name'=>'Matrículas','url'=>$baseProd.'/matriculas/']];if($path!=='/matriculas/')$breadcrumbs[]=['name'=>$h1,'url'=>$canonical];}
if($isEv){
$breadcrumbs=[['name'=>'España','url'=>$baseProd.'/'],['name'=>'Puntos de recarga','url'=>$baseProd.'/puntos-de-recarga/']];
if($evMode==='ev-municipality'){
$breadcrumbs[]=['name'=>(string)$evRoute['province'],'url'=>$baseProd.'/puntos-de-recarga/'.EvRepository::slug((string)$evRoute['province']).'/'];
$breadcrumbs[]=['name'=>(string)$evRoute['municipality'],'url'=>$canonical];
}elseif($evMode==='ev-operator'){
$breadcrumbs[]=['name'=>'Operadores','url'=>$baseProd.'/puntos-de-recarga/operadores/'];
$breadcrumbs[]=['name'=>(string)$evRoute['operator']['nombre'],'url'=>$canonical];
}elseif($evMode==='ev-community'){
$breadcrumbs[]=['name'=>(string)$evRoute['community'],'url'=>$canonical];
}elseif($path!=='/puntos-de-recarga/'){
$breadcrumbs[]=['name'=>$evMode==='ev-province'?(string)$evRoute['province']:$h1,'url'=>$canonical];
}
}
if($isVehicleCatalog){
$breadcrumbs=[['name'=>'España','url'=>$baseProd.'/'],['name'=>'Vehículos','url'=>$baseProd.'/vehiculos/']];
if($vehicleMode==='registrations')$breadcrumbs[]=['name'=>'Matriculaciones','url'=>$canonical];
elseif($vehicleMode==='best-selling')$breadcrumbs[]=['name'=>'Coches más vendidos','url'=>$canonical];
elseif(in_array($vehicleMode,['best-brands','best-brands-year'],true)){ $breadcrumbs[]=['name'=>'Marcas más vendidas','url'=>$baseProd.'/vehiculos/marcas-mas-vendidas/']; if($vehicleMode==='best-brands-year')$breadcrumbs[]=['name'=>(string)$registrationYear,'url'=>$canonical]; }
elseif($vehicleMode==='electric-cars')$breadcrumbs[]=['name'=>'Coches eléctricos','url'=>$canonical];
elseif(in_array($vehicleMode,['electric-best-selling','electric-best-selling-year'],true)){$breadcrumbs[]=['name'=>'Coches eléctricos','url'=>$baseProd.'/vehiculos/coches-electricos/'];$breadcrumbs[]=['name'=>'Más matriculados','url'=>$baseProd.'/vehiculos/coches-electricos-mas-vendidos/'];if($vehicleMode==='electric-best-selling-year')$breadcrumbs[]=['name'=>(string)$registrationYear,'url'=>$canonical];}
elseif($vehicleMode==='sale-contract'){$breadcrumbs[]=['name'=>'Transferencia de coche','url'=>$baseProd.'/vehiculos/transferencia-coche/'];$breadcrumbs[]=['name'=>'Contrato de compraventa','url'=>$canonical];}
elseif($vehicleMode==='best-selling-year'){$breadcrumbs[]=['name'=>'Coches más vendidos','url'=>$baseProd.'/vehiculos/coches-mas-vendidos/'];$breadcrumbs[]=['name'=>(string)$registrationYear,'url'=>$canonical];}
if($vehicleMode==='vehicle-brands')$breadcrumbs[]=['name'=>'Marcas','url'=>$canonical];
elseif($vehicleMode==='vehicle-brand')$breadcrumbs[]=['name'=>(string)$vehicleRoute['brand']['nombre'],'url'=>$canonical];
elseif($vehicleMode==='vehicle-family'){$breadcrumbs[]=['name'=>(string)$vehicleRoute['brand']['nombre'],'url'=>$baseProd.'/vehiculos/'.VehicleCatalogRepository::slug((string)$vehicleRoute['brand']['nombre']).'/'];$breadcrumbs[]=['name'=>(string)$vehicleRoute['family']['familia'],'url'=>$canonical];}
elseif($vehicleMode==='vehicle-model'){$breadcrumbs[]=['name'=>(string)$vehicleRoute['brand']['nombre'],'url'=>$baseProd.'/vehiculos/'.VehicleCatalogRepository::slug((string)$vehicleRoute['brand']['nombre']).'/'];$breadcrumbs[]=['name'=>(string)$vehicleRoute['model']['modelo'],'url'=>$canonical];}
}
$schemas=Seo::schemas(['base'=>$baseProd,'canonical'=>$canonical,'title'=>$metaTitle,'description'=>$description,'station'=>$station,'breadcrumbs'=>$breadcrumbs,'mode'=>$mode,'page'=>$page]);
// ---------------- Data by page intent ----------------
$snapshot=in_array($mode,['home','prices','territory','feature','cheapest'],true)?$prices->snapshot($scope):[];
$rankings=in_array($mode,['home','territory','feature'],true)?$prices->rankings($scope,15):[];
$communities=in_array($mode,['home','map','territory','feature'],true)?$prices->communities($isFeature?$scope:[]):[];
$provinces=$scope['geo_kind']==='community'?($isFeature?$prices->provincesForScope($scope):$prices->provinces((int)$scope['community_id'])):[];
$municipalities=$scope['geo_kind']==='province'?($isFeature?$prices->municipalitiesForScope($scope):$prices->municipalities((string)$scope['province'])):[];
$municipalityMeta=$scope['geo_kind']==='municipality'?$prices->municipalityMeta((string)$scope['municipality']):null;
$nearby=$municipalityMeta?$prices->nearbyMunicipalities((string)$scope['municipality'],(string)$scope['province'],12):[];
if($nearby){usort($nearby,static function(array $a,array $b):int{$pa=(float)($a['min95']??0);$pb=(float)($b['min95']??0);if($pa<=0&&$pb>0)return 1;if($pb<=0&&$pa>0)return -1;$cmp=$pa<=>$pb;return $cmp!==0?$cmp:((float)($a['distance_km']??9999)<=>(float)($b['distance_km']??9999));});}
$comparison=($municipalityMeta&&!$isFeature)?$prices->contextComparison((string)$scope['municipality'],(string)$scope['province'],(int)$scope['community_id']):null;
$brandStats=$isBrands?$prices->brandStats('gasolina_95'):[];
$communityStats=$isCheapest?$prices->communityFuelStats('gasolina_95'):[];
$articles=$isHome||$isSavings?$pages->editorialArticles(8):[];
$rankFuel='gasolina_95';if($station){foreach(['gasolina_95','gasoleo_a','gasolina_98','nuevo_gasoleo_a','gas_licuado_petroleo'] as $rf)if((float)($station[$rf]??0)>0){$rankFuel=$rf;break;}}$stationRanks=$station?$prices->stationRankContext($station,$rankFuel):[];
$import=$prices->lastSuccessfulImport();
$searchQ=trim((string)($_GET['q']??''));$searchRows=$isSearch&&mb_strlen($searchQ)>=2?$prices->searchLocations($searchQ,50):[];
$plateLatest=$isMatriculas?$vehicles->latestSeries():null;$plateRecent=$isMatriculas?$vehicles->recentSeries(18):[];$plateYears=$mode==='matricula-years'?$vehicles->yearsSummary():[];
$evSummary=$isEv?$ev->summary():[];$evOperators=$isEv?$ev->topOperators(40):[];$evPower=$isEv?$ev->powerSummary():[];$evConnectors=$isEv?$ev->connectorSummary(8):[];$evProvinces=$mode==='electrolineras'?$ev->provinceSummary(60):[];$evCommunities=$mode==='electrolineras'?$ev->communitySummary(30):[];
$evTerritorySummary=in_array($mode,['ev-province','ev-municipality'],true)?$ev->territorySummary((string)$evRoute['province'],$mode==='ev-municipality'?(string)$evRoute['municipality']:null):[];
$evTerritoryRows=in_array($mode,['ev-province','ev-municipality'],true)?$ev->territoryInstallations((string)$evRoute['province'],$mode==='ev-municipality'?(string)$evRoute['municipality']:null,300):[];
$evMunicipalities=$mode==='ev-province'?$ev->municipalities((string)$evRoute['province'],300):[];
$evCommunitySummary=$mode==='ev-community'?$ev->communityTerritorySummary((string)$evRoute['community']):[];
$evCommunityRows=$mode==='ev-community'?$ev->communityInstallations((string)$evRoute['community'],500):[];
$evCommunityProvinces=$mode==='ev-community'?$ev->communityProvinces((string)$evRoute['community'],40):[];
$evOperatorSummary=$mode==='ev-operator'?$ev->operatorSummary((int)$evRoute['operator']['id']):[];
$evOperatorProvinces=$mode==='ev-operator'?$ev->operatorProvinces((int)$evRoute['operator']['id'],80):[];
if(!gb_config('noindex') && in_array($evMode,['ev-province','ev-municipality'],true) && $evReady){
$robots=(int)($evTerritorySummary['puntos']??0)>=3?'index,follow':'noindex,follow';
}
if(!gb_config('noindex') && $evMode==='ev-community' && $evReady){
$robots=(int)($evCommunitySummary['puntos']??0)>=10?'index,follow':'noindex,follow';
}
if(!gb_config('noindex') && $evMode==='ev-operator' && $evReady){
$robots=(int)($evOperatorSummary['puntos']??0)>=10?'index,follow':'noindex,follow';
}
$vehicleOverview=$isVehicleCatalog?gb_cache_remember('vc-overview',21600,fn()=>$vehicleCatalog->overview()):[];
$vehicleBrands=in_array($mode,['vehicle-brands','vehicle-brand'],true)?gb_cache_remember('vc-brands-200',21600,fn()=>$vehicleCatalog->brands(200)):[];
$vehicleTopModels=$mode==='vehicles'?gb_cache_remember('vc-top-models-60',21600,fn()=>$vehicleCatalog->topModels(60)):[];
$vehicleBrandModels=$mode==='vehicle-brand'?gb_cache_remember('vc-brand-models-'.(int)$vehicleRoute['brand']['id'],21600,fn()=>$vehicleCatalog->modelsForBrand((int)$vehicleRoute['brand']['id'],500)):[];
$vehicleBrandFamilies=$mode==='vehicle-brand'?gb_cache_remember('vc-brand-families-v785-'.(int)$vehicleRoute['brand']['id'],21600,fn()=>$vehicleCatalog->modelFamiliesForBrand((int)$vehicleRoute['brand']['id'])):[];
$vehicleBrandStats=$mode==='vehicle-brand'?gb_cache_remember('vc-brand-stats-'.(int)$vehicleRoute['brand']['id'],21600,fn()=>$vehicleCatalog->brandStats((int)$vehicleRoute['brand']['id'])):[];
$vehicleFamilyStats=$mode==='vehicle-family'?gb_cache_remember('vc-family-stats-'.(int)$vehicleRoute['brand']['id'].'-'.(string)$vehicleRoute['family']['slug'],21600,fn()=>$vehicleCatalog->familyStats((int)$vehicleRoute['brand']['id'],(string)$vehicleRoute['family']['slug'])):[];
$vehicleModelStats=$mode==='vehicle-model'?$vehicleCatalog->modelStats((int)$vehicleRoute['model']['id']):[];
$registrationSummary=in_array($mode,['registrations','best-selling','best-brands','best-selling-year','best-brands-year'],true)?gb_cache_remember('reg-summary',3600,fn()=>$registrations->summary()):[];
$registrationLatest=(string)($registrationSummary['latest_period']??'');
$requestedStatsYear=(int)($_GET['anio']??0);if($requestedStatsYear<2014||$requestedStatsYear>(int)date('Y')+1)$requestedStatsYear=0;
$registrationYearShown=in_array($mode,['best-selling-year','best-brands-year'],true)?(int)$registrationYear:(int)substr($registrationLatest ?: date('Y-m'),0,4);
$registrationTopLatest=$mode==='registrations'&&$registrationLatest?gb_cache_remember('reg-top-period-'.$registrationLatest,1800,fn()=>$registrations->topModelsForPeriod($registrationLatest,80)):[];
$registrationTopYear=in_array($mode,['registrations','best-selling-year'],true)?gb_cache_remember('reg-top-year-'.$registrationYearShown,21600,fn()=>$registrations->topModelsForYear($registrationYearShown,200)):[];
$registrationTopBrands=$mode==='best-brands-year'?gb_cache_remember('reg-top-brands-'.$registrationYearShown,21600,fn()=>$registrations->topBrandsForYear($registrationYearShown,100)):[];
$bestSellingWinners=[]; // Se cargan por año de forma progresiva para no bloquear la landing.
$bestBrandWinners=[];
$registrationEvolution=$mode==='registrations'?gb_cache_remember('reg-evolution-36',3600,fn()=>$registrations->monthlyEvolution(36)):[];
$registrationYears=in_array($mode,['registrations','best-selling','best-brands','best-selling-year','best-brands-year','electric-best-selling','electric-best-selling-year'],true)?gb_cache_remember('reg-years',21600,fn()=>$registrations->availableYears()):[];
$parkSummary=in_array($mode,['park','common-cars','electric-cars','badges','badge-b','badge-c','badge-eco','badge-zero','badge-none'],true)?gb_cache_remember('park-summary',1800,fn()=>$insights->parkSummary()):[];
$parkPropulsion=$mode==='park'?$insights->propulsionSummary():[];
$parkBadges=in_array($mode,['park','badges'],true)?$insights->badgeSummary():[];
$parkAges=$mode==='park'?$insights->ageDistribution():[];
$parkProvinces=$mode==='park'?gb_cache_remember('park-provinces',1800,fn()=>$insights->provinceTotals(60)):[];
$electricPark=$mode==='electric-cars'?gb_cache_remember('electric-total',1800,fn()=>$insights->propulsionTotal('Eléctrico')):[];
$electricProvinces=$mode==='electric-cars'?gb_cache_remember('electric-provinces',1800,fn()=>$insights->propulsionProvinces('Eléctrico',60)):[];
$electricYear=$mode==='electric-best-selling-year'?(int)$registrationYear:(int)substr($registrations->latestPeriod()?:date('Y-m'),0,4);
$electricTop=$mode==='electric-best-selling-year'?gb_cache_remember('electric-top-'.$electricYear,21600,fn()=>$registrations->topModelsForYearByPropulsion($electricYear,'Eléctrico',200)):[];
$electricYearTotal=$mode==='electric-best-selling-year'?gb_cache_remember('electric-total-year-'.$electricYear,21600,fn()=>$registrations->propulsionYearTotal($electricYear,'Eléctrico')):0;
$electricWinners=[];
$badgeCode=match($mode){'badge-b'=>'B','badge-c'=>'C','badge-eco'=>'ECO','badge-zero'=>'0','badge-none'=>'SIN',default=>null};
$badgeProvinces=$badgeCode?gb_cache_remember('badge-provinces-'.$badgeCode,21600,fn()=>$insights->badgeProvinces($badgeCode,60)):[];
$usedSummary=in_array($mode,['used-market','used-ranking'],true)?gb_cache_remember('used-summary-fast-v787',21600,fn()=>$insights->transferSummary()):[];
$usedTop=[]; // Se carga por AJAX para que la página pinte sin esperar a agregaciones pesadas.
$usedAges=[]; // Se carga por AJAX.
$bajasSummary=$mode==='longevity'?gb_cache_remember('bajas-summary-fast-v787',21600,fn()=>$insights->bajasSummary()):[];
$longevityTop=[]; // Ranking diferido por AJAX; evita bloquear el HTML inicial.
$stolenTop=$mode==='stolen-indicator'?$insights->stolenIndicatorModels(50,100):[];
$fiscalSummary=in_array($mode,['fiscal-value','itp','transfer-guide'],true)?$fiscal->summary():[];
$fiscalQ=$mode==='fiscal-value'?trim((string)($_GET['q']??'')):'';
$fiscalRows=$mode==='fiscal-value'&&mb_strlen($fiscalQ)>=2?$fiscal->search($fiscalQ,80):[];
if($mode==='vehicle-family' && (int)($vehicleFamilyStats['parque']??0)<50 && (int)($vehicleFamilyStats['matriculaciones_12m']??0)<25 && !gb_config('noindex'))$robots='noindex,follow';
if($mode==='vehicle-model' && !$vehicleCatalog->modelIndexable((array)$vehicleRoute['model'],$vehicleModelStats) && !gb_config('noindex'))$robots='noindex,follow';
// Datos estructurados específicos de las nuevas verticales.
$richItems=[];$richPlaces=[];$richVariables=[];$richTemporal='';$richSpatial='';$richModified='';$richVehicle=null;
if(in_array($mode,['matriculas','matricula-latest','matricula-date','matricula-years','matricula-by-date'],true)){
$richVariables=['Serie de matrícula','Número de matriculaciones','Periodo'];
$richTemporal=(string)($plateLatest['periodo']??'');
}
if(in_array($mode,['registrations','best-selling','best-selling-year'],true)){
$richVariables=['Matriculaciones','Marca','Modelo','Periodo'];
$richTemporal=$mode==='best-selling-year'?(string)$registrationYearShown:(string)$registrationLatest;
foreach(($mode==='registrations'?$registrationTopLatest:$registrationTopYear) as $r)$richItems[]=['name'=>trim((string)$r['marca'].' '.(string)$r['modelo']),'url'=>$baseProd.'/vehiculos/'.$r['marca_slug'].'/'.$r['modelo_slug'].'/'];
}
if(in_array($mode,['best-brands','best-brands-year'],true)){
$richVariables=['Matriculaciones por marca','Periodo'];$richTemporal=(string)$registrationYearShown;
foreach($registrationTopBrands as $r)$richItems[]=['name'=>(string)$r['marca'],'url'=>$baseProd.'/vehiculos/'.$r['slug'].'/'];
}
if($mode==='electric-cars'){
$richVariables=['Vehículos eléctricos en el parque','Provincia'];$richTemporal=(string)($electricPark['periodo']??'');$richSpatial='España';
foreach($electricProvinces as $r)$richItems[]=['name'=>(string)$r['provincia']];
}
if(in_array($mode,['electric-best-selling','electric-best-selling-year'],true)){
$richVariables=['Matriculaciones de vehículos eléctricos','Marca','Modelo'];$richTemporal=(string)$electricYear;$richSpatial='España';
foreach($electricTop as $r)$richItems[]=['name'=>trim((string)$r['marca'].' '.(string)$r['modelo']),'url'=>$baseProd.'/vehiculos/'.$r['marca_slug'].'/'.$r['modelo_slug'].'/'];
}
if(in_array($mode,['park','badges','badge-b','badge-c','badge-eco','badge-zero','badge-none','common-cars'],true)){
$richVariables=['Vehículos en el parque','Provincia','Distintivo ambiental','Propulsión'];$richTemporal=(string)($parkSummary['periodo']??'');$richSpatial='España';
}
if(in_array($mode,['used-market','used-ranking'],true)){
$richVariables=['Transferencias registradas','Marca','Modelo','Antigüedad'];$richTemporal=trim((string)($usedSummary['desde']??'').'/'.(string)($usedSummary['hasta']??''),'/');$richSpatial='España';
foreach($usedTop as $r)$richItems[]=['name'=>trim((string)$r['marca'].' '.(string)$r['modelo']),'url'=>$baseProd.'/vehiculos/'.$r['marca_slug'].'/'.$r['modelo_slug'].'/'];
}
if($mode==='longevity'){
$richVariables=['Edad media al registrarse la baja','Bajas registradas','Marca','Modelo'];$richTemporal=trim((string)($bajasSummary['desde']??'').'/'.(string)($bajasSummary['hasta']??''),'/');$richSpatial='España';
foreach($longevityTop as $r)$richItems[]=['name'=>trim((string)$r['marca'].' '.(string)$r['modelo']),'url'=>$baseProd.'/vehiculos/'.$r['marca_slug'].'/'.$r['modelo_slug'].'/'];
}
if($mode==='vehicle-brand'){
$richVariables=['Vehículos en el parque','Matriculaciones','Edad media'];$richSpatial='España';
foreach(array_slice($vehicleBrandModels,0,50) as $r)$richItems[]=['name'=>trim((string)$vehicleRoute['brand']['nombre'].' '.(string)$r['modelo']),'url'=>$baseProd.'/vehiculos/'.$r['marca_slug'].'/'.$r['modelo_slug'].'/'];
}
if($mode==='vehicle-model'){
$park=(array)($vehicleModelStats['parque']??[]);
$richVariables=['Vehículos en el parque','Edad media','Matriculaciones','Transferencias','Bajas'];$richTemporal=(string)($park['periodo']??'');$richSpatial='España';
$richVehicle=[
'brand'=>(string)($vehicleRoute['brand']['nombre']??''),
'model'=>(string)($vehicleRoute['model']['modelo']??''),
'park'=>(int)($park['numero']??0),
'avg_age'=>isset($park['edad_media'])&&$park['edad_media']!==null?round((float)$park['edad_media'],1):null,
'registrations_12m'=>(int)($vehicleModelStats['matriculaciones_12m']??0),
'transfers'=>(int)($vehicleModelStats['transferencias']['numero']??0),
'deregistrations'=>(int)($vehicleModelStats['bajas']['numero']??0),
];
}
if($mode==='fiscal-value'){$richVariables=['Valor fiscal','Marca','Modelo o tipo','Potencia','Periodo comercial'];$richTemporal=(string)($fiscalSummary['ejercicio']??'');}
if($isEv){
$richVariables=['Instalaciones de recarga','Puntos de recarga','Potencia máxima','Operador','Ubicación'];
$richModified=(string)($evSummary['updated']??'');
if($mode==='ev-community'){$richSpatial=(string)$evRoute['community'];$rowsForSchema=$evCommunityRows;}
elseif($mode==='ev-province'){$richSpatial=(string)$evRoute['province'];$rowsForSchema=$evTerritoryRows;}
elseif($mode==='ev-municipality'){$richSpatial=(string)$evRoute['municipality'].', '.(string)$evRoute['province'];$rowsForSchema=$evTerritoryRows;}
else{$richSpatial='España';$rowsForSchema=[];}
foreach(array_slice($rowsForSchema??[],0,50) as $r)$richPlaces[]=['name'=>(string)($r['nombre']?:'Punto de recarga'),'lat'=>$r['latitud']??null,'lng'=>$r['longitud']??null,'address'=>(string)($r['direccion']??'')];
if($mode==='ev-operator')foreach($evOperatorProvinces as $r)$richItems[]=['name'=>(string)$r['provincia']];
elseif($mode==='electrolineras')foreach($evProvinces as $r)$richItems[]=['name'=>(string)$r['provincia'],'url'=>$baseProd.'/puntos-de-recarga/'.EvRepository::slug((string)$r['provincia']).'/'];
}
$schemas=array_merge($schemas,Seo::richSchemas([
'base'=>$baseProd,'canonical'=>$canonical,'title'=>$metaTitle,'description'=>$description,'mode'=>$mode,
'variables'=>$richVariables,'temporalCoverage'=>$richTemporal,'spatialName'=>$richSpatial,'dateModified'=>$richModified,
'itemList'=>$richItems,'places'=>$richPlaces,'vehicleModel'=>$richVehicle,
]));
$noAdsPaths=['/aviso-legal/','/politica-privacidad/','/politica-cookies/','/contacto/'];$monetizable=!$is404&&!in_array($path,$noAdsPaths,true);
?>
Fatal error: Uncaught Error: Call to undefined function gb_h() in /home/gasolinabarata/public_html/index.php:668
Stack trace:
#0 {main}
thrown in /home/gasolinabarata/public_html/index.php on line 668