From 957468d286676ed2f269dbcf0e73df2c8d2de6f0 Mon Sep 17 00:00:00 2001 From: ihabz Date: Mon, 16 Dec 2024 11:58:18 -0800 Subject: [PATCH] add missing package. --- .../kigkonsult/icalcreator/docs/demoUsage.md | 232 +++ .../kigkonsult/icalcreator/docs/gpl-3.0.txt | 674 ++++++++ vendor/kigkonsult/icalcreator/releaseNotes | 308 ++++ .../kigkonsult/icalcreator/src/Available.php | 156 ++ .../icalcreator/src/Formatter/Available.php | 149 ++ .../icalcreator/src/Formatter/DScomponent.php | 104 ++ .../icalcreator/src/Formatter/FormatBase.php | 96 ++ .../icalcreator/src/Formatter/Participant.php | 190 +++ .../src/Formatter/Property/Attendee.php | 215 +++ .../src/Formatter/Property/CalMetProVer.php | 53 + .../src/Formatter/Property/Dt1Property.php | 93 ++ .../src/Formatter/Property/DtxProperty.php | 67 + .../src/Formatter/Property/DurDates.php | 72 + .../src/Formatter/Property/Exdate.php | 136 ++ .../src/Formatter/Property/Freebusy.php | 101 ++ .../src/Formatter/Property/Geo.php | 67 + .../src/Formatter/Property/IntProperty.php | 67 + .../src/Formatter/Property/MultiProps.php | 198 +++ .../src/Formatter/Property/Property.php | 60 + .../src/Formatter/Property/PropertyBase.php | 485 ++++++ .../src/Formatter/Property/Rdate.php | 151 ++ .../src/Formatter/Property/Recur.php | 210 +++ .../src/Formatter/Property/Requeststatus.php | 83 + .../src/Formatter/Property/SingleProps.php | 86 + .../src/Formatter/Property/Xproperty.php | 87 ++ .../icalcreator/src/Formatter/Valarm.php | 133 ++ .../src/Formatter/Vavailability.php | 173 +++ .../icalcreator/src/Formatter/Vcalendar.php | 120 ++ .../icalcreator/src/Formatter/Vevent.php | 269 ++++ .../icalcreator/src/Formatter/Vfreebusy.php | 141 ++ .../icalcreator/src/Formatter/Vjournal.php | 217 +++ .../icalcreator/src/Formatter/Vlocation.php | 101 ++ .../icalcreator/src/Formatter/Vresource.php | 96 ++ .../icalcreator/src/Formatter/Vtimzone.php | 91 ++ .../icalcreator/src/Formatter/Vtodo.php | 274 ++++ .../src/Parser/ComponentParser.php | 481 ++++++ .../icalcreator/src/Parser/ParserBase.php | 510 ++++++ .../src/Parser/VcalendarParser.php | 325 ++++ .../icalcreator/src/Participant.php | 184 +++ vendor/kigkonsult/icalcreator/src/Pc.php | 560 +++++++ .../src/Traits/ACKNOWLEDGEDrfc9074trait.php | 127 ++ .../src/Traits/BUSYTYPErfc7953trait.php | 125 ++ .../Traits/CALENDAR_ADDRESSrfc9073trait.php | 127 ++ .../src/Traits/LOCATIONTYPErfc9073trait.php | 126 ++ .../icalcreator/src/Traits/MvalTrait.php | 259 +++ .../src/Traits/NewVlocationTrait.php | 52 + .../Traits/PARTICIPANT_TYPErfc9073trait.php | 121 ++ .../src/Traits/PROXIMITYrfc9074trait.php | 125 ++ .../Traits/Participants2AttendeesTrait.php | 64 + .../src/Traits/RESOURCE_TYPErfc9073trait.php | 121 ++ .../Traits/STRUCTURED_DATArfc9073trait.php | 166 ++ .../Traits/STYLED_DESCRIPTIONrfc9073trait.php | 173 +++ .../src/Traits/SubCompsGetTrait.php | 142 ++ .../src/Traits/TZID_ALIAS_OFrfc7808trait.php | 157 ++ .../src/Traits/TZUNTILrfc7808trait.php | 134 ++ .../icalcreator/src/V2component.php | 61 + .../icalcreator/src/V3component.php | 117 ++ .../icalcreator/src/VAcomponent.php | 63 + .../icalcreator/src/Vavailability.php | 189 +++ .../kigkonsult/icalcreator/src/Vlocation.php | 140 ++ .../kigkonsult/icalcreator/src/Vresource.php | 138 ++ .../icalcreator/src/Xml/Formatter.php | 1382 +++++++++++++++++ .../kigkonsult/icalcreator/src/Xml/Parser.php | 729 +++++++++ .../icalcreator/src/Xml/XmlBase.php | 118 ++ .../icalcreator/test/Exception8Test.php | 197 +++ .../icalcreator/test/FactoryCompTest.php | 607 ++++++++ .../test/GetPropMethodNamesTrait.php | 55 + .../kigkonsult/icalcreator/test/ParseTest.php | 710 +++++++++ vendor/kigkonsult/icalcreator/test/PcTest.php | 266 ++++ .../icalcreator/test/Prop1TextSingleTest.php | 865 +++++++++++ .../icalcreator/test/Prop2TextMultiTest.php | 1351 ++++++++++++++++ .../icalcreator/test/Prop3Comp2PropTest.php | 233 +++ .../icalcreator/test/PropEmptyTest.php | 303 ++++ .../icalcreator/test/PropSortTest.php | 677 ++++++++ .../kigkonsult/icalcreator/test/PropXTest.php | 277 ++++ .../test/SelectComponentsTest2.php | 809 ++++++++++ .../icalcreator/test/StringfuncTest.php | 232 +++ .../kigkonsult/icalcreator/test/autoload.php | 71 + vendor/phpmailer/phpmailer/.editorconfig | 15 + .../phpmailer/language/phpmailer.lang-as.php | 35 + .../phpmailer/language/phpmailer.lang-bn.php | 35 + .../phpmailer/language/phpmailer.lang-ku.php | 27 + .../phpmailer/language/phpmailer.lang-si.php | 34 + .../phpmailer/language/phpmailer.lang-ur.php | 30 + .../phpmailer/src/DSNConfigurator.php | 245 +++ 85 files changed, 19845 insertions(+) create mode 100644 vendor/kigkonsult/icalcreator/docs/demoUsage.md create mode 100644 vendor/kigkonsult/icalcreator/docs/gpl-3.0.txt create mode 100644 vendor/kigkonsult/icalcreator/releaseNotes create mode 100644 vendor/kigkonsult/icalcreator/src/Available.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Available.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/DScomponent.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/FormatBase.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Participant.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/Attendee.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/CalMetProVer.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/Dt1Property.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/DtxProperty.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/DurDates.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/Exdate.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/Freebusy.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/Geo.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/IntProperty.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/MultiProps.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/Property.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/PropertyBase.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/Rdate.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/Recur.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/Requeststatus.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/SingleProps.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Property/Xproperty.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Valarm.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Vavailability.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Vcalendar.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Vevent.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Vfreebusy.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Vjournal.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Vlocation.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Vresource.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Vtimzone.php create mode 100644 vendor/kigkonsult/icalcreator/src/Formatter/Vtodo.php create mode 100644 vendor/kigkonsult/icalcreator/src/Parser/ComponentParser.php create mode 100644 vendor/kigkonsult/icalcreator/src/Parser/ParserBase.php create mode 100644 vendor/kigkonsult/icalcreator/src/Parser/VcalendarParser.php create mode 100644 vendor/kigkonsult/icalcreator/src/Participant.php create mode 100644 vendor/kigkonsult/icalcreator/src/Pc.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/ACKNOWLEDGEDrfc9074trait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/BUSYTYPErfc7953trait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/CALENDAR_ADDRESSrfc9073trait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/LOCATIONTYPErfc9073trait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/MvalTrait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/NewVlocationTrait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/PARTICIPANT_TYPErfc9073trait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/PROXIMITYrfc9074trait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/Participants2AttendeesTrait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/RESOURCE_TYPErfc9073trait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/STRUCTURED_DATArfc9073trait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/STYLED_DESCRIPTIONrfc9073trait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/SubCompsGetTrait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/TZID_ALIAS_OFrfc7808trait.php create mode 100644 vendor/kigkonsult/icalcreator/src/Traits/TZUNTILrfc7808trait.php create mode 100644 vendor/kigkonsult/icalcreator/src/V2component.php create mode 100644 vendor/kigkonsult/icalcreator/src/V3component.php create mode 100644 vendor/kigkonsult/icalcreator/src/VAcomponent.php create mode 100644 vendor/kigkonsult/icalcreator/src/Vavailability.php create mode 100644 vendor/kigkonsult/icalcreator/src/Vlocation.php create mode 100644 vendor/kigkonsult/icalcreator/src/Vresource.php create mode 100644 vendor/kigkonsult/icalcreator/src/Xml/Formatter.php create mode 100644 vendor/kigkonsult/icalcreator/src/Xml/Parser.php create mode 100644 vendor/kigkonsult/icalcreator/src/Xml/XmlBase.php create mode 100644 vendor/kigkonsult/icalcreator/test/Exception8Test.php create mode 100644 vendor/kigkonsult/icalcreator/test/FactoryCompTest.php create mode 100644 vendor/kigkonsult/icalcreator/test/GetPropMethodNamesTrait.php create mode 100644 vendor/kigkonsult/icalcreator/test/ParseTest.php create mode 100644 vendor/kigkonsult/icalcreator/test/PcTest.php create mode 100644 vendor/kigkonsult/icalcreator/test/Prop1TextSingleTest.php create mode 100644 vendor/kigkonsult/icalcreator/test/Prop2TextMultiTest.php create mode 100644 vendor/kigkonsult/icalcreator/test/Prop3Comp2PropTest.php create mode 100644 vendor/kigkonsult/icalcreator/test/PropEmptyTest.php create mode 100644 vendor/kigkonsult/icalcreator/test/PropSortTest.php create mode 100644 vendor/kigkonsult/icalcreator/test/PropXTest.php create mode 100644 vendor/kigkonsult/icalcreator/test/SelectComponentsTest2.php create mode 100644 vendor/kigkonsult/icalcreator/test/StringfuncTest.php create mode 100644 vendor/kigkonsult/icalcreator/test/autoload.php create mode 100644 vendor/phpmailer/phpmailer/.editorconfig create mode 100644 vendor/phpmailer/phpmailer/language/phpmailer.lang-as.php create mode 100644 vendor/phpmailer/phpmailer/language/phpmailer.lang-bn.php create mode 100644 vendor/phpmailer/phpmailer/language/phpmailer.lang-ku.php create mode 100644 vendor/phpmailer/phpmailer/language/phpmailer.lang-si.php create mode 100644 vendor/phpmailer/phpmailer/language/phpmailer.lang-ur.php create mode 100644 vendor/phpmailer/phpmailer/src/DSNConfigurator.php diff --git a/vendor/kigkonsult/icalcreator/docs/demoUsage.md b/vendor/kigkonsult/icalcreator/docs/demoUsage.md new file mode 100644 index 0000000..366fbf4 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/docs/demoUsage.md @@ -0,0 +1,232 @@ +# iCalcreator + +###### Demo usage + +``` php + "kigkonsult.se", ] ) + + // with calendaring info + ->setMethod( Vcalendar::PUBLISH ) + ->setXprop( Vcalendar::X_WR_CALNAME, "Calendar Sample" ) + ->setXprop( Vcalendar::X_WR_CALDESC, "This is a demo calendar" ) + ->setXprop( Vcalendar::X_WR_RELCALID, "3E26604A-50F4-4449-8B3E-E4F4932D05B5" ) + ->setXprop( Vcalendar::X_WR_TIMEZONE, "Europe/Stockholm" ); + + // create a new event +$event1 = $vcalendar->newVevent() + ->setTransp( Vcalendar::OPAQUE ) + ->setClass( Vcalendar::P_BLIC ) + ->setSequence( 1 ) + // describe the event + ->setSummary( 'Scheduled meeting with five occurrences' ) + ->setDescription( + 'Agenda for the the meeting...', + [ Vcalendar::ALTREP => 'CID:' ] + ) + ->setComment( 'It\'s going to be fun..' ) + // place the event + ->setLocation( 'Kafé Ekorren Stockholm' ) + ->setGeo( '59.32206', '18.12485' ) + // set the time + ->setDtstart( + new DateTime( + '20190421T090000', + new DateTimezone( 'Europe/Stockholm' ) + ) + ) + ->setDtend( + new DateTime( + '20190421T100000', + new DateTimezone( 'Europe/Stockholm' ) + ) + ) + // with recurrence rule + ->setRrule( + [ + Vcalendar::FREQ => Vcalendar::WEEKLY, + Vcalendar::COUNT => 5, + ] + ) + // and set another on a specific date + ->setRdate( + [ + new DateTime( + '20190609T090000', + new DateTimezone( 'Europe/Stockholm' ) + ), + new DateTime( + '20190609T110000', + new DateTimezone( 'Europe/Stockholm' ) + ), + ], + [ Vcalendar::VALUE => Vcalendar::PERIOD ] + ) + // and revoke a recurrence date + ->setExdate( + new DateTime( + '2019-05-12 09:00:00', + new DateTimezone( 'Europe/Stockholm' ) + ) + ) + // organizer, chair and some participants + ->setOrganizer( + 'secretary@coffeebean.com', + [ Vcalendar::CN => 'Secretary CoffeeBean' ] + ) + ->setAttendee( + 'president@coffeebean.com', + [ + Vcalendar::ROLE => Vcalendar::CHAIR, + Vcalendar::PARTSTAT => Vcalendar::ACCEPTED, + Vcalendar::RSVP => Vcalendar::FALSE, + Vcalendar::CN => 'President CoffeeBean', + ] + ) + ->setAttendee( + 'participant1@coffeebean.com', + [ + Vcalendar::ROLE => Vcalendar::REQ_PARTICIPANT, + Vcalendar::PARTSTAT => Vcalendar::NEEDS_ACTION, + Vcalendar::RSVP => Vcalendar::TRUE, + Vcalendar::CN => 'Participant1 CoffeeBean', + ] + ) + ->setAttendee( + 'participant2@coffeebean.com', + [ + Vcalendar::ROLE => Vcalendar::REQ_PARTICIPANT, + Vcalendar::PARTSTAT => Vcalendar::NEEDS_ACTION, + Vcalendar::RSVP => Vcalendar::TRUE, + Vcalendar::CN => 'Participant2 CoffeeBean', + ] + ); + + // add alarm for the event +$alarm = $event1->newValarm() + ->setAction( Vcalendar::DISPLAY ) + // copy description from event + ->setDescription( $event1->getDescription()) + // fire off the alarm one day before + ->setTrigger( '-P1D' ); + + // alter day and time for one event in recurrence set +$event2 = $vcalendar->newVevent() + ->setTransp( Vcalendar::OPAQUE ) + ->setClass( Vcalendar::P_BLIC ) + // reference to event in recurrence set + ->setUid( $event1->getUid()) + ->setSequence( 2 ) + // pointer to event in the recurrence set + ->setRecurrenceid( '20190505T090000 Europe/Stockholm' ) + // reason text + ->setDescription( + 'Altered day and time for event 2019-05-05', + [ + Vcalendar::ALTREP =>'CID:' + ] + ) + ->setComment( 'Now we are working hard for two hours' ) + // the altered day and time with duration + ->setDtstart( + new DateTime( + '20190504T100000', + new DateTimezone( 'Europe/Stockholm' ) + ) + ) + ->setDuration( 'PT2H' ) + // add alarm (copy from event1) + ->setComponent( $event1->getComponent( Vcalendar::VALARM )); + +$vcalendarString = + // apply appropriate Vtimezone with Standard/DayLight components + $vcalendar->vtimezonePopulate() + // and create the (string) calendar + ->createCalendar(); +``` + +And the content of the ```$vcalendarString``` : + +``` +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//kigkonsult.se//NONSGML kigkonsult.se iCalcreator 2.41.74// +METHOD:PUBLISH +X-WR-CALNAME:Calendar Sample +X-WR-CALDESC:This is a demo calendar +X-WR-RELCALID:3E26604A-50F4-4449-8B3E-E4F4932D05B5 +X-WR-TIMEZONE:Europe/Stockholm +BEGIN:VTIMEZONE +TZID:Europe/Stockholm +BEGIN:STANDARD +TZNAME:CET +DTSTART:20181028T030000 +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +RDATE:20191027T030000 +RDATE:20201025T030000 +END:STANDARD +BEGIN:DAYLIGHT +TZNAME:CEST +DTSTART:20190331T020000 +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +RDATE:20200329T020000 +END:DAYLIGHT +END:VTIMEZONE +BEGIN:VEVENT +UID:20190312T194303CET-3879fa226b@kigkonsult.se +DTSTAMP:20190312T184303Z +ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN=President CoffeeBean:MAILTO:presid + ent@coffeebean.com +ATTENDEE;RSVP=TRUE;CN=Participant1 CoffeeBean:MAILTO:participant1@coffeebea + n.com +ATTENDEE;RSVP=TRUE;CN=Participant2 CoffeeBean:MAILTO:participant2@coffeebea + n.com +COMMENT:It's going to be fun.. +CLASS:PUBLIC +DESCRIPTION;ALTREP="CID:": + Agenda for the the meeting... +DTSTART;TZID=Europe/Stockholm:20190421T090000 +DTEND;TZID=Europe/Stockholm:20190421T100000 +EXDATE;TZID=Europe/Stockholm:20190512T090000 +GEO:+59.32206;+18.12485 +LOCATION:Kafé Ekorren Stockholm +ORGANIZER;CN=Secretary CoffeeBean:MAILTO:secretary@coffeebean.com +RDATE;VALUE=PERIOD;TZID=Europe/Stockholm:20190609T090000/20190609T110000 +RRULE:FREQ=WEEKLY;COUNT=5 +SEQUENCE:1 +SUMMARY:Scheduled meeting with six occurrences +TRANSP:OPAQUE +BEGIN:VALARM +ACTION:DISPLAY +DESCRIPTION:Agenda for the the meeting... +TRIGGER:-P1D +END:VALARM +END:VEVENT +BEGIN:VEVENT +UID:20190312T194303CET-3879fa226b@kigkonsult.se +DTSTAMP:20190312T184303Z +COMMENT:Now we are working hard for two hours +CLASS:PUBLIC +DESCRIPTION;ALTREP="CID:": + Altered day and time for event 2019-05-05 +DTSTART;TZID=Europe/Stockholm:20190504T100000 +DURATION:PT2H +RECURRENCE-ID;TZID=Europe/Stockholm:20190505T090000 +SEQUENCE:2 +TRANSP:OPAQUE +BEGIN:VALARM +ACTION:DISPLAY +DESCRIPTION:Agenda for the the meeting... +TRIGGER:-P1D +END:VALARM +END:VEVENT +END:VCALENDAR +``` diff --git a/vendor/kigkonsult/icalcreator/docs/gpl-3.0.txt b/vendor/kigkonsult/icalcreator/docs/gpl-3.0.txt new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/docs/gpl-3.0.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/vendor/kigkonsult/icalcreator/releaseNotes b/vendor/kigkonsult/icalcreator/releaseNotes new file mode 100644 index 0000000..4a6c026 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/releaseNotes @@ -0,0 +1,308 @@ + +iCalcreator 2.29.18 releaseNotes + +v2.29.1 Removal of all set-methods date(time)/interval ARRAY arguments + as well as get-methods return date(time)/interval ARRAY formats + DTSTART, DTEND, DUE, RECURRENCE_ID + CREATED, COMPLETED, DTSTAMP, LAST_MODIFIED + +v2.29.2 Removal of all set-methods DateInterval ARRAY arguments + as well as get-methods return DateInterval ARRAY formats + REFRESH_INTERVAL, DURATION, TRIGGER + RDATE, EXDATE + FREEBUSY, RRULE, EXRULE + +v2.29.3 Rewrite of Vcalendar::parse() + only string|array input allowed, file/url parse removed + +v2.29.4 Removal of deprecated methods + Vcalendar::saveCalendar() + Vcalendar::useCachedCalendar() + + Vcalendar::deleteProperty() + Vcalendar::setProperty() + Vcalendar::addComponent() + + CalendarComponent::deleteProperty() + CalendarComponent::getProperty() + CalendarComponent::setProperty() + + VetComponent::newComponent() + VTimezone::newComponent() + + IcalXMLFactory::XMLfile2iCal() + IcalXMLFactory::XMLstr2iCal() + + Removal of deprecated config/keys + DELIMITER, DIRECTORY, FILENAME, DIRFILE, FILESIZE, FILEINFO + + All keys and (fixed) property values as constants available in IcalInterface + +v2.29.5 Implement rfc7986 + new properties; COLOR, NAME, CONFERENCE, IMAGE, REFRESH-INTERVAL, SOURCE + allow calendar-properties; UID, LAST-MODIFIED, URL, REFRESH-INTERVAL, SOURCE, + COLOR, NAME, DESCRIPTION, CATEGORIES, IMAGE + replace rfc5545 (date+unique_id) UID by rfc7986 guid UID + +v2.29.6 alter RRULE/EXRULE to single occurence + +v2.29.7 Allow iana-token (Other IANA-registered type) property PARAMETER names + For ACTION and CLASS, iana-token / x-name VALUES are allowed + However, IANA Properties still not supported + +v2.29.8 Vcalendar::sort() order adjustment + +v2.29.9 Conformed method names for Last-Modified, Request-Status, Related-to + +v2.29.10 fix other (Ms) timezones conversion to PHP timezones (ie map on offset) + in RegulateTimezoneFactory, to be used before Vcalendar::parse + +v2.29.11 code reworks: StringFactory, SortFactory, CalAddressFactory, *Traits etc + +v2.29.12 Vtimezone::populate() moved to Util/VtimezonePopulateFactory::process() + +v2.29.13 CATEGORIES, RESOURCES no longer accepts array input + +v2.29.14 String asserts in set-methods for TEXT Valuetype properties + +v2.29.15 Vcalendar::returnCalendar() new fileName arg + +v2.29.16 Methods with DateTime arg now accepts DateTimeInterface + +v2.29.17 assert for method exists + +v2.29.18 xml header update + +v2.29.20 PHP 7.4 compability (Util/DateIntervalFactory, Util/StringFactory) + +v2.29.21 more 2.29.16 (DateTimeFactory, RecurFactory) +v2.29.22 Issue #88, code style, PHP 7+ compability +v2.29.23 StringFactory needle/haystack functions + +v2.29.24 Issue #87, RecurFactory split in 2, reworked + more recur improved select base methods + +v2.29.25 bug RecurFactory::setRexRule() + RecurFactory2::assertRecur() rules + + +v2.29.26 bug RecurFactory, BYDAY + +v2.20.27 docs: setCategories/setResources don't accepts array parameter + setRrule(/setExrule) allows only one in component + +v2.29.28 bug RecurFactory2::recurWeekly2() + +v2.29.29 bug StringFactory::size75(), max rowlength + + +v2.29.30 Issue #89 URL adapt, strip of value opt (urlencoded) prefix/suffix '<>' + (IcalXMLFactory) SOURCE value-type conform + +v2.29.30b More issue #89 URL adapt, parse parameter + + + +v3.30.2 #89, URL (TZURL/SOURCE) for rfc (prescribed) property value, + parameter VALUE type URI removed, parse adapt + ParameterFactory::ifExistRemove() + StringFactory::splitContent() + StringFactory::colonIsPrefixedByProtocol() + HttpFcatory::urlSet() + URLTrait::setUrl() (also TZURL/SOURCE traits) + + +v3.30.3 #89, URL (TZURL/SOURCE) value prefix (protocol) + StringFactory::splitContent() / checkFixUriValue() + HttpFcatory::urlSet() + IcalXMLFactory::addXMLchildUri() / XMLgetProps() + + +v3.39 3.4 release candidate + PHP 7 (PHPStan/strict types) + iCalBase static methodName methods moved to StringFactory + iCalBase Component multi-prop methods moved to CalendarComponent + CalAddressFactory::getCalAddresses() arg inclParams removed + TRIGGERtrait : setTrigger() bug fix + ATTENDEE/ORGANIZER (CalAddressFactory) + value MAILTO prefix + parameter EMAIL etc logic upd + IcalvCard::iCal2vCards() arg bug + + +2.40 PHP8 + +2.40.1 removal of ext-debug in cmposer.json + +2.40.2 test RecurMonthTest/RecurYearTest upd +2.40.3 PHP8 upd +2.40.4 Selectfactory::selectComponents bug + flat:false, any:true, split:false + DAILY, over night github#95 + phpunit tests + +2.40.5 removal of ext-debug in cmposer.json.... + +2.40.6 more DAILY, over night github#95 + +2.40.7 more DAILY, over night github#95 + +2.40.8 github#98 setConfig arg + +2.40.9 more DAILY, over night github#95 +2.40.10 recur bug, RecurFactory2 + + +2.40.11 more PHP8 updates, StringFactory::getRandChars() upd + +2.41.1 rfc7808 new Vtimezone properties TZID-ALIAS-OF/TZUNTIL +2.41.2 rfc9074 new Valarm properties: UID, RELATED-TO, ACKNOWLEDGED, PROXIMITY +2.41.3 rfc9073 new properties, + for Vevent, Vtodo, Vjournal : STRUCTURED-DATA + for Vevent, Vtodo, Vjournal, Valarm : STYLED_DESCRIPTION +2.41.4 rfc9073 new component PARTICIPANT + with new properties CALENDAR-ADDRESS/PARTICIPANT-TYPE + new Vcalendar/component method participants2Attendees() +2.41.5 rfc9073 new subComponent VLOCATION + with new property LOCATION-TYPE +2.41.6 method(s) Vcalendar/caledarComponent::getComponent() moved to IcalBase +2.41.7 rfc9073 new subComponent VRESOURCE + with new property RESOURCE-TYPE + restructure of abstract classes +2.41.8 (new) signatures of newValarm, newParticipant, newVlocation, newVresource methods +2.41.9 rfc7953 new component VAVAILABILITY + with new property BUSYTYPE + rfc7953 new component AVAILABLE + NO support for AVAILABLE in Vcalendar::selectComponents() +2.41.10 upd VtimezonePopulateFactory::process(), accept multiple timeszones + arg timezone as string|string[] +2.41.11 rfc9074 new Valarm sub-component VLOCATION +2.41.14 rfc 6868 Parameter Value Encoding in iCalendar and vCard TEST +2.41.12 rfc5870 Uniform Resource Identifier for Geographic Locations ('geo' URI) + rfc9073 (7.2. Location) defines VLOCATION with a GEO property + rfc9074 (8. Alarm Proximity Trigger) add VLOCATION(s) to VALARM + with a URL 'geo' URI [RFC5870] property + As for now, accept + VLOCATION with properties URL (with 'geo' URI) and GEO (without) + any Vcalendar component with URL and with 'geo' URI + any ?? or only VLOCATION URL +2.41.13 Icalbase::$OTHERPROPS renamed to $SELSORTPROPS +2.41.14 DateTimeFactory::setDate() will also use ParameterFactory::setParams() +2.41.15 rfc6868 Parameter Value Encoding in iCalendar and vCard +2.41.16 rfc7529 Non-Gregorian Recurrence Rules in the Internet Calendaring and + Scheduling Core Object Specification (iCalendar) + new RRULE elements RSCALE, SKIP accepted + For Vcalendar::selectComponents(), if RRULE RSCALE set only GREGORIAN accepted + + +2.41.17 Vcalendar/component method participants2Attendees() upd (Participant uid+type as x-params) +2.41.18 using.html doc upd +2.41.19 Vcalendar/Vevent/Vtodo method vlocationNames2Locations()() upd (Vlocation uid+type as x-params) + upd args component::newVLocation( [ type [, name ]] ) +2.41.20 upd multi Decription +2.41.21 Vcalendar/Vevent/Vtodo method vresourceNames2Resources() upd (Vresource uid+type as x-params) + upd args component::newVresource( [ type [, name ]] ) +2.41.22 upd args Vcalendar::newVavailability( [ busytype [, start [, end [, duration ]]]] ) +2.41.23 upd args Vcalendar::newVtimezone( [ tzid ] ) +2.41.24 upd args Vcalendar::newVevent( [ dtstart [, dtend [, duration [, summary ]]]] ) +2.41.25 upd signatures of newValarm, accepts DateTimeInterface +2.41.26 upd args Vcalendar::newVtodo( [ dtstart [, due [, duration [, summary ]]]] ) +2.41.27 upd args Vcalendar::newVJournal( [ dtstart [, summary ]] ) +2.41.28 upd args Vcalendar::newVfreebusy( [ dtstart [, dtend [, duration ]]] ) + bug component::setDtend() +2.41.29 upd createCalendar/createComponent methods +2.41.30 Vcalendar/Component::getXprop() consecutive invokes bug + + +2.41.31 Parsetest upd +2.41.32 doc upd GEO/NAME component occurence + CONTACT/DESCRIPTION/LOCATION/NAME property get-methods and + IcalXMLFactory::compProps2Xml() logic +2.41.33 Vcalendar::setComponents() bug, insert Vtimezone(s) first (not last) +2.41.34 upd participants2Attendees() : Participant-type to (ATTENDEE) parameter ROLE + +2.41.35 new Component::isset() methods + +2.41.36 All property contents are now (class) Pc, an ArrayObject extend class + get methods return property->value or Pc (dep. arg inclParam) + For get return: $return::{'value'} (params) <=> $return->value (params) + Pc has also getter/setter methods etc + rewrite Vcalendar/Component::set methods + Vcalendar/Component::set methods accepts Pc as first arg + +2.41.37 Component::createAttendee() param format bug +2.41.38 Altered Freebusy::getFreebusy() output, fbBusyType now in params +2.41.39 Multi-properties help methods moved to trait + +2.41.40 Component::getRequeststatus() bug, return array +2.41.41 Component::getExrule() bug, return bool|array|Pc +2.41.42 Pc::getParams() new arg (bool) asXparamkey +2.41.43 int property value Component::is/set-mehods bug + +2.41.44 github::#101, Tzuntil trait bug and upd logic + +2.41.45 github::#99, SelectFactoy::selectComponents() bug +2.41.46 github::#100, Component::getExdate() bug, return bool|array|Pc + +2.41.47 Extended tests +2.41.48 Refresh_interval trait bug +2.41.49 Calendar parse upd + +2.41.50 vCalendar/CalenadarComponent::getComponents() +2.41.51 ALL multi-props have method, return array, values only / full +2.41.52 opt URI (email) mailto-prefix in lowercase +2.41.53 new class factory methods, upd class constructs + removed deleteDtstamp/deleteUid methods (use set-method to recreate) +2.41.54 moved Vcalendar/Component parser logic to parser classes +2.41.55 moved Vcalendar/Component format logic to formatter classes +2.41.56 Vtimezone, Util and misc code tidy up... + +2.41.57 GitHub#103 (non-PHP timezones) + Note Vtimezone::TZID property still accepts any timezone, + RegulateTimezoneFactory deprecated (RegulateTimezoneFactoryTest removed) + +2.41.58 upd (Traits/) getAll-methods return type +2.41.59 code clean up, phpdoc args etc +2.41.60 setTzOffset conform logic + +2.41.61 GitHub#104 (TZUNTIL bug) + +2.41.62 Geo/Version property (empty-)bug + +2.41.63 new Pc::getValueParam() method + upd Property parameters format logic + +2.41.64 SelectFactory method argument typing + +2.41.65 upd Pc::getParams() return types +2.41.66 upd tests and format property output logic +2.41.67 DateTimeInterface adapt + +2.41.68 more code clean up, methods args etc +2.41.69 Util/IcalXMLFactory split up in Xml/Formatter+Parser +2.41.70 more 2.41.57 (timezones) + +2.41.71 recur bug, Github #105, Leading semicolon in RRULE + recur BYDAY input logic rework +2.41.73 timezone bug, Github #106, + The isUTCtimeZone method does not work properly all the time +2.41.74 demo bug, Github #107 + +2.41.75 DateInterval bug, github #109 +2.41.76 github #110, code clean up, phpdoc, args etc + +2.41.78 DateInterval bug, github #109 +2.41.79 github #112, Sequence (int) trim, Util +2.41.80 github #112, non-mailto Organizer, ORGANIZERtrait + +2.41.81 github #113, trait URL/TZURL/SOURCE rtrim + +2.41.82 DateInterval bug, github #109 +2.41.83 DateTime timezone bug, github #114 + +2.41.84 composer.json upd +2.41.85 major upd class Pc (+Traits/*) +2.41.86 upd DateIntervalFactory +2.41.87 upd tests +2.41.88 code rewrites, Xml\Formatter+Parser, Formatter/* etc +2.41.89 ParameterFactory deprecated +2.41.90 upd StringFactory diff --git a/vendor/kigkonsult/icalcreator/src/Available.php b/vendor/kigkonsult/icalcreator/src/Available.php new file mode 100644 index 0000000..c0c02c3 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Available.php @@ -0,0 +1,156 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator; + +use DateInterval; +use DateTimeInterface; +use Exception; +use InvalidArgumentException; +use Kigkonsult\Icalcreator\Formatter\Available as Formatter; + +/** + * iCalcreator rfc7953 Available component class + * + * @since 2.41.55 - 2022-08-13 + */ +final class Available extends VAcomponent +{ + // the following are OPTIONAL but MUST NOT occur more than once (and NOT declared in VAcomponent) + use Traits\RECURRENCE_IDtrait; + use Traits\RRULEtrait; + + // the following are OPTIONAL and MAY occur more than once (and NOT declared in VAcomponent) + use Traits\EXDATEtrait; + use Traits\RDATEtrait; + + /** + * @var string + */ + protected static string $compSgn = 'av'; + + /** + * Constructor + * + * @param null|string[] $config + * @throws Exception + * @since 2.41.53 - 2022-08-11 + */ + public function __construct( ? array $config = [] ) + { + parent::__construct( $config ); + $this->setDtstamp(); + $this->setUid(); + } + + /** + * Return Available object instance + * + * @param null|string[] $config + * @param null|string|DateTimeInterface $dtstart + * @param null|string|DateTimeInterface $dtend + * @param null|string|DateInterval $duration + * @return Available + * @throws InvalidArgumentException + * @throws Exception + * @since 2.41.53 - 2022-08-08 + */ + public static function factory( + ? array $config = [], + null|string|DateTimeInterface $dtstart = null, + null|string|DateTimeInterface $dtend = null, + null|string|DateInterval $duration = null + ) : Available + { + $instance = new Available( $config ); + if( null !== $dtstart ) { + $instance->setDtstart( $dtstart ); + } + if( null !== $dtend ) { + $instance->setDtend( $dtend ); + } + elseif( null !== $duration ) { + $instance->setDuration( $duration ); + } + return $instance; + } + + /** + * Destructor + * + * @since 2.41.3 2022-01-17 + */ + public function __destruct() + { + unset( + $this->compType, + $this->xprop, + $this->components, + $this->config, + $this->compix, + $this->propIx, + $this->propDelIx + ); + unset( + $this->cno, + $this->srtk + ); + unset( + $this->categories, + $this->comment, + $this->contact, + $this->created, + $this->description, + $this->dtstamp, + $this->dtstart, + $this->dtend, + $this->duration, + $this->exdate, + $this->lastmodified, + $this->location, + $this->recurrenceid, + $this->rdate, + $this->rrule, + $this->summary, + $this->uid + ); + } + + /** + * Return formatted output for calendar component Available object instance + * + * @return string + * @throws Exception (on Duration/Rdate err) + * @since 2.41.55 2022-08-13 + */ + public function createComponent() : string + { + return Formatter::format( $this ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Available.php b/vendor/kigkonsult/icalcreator/src/Formatter/Available.php new file mode 100644 index 0000000..8cbfdef --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Available.php @@ -0,0 +1,149 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Available as Source; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.55 - 2022-08-12 + */ +final class Available extends FormatBase +{ + /** + * @param CalendarComponent|Source $source + * @return string + * @throws Exception + */ + public static function format( CalendarComponent|Source $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + $output = + sprintf( self::$FMTBEGIN, $compType ) . + Property\Property::format( + self::UID, + $source->getUid( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::DTSTAMP, + $source->getDtstamp( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::CATEGORIES, + $source->getAllCategories( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::COMMENT, + $source->getAllComment( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::CONTACT, + $source->getAllContact( true ), + $allowEmpty, + $lang + ) . + Property\DtxProperty::format( + self::CREATED, + $source->getCreated( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::DESCRIPTION, + $source->getAllDescription( true ), + $allowEmpty, + $lang + ); + $dtStart = $source->getDtstart( true ); + $output .= Property\Dt1Property::format( + self::DTSTART, + $dtStart, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart ), + Property\Dt1Property::getIsLocalTime( $dtStart ) + ); + $dtEnd = $source->getDtend( true ); + $output .= Property\Dt1Property::format( + self::DTEND, + $dtEnd, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart, $dtEnd ), + Property\Dt1Property::getIsLocalTime( $dtEnd ) + ) . + Property\DurDates::format( + self::DURATION, + $source->getDuration( true ), + $allowEmpty + ) . + Property\Exdate::format( + self::EXDATE, + $source->getAllExdate( true ), + $allowEmpty + ) . + Property\Recur::format( + self::RRULE, + $source->getRrule( true ), + $allowEmpty + ); + $reCurrId = $source->getRecurrenceid( true ); + $output .= + Property\Dt1Property::format( + self::RECURRENCE_ID, + $reCurrId, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart, $reCurrId ), + Property\Dt1Property::getIsLocalTime( $reCurrId ) + ) . + Property\SingleProps::format( + self::SUMMARY, + $source->getSummary( true ), + $allowEmpty, + $lang + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ) . + sprintf( self::$FMTEND, $compType ) ; + return $output; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/DScomponent.php b/vendor/kigkonsult/icalcreator/src/Formatter/DScomponent.php new file mode 100644 index 0000000..bfce061 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/DScomponent.php @@ -0,0 +1,104 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Daylight as Source1; +use Kigkonsult\Icalcreator\Standard as Source2; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.55 - 2022-08-13 + */ +final class DScomponent extends FormatBase +{ + /** + * @param CalendarComponent|Source1|Source2 $source + * @return string + * @throws Exception + */ + public static function format( CalendarComponent|Source1|Source2 $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + return + sprintf( self::$FMTBEGIN, $compType ) . + Property\MultiProps::format( + self::TZNAME, + $source->getAllTzname( true ), + $allowEmpty, + $lang + ) . + Property\Dt1Property::format( + self::DTSTART, + $source->getDtstart( true ), + $allowEmpty, + false, + true + ) . + Property\Property::format( + self::TZOFFSETFROM, + $source->getTzoffsetfrom( true ), + $allowEmpty + ) . + Property\Property::format( + self::TZOFFSETTO, + $source->getTzoffsetto( true ), + $allowEmpty + ) . + Property\Rdate::format( + self::RDATE, + $source->getAllRdate( true ), + $allowEmpty, + $source->getCompType() + ) . + Property\Recur::format( + self::RRULE, + $source->getRrule( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::COMMENT, + $source->getAllComment( true ), + $allowEmpty, + $lang + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ) . + sprintf( self::$FMTEND, $compType ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/FormatBase.php b/vendor/kigkonsult/icalcreator/src/Formatter/FormatBase.php new file mode 100644 index 0000000..8d941b3 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/FormatBase.php @@ -0,0 +1,96 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\IcalInterface; +use Kigkonsult\Icalcreator\Vcalendar; + +abstract class FormatBase implements IcalInterface +{ + /** + * @var string + */ + protected static string $FMTBEGIN = "BEGIN:%s\r\n"; + + /** + * @var string + */ + protected static string $FMTEND = "END:%s\r\n"; + + /** + * @var string + */ + protected static string$SP0 = ''; + + /** + * @param CalendarComponent $component + * @return string + * @throws Exception + */ + protected static function formatComponent( CalendarComponent $component ) : string + { + switch( $component->getCompType()) { + case self::AVAILABLE : return Available::format( $component ); + case self::DAYLIGHT : return DScomponent::format( $component ); + case self::PARTICIPANT : return Participant::format( $component ); + case self::STANDARD : return DScomponent::format( $component ); + case self::VALARM : return Valarm::format( $component ); + case self::VAVAILABILITY : return Vavailability::format( $component ); + case self::VEVENT : return Vevent::format( $component ); + case self::VFREEBUSY : return Vfreebusy::format( $component ); + case self::VJOURNAL : return Vjournal::format( $component ); + case self::VLOCATION : return Vlocation::format( $component ); + case self::VRESOURCE : return Vresource::format( $component ); + case self::VTIMEZONE : return Vtimzone::format( $component ); + case self::VTODO : return Vtodo::format( $component ); + } // end switch + return self::$SP0; + } + + /** + * Return formatted output for subcomponents + * + * @param Vcalendar|CalendarComponent $component + * @return string + * @since 2.41.55 2022-08-13 + * @throws Exception (on Valarm/Standard/Daylight) err) + */ + protected static function formatSubComponents( Vcalendar|CalendarComponent $component ) : string + { + $config = $component->getConfig(); + $output = self::$SP0; + foreach( $component->getComponents() as $subComp ) { + $output .= self::formatComponent( $subComp->setConfig( $config, false, true )); + } + return $output; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Participant.php b/vendor/kigkonsult/icalcreator/src/Formatter/Participant.php new file mode 100644 index 0000000..9d413db --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Participant.php @@ -0,0 +1,190 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Participant as Source; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.55 - 2022-08-13 + */ +final class Participant extends FormatBase +{ + /** + * @param CalendarComponent|Source $source + * @return string + * @throws Exception + */ + public static function format( CalendarComponent|Source $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + return + sprintf( self::$FMTBEGIN, $compType ) . + Property\Property::format( + self::UID, + $source->getUid( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::DTSTAMP, + $source->getDtstamp( true ), + $allowEmpty + ) . + Property\Property::format( + self::PARTICIPANT_TYPE, + $source->getParticipanttype( true ), + $allowEmpty + ) . + Property\Property::format( + self::CALENDAR_ADDRESS, + $source->getCalendaraddress( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::CONTACT, + $source->getAllContact( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::LOCATION, + $source->getAllLocation( true ), + $allowEmpty, + $lang + ) . + Property\DtxProperty::format( + self::CREATED, + $source->getCreated( true ), + $allowEmpty + ) . + Property\SingleProps::format( + self::SUMMARY, + $source->getSummary( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::DESCRIPTION, + $source->getAllDescription( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::STYLED_DESCRIPTION, + $source->getAllStyleddescription( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::STRUCTURED_DATA, + $source->getAllStructureddata( true ), + $allowEmpty, + $lang + ) . + Property\Geo::format( + self::GEO, + $source->getGeo( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::LAST_MODIFIED, + $source->getLastmodified( true ), + $allowEmpty + ) . + Property\IntProperty::format( + self::PRIORITY, + $source->getPriority( true ), + $allowEmpty + ) . + Property\IntProperty::format( + self::SEQUENCE, + $source->getSequence( true ), + $allowEmpty + ) . + Property\Property::format( + self::STATUS, + $source->getStatus( true ), + $allowEmpty + ) . + Property\Property::format( + self::URL, + $source->getUrl( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::ATTACH, + $source->getAllAttach( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::CATEGORIES, + $source->getAllCategories( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::COMMENT, + $source->getAllComment( true ), + $allowEmpty, + $lang + ) . + Property\Requeststatus::format( + self::REQUEST_STATUS, + $source->getAllRequeststatus( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::RELATED_TO, + $source->getAllRelatedto( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::RESOURCES, + $source->getAllResources( true ), + $allowEmpty, + $lang + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ) . + self::formatSubComponents( $source ) . + sprintf( self::$FMTEND, $compType ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/Attendee.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Attendee.php new file mode 100644 index 0000000..3462a8b --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Attendee.php @@ -0,0 +1,215 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Kigkonsult\Icalcreator\Pc; + +use Kigkonsult\Icalcreator\Util\StringFactory; +use function array_keys; +use function implode; +use function in_array; +use function is_array; +use function sprintf; +use function str_contains; + +/** + * Format ATTENDEE + * + * 1 + * @since 2.41.88 - 2024-01-18 + */ +final class Attendee extends PropertyBase +{ + /** + * @var string + */ + private static string $FMT = ';%s=%s'; + + /** + * @param string $propName + * @param Pc[] $values + * @param bool|null $allowEmpty + * @return string + * @since 2.41.88 - 2024-01-18 + */ + public static function format( string $propName, array $values, ? bool $allowEmpty = true ) : string + { + static $AllKeys = [ + self::CUTYPE, self::MEMBER, self::ROLE, self::PARTSTAT, self::RSVP, self::DELEGATED_TO, + self::DELEGATED_FROM, self::SENT_BY, self::EMAIL, self::DIR, self::CN, self::LANGUAGE + ]; + static $KEYGRP1 = [ self::ROLE, self::PARTSTAT, self::RSVP ]; + static $KEYGRP2 = [ self::DELEGATED_TO, self::DELEGATED_FROM ]; + static $KEYGRP3 = [ self::SENT_BY, self::EMAIL ]; + static $KEYGRP4 = [ self::CN, self::LANGUAGE ]; + if( empty( $values )) { + return StringFactory::$SP0; + } + $output = StringFactory::$SP0; + foreach( array_keys( $values ) as $aPix ) { + $attendeePart = clone $values[$aPix]; // Pc + $pcValue = $attendeePart->getValue(); + if( ! $attendeePart->isset() || empty( $pcValue )) { + if( $allowEmpty ) { + $output .= self::renderProperty( $propName ); + } + continue; + } + $pcParams = (array) $attendeePart->getParams(); + if( empty( $pcParams)) { + $output .= self::renderProperty( $propName, null, $pcValue ); + continue; + } + $aParams = self::fixOptQuotesForParamValue( $pcParams ); + $attributes = StringFactory::$SP0; + /* set attendee parameters in (almost) rfc2445 order */ + if( isset( $aParams[self::CUTYPE] )) { + $attributes .= sprintf( self::$FMT, self::CUTYPE, (string) $aParams[self::CUTYPE] ); + } + if( isset( $aParams[self::MEMBER] )) { + $attributes .= self::renderQuotedListItems( self::MEMBER, $aParams[self::MEMBER] ); + } + foreach( $KEYGRP1 as $key ) { // ROLE, PARTSTAT, RSVP + if( isset( $aParams[$key] )) { + $attributes .= sprintf( self::$FMT, $key, (string) $aParams[$key] ); + } + } // end foreach + foreach( $KEYGRP2 as $key ) { // DELEGATED_TO, DELEGATED_FROM + if( isset( $aParams[$key] )) { + $attributes .= self::renderQuotedListItems( $key, $aParams[$key] ); + } + } // end foreach + foreach( $KEYGRP3 as $key ) { // SENT_BY, EMAIL + if( isset( $aParams[$key] )) { + $attributes .= sprintf( self::$FMT, $key, (string) $aParams[$key] ); + } + } // end foreach + if( isset( $aParams[self::DIR] )) { + $attributes .= self::renderDirParam((string) $aParams[self::DIR] ); + } + foreach( $KEYGRP4 as $key ) { // CN, LANGUAGE + if( isset( $aParams[$key] )) { + $attributes .= sprintf( self::$FMT, $key, (string) $aParams[$key] ); + } + } // end foreach + $xParams = []; + foreach( $aParams as $pLabel2 => $pValue2 ) { + if( ! in_array( $pLabel2, $AllKeys, true )) { + $xParams[$pLabel2] = $pValue2; + } + } + if( ! empty( $xParams )) { + ksort( $xParams, SORT_STRING ); + foreach( $xParams as $pLabel2 => $pValue2 ) { + $attributes .= sprintf( self::$FMT, $pLabel2, (string) $pValue2 ); + } + } + $output .= self::renderProperty( $propName, $attributes, $pcValue ); + } // end foreach( $pc->value as $ax => $attendeePart ) + return $output; + } + + /** + * Fix opt quoted param values, all but DELEGATED-FROM, DELEGATED-TO, MEMBER + * + * @param string[]|string[][] $aParams + * @return string[]|string[][] + * @since 2.41.68 - 2019-10-24 + */ + private static function fixOptQuotesForParamValue( array $aParams ) : array + { + static $ParamArrayKeys = [ + self::MEMBER, + self::DELEGATED_TO, + self::DELEGATED_FROM, + ]; + $output = []; + foreach( $aParams as $pLabel2 => $pValue2 ) { // fix (opt) quotes + if( is_array( $pValue2 ) || in_array( $pLabel2, $ParamArrayKeys, true )) { + $output[$pLabel2] = $pValue2; + continue; + } + $pValue3 = self::circumflexQuoteInvoke( $pValue2 ); + $output[$pLabel2] = self::hasColonOrSemicOrComma( $pValue3 ) + ? self::getQuotedItem( $pValue3 ) + : $pValue3; + } // end foreach + return $output; + } + + /** + * Return quoted item + * + * @param string $item + * @return string + * @since 2.27.11 - 2019-01-03 + */ + private static function getQuotedItem( string $item ) : string + { + static $FMTQVALUE = '"%s"'; + return sprintf( $FMTQVALUE, $item ); + } + + /** + * Return string. attribute with opt comma-separated quoted array members + * + * @param string $pLabel + * @param string|string[] $list + * @return string + * @since 2.41.88 - 2024-01-17 + */ + private static function renderQuotedListItems( string $pLabel, string|array $list ) : string + { + if( ! is_array( $list )) { + $list = [ $list ]; + } + foreach( $list as $x => $v ) { + $list[$x] = self::getQuotedItem( $v ); + } + return sprintf( + self::$FMT, + $pLabel, + implode( StringFactory::$COMMA, $list ) + ); + } + + /** + * Return rendered DIR param + * @param string $dir + * @return string + */ + private static function renderDirParam( string $dir ) : string + { + static $QQ = '"'; + static $FMTDIREQ = ';%s=%s%s%s'; + $delim = str_contains( $dir, $QQ ) ? StringFactory::$SP0 : $QQ; + return sprintf( $FMTDIREQ, self::DIR, $delim, $dir, $delim ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/CalMetProVer.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/CalMetProVer.php new file mode 100644 index 0000000..83e3ef9 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/CalMetProVer.php @@ -0,0 +1,53 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Kigkonsult\Icalcreator\Util\StringFactory; +use function sprintf; + +/** + * Format CALSCALE, METHOD, PRODID, VERSION + * + * 4 + * @since 2.41.55 - 2022-08-12 + */ +final class CalMetProVer extends PropertyBase +{ + /** + * @param string $propName + * @param null|bool|string $value + * @return string + */ + public static function format( string $propName, null|bool|string $value ) : string + { + static $FMTICAL = "%s:%s\r\n"; + return empty( $value ) ? StringFactory::$SP0 : sprintf( $FMTICAL, $propName, $value ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/Dt1Property.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Dt1Property.php new file mode 100644 index 0000000..ab5fa1f --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Dt1Property.php @@ -0,0 +1,93 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Exception; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\DateTimeFactory; +use Kigkonsult\Icalcreator\Util\StringFactory; + +/** + * Format DTSTART, RECURRENCE_ID and DUE, DTEND (has spec cond on DATE-format) + * + * 4 + * @since 2.41.88 2024-01-18 + */ +final class Dt1Property extends PropertyBase +{ + /** + * @param string $propName + * @param null|bool|Pc $pc + * @param null|bool $allowEmpty + * @param null|bool $isDate + * @param null|bool $isLocalTime + * @return string + * @throws Exception + */ + public static function format( + string $propName, + null|bool|Pc $pc, + ? bool $allowEmpty = true, + ? bool $isDate = false, + ? bool $isLocalTime = false + ) : string + { + if( empty( $pc )) { + return StringFactory::$SP0; + } + $pcValue = $pc->getValue(); + return empty( $pcValue ) + ? self::renderSinglePropEmpty( $propName, $allowEmpty ) + : self::renderProperty( + $propName, + $pc->getParams(), + DateTimeFactory::dateTime2Str( $pcValue, $isDate, $isLocalTime ) + ); + } + + /** + * @param bool|Pc $dtStart + * @param null|bool|Pc $endDue + * @return bool + */ + public static function getIsDate( bool | Pc $dtStart, null | bool | Pc $endDue = null ) : bool + { + return match ( true ) { + ! empty( $dtStart ) => $dtStart->hasParamValue( self::DATE ), + ! empty( $endDue ) => $endDue->hasParamValue( self::DATE ), + default => false + }; + } + + public static function getIsLocalTime( null | bool | Pc $dtDate ) : bool + { + return ( ! empty( $dtDate ) && $dtDate->hasParamIsLocalTime()); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/DtxProperty.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/DtxProperty.php new file mode 100644 index 0000000..b980ef3 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/DtxProperty.php @@ -0,0 +1,67 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Exception; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\DateTimeFactory; +use Kigkonsult\Icalcreator\Util\StringFactory; + +/** + * Format ACKNOWLEDGED, COMPLETED, CREATED, DTSTAMP, LAST_MODIFIED, TZUNTIL + * + * 6 + * @since 2.41.88 2024-01-18 + */ +final class DtxProperty extends PropertyBase +{ + /** + * @param string $propName + * @param null|bool|Pc $pc + * @param bool|null $allowEmpty + * @return string + * @throws Exception + * @since 2.41.88 2024-01-18 + */ + public static function format( string $propName, null|bool|Pc $pc, ? bool $allowEmpty = true ) : string + { + if( empty( $pc )) { + return StringFactory::$SP0; + } + $pcValue = $pc->getValue(); + return empty( $pcValue ) + ? self::renderSinglePropEmpty( $propName, $allowEmpty ) + : self::renderProperty( + $propName, + $pc->getParams(), + DateTimeFactory::dateTime2Str( $pcValue ) + ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/DurDates.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/DurDates.php new file mode 100644 index 0000000..2ee9ae8 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/DurDates.php @@ -0,0 +1,72 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use DateInterval; +use Exception; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\DateIntervalFactory; +use Kigkonsult\Icalcreator\Util\DateTimeFactory; +use Kigkonsult\Icalcreator\Util\StringFactory; + +/** + * Format DURATION, REFRESH_INTERVAL, TRIGGER + * + * 3 + * @since 2.41.88 2024-01-18 + */ +final class DurDates extends PropertyBase +{ + /** + * @param string $propName + * @param null|bool|Pc $pc + * @param bool|null $allowEmpty + * @return string + * @throws Exception + * @since 2.41.88 2024-01-18 + */ + public static function format( string $propName, null|bool|Pc $pc, ? bool $allowEmpty = true ) : string + { + if( empty( $pc )) { + return StringFactory::$SP0; + } + $pcValue = $pc->getValue(); + return empty( $pcValue ) + ? self::renderSinglePropEmpty( $propName, $allowEmpty ) + : self::renderProperty( + $propName, + $pc->getParams(), + (( $pcValue instanceof DateInterval ) + ? DateIntervalFactory::dateInterval2String( $pcValue, ( self::TRIGGER === $propName )) + : DateTimeFactory::dateTime2Str( $pcValue ) + ) + ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/Exdate.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Exdate.php new file mode 100644 index 0000000..145c05a --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Exdate.php @@ -0,0 +1,136 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use DateTime; +use Exception; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\DateTimeFactory; + +use Kigkonsult\Icalcreator\Util\StringFactory; +use function count; +use function reset; +use function strcmp; +use function usort; + +/** + * Format EXDATE + * + * 1 + * @since 2.41.88 2024-01-18 + */ +final class Exdate extends PropertyBase +{ + /** + * @param string $propName + * @param Pc[] $values + * @param bool|null $allowEmpty + * @return string + * @throws Exception + * @since 2.41.88 2024-01-18 + */ + public static function format( string $propName, array $values, ? bool $allowEmpty = true ) : string + { + static $SORTER1 = [ __CLASS__, 'sortExdate1', ]; + static $SORTER2 = [ __CLASS__, 'sortExdate2', ]; + if( empty( $values )) { + return StringFactory::$SP0; + } + $output = StringFactory::$SP0; + $exdates = []; + foreach( $values as $theExdate ) { // Pc + $theExdateValue = $theExdate->getValue(); + if( empty( $theExdateValue )) { + if( $allowEmpty ) { + $output .= self::renderProperty( $propName ); + } + continue; + } + if( 1 < count( $theExdateValue )) { + usort( $theExdateValue, $SORTER1 ); + $theExdate->setValue( $theExdateValue ); + } + $exdates[] = $theExdate; + } // end foreach + if( 1 < count( $exdates )) { + usort( $exdates, $SORTER2 ); + } + $eix = 0; + foreach( $exdates as $theExdate ) { // Pc + $content = StringFactory::$SP0; + foreach( $theExdate->getValue() as $exDatePart ) { + $formatted = DateTimeFactory::dateTime2Str( + $exDatePart, + $theExdate->hasParamValue(self::DATE ), + $theExdate->hasParamIsLocalTime() + ); + $content .= ( 0 < $eix++ ) ? StringFactory::$COMMA . $formatted : $formatted; + } // end foreach + $output .= self::renderProperty( $propName, (array) $theExdate->getParams(), $content ); + } // end foreach(( array_keys( $exdates... + return $output; + } + + /** + * Sort callback function for exdate + * + * @param DateTime $a + * @param DateTime $b + * @return int + * @since 2.29.2 2019-06-23 + */ + public static function sortExdate1( DateTime $a, DateTime $b ) : int + { + return strcmp( + $a->format( DateTimeFactory::$YmdTHis ), + $b->format( DateTimeFactory::$YmdTHis ) + ); + } + + /** + * Sort callback function for exdate + * + * @param Pc $a + * @param Pc $b + * @return int + * @since 2.29.2 2019-06-23 + */ + public static function sortExdate2( Pc $a, Pc $b ) : int + { + $pcValue = $a->getValue(); + $a1 = reset( $pcValue ); + $pcValue = $b->getValue(); + $b1 = reset( $pcValue ); + return strcmp( + $a1->format( DateTimeFactory::$YmdTHis ), + $b1->format( DateTimeFactory::$YmdTHis ) + ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/Freebusy.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Freebusy.php new file mode 100644 index 0000000..fee851a --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Freebusy.php @@ -0,0 +1,101 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use DateInterval; +use Exception; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\DateIntervalFactory; +use Kigkonsult\Icalcreator\Util\DateTimeFactory; +use Kigkonsult\Icalcreator\Util\SortFactory; + +use Kigkonsult\Icalcreator\Util\StringFactory; +use function sprintf; +use function usort; + +/** + * Format FREEBUSY + * + * 1 + * @since 2.41.88 - 2024-01-18 + */ +final class Freebusy extends PropertyBase +{ + /** + * @param string $propName + * @param Pc[] $values + * @param bool|null $allowEmpty + * @return string + * @throws Exception + * @since 2.41.88 - 2024-01-18 + */ + public static function format( string $propName, array $values , ? bool $allowEmpty = true ) : string + { + static $FMT = ';FBTYPE=%s'; + static $SORTER = [ SortFactory::class, 'sortRdate1' ]; + if( empty( $values )) { + return StringFactory::$SP0; + } + $output = StringFactory::$SP0; + foreach( $values as $freebusyPart ) { // Pc + $freebusyPartValue = $freebusyPart->getValue(); + if( empty( $freebusyPartValue )) { + if( $allowEmpty ) { + $output .= self::renderProperty( $propName ); + } + continue; + } + $params = (array) $freebusyPart->getParams(); + $attributes = sprintf( $FMT, $params[self::FBTYPE] ); // always set + unset( $params[self::FBTYPE] ); + $attributes .= self::formatParams( $params ); + $cnt = count( $freebusyPartValue ); + if( 1 < $cnt ) { + usort( $freebusyPartValue, $SORTER ); + } + $content = StringFactory::$SP0; + foreach( $freebusyPartValue as $freebusyPeriod ) { + if( ! empty( $content )) { + $content .= StringFactory::$COMMA; + } + $content .= DateTimeFactory::dateTime2Str( $freebusyPeriod[0] ); + $content .= StringFactory::$SLASH; + if( $freebusyPeriod[1] instanceof DateInterval ) { // period with duration + $content .= DateIntervalFactory::dateInterval2String( $freebusyPeriod[1] ); + } + else { // period ends with date-time + $content .= DateTimeFactory::dateTime2Str( $freebusyPeriod[1] ); + } + } // end foreach + $output .= self::renderProperty( $propName, $attributes, $content ); + } // end foreach( $values as $freebusyPart ) + return $output; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/Geo.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Geo.php new file mode 100644 index 0000000..d95d86b --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Geo.php @@ -0,0 +1,67 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\GeoFactory; +use Kigkonsult\Icalcreator\Util\StringFactory; + +/** + * Format GEO + * + * 1 + * @since 2.41.88 2024-01-18 + */ +final class Geo extends PropertyBase +{ + /** + * @param string $propName + * @param null|bool|Pc $pc + * @param bool|null $allowEmpty + * @return string + * @since 2.41.88 2024-01-18 + */ + public static function format( string $propName, null|bool|Pc $pc, ? bool $allowEmpty = true ) : string + { + if( empty( $pc )) { + return StringFactory::$SP0; + } + $pcValue = $pc->getValue(); + return empty( $pcValue ) + ? self::renderSinglePropEmpty( $propName, $allowEmpty ) + : self::renderProperty( + self::GEO, + (array) $pc->getParams(), + GeoFactory::geo2str2( $pcValue[self::LATITUDE], GeoFactory::$geoLatFmt ) . + StringFactory::$SEMIC . + GeoFactory::geo2str2( $pcValue[self::LONGITUDE], GeoFactory::$geoLongFmt ) + ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/IntProperty.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/IntProperty.php new file mode 100644 index 0000000..ce90d7a --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/IntProperty.php @@ -0,0 +1,67 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Kigkonsult\Icalcreator\Pc; + +use Kigkonsult\Icalcreator\Util\StringFactory; +use function is_numeric; + +/** + * Format PERCENT_COMPLETE, PRIORITY, REPEAT, SEQUENCE + * + * 4 + * @since 2.41.88 - 2024-01-18 + */ +final class IntProperty extends PropertyBase +{ + /** + * @param string $propName + * @param null|bool|Pc $pc + * @param bool|null $allowEmpty + * @return string + * @since 2.41.88 - 2024-01-18 + */ + public static function format( + string $propName, + null|bool|Pc $pc, + ? bool $allowEmpty = true + ) : string + { + if( empty( $pc ) || ! $pc->isset()) { + return StringFactory::$SP0; + } + $value = $pc->getValue(); + return (( empty( $value ) && ! is_numeric( $value )) && + (( self::SEQUENCE !== $propName ) || ( 0 !== $value ))) + ? self::renderSinglePropEmpty( $propName, $allowEmpty ) + : self::renderProperty( $propName, $pc->getParams(), (string) $value ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/MultiProps.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/MultiProps.php new file mode 100644 index 0000000..8e639d0 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/MultiProps.php @@ -0,0 +1,198 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Kigkonsult\Icalcreator\Pc; + +use Kigkonsult\Icalcreator\Util\StringFactory; +use function in_array; + +/** + * Format CATEGORIES, COMMENT, CONFERENCE, CONTACT, DESCRIPTION, LOCATION, + * NAME, RELATED_TO, RESOURCES, + * TZID_ALIAS_OF, TZNAME + * Format STYLED_DESCRIPTION, STRUCTURED_DATA, + * Format ATTACH, IMAGE + * + * 15 + * @since 2.41.88 - 2024-01-17 + */ +final class MultiProps extends PropertyBase +{ + /** + * @param string $propName + * @param Pc[] $values + * @param null|bool $allowEmpty + * @param null|bool|string $lang + * @return string + * @since 2.41.88 - 2024-01-17 + */ + public static function format( + string $propName, + array $values, + ? bool $allowEmpty = true, + null|bool|string $lang = false + ) : string + { + static $ATTCONFIMG = [ self::ATTACH, self::CONFERENCE, self::IMAGE ]; // URI + if( empty( $values )) { + return StringFactory::$SP0; + } + [ $specKeys, $lang ] = self::getSpeckeys1Lang1( $propName, $lang ); + $output = StringFactory::$SP0; + foreach( $values as $pc ) { + $pcValue = $pc->getValue(); + if( ! empty( $pcValue )) { + [ $specKeys2, $lang2 ] = self::getSpeckeys2Lang2( + $propName, + $pc->getValueParam(), + $specKeys, + $lang + ); + $output .= self::renderProperty( + $propName, + self::formatParams( $pc->getParams(), $specKeys2, $lang2 ), + ( in_array( $propName, $ATTCONFIMG, true ) + ? $pcValue + : self::strrep( $pcValue )) + ); + } // end if + elseif( $allowEmpty ) { + $output .= self::renderProperty( $propName ); + } + } // end foreach + return $output; + } + + /** + * Init specKeys and lang + * + * IMAGE has no default valueType (VALUE required) + * + * @param string $propName + * @param null|bool|string $lang + * @return string[]|string[][] + */ + private static function getSpeckeys1Lang1( string $propName, null|bool|string $lang ) : array + { + static $langProps = [ self::CATEGORIES, self::TZNAME ]; + static $langkey = [ self::LANGUAGE ]; + static $altLangProps = [ + self::COMMENT, + self::CONTACT, + self::DESCRIPTION, + self::LOCATION, + self::NAME, + self::RESOURCES + ]; + static $ATTACHKEYS = [ self::VALUE, self::FEATURE ]; + static $CONFPKEYS = [ self::FEATURE, self::LABEL, self::LANGUAGE ]; + static $IMAGEPKEYS = [ self::FMTTYPE, self::ALTREP, self::DISPLAY ]; + static $STYDESCR1 = [ self::ALTREP, self::LANGUAGE, self::FMTTYPE, self::DERIVED ]; + static $noLangProps = [ self::ATTACH, self::RELATED_TO, self::TZID_ALIAS_OF ]; + switch( true ) { + case ( self::CONFERENCE === $propName ) : + $specKeys = $CONFPKEYS; + break; + case ( self::IMAGE === $propName ) : + $specKeys = $IMAGEPKEYS; + $lang = null; + break; + case ( self::STYLED_DESCRIPTION === $propName ) : + $specKeys = $STYDESCR1; + break; + case in_array( $propName, $langProps, true ) : + $specKeys = $langkey; + break; + case in_array( $propName, $altLangProps, true ) : + $specKeys = self::$ALTRPLANGARR; + break; + case ( self::ATTACH === $propName ) : + $specKeys = $ATTACHKEYS; + $lang = null; + break; + case in_array( $propName, $noLangProps, true ) : + $specKeys = []; + $lang = null; + break; + default : + $specKeys = []; + } // end switch + return [ $specKeys, $lang ]; + } + + /** + * Finetune specKeys and lang + * + * STRUCTURED_DATA has no default valueType, VALUE required + * + * @param string $propName + * @param null|string $paramValue + * @param string[] $specKeys + * @param null|bool|string $lang + * @return string[]|string[][] + * @since 2.41.63 - 2022-09-03 + */ + private static function getSpeckeys2Lang2( + string $propName, + ? string $paramValue, + array $specKeys, + null|bool|string $lang + ) : array + { + static $STRDTAToU = [ self::TEXT, self::URI ]; + static $STRDTATXTURI = [ self::VALUE, self::FMTTYPE, self::SCHEMA ]; + static $STRDTABIN = [ self::VALUE, self::ENCODING, self::FMTTYPE, self::SCHEMA]; + static $STYDESCR1 = [ self::VALUE, self::ALTREP, self::LANGUAGE, self::FMTTYPE, self::DERIVED ]; + static $STYDESCR2 = [ self::VALUE, self::ALTREP, self::FMTTYPE, self::DERIVED ]; + $hasValueText = ( self::TEXT === $paramValue ); + $isStyledDescription = ( self::STYLED_DESCRIPTION === $propName ); + switch( true ) { + case ( $isStyledDescription && $hasValueText ) : + $specKeys2 = $STYDESCR1; + $lang2 = $lang; + break; + case ( $isStyledDescription && ! $hasValueText ) : + $specKeys2 = $STYDESCR2; + $lang2 = null; + break; + case ( self::STRUCTURED_DATA === $propName ) : + $specKeys2 = ( in_array( $paramValue, $STRDTAToU, true )) + ? $STRDTATXTURI + : $STRDTABIN; + $lang2 = $hasValueText ? $lang : null; + break; + default : + $specKeys2 = $specKeys; + $lang2 = $lang; + } // end switch + return [ $specKeys2, $lang2 ]; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/Property.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Property.php new file mode 100644 index 0000000..77e7cec --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Property.php @@ -0,0 +1,60 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\StringFactory; + +/** + * Format ACTION, BUSYTYPE, CALENDAR_ADDRESS, KLASS, COLOR, LOCATION_TYPE, PARTICIPANT_TYPE, PROXIMITY, + * RESOURCE_TYPE, STATUS, TRANSP, TZOFFSETFROM, TZOFFSETTO, TZURL, URL, UID + * + * 16 + * @since 2.41.88 2024-01-18 + */ +final class Property extends PropertyBase +{ + /** + * @param string $propName + * @param null|bool|Pc $pc + * @param bool|null $allowEmpty + * @return string + */ + public static function format( string $propName, null|bool|Pc $pc, ? bool $allowEmpty = true ) : string + { + if( empty( $pc )) { + return StringFactory::$SP0; + } + $pcValue = $pc->getValue(); + return empty( $pcValue ) + ? self::renderSinglePropEmpty( $propName, $allowEmpty ) + : self::renderProperty( $propName, (array) $pc->getParams(), $pcValue ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/PropertyBase.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/PropertyBase.php new file mode 100644 index 0000000..66e6ef4 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/PropertyBase.php @@ -0,0 +1,485 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Kigkonsult\Icalcreator\IcalInterface; +use Kigkonsult\Icalcreator\Util\StringFactory as SF; + +use function array_change_key_case; +use function array_keys; +use function in_array; +use function is_array; +use function is_int; +use function is_string; +use function ord; +use function sprintf; +use function str_contains; +use function str_replace; +use function strlen; + +/** + * @since 2.41.68 - 2022-10-03 + */ +abstract class PropertyBase implements IcalInterface +{ + /** + * @var string[] + */ + protected static array $ALTRPLANGARR = [ self::ALTREP, self::LANGUAGE ]; + + /** + * Return formatted output for calendar component property + * + * @param string $label property name + * @param null|string|string[] $attributes property attributes + * @param null|string $content property content + * @return string + * @since 2.41.66 2022-09-07 + */ + public static function renderProperty( + string $label, + null|string|array $attributes = null, + ? string $content = null + ) : string + { + $output = strtoupper( $label ); + switch( true ) { + case empty( $attributes ) : + break; + case is_array( $attributes ) : + $output .= self::formatParams( $attributes ); + break; + default : + $output .= trim( $attributes ); + break; + } + $output .= SF::$COLON . trim((string) $content ); + return self::size75( $output ); + } + + /** + * Create iCal string of empty property + * + * @param string $propName + * @param null|bool $allowEmpty + * @return string + * @since 2.41.63 2022-09-05 + */ + protected static function renderSinglePropEmpty( string $propName, ? bool $allowEmpty = true ) : string + { + return $allowEmpty ? self::renderProperty( $propName ) : SF::$SP0; + } + + /** + * Return formatted output for calendar component property parameters + * + * @param string[]|string[][] $inputParams + * @param null|string[] $ctrKeys + * @param null|bool|string $lang bool false if config lang not found + * @return string + * @since 2.41.68 2022-10-23 + */ + public static function formatParams( + array $inputParams, + ? array $ctrKeys = [], + null|bool|string $lang = null + ) : string + { + static $VALENC = [ self::VALUE, self::ENCODING ]; + static $KEYGRP1 = [ self::TZID, self::RANGE, self::RELTYPE ]; + static $KEYGRP3 = [ self::SENT_BY, self::FEATURE, self::LABEL ]; + unset( $inputParams[self::ISLOCALTIME ] ); + if( empty( $inputParams ) && empty( $ctrKeys ) && empty( $lang )) { + return SF::$SP0; + } + if( empty( $ctrKeys )) { + $ctrKeys = []; + } + $attrLANG = $output = SF::$SP0; + $hasLANGctrKey = in_array( self::LANGUAGE, $ctrKeys, true ); + $CNattrExist = false; + [ $params, $xparams ] = self::quoteParams( $inputParams ); + if( isset( $params[self::VALUE] ) && ! in_array( self::VALUE, $ctrKeys, true )) { + $output .= self::renderKeyGroup( $VALENC, $VALENC, $params ); // VALUE+ENCODING + } + $output .= self::renderKeyGroup( $KEYGRP1, $ctrKeys, $params ); // TZID, RANGE, RELTYPE + if( isset( $params[self::CN] ) && in_array( self::CN, $ctrKeys, true )) { + $output .= self::renderParam( self::CN, $params ); + $CNattrExist = true; + } + $output .= self::renderKeyGroup( $KEYGRP3, $ctrKeys, $params ); // SENT_BY, FEATURE, LABEL + if( $hasLANGctrKey && isset( $params[self::LANGUAGE] )) { + $attrLANG .= self::renderParam( self::LANGUAGE, $params ); + } + elseif(( $CNattrExist || $hasLANGctrKey ) && is_string( $lang ) && ! empty( $lang )) { + $langArr = [ self::LANGUAGE => $lang ]; + $attrLANG .= self::renderParam( self::LANGUAGE, $langArr ); + } + if( isset( $params[self::VALUE] )) { + $output .= self::renderKeyGroup( $VALENC, $VALENC, $params ); // VALUE+ENCODING + } + if( isset( $params[self::DERIVED] ) && ( self::FALSE === $params[self::DERIVED] )) { + unset( $params[self::DERIVED] ); // skip default FALSE for DERIVED + } + $output .= self::renderKeyGroup( $ctrKeys, $ctrKeys, $params ); // ctrKeys in order + if( ! empty( $params )) { // accept other or iana-token (Other IANA-registered) parameter types, last + $paramKeys = array_keys( $params ); + $output .= self::renderKeyGroup( $paramKeys, $paramKeys, $params ); + } + $output .= $attrLANG; + if( ! empty( $xparams )) { // x-params last + $paramKeys = array_keys( $xparams ); + $output .= self::renderKeyGroup( $paramKeys, $paramKeys, $xparams ); + } + return $output; + } + + /** + * Return parameters+x-params with opt. quoted parameter value + * + * "-Quotes a value if it contains ':', ';' or ',' + * + * @param string[] $inputParams + * @return string[][] + * @since 2.41.63 2022-09-05 + */ + protected static function quoteParams( array $inputParams ) : array + { + static $DFKEYS = [ self::DISPLAY, self::FEATURE ]; + static $FMTQ = '"%s"'; + $params = $xparams = []; + foreach( array_change_key_case( $inputParams, CASE_UPPER ) as $paramKey => $paramValue ) { + $paramValue = self::circumflexQuoteInvoke( $paramValue ); + if( self::hasColonOrSemicOrComma( $paramValue ) && + ! in_array( $paramKey, $DFKEYS, true )) { // DISPLAY, FEATURE + $paramValue = sprintf( $FMTQ, $paramValue ); + } + if( self::isXprefixed( $paramKey )) { + $xparams[$paramKey] = $paramValue; + } + else { + $params[$paramKey] = $paramValue; + } + } // end foreach + ksort( $xparams, SORT_STRING ); + return [ $params, $xparams ]; + } + + /** + * Return parameter VALUE with opt. circumflex formatted as of rfc6868 + * + * formatted text line breaks are encoded into ^n (U+005E, U+006E) + * the ^ character (U+005E) is encoded into ^^ (U+005E, U+005E) + * the " character (U+0022) is encoded into ^' (U+005E, U+0027) + * + * Also ' is encoded into ^' (U+005E, U+0027), NOT rfc6868 + * + * @param int|string $value + * @return string + * @since 2.41.63 - 2022-09-05 + */ + public static function circumflexQuoteInvoke( int|string $value ) : string + { + static $CFN = '^n'; + static $CFCF = '^^'; + static $CFSQ = "^'"; + static $CIRCUMFLEX = '^'; + static $NLCHARS = '\n'; + if( is_int( $value )) { + return (string) $value; + } + $nlCharsExist = str_contains( $value, $NLCHARS ); + $cfCfExist = str_contains( $value, $CIRCUMFLEX ); + $quotExist = str_contains( $value, SF::$QQ ); + if( $nlCharsExist ) { + $value = str_replace( $NLCHARS, $CFN, $value ); + } + if( $cfCfExist ) { + $value = str_replace( $CIRCUMFLEX, $CFCF, $value ); + } + if( $quotExist ) { + $value = str_replace( SF::$QQ, $CFSQ, $value ); + } + return $value; + } + + /** + * Return rendered parameter (if exists) + * + * @param string $paramKey + * @param string[] $params + * @return string + */ + protected static function renderParam( string $paramKey, array & $params ) : string + { + static $DIRALTR = [ self::DIR, self::ALTREP ]; + static $FMTCMN = ';%s=%s'; + static $FMTQTD = ';%s=%s%s%s'; + if( ! isset( $params[$paramKey] )) { + return SF::$SP0; + } + if( in_array( $paramKey, $DIRALTR, true )) { + $delim = str_contains( $params[$paramKey], SF::$QQ ) ? SF::$SP0 : SF::$QQ; + $output = sprintf( $FMTQTD, $paramKey, $delim, $params[$paramKey], $delim ); + } + else { + $output = sprintf( $FMTCMN, $paramKey, $params[$paramKey] ); + } + unset( $params[$paramKey] ); + return $output; + } + + /** + * Return rendered parameter (if exists) + * + * @param string[] $keyGroup keys to probe + * @param string[] $ctrKeys probe list + * @param string[] $params + * @return string + */ + protected static function renderKeyGroup( array $keyGroup, array $ctrKeys, array & $params ) : string + { + $output = SF::$SP0; + foreach( $keyGroup as $key ) { + if( in_array( $key, $ctrKeys, true )) { + $output .= self::renderParam( $key, $params ); + } + } // end foreach + return $output; + } + + /** + * Return bool true if string contains any of :;, + * + * @param mixed $string + * @return bool + */ + protected static function hasColonOrSemicOrComma( mixed $string ): bool + { + return ( is_string( $string ) && + ( str_contains( $string, SF::$COLON ) || + str_contains( $string, SF::$SEMIC ) || + str_contains( $string, SF::$COMMA ))); + } + + /** + * Fix rfc5545. 3.3.11 Text, ESCAPED-CHAR + * + * @param string $string + * @return string + * @since 2.27.14 - 2019-02-20 + */ + public static function strrep( string $string ) : string + { + static $BSLCN = '\n'; + static $SPECCHAR = [ 'n', 'N', 'r', ',', ';' ]; + static $SQ = "'"; + static $QBSLCR = "\r"; + static $QBSLCN = "\n"; + static $BSUCN = '\N'; + $strLen = strlen( $string ); + $pos = 0; + // replace single (solo-)backslash by double ones + while( $pos < $strLen ) { + if( false === ( $pos = strpos( $string, SF::$BS2, $pos ))) { + break; + } + if( ! in_array( $string[$pos], $SPECCHAR )) { + $string = substr( $string, 0, $pos ) . + SF::$BS2 . substr( $string, ( $pos + 1 )); + ++$pos; + } + ++$pos; + } // end while + // replace double quote by single ones + if( str_contains( $string, SF::$QQ )) { + $string = str_replace( SF::$QQ, $SQ, $string ); + } + // replace comma by backslash+comma but skip any previously set of backslash+comma + // replace semicolon by backslash+semicolon but skip any previously set of backslash+semicolon + foreach( [ SF::$COMMA, SF::$SEMIC ] as $char ) { + $offset = 0; + while( false !== ( $pos = strpos( $string, $char, $offset ))) { + if(( 0 < $pos ) && ( SF::$BS2 !== substr( $string, ( $pos - 1 )))) { + $string = substr( $string, 0, $pos ) . + SF::$BS2 . substr( $string, $pos ); + } + $offset = $pos + 2; + } // end while + $string = str_replace( + SF::$BS2 . SF::$BS2 . $char, + SF::$BS2 . $char, + $string + ); + } + // replace "\r\n" by '\n' + if( str_contains( $string, SF::$CRLF )) { + $string = str_replace( SF::$CRLF, $BSLCN, $string ); + } + // or replace "\r" by '\n' + elseif( str_contains( $string, $QBSLCR )) { + $string = str_replace( $QBSLCR, $BSLCN, $string ); + } + // or replace '\N' by '\n' + elseif( str_contains( $string, $QBSLCN )) { + $string = str_replace( $QBSLCN, $BSLCN, $string ); + } + // replace '\N' by '\n' + if( str_contains( $string, $BSUCN )) { + $string = str_replace( $BSUCN, $BSLCN, $string ); + } + // replace "\r\n" by '\n' + return str_replace( SF::$CRLF, $BSLCN, $string ); + } + + /** + * Return bool true if name is X-prefixed + * + * @param string $name + * @return bool + * @since 2.29.5 - 2019-08-30 + */ + public static function isXprefixed( string $name ) : bool + { + static $X_ = 'X-'; + return ( 0 === stripos( $name, $X_ )); + } + + /** + * Return wrapped string with (byte oriented) line breaks at pos 75 + * + * Lines of text SHOULD NOT be longer than 75 octets, excluding the line + * break. Long content lines SHOULD be split into a multiple line + * representations using a line "folding" technique. That is, a long + * line can be split between any two characters by inserting a CRLF + * immediately followed by a single linear white space character (i.e., + * SPACE, US-ASCII decimal 32 or HTAB, US-ASCII decimal 9). Any sequence + * of CRLF followed immediately by a single linear white space character + * is ignored (i.e., removed) when processing the content type. + * + * Edited 2007-08-26 by Anders Litzell, anders@litzell.se to fix bug where + * the reserved expression "\n" in the arg $string could be broken up by the + * folding of lines, causing ambiguity in the return string. + * + * @param string $string + * @return string + * @link http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + * @since 2.40 - 2021-10-04 + */ + public static function size75( string $string ) : string + { + static $LCN = 'n'; + static $UCN = 'N'; + static $SPBSLCN = ' \n'; + static $SP1 = ' '; + $tmp = $string; + $inLen = strlen( $tmp ); + $string = SF::$SP0; + $outLen = $x = 0; + while( true ) { + $x1 = $x + 1; + if( $inLen <= $x ) { + $string .= SF::$CRLF; // loop breakes here + break; + } + if(( 74 <= $outLen ) && + ( SF::$BS2 === $tmp[$x]) && // '\\' + (( $LCN === $tmp[$x1]) || + ( $UCN === $tmp[$x1]))) { + $string .= SF::$CRLF . $SPBSLCN; // don't break lines inside '\n' + $x += 2; + if( $inLen < $x ) { + $string .= SF::$CRLF; + break; // or here... + } + $outLen = 3; + } + elseif( 75 <= $outLen ) { + $string .= SF::$CRLF; + if( $inLen === $x ) { + break; // or here.. + } + $string .= $SP1; + $outLen = 1; + } + $str1 = $tmp[$x]; + $byte = ord( $str1 ); + $string .= $str1; + switch( true ) { + case(( $byte >= 0x20 ) && ( $byte <= 0x7F )) : + ++$outLen; // characters U-00000000 - U-0000007F (same as ASCII) + break; // add a one byte character + case(( $byte & 0xE0 ) === 0xC0 ) : // characters U-00000080 - U-000007FF, mask 110XXXXX + if( $inLen > ( $x + 1 )) { + ++$outLen; + ++$x; // add second byte of a two bytes character + $string .= $tmp[$x]; + } + break; + case(( $byte & 0xF0 ) === 0xE0 ) : // characters U-00000800 - U-0000FFFF, mask 1110XXXX + if( $inLen > ( $x + 2 )) { + ++$outLen; + ++$x; + $string .= substr( $tmp, $x1, 2 ); + ++$x; // add byte 2-3 of a three bytes character + } + break; + case(( $byte & 0xF8 ) === 0xF0 ) : // characters U-00010000 - U-001FFFFF, mask 11110XXX + if( $inLen > ( $x + 3 )) { + ++$outLen; + ++$x; + $string .= substr( $tmp, $x1, 3 ); + $x += 2; // add byte 2-4 of a four bytes character + } + break; + case(( $byte & 0xFC ) === 0xF8 ) : // characters U-00200000 - U-03FFFFFF, mask 111110XX + if( $inLen > ( $x + 4 )) { + ++$outLen; + ++$x; + $string .= substr( $tmp, $x, 4 ); + $x += 3; // add byte 2-5 of a five bytes character + } + break; + case(( $byte & 0xFE ) === 0xFC ) : // characters U-04000000 - U-7FFFFFFF, mask 1111110X + if( $inLen > ( $x + 5 )) { + ++$outLen; + ++$x; + $string .= substr( $tmp, $x, 5 ); + $x += 4; // add byte 2-6 of a six bytes character + } + break; + default: // add any other byte without counting up $cCnt + break; + } // end switch( true ) + ++$x; // next 'byte' to test + } // end while( true ) + return $string; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/Rdate.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Rdate.php new file mode 100644 index 0000000..b54870c --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Rdate.php @@ -0,0 +1,151 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use DateInterval; +use Exception; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\DateIntervalFactory; +use Kigkonsult\Icalcreator\Util\DateTimeFactory; +use Kigkonsult\Icalcreator\Util\SortFactory; +use Kigkonsult\Icalcreator\Util\StringFactory; +use Kigkonsult\Icalcreator\Vcalendar; + +use function count; +use function is_array; +use function usort; + +/** + * Format RDATE + * + * 1 + * @since 2.41.88 2024-01-17 + */ +final class Rdate extends PropertyBase +{ + /** + * @param string $propName + * @param Pc[] $values + * @param bool|null $allowEmpty + * @param null|string $compType + * @return string + * @throws Exception + * @since 2.41.88 2024-01-17 + */ + public static function format( + string $propName, + array $values, + ? bool $allowEmpty = true, + ? string $compType = null + ) : string + { + static $SORTER1 = [ SortFactory::class, 'sortRdate1' ]; + static $SORTER2 = [ SortFactory::class, 'sortRdate2' ]; + if( empty( $values )) { + return StringFactory::$SP0; + } + $utcTime = Vcalendar::isTzComp( $compType ); + $output = StringFactory::$SP0; + $rDates = []; + foreach( $values as $theRdate ) { // Pc + $theRdateValue = $theRdate->getValue(); + if( empty( $theRdateValue )) { + if( $allowEmpty ) { + $output .= self::renderProperty( $propName ); + } + continue; + } + if( $utcTime ) { + $theRdate->removeParam( self::TZID ); + } + if( 1 < count( $theRdateValue )) { + usort( $theRdateValue, $SORTER1 ); + $theRdate->setValue( $theRdateValue ); + } + $rDates[] = $theRdate; + } // end foreach + if( 1 < count( $rDates )) { + usort( $rDates, $SORTER2 ); + } + foreach( $rDates as $theRdate ) { // Pc + $output .= self::formatPart( $theRdate, $propName ); + } + return $output; + } + + /** + * Format a Rdate row + * + * @param Pc $theRdate + * @param string $propName + * @return string + * @throws Exception + */ + private static function formatPart( Pc $theRdate, string $propName ) : string + { + $isPeriod = $theRdate->hasParamValue( self::PERIOD ); + $isValueDate = $theRdate->hasParamValue( self::DATE ); // i.e. NOT datetime + $isLocalTime = $theRdate->hasParamIsLocalTime(); + $rdateValue = $theRdate->getValue(); + $cnt = count( $rdateValue ); + $content = StringFactory::$SP0; + $rno = 1; + foreach( $rdateValue as $rdatePart ) { + $content .= ( is_array( $rdatePart ) && $isPeriod ) + ? self::getPeriod( $rdatePart, $isValueDate, $isLocalTime ) // is period + : DateTimeFactory::dateTime2Str( $rdatePart, $isValueDate, $isLocalTime ); // is date[time] + if( $rno < $cnt ) { + $content .= StringFactory::$COMMA; + } + $rno++; + } // end foreach( $rDates as $theRdate ) + return self::renderProperty( $propName, (array) $theRdate->getParams(), $content ); + } + + /** + * @param array $rdatePart + * @param bool $isValueDate + * @param bool $isLocalTime + * @return string + * @throws Exception + */ + private static function getPeriod( array $rdatePart, bool $isValueDate, bool $isLocalTime ) : string + { + static $S = '/'; + // PERIOD, part 1 + $period = DateTimeFactory::dateTime2Str( $rdatePart[0], $isValueDate, $isLocalTime ); + $period .= $S; + // PERIOD, part 2 + $period .= ( $rdatePart[1] instanceof DateInterval ) + ? DateIntervalFactory::dateInterval2String( $rdatePart[1] ) + : DateTimeFactory::dateTime2Str( $rdatePart[1], $isValueDate, $isLocalTime ); // date-time + return $period; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/Recur.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Recur.php new file mode 100644 index 0000000..41710ab --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Recur.php @@ -0,0 +1,210 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Exception; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\DateTimeFactory; +use Kigkonsult\Icalcreator\Util\StringFactory; + +use function count; +use function ctype_digit; +use function implode; +use function is_array; +use function sprintf; +use function strtoupper; +use function substr; +use function usort; + +/** + * Format EXRULE, RRULE + * + * 2 + * @since 2.41.88 2024-01-18 + */ +final class Recur extends PropertyBase +{ + /** + * @param string $propName + * @param null|bool|Pc $pc + * @param bool|null $allowEmpty + * @return string + * @throws Exception + * @since 2.41.88 2024-01-18 + */ + public static function format( + string $propName, + null|bool|Pc $pc, + ? bool $allowEmpty = true + ) : string + { + if( empty( $pc )) { + return StringFactory::$SP0; + } + $pcValue = $pc->getValue(); + if( empty( $pcValue )) { + return $allowEmpty ? self::renderProperty( $propName ) : StringFactory::$SP0; + } + $content1 = $content2 = StringFactory::$SP0; + $first = true; + foreach( $pcValue as $ruleLabel => $ruleValue ) { + $ruleLabel = strtoupper( $ruleLabel ); + switch( $ruleLabel ) { + case self::RSCALE : // fall through + case self::FREQ : + $content1 .= self::renderFirst( $ruleLabel, $ruleValue, $first ); + break; + case self::UNTIL : + $ruleValue = DateTimeFactory::dateTime2Str( $ruleValue, self::getIsValueDate( $pc )); // fall through + case self::COUNT : // fall through + case self::INTERVAL : // fall through + case self::WKST : // fall through + $content2 .= self::renderString( $ruleLabel, (string) $ruleValue ); + break; + case self::BYDAY : + $content2 .= self::renderByday( $ruleValue ); + break; + default : // BYSECOND/BYMINUTE/BYHOUR/BYMONTHDAY/BYYEARDAY/BYWEEKNO/BYMONTH/BYSETPOS... + $content2 .= self::renderDefault( $ruleLabel, $ruleValue ); + break; + } // end switch( $ruleLabel ) + } // end foreach( $pc->value as $ruleLabel => $ruleValue ) + return self::renderProperty( $propName, (array) $pc->getParams(),$content1 . $content2 ); + } + + /** + * @param Pc $pc + * @return bool + */ + private static function getIsValueDate( Pc $pc ) : bool + { + $isValueDate = $pc->hasParamValue( self::DATE ); + if( ! empty( $pc->params )) { + $pc = clone $pc; + $pc->removeParam( self::VALUE ); + } + return $isValueDate; + } + + /** + * @param string $ruleLabel + * @param string $ruleValue + * @param bool $first + * @return string + */ + private static function renderFirst( string $ruleLabel, string $ruleValue, bool & $first ) : string + { + static $FMT = '%s%s=%s'; + $output = sprintf( + $FMT, + ( $first ? StringFactory::$SP0 : StringFactory::$SEMIC ), + $ruleLabel, + $ruleValue + ); + $first = false; + return $output; + } + + /** + * @param string $ruleLabel + * @param string $ruleValue + * @return string + */ + private static function renderString( string $ruleLabel, string $ruleValue ) : string + { + static $FMT = ';%s=%s'; + return sprintf( $FMT, $ruleLabel, $ruleValue ); + } + + /** + * @param string[]|string[][] $ruleValue + * @return string + */ + private static function renderByday( array $ruleValue ) : string + { + static $RECURBYDAYSORTER = [ __CLASS__, 'recurBydaySort' ]; + $byday = [ StringFactory::$SP0 ]; + $bx = 0; + foreach( $ruleValue as $bydayPart ) { + if( ! empty( $byday[$bx] ) && // new day + ! ctype_digit( substr( $byday[$bx], -1 ))) { + $byday[++$bx] = StringFactory::$SP0; + } + if( ! is_array( $bydayPart )) { // day without rel pos number + $byday[$bx] .= $bydayPart; + } + else { // day with rel pos number + foreach( $bydayPart as $bydayPart2 ) { + $byday[$bx] .= $bydayPart2; + } + } + } // end foreach( $ruleValue as $bydayPart ) + if( 1 < count( $byday )) { + usort( $byday, $RECURBYDAYSORTER ); + } + return self::renderString( self::BYDAY, implode( StringFactory::$COMMA, $byday )); + } + + /** + * Sort recur BYDAYs + * + * @param string $byDayA + * @param string $byDayB + * @return int + */ + private static function recurBydaySort( string $byDayA, string $byDayB ) : int + { + static $days = [ + self::SU => 0, + self::MO => 1, + self::TU => 2, + self::WE => 3, + self::TH => 4, + self::FR => 5, + self::SA => 6, + ]; + return ( $days[substr( $byDayA, -2 )] < $days[substr( $byDayB, -2 )] ) + ? -1 + : 1; + } + + /** + * @param string $ruleLabel + * @param int|string|string[] $ruleValue + * @return string + */ + private static function renderDefault( string $ruleLabel, int|string|array $ruleValue ) : string + { + return self::renderString( + $ruleLabel, + ( is_array( $ruleValue ) ? implode( StringFactory::$COMMA, $ruleValue ) : ( string) $ruleValue ) + ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/Requeststatus.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Requeststatus.php new file mode 100644 index 0000000..bae05ed --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Requeststatus.php @@ -0,0 +1,83 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\StringFactory; + +/** + * Format REQUEST_STATUS + * + * 1 + * @since 2.41.88 - 2024-01-18 + */ +final class Requeststatus extends PropertyBase +{ + /** + * @param string $propName + * @param Pc[] $values + * @param null|bool $allowEmpty + * @param null|bool|string $lang + * @return string + */ + public static function format( + string $propName, + array $values, + ? bool $allowEmpty = true, + null|bool|string $lang = false + ) : string + { + if( empty( $values )) { + return StringFactory::$SP0; + } + $output = StringFactory::$SP0; + foreach( $values as $pc ) { + $pcValue = $pc->getValue(); + if( ! empty( $pcValue )) { + $content = + $pcValue[self::STATCODE] . + StringFactory::$SEMIC . + self::strrep( $pcValue[self::STATDESC] ); + if( isset( $pcValue[self::EXTDATA] )) { + $content .= StringFactory::$SEMIC . self::strrep( $pcValue[self::EXTDATA] ); + } + $output .= self::renderProperty( + $propName, + self::formatParams((array) $pc->getParams(), [ self::LANGUAGE ], $lang ), + $content + ); + } + elseif( $allowEmpty ) { + $output .= self::renderProperty( $propName ); + } + } // end foreach + return $output; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/SingleProps.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/SingleProps.php new file mode 100644 index 0000000..fbaa070 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/SingleProps.php @@ -0,0 +1,86 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\StringFactory; + +/** + * Format ORGANIZER, SOURCE + * Format SUMMARY, TZID + * + * 4 + * @since 2.41.88 - 2024-01-18 + */ +final class SingleProps extends PropertyBase +{ + /** + * @param string $propName + * @param null|bool|Pc $pc + * @param null|bool $allowEmpty + * @param null|bool|string $lang + * @return string + * @since 2.41.88 - 2024-01-18 + */ + public static function format( + string $propName, + null|bool|Pc $pc, + ? bool $allowEmpty = true, + null|bool|string $lang = false + ) : string + { + static $ORGPKEYS = [ self::CN, self::DIR, self::SENT_BY, self::LANGUAGE ]; + static $STRRPROPS = [ self::SUMMARY, self::TZID ]; + if( empty( $pc )) { + return StringFactory::$SP0; + } + $pcValue = $pc->getValue(); + if( empty( $pcValue )) { + return self::renderSinglePropEmpty( $propName, $allowEmpty ); + } + switch( $propName ) { + case self::SUMMARY : + $specKeys = self::$ALTRPLANGARR; + break; + case self::ORGANIZER : + $specKeys = $ORGPKEYS; + break; + default : + $specKeys = []; + $lang = null; + break; + } + return self::renderProperty( + $propName, + self::formatParams((array) $pc->getParams(), $specKeys, $lang ), + ( in_array( $propName, $STRRPROPS, true ) ? self::strrep( $pcValue) : $pcValue ) + ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Property/Xproperty.php b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Xproperty.php new file mode 100644 index 0000000..d4e6f5e --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Property/Xproperty.php @@ -0,0 +1,87 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter\Property; + +use Kigkonsult\Icalcreator\Util\StringFactory; +use function is_array; +use function is_numeric; + +/** + * Format X-properties + * + * @since 2.41.88 2024-01-18 + */ +final class Xproperty extends PropertyBase +{ + /** + * @param array $values [ *( propname, Pc ) ] + * @param null|bool $allowEmpty + * @param null|bool|string $lang + * @return string + * @since 2.41.88 2024-01-18 + */ + public static function format( + array $values, + ? bool $allowEmpty = true, + null|bool|string $lang = false + ) : string + { + $output = StringFactory::$SP0; + if( empty( $values )) { + return $output; + } + foreach( $values as $xpropBase ) { + [ $xpropName, $xpropPc ] = $xpropBase; + $xpropPcValue = $xpropPc->getValue(); + if( ! $xpropPc->isset() || + ( empty( $xpropPcValue ) && ! is_numeric( $xpropPcValue ))) { + if( $allowEmpty ) { + $output .= self::renderProperty( $xpropName ); + } + continue; + } + if( is_array( $xpropPcValue )) { + foreach( $xpropPcValue as $pix => $theXpart ) { + $xpropPcValue[$pix] = self::strrep( $theXpart ); + } + $xpropPcValue = implode( StringFactory::$COMMA, $xpropPcValue ); + } + else { + $xpropPcValue = self::strrep( $xpropPcValue ); + } + $output .= self::renderProperty( + $xpropName, + self::formatParams( $xpropPc->params, [ self::LANGUAGE ], $lang ), + $xpropPcValue + ); + } // end foreach + return $output; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Valarm.php b/vendor/kigkonsult/icalcreator/src/Formatter/Valarm.php new file mode 100644 index 0000000..9c40ca7 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Valarm.php @@ -0,0 +1,133 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Valarm as Source; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.55 - 2022-08-13 + */ +final class Valarm extends FormatBase +{ + /** + * @param CalendarComponent|Source $source + * @return string + * @throws Exception + */ + public static function format( CalendarComponent|Source $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + return + sprintf( self::$FMTBEGIN, $compType ) . + Property\Property::format( + self::UID, + $source->getUid( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::RELATED_TO, + $source->getAllRelatedto( true ), + $allowEmpty, + $lang + ) . + Property\Property::format( + self::ACTION, + $source->getAction( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::ATTACH, + $source->getAllAttach( true ), + $allowEmpty + ) . + Property\Attendee::format( + self::ATTENDEE, + $source->getAllAttendee( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::DESCRIPTION, + $source->getAllDescription( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::STYLED_DESCRIPTION, + $source->getAllStyleddescription( true ), + $allowEmpty, + $lang + ) . + Property\Property::format( + self::PROXIMITY, + $source->getProximity( true ), + $allowEmpty + ) . + Property\DurDates::format( + self::DURATION, + $source->getDuration( true ), + $allowEmpty + ) . + Property\IntProperty::format( + self::REPEAT, + $source->getRepeat( true ), + $allowEmpty + ) . + Property\SingleProps::format( + self::SUMMARY, + $source->getSummary( true ), + $allowEmpty, + $lang + ) . + Property\DurDates::format( + self::TRIGGER, + $source->getTrigger( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::ACKNOWLEDGED, + $source->getAcknowledged( true ), + $allowEmpty + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ) . + self::formatSubComponents( $source ) . + sprintf( self::$FMTEND, $compType ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Vavailability.php b/vendor/kigkonsult/icalcreator/src/Formatter/Vavailability.php new file mode 100644 index 0000000..70e618e --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Vavailability.php @@ -0,0 +1,173 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Vavailability as Source; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.55 - 2022-08-13 + */ +final class Vavailability extends FormatBase +{ + /** + * @param CalendarComponent|Source $source + * @return string + * @throws Exception + */ + public static function format( CalendarComponent|Source $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + $output = + sprintf( self::$FMTBEGIN, $compType ) . + Property\Property::format( + self::UID, + $source->getUid( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::DTSTAMP, + $source->getDtstamp( true ), + $allowEmpty + ) . + Property\Property::format( + self::BUSYTYPE, + $source->getBusytype( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::CATEGORIES, + $source->getAllCategories( true ), + $allowEmpty, + $lang + ) . + Property\Property::format( + self::KLASS, + $source->getClass( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::CREATED, + $source->getCreated( true ), + $allowEmpty + ) . + Property\SingleProps::format( + self::SUMMARY, + $source->getSummary( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::DESCRIPTION, + $source->getAllDescription( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::COMMENT, + $source->getAllComment( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::CONTACT, + $source->getAllContact( true ), + $allowEmpty, + $lang + ); + $dtStart = $source->getDtstart( true ); + $output .= Property\Dt1Property::format( + self::DTSTART, + $dtStart, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart ), + Property\Dt1Property::getIsLocalTime( $dtStart ) + ); + $dtEnd = $source->getDtend( true ); + $output .= Property\Dt1Property::format( + self::DTEND, + $dtEnd, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart, $dtEnd ), + Property\Dt1Property::getIsLocalTime( $dtEnd ) + ) . + Property\DurDates::format( + self::DURATION, + $source->getDuration( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::LAST_MODIFIED, + $source->getLastmodified( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::LOCATION, + $source->getAllLocation( true ), + $allowEmpty, + $lang + ) . + Property\SingleProps::format( + self::ORGANIZER, + $source->getOrganizer( true ), + $allowEmpty, + $lang + ) . + Property\IntProperty::format( + self::PRIORITY, + $source->getPriority( true ), + $allowEmpty + ) . + Property\IntProperty::format( + self::SEQUENCE, + $source->getSequence( true ), + $allowEmpty + ) . + Property\Property::format( + self::URL, + $source->getUrl( true ), + $allowEmpty + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ) . + self::formatSubComponents( $source ) . + sprintf( self::$FMTEND, $compType ); + return $output; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Vcalendar.php b/vendor/kigkonsult/icalcreator/src/Formatter/Vcalendar.php new file mode 100644 index 0000000..6765930 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Vcalendar.php @@ -0,0 +1,120 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\Vcalendar as Source; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.55 - 2022-08-12 + */ +final class Vcalendar extends FormatBase +{ + /** + * @param Source $source + * @return string + * @throws Exception + */ + public static function format( Source $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + return + sprintf( self::$FMTBEGIN, $compType ) . + Property\CalMetProVer::format( self::VERSION, $source->getVersion()) . + Property\CalMetProVer::format( self::PRODID, $source->getProdid()) . + Property\CalMetProVer::format( self::CALSCALE, $source->getCalscale()) . + Property\CalMetProVer::format( self::METHOD, $source->getMethod()) . + Property\DtxProperty::format( + self::LAST_MODIFIED, + $source->getLastmodified( true ), + $allowEmpty + ) . + Property\Property::format( + self::UID, + $source->getUid( true ), + $allowEmpty + ) . + Property\Property::format( + self::URL, + $source->getUrl( true ), + $allowEmpty + ) . + Property\DurDates::format( + self::REFRESH_INTERVAL, + $source->getRefreshinterval( true ), + $allowEmpty + ) . + Property\SingleProps::format( + self::SOURCE, + $source->getSource( true ), + $allowEmpty + ) . + Property\Property::format( + self::COLOR, + $source->getColor( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::NAME, + $source->getAllName( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::DESCRIPTION, + $source->getAllDescription( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::CATEGORIES, + $source->getAllCategories( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::IMAGE, + $source->getAllImage( true ), + $allowEmpty + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ) . + self::formatSubComponents( $source ) . + sprintf( self::$FMTEND, $compType ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Vevent.php b/vendor/kigkonsult/icalcreator/src/Formatter/Vevent.php new file mode 100644 index 0000000..9063e7e --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Vevent.php @@ -0,0 +1,269 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Vevent as Source; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.55 - 2022-08-13 + */ +final class Vevent extends FormatBase +{ + /** + * @param CalendarComponent|Source $source + * @return string + * @throws Exception + */ + public static function format( CalendarComponent|Source $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + $output = + sprintf( self::$FMTBEGIN, $compType ) . + Property\Property::format( + self::UID, + $source->getUid( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::DTSTAMP, + $source->getDtstamp( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::ATTACH, + $source->getAllAttach( true ), + $allowEmpty + ) . + Property\Attendee::format( + self::ATTENDEE, + $source->getAllAttendee( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::CATEGORIES, + $source->getAllCategories( true ), + $allowEmpty, + $lang + ) . + Property\Property::format( + self::KLASS, + $source->getClass( true ), + $allowEmpty + ) . + Property\Property::format( + self::COLOR, + $source->getColor( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::COMMENT, + $source->getAllComment( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::CONFERENCE, + $source->getAllConference( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::CONTACT, + $source->getAllContact( true ), + $allowEmpty, + $lang + ) . + Property\DtxProperty::format( + self::CREATED, + $source->getCreated( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::DESCRIPTION, + $source->getAllDescription( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::STYLED_DESCRIPTION, + $source->getAllStyleddescription( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::STRUCTURED_DATA, + $source->getAllStructureddata( true ), + $allowEmpty, + $lang + ); + $dtStart = $source->getDtstart( true ); + $output .= Property\Dt1Property::format( + self::DTSTART, + $dtStart, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart ), + Property\Dt1Property::getIsLocalTime( $dtStart ) + ); + $dtEnd = $source->getDtend( true ); + $output .= Property\Dt1Property::format( + self::DTEND, + $dtEnd, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart, $dtEnd ), + Property\Dt1Property::getIsLocalTime( $dtEnd ) + ) . + Property\DurDates::format( + self::DURATION, + $source->getDuration( true ), + $allowEmpty + ) . + Property\Exdate::format( + self::EXDATE, + $source->getAllExdate( true ), + $allowEmpty + ) . + Property\Recur::format( + self::EXRULE, + $source->getExrule( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::IMAGE, + $source->getAllImage( true ), + $allowEmpty + ) . + Property\Geo::format( + self::GEO, + $source->getGeo( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::LAST_MODIFIED, + $source->getLastmodified( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::LOCATION, + $source->getAllLocation( true ), + $allowEmpty, + $lang + ) . + Property\SingleProps::format( + self::ORGANIZER, + $source->getOrganizer( true ), + $allowEmpty, + $lang + ) . + Property\IntProperty::format( + self::PRIORITY, + $source->getPriority( true ), + $allowEmpty + ) . + Property\Rdate::format( + self::RDATE, + $source->getAllRdate( true ), + $allowEmpty, + $source->getCompType() + ) . + Property\Recur::format( + self::RRULE, + $source->getRrule( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::RELATED_TO, + $source->getAllRelatedto( true ), + $allowEmpty, + $lang + ) . + Property\Requeststatus::format( + self::REQUEST_STATUS, + $source->getAllRequeststatus( true ), + $allowEmpty, + $lang + ); + $reCurrId = $source->getRecurrenceid( true ); + $output .= + Property\Dt1Property::format( + self::RECURRENCE_ID, + $reCurrId, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart, $reCurrId ), + Property\Dt1Property::getIsLocalTime( $reCurrId ) + ) . + Property\MultiProps::format( + self::RESOURCES, + $source->getAllResources( true ), + $allowEmpty, + $lang + ) . + Property\IntProperty::format( + self::SEQUENCE, + $source->getSequence( true ), + $allowEmpty + ) . + Property\Property::format( + self::STATUS, + $source->getStatus( true ), + $allowEmpty + ) . + Property\SingleProps::format( + self::SUMMARY, + $source->getSummary( true ), + $allowEmpty, + $lang + ) . + Property\Property::format( + self::TRANSP, + $source->getTransp( true ), + $allowEmpty + ) . + Property\Property::format( + self::URL, + $source->getUrl( true ), + $allowEmpty + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ) . + self::formatSubComponents( $source ) . + sprintf( self::$FMTEND, $compType ); + return $output; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Vfreebusy.php b/vendor/kigkonsult/icalcreator/src/Formatter/Vfreebusy.php new file mode 100644 index 0000000..d073b8e --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Vfreebusy.php @@ -0,0 +1,141 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Vfreebusy as Source; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.55 - 2022-08-13 + */ +final class Vfreebusy extends FormatBase +{ + /** + * @param CalendarComponent|Source $source + * @return string + * @throws Exception + */ + public static function format( CalendarComponent|Source $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + $output = + sprintf( self::$FMTBEGIN, $compType ) . + Property\Property::format( + self::UID, + $source->getUid( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::DTSTAMP, + $source->getDtstamp( true ), + $allowEmpty + ) . + Property\Attendee::format( + self::ATTENDEE, + $source->getAllAttendee( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::STYLED_DESCRIPTION, + $source->getAllStyleddescription( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::COMMENT, + $source->getAllComment( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::CONTACT, + $source->getAllContact( true ), + $allowEmpty, + $lang + ); + $dtStart = $source->getDtstart( true ); + $output .= Property\Dt1Property::format( + self::DTSTART, + $dtStart, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart ), + Property\Dt1Property::getIsLocalTime( $dtStart ) + ); + $dtEnd = $source->getDtend( true ); + $output .= Property\Dt1Property::format( + self::DTEND, + $dtEnd, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart, $dtEnd ), + Property\Dt1Property::getIsLocalTime( $dtEnd ) + ) . + Property\DurDates::format( + self::DURATION, + $source->getDuration( true ), + $allowEmpty + ) . + Property\Freebusy::format( + self::FREEBUSY, + $source->getAllFreebusy( true ), + $allowEmpty + ) . + Property\SingleProps::format( + self::ORGANIZER, + $source->getOrganizer( true ), + $allowEmpty, + $lang + ) . + Property\Requeststatus::format( + self::REQUEST_STATUS, + $source->getAllRequeststatus( true ), + $allowEmpty, + $lang + ) . + Property\Property::format( + self::URL, + $source->getUrl( true ), + $allowEmpty + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ) . + self::formatSubComponents( $source ) . + sprintf( self::$FMTEND, $compType ); + return $output; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Vjournal.php b/vendor/kigkonsult/icalcreator/src/Formatter/Vjournal.php new file mode 100644 index 0000000..86e27fc --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Vjournal.php @@ -0,0 +1,217 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Vjournal as Source; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.68 2022-10-03 + */ +final class Vjournal extends FormatBase +{ + /** + * @param CalendarComponent|Source $source + * @return string + * @throws Exception + */ + public static function format( CalendarComponent|Source $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + $output = + sprintf( self::$FMTBEGIN, $compType ) . + Property\Property::format( + self::UID, + $source->getUid( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::DTSTAMP, + $source->getDtstamp( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::ATTACH, + $source->getAllAttach( true ), + $allowEmpty + ) . + Property\Attendee::format( + self::ATTENDEE, + $source->getAllAttendee( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::CATEGORIES, + $source->getAllCategories( true ), + $allowEmpty, + $lang + ) . + Property\Property::format( + self::KLASS, + $source->getClass( true ), + $allowEmpty + ) . + Property\Property::format( + self::COLOR, + $source->getColor( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::COMMENT, + $source->getAllComment( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::CONTACT, + $source->getAllContact( true ), + $allowEmpty, + $lang + ) . + Property\DtxProperty::format( + self::CREATED, + $source->getCreated( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::DESCRIPTION, + $source->getAllDescription( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::STYLED_DESCRIPTION, + $source->getAllStyleddescription( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::STRUCTURED_DATA, + $source->getAllStructureddata( true ), + $allowEmpty, + $lang + ); + $dtStart = $source->getDtstart( true ); + $output .= Property\Dt1Property::format( + self::DTSTART, + $dtStart, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart ), + Property\Dt1Property::getIsLocalTime( $dtStart ) + ) . + Property\Exdate::format( + self::EXDATE, + $source->getAllExdate( true ), + $allowEmpty + ) . + Property\Recur::format( + self::EXRULE, + $source->getExrule( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::IMAGE, + $source->getAllImage( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::LAST_MODIFIED, + $source->getLastmodified( true ), + $allowEmpty + ) . + Property\SingleProps::format( + self::ORGANIZER, + $source->getOrganizer( true ), + $allowEmpty, + $lang + ) . + Property\Rdate::format( + self::RDATE, + $source->getAllRdate( true ), + $allowEmpty, + $source->getCompType() + ) . + Property\Requeststatus::format( + self::REQUEST_STATUS, + $source->getAllRequeststatus( true ), + $allowEmpty, + $lang + ); + $reCurrId = $source->getRecurrenceid( true ); + return $output . + Property\Dt1Property::format( + self::RECURRENCE_ID, + $reCurrId, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart, $reCurrId ), + Property\Dt1Property::getIsLocalTime( $reCurrId ) + ) . + Property\MultiProps::format( + self::RELATED_TO, + $source->getAllRelatedto( true ), + $allowEmpty, + $lang + ) . + Property\Recur::format( + self::RRULE, + $source->getRrule( true ), + $allowEmpty + ) . + Property\IntProperty::format( + self::SEQUENCE, + $source->getSequence( true ), + $allowEmpty + ) . + Property\Property::format( + self::STATUS, + $source->getStatus( true ), + $allowEmpty + ) . + Property\SingleProps::format( + self::SUMMARY, + $source->getSummary( true ), + $allowEmpty, + $lang + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ) . + self::formatSubComponents( $source ) . + sprintf( self::$FMTEND, $compType ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Vlocation.php b/vendor/kigkonsult/icalcreator/src/Formatter/Vlocation.php new file mode 100644 index 0000000..a33324b --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Vlocation.php @@ -0,0 +1,101 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Vlocation as Source; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.55 - 2022-08-13 + */ +final class Vlocation extends FormatBase +{ + /** + * @param CalendarComponent|Source $source + * @return string + * @throws Exception + */ + public static function format( CalendarComponent|Source $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + return + sprintf( self::$FMTBEGIN, $compType ) . + Property\Property::format( + self::UID, + $source->getUid( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::DESCRIPTION, + $source->getAllDescription( true ), + $allowEmpty, + $lang + ) . + Property\Geo::format( + self::GEO, + $source->getGeo( true ), + $allowEmpty + ) . + Property\Property::format( + self::URL, + $source->getUrl( true ), + $allowEmpty + ) . + Property\Property::format( + self::LOCATION_TYPE, + $source->getLocationtype( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::NAME, + $source->getAllName( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::STRUCTURED_DATA, + $source->getAllStructureddata( true ), + $allowEmpty, + $lang + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ) . + sprintf( self::$FMTEND, $compType ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Vresource.php b/vendor/kigkonsult/icalcreator/src/Formatter/Vresource.php new file mode 100644 index 0000000..40626cd --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Vresource.php @@ -0,0 +1,96 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Vresource as Source; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.55 - 2022-08-13 + */ +final class Vresource extends FormatBase +{ + /** + * @param CalendarComponent|Source $source + * @return string + * @throws Exception + */ + public static function format( CalendarComponent|Source $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + return + sprintf( self::$FMTBEGIN, $compType ) . + Property\Property::format( + self::UID, + $source->getUid( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::DESCRIPTION, + $source->getAllDescription( true ), + $allowEmpty, + $lang + ) . + Property\Geo::format( + self::GEO, + $source->getGeo( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::NAME, + $source->getAllName( true ), + $allowEmpty, + $lang + ) . + Property\Property::format( + self::RESOURCE_TYPE, + $source->getResourcetype( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::STRUCTURED_DATA, + $source->getAllStructureddata( true ), + $allowEmpty, + $lang + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ) . + sprintf( self::$FMTEND, $compType ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Vtimzone.php b/vendor/kigkonsult/icalcreator/src/Formatter/Vtimzone.php new file mode 100644 index 0000000..63a3cd4 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Vtimzone.php @@ -0,0 +1,91 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Vtimezone as Source; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.55 - 2022-08-13 + */ +final class Vtimzone extends FormatBase +{ + /** + * @param CalendarComponent|Source $source + * @return string + * @throws Exception + */ + public static function format( CalendarComponent|Source $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + $output = + sprintf( self::$FMTBEGIN, $compType ) . + Property\SingleProps::format( + self::TZID, + $source->getTzid( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::TZID_ALIAS_OF, + $source->getAllTzidaliasof( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::LAST_MODIFIED, + $source->getLastmodified( true ), + $allowEmpty + ) . + Property\Property::format( + self::TZURL, + $source->getTzurl( true ), + $allowEmpty + ) . + Property\Dt1Property::format( + self::TZUNTIL, + $source->getTzuntil( true ), + $allowEmpty + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ); + $source->sortVtimezonesSubComponents(); + return $output . + self::formatSubComponents( $source ) . + sprintf( self::$FMTEND, $compType ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Formatter/Vtodo.php b/vendor/kigkonsult/icalcreator/src/Formatter/Vtodo.php new file mode 100644 index 0000000..35c56c0 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Formatter/Vtodo.php @@ -0,0 +1,274 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Formatter; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Vtodo as Source; + +use function strtoupper; +use function sprintf; + +/** + * @since 2.41.55 - 2022-08-13 + */ +final class Vtodo extends FormatBase +{ + /** + * @param CalendarComponent|Source $source + * @return string + * @throws Exception + */ + public static function format( CalendarComponent|Source $source ) : string + { + $compType = strtoupper( $source->getCompType()); + $allowEmpty = $source->getConfig( self::ALLOWEMPTY ); + $lang = $source->getConfig( self::LANGUAGE ); + $output = + sprintf( self::$FMTBEGIN, $compType ) . + Property\Property::format( + self::UID, + $source->getUid( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::DTSTAMP, + $source->getDtstamp( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::ATTACH, + $source->getAllAttach( true ), + $allowEmpty + ) . + Property\Attendee::format( + self::ATTENDEE, + $source->getAllAttendee( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::CATEGORIES, + $source->getAllCategories( true ), + $allowEmpty, + $lang + ) . + Property\Property::format( + self::KLASS, + $source->getClass( true ), + $allowEmpty + ) . + Property\Property::format( + self::COLOR, + $source->getColor( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::COMMENT, + $source->getAllComment( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::CONFERENCE, + $source->getAllConference( true ), + $allowEmpty, + $lang + ) . + Property\DtxProperty::format( + self::COMPLETED, + $source->getCompleted( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::CONTACT, + $source->getAllContact( true ), + $allowEmpty, + $lang + ) . + Property\DtxProperty::format( + self::CREATED, + $source->getCreated( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::DESCRIPTION, + $source->getAllDescription( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::STYLED_DESCRIPTION, + $source->getAllStyleddescription( true ), + $allowEmpty, + $lang + ) . + Property\MultiProps::format( + self::STRUCTURED_DATA, + $source->getAllStructureddata( true ), + $allowEmpty, + $lang + ); + $dtStart = $source->getDtstart( true ); + $output .= Property\Dt1Property::format( + self::DTSTART, + $dtStart, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart ), + Property\Dt1Property::getIsLocalTime( $dtStart ) + ); + $due = $source->getDue( true ); + $output .= Property\Dt1Property::format( + self::DUE, + $due, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart, $due ), + Property\Dt1Property::getIsLocalTime( $due ) + ) . + Property\DurDates::format( + self::DURATION, + $source->getDuration( true ), + $allowEmpty + ) . + Property\Exdate::format( + self::EXDATE, + $source->getAllExdate( true ), + $allowEmpty + ) . + Property\Recur::format( + self::EXRULE, + $source->getExrule( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::IMAGE, + $source->getAllImage( true ), + $allowEmpty + ) . + Property\Geo::format( + self::GEO, + $source->getGeo( true ), + $allowEmpty + ) . + Property\DtxProperty::format( + self::LAST_MODIFIED, + $source->getLastmodified( true ), + $allowEmpty + ) . + Property\MultiProps::format( + self::LOCATION, + $source->getAllLocation( true ), + $allowEmpty, + $lang + ) . + Property\SingleProps::format( + self::ORGANIZER, + $source->getOrganizer( true ), + $allowEmpty, + $lang + ) . + Property\IntProperty::format( + self::PERCENT_COMPLETE, + $source->getPercentcomplete( true ), + $allowEmpty + ) . + Property\IntProperty::format( + self::PRIORITY, + $source->getPriority( true ), + $allowEmpty + ) . + Property\Rdate::format( + self::RDATE, + $source->getAllRdate( true ), + $allowEmpty, + $source->getCompType() + ) . + Property\MultiProps::format( + self::RELATED_TO, + $source->getAllRelatedto( true ), + $allowEmpty, + $lang + ) . + Property\Requeststatus::format( + self::REQUEST_STATUS, + $source->getAllRequeststatus( true ), + $allowEmpty, + $lang + ); + $reCurrId = $source->getRecurrenceid( true ); + $output .= + Property\Dt1Property::format( + self::RECURRENCE_ID, + $reCurrId, + $allowEmpty, + Property\Dt1Property::getIsDate( $dtStart, $reCurrId ), + Property\Dt1Property::getIsLocalTime( $reCurrId ) + ) . + Property\MultiProps::format( + self::RESOURCES, + $source->getAllResources( true ), + $allowEmpty, + $lang + ) . + Property\Recur::format( + self::RRULE, + $source->getRrule( true ), + $allowEmpty + ) . + Property\IntProperty::format( + self::SEQUENCE, + $source->getSequence( true ), + $allowEmpty + ) . + Property\Property::format( + self::STATUS, + $source->getStatus( true ), + $allowEmpty + ) . + Property\SingleProps::format( + self::SUMMARY, + $source->getSummary( true ), + $allowEmpty, + $lang + ) . + Property\Property::format( + self::URL, + $source->getUrl( true ), + $allowEmpty + ) . + Property\Xproperty::format( + $source->getAllXprop( true ), + $allowEmpty, + $lang + ) . + self::formatSubComponents( $source ) . + sprintf( self::$FMTEND, $compType ); + return $output; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Parser/ComponentParser.php b/vendor/kigkonsult/icalcreator/src/Parser/ComponentParser.php new file mode 100644 index 0000000..142a3ee --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Parser/ComponentParser.php @@ -0,0 +1,481 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Parser; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\Util\StringFactory; +use RuntimeException; + +use function count; +use function ctype_alpha; +use function explode; +use function implode; +use function in_array; +use function is_array; +use function str_starts_with; +use function strcasecmp; +use function stripos; +use function strlen; +use function strtoupper; +use function substr; +use function trim; + +/** + * @since 2.41.88 2024-01-17 + */ +final class ComponentParser extends ParserBase +{ + /** + * @inheritDoc + * @throws RuntimeException + */ + public function parse( null|array|string $unParsedText = null ) : CalendarComponent + { + try { + $rows = $this->parse1prepInput( $unParsedText ); + if( ! empty( $rows ) ) { + $this->parse2intoComps( $rows ); + } + } + catch( Exception $e ) { + throw new RuntimeException( $e->getMessage(), $e->getCode(), $e ); + } + return $this->subject; + } + + /** + * Return rows to parse + * + * @param null|string|string[] $unParsedText strict rfc2445 formatted, single property string or array of strings + * @return string[] + * @throws Exception + * @since 2.29.3 - 2019-06-20 + */ + private function parse1prepInput( null|string|array $unParsedText = null ) : array + { + static $NLCHARS = '\n'; + static $BEGIN = 'BEGIN:'; + switch( true ) { + case ( ! empty( $unParsedText )) : + $arrParse = false; + if( is_array( $unParsedText )) { + $unParsedText = implode( + $NLCHARS . self::$CRLF, + $unParsedText + ); + $arrParse = true; + } + $rows = self::convEolChar( $unParsedText ); + if( $arrParse ) { + foreach( $rows as $lix => $row ) { + $rows[$lix] = StringFactory::trimTrailNL( $row ); + } + } + break; + case empty( $this->unparsed ) : + $rows = []; + break; + default : + $rows = $this->unparsed; + break; + } // end switch + /* skip leading (empty/invalid) lines */ + foreach( $rows as $lix => $row ) { + if( false !== ( $pos = stripos( $row, $BEGIN ))) { + $rows[$lix] = substr( $row, $pos ); + break; + } + $tst = trim( $row ); + if(( $NLCHARS === $tst ) || empty( $tst )) { + unset( $rows[$lix] ); + } + } // end foreach + return $rows; + } + + /** + * Parse into this and sub-components data + * + * @param string[] $rows + * @return void + * @throws Exception + * @since 2.41.11 - 2022-01-27 + */ + private function parse2intoComps( array $rows ) : void + { + static $END_ALARM = 'END:VALARM'; + static $END_PARTICIPANT = 'END:PARTICIPANT'; + static $ENDSARR = [ 'END:AV', 'END:DA', 'END:ST', 'END:VL', 'END:VR' ]; + static $END = 'END:'; + static $BEGIN = 'BEGIN:'; + static $BEGIN_AVAILABLE = 'BEGIN:AVAILABLE'; + static $BEGIN_DAYLIGHT = 'BEGIN:DAYLIGHT'; + static $BEGIN_PARTICIPANT = 'BEGIN:PARTICIPANT'; + static $BEGIN_STANDARD = 'BEGIN:STANDARD'; + static $BEGIN_VALARM = 'BEGIN:VALARM'; + static $BEGIN_VLOCATION = 'BEGIN:VLOCATION'; + static $BEGIN_VRESOURCE = 'BEGIN:VRESOURCE'; + $parser = $this; + $this->unparsed = []; + $compType = strtoupper( $this->subject->getCompType()); + $beginTag = $BEGIN . $compType; + $endTag = $END . $compType; + $endFound = false; + $isParticipantCurrent = $isValarmCurrent = false; + foreach( $rows as $row ) { + switch( true ) { + case str_starts_with( $row, $beginTag ) : // begin: + break; + case str_starts_with( $row, $endTag ) : // end: + $this->parse3thisProperties(); + $endFound = true; + break 2; // skip opt trailing empty lines.. + case $isValarmCurrent && str_starts_with( $row, $END_ALARM ) : + $parser->parse(); + $isValarmCurrent = false; + break; + case $isParticipantCurrent && str_starts_with( $row, $END_PARTICIPANT ) : + $parser->parse(); + $isParticipantCurrent = false; + break; + case ( $isValarmCurrent || $isParticipantCurrent ) : + $parser->addUnparsedRow( $row ); + break; + case ( in_array( strtoupper( substr( $row, 0, 6 )), $ENDSARR, true )) : + $parser->parse(); + break; + case str_starts_with( $row, $BEGIN_VALARM ) : + $parser = self::factory( $this->subject->newValarm()); + $isValarmCurrent = true; + break; + case str_starts_with( $row, $BEGIN_PARTICIPANT ) : + $parser = self::factory( $this->subject->newParticipant()); + $isParticipantCurrent = true; + break; + case str_starts_with( $row, $BEGIN_AVAILABLE ) : + $parser = self::factory( $this->subject->newAvailable()); + break; + case str_starts_with( $row, $BEGIN_DAYLIGHT ) : + $parser = self::factory( $this->subject->newDaylight()); + break; + case str_starts_with( $row, $BEGIN_STANDARD ) : + $parser = self::factory( $this->subject->newStandard()); + break; + case str_starts_with( $row, $BEGIN_VLOCATION ) : + $parser = self::factory( $this->subject->newVlocation()); + break; + case str_starts_with( $row, $BEGIN_VRESOURCE ) : + $parser = self::factory( $this->subject->newVresource()); + break; + default : + $parser->addUnparsedRow( $row ); + break; + } // end switch( true ) + } // end foreach( $rows as $lix => $row ) + if( ! $endFound ) { + $this->parse3thisProperties(); + } + } + + /** + * Parse this properties + * + * @return void + * @since 2.41.88 2024-01-17 + * @todo report invalid properties ?? + */ + private function parse3thisProperties() : void + { + static $STRUNREPPROPS = [ + self::CATEGORIES, self::COMMENT, self::CONTACT, self::DESCRIPTION, + self::LOCATION, self::PROXIMITY, self::RESOURCES, self::STRUCTURED_DATA, + self::STYLED_DESCRIPTION, self::SUMMARY, + self::ACTION, self::BUSYTYPE, self::KLASS, self::RELATED_TO, self::STATUS, + self::TRANSP, self::TZID, self::TZID_ALIAS_OF, self::TZNAME, self::UID, + ]; + static $STRUNREPPROP = 'STRUNREPPROP'; + if( empty( $this->unparsed )) { + return; + } + /* concatenate property values spread over several lines */ + $this->unparsed = self::concatRows( $this->unparsed ); + /* parse each property 'line' */ + foreach( $this->unparsed as $row ) { + /* get propname + split property name and opt.params and value */ + [ $propName, $row ] = StringFactory::getPropName( $row ); + if( StringFactory::isXprefixed( $propName )) { + [ $value, $propAttr ] = self::splitContent( $row ); + $this->subject->setXprop( $propName, StringFactory::strunrep( $value ), $propAttr ); + continue; + } + if( ! property_exists( $this->subject, StringFactory::getInternalPropName( $propName ))) { + continue; // skip property names not in comp, todo report invalid properties ?? + } + /* separate attributes from value */ + [ $value, $propAttr ] = self::splitContent( $row, $propName ); + if( ! in_array( $propName, self::$TEXTPROPS, true )) { + $value = StringFactory::trimTrailNL( $value ); + } + /* call set(.. . */ + $method = StringFactory::getSetMethodName( $propName ); + if( in_array( $propName, $STRUNREPPROPS, true )) { + $propName = $STRUNREPPROP; + } + match( $propName ) { + self::ATTENDEE => + $this->subject->{$method}( $value, self::processAttendeeParams( $propAttr )), + $STRUNREPPROP => + $this->subject->{$method}( StringFactory::strunrep( $value ), $propAttr ), + self::REQUEST_STATUS => + $this->parseRequestStatus( $method, $value, $propAttr ), + self::FREEBUSY => + $this->parseFreebusy( $method, $value, $propAttr ), + self::GEO => + $this->parseGeo( $method, $value, $propAttr ), + self::EXDATE => + $this->subject->{$method}( self::parseExdate( $value ), $propAttr ), + self::RDATE => + $this->parseRdate( $method, $value, $propAttr ), + self::EXRULE, self::RRULE => + $this->subject->{$method}( self::parseRexrule( $value ), $propAttr ), + default => + $this->subject->{$method}( $value, $propAttr ) + }; // end match( $propName.. . + } // end foreach( $this->unparsed as $lix => $row ) + $this->unparsed = []; + } + + /** + * Split multiple Attendees MEMBER/DELEGATED-TO/DELEGATED-FROM into array, if found + * + * @param string[]|string[][] $propAttr + * @return string[]|string[][] + * @since 2.27.11 - 2019-01-04 + */ + private static function processAttendeeParams( array $propAttr ) : array + { + static $ParamArrayKeys = [ self::MEMBER, self::DELEGATED_TO, self::DELEGATED_FROM ]; + foreach( $propAttr as $pix => $attr ) { + if( ! in_array( strtoupper( $pix ), $ParamArrayKeys, true )) { + continue; + } + $attr2 = explode( self::$COMMA, (string) $attr ); + if( 1 < count( $attr2 )) { + $propAttr[$pix] = $attr2; + } + } + return $propAttr; + } + + /** + * Return Request-Status value array + * + * @param string $method + * @param string $value + * @param string[] $propAttr + * @return void + * @since 2.41.88 2024-01-17 + */ + private function parseRequestStatus( string $method, string $value, array $propAttr ) : void + { + $input = $this->subject::extractRequeststatus( $value ); + if( isset( $input[1] )) { + $input[1] = StringFactory::strunrep( $input[1] ); + } + else { + $propAttr = []; + } + if( isset( $input[2] )) { + $input[2] = StringFactory::strunrep( $input[2] ); + } + $this->subject->{$method}( $input[0], $input[1], $input[2], $propAttr ); + } + + /** + * Return type, value and parameters from parsed (Freebusy) row and propAttr + * + * @param string $method + * @param string $row + * @param string[] $propAttr + * @return void + * @since 2.41.88 2024-01-17 + */ + private function parseFreebusy( string $method, string $row, array $propAttr ) : void + { + static $SS = '/'; + $fbtype = $values = null; + if( ! empty( $propAttr )) { + foreach( $propAttr as $k => $v ) { + if( 0 === strcasecmp( self::FBTYPE, $k )) { + $fbtype = $v; + unset( $propAttr[$k] ); + break; + } + } // end foreach + } // end if + if( ! empty( $row )) { + $values = explode( self::$COMMA, $row ); + foreach( $values as $vix => $value ) { + $value2 = explode( $SS, $value ); // '/' + if( 1 < count( $value2 )) { + $values[$vix] = $value2; + } + } // end foreach + } // end if + $this->subject->{$method}( $fbtype, $values, $propAttr ); + } + + /** + * Return Geo value array + * + * @param string $method + * @param string $value + * @param string[] $propAttr + * @return void + * @since 2.41.88 2024-01-17 + */ + private function parseGeo( string $method, string $value, array $propAttr ) : void + { + $input = $this->subject::extractGeoLatLong( $value ); + if( ! isset( $input[0] )) { + $propAttr = []; + } + $this->subject->{$method}( $input[0], $input[1], $propAttr ); + } + + /** + * Return Exdate value + * + * @param string $value + * @return null|string[] + * @since 2.41.68 - 2022-19-24 + */ + private static function parseExdate( string $value ) : ?array + { + return empty( $value ) ? null : explode( self::$COMMA, $value ); + } + + /** + * Return value and parameters from parsed row and propAttr + * + * @param string $method + * @param string $row + * @param string[] $propAttr + * @return void + * @since 2.41.88 - 2024-01-17 + */ + private function parseRdate( string $method, string $row, array $propAttr ) : void + { + static $SS = '/'; + if( empty( $row )) { + $this->subject->{$method}( null, $propAttr ); + return; + } + $values = explode( self::$COMMA, $row ); + foreach( $values as $vix => $value ) { + if( ! str_contains( $value, $SS ) ) { + continue; + } + $value2 = explode( $SS, $value ); + if( 1 < count( $value2 )) { + $values[$vix] = $value2; + } + } // end foreach + $this->subject->{$method}( $values, $propAttr ); + } + + /** + * Return (array) parsed rexrule string + * + * @param string $row + * @return string[]|string[][] + * @since 2.27.3 - 2018-12-28 + */ + private static function parseRexrule( string $row ) : array + { + static $EQ = '='; + $recur = []; + $values = explode( self::$SEMIC, $row ); + foreach( $values as $value2 ) { + if( empty( $value2 )) { + continue; + } // ;-char in end position ??? + $value3 = explode( $EQ, $value2, 2 ); + $ruleLabel = strtoupper( $value3[0] ); + $value4 = explode( self::$COMMA, $value3[1] ); + if( self::BYDAY === $ruleLabel ) { + if( 1 < count( $value4 )) { + foreach( $value4 as $v5ix => $value5 ) { + $value4[$v5ix] = self::updateDayNoAndDayName( trim( $value5 )); + } + } + else { + $value4 = self::updateDayNoAndDayName( trim( $value3[1] )); + } + $recur[$ruleLabel] = $value4; + } // end if + else { + if( 1 < count( $value4 )) { + $value3[1] = $value4; + } + $recur[$ruleLabel] = $value3[1]; + } // end else + } // end - foreach( $values.. . + return $recur; + } + + /** + * Return array, day rel pos number (opt) and day name abbr + * + * @param string $dayValueBase + * @return string[] + * @since 2.27.16 - 2019-03-03 + */ + private static function updateDayNoAndDayName( string $dayValueBase ) : array + { + $output = []; + $dayno = $dayName = false; + if(( ctype_alpha( substr( $dayValueBase, -1 ))) && + ( ctype_alpha( $dayValueBase[strlen( $dayValueBase ) - 2] ))) { + $dayName = substr( $dayValueBase, -2, 2 ); + if( 2 < strlen( $dayValueBase )) { + $dayno = (int) substr( $dayValueBase, 0, ( strlen( $dayValueBase ) - 2 )); + } + } + if( false !== $dayno ) { + $output[] = $dayno; + } + if( false !== $dayName ) { + $output[self::DAY] = $dayName; + } + return $output; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Parser/ParserBase.php b/vendor/kigkonsult/icalcreator/src/Parser/ParserBase.php new file mode 100644 index 0000000..9cfe96f --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Parser/ParserBase.php @@ -0,0 +1,510 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Parser; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\IcalInterface; +use Kigkonsult\Icalcreator\Util\CalAddressFactory; +use Kigkonsult\Icalcreator\Util\StringFactory as SF; +use Kigkonsult\Icalcreator\Vcalendar; + +use function bin2hex; +use function count; +use function ctype_digit; +use function explode; +use function in_array; +use function rtrim; +use function sprintf; +use function str_replace; +use function stristr; +use function strlen; +use function strpos; +use function strstr; +use function strtolower; +use function strtoupper; +use function substr; +use function substr_count; + +/** + * @since 2.41.88 2024-01-17 + */ +abstract class ParserBase implements IcalInterface +{ + /** + * @var string + */ + protected static string $COLON = ':'; + + /** + * @var string + */ + protected static string $COMMA = ','; + + /** + * @var string + */ + protected static string $CRLF = "\r\n"; + + /** + * @var string + */ + protected static string $SEMIC = ';'; + + /** + * @var string + */ + protected static string $SP0 = ''; + + /** + * @var string[] iCal component TEXT properties that may contain '\\', ',', ';' + * @usedby VcalendarParser + ComponentParser + * + * the others are + * ACTION, CLASS, COLOR, RELATED-TO, + * PARTICIPANT_TYPE, REQUEST-STATUS, RESOURCE_TYPE + * STATUS, TRANSP, TZID, TZID_ALIAS_OF, TZNAME, UID + */ + protected static array $TEXTPROPS = [ + self::CATEGORIES, + self::COMMENT, + self::CONTACT, + self::DESCRIPTION, + self::LOCATION, + self::LOCATION_TYPE, + self::NAME, + self::RESOURCES, + self::STRUCTURED_DATA, + self::STYLED_DESCRIPTION, + self::SUMMARY, + ]; + + /** + * Subject to parse into + * + * @var Vcalendar|CalendarComponent + */ + protected Vcalendar|CalendarComponent $subject; + + /** + * Rows to parse + * + * @var string[] + */ + protected array $unparsed = []; + + /** + * @param Vcalendar|CalendarComponent $subject + * @return static + */ + public static function factory( Vcalendar|CalendarComponent $subject ) : static + { + $instance = new static(); + $instance->setSubject( $subject ); + return $instance; + } + + protected static string $EQ = '='; + protected static string $QQ = '"'; + + /** + * Return array property value and attributes + * + * Attributes are prefixed by ';', value by ':', BUT they may exist in both attr (quoted?) and values + * Known bug here: property parse with param ALTREP (etc?) with unquoted url with ..>user.passwd@<.. before hostname + * + * @param string $line property content + * @param null|string $propName + * @return array [ value, [ *( propAttrKey => propAttrValue) ] ] + * @since 2.41.70 2022-10-21 + */ + public static function splitContent( string $line, ?string $propName = null ) : array + { + $clnPos = strpos( $line, self::$COLON ); + if( ( false === $clnPos )) { + return [ $line, [] ]; // no params and no colon (empty property) + } + if( 0 === $clnPos ) { // no params, most frequent + return [ substr( $line, 1 ), [] ]; + } + if( self::checkSingleParam( $line )) { // one (simpler) param + return self::processSingleParam( $line ); + } + if( self::mayHaveUriParam( $propName )) { + SF::checkFixUrlDecode( $line ); + $line = self::checkFixUriMessage( $line ); + } + /* more than one param here (or a tricky one...) */ + $attr = []; + $line = self::extractTextParams( $line, $attr ); // simpler (text) ones + $line = self::extractMultiParams( $line, $attr ); + return [ $line, self::processAttributes( $attr) ]; + } + + /** + * Return bool true if propName may a URI VALUE parameter + * + * @param string|null $propName + * @return bool + */ + protected static function mayHaveUriParam( ? string $propName ) : bool + { + static $URIprops = [ self::SOURCE, self::URL, self::TZURL ]; + return ( ! empty( $propName ) && + in_array( strtoupper( $propName ), $URIprops, true )); + } + + /** + * Remove opt 'VALUE=URI:message:' + * + * orginating from any Apple device + * + * @param string $line + * @return string + * @since 2.41.88 2024-01-17 + */ + protected static function checkFixUriMessage( string $line ) : string + { + static $Um = 'URI:message'; + static $SQVEQUm = ';VALUE=URI:message'; + static $SQVEQUmq = ';VALUE=\'URI:message\''; + static $SQVEQUmqq = ';VALUE="URI:message"'; + return match( true ) { + ( false === stripos( $line, $Um )) => $line, + ( false !== stripos( $line, $SQVEQUm )) => // no quote + str_ireplace( $SQVEQUm, SF::$SP0, $line ), + ( false !== stripos( $line, $SQVEQUmq )) => // single quote + str_ireplace( $SQVEQUmq, SF::$SP0, $line ), + ( false !== stripos( $line, $SQVEQUmqq )) => // double quote + str_ireplace( $SQVEQUmqq, SF::$SP0, $line ), + default => $line + }; // end match + } + + /** + * Extract and remove opt (simpler) TEXT parameters from line and upd attr array + * + * @param string $line + * @param string[] $attr + * @return string + * @since 2.41.70 2022-10-20 + */ + protected static function extractTextParams( string $line, array & $attr ) : string + { + static $searchKeyArr = [ + 'CUTYPE=', + 'ENCODING=', + 'FMTTYPE=', + 'FBTYPE=', + 'LANGUAGE=', + 'ORDER=', + 'PARTSTAT=', + 'RELATED=', + 'RELTYPE=', + 'ROLE=', + 'VALUE=', + 'TZID=' + ]; + foreach( $searchKeyArr as $needle ) { + $search = self::$SEMIC . $needle; + if( ! str_contains( $line, $search )) { + continue; + } + $line1 = stristr( $line, $search, true ); + $temp = SF::after( $search, $line ); + [ $attrValue, $rightPart ] = SF::splitByFirstSQorColon( $temp ); + $attr[] = $needle . $attrValue; + $line = $line1 . $rightPart; + } // end foreach + return $line; + } + + /** + * Extract and remove multi parameters from line and upd attr array + * + * @param string $line + * @param string[] $attr + * @return string + * @since 2.41.70 2022-10-21 + */ + protected static function extractMultiParams( string $line, array & $attr ) : string + { + static $CSS = '://'; + if( self::$COLON === $line[0] ) { // no params found + return substr( $line, 1 ); + } + $attrix = count( $attr ) - 1; + $withinQuotes = false; + $len = strlen( $line ); + $cix = 0; + while( $cix < $len ) { + $str1 = $line[$cix]; + $cix1 = $cix + 1; + if( ! $withinQuotes && + ( self::$COLON === $str1 ) && + ( $CSS !== substr( $line, $cix, 3 )) && // '://' + ! self::colonIsPrefixedByProtocol( $line, $cix ) && + ! self::hasPortNUmber( substr( $line, $cix1, 7 ))) { + $line = substr( $line, $cix1 ); + break; + } + if( self::$QQ === $str1 ) { // '"' + $withinQuotes = ! $withinQuotes; + } + if( self::$SEMIC === $str1 ) { // ';' + ++$attrix; + $attr[$attrix] = self::$SP0; // initiate new param + } + else { + $attr[$attrix] .= $str1; + } + ++$cix; + } // end while... + return $line; + } + + /** + * Return bool true if leading chars in (unquoted) string is a port number (i.e. followed by '/') + * + * @param string $string + * @return bool + * @since 2.41.49 - 2022-05-02 + */ + public static function hasPortNUmber( string $string ) : bool + { + $len = strlen( $string ); + $hasDigit = false; + for( $x = 0; $x < $len; $x++ ) { + $str1 = $string[$x]; + if( ctype_digit( $str1 )) { + $hasDigit = true; + continue; + } + if( $hasDigit && ( SF::$SLASH === $str1 )) { + return true; + } + break; + } // end for + return false; + } + + /** + * Return true if single param only (and no colon/semicolon in param values) + * + * 2nd most frequent + * + * @param string $line + * @return bool + * @since 2.30.3 - 2021-02-14 + */ + protected static function checkSingleParam( string $line ) : bool + { + if( SF::$SEMIC !== $line[0] ) { + return false; + } + return (( 1 === substr_count( $line, SF::$SEMIC )) && + ( 1 === substr_count( $line, SF::$COLON ))); + } + + /** + * Return array, property content and single param array + * + * @param string $line + * @return array + */ + protected static function processSingleParam( string $line ) : array + { + $param = SF::between( SF::$SEMIC, SF::$COLON, $line ); + return [ + SF::after( self::$COLON, $line ), + [ + strstr( $param, self::$EQ, true ) => + trim( SF::after( self::$EQ, $param ), self::$QQ ) + ] + ]; + } + + /** + * Return bool true if colon-pos is prefixed by protocol + * + * @see https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml overkill !! + * + * @param string $line + * @param int $cix + * @return bool + * @since 2.30.2 - 2021-02-04 + */ + public static function colonIsPrefixedByProtocol( string $line, int $cix ) : bool + { + static $MSTZ = [ 'utc-', 'utc+', 'gmt-', 'gmt+' ]; + $line = strtolower( $line ); + return ( ( in_array( substr( $line, $cix - 6, 4 ), $MSTZ )) || // ?? -6 + ( in_array( substr( $line, $cix - 3, 4 ), CalAddressFactory::$PROTO3, true )) || + ( in_array( substr( $line, $cix - 4, 5 ), CalAddressFactory::$PROTO4, true )) || + ( in_array( substr( $line, $cix - 5, 6 ), CalAddressFactory::$PROTO5, true )) || + ( in_array( substr( $line, $cix - 6, 7 ), CalAddressFactory::$PROTO6, true )) || + ( in_array( substr( $line, $cix - 7, 8 ), CalAddressFactory::$PROTO7, true ))); + } + + /** + * Return attributes in array format, i.e. split key and value + * + * @param string[] $attr + * @return string[] + */ + protected static function processAttributes( array $attr ) : array + { + $propAttr = []; + foreach( $attr as $attribute ) { + if( ! str_contains( $attribute, self::$EQ ) ) { + continue;// skip empty? attributes + } + $attrSplit = explode( self::$EQ, $attribute, 2 ); + $propAttr[$attrSplit[0]] = $attrSplit[1]; + } + return $propAttr; + } + + /** + * @param null|string|string[] $unParsedText strict rfc2445 formatted, single property string or array of strings + * @return Vcalendar|CalendarComponent + */ + abstract public function parse( null|string|array $unParsedText ) : Vcalendar|CalendarComponent; + + /** + * @return CalendarComponent|Vcalendar|null + */ + public function getSubject() : Vcalendar | CalendarComponent | null + { + return $this->subject; + } + + /** + * @param CalendarComponent|Vcalendar|null $subject + * @return static + */ + public function setSubject( Vcalendar | CalendarComponent | null $subject ) : static + { + $this->subject = $subject; + return $this; + } + + /** + * @return string[] + */ + public function getUnparsed() : array + { + return $this->unparsed; + } + + /** + * @param string $row + * @return static + */ + public function addUnparsedRow ( string $row ) : static + { + $this->unparsed[] = $row; + return $this; + } + + /** + * @param string[] $unparsed + * @return static + */ + public function setUnparsed( array $unparsed ) : static + { + $this->unparsed = $unparsed; + return $this; + } + + /** + * Return concatenated calendar rows, one row for each property + * + * @param string[] $rows + * @return string[] + * @since 2.29.20 - 2020-01-31 + */ + public static function concatRows( array $rows ) : array + { + static $CHARs = [ ' ', "\t" ]; + $output = []; + $cnt = count( $rows ); + for( $i = 0; $i < $cnt; $i++ ) { + $line = rtrim( $rows[$i], SF::$CRLF ); + $i1 = $i + 1; + while( ( $i < $cnt ) && + ! empty( $rows[$i1] ) && + in_array( $rows[$i1][0], $CHARs )) { + ++$i; + $line .= rtrim( substr( $rows[$i], 1 ), SF::$CRLF ); + $i1 = $i + 1; + } // end while + $output[] = $line; + } // end for + return $output; + } + + /** + * Return strings with removed ical line folding + * + * Remove any line-endings that may include spaces or tabs + * and convert all line endings (iCal default '\r\n'), + * takes care of '\r\n', '\r' and '\n' and mixed '\r\n'+'\r', '\r\n'+'\n' + * + * @param string $text + * @return string[] + * @throws Exception + * @since 2.29.9 - 2019-03-30 + */ + protected static function convEolChar( string & $text ) : array + { + static $BASEDELIM = null; + static $BASEDELIMs = null; + static $EMPTYROW = null; + static $FMT = '%1$s%2$75s%1$s'; + static $CRLFs = [ "\r\n", "\n\r", "\n", "\r" ]; + static $CRLFexts = [ "\r\n ", "\r\n\t" ]; + /* fix dummy line separator etc */ + if( empty( $BASEDELIM )) { + $BASEDELIM = bin2hex( SF::getRandChars( 16 )); + $BASEDELIMs = $BASEDELIM . $BASEDELIM; + $EMPTYROW = sprintf( $FMT, $BASEDELIM, SF::$SP0 ); + } + /* fix eol chars */ + $text = str_replace( $CRLFs, $BASEDELIM, $text ); + /* fix empty lines */ + $text = str_replace( $BASEDELIMs, $EMPTYROW, $text ); + /* fix line folding */ + $text = str_replace( $BASEDELIM, SF::$CRLF, $text ); + $text = str_replace( $CRLFexts, SF::$SP0, $text ); + /* split in component/property lines */ + return explode( SF::$CRLF, $text ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Parser/VcalendarParser.php b/vendor/kigkonsult/icalcreator/src/Parser/VcalendarParser.php new file mode 100644 index 0000000..9547c02 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Parser/VcalendarParser.php @@ -0,0 +1,325 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Parser; + +use Exception; +use InvalidArgumentException; +use Kigkonsult\Icalcreator\Util\StringFactory; +use Kigkonsult\Icalcreator\Vcalendar; +use UnexpectedValueException; + +use function array_unshift; +use function count; +use function implode; +use function in_array; +use function is_array; +use function sprintf; +use function str_starts_with; +use function stripos; +use function strtoupper; +use function substr; +use function trim; + +/** + * @since 2.41.54 - 2022-08-09 + */ +final class VcalendarParser extends ParserBase +{ + /** + * @var string + */ + private static string $BEGIN_VCALENDAR = 'BEGIN:VCALENDAR'; + + /** + * @var string + */ + private static string $END_VCALENDAR = 'END:VCALENDAR'; + + /** + * @var string + */ + private static string $NLCHARS = '\n'; + + /** + * Parse iCal text/file into Vcalendar, components, properties and parameters + * + * @inheritDoc + * @throws Exception + * @throws InvalidArgumentException + * @throws UnexpectedValueException + * @since 2.41.54 2022-08-08 + */ + public function parse( null|string|array $unParsedText ) : Vcalendar + { + $rows = self::conformParseInput( $unParsedText ); + $this->parse2intoComps( $rows ); + $this->parse3thisProperties(); + return $this->subject; + } + + /** + * Return rows to parse from string or array + * + * @param string|string[] $unParsedText strict rfc2445 formatted, single property string or array of strings + * @return string[] + * @throws UnexpectedValueException + * @throws Exception + * @since 2.41.49 - 2022-05-01 + */ + public static function conformParseInput( string | array $unParsedText ) : array + { + static $ERR10 = 'Only %d rows in calendar content :%s'; + $arrParse = false; + if( is_array( $unParsedText )) { + $rows = implode( self::$NLCHARS . StringFactory::$CRLF, $unParsedText ); + $arrParse = true; + } + else { // string + $rows = $unParsedText; + } + /* fix line folding */ + $rows = self::convEolChar( $rows ); + if( $arrParse ) { + foreach( $rows as $lix => $row ) { + $rows[$lix] = StringFactory::trimTrailNL( $row ); + } + } + if( empty( $rows )) { /* err 9 */ + throw new UnexpectedValueException( + sprintf( $ERR10, 9, StringFactory::$SP0 ) + ); + } + /* skip leading (empty/invalid) lines (and remove leading BOM chars etc) */ + $rows = self::trimLeadingRows( $rows ); + /* skip trailing empty lines and ensure an end row */ + $rows = self::trimTrailingRows( $rows ); + $cnt = count( $rows ); + if( 2 === $cnt ) { /* err 10 */ + throw new UnexpectedValueException( + sprintf( $ERR10, $cnt, PHP_EOL . implode( PHP_EOL, $rows )) + ); + } + return $rows; + } + + /** + * Return array to parse with leading (empty/invalid) lines removed (incl leading BOM chars etc) + * + * Ensure BEGIN:CALENDAR on the first row + * + * @param string[] $rows + * @return string[] + * @since 2.41.49 - 2022-05-01 + */ + private static function trimLeadingRows( array $rows ) : array + { + $beginFound = false; + foreach( $rows as $lix => $row ) { + if( false !== stripos( $row, self::$BEGIN_VCALENDAR )) { + $rows[$lix] = self::$BEGIN_VCALENDAR; + $beginFound = true; + continue; + } + if( ! empty( trim( $row ))) { + break; + } + unset( $rows[$lix] ); + } // end foreach + if( ! $beginFound ) { + array_unshift( $rows, self::$BEGIN_VCALENDAR ); + } + return $rows; + } + + /** + * Return array to parse with trailing empty lines removed and ensured an end row + * + * Ensure END:CALENDAR on the last row + * + * @param string[] $rows + * @return string[] + * @since 2.41.49 - 2022-05-01 + */ + private static function trimTrailingRows( array $rows ) : array + { + end( $rows ); + $lix = key( $rows ); + while( 0 <= $lix ) { + $tst = trim( $rows[$lix] ); + if(( self::$NLCHARS === $tst ) || empty( $tst )) { + unset( $rows[$lix] ); + $lix--; + continue; + } + if( false === stripos( $rows[$lix], self::$END_VCALENDAR )) { + $rows[] = self::$END_VCALENDAR; + } + else { + $rows[$lix] = self::$END_VCALENDAR; + } + break; + } // end while + return $rows; + } + + /** + * Parse into calendar and comps data + * + * @param string[] $rows + * @return void + * @throws Exception + * @throws UnexpectedValueException + * @since 2.41.9 - 2022-01-27 + */ + private function parse2intoComps( array $rows ) : void + { + static $ENDSARR = [ 'END:VAV', 'END:VEV', 'END:VFR', 'END:VJO', 'END:VTI', 'END:VTO' ]; + static $BEGIN_VAVAILABILITY = 'BEGIN:VAVAILABILITY'; + static $BEGIN_VEVENT = 'BEGIN:VEVENT'; + static $BEGIN_VFREEBUSY = 'BEGIN:VFREEBUSY'; + static $BEGIN_VJOURNAL = 'BEGIN:VJOURNAL'; + static $BEGIN_VTODO = 'BEGIN:VTODO'; + static $BEGIN_VTIMEZONE = 'BEGIN:VTIMEZONE'; + $parser = $this; + /* identify components and update unparsed data for components */ + foreach( $rows as $row ) { + switch( true ) { + case str_starts_with( $row, self::$BEGIN_VCALENDAR ) : + break; + case str_starts_with( $row, self::$END_VCALENDAR ) : + $this->parse3thisProperties(); + break 2; + case ( in_array( strtoupper( substr( $row, 0, 7 )), $ENDSARR, true )) : + $parser->parse(); // i.e. NOT Vcalendar + break; + case str_starts_with( $row, $BEGIN_VAVAILABILITY ) : + $parser = ComponentParser::factory( $this->subject->newVavailability()); + break; + case str_starts_with( $row, $BEGIN_VEVENT ) : + $parser = ComponentParser::factory( $this->subject->newVevent()); + break; + case str_starts_with( $row, $BEGIN_VFREEBUSY ) : + $parser = ComponentParser::factory( $this->subject->newVfreebusy()); + break; + case str_starts_with( $row, $BEGIN_VJOURNAL ) : + $parser = ComponentParser::factory( $this->subject->newVjournal()); + break; + case str_starts_with( $row, $BEGIN_VTODO ) : + $parser = ComponentParser::factory( $this->subject->newVtodo()); + break; + case str_starts_with( $row, $BEGIN_VTIMEZONE ) : + $parser = ComponentParser::factory( $this->subject->newVtimezone()); + break; + default : /* update component with unparsed data */ + $parser->addUnparsedRow( $row ); + break; + } // switch( true ) + } // end foreach( $rows as $lix => $row ) + } + + /** + * Parse calendar data + * + * @return void + * @throws UnexpectedValueException + * @since 2.29.22 - 2020-08-26 + */ + private function parse3thisProperties() : void + { + static $BEGIN = 'BEGIN:'; + static $ERR = 'Unknown ical component (row %d) %s'; + static $PVPROPS = [ self::PRODID, self::VERSION ]; + static $CALPROPS = [ + self::CALSCALE, + self::METHOD, + self::PRODID, + self::VERSION, + ]; + static $RFC7986PROPS = [ + self::COLOR, + self::CATEGORIES, + self::DESCRIPTION, + self::IMAGE, + self::NAME, + self::LAST_MODIFIED, + self::REFRESH_INTERVAL, + self::SOURCE, + self::UID, + self::URL, + ]; + if( ! isset( $this->unparsed ) || + ( 1 > count( $this->unparsed ))) { + return; + } + /* concatenate property values spread over several rows */ + static $TRIMCHARS = "\x00..\x1F"; + $rows = self::concatRows( $this->unparsed ); + foreach( $rows as $lix => $row ) { + if( str_starts_with( $row, $BEGIN )) { // ?? + throw new UnexpectedValueException( + sprintf( $ERR, $lix, PHP_EOL . implode( PHP_EOL, $rows )) + ); + } + /* split property name and opt.params and value */ + [ $propName, $row ] = StringFactory::getPropName( $row ); + switch( true ) { + case ( StringFactory::isXprefixed( $propName ) || + in_array( $propName, $RFC7986PROPS, true )) : + break; + case in_array( $propName, $PVPROPS, true ) : + continue 2; // ignore version/prodid properties + case ( ! in_array( $propName, $CALPROPS, true )) : + continue 2; // skip non standard property names + } // end switch + /* separate attributes from value */ + [ $value, $propAttr ] = self::splitContent( $row ); + /* update Property */ + if( StringFactory::isXprefixed( $propName )) { + $this->subject->setXprop( $propName, StringFactory::strunrep( $value ), $propAttr ); + continue; + } + if( ! in_array( $propName, self::$TEXTPROPS, true )) { + $value = StringFactory::trimTrailNL( $value ); + } + $method = StringFactory::getSetMethodName( $propName ); + switch( $propName ) { + case self::LAST_MODIFIED : // fall through + case self::REFRESH_INTERVAL : // fall through + case self::URL : + $this->subject->{$method}( $value, $propAttr ); + break; + default : + $value = StringFactory::strunrep( rtrim( $value, $TRIMCHARS )); + $this->subject->{$method}( $value, $propAttr ); + } // end switch + } // end foreach + $this->unparsed = []; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Participant.php b/vendor/kigkonsult/icalcreator/src/Participant.php new file mode 100644 index 0000000..55897f9 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Participant.php @@ -0,0 +1,184 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator; + +use Exception; +use Kigkonsult\Icalcreator\Formatter\Participant as Formatter; + +/** + * iCalcreator PARTICIPANT component class + * + * @since 2.41.55 - 2022-08-13 + */ +final class Participant extends Vcomponent +{ + /* The following are REQUIRED but MUST NOT occur more than once. */ + use Traits\PARTICIPANT_TYPErfc9073trait; + use Traits\UIDrfc7986trait; + + /* The following are OPTIONAL but MUST NOT occur more than once. */ + use Traits\CALENDAR_ADDRESSrfc9073trait; + use Traits\CREATEDtrait; + use Traits\DESCRIPTIONtrait; + use Traits\GEOtrait; + use Traits\LAST_MODIFIEDtrait; + use Traits\PRIORITYtrait; + use Traits\SEQUENCEtrait; + use Traits\STATUStrait; + use Traits\SUMMARYtrait; + use Traits\URLtrait; + + /* The following are OPTIONAL and MAY occur more than once. */ + use Traits\ATTACHtrait; + use Traits\CATEGORIEStrait; + use Traits\COMMENTtrait; + use Traits\CONTACTtrait; + use Traits\LOCATIONtrait; + use Traits\REQUEST_STATUStrait; + use Traits\RELATED_TOtrait; + use Traits\RESOURCEStrait; + // strucloc ?? + // strucres ?? + use Traits\STYLED_DESCRIPTIONrfc9073trait; + use Traits\STRUCTURED_DATArfc9073trait; + + /** + * @var string + */ + protected static string $compSgn = 'p'; + + /** + * Constructor + * + * @param null|string[] $config + * @throws Exception + * @since 2.41.53 - 2022-08-11 + */ + public function __construct( ? array $config = [] ) + { + parent::__construct( $config ); + $this->setDtstamp(); + $this->setUid(); + } + + /** + * Return Participant object instance + * + * @param null|string[] $config + * @param null|string $participanttype property PARTICIPANT-TYPE value + * @param null|string $calendaraddress property CALENDAR-ADDRESS value + * @param null|string $url property URL value + * @return Participant + * @throws Exception + * @since 2.41.53 - 2022-08-08 + */ + public static function factory( + ? array $config = [], + ? string $participanttype = null, + ? string $calendaraddress = null, + ? string $url = null + ) : Participant + { + $instance = new Participant( $config ); + if( null !== $participanttype ) { + $instance->setParticipanttype( $participanttype ); + } + if( null !== $calendaraddress ) { + $instance->setCalendaraddress( $calendaraddress ); + } + if( null !== $url ) { + $instance->seturl( $url ); + } + return $instance; + } + + /** + * Destructor + * + * @since 2.41.4 2022-01-18 + */ + public function __destruct() + { + unset( + $this->compType, + $this->xprop, + $this->components, + $this->config, + $this->propIx, + $this->compix, + $this->propDelIx + ); + unset( + $this->cno, + $this->srtk + ); + unset( + $this->participanttype, + $this->uid, + + $this->calendaraddress, + $this->created, + $this->description, + $this->dtstamp, + $this->geo, + $this->lastmodified, + $this->priority, + $this->sequence, + $this->status, + $this->summary, + $this->url, + + $this->attach, + $this->categories, + $this->comment, + $this->contact, + $this->location, + $this->rstatus, + $this->relatedto, + $this->resources, + // strucloc ?? + // strucres ?? + $this->styleddescription, + $this->structureddata + ); + } + + /** + * Return formatted output for calendar component PARTICIPANT object instance + * + * @return string + * @throws Exception + * @since 2.41.55 - 2022-08-13 + */ + public function createComponent() : string + { + return Formatter::format( $this ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Pc.php b/vendor/kigkonsult/icalcreator/src/Pc.php new file mode 100644 index 0000000..cbb4e28 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Pc.php @@ -0,0 +1,560 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator; + +use ArrayObject; + +use DateTimeInterface; +use Kigkonsult\Icalcreator\Util\StringFactory; + +use function array_keys; +use function in_array; +use function is_array; +use function is_bool; +use function is_int; +use function is_scalar; +use function is_string; +use function str_contains; +use function str_replace; +use function str_starts_with; +use function strtoupper; +use function substr_count; +use function trim; +use function var_export; + +/** + * Property Contents + * + * @since 2.41.89 2024-01-20 + */ +class Pc extends ArrayObject +{ + /** + * @var string Component property value, (array) key + */ + public static string $LCvalue = 'value'; + + /** + * @var string Component property parameters, (array) key + */ + public static string $LCparams = 'params'; + + /** + * @var mixed[] + */ + private static array $propTmpl = [ 'value' => null, 'params' => [] ]; + + /** + * @var string + */ + private static string $iteratorTmpl = 'ArrayIterator'; + + /** + * The property value + * + * @var mixed + */ + public mixed $value; + + /** + * The property parameters + * + * @var null|int|mixed[] + */ + public null|int|array $params; + + /** + * Class constructor + * + * @overrides + * @param null|mixed[] $array ignored + * @param null|int $flags ignored + * @param null|string $iteratorClass ArrayIterator + */ + public function __construct( + ? array $array = [], + ? int $flags = 0, + ? string $iteratorClass = 'ArrayIterator' + ) + { + parent::__construct( + self::$propTmpl, + ArrayObject::ARRAY_AS_PROPS, + self::$iteratorTmpl + ); + } + + /** + * Class factory method + * + * @param mixed|null $value ant property value or a Pc + * @param null|string[] $params + * @return Pc + */ + public static function factory( mixed $value = null, ? array $params = [] ) : Pc + { + if( $value instanceof Pc ) { + return clone $value; + } + $instance = new self(); + if( null !== $value ) { + $instance->setValue( $value ); + } + if( ! empty( $params )) { + $instance->setParams( $params ); + } + return $instance; + } + + /** + * Inherited but 'closed' methods + */ + public function exchangeArray( mixed $array ) : array { return $this->getArrayCopy(); } + public function setFlags( mixed $flags ) : void {} + public function setIteratorClass( mixed $iteratorClass ) : void {} + + /** + * Value methods + */ + + /** + * @return mixed[] + */ + public function getAsArray() : array + { + return $this->getArrayCopy(); + } + + /** + * Return bool true if property value is set, i.e not null + * + * @return bool + */ + public function isset() : bool + { + return ( null !== $this->value ); + } + + /** + * Return value, false if not set + * + * @return mixed + */ + public function getValue() : mixed + { + return $this->value ?? false; + } + + /** + * Set to 'empty' state + * + * @return Pc + */ + public function setEmpty() : Pc + { + static $SP0 = ''; + $this->value = $SP0; + $this->params = []; + return $this; + } + + /** + * Set value + * + * @param mixed|null $value + * @return Pc + */ + public function setValue( mixed $value = null ) : Pc + { + $this->value = $value; + return $this; + } + + /** + * Parameters methods + */ + + /** + * Return all parameters (array) or single parameter key value, null if not exists + * + * @param null|string $pKey parameter key + * @param bool $asXparamKey only if not empty pKey, opt do X-prefix pkey + * @return null|int|string|string[] + * @since 2.41.88 - 2024-01-18 + */ + public function getParams( ? string $pKey = null, ? bool $asXparamKey = false ) : null|int|string|array + { + if( null === $pKey ) { + return $this->params; + } + $pKey = $asXparamKey ? self::setXPrefix( $pKey ) : strtoupper( $pKey ); + return $this->hasParamKey( $pKey ) ? $this->params[$pKey] : null; + } + + /** + * Return value of the parameter key VALUE or null + * + * @return string|null + */ + public function getValueParam() : null|string + { + return $this->params[IcalInterface::VALUE] ?? null; + } + + /** + * Return bool true if params has key, opt with spec. value + * + * @param string $pKey + * @param null|string $pValue + * @return bool + */ + public function hasParamKey( string $pKey, ? string $pValue = null ) : bool + { + $key = strtoupper( $pKey); + return ( null === $pValue ) + ? isset( $this->params[$key] ) + : ( isset( $this->params[$key] ) && ( $pValue === $this->params[$key] )); + } + + /** + * Return bool true if params has ISLOCALTIME key + * + * @return bool + */ + public function hasParamIsLocalTime() : bool + { + return $this->hasParamKey( IcalInterface::ISLOCALTIME ); + } + + /** + * Return bool true if params has VALUE key, opt with spec. value + * + * @param null|string $pValue + * @return bool + */ + public function hasParamValue( ? string $pValue = null ) : bool + { + return $this->hasParamKey( IcalInterface::VALUE, $pValue ); + } + + /** + * Return bool true if params has X-key, opt with spec. value + * + * @param string $pKey + * @param null|string $pValue + * @return bool + */ + public function hasXparamKey( string $pKey, ? string $pValue = null ) : bool + { + return $this->hasParamKey( self::setXPrefix( $pKey), $pValue ); + } + + /** + * Return array, parameter keys + * + * @return string[] + */ + public function getParamKeys() : array + { + return array_keys( $this->params ); + } + + /** + * Remove parameter key, opt only with spec. value + * + * @param null|string $pKey + * @param null|string $pValue + * @return Pc + */ + public function removeParam( ? string $pKey = null, ? string $pValue = null ) : Pc + { + if(( null === $pKey ) && ( null === $pValue )) { + $this->params = []; + } + elseif(( null === $pValue ) || ( $this->hasParamKey( $pKey, $pValue ))) { + unset( $this->params[strtoupper( $pKey )] ); + } + return $this; + } + + /** + * Remove parameter X-key + * + * @param string $pKey + * @return Pc + */ + public function removeXparam( string $pKey ) : Pc + { + return $this->removeParam( self::setXPrefix( $pKey )); + } + + /** + * Set parameter key/value, default overwrite (key always set to uppercase) + * + * @param string $pKey + * @param mixed $pValue + * @param null|bool $overwrite + * @return Pc + * @since 2.41.89 2024-01-20 + */ + public function addParam( string $pKey, mixed $pValue, ? bool $overwrite = true ) : Pc + { + self::conformParamKeyValue( $pKey, $pValue ); + if( $overwrite || ! $this->hasParamKey( $pKey )) { + $this->params[$pKey] = $pValue; + } + return $this; + } + + /** + * Set value for parameter key VALUE, default overwrite (key always set to uppercase) + * + * @param mixed $pValue + * @param null|bool $overwrite + * @return Pc + */ + public function addParamValue( mixed $pValue, ? bool $overwrite = true ) : Pc + { + return $this->addParam( IcalInterface::VALUE, $pValue, $overwrite ); + } + + /** + * Set parameter X-key/value, overwrite if exists (key always set to uppercase, x-prefixed if missing) + * + * @param string $pKey + * @param mixed $pValue + * @param null|bool $overwrite + * @return Pc + */ + public function addXparam( string $pKey, mixed $pValue, ? bool $overwrite = true ) : Pc + { + return $this->addParam( self::setXPrefix( $pKey ), $pValue, $overwrite ); + } + + /** + * Set parameter X-key/value array, default overwrite (key always set to uppercase ) + * + * Conform parameters first + * + * @param string[] $params + * @param null|bool $overwrite + * @return Pc + * @since 2.41.85 2024-01-19 + */ + public function setParams( array $params, ? bool $overwrite = true ) : Pc + { + foreach( $params as $kPkey => $pValue ) { + $this->addParam( $kPkey, $pValue, $overwrite ); + } + return $this; + } + + /** + * @return string + * @since 2.41.85 2024-01-16 + */ + public function __toString() : string + { + static $FORMAT = 'Ymd-His e'; + static $SP0 = ''; + static $GTEQ = '=>'; + static $CMSP1 = ', '; + $str = match ( true ) { + null === $this->value => $SP0, + is_scalar( $this->value ) => (string) $this->value, + $this->value instanceof DateTimeInterface => $this->value->format( $FORMAT ), + default => str_replace( PHP_EOL, $SP0, var_export( $this->value, true )), + }; // end match + if( is_array( $this->params )) { + foreach( $this->params as $k => $v ) { + $str .= $CMSP1 . $k . $GTEQ . $v; + } + } + return rtrim( $str ); + } + + /** + * Parameters static key methods + */ + + /** + * @var string + */ + protected static string $xPrefix = 'X-'; + + /** + * Return bool true if (key-)value is X-prefixed + * + * @param string $key + * @return bool + */ + public static function isXprefixed( string $key ) : bool + { + return str_starts_with( strtoupper( $key ), self::$xPrefix ); + } + + /** + * Return X-prefixed key in upper case + * + * @param string $key + * @return string + */ + public static function setXPrefix( string $key ) : string + { + return strtoupper( self::isXprefixed( $key ) ? $key : self::$xPrefix . $key ); + } + + /** + * Return string with opt. leading x-prefix removed + * + * @param string $key + * @return string + */ + public static function unsetXPrefix( string $key ) : string + { + return self::isXprefixed( $key ) ? substr( $key, 2 ) : $key; + } + + /** + * Parameters static value methods + */ + + private static string $CIRCUMFLEX = '^'; + private static string $CFN = '^n'; + private static string $CFCF = '^^'; + private static string $CFSQ = "^'"; + private static string $CFQQ = '^"'; + private static string $NLCHARS = '\n'; + + /** + * Return parsed parameter VALUE with opt. circumflex deformatted as of rfc6868 + * + * the character sequence ^n (U+005E, U+006E) is decoded into an + * appropriate formatted line break according to the type of system + * being used + * the character sequence ^^ (U+005E, U+005E) is decoded into the ^ character (U+005E) + * the character sequence ^' (U+005E, U+0027) is decoded into the " character (U+0022) + * if a ^ (U+005E) character is followed by any character other than the ones above, + * parsers MUST leave both the ^ and the following character in place + * + * Also ^" and ' are decoded into the " character (U+0022), NOT rfc6868 + * + * @param mixed $value + * @return mixed + * @since 2.41.89 2024-01-20 + */ + public static function circumflexQuoteParse( mixed $value ) : mixed + { + static $SQUOTE = "'"; + if( ! is_string( $value )) { + return $value; + } + if( str_contains( $value, self::$CFN )) { + $value = str_replace( self::$CFN, self::$NLCHARS, $value ); + } + if( str_contains( $value, self::$CFCF )) { + $value = str_replace( self::$CFCF, self::$CIRCUMFLEX, $value ); + } + if( str_contains( $value, self::$CFSQ )) { + $value = str_replace( self::$CFSQ, StringFactory::$QQ, $value ); + } + if( str_contains( $value, self::$CFQQ )) { + $value = str_replace( self::$CFQQ, StringFactory::$QQ, $value ); + } + if( str_contains( $value, $SQUOTE ) && ( 0 === ( substr_count( $value, $SQUOTE ) % 2 ))) { + $value = str_replace( $SQUOTE, StringFactory::$QQ, $value ); + } + return $value; + } + /** + * Return (conformed) iCal component property parameters + * + * Trim quoted values, default parameters may be set, if missing + * Non-string values set to string + * + * @param string $pKey + * @param mixed $pValue + * @return void + * @since 2.41.89 2024-01-20 + */ + public static function conformParamKeyValue( string & $pKey, mixed & $pValue ) : void + { + static $TRUEFALSEARR = [ IcalInterface::TRUE, IcalInterface::FALSE ]; + $pKey = strtoupper( $pKey ); + $pValue = self::circumflexQuoteParse( $pValue ); + switch( $pKey ) { + case IcalInterface::ISLOCALTIME : + break; + case IcalInterface::DERIVED : + if( is_bool( $pValue )) { + $pValue = $pValue ? IcalInterface::TRUE : IcalInterface::FALSE; + } + elseif( in_array( strtoupper( $pValue ), $TRUEFALSEARR, true )) { + $pValue = strtoupper( $pValue ); + } + break; + case IcalInterface::ORDER : + if( ! is_int( $pValue )) { + $pValue = (int) $pValue; + } + if( 1 > $pValue ) { + $pValue = 1; + } + break; + case IcalInterface::VALUE : + $pValue = strtoupper( $pValue ); + break; + default : + if( is_array( $pValue )) { + foreach( $pValue as $pkey2 => $pValue2 ) { + $pValue[$pkey2] = self::conformValue( $pValue2 ); + } + break; + } + $pValue = self::conformValue( $pValue ); + break; + } // end switch + } + + /** + * @param mixed $value + * @return string + * @since 2.41.89 2024-01-20 + */ + private static function conformValue ( mixed $value ) : string + { + static $ONE = '1'; + return match ( true ) { + is_string( $value ) => trim( $value, StringFactory::$QQ ), + is_bool( $value ) => $value ? $ONE : StringFactory::$ZERO, + default => (string) $value, + }; // end match + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/ACKNOWLEDGEDrfc9074trait.php b/vendor/kigkonsult/icalcreator/src/Traits/ACKNOWLEDGEDrfc9074trait.php new file mode 100644 index 0000000..62c3b78 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/ACKNOWLEDGEDrfc9074trait.php @@ -0,0 +1,127 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use DateTime; +use DateTimeInterface; +use Exception; +use InvalidArgumentException; +use Kigkonsult\Icalcreator\Formatter\Property\DtxProperty; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\DateTimeFactory; + +/** + * ACKNOWLEDGED property functions + * + * @since 2.41.85 2024-01-18 + */ +trait ACKNOWLEDGEDrfc9074trait +{ + /** + * @var null|Pc component property ACKNOWLEDGED value + */ + protected ? Pc $acknowledged = null; + + /** + * Return formatted output for calendar component property acknowledged + * + * @return string + * @throws Exception + * @throws InvalidArgumentException + */ + public function createAcknowledged() : string + { + return DtxProperty::format( + self::ACKNOWLEDGED, + $this->acknowledged, + $this->getConfig( self::ALLOWEMPTY ) + ); + } + + /** + * Delete calendar component property acknowledged + * + * @return bool + */ + public function deleteAcknowledged() : bool + { + $this->acknowledged = null; + return true; + } + + /** + * Return calendar component property acknowledged + * + * @param null|bool $inclParam + * @return bool|string|DateTime|Pc + */ + public function getAcknowledged( ? bool $inclParam = false ) : DateTime | bool | string | Pc + { + if( empty( $this->acknowledged )) { + return false; + } + return $inclParam ? clone $this->acknowledged : $this->acknowledged->getValue(); + } + + /** + * Return bool true if set (and ignore empty property) + * + * @return bool + * @since 2.41.88 2024-01-17 + */ + public function isAcknowledgedSet() : bool + { + return self::isPropSet( $this->acknowledged ); + } + + /** + * Set calendar component property acknowledged, if empty: 'now' + * + * @param null|string|Pc|DateTimeInterface $value + * @param null|mixed[] $params + * @return static + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.85 2024-01-18 + */ + public function setAcknowledged( + null | string | Pc | DateTimeInterface $value = null, + ? array $params = [] + ) : static + { + $pc = Pc::factory( $value, $params ); + $pc->addParamValue( self::DATE_TIME ); // req + $this->acknowledged = $pc->isset() + ? DateTimeFactory::setDate( $pc, true ) + : $pc->setValue( DateTimeFactory::factory( null, self::UTC )) + ->removeParam( self::VALUE ); + return $this; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/BUSYTYPErfc7953trait.php b/vendor/kigkonsult/icalcreator/src/Traits/BUSYTYPErfc7953trait.php new file mode 100644 index 0000000..2ffd53d --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/BUSYTYPErfc7953trait.php @@ -0,0 +1,125 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use Kigkonsult\Icalcreator\Formatter\Property\Property; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\StringFactory; +use InvalidArgumentException; + +use function strtoupper; + +/** + * rfc7953 BUSYTYPE property functions + * + * @since 2.41.85 2024-01-18 + */ +trait BUSYTYPErfc7953trait +{ + /** + * @var null|Pc component property busytype value + */ + protected ? Pc $busytype = null; + + /** + * Return formatted output for calendar component property busytype + * + * @return string + */ + public function createBusytype() : string + { + return Property::format( + self::BUSYTYPE, + $this->busytype, + $this->getConfig( self::ALLOWEMPTY ) + ); + } + + /** + * Delete calendar component property busytype + * + * @return bool + */ + public function deleteBusytype() : bool + { + $this->busytype = null; + return true; + } + + /** + * Get calendar component property busytype + * + * @param null|bool $inclParam + * @return bool|string|Pc + * @since 2.41.85 2024-01-18 + */ + public function getBusytype( ? bool $inclParam = false ) : bool | string | Pc + { + if( empty( $this->busytype )) { + return false; + } + return $inclParam ? clone $this->busytype : $this->busytype->getValue(); + } + + /** + * Return bool true if set (and ignore empty property) + * + * @return bool + * @since 2.41.88 2024-01-19 + */ + public function isBusytypeSet() : bool + { + return self::isPropSet( $this->busytype ); + } + + /** + * Set calendar component property busytype + * + * @param null|string|Pc $value + * @param null|mixed[] $params + * @return static + * @throws InvalidArgumentException + * @since 2.41.85 2024-01-18 + */ + public function setBusytype( null|string|Pc $value = null, ? array $params = [] ) : static + { + $pc = Pc::factory( $value, $params ); + $pcValue = $pc->getValue(); + if( empty( $pcValue )) { + $this->assertEmptyValue( $pcValue, self::BUSYTYPE ); + $pc->setEmpty(); + } + else { + $pc->setValue( strtoupper( StringFactory::trimTrailNL( $pcValue ))); + } + $this->busytype = $pc; + return $this; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/CALENDAR_ADDRESSrfc9073trait.php b/vendor/kigkonsult/icalcreator/src/Traits/CALENDAR_ADDRESSrfc9073trait.php new file mode 100644 index 0000000..81c6ba2 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/CALENDAR_ADDRESSrfc9073trait.php @@ -0,0 +1,127 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use Kigkonsult\Icalcreator\Formatter\Property\Property; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\Util; +use Kigkonsult\Icalcreator\Util\CalAddressFactory; +use InvalidArgumentException; + +/** + * CALENDAR-ADDRESS property functions + * + * @since 2.41.85 2024-01-18 + */ +trait CALENDAR_ADDRESSrfc9073trait +{ + /** + * @var null|Pc component property CALENDAR-ADDRESS value + */ + protected ? Pc $calendaraddress = null; + + /** + * Return formatted output for calendar component property calendaraddress + * + * @return string + */ + public function createCalendaraddress() : string + { + return Property::format( + self::CALENDAR_ADDRESS, + $this->calendaraddress, + $this->getConfig( self::ALLOWEMPTY ) + ); + } + + /** + * Delete calendar component property calendaraddress + * + * @return bool + */ + public function deleteCalendaraddress() : bool + { + $this->calendaraddress = null; + return true; + } + + /** + * Get calendar component property calendaraddress + * + * @param null|bool $inclParam + * @return bool|string|Pc + * @since 2.41.85 2024-01-18 + */ + public function getCalendaraddress( ? bool $inclParam = false ) : bool | string | Pc + { + if( empty( $this->calendaraddress )) { + return false; + } + return $inclParam ? clone $this->calendaraddress : $this->calendaraddress->getValue(); + } + + /** + * Return bool true if set (and ignore empty property) + * + * @return bool + * @since 2.41.88 2024-01-19 + */ + public function isCalendaraddressSet() : bool + { + return self::isPropSet( $this->calendaraddress ); + } + + /** + * Set calendar component property calendaraddress + * + * @param null|string|Pc $value + * @param null|mixed[] $params + * @return static + * @throws InvalidArgumentException + * @since 2.41.85 2024-01-18 + */ + public function setCalendaraddress( null|string|Pc $value = null, ? array $params = [] ) : static + { + $pc = Pc::factory( $value, $params ); + $pcValue = $pc->getValue(); + if( empty( $pcValue )) { + $this->assertEmptyValue( $pcValue, self::CALENDAR_ADDRESS ); + $pc->setEmpty(); + } + else { + $pcValue = Util::assertString( $pcValue, self::CALENDAR_ADDRESS ); + $pcValue = CalAddressFactory::conformCalAddress( $pcValue, true ); + CalAddressFactory::assertCalAddress( $pcValue ); + $pc->setValue( $pcValue ); + } + $this->calendaraddress = $pc; + return $this; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/LOCATIONTYPErfc9073trait.php b/vendor/kigkonsult/icalcreator/src/Traits/LOCATIONTYPErfc9073trait.php new file mode 100644 index 0000000..b5b9c36 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/LOCATIONTYPErfc9073trait.php @@ -0,0 +1,126 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use Kigkonsult\Icalcreator\Formatter\Property\Property; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\StringFactory; +use InvalidArgumentException; + +/** + * LOCATION-TYPE property functions + * + * @since 2.41.85 2024-01-18 + */ +trait LOCATIONTYPErfc9073trait +{ + /** + * @var null|Pc component property LOCATION-TYPE value + */ + protected ? Pc $locationtype = null; + + /** + * Return formatted output for calendar component property LOCATION-TYPE + * + * @return string + */ + public function createLocationtype() : string + { + return Property::format( + self::LOCATION_TYPE, + $this->locationtype, + $this->getConfig( self::ALLOWEMPTY ) + ); + } + + /** + * Delete calendar component property transp + * + * @return bool + */ + public function deleteLocationtype() : bool + { + $this->locationtype = null; + return true; + } + + /** + * Get calendar component property LOCATION-TYPE + * + * @param null|bool $inclParam + * @return bool|string|Pc + * @since 2.41.85 2024-01-18 + */ + public function getLocationtype( ? bool $inclParam = false ) : bool | string | Pc + { + if( empty( $this->locationtype )) { + return false; + } + return $inclParam ? clone $this->locationtype : $this->locationtype->getValue(); + } + + /** + * Return bool true if set (and ignore empty property) + * + * @return bool + * @since 2.41.88 2024-01-19 + */ + public function isLocationtypeSet() : bool + { + return self::isPropSet( $this->locationtype ); + } + + /** + * Set calendar component property LOCATION-TYPE + * + * Values for this parameter are taken from the values defined in Section 3 of [RFC4589]. + * New location types SHOULD be registered in the manner laid down in Section 5 of [RFC4589]. + * + * @param null|string|Pc $value + * @param null|mixed[] $params + * @return static + * @throws InvalidArgumentException + * @since 2.41.85 2024-01-18 + */ + public function setLocationtype( null|string|Pc $value = null, ? array $params = [] ) : static + { + $pc = Pc::factory( $value, $params ); + $pcValue = $pc->getValue(); + if( empty( $pcValue )) { + $this->assertEmptyValue( $pcValue, self::LOCATION_TYPE ); + $pc->setEmpty(); + } + else { + $pc->setValue( StringFactory::trimTrailNL( $pcValue )); + } + $this->locationtype = $pc; + return $this; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/MvalTrait.php b/vendor/kigkonsult/icalcreator/src/Traits/MvalTrait.php new file mode 100644 index 0000000..3fa7a70 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/MvalTrait.php @@ -0,0 +1,259 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use Kigkonsult\Icalcreator\IcalBase; +use Kigkonsult\Icalcreator\Pc; + +use function array_slice; +use function is_int; +use function key; +use function ksort; + +/** + * Vcalendar/CalendarComponent multi-properties help methods + * @since 2.41.85 2024-01-18 + */ +trait MvalTrait +{ + /** + * Recount property propIx, used at consecutive getProperty calls + * + * @param string[] $propArr component (multi-)property + * @param int $propIx getter counter + * @return bool + * @since 2.41.39 - 2022-04-09 + */ + protected static function recountMvalPropix( array $propArr, int & $propIx ) : bool + { + if( empty( $propArr )) { + return false; + } + $last = key( array_slice( $propArr, -1, 1, true )); + while( ! isset( $propArr[$propIx] ) && ( $last > $propIx )) { + $propIx++; + } + return true; + } + + /** + * Delete calendar component multiProp property[ix] + * + * @param array $multiProp component (multi-)property + * @param string $propName + * @param IcalBase $instance + * @param null|int $propDelIx specific property in case of multiply occurrence + * @return bool true on success + * @since 2.27.1 - 2018-12-15 + */ + protected static function deletePropertyM( + array & $multiProp, + string $propName, + IcalBase $instance, + ? int $propDelIx = null + ) : bool + { + if( empty( $multiProp )) { + unset( $instance->propDelIx[$propName] ); + return false; + } + $propDelIx = self::getIndex( $instance->propDelIx, $propName, $propDelIx ); + if( isset( $multiProp[$propDelIx] )) { + unset( $multiProp[$propDelIx] ); + } + if( empty( $multiProp )) { + $multiProp = []; + unset( $instance->propDelIx[$propName] ); + return false; + } + return true; + } + + /** + * Return propName index + * + * @param array $indexArr + * @param string $propName + * @param int|null $index + * @return int + * @since 2.27.1 - 2018-12-15 + */ + protected static function getIndex( + array & $indexArr, + string $propName, + ? int $index = null + ) : int + { + if( null === $index ) { + $index = ( isset( $indexArr[$propName] )) ? $indexArr[$propName] + 2 : 1; + } + --$index; + $indexArr[$propName] = $index; + return $index; + } + + /** + * Return array, all calendar component multiProp properties + * + * @param null|array $multiProp component (multi-)property + * @param bool $inclParam + * @return array + * @since 2.41.85 2024-01-18 + */ + protected static function getMvalProperties( + ? array $multiProp = [], + ? bool $inclParam = false + ) : array + { + if( empty( $multiProp )) { + return []; + } + if( $inclParam ) { + return $multiProp; + } + $output = []; + foreach( $multiProp as $property ) { + $output[] = $property->getValue(); + } + return $output; + } + + /** + * Get calendar component multpProp property + * + * @param array $multiProp component (multi-)property + * @param string $propName + * @param IcalBase $instance + * @param null|int $propIx specific property in case of multiply occurrence + * @param bool $inclParam + * @return bool|string|array|Pc + * @since 2.41.85 2024-01-18 + */ + protected static function getMvalProperty( + array $multiProp, + string $propName, + IcalBase $instance, + ? int $propIx = null, + ? bool $inclParam = false + ) : bool | string | array | Pc + { + if( empty( $multiProp )) { + unset( $instance->propIx[$propName] ); + return false; + } + $propIx = self::getIndex( $instance->propIx, $propName, $propIx ); + if( ! self::recountMvalPropix( $multiProp, $propIx )) { + unset( $instance->propIx[$propName] ); + return false; + } + $instance->propIx[$propName] = $propIx; + if( ! isset( $multiProp[$propIx] )) { + unset( $instance->propIx[$propName] ); + return false; + } + return ( $inclParam ) + ? clone $multiProp[$propIx] + : $multiProp[$propIx]->getValue(); + } + + /** + * Return bool true if any multi property value is not empty + * + * @param null|Pc[] $valueArr + * @return bool + * @since 2.41.88 2024-01-19 + */ + protected static function isMvalSet( ? array $valueArr = [] ) : bool + { + if( empty( $valueArr )) { + return false; + } + foreach( $valueArr as $value ) { + if( self::isPropSet( $value )) { + return true; + } + } + return false; + } + + /** + * Marshall input for multi-value properties + * + * @param mixed $value + * @param null|int|array $params + * @param null|int $index + * @return Pc + * @since 2.41.36 2022-04-09 + */ + protected static function marshallInputMval( mixed $value, null|int|array $params, ? int & $index) : Pc + { + if( $value instanceof Pc ) { + $pc = clone $value; + if( is_int( $params )) { + $index = $params; + } + } + else { + $pc = Pc::factory( $value, $params ); + } + return $pc; + } + + /** + * Check index and set (an indexed) content in a multiple value array + * + * @param null|array $valueArr + * @param Pc $value + * @param null|int $index + * @return void + * @since 2.41.36 2022-04-09 + */ + protected static function setMval( + ? array & $valueArr, + Pc $value, + ? int $index = null + ) : void + { + if( empty( $valueArr )) { + $valueArr = []; + } + if( null === $index ) { // i.e. next + $valueArr[] = $value; + return; + } + --$index; + if( isset( $valueArr[$index] )) { // replace + $valueArr[$index] = $value; + return; + } + $valueArr[$index] = $value; + ksort( $valueArr ); // order + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/NewVlocationTrait.php b/vendor/kigkonsult/icalcreator/src/Traits/NewVlocationTrait.php new file mode 100644 index 0000000..db4ba34 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/NewVlocationTrait.php @@ -0,0 +1,52 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use Exception; +use Kigkonsult\Icalcreator\Vlocation; + +trait NewVlocationTrait +{ + /** + * Return Vlocation object instance + * + * @param null|string $locationType property LOCATION-TYPE value + * @param null|string $name property NAME value + * @return Vlocation + * @throws Exception + * @since 2.41.53 - 2022-08-08 + */ + public function newVlocation( ? string $locationType = null, ? string $name = null ) : Vlocation + { + $ix = $this->getNextComponentIndex(); + $this->components[$ix] = Vlocation::factory( $this->getConfig(), $locationType, $name ); + return $this->components[$ix]; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/PARTICIPANT_TYPErfc9073trait.php b/vendor/kigkonsult/icalcreator/src/Traits/PARTICIPANT_TYPErfc9073trait.php new file mode 100644 index 0000000..07ee499 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/PARTICIPANT_TYPErfc9073trait.php @@ -0,0 +1,121 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use Kigkonsult\Icalcreator\Formatter\Property\Property; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\Util; + +/** + * PARTICIPANT_TYPE property functions + * + * @since 2.41.85 2024-01-18 + */ +trait PARTICIPANT_TYPErfc9073trait +{ + /** + * @var null|Pc component property PARTICIPANT_TYPE value + */ + protected ? Pc $participanttype = null; + + /** + * Return formatted output for calendar component property participanttype + * + * @return string + */ + public function createParticipanttype() : string + { + return Property::format( + self::PARTICIPANT_TYPE, + $this->participanttype, + $this->getConfig( self::ALLOWEMPTY ) + ); + } + + /** + * Delete calendar component property participanttype + * + * @return bool + */ + public function deleteParticipanttype() : bool + { + $this->participanttype = null; + return true; + } + + /** + * Get calendar component property participanttype + * + * @param null|bool $inclParam + * @return bool|string|Pc + * @since 2.41.85 2024-01-18 + */ + public function getParticipanttype( ? bool $inclParam = false ) : bool | string | Pc + { + if( empty( $this->participanttype )) { + return false; + } + return $inclParam ? clone $this->participanttype : $this->participanttype->getValue(); + } + + /** + * Return bool true if set (and ignore empty property) + * + * @return bool + * @since 2.41.88 2024-01-19 + */ + public function isParticipanttypeSet() : bool + { + return self::isPropSet( $this->participanttype ); + } + + /** + * Set calendar component property participanttype + * + * @param null|string|Pc $value + * @param null|mixed[] $params + * @return static + * @since 2.41.85 2024-01-18 + */ + public function setParticipanttype( null|string|Pc $value = null, ? array $params = [] ) : static + { + $pc = Pc::factory( $value, $params ); + $pcValue = $pc->getValue(); + if( empty( $pcValue )) { + $this->assertEmptyValue( $pcValue, self::PARTICIPANT_TYPE ); + $pc->setEmpty(); + } + else { + Util::assertString( $pcValue, self::PARTICIPANT_TYPE ); + } + $this->participanttype = $pc; + return $this; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/PROXIMITYrfc9074trait.php b/vendor/kigkonsult/icalcreator/src/Traits/PROXIMITYrfc9074trait.php new file mode 100644 index 0000000..452b073 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/PROXIMITYrfc9074trait.php @@ -0,0 +1,125 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use Kigkonsult\Icalcreator\Formatter\Property\Property; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\StringFactory; +use InvalidArgumentException; + +/** + * PROXIMITY property functions + * + * @since 2.41.85 2024-01-18 + */ +trait PROXIMITYrfc9074trait +{ + /** + * @var null|Pc Valarm component property PROXIMITY value + */ + protected ? Pc $proximity = null; + + /** + * Return formatted output for calendar Valarm component property proximity + * + * @return string + */ + public function createProximity() : string + { + return Property::format( + self::PROXIMITY, + $this->proximity, + $this->getConfig( self::ALLOWEMPTY ) + ); + } + + /** + * Delete calendar Valarm component property proximity + * + * @return bool + * @since 2.27.1 - 2018-12-15 + */ + public function deleteProximity() : bool + { + $this->proximity = null; + return true; + } + + /** + * Get calendar Valarm component property proximity + * + * @param null|bool $inclParam + * @return bool|string|Pc + * @since 2.41.85 2024-01-18 + */ + public function getProximity( ? bool $inclParam = false ) : bool | string | Pc + { + if( empty( $this->proximity )) { + return false; + } + return $inclParam ? clone $this->proximity : $this->proximity->getValue(); + } + + /** + * Return bool true if set (and ignore empty property) + * + * @return bool + * @since 2.41.88 2024-01-19 + */ + public function isProximitySet() : bool + { + return self::isPropSet( $this->proximity ); + } + + /** + * Set calendar component property proximity + * + * @since 2.23.12 - 2017-04-22 + * @param null|string|Pc $value + * @param null|mixed[] $params + * @return static + * @throws InvalidArgumentException + * @since 2.41.85 2024-01-18 + */ + public function setProximity( null|string|Pc $value = null, ? array $params = [] ) : static + { + $pc = Pc::factory( $value, $params ); + $pcValue = $pc->getValue(); + if( empty( $pcValue )) { + $this->assertEmptyValue( $pcValue, self::PROXIMITY ); + $pc->setEmpty(); + } + else { + $pc->setValue( StringFactory::trimTrailNL( $pcValue )); + } + $this->proximity = $pc; + return $this; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/Participants2AttendeesTrait.php b/vendor/kigkonsult/icalcreator/src/Traits/Participants2AttendeesTrait.php new file mode 100644 index 0000000..e8d457c --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/Participants2AttendeesTrait.php @@ -0,0 +1,64 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use Kigkonsult\Icalcreator\Vcalendar; + +use function in_array; + +trait Participants2AttendeesTrait +{ + /** + * Set subComponent Participants (calendaraddress) as Attendees, skip if set + * + * Participant UID set as X-param x-participantid + * Used in V3component (Vevent, Vtodo ), VFreebusy, Vjournal + * + * @return static + * @since 2.41.34 - 2022-03-28 + */ + public function participants2Attendees() : static + { + if( ! in_array( $this->getCompType(), Vcalendar::$VCOMBS, true )) { + return $this; + } + [ $participants, $lcArr ] = $this->getSubCompsDetailType( + self::PARTICIPANT, + self::CALENDAR_ADDRESS, + self::X_PARTICIPANTID, + self::PARTICIPANT_TYPE, + [ self::X_PARTICIPANT_TYPE, self::ROLE ] + ); + if( ! empty( $participants )) { + $this->comPropUpdFromSub( self::ATTENDEE, true, $participants, $lcArr ); + } + return $this; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/RESOURCE_TYPErfc9073trait.php b/vendor/kigkonsult/icalcreator/src/Traits/RESOURCE_TYPErfc9073trait.php new file mode 100644 index 0000000..ce9c070 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/RESOURCE_TYPErfc9073trait.php @@ -0,0 +1,121 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use Kigkonsult\Icalcreator\Formatter\Property\Property; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\Util; + +/** + * RESOURCE_TYPE property functions + * + * @since 2.41.85 2024-01-18 + */ +trait RESOURCE_TYPErfc9073trait +{ + /** + * @var null|Pc component property resourcetype value + */ + protected ? Pc $resourcetype = null; + + /** + * Return formatted output for calendar component property resourcetype + * + * @return string + */ + public function createResourcetype() : string + { + return Property::format( + self::RESOURCE_TYPE, + $this->resourcetype, + $this->getConfig( self::ALLOWEMPTY ) + ); + } + + /** + * Delete calendar component property resourcetype + * + * @return bool + */ + public function deleteResourcetype() : bool + { + $this->resourcetype = null; + return true; + } + + /** + * Get calendar component property resourcetype + * + * @param null|bool $inclParam + * @return bool|string|Pc + * @since 2.41.85 2024-01-18 + */ + public function getResourcetype( ? bool $inclParam = false ) : bool | string | Pc + { + if( empty( $this->resourcetype )) { + return false; + } + return $inclParam ? clone $this->resourcetype : $this->resourcetype->getValue(); + } + + /** + * Return bool true if set (and ignore empty property) + * + * @return bool + * @since 2.41.88 2024-01-19 + */ + public function isResourcetypeSet() : bool + { + return self::isPropSet( $this->resourcetype ); + } + + /** + * Set calendar component property resourcetype + * + * @param null|string|Pc $value + * @param null|mixed[] $params + * @return static + * @since 2.41.85 2024-01-18 + */ + public function setResourcetype( null|string|Pc $value = null, ? array $params = [] ) : static + { + $pc = Pc::factory( $value, $params ); + $pcValue = $pc->getValue(); + if( empty( $pcValue )) { + $this->assertEmptyValue( $pcValue, self::RESOURCE_TYPE ); + $pc->setEmpty(); + } + else { + Util::assertString( $pcValue, self::RESOURCE_TYPE ); + } + $this->resourcetype = $pc; + return $this; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/STRUCTURED_DATArfc9073trait.php b/vendor/kigkonsult/icalcreator/src/Traits/STRUCTURED_DATArfc9073trait.php new file mode 100644 index 0000000..04eaabe --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/STRUCTURED_DATArfc9073trait.php @@ -0,0 +1,166 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use InvalidArgumentException; +use Kigkonsult\Icalcreator\Formatter\Property\MultiProps; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\Util; + +/** + * STRUCTURED-DATA property functions + * + * @since 2.41.85 2024-01-18 + */ +trait STRUCTURED_DATArfc9073trait +{ + /** + * @var null|Pc[] component property structureddata value + */ + protected ? array $structureddata = null; + + /** + * Return formatted output for calendar component property structureddata + * + * @return string + */ + public function createStructureddata() : string + { + return MultiProps::format( + self::STRUCTURED_DATA, + $this->structureddata ?? [], + $this->getConfig( self::ALLOWEMPTY ) + ); + } + + /** + * Delete calendar component property structureddata + * + * @param null|int $propDelIx specific property in case of multiply occurrence + * @return bool + */ + public function deleteStructureddata( ? int $propDelIx = null ) : bool + { + if( empty( $this->structureddata )) { + unset( $this->propDelIx[self::STRUCTURED_DATA] ); + return false; + } + return self::deletePropertyM( + $this->structureddata, + self::STRUCTURED_DATA, + $this, + $propDelIx + ); + } + + /** + * Get calendar component property structureddata + * + * @param null|int $propIx specific property in case of multiply occurrence + * @param bool $inclParam + * @return bool|string|Pc + */ + public function getStructureddata( int $propIx = null, bool $inclParam = false ) : bool | string |Pc + { + if( empty( $this->structureddata )) { + unset( $this->propIx[self::STRUCTURED_DATA] ); + return false; + } + return self::getMvalProperty( + $this->structureddata, + self::STRUCTURED_DATA, + $this, + $propIx, + $inclParam + ); + } + + /** + * Return array, all calendar component property structureddata + * + * @param null|bool $inclParam + * @return Pc[] + * @since 2.41.58 2022-08-24 + */ + public function getAllStructureddata( ? bool $inclParam = false ) : array + { + return self::getMvalProperties( $this->structureddata, $inclParam ); + } + + /** + * Return bool true if set (and ignore empty property) + * + * @return bool + * @since 2.41.35 2022-03-28 + */ + public function isStructureddataSet() : bool + { + return self::isMvalSet( $this->structureddata ); + } + + /** + * Set calendar component property structureddata + * + * Set default param DERIVED to FALSE if missing (default) + * + * fmttypeparam/ schemaparam are OPTIONAL for a URI value, REQUIRED for a TEXT or BINARY value + * and MUST NOT occur more than once + * + * @param null|string|Pc $value + * @param null|int|array $params VALUE TEXT/URI + * @param null|int $index + * @return static + * @throws InvalidArgumentException + * @since 2.41.85 2024-01-18 + */ + public function setStructureddata( + null|string|Pc $value = null, + null|int|array $params = [], + ? int $index = null + ) : static + { + $pc = self::marshallInputMval( $value, $params, $index ); + $pcValue = $pc->getValue(); + if( empty( $pcValue )) { + $this->assertEmptyValue( $pcValue, self::STRUCTURED_DATA ); + $pc->setEmpty(); + } + else { + $pc->setValue( Util::assertString( $pcValue, self::STRUCTURED_DATA )); + $pc->addParamValue( self::TEXT, false ); // must have VALUE + if( $pc->hasParamValue( self::BINARY ) && + ! $pc->hasParamKey( self::ENCODING )) { + $pc->addParam( self::ENCODING, self::BASE64 ); + } + } + self::setMval( $this->structureddata, $pc, $index ); + return $this; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/STYLED_DESCRIPTIONrfc9073trait.php b/vendor/kigkonsult/icalcreator/src/Traits/STYLED_DESCRIPTIONrfc9073trait.php new file mode 100644 index 0000000..9155af8 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/STYLED_DESCRIPTIONrfc9073trait.php @@ -0,0 +1,173 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use InvalidArgumentException; +use Kigkonsult\Icalcreator\Formatter\Property\MultiProps; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\Util; + +/** + * STYLED-DESCRIPTION property functions + * + * @since 2.41.85 2024-01-18 + */ +trait STYLED_DESCRIPTIONrfc9073trait +{ + /** + * @var null|Pc[] component property styleddescription value + */ + protected ? array $styleddescription = null; + + /** + * Return formatted output for calendar component property styleddescription + * + * @return string + */ + public function createStyleddescription() : string + { + return MultiProps::format( + self::STYLED_DESCRIPTION, + $this->styleddescription ?? [], + $this->getConfig( self::ALLOWEMPTY ), + $this->getConfig( self::LANGUAGE ) + ); + } + + /** + * Delete calendar component property styleddescription + * + * @param null|int $propDelIx specific property in case of multiply occurrence + * @return bool + */ + public function deleteStyleddescription( ? int $propDelIx = null ) : bool + { + if( empty( $this->styleddescription )) { + unset( $this->propDelIx[self::STYLED_DESCRIPTION] ); + return false; + } + return self::deletePropertyM( + $this->styleddescription, + self::STYLED_DESCRIPTION, + $this, + $propDelIx + ); + } + + /** + * Get calendar component property styleddescription + * + * @param null|int $propIx specific property in case of multiply occurrence + * @param bool $inclParam + * @return bool|string|Pc + */ + public function getStyleddescription( int $propIx = null, bool $inclParam = false ) : bool | string | Pc + { + if( empty( $this->styleddescription )) { + unset( $this->propIx[self::STYLED_DESCRIPTION] ); + return false; + } + return self::getMvalProperty( + $this->styleddescription, + self::STYLED_DESCRIPTION, + $this, + $propIx, + $inclParam + ); + } + + /** + * Return array, all calendar component property styleddescription + * + * @param null|bool $inclParam + * @return Pc[] + * @since 2.41.58 2022-08-24 + */ + public function getAllStyleddescription( ? bool $inclParam = false ) : array + { + return self::getMvalProperties( $this->styleddescription, $inclParam ); + } + + /** + * Return bool true if set (and ignore empty property) + * + * @return bool + * @since 2.41.35 2022-03-28 + */ + public function isStyleddescriptionSet() : bool + { + return self::isMvalSet( $this->styleddescription ); + } + + /** + * Set calendar component property styleddescription + * + * Set default param DERIVED to FALSE if missing (default) + * + * If it does appear more than once, there MUST be exactly one instance of the property + * with no "DERIVED" parameter or DERIVED=FALSE. All others MUST have DERIVED=TRUE. + * + * Additionally, if there is one or more "STYLED-DESCRIPTION" property, + * then the "DESCRIPTION" property should either be absent or have the parameter DERIVED=TRUE. + * + * @param null|string|Pc $value + * @param null|int|array $params VALUE TEXT/URI + * @param null|int $index + * @return static + * @throws InvalidArgumentException + * @since 2.41.85 2024-01-18 + */ + public function setStyleddescription( + null|string|Pc $value = null, + null|int|array $params = [], + ? int $index = null + ) : static + { + $pc = self::marshallInputMval( $value, $params, $index ); + $pcValue = $pc->getValue(); + if( empty( $pcValue )) { + $this->assertEmptyValue( $pcValue, self::STYLED_DESCRIPTION ); + $pc->setEmpty(); + } + else { + $pc->setValue( Util::assertString( $pcValue, self::STYLED_DESCRIPTION )); + $pc->addParamValue( self::TEXT, false ); // must have one + if( ! $pc->hasParamValue( self::TEXT )) { // text may have but URI not... + $pc->removeParam( self::ALTREP ); + $pc->removeParam( self::LANGUAGE ); + } + if( ! $pc->hasParamKey( self::DERIVED )) { + $pc->addParam( self::DERIVED, self::FALSE ); // default + } + } + self::setMval( $this->styleddescription, $pc, $index ); + return $this; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/SubCompsGetTrait.php b/vendor/kigkonsult/icalcreator/src/Traits/SubCompsGetTrait.php new file mode 100644 index 0000000..d8fe3d8 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/SubCompsGetTrait.php @@ -0,0 +1,142 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use Kigkonsult\Icalcreator\Util\StringFactory; + +use function array_keys; +use function in_array; +use function mb_strtolower; + +trait SubCompsGetTrait +{ + /** + * Return (compType) subComp detail contents and (opt) type value + * + * @param string $compType + * @param string $detailPropName + * @param string $xParamRefId + * @param string $xPropTypeName + * @param string|string[] $xParamTypeRef + * @return array[] + * @since 2.41.68 - 2022-10-24 + */ + protected function getSubCompsDetailType( + string $compType, + string $detailPropName, + string $xParamRefId, + string $xPropTypeName, + string|array $xParamTypeRef + ) : array + { + $vSubValues = $lcArr = []; + $method1 = StringFactory::getGetMethodName( $detailPropName ); + $method2 = StringFactory::getGetMethodName( $xPropTypeName ); + foreach( array_keys( $this->components ) as $cix ) { + if( $compType !== $this->components[$cix]->getCompType()) { + continue; + } + if(( false === ( $pc = $this->components[$cix]->{$method1}( true ))) || + empty( $pc->value )) { + continue; + } + $lcValue = mb_strtolower( $pc->value ); + if( in_array( $lcValue, $lcArr, true )) { // no dupl. + continue; + } + $vSubValues[$pc->value] = $pc->params; + $vSubValues[$pc->value][$xParamRefId] = $this->components[$cix]->getUID(); + if( false !== ( $type = $this->components[$cix]->{$method2}())) { + foreach((array) $xParamTypeRef as $pKey ) { + $vSubValues[$pc->value][$pKey] = $type; + } + } + $lcArr[$pc->value] = $lcValue; + } // end foreach + return [ $vSubValues, $lcArr ]; + } + + /** + * Update properties from subCompData, create new ones for all but found + * + * @param string $propName + * @param bool $multi if prop may occur multiple times in component + * @param array $subCompsData + * @param array $lcArr + * @return void + * @since 2.41.68 - 2022-10-24 + */ + protected function comPropUpdFromSub( string $propName, bool $multi, array $subCompsData, array $lcArr ) : void + { + // get all component property values + $method = StringFactory::getGetMethodName( $propName ); + $compPropData = []; + while( false !== ( $content = $this->{$method}( null, true ))) { + if( ! empty( $content->value )) { + $compPropData[$content->value] = $content->params; + } + if( ! $multi ) { + break; // the only one is found + } + } // end while + // check for hits (ignore case), if hit then update this::hit and remove current $subCompsData + $update = false; + foreach( array_keys( $compPropData ) as $cValue ) { + if( in_array( mb_strtolower( $cValue ), $lcArr, true )) { + $update = true; + foreach( $subCompsData[$cValue] as $vParamKey => $vParamValue ) { + if( ! isset( $compPropData[$cValue][$vParamKey] )) { + $compPropData[$cValue][$vParamKey] = $vParamValue; + } + } // end foreach + if( $multi ) { + unset( $subCompsData[$cValue] ); + } + else { + $subCompsData = [ $cValue => $compPropData[$cValue] ]; // upd the only one + $compPropData = []; + break; + } + } // end if + } // end foreach + if( $update ) { + $method = StringFactory::getDeleteMethodName( $propName ); + while( false !== $this->{$method}()) {} // remove all + $subCompsData = array_merge( $subCompsData, $compPropData ); // force write back + } + // create new properties from subdata + if( ! empty( $subCompsData )) { + $method = StringFactory::getSetMethodName( $propName ); + foreach( $subCompsData as $value => $params ) { + $this->{$method}( $value, $params ); + } + } // end if + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/TZID_ALIAS_OFrfc7808trait.php b/vendor/kigkonsult/icalcreator/src/Traits/TZID_ALIAS_OFrfc7808trait.php new file mode 100644 index 0000000..f12bc07 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/TZID_ALIAS_OFrfc7808trait.php @@ -0,0 +1,157 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use Kigkonsult\Icalcreator\Formatter\Property\MultiProps; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\Util; + +/** + * TZID-ALIAS-OF property functions + * + * @since 2.41.85 2024-01-18 + */ +trait TZID_ALIAS_OFrfc7808trait +{ + /** + * @var null|Pc[] component property TZID_ALIAS_OF value + */ + protected ? array $tzidaliasof = null; + + /** + * Return formatted output for calendar component property TZID-ALIAS-OF + * + * @return string + * @since 2.41.55 2022-08-13 + */ + public function createTzidaliasof() : string + { + return MultiProps::format( + self::TZID_ALIAS_OF, + $this->tzidaliasof ?? [], + $this->getConfig( self::ALLOWEMPTY ) + ); + } + + /** + * Delete calendar component property TZID-ALIAS-OF + * + * @param null|int $propDelIx specific property in case of multiply occurrence + * @return bool + * @since 2.41.1 2022-01-15 + */ + public function deleteTzidaliasof( ? int $propDelIx = null ) : bool + { + if( empty( $this->tzidaliasof )) { + unset( $this->propDelIx[self::TZID_ALIAS_OF] ); + return false; + } + return self::deletePropertyM( + $this->tzidaliasof, + self::TZID_ALIAS_OF, + $this, + $propDelIx + ); + } + + /** + * Get calendar component property TZID-ALIAS-OF + * + * @param null|int $propIx specific property in case of multiply occurrence + * @param bool $inclParam + * @return bool|string|Pc + * @since 2.41.36 2022-04-03 + */ + public function getTzidaliasof( int $propIx = null, bool $inclParam = false ) : bool | string | Pc + { + if( empty( $this->tzidaliasof )) { + unset( $this->propIx[self::TZID_ALIAS_OF] ); + return false; + } + return self::getMvalProperty( + $this->tzidaliasof, + self::TZID_ALIAS_OF, + $this, + $propIx, + $inclParam + ); + } + + /** + * Return array, all calendar component property tzidaliasof + * + * @param null|bool $inclParam + * @return Pc[] + * @since 2.41.58 2022-08-24 + */ + public function getAllTzidaliasof( ? bool $inclParam = false ) : array + { + return self::getMvalProperties( $this->tzidaliasof, $inclParam ); + } + + /** + * Return bool true if set (and ignore empty property) + * + * @return bool + * @since 2.41.35 2022-03-28 + */ + public function isTzidaliasofSet() : bool + { + return self::isMvalSet( $this->tzidaliasof ); + } + + /** + * Set calendar component property TZID-ALIAS-OF + * + * @param null|string|Pc $value + * @param null|int|array $params + * @param null|int $index + * @return static + * @since 2.41.85 2024-01-18 + */ + public function setTzidaliasof( + null|string|Pc $value = null, + null|int|array $params = [], + ? int $index = null + ) : static + { + $pc = self::marshallInputMval( $value, $params, $index ); + $pcValue = $pc->getValue(); + if( empty( $pcValue )) { + $this->assertEmptyValue( $pcValue, self::TZID_ALIAS_OF ); + $pc->setEmpty(); + } + else { + $pcValue = Util::assertString( $pcValue, self::TZID_ALIAS_OF ); + } + self::setMval( $this->tzidaliasof, $pc->setValue( $pcValue ), $index ); + return $this; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Traits/TZUNTILrfc7808trait.php b/vendor/kigkonsult/icalcreator/src/Traits/TZUNTILrfc7808trait.php new file mode 100644 index 0000000..95bdbf1 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Traits/TZUNTILrfc7808trait.php @@ -0,0 +1,134 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Traits; + +use DateTime; +use DateTimeInterface; +use Exception; +use InvalidArgumentException; +use Kigkonsult\Icalcreator\Formatter\Property\DtxProperty; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\DateTimeFactory; + +/** + * TZUNTIL property functions + * + * @since 2.41.85 2024-01-18 + */ +trait TZUNTILrfc7808trait +{ + /** + * @var null|Pc component property TZUNTIL value + */ + protected ? Pc $tzuntil = null; + + /** + * Return formatted output for calendar component property TZUNTIL + * + * @return string + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.55 - 2022-08-13 + */ + public function createTzuntil() : string + { + return DtxProperty::format( + self::TZUNTIL, + $this->tzuntil, + $this->getConfig( self::ALLOWEMPTY ) + ); + } + + /** + * Delete calendar component property TZUNTIL + * + * @return bool + * @since 2.41.1 2022-01-15 + */ + public function deleteTzuntil() : bool + { + $this->tzuntil = null; + return true; + } + + /** + * Return calendar component property TZUNTIL + * + * @param null|bool $inclParam + * @return bool|string|DateTime|Pc + * @since 2.41.85 2024-01-18 + */ + public function getTzuntil( ? bool $inclParam = false ) : DateTime | bool | string | Pc + { + if( empty( $this->tzuntil )) { + return false; + } + return $inclParam ? clone $this->tzuntil : $this->tzuntil->getValue(); + } + + /** + * Return bool true if set (and ignore empty property) + * + * @return bool + * @since 2.41.88 2024-01-19 + */ + public function isTzuntilSet() : bool + { + return self::isPropSet( $this->tzuntil ); + } + + /** + * Set calendar component property TZUNTIL, datetime UTC + * + * @param null|string|Pc|DateTimeInterface $value + * @param null|mixed[] $params + * @return static + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.85 2024-01-18 + */ + public function setTzuntil( + null | string | Pc | DateTimeInterface $value = null, + ? array $params = [] + ) : static + { + $pc = Pc::factory( $value, $params ); + $pcValue = $pc->getValue(); + if( empty( $pcValue )) { + $this->assertEmptyValue( $pcValue, self::TZUNTIL ); + $this->tzuntil = $pc->setEmpty(); + } + else { + $pc->addParamValue( self::DATE_TIME ); // req + $this->tzuntil = DateTimeFactory::setDate( $pc, true ); // force UTC + } + return $this; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/V2component.php b/vendor/kigkonsult/icalcreator/src/V2component.php new file mode 100644 index 0000000..f81e137 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/V2component.php @@ -0,0 +1,61 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator; + +use Exception; + +abstract class V2component extends Vcomponent +{ + /** + * Return Participant object instance + * + * @param null|string $participanttype property PARTICIPANT-TYPE value + * @param null|string $calendaraddress property CALENDAR-ADDRESS value + * @param null|string $url property URL value + * @return Participant + * @throws Exception + * @since 2.41.53 - 2022-08-08 + */ + public function newParticipant( + ? string $participanttype = null, + ? string $calendaraddress = null, + ? string $url = null + ) : Participant + { + $ix = $this->getNextComponentIndex(); + $this->components[$ix] = Participant::factory( + $this->getConfig(), + $participanttype, + $calendaraddress, + $url + ); + return $this->components[$ix]; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/V3component.php b/vendor/kigkonsult/icalcreator/src/V3component.php new file mode 100644 index 0000000..ca6e79d --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/V3component.php @@ -0,0 +1,117 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator; + +use DateInterval; +use DateTimeInterface; +use Exception; + +/** + * iCalcreator VEVENT/VTODO component base class + * + * @since 2.41.53 - 2022-08-08 + */ +abstract class V3component extends V2component +{ + /** + * Return Valarm object instance + * + * @param null|string $action property ACTION value + * @param null|string|DateInterval|DateTimeInterface $trigger property TRIGGER value + * @return Valarm + * @throws Exception + * @since 2.41.53 - 2022-08-08 + */ + public function newValarm( + ? string $action = null, + null|string|DateInterval|DateTimeInterface $trigger = null + ) : Valarm + { + $ix = $this->getNextComponentIndex(); + $this->components[$ix] = Valarm::factory( $this->getConfig(), $action, $trigger ); + return $this->components[$ix]; + } + + use Traits\Participants2AttendeesTrait; + + /** + * Set Vevent/Vtodo subComponent Vlocation names as Locations, skip if set + * + * Vlocation UID set as Location X-param x-vlocationid + * All Vlocation name parameters are set if not exist. + * Vlocation LOCATION_TYPE set as Location X-param x-location-type + * + * @return static + * @since 2.41.19 - 2022-02-19 + */ + public function vlocationNames2Location() : static + { + // get all (sub) Vlocation names etc (incl params) + [ $vLocations, $lcArr ] = $this->getSubCompsDetailType( + self::VLOCATION, + self::NAME, + self::X_VLOCATIONID, + self::LOCATION_TYPE, + self::X_LOCATION_TYPE + ); + if( ! empty( $vLocations )) { + $this->comPropUpdFromSub( self::LOCATION, false, $vLocations, $lcArr ); + } + return $this; + } + + /** + * Set Vevent/Vtodo subComponent Vresource names as Resource, skip if set + * + * Vresource UID set as Resurce X-param x-participantid + * Other Vresource name parameters are set if ot exist. + * Vresource RESOURCE_TYPE set as Location X-param x-resource-type + * + * @return static + * @since 2.41.21 - 2022-02-18 + */ + public function vresourceNames2Resources() : static + { + // get all (sub) Vresource names etc (incl params) + [ $vResources, $lcArr ] = $this->getSubCompsDetailType( + self::VRESOURCE, + self::NAME, + self::X_VRESOURCEID, + self::RESOURCE_TYPE, + self::X_RESOURCE_TYPE + ); + if( ! empty( $vResources )) { + $this->comPropUpdFromSub( self::RESOURCES, true, $vResources, $lcArr ); + } + return $this; + } + + use Traits\SubCompsGetTrait; +} diff --git a/vendor/kigkonsult/icalcreator/src/VAcomponent.php b/vendor/kigkonsult/icalcreator/src/VAcomponent.php new file mode 100644 index 0000000..e151bc8 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/VAcomponent.php @@ -0,0 +1,63 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator; + +/** + * iCalcreator VAcomponents base class + * + * @since 2.41.53 - 2022-08-11 + */ +abstract class VAcomponent extends Vcomponent +{ + //the following are REQUIRED but MUST NOT occur more than once + use Traits\UIDrfc7986trait; + + // the following are REQUIRED but MUST NOT occur more than once : AVAILABLE + // the following are OPTIONAL but MUST NOT occur more than once : Vavailability + use Traits\DTSTARTtrait; + + // the following are OPTIONAL but MUST NOT occur more than once + use Traits\CREATEDtrait; + use Traits\DESCRIPTIONtrait; + use Traits\LAST_MODIFIEDtrait; + use Traits\LOCATIONtrait; + use Traits\SUMMARYtrait; + + // Either 'dtend' or 'duration' MAY appear in an 'availableprop', + // but 'dtend' and 'duration' MUST NOT occur in the same 'availabilityprop'/'availableprop'. + // 'duration' MUST NOT be present if 'dtstart' is not present : VAVAILABILITYonly + use Traits\DTENDtrait; + use Traits\DURATIONtrait; + + //the following are OPTIONAL and MAY occur more than once + use Traits\CATEGORIEStrait; + use Traits\COMMENTtrait; + use Traits\CONTACTtrait; +} diff --git a/vendor/kigkonsult/icalcreator/src/Vavailability.php b/vendor/kigkonsult/icalcreator/src/Vavailability.php new file mode 100644 index 0000000..c1ff2c7 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Vavailability.php @@ -0,0 +1,189 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator; + +use DateInterval; +use DateTimeInterface; +use Exception; +use InvalidArgumentException; +use Kigkonsult\Icalcreator\Formatter\Vavailability as Formatter; + +use function array_keys; + +/** + * iCalcreator rfc7953 VAVAILABILITY component class + * + * @since 2.41.55 - 2022-08-13 + */ +final class Vavailability extends VAcomponent +{ + // the following are OPTIONAL but MUST NOT occur more than once (and NOT declared in VAcomponent) + use Traits\BUSYTYPErfc7953trait; + use Traits\CLASStrait; + use Traits\ORGANIZERtrait; + use Traits\PRIORITYtrait; + use Traits\SEQUENCEtrait; + use Traits\URLtrait; + + /** + * @var string + */ + protected static string $compSgn = 'va'; + + /** + * Constructor + * + * @param null|string[] $config + * @throws Exception + * @since 2.41.53 - 2022-08-11 + */ + public function __construct( ? array $config = [] ) + { + parent::__construct( $config ); + $this->setDtstamp(); + $this->setUid(); + } + + /** + * Return Vavailability object instance + * + * @param null|string[] $config + * @param null|string $busyType + * @param null|string|DateTimeInterface $dtstart + * @param null|string|DateTimeInterface $dtend + * @param null|string|DateInterval $duration + * @return Vavailability + * @throws InvalidArgumentException + * @throws Exception + * @since 2.41.53 - 2022-08-08 + */ + public static function factory( + ? array $config = [], + ? string $busyType = null, + null|string|DateTimeInterface $dtstart = null, + null|string|DateTimeInterface $dtend = null, + null|string|DateInterval $duration = null + ) : Vavailability + { + $instance = new Vavailability( $config ); + if( null !== $busyType ) { + $instance->setBusytype( $busyType ); + } + if( null !== $dtstart ) { + $instance->setDtstart( $dtstart ); + } + if( null !== $dtend ) { + $instance->setDtend( $dtend ); + } + elseif( null !== $duration ) { + $instance->setDuration( $duration ); + } + return $instance; + } + + /** + * Destructor + */ + public function __destruct() + { + if( ! empty( $this->components )) { + foreach( array_keys( $this->components ) as $cix ) { + $this->components[$cix]->__destruct(); + } + } + unset( + $this->compType, + $this->xprop, + $this->components, + $this->config, + $this->compix, + $this->propIx, + $this->propDelIx + ); + unset( + $this->cno, + $this->srtk + ); + unset( + $this->busytype, + $this->class, + $this->comment, + $this->contact, + $this->created, + $this->description, + $this->dtend, + $this->dtstamp, + $this->dtstart, + $this->duration, + $this->lastmodified, + $this->location, + $this->organizer, + $this->priority, + $this->sequence, + $this->summary, + $this->uid, + $this->url + ); + } + + /** + * Return Available object instance + * + * @param null|string|DateTimeInterface $dtstart + * @param null|string|DateTimeInterface $dtend + * @param null|string|DateInterval $duration + * @return Available + * @throws InvalidArgumentException + * @throws Exception + * @since 2.41.53 - 2022-08-08 + */ + public function newAvailable( + null|string|DateTimeInterface $dtstart = null, + null|string|DateTimeInterface $dtend = null, + null|string|DateInterval $duration = null + ) : Available + { + $ix = $this->getNextComponentIndex(); + $this->components[$ix] = Available::factory( $this->getConfig(), $dtstart, $dtend, $duration ); + return $this->components[$ix]; + } + + /** + * Return formatted output for calendar component Vavailability object instance + * + * @return string + * @throws Exception (on Duration/Rdate err) + * @since 2.41.55 - 2022-08-13 + */ + public function createComponent() : string + { + return Formatter::format( $this ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Vlocation.php b/vendor/kigkonsult/icalcreator/src/Vlocation.php new file mode 100644 index 0000000..5d51479 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Vlocation.php @@ -0,0 +1,140 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator; + +use Exception; +use Kigkonsult\Icalcreator\Formatter\Vlocation as Formatter; + +/** + * iCalcreator Vlocation component class + * + * @since 2.41.55 - 2022-08-13 + */ +final class Vlocation extends CalendarComponent +{ + /* The following are REQUIRED but MUST NOT occur more than once. */ + use Traits\UIDrfc7986trait; + + /* The following are OPTIONAL but MUST NOT occur more than once. */ + use Traits\DESCRIPTIONtrait; + use Traits\GEOtrait; // opt removal ?? + use Traits\LOCATIONTYPErfc9073trait; + use Traits\NAMErfc7986trait; + use Traits\URLtrait; + + /* The following are OPTIONAL and MAY occur more than once. */ + use Traits\STRUCTURED_DATArfc9073trait; + + /** + * @var string + */ + protected static string $compSgn = 'vl'; + + /** + * Constructor + * + * @param null|string[] $config + * @throws Exception + * @since 2.41.53 - 2022-08-11 + */ + public function __construct( ? array $config = [] ) + { + parent::__construct( $config ); + $this->setUid(); + } + + /** + * Return Vlocation object instance + * + * @param null|string[] $config + * @param null|string $locationType property LOCATION-TYPE value + * @param null|string $name property NAME value + * @return Vlocation + * @throws Exception + * @since 2.41.53 - 2022-08-08 + */ + public static function factory( + ? array $config = [], + ? string $locationType = null, + ? string $name = null + ) : Vlocation + { + $instance = new Vlocation( $config ); + if( null !== $locationType ) { + $instance->setLocationtype( $locationType ); + } + if( null !== $name ) { + $instance->setName( $name ); + } + return $instance; + } + + /** + * Destructor + * + * @since 2.41.5 2022-01-19 + */ + public function __destruct() + { + unset( + $this->compType, + $this->xprop, + $this->components, + $this->config, + $this->propIx, + $this->propDelIx + ); + unset( + $this->cno, + $this->srtk + ); + unset( + $this->uid, + $this->description, + $this->geo, + $this->locationtype, + $this->name, + $this->structureddata, + $this->url + ); + } + + /** + * Return formatted output for calendar component VALARM object instance + * + * @return string + * @throws Exception (on Duration/Trigger err) + * @since 2.41.55 - 2022-08-13 + */ + public function createComponent() : string + { + return Formatter::format( $this ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Vresource.php b/vendor/kigkonsult/icalcreator/src/Vresource.php new file mode 100644 index 0000000..dcb8e19 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Vresource.php @@ -0,0 +1,138 @@ + + * @copyright 2007-2023 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator; + +use Exception; +use Kigkonsult\Icalcreator\Formatter\Vresource as Formatter; + +/** + * iCalcreator Vlocation component class + * + * @since 2.41.55 - 2022-08-13 + */ +final class Vresource extends CalendarComponent +{ + /* The following are REQUIRED but MUST NOT occur more than once. */ + use Traits\UIDrfc7986trait; + + /* The following are OPTIONAL but MUST NOT occur more than once. */ + use Traits\DESCRIPTIONtrait; + use Traits\GEOtrait; + use Traits\NAMErfc7986trait; + use Traits\RESOURCE_TYPErfc9073trait; + + /* The following are OPTIONAL and MAY occur more than once. */ + use Traits\STRUCTURED_DATArfc9073trait; + + /** + * @var string + */ + protected static string $compSgn = 'vr'; + + /** + * Constructor + * + * @param null|string[] $config + * @throws Exception + * @since 2.41.53 - 2022-08-11 + */ + public function __construct( ? array $config = [] ) + { + parent::__construct( $config ); + $this->setUid(); + } + + /** + * Return Vresource object instance + * + * @param null|string[] $config + * @param null|string $resourceType property RESOURCE-TYPE value + * @param null|string $name property NAME value + * @return Vresource + * @throws Exception + * @since 2.41.53 - 2022-08-08 + */ + public static function factory( + ? array $config = [], + ? string $resourceType = null, + ? string $name = null + ): Vresource + { + $instance = new Vresource( $config ); + if( null !== $resourceType ) { + $instance->setResourcetype( $resourceType ); + } + if( null !== $name ) { + $instance->setName( $name ); + } + return $instance; + } + + /** + * Destructor + * + * @since 2.41.7 2022-01-20 + */ + public function __destruct() + { + unset( + $this->compType, + $this->xprop, + $this->components, + $this->config, + $this->propIx, + $this->propDelIx + ); + unset( + $this->cno, + $this->srtk + ); + unset( + $this->uid, + $this->description, + $this->geo, + $this->name, + $this->resourcetype, + $this->structureddata + ); + } + + /** + * Return formatted output for calendar component VALARM object instance + * + * @return string + * @throws Exception (on Duration/Trigger err) + * @since 2.41.55 - 2022-08-13 + */ + public function createComponent() : string + { + return Formatter::format( $this ); + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Xml/Formatter.php b/vendor/kigkonsult/icalcreator/src/Xml/Formatter.php new file mode 100644 index 0000000..2671ca4 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Xml/Formatter.php @@ -0,0 +1,1382 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Xml; + +use DateInterval; +use DateTime; +use Exception; +use InvalidArgumentException; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\IcalInterface; +use Kigkonsult\Icalcreator\Pc; +use Kigkonsult\Icalcreator\Util\DateIntervalFactory; +use Kigkonsult\Icalcreator\Util\DateTimeFactory; +use Kigkonsult\Icalcreator\Util\GeoFactory; +use Kigkonsult\Icalcreator\Util\StringFactory; +use Kigkonsult\Icalcreator\Vcalendar; +use Kigkonsult\Icalcreator\Vevent; +use SimpleXMLElement; + +use function array_change_key_case; +use function count; +use function htmlspecialchars; +use function implode; +use function in_array; +use function is_array; +use function sprintf; +use function strcasecmp; +use function strlen; +use function strstr; +use function strtolower; +use function strtoupper; +use function substr; + +/** + * iCalcreator XML (rfc6321) formatter class + * + * @since 2.41.88 2024-01-17 + */ +final class Formatter extends XmlBase +{ + /** + * @var string[] + */ + private static array $calProps = [ + IcalInterface::VERSION, + IcalInterface::PRODID, + IcalInterface::CALSCALE, + IcalInterface::METHOD, + ]; + + /** + * @var string[] + */ + private static array $calPropsrfc7986Single = [ + IcalInterface::UID, + IcalInterface::LAST_MODIFIED, + IcalInterface::URL, + IcalInterface::REFRESH_INTERVAL, + IcalInterface::SOURCE, + IcalInterface::COLOR + ]; + + /** + * @var string[] + */ + private static array $calPropsrfc7986Multi = [ + IcalInterface::NAME, + IcalInterface::DESCRIPTION, + IcalInterface::CATEGORIES, + IcalInterface::IMAGE + ]; + + /** + * @var string + */ + private static string $boolean = 'boolean'; + + /** + * @var string + */ + private static string $integer = 'integer'; + + /** + * @var string + */ + private static string $rstatus = 'rstatus'; + + /** + * @var string + */ + private static string $time = 'time'; + + /** + * @var string + */ + private static string $utc_offset = 'utc-offset'; + + + /** + * @var string + */ + private static string $bysecond = 'bysecond'; + + /** + * @var string + */ + private static string $byminute = 'byminute'; + + /** + * @var string + */ + private static string $byhour = 'byhour'; + + /** + * @var string + */ + private static string $bymonthday = 'bymonthday'; + + /** + * @var string + */ + private static string $byyearday = 'byyearday'; + + /** + * @var string + */ + private static string $byweekno = 'byweekno'; + + /** + * @var string + */ + private static string $bymonth = 'bymonth'; + + /** + * @var string + */ + private static string $bysetpos = 'bysetpos'; + + /** + * @var string + */ + private static string $byday = 'byday'; + + /** + * @var string + */ + public static string $XMLstart = + ''; + + /** + * Return iCal XML (rfc6321) string output, false on error + * + * @param Vcalendar $calendar iCalcreator Vcalendar instance + * @return bool|string + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.69 2022-10-04 + */ + public static function iCal2XML( Vcalendar $calendar ) : bool | string + { + static $YMDTHISZ = 'Ymd\THis\Z'; + // fix an SimpleXMLElement instance and create root element + $xml = new SimpleXMLElement( + sprintf( self::$XMLstart, ICALCREATOR_VERSION, gmdate( $YMDTHISZ )) + ); + $vCalendarXml = self::addSubChild( $xml, self::$Vcalendar ); + $langCal = $calendar->getConfig( IcalInterface::LANGUAGE ); + // fix calendar properties + self::calendarProps2Xml( $calendar, $vCalendarXml, $langCal ); + // prepare to fix components with properties/subComponents + $componentsXml = self::addSubChild( $vCalendarXml, self::$components ); + // fix component properties + foreach( $calendar->getComponents() as $component ) { + $componentChild = self::addSubChild( $componentsXml, strtolower( $component->getCompType())); + self::componentProps2Xml( $component, $componentChild, $langCal ); + } // end foreach + return $xml->asXML(); + } + + /** + * Parse Vcalendar properties into XML + * + * @param Vcalendar $calendar iCalcreator Vcalendar instance + * @param SimpleXMLElement $vCalendarXml + * @param bool|string $langCal + * @throws Exception + * @since 2.41.69 2022-10-07 + */ + private static function calendarProps2Xml( + Vcalendar $calendar, + SimpleXMLElement $vCalendarXml, + bool | string $langCal + ) : void + { + $properties = self::addSubChild( $vCalendarXml, self::$properties ); + foreach( self::$calProps as $propName ) { + $method = StringFactory::getGetMethodName( $propName ); + if( false !== ( $content = $calendar->{$method}())) { + self::addXMLchildText( $properties, $propName, Pc::factory( $content )); + } + } // end foreach + foreach( self::$calPropsrfc7986Single as $propName ) { + $getMethod = StringFactory::getGetMethodName( $propName ); + if( false === ( $content = $calendar->{$getMethod}( true ))) { + continue; + } + match( strtoupper( $propName )) { + IcalInterface::UID, IcalInterface::COLOR => + self::addXMLchildText( $properties, $propName, $content ), + IcalInterface::LAST_MODIFIED => + self::addXMLchildDateTime( $properties, $propName, $content, true ), + IcalInterface::SOURCE, IcalInterface::URL => + self::addXMLchildUri( $properties, $propName, $content ), + IcalInterface::REFRESH_INTERVAL => + self::addXMLchildDuration( $properties, $propName, $content ), + default => null + }; // end match + } // end foreach + foreach( self::$calPropsrfc7986Multi as $propName ) { + $method = StringFactory::getGetAllMethodName( $propName ); + switch( strtoupper( $propName )) { + case IcalInterface::CATEGORIES : // fall through + case IcalInterface::DESCRIPTION : // fall through + case IcalInterface::NAME : + foreach( $calendar->{$method}( true ) as $content ) { + self::addXMLchildText( $properties, $propName, $content, $langCal ); + } // end while + break; + case IcalInterface::IMAGE : + self::addXMLchildBinaryUriArr( $properties, $propName, $calendar->{$method}( true )); // array + break; + } // end switch + } // end foreach + foreach( $calendar->getAllXprop( true ) as $contents ) { + self::addXMLchild( $properties, $contents[0], self::$unknown, $contents[1] ); + } // end while + } + + /** + * Parse component into XML + * + * @param CalendarComponent|Vevent $component + * @param SimpleXMLElement $parentXml + * @param bool|string $langCal + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function componentProps2Xml( + CalendarComponent|Vevent $component, + SimpleXMLElement $parentXml, + bool | string $langCal + ) : void + { + $compName = $component->getCompType(); + $properties = self::addSubChild( $parentXml, self::$properties ); + $langComp = $component->getConfig( IcalInterface::LANGUAGE ); + $lang = ( $langComp ?: $langCal ); + $props = $component->getConfig( IcalInterface::SETPROPERTYNAMES ); + foreach( $props as $propName ) { + if( StringFactory::isXprefixed( $propName )) { + $content = $component->getXprop( $propName, null, true ); + self::addXMLchild( $properties, $content[0], self::$unknown, $content[1] ); + continue; + } + $method = Vcalendar::isMultiProp( $propName ) + ? StringFactory::getGetAllMethodName( $propName ) + : StringFactory::getGetMethodName( $propName ); + $data = $component->{$method}( true ); + match( strtoupper( $propName )) { + IcalInterface::ATTACH, // may occur multiple times + IcalInterface::IMAGE => + self::addXMLchildBinaryUriArr( $properties, $propName, $data ), // array + IcalInterface::ATTENDEE => // may occur multiple times + self::addXMLchildCalAddress( $properties, $propName, $data, $langComp ), + IcalInterface::EXDATE => + self::addXMLchildExdate( $properties, $propName, $data ), + IcalInterface::FREEBUSY => + self::addXMLchildFreebusy( $properties, $propName, $data ), + IcalInterface::REQUEST_STATUS => + self::addXMLchildReqStat( $properties, $propName, $data, $langComp, $langCal ), + IcalInterface::RDATE => + self::addXMLchildRdate( $properties, $propName, $data), + IcalInterface::DESCRIPTION, // multiple in VCALENDAR/VJOURNAL, single elsewere + IcalInterface::LOCATION => // multiple in PARTICIPANT, single elsewere + self::addXMLchildDescrLoc( $component, $properties, $propName, $data, $lang, $compName ), + IcalInterface::STYLED_DESCRIPTION => + self::addXMLchildStlDescr( $properties, $propName, $data, $lang ), + IcalInterface::CATEGORIES, IcalInterface::COMMENT, + IcalInterface::CONTACT, // // single in VFREEBUSY, multiple elsewhere + IcalInterface::NAME, // dito, multi i Vcalendar, single in Vlocation/Vresource (here) + IcalInterface::TZID_ALIAS_OF, IcalInterface::TZNAME, + IcalInterface::RESOURCES, IcalInterface::RELATED_TO => + self::addXMLchildGroup1( $component, $properties, $propName, $data, $langComp, $langCal, $compName ), + IcalInterface::ACKNOWLEDGED, IcalInterface::CREATED, IcalInterface::COMPLETED, + IcalInterface::DTSTAMP, IcalInterface::LAST_MODIFIED, + IcalInterface::DTSTART, IcalInterface::DTEND, IcalInterface::DUE, + IcalInterface::RECURRENCE_ID, IcalInterface::TZUNTIL => + self::addXMLchildGroup2( $properties, $propName, $data ), + IcalInterface::DURATION => + self::addXMLchildDuration( $properties, $propName, $data ), + IcalInterface::EXRULE, IcalInterface::RRULE => + self::addXMLchildRecur( $properties, $propName, $data ), + IcalInterface::LOCATION_TYPE, IcalInterface::SUMMARY, IcalInterface::ACTION, + IcalInterface::BUSYTYPE, IcalInterface::KLASS, IcalInterface::COLOR, + IcalInterface::PROXIMITY, IcalInterface::PARTICIPANT_TYPE, IcalInterface::RESOURCE_TYPE, + IcalInterface::STATUS, IcalInterface::TRANSP, IcalInterface::TZID, IcalInterface::UID => + self::addXMLchildGroup3( $properties, $propName, $data, $langComp, $langCal ), + IcalInterface::GEO => + self::addXMLchild( $properties, $propName, strtolower( IcalInterface::GEO ), $data ), + IcalInterface::CALENDAR_ADDRESS, IcalInterface::ORGANIZER => + self::addXMLchildCalAddress( $properties, $propName, [ $data ], $lang ), + IcalInterface::PERCENT_COMPLETE, IcalInterface::PRIORITY, + IcalInterface::REPEAT, IcalInterface::SEQUENCE => + self::addXMLchildInteger( $properties, $propName, $data ), + IcalInterface::STRUCTURED_DATA => + self::addXMLchildStrData( $properties, $propName, $data ), + IcalInterface::CONFERENCE => + self::addXMLchildConferens( $properties, $propName, $data ), + IcalInterface::TRIGGER => + self::addXMLchildTrigger( $properties, $propName, $data ), + IcalInterface::TZOFFSETFROM, IcalInterface::TZOFFSETTO => + self::addXMLchild( $properties, $propName, self::$utc_offset, $data ), + IcalInterface::TZURL, IcalInterface::URL => + self::addXMLchildUri( $properties, $propName, $data ), + default => null + }; // end match( $propName ) + } // end foreach( $props as $pix => $propName ) + // fix subComponent properties, if any + foreach( $component->getComponents() as $subComp ) { + $subCompChild =self::addSubChild( $parentXml, strtolower( $subComp->getCompType())); + self::componentProps2Xml( $subComp, $subCompChild, $langCal ); + } // end foreach + } + + /** + * Manage Exdate + * + * @param SimpleXMLElement $properties + * @param string $propName + * @param array $data + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function addXMLchildExdate( + SimpleXMLElement $properties, + string $propName, + array $data + ) : void + { + foreach( $data as $content ) { + if( self::hasValueDateSet( $content )) { + self::addXMLchildDate( $properties, $propName, $content ); + continue; + } + self::addXMLchildDateTime( $properties, $propName, $content ); + } // end foreach + } + + /** + * Manage FREEBUSY + * + * @param SimpleXMLElement $properties + * @param string $propName + * @param array $data + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function addXMLchildFreebusy( + SimpleXMLElement $properties, + string $propName, + array $data + ) : void + { + foreach( $data as $content ) { + self::addXMLchild( $properties, $propName, self::$period, $content ); + } // end foreach + } + + /** + * Manage REQUEST_STATUS + * + * @param SimpleXMLElement $properties + * @param string $propName + * @param array $data + * @param bool | string $langComp + * @param bool | string $langCal + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function addXMLchildReqStat( + SimpleXMLElement $properties, + string $propName, + array $data, + bool | string $langComp, + bool | string $langCal + ) : void + { + foreach( $data as $content ) { + self::addLanguage( $content, $langComp, $langCal ); + self::addXMLchild( $properties, $propName, self::$rstatus, $content ); + } // end foreach + } + + /** + * Manage Rdate + * + * @param SimpleXMLElement $properties + * @param string $propName + * @param array $data + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function addXMLchildRdate( + SimpleXMLElement $properties, + string $propName, + array $data + ) : void + { + foreach( $data as $content ) { + $type = self::getRdateValueType( $content ); + self::addXMLchild( $properties, $propName, $type, $content ); + } // end foreach + } + + /** + * Manage DESCRIPTION+LOCATION + * + * @param CalendarComponent|Vevent $component + * @param SimpleXMLElement $properties + * @param string $propName + * @param array $data + * @param bool|string $lang + * @param string $compName + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function addXMLchildDescrLoc( + CalendarComponent|Vevent $component, + SimpleXMLElement $properties, + string $propName, + array $data, + bool|string $lang, + string $compName + ) : void + { + foreach( $data as $content ) { + self::addXMLchildText( $properties, $propName, $content, $lang ); + if(( IcalInterface::DESCRIPTION === $propName ) && + $component::isDescriptionSingleProp( $compName )) { + break; + } + if(( IcalInterface::LOCATION === $propName ) && + $component::isLocationSingleProp( $compName )) { + break; + } + } // end foreach + } + + /** + * Manage STYLED_DESCRIPTION + * + * @param SimpleXMLElement $properties + * @param string $propName + * @param array $data + * @param bool|string $lang + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function addXMLchildStlDescr( + SimpleXMLElement $properties, + string $propName, + array $data, + bool|string $lang + ) : void + { + foreach( $data as $content ) { + if( $content->hasParamValue( IcalInterface::URI )) { + self::addXMLchildUri( $properties, $propName, $content ); + continue; + } + self::addXMLchildText( $properties, $propName, $content, $lang ); + } // end foreach + } + + /** + * Manage CATEGORIES+COMMENT+CONTACT+NAME+TZID_ALIAS_OF+TZNAME+RESOURCES+RELATED_TO + * + * @param CalendarComponent|Vevent $component + * @param SimpleXMLElement $properties + * @param string $propName + * @param array $data + * @param bool | string $langComp + * @param bool | string $langCal + * @param string $compName + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function addXMLchildGroup1( + CalendarComponent|Vevent $component, + SimpleXMLElement $properties, + string $propName, + array $data, + bool | string $langComp, + bool | string $langCal, + string $compName + ) : void + { + foreach( $data as $content ) { + if( $propName !== IcalInterface::RELATED_TO ) { + self::addLanguage( $content, $langComp, $langCal ); + } + self::addXMLchildText( $properties, $propName, $content ); + if( ( IcalInterface::NAME === $propName ) || + ( ( IcalInterface::CONTACT === $propName ) && + $component::isContactSingleProp( $compName ) ) ) { + break; + } + } // end foreach + } + + /** + * Manage ACKNOWLEDGED+CREATED+COMPLETED+DTSTAMP+LAST_MODIFIED+DTSTART+DTEND+DUE+RECURRENCE_IDTZUNTIL + * + * @param SimpleXMLElement $properties + * @param string $propName + * @param Pc $content + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function addXMLchildGroup2( + SimpleXMLElement $properties, + string $propName, + Pc $content + ) : void + { + if( self::hasValueDateSet( $content )) { + self::addXMLchildDate( $properties, $propName, $content ); + } + else { + self::addXMLchildDateTime( $properties, $propName, $content ); + } + } + + /** + * Manage group3 of properties + * + * LOCATION_TYPE+SUMMARY+ACTION+BUSYTYPE+KLASS+COLOR+PROXIMITY+PARTICIPANT_TYPE+ + * RESOURCE_TYPE+STATUS+TRANSP+TZID+UID : + * + * @param SimpleXMLElement $properties + * @param string $propName + * @param Pc $content + * @param bool | string $langCal + * @param bool | string $langComp + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function addXMLchildGroup3( + SimpleXMLElement $properties, + string $propName, + Pc $content, + bool | string $langComp, + bool | string $langCal + ) : void + { + static $LOCTSUM = [ IcalInterface::LOCATION_TYPE, IcalInterface::SUMMARY ]; + if( in_array( $propName, $LOCTSUM, true )) { + self::addLanguage( $content, $langComp, $langCal ); + } + self::addXMLchildText( $properties, $propName, $content ); + } + + /** + * Manage STRUCTURED_DATA + * + * @param SimpleXMLElement $properties + * @param string $propName + * @param array $data + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function addXMLchildStrData( + SimpleXMLElement $properties, + string $propName, + array $data + ) : void + { + foreach( $data as $content ) { + if( $content->hasParamValue( IcalInterface::TEXT )) { + self::addXMLchildText( $properties, $propName, $content ); + continue; + } + self::addXMLchildBinaryUri( $properties, $propName, $content ); + } // end foreach + } + + /** + * Manage CONFERENCE + * + * @param SimpleXMLElement $properties + * @param string $propName + * @param array $data + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function addXMLchildConferens( + SimpleXMLElement $properties, + string $propName, + array $data + ) : void + { + foreach( $data as $content ) { + self::addXMLchildUri( $properties, $propName, $content ); + } + } + + /** + * Manage TRIGGER + * + * @param SimpleXMLElement $properties + * @param string $propName + * @param Pc $content + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 2024-01-16 + */ + private static function addXMLchildTrigger( + SimpleXMLElement $properties, + string $propName, + Pc $content + ) : void + { + if( $content->getValue() instanceof DateInterval ) { + self::addXMLchildDuration( $properties, $propName, $content ); + } + else { + self::addXMLchildDateTime( $properties, $propName, $content ); + } + } + + /** + * Add Pc content parameter language if not set + * + * @param Pc $content property content + * @param bool|string $langComp + * @param bool|string $langCal + * @return void + * @since 2.41.88 2024-01-17 + */ + private static function addLanguage( Pc $content, bool | string $langComp, bool | string $langCal ) : void + { + match( true ) { + $content->hasParamKey( IcalInterface::LANGUAGE ) => null, + ( ! empty( $langComp )) => + $content->addParam( IcalInterface::LANGUAGE, $langComp ), + ( ! empty( $langCal )) => + $content->addParam( IcalInterface::LANGUAGE, $langCal ), + default => null, + }; // end match + } + + /** + * Return bool true if VALUE=DATE, remove param VALUE + * + * @param Pc $content + * @return bool + */ + private static function hasValueDateSet( Pc $content ) : bool + { + $isDateSet = $content->hasParamValue( IcalInterface::DATE ); + $content->removeParam( IcalInterface::VALUE ); + return $isDateSet; + } + + /** + * @param Pc $content + * @return string + */ + private static function getRdateValueType( Pc $content ) : string + { + $type = self::$date_time; + if( $content->hasParamValue( IcalInterface::DATE )) { + $type = self::$date; + } + elseif( $content->hasParamValue( IcalInterface::PERIOD )) { + $type = self::$period; + } // end if + $content->removeParam( IcalInterface::VALUE ); + return $type; + } + + /** + * Add XML (rfc6321) binary/uri children to SimpleXMLelement from array + * + * @param SimpleXMLElement $parent a SimpleXMLelement class instance + * @param string $name new element node name + * @param Pc[] $contents new subelements content + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.69 2022-10-05 + */ + private static function addXMLchildBinaryUriArr( SimpleXMLElement $parent, string $name, array $contents ) : void + { + foreach( $contents as $content ) { + self::addXMLchildBinaryUri( $parent, $name, $content ); + } + } + + /** + * Add XML (rfc6321) binary/uri children to SimpleXMLelement + * + * @param SimpleXMLElement $parent a SimpleXMLelement class instance + * @param string $name new element node name + * @param Pc $content new subelement content + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.69 2022-10-04 + */ + private static function addXMLchildBinaryUri( SimpleXMLElement $parent, string $name, Pc $content ) : void + { + $type = $content->hasParamValue( IcalInterface::BINARY ) + ? self::$binary + : self::$uri; + $content->removeParam( IcalInterface::VALUE ); + self::addXMLchild( $parent, $name, $type, $content ); + } + + /** + * Add XML (rfc6321) cal-address children to SimpleXMLelement + * + * @param SimpleXMLElement $parent a SimpleXMLelement class instance + * @param string $name new element node name + * @param Pc[] $contents new subelement contents + * @param bool|string $lang + * @return void + * @throws Exception + * @since 2.41.69 2022-11-02 + */ + private static function addXMLchildCalAddress( + SimpleXMLElement $parent, + string $name, + array $contents, + bool|string $lang + ) : void + { + foreach( $contents as $content ) { + if( $content->hasParamKey( IcalInterface::CN )) { + self::addLanguage( $content, $lang, false ); + } + self::addXMLchild( $parent, $name, self::$cal_address, $content ); + } // end foreach + } + + /** + * Add XML (rfc6321) date children to SimpleXMLelement + * + * @param SimpleXMLElement $parent a SimpleXMLelement class instance + * @param string $name new element node name + * @param Pc $content new subelement contents + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.69 2022-10-04 + */ + private static function addXMLchildDate( SimpleXMLElement $parent, string $name, Pc $content ) : void + { + self::addXMLchild( $parent, $name, self::$date, $content ); + } + + /** + * Add XML (rfc6321) date-time children to SimpleXMLelement + * + * @param SimpleXMLElement $parent a SimpleXMLelement class instance + * @param string $name new element node name + * @param Pc $content new subelement content + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.69 2022-10-04 + */ + private static function addXMLchildDateTime( + SimpleXMLElement $parent, + string $name, + Pc $content, + ? bool $skipValue = false + ) : void + { + if( $skipValue ) { + $content->removeParam(IcalInterface::VALUE ); + } + self::addXMLchild( $parent, $name, self::$date_time, $content ); + } + + /** + * Add XML (rfc6321) duration children to SimpleXMLelement + * + * @param SimpleXMLElement $parent a SimpleXMLelement class instance + * @param string $name new element node name + * @param Pc $content new subelement content + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.69 2022-10-04 + */ + private static function addXMLchildDuration( SimpleXMLElement $parent, string $name, Pc $content ) : void + { + self::addXMLchild( $parent, $name, strtolower( IcalInterface::DURATION ), $content ); + } + + /** + * Add XML (rfc6321) integer children to SimpleXMLelement + * + * @param SimpleXMLElement $parent a SimpleXMLelement class instance + * @param string $name new element node name + * @param Pc $content new subelement content + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.69 2022-10-04 + */ + private static function addXMLchildInteger( SimpleXMLElement $parent, string $name, Pc $content ) : void + { + self::addXMLchild( $parent, $name, self::$integer, $content ); + } + + /** + * Add XML (rfc6321) recur children to SimpleXMLelement + * + * @param SimpleXMLElement $parent a SimpleXMLelement class instance + * @param string $name new element node name + * @param Pc $content new subelement content + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.69 2022-10-04 + */ + private static function addXMLchildRecur( SimpleXMLElement $parent, string $name, Pc $content ) : void + { + self::addXMLchild( $parent, $name, self::$recur, $content ); + } + + /** + * Add XML (rfc6321) text children to SimpleXMLelement + * + * @param SimpleXMLElement $parent a SimpleXMLelement class instance + * @param string $name new element node name + * @param Pc $content new subelement content + * @param null|bool|string $lang + * @return void + * @throws Exception + * @since 2.41.69 2022-10-04 + */ + private static function addXMLchildText( + SimpleXMLElement $parent, + string $name, + Pc $content, + null|bool|string $lang = false + ) : void + { + if( $lang ) { + self::addLanguage( $content, false, $lang ); + } + self::addXMLchild( $parent, $name, self::$text, $content ); + } + + /** + * Add XML (rfc6321) uri children to SimpleXMLelement + * + * @param SimpleXMLElement $parent a SimpleXMLelement class instance + * @param string $name new element node name + * @param Pc $content new subelement content + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 - 2024-01-18 + */ + private static function addXMLchildUri( SimpleXMLElement $parent, string $name, Pc $content ) : void + { + $content->setValue( htmlentities( $content->getValue())); + self::addXMLchild( $parent, $name, self::$uri, $content ); + } + + /** + * Add XML (rfc6321) children to SimpleXMLelement + * + * @param SimpleXMLElement $parent a SimpleXMLelement class instance + * @param string $name new element node name + * @param string $type content type, subelement(-s) name + * @param Pc $subData new subelement value and 'attributes' + * @return void + * @throws Exception + * @throws InvalidArgumentException + * @since 2.41.88 - 2024-01-18 + */ + private static function addXMLchild( + SimpleXMLElement $parent, + string $name, + string $type, + Pc $subData + ) : void + { + /** create new child node */ + $name = strtolower( $name ); + $child = self::addSubChild( $parent, $name ); + $value = $subData->getValue(); + if( empty( $value ) && ( StringFactory::$ZERO !== (string) $value )) { + self::addSubChild( $child, $type ); + return; + } + $recurDateIsSet = false; + $isLocalTime = $subData->hasParamIsLocalTime(); + $params = (array) $subData->getParams(); + $isOneParm = ( 1 === count( $params )); + switch( true ) { + case ( empty( $params ) || ( $isOneParm && $isLocalTime )) : + break; + case ( self::$recur === $type ) : + $recurDateIsSet = $subData->hasParamValue( IcalInterface::DATE ); + if( $isOneParm && $subData->hasParamValue()) { + break; + } + $subData->removeParam( IcalInterface::VALUE ); + // fall through + default : + $parameters = self::addSubChild( $child, self::$PARAMETERS ); + self::addXMLchildParams( $parameters, $type, $params ); + break; + } // end switch + /** store content dep. on type */ + self::addXMLchildForType( $child, $type, $subData->getValue(), $isLocalTime, $recurDateIsSet ); + } + + /** + * @param SimpleXMLElement $parameters + * @param string $type + * @param array $params + * @return void + * @throws Exception + */ + private static function addXMLchildParams( SimpleXMLElement $parameters, string $type, array $params ) : void + { + static $altrep = 'altrep'; + static $dir = 'dir'; + static $delegated_from = 'delegated-from'; + static $delegated_to = 'delegated-to'; + static $member = 'member'; + static $order = 'order'; + static $sent_by = 'sent-by'; + static $rsvp = 'rsvp'; + static $derived = 'derived'; + foreach( $params as $pKey => $parVal ) { + if( IcalInterface::VALUE === $pKey ) { + if( str_contains( $parVal, StringFactory::$COLON )) { + $p1 = self::addSubChild( $parameters, strtolower( $pKey )); + self::addSubChild( $p1, self::$unknown, htmlspecialchars( $parVal )); + $type = strtolower( strstr( $parVal, StringFactory::$COLON, true )); + } + elseif( 0 !== strcasecmp( $type, $parVal )) { + $type = strtolower( $parVal ); + } + continue; + } // end if VALUE + if( IcalInterface::ISLOCALTIME === $pKey ) { + continue; + } + $pKey = strtolower( $pKey ); + if( StringFactory::isXprefixed( $pKey )) { + $p1 = self::addSubChild( $parameters, $pKey ); + self::addSubChild( $p1, self::$unknown, htmlspecialchars( $parVal )); + continue; + } + $p1 = self::addSubChild( $parameters, $pKey ); + $ptype = match ( $pKey ) { + $altrep, $dir => self::$uri, + $delegated_from, $delegated_to, $member, $sent_by => self::$cal_address, + $order => self::$integer, + $rsvp, $derived => self::$boolean, + default => self::$text, + }; // end match + if( is_array( $parVal )) { + foreach( $parVal as $pV ) { + self::addSubChild( $p1, $ptype, htmlspecialchars((string) $pV )); + } + } + else { + self::addSubChild( $p1, $ptype, htmlspecialchars((string) $parVal )); + } + } // end foreach $params + } + + /** + * @param SimpleXMLElement $child + * @param string $type + * @param mixed $value + * @param bool $isLocalTime + * @param bool $recurDateIsSet + * @return void + * @throws Exception + */ + private static function addXMLchildForType( + SimpleXMLElement $child, + string $type, + mixed $value, + bool $isLocalTime, + bool $recurDateIsSet + ) : void + { + match( $type ) { + self::$boolean, self::$time => null, + self::$binary, self::$uri, self::$cal_address => + self::addSubChild( $child, $type, $value ), + self::$date => + self::addXMLchildForTypeDate( $child, $type, $value ), + self::$date_time => + self::addXMLchildForTypeDateTime( $child, $type, $value, $isLocalTime ), + strtolower( IcalInterface::DURATION ) => + self::addSubChild( $child, $type, DateIntervalFactory::dateInterval2String( $value, true )), + strtolower( IcalInterface::GEO ) => + self::addXMLchildForTypeGeo( $child, $value ), + self::$integer => + self::addSubChild( $child, $type, (string) $value ), + self::$period => + self::addXMLchildForTypePeriod( $child, $type, $value, $isLocalTime ), + self::$recur => + self::addXMLchildForTypeRecur( $child, $value, $recurDateIsSet ), + self::$rstatus => + self::addXMLchildForTypeRstatus( $child, $value ), + self::$text => + self::addXMLchildForTypeText( $child, $type, $value ), + self::$utc_offset => + self::addXMLchildForTypeUtcOffset( $child, $type, $value ), + default => // also self::$unknown + self::addXMLchildForTypeUnknowDefault( $child, $value ), + }; // end match + } + + /** + * Manage date type + * + * @param SimpleXMLElement $child + * @param string $type + * @param mixed $value + * @return void + * @throws Exception + */ + private static function addXMLchildForTypeDate( SimpleXMLElement $child, string $type, mixed $value ) : void + { + if( $value instanceof DateTime ) { + $value = [ $value ]; + } + foreach( $value as $date ) { + self::addSubChild( $child, $type, DateTimeFactory::dateTime2Str( $date, true )); + } + } + + /** + * Manage date-time type + * + * @param SimpleXMLElement $child + * @param string $type + * @param mixed $value + * @param bool $isLocalTime + * @return void + * @throws Exception + */ + private static function addXMLchildForTypeDateTime( + SimpleXMLElement $child, + string $type, + mixed $value, + bool $isLocalTime + ) : void + { + if( $value instanceof DateTime ) { + $value = [ $value ]; + } + foreach( $value as $dt ) { + self::addSubChild( $child, $type, DateTimeFactory::dateTime2Str( $dt, false, $isLocalTime )); + } // end foreach + } + + /** + * Manage geo type + * + * @param SimpleXMLElement $child + * @param mixed $value + * @return void + * @throws Exception + */ + private static function addXMLchildForTypeGeo( SimpleXMLElement $child, mixed $value ) : void + { + if( ! empty( $value )) { + self::addSubChild( + $child, + IcalInterface::LATITUDE, + GeoFactory::geo2str2( $value[IcalInterface::LATITUDE], GeoFactory::$geoLatFmt ) + ); + self::addSubChild( + $child, + IcalInterface::LONGITUDE, + GeoFactory::geo2str2( $value[IcalInterface::LONGITUDE], GeoFactory::$geoLatFmt ) + ); + } // end if + } + + /** + * Manage period type + * + * @param SimpleXMLElement $child + * @param string $type + * @param mixed $value + * @param bool $isLocalTime + * @return void + * @throws Exception + */ + private static function addXMLchildForTypePeriod( + SimpleXMLElement $child, + string $type, + mixed $value, + bool $isLocalTime + ) : void + { + static $START = 'start'; + static $END = 'end'; + if( ! is_array( $value )) { + return; + } + foreach( $value as $period ) { + $v1 = self::addSubChild( $child, $type ); + $str = DateTimeFactory::dateTime2Str( $period[0], false, $isLocalTime ); + self::addSubChild( $v1, $START, $str ); + if( $period[1] instanceof DateInterval ) { + self::addSubChild( + $v1, + strtolower( IcalInterface::DURATION ), + DateIntervalFactory::dateInterval2String( $period[1] ) + ); + } + elseif( $period[1] instanceof DateTime ) { + $str = DateTimeFactory::dateTime2Str( $period[1], false, $isLocalTime ); + self::addSubChild( $v1, $END, $str ); + } + } // end foreach + } + + /** + * Manage recur type + * + * @param SimpleXMLElement $child + * @param mixed $value + * @param bool $recurDateIsSet + * @return void + * @throws Exception + */ + private static function addXMLchildForTypeRecur( + SimpleXMLElement $child, + mixed $value, + bool $recurDateIsSet + ) : void + { + static $UNTIL = 'until'; + $value = array_change_key_case( $value ); + foreach( $value as $ruleLabel => $ruleValue ) { + match( $ruleLabel ) { + $UNTIL => + self::addSubChild( $child, $ruleLabel, DateTimeFactory::dateTime2Str( $ruleValue, $recurDateIsSet )), + self::$bysecond, self::$byminute, self::$byhour, + self::$bymonthday, self::$byyearday, self::$byweekno, self::$bymonth, self::$bysetpos => + self::addXMLchildForTypeRecurGroup1( $child, $ruleLabel, $ruleValue ), + self::$byday => + self::addXMLchildForTypeRecurByDay( $child, $ruleLabel, $ruleValue ), + default => // self::$freq, self::$count, self::$interval, self::$wkst + self::addSubChild( $child, $ruleLabel, (string) $ruleValue ), + }; // end match( $ruleLabel ) + } // end foreach( $value as $ruleLabel => $ruleValue ) + } + + /** + * @param SimpleXMLElement $child + * @param string $ruleLabel + * @param mixed $ruleValue + * @return void + * @throws Exception + */ + private static function addXMLchildForTypeRecurGroup1( + SimpleXMLElement $child, + string $ruleLabel, + mixed $ruleValue + ) : void + { + if( is_array( $ruleValue )) { + foreach( $ruleValue as $valuePart ) { + self::addSubChild( $child, $ruleLabel, (string) $valuePart ); + } + } + else { + self::addSubChild( $child, $ruleLabel, $ruleValue ); + } + } + + /** + * @param SimpleXMLElement $child + * @param string $ruleLabel + * @param mixed $ruleValue + * @return void + * @throws Exception + */ + private static function addXMLchildForTypeRecurByDay( + SimpleXMLElement $child, + string $ruleLabel, + mixed $ruleValue + ) : void + { + if( isset( $ruleValue[IcalInterface::DAY] )) { + $str = $ruleValue[0] ?? StringFactory::$SP0; + $str .= $ruleValue[IcalInterface::DAY]; + self::addSubChild( $child, $ruleLabel, $str ); + } + else { + foreach( $ruleValue as $valuePart ) { + if( isset( $valuePart[IcalInterface::DAY] )) { + $str = $valuePart[0] ?? StringFactory::$SP0; + $str .= $valuePart[IcalInterface::DAY]; + self::addSubChild( $child, $ruleLabel, $str ); + } + else { + self::addSubChild( $child, $ruleLabel, $valuePart ); + } + } // end foreach + } + } + + /** + * Manage rstatus type + * + * @param SimpleXMLElement $child + * @param mixed $value + * @return void + * @throws Exception + */ + private static function addXMLchildForTypeRstatus( SimpleXMLElement $child, mixed $value ) : void + { + self::addSubChild( + $child, + self::$code, + StringFactory::numberFormat( $value[IcalInterface::STATCODE] ) + ); + self::addSubChild( $child, self::$description, htmlspecialchars( $value[IcalInterface::STATDESC] )); + if( isset( $value[IcalInterface::EXTDATA] )) { + self::addSubChild( $child, self::$data, htmlspecialchars( $value[IcalInterface::EXTDATA] )); + } + } + + /** + * Manage text type + * + * @param SimpleXMLElement $child + * @param string $type + * @param mixed $value + * @return void + * @throws Exception + */ + private static function addXMLchildForTypeText( SimpleXMLElement $child, string $type, mixed $value ) : void + { + if( ! is_array( $value )) { + $value = [ $value ]; + } + foreach( $value as $part ) { + self::addSubChild( $child, $type, htmlspecialchars( $part ) ); + } + } + + /** + * Manage utc_offset type + * + * @param SimpleXMLElement $child + * @param string $type + * @param mixed $value + * @return void + * @throws Exception + */ + private static function addXMLchildForTypeUtcOffset( SimpleXMLElement $child, string $type, mixed $value ) : void + { + if( DateIntervalFactory::hasPlusMinusPrefix( $value )) { + $str = $value[0]; + $value = substr( $value, 1 ); + } + else { + $str = StringFactory::$PLUS; + } + $str .= substr( $value, 0, 2 ) . + StringFactory::$COLON . substr( $value, 2, 2 ); + if( 4 < strlen( $value )) { + $str .= StringFactory::$COLON . substr( $value, 4 ); + } + self::addSubChild( $child, $type, $str ); + } + + /** + * Manage unknown and default type + * + * @param SimpleXMLElement $child + * @param mixed $value + * @return void + * @throws Exception + */ + private static function addXMLchildForTypeUnknowDefault( SimpleXMLElement $child, mixed $value ) : void + { + if( is_array( $value )) { + $value = implode( $value ); + } + self::addSubChild( $child, self::$unknown, htmlspecialchars( $value )); + } + + /** + * @param SimpleXMLElement $child + * @param string $name + * @param null|string $value + * @return SimpleXMLElement + * @throws Exception + */ + private static function addSubChild( SimpleXMLElement $child, string $name, ? string $value = null ) : SimpleXMLElement + { + $subChild = $child->addChild( $name, $value ); + if( null === $subChild ) { + throw new Exception( 'Can\'t add XML child ' . $name ); + } + return $subChild; + } +} diff --git a/vendor/kigkonsult/icalcreator/src/Xml/Parser.php b/vendor/kigkonsult/icalcreator/src/Xml/Parser.php new file mode 100644 index 0000000..7449cc8 --- /dev/null +++ b/vendor/kigkonsult/icalcreator/src/Xml/Parser.php @@ -0,0 +1,729 @@ + + * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved + * @link https://kigkonsult.se + * @license Subject matter of licence is the software iCalcreator. + * The above copyright, link, package and version notices, + * this licence notice and the invariant [rfc5545] PRODID result use + * as implemented and invoked in iCalcreator shall be included in + * all copies or substantial portions of the iCalcreator. + * + * iCalcreator is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * iCalcreator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with iCalcreator. If not, see . + */ +declare( strict_types = 1 ); +namespace Kigkonsult\Icalcreator\Xml; + +use Exception; +use Kigkonsult\Icalcreator\CalendarComponent; +use Kigkonsult\Icalcreator\IcalInterface; +use Kigkonsult\Icalcreator\Util\StringFactory; +use Kigkonsult\Icalcreator\Vcalendar; + +use function html_entity_decode; +use function in_array; +use function is_array; +use function sprintf; +use function str_replace; +use function str_starts_with; +use function stripos; +use function strlen; +use function strtolower; +use function strtoupper; +use function substr; +use function trim; +use function ucfirst; + +/** + * iCalcreator XML (rfc6321) parser class + * + * @since 2.41.88 2024-01-16 + */ +final class Parser extends XmlBase +{ + /** + * Parse (rfc6321) XML string into iCalcreator instance + * + * @param string $xmlStr + * @param null|string[] $iCalcfg Vcalendar config array (opt) + * @return Vcalendar|bool false on error + * @throws Exception + * @since 2.41.69 2022-10-04 + */ + public static function XML2iCal( string $xmlStr, ? array $iCalcfg = [] ) : Vcalendar | bool + { + static $CRLF = [ "\r\n", "\n\r", "\n", "\r" ]; + $xmlStr = str_replace( $CRLF, StringFactory::$SP0, $xmlStr ); + $xml = self::XMLgetTagContent1( $xmlStr, self::$Vcalendar, $endIx ); + $iCal = new Vcalendar( $iCalcfg ?? [] ); + if( false === self::XMLgetComps( $iCal, $xmlStr )) { + return false; + } + return $iCal; + } + + /** + * Parse (rfc6321) XML string into iCalcreator components + * + * @ param IcalInterface $iCal + * @param Vcalendar|CalendarComponent $iCal + * @param string $xml + * @return IcalInterface|bool false on error + * @since 2.41.69 2022-10-04 + */ + private static function XMLgetComps( Vcalendar|CalendarComponent $iCal, string $xml ) : IcalInterface | bool + { + static $PROPSTAGempty = ''; + static $PROPSTAGstart = ''; + static $COMPSTAGempty = ''; + static $COMPSTAGstart = ''; + static $NEW = 'new'; + static $ALLCOMPS = [ // all IcalBase::$CALCOMPS + IcalBase::$TZCOMPS + IcalInterface::AVAILABLE, + IcalInterface::DAYLIGHT, + IcalInterface::PARTICIPANT, + IcalInterface::STANDARD, + IcalInterface::VALARM, + IcalInterface::VAVAILABILITY, + IcalInterface::VEVENT, + IcalInterface::VFREEBUSY, + IcalInterface::VJOURNAL, + IcalInterface::VLOCATION, + IcalInterface::VRESOURCE, + IcalInterface::VTIMEZONE, + IcalInterface::VTODO, + ]; + $len = strlen( $xml ); + $sx = 0; + while( + ((( $sx + 12 ) < $len ) && + ! str_starts_with( substr( $xml, $sx ), $PROPSTAGstart ) && + ! str_starts_with( substr( $xml, $sx ), $COMPSTAGstart ) + ) && + ((( $sx + 13 ) < $len ) && + ! str_starts_with( substr( $xml, $sx ), $PROPSTAGempty ) && + ! str_starts_with( substr( $xml, $sx ), $COMPSTAGempty ))) { + ++$sx; + } // end while + if(( $sx + 11 ) >= $len ) { + return false; + } + if( str_starts_with( $xml, $PROPSTAGempty )) { + $pos = strlen( $PROPSTAGempty ); + $xml = substr( $xml, $pos ); + } + elseif( str_starts_with( substr( $xml, $sx ), $PROPSTAGstart )) { + $xml2 = self::XMLgetTagContent1( $xml, self::$properties, $endIx ); + self::XMLgetProps( $iCal, $xml2 ); + $xml = substr( $xml, $endIx ); + } + if( str_starts_with( $xml, $COMPSTAGempty )) { + $pos = strlen( $COMPSTAGempty ); + $xml = substr( $xml, $pos ); + } + elseif( str_starts_with( $xml, $COMPSTAGstart )) { + $xml = self::XMLgetTagContent1( $xml, self::$components, $endIx ); + } + while( ! empty( $xml )) { + $xml2 = self::XMLgetTagContent2( $xml, $tagName, $endIx ); + $compType = ucfirst( strtolower( $tagName )); + if( in_array( $compType, $ALLCOMPS, true )) { + $iCalComp = $iCal->{$NEW . $compType}(); + self::XMLgetComps( $iCalComp, $xml2 ); + } + $xml = substr( $xml, $endIx ); + } // end while( ! empty( $xml )) + return $iCal; + } + + /** + * Parse (rfc6321) XML into iCalcreator properties + * + * @param Vcalendar|CalendarComponent $iCalComp + * @param string $xml + * @return void + * @since 2.41.88 2024-01-16 + */ + private static function XMLgetProps( Vcalendar|CalendarComponent $iCalComp, string $xml ) : void + { + static $PARAMENDTAG = ''; + static $PARAMTAG = ''; + $endIx3 = strlen( $xml ) + 1; // i.e. init var as int + while( ! empty( $xml )) { + $xml2 = self::XMLgetTagContent2( $xml, $propName, $endIx ); + $propName = strtoupper( $propName ); + if( empty( $xml2 ) && ( StringFactory::$ZERO !== $xml2 )) { + self::XMLgetEmptyProp( $iCalComp, $propName ); + $xml = substr( $xml, $endIx ); + continue; + } // end if + $params = []; + if( str_starts_with( $xml2, $PARAMENDTAG )) { // no params + $xml2 = substr( $xml2, 13 ); + } + elseif( str_starts_with( $xml2, $PARAMTAG )) { + $xml3 = self::XMLgetTagContent1( $xml2, self::$PARAMETERS, $endIx2 ); + self::XMLgetPropParams( $xml3, $params, $endIx3 ); + $xml2 = substr( $xml2, $endIx2 ); + } // end elseif - parameters + $valueType = StringFactory::$SP0; + $value = ( ! empty( $xml2 ) || ( StringFactory::$ZERO === $xml2 )) + ? self::XMLgetTagContent2( $xml2, $valueType, $endIx3 ) + : StringFactory::$SP0; + match( $propName ) { // get/prep property value + IcalInterface::URL, IcalInterface::TZURL => + $value = html_entity_decode( $value ), + IcalInterface::EXDATE, IcalInterface::RDATE, IcalInterface::FREEBUSY => + $value = self::XMLgetRexFreeBProp( $propName, $xml2, $valueType, $params ), + IcalInterface::TZOFFSETTO, IcalInterface::TZOFFSETFROM => + $value = str_replace( StringFactory::$COLON, StringFactory::$SP0, $value ), + IcalInterface::GEO => + $value = self::XMLgetGeoProp( $xml2, $value ), + IcalInterface::EXRULE, IcalInterface::RRULE => + $value = self::XMLgetRexRuleProp( substr( $xml2, $endIx3 ), [ $valueType => $value ] ), + IcalInterface::REQUEST_STATUS => + $value = self::XMLgetReqStatProp( $xml2 ), + IcalInterface::STRUCTURED_DATA => + self::XMLStrucDataProp( $valueType, $params ), + IcalInterface::STYLED_DESCRIPTION => + self::XMLStyldDescrProp( $valueType, $params ), + default => + $value = self::XMLgetDefaultProp( $valueType, $value, $propName, $params ) + }; // end match( $propName ) + self::XMLsetIcalProp( $iCalComp, $propName, $value, $params ); + $xml = substr( $xml, $endIx ); + } // end while( ! empty( $xml )) + } + + /** + * Manage an empty property + * + * @param Vcalendar|CalendarComponent $iCalComp + * @param string $propName + * @return void + */ + private static function XMLgetEmptyProp( Vcalendar|CalendarComponent $iCalComp, string $propName ) : void + { + if( StringFactory::isXprefixed( $propName )) { + $iCalComp->setXprop( $propName ); + return; + } + $method = StringFactory::getSetMethodName( $propName ); + $iCalComp->{$method}(); + } + + + /** + * Manage prop params + * + * @param string $xml3 + * @param string[]|string[][] $params + * @param int|null $endIx + * @return void + * @since 2.41.88 2024-01-16 + */ + private static function XMLgetPropParams( string $xml3, array & $params, ? int & $endIx = null ) : void + { + static $ATTENDEEPARKEYS = [ + IcalInterface::DELEGATED_FROM, + IcalInterface::DELEGATED_TO, + IcalInterface::MEMBER + ]; + $endIx3 = 0; + while( ! empty( $xml3 )) { + $xml4 = self::XMLgetTagContent2( $xml3, $paramKey, $endIx3 ); + $paramKey = strtoupper( $paramKey ); + if( in_array( $paramKey, $ATTENDEEPARKEYS, true )) { + while( ! empty( $xml4 )) { + $paramValue = self::XMLgetTagContent1( $xml4, self::$cal_address, $endIx4 ); + if( ! isset( $params[$paramKey] )) { + $params[$paramKey] = [ $paramValue ]; + } + else { + $params[$paramKey][] = $paramValue; + } + $xml4 = substr( $xml4, $endIx4 ); + } // end while + } // end if( in_array( $paramKey, $ATTENDEEPARKEYS )) + else { + $pType = StringFactory::$SP0; // skip parameter valueType + $paramValue = html_entity_decode( + self::XMLgetTagContent2( $xml4, $pType, $endIx4 ) + ); + if( ! isset( $params[$paramKey] )) { + $params[$paramKey] = $paramValue; + } + else { + $params[$paramKey] .= StringFactory::$COMMA . $paramValue; + } + } + $xml3 = substr( $xml3, $endIx3 ); + } // end while + } + + /** + * Manage Rdate prop + * + * @param string $propName + * @param string $xml2 + * @param string $valueType + * @param string[] $params + * @return string[] + * @since 2.41.88 2024-01-16 + */ + private static function XMLgetRexFreeBProp( + string $propName, + string $xml2, + string $valueType, + array & $params + ) : array + { + static $REXDATE = [ IcalInterface::EXDATE, IcalInterface::RDATE ]; + if( in_array( $propName, $REXDATE ) && + ( self::$period !== $valueType )) { + return self::XMLgetRdateProp( $xml2, $valueType, $params ); + } + if( IcalInterface::FREEBUSY !== $propName ) { + $params[ IcalInterface::VALUE ] = IcalInterface::PERIOD; + } + return self::XMLgetPeriodProp( $xml2 ); + } + + /** + * Manage Rdate prop + * + * @param string $xml2 + * @param string $valueType + * @param string[] $params + * @return string[] + * @since 2.41.88 2024-01-16 + */ + private static function XMLgetRdateProp( string $xml2, string $valueType, array & $params ) : array + { + static $DATETAGST = ' $value, + IcalInterface::LONGITUDE => self::XMLgetTagContent1( + substr( $xml2, $endIx3 ), + IcalInterface::LONGITUDE, + $endIx3 + ) + ]; + } + + /** + * Manage ExRule/RexRule prop + * + * @param string $xml2 + * @param string[] $tValue + * $valueType => $value + * @return string[] + * @since 2.41.88 2024-01-16 + */ + private static function XMLgetRexRuleProp( string $xml2, array $tValue ) : array + { + $valueType = StringFactory::$SP0; + while( ! empty( $xml2 )) { + $t = self::XMLgetTagContent2( $xml2, $valueType, $endIx4 ); + $valueType = strtoupper( $valueType ); + switch( $valueType ) { + case IcalInterface::FREQ : // fall through + case IcalInterface::COUNT : // fall through + case IcalInterface::INTERVAL : // fall through + case IcalInterface::RSCALE : // fall through + case IcalInterface::SKIP : // fall through + case IcalInterface::UNTIL : // fall through + case IcalInterface::WKST : + $tValue[$valueType] = $t; + break; + case IcalInterface::BYDAY : + self::assureElementIsArray( $tValue, IcalInterface::BYDAY ); + $tLen = strlen( $t ); + if( 2 === $tLen ) { + self::addElementValue( + $tValue, + IcalInterface::BYDAY, + [ IcalInterface::DAY => $t ] + ); + } + else { + $day = substr( $t, -2 ); + $key = substr( $t, 0, ( $tLen - 2 )); + self::addElementValue( + $tValue, + IcalInterface::BYDAY, + [ $key, IcalInterface::DAY => $day ] + ); + } + break; + default: + self::assureElementIsArray( $tValue, $valueType ); + self::addElementValue( $tValue, $valueType, $t ); + break; + } // end switch + $xml2 = substr( $xml2, $endIx4 ); + } // end while + return $tValue; + } + + /** + * Manage Req-Stat p + * + * @param string $xml2 + * @return string[] + * @since 2.41.88 2024-01-16 + */ + private static function XMLgetReqStatProp( string $xml2 ) : array + { + $value = [ + self::$code => null, + self::$description => null, + self::$data => null + ]; + while( ! empty( $xml2 )) { + $t = html_entity_decode( + self::XMLgetTagContent2( $xml2, $valueType, $endIx4 ) + ); + $value[$valueType] = $t; + $xml2 = substr( $xml2, $endIx4 ); + } // end while + return $value; + } + + /** + * Manage STRUCTURED_DATA prop + * + * @param string $valueType + * @param mixed[] $params + * @return void + * @since 2.41.88 2024-01-16 + */ + private static function XMLStrucDataProp( string $valueType, array & $params ) : void + { + $params[IcalInterface::VALUE] = match( $valueType ) { + self::$binary => IcalInterface::BINARY, + self::$text => IcalInterface::TEXT, + self::$uri => IcalInterface::URI, + }; + } + + /** + * Manage STYLED_DESCRIPTION prop + * + * @param string $valueType + * @param mixed[] $params + * @return void + * @since 2.41.88 2024-01-16 + */ + private static function XMLStyldDescrProp( string $valueType, array & $params ) : void + { + $params[IcalInterface::VALUE] = match( $valueType ) { + self::$text => IcalInterface::TEXT, + self::$uri => IcalInterface::URI + }; + } + + /** + * Manage whatever left prop + * + * @param string $valueType + * @param string $value + * @param string $propName + * @param string[] $params + * @return string + * @since 2.41.88 2024-01-16 + */ + private static function XMLgetDefaultProp( + string $valueType, + string $value, + string $propName, + array & $params + ) : string + { + static $ATTSRC = [ IcalInterface::ATTACH, IcalInterface::SOURCE ]; + switch( $valueType ) { + case self::$uri : + $value = html_entity_decode( $value ); + if( in_array( $propName, $ATTSRC, true )) { + break; + } + $params[IcalInterface::VALUE] = IcalInterface::URI; + break; + case self::$binary : + $params[IcalInterface::VALUE] = IcalInterface::BINARY; + break; + case self::$date : + $params[IcalInterface::VALUE] = IcalInterface::DATE; + break; + case self::$date_time : + $params[IcalInterface::VALUE] = IcalInterface::DATE_TIME; + break; + case self::$text : + // fall through + case self::$unknown : + $value = html_entity_decode( $value ); + break; + default : + if( StringFactory::isXprefixed( $propName ) && + ( self::$unknown !== strtolower( $valueType ))) { + $params[IcalInterface::VALUE] = strtoupper( $valueType ); + } + break; + } // end switch + return $value; + } + + /** + * @param CalendarComponent|Vcalendar $iCalComp + * @param string $propName + * @param null|string|array $value + * @param array $params + * @return void + */ + private static function XMLsetIcalProp( + CalendarComponent|Vcalendar $iCalComp, + string $propName, + null|string|array $value, + array $params + ) : void + { + static $VERSIONPRODID = [ IcalInterface::VERSION, IcalInterface::PRODID ]; + static $REXRULE = [ IcalInterface::EXRULE, IcalInterface::RRULE ]; + $method = StringFactory::getSetMethodName( $propName ); + switch( true ) { + case ( in_array( $propName, $VERSIONPRODID, true )) : + break; + case ( StringFactory::isXprefixed( $propName )) : + $iCalComp->setXprop( $propName, $value, $params ); + break; + case ( in_array( $propName, $REXRULE, true ) && + isset( $value[self::$recur] ) && empty( $value[self::$recur] )) : + $iCalComp->{$method}(); // empty rexRule + break; + case ( IcalInterface::FREEBUSY === $propName ) : + $fbtype = $params[IcalInterface::FBTYPE] ?? null; + unset( $params[IcalInterface::FBTYPE] ); + $iCalComp->{$method}( $fbtype, $value, $params ); + break; + case ( IcalInterface::GEO === $propName ) : + $input = $iCalComp::extractGeoLatLong( $value ); + $iCalComp->{$method}( $input[0], $input[1], ( empty( $input[0] ) ? [] : $params )); + break; + case ( IcalInterface::REQUEST_STATUS === $propName ) : + $input = $iCalComp::extractRequeststatus( $value ); + $iCalComp->{$method}( $input[0], $input[1], $input[2], ( empty( $input[1] ) ? [] : $params )); + break; + default : + if( empty( $value ) && ( is_array( $value ) || ( StringFactory::$ZERO > $value ))) { + $value = null; + } + $iCalComp->{$method}( $value, $params ); + break; + } // end switch + } + + /** + * @param array $array + * @param string $key + */ + private static function assureElementIsArray( array & $array, string $key ) : void + { + if( ! isset( $array[$key] )) { + $array[$key] = []; + } + } + + /** + * @param array $array + * @param string $key + * @param int|string|array $value + */ + private static function addElementValue( array & $array, string $key, int|string|array $value ) : void + { + $array[$key][] = $value; + } + + /** + * Fetch a specific XML tag content + * + * @param string $xml + * @param string $tagName + * @param null|int $endIx + * @return string + * @since 2.41.69 2022-10-04 + */ + private static function XMLgetTagContent1( string $xml, string $tagName, ? int & $endIx = 0 ) : string + { + static $FMT0 = '<%s>'; + static $FMT1 = '<%s />'; + static $FMT2 = '<%s/>'; + static $FMT3 = ''; + $tagName = strtolower( $tagName ); + $strLen = strlen( $tagName ); + $xmlLen = strlen( $xml ); + $sx1 = 0; + while( $sx1 < $xmlLen ) { + if((( $sx1 + $strLen + 1 ) < $xmlLen ) && // start tag + ( sprintf( $FMT0, $tagName ) === strtolower( substr( $xml, $sx1, ( $strLen + 2 )))) + ) { + break; + } + if((( $sx1 + $strLen + 3 ) < $xmlLen ) && // empty tag1 + ( sprintf( $FMT1, $tagName ) === strtolower( substr( $xml, $sx1, ( $strLen + 4 )))) + ) { + $endIx = $strLen + 5; + return StringFactory::$SP0; // empty tag + } + if((( $sx1 + $strLen + 2 ) < $xmlLen ) && // empty tag2 + ( sprintf( $FMT2, $tagName ) === strtolower( substr( $xml, $sx1, ( $strLen + 3 )))) + ) { + $endIx = $strLen + 4; + return StringFactory::$SP0; // empty tag + } + ++$sx1; + } // end while... + if( ! isset( $xml[$sx1] )) { + $endIx = ( empty( $sx1 )) ? 0 : $sx1 - 1; // ?? + return StringFactory::$SP0; + } + $endTag = sprintf( $FMT3, $tagName ); + if( false === ( $pos = stripos( $xml, $endTag ))) { // missing end tag?? + $endIx = $xmlLen + 1; + return StringFactory::$SP0; + } + $endIx = $pos + $strLen + 3; + $start = $sx1 + $strLen + 2; + $len = $pos - $sx1 - 2 - $strLen; + return substr( $xml, $start, $len ); + } + + /** + * Fetch next (unknown) XML tagname AND content + * + * @param string $xml + * @param string|null $tagName + * @param int|null $endIx + * @return string + * @since 2.41.69 2022-10-04 + */ + private static function XMLgetTagContent2( string $xml, ? string & $tagName = null, ? int & $endIx = null ) : string + { + static $LT = '<'; + static $CMTSTART = '