Extract the classes in the given file

@param string $path The file to check

@return array The found classes
161086
private static function findClasses($path)
    {
        $contents = file_get_contents($path);
        try {
        	//$nbResults = preg_match_all('{\b(?:class|interface|trait)\b}i', $contents);
        	//$nbResults = preg_match_all('{\b(?:class)\b}i', $contents, $results, PREG_OFFSET_CAPTURE);
        	
        	
        	/*$nbResults = preg_match_all('{\b(?:class)\b}i', $contents);
            if ($nbResults == 0) {
                return array();
            }*/
        	
            // Let's trim the content after the last "class" keyword line.
            $classKeywordPos = strrpos($contents, 'class');
            if ($classKeywordPos === false) {
            	return array();
            }
            //$classKeywordPos = $results[0][count($results[0])-1][1];
            
            // Jump 2 newlines after the last class keyword.
            if (strlen($contents) > $classKeywordPos+6) {
	            $newLinePos = strpos($contents, "\n", $classKeywordPos+6);
	            if ($newLinePos) {
		            $newLinePos = strpos($contents, "\n", $newLinePos+1);
		            if ($newLinePos) {
		            	$contents = substr($contents, 0, $newLinePos);
		            }
	            }
            }
            
            // Let's ignore any warning because we are cutting in the middle of a PHP file and we might cut in a 
            // comment.
            $currentErrorReporting = error_reporting(E_ALL & ~E_COMPILE_WARNING);
            $tokens = token_get_all($contents);
            error_reporting($currentErrorReporting);
        } catch (\Exception $e) {
            throw new \RuntimeException('Could not scan for classes inside '.$path.": \n".$e->getMessage(), 0, $e);
        }
        $T_TRAIT  = version_compare(PHP_VERSION, '5.4', '<') ? -1 : T_TRAIT;

        $classes = array();

        $namespace = '';
       	
        for ($i = 0, $max = count($tokens); $i < $max; $i++) {
            $token = $tokens[$i];

            if (is_string($token)) {
                continue;
            }

            $class = '';

            switch ($token[0]) {
                case T_NAMESPACE:
                    $namespace = '';
                    // If there is a namespace, extract it
                    while (($t = $tokens[++$i]) && is_array($t)) {
                        if (in_array($t[0], array(T_STRING, T_NS_SEPARATOR))) {
                            $namespace .= $t[1];
                        }
                    }
                    $namespace .= '\\';
                    break;
                case T_CLASS:
                //case T_INTERFACE:
                //case $T_TRAIT:
                    // Find the classname
            		
                    while (($t = $tokens[++$i]) && is_array($t)) {
                    	if (T_STRING === $t[0]) {
                            $class .= $t[1];
                        } elseif ($class !== '' && T_WHITESPACE == $t[0]) {
                            break;
                        }
                    }

                    $classes[] = ltrim($namespace . $class, '\\');
                    /*if ($nbResults == 1) {
                    	// Optim: if there is only one "class" keyword in the file, there is only one class, and we have it!
                    	return $classes;
                    }*/
                    break;
                default:
                    break;
            }
        }
        

        return $classes;
    }
1064163
private function getClasses($directory)
    {
        $classes = [];
        $directoryList = [];
        $includedFiles = [];

        $finder = new Finder();
        try {
            $finder->in($directory)->files()->name('*.php');
        } catch (\InvalidArgumentException $e) {
            return [[], []];
        }

        foreach ($finder as $file) {
            $directoryList[$file->getPath()] = true;
            $sourceFile = $file->getRealpath();
            if (!preg_match('(^phar:)i', $sourceFile)) {
                $sourceFile = realpath($sourceFile);
            }

            require_once $sourceFile;
            $includedFiles[$sourceFile] = true;
        }

        $declared = get_declared_classes();
        foreach ($declared as $className) {
            $reflectionClass = new \ReflectionClass($className);
            $sourceFile = $reflectionClass->getFileName();

            if ($reflectionClass->isAbstract()) {
                continue;
            }

            if (method_exists($reflectionClass, 'isAnonymous') && $reflectionClass->isAnonymous()) {
                continue;
            }

            if (isset($includedFiles[$sourceFile])) {
                $classes[$className] = true;
            }
        }

        return [array_keys($classes), $directoryList];
    }
490892
private function _list(string $path): array {
        $result = [];
        $scan = glob($path . '/*');
        foreach ($scan as $item) {
            if (is_dir($item)) {
                $result[basename($item)] = $this->_list($item);
            } else {
                $result[] = basename($item);
            }
        }
        return $result;
    }
244268
private function getFiles($path)
    {
        $files = [];

        if (false !== $pos = strpos($path, '*')) {
            list($before, $after) = explode('*', $path, 2);
            $input = $this->fileLocator->locate($before).'*'.$after;

            if (false !== $paths = glob($input)) {
                foreach ($paths as $path) {
                    $files[] = $path;
                }
            }
        } else {
            $files = [$this->fileLocator->locate($path)];
        }

        return $files;
    }
95966
public function extract($path, $files = array())
    {
        if (empty($files)) {
            return $this->zip->extractTo($path);
        }

        return $this->zip->extractTo($path, $files);
    }
1320114
protected static function selectClasses(string $path, string $classOrInterface): iterable
    {
        $selectedFiles = [];

        $flags = GlobIterator::SKIP_DOTS | GlobIterator::CURRENT_AS_PATHNAME;
        foreach (new GlobIterator($path, $flags) as $filePath) {
            if (is_file($filePath) === true) {
                $filePath = realpath($filePath);
                try {
                    /** @noinspection PhpIncludeInspection */
                    require_once $filePath;
                } catch (Exception $ex) {
                    // Files might have syntax errors and etc.
                    // For the purposes of this method it doesn't matter so just skip it.
                    continue;
                }
                $selectedFiles[$filePath] = true;
            }
        }

        foreach (get_declared_classes() as $class) {
            // if class actually implements requested one and ...
            if ($class === $classOrInterface || static::classInherits($class, $classOrInterface) === true) {
                // ... it was loaded from a file we've selected then...
                $reflectionClass = new ReflectionClass($class);
                if ($reflectionClass->isInstantiable() === true &&
                    ($classFileName = $reflectionClass->getFileName()) !== false &&
                    array_key_exists($classFileName, $selectedFiles) === true
                ) {
                    // ... that's what we need.
                    yield $class;
                }
            }
        }
    }
856872
public function findClasses()
    {
        $files = $this->getFiles($this->searchPath);

        // if class are not loaded they will ne be caught by "declared_classes"
        $this->loadFiles($files);

        return $this->identifyClasses();
    }
1075121
public function findMatchingFiles(string $path): array
    {
        $path = $this->validatePath($path);

        if (is_dir($path)) {
            $pathCollection = $this->findMatchingFilesInDirectory($path);
        } elseif (is_file($path)) {
            $pathCollection = [$path];
        } else {
            throw new FileException(sprintf('Could not get file(s) for path %s', $path));
        }

        $fileIncludingTests = [];
        foreach ($pathCollection as $path) {
            $file = new File($path);
            if ($this->getFileIncludesTest($file)) {
                $fileIncludingTests[] = $file;
            }
        }

        return $fileIncludingTests;
    }
755323
private function getCompiledViewPaths(string $path) : array
    {
        if (!is_dir($path)) {
            return [];
        }

        $files = [];
        $iter = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS),
            RecursiveIteratorIterator::SELF_FIRST,
            RecursiveIteratorIterator::CATCH_GET_CHILD
        );
        $iter->setMaxDepth(0);

        foreach ($iter as $path => $item) {
            if ($item->isFile()) {
                $files[] = $path;
            }
        }

        return $files;
    }
352620
private function findFeatureFiles($path)
    {
        $absolutePath = $this->findAbsolutePath($path);

        if (!$absolutePath) {
            return array($path);
        }

        if (is_file($absolutePath)) {
            return array($absolutePath);
        }

        $iterator = new RegexIterator(
            new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator(
                    $absolutePath,
                    RecursiveDirectoryIterator::FOLLOW_SYMLINKS | RecursiveDirectoryIterator::SKIP_DOTS
                )
            ),
            '/^.+\.feature$/i',
            RegexIterator::MATCH
        );

        $paths = array_map('strval', iterator_to_array($iterator));
        uasort($paths, 'strnatcasecmp');

        return $paths;
    }
455881
protected function loadFile($path): array
    {
        $reader = ReaderFactory::get($this->builder, $path);

        return $reader->read($path);
    }
922746
public function getList(string $path)
    {
        $entity = $this->getEntity($path);

        if (null !== $entity && $entity->file_exists() && $entity->is_dir()) {
            $files = [];
            $changes = $this->getChanges();
            $own = $changes->own($path);

            if (!($entity instanceof VirtualInterface)) {
                $directory = $this->getRoot();
                $directoryPath = $directory->path().'/'.$path;

                $dirHandler = opendir($directoryPath);
                if ($dirHandler) {
                    while (true) {
                        $file = readdir($dirHandler);
                        if (false === $file) {
                            break;
                        } elseif ('.' == $file || '..' == $file) {
                            continue;
                        }

                        $changesKey = ($path ? $path.'/' : '').$file;
                        if (isset($own[$changesKey])) {
                            continue;
                        }
                        $files[$changesKey] = Entity::newInstance($changesKey);
                    }
                    closedir($dirHandler);
                }
            }

            foreach ($own as $changesKey => $file) {
                /* @var $file EntityInterface */
                if ($file instanceof DeletedInterface) {
                    unset($own[$changesKey]);
                }
            }

            $mergedFiles = array_merge($files, $own);
            ksort($mergedFiles);

            $result = array_values($mergedFiles);
        } else {
            $result = null;
        }

        return $result;
    }
597159
public static function classes_for_folder($folderPath)
    {
        $absFolderPath = Director::getAbsFile($folderPath);
        $classManifest = ClassLoader::inst()->getManifest();
        $classes = $classManifest->getClasses();
        $classNames = $classManifest->getClassNames();

        $matchedClasses = [];
        foreach ($classes as $lowerClass => $compareFilePath) {
            if (stripos($compareFilePath, $absFolderPath) === 0) {
                $matchedClasses[$lowerClass] = $classNames[$lowerClass];
            }
        }

        return $matchedClasses;
    }
76761
protected function extractParameterNames($path) {
        $names = [];
        $matches = [];
        preg_match_all('#\{([a-zA-Z0-9?]+)\}#', $path, $matches);

        foreach (array_get($matches, 1, []) as $name) {
            $names[] = str_replace('?', '', $name);
        }

        return $names;
    }
927374
protected function get_files( $path ) {
		$filtered_files = array();
		try {
			$files = new RecursiveIteratorIterator(
				new RecursiveDirectoryIterator(
					$path,
					RecursiveDirectoryIterator::SKIP_DOTS
				),
				RecursiveIteratorIterator::CHILD_FIRST
			);
			foreach ( $files as $file_info ) {
				$pathname = self::normalize_directory_separators( substr( $file_info->getPathname(), strlen( $path ) ) );
				if ( $file_info->isFile() && $this->filter_file( $pathname ) ) {
					$filtered_files[] = $pathname;
				}
			}
		} catch ( Exception $e ) {
			WP_CLI::error( $e->getMessage() );
		}

		return $filtered_files;
	}
45304
public function read($path)
    {
        if ($response = $this->readStream($path)) {
            return ['contents' => stream_get_contents($response['stream']), 'path' => $response['path']];
        }

        return false;
    }
1218785
public function extract($path) {

        if (empty($path)) {
            return $this->props;
        }
        // Simple paths.
        if (!preg_match('/[{\[]/', $path)) {
            return (array)$this->get($path);
        }
        if (strpos($path, '[') === false) {
            $tokens = explode('/', $path);
        } else {
            $tokens = $this->_tokenize($path, '/', '[', ']');
        }
        $_key = '__set_item__';
        $context = array($_key => array($this->props));
        foreach ($tokens as $token) {
            $next = array();
            list($token, $conditions) = $this->_splitConditions($token);
            foreach ($context[$_key] as $item) {
                foreach ((array)$item as $k => $v) {
                    if ($this->_matchToken($k, $token)) {
                        $next[] = $v;
                    }
                }
            }
            // Filter for attributes.
            if ($conditions) {
                $filter = array();
                foreach ($next as $item) {
                    if (is_array($item) && $this->_matches($item, $conditions)) {
                        $filter[] = $item;
                    }
                }
                $next = $filter;
            }
            $context = array($_key => $next);
        }
        return $context[$_key];
    }