<?php

//--------------------------------------------------
// Setup

    
header("Content-Security-Policy: default-src 'none'; base-uri 'none'; form-action 'self'; style-src 'unsafe-inline'; img-src 'self'; frame-ancestors 'none'; require-trusted-types-for 'script'; trusted-types 'none'; block-all-mixed-content");

    require_once(
__DIR__ '/../wordpress/wp-load.php');

    
$db_path __DIR__ '/../wordpress/wp-content/db.php';

//--------------------------------------------------
// Test

    
$test_folder __DIR__ '/tests';

    
$test_count count(glob($test_folder '/*.php'));

    
$test_id intval($_POST['test'] ?? 0);

    if (
$test_id >= && $test_id <= $test_count) {
        
$test_path $test_folder '/' str_pad(intval($test_id), 3'0'STR_PAD_LEFT) . '.php';
    } else {
        
$test_path NULL;
    }

//--------------------------------------------------
// Download source

    
$download = ($_GET['download'] ?? NULL);

    if (
$download == 'db') {

        
header('Content-Type: application/octet-stream; charset=UTF-8');
        
header('Content-Disposition: attachment; filename="db.php"');
        
header('Content-Length: ' filesize($db_path));
        
readfile($db_path);
        exit();

    }

//--------------------------------------------------
// View source

    
$view = ($_GET['view'] ?? NULL);

    if (
$view == 'index') {

        
highlight_file(__DIR__ '/index.php');
        exit();

    } else if (
$view == 'prepare0' || $view == 'prepare1' || $view == 'prepare2') {

        
highlight_file(__DIR__ '/wpdb/' $view '.php');
        exit();

    } else if (
$view == 'diff1' || $view == 'diff2') {

        if (
$view == 'diff1') {
            
$prepare_file 'prepare1';
        } else {
            
$prepare_file 'prepare2';
        }

        echo 
'<pre style="tab-size: 2">';
        echo 
htmlentities(shell_exec('diff ' escapeshellarg(__DIR__ '/wpdb/prepare0.php') . ' ' escapeshellarg(__DIR__ '/wpdb/' $prepare_file '.php')));
        echo 
'</pre>';
        exit();

    } else if (
$view == 'db') {

        
highlight_file($db_path);
        exit();

    }

//--------------------------------------------------
// Run test

    
$test_runs 1000;

    if (
$test_path !== NULL) {

        
$time array_fill_keys([012], 0);

        require_once(
$test_path);

        
$time[0] = ($time[0] * $test_runs);
        
$time[1] = ($time[1] * $test_runs);
        
$time[2] = ($time[2] * $test_runs);

        
$sql1 = ($sql1 ?? $sql);
        
$sql2 = ($sql2 ?? $sql);
        
$sql3 = ($sql3 ?? $sql);

        
$values1 = ($values1 ?? $values);
        
$values2 = ($values2 ?? $values);
        
$values3 = ($values3 ?? $values);

        for (
$k 0$k $test_runs; ++$k) {

            
//--------------------------------------------------

                
if ($sql1 !== false) {

                    
$start hrtime(true);

                    
$result0 $wpdb->prepare_0($sql1$values1);

                    
$time[0] += (hrtime(true) - $start);

                }

            
//--------------------------------------------------

                
if ($sql2 !== false) {

                    
$start hrtime(true);

                    
$result1 $wpdb->prepare_1($sql2$values2);

                    
$time[1] += (hrtime(true) - $start);

                }

            
//--------------------------------------------------

                
if ($sql3 !== false) {

                    
$start hrtime(true);

                    
$result2 $wpdb->prepare_2($sql3$values3);

                    
$time[2] += (hrtime(true) - $start);

                }

        }

        
$time_r[0] = ($time[0] == NULL round(($time[0]/1000000000), 4));
        
$time_r[1] = ($time[1] == NULL round(($time[1]/1000000000), 4));
        
$time_r[2] = ($time[2] == NULL round(($time[2]/1000000000), 4));

        if (
$time[1] < $time[2]) {
            
$fp_time $time[1];
        } else {
            
$fp_time $time[2];
        }

        
header('X-Response-Ref: ' $test_id ',' $time_r[0] . ',' $time_r[1] . ',' $time_r[2]);

    }

//--------------------------------------------------
// HTML

?>
<!DOCTYPE html>
<html lang="en-GB" xml:lang="en-GB" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8" />
    <title>WPDB 2</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="description" content="Testing changes with WPDB." />
    <style>
        .output q {
            color: #DD0000;
            white-space: pre;
        }
        .output q::before,
        .output q::after {
            content: "'";
        }
        .fast_new,
        .output strong.matched {
            color: #007700;
        }
        .fast_old,
        .output strong.different {
            color: #DD0000;
        }
        blockquote {
            margin: 1em 0 1em 1em;
            overflow-x: auto;
            white-space: nowrap;
        }
    </style>
</head>
<body>

    <h1>WP-DB</h1>
    <p>Testing a patch to make `WHERE id IN(1,2,3)` style queries easier with `WHERE id IN %...d`.</p>
    <p>Each test is run <?= htmlspecialchars($test_runs?> times, on a Virtual Machine (noisy neighbours), does not account for TurboBoost, or CPU temperature changes (throttling).</p>

    <h2>Run Test</h2>
    <form action="./" method="post">
        <ul>
            <?php for ($k 1$k <= $test_count$k++) { ?>

                <li>

                    <p><input type="submit" name="test" value="<?= htmlentities(str_pad($k3'0'STR_PAD_LEFT)) ?>" /></p>

                    <?php if ($k === $test_id && $test_path !== NULL) { ?>

                        <?php if ($time_r[0] !== NULL) { ?>

                            <p>
                                x<?= htmlentities($test_runs?> =<br />
                                &#xA0; <?= htmlentities(str_pad($time_r[0], 6'0'STR_PAD_RIGHT)) ?>s - Current WPDB Time<?= ($time[0] < $fp_time ' ← <strong class="fast_old">Faster</strong>' ' (+' round((($time[0] - $fp_time) / $fp_time) * 100) . '%)'?><br />
                                &#xA0; <?= htmlentities(str_pad($time_r[1], 6'0'STR_PAD_RIGHT)) ?>s - Patch 1 WPDB Time<?= ($time[1] < $time[0] ? ' ← <strong class="fast_new">Faster</strong>' ' (+' round((($time[1] - $time[0]) / $time[0]) * 100) . '%)'?><br />
                                &#xA0; <?= htmlentities(str_pad($time_r[2], 6'0'STR_PAD_RIGHT)) ?>s - Patch 2 WPDB Time<?= ($time[2] < $time[0] ? ' ← <strong class="fast_new">Faster</strong>' ' (+' round((($time[2] - $time[0]) / $time[0]) * 100) . '%)'?>
                            </p>

                            <p class="output">
                                <q><?= htmlentities($result0?></q> - Current WPDB Output<br />
                                <q><?= htmlentities($result1?></q> - Patch 1 WPDB Output - <?= ($result0 == $result1 '<strong class="matched">Matched</strong>' '<strong class="different">Different</strong>'?><br />
                                <q><?= htmlentities($result2?></q> - Patch 2 WPDB Output - <?= ($result0 == $result2 '<strong class="matched">Matched</strong>' '<strong class="different">Different</strong>'?>
                            </p>

                        <?php } else if ($time_r[1] !== NULL) { ?>

                            <p>
                                x<?= htmlentities($test_runs?> =<br />
                                &#xA0; <?= htmlentities(str_pad($time_r[1], 6'0'STR_PAD_RIGHT)) ?>s - Patch 1 WPDB Time<?= ($time[1] < $time[2] ? ' ← <strong class="fast_new">Faster</strong>' ' (+' round((($time[1] - $time[2]) / $time[2]) * 100) . '%)'?><br />
                                &#xA0; <?= htmlentities(str_pad($time_r[2], 6'0'STR_PAD_RIGHT)) ?>s - Patch 2 WPDB Time<?= ($time[2] < $time[1] ? ' ← <strong class="fast_new">Faster</strong>' ' (+' round((($time[2] - $time[1]) / $time[1]) * 100) . '%)'?>
                            </p>

                            <p class="output">
                                <q><?= htmlentities($result1?></q> - Patch 1 WPDB Output<br />
                                <q><?= htmlentities($result2?></q> - Patch 2 WPDB Output - <?= ($result1 == $result2 '<strong class="matched">Matched</strong>' '<strong class="different">Different</strong>'?>
                            </p>

                        <?php } else if ($time_r[2] !== NULL) { ?>

                            <p>
                                x<?= htmlentities($test_runs?> =<br />
                                &#xA0; <?= htmlentities(str_pad($time_r[2], 6'0'STR_PAD_RIGHT)) ?>s - Patch 2 WPDB Time
                            </p>

                            <p class="output">
                                <q><?= htmlentities($result2?></q> - Patch 2 WPDB Output
                            </p>

                        <?php ?>

                        <blockquote>
                            <?php highlight_file($test_path); ?>
                        </blockquote>

                    <?php ?>

                </li>

            <?php ?>
        </ul>
    </form>

    <h2>View Source</h2>

    <p>View <a href="./?view=index">/index.php</a> and <a href="./?view=db">/wp-content/db.php</a> to see how this page works.</p>

    <p>And the 3 prepare implementations:</p>

    <ul>
        <li><a href="./?view=prepare0">Original</a></li>
        <li><a href="./?view=prepare1">Patch 1</a> (<a href="./?view=diff1">diff</a>) - Supports basic "%...d".</li>
        <li><a href="./?view=prepare2">Patch 2</a> (<a href="./?view=diff2">diff</a>) - Supports argnum (e.g. "%...3$s") and formatting (e.g. "%...5s").</li>
    </ul>

</body>
</html>