first commit

This commit is contained in:
2024-07-15 12:33:27 +02:00
commit ce50ae282b
22084 changed files with 2623791 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
name: Api Documentation
on:
release:
types: [published]
jobs:
build-api:
name: Build api
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Checkout api repository
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.2
extensions: mbstring, dom, json, libxml, xml, xmlwriter
coverage: none
- name: Download Sami
run: wget https://github.com/cristianoc72/Sami/releases/download/v4.1.3/sami.phar
- name: Build api documentation
run: php sami.phar update sami.php
- name: Deploy api documentation site
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./api

View File

@@ -0,0 +1,28 @@
# Run coverage report and upload it
name: Coverage
on:
push:
branches: [master]
jobs:
coverage:
name: coverage
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: 8.0
extensions: mbstring, dom, json, libxml, xml, xmlwriter
coverage: pcov
- name: Install dependencies
run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader
- name: Generate coverage report
run: composer coverage:clover
- name: Upload coverage report to Scrutinizer
uses: sudo-bot/action-scrutinizer@latest
with:
cli-args: "--format=php-clover clover.xml"

View File

@@ -0,0 +1,38 @@
name: Docblock Test Suite
on: [push, pull_request]
jobs:
test:
name: test
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
php-versions: ['8.0']
runs-on: ${{ matrix.operating-system }}
steps:
- name: Fix autocrlf on Windows
if: matrix.operating-system == 'windows-latest'
run: git config --global core.autocrlf false
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, dom, json, libxml, xml, xmlwriter
coverage: none
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v1
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader
- name: Check code style
run: composer cs
- name: Test with phpunit
run: composer test

10
vendor/phpowermove/docblock/.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
.buildpath
clover.xml
composer.lock
composer.phar
*.cache
sami.phar
vendor/
api/
cache/
coverage/

View File

@@ -0,0 +1,9 @@
<?php declare(strict_types=1);
$config = new phootwork\fixer\Config();
$config->getFinder()
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests')
;
return $config;

34
vendor/phpowermove/docblock/.project vendored Normal file
View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>docblock</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.dubture.composer.core.builder.buildPathManagementBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.dltk.core.scriptbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.php.core.PHPNature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>com.dubture.composer.core.composerNature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,2 @@
com.dubture.composer.corebuildpath.includes.excludes=<buildpathentry including\="tests/" kind\="src" path\="vendor"/>\n
eclipse.preferences.version=1

View File

@@ -0,0 +1,2 @@
eclipse.preferences.version=1
org.eclipse.php.composer.corebuildpath.includes.excludes=<buildpathentry kind\="src" path\="vendor"/>\n

View File

@@ -0,0 +1,5 @@
eclipse.preferences.version=1
include_path=
phpVersion=php5.6
useShortTags=false
use_asp_tags_as_php=false

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<installed facet="php.core.component" version="1"/>
<installed facet="php.composer.component" version="1"/>
<installed facet="php.component" version="5.6"/>
</faceted-project>

View File

@@ -0,0 +1,2 @@
disabled=06vendor
eclipse.preferences.version=1

22
vendor/phpowermove/docblock/LICENSE vendored Normal file
View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Thomas Gossmann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

125
vendor/phpowermove/docblock/README.md vendored Normal file
View File

@@ -0,0 +1,125 @@
# Docblock
[![License](https://img.shields.io/github/license/phpowermove/docblock.svg?style=flat-square)](https://packagist.org/packages/phpowermove/docblock)
[![Latest Stable Version](https://img.shields.io/packagist/v/phpowermove/docblock.svg?style=flat-square)](https://packagist.org/packages/phpowermove/docblock)
[![Total Downloads](https://img.shields.io/packagist/dt/phpowermove/docblock.svg?style=flat-square&colorB=007ec6)](https://packagist.org/packages/phpowermove/docblock)
![Tests](https://github.com/phpowermove/docblock/workflows/Docblock%20Test%20Suite/badge.svg)
![Coverage report](https://github.com/phpowermove/docblock/workflows/Coverage/badge.svg)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/phpowermove/docblock/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/phpowermove/docblock/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/phpowermove/docblock/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/phpowermove/docblock/?branch=master)
PHP Docblock parser and generator. An API to read and write Docblocks.
> __WARNING__: starting from version 4.0 the library has moved to [phpowermove organization](https://github.com/phpowermove) and the namespace is `phpowermove\docblock`.
## Installation
Install via Composer:
```
composer require phpowermove/docblock
```
## Usage
### 1. Generate a Docblock instance
a) Simple:
```php
use phpowermove\docblock\Docblock;
$docblock = new Docblock();
```
b) Create from string:
```php
use phpowermove\docblock\Docblock;
$docblock = new Docblock('/**
* Short Description.
*
* Long Description.
*
* @author gossi
*/');
```
c) Create from reflection:
```php
use phpowermove\docblock\Docblock;
$docblock = new Docblock(new \ReflectionClass('MyClass'));
```
### 2. Manipulate tags
Get the tags:
```php
$tags = $docblock->getTags();
```
Get tags by name:
```php
$tags = $docblock->getTags('author');
```
Append a tag:
```php
use phpowermove\docblock\tags\AuthorTag;
$author = new AuthorTag();
$author->setName('gossi');
$docblock->appendTag($author);
```
or with fluent API:
```php
use phpowermove\docblock\tags\AuthorTag;
$docblock->appendTag(AuthorTag::create()
->setName('gossi')
);
```
Check tag existence:
```php
$docblock->hasTag('author');
```
### 3. Get back the string
Call `toString()`:
```php
$docblock->toString();
```
or if you are in a write-context, the magical `__toString()` will take care of it:
```php
echo $docblock;
```
## Documentation Api
See https://phpowermove.github.io/docblock
## Contributing
Feel free to fork and submit a pull request (don't forget the tests) and I am happy to merge.
## References
- This project uses the parsers from [phpDocumentor/ReflectionDocBlock](https://github.com/phpDocumentor/ReflectionDocBlock)
## Changelog
Refer to [Releases](https://github.com/phpowermove/docblock/releases)

View File

@@ -0,0 +1,61 @@
{
"name" : "phpowermove/docblock",
"type" : "library",
"description" : "PHP Docblock parser and generator. An API to read and write Docblocks.",
"license" : "MIT",
"authors" : [{
"name" : "Thomas Gossmann",
"homepage" : "http://gos.si"
}
],
"keywords" : [
"docblock",
"parser",
"generator"
],
"support" : {
"issues" : "https://github.com/phpowermove/docblock/issues"
},
"autoload" : {
"psr-4" : {
"phpowermove\\docblock\\" : "src/"
}
},
"autoload-dev" : {
"psr-4" : {
"phpowermove\\docblock\\tests\\" : "tests/"
}
},
"require" : {
"php" : ">=8.0",
"phootwork/collection" : "^3.0",
"phootwork/lang": "^3.0"
},
"require-dev" : {
"phpunit/phpunit" : "^9.0",
"phootwork/php-cs-fixer-config": "^0.4",
"psalm/phar": "^4.3"
},
"scripts": {
"analytics": "vendor/bin/psalm.phar",
"check": [
"@test",
"@analytics",
"@cs-fix"
],
"coverage:html": "@test --coverage-html coverage/",
"coverage:clover": "@test --coverage-clover clover.xml",
"cs": "php-cs-fixer fix -v --diff --dry-run",
"cs-fix": "php-cs-fixer fix -v --diff",
"test": "phpunit --colors=always"
},
"scripts-descriptions": {
"analytics": "Run static analysis tool",
"check": "Perform all tests and analysis, required before submitting a pull request",
"coverage:html": "Create a code coverage report in html format, into the `coverage/` directory",
"coverage:clover": "Create a code coverage report in xml format, into clover.xml file",
"cs": "Run code style analysis, without fixing errors",
"cs-fix": "Run code style analysis and fix errors",
"test": "Run all tests"
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
bootstrap="vendor/autoload.php"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Docblock Test Suite">
<directory>tests/</directory>
</testsuite>
</testsuites>
</phpunit>

15
vendor/phpowermove/docblock/psalm.xml vendored Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<psalm
errorLevel="1"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="src" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
</psalm>

16
vendor/phpowermove/docblock/sami.php vendored Normal file
View File

@@ -0,0 +1,16 @@
<?php
use Sami\Sami;
use Symfony\Component\Finder\Finder;
$iterator = Finder::create()
->files()
->name('*.php')
->in(__DIR__ . '/src')
;
return new Sami($iterator, [
'title' => 'DocBlock API Documentation',
'build_dir' => __DIR__ . '/api',
'default_opened_level' => 2
]);

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 {
}

View File

@@ -0,0 +1,220 @@
<?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\tests;
use InvalidArgumentException;
use phpowermove\docblock\Docblock;
use phpowermove\docblock\tags\AuthorTag;
use phpowermove\docblock\tags\ParamTag;
use phpowermove\docblock\tags\PropertyTag;
use phpowermove\docblock\tags\ReturnTag;
use phpowermove\docblock\tags\SeeTag;
use phpowermove\docblock\tags\SinceTag;
use phpowermove\docblock\tags\ThrowsTag;
use phpowermove\docblock\tags\UnknownTag;
use phpowermove\docblock\tests\fixtures\MyDocBlock;
use PHPUnit\Framework\TestCase;
class DocblockTest extends TestCase {
public function testShortDescription(): void {
$desc = 'Hello World';
$docblock = new Docblock();
$docblock->setShortDescription($desc);
$this->assertEquals($desc, $docblock->getShortDescription());
}
public function testLongDescription(): void {
$desc = 'Hello World';
$docblock = new Docblock();
$docblock->setLongDescription($desc);
$this->assertEquals($desc, $docblock->getLongDescription());
}
public function testSimpleReadWrite(): void {
$expected = '/**
* Short Description.
*
* Long Description.
*/';
$docblock = new Docblock($expected);
$this->assertEquals('Short Description.', $docblock->getShortDescription());
$this->assertEquals('Long Description.', $docblock->getLongDescription());
$this->assertEquals($expected, $docblock->toString());
}
public function testSingleLine(): void {
$docblock = new Docblock('/** Single Line Doc */');
$this->assertEquals('Single Line Doc', $docblock->getShortDescription());
}
public function testTags(): void {
$expected = '/**
* @see https://github.com/gossi/docblock
* @author gossi
* @author KH
* @since 28.5.2014
*/';
$docblock = new Docblock($expected);
$tags = $docblock->getTags();
$this->assertEquals(4, $tags->size());
$this->assertTrue($docblock->hasTag('see'));
$this->assertTrue($docblock->hasTag('author'));
$this->assertTrue($docblock->hasTag('since'));
$this->assertFalse($docblock->hasTag('license'));
$authors = $docblock->getTags('author');
$this->assertEquals(2, $authors->size());
$this->assertEquals($expected, $docblock->toString());
$this->assertSame($docblock, $docblock->appendTag(ThrowsTag::create()));
$tags = $docblock->getTags();
$this->assertEquals(5, $tags->size());
$this->assertTrue($docblock->hasTag('author'));
$this->assertFalse($docblock->hasTag('moooh'));
}
public function testInvalidTags(): void {
$this->expectException(InvalidArgumentException::class);
new MyDocBlock('');
}
public function testInvalidDocblockParameter(): void {
$this->expectException(\TypeError::class);
new Docblock(new \stdClass());
}
public function testMultilLongLineDescription(): void {
$expected = '/**
* Short Description.
*
* Long Description, which is very long and takes ages to reach the very last of the current line
* before it brakes onto the next line
*
* sdfasdf @tag
*
* @tag2 wurst multi-
* linee
*/';
$docblock = new Docblock($expected);
$this->assertEquals($expected, $docblock->toString());
}
public function testFromReflection(): void {
$expected = '/**
* Short Description.
*
* @author gossi
*/';
$reflection = new \ReflectionClass('\\phpowermove\\docblock\\tests\\fixtures\\ReflectionTestClass');
$docblock = Docblock::create($reflection);
$this->assertEquals($expected, '' . $docblock);
}
public function testTagSorting(): void {
$doc = new Docblock();
$doc->appendTag(new AuthorTag());
$doc->appendTag(new SeeTag());
$doc->appendTag(new ThrowsTag());
$doc->appendTag((new UnknownTag())->setTagName('wurst'));
$doc->appendTag(new SinceTag());
$doc->appendTag(new ParamTag());
$doc->appendTag(new ParamTag());
$doc->appendTag(new PropertyTag());
$doc->appendTag(new ReturnTag());
$actual = [];
$expected = ['wurst', 'see', 'author', 'property', 'since', 'param', 'param', 'throws', 'return'];
$sorted = $doc->getSortedTags();
foreach ($sorted as $tag) {
$actual[] = $tag->getTagName();
}
$this->assertEquals($expected, $actual);
}
public function testEmpty(): void {
$doc = new Docblock();
$this->assertTrue($doc->isEmpty());
$doc->setLongDescription('bla');
$this->assertFalse($doc->isEmpty());
$doc->setLongDescription();
$this->assertTrue($doc->isEmpty());
$doc->setShortDescription('bla');
$this->assertFalse($doc->isEmpty());
$doc->setShortDescription();
$this->assertTrue($doc->isEmpty());
$doc->appendTag(new SeeTag());
$this->assertFalse($doc->isEmpty());
}
public function testRemoveTag(): void {
$expected = '/**
* @see https://github.com/gossi/docblock
* @author gossi
* @author KH
* @since 28.5.2014
*/';
$docblock = new Docblock($expected);
$tags = $docblock->getTags();
$this->assertEquals(4, $tags->size());
$this->assertTrue($docblock->hasTag('see'));
$this->assertTrue($docblock->hasTag('author'));
$this->assertTrue($docblock->hasTag('since'));
$docblock->removeTags('author');
$tags = $docblock->getTags();
$this->assertEquals(2, $tags->size());
$this->assertTrue($docblock->hasTag('see'));
$this->assertTrue($docblock->hasTag('since'));
$this->assertFalse($docblock->hasTag('author'));
$docblock->removeTags('since');
$tags = $docblock->getTags();
$this->assertEquals(1, $tags->size());
$this->assertTrue($docblock->hasTag('see'));
$this->assertFalse($docblock->hasTag('since'));
}
public function testDocblockWithBlankLines(): void {
$text = '/**
* @param string $foo makes a fow
*
* @return bool true on success and false if it fails
*/';
$docblock = new Docblock($text);
$tags = $docblock->getTags();
$this->assertEquals(2, $tags->size());
$this->assertInstanceOf(ParamTag::class, $tags->get(0));
$this->assertEquals('makes a fow', $tags->get(0)->getDescription());
$this->assertInstanceOf(ReturnTag::class, $tags->get(1));
$this->assertEquals('true on success and false if it fails', $tags->get(1)->getDescription());
}
}

View File

@@ -0,0 +1,30 @@
<?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\tests;
use phootwork\collection\ArrayList;
use phpowermove\docblock\TagNameComparator;
use PHPUnit\Framework\TestCase;
class TagNameComparatorTest extends TestCase {
public function testComparison(): void {
$list = new ArrayList(['author', 'since', 'see', 'param', 'author']);
$list->sort(new TagNameComparator());
$this->assertEquals(['see', 'author', 'author', 'since', 'param'], $list->toArray());
}
public function testComparisonWithInvalidTag(): void {
$list = new ArrayList(['invalid_tag', 'author', 'since', 'see', 'param', 'author']);
$list->sort(new TagNameComparator());
$this->assertEquals(['invalid_tag', 'see', 'author', 'author', 'since', 'param'], $list->toArray());
}
}

View File

@@ -0,0 +1,10 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\fixtures;
use phpowermove\docblock\Docblock;
class MyDocBlock extends Docblock {
protected function splitDocblock($comment): array {
return ['', '', 'Invalid tag block'];
}
}

View File

@@ -0,0 +1,11 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\fixtures;
/**
* Short Description.
*
* @author gossi
*/
class ReflectionTestClass {
}

View File

@@ -0,0 +1,38 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\AuthorTag;
use PHPUnit\Framework\TestCase;
class AuthorTagTest extends TestCase {
public function testReadWrite(): void {
$author = new AuthorTag('gossi <hans@wurst.de>');
$this->assertEquals('gossi', $author->getName());
$this->assertEquals('hans@wurst.de', $author->getEmail());
$this->assertEquals('@author gossi <hans@wurst.de>', $author->toString());
$author = new AuthorTag('lil-g');
$this->assertEquals('lil-g', $author->getName());
$this->assertEmpty($author->getEmail());
$this->assertEquals('@author lil-g', $author->toString());
}
public function testName(): void {
$name = 'gossi';
$author = new AuthorTag();
$this->assertSame($author, $author->setName($name));
$this->assertEquals($name, $author->getName());
}
public function testEmail(): void {
$email = 'hans@wurst.de';
$author = new AuthorTag();
$this->assertSame($author, $author->setEmail($email));
$this->assertEquals($email, $author->getEmail());
}
}

View File

@@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\DeprecatedTag;
use PHPUnit\Framework\TestCase;
class DeprecatedTagTest extends TestCase {
public function testReadWrite(): void {
$deprecated = new DeprecatedTag();
$this->assertEquals('@deprecated', $deprecated->toString());
}
}

View File

@@ -0,0 +1,37 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\LicenseTag;
use PHPUnit\Framework\TestCase;
class LicenseTagTest extends TestCase {
public function testReadWrite(): void {
$license = new LicenseTag('MIT');
$this->assertEquals('MIT', $license->getLicense());
$this->assertEquals('@license MIT', $license->toString());
$license = new LicenseTag('http://opensource.org/licenses/MIT MIT');
$this->assertEquals('MIT', $license->getLicense());
$this->assertEquals('http://opensource.org/licenses/MIT', $license->getUrl());
$this->assertEquals('@license http://opensource.org/licenses/MIT MIT', $license->toString());
}
public function testLicense(): void {
$name = 'gossi';
$license = new LicenseTag();
$this->assertSame($license, $license->setLicense($name));
$this->assertEquals($name, $license->getLicense());
}
public function testUrl(): void {
$url = 'http://opensource.org/licenses/MIT';
$license = new LicenseTag();
$this->assertSame($license, $license->setUrl($url));
$this->assertEquals($url, $license->getUrl());
}
}

View File

@@ -0,0 +1,39 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\LinkTag;
use PHPUnit\Framework\TestCase;
class LinkTagTest extends TestCase {
public function testReadWrite(): void {
$link = new LinkTag('http://example.com');
$this->assertEquals('http://example.com', $link->getUrl());
$this->assertEquals('@link http://example.com', $link->toString());
$link = new LinkTag('http://example.com desc');
$this->assertEquals('http://example.com', $link->getUrl());
$this->assertEquals('desc', $link->getDescription());
$this->assertEquals('@link http://example.com desc', $link->toString());
$link = new LinkTag('http://.example.com desc');
$this->assertEmpty($link->getUrl());
$this->assertEquals('http://.example.com desc', $link->getDescription());
}
public function testUrl(): void {
$url = 'http://example.com';
$link = new LinkTag();
$this->assertSame($link, $link->setUrl($url));
$this->assertEquals($url, $link->getUrl());
}
public function testDescription(): void {
$desc = 'desc';
$link = new LinkTag();
$this->assertSame($link, $link->setDescription($desc));
$this->assertEquals($desc, $link->getDescription());
}
}

View File

@@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\MethodTag;
use PHPUnit\Framework\TestCase;
class MethodTagTest extends TestCase {
public function testReadWrite(): void {
$method = new MethodTag('string myMethod()');
$this->assertEquals('@method string myMethod()', $method->toString());
}
}

View File

@@ -0,0 +1,62 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\ParamTag;
use PHPUnit\Framework\TestCase;
class ParamTagTest extends TestCase {
public function testReadWrite(): void {
$param = new ParamTag('string $a the string');
$this->assertEquals('string', $param->getType());
$this->assertEquals('a', $param->getVariable());
$this->assertEquals('the string', $param->getDescription());
$this->assertFalse($param->isVariadic());
$this->assertEquals('@param string $a the string', $param->toString());
$param = new ParamTag('string ...$a');
$this->assertEmpty($param->getDescription());
$this->assertTrue($param->isVariadic());
$this->assertEquals('@param string ...$a', $param->toString());
}
public function testType(): void {
$type = 'int';
$param = new ParamTag();
$this->assertSame($param, $param->setType($type));
$this->assertEquals($type, $param->getType());
}
public function testVariable(): void {
$variable = '$v';
$param = new ParamTag();
$this->assertSame($param, $param->setVariable($variable));
$this->assertEquals($variable, $param->getExpression());
}
public function testVariadicVariable(): void {
$variable = '...$v';
$param = new ParamTag();
$this->assertSame($param, $param->setVariable($variable));
$this->assertEquals('$v', $param->getExpression());
$this->assertTrue($param->isVariadic());
}
public function testVariadic(): void {
$param = new ParamTag();
$this->assertSame($param, $param->setVariadic(true));
$this->assertTrue($param->isVariadic());
}
public function testGetVariableNameOnEmptyTag(): void {
$param = new ParamTag();
$this->assertEquals('', $param->getVariable());
}
}

View File

@@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\PropertyReadTag;
use PHPUnit\Framework\TestCase;
class PropertyReadTagTest extends TestCase {
public function testReadWrite(): void {
$prop = new PropertyReadTag('string $var');
$this->assertEquals('@property-read string $var', $prop->toString());
}
}

View File

@@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\PropertyTag;
use PHPUnit\Framework\TestCase;
class PropertyTagTest extends TestCase {
public function testReadWrite() {
$prop = new PropertyTag('string $var');
$this->assertEquals('@property string $var', $prop->toString());
}
}

View File

@@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\PropertyWriteTag;
use PHPUnit\Framework\TestCase;
class PropertyWriteTagTest extends TestCase {
public function testReadWrite() {
$prop = new PropertyWriteTag('string $var');
$this->assertEquals('@property-write string $var', $prop->toString());
}
}

View File

@@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\ReturnTag;
use PHPUnit\Framework\TestCase;
class ReturnTagTest extends TestCase {
public function testReadWrite() {
$return = new ReturnTag('Foo bar');
$this->assertEquals('@return Foo bar', $return->toString());
}
}

View File

@@ -0,0 +1,19 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\SeeTag;
use PHPUnit\Framework\TestCase;
class SeeTagTest extends TestCase {
public function testReadWrite(): void {
$see = new SeeTag('Dest::nation() 0815');
$this->assertEquals('@see Dest::nation() 0815', $see->toString());
}
public function testReference(): void {
$see = new SeeTag();
$this->assertSame($see, $see->setReference('hier-lang'));
$this->assertEquals('hier-lang', $see->getReference());
}
}

View File

@@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\SinceTag;
use PHPUnit\Framework\TestCase;
class SinceTagTest extends TestCase {
public function testReadWrite(): void {
$since = new SinceTag('1.0 baz');
$this->assertEquals('@since 1.0 baz', $since->toString());
}
}

View File

@@ -0,0 +1,22 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\AuthorTag;
use phpowermove\docblock\tags\TagFactory;
use phpowermove\docblock\tags\UnknownTag;
use PHPUnit\Framework\TestCase;
class TagFactoryTest extends TestCase {
public function testFactory(): void {
$factory = new TagFactory();
$author = $factory->create('author', 'lil-g');
$this->assertTrue($author instanceof AuthorTag);
$this->assertEquals('lil-g', $author->getName());
$unknown = $factory->create('wurst');
$this->assertTrue($unknown instanceof UnknownTag);
$this->assertEquals('wurst', $unknown->getTagName());
}
}

View File

@@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\ThrowsTag;
use PHPUnit\Framework\TestCase;
class ThrowsTagTest extends TestCase {
public function testReadWrite() {
$ex = new ThrowsTag('\Exception oups');
$this->assertEquals('@throws \Exception oups', $ex->toString());
}
}

View File

@@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\TypeTag;
use PHPUnit\Framework\TestCase;
class TypeTagTest extends TestCase {
public function testReadWrite(): void {
$type = new TypeTag('Foo ...$bar');
$this->assertEquals('@type Foo ...$bar', $type->toString());
}
}

View File

@@ -0,0 +1,20 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\UnknownTag;
use PHPUnit\Framework\TestCase;
class UnknownTagTest extends TestCase {
public function testReadWrite(): void {
$unknown = new UnknownTag('description');
$unknown = $unknown->setTagName('my-tag');
$this->assertEquals('@my-tag description', $unknown->toString());
$this->assertEquals('my-tag', $unknown->getTagName());
$this->assertEquals($unknown->toString(), '' . $unknown);
$this->assertTrue(UnknownTag::create() instanceof UnknownTag);
}
}

View File

@@ -0,0 +1,29 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\Docblock;
use phpowermove\docblock\tags\VarTag;
use PHPUnit\Framework\TestCase;
class VarTagTest extends TestCase {
public function testReadWrite(): void {
$var = new VarTag('Foo ...$bar');
$this->assertEquals('@var Foo ...$bar', $var->toString());
}
public function testDocblock(): void {
$expected = '/**
* @var mixed $foo bar
*/';
$docblock = new Docblock();
$var = VarTag::create()
->setType('mixed')
->setVariable('foo')
->setDescription('bar')
;
$docblock->appendTag($var);
$this->assertEquals($expected, $docblock->toString());
}
}

View File

@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
namespace phpowermove\docblock\tests\tags;
use phpowermove\docblock\tags\VersionTag;
use PHPUnit\Framework\TestCase;
class VersionTagTest extends TestCase {
public function testReadWrite(): void {
$version = new VersionTag('1.3.3.7 jupjup');
$this->assertEquals('@version 1.3.3.7 jupjup', $version->toString());
$this->assertEquals('jupjup', $version->getDescription());
$this->assertEquals('1.3.3.7', $version->getVersion());
$this->assertSame($version, $version->setVersion('3.14'));
$this->assertEquals('3.14', $version->getVersion());
}
}