Passed
Push — master ( 41a7c0...823f6c )
by Bruno
15:50 queued 07:18
created

PolicyGenerator::processDirectives()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0175

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 8
nc 3
nop 2
dl 0
loc 12
ccs 7
cts 8
cp 0.875
crap 3.0175
rs 10
c 1
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Modelarium\Laravel\Targets;
4
5
use GraphQL\Language\AST\DirectiveNode;
6
use GraphQL\Type\Definition\NonNull;
7
use GraphQL\Type\Definition\ObjectType;
8
use GraphQL\Type\Definition\Type;
9
use Illuminate\Support\Str;
10
use Modelarium\BaseGenerator;
11
use Modelarium\GeneratedCollection;
12
use Modelarium\GeneratedItem;
13
use Modelarium\Parser;
14
use Nette\PhpGenerator\ClassType;
15
use Nette\PhpGenerator\PhpNamespace;
16
17
class PolicyGenerator extends BaseGenerator
18
{
19
    /**
20
     * @var string
21
     */
22
    protected $stubDir = __DIR__ . "/stubs/";
23
24
    /**
25
     * @var ObjectType
26
     */
27
    protected $type = null;
28
29
    /**
30
     * @var GeneratedCollection
31
     */
32
    protected $collection = null;
33
34
    /**
35
     *
36
     * @var ClassType[]
37
     */
38
    protected $policyClasses = [];
39
40
    /**
41
     * @param Parser $parser
42
     * @param string $name
43
     * @param Type|string $type
44
     * @phpstan-ignore-next-line
45
     */
46 2
    public function __construct(Parser $parser, string $name, $type = null)
47
    {
48 2
        parent::__construct($parser, '', $type);
49 2
        $this->collection = new GeneratedCollection();
50 2
    }
51
52 2
    public function generate(): GeneratedCollection
53
    {
54 2
        foreach ($this->type->getFields() as $field) {
55 1
            $directives = $field->astNode->directives;
56 1
            $this->processDirectives($field, $directives);
57
        }
58
59
60 2
        $printer = new \Nette\PhpGenerator\PsrPrinter;
61
62 2
        foreach ($this->policyClasses as $name => $c) {
63 1
            $namespace = new PhpNamespace('App\\Policies');
64 1
            $namespace->addUse('App\\Models\\User');
65 1
            $namespace->addUse('App\\Models\\' . $name);
66 1
            $namespace->add($c);
67
68 1
            $this->collection->push(
69 1
                new GeneratedItem(
70 1
                    GeneratedItem::TYPE_POLICY,
71 1
                    "<?php declare(strict_types=1);\n\n" . $printer->printNamespace($namespace),
72 1
                    $this->getGenerateFilename($name)
73
                )
74
            );
75
        }
76 2
        return $this->collection;
77
    }
78
79 1
    public function processDirectives(
80
        \GraphQL\Type\Definition\FieldDefinition $field,
81
        \GraphQL\Language\AST\NodeList $directives
82
    ): void {
83 1
        foreach ($directives as $directive) {
84 1
            $name = $directive->name->value;
85 1
            switch ($name) {
86 1
            case 'can':
87 1
                $this->processCan($field, $directive);
88 1
            break;
89
            default:
90
            break;
91
            }
92
        }
93 1
    }
94
95 1
    public function processCan(
96
        \GraphQL\Type\Definition\FieldDefinition $field,
97
        DirectiveNode $directive
98
    ): void {
99 1
        $ability = '';
100 1
        $find = '';
101 1
        $injected = false;
102 1
        $args = false;
103
104 1
        if ($field->type instanceof NonNull) {
105
            $type = $field->type->getWrappedType();
106
        } else {
107 1
            $type = $field->type;
108
        }
109
110 1
        $model = $type->name; /** @phpstan-ignore-line */;
111
        
112 1
        foreach ($directive->arguments as $arg) {
113 1
            switch ($arg->name->value) {
114 1
                case 'ability':
115
                    // @phpstan-ignore-next-line
116 1
                    $ability = $arg->value->value;
0 ignored issues
show
Bug introduced by
Accessing value on the interface GraphQL\Language\AST\ValueNode suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
117 1
                break;
118 1
                case 'find':
119
                    // @phpstan-ignore-next-line
120 1
                    $find = $arg->value->value;
121 1
                break;
122 1
                case 'model':
123
                    // @phpstan-ignore-next-line
124
                    $model = $arg->value->value;
125
                break;
126 1
                case 'injectArgs':
127 1
                    $injected = true;
128 1
                break;
129 1
                case 'args':
130 1
                    $args = true;
131 1
                break;
132
            }
133
        }
134
135 1
        list($namespace, $modelClassName, $relativePath) = $this->splitClassName($model);
136
137 1
        $class = $this->getClass($modelClassName);
138
139 1
        $method = $class->addMethod($ability);
140 1
        $method->setPublic()
141 1
            ->setReturnType('bool')
142 1
            ->addBody(
143 1
                'return false;'
144
            );
145 1
        $method->addParameter('user')->setType('\\App\\Models\\User');
146
147 1
        if ($find) {
148 1
            $method->addParameter('model')->setType('\\App\\Models\\' . $modelClassName);
149
        }
150 1
        if ($injected) {
151 1
            $method->addParameter('injectedArgs')->setType('array');
152
        }
153 1
        if ($args) {
154 1
            $method->addParameter('staticArgs')->setType('array');
155
        }
156 1
    }
157
158 1
    protected function getClass(string $name): ClassType
159
    {
160 1
        if (array_key_exists($name, $this->policyClasses)) {
161 1
            return $this->policyClasses[$name];
162
        }
163
164
        /**
165
         * @var ClassType $class
166
         */
167 1
        $class = new ClassType($name . 'Policy');
168
        $class
169 1
            ->addComment("This file was automatically generated by Modelarium.")
170 1
            ->setTraits(['Illuminate\Auth\Access\HandlesAuthorization']);
171 1
        $this->policyClasses[$name] = $class;
172 1
        return $class;
173
    }
174
175 1
    public function getGenerateFilename(string $name): string
176
    {
177 1
        return $this->getBasePath('app/Policies/'. Str::studly($name) . 'Policy.php');
178
    }
179
}
180