TJOP
asked on
Displaying Upcoming Events with Google Calendar XML
I'm using code I found online to display upcoming events from a Google Calendar on our web page. It works alright but doesn't quite do what I need it to. Currently, it shows the five closest upcomings, I'd like it to instead show "Today" and "Tomorrow"s events. With a "No events" underneath the days if nothing is happening. I know nothing about pulling in XML data and I have no idea what to change in order to achieve this. My current code is below. Can anyone assist?
<?php
if (!isset($calendarfeed)) {$calendarfeed = "https://www.google.com/calendar/feeds/ni77gvsbpnvks91btbqdi3ga33shl7cr%40import.calendar.google.com/public/basic"; }
$dateformat="F jS Y";
$timeformat="g.ia";
date_default_timezone_set('America/Phoenix');
$event_display="<b>###TITLE###</b> - from ###FROM### ###DATESTART### until ###UNTIL### ###DATEEND###<br /><br />";
$event_error="<P>There are no events to display.</p>";
$event_dateheader="<span style='font-weight:bold;font-size:16px;color:#917f74;'>###DATE###</span><br />";
$GroupByDate=true;
$items_to_show=5; ///999 = unlimited
$use_cache=false;
$debug_mode=false;
$calendar_xml_address = str_replace("/basic","/full?singleevents=true&futureevents=true&max-results".$items_to_show."&orderby=starttime&sortorder=a",$calendarfeed);
$xml = simplexml_load_file($calendar_xml_address);
$items_shown=0;
$old_date="";
$xml->asXML();
foreach ($xml->entry as $entry){
$ns_gd = $entry->children('http://schemas.google.com/g/2005');
$description = preg_replace('"\b(http://\S+)"', '<a href="$1">$1</a>', $entry->content);
$description = preg_replace("`([-_a-z0-9]+(\.[-_a-z0-9]+)*@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]{2,6})`i","<a href=\"mailto:\\1\" title=\"mailto:\\1\">\\1</a>", $description);
$gCalDate = date($dateformat, strtotime($ns_gd->when->attributes()->startTime));
$gCalDateStart = date($dateformat, strtotime($ns_gd->when->attributes()->startTime));
$gCalDateEnd = date($dateformat, strtotime($ns_gd->when->attributes()->endTime));
$gCalStartTime = date($timeformat, strtotime($ns_gd->when->attributes()->startTime));
$gCalEndTime = date($timeformat, strtotime($ns_gd->when->attributes()->endTime));
$temp_event=$event_display;
$temp_dateheader=$event_dateheader;
$temp_event=str_replace("###TITLE###",$entry->title,$temp_event);
$temp_event=str_replace("###DESCRIPTION###",$description,$temp_event);
if ($gCalDateStart!=$gCalDateEnd) {
$temp_event=str_replace("###DATESTART###",$gCalDateStart,$temp_event);
$temp_event=str_replace("###DATEEND###",$gCalDateEnd,$temp_event);
} else {
$temp_event=str_replace("###DATESTART###",'',$temp_event);
$temp_event=str_replace("###DATEEND###",'',$temp_event);
}
$temp_event=str_replace("###DATE###",$gCalDate,$temp_event);
$temp_dateheader=str_replace("###DATE###",$gCalDate,$temp_dateheader);
$temp_event=str_replace("###FROM###",$gCalStartTime,$temp_event);
$temp_event=str_replace("###UNTIL###",$gCalEndTime,$temp_event);
$temp_event=str_replace("###WHERE###",$ns_gd->where->attributes()->valueString,$temp_event);
$temp_event=str_replace("###LINK###",$entry->link->attributes()->href,$temp_event);
$temp_event=str_replace("###MAPLINK###","http://maps.google.com/?q=".urlencode($ns_gd->where->attributes()->valueString),$temp_event);
$temp_event=str_replace("<","<",$temp_event);
$temp_event=str_replace(">",">",$temp_event);
$temp_event=str_replace(""","\"",$temp_event);
if (($items_to_show>0 AND $items_shown<$items_to_show)) {
if ($GroupByDate) {if ($gCalDate!=$old_date) { echo $temp_dateheader; $old_date=$gCalDate;}}
echo $temp_event;
$items_shown++;
}
}
if (!$items_shown) { echo $event_error; }
?>
I'll take a run at it - there would be a fairly large amount of programming that might need to be changed, so I may not get to all of the features you want (and it might make sense to hire a professional programmer to help you with this). The first thing I will do is apply some coding standards to make the code easier to read and understand, then I'll see what we can do with the data.
Actually now that I look at the XML and the resulting object, it's going to be a little bit hard to test, since I cannot find more than two calendar items. One is today (30th) and one is tomorrow (31st). So the ability to exclude anything that does not match the Today or Tomorrow screening is out of play.
I have to give up on this. I just discovered that the test data has changed, and I don't have the time or the tools to set up my own test cases. Recommend that you hire a programmer to help you work it out.
Here is what I have so far. I believe it will identify Today and Tomorrow, but since I can't test it, I'll have to leave that part to you.
http://www.laprbass.com/RAY_temp_tjop.php
Here is what I have so far. I believe it will identify Today and Tomorrow, but since I can't test it, I'll have to leave that part to you.
http://www.laprbass.com/RAY_temp_tjop.php
<?php // RAY_temp_tjop.php
error_reporting(E_ALL);
date_default_timezone_set('America/Phoenix');
$calendarfeed = "https://www.google.com/calendar/feeds/ni77gvsbpnvks91btbqdi3ga33shl7cr%40import.calendar.google.com/public/basic";
$dateformat = "F jS Y";
$timeformat = "g.ia";
$isoformat = 'Y-m-d\TH:i:s';
$event_display ="<b>###TODAY###<br>###TITLE###</b> - from ###FROM### ###DATESTART### until ###UNTIL### ###DATEEND###<br /><br />";
$event_error ="<P>There are no events to display.</p>";
$event_dateheader ="<span style='font-weight:bold;font-size:16px;color:#917f74;'>###DATE###</span><br />";
$GroupByDate = TRUE;
$items_to_show = 15; ///999 = unlimited
$use_cache = FALSE;
$debug_mode = FALSE;
$calendar_xml_address = str_replace("/basic","/full?singleevents=true&futureevents=true&max-results=".$items_to_show."&orderby=starttime&sortorder=a",$calendarfeed);
$xml = file_get_contents($calendar_xml_address);
$obj = simplexml_load_string($xml);
// DIAGNOSTIC CODE
// echo '<pre>';
// echo $xml;
// var_dump($obj);
// die();
$items_shown=0;
$old_date="";
// $obj->asXML(); // REMOVED -- NOT USEFUL
// SET ISO-8601 DATETIME VALUES FOR TODAY AND TOMORROW
$today = array
( 'a' => date($isoformat, strtotime('Today'))
, 'z' => date($isoformat, strtotime('Today 11:59:59'))
)
;
$morow = array
( 'a' => date($isoformat, strtotime('Tomorrow'))
, 'z' => date($isoformat, strtotime('Tomorrow 11:59:59'))
)
;
foreach ($obj->entry as $entry)
{
// PICK UP THE NAMESPACE INFO
$ns_gd = $entry->children('http://schemas.google.com/g/2005');
// DOES THIS MAP TO TODAY OR TOMORROW?
$entry->myTodayTomorrow = 0;
$dt_a = date($isoformat, strtotime($ns_gd->when->attributes()->startTime));
$dt_z = date($isoformat, strtotime($ns_gd->when->attributes()->endTime));
if ( ($dt_a >= $today['a']) && ($dt_z <= $today['z']) )
{
$entry->myTodayTomorrow = 'Today';
}
elseif ( ($dt_a >= $morow['a']) && ($dt_z <= $morow['z']) )
{
$entry->myTodayTomorrow = 'Tomorrow';
}
// SKIP ENTRIES THAT ARE NOT TODAY OR TOMORROW
if (!$entry->myTodayTomorrow) continue;
$description = preg_replace('"\b(http://\S+)"', '<a href="$1">$1</a>', $entry->content);
$description = preg_replace("`([-_a-z0-9]+(\.[-_a-z0-9]+)*@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]{2,6})`i","<a href=\"mailto:\\1\" title=\"mailto:\\1\">\\1</a>", $description);
$gCalDate = date($dateformat, strtotime($ns_gd->when->attributes()->startTime));
$gCalDateStart = date($dateformat, strtotime($ns_gd->when->attributes()->startTime));
$gCalDateEnd = date($dateformat, strtotime($ns_gd->when->attributes()->endTime));
$gCalStartTime = date($timeformat, strtotime($ns_gd->when->attributes()->startTime));
$gCalEndTime = date($timeformat, strtotime($ns_gd->when->attributes()->endTime));
$temp_event = $event_display;
$temp_dateheader = $event_dateheader;
$temp_event = str_replace("###TODAY###", $entry->myTodayTomorrow, $temp_event);
$temp_event = str_replace("###TITLE###", $entry->title, $temp_event);
$temp_event = str_replace("###DESCRIPTION###", $description, $temp_event);
if ($gCalDateStart != $gCalDateEnd) {
$temp_event = str_replace("###DATESTART###", $gCalDateStart, $temp_event);
$temp_event = str_replace("###DATEEND###", $gCalDateEnd, $temp_event);
} else {
$temp_event = str_replace("###DATESTART###", '', $temp_event);
$temp_event = str_replace("###DATEEND###", '', $temp_event);
}
$temp_event = str_replace("###DATE###",$gCalDate,$temp_event);
$temp_dateheader = str_replace("###DATE###",$gCalDate,$temp_dateheader);
$temp_event = str_replace("###FROM###",$gCalStartTime,$temp_event);
$temp_event = str_replace("###UNTIL###",$gCalEndTime,$temp_event);
$temp_event = str_replace("###WHERE###",$ns_gd->where->attributes()->valueString,$temp_event);
$temp_event = str_replace("###LINK###",$entry->link->attributes()->href,$temp_event);
$temp_event = str_replace("###MAPLINK###","http://maps.google.com/?q=".urlencode($ns_gd->where->attributes()->valueString),$temp_event);
$temp_event = str_replace("<","<",$temp_event);
$temp_event = str_replace(">",">",$temp_event);
$temp_event = str_replace(""","\"",$temp_event);
if (($items_to_show > 0 AND $items_shown < $items_to_show)) {
if ($GroupByDate) {
if ($gCalDate != $old_date) {
echo $temp_dateheader;
$old_date=$gCalDate;
}
}
echo $temp_event;
$items_shown++;
}
}
if (!$items_shown) {
echo $event_error;
}
Best of luck with the project, ~Ray
ASKER
Ray,
Thank you so much for your help thus far. By test data, do you mean events on the calendar? There are a ton now and it is not working. If you can find the time, I'd really appreciate any last help to make this thing work. Unfortunately there just isn't a budget to hire a programmer and this is the last thing we need to complete the site!
I just need to to say "Today" then list events, and "Tomorrow" then list events. None outside of those two days. At the moment it's showing all dates and all events.
Once again, thank you regardless for your help thus far. But I'm at a loss of how to complete it.
Thank you so much for your help thus far. By test data, do you mean events on the calendar? There are a ton now and it is not working. If you can find the time, I'd really appreciate any last help to make this thing work. Unfortunately there just isn't a budget to hire a programmer and this is the last thing we need to complete the site!
I just need to to say "Today" then list events, and "Tomorrow" then list events. None outside of those two days. At the moment it's showing all dates and all events.
Once again, thank you regardless for your help thus far. But I'm at a loss of how to complete it.
OK, let's have a try with this. The test data seems to be changing as I am trying to test, and that's usually fatal for any programming effort. To learn more about why test data matters more than any other part of the programmer's toolkit, please read this article.
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_7830-A-Quick-Tour-of-Test-Driven-Development.html
Code is located at this URL:
http://www.laprbass.com/RAY_temp_tjop.php
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_7830-A-Quick-Tour-of-Test-Driven-Development.html
Code is located at this URL:
http://www.laprbass.com/RAY_temp_tjop.php
<?php // RAY_temp_tjop.php
error_reporting(E_ALL);
date_default_timezone_set('America/Phoenix');
$calendarfeed = "https://www.google.com/calendar/feeds/ni77gvsbpnvks91btbqdi3ga33shl7cr%40import.calendar.google.com/public/basic";
$dateformat = "F jS Y";
$timeformat = "g.ia";
$isoformat = 'Y-m-d';
$event_display ="<b>###TODAY###<br>###TITLE###</b> - from ###FROM### ###DATESTART### until ###UNTIL### ###DATEEND###<br /><br />";
$event_error ="<P>There are no events to display.</p>";
$event_dateheader ="<span style='font-weight:bold;font-size:16px;color:#917f74;'>###DATE###</span><br />";
$GroupByDate = TRUE;
$items_to_show = 15; ///999 = unlimited
$use_cache = FALSE;
$debug_mode = FALSE;
$calendar_xml_address = str_replace("/basic","/full?singleevents=true&futureevents=true&max-results=".$items_to_show."&orderby=starttime&sortorder=a",$calendarfeed);
$xml = file_get_contents($calendar_xml_address);
$obj = simplexml_load_string($xml);
// DIAGNOSTIC CODE
// echo '<pre>';
// echo $xml;
// var_dump($obj);
// die();
$items_shown=0;
$old_date="";
// SET ISO-8601 DATETIME VALUES FOR TODAY AND TOMORROW
$today = date($isoformat, strtotime('Today'));
$morow = date($isoformat, strtotime('Tomorrow'));
foreach ($obj->entry as $key => $entry)
{
// PICK UP THE NAMESPACE INFO
$ns_gd = $entry->children('http://schemas.google.com/g/2005');
// GET STARTING DAY
$start = date($isoformat, strtotime($ns_gd->when->attributes()->startTime));
// DIAGNOSTIC
// print_r($start);
// DOES THIS MAP TO TODAY OR TOMORROW?
$entry->myTodayTomorrow = 0;
if ($start == $today)
{
$entry->myTodayTomorrow = 'Today';
}
elseif ($start == $morow)
{
$entry->myTodayTomorrow = 'Tomorrow';
}
// SKIP ENTRIES THAT ARE NOT TODAY OR TOMORROW
else
{
continue;
}
$description = preg_replace('"\b(http://\S+)"', '<a href="$1">$1</a>', $entry->content);
$description = preg_replace("`([-_a-z0-9]+(\.[-_a-z0-9]+)*@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]{2,6})`i","<a href=\"mailto:\\1\" title=\"mailto:\\1\">\\1</a>", $description);
$gCalDate = date($dateformat, strtotime($ns_gd->when->attributes()->startTime));
$gCalDateStart = date($dateformat, strtotime($ns_gd->when->attributes()->startTime));
$gCalDateEnd = date($dateformat, strtotime($ns_gd->when->attributes()->endTime));
$gCalStartTime = date($timeformat, strtotime($ns_gd->when->attributes()->startTime));
$gCalEndTime = date($timeformat, strtotime($ns_gd->when->attributes()->endTime));
$temp_event = $event_display;
$temp_dateheader = $event_dateheader;
$temp_event = str_replace("###TODAY###", $entry->myTodayTomorrow, $temp_event);
$temp_event = str_replace("###TITLE###", $entry->title, $temp_event);
$temp_event = str_replace("###DESCRIPTION###", $description, $temp_event);
if ($gCalDateStart != $gCalDateEnd) {
$temp_event = str_replace("###DATESTART###", $gCalDateStart, $temp_event);
$temp_event = str_replace("###DATEEND###", $gCalDateEnd, $temp_event);
} else {
$temp_event = str_replace("###DATESTART###", '', $temp_event);
$temp_event = str_replace("###DATEEND###", '', $temp_event);
}
$temp_event = str_replace("###DATE###",$gCalDate,$temp_event);
// REMOVED TO JUST SHOW TODAY OR TOMORROW
// $temp_dateheader = str_replace("###DATE###",$gCalDate,$temp_dateheader);
$temp_dateheader = str_replace("###DATE###",NULL,$temp_dateheader);
$temp_event = str_replace("###FROM###",$gCalStartTime,$temp_event);
$temp_event = str_replace("###UNTIL###",$gCalEndTime,$temp_event);
$temp_event = str_replace("###WHERE###",$ns_gd->where->attributes()->valueString,$temp_event);
$temp_event = str_replace("###LINK###",$entry->link->attributes()->href,$temp_event);
$temp_event = str_replace("###MAPLINK###","http://maps.google.com/?q=".urlencode($ns_gd->where->attributes()->valueString),$temp_event);
$temp_event = str_replace("<","<",$temp_event);
$temp_event = str_replace(">",">",$temp_event);
$temp_event = str_replace(""","\"",$temp_event);
if (($items_to_show > 0 AND $items_shown < $items_to_show)) {
if ($GroupByDate) {
if ($gCalDate != $old_date) {
echo $temp_dateheader;
$old_date=$gCalDate;
}
}
echo $temp_event;
$items_shown++;
}
}
if (!$items_shown) {
echo $event_error;
}
ASKER
Sooo close! Thank you! Just two questions with it:
Is there any way to make it alert of no events, as well as group same day events? For instance, right now it's
Tomorrow
Event here
Tomorrow
Event here
Is it possible to do:
Today
No events for today
Tomorrow
Event here
Event here
Etc...?
Is there any way to make it alert of no events, as well as group same day events? For instance, right now it's
Tomorrow
Event here
Tomorrow
Event here
Is it possible to do:
Today
No events for today
Tomorrow
Event here
Event here
Etc...?
Yes, I am sure it's possible, but the starting script really needs to be re-written to add this functionality. The way it uses echo inside a loop makes it much more complicated to extend the new logic. I really think you should hire a professional to help you with this. It's not a question that has an answer -- it's a moving requirement for application development, and for that a professional developer is going to be able to give you the best answer.
ASKER
But in the original script, it groups them by date. Wouldn't it be possible to just replace the dates with "Today" and "Tomorrow"? I'd love to hire a programmer for this, just won't be able to talk anyone into spending the money.
If it's not worth any money to anyone, maybe you should just not do it.
If I get some spare time I will look at it again later this week. Going forward, when you find "free code online" you might want to consider whether or not it is worth exactly what you paid for it!
If I get some spare time I will look at it again later this week. Going forward, when you find "free code online" you might want to consider whether or not it is worth exactly what you paid for it!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Ray, you are a damn god among men. It works beautifully. I'm sorry to be such a pain, but I simply can't express through typing how much I appreciate all your help. Hopefully this will help others too.
Once again, thank you!!
Once again, thank you!!
ASKER
Couldn't be more perfect. Thank you!!!
Thanks for the points, and while it may be doing what you want, if you ever need to make changes, it's going to be a PITA. So instead of planning to make changes, plan to refactor the script the next time you need to go in. It won't take much longer than any modest change, and once this is rewritten correctly it will be much easier to maintain, extend and reuse!
Best regards, ~Ray
Best regards, ~Ray
ASKER
Ray,
Not sure if you'll see this... but it completely randomly stopped working. Just shows no events at all times now. I've poured over the code over and over and over and I can't find what could possibly be causing the issue out of nowhere. I hate to bring it up again, but figured it was worth a show.
Not sure if you'll see this... but it completely randomly stopped working. Just shows no events at all times now. I've poured over the code over and over and over and I can't find what could possibly be causing the issue out of nowhere. I hate to bring it up again, but figured it was worth a show.
Please activate the diagnostic code in the snippet above. Then use "view source" to look at the output. According to what I get from the API there is nothing scheduled for today or tomorrow. This is a data-dependent problem.
Sidebar note... I often "Unmonitor" questions after they are answered. Glad I saw this one. But going forward it's usually best to create the SSCCE and post a new question.
Sidebar note... I often "Unmonitor" questions after they are answered. Glad I saw this one. But going forward it's usually best to create the SSCCE and post a new question.