WP Manifestindependent plugin directory
manifest / events / xtendify-assignment

Upcoming Calendar Events

WordPress plugin: display upcoming Google Calendar events via shortcode + AJAX, with transient caching

by Shivam · github.com/shivamtechie/xtendify-assignment · website

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/shivamtechie/xtendify-assignment/archive/refs/heads/main.zip

Readme

Upcoming Calendar Events

A small WordPress plugin that displays upcoming events from a Google Calendar on the front-end of your site via the [upcoming_events] shortcode. Events are fetched through the Google Calendar API, cached with WordPress transients, and rendered on the page with AJAX.


Features

  • Settings page under Settings → Calendar Events (Google API key, cache duration, default event count) with a Save and validate button that performs a live test call against the API key.
  • [upcoming_events] shortcode with attributes for count, look-ahead window, descriptions and the target calendar.
  • Transient caching to stay well under Google's rate limits. Cache is automatically invalidated when settings are saved, and can be cleared manually with the Refresh cache button.
  • AJAX rendering so page/full-page caches never serve stale event markup.
  • Graceful failure: network errors, malformed responses, an empty calendar or a missing API key never break the page.
  • OOP, namespaced, PSR-4 autoloaded code; sanitization on input, escaping on output, nonces on every form, capability checks on every admin action.

Requirements

  • WordPress 5.8+
  • PHP 7.4+
  • A Google API key with the Google Calendar API enabled
  • A public Google Calendar (or one shared publicly) and its Calendar ID

Installation

Option A — download / clone

  1. Copy the upcoming-calendar-events folder into wp-content/plugins/.
  2. (Optional, recommended) From the plugin folder run composer install to generate the optimized autoloader. If you skip this, the plugin still works — it falls back to a built-in PSR-4 autoloader.
  3. Activate Upcoming Calendar Events in Plugins.

Option B — zip upload

Zip the upcoming-calendar-events folder and upload it via Plugins → Add New → Upload Plugin.


Configuration

  1. Go to Settings → Calendar Events.
  2. Enter your Google API key, set the cache duration (default 60 min) and default number of events (default 5).
  3. Click Save and validate. A green notice confirms the key works; a red notice shows the exact error reported by Google.

How to obtain a Google API key

  1. Go to the Google Cloud Console.
  2. Create a project (or select an existing one).
  3. Navigate to APIs & Services → Library, search for Google Calendar API, and click Enable.
  4. Go to APIs & Services → Credentials → Create Credentials → API key.
  5. Copy the key. For security, click Restrict key and limit it to the Google Calendar API (and optionally to your server's IP / HTTP referrers).

This plugin uses an API key, not OAuth, so it can only read public calendars. That is sufficient for displaying public event listings.

How to find your Calendar ID

  1. Open Google Calendar on the web.
  2. Hover the calendar in the left sidebar → ⋮ → Settings and sharing.
  3. Under Access permissions for events, tick Make available to public.
  4. Scroll to Integrate calendar and copy the Calendar ID — it looks like something@group.calendar.google.com (your personal calendar's ID is your Gmail address).

Usage

Add the shortcode to any post or page:

[upcoming_events count="10" days_ahead="30" show_description="true" google_calendar_id="something@group.calendar.google.com"]

Shortcode attributes

Attribute Required Type Default Description
google_calendar_id Yes string The Google Calendar ID to read from.
days_ahead Yes numeric How many days into the future to look.
count No numeric settings value (5) Maximum number of events to show.
show_description No boolean false Whether to display each event's description.

If a mandatory attribute is missing, editors (users who can edit posts) see a helpful inline message while ordinary visitors see nothing — the page is never broken.


Architecture decisions

The plugin is intentionally split into single-responsibility classes under the Shivam\UpcomingCalendarEvents namespace (PSR-4, autoloaded by Composer with a hand-written fallback so it runs without a build step):

upcoming-calendar-events.php   Bootstrap: constants, autoloader, activation hooks
src/Plugin.php                 Singleton orchestrator; wires services + asset registration
src/Admin/SettingsPage.php     Options screen, save/validate + cache-refresh handlers
src/Api/GoogleCalendarClient.php  Thin Google Calendar v3 client; normalises responses
src/Service/EventService.php   Cache-aware façade used by both shortcode and AJAX
src/Cache/CacheManager.php     Transient wrapper with a key index for reliable flushing
src/Frontend/Shortcode.php     Registers [upcoming_events]; outputs the AJAX container
src/Frontend/Renderer.php      Turns normalised events into escaped, semantic HTML
src/Ajax/AjaxHandler.php       admin-ajax endpoint; re-validates input, returns HTML
assets/js/frontend.js          Vanilla-JS loader (no jQuery)
assets/css/frontend.css        Minimal default styling

Key choices and the reasoning behind them:

  • AJAX rendering instead of server-side output. The brief asks for AJAX, and it has a real benefit: full-page caches (and CDNs) would otherwise freeze the event list into the cached HTML. Rendering client-side keeps the markup fresh while the transient cache still protects the Google API from per-view hits.
  • A façade (EventService) shared by the shortcode and AJAX handler. Cache lookup + API fallback live in exactly one place, so both entry points behave identically.
  • A tracked key index in CacheManager. Deleting transients by SQL LIKE '_transient_uce_%' breaks on persistent object caches (Redis/Memcached). Keeping an index of our keys lets "flush all" work on every backend.
  • Errors are never cached. A failed API call returns a WP_Error and is not stored, so a transient outage doesn't lock in a broken state for the cache duration. The detail is logged (when WP_DEBUG), and visitors get a generic message.
  • Defence in depth on input. The shortcode validates attributes, and the AJAX handler re-sanitizes and re-validates everything from $_POST — the client is never trusted. Output is escaped at the point of printing.
  • admin-post.php over the Settings API. The page needs custom side effects (live key validation, cache flush, two separate buttons), which are clearer to express with explicit nonce-protected handlers.

Coding standards & debugging

  • Sanitization on all input, escaping on all output, nonces on every form, manage_options capability checks on admin actions.
  • Activates cleanly with WP_DEBUG = true — no notices or warnings.

Possible improvements (given more time)

  • Gutenberg block wrapping the shortcode with live preview controls.
  • Merge multiple calendars into one chronologically-sorted list.
  • Group events by day with date headings.
  • AJAX "Load more" pagination using the Calendar API pageToken.
  • PHPUnit / WP test suite and PHPCS (WordPress-Extra) wired into CI.
  • Stale-while-revalidate caching — serve the old cache instantly and refresh in the background via WP-Cron.

AI assistance declaration

See AI-DECLARATION.md.

Read the full README on GitHub →