views:

631

answers:

3

I built a site in PHP 5 and MySQL with a table that keeps track of scheduled photo shoots. I want to push out a feed of those scheduled "events" into an ical file.

I originally asked this question and got a good answer from S. Gehrig. I got a sample ical file working, and updating regularly in Google Calendar whenever I manually adjusted the file in Dreamweaver. However, now that I've added dynamic PHP pulling from the database, it won't work.

Here's the PHP:

<?php
require_once('../../_includes/initialize.php');

$ical = " BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN ";

$slots = Slot::find_all();
foreach($slots as $slot) {
    $job = Job::find_by_id($slot->job_id);

    $start_stamp = strtotime($slot->start);
    $end_stamp = strtotime($slot->endtime);
    $dtstart = gmdate('Ymd', $start_stamp).'T'. gmdate('His', $start_stamp) . "Z"; // converts to UTC time
    $dtend = gmdate('Ymd', $end_stamp).'T'. gmdate('His', $end_stamp) . "Z"; // converts to UTC time

    $summary = $job->title;

    $ical .= " BEGIN:VEVENT
    UID:" . $slot->id . "@homewoodphoto.jhu.edu
    DTSTAMP:" . gmdate('Ymd').'T'. gmdate('His') . "Z
    DTSTART:" . $dtstart . "
    DTEND:" . $dtend . "
    SUMMARY:" . $summary . "
    END:VEVENT ";
}

$ical .= " END:VCALENDAR";

//set correct content-type-header
header('Content-type: text/calendar; charset=utf-8');
header('Content-Disposition: inline; filename=homewoodphoto_master.ics');
echo $ical;
exit;

?>

The output of this file is exactly the same as the manual, hard-coded version that I have working, as far as I can tell. Can anyone see why this isn't working????

PS Here is the code of the file that IS working -- I just posted it on my server and subscribed via URL in Google Calendar. When I hardcoded in the 2nd event, it showed up shortly in Google Calendar on its own.

<?php

$ical = "BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN

BEGIN:VEVENT
UID:" . md5(uniqid(mt_rand(), true)); . "@yourhost.test
DTSTAMP:" . gmdate('Ymd').'T'. gmdate('His') . "Z
DTSTART:20090925T170000Z
DTEND:20090928T035959Z
SUMMARY:Bastille Day Party
END:VEVENT

BEGIN:VEVENT
UID:" . md5(uniqid(mt_rand(), true)); . "@yourhost.test
DTSTAMP:" . gmdate('Ymd').'T'. gmdate('His') . "Z
DTSTART:20090929T170000Z
DTEND:20090930T035959Z
SUMMARY:Camping Trip
END:VEVENT

END:VCALENDAR";

//set correct content-type-header
header('Content-type: text/calendar; charset=utf-8');
header('Content-Disposition: inline; filename=calendar.ics');

echo $ical;

exit;

?>

HELP!

A commenter suggested I test by removing the headers and echoing the $ical var. Here are the results of that test, with line breaks added for your convenience:

BEGIN:VCALENDAR 
VERSION:2.0 
PRODID:-//hacksw/handcal//NONSGML v1.0//EN 
BEGIN:VEVENT 
UID:[email protected] 
DTSTAMP:20090929T212141Z 
DTSTART:20091001T230000Z 
DTEND:20091001T230000Z 
SUMMARY:little title 
END:VEVENT 
BEGIN:VEVENT 
UID:[email protected] 
DTSTAMP:20090929T212141Z 
DTSTART:20090926T230000Z 
DTEND:20090927T010000Z 
SUMMARY:A big photo shoot 
END:VEVENT 
BEGIN:VEVENT 
UID:[email protected] 
DTSTAMP:20090929T212141Z 
DTSTART:20091003T230000Z 
DTEND:20091004T010000Z 
SUMMARY:A big photo shoot 
END:VEVENT 
END:VCALENDAR

Thanks!

+1  A: 

Initial guess would be your array is not populated correctly. So to test it I would start with removing

//set correct content-type-header
header('Content-type: text/calendar; charset=utf-8');
header('Content-Disposition: inline; filename=homewoodphoto_master.ics');

and changing $slots = Slot::find_all(); to

$slots = Slot::find_all();
print_r($slots);

to make sure your array of object is being set.

Then run it from either command line or browser to make sure it outputs as expected before submitting to google.

Try the following code to avoid white space:

<?php
require_once('../../_includes/initialize.php');

$ical = "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//hacksw/handcal//NONSGML v1.0//EN";

$slots = Slot::find_all();
foreach($slots as $slot) {
    $job = Job::find_by_id($slot->job_id);

    $start_stamp = strtotime($slot->start);
    $end_stamp = strtotime($slot->endtime);
    $dtstart = gmdate('Ymd', $start_stamp).'T'. gmdate('His', $start_stamp) . "Z"; // converts to UTC time
    $dtend = gmdate('Ymd', $end_stamp).'T'. gmdate('His', $end_stamp) . "Z"; // converts to UTC time

    $summary = $job->title;

    $ical .= "BEGIN:VEVENT\n";
    $ical .= "UID:" . $slot->id . "@homewoodphoto.jhu.edu\n";
    $ical .= "DTSTAMP:" . gmdate('Ymd').'T'. gmdate('His') . "Z\n";
    $ical .= "DTSTART:" . $dtstart . "\n";
    $ical .= "DTEND:" . $dtend . "\n";
    $ical .= "SUMMARY:" . $summary . "\n";
    $ical .= "END:VEVENT\n";
}

$ical .= "\nEND:VCALENDAR";

//set correct content-type-header
header('Content-type: text/calendar; charset=utf-8');
header('Content-Disposition: inline; filename=homewoodphoto_master.ics');
echo $ical;
exit;

?>
Mohammad
Mohammad, thanks. I actually removed the headers and just ran it to echo $ical to see what was being output. It was exactly the same as the hard-coded test, just with different dates and summaries. ??
Jason Rhodes
I'll add the output of that test to the end of the question above...
Jason Rhodes
Alright, it looks strange, so I started testing your output with a ics validator:http://severinghaus.org/projects/icv/and seems like white space at the end of each node is causing it! (in your loop, for formatting reasons you have indented your code which in open strings, it creates white space)UID:" . $slot->id . "@homewoodphoto.jhu.edu DTSTAMP:" . gmdate('Ymd').'T'. gmdate('His') . "Z DTSTART:" . $dtstart . " DTEND:" . $dtend . " SUMMARY:" . $summary . " END:VEVENT ";I will update the original answer with the correct code.
Mohammad
Mohammad, when I saw your answer something clicked and I was sure you were going to be right. But it didn't work. So I deleted your \n linebreaks and did manual linebreaks, without the indent, and somehow, that seems to be working! I'll post the code up in the answer. Thanks.
Jason Rhodes
Actually, I'll just answer the question so it's listed as answered.
Jason Rhodes
cool :) issue was that I knew it was the space issue but couldn't test it without rest of your database and code so I figured using \n to address it. but I am glad you got it working now.
Mohammad
A: 

Thanks to Mohammad's help, we deduced that it was the indented code adding whitespace to the ics file that was causing the errors. M's suggestion to use \n linebreaks didn't work, but manually hitting enter to create linebreaks, but without indenting the next line, seems to have done it. Here's the code that works:

<?php
require_once('../../_includes/initialize.php');

$ical = "BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
";

$slots = Slot::find_all();
foreach($slots as $slot) {
$job = Job::find_by_id($slot->job_id);

$start_stamp = strtotime($slot->start);
$end_stamp = strtotime($slot->endtime);
$dtstart = gmdate('Ymd', $start_stamp).'T'. gmdate('His', $start_stamp) . "Z"; // converts to UTC time
$dtend = gmdate('Ymd', $end_stamp).'T'. gmdate('His', $end_stamp) . "Z"; // converts to UTC time

$summary = $job->title;

$ical .= "BEGIN:VEVENT
UID:" . $slot->id . "@homewoodphoto.jhu.edu
DTSTAMP:" . gmdate('Ymd').'T'. gmdate('His') . "Z
DTSTART:" . $dtstart . "
DTEND:" . $dtend . "
SUMMARY:" . $summary . "
END:VEVENT
";
}

$ical .= "END:VCALENDAR";

//set correct content-type-header
header('Content-type: text/calendar; charset=utf-8');
header('Content-Disposition: inline; filename=homewoodphoto_master.ics');
echo $ical;
exit;
?>
Jason Rhodes