Files
wrapartamenty.pl/wp-content/plugins/mphb-ical-sync/includes/Parser.php
Jacek Pyziak c49d3b39d4 Add MPHB iCal Sync plugin for automatic iCal synchronization and booking management
- Implement SyncCron class for scheduling iCal sync every 15 minutes.
- Create main plugin file with initialization and activation hooks.
- Add admin booking modal for managing reservations, including AJAX functionality for searching available rooms and creating bookings.
- Include necessary CSS and JS for modal functionality and user interaction.
- Ensure compatibility with MotoPress Hotel Booking plugin.
2026-03-02 18:14:50 +01:00

145 lines
3.4 KiB
PHP

<?php
namespace MphbIcalSync;
/**
* Parser plików iCal (.ics) zgodny z RFC 5545.
* Nie wymaga zewnętrznych bibliotek.
*/
class Parser {
/**
* Parsuje zawartość pliku .ics i zwraca tablicę eventów.
*
* @param string $icsContent Zawartość pliku .ics
* @return array[] Tablica eventów: [uid, dtstart, dtend, summary, status]
*/
public function parse( string $icsContent ): array {
// Unfold lines (RFC 5545: linia złożona z CRLF + spacja/tab jest kontynuacją)
$icsContent = preg_replace( "/\r\n[ \t]/", '', $icsContent );
$icsContent = preg_replace( "/\n[ \t]/", '', $icsContent );
$lines = preg_split( "/\r\n|\n|\r/", $icsContent );
$events = [];
$inEvent = false;
$current = [];
foreach ( $lines as $line ) {
$line = trim( $line );
if ( $line === 'BEGIN:VEVENT' ) {
$inEvent = true;
$current = [];
continue;
}
if ( $line === 'END:VEVENT' ) {
$inEvent = false;
if ( ! empty( $current ) ) {
$event = $this->parseEvent( $current );
if ( $event !== null ) {
$events[] = $event;
}
}
continue;
}
if ( $inEvent && $line !== '' ) {
$current[] = $line;
}
}
return $events;
}
/**
* @param string[] $lines Linie z wnętrza VEVENT
* @return array|null Sparsowany event lub null (jeśli CANCELLED/niepełny)
*/
private function parseEvent( array $lines ): ?array {
$event = [
'uid' => '',
'dtstart' => '',
'dtend' => '',
'summary' => '',
'status' => '',
];
foreach ( $lines as $line ) {
$colonPos = strpos( $line, ':' );
if ( $colonPos === false ) {
continue;
}
$key = strtoupper( substr( $line, 0, $colonPos ) );
$value = substr( $line, $colonPos + 1 );
// Oddziel parametry od nazwy właściwości (DTSTART;VALUE=DATE → DTSTART)
$semiPos = strpos( $key, ';' );
$baseKey = $semiPos !== false ? substr( $key, 0, $semiPos ) : $key;
switch ( $baseKey ) {
case 'UID':
$event['uid'] = trim( $value );
break;
case 'DTSTART':
$event['dtstart'] = $this->parseDate( $value );
break;
case 'DTEND':
$event['dtend'] = $this->parseDate( $value );
break;
case 'SUMMARY':
$event['summary'] = $this->unescapeIcalText( $value );
break;
case 'STATUS':
$event['status'] = strtoupper( trim( $value ) );
break;
}
}
// Pomiń anulowane eventy
if ( $event['status'] === 'CANCELLED' ) {
return null;
}
// Pomiń eventy bez wymaganych pól
if ( empty( $event['uid'] ) || empty( $event['dtstart'] ) || empty( $event['dtend'] ) ) {
return null;
}
return $event;
}
/**
* Konwertuje datę iCal do formatu Y-m-d.
* Obsługuje: YYYYMMDD, YYYYMMDDTHHmmss, YYYYMMDDTHHmmssZ
*/
private function parseDate( string $value ): string {
$value = trim( $value );
// Usuń część czasową i strefę czasową (Z lub identyfikator)
$tPos = strpos( $value, 'T' );
if ( $tPos !== false ) {
$value = substr( $value, 0, $tPos );
}
// Usuń myślniki jeśli są
$value = str_replace( '-', '', $value );
if ( strlen( $value ) === 8 && ctype_digit( $value ) ) {
return substr( $value, 0, 4 ) . '-' . substr( $value, 4, 2 ) . '-' . substr( $value, 6, 2 );
}
return '';
}
private function unescapeIcalText( string $text ): string {
$text = str_replace( '\\n', "\n", $text );
$text = str_replace( '\,', ',', $text );
$text = str_replace( '\;', ';', $text );
$text = str_replace( '\\\\', '\\', $text );
return $text;
}
}