{"id":310379,"date":"2026-06-15T17:13:18","date_gmt":"2026-06-15T17:13:18","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/sermon-works\/"},"modified":"2026-06-15T17:12:50","modified_gmt":"2026-06-15T17:12:50","slug":"mattytap-sermons","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/mattytap-sermons\/","author":23496046,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"3.1.2","stable_tag":"3.1.2","tested":"7.0","requires":"6.0","requires_php":"8.1","requires_plugins":null,"header_name":"Mattytap Sermons","header_author":"Matt Fawcett (restoration); WP for Church (original)","header_description":"A maintained restoration of WP-for-Church's Sermon Manager: add audio and video sermons, manage preachers, series, and more.","assets_banners_color":"1f2a44","last_updated":"2026-06-15 17:12:50","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/github.com\/mattytap\/Mattytap-Sermons","header_author_uri":"https:\/\/github.com\/mattytap","rating":0,"author_block_rating":0,"active_installs":0,"downloads":15,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"3.1.2":{"tag":"3.1.2","author":"mattytap","date":"2026-06-15 17:12:50"}},"upgrade_notice":{"3.1.2":"<p>Security hardening: output escaping on sermon templates and validation of the debug update-runner. No functional or data change; safe upgrade from 3.1.x.<\/p>","3.1.1":"<p>Completes the plugin rename in user-visible admin text. No functional or data change; safe upgrade from 3.1.<\/p>","3.1":"<p>First stable release of Mattytap Sermons. No data migration. Existing 3.0.x and Sermon Works installs migrate by deactivating the old plugin and activating Mattytap Sermons; existing Sermon Manager installs (including 2.30.0) can switch as a drop-in replacement.<\/p>","3.1-rc3":"<p>Fixes a sermon-export fatal on WordPress 6.0 through 6.8 (the exporter called a function only added in WordPress 6.9). No data migration. Sites on WordPress 6.9 or later are unaffected.<\/p>","3.1-rc2":"<p>Three rc1 playback and widget regressions fixed: YouTube embed seek-on-load no longer throws after the Plyr 3.7 upgrade; <code>\/<\/code> elements again include their <code>children; the sermon archive sort widget renders its<\/code> tags. No data migration.<\/p>","3.1-rc1":"<p>Plugin renamed from Sermon Works to Mattytap Sermons under the WordPress.org slug <code>mattytap-sermons<\/code>. Database, content, post type, taxonomies, and front-end render unchanged. Migrate by activating Mattytap Sermons and deactivating Sermon Works. Also closes ten technical items raised by the WordPress.org plugin reviewer&#039;s automated pre-review of 3.0.2.<\/p>","3.0.2":"<p>Editor-pane render fix following 3.0.1. Content typed into the WordPress editor on the edit-sermon screen now renders on the front-end alongside the existing <code>sermon_description<\/code> rendering. Existing sermons unaffected; no data migration.<\/p>","3.0.1":"<p>Drop-in compatibility cherry-picks from upstream 2.30.0: multi-attachments rendering for notes and bulletin (closes a render gap on sites that ran the upstream multi-attachments migration), post-body editor support, and Twenty Twenty-Four theme wrapper. Database and front-end render unchanged for existing sites.<\/p>","3.0":"<p>Plugin renamed from Sermon Manager to Sermon Works; database and content unchanged. Migrate by activating Sermon Works and deactivating Sermon Manager. Includes fixes for three CVEs filed against the upstream Sermon Manager codebase.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3573498,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3573498,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3573498,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3573498,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["3.1.2"],"block_files":[],"assets_screenshots":[],"screenshots":{"1":"Sermon Details","2":"Sermon Files"}},"plugin_section":[],"plugin_tags":[452,6970,238,55653,17517],"plugin_category":[39,50,56],"plugin_contributors":[267278],"plugin_business_model":[],"class_list":["post-310379","plugin","type-plugin","status-publish","hentry","plugin_tags-audio","plugin_tags-church","plugin_tags-podcast","plugin_tags-preaching","plugin_tags-sermon","plugin_category-business","plugin_category-media","plugin_category-social-and-sharing","plugin_contributors-mattytap","plugin_committers-mattytap"],"banners":{"banner":"https:\/\/ps.w.org\/mattytap-sermons\/assets\/banner-772x250.png?rev=3573498","banner_2x":"https:\/\/ps.w.org\/mattytap-sermons\/assets\/banner-1544x500.png?rev=3573498","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/mattytap-sermons\/assets\/icon-128x128.png?rev=3573498","icon_2x":"https:\/\/ps.w.org\/mattytap-sermons\/assets\/icon-256x256.png?rev=3573498","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>Mattytap Sermons lets a church publish sermons online with the structure they actually need: speakers, series, topics, books of the Bible, and service types, all as proper WordPress taxonomies, all searchable, all filterable. Add audio and video, attach handouts (PDF, DOC, PPT, anything), embed video from YouTube or Vimeo, and ship a fully-featured iTunes-compatible podcast feed for the whole library or for any individual series, speaker, topic, or book.<\/p>\n\n<p>Mattytap Sermons is a maintained restoration of <a href=\"https:\/\/wordpress.org\/plugins\/sermon-manager-for-wordpress\/\">Sermon Manager<\/a> by WP for Church. The original plugin was last published to WordPress.org in September 2024 (version 2.30.0); the upstream maintainer's web presence is no longer reachable, and several publicly-disclosed CVEs remain unpatched in 2.30.0 and earlier. Mattytap Sermons is the successor line. Existing Sermon Manager installs (including 2.30.0) can switch to Mattytap Sermons as a drop-in replacement: the database schema, custom post type (<code>wpfc_sermon<\/code>), taxonomies (<code>wpfc_preacher<\/code>, <code>wpfc_sermon_series<\/code>, etc.), all <code>wpfc_*<\/code> option keys, six core shortcodes, and view templates are preserved. Multi-attachments for notes and bulletin, post-body editor support, and Twenty Twenty-Four theme wrapper are cherry-picked from upstream 2.30.0.<\/p>\n\n<h4>What Mattytap Sermons preserves<\/h4>\n\n<ul>\n<li>Same shortcodes (<code>[sermons]<\/code>, <code>[sermon_images]<\/code>, <code>[list_podcasts]<\/code>, <code>[list_sermons]<\/code>, <code>[latest_series]<\/code>, <code>[sermon_sort_fields]<\/code>)<\/li>\n<li>Same custom post type and taxonomies: existing sermon data carries over without import<\/li>\n<li>Same template files in <code>views\/<\/code>: existing theme overrides continue to work<\/li>\n<li>Same Bib.ly Bible-reference integration<\/li>\n<li>Same iTunes-compatible podcast feeds<\/li>\n<\/ul>\n\n<h4>What's new in Mattytap Sermons<\/h4>\n\n<ul>\n<li>Active security maintenance, with <a href=\"https:\/\/github.com\/mattytap\/Mattytap-Sermons\/security\">private vulnerability reporting<\/a> for responsible disclosure<\/li>\n<li>Modernised for PHP 8.1+ and WordPress 6.0+<\/li>\n<li>Bundled outdated third-party dependencies removed or upgraded (CMB2, wp-background-processing, the entry-views polyfill, taxonomy-images)<\/li>\n<li>Continuing development on <a href=\"https:\/\/github.com\/mattytap\/Mattytap-Sermons\">GitHub<\/a><\/li>\n<\/ul>\n\n<h4>Popular shortcodes<\/h4>\n\n<ul>\n<li><code>[sermons]<\/code>: list the 10 most recent sermons<\/li>\n<li><code>[sermons per_page=\"20\"]<\/code>: list the 20 most recent sermons<\/li>\n<li><code>[sermon_images]<\/code>: list all sermon series with associated image in a grid<\/li>\n<li><code>[list_podcasts]<\/code>: list available podcast services with large buttons<\/li>\n<li><code>[list_sermons]<\/code>: list all series or speakers in a simple unordered list<\/li>\n<li><code>[latest_series]<\/code>: display information about the latest sermon series, including the image, title, and description<\/li>\n<li><code>[sermon_sort_fields]<\/code>: dropdown selections to navigate to sermons by series or speaker<\/li>\n<\/ul>\n\n<h3>Credits<\/h3>\n\n<p>Mattytap Sermons is a restoration of <a href=\"https:\/\/wordpress.org\/plugins\/sermon-manager-for-wordpress\/\">Sermon Manager for WordPress<\/a>, originally by WP for Church (Jason Westbrook and contributors). The full upstream contributor list is recorded in <a href=\"https:\/\/github.com\/mattytap\/Mattytap-Sermons\/blob\/main\/CONTRIBUTORS.md\">CONTRIBUTORS.md<\/a>. Translations were originally contributed by GITNE (German, Polish), Gilles Pilloud (French), and the Dutch translation behind v2.15.13.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Use the \"Add New\" button in the Plugins section of your WordPress dashboard. Search for \"Mattytap Sermons\".<\/li>\n<li>Activate the plugin.<\/li>\n<li>Add a sermon through the dashboard.<\/li>\n<li>Display sermons on the front end via shortcode (<code>[sermons]<\/code> in any page or post), or by visiting <code>https:\/\/yourdomain.example\/sermons<\/code> (with pretty permalinks enabled) or <code>https:\/\/yourdomain.example\/?post_type=wpfc_sermon<\/code> (without).<\/li>\n<\/ol>\n\n<h4>Migrating from Sermon Manager<\/h4>\n\n<p>If you have an existing Sermon Manager install, install and activate Mattytap Sermons, then deactivate Sermon Manager. All your sermons, speakers, series, topics, and settings carry over without further action. The two plugins use the same database schema. Don't run both at once; the schema overlap will cause conflicts.<\/p>\n\n<h4>Migrating from Sermon Browser or Series Engine<\/h4>\n\n<p>Mattytap Sermons inherits Sermon Manager's import functionality for these older sermon plugins. Once Mattytap Sermons is activated, the importer is available under Tools \u2192 Import.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"how%20do%20i%20display%20sermons%20on%20the%20front%20end%3F\"><h3>How do I display sermons on the front end?<\/h3><\/dt>\n<dd><p>Use the shortcode <code>[sermons]<\/code> in any page or post, or visit <code>https:\/\/yourdomain.example\/sermons<\/code> (with pretty permalinks enabled) or <code>https:\/\/yourdomain.example\/?post_type=wpfc_sermon<\/code> (without).<\/p><\/dd>\n<dt id=\"how%20do%20i%20create%20a%20menu%20link%20to%20the%20sermons%20archive%3F\"><h3>How do I create a menu link to the sermons archive?<\/h3><\/dt>\n<dd><p>Go to Appearance \u2192 Menus. In \"Custom Links\" add <code>https:\/\/yourdomain.example\/?post_type=wpfc_sermon<\/code> as the URL and \"Sermons\" as the label. Click \"Add to Menu\".<\/p><\/dd>\n<dt id=\"i%27m%20coming%20from%20sermon%20manager.%20will%20my%20sermons%20survive%3F\"><h3>I'm coming from Sermon Manager. Will my sermons survive?<\/h3><\/dt>\n<dd><p>Yes. Mattytap Sermons uses the same database schema, custom post type, taxonomies, and option keys as Sermon Manager. Activate Mattytap Sermons, deactivate Sermon Manager, and existing sermons keep working. Don't run both at once. The overlapping schema will conflict.<\/p><\/dd>\n<dt id=\"how%20do%20i%20report%20a%20bug%20or%20request%20a%20feature%3F\"><h3>How do I report a bug or request a feature?<\/h3><\/dt>\n<dd><p><a href=\"https:\/\/github.com\/mattytap\/Mattytap-Sermons\/issues\">GitHub Issues<\/a>. For security issues, please use <a href=\"https:\/\/github.com\/mattytap\/Mattytap-Sermons\/security\/advisories\/new\">private vulnerability reporting<\/a> rather than public issues.<\/p><\/dd>\n<dt id=\"is%20there%20a%20paid%20version%20or%20commercial%20support%3F\"><h3>Is there a paid version or commercial support?<\/h3><\/dt>\n<dd><p>No. Mattytap Sermons is GPLv2 free software with no paid tier, no premium add-ons, and no commercial support. Bug fixes, feature requests, and translation contributions are welcome through GitHub.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>3.1.2<\/h4>\n\n<ul>\n<li>Hardened the \"Specific Background Updates\" debug tool: the submitted value is now validated against the registered list of update routines before anything is executed.<\/li>\n<li>Escaping pass over filtered template output: the previous\/next sermon navigation links, the deprecated v1 sermon renderers, the <code>[sermons]<\/code> shortcode's per-sermon output, and the preacher-image filter on archive cards are now escaped at output with <code>wp_kses<\/code>. The sermon-template allowlist now admits provider iframes so pasted video embed codes continue to render.<\/li>\n<li>The Uncode theme-compatibility init call is now printed via <code>wp_print_inline_script_tag()<\/code> instead of a hand-built script tag.<\/li>\n<\/ul>\n\n<h4>3.1.1<\/h4>\n\n<ul>\n<li>Completed the Mattytap Sermons rename in user-visible admin text. The settings and Import\/Export screens, the plugins-page action link, several settings descriptions, and two front-end error messages still displayed \"Sermon Works\"; all now read \"Mattytap Sermons\". The settings page heading is now also translatable.<\/li>\n<li>Fixed a PHP warning (undefined array key \"display\") in the <code>[sermon_images]<\/code> shortcode when no matching term images exist.<\/li>\n<li>Replaced <code>wp_reset_query()<\/code> with <code>wp_reset_postdata()<\/code> after the podcast feed's secondary loop, the correct reset for a custom WP_Query.<\/li>\n<\/ul>\n\n<h4>3.1<\/h4>\n\n<p>First stable release of the renamed Mattytap Sermons line, and the first WordPress.org submission. No runtime change against 3.1-rc3: this entry promotes the release-candidate cycle to stable. The rc1, rc2, and rc3 entries below record the rename from Sermon Works, the ten WordPress.org pre-review fixes, the three rc1 playback and widget regressions, and the WordPress 6.0 to 6.8 export-compatibility fix closed during the candidate cycle.<\/p>\n\n<h4>3.1-rc3<\/h4>\n\n<ul>\n<li>Fixed a WordPress 6.0 to 6.8 compatibility regression in the sermon exporter. <code>wxr_cdata()<\/code> guarded its encoding fallback with <code>wp_is_valid_utf8()<\/code>, a function only available since WordPress 6.9, which would fatal on older supported versions. Switched to <code>mb_check_encoding()<\/code>, restoring the declared WordPress 6.0 floor. Sites on WordPress 6.9 or later were unaffected.<\/li>\n<li>Raised \"Tested up to\" to WordPress 7.0.<\/li>\n<li>Plugin Check housekeeping in the WXR exporter, a near-verbatim port of WordPress core's <code>wp-admin\/includes\/export.php<\/code>: scoped the self-escaping <code>wxr_cdata()<\/code> output under a documented escape-sniff exemption, and annotated a prepared query the analyser misread as unprepared. No runtime change.<\/li>\n<\/ul>\n\n<h4>3.1-rc2<\/h4>\n\n<p>Three regressions surfaced during 3.1-rc1 LocalWP canary verification.<\/p>\n\n<ul>\n<li>Plyr 3.5+ removed <code>embed.setCurrentTime()<\/code> from the YouTube embed surface; the seek-on-load handler in <code>assets\/js\/plyr.js<\/code> was still calling it directly after setting <code>instance.currentTime<\/code> via Plyr's high-level API. Dropped the redundant embed-direct call: the high-level setter handles seek normalisation across HTML5, YouTube, and Vimeo in 3.7.x.<\/li>\n<li>The F-escape sweep's <code>sm_template_allowed_html()<\/code> helper didn't whitelist <code>&lt;source&gt;<\/code> as an allowed child of <code>&lt;audio&gt;<\/code> and <code>&lt;video&gt;<\/code>, so every <code>&lt;source&gt;<\/code> child was stripped silently when the audio\/video render passed through <code>wp_kses()<\/code>. Audio and video elements rendered as empty shells with no playable source. Added <code>&lt;source&gt;<\/code> with <code>src<\/code>, <code>type<\/code>, <code>media<\/code>, <code>srcset<\/code>.<\/li>\n<li>The same helper covered <code>&lt;select&gt;<\/code> for the <code>onchange<\/code> attribute only and didn't whitelist <code>&lt;option&gt;<\/code>, <code>&lt;form&gt;<\/code>, or the rest of <code>&lt;select&gt;<\/code>'s attribute set. The sermon archive sort widget and the five taxonomy templates rendered as bare <code>&lt;select onchange=\"...\"&gt;<\/code> shells with no <code>&lt;option&gt;<\/code> tags. Added the form-element family.<\/li>\n<\/ul>\n\n<h4>3.1-rc1<\/h4>\n\n<p>First release-candidate of the renamed line. Sermon Works has been renamed to Mattytap Sermons under the WordPress.org slug <code>mattytap-sermons<\/code> following plugin-team trademark guidance against the prior name. Strapline updated to \"Faithful to the source.\" Same caretaker, same codebase, same migration path; existing 3.0.x installs upgrade in place.<\/p>\n\n<p>This release also closes the ten technical items the WordPress.org reviewer's automated pre-review flagged against the 3.0.2 submission:<\/p>\n\n<ul>\n<li>Removed the <code>load_plugin_textdomain<\/code> call (WordPress.org auto-loads translations since WP 4.6).<\/li>\n<li>Replaced PHP 8.2-deprecated <code>utf8_encode<\/code> with <code>mb_convert_encoding<\/code> in the WXR exporter's UTF-8 fallback branch.<\/li>\n<li>Added <code>sanitize_text_field( wp_unslash() )<\/code> on the defence-in-depth <code>$_REQUEST['_wpnonce']<\/code> read in the settings save-handler.<\/li>\n<li>Added <code>esc_url_raw( wp_unslash() )<\/code> on the <code>$_SERVER['REQUEST_URI']<\/code> read in the import form action.<\/li>\n<li>Removed the unpaired <code>ob_start()<\/code> at <code>admin_init<\/code> priority 1. The other twelve <code>ob_start()<\/code> sites in the codebase are properly paired with <code>ob_end_flush()<\/code> and continue to work as before.<\/li>\n<li>Annotated 45 reviewer-flagged sites carrying legacy upstream <code>wpfc_*<\/code> \/ <code>wp_sm_*<\/code> \/ <code>sm_*<\/code> prefixes with <code>phpcs:ignore<\/code> plus rationale comments. The prefixes themselves are preserved deliberately for drop-in compatibility with Sermon Manager.<\/li>\n<li>Applied <code>wp_kses()<\/code> and friends at 40 sites across 11 view templates in <code>views\/<\/code>. A small helper <code>sm_template_allowed_html()<\/code> extends <code>wp_kses_allowed_html('post')<\/code> for Plyr <code>data-*<\/code> attributes and audio\/video element attributes the default kses table strips. Five genuinely-unfixable sites (CDATA-wrapped strings and attribute-fragment echoes) are left annotated with rationale.<\/li>\n<li>Wrapped editor-pane content in <code>wp_kses_post()<\/code> in the <code>the_content<\/code> filter callback. The <code>[list_podcasts]<\/code> shortcode is now internationalised via <code>__()<\/code> \/ <code>sprintf()<\/code> and its return value wrapped in <code>wp_kses_post()<\/code> so static scanners see an explicit escaper at the function boundary.<\/li>\n<li>Consolidated the Plyr enqueue path in <code>sermons.php<\/code>: replaced two <code>wp_localize_script<\/code> calls with <code>wp_add_inline_script<\/code>; dropped <code>maybe_print_cloudflare_plyr<\/code> and its manual <code>&lt;script data-cfasync=\"false\"&gt;<\/code> echo in favour of a <code>script_loader_tag<\/code> filter that injects the attribute on the two Plyr handles. Hoisted the dashboard \"At a Glance\" widget's inline <code>&lt;style&gt;<\/code> block to <code>wp_add_inline_style<\/code> against the dashicons handle. The two <code>UNCODE.initHeader()<\/code> inline-script sites in the Uncode theme branch remain inline with <code>phpcs:ignore<\/code> plus rationale: those calls fire at a mid-body DOM position the Uncode theme's header initialisation depends on.<\/li>\n<li>Refreshed bundled vendor libraries: Plyr 3.4.7 \u2192 3.7.8 (verbatim swap from the upstream npm tarball; no JS-API breaking changes; the 3.7.x line includes preview-thumbnail, focus-visible, and border-radius CSS updates which are absorbed automatically because we ship the precompiled CSS from the same release). wp-color-picker-alpha 2.1.3 \u2192 3.0.4 (verbatim swap from upstream <code>main<\/code>; the 3.0.x line is a full rewrite that drops the WordPress 5.5-removed <code>wpColorPickerL10n<\/code> global dependency. No runtime delta in this plugin because the script is dead code: no CMB2 colorpicker field in the codebase sets <code>'alpha' =&gt; true<\/code>).<\/li>\n<\/ul>\n\n<p>Drop-in compatibility ethic preserved: the <code>wpfc_sermon<\/code> custom post type, the <code>wpfc_preacher<\/code> and <code>wpfc_sermon_series<\/code> taxonomies, and all <code>wpfc_*<\/code> option keys are unchanged. Existing Sermon Manager (or 3.0.x Sermon Works) installs continue to migrate without data loss.<\/p>\n\n<h4>3.0.2<\/h4>\n\n<p>Editor-pane render fix following the 3.0.1 cherry-pick of <code>'editor'<\/code> into the <code>wpfc_sermon<\/code> post type's <code>supports<\/code> array. In 3.0.1 the WordPress block (or classic) editor pane was visible on the edit-sermon screen but content typed there did not reach the front-end: the <code>add_wpfc_sermon_content<\/code> callback that drives the <code>the_content<\/code> filter for sermon posts replaced the post body entirely with the sermon-template render, discarding <code>post_content<\/code>. Site administrators reaching for the editor pane first (the natural place for any WordPress user) would publish a sermon and see their typed content vanish on the public page.<\/p>\n\n<p>3.0.2 closes this. The callback now preserves the incoming <code>post_content<\/code> and, on singular sermon views where it is non-empty, appends it after the sermon-template render in a <code>&lt;div class=\"wpfc-sermon-editor-content\"&gt;<\/code> wrapper that themes can target. Existing sermons (whose body content lives in the <code>sermon_description<\/code> post meta key, not in <code>post_content<\/code>) are unaffected: their <code>post_content<\/code> is empty, the conditional skip fires, and the front-end render is byte-identical to 3.0.1. New sermons authored via the editor pane now render their content alongside the legacy <code>sermon_description<\/code> rendering.<\/p>\n\n<p>No security delta against 3.0.1; no API surface changes; no data migration. Single-file change in <code>includes\/sm-template-functions.php<\/code>.<\/p>\n\n<h4>3.0.1<\/h4>\n\n<p>Drop-in compatibility cherry-picks from upstream Sermon Manager 2.30.0 (the last WP.org-shipped version of the original plugin), informed by a 10-surface compatibility audit against the 2.30.0 baseline (<code>.restoration\/DROP-IN-AUDIT.md<\/code>):<\/p>\n\n<ul>\n<li>Multi-attachments for notes and bulletin: the front-end view template now renders the <code>sermon_notes_multiple<\/code> and <code>sermon_bulletin_multiple<\/code> arrays alongside the singular keys. Existing 2.30.0 sites that ran the upstream multi-attachments migration have data in the <code>_multiple<\/code> keys; this restores their visibility on the front-end. Two new <code>file_list<\/code> CMB2 fields (\"Sermon Notes (multiple)\", \"Bulletin (multiple)\") are added to the Sermon Files metabox so Sermon Works admins can also create new multi-attachments themselves.<\/li>\n<li>Post-body editor support: <code>'editor'<\/code> is added to the <code>wpfc_sermon<\/code> post type's <code>supports<\/code> array, enabling the WordPress block (or classic) editor on the edit-sermon screen. The Sermon Works rendering model continues to use <code>sermon_description<\/code> plus the <code>the_content<\/code> filter; existing sermons render unchanged. New sermons created post-3.0.1 can populate <code>post_content<\/code> via the editor pane in addition to <code>sermon_description<\/code>.<\/li>\n<li>Twenty Twenty-Four theme wrapper: the theme-specific archive wrapper now has a balanced <code>twentytwentyfour<\/code> case opening <code>&lt;div class=\"wp-block-group has-global-padding is-layout-constrained ...\"&gt;&lt;div id=\"primary\"&gt;&lt;main class=\"site-main wpfc-sermon-container wpfc-twentytwentyfour ...\"&gt;<\/code> and the matching close in the wrapper-end partial. Upstream 2.30.0 ships unbalanced (no matching close); Sermon Works ships balanced.<\/li>\n<\/ul>\n\n<p>Three upstream changes from 2.30.0 are deliberately not cherry-picked, with rationale documented in <code>.restoration\/DROP-IN-AUDIT.md<\/code>:<\/p>\n\n<ul>\n<li>The full editor-support cluster (REST surface change, <code>the_content<\/code> filter disablement, AJAX <code>update_sermon_posts<\/code> migration with \"Sync Now\" button): the upstream rendering-model swap from <code>sermon_description<\/code> to <code>post_content<\/code> is invasive, partial cherry-picks risk broken rendering, and the upstream migration has quality issues (missing capability check, debug residue, no rollback UI). Sermon Works keeps the sermon_description-based rendering model.<\/li>\n<li>The <code>[latest_sermon]<\/code> shortcode: the upstream handler has three known bugs (orderby attribute silently ignored due to a typo in query-args assembly, duplicate HTML id on a nested div, static-property side effects that persist across requests). Use <code>[sermons per_page=\"N\" order=\"DESC\" orderby=\"date\"]<\/code> for the same effect.<\/li>\n<\/ul>\n\n<p>Framing correction in README and readme.txt: the original Sermon Manager line was actively maintained on WordPress.org through September 2024 (last published version 2.30.0). The \"abandoned since 2019\" framing in pre-3.0.1 docs was based on the GitHub state and missed the WP.org line.<\/p>\n\n<h4>3.0<\/h4>\n\n<p>3.0 stable cut. No runtime changes against rc6. This entry promotes the release-candidate cycle to stable, capping the restoration arc that began in rc1.<\/p>\n\n<h4>3.0-rc6<\/h4>\n\n<p>CI gate clearance for WordPress.org submission, no runtime changes against rc5. The Plugin Check workflow now passes cleanly on <code>main<\/code>. The WXR exporter port (<code>includes\/admin\/export\/class-sm-export-sm.php<\/code>) is excluded at workflow level: it is a near-verbatim derivative of WordPress core's <code>wp-admin\/includes\/export.php<\/code>, and the project's <code>phpcs.xml.dist<\/code> registration of <code>wxr_cdata<\/code> as <code>customAutoEscapedFunctions<\/code> is honoured by local PHPCS but not by the Plugin Check action. Targeted <code>phpcs:ignore<\/code> annotations carrying per-site rationale clear the remaining submission-blocking sniffs: the file-system reads in the PNG\/JPEG dimension sniffers (<code>sm_get_png_dimensions<\/code>, <code>sm_get_jpeg_dimensions<\/code>), the inline Cloudflare-bypass <code>&lt;script&gt;<\/code> tag in the Plyr enqueuer, and the transient-cleanup direct-DB call. The audit-deferred warning tail (REST nonce annotations, superglobal-input sanitisation, db-caching, footer-flag enqueues) rides this submission with <code>ignore-warnings: true<\/code> on the action's pass\/fail logic; warnings still surface in the JSON report for review.<\/p>\n\n<h4>3.0-rc5<\/h4>\n\n<p>WordPress.org submission-ready cut, held back behind one more RC for maintainer verification before the 3.0 stable tag flips. Two work strands gating the stable tag are now closed.<\/p>\n\n<p>Plugin Check \"Bucket B\" output-escaping sweep (317 sites across 28 files): every <code>echo<\/code> and <code>&lt;?= ?&gt;<\/code> site that the WordPress.org reviewer ruleset flagged as <code>WordPress.Security.EscapeOutput.OutputNotEscaped<\/code> now uses a context-appropriate escaper. <code>esc_html<\/code> for text content between tags, <code>esc_attr<\/code> for HTML attribute values, <code>esc_url<\/code> for URLs, <code>(int)<\/code> cast for numeric IDs, <code>wp_kses_post<\/code> for already-built HTML fragments, <code>esc_textarea<\/code> for textarea content, and <code>esc_xml<\/code>-equivalent (<code>esc_html<\/code> plus CDATA wrapping where appropriate) for XML output in the WXR exporter and the iTunes podcast feed. Where <code>wp_kses_post<\/code> would strip needed markup (audio\/video player iframes, Uncode theme integration), per-line <code>phpcs:ignore<\/code> annotations carry the rationale rather than weakening the sniff. The WXR exporter also picks up <code>wxr_cdata<\/code> as a registered custom-auto-escaped function in the project's PHPCS config.<\/p>\n\n<p>Pre-3.0 small fixes pulled forward from the pre-submission audit:<\/p>\n\n<ul>\n<li>Fixed a runtime PHP 8.0+ warning (<code>foreach() argument must be of type array|object, string given<\/code>) in <code>sm-core-functions.php:663<\/code>. The <code>apply_filters( 'sermon-images-get-the-terms', '', ... )<\/code> default value was an empty string; foreach over a string fails on PHP 8.0+. Default coerced to <code>array()<\/code> with a belt-and-braces <code>(array)<\/code> cast on the result.<\/li>\n<li>Added the <code>defined( 'ABSPATH' ) || exit;<\/code> guard to <code>includes\/class-sm-roles.php<\/code> (missed in the rc4 sweep).<\/li>\n<li>Fixed two PHP 8.2 deprecation warnings: <code>\"[${time}]\"<\/code> -&gt; <code>\"[{$time}]\"<\/code> in the Sermon Browser and Sermon Manager importers. Plugin floor stays at PHP 8.1 where this isn't deprecated, but WordPress.org test environments cover 8.2 and 8.3.<\/li>\n<li>Bug fix in the recent-sermons widget admin form: textarea contents for <code>before_widget<\/code> \/ <code>after_widget<\/code> were being echoed as kses-stripped HTML, which renders as visible literal text in a textarea. Now <code>esc_textarea<\/code>, which entity-encodes for the textarea context. Round-trip edit workflow now matches what the user typed at save.<\/li>\n<\/ul>\n\n<h4>3.0-rc4<\/h4>\n\n<p>WordPress.org Plugin Check sweep, \"Bucket A\" mechanical fixes (~70 sites across 10 commits):<\/p>\n\n<ul>\n<li>Plugin header: added <code>License: GPLv2<\/code> and <code>License URI<\/code> lines for WP.org guideline compliance.<\/li>\n<li>Direct file access protection: added <code>defined( 'ABSPATH' ) or die;<\/code> guards to 11 view templates (<code>views\/*.php<\/code>).<\/li>\n<li>Replaced <code>date()<\/code> with <code>gmdate()<\/code> (12 sites) or <code>wp_date()<\/code> (2 user-facing admin column sites) in 9 files. PHP <code>date()<\/code> is affected by <code>date_default_timezone_set()<\/code> and unsafe inside WordPress. Incidentally corrects a latent bug in the RSS feed (<code>pubDate<\/code> and <code>lastBuildDate<\/code> previously claimed <code>+0000<\/code> UTC while passing server-local timestamps).<\/li>\n<li>Replaced <code>parse_url()<\/code> with <code>wp_parse_url()<\/code> (8 sites). WP wrapper suppresses warnings on malformed URLs.<\/li>\n<li>Replaced <code>strip_tags()<\/code> with <code>wp_strip_all_tags()<\/code> (7 sites). WP wrapper additionally strips script\/style tag contents.<\/li>\n<li>Replaced <code>@unlink()<\/code> with <code>wp_delete_file()<\/code> (6 sites in the WXR importer). WP wrapper respects the <code>wp_delete_file<\/code> filter.<\/li>\n<li>Replaced <code>rand()<\/code> with <code>wp_rand()<\/code> (1 site). WP wrapper produces better random numbers.<\/li>\n<li>i18n: added the <code>'sermon-works'<\/code> text-domain argument to 10 <code>__()<\/code> \/ <code>esc_html__()<\/code> calls that previously omitted it (Plugin Check <code>MissingArgDomain<\/code>).<\/li>\n<li>i18n: corrected 9 calls in the WXR importer that used <code>'wordpress-importer'<\/code> instead of <code>'sermon-works'<\/code> as the text-domain (Plugin Check <code>TextDomainMismatch<\/code>).<\/li>\n<li>i18n: added <code>\/* translators: *\/<\/code> comments above 3 placeholder strings (Plugin Check <code>MissingTranslatorsComment<\/code>).<\/li>\n<\/ul>\n\n<p>Tier 2 substantive Plugin Check items (file system operations, prepared SQL audits, enqueued scripts, output escaping) are deferred to a future release; see <a href=\"https:\/\/github.com\/mattytap\/Mattytap-Sermons\/blob\/main\/.restoration\/plugin-check-summary.md\"><code>.restoration\/plugin-check-summary.md<\/code><\/a> for the full triage.<\/p>\n\n<h4>3.0-rc3<\/h4>\n\n<p>Bug fix for installs on case-sensitive filesystems (Linux hosts including most production WordPress hosting):<\/p>\n\n<ul>\n<li>Rename bundled <code>includes\/vendor\/CMB2\/includes\/CMB2_hookup.php<\/code> to <code>CMB2_Hookup.php<\/code> so CMB2's class autoloader can find the file. Without this, activating Sermon Works on a Linux host produced a fatal \"class CMB2_Hookup not found\" error. The casing inconsistency was inherited from the upstream CMB2 v2.11.0 vendor bundle and only manifested on case-sensitive filesystems; Windows and macOS users would not have noticed.<\/li>\n<\/ul>\n\n<h4>3.0-rc2<\/h4>\n\n<p>Salvaged bug-fix PRs from the upstream open-PR backlog, ingested with original authors preserved as git commit authors:<\/p>\n\n<ul>\n<li>Fix shortcode pagination on static front page (upstream PR <a href=\"https:\/\/github.com\/WP-for-Church\/Sermon-Manager\/pull\/274\">#274<\/a> by <a href=\"https:\/\/github.com\/brianfreytag\">@brianfreytag<\/a>).<\/li>\n<li>Defensive guard around the import-message cleanup loop in <code>sermons.php<\/code> (upstream PR <a href=\"https:\/\/github.com\/WP-for-Church\/Sermon-Manager\/pull\/292\">#292<\/a> by <a href=\"https:\/\/github.com\/tstephen\">@tstephen<\/a>). Prevents a PHP 8.x fatal when <code>_sm_import_se_messages<\/code> \/ <code>_sm_import_sb_messages<\/code> options are non-array.<\/li>\n<li>Add French Bible versions (Louis Segond 1910, Segond 21) to the verse-popup settings dropdown (upstream PR <a href=\"https:\/\/github.com\/WP-for-Church\/Sermon-Manager\/pull\/264\">#264<\/a> by <a href=\"https:\/\/github.com\/rjorel\">@rjorel<\/a>).<\/li>\n<\/ul>\n\n<h4>3.0-rc1: Sermon Works restoration<\/h4>\n\n<p>This release renames the plugin from Sermon Manager to Sermon Works (text domain <code>sermon-works<\/code>) and ships the in-place restoration completed across early 2026:<\/p>\n\n<ul>\n<li>Security: 25 issues resolved from a focused audit, including three CVEs filed against the upstream Sermon Manager codebase: CVE-2025-12368 (stored XSS in <code>[sermon-views]<\/code>), CVE-2025-63002 (unauthenticated missing authorisation), and CVE-2025-63000 (stored XSS in <code>[list_sermons]<\/code> \/ <code>[sermon_images]<\/code>). All three sinks have been removed or hardened in Sermon Works.<\/li>\n<li>Modernised: PHP 8.1+ and WordPress 6.0+ floor; deprecated WordPress function calls replaced with current equivalents; dead PHP 5.3 compatibility paths and stale upstream marketing links removed.<\/li>\n<li>Bundled vendor cleanup: CMB2 upgraded v2.2.3.1 \u2192 v2.11.0; wp-background-processing upgraded 1.0.1 \u2192 1.4.0; bundled <code>entry-views.php<\/code> polyfill removed (replaced with a small WordPress-native counter); <code>taxonomy-images<\/code> library removed (migrated to core term_meta + a dedicated metabox).<\/li>\n<li>Database, shortcodes, post types, taxonomies, and template files unchanged. Existing Sermon Manager installs migrate as a drop-in replacement.<\/li>\n<\/ul>\n\n<h4>Older releases<\/h4>\n\n<p>For Sermon Manager release history (2.13 through 2.15.16, dating from 2015\u20132018), see <a href=\"https:\/\/github.com\/mattytap\/Mattytap-Sermons\/blob\/main\/changelog.txt\"><code>changelog.txt<\/code><\/a> in the plugin directory.<\/p>","raw_excerpt":"A maintained restoration of Sermon Manager: publish, organise, and podcast sermons on a WordPress site.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/310379","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=310379"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/mattytap"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=310379"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=310379"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=310379"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=310379"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=310379"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=310379"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}