Security: - Validate CSV upload MIME type server-side via finfo - Deliver import notices via per-user transient (prevents GET-param spoofing) - Sanitise translatable success string with wp_kses to block HTML injection - Switch sanitize_url to esc_url_raw; wp_kses_post to sanitize_textarea_field for plain-text bio Bug fixes: - Guard preg_replace null return in normalise_name() to prevent TypeError on PHP 8 - Replace generic save_post hook with save_post_tec_speaker / save_post_tribe_events so saves no longer need a manual revision check and cannot interact with TEC's own save_post handler at priority 15 TEC integration: - Check for tribe-select2 / tribe-select2-css handles first (TEC ships SelectWoo, not vanilla Select2); CDN was previously always loaded unnecessarily - Type-specific save hooks make event/speaker save paths explicit and independent Improvements: - Add register_activation_hook to flush rewrite rules on activation - Wrap instantiation in plugins_loaded so TEC is guaranteed loaded first - Show admin notice and skip TEC-specific hooks when TEC is inactive - Cap event picker query at PICKER_LIMIT = 200 (was unbounded -1) - Register front-end CSS via wp_add_inline_style on wp_enqueue_scripts - absint() on speaker IDs in option value attributes Documentation: - Write full README.md (was blank) - Add CHANGELOG.md with detailed 1.0.0 and 1.0.1 entries Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4 KiB
4 KiB
Changelog
All notable changes to this project will be documented in this file.
[1.0.1] — 2026-05-17
Security
- CSV MIME validation — the importer now checks the uploaded file's MIME type server-side via
finfobefore opening it. The browser-sideaccept=".csv"attribute is not a security control and was the only prior gate. - Admin notice spoofing — import result banners (success/error) are now delivered via a per-user transient rather than raw GET parameters. A crafted URL can no longer display false success or error messages to an admin.
- HTML in translatable string — the success notice now passes through
wp_kses()restricted to<strong>, preventing a tampered translation file from injecting arbitrary markup. esc_url_rawoversanitize_url— switched to the canonical WordPress function for storing URLs (functionally equivalent;sanitize_urlis an undocumented alias).sanitize_textarea_fieldfor CSV bio — the importer previously usedwp_kses_post(), which permitted HTML in a field described to users as plain-text. Now consistently plain-text.
Bug fixes
normalise_name()null return —preg_replace()returnsnullon failure (e.g. backtracking limit, invalid UTF-8). Both calls now fall back to the input string via?? $name, preventing aTypeErroron PHP 8.- Revision saves — the generic
save_posthook was replaced with type-specificsave_post_tec_speakerandsave_post_tribe_eventshooks.save_post_tribe_eventsdoes not fire for revisions (which have post type'revision'), so the separatewp_is_post_revision()guard is no longer needed.
Integration
- Correct SelectWoo handles — The Events Calendar ships SelectWoo (a Select2 fork) under the handles
tribe-select2(JS) andtribe-select2-css(CSS), notselect2. The admin script loader now checks fortribe-select2first, thenselect2, then falls back to a CDN copy. Previously, TEC's registration was never detected and the CDN was always loaded unnecessarily. - Type-specific save hooks — replaced the single generic
save_posthook (priority 10) withsave_post_tec_speakerandsave_post_tribe_events. TEC hooks its own meta save tosave_postat priority 15; using type-specific hooks eliminates any ordering dependency and makes intent explicit.
Improvements
- Activation hook — added
register_activation_hookto register the CPT and flush rewrite rules on activation, fixing the "Speaker archive returns 404 until Permalinks are re-saved" issue on first install. plugins_loadedwrapper — the plugin is now instantiated insideadd_action('plugins_loaded', …)instead of at file-include time, ensuring all plugins (including TEC) are loaded before the constructor runs.- TEC dependency notice — if The Events Calendar is not active, an admin notice is shown. TEC-specific hooks (event display, event meta box) are skipped; the Speaker CPT, admin menu, and shortcode remain functional.
- Admin picker cap — the event speaker picker query is capped at 200 results (
PICKER_LIMITconstant) instead of an unboundedposts_per_page => -1, preventing memory issues on large installs. absint()on option values — speaker IDs written into<option value>attributes are now explicitly cast withabsint().- Styles via
wp_add_inline_style— front-end CSS is now registered through WordPress's style system (wp_register_style+wp_add_inline_styleonwp_enqueue_scripts) rather than echoed as a raw<style>tag mid-content. Caching, minification, and CSP plugins can now manage the styles correctly.
[1.0.0] — 2026-05-16
Initial release.
tec_speakercustom post type with title, editor, excerpt, featured image, website URL, and email.- Searchable multi-select speaker picker on event edit screens (Select2/SelectWoo).
- Automatic speaker display beneath event meta on single event pages.
[tec_speakers]shortcode withlimitandsearchattributes.- CSV bulk importer with duplicate-name detection and honorific normalisation.