mirror of
https://github.com/barryvdh/ReflectionDocBlock.git
synced 2026-08-18 01:57:13 +00:00
Add example on writing your own Tag and prepare for TagFactory objects
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
require_once(__DIR__ . '/../vendor/autoload.php');
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Serializer;
|
||||
@@ -18,6 +19,9 @@ DOCCOMMENT;
|
||||
$factory = DocBlockFactory::createInstance();
|
||||
$docblock = $factory->create($docComment);
|
||||
|
||||
$serializer = new Serializer();
|
||||
// Create the serializer that will reconstitute the DocBlock back to its original form.
|
||||
$serializer = new Serializer();
|
||||
|
||||
// Reconstitution is performed by the `getDocComment()` method.
|
||||
$reconstitutedDocComment = $serializer->getDocComment($docblock);
|
||||
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
/**
|
||||
* In this example we demonstrate how you can add your own Tag using a Static Factory method in your Tag class.
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../vendor/autoload.php');
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Serializer;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod;
|
||||
use phpDocumentor\Reflection\DocBlockFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\BaseTag;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
/**
|
||||
* An example of a custom tag called `my-tag` with an optional description.
|
||||
*
|
||||
* A Custom Tag is a class that can consist of two parts:
|
||||
*
|
||||
* 1. a method `create` that is a static factory for this class.
|
||||
* 2. methods and properties that have this object act as an immutable Value Object representing a Tag instance.
|
||||
*
|
||||
* The static factory `create` is used to convert a tag line (without the tag name) into an instance of the
|
||||
* same tag object with the right constructor parameters set. This method has a dynamic list of parameters so that you
|
||||
* can inject various dependencies, see the method's DocBlock for more information.
|
||||
*
|
||||
* An object of this class, and its methods and properties, represent a single instance of that tag in your
|
||||
* documentation in the form of a Value Object whose properties should not be changed after instantiation (it should be
|
||||
* immutable).
|
||||
*
|
||||
* > Important: Tag classes that act as Factories using the `create` method should implement the TagFactory interface.
|
||||
*/
|
||||
final class MyTag extends BaseTag implements StaticMethod
|
||||
{
|
||||
/**
|
||||
* A required property that is used by Formatters to reconstitute the complete tag line.
|
||||
*
|
||||
* @see Formatter
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'my-tag';
|
||||
|
||||
/**
|
||||
* The constructor for this Tag; this should contain all properties for this object.
|
||||
*
|
||||
* @param Description $description An example of how to add a Description to the tag; the Description is often
|
||||
* an optional variable so passing null is allowed in this instance (though you can
|
||||
* also construct an empty description object).
|
||||
*
|
||||
* @see BaseTag for the declaration of the description property and getDescription method.
|
||||
*/
|
||||
public function __construct(Description $description = null)
|
||||
{
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* A static Factory that creates a new instance of the current Tag.
|
||||
*
|
||||
* In this example the MyTag tag can be created by passing a description text as $body. Because we have added
|
||||
* a $descriptionFactory that is type-hinted as DescriptionFactory we can now construct a new Description object
|
||||
* and pass that to the constructor.
|
||||
*
|
||||
* > You could directly instantiate a Description object here but that won't be parsed for inline tags and Types
|
||||
* > won't be resolved. The DescriptionFactory will take care of those actions.
|
||||
*
|
||||
* The `create` method's interface states that this method only features a single parameter (`$body`) but the
|
||||
* {@see TagFactory} will read the signature of this method and if it has more parameters then it will try
|
||||
* to find declarations for it in the ServiceLocator of the TagFactory (see {@see TagFactory::$serviceLocator}).
|
||||
*
|
||||
* > Important: all properties following the `$body` should default to `null`, otherwise PHP will error because
|
||||
* > it no longer matches the interface. This is why you often see the default tags check that an optional argument
|
||||
* > is not null nonetheless.
|
||||
*
|
||||
* @param string $body
|
||||
* @param DescriptionFactory $descriptionFactory
|
||||
* @param Context|null $context The Context is used to resolve Types and FQSENs, although optional
|
||||
* it is highly recommended to pass it. If you omit it then it is assumed that
|
||||
* the DocBlock is in the global namespace and has no `use` statements.
|
||||
*
|
||||
* @see Tag for the interface declaration of the `create` method.
|
||||
* @see Tag::create() for more information on this method's workings.
|
||||
*
|
||||
* @return MyTag
|
||||
*/
|
||||
public static function create($body, DescriptionFactory $descriptionFactory = null, Context $context = null)
|
||||
{
|
||||
Assert::string($body);
|
||||
Assert::notNull($descriptionFactory);
|
||||
|
||||
return new static($descriptionFactory->create($body, $context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rendition of the original tag line.
|
||||
*
|
||||
* This method is used to reconstitute a DocBlock into its original form by the {@see Serializer}. It should
|
||||
* feature all parts of the tag so that the serializer can put it back together.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string)$this->description;
|
||||
}
|
||||
}
|
||||
|
||||
$docComment = <<<DOCCOMMENT
|
||||
/**
|
||||
* This is an example of a summary.
|
||||
*
|
||||
* @my-tag I have a description
|
||||
*/
|
||||
DOCCOMMENT;
|
||||
|
||||
// Make a mapping between the tag name `my-tag` and the Tag class containing the Factory Method `create`.
|
||||
$customTags = ['my-tag' => MyTag::class];
|
||||
|
||||
// Do pass the list of custom tags to the Factory for the DocBlockFactory.
|
||||
$factory = DocBlockFactory::createInstance($customTags);
|
||||
// You can also add Tags later using `$factory->registerTagHandler()` with a tag name and Tag class name.
|
||||
|
||||
// Create the DocBlock
|
||||
$docblock = $factory->create($docComment);
|
||||
|
||||
// Take a look: the $customTagObjects now contain an array with your newly added tag
|
||||
$customTagObjects = $docblock->getTagsByName('my-tag');
|
||||
|
||||
// As an experiment: let's reconstitute the DocBlock and observe that because we added a __toString() method
|
||||
// to the tag class that we can now also see it.
|
||||
$serializer = new Serializer();
|
||||
$reconstitutedDocComment = $serializer->getDocComment($docblock);
|
||||
@@ -109,7 +109,8 @@ class Serializer
|
||||
*/
|
||||
private function getSummaryAndDescriptionTextBlock(DocBlock $docblock, $wrapLength)
|
||||
{
|
||||
$text = $docblock->getSummary() . "\n\n" . $docblock->getDescription();
|
||||
$text = $docblock->getSummary() . ((string)$docblock->getDescription() ? "\n\n" . $docblock->getDescription()
|
||||
: '');
|
||||
if ($wrapLength !== null) {
|
||||
$text = wordwrap($text, $wrapLength);
|
||||
return $text;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Generic;
|
||||
use phpDocumentor\Reflection\FqsenResolver;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
@@ -139,7 +140,7 @@ final class StandardTagFactory implements TagFactory
|
||||
Assert::stringNotEmpty($tagName);
|
||||
Assert::stringNotEmpty($handler);
|
||||
Assert::classExists($handler);
|
||||
Assert::implementsInterface($handler, Tag::class);
|
||||
Assert::implementsInterface($handler, StaticMethod::class);
|
||||
|
||||
if (strpos($tagName, '\\') && $tagName[0] !== '\\') {
|
||||
throw new \InvalidArgumentException(
|
||||
|
||||
@@ -17,7 +17,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for an {@}author tag in a Docblock.
|
||||
*/
|
||||
final class Author extends BaseTag
|
||||
final class Author extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
/** @var string register that this is the author tag. */
|
||||
protected $name = 'author';
|
||||
|
||||
@@ -22,7 +22,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a @covers tag in a Docblock.
|
||||
*/
|
||||
final class Covers extends BaseTag
|
||||
final class Covers extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
protected $name = 'covers';
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a {@}deprecated tag in a Docblock.
|
||||
*/
|
||||
final class Deprecated extends BaseTag
|
||||
final class Deprecated extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
protected $name = 'deprecated';
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
interface StaticMethod
|
||||
{
|
||||
public static function create($body);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
interface Strategy
|
||||
{
|
||||
public function create($body);
|
||||
}
|
||||
@@ -21,7 +21,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Parses a tag definition for a DocBlock.
|
||||
*/
|
||||
class Generic extends BaseTag
|
||||
class Generic extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
/**
|
||||
* Parses a tag and populates the member variables.
|
||||
|
||||
@@ -20,7 +20,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a @link tag in a Docblock.
|
||||
*/
|
||||
final class Link extends BaseTag
|
||||
final class Link extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
protected $name = 'link';
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for an {@}method in a Docblock.
|
||||
*/
|
||||
final class Method extends BaseTag
|
||||
final class Method extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
protected $name = 'method';
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for the {@}param tag in a Docblock.
|
||||
*/
|
||||
final class Param extends BaseTag
|
||||
final class Param extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
/** @var string */
|
||||
protected $name = 'param';
|
||||
|
||||
@@ -22,7 +22,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a {@}property tag in a Docblock.
|
||||
*/
|
||||
class Property extends BaseTag
|
||||
class Property extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
/** @var string */
|
||||
protected $name = 'property';
|
||||
|
||||
@@ -22,7 +22,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a {@}property-read tag in a Docblock.
|
||||
*/
|
||||
class PropertyRead extends BaseTag
|
||||
class PropertyRead extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
/** @var string */
|
||||
protected $name = 'property-read';
|
||||
|
||||
@@ -22,7 +22,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a {@}property-write tag in a Docblock.
|
||||
*/
|
||||
class PropertyWrite extends BaseTag
|
||||
class PropertyWrite extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
/** @var string */
|
||||
protected $name = 'property-write';
|
||||
|
||||
@@ -22,7 +22,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a {@}return tag in a Docblock.
|
||||
*/
|
||||
final class Return_ extends BaseTag
|
||||
final class Return_ extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
protected $name = 'return';
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for an {@}see tag in a Docblock.
|
||||
*/
|
||||
class See extends BaseTag
|
||||
class See extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
protected $name = 'see';
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a {@}since tag in a Docblock.
|
||||
*/
|
||||
final class Since extends BaseTag
|
||||
final class Since extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
protected $name = 'since';
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a {@}source tag in a Docblock.
|
||||
*/
|
||||
final class Source extends BaseTag
|
||||
final class Source extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
/** @var string */
|
||||
protected $name = 'source';
|
||||
|
||||
@@ -22,7 +22,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a {@}throws tag in a Docblock.
|
||||
*/
|
||||
final class Throws extends BaseTag
|
||||
final class Throws extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
protected $name = 'throws';
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a {@}uses tag in a Docblock.
|
||||
*/
|
||||
final class Uses extends BaseTag
|
||||
final class Uses extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
protected $name = 'uses';
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a {@}var tag in a Docblock.
|
||||
*/
|
||||
class Var_ extends BaseTag
|
||||
class Var_ extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
/** @var string */
|
||||
protected $name = 'var';
|
||||
|
||||
@@ -20,7 +20,7 @@ use Webmozart\Assert\Assert;
|
||||
/**
|
||||
* Reflection class for a {@}version tag in a Docblock.
|
||||
*/
|
||||
final class Version extends BaseTag
|
||||
final class Version extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
protected $name = 'version';
|
||||
|
||||
|
||||
@@ -54,11 +54,12 @@ final class DocBlockFactory implements DocBlockFactoryInterface
|
||||
$tagFactory->addService($descriptionFactory);
|
||||
$tagFactory->addService(new TypeResolver($fqsenResolver));
|
||||
|
||||
foreach ($additionalTags as $tagName => $tagClassName) {
|
||||
$tagFactory->registerTagHandler($tagName, $tagClassName);
|
||||
$docBlockFactory = new self($descriptionFactory, $tagFactory);
|
||||
foreach ($additionalTags as $tagName => $tagHandler) {
|
||||
$docBlockFactory->registerTagHandler($tagName, $tagHandler);
|
||||
}
|
||||
|
||||
return new self($descriptionFactory, $tagFactory);
|
||||
return $docBlockFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,6 +101,11 @@ final class DocBlockFactory implements DocBlockFactoryInterface
|
||||
);
|
||||
}
|
||||
|
||||
public function registerTagHandler($tagName, $handler)
|
||||
{
|
||||
$this->tagFactory->registerTagHandler($tagName, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips the asterisks from the DocBlock comment.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\StandardTagFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\See;
|
||||
|
||||
/**
|
||||
* @coversNothing
|
||||
*/
|
||||
class UsingTagsTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testAddingYourOwnTagUsingAStaticMethodAsFactory()
|
||||
{
|
||||
/**
|
||||
* @var object[] $customTagObjects
|
||||
* @var string $docComment
|
||||
* @var string $reconstitutedDocComment
|
||||
*/
|
||||
include(__DIR__ . '/../../examples/04-adding-your-own-tag.php');
|
||||
|
||||
$this->assertInstanceOf(\MyTag::class, $customTagObjects[0]);
|
||||
$this->assertSame('my-tag', $customTagObjects[0]->getName());
|
||||
$this->assertSame('I have a description', (string)$customTagObjects[0]->getDescription());
|
||||
$this->assertSame($docComment, $reconstitutedDocComment);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user