Forum Replies Created

Viewing 3 replies - 1 through 3 (of 3 total)
  • 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.

Viewing 3 replies - 1 through 3 (of 3 total)