Creating ICal For Custom Post Type In WordPress Without A Plugin.

define( 'EVENT_CALENDAR_FEED_SLUG', 'events-calendar' );
define( 'CUSTOM_POST_TYPE_SLUG', 'your-post-type-slug' );
<?php
/**
* Ical functions.
*
* For a better understanding of ics requirements and time formats
* please check https://gist.github.com/jakebellacera/635416
*
*
@package YoutTheme
*/

namespace YourNamespace;
use WP_Query;

/**
* Escapes a string of characters
*
*
@param string $string String.
*
*
@return array|string
*/
function escapeString( string $string ) {
return preg_replace( '/([\,;])/', '\\\$1', $string );
}

/**
* Shorten a string to desired characters length
*
* eg. shorter_version($string, 100);
*
*
@param string $string String.
*
@param int $length Length.
*
*
@return false|mixed|string
*/
function shorter_version( string $string, int $length ) {

if ( empty( $string ) || empty( $length ) ) {
return '';
}

return strlen( $string ) >= $length ? substr( $string, 0, $length ) : $string;
}

/**
* Add a custom endpoint 'event-calendar'
*/
function add_calendar_feed(){

add_feed( EVENT_CALENDAR_FEED_SLUG, __NAMESPACE__ . '\\export_ics' );

/**
* Only uncomment the below two lines, the first time you load this script,
* to update WP rewrite rules, or in case you see a 404
*/
global $wp_rewrite;
$wp_rewrite->flush_rules( false );
}

add_action('init', __NAMESPACE__ . '\\add_calendar_feed');

/**
* Calendar function
*/
function export_ics(){

// Collect output.
ob_start();

// Set the correct headers for this file
header("Content-Description: File Transfer");
header('Content-type: text/calendar; charset=utf-8');
header("Pragma: 0");
header("Expires: 0");

$eol = "\r\n";

?>
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//<?php echo get_bloginfo('name'); ?> //NONSGML Events //EN
CALSCALE:GREGORIAN
X-WR-CALNAME:<?php echo get_bloginfo('name').$eol;?>
<?php

// Query the event.
$the_event = new WP_Query( [
'post_type' => CUSTOM_POST_TYPE_SLUG,
'p' => intval( $_REQUEST['id'] ), // Post Id.
'update_post_meta_cache' => false,
'no_found_rows' => true,
'update_post_term_cache' => false,
] );

if ( $the_event->have_posts() ) :

while ( $the_event->have_posts() ) : $the_event->the_post();

/**
* The correct date format, for ALL dates is date_i18n('Ymd\THis\Z',time(), true)
* So if your date is not in this format, use that function
* Second param of date_i18n needs to be a timestamp.
*/
$event_start_date = 'your-event-start-date-time-stamp';
$event_end_date = 'your-event-end-date-time-stamp';
$start_date = date_i18n( 'Ymd\THis\Z', strtotime( $event_start_date ) );
$end_date = date_i18n( 'Ymd\THis\Z', strtotime( $event_end_date ) );
$deadline = date_i18n( 'Ymd\THis\Z', strtotime( $event_end_date ) ); // Reminder is set 30 mins before this time.

$timestamp = date_i18n( 'Ymd\THis\Z', time(), true );
$uid = get_the_ID();
$created_date = get_post_time( 'Ymd\THis\Z', true, $uid );
$organiser = __( 'Codeytek Academy', 'text-domain' );
$address = __( 'Codeytek Academy', 'text-domain' ); // @TODO be checked later if this needs to change.
$url = get_the_permalink();
$content = html_entity_decode( trim( preg_replace( '/\s\s+/', ' ', get_the_content() ) ) ); // removes newlines and double spaces
$title = html_entity_decode( get_the_title() );

//Give the iCal export a filename
$filename = sprintf( '%1$s-ical-%2$s.ics', esc_html( $title ), date('Y-m-d') );
$filename = urlencode( $filename );
header( "Content-Disposition: attachment; filename=" . $filename );
/**
* The below ics structure MUST NOT have spaces before each line
*
*
@see https://gist.github.com/jakebellacera/635416
*/
?>
BEGIN:VEVENT
CREATED:<?php printf( '%1$s%2$s', esc_html( $created_date ), $eol );?>
UID:<?php printf( '%1$s%2$s', esc_html( $uid ), $eol );?>
DTEND;VALUE=DATE:<?php printf( '%1$s%2$s', esc_html( $end_date ), $eol );?>
DTSTART;VALUE=DATE:<?php printf( '%1$s%2$s', esc_html( $start_date ), $eol );?>
DTSTAMP:<?php printf( '%1$s%2$s', esc_html( $timestamp ), $eol );?>
LOCATION:<?php printf( '%1$s%2$s', esc_html( $address ), $eol );?>
DESCRIPTION:<?php printf( '%1$s%2$s', esc_html( $content ), $eol );?>
SUMMARY:<?php printf( '%1$s%2$s', esc_html( $title ), $eol );?>
ORGANIZER:<?php printf( '%1$s%2$s', esc_html( escapeString( $organiser ) ), $eol );?>
URL;VALUE=URI:<?php printf( '%1$s%2$s', esc_url( escapeString( $url ) ), $eol );?>
TRANSP:OPAQUE
BEGIN:VALARM
ACTION:DISPLAY
TRIGGER;VALUE=DATE-TIME:<?php printf( '%1$s%2$s', esc_html( $deadline ), $eol );?>
DESCRIPTION:Reminder for <?php printf( '%1$s%2$s', esc_html( escapeString( $title ) ), $eol );?>
END:VALARM
END:VEVENT<?php echo $eol; ?>
<?php endwhile; ?>END:VCALENDAR<?php
//Collect output and echo
$eventsical = ob_get_contents();
ob_end_clean();
echo $eventsical;
exit();

endif;

}

?>
$calendar_feed_link = sprintf( '%1$s?id=%2$s', get_feed_link( EVENT_CALENDAR_FEED_SLUG ), get_the_ID() );<a class="no-underline-link flex items-center py-5 lg:py-6" href="<?php echo esc_url( $calendar_feed_link ); ?>" title="<?php esc_attr_e( 'Add to my calendar', 'text-domain' ); ?>">
<span class="text-2xl lg:text-3xl uppercase"><?php esc_html_e( 'Add to my calendar', 'text-domain' ); ?></span>
</a>

--

--

--

👤 Full Stack Developer at rtCamp, Speaker, Blogger, YouTuber, Wordpress, React, Node, Laravel Developer http://youtube.com/ImranSayedDev

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Create Your Own Chrome Extension

React Fundamentals

I left Meteor

Passing state up to parent component from child component in React.js

How to make matrix effect shader with GLSL

How to open-source a project in 4 steps: Part 1

Dependency Injection 101

Deploying Node.js application on GCP

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Imran Sayed

Imran Sayed

👤 Full Stack Developer at rtCamp, Speaker, Blogger, YouTuber, Wordpress, React, Node, Laravel Developer http://youtube.com/ImranSayedDev

More from Medium

How to Create Auto Generate Slug in Strapi 4

How to Add or Remove Input Fields Dynamically Using jQuery?

Developing Tailpages: A Jekyll Template based on Tailwind CSS

Koovs Website Cloning