| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | /* | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  * Copyright 2011 Johannes M. Schmitt <[email protected]> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  |  * you may not use this file except in compliance with the License. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  |  * You may obtain a copy of the License at | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |  * http://www.apache.org/licenses/LICENSE-2.0 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  |  * Unless required by applicable law or agreed to in writing, software | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |  * See the License for the specific language governing permissions and | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  |  * limitations under the License. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | namespace JMS\SerializerBundle\Cache; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | use Metadata\MetadataFactoryInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | use Symfony\Component\Finder\Finder; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |  * @author Asmir Mustafic <[email protected]> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  | class CacheWarmer implements CacheWarmerInterface | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |      * @var MetadataFactoryInterface | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |     private $metadataFactory; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |      * @var string[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |     private $includePaths = array(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |      * @var string[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |     private $excludePaths = array(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |     public function __construct(array $includePaths, MetadataFactoryInterface $metadataFactory, array $excludePaths = array()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |         $this->metadataFactory = $metadataFactory; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |         $this->includePaths = $includePaths; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |         $this->excludePaths = $excludePaths; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 49 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 50 |  |  |     public function warmUp($cacheDir) | 
            
                                                                        
                            
            
                                    
            
            
                | 51 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 52 |  |  |         $finder = Finder::create() | 
            
                                                                        
                            
            
                                    
            
            
                | 53 |  |  |             ->ignoreVCS(true) | 
            
                                                                        
                            
            
                                    
            
            
                | 54 |  |  |             ->ignoreDotFiles(true) | 
            
                                                                        
                            
            
                                    
            
            
                | 55 |  |  |             ->ignoreUnreadableDirs(true) | 
            
                                                                        
                            
            
                                    
            
            
                | 56 |  |  |             ->in($this->includePaths) | 
            
                                                                        
                            
            
                                    
            
            
                | 57 |  |  |             ->exclude($this->excludePaths) | 
            
                                                                        
                            
            
                                    
            
            
                | 58 |  |  |             ->name('*.php'); | 
            
                                                                        
                            
            
                                    
            
            
                | 59 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 60 |  |  |         foreach ($finder as $file) { | 
            
                                                                        
                            
            
                                    
            
            
                | 61 |  |  |             $classes = self::findClasses($file->getPathname()); | 
            
                                                                        
                            
            
                                    
            
            
                | 62 |  |  |             foreach ($classes as $class) { | 
            
                                                                        
                            
            
                                    
            
            
                | 63 |  |  |                 $this->metadataFactory->getMetadataForClass($class); | 
            
                                                                        
                            
            
                                    
            
            
                | 64 |  |  |             } | 
            
                                                                        
                            
            
                                    
            
            
                | 65 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 66 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |     public function isOptional() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |         return true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |      * Extract the classes in the given file. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |      * This has been copied from https://github.com/composer/composer/blob/bfed974ae969635e622c4844e5e69526d8459baf/src/Composer/Autoload/ClassMapGenerator.php#L120-L214 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |      * @param  string $path The file to check | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |      * @throws \RuntimeException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |      * @return array             The found classes | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |     private static function findClasses($path) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |         $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |         if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |             $extraTypes .= '|enum'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |         // Use @ here instead of Silencer to actively suppress 'unhelpful' output | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |         // @link https://github.com/composer/composer/pull/4886 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |         $contents = @php_strip_whitespace($path); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |         if (!$contents) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |             if (!file_exists($path)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |                 $message = 'File at "%s" does not exist, check your classmap definitions'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |             } elseif (!is_readable($path)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |                 $message = 'File at "%s" is not readable, check its permissions'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |             } elseif ('' === trim(file_get_contents($path))) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |                 // The input file was really empty and thus contains no classes | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |                 return array(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |             } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |                 $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |             $error = error_get_last(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |             if (isset($error['message'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |                 $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |             throw new \RuntimeException(sprintf($message, $path)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |         // return early if there is no chance of matching anything in this file | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |         if (!preg_match('{\b(?:class|interface' . $extraTypes . ')\s}i', $contents)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |             return array(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |         // strip heredocs/nowdocs | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |         $contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |         // strip strings | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |         $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |         // strip leading non-php code if needed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |         if (substr($contents, 0, 2) !== '<?') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |             $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |             if ($replacements === 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |                 return array(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |         // strip non-php blocks in the file | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |         $contents = preg_replace('{\?>.+<\?}s', '?><?', $contents); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |         // strip trailing non-php code if needed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |         $pos = strrpos($contents, '?>'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |         if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |             $contents = substr($contents, 0, $pos); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |         preg_match_all('{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |             (?: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |                  \b(?<![\$:>])(?P<type>class|interface' . $extraTypes . ') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |                | \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |             ) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |         }ix', $contents, $matches); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |         $classes = array(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |         $namespace = ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |         for ($i = 0, $len = count($matches['type']); $i < $len; $i++) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |             if (!empty($matches['ns'][$i])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |                 $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |             } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |                 $name = $matches['name'][$i]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |                 // skip anon classes extending/implementing | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |                 if ($name === 'extends' || $name === 'implements') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |                     continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  |                 if ($name[0] === ':') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  |                     // This is an XHP class, https://github.com/facebook/xhp | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |                     $name = 'xhp' . substr(str_replace(array('-', ':'), array('_', '__'), $name), 1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |                 } elseif ($matches['type'][$i] === 'enum') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |                     // In Hack, something like: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |                     //   enum Foo: int { HERP = '123'; } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |                     // The regex above captures the colon, which isn't part of | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |                     // the class name. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |                     $name = rtrim($name, ':'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  |                 $classes[] = ltrim($namespace . $name, '\\'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  |         return $classes; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 169 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 170 |  |  |  |