<?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 >= 1 && $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([0, 1, 2], 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] == 0 ? NULL : round(($time[0]/1000000000), 4));
        $time_r[1] = ($time[1] == 0 ? NULL : round(($time[1]/1000000000), 4));
        $time_r[2] = ($time[2] == 0 ? 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($k, 3, '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>