• Resolved pbaddock

    (@pbaddock)


    Environment

    • WPCode Lite: 2.3.5 (latest)
    • WordPress: 6.9.4
    • PHP: 8.2.30 (ZTS)
    • Hosting: SiteGround Cloud
    • Object cache: Not enabled (standard wp_options autoload)
    • Active PHP snippets: ~59

    Summary

    All active PHP snippets (location: “Run Everywhere”) silently stop executing. No errors are logged, no snippets are deactivated — they simply don’t run. The wpcode_snippets option in wp_options exists and contains what appears to be valid cached data, but the snippets are not executed on page load.

    This affects all PHP snippet types including shortcode registrations, add_filter() / add_action() hooks, and custom URL routing — meaning entire sections of the site break silently when this occurs.Reproduction

    This issue is persistent on our installation. Every time we rely solely on WPCode’s native snippet loader (the wpcode_snippets option cache), PHP snippets do not execute. We have confirmed this by:

    1. Creating a workaround mu-plugin that loads snippets directly from the database (bypassing WPCode’s cache) — all snippets work correctly.
    2. Disabling the mu-plugin and flushing all caches (wp cache flush, wp transient delete --all) — snippets immediately stop executing. In our case, this breaks custom post type URL routing (registered via a WPCode snippet), causing hotel pages on our website to 404 and redirect to the homepage.
    3. Re-enabling the mu-plugin — everything works again immediately.

    This has been tested multiple times with the same result. The issue is 100% reproducible.Suspected root cause

    After tracing through the WPCode source code, I believe the issue is in how the snippet cache interacts with the WPCode_Snippet class:1. get_data_for_caching() omits the active property

    In class-wpcode-snippet.php (around line 935), the get_data_for_caching() method returns an array with id, title, code, code_type, location, auto_insert, insert_number, use_rules, rules, priority, location_extra, shortcode_attributes, compiled_code, and modified — but does not include active.2. Cache-loaded snippets have is_active() === false

    When a snippet is reconstructed from cached array data:

    • load_from_array() iterates get_object_vars($this) and sets matching properties. Since active is not in the cached array, $this->active remains null.
    • $this->post_data is also never set (it’s only set when loading from a WP_Post object or by ID from the database).
    • When is_active() is called, it checks !isset($this->active)true (since null), then falls through to isset($this->post_data->post_status) && 'publish' === $this->post_data->post_statusfalse (since post_data is not set).
    • Result: every snippet loaded from cache reports is_active() === false.

    3. This blocks shortcode execution

    In includes/shortcode.php line 41, shortcode output is gated by:

    if ( ! $snippet->is_active() ) {
        return '';
    }

    Since is_active() returns false for all cache-loaded snippets, no shortcode registered by a WPCode snippet produces any output.4. The “Run Everywhere” auto-insert path may also be affected

    While WPCode_Auto_Insert_Everywhere::run_snippets() doesn’t directly call is_active(), it passes snippet output through the wpcode_snippet_output_php and wpcode_snippet_output filters. If any other part of the system checks is_active() during this flow, it would also fail.Suggested fix

    Add active to the cached data array in get_data_for_caching():

    return array(
        'id'                   => $this->get_id(),
        'title'                => $this->get_title(),
        'active'               => $this->is_active(),  // <-- ADD THIS
        'code'                 => $this->get_code(),
        'code_type'            => $this->get_code_type(),
        // ... rest of array
    );

    Since only active/published snippets are cached (the cache is built from cache_all_loaded_snippets() which queries published snippets), this value will always be true in practice — but without it, is_active() can’t determine the snippet’s status when post_data isn’t available.Current workaround

    We are running a must-use plugin (wp-content/mu-plugins/fix-wpcode-cache.php) that:

    1. Hooks into plugins_loaded at priority 3 (before WPCode’s priority 5)
    2. Queries the database directly for all published PHP snippets (post_type = 'wpcode', post_status = 'publish', taxonomy wpcode_type = php, plus _wpcode_active = 1 meta)
    3. eval()s each snippet’s post_content
    4. Suppresses WPCode’s own PHP execution via add_filter('wpcode_snippet_output_php', '__return_empty_string', 1) to prevent redeclaration errors

    This workaround has been stable for several months but adds an extra database query on every request, which is not ideal.

    Note on version 2.3.5 changelog

    The 2.3.5 changelog mentions: “Resolved a fatal error that could occur when the snippet library cache returns invalid data.” This fix appears to address a different symptom (a fatal error from malformed cache data) but does not fix the underlying issue of snippets silently not executing due to the missing active property in cached data.

Viewing 2 replies - 1 through 2 (of 2 total)
  • Plugin Support markomiljanovic

    (@markomiljanovic)

    Hi @pbaddock,

    The missing active property in the cached data is a real finding, and we’ll look into it, but it isn’t what’s causing your symptom. Nothing on the Run Everywhere runtime path calls is_active(), so cache-loaded snippets execute regardless of what it returns.

    The likely culprit is that all Run Everywhere PHP snippets are concatenated and passed to a single eval(). A closing ?> in any earlier snippet or an unclosed /* */ comment will cause every subsequent snippet in the batch to silently not execute. Your mu-plugin works around it because it evals each snippet separately.

    It is worth checking your active Run Everywhere snippets for a trailing ?> or an unterminated /* */ comment. To narrow it down quickly, you can use the search bar on the Code Snippets list to search for ?> and /*. That should surface the candidates in a few seconds.

    Thanks,

    Thread Starter pbaddock

    (@pbaddock)

    Ahhh yes, perfect, thanks so much Marko – I’ll adjust from here – appreciate the prompt response.

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

You must be logged in to reply to this topic.