Skip to content

Helpful strategies (snippets)

Shalvah edited this page May 30, 2021 · 3 revisions

This is a list of helpful strategy snippets you can copy and add to your own project. Note that you may need to update them, as there's no guarantee they will be kept up-to-date with every change in Scribe.

Authenticating as a particular user for response calls

Originally contributed by @ajcastro

use App\User;
use Illuminate\Routing\Route;
use Knuckles\Scribe\Extracting\Strategies\Responses\ResponseCalls;
use Illuminate\Http\Request;

class ResponseCallsWithUserAuth extends ResponseCalls
{
    protected function prepareRequest(Route $route, array $rulesToApply, array $urlParams, array $bodyParams, array $queryParams, array $headers): Request
    {
        $request = parent::prepareRequest($route, $rulesToApply, $urlParams, $bodyParams, $queryParams, $headers);

        if (in_array('auth:api', $route->gatherMiddleware())) {
            $user = factory(User::class)->create();
            $token = auth()->fromUser($user);

            $request->headers->set('Authorization', "Bearer {$token}");
        }

        return $request;
    }
}

Notes:

  1. Scribe supports authentication in response calls by setting the auth.use_value key, but this can currently only be a static value or gotten from the environment.

Get metadata from parent class' docblock

Originally contributed by @ajcastro

use Illuminate\Routing\Route;
use Knuckles\Scribe\Extracting\RouteDocBlocker;
use Knuckles\Scribe\Extracting\Strategies\Metadata\GetFromDocBlocks;
use ReflectionClass;
use ReflectionMethod;

class MyGetFromDocBlocks extends GetFromDocBlocks
{
    public function __invoke(Route $route, ReflectionClass $controller, ReflectionMethod $method, array $routeRules, array $context = [])
    {
        $docBlocks = RouteDocBlocker::getDocBlocksFromRoute($route);
        /** @var DocBlock $methodDocBlock */
        $methodDocBlock = $docBlocks['method'];
        $classDocBlock = $docBlocks['class'];

        list($routeGroupName, $routeGroupDescription, $routeTitle) = $this->getRouteGroupDescriptionAndTitle($methodDocBlock, $classDocBlock);

        $routeTitle = $this->getTitle($controller, $routeTitle ?: $methodDocBlock->getShortDescription());

        return [
            'groupName' => $routeGroupName,
            'groupDescription' => $routeGroupDescription,
            'title' => $routeTitle ?: $methodDocBlock->getShortDescription(),
            'description' => $methodDocBlock->getLongDescription()->getContents(),
            'authenticated' => $this->getAuthStatusFromDocBlock($classDocBlock->getTags())?:$this->getAuthStatusFromDocBlock($methodDocBlock->getTags()),
        ];
    }

    private function getTitle($controller, $routeTitle)
    {
        // if no curly brace return the default routeTitle
        if (!preg_match_all('/{(.*?)}/', $routeTitle, $matches)) {
            return $routeTitle;
        }

        $parameterNames = $matches[1];

        foreach ($parameterNames as $parameterSignature) {
            $modifiers = explode('|', $parameterSignature);
            $parameterName = array_shift($modifiers);

            $reflectParam = array_first(
                $controller->getMethod('__construct')->getParameters(),
                function ($reflectParam) use ($parameterName) {
                    return $reflectParam->getName() === $parameterName;
                }
            );

            if (is_null($reflectParam)) {
                continue;
            }

            $typeHintClass = last(explode('\\', $reflectParam->getType()->getName()));

            foreach ($modifiers as $modifier) {
                $typeHintClass = call_user_func_array($modifier, [$typeHintClass]);
            }

            $routeTitle = str_replace('{'.$parameterSignature.'}', $typeHintClass, $routeTitle);
        }

        return $routeTitle;
    }
}