Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Reflection: get constant's doc comment

It is easy to retrieve the doc comment for methods and properties. But what about constants? There is no ReflectionConstant class which would allow me to call getDocComment() on them. It's possible to get the list of constants and their values as strings using ReflectionClass::getConstants but that's all. Is there a workaround?

like image 531
tobik Avatar asked Dec 19 '22 17:12

tobik


1 Answers

To my best knowledge there is no built-in function or class that allows you to retrieve class constant doc comments. However, you can use token_get_all($classContent) and write your own parser.

Here is what I have come up with, after needing this feature as well:

/**
 * Simple DocComment support for class constants.
 */
class ConstDoc
{
    /** @var array Constant names to DocComment strings. */
    private $docComments = [];

    /** Constructor. */
    public function __construct($clazz)
    {
        $this->parse(new \ReflectionClass($clazz));
    }

    /** Parses the class for constant DocComments. */
    private function parse(\ReflectionClass $clazz)
    {
        $content = file_get_contents($clazz->getFileName());
        $tokens = token_get_all($content);

        $doc = null;
        $isConst = false;
        foreach($tokens as $token)
        {
            if (!is_array($token) || count($token) <= 1)
            {
                continue;
            }

            list($tokenType, $tokenValue) = $token;

            switch ($tokenType)
            {
                // ignored tokens
                case T_WHITESPACE:
                case T_COMMENT:
                    break;

                case T_DOC_COMMENT:
                    $doc = $tokenValue;
                    break;

                case T_CONST:
                    $isConst = true;
                    break;

                case T_STRING:
                    if ($isConst)
                    {
                        $this->docComments[$tokenValue] = self::clean($doc);
                    }
                    $doc = null;
                    $isConst = false;
                    break;

                // all other tokens reset the parser
                default:
                    $doc = null;
                    $isConst = false;
                    break;
            }
        }
    }

    /** Returns an array of all constants to their DocComment. If no comment is present the comment is null. */
    public function getDocComments()
    {
        return $this->docComments;
    }

    /** Returns the DocComment of a class constant. Null if the constant has no DocComment or the constant does not exist. */
    public function getDocComment($constantName)
    {
        if (!isset($this->docComments) || !isset($this->docComments[$constantName]))
        {
            return null;
        }

        return $this->docComments[$constantName];
    }

    /** Cleans the doc comment. Returns null if the doc comment is null. */
    private static function clean($doc)
    {
        if ($doc === null)
        {
            return null;
        }

        $result = null;
        $lines = preg_split('/\R/', $doc);
        foreach($lines as $line)
        {
            $line = trim($line, "/* \t\x0B\0");
            if ($line === '')
            {
                continue;
            }

            if ($result != null)
            {
                $result .= ' ';
            }
            $result .= $line;
        }
        return $result;
    }
}
like image 162
mpdeimos Avatar answered Dec 24 '22 02:12

mpdeimos