class = $class; } public static function fromClass($class) : self { return new static($class); } public function getProperty(ReflectionProperty $property) { return $this->parseDocComment($property); } public function getClass(ReflectionClass $class) { return $this->parseDocComment($class); } public function getMethod(ReflectionMethod $method) { return $this->parseDocComment($method); } protected function parseDocComment(\Reflector $reflect) { $tags = []; if ( $attributes = $reflect->getAttributes() ) { foreach($attributes as $attr) { try { $tags[] = [ 'tag' => substr(strrchr($attr->getName(), "\\"), 1), 'arguments' => $attr->getArguments(), 'object' => $attr->newInstance(), ]; } catch(\Throwable $e) { throw new \Exception(sprintf("%s for %s in file '%s'", $e->getMessage(), $reflect, $this->class)); } } } else { $namespace = $this->getObjectNamespace($reflect); foreach (preg_split("/\r\n|\n|\r/", $reflect->getDocComment()) as $line) { $line = ltrim($line, "* \t\/"); $line = rtrim($line, "\t "); if (substr($line, 0, 1) === '@') { $line = ltrim($line, '@'); $open = strpos($line, "("); $close = strrpos($line, ")"); if (!in_array(false, [$open, $close], true) && (++$open !== $close)) { $arguments = substr($line, $open, $close - $open); try { $tags[] = [ 'tag' => substr($line, 0, $open - 1), 'arguments' => eval("namespace $namespace; return [ $arguments ];"), ]; } catch (\Throwable $error) { throw new \InvalidArgumentException("An error occured while parsing annotation from '" . $this->getObjectName($reflect) . "' : @$line -- " . $error->getMessage()); } } else { $tags[] = [ 'tag' => $line, 'arguments' => [], ]; } } } } return $tags; } protected function getObjectName(Reflector $reflect) : string { switch(true) { case $reflect instanceof ReflectionMethod : case $reflect instanceof ReflectionProperty : return $reflect->class . "::" . $reflect->name; case $reflect instanceof ReflectionClass : return $reflect->name; } } protected function getObjectNamespace(Reflector $reflect) : string { switch(true) { case $reflect instanceof ReflectionMethod : case $reflect instanceof ReflectionProperty : return $reflect->getDeclaringClass()->getNamespaceName(); case $reflect instanceof ReflectionClass : return $reflect->getNamespaceName(); } } }