WP Manifestindependent plugin directory
manifest / events / parish-events

Parish Events & Programs releasesself-updates

WordPress plugin importing parish calendar events from a CCB feed into a custom post type with scheduled sync, structured data, and display shortcodes.

by St. Paul the Apostle Catholic Church · github.com/wakcyscanner/parish-events · website

0stars
38release downloads
0forks

Install

The author publishes release zips, so WP-CLI can install straight from GitHub:

wp plugin install https://github.com/wakcyscanner/parish-events/releases/download/v1.3.0/parish-events-1.3.0.zip

Ships its own WordPress updater (built-in updater), so new versions show up under Dashboard → Updates.

Readme

Parish Events & Programs

A WordPress plugin that turns a parish calendar feed into real WordPress content. It imports events from a Church Community Builder (CCB) XML feed into a custom post type on a schedule, giving every event a permanent URL, search-engine structured data, and full editorial control — replacing client-side calendar embeds.

It also provides Programs: hand-authored sets of events packaged together for promotion, displayed as card grids or carousels. See Programs.

Requires: WordPress 6.0+, PHP 7.4+ · License: GPLv2 or later

Installable zips are published under Releases.

Features

Import & sync

  • Scheduled import (hourly to daily, or on demand) of the current month plus the next two, directly from the Pushpay ChMS v1 API (public_calendar_listing, HTTP Basic Auth) — or from any custom proxy endpoint returning the same XML. Credentials live in Settings or, preferably on production, in PE_CHMS_SUBDOMAIN / PE_CHMS_USERNAME / PE_CHMS_PASSWORD wp-config constants that keep the secret out of the database.
  • One parish_event post per occurrence, keyed by CCB event ID + date — upstream edits update the same post and its URL never changes.
  • Safe by design: a failed, empty, or malformed fetch never removes anything; unchanged feeds produce zero writes; past events are never touched.
  • Import failure alerts by email (after three consecutive failed runs, with a recovery notice), plus a run log in the settings screen.
  • Only text wrapped in [public]...[/public] in the feed description is published. Internal staff notes are never stored in WordPress, and leader contact details are visible to admins only.

Event lifecycle

  • Events deleted upstream move to a Removed upstream status — never deleted. Their pages show a neutral "no longer listed" notice for a grace period, then return 410 Gone.
  • Removed is not cancelled: marking an event cancelled is an explicit checkbox that switches the notice and emits schema.org EventCancelled markup. Absence from the feed is never assumed to mean cancelled.
  • If a suppression rule with a link later covers an already-imported series, those posts' URLs permanently redirect (301) to the rule's destination, so saved bookmarks and indexed links keep working.
  • Events that return to the feed are restored automatically.

Editorial control

  • Manual override flag per event: imports stop touching every field, and the date, times, location, group, and type become editable alongside the content (block editor supported).
  • Always editable, override or not: featured image, featured flag, cancelled flag, a featured video slot (YouTube/Vimeo URL shown above the details), an event flyer image slot (shown below the details, linked to full size), a registration/RSVP link (shown as a button; the feed has no sign-up field), and an optional cost field (shown in the details and reflected in structured data).
  • Admin list table with event date sorting, sync-status column, flag icons, and filters by event month, group, and upcoming/past.

Suppression & locations

  • Suppression rules (by CCB event ID, exact title, or title keyword) stop recurring events like daily Mass from generating hundreds of posts. Suppressed occurrences still appear on the calendar, linking to a single URL you choose per rule (for example, a Mass times page).
  • Location directory: give each location a link to its own page, or an expandable "where is this?" description shown wherever the location appears. Global and per-event location substitutions clean up raw feed values.

Display

  • [parish_events_calendar] — server-rendered list and month views with a group filter and month navigation. No JavaScript framework, crawlable, cached.
  • [parish_events_featured] — card grid of featured upcoming events.
  • [parish_events_upcoming] — compact list of the next events (also available as a widget).
  • [parish_events_subscribe] — calendar subscribe button.

Calendar integration & SEO

  • "Add to calendar (.ics)" and "Google Calendar" buttons on every upcoming event page.
  • Subscribable webcal/ICS feed of all published events at /?pe_ics=feed. The feed body is cached server-side, served with Cache-Control: public and an ETag (so polling calendar apps get cheap 304s), and refreshes whenever an import changes content.
  • Schema.org Event JSON-LD, Open Graph, and Twitter meta tags on single event pages.
  • wp parish-events import WP-CLI command (non-zero exit on failure) and wp parish-events status for recent runs.

Programs

A program is a set of events packaged together for promotion — "Financial Peace University", "That Man is You!", an adoration chapel signup. Unlike calendar events they are hand-authored, have no upstream feed, and have no pages of their own: every card links out to a ministry or registration page.

  • Separate parish_program post type, edited under Programs. Title, description, image, an optional free-text schedule line ("Tuesdays · Aug 4 – Oct 6 · 6:30 PM"), and a link with custom button text.
  • Program Groups taxonomy for sectioning ("Upcoming Series", "Grow in Community"), and drag-free ordering via the Order field.
  • Display as a card grid or carousel with [parish_programs], the Parish Programs block, or homepage injection — a CSS-selector-based insert for themes whose homepage template can't be edited.
  • Settings under Programs → Settings, kept separate from calendar settings.
  • wp parish-programs import --from=<url-or-path> migrates programs from the legacy Come to Me programs.json, sideloading images into the media library.

Programs are deliberately not stored as parish events. Events are feed-owned — the importer reconciles them against ChMS on every run and marks rows Removed upstream when they disappear — so hand-authored rows in that post type would be reconciled away. The importer is scoped to the event post type throughout, so the two features never touch.

Installation

  1. Download the latest parish-events-x.y.z.zip from Releases.
  2. In wp-admin, go to Plugins → Add New Plugin → Upload Plugin, and upload the zip (uploading a newer zip over an existing install upgrades it in place).
  3. Activate. The plugin flushes rewrite rules on activation; if event URLs 404, re-save Settings → Permalinks once.
  4. Configure Parish Events → Settings: ChMS subdomain + API credentials (or a legacy custom feed URL), schedule, suppression rules, location directory, and alert emails.

After the initial install, updates arrive like any other plugin: the plugin checks this repo's Releases and offers new versions on the Plugins screen, where they can be installed in one click (or auto-updated, if enabled).

Release channels

There are two update channels:

  • Stable (the default) — sees full releases only. Production sites stay here.
  • Beta — additionally sees pre-releases. Enable it per site with the "Receive beta updates" checkbox in Parish Events → Settings. Meant for staging sites; a stable release newer than the newest beta always wins.

The development flow behind that:

  1. Feature work lands on the beta branch and ships as a pre-release: version like 1.1.0-beta.1, tag v1.1.0-beta.1. Any tag containing a hyphen publishes as a GitHub prerelease, which the stable channel never sees.
  2. Staging (on the beta channel) receives it as a normal plugin update and soaks it.
  3. When it's proven, beta merges to main and ships as a stable release (1.1.0, tag v1.1.0) — production picks it up.

Both channels use the same release workflow: bump the plugin Version header, add a CHANGELOG.md section for the version, and push the matching tag.

Launch checklist

  1. The plugin claims the /events/ URL base for event posts. If another plugin or page already serves /events/, resolve that first: deactivate the conflicting plugin, or keep a page at /events/ and put the [parish_events_calendar] shortcode in it — the page URL and the post type coexist.
  2. Review the settings, then click Run import now and spot-check a few event pages and the admin list.
  3. Place [parish_events_calendar] on your calendar page and [parish_events_featured] wherever featured cards should appear.
  4. Set up a real cron job: WordPress cron only fires on site visits, which is unreliable on low-traffic sites. Either have the host request wp-cron.php every 15 minutes and set define( 'DISABLE_WP_CRON', true ); in wp-config.php, or point a system cron job at wp parish-events import directly.
  5. If the site sits behind Cloudflare (or another CDN), add a cache rule for the ICS subscribe feed so calendar-app polling is absorbed at the edge instead of hitting PHP: cache URLs whose query string contains pe_ics=feed, respecting the origin cache headers (the plugin sends Cache-Control: public, max-age=900, s-maxage=3600 plus an ETag). CDNs don't cache this URL by default because of the query string.
  6. Once satisfied, remove any old calendar embed the plugin replaces.
  7. Keep calendar customizations in this plugin (or a site plugin), not in theme files, so theme updates can't overwrite them.

Shortcodes

[parish_events_calendar view="list" months="2" group="" show_filter="1" show_toggle="1"]
[parish_events_featured count="3" order="date" columns="3" show_excerpt="1"]
[parish_events_upcoming count="5" show_location="0"]
[parish_events_subscribe label="Subscribe to calendar"]
[parish_programs layout="grid" count="0" heading="" align="" group="" groups=""]

[parish_programs]: layout is grid or carousel; count="0" shows all; group filters to one Program Group slug; groups renders one titled section per group (comma-separated slugs, or all) and takes precedence over group.

FAQ

Imports aren't running on schedule. See step 4 of the launch checklist — use a real cron job instead of visit-driven WordPress cron.

An event I edited got flagged "missing upstream". The event has the manual-override flag and disappeared from the feed. Decide whether to unpublish it yourself or leave it; imports won't touch it either way.

Why did a suppressed event's old page start redirecting? A suppression rule with a link URL now covers it. The redirect preserves saved bookmarks and search results by sending them to the rule's destination.

Changelog

See Releases for per-version notes.

Read the full README on GitHub →

Releases

TagPublishedAssetDownloads
v1.3.0 Aug 5, 2026 parish-events-1.3.0.zip 2
v1.3.0-beta.8 Jul 31, 2026 parish-events-1.3.0-beta.8.zip 1
v1.3.0-beta.7 Jul 31, 2026 parish-events-1.3.0-beta.7.zip 1
v1.3.0-beta.6 Jul 31, 2026 parish-events-1.3.0-beta.6.zip 1
v1.3.0-beta.5 Jul 31, 2026 parish-events-1.3.0-beta.5.zip 1
v1.3.0-beta.4 Jul 31, 2026 parish-events-1.3.0-beta.4.zip 1
v1.3.0-beta.3 Jul 31, 2026 parish-events-1.3.0-beta.3.zip 1
v1.3.0-beta.2 Jul 31, 2026 parish-events-1.3.0-beta.2.zip 1
v1.3.0-beta.1 Jul 31, 2026 parish-events-1.3.0-beta.1.zip 2
v1.2.1 Jul 31, 2026 parish-events-1.2.1.zip 1
v1.2.0 Jul 22, 2026 parish-events-1.2.0.zip 3
v1.2.0-beta.2 Jul 22, 2026 parish-events-1.2.0-beta.2.zip 2
v1.2.0-beta.1 Jul 22, 2026 parish-events-1.2.0-beta.1.zip 2
v1.1.0 Jul 22, 2026 parish-events-1.1.0.zip 3
v1.1.0-beta.2 Jul 22, 2026 parish-events-1.1.0-beta.2.zip 2
v1.0.13 Jul 17, 2026 parish-events-1.0.13.zip 3
v1.0.12 Jul 17, 2026 parish-events-1.0.12.zip 2
v1.0.11 Jul 17, 2026 parish-events-1.0.11.zip 2
v1.0.10 Jul 16, 2026 parish-events-1.0.10.zip 3
v1.0.9 Jul 16, 2026 parish-events-1.0.9.zip 1
v1.0.8 Jul 16, 2026 parish-events-1.0.8.zip 3