ludofleury
2/22/2012 - 5:04 PM

Extract namespace from a PHP file

Extract namespace from a PHP file

<?php

// Works in every situations
function by_token ($src) {
    $class = false;
    $namespace = false;
    $tokens = token_get_all($src);
    for ($i = 0, $count = count($tokens); $i < $count; $i++) {
        $token = $tokens[$i];

        if (!is_array($token)) {
            continue;
        }

        if (true === $class && T_STRING === $token[0]) {
            return $namespace.'\\'.$token[1];
        }

        if (true === $namespace && T_STRING === $token[0]) {
            $namespace = '';
            do {
                $namespace .= $token[1];
                $token = $tokens[++$i];
            } while ($i < $count && is_array($token) && in_array($token[0], array(T_NS_SEPARATOR, T_STRING)));
        }

        if (T_CLASS === $token[0]) {
            $class = true;
        }

        if (T_NAMESPACE === $token[0]) {
            $namespace = true;
        }
    }

    return null;
}

// Makes many assumptions on file format:
// namespace is declared on its own line, starting with "namespace" (no spaces).
function by_regexp($src) {
    if (preg_match('#^namespace\s+(.+?);.*class\s+(\w+).+;$#sm', $src, $m)) {
        return $m[1].'\\'.$m[2];
    }
    return null;
}

function bench($foo, $src) {
    $start = microtime(true);
    for ($i=0; $i<10000; $i++) {
        $fqdn = $foo($src);
        if ($fqdn !== 'Symfony\\Component\\DependencyInjection\\Container') {
            throw new Exception('Mother (gentle) fucker ?');
        }
    }
    $end = microtime(true);
    return $end - $start;
}



$src = file_get_contents("/srv/retent.io/symfony/src/Symfony/Component/DependencyInjection/Container.php");
var_dump(bench('by_token', $src), bench('by_regexp', $src));

// by_token : float 24.221081018448 ~ 24.579097032547
// by_regexp: float 1.8785789012909 ~ 1.9564740657806