From 6acaadbaaf2ce78de6ffc15c17ec0e17fda8e54b Mon Sep 17 00:00:00 2001 From: Alexandr Chernyaev Date: Thu, 17 Oct 2019 23:23:28 +0300 Subject: [PATCH 1/2] Added phpdoc for facade Breadcrumbs Hi, this is a great package, but I think we can improve the experience with it. In order for the IDE to have tips, you need to add a few comments, which will greatly facilitate life. In the same way they solve the problem in laravel itself. For example: https://github.com/laravel/framework/blob/f61b787d88505d94d4ca691d43307518aed3dbd9/src/Illuminate/Support/Facades/Log.php#L5-L20 This PR adds comments to the main methods. --- src/Facades/Breadcrumbs.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Facades/Breadcrumbs.php b/src/Facades/Breadcrumbs.php index 0d33173..b0de26b 100644 --- a/src/Facades/Breadcrumbs.php +++ b/src/Facades/Breadcrumbs.php @@ -8,6 +8,19 @@ /** * Breadcrumbs facade - allows easy access to the Manager instance. * + * @method static void for(string $page, callable $callback) + * @method static void register(string $name, callable $callback) + * @method static void before(callable $callback) + * @method static void after(callable $callback) + * @method static bool exists(string|null $name) + * @method static \Illuminate\Support\Collection generate(string|null $name, ...$params) + * @method static \Illuminate\Support\HtmlString view(string $view, string $name, ...$params) + * @method static \Illuminate\Support\HtmlString render(string $name, ...$params) + * @method static \stdClass|null current() + * @method static array getCurrentRoute() + * @method static void setCurrentRoute(string $name, ...$params) + * @method static void clearCurrentRoute() + * * @see BreadcrumbsManager */ class Breadcrumbs extends Facade From 033a80b66cadd3e7a619ac666d7fb54b0e7c70cc Mon Sep 17 00:00:00 2001 From: tabuna Date: Fri, 18 Oct 2019 15:23:47 +0300 Subject: [PATCH 2/2] refs #206 [phpDocs] Added test for checking meta tags --- src/BreadcrumbsManager.php | 2 +- src/Facades/Breadcrumbs.php | 15 +++-- tests/FacadePhpDocTest.php | 116 ++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 7 deletions(-) diff --git a/src/BreadcrumbsManager.php b/src/BreadcrumbsManager.php index b3c2427..fa00780 100644 --- a/src/BreadcrumbsManager.php +++ b/src/BreadcrumbsManager.php @@ -242,7 +242,7 @@ public function render(string $name = null, ...$params): HtmlString * @throws \DaveJamesMiller\Breadcrumbs\Exceptions\UnnamedRouteException if the current route doesn't have an associated name. * @throws \DaveJamesMiller\Breadcrumbs\Exceptions\InvalidBreadcrumbException if the name is (or any ancestor names are) not registered. */ - public function current() + public function current(): ?\stdClass { return $this->generate()->where('current', '!==', false)->last(); } diff --git a/src/Facades/Breadcrumbs.php b/src/Facades/Breadcrumbs.php index b0de26b..b7ec854 100644 --- a/src/Facades/Breadcrumbs.php +++ b/src/Facades/Breadcrumbs.php @@ -8,18 +8,21 @@ /** * Breadcrumbs facade - allows easy access to the Manager instance. * - * @method static void for(string $page, callable $callback) + * @method static void for(string $name, callable $callback) * @method static void register(string $name, callable $callback) * @method static void before(callable $callback) * @method static void after(callable $callback) - * @method static bool exists(string|null $name) - * @method static \Illuminate\Support\Collection generate(string|null $name, ...$params) - * @method static \Illuminate\Support\HtmlString view(string $view, string $name, ...$params) - * @method static \Illuminate\Support\HtmlString render(string $name, ...$params) + * @method static bool exists(string $name = null) + * @method static \Illuminate\Support\Collection generate(string $name = null, $params) + * @method static \Illuminate\Support\HtmlString view(string $view, string $name = null, $params) + * @method static \Illuminate\Support\HtmlString render(string $name = null, $params) * @method static \stdClass|null current() * @method static array getCurrentRoute() - * @method static void setCurrentRoute(string $name, ...$params) + * @method static void setCurrentRoute(string $name, $params) * @method static void clearCurrentRoute() + * @method static macro($name, $macro) + * @method static mixin($mixin, $replace = 1) + * @method static hasMacro($name) * * @see BreadcrumbsManager */ diff --git a/tests/FacadePhpDocTest.php b/tests/FacadePhpDocTest.php index b808e5b..b24f7c5 100644 --- a/tests/FacadePhpDocTest.php +++ b/tests/FacadePhpDocTest.php @@ -2,8 +2,36 @@ namespace BreadcrumbsTests; +use DaveJamesMiller\Breadcrumbs\BreadcrumbsManager; +use DaveJamesMiller\Breadcrumbs\Facades\Breadcrumbs; +use Illuminate\Support\Str; +use ReflectionClass; +use ReflectionMethod; +use ReflectionParameter; + class FacadePhpDocTest extends TestCase { + /** + * Methods that are not needed in phpDoc + */ + private const EXCLUSION_METHODS = [ + '__construct', + '__destruct', + '__call', + '__callStatic', + '__get', + '__set', + '__isset', + '__unset', + '__sleep', + '__wakeup', + '__toString', + '__invoke', + '__set_state', + '__clone', + '__debugInfo', + ]; + public function tags() { $code = file_get_contents(__DIR__ . '/../src/BreadcrumbsManager.php'); @@ -40,4 +68,92 @@ public function testFullyQualifiedClassNames($class, $line) "Must use fully qualified class names in BreadcrumbsManger PhpDoc: $line" ); } + + public function testBreadcrumbsFacade() + { + $this->checkMethodDocBlock(Breadcrumbs::class, BreadcrumbsManager::class); + } + + /** + * Checks the correctness of building the doc block according to the main class + * + * @param string $facade + * @param string $class + * + * @throws \ReflectionException + */ + private function checkMethodDocBlock(string $facade, string $class) + { + $class = new ReflectionClass($class); + $methods = $class->getMethods(ReflectionMethod::IS_PUBLIC); + $facadeDocs = (new ReflectionClass($facade))->getDocComment(); + + collect($methods) + ->map(function (ReflectionMethod $method) { + return in_array($method->name, self::EXCLUSION_METHODS, true) ? null : $method; + }) + ->filter() + ->map(function (ReflectionMethod $method) { + + $parameters = $this->buildParametsDocBlock($method->getParameters()); + $returns = $this->buildReturnTypeDocBlock($method->getReturnType()); + + $docMethod = sprintf('@method static %s %s%s', + $returns, + $method->getName(), + $parameters + ); + + return preg_replace('/\s+/', ' ', $docMethod); + }) + ->each(function (string $method) use ($facadeDocs) { + $this->assertStringContainsString($method, $facadeDocs, 'Not found: ' . $method); + }); + } + + /** + * @param ReflectionParameter[] $parameters + * + * @return string + */ + private function buildParametsDocBlock($parameters = []) + { + $parameters = array_map(function (ReflectionParameter $parameter) { + $name = optional($parameter->getType())->getName(); + + $strParam = sprintf('%s $%s', $name, $parameter->getName()); + $strParam = trim($strParam); + + if (!$parameter->isDefaultValueAvailable()) { + return $strParam; + } + + $defaultValue = $parameter->getDefaultValue() ?? 'null'; + return sprintf('%s = %s', $strParam, $defaultValue); + }, $parameters); + + return sprintf('(%s)', implode(', ', $parameters)); + } + + /** + * @param \ReflectionType|null $reflectionType + * + * @return string + */ + private function buildReturnTypeDocBlock(\ReflectionType $reflectionType = null) + { + $reflectionType = optional($reflectionType); + + $strReturn = $reflectionType->getName(); + + if (class_exists($strReturn)) { + $strReturn = Str::start($strReturn, '\\'); + } + + if ($reflectionType->allowsNull()) { + $strReturn = sprintf('%s|%s', $strReturn, 'null'); + } + + return $strReturn; + } }