Skip to content

Browser Support Test — PHP source

Audit your real browser against 30 modern web capabilities - WebGPU, WASM, WebAuthn, Service Workers and more. Get a weighted readiness score, copy-paste detection snippets, and a shareable link.

This is the PHP implementation — the same logic the interactive tool runs, in a shareable, citable form.

<?php
/**
 * Browser Support Test — runtime capability probe, weighted score, tier.
 *
 * Language: PHP
 * CosmoDev polyglot showcase port of the `browser-support-test` tool.
 * Ported from src/tools/BrowserSupportTest.tsx (+ browser-support/* modules) —
 * display source, part of CosmoDev's polyglot tool pages.
 *
 * ILLUSTRATIVE PORT: the live tool detects *browser* features at runtime
 * (navigator/window probes) — a browser-only concern that cannot run in a
 * server-side PHP process. This port shows the ANALOGOUS pattern for PHP:
 * extension_loaded(), function_exists(), class_exists(), and defined() are
 * PHP's native feature-presence probes — the direct equivalent of
 * `'feature' in window`. The scoring algorithm and tier thresholds below are
 * byte-for-byte the same as the TypeScript lib's; only the probe targets differ.
 */

const SUPPORTED    = 'supported';
const LIMITED      = 'limited';
const UNSUPPORTED  = 'unsupported';
const UNKNOWN      = 'unknown';

/**
 * Contribution × weight. Same values as src/tools/browser-support/score.ts.
 */
function contribution(string $status): float {
    return match ($status) {
        'supported'    => 1.0,
        'limited'      => 0.5,
        'needs-https'  => 0.3,
        default        => 0.0, // unsupported, unknown
    };
}

/**
 * Weighted readiness 0–100; matches computeScore() exactly.
 * Results whose id isn't in $checks are ignored.
 */
function computeScore(array $results, array $checks): int {
    $wm = [];
    foreach ($checks as $c) { $wm[$c['id']] = $c['weight']; }
    $earned = 0.0; $possible = 0.0;
    foreach ($results as $r) {
        if (!isset($wm[$r['id']])) continue;
        $earned   += contribution($r['status']) * $wm[$r['id']];
        $possible += $wm[$r['id']];
    }
    if ($possible == 0.0) return 0;
    return (int) round($earned / $possible * 100);
}

/**
 * tierFor mirrors tierFor() in the island — same thresholds.
 */
function tierFor(int $score): array {
    if ($score >= 90) return ['label' => 'Fully modern',         'tone' => 'text-success'];
    if ($score >= 75) return ['label' => 'Very capable',         'tone' => 'text-success'];
    if ($score >= 55) return ['label' => 'Capable, minor gaps',  'tone' => 'text-accent'];
    if ($score >= 35) return ['label' => 'Showing its age',      'tone' => 'text-fg-muted'];
    return                ['label' => 'Legacy browser',          'tone' => 'text-danger'];
}

/**
 * Representative catalog of PHP capability probes. Each `probe` closure returns
 * true when the capability is available in THIS runtime.
 */
function checks(): array {
    return [
        ['id' => 'openssl',     'title' => 'OpenSSL',        'category' => 'Crypto',  'weight' => 3.0, 'probe' => fn() => extension_loaded('openssl')],
        ['id' => 'mbstring',    'title' => 'mbstring',       'category' => 'Text',    'weight' => 2.0, 'probe' => fn() => extension_loaded('mbstring')],
        ['id' => 'intl',        'title' => 'intl (ICU)',     'category' => 'Text',    'weight' => 2.0, 'probe' => fn() => extension_loaded('intl')],
        ['id' => 'pdo',         'title' => 'PDO',            'category' => 'Data',    'weight' => 3.0, 'probe' => fn() => extension_loaded('pdo')],
        ['id' => 'fiber',       'title' => 'Fibers',         'category' => 'Runtime', 'weight' => 2.0, 'probe' => fn() => class_exists('Fiber')],
        ['id' => 'enum',        'title' => 'Enums',          'category' => 'Language','weight' => 2.0, 'probe' => fn() => function_exists('enum_exists')],
        ['id' => 'array-key-first', 'title' => 'array_key_first', 'category' => 'Language','weight' => 1.0, 'probe' => fn() => function_exists('array_key_first')],
        ['id' => 'readonly',    'title' => 'readonly props', 'category' => 'Language','weight' => 1.0, 'probe' => fn() => version_compare(PHP_VERSION, '8.1.0', '>=')],
    ];
}

/**
 * Run probes; a throw degrades to 'unknown' so one failure can't abort the audit.
 */
function runChecks(array $checks): array {
    $out = [];
    foreach ($checks as $c) {
        try {
            $ok = ($c['probe'])();
            $out[] = ['id' => $c['id'], 'status' => $ok ? SUPPORTED : UNSUPPORTED];
        } catch (\Throwable $e) {
            $out[] = ['id' => $c['id'], 'status' => UNKNOWN];
        }
    }
    return $out;
}

$checks  = checks();
$results = runChecks($checks);
$score   = computeScore($results, $checks);
$tier    = tierFor($score);
$supported = count(array_filter($results, fn($r) => $r['status'] === SUPPORTED));

echo 'PHP ' . PHP_VERSION . ' · ' . PHP_SAPI . "\n";
echo $supported . '/' . count($results) . ' capabilities · readiness ' . $score . ' · ' . $tier['label'] . "\n";

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →