ivoreis82
Forum Replies Created
-
workaround while waiting for an upstream fix
We hit the same issue on the admin event edit screen and found a temporary workaround while waiting for an upstream fix.
What we observed:
- Events Manager (v7.2.3.1) initializes Flatpickr in admin JS and assumes the global flatpickr object includes:
- flatpickr.l10ns[…] (locale bundle, e.g. pt)
- flatpickr.localize()
- In our case, window.flatpickr existed, but it was incomplete (missing l10ns and/or localize), which caused a JS exception during EM UI initialization.
- Once that exception happens, the date/time UI initialization is interrupted, and time fields visually change but do not save correctly (often staying 00:00:00).
Console errors we saw included:
- flatpickr.l10ns is undefined
- flatpickr.localize is not a function
Temporary fix (workaround):
- We added a small MU plugin (wp-content/mu-plugins/…) that injects a defensive admin-side JS shim.
- The shim ensures window.flatpickr has:
- l10ns
- l10ns.default
- l10ns.pt (fallback to default)
- localize() (safe fallback)
- This prevents Events Manager from crashing on admin screen load and restores normal date/time editing and saving.
Important:
- This is only a workaround to avoid the JS crash.
- The root issue appears to be a compatibility/enqueue problem (EM expecting a full Flatpickr API/locale to be
present, but another script/build provides an incomplete global or the locale helper is not loaded in time).
<?php
/*
Plugin Name: Events Manager - Flatpickr Locale Shim
Description: Prevents admin JS errors when Events Manager expects flatpickr.l10ns.pt but the locale bundle was not loaded.
Version: 1.0.0
Author: Local patch
*/
add_action('admin_enqueue_scripts', function () {
$js = <<<'JS'
(function () {
function ensureFlatpickrLocaleShim() {
var fp = window.flatpickr;
if (!fp) return false;
if (!fp.l10ns || typeof fp.l10ns !== 'object') {
fp.l10ns = {};
}
if (!fp.l10ns.default || typeof fp.l10ns.default !== 'object') {
fp.l10ns.default = { firstDayOfWeek: 0 };
}
// Events Manager may call flatpickr.l10ns.pt directly.
if (!fp.l10ns.pt) {
fp.l10ns.pt = fp.l10ns.default;
}
// Some builds expose flatpickr without the localize helper.
if (typeof fp.localize !== 'function') {
fp.localize = function (locale) {
if (locale && typeof locale === 'object') {
fp.l10ns.default = Object.assign({}, fp.l10ns.default || {}, locale);
}
return fp.l10ns.default;
};
}
return true;
}
if (ensureFlatpickrLocaleShim()) return;
var tries = 0;
var timer = setInterval(function () {
tries++;
if (ensureFlatpickrLocaleShim() || tries > 200) {
clearInterval(timer);
}
}, 25);
})();
JS;
// Attach early in admin pages; jquery-core is always available in wp-admin.
wp_register_script('em-flatpickr-l10ns-shim', false, array('jquery-core'), null, false);
wp_enqueue_script('em-flatpickr-l10ns-shim');
wp_add_inline_script('em-flatpickr-l10ns-shim', $js);
}, 1);It would be great if Events Manager could add defensive checks before calling:
- flatpickr.localize(…)
- flatpickr.l10ns[locale]
For example, only localize if those APIs exist, and gracefully fall back otherwise.
Hey @misfist , thanks for sharing your original approach!
We’ve confirmed that the issue still occurs in Events Manager 7.2.2.1: the plugin’s publish_future_post handler is applied globally, which can affect scheduled posts outside Events Manager (like standard posts) and sometimes clear their slugs.
We built on your idea — unhooking EM’s handler and reattaching it only for EM post types — and added a few safeguards to make it safer and more maintainable. The improved version is below.<?php
/*
Plugin Name: Events Manager – Scoped publish_future_post Hook
Description: Restricts Events Manager's publish_future_post handler to its own custom post types only, preventing interference with standard posts.
Version: 1.0.1
Author: (anonymous community patch)
*/
/**
* Optional debug flag:
* You can enable verbose logging by defining this constant in wp-config.php:
* define('EM_SCOPE_DEBUG', true);
*/
if ( ! function_exists('em_scope_log') ) {
function em_scope_log($msg) {
if (defined('EM_SCOPE_DEBUG') && EM_SCOPE_DEBUG) {
error_log('[' . gmdate('Y-m-d H:i:s') . "Z] " . $msg . "\n", 3, WP_CONTENT_DIR . '/debug-em-scope.log');
}
}
}
/**
* Ensures the publish_future_post hook from Events Manager
* only runs for its own CPTs (event, event-recurring, location).
*
* This prevents EM from touching regular WordPress posts
* or other custom post types during scheduled publishing.
*/
add_action('plugins_loaded', function () {
static $wired = false;
if ($wired) {
return; // Avoid reattaching multiple times per process.
}
// Skip if Events Manager is not active.
if ( ! class_exists('EM_Event_Post') ) {
return;
}
// Remove EM's default hook safely.
$priority = has_action('publish_future_post', ['EM_Event_Post', 'publish_future_post']);
if (false !== $priority) {
remove_action('publish_future_post', ['EM_Event_Post', 'publish_future_post'], $priority);
}
// Define Events Manager post types (with fallbacks).
$allowed = array_unique(array_filter([
defined('EM_POST_TYPE_EVENT') ? EM_POST_TYPE_EVENT : 'event',
defined('EM_POST_TYPE_EVENT_RECURRENCE') ? EM_POST_TYPE_EVENT_RECURRENCE : 'event-recurring',
defined('EM_POST_TYPE_LOCATION') ? EM_POST_TYPE_LOCATION : 'location',
]));
// Reattach a scoped handler for publish_future_post.
add_action('publish_future_post', function ($post_id) use ($allowed) {
$type = get_post_type($post_id);
// Ignore non-EM post types.
if ( ! $type || ! in_array($type, $allowed, true) ) {
em_scope_log("EM scope: ignored publish_future_post for ID={$post_id} type={$type}");
return;
}
// Delegate to EM only for its own post types.
if (is_callable(['EM_Event_Post', 'publish_future_post'])) {
\EM_Event_Post::publish_future_post($post_id);
em_scope_log("EM scope: delegated to EM_Event_Post::publish_future_post for ID={$post_id} type={$type}");
}
}, 10, 1);
$wired = true;
em_scope_log('EM scope: handler restricted to CPTs: ' . implode(',', $allowed));
}, 20);Why this version is safer:
– Runs only for EM post types (event, event-recurring, location)
– Checks if EM_Event_Post exists before modifying hooks
– Prevents multiple re-hooks in the same process
– Avoids dependency on Archetypes, preventing fatals if EM changes internally
– Supports optional debug logging via define(‘EM_SCOPE_DEBUG’, true);
This fix works as a small MU-plugin, requires no edits to plugin files, and fully resolves the missing-slug issue on scheduled posts.
Thanks again for your clear explanation. - Events Manager (v7.2.3.1) initializes Flatpickr in admin JS and assumes the global flatpickr object includes: