This commit is contained in:
2026-04-01 20:15:45 +02:00
parent 92b7a2a95e
commit 9b36f8fec3
35 changed files with 2371 additions and 31 deletions

View File

@@ -0,0 +1,133 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Elementor Widget: Carei Branches — grid oddziałów z adresami.
*/
class Carei_Branches_Widget extends \Elementor\Widget_Base {
const NAME_FIXES = array(
'BYDGOSZC' => 'BYDGOSZCZ',
'GORZÓW WIE' => 'GORZÓW WIELKOPOLSKI',
'RZSZÓW' => 'RZESZÓW',
'SK-KAM' => '',
);
public function get_name() {
return 'carei-branches';
}
public function get_title() {
return 'Carei Branches';
}
public function get_icon() {
return 'eicon-posts-grid';
}
public function get_categories() {
return array( 'general' );
}
public function get_style_depends() {
return array( 'carei-reservation-css' );
}
protected function register_controls() {}
/**
* Clean branch name and return base city.
*/
private static function clean_name( $raw ) {
$name = trim( $raw );
$name = preg_replace( '/\s+[DL]$/u', '', $name );
if ( isset( self::NAME_FIXES[ $name ] ) ) {
$name = self::NAME_FIXES[ $name ];
}
if ( empty( $name ) || preg_match( '/^[A-Z]{2,4}-[A-Z]{2,4}$/u', $name ) ) {
return '';
}
return $name;
}
/**
* Get unique branches with addresses.
*/
private function get_branches_data() {
$api = Carei_Softra_API::get_instance();
if ( null === $api ) {
return array();
}
$branches = $api->get_branches_cached();
if ( is_wp_error( $branches ) || ! is_array( $branches ) ) {
return array();
}
$result = array();
$seen = array();
foreach ( $branches as $b ) {
$raw_name = isset( $b['name'] ) ? $b['name'] : '';
$city = self::clean_name( $raw_name );
if ( empty( $city ) ) {
continue;
}
$norm = mb_strtolower( $city, 'UTF-8' );
if ( isset( $seen[ $norm ] ) ) {
continue;
}
$seen[ $norm ] = true;
$display_city = mb_convert_case( $city, MB_CASE_TITLE, 'UTF-8' );
$street = isset( $b['street'] ) ? trim( $b['street'] ) : '';
$zip = isset( $b['zipCode'] ) ? trim( (string) $b['zipCode'] ) : '';
$api_city = isset( $b['city'] ) ? trim( $b['city'] ) : '';
$api_city_tc = mb_convert_case( $api_city, MB_CASE_TITLE, 'UTF-8' );
// Format street
if ( $street ) {
$street_lower = mb_strtolower( $street, 'UTF-8' );
$has_prefix = preg_match( '/^(ul\.|al\.|pl\.|os\.)/u', $street_lower );
$street = $has_prefix ? $street : 'ul. ' . $street;
}
$result[] = array(
'name' => 'Oddział ' . $display_city,
'street' => $street,
'zipCity' => trim( $zip . ' ' . $api_city_tc ),
);
}
usort( $result, function ( $a, $b ) {
return strcmp( $a['name'], $b['name'] );
} );
return $result;
}
protected function render() {
$branches = $this->get_branches_data();
if ( empty( $branches ) ) {
return;
}
?>
<div class="carei-branches">
<?php foreach ( $branches as $branch ) : ?>
<div class="carei-branches__item">
<div class="carei-branches__name"><?php echo esc_html( $branch['name'] ); ?></div>
<?php if ( $branch['street'] ) : ?>
<div class="carei-branches__street"><?php echo esc_html( $branch['street'] ); ?></div>
<?php endif; ?>
<?php if ( $branch['zipCity'] ) : ?>
<div class="carei-branches__zip-city"><?php echo esc_html( $branch['zipCity'] ); ?></div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php
}
}

View File

@@ -0,0 +1,120 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Elementor Widget: Carei Cities — siatka miast oddziałów.
*/
class Carei_Cities_Widget extends \Elementor\Widget_Base {
public function get_name() {
return 'carei-cities';
}
public function get_title() {
return 'Carei Cities';
}
public function get_icon() {
return 'eicon-bullet-list';
}
public function get_categories() {
return array( 'general' );
}
public function get_style_depends() {
return array( 'carei-reservation-css' );
}
public function get_script_depends() {
return array( 'carei-reservation-js' );
}
protected function register_controls() {}
/**
* Truncated / misspelled names from Softra API → correct full city names.
*/
const NAME_FIXES = array(
'BYDGOSZC' => 'BYDGOSZCZ',
'GORZÓW WIE' => 'GORZÓW WIELKOPOLSKI',
'RZSZÓW' => 'RZESZÓW',
'SK-KAM' => '',
);
/**
* Clean branch name: handle D(Dworzec)/L suffixes, fix truncated names, title-case.
* API returns names like "GDAŃSK D", "GDAŃSK L", "BYDGOSZC D", "SK-KAM", "GORZÓW WIE".
* D-suffix branches without a base variant → "Oddział [City]".
*/
private static function clean_city_name( $raw ) {
$name = trim( $raw );
// Detect D (Dworzec) suffix before stripping
$is_dworzec = (bool) preg_match( '/\s+D$/u', $name );
// Strip trailing single-letter suffixes (D=Dworzec, L=Lotnisko/inne)
$name = preg_replace( '/\s+[DL]$/u', '', $name );
// Fix known truncated/misspelled names
if ( isset( self::NAME_FIXES[ $name ] ) ) {
$name = self::NAME_FIXES[ $name ];
}
// Skip empty or non-city codes
if ( empty( $name ) || preg_match( '/^[A-Z]{2,4}-[A-Z]{2,4}$/u', $name ) ) {
return '';
}
// Title-case: "GDAŃSK" → "Gdańsk"
$name = mb_convert_case( $name, MB_CASE_TITLE, 'UTF-8' );
return $name;
}
/**
* Extract unique city names from branches.
*/
private function get_city_names() {
$api = Carei_Softra_API::get_instance();
if ( null === $api ) {
return array();
}
$branches = $api->get_branches_cached();
if ( is_wp_error( $branches ) || ! is_array( $branches ) ) {
return array();
}
$cities = array();
$seen = array();
foreach ( $branches as $b ) {
$name = isset( $b['name'] ) ? $b['name'] : '';
$city = self::clean_city_name( $name );
if ( empty( $city ) ) {
continue;
}
$norm = mb_strtolower( $city, 'UTF-8' );
if ( isset( $seen[ $norm ] ) ) {
continue;
}
$seen[ $norm ] = true;
$cities[] = $city;
}
sort( $cities );
return $cities;
}
protected function render() {
$cities = $this->get_city_names();
if ( empty( $cities ) ) {
return;
}
?>
<div class="carei-cities">
<?php foreach ( $cities as $i => $city ) : ?>
<span class="carei-cities__item"><?php echo esc_html( $city ); ?></span>
<?php endforeach; ?>
</div>
<?php
}
}

File diff suppressed because one or more lines are too long

View File

@@ -117,6 +117,13 @@ class Carei_REST_Proxy {
),
) );
// GET /branches-full (cached, full branch objects with descriptions)
register_rest_route( self::NAMESPACE, '/branches-full', array(
'methods' => 'GET',
'callback' => array( $this, 'get_branches_full' ),
'permission_callback' => '__return_true',
) );
// GET /agreements
register_rest_route( self::NAMESPACE, '/agreements', array(
'methods' => 'GET',
@@ -276,6 +283,14 @@ class Carei_REST_Proxy {
) );
}
public function get_branches_full( WP_REST_Request $request ) {
$api = $this->api();
if ( is_wp_error( $api ) ) {
return $api;
}
return $this->respond( $api->get_branches_cached() );
}
public function get_agreements( WP_REST_Request $request ) {
$api = $this->api();
if ( is_wp_error( $api ) ) {

View File

@@ -153,6 +153,26 @@ class Carei_Softra_API {
return $this->request( 'GET', '/branch/list' );
}
/**
* Get branches with 60-min transient cache.
*/
public function get_branches_cached() {
$cache_key = 'carei_branches_list';
$cached = get_transient( $cache_key );
if ( false !== $cached ) {
return $cached;
}
$branches = $this->get_branches();
if ( is_wp_error( $branches ) || ! is_array( $branches ) ) {
return is_wp_error( $branches ) ? $branches : array();
}
set_transient( $cache_key, $branches, HOUR_IN_SECONDS );
return $branches;
}
public function get_all_car_classes() {
return $this->request( 'GET', '/car/class/listAll' );
}
@@ -170,7 +190,7 @@ class Carei_Softra_API {
return $cached;
}
$branches = $this->get_branches();
$branches = $this->get_branches_cached();
if ( is_wp_error( $branches ) || ! is_array( $branches ) ) {
return is_wp_error( $branches ) ? $branches : array();
}