Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

So following on from this post: http://stackoverflow.com/q/1463480/1086990 I was wondering how exactly it would work integrating it into Wordpress.

I have a custom post type setup, and so far I have tried both linking to a "ical.php" with the above link code (and changing the title into the_title() and the dates into GMT versions of my date(..) code). None work, because it can find the get_post_custom_values() which is obvious since not in WP loop, or a WP associated file.

Next I tried adding the headers into the header.php WP file, and adding a if(is_singular("event")), but the headers auto download. If I can stop the auto download then I'm ace, otherwise I come here for help!

Is there any reasonable way that is dynamically able to be populated via WP and only download when the link is clicked, not automatically?

I would host everything, but the events are going to be so often, that making and hosting would be a waste also is there maybe a href generator like Google Calendar that would automatically work?


EDIT (My working code):

Custom Taxonomy Loop

<form action="<?php echo get_feed_link('calendar-event'); ?>" method="post">
    <input hidden="hidden" name="eventID" value="<?php the_ID(); ?>">
    <button title="Add to iCal" type="submit" name="iCalForm">iCal</button>
</form>

iCal.php I included this into the functions.php via a require().

<?php //Event ICAL feed
class SH_Event_ICAL_Export  {

    public function load() { add_feed('calendar-event', array(__CLASS__,'export_events')); }

    // Creates an ICAL file of events in the database
    public function export_events(){ 

        //Give the iCal export a filename
        $filename = urlencode( 'event-ical-' . date('Y-m-d') . '.ics' );

        //Collect output 
        ob_start();

        // File header
        header("Content-Description: File Transfer");
        header("Content-Disposition: attachment; filename=".$filename);
        header("Content-type: text/calendar");
        header("Pragma: 0");
        header("Expires: 0");
?>
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//<?php echo get_bloginfo('name'); ?> //NONSGML Events //EN
CALSCALE:GREGORIAN
X-WR-CALNAME:<?php echo get_bloginfo('name');?>: Events
<?php // Query for events

    if(isset($_POST['iCalForm'])) {
        $post_ID = $_POST['eventID'];
        $events = new WP_Query(array(
            'p' => $post_ID,
            'post_type' => 'event'  //Or whatever the name of your post type is
        ));

    if($events->have_posts()) : while($events->have_posts()) : $events->the_post();
        $uid = get_the_ID(); // Universal unique ID
        $dtstamp = date_i18n('Ymd\THis\Z',time(), true); // Date stamp for now.
        $created_date = get_post_time('Ymd\THis\Z', true, get_the_ID() ); // Time event created
        // Other pieces of "get_post_custom_values()" that make up for the StartDate, EndDate, EventOrganiser, Location, etc.
        // I also had a DeadlineDate which I included into the BEGIN:VALARM
        // Other notes I found while trying to figure this out was for All-Day events, you just need the date("Ymd"), assuming that Apple iCal is your main focus, and not Outlook, or others which I haven't tested :]
?>
BEGIN:VEVENT
CREATED:<?php echo $created_date;?>

UID:<?php echo $uid;?>

DTEND;VALUE=DATE:<?php echo $end_date; ?>

TRANSP:OPAQUE
SUMMARY:<?php echo $organiser; ?>

DTSTART;VALUE=DATE:<?php echo $start_date ; ?>

DTSTAMP:<?php echo $dtstamp;?>

LOCATION:<?php echo $location;?>

ORGANIZER:<?php echo $organiser;?>

URL;VALUE=URI:<?php echo "http://".$url; ?>

BEGIN:VALARM
ACTION:DISPLAY
TRIGGER;VALUE=DATE-TIME:<?php echo $dLine; ?>

DESCRIPTION:Closing submission day of films for <?php echo $organiser; ?>! Enter quickly!
END:VALARM
END:VEVENT
<?php endwhile; endif; } ?>
END:VCALENDAR
<?php //Collect output and echo 
    $eventsical = ob_get_contents();
    ob_end_clean();
    echo $eventsical;
    exit();
    }   

} // end class
SH_Event_ICAL_Export::load();
?>

Hope this serves well to whoever needs it, as it is a fantastic piece of work, so again thanks Stephen Harris who helped more than the question, and additionally without suggesting I use his plugin.

share|improve this question

1 Answer 1

up vote 2 down vote accepted

I would use WordPress' feeds. You can create your own feed with add_feed. You specify a callback and this callback is responsible for displaying the output.

Creating a feed

add_feed('my-events','wpse56187_ical_cb');

wpse56187_ical_cb is that responsible for getting the events (use WP_Query), looping through them and printing the ICAL fields.

Downloading the ICAL file

If your feed is 'my-events', then the ical file can then be downloaded by going to:

www.yoursite.com?feed=my-events
www.yoursite.com/feed/my-events //If you have pretty permalinks

The link to the feed can be obtained by get_feed_link(). So if you wanted to create a link to you event's feed in your template:

<a href="<?php echo get_feed_link('my-events'); ?>" > Click here for ical file </a>

Example

I've omitted the details of filling in the event details in ICAL format (how you do this will depend on how you've stored the details).

The following class implements the above method and creates a feed called 'my-events'. You will need to make sure the details are formatted correctly and are valid (see this site)

Please note, I've not tested the following so there may be syntax errors

<?php
/**
 * Event ICAL feed
 */
class SH_Event_ICAL_Export  {

    public function load(){
        add_feed('my-events', array(__CLASS__,'export_events'));
    }

   /**
    * Creates an ICAL file of events in the database
    *  @param string filename - the name of the file to be created
    *  @param string filetype - the type of the file ('text/calendar')
    */ 
    public function export_events( ){ 

    //Give the ICAL a filename
    $filename = urlencode( 'event-ical-' . date('Y-m-d') . '.ics' );

    //Collect output 
    ob_start();

    // File header
    header( 'Content-Description: File Transfer' );
    header( 'Content-Disposition: attachment; filename=' . $filename );
    header('Content-type: text/calendar');
    header("Pragma: 0");
    header("Expires: 0");
?>
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//<?php  get_bloginfo('name'); ?>//NONSGML Events //EN
CALSCALE:GREGORIAN
X-WR-CALNAME:<?php echo get_bloginfo('name');?> - Events

<?php

    // Query for events
    $events = WP_Query(array(
         'post_type'=>'event' //Or whatever the name of your post type is
         'posts_per_page'=>-1 //Get all events
          ...
    ));

    if( $events->have_posts() ):
        while( $events->have_posts() ): $events->the_post();
            $uid=''; //Universal unique ID
            $dtstamp=date_i18n('Ymd\THis\Z',time(), true); //date stamp for now.
            $created_date=get_post_time('Ymd\THis\Z', true, get_the_ID() ); //time event created
            $start_date=""//event start date
            $end_date=""//event end date
            $reoccurrence_rule=false//event reoccurrence rule.
            $location=''//event location
            $organiser=''//event organiser
?>
BEGIN:VEVENT
UID:<?php echo $uid;?>

DTSTAMP:<?php echo $dtstamp;?>

CREATED:<?php echo $created_date;?>

DTSTART:<?php echo $start_date ; ?>

DTEND:<?php echo $end_date; ?>

<?php if ($reoccurrence_rule):?>
RRULE:<?php echo $reoccurrence_rule;?>

<?php endif;?>

LOCATION: <?php echo $location;?>

ORGANIZER: <?php $organiser;?>

END:VEVENT
<?php
        endwhile;
    endif;
?>
END:VCALENDAR
<?php

    //Collect output and echo 
    $eventsical = ob_get_contents();
    ob_end_clean();
    echo $eventsical;
    exit();
    }   

} // end class
SH_Event_ICAL_Export::load();
share|improve this answer
    
Firstly, thank you! I understand what you're doing, and its making things tonnes easier, but unfortunately I'm not familiar with PHP Classes, and the placement of that code. Under "Creating A Feed" should I add add_feed('my-events','wpse56187_ical_cb'); directly to the functions.php, or should it be called elsewhere? This because, when I call <a href="<?php echo get_feed_link('my-events'); ?>" > Click here for ical file </a> it directs to a 404 page, not the content. –  Ahhhhhhhhhhhhhdfgbv Jun 23 '12 at 11:57
    
Also the mass chunk of code, do I make that another file (i.e. ical.php) and include/require it in the single-event.php (single for taxonomy)? And with the WP_Query do I only call the custom data, because I usually use get_post_custom_values() for that, or should it be the whole shebang (post_type, offset,paged,etc.)? Sorry if that's a lot, but yeah I tried your example, and I'm no novice, nor expert, but couldn't get it going? –  Ahhhhhhhhhhhhhdfgbv Jun 23 '12 at 11:57
    
Sorry, I omitted SH_Event_ICAL_Export::load() from the very bottom (will edit answer now). The code should work 'as is' once you've filled in the details for the WP_Query (except for maybe syntax errors). So the above chunk can go wholesale into functions.php - though it should really be a plug-in. –  Stephen Harris Jun 23 '12 at 15:27
    
The WP_Query should query for your event post type. Inside the loop, set the the variables with the appropriate data (see comments). How you do that depends on where you store the data - presumably you're storing in post meta? –  Stephen Harris Jun 23 '12 at 15:31
    
Yep that was all great! But note for any other future readers, make sure you save your permalinks if you've been messing with them or else the 404 error page will show up (the code above is solid other than syntax errors)! On other notes, would've used your plugin if I didn't already customise my own event taxonomy :] True champ! –  Ahhhhhhhhhhhhhdfgbv Jun 24 '12 at 11:04

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.