예제 #1
0
 /** @return array */
 public function generateRoutes()
 {
     $controllerFiles = array();
     foreach ($this->controllerDirs as $dir) {
         $controllerFiles = array_merge($controllerFiles, FileList::getFilesRecursively($dir));
     }
     $classes = array();
     foreach ($controllerFiles as $file) {
         $content = file_get_contents($file);
         $namespace = '';
         if (preg_match('/^namespace\\s+(\\S+);$/m', $content, $namespaceMatch)) {
             $namespace = '\\' . $namespaceMatch[1];
         }
         if (!preg_match('/^class\\s+(\\S+)(?:(?:\\s+extends|\\s+implements|\\s*\\{)|$)/m', $content, $classMatch)) {
             continue;
         }
         $class = $classMatch[1];
         $classes[] = $namespace . '\\' . $class;
     }
     $routes = array();
     foreach ($classes as $class) {
         $rClass = new \ReflectionClass($class);
         $classPattern = '';
         $classDefaults = array();
         $classPriority = 0;
         foreach (AnnotationReader::getPhpdocTags($rClass->getDocComment()) as $annotation) {
             if ($annotation['name'] != 'route') {
                 continue;
             }
             if (!empty($classPattern)) {
                 throw new \Exception("Class {$class} has more than one @route annotation");
             }
             $classPriority = $this->shiftPriorityFromArgs($annotation['args']);
             if (empty($annotation['args'])) {
                 throw new \Exception("Class {$class} has incorrect @route annotation (syntax: @route [priority=123] /blah)");
             }
             $classPattern = array_shift($annotation['args']);
             $classDefaults = $annotation['args'];
         }
         $rMethods = $rClass->getMethods();
         foreach ($rMethods as $rMethod) {
             if ($rMethod->isAbstract() || !$rMethod->isPublic() || $rMethod->isStatic()) {
                 continue;
             }
             foreach (AnnotationReader::getPhpdocTags($rMethod->getDocComment()) as $annotation) {
                 if ($annotation['name'] != 'route') {
                     continue;
                 }
                 // TODO файлы и строки/методы в тексты исключений
                 $priority = $this->shiftPriorityFromArgs($annotation['args'], $classPriority);
                 if (!empty($annotation['args']) && preg_match('/^priority=(-?\\d+)$/', $annotation['args'][0], $match)) {
                     $priority = (int) $match[1];
                     array_shift($annotation['args']);
                 }
                 if (count($annotation['args']) < 2) {
                     throw new \Exception('Incorrect annotation: ' . $annotation['string'] . ' (syntax: @route [priority=123] GET /blah)');
                 }
                 $method = array_shift($annotation['args']);
                 if (!preg_match('/^[A-Z]+$/', $method)) {
                     throw new \Exception('Incorrect HTTP method in annotation: ' . $annotation['string']);
                 }
                 // class route "/blah" and method route "/" should give "/blah", not "/blah/"
                 $pattern = rtrim($classPattern . array_shift($annotation['args']), '/');
                 $defaultDefs = array_merge($classDefaults, $annotation['args']);
                 $defaults = array();
                 foreach ($defaultDefs as $def) {
                     $parts = explode('=', $def, 2);
                     if (count($parts) != 2) {
                         throw new \Exception("Incorrect route default: {$def} in " . $annotation['string']);
                     }
                     $defaults[$parts[0]] = $parts[1];
                 }
                 $routes[] = array('callback' => array($class, $rMethod->getName()), 'method' => $method, 'pattern' => $pattern, 'regexp' => static::makeRouteRegexp($pattern), 'defaults' => $defaults, 'priority' => $priority);
             }
         }
     }
     // STOPPER финансер не работает, нужно или сделать поддержку форматов или как-то мозг не ебать, или в разделители добавить кроме / еще всякие _,-.
     //$this->ensureNoOverlappingRoutes($routes);
     $routes = $this->sortRoutesByPriority($routes);
     // we don't want to cache unnecessary data
     foreach ($routes as $i => $route) {
         unset($routes[$i]['pattern'], $routes[$i]['priority']);
     }
     return $routes;
 }
예제 #2
0
 /**
  * @dataProvider phpdocTagsProvider
  */
 public function testGetPhpdocTags($expected, $phpdoc)
 {
     $this->assertEquals($expected, AnnotationReader::getPhpdocTags($phpdoc));
 }