craigk5n / php-icalendar-core
RFC 5545 compliant PHP library for iCalendar parsing and writing
Installs: 159
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/craigk5n/php-icalendar-core
Requires
- php: >=8.2
Requires (Dev)
- infection/infection: ^0.29
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.0
- vimeo/psalm: ^5.0 || ^6.0
README
This library provides robust parsing and writing capabilities for the iCalendar (RFC 5545) format. It aims for high compatibility with RFC specifications while offering flexible parsing modes and supporting standardized extensions for richer data.
Features
- RFC 5545 Compliant: Adheres to the iCalendar standard for data representation.
- Parser & Writer: Full support for reading and writing iCalendar data.
- Component & Property Support: Handles various iCalendar components (VEVENT, VTODO, VCALENDAR, etc.) and properties.
- Recurrence Rule (RRULE) Handling: Advanced support for parsing and generating recurrence rules.
- Timezone Support: Correctly parses and handles timezone information.
- Rich Text Descriptions (RFC 9073): Supports the
STYLED-DESCRIPTIONproperty for HTML or URI-based rich text descriptions, enhancing event details. This includes parsingSTYLED-DESCRIPTIONand handling backward compatibility with the plainDESCRIPTIONproperty (omitting it unlessDERIVED=TRUE). Writing also respects this rule. - Extensibility: Designed to be extensible for custom component or property types.
- Memory Efficiency: Utilizes generators and streaming where possible for handling large files. Performance benchmarks are calibrated for execution without code coverage overhead.
Strict vs. Lenient Parsing Modes
This library supports two parsing modes to accommodate varying .ics file compliance:
Strict Mode (Parser::STRICT)
- Behavior: In strict mode, the parser rigorously enforces RFC 5545 compliance. Any deviation from the standard, such as malformed date/time values, unexpected component types, or syntax errors, will result in a
ParseExceptionbeing thrown immediately. This mode also enforces strict handling of extensions likeSTYLED-DESCRIPTIONand its interaction withDESCRIPTION. - Use Case: Ideal for validating compliant
.icsfiles or when strict adherence to the standard is paramount. It acts as a robust syntax checker for iCalendar data.
Lenient Mode (Parser::LENIENT)
- Behavior: In lenient mode, the parser prioritizes data import by attempting to process
.icsfiles even with non-compliant structures.- Instead of throwing exceptions for certain violations (specifically related to dates, times, and the
SUMMARYproperty), the parser will collect warnings. - These warnings can be retrieved using the
getWarnings()method after parsing is complete. - The parser attempts to handle known extensions like
STYLED-DESCRIPTIONgracefully, collecting warnings for any non-critical deviations.
- Instead of throwing exceptions for certain violations (specifically related to dates, times, and the
- Use Case: Useful for importing data from
.icsfiles that may not perfectly adhere to the RFC, allowing for maximum data recovery.
Choosing a Mode
Clients can select the parsing mode by passing a constant to the Parser constructor:
use Icalendar\Parser\Parser; // Strict mode (default) $parserStrict = new Parser(Parser::STRICT); $calendarStrict = $parserStrict->parse($icsData); // Lenient mode $parserLenient = new Parser(Parser::LENIENT); $calendarLenient = $parserLenient->parse($icsData); // Access warnings collected in lenient mode $warnings = $parserLenient->getWarnings(); // Note: getErrors() is an alias for getWarnings() for backward compatibility
Installation
Requires PHP 8.2+ and no external production dependencies.
# Assuming you have Composer installed
composer require craigk5n/php-icalendar-core
Usage
Parsing
use Icalendar\Parser\Parser; use Icalendar\Exception\ParseException; use Icalendar\Validation\ErrorSeverity; // For checking warning severity if needed $icsData = file_get_contents('path/to/your/calendar.ics'); // Use Parser::LENIENT to collect warnings for non-compliant data $parser = new Parser(Parser::LENIENT); try { $calendar = $parser->parse($icsData); // Process the calendar object... // e.g., $events = $calendar->getComponents('VEVENT'); // Check for warnings if in lenient mode if ($parser->getMode() === Parser::LENIENT) { $warnings = $parser->getWarnings(); // getErrors() is an alias for backward compatibility if (!empty($warnings)) { echo "Parsing completed with warnings:\n"; foreach ($warnings as $warning) { // Example: check if it's a warning if ($warning->getSeverity() === ErrorSeverity::WARNING) { echo "- Warning (Code: {$warning->getCode()}): {$warning->getMessage()} (Property: {$warning->getProperty()}) [Line {$warning->getLineNumber()}]\n"; } else { echo "- Error (Code: {$warning->getCode()}): {$warning->getMessage()} (Property: {$warning->getProperty()}) [Line {$warning->getLineNumber()}]\n"; } } } } } catch (ParseException $e) { echo "Parsing failed: " . $e->getMessage() . "\n"; }
STYLED-DESCRIPTION Support (RFC 9073)
The library now supports the STYLED-DESCRIPTION property introduced in RFC 9073, which allows for rich text descriptions (e.g., HTML) or URI references.
- Parsing:
STYLED-DESCRIPTIONis parsed and stored. WhenSTYLED-DESCRIPTIONis present, plainDESCRIPTIONproperties that are not markedDERIVED=TRUEare ignored during parsing to adhere to RFC 9073's backward compatibility rules. - Writing:
STYLED-DESCRIPTIONproperties are correctly serialized. When writing a component that includesSTYLED-DESCRIPTION, any plainDESCRIPTIONproperties withoutDERIVED=TRUEwill be omitted from the output.
Writing
use Icalendar\Writer\Writer; use Icalendar\Component\VCalendar; // Assume $calendar is a VCalendar object populated with data $writer = new Writer(); $icsString = $writer->write($calendar); file_put_contents('output.ics', $icsString);
Documentation
- Full Documentation (DeepWiki) — Auto-generated wiki covering architecture, parsing, writing, recurrence rules, and API reference.
- PRD.md — Product requirements and RFC 5545 compliance details.
- STATUS.md — Detailed task tracking and implementation status.
Contributing
Please refer to the CONTRIBUTING.md file.
AI Assistance Disclosure
This project was developed with the assistance of generative AI tools (Claude Code by Anthropic, OpenCode, and Google Gemini) for tasks such as:
- Structuring the initial PRD and task breakdown
- Generating code skeletons, design patterns, and documentation drafts
- Suggesting test cases and edge-case handling
- Refining explanations, README content, and commit messages
All AI-generated output has been carefully reviewed, edited, tested, and validated by the human maintainer (Craig Knudsen) for correctness, security, RFC 5545 compliance, and project goals. No AI-generated code was merged without human understanding and modification.
The final codebase, architecture decisions, and quality assurance remain the responsibility of the human author. This approach accelerated development while preserving full ownership and accountability.
License
This project is licensed under the MIT License - see the LICENSE file for details.