ClassFinder.php 3.53 KB
Newer Older
jhon committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
<?php

namespace Illuminate\Filesystem;

use Symfony\Component\Finder\Finder;

class ClassFinder
{
    /**
     * Find all the class and interface names in a given directory.
     *
     * @param  string  $directory
     * @return array
     */
    public function findClasses($directory)
    {
        $classes = [];

        foreach (Finder::create()->in($directory)->name('*.php') as $file) {
            $classes[] = $this->findClass($file->getRealPath());
        }

        return array_filter($classes);
    }

    /**
     * Extract the class name from the file at the given path.
     *
     * @param  string  $path
     * @return string|null
     */
    public function findClass($path)
    {
        $namespace = null;

        $tokens = token_get_all(file_get_contents($path));

        foreach ($tokens as $key => $token) {
            if ($this->tokenIsNamespace($token)) {
                $namespace = $this->getNamespace($key + 2, $tokens);
            } elseif ($this->tokenIsClassOrInterface($token)) {
                return ltrim($namespace.'\\'.$this->getClass($key + 2, $tokens), '\\');
            }
        }
    }

    /**
     * Find the namespace in the tokens starting at a given key.
     *
     * @param  int  $key
     * @param  array  $tokens
     * @return string|null
     */
    protected function getNamespace($key, array $tokens)
    {
        $namespace = null;

        $tokenCount = count($tokens);

        for ($i = $key; $i < $tokenCount; $i++) {
            if ($this->isPartOfNamespace($tokens[$i])) {
                $namespace .= $tokens[$i][1];
            } elseif ($tokens[$i] == ';') {
                return $namespace;
            }
        }
    }

    /**
     * Find the class in the tokens starting at a given key.
     *
     * @param  int  $key
     * @param  array  $tokens
     * @return string|null
     */
    protected function getClass($key, array $tokens)
    {
        $class = null;

        $tokenCount = count($tokens);

        for ($i = $key; $i < $tokenCount; $i++) {
            if ($this->isPartOfClass($tokens[$i])) {
                $class .= $tokens[$i][1];
            } elseif ($this->isWhitespace($tokens[$i])) {
                return $class;
            }
        }
    }

    /**
     * Determine if the given token is a namespace keyword.
     *
     * @param  array|string  $token
     * @return bool
     */
    protected function tokenIsNamespace($token)
    {
        return is_array($token) && $token[0] == T_NAMESPACE;
    }

    /**
     * Determine if the given token is a class or interface keyword.
     *
     * @param  array|string  $token
     * @return bool
     */
    protected function tokenIsClassOrInterface($token)
    {
        return is_array($token) && ($token[0] == T_CLASS || $token[0] == T_INTERFACE);
    }

    /**
     * Determine if the given token is part of the namespace.
     *
     * @param  array|string  $token
     * @return bool
     */
    protected function isPartOfNamespace($token)
    {
        return is_array($token) && ($token[0] == T_STRING || $token[0] == T_NS_SEPARATOR);
    }

    /**
     * Determine if the given token is part of the class.
     *
     * @param  array|string  $token
     * @return bool
     */
    protected function isPartOfClass($token)
    {
        return is_array($token) && $token[0] == T_STRING;
    }

    /**
     * Determine if the given token is whitespace.
     *
     * @param  array|string  $token
     * @return bool
     */
    protected function isWhitespace($token)
    {
        return is_array($token) && $token[0] == T_WHITESPACE;
    }
}