File "GetFromDocBlocks.php"
Full Path: /var/www/html/back/vendor/knuckleswtf/scribe/src/Extracting/Strategies/Metadata/GetFromDocBlocks.php
File size: 5.98 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace Knuckles\Scribe\Extracting\Strategies\Metadata;
use Knuckles\Camel\Extraction\ExtractedEndpointData;
use Knuckles\Scribe\Extracting\RouteDocBlocker;
use Knuckles\Scribe\Extracting\Strategies\Strategy;
use Mpociot\Reflection\DocBlock;
class GetFromDocBlocks extends Strategy
{
public function __invoke(ExtractedEndpointData $endpointData, array $routeRules = []): array
{
$docBlocks = RouteDocBlocker::getDocBlocksFromRoute($endpointData->route);
$methodDocBlock = $docBlocks['method'];
$classDocBlock = $docBlocks['class'];
return $this->getMetadataFromDocBlock($methodDocBlock, $classDocBlock);
}
public function getMetadataFromDocBlock(DocBlock $methodDocBlock, DocBlock $classDocBlock): array
{
[$groupName, $groupDescription, $title] = $this->getEndpointGroupAndTitleDetails($methodDocBlock, $classDocBlock);
$metadata = [
'groupName' => $groupName,
'groupDescription' => $groupDescription,
'subgroup' => $this->getEndpointSubGroup($methodDocBlock, $classDocBlock),
'subgroupDescription' => $this->getEndpointSubGroupDescription($methodDocBlock, $classDocBlock),
'title' => $title ?: $methodDocBlock->getShortDescription(),
'description' => $methodDocBlock->getLongDescription()->getContents(),
'deprecated' => $this->getDeprecatedStatusFromDocBlock($methodDocBlock, $classDocBlock),
];
if (!is_null($authStatus = $this->getAuthStatusFromDocBlock($methodDocBlock, $classDocBlock))) {
$metadata['authenticated'] = $authStatus;
}
return $metadata;
}
protected function getAuthStatusFromDocBlock(DocBlock $methodDocBlock, ?DocBlock $classDocBlock = null): ?bool
{
foreach ($methodDocBlock->getTags() as $tag) {
if (strtolower($tag->getName()) === 'authenticated') {
return true;
}
if (strtolower($tag->getName()) === 'unauthenticated') {
return false;
}
}
return $classDocBlock
? $this->getAuthStatusFromDocBlock($classDocBlock)
: null;
}
protected function getDeprecatedStatusFromDocBlock(DocBlock $methodDocBlock, ?DocBlock $classDocBlock = null): bool|string
{
foreach ($methodDocBlock->getTags() as $tag) {
if (strtolower($tag->getName()) === 'deprecated') {
return $tag->getContent() === '' ? true : $tag->getContent();
}
}
if ($classDocBlock instanceof DocBlock) {
return $this->getDeprecatedStatusFromDocBlock($classDocBlock);
}
return false;
}
/**
* @return array The endpoint's group name, the group description, and the endpoint title
*/
protected function getEndpointGroupAndTitleDetails(DocBlock $methodDocBlock, DocBlock $controllerDocBlock)
{
foreach ($methodDocBlock->getTags() as $tag) {
if ($tag->getName() === 'group') {
$endpointGroupParts = explode("\n", trim($tag->getContent()));
$endpointGroupName = array_shift($endpointGroupParts);
$endpointGroupDescription = trim(implode("\n", $endpointGroupParts));
// If the endpoint has no title (the methodDocBlock's "short description"),
// we'll assume the endpointGroupDescription is actually the title
// Something like this:
// /**
// * Fetch cars. <-- This is endpoint title.
// * @group Cars <-- This is group name.
// * APIs for cars. <-- This is group description (not required).
// **/
// VS
// /**
// * @group Cars <-- This is group name.
// * Fetch cars. <-- This is endpoint title, NOT group description.
// **/
// BTW, this is a spaghetti way of doing this.
// It shall be refactored soon. Deus vult!💪
// ...Or maybe not
if (empty($methodDocBlock->getShortDescription())) {
return [$endpointGroupName, '', $endpointGroupDescription];
}
return [$endpointGroupName, $endpointGroupDescription, $methodDocBlock->getShortDescription()];
}
}
// Fall back to the controller
foreach ($controllerDocBlock->getTags() as $tag) {
if ($tag->getName() === 'group') {
$endpointGroupParts = explode("\n", trim($tag->getContent()));
$endpointGroupName = array_shift($endpointGroupParts);
$endpointGroupDescription = implode("\n", $endpointGroupParts);
return [$endpointGroupName, $endpointGroupDescription, $methodDocBlock->getShortDescription()];
}
}
return [null, '', $methodDocBlock->getShortDescription()];
}
protected function getEndpointSubGroup(DocBlock $methodDocBlock, DocBlock $controllerDocBlock): ?string
{
foreach ($methodDocBlock->getTags() as $tag) {
if (strtolower($tag->getName()) === 'subgroup') {
return trim($tag->getContent());
}
}
foreach ($controllerDocBlock->getTags() as $tag) {
if (strtolower($tag->getName()) === 'subgroup') {
return trim($tag->getContent());
}
}
return null;
}
protected function getEndpointSubGroupDescription(DocBlock $methodDocBlock, DocBlock $controllerDocBlock): ?string
{
foreach ($methodDocBlock->getTags() as $tag) {
if (strtolower($tag->getName()) === 'subgroupdescription') {
return trim($tag->getContent());
}
}
foreach ($controllerDocBlock->getTags() as $tag) {
if (strtolower($tag->getName()) === 'subgroupdescription') {
return trim($tag->getContent());
}
}
return null;
}
}