cubecart / v6

CubeCart Version 6
https://cubecart.com
73 stars 57 forks source link

Parts of Spooled Debug Missing - Sometimes #3450

Open bhsmither opened 10 months ago

bhsmither commented 10 months ago

I am still tracing this out, and maybe #3449 fixed it, but on a httpredir bounce, sometimes the first one or two dumps to the debug spool gets lost between script exits.

The sequence I am tracing is: Search using a word found only in one product. CubeCart should httpredir with ?_a=product&product_id=x The browser asks for that page. CubeCart should httpredir with appropriate /seo_url for x The browser asks for that page. CubeCart delivers that page.

On the page that is finally delivered, the debug is missing all the work that was done during the search.

bhsmither commented 10 months ago

So far, I have narrowed it down to:

In Debug->__destruct():
There is:
Session::getInstance()->set('debug_spool', array($this->display(true)));
In Session->set():
There is:
$_SESSION[$namespace][$name] = merge_array($_SESSION[$namespace][$name], $value);
In function merge_array($first, $second):
There is:
$first[(string)$key[$i]] = (is_array($second[$key[$i]])) ? array_merge($first[$key[$i]], $second[$key[$i]]) : $second[$key[$i]];

The two arrays to be merged are:

$first => array (size=1) [0] => string '<h2>Debug Output - /search?search[keywords]=Test ... ' (length=25796)
$second => array (size=1) [0] => string '<h2>Debug Output - /search?_a=product&product_id=1 ...' (length=15616)

Because $second is not empty and is an array, the merge will be attempted. The keys of $second, and the size of those keys, are:

$key => array (size=1) [0] => int 0
$size => '1'

This is index 0 of less than 1 ... Because $first[0] exists, and if $second[0] is an array, try to array_merge($first[0], $second[0]) and assign to $first['0']. But if $second[0] is not an array, use $second[0] directly assign to $first['0'].

Here's the problem. $second[0] is a string. (And so is $first[0] by the way.)

bhsmither commented 10 months ago

I hope you can find a better solution. I didn't want to mess with any of the legacy code.

So, this is what I did:

In Debug->__destruct():
From:
Session::getInstance()->set('debug_spool', array($this->display(true)));
To:
// Fetch the debug_spool array, where the default return is an array, and remove empty elements.
$debug_spool = array_filter($GLOBALS['session']->get('debug_spool', 'system', array()));
// Push the latest debug content string.
$debug_spool[] = $this->display(true);
// The new debug_spool overwrites.
Session::getInstance()->set('debug_spool', $debug_spool, 'system', true);