Chris@12: Chris@12: * @license http://www.opensource.org/licenses/mit-license.php MIT Chris@12: * @link http://phpdoc.org Chris@12: */ Chris@12: Chris@12: namespace phpDocumentor\Reflection\DocBlock; Chris@12: Chris@12: use phpDocumentor\Reflection\DocBlock\Tags\Formatter; Chris@12: use phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter; Chris@12: use Webmozart\Assert\Assert; Chris@12: Chris@12: /** Chris@12: * Object representing to description for a DocBlock. Chris@12: * Chris@12: * A Description object can consist of plain text but can also include tags. A Description Formatter can then combine Chris@12: * a body template with sprintf-style placeholders together with formatted tags in order to reconstitute a complete Chris@12: * description text using the format that you would prefer. Chris@12: * Chris@12: * Because parsing a Description text can be a verbose process this is handled by the {@see DescriptionFactory}. It is Chris@12: * thus recommended to use that to create a Description object, like this: Chris@12: * Chris@12: * $description = $descriptionFactory->create('This is a {@see Description}', $context); Chris@12: * Chris@12: * The description factory will interpret the given body and create a body template and list of tags from them, and pass Chris@12: * that onto the constructor if this class. Chris@12: * Chris@12: * > The $context variable is a class of type {@see \phpDocumentor\Reflection\Types\Context} and contains the namespace Chris@12: * > and the namespace aliases that apply to this DocBlock. These are used by the Factory to resolve and expand partial Chris@12: * > type names and FQSENs. Chris@12: * Chris@12: * If you do not want to use the DescriptionFactory you can pass a body template and tag listing like this: Chris@12: * Chris@12: * $description = new Description( Chris@12: * 'This is a %1$s', Chris@12: * [ new See(new Fqsen('\phpDocumentor\Reflection\DocBlock\Description')) ] Chris@12: * ); Chris@12: * Chris@12: * It is generally recommended to use the Factory as that will also apply escaping rules, while the Description object Chris@12: * is mainly responsible for rendering. Chris@12: * Chris@12: * @see DescriptionFactory to create a new Description. Chris@12: * @see Description\Formatter for the formatting of the body and tags. Chris@12: */ Chris@12: class Description Chris@12: { Chris@12: /** @var string */ Chris@12: private $bodyTemplate; Chris@12: Chris@12: /** @var Tag[] */ Chris@12: private $tags; Chris@12: Chris@12: /** Chris@12: * Initializes a Description with its body (template) and a listing of the tags used in the body template. Chris@12: * Chris@12: * @param string $bodyTemplate Chris@12: * @param Tag[] $tags Chris@12: */ Chris@12: public function __construct($bodyTemplate, array $tags = []) Chris@12: { Chris@12: Assert::string($bodyTemplate); Chris@12: Chris@12: $this->bodyTemplate = $bodyTemplate; Chris@12: $this->tags = $tags; Chris@12: } Chris@12: Chris@12: /** Chris@12: * Returns the tags for this DocBlock. Chris@12: * Chris@12: * @return Tag[] Chris@12: */ Chris@12: public function getTags() Chris@12: { Chris@12: return $this->tags; Chris@12: } Chris@12: Chris@12: /** Chris@12: * Renders this description as a string where the provided formatter will format the tags in the expected string Chris@12: * format. Chris@12: * Chris@12: * @param Formatter|null $formatter Chris@12: * Chris@12: * @return string Chris@12: */ Chris@12: public function render(Formatter $formatter = null) Chris@12: { Chris@12: if ($formatter === null) { Chris@12: $formatter = new PassthroughFormatter(); Chris@12: } Chris@12: Chris@12: $tags = []; Chris@12: foreach ($this->tags as $tag) { Chris@12: $tags[] = '{' . $formatter->format($tag) . '}'; Chris@12: } Chris@12: Chris@12: return vsprintf($this->bodyTemplate, $tags); Chris@12: } Chris@12: Chris@12: /** Chris@12: * Returns a plain string representation of this description. Chris@12: * Chris@12: * @return string Chris@12: */ Chris@12: public function __toString() Chris@12: { Chris@12: return $this->render(); Chris@12: } Chris@12: }