Passed
Push — master ( 8366d7...daf92e )
by Bruno
08:53
created

PolicyGenerator::getClass()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

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