Skip to content

Smart Coupons Debugging Script #39

Description

@noelsaw1

MU Plugin: Query Dump with Backtraces

1. Create the MU plugin file

Path: {site-root}/wp-content/mu-plugins/query-dump.php

<?php
/**
 * Query Dump — writes all $wpdb->queries to /tmp/wpdebug-queries.log on shutdown.
 * Remove or rename this file when done.
 */
define( 'SAVEQUERIES', true );

add_action( 'shutdown', function () {
    global $wpdb;
    if ( empty( $wpdb->queries ) ) return;

    $url    = $_SERVER['REQUEST_URI'] ?? '(unknown)';
    $time   = date( 'Y-m-d H:i:s' );
    $pid    = getmypid();
    $out    = "\n\n=== REQUEST pid=$pid $time $url ===\n";

    foreach ( $wpdb->queries as $i => $q ) {
        // $q = [ sql, elapsed_ms, backtrace_string ]
        $sql     = trim( $q[0] );
        $elapsed = round( $q[1] * 1000, 2 ); // ms
        $trace   = $q[2] ?? '';
        $out    .= "\n--- Query #" . ( $i + 1 ) . " ({$elapsed}ms) ---\n$sql\n$trace\n";
    }

    file_put_contents( '/tmp/wpdebug-queries.log', $out, FILE_APPEND | LOCK_EX );
} );

Why MU plugin: zero activation friction, survives plugin toggles, loads before everything else.


2. Verify it's loading

wp --path="$WP_PATH" eval 'echo defined("SAVEQUERIES") ? "ON" : "OFF";'

Should print ON. If it prints OFF, SAVEQUERIES was already defined earlier in wp-config.php — check there.


3. Clear the log and run your confirmed Playwright flow

rm -f /tmp/wpdebug-queries.log

node temp/pw-xdebug-profile-run.js   # or whichever script drives the full prep flow

The flow hits: homepage → add-to-cart → coupon URL → homepage-after-prep. Each of those is a separate PHP process and will write a separate === REQUEST === block.


4. Read the log — find the right request block first

grep "=== REQUEST" /tmp/wpdebug-queries.log

You'll see one line per PHP request, with the URI. Identify which block is:

  • the coupon URL request (/?coupon-code=binoid15...)
  • the final homepage request (after prep)

5. Search for the coupon lookup SQL specifically

grep -n "shop_coupon" /tmp/wpdebug-queries.log

This will show exactly which request block contains the binoid15 / shop_coupon query and its line number. Then read that block's backtrace:

# example: query showed up at line 84, read surrounding context
sed -n '80,120p' /tmp/wpdebug-queries.log

The backtrace string (field $q[2]) is a comma-separated call chain from $wpdb->query() up through WooCommerce/Smart Coupons. That chain will either show WC_SC_URL_Coupon, WC_SC_Coupon_Actions, or something else entirely.


6. Clean up

Once you have your answer, either delete the file or rename it so it stops running:

mv wp-content/mu-plugins/query-dump.php wp-content/mu-plugins/query-dump.php.off

What you're looking for

Finding Implication
shop_coupon lookup is in the coupon URL block The query fires during coupon application, not homepage rehydration
shop_coupon lookup is in the homepage-after-prep block Cart/session rehydration on homepage is the source — primary theory confirmed
Backtrace shows WC_SC_Coupon_Actions Coupon-actions path is the issuer — patch there
Backtrace shows WC_SC_URL_Coupon URL/session rehydration path is the issuer
Backtrace shows WC core (WC_Coupon->__construct) May be a WC core issue unrelated to Smart Coupons specifically

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions