baeb4c1abad42dd74996c9c3556f575ee9d8bc69
[yaffs-website] / vendor / symfony / class-loader / ClassMapGenerator.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\ClassLoader;
13
14 /**
15  * ClassMapGenerator.
16  *
17  * @author Gyula Sallai <salla016@gmail.com>
18  */
19 class ClassMapGenerator
20 {
21     /**
22      * Generate a class map file.
23      *
24      * @param array|string $dirs Directories or a single path to search in
25      * @param string       $file The name of the class map file
26      */
27     public static function dump($dirs, $file)
28     {
29         $dirs = (array) $dirs;
30         $maps = array();
31
32         foreach ($dirs as $dir) {
33             $maps = array_merge($maps, static::createMap($dir));
34         }
35
36         file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
37     }
38
39     /**
40      * Iterate over all files in the given directory searching for classes.
41      *
42      * @param \Iterator|string $dir The directory to search in or an iterator
43      *
44      * @return array A class map array
45      */
46     public static function createMap($dir)
47     {
48         if (is_string($dir)) {
49             $dir = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir));
50         }
51
52         $map = array();
53
54         foreach ($dir as $file) {
55             if (!$file->isFile()) {
56                 continue;
57             }
58
59             $path = $file->getRealPath() ?: $file->getPathname();
60
61             if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') {
62                 continue;
63             }
64
65             $classes = self::findClasses($path);
66
67             if (\PHP_VERSION_ID >= 70000) {
68                 // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
69                 gc_mem_caches();
70             }
71
72             foreach ($classes as $class) {
73                 $map[$class] = $path;
74             }
75         }
76
77         return $map;
78     }
79
80     /**
81      * Extract the classes in the given file.
82      *
83      * @param string $path The file to check
84      *
85      * @return array The found classes
86      */
87     private static function findClasses($path)
88     {
89         $contents = file_get_contents($path);
90         $tokens = token_get_all($contents);
91
92         $classes = array();
93
94         $namespace = '';
95         for ($i = 0; isset($tokens[$i]); ++$i) {
96             $token = $tokens[$i];
97
98             if (!isset($token[1])) {
99                 continue;
100             }
101
102             $class = '';
103
104             switch ($token[0]) {
105                 case T_NAMESPACE:
106                     $namespace = '';
107                     // If there is a namespace, extract it
108                     while (isset($tokens[++$i][1])) {
109                         if (in_array($tokens[$i][0], array(T_STRING, T_NS_SEPARATOR))) {
110                             $namespace .= $tokens[$i][1];
111                         }
112                     }
113                     $namespace .= '\\';
114                     break;
115                 case T_CLASS:
116                 case T_INTERFACE:
117                 case T_TRAIT:
118                     // Skip usage of ::class constant
119                     $isClassConstant = false;
120                     for ($j = $i - 1; $j > 0; --$j) {
121                         if (!isset($tokens[$j][1])) {
122                             break;
123                         }
124
125                         if (T_DOUBLE_COLON === $tokens[$j][0]) {
126                             $isClassConstant = true;
127                             break;
128                         } elseif (!in_array($tokens[$j][0], array(T_WHITESPACE, T_DOC_COMMENT, T_COMMENT))) {
129                             break;
130                         }
131                     }
132
133                     if ($isClassConstant) {
134                         break;
135                     }
136
137                     // Find the classname
138                     while (isset($tokens[++$i][1])) {
139                         $t = $tokens[$i];
140                         if (T_STRING === $t[0]) {
141                             $class .= $t[1];
142                         } elseif ('' !== $class && T_WHITESPACE === $t[0]) {
143                             break;
144                         }
145                     }
146
147                     $classes[] = ltrim($namespace.$class, '\\');
148                     break;
149                 default:
150                     break;
151             }
152         }
153
154         return $classes;
155     }
156 }