Giter VIP home page Giter VIP logo

ical's Introduction

πŸ“… eluceo β€” iCal 2

Continuous Integration codecov Psalm coverage License Latest Stable Version Monthly Downloads Infection MSI

This package offers an abstraction layer for creating iCalendars files. By using this PHP package, you can create *.ics files without the knowledge of the underling format. The output itself will follow RFC 5545 as good as possible.

Navigate through the project

Installation

You can install this package by using Composer, running the following command:

composer require eluceo/ical

Version / Upgrade

The initial version was released back in 2012. The version 2 of this package is a complete rewrite of the package and is not compatible to older version. Please see the upgrade guide if you want to migrate from version 0.* to 2.*. If you just start using this package, you should install version 2.

Version PHP Version
2.* 7.4 - 8.3
0.16.* 7.0 - 8.2
0.11.* 5.3.0 - 7.4

Documentation

Visit ical.poerschke.nrw for complete documentation.

Usage

The classes within this package are grouped into two namespaces:

  • The Domain contains the information about the events.
  • The Presentation contains the transformation from Domain into a *.ics file.

To create a calendar, the first step will be to create the corresponding domain objects. Then these objects can be transformed into a iCalendar PHP representation, which can be cast to string.

Empty event

In this very basic example, that renders an empty event. You will learn how to create an event domain object, how to add it to a calendar and how to transform it to a iCalendar component.

1. Create an event domain entity

$event = new \Eluceo\iCal\Domain\Entity\Event();

2. Create a calendar domain entity

$calendar = new \Eluceo\iCal\Domain\Entity\Calendar([$event]);

3. Transform calendar domain object into a presentation object

$iCalendarComponent = (new \Eluceo\iCal\Presentation\Factory\CalendarFactory())->createCalendar($calendar);

4. a) Save to file

file_put_contents('calendar.ics', (string) $iCalendarComponent);

4. b) Send via HTTP

header('Content-Type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename="cal.ics"');

echo $iCalendarComponent;

Full example

The following example will create a single day event with a summary and a description. More examples can be found in the examples/ folder.

<?php

require_once __DIR__ . '/../vendor/autoload.php';

// 1. Create Event domain entity
$event = (new Eluceo\iCal\Domain\Entity\Event())
    ->setSummary('Christmas Eve')
    ->setDescription('Lorem Ipsum Dolor...')
    ->setOccurrence(
        new Eluceo\iCal\Domain\ValueObject\SingleDay(
            new Eluceo\iCal\Domain\ValueObject\Date(
                \DateTimeImmutable::createFromFormat('Y-m-d', '2030-12-24')
            )
        )
    );

// 2. Create Calendar domain entity
$calendar = new Eluceo\iCal\Domain\Entity\Calendar([$event]);

// 3. Transform domain entity into an iCalendar component
$componentFactory = new Eluceo\iCal\Presentation\Factory\CalendarFactory();
$calendarComponent = $componentFactory->createCalendar($calendar);

// 4. Set headers
header('Content-Type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename="cal.ics"');

// 5. Output
echo $calendarComponent;

License

This package is released under the MIT license.

ical's People

Contributors

ajf58 avatar brutuscat avatar buggedcom avatar cachan avatar cmbuckley avatar cmfcmf avatar davesouthey avatar dependabot-preview[bot] avatar dependabot[bot] avatar edrush avatar elceka avatar foaly-nr1 avatar gared avatar hanzi avatar jrjohnson avatar ker0x avatar markuspoerschke avatar markuspoerschke-bot avatar mlebkowski avatar navarr avatar nielsjanssen avatar puhr-mde avatar ravishtiwari avatar raymondelooff avatar rvanlaak avatar scentyoo avatar sebastian-alfers avatar sgehrig avatar shyx0rmz avatar westy92 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ical's Issues

Description doesn't allow new lines

If I call Event->setDescription() with "\n" (so that the new line is rendered), then the description field ends up with a new line being inserted and appearing like this:

DESCRIPTION:First line of description
Second line of description

When this is imported into an application, then only the first line of the description appears.

If I call the same method with '\n' (a literal \n) then the description field ends up like this:

DESCRIPTION:First line of description\\nSecond line of description

When this is imported it results in a literal \n appearing.

What you want is this appearing in the file:

DESCRIPTION:First line of description\nSecond line of description

From digging around in the code it looks like you can swap this call in Eluceo\iCal\Property\Event\Description:

    public function getEscapedValue()
    {
        return PropertyValueUtil::escapeValueAllowNewLine((string) $this->value);
    }

with:

    public function getEscapedValue()
    {
        return PropertyValueUtil::escapeValue((string) $this->value);
    }

That appears to work, although I haven't tried running the tests

Empty events after cancelling

Hello and thank you for this great extension!

I'm having an issue with cancelling an event, which is creation of empty event.

For example I have downloaded an .ics file and added it to my calendar: http://bit.ly/2kZhUCf

Then I'm creating event cancellation file with this code:

<?php
    /**
     * @param int $id
     * @return \Eluceo\iCal\Component\Event
     */
    public static function cancelICal(int $id): \Eluceo\iCal\Component\Event
    {
        return (new \Eluceo\iCal\Component\Event($id))
            ->setCancelled(true);
    }

And I get following result: http://bit.ly/2lCho0D

When I dig into generated .ics file, I see that it contains todays date:

BEGIN:VCALENDAR
VERSION:2.0
PRODID:mywebsite.com
X-PUBLISHED-TTL:P1W
BEGIN:VEVENT
UID:16927
DTSTART;VALUE=DATE:20170220
SEQUENCE:0
TRANSP:OPAQUE
CLASS:PUBLIC
STATUS:CANCELLED
X-MICROSOFT-CDO-ALLDAYEVENT:TRUE
DTSTAMP:20170220T163032Z
END:VEVENT
END:VCALENDAR

How can I override this behavior? Thanks in advance!

Consider implementing X-MICROSOFT-CDO-BUSYSTATUS

We sometimes need to specify out-of-office (X-MICROSOFT-CDO-BUSYSTATUS:OOF) for the status, but this library doesn't support it at the moment. I don't know if this can be implemented as part of $event->setStatus or if it would need to be a separate new property. If this can't be implemented, is there a way to set a custom property manually?

Events list?

Is there any list with all events or just the examples?

Write more detailed documentation

A lot of aspects of this library aren’t documented very well.

  • Currently the documentation is only a rough summary of the basic usage: creating simple ics files.
  • There should be a more detailed explanation.
  • Also the examples need more explanation.
  • Maybe generated PHPDoc can be added.
  • Full aspects of this issue are tbd.
  • Some methods are confusing like #83 (comment) maybe also the API needs some change (not part of this issue of course)
  • Some feature are not documented at all:

TimeZone in DTSTART break Subscribing when including Time

Hello,

Thanks for making this package

The TimeStamp format for DTSTART and DTEND includes the TimeZone in the middle of the string. Like this:

DTSTART:20100827PDT130000

This causes Mac OSX Calendar and BusyCal to fail

Here is the error from the log
9/19/12 1:15:02.322 PM CalendarAgent[200]: *** WARNING Invalid component, discarding: Error Domain=com.apple.iCalendar Code=1000 "DTSTART is required for VEVENT." UserInfo=0x7fe43accbff0 {NSLocalizedDescription=DTSTART is required for VEVENT.}
nil description

I quickly hacked this out to get rid of the timezone in the TimeStamps

This is in the Event.php file

private function getDateFormat($noTime = false)
    {
        // this doesnt' work
        //return $noTime ? 'Ymd' : 'YmdTHi00';

        //this does
        return $noTime ? 'Ymd' : 'Ymd\THis';
    }

However this is probably not the best. It probably needs proper TimeZone Support. If I have time I will try to work that out.

Thanks again

Todd

ORGANIZER does not support property parameters

ORGANIZER, as ATTENDEE, supports parameters according to RFC2445. At the moment you can only set the value with $vEvent->setOrganizer('mailto:[email protected]'), which is rendered as ORGANIZER:mailto:[email protected].

It would be nice if we could set parameters too, in a similar way as we for for attendees:

$vEvent->setOrganizer('mailto:[email protected]', ['CN' => 'Giulio Troccoli']);

which would be rendered as

ORGANIZER;CN=Giulio Troccoli:mailto:[email protected]

Generated ical not importing events in outlook

Reference to this issue on stackoverflow: http://stackoverflow.com/questions/43249331/outlook-web-app-is-not-importing-events-from-my-generated-icalendar

When a student wants to subscribe to his or her calender, we generate an URL which can be filled into Google Calender and Outlook. Except the last mentioned outlook it isn't importing any events.

Example of how our generated ICS looks like. This contains 1 event with the description of 'test'.

BEGIN:VCALENDAR 
VERSION:2.0 
PRODID:www.onderwijsonline.nl 
X-PUBLISHED-TTL:PT15M 
BEGIN:VEVENT 
UID:58e5f21fc2551 
DTSTART;TZID=Europe/Amsterdam:20170406T090000 
SEQUENCE:0 
TRANSP:OPAQUE DTEND;TZID=Europe/Amsterdam:20170406T140000 URL:http://oo.dev/calendar/event/420 
SUMMARY:Test 
CLASS:PUBLIC 
DTSTAMP:20170406T094535Z 
END:VEVENT 
END:VCALENDAR

The script that calls the package to generate this:

public function getIcal($token = null)
    {
        $user = $this->userRepository->getByToken($token);

        $vCalendar = new \Eluceo\iCal\Component\Calendar('www.onderwijsonline.nl');
        $vCalendar->setPublishedTTL('PT15M');

        if (!is_null($user)) {

            /**
             * Calendar events
             */
            $events = $this->calendarRepository->getEventsForUser($user->id, Carbon::now()->subWeeks(2), Carbon::now()->addWeeks(6));
            foreach ($events as $event) {

                $vEvent = new \Eluceo\iCal\Component\Event();

                $vEvent
                    ->setUseTimezone(true)
                    ->setUseUtc(false)
                    ->setDtStart(Carbon::parse($event['start']))
                    ->setDtEnd(Carbon::parse($event['end']))
                    ->setNoTime(($event['allDay'] == 1 ? true : false))
                    ->setUrl($event['href'])
                    ->setDescription($event['description'])
                    ->setSummary($event['title']);

                $vCalendar->addComponent($vEvent);
            }

            /**
             * Project events
             */
            $events = $this->calendarRepository->getEventsForProjects($user->id, null, null);

            foreach ($events as $event) {
                $vEvent = new \Eluceo\iCal\Component\Event();

                $vEvent
                    ->setUseTimezone(true)
                    ->setUseUtc(false)
                    ->setDtStart(Carbon::parse($event['start']))
                    ->setDtEnd(Carbon::parse($event['end']))
                    ->setNoTime(($event['allDay'] == 1 ? true : false))
                    ->setUrl($event['href'])
                    ->setSummary($event['title']);

                $vCalendar->addComponent($vEvent);
            }

            /**
             * Timetable events
             */
            $events = $this->calendarRepository->getEventsForTimetables($user->id, Carbon::now()->subWeeks(2), Carbon::now()->addWeeks(6));
            foreach ($events as $event) {
                $vEvent = new \Eluceo\iCal\Component\Event();

                $vEvent
                    ->setUseTimezone(true)
                    ->setUseUtc(false)
                    ->setDtStart(Carbon::parse($event['start']))
                    ->setDtEnd(Carbon::parse($event['end']))
                    ->setNoTime(($event['allDay'] == 1 ? true : false))
                    ->setSummary($event['title']);

                $vCalendar->addComponent($vEvent);
            }
        }

        header('Content-Type: text/calendar; charset=utf-8');
        header('Content-Disposition: inline; filename=onderwijsonline.ics');

        return $vCalendar->render();
    }

As I've mentioned above, this exact setup works fine for Google Calendar, but is not for outlook.

Create new tagged release

Hi there, would it be possible to get a new tagged release? It seems there are a bunch of changes from the 0.9 release and what's on master. Thanks!

Interest for a ICS parser ?

I am looking for an ICS lib that would allow me to read and write ICS files. Out of all projects I looked at, this one is definitely the most modern one and promising. But it unfortunately lacks a parser for my need. So the question is, if I was to implement a parser and submit a PR, would you accept it ? Or is it out of scope for this project ?

I usually quite like the idea to have model classes, and then separate Writer(s) and Reader(s) classes. This could allow, in the far future, for other writers (ESS ?).

But in this project the writer is "mixed" with the model. So the easiest way would probably be to add the missing getters for all Eventproperties (and similar classes). And then implement Component::parse() for all components.

Some projects that could be used as inspiration for implementing the parser could be:

What do you think about that ? Is it worth investigating deeper ?

How can I get setTitle

Hi

I'd like to get Title. I don't see the method setTitle();
How can I get that?

Thanks

Last day not shown in calendar?

Hi,

my iCal is delivered like this:

BEGIN:VEVENT
UID:5916c2b4da9d7
DTSTART;TZID=Europe/Berlin;VALUE=DATE:20170630
SEQUENCE:0
TRANSP:OPAQUE
DTEND;TZID=Europe/Berlin;VALUE=DATE:20170702
LOCATION:My Location
SUMMARY:My Summary
CLASS:PUBLIC
X-MICROSOFT-CDO-ALLDAYEVENT:TRUE
DTSTAMP:20170513T102420Z
END:VEVENT

The problem is, that my calendar shows the event from 06/30/2017 to 07/01/2017 instead of 07/02/2017. Why does the last day is missing or what did I wrong?

Thank you,
Marc

X-ALT-DESC

Hi,

Great library.

Is it possible to set the X-ALT-DESC property - if so how?

Or

How do I stop the description field being parsed... Some text comes out blue, some the font size has increased.

Thanks

Add possibility to add custom calendar properties

As far as I have seen in the code it is not possible to add custom properties, right?
Is there any reason for that? Maybe it was your intention to only support the properties defined by the RFC?

There are several already existing properties one might use (e.g. X-ALT-DESC, ...) or even custom properties only some clients may interpret (e.g. needed for a customer application).
Wouldn't it be helpful to add some kind of setCustomProperties()/addCustomProperty() functionality?

For now I have to extend your Component (e.g. Event) or manipulate the set of properties created by buildPropertyBag()?
It would be handy to be able to add such properties with your lib natively.

Is there a way to change sync frequency?

I have imported the cal generated by this package to outlook and it says that it will sync once in 168 hours, due to the limit set by the calendar provider. Is there a way to change this ?

Add option to set rrule from string

I have all my rrules stored as strings (like FREQ=WEEKLY;INTERVAL=1;COUNT=30). I would like to directly pass that string to the Eluceo/iCal/Component/Event.
I tried to use $vEvent->setRecurrenceRule($myRRule);, but it only accepts a RecurrenceRule object. The RecurrenceRule object, however, has no method to set the rrule from string. So I basically have to parse my stored rrules and then call the setBy* methods on the RecurrenceRule object.

I suggest to either

  • make setRecurrenceRule accept a string as well.
  • add a setFromString method to RecurrenceRule.
  • add a setRecurrenceRuleString method to the event class.

Thank you for this cool library πŸ˜„ πŸ’―

Problem with GEO property when importing into Google Calendar

It seems as if the Google Calendar does not support the GEO property that was added with commit 7a3751f (this is also addressed in pull request #66). Importing an event with a GEO property fails in Google Calendar.

There should be an option to disable the GEO property because setting the geo location works perfectly for iOS and Mac using the X-APPLE-STRUCTURED-LOCATION property.

Long DESCRIPTION is folding wrong - method fold

I am getting results like the following from long descriptions.

DESCRIPTION:Description keeps on going and going and going and going and go

ing and going and going and going and going and going and going and goi
ng
and going and going and going and going and going and going and goin
g and
going and going and going and going and going and going and going
and goin
g and going and going and going and going and going and going
and going an
d going and going and going and going

Apple Calendar crashes upon import/subscription

Apple Calendar crashes when importing or subscribing to a vCal created with this package... at least on the most recent versions of OS X.

It looks like it has to do with a missing entry called X-APPLE-CALENDAR-COLOR

Provide a ComponentInterface

In my application i already have event objects. Now when I add my Events into an Calendar I need a foreach loop and create an Eluceo\iCal\Component\Event and translate all data.

Better: Provide an interface that my Event class can implement so I can pass them directly into the calender.

iCal as Symfony2 bundle with storable entities?

Hi,

I'm searching for an event library to include in a Symfony2 application. I'd like to store events in a database and be able to deliver them in iCalendar format - your package looks pretty good for this, right? Have there ever been thoughts to deliver it as a Symfony bundle?
I'm thinking about doing so, to then add database mappings to your code to manage events in a database, while not messing up your code too much - what do you mean? Or do you know of existing implementations for that?

Best regards!

Add support for ATTACH in Events

attach is the way of thunderbird to add multiple webpages or links to documents to an event.

3.1.3.  Binary Content

   Binary content information in an iCalendar object SHOULD be
   referenced using a URI within a property value.  That is, the binary
   content information SHOULD be placed in an external MIME entity that
   can be referenced by a URI from within the iCalendar object.  In
   applications where this is not feasible, binary content information
   can be included within an iCalendar object, but only after first
   encoding it into text using the "BASE64" encoding method defined in
   [RFC4648].  Inline binary content SHOULD only be used in applications
   whose special circumstances demand that an iCalendar object be
   expressed as a single entity.  A property containing inline binary
   content information MUST specify the "ENCODING" property parameter.
   Binary content information placed external to the iCalendar object
   MUST be referenced by a uniform resource identifier (URI).

   The following example specifies an "ATTACH" property that references
   an attachment external to the iCalendar object with a URI reference:

     ATTACH:http://example.com/public/quarterly-report.doc

Version 0.11.2 uses PHP 7 features and breaks BC with PHP < 7

The Eluceo\iCal\Property\Event\Geo class uses PHP 7 scalar type hints and therefore breaks BC with PHP < 7. It should be compatible with PHP >= 5.3.0 as stated in composer.json.

If PHP 7 is a strict requirement now, this version should be a new major version to follow semantic versioning IMHO.

Fatal Compile Error: Default value for parameters with a class type hint can only be NULL

Support for time zone ID prefix

Both rfc2445 and rfc5545 define an optional '/' prefix for the time zone. Since the Eluceo\iCal\Util\DateUtil class is pulling the time zone out of the DateTime object there's no way to set the prefix.

Add Attendees

Hi,

How i can add Attendees to ics. can you give the the code?

Thanks,

No examples for VALARM in README.md or iCal/examples/

The README.md file says at the top that VALARM components are supported, but there are no examples in the main part of the README.md and no examples in the iCal/examples/exampleN.php files.

Would anyone object if I were to write some text for README.md and/or add a VALARM component to one of the example files, and put in a merge request?

Event::setLocation fails on PHP 5.x

More precisely Geo class is PHP 7 compliant (uses scalar type hints).

There is no unit tests that covers this class so the they always passes

Create beta release tag with version

Your Project using by many users, but if they want to more stability, he's need to provide some version, that have the same API without critical changes.

Currently your Project is ready to use in Production needs, but 'dev-master' in composer.json it's bad idea.

setRecurrenceRuleAsString() ?

Hey !
First of all, nice work, very usefull ! :)

I think it could be nice to implement a setRecurrenceRuleAsString() function for those (like me :D) who has already the RRULE in string format.

I'll try to PR something, i'm not really familiar with this.

Regards,

URL value types should not be escaped

In version 0.9.0, URL and CAL-ADDRESS value types are treated like ordinary string values and escaped like them. Instead, they should not be escaped.

Property values with this value type MUST follow the generic URI
syntax defined in [RFC3986].
...
No additional content value encoding (i.e., BACKSLASH character
encoding, see Section 3.3.11) is defined for this value type.

Fixing this bug would be useful if someone wants to add an attendee to an event that does not have an email address. 'mailto:;' could be supplied for that.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.