DEV Community

Cover image for Enhancing Laravel Commands: Parameterized Inputs and Custom Output Formats [4/4]
Nick Ciolpan for Graffino

Posted on

Enhancing Laravel Commands: Parameterized Inputs and Custom Output Formats [4/4]

So far, so good. It gives us some insights into the current state of our gating system, but not much more. Since we've come this far, we might as well take one step further and incorporate two crucial aspects of commands: the ability to pass parameters. Once we have this functionality in place, the console kernel becomes equally powerful as the web kernel, granting access to all infrastructure and data layers, just as you would normally have.

What we do is pass a username to the command and then examine each gate for the retrieved user. We mark, in an additional column, whether the user can pass it or not, indicating a green "pass" or a red "restricted".

Try to and identify the new code additions. I’ll give you a hint: start with the command signature. Feel free to comment if you have any questions. And, most importantly, have fun!

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Contracts\Auth\Access\Gate;
use App\Models\User;

class CheckGates extends Command
{
    protected $signature = 'gate:check {username}';
    protected $description = 'Check access of user for all defined gates in Laravel';

    protected $gate;

    public function __construct(Gate $gate)
    {
        parent::__construct();
        $this->gate = $gate;
    }
    protected function getClosureContents(\Closure $closure)
    {
        $reflection = new \ReflectionFunction($closure);
        $closureCode = file($reflection->getFileName());

        $startLine = $reflection->getStartLine();
        $endLine = $reflection->getEndLine();

        $contents = array_slice($closureCode, $startLine - 1, $endLine - $startLine + 1);

        return implode('', $contents);
    }
    public function handle()
    {
        $username = $this->argument('username');
        $user = User::where('username', $username)->first();

        if (!$user) {
            $this->error("No user found with username: $username");
            return;
        }

        $gates = $this->gate->abilities();
        $self = $this;

        $tableData = array_reduce(array_keys($gates), function ($carry, $key) use ($gates, $user, $self) {
            $value = $gates[$key];
            $hasAccess = $this->gate->forUser($user)->check($key);

            $carry[] = [
                'Gate Name' => $key,
                'Access' => $hasAccess ? '<fg=green>Pass</>' : '<fg=red>Restricted</>',
                'Closure Contents' => $self->getClosureContents($value),
            ];

            return $carry;
        }, []);

        $this->table(['Gate Name','Access', 'Closure Contents'], $tableData);
    }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)