Jump to content

ICS Generator


thausmann
 Share

Recommended Posts

The module can generate basic ICS calendar strings and files.

Usage Example:

$icsgen = wire()->modules->IcsGenerator;

// set properties
$icsgen->setArray(array(
  'date' => new \DateTime('2033-12-24 12:00'),
  'dateEnd' => new \DateTime('2033-12-24 13:00'),
  'summary' => 'Event title',
  'description' => 'Event description',
));

// get path to a temporary .ics file
// (using wire()->files->tempDir)
$icspath = $icsgen->getFile();

// send email with ics file
$mail = wireMail();
$mail->attachment($icspath, 'calendar.ics');
$mail->to($user->email);
$mail->subject('ICS Demo');
$mail->body('This is a ICS demo.');
$numSent = $mail->send();

For more infos see GitHub Readme or Modules Page. If you experience reproducable issues please open a GitHub issue.

  • Like 17
  • Thanks 2
Link to comment
Share on other sites

  • 6 months later...

Hi!
This is exactly what I need for a project I am working on.
But the module is not generating any files for me. Maybe I am doing something wrong?

Here is my code (testet locally on laravel valet and on a shared hosting server):

function icsLink() {
  $icsgen = wire()->modules->IcsGenerator;

  // set single properties (date strings)
  $icsgen->setArray(array(
    'date' => '2033-12-24 12:00',
    'dateEnd' => '2033-12-24 14:00',
    'summary' => 'Event title',
    'description' => 'Event description',
  ));

  $icsPath = $icsgen->getFile();

  $out = '<a href="' . $icsPath . '">Merken</a>';

  return $out;
}

The function returns the link successfully, but when I click the link I get a 404. While the link points to a file (site/assets/cache/WireTempDir/.icsgenerator/0/ics-1663226011-413791867.ics), it seems like the file is never created. Any ideas?

Link to comment
Share on other sites

Hey @jploch,

oh yes, getFile() only creates temporary files, they are deleted automatically when ProcessWire is done with the request. That may sounds weird, but my use case was to send ICS via E-Mail. 

To permanently store the file somewhere, I could imagine something like this:

// write ICS to a custom file
// https://processwire.com/api/ref/wire-file-tools/file-put-contents/
$str = $icsgen->getString();
$files->filePutContents('/my/server/path/event.ics', $str);

or

// add the temporary file to a file field (field named "ics_files")
// https://processwire.com/talk/topic/15928-adding-a-file-to-pagefiles-and-saving-to-database/
$path = $icsgen->getFile();
$page->of(false);
$page->ics_files->add($path);
$page->save('ics_files');

Both untested, let me know if this works.

  • Like 2
Link to comment
Share on other sites

@thausmann Thanks for your quick reply! 

This was very helpful! It seems like filePutContents works great, but you have to give it the full path:

    <?php
	//create ics file
    $icsgen = wire()->modules->IcsGenerator;
    $icsgen->set('date', '2033-12-24 12:00');
    $icsgen->set('dateEnd', '2033-12-24 14:00');
    $icsFileContent = $icsgen->getString();
    $icsFilePath = wire()->config->paths->assets.'files/'.$page->id.'/event.ics'; // use full path to create the file
    $icsFileUrl = wire()->config->urls->assets.'files/'.$page->id.'/event.ics'; // use relativ url to set the link target
    wire()->files->filePutContents($icsFilePath, $icsFileContent);
	?>
	
	<!-- Link to file -->
	<a href="<?= $icsFileUrl ?>">ICS File</a>

 

  • Like 3
Link to comment
Share on other sites

  • 3 months later...

@thausmann I can understand your reasoning and for individual dates that is fine.

But I have in a nonprofit association only the issue that until now just the complete events are output in a list and in addition again all dates are maintained in a Google calendar. The whole thing is always double work and leads to great joy for the people who are allowed to maintain it ...

Therefore I wanted to replace the Google calendar and not only create an output on the homepage from the data in Processwire but also offer a *.ics file.

With the "LAST-MODIFIED:" Specification (which I fill via the modified date of PW) the whole thing would then even still updateable!

Concerning the problems with Outlook I agree with you, this is not quite trivial but I solved it in such a way that a) I wanted a separate calendar in Outlook explicitly and b) I simply put a small instruction on the homepage, how one must proceed with Outlook integration.

Instructions for Outlook:
1. mark one of the links from above (ATTENTION please don't click on the link, otherwise the calendar will be opened in Outlook as a calendar snapshot, which will NOT be updated).
2. now click in Outlook in the menu Tools on Account Settings (from Outlook 2010 -> File - Details - Account Settings - Account Settings).
3. click on the tab Internet Calendar on New.
4. Paste the link into the field with a right click - Paste.
5. Click on Add.
6. Now enter the name of the calendar you want to display in Outlook in the Order name field and click OK.


Recurring events would also be a great addition, but in my current case I don't need them.

 

Link to comment
Share on other sites

@Ralf alright I'm on it. The new approach is a WireArray events property, that can hold data for one or more events. 

// get the module
$icsgen = wire()->modules->IcsGenerator;

// add an event
$icsgen->events->add([
    'summary' => 'Event Title 1',
    'description' => 'Event body 1',
    'dtstart' =>'2033-12-24 12:00',
    'dtend' => '2033-12-24 14:00',
]);

This is a breaking change, rest of the API stays the same.

Here is a working prototype so you can already test it if you like. I aim for a new version that also supports most ICS event properties like last-modified etc.

Edit: should be mostly done, just have to add some docs. Maybe someone can test it in Outlook.

Edited by thausmann
  • Like 1
Link to comment
Share on other sites

  • 5 weeks later...

Hi all guys! And thanks for the job you made!

I have a question. I need a way to create 1 .ics for each user I have In ProcessWire, and when something happen (people confirm me dates etc) I want to append a VEVENT on the same .ics 

In this way the user have his link to .ics calendar and he can use it in sync outside (phone, os calendar, etc)

Can I do it with this module?

if yes, can someone share me some pseudo code to look in?

Thanks guys for your great job!

Link to comment
Share on other sites

Hi @e0f! Skimming the latest replies in this thread it sounds like that should be possible with @thausmann’s prototype version: https://github.com/timohausmann/IcsGenerator/tree/multievents

You can keep the .ics files around as static files that you only update when something changes (say, by hooking Pages::savedPageOrField) or you can just build them live for each request as you would any other page. Where do you want these files to live exactly?

If these calendars are supposed to be private to each user, you’ll need to figure out how to authenticate requests originating from your users’ calendar apps. That may or may not be the biggest hurdle in this endeavour, since they’re probably not going to send the session cookies ProcessWire normally uses.

Do you struggle with anything in particular?

  • Like 1
Link to comment
Share on other sites

  • 1 year later...

FYI I eventually merged the multievents into the main branch. So updating this module from 1.2 to 2.0 requires refactoring.

All data is moved to the events property (WireArray), no matter if single or multiple events.

// get the module
$icsgen = wire()->modules->IcsGenerator;

// create a new event using date strings
$myEvent = new WireData([
    'summary' => 'Christmas 2033',
    'dtstart' => '2033-12-24 18:00',
    'dtend' => '2033-12-24 22:00'
]);

// add to events
$icsgen->events->add($myEvent);
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...