clean install

This commit is contained in:
2024-12-10 15:08:16 +01:00
commit e14eb2d8fd
31193 changed files with 3555714 additions and 0 deletions

View File

@@ -0,0 +1,445 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock;
use InvalidArgumentException;
use LogicException;
use phootwork\collection\ArrayList;
use phootwork\collection\Map;
use phootwork\lang\Comparator;
use phpowermove\docblock\tags\AbstractTag;
use phpowermove\docblock\tags\TagFactory;
use ReflectionClass;
use ReflectionFunctionAbstract;
use ReflectionProperty;
class Docblock implements \Stringable {
protected string $shortDescription;
protected string $longDescription;
protected ArrayList $tags;
protected ?Comparator $comparator = null;
public const REGEX_TAGNAME = '[\w\-\_\\\\]+';
/**
* Static docblock factory
*
* @param ReflectionFunctionAbstract|ReflectionClass|ReflectionProperty|string $docblock a docblock to parse
*
* @return $this
*/
public static function create(ReflectionFunctionAbstract|ReflectionClass|ReflectionProperty|string $docblock = ''): self {
return new static($docblock);
}
/**
* Creates a new docblock instance and parses the initial string or reflector object if given
*
* @param ReflectionFunctionAbstract|ReflectionClass|ReflectionProperty|string $docblock a docblock to parse
*/
final public function __construct(ReflectionFunctionAbstract|ReflectionClass|ReflectionProperty|string $docblock = '') {
$this->tags = new ArrayList();
$this->parse($docblock);
}
/**
* @see https://github.com/phpDocumentor/ReflectionDocBlock/blob/master/src/phpDocumentor/Reflection/DocBlock.php Original Method
*
* @param ReflectionFunctionAbstract|ReflectionClass|ReflectionProperty|string $docblock
*
* @throws InvalidArgumentException if there is no getDocComment() method available
*/
protected function parse(ReflectionFunctionAbstract|ReflectionClass|ReflectionProperty|string $docblock): void {
$docblock = is_object($docblock) ? $docblock->getDocComment() : $docblock;
$docblock = $this->cleanInput($docblock);
[$short, $long, $tags] = $this->splitDocBlock($docblock);
$this->shortDescription = $short;
$this->longDescription = $long;
$this->parseTags($tags);
}
/**
* Strips the asterisks from the DocBlock comment.
*
* @see https://github.com/phpDocumentor/ReflectionDocBlock/blob/master/src/phpDocumentor/Reflection/DocBlock.php Original Method
*
* @param string $comment String containing the comment text.
*
* @return string
*/
protected function cleanInput(string $comment): string {
$comment = trim(preg_replace('#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]{0,1}(.*)?#u', '$1', $comment));
// reg ex above is not able to remove */ from a single line docblock
if (substr($comment, -2) == '*/') {
$comment = trim(substr($comment, 0, -2));
}
// normalize strings
$comment = str_replace(["\r\n", "\r"], "\n", $comment);
return $comment;
}
/**
* Splits the Docblock into a short description, long description and
* block of tags.
*
* @see https://github.com/phpDocumentor/ReflectionDocBlock/blob/master/src/phpDocumentor/Reflection/DocBlock.php Original Method
*
* @param string $comment Comment to split into the sub-parts.
*
* @author RichardJ Special thanks to RichardJ for the regex responsible
* for the split.
*
* @return string[] containing the short-, long description and an element
* containing the tags.
*/
protected function splitDocBlock(string $comment): array {
$matches = [];
if (str_starts_with($comment, '@')) {
$matches = ['', '', $comment];
} else {
// clears all extra horizontal whitespace from the line endings
// to prevent parsing issues
$comment = preg_replace('/\h*$/Sum', '', $comment);
/*
* Splits the docblock into a short description, long description and
* tags section
* - The short description is started from the first character until
* a dot is encountered followed by a newline OR
* two consecutive newlines (horizontal whitespace is taken into
* account to consider spacing errors)
* - The long description, any character until a new line is
* encountered followed by an @ and word characters (a tag).
* This is optional.
* - Tags; the remaining characters
*
* Big thanks to RichardJ for contributing this Regular Expression
*/
preg_match(
'/
\A (
[^\n.]+
(?:
(?! \. \n | \n{2} ) # disallow the first seperator here
[\n.] (?! [ \t]* @\pL ) # disallow second seperator
[^\n.]+
)*
\.?
)
(?:
\s* # first seperator (actually newlines but it\'s all whitespace)
(?! @\pL ) # disallow the rest, to make sure this one doesn\'t match,
#if it doesn\'t exist
(
[^\n]+
(?: \n+
(?! [ \t]* @\pL ) # disallow second seperator (@param)
[^\n]+
)*
)
)?
(\s+ [\s\S]*)? # everything that follows
/ux',
$comment,
$matches
);
array_shift($matches);
}
while (count($matches) < 3) {
$matches[] = '';
}
return $matches;
}
/**
* Parses the tags
*
* @see https://github.com/phpDocumentor/ReflectionDocBlock/blob/master/src/phpDocumentor/Reflection/DocBlock.php Original Method
*
* @param string $tags
*
* @throws LogicException
* @throws InvalidArgumentException
*/
protected function parseTags(string $tags): void {
$tags = trim($tags);
if ($tags !== '') {
// sanitize lines
$result = [];
foreach (explode("\n", $tags) as $line) {
if ($this->isTagLine($line) || count($result) == 0) {
$result[] = $line;
} elseif ($line !== '') {
$result[count($result) - 1] .= "\n" . $line;
}
}
// create proper Tag objects
if (count($result)) {
$this->tags->clear();
foreach ($result as $line) {
$this->tags->add($this->parseTag($line));
}
}
}
}
/**
* Checks whether the given line is a tag line (= starts with @) or not
*
* @param string $line
*
* @return bool
*/
protected function isTagLine(string $line): bool {
return str_starts_with($line, '@');
}
/**
* Parses an individual tag line
*
* @param string $line
*
* @throws InvalidArgumentException
*
* @return AbstractTag
*/
protected function parseTag(string $line): AbstractTag {
$matches = [];
if (!preg_match('/^@(' . self::REGEX_TAGNAME . ')(?:\s*([^\s].*)|$)?/us', $line, $matches)) {
throw new InvalidArgumentException('Invalid tag line detected: ' . $line);
}
$tagName = $matches[1];
$content = $matches[2] ?? '';
return TagFactory::create($tagName, $content);
}
/**
* Returns the short description
*
* @return string the short description
*/
public function getShortDescription(): string {
return $this->shortDescription;
}
/**
* Sets the short description
*
* @param string $description the new description
*
* @return $this
*/
public function setShortDescription(string $description = ''): self {
$this->shortDescription = $description;
return $this;
}
/**
* Returns the long description
*
* @return string the long description
*/
public function getLongDescription(): string {
return $this->longDescription;
}
/**
* Sets the long description
*
* @param string $description the new description
*
* @return $this
*/
public function setLongDescription(string $description = ''): self {
$this->longDescription = $description;
return $this;
}
/**
* Adds a tag to this docblock
*
* @param AbstractTag $tag
*
* @return $this
*/
public function appendTag(AbstractTag $tag): self {
$this->tags->add($tag);
return $this;
}
/**
* Removes tags (by tag name)
*
* @param string $tagName
*/
public function removeTags(string $tagName = ''): void {
$this->tags = $this->tags->filter(function (AbstractTag $tag) use ($tagName): bool {
return $tagName !== $tag->getTagName();
});
}
/**
* Checks whether a tag is present
*
* @param string $tagName
*
* @return bool
*/
public function hasTag(string $tagName): bool {
return $this->tags->search(
$tagName,
fn (AbstractTag $tag, string $query): bool => $tag->getTagName() === $query
);
}
/**
* Gets tags (by tag name)
*
* @param string $tagName
*
* @return ArrayList the tags
*/
public function getTags(string $tagName = ''): ArrayList {
return $tagName === '' ? $this->tags : $this->tags->filter(
fn (AbstractTag $tag): bool => $tag->getTagName() === $tagName
);
}
/**
* A list of tags sorted by tag-name
*
* @return ArrayList
*/
public function getSortedTags(): ArrayList {
$this->comparator = $this->comparator ?? new TagNameComparator();
// 1) group by tag name
$group = new Map();
/** @var AbstractTag $tag */
foreach ($this->tags->toArray() as $tag) {
if (!$group->has($tag->getTagName())) {
$group->set($tag->getTagName(), new ArrayList());
}
/** @var ArrayList $list */
$list = $group->get($tag->getTagName());
$list->add($tag);
}
// 2) Sort the group by tag name
$group->sortKeys(new TagNameComparator());
// 3) flatten the group
$sorted = new ArrayList();
/** @var array $tags */
foreach ($group->values()->toArray() as $tags) {
$sorted->add(...$tags);
}
return $sorted;
}
/**
* Returns true when there is no content in the docblock
*
* @return bool
*/
public function isEmpty(): bool {
return $this->shortDescription === ''
&& $this->longDescription === ''
&& $this->tags->size() === 0;
}
/**
* Returns the string version of the docblock
*
* @return string
*/
public function toString(): string {
$docblock = "/**\n";
// short description
$short = trim($this->shortDescription);
if ($short !== '') {
$docblock .= $this->writeLines(explode("\n", $short));
}
// short description
$long = trim($this->longDescription);
if ($long !== '') {
$docblock .= $this->writeLines(explode("\n", $long), !empty($short));
}
// tags
$tags = $this->getSortedTags()->map(function (AbstractTag $tag): string {
return (string) $tag;
});
if (!$tags->isEmpty()) {
/** @psalm-suppress MixedArgumentTypeCoercion */
$docblock .= $this->writeLines($tags->toArray(), $short !== '' || $long !== '');
}
$docblock .= ' */';
return $docblock;
}
/**
* Writes multiple lines with ' * ' prefixed for docblock
*
* @param string[] $lines the lines to be written
* @param bool $newline if a new line should be added before
*
* @return string the lines as string
*/
protected function writeLines(array $lines, bool $newline = false): string {
$docblock = '';
if ($newline) {
$docblock .= " *\n";
}
foreach ($lines as $line) {
if (str_contains($line, "\n")) {
$sublines = explode("\n", $line);
$line = array_shift($sublines);
$docblock .= " * $line\n";
$docblock .= $this->writeLines($sublines);
} else {
$docblock .= " * $line\n";
}
}
return $docblock;
}
/**
* Magic toString() method
*
* @return string
*/
public function __toString(): string {
return $this->toString();
}
}

View File

@@ -0,0 +1,37 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock;
use phootwork\lang\Comparator;
class TagNameComparator implements Comparator {
public function compare($a, $b): int {
$order = ['see', 'author', 'property-read', 'property-write', 'property',
'method', 'deprecated', 'since', 'version', 'var', 'type', 'param',
'throws', 'return'];
if ($a == $b) {
return 0;
}
if (!in_array($a, $order)) {
return -1;
}
if (!in_array($b, $order)) {
return 1;
}
$pos1 = array_search($a, $order);
$pos2 = array_search($b, $order);
return $pos1 < $pos2 ? -1 : 1;
}
}

View File

@@ -0,0 +1,39 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Abstract tag with a description
*/
abstract class AbstractDescriptionTag extends AbstractTag {
protected string $description = '';
/**
* Returns the description
*
* @return string the description
*/
public function getDescription(): string {
return $this->description;
}
/**
* Sets the description
*
* @param string $description the new description
*
* @return $this
*/
public function setDescription(string $description): self {
$this->description = $description;
return $this;
}
}

View File

@@ -0,0 +1,75 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
use phootwork\lang\Text;
abstract class AbstractTag implements \Stringable {
protected string $tagName = '';
/**
* Creates a new tag instance
*
* @param string $content
*
* @return $this
*/
public static function create(string $content = ''): self {
return new static($content);
}
/**
* Creates a new tag instance
*
* @param string $content
*/
final public function __construct(string $content = '') {
$this->tagName = Text::create(get_class($this))
->trimStart('phpowermove\\docblock\\tags\\')
->trimEnd('Tag')
->toKebabCase()
->toString()
;
$this->parse($content);
}
/**
* Returns the tag name.
*
* @return string the tag name
*/
public function getTagName(): string {
return $this->tagName;
}
public function setTagName(string $tagName): self {
$this->tagName = $tagName;
return $this;
}
/**
* Parses the given string
*
* @param string $content
*/
abstract protected function parse(string $content): void;
abstract public function toString(): string;
/**
* Magic toString() method
*
* @return string
*/
public function __toString(): string {
return $this->toString();
}
}

View File

@@ -0,0 +1,54 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents tags which are in the format
*
* `@tag [Type] [Description]`
*/
abstract class AbstractTypeTag extends AbstractDescriptionTag {
protected string $type = '';
protected function parse(string $content): void {
$parts = preg_split('/\s+/Su', $content, 2);
$this->type = $parts[0];
$this->setDescription($parts[1] ?? '');
}
public function toString(): string {
$type = $this->type ? $this->type . ' ' : '';
return trim(sprintf('@%s %s%s', $this->tagName, $type, $this->description));
}
/**
* Returns the type
*
* @return string the type
*/
public function getType(): string {
return $this->type;
}
/**
* Sets the type
*
* @param string $type the new type
*
* @return $this
*/
public function setType(string $type): self {
$this->type = $type;
return $this;
}
}

View File

@@ -0,0 +1,140 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
use phootwork\lang\Text;
/**
* Represents tags which are in the format
*
* @tag [Type] [Variable] [Description]
*/
abstract class AbstractVarTypeTag extends AbstractTypeTag {
protected string $variable = '';
protected bool $isVariadic = false;
/**
* @see https://github.com/phpDocumentor/ReflectionDocBlock/blob/master/src/phpDocumentor/Reflection/DocBlock/Tag/ParamTag.php Original Method: setContent()
* @see \phpowermove\docblock\tags\AbstractTypeTag::parse()
*
* @param string $content
*/
protected function parse(string $content): void {
$parts = preg_split('/(\s+)/Su', $content, 3, PREG_SPLIT_DELIM_CAPTURE);
$this->parseType($parts);
$this->parseVariable($parts);
$this->setDescription(implode('', $parts));
}
/**
* Parses the type from the extracted parts
*
* @param string[] $parts
*/
private function parseType(array &$parts): void {
// if the first item that is encountered is not a variable; it is a type
if (isset($parts[0])
&& (strlen($parts[0]) > 0)
&& !str_starts_with($parts[0], '$')
&& !str_starts_with($parts[0], '...$')) {
$this->type = array_shift($parts);
array_shift($parts);
}
}
/**
* Parses the variable from the extracted parts
*
* @param string[] $parts
*/
private function parseVariable(array &$parts): void {
// if the next item starts with a $ or ...$ it must be the variable name
if (isset($parts[0])
&& (strlen($parts[0]) > 0)
&& (str_starts_with($parts[0], '$') || str_starts_with($parts[0], '...$'))) {
$this->variable = array_shift($parts);
array_shift($parts);
if (str_starts_with($this->variable, '...')) {
$this->isVariadic = true;
$this->variable = substr($this->variable, 3);
}
}
}
public function toString(): string {
$type = $this->type === '' ? '' : $this->type . ' ';
$var = $this->variable !== ''
? ($this->isVariadic ? '...' : '') . $this->variable . ' ' : '';
return trim(sprintf('@%s %s%s%s', $this->tagName, $type, $var, $this->description));
}
/**
* Returns the variable name, starting with `$`
*
* @return string the variable name
*/
public function getExpression(): string {
return $this->variable;
}
/**
* Sets the variable name
*
* @param string $variable the new variable name
*
* @return $this
*/
public function setVariable(string $variable): self {
if (str_starts_with($variable, '...')) {
$this->setVariadic(true);
$variable = substr($variable, 3);
}
$this->variable = str_starts_with($variable, '$') ? $variable : "\$$variable";
return $this;
}
/**
* Returns the variable name
*
* @return string the variable name
*/
public function getVariable(): string {
$variable = new Text($this->variable);
return $variable->isEmpty() ? '' : $variable->slice(1)->toString();
}
/**
* Returns if the variable is variadic
*
* @return bool if the variable is variadic
*/
public function isVariadic(): bool {
return $this->isVariadic;
}
/**
* Sets whether the variable should be variadic
*
* @param bool $variadic
*
* @return $this
*/
public function setVariadic(bool $variadic): self {
$this->isVariadic = $variadic;
return $this;
}
}

View File

@@ -0,0 +1,86 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents tags which are in the format
*
* `@tag [Version] [Description]`
*/
abstract class AbstractVersionTag extends AbstractDescriptionTag {
/**
* PCRE regular expression matching a version vector.
* Assumes the "x" modifier.
*/
public const REGEX_VERSION = '(?:
# Normal release vectors.
\d\S*
|
# VCS version vectors. Per PHPCS, they are expected to
# follow the form of the VCS name, followed by ":", followed
# by the version vector itself.
# By convention, popular VCSes like CVS, SVN and GIT use "$"
# around the actual version vector.
[^\s\:]+\:\s*\$[^\$]+\$
)';
protected string $version = '';
/**
* @see https://github.com/phpDocumentor/ReflectionDocBlock/blob/master/src/phpDocumentor/Reflection/DocBlock/Tag/VersionTag.php Original Method: setContent()
* @see \phpowermove\docblock\tags\AbstractTag::parse()
*
* @param string $content
*/
protected function parse(string $content): void {
$matches = [];
if (preg_match(
'/^
# The version vector
(' . self::REGEX_VERSION . ')
\s*
# The description
(.+)?
$/sux',
$content,
$matches
)) {
$this->version = $matches[1];
$this->setDescription($matches[2] ?? '');
}
}
public function toString(): string {
return trim(sprintf('@%s %s %s', $this->tagName, $this->version, $this->description));
}
/**
* Returns the version
*
* @return string the version
*/
public function getVersion(): string {
return $this->version;
}
/**
* Sets the version
*
* @param string $version the new version
*
* @return $this
*/
public function setVersion(string $version): self {
$this->version = $version;
return $this;
}
}

View File

@@ -0,0 +1,101 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@author` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/author.html
*/
class AuthorTag extends AbstractTag {
/**
* PCRE regular expression matching any valid value for the name component.
*/
public const REGEX_AUTHOR_NAME = '[^\<]*';
/**
* PCRE regular expression matching any valid value for the email component.
*/
public const REGEX_AUTHOR_EMAIL = '[^\>]*';
protected string $name = '';
protected string $email = '';
/**
* @see https://github.com/phpDocumentor/ReflectionDocBlock/blob/master/src/phpDocumentor/Reflection/DocBlock/Tag/AuthorTag.php Original Method: setContent()
* @see \phpowermove\docblock\tags\AbstractTag::parse()
*
* @param string $content
*/
protected function parse(string $content): void {
$matches = [];
if (preg_match(
'/^(' . self::REGEX_AUTHOR_NAME . ')(\<(' . self::REGEX_AUTHOR_EMAIL . ')\>)?$/u',
$content,
$matches
)) {
$this->name = trim($matches[1]);
if (isset($matches[3])) {
$this->email = trim($matches[3]);
}
}
}
public function toString(): string {
$email = $this->email !== '' ? '<' . $this->email . '>' : '';
return trim(sprintf('@author %s %s', $this->name, $email));
}
/**
* Returns the authors name
*
* @return string the authors name
*/
public function getName(): string {
return $this->name;
}
/**
* Sets the authors name
*
* @param string $name the new name
*
* @return $this
*/
public function setName(string $name): self {
$this->name = $name;
return $this;
}
/**
* Returns the authors email
*
* @return string the authors email
*/
public function getEmail(): string {
return $this->email;
}
/**
* Sets the authors email
*
* @param string $email the new email
*
* @return $this
*/
public function setEmail(string $email): self {
$this->email = $email;
return $this;
}
}

View File

@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@deprecated` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/deprecated.html
*/
class DeprecatedTag extends AbstractVersionTag {
}

View File

@@ -0,0 +1,80 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents a `@license` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/license.html
*/
class LicenseTag extends AbstractTag {
private string $url = '';
private string $license = '';
protected function parse(string $content): void {
$parts = preg_split('/\s+/Su', $content, 2);
$urlCandidate = $parts[0];
if (preg_match(LinkTag::URL_REGEX, $urlCandidate)) {
$this->url = $urlCandidate;
$this->license = $parts[1] ?? '';
} else {
$this->license = $content;
}
}
/**
* Returns the url
*
* @return string the url
*/
public function getUrl(): string {
return $this->url;
}
/**
* Sets the url
*
* @param string $url
*
* @return $this
*/
public function setUrl(string $url): self {
$this->url = $url;
return $this;
}
/**
* Returns the license
*
* @return string
*/
public function getLicense(): string {
return $this->license;
}
/**
* Sets the license
*
* @param string $license
*
* @return $this
*/
public function setLicense(string $license): self {
$this->license = $license;
return $this;
}
public function toString(): string {
return sprintf('@license %s', trim($this->url . ' ' . $this->license));
}
}

View File

@@ -0,0 +1,66 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents a `@link` tag
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/link.html
*/
class LinkTag extends AbstractDescriptionTag {
private string $url = '';
/**
* Url Regex by @diegoperini
*
* @see https://mathiasbynens.be/demo/url-regex
*
* @var string
*/
public const URL_REGEX = '_^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS';
protected function parse(string $content): void {
$parts = preg_split('/\s+/Su', $content, 2);
$urlCandidate = $parts[0];
if (preg_match(self::URL_REGEX, $urlCandidate)) {
$this->url = $urlCandidate;
$this->setDescription($parts[1] ?? '');
} else {
$this->setDescription($content);
}
}
/**
* Returns the url
*
* @return string the url
*/
public function getUrl(): string {
return $this->url;
}
/**
* Sets the url
*
* @param string $url
*
* @return $this
*/
public function setUrl(string $url): self {
$this->url = $url;
return $this;
}
public function toString(): string {
return trim(sprintf('@link %s', trim($this->url . ' ' . $this->description)));
}
}

View File

@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@method` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/method.html
*/
class MethodTag extends AbstractVarTypeTag {
}

View File

@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@param` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/param.html
*/
class ParamTag extends AbstractVarTypeTag {
}

View File

@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@property-read` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/property-read.html
*/
class PropertyReadTag extends AbstractVarTypeTag {
}

View File

@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@property` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/property-read.html
*/
class PropertyTag extends AbstractVarTypeTag {
}

View File

@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@property-write` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/property-write.html
*/
class PropertyWriteTag extends AbstractVarTypeTag {
}

View File

@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@return` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/return.html
*/
class ReturnTag extends AbstractTypeTag {
}

View File

@@ -0,0 +1,52 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@see' tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/see.html
*/
class SeeTag extends AbstractDescriptionTag {
protected string $reference;
protected function parse(string $content): void {
$parts = preg_split('/\s+/Su', $content, 2);
$this->reference = $parts[0];
$this->setDescription(isset($parts[1]) ? $parts[1] : '');
}
public function toString(): string {
return trim(sprintf('@see %s', trim($this->reference . ' ' . $this->description)));
}
/**
* Returns the reference
*
* @return string the reference
*/
public function getReference(): string {
return $this->reference;
}
/**
* Sets the reference
*
* @param string $reference a URL or FQSEN
*
* @return SeeTag
*/
public function setReference(string $reference): self {
$this->reference = $reference;
return $this;
}
}

View File

@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@since` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/since.html
*/
class SinceTag extends AbstractVersionTag {
}

View File

@@ -0,0 +1,44 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
use phootwork\lang\Text;
/**
* Tag Factory
*/
class TagFactory {
/**
* Creates a new tag instance on the given name
*
* @param string $tagName
* @param string $content
*
* @return AbstractTag
*
* @psalm-suppress MoreSpecificReturnType
* @psalm-suppress LessSpecificReturnStatement
*/
public static function create(string $tagName, string $content = ''): AbstractTag {
$class = Text::create($tagName)
->toStudlyCase()
->prepend('phpowermove\\docblock\\tags\\')
->append('Tag')
->toString()
;
if (!class_exists($class)) {
return (new UnknownTag($content))->setTagName($tagName);
}
/** @psalm-suppress MixedMethodCall */
return new $class($content);
}
}

View File

@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@throws` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/throws.html
*/
class ThrowsTag extends AbstractTypeTag {
}

View File

@@ -0,0 +1,19 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@type` tag.
*
* @deprecated this tag was removed in phpDocumentor version 3.0
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/index.html
*/
class TypeTag extends AbstractVarTypeTag {
}

View File

@@ -0,0 +1,23 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents an unknown tag.
*/
class UnknownTag extends AbstractDescriptionTag {
protected function parse(string $content): void {
$this->setDescription($content);
}
public function toString(): string {
return sprintf('@%s %s', $this->tagName, $this->description);
}
}

View File

@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@var` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/var.html
*/
class VarTag extends AbstractVarTypeTag {
}

View File

@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/*
* This file is part of the Docblock package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace phpowermove\docblock\tags;
/**
* Represents the `@version` tag.
*
* @see https://docs.phpdoc.org/3.0/guide/references/phpdoc/tags/version.html
*/
class VersionTag extends AbstractVersionTag {
}