Skip to content

Commit afbe4e5

Browse files
Marick van TuilMarick van Tuil
Marick van Tuil
authored and
Marick van Tuil
committed
Make PHPStan happy
1 parent fdffa8e commit afbe4e5

13 files changed

+232
-70
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Add a new queue connection to `config/queue.php`
4545
'service_account_email' => env('CLOUD_TASKS_SERVICE_EMAIL', ''),
4646

4747
'backoff' => 0,
48+
'after_commit' => false,
4849
],
4950
```
5051

composer.json

+1-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"require-dev": {
1717
"orchestra/testbench": "^10.0",
1818
"thecodingmachine/phpstan-safe-rule": "^1.2",
19-
"laravel/legacy-factories": "^1.3",
2019
"laravel/pint": "^1.13",
2120
"larastan/larastan": "^3.0"
2221
},
@@ -27,8 +26,7 @@
2726
},
2827
"autoload-dev": {
2928
"psr-4": {
30-
"Tests\\": "tests/",
31-
"Factories\\": "factories/"
29+
"Tests\\": "tests/"
3230
}
3331
},
3432
"extra": {

phpstan.neon

+2
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ parameters:
55
paths:
66
- src
77
level: 9
8+
ignoreErrors:
9+
- "/dispatchAfterCommit with no type specified/"

src/CloudTasksApiFake.php

+9
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,17 @@
1010

1111
class CloudTasksApiFake implements CloudTasksApiContract
1212
{
13+
/**
14+
* @var array<int, array{
15+
* queueName: string,
16+
* task: Task
17+
* }>
18+
*/
1319
public array $createdTasks = [];
1420

21+
/**
22+
* @var array<int, string>
23+
*/
1524
public array $deletedTasks = [];
1625

1726
public function createTask(string $queueName, Task $task): Task

src/CloudTasksConnector.php

+17
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,25 @@
77
use Google\Cloud\Tasks\V2\Client\CloudTasksClient;
88
use Illuminate\Queue\Connectors\ConnectorInterface;
99

10+
/**
11+
* @phpstan-type QueueConfig array{
12+
* driver: string,
13+
* project: string,
14+
* location: string,
15+
* queue: string,
16+
* app_engine?: bool,
17+
* app_engine_service?: string,
18+
* handler?: string,
19+
* service_account_email?: string,
20+
* backoff?: int,
21+
* after_commit?: bool
22+
* }
23+
*/
1024
class CloudTasksConnector implements ConnectorInterface
1125
{
26+
/**
27+
* @param QueueConfig $config
28+
*/
1229
public function connect(array $config): CloudTasksQueue
1330
{
1431
return new CloudTasksQueue(

src/CloudTasksJob.php

+32-2
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,48 @@
1414
use Illuminate\Contracts\Queue\Job as JobContract;
1515
use Stackkit\LaravelGoogleCloudTasksQueue\Events\JobReleased;
1616

17+
/**
18+
* @phpstan-type JobShape array{
19+
* uuid: string,
20+
* displayName: string,
21+
* job: string,
22+
* maxTries: int,
23+
* maxExceptions: int|null,
24+
* failOnTimeout: bool,
25+
* backoff: int|null,
26+
* timeout: int|null,
27+
* retryUntil: int|null,
28+
* data: array{
29+
* commandName: string,
30+
* command: string
31+
* },
32+
* internal?: array{
33+
* attempts: int,
34+
* errored?: bool
35+
* }
36+
* }
37+
* @phpstan-type JobBeforeDispatch object{
38+
* queue: ?string
39+
* }&\stdClass
40+
*/
1741
class CloudTasksJob extends LaravelJob implements JobContract
1842
{
1943
protected $container;
2044

2145
private CloudTasksQueue $driver;
2246

47+
/**
48+
* @var JobShape
49+
*/
2350
public array $job;
2451

2552
protected $connectionName;
2653

2754
protected $queue;
2855

56+
/**
57+
* @param JobShape $job
58+
*/
2959
public function __construct(
3060
Container $container,
3161
CloudTasksQueue $driver,
@@ -53,9 +83,9 @@ public function getRawBody(): string
5383
return json_encode($this->job);
5484
}
5585

56-
public function attempts(): ?int
86+
public function attempts(): int
5787
{
58-
return $this->job['internal']['attempts'];
88+
return $this->job['internal']['attempts'] ?? 0;
5989
}
6090

6191
public function setAttempts(int $attempts): void

src/CloudTasksQueue.php

+80-23
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Stackkit\LaravelGoogleCloudTasksQueue;
66

77
use Closure;
8+
use Exception;
89
use Illuminate\Support\Str;
910

1011
use function Safe\json_decode;
@@ -23,17 +24,34 @@
2324
use Illuminate\Contracts\Queue\Queue as QueueContract;
2425
use Stackkit\LaravelGoogleCloudTasksQueue\Events\TaskCreated;
2526

27+
/**
28+
* @phpstan-import-type QueueConfig from CloudTasksConnector
29+
* @phpstan-import-type JobShape from CloudTasksJob
30+
* @phpstan-import-type JobBeforeDispatch from CloudTasksJob
31+
*
32+
* @phpstan-type JobOptions array{
33+
* job?: Closure|string|object,
34+
* delay?: ?int
35+
* }
36+
*/
2637
class CloudTasksQueue extends LaravelQueue implements QueueContract
2738
{
28-
private static ?Closure $handlerUrlCallback = null;
39+
protected static ?Closure $handlerUrlCallback = null;
2940

30-
private static ?Closure $taskHeadersCallback = null;
41+
protected static ?Closure $taskHeadersCallback = null;
3142

3243
/** @var (Closure(IncomingTask): WorkerOptions)|null */
33-
private static ?Closure $workerOptionsCallback = null;
44+
protected static ?Closure $workerOptionsCallback = null;
3445

35-
public function __construct(public array $config, public CloudTasksClient $client, public $dispatchAfterCommit = false)
36-
{
46+
/**
47+
* @param QueueConfig $config
48+
*/
49+
public function __construct(
50+
public array $config,
51+
public CloudTasksClient $client,
52+
// @phpstan-ignore-next-line
53+
public $dispatchAfterCommit = false,
54+
) {
3755
//
3856
}
3957

@@ -92,15 +110,20 @@ public function size($queue = null): int
92110
/**
93111
* Push a new job onto the queue.
94112
*
95-
* @param string|object $job
113+
* @param string|Closure|JobBeforeDispatch $job
96114
* @param mixed $data
97115
* @param string|null $queue
98-
* @return void
116+
* @return mixed
99117
*/
100118
public function push($job, $data = '', $queue = null)
101119
{
102-
if (! ($job instanceof Closure)) {
103-
$job->queue = $queue ?? $job->queue ?? $this->config['queue'];
120+
if (! $queue) {
121+
$queue = $this->getQueueForJob($job);
122+
}
123+
124+
if (is_object($job) && ! $job instanceof Closure) {
125+
/** @var JobBeforeDispatch $job */
126+
$job->queue = $queue;
104127
}
105128

106129
return $this->enqueueUsing(
@@ -119,6 +142,7 @@ function ($payload, $queue) use ($job) {
119142
*
120143
* @param string $payload
121144
* @param string|null $queue
145+
* @param JobOptions $options
122146
* @return string
123147
*/
124148
public function pushRaw($payload, $queue = null, array $options = [])
@@ -133,13 +157,18 @@ public function pushRaw($payload, $queue = null, array $options = [])
133157
* Push a new job onto the queue after a delay.
134158
*
135159
* @param \DateTimeInterface|\DateInterval|int $delay
136-
* @param string|object $job
160+
* @param Closure|string|JobBeforeDispatch $job
137161
* @param mixed $data
138162
* @param string|null $queue
139-
* @return void
163+
* @return mixed
140164
*/
141165
public function later($delay, $job, $data = '', $queue = null)
142166
{
167+
// Laravel pls fix your typehints
168+
if (! $queue) {
169+
$queue = $this->getQueueForJob($job);
170+
}
171+
143172
return $this->enqueueUsing(
144173
$job,
145174
$this->createPayload($job, $queue, $data),
@@ -157,7 +186,7 @@ function ($payload, $queue, $delay) use ($job) {
157186
* @param string|null $queue
158187
* @param string $payload
159188
* @param \DateTimeInterface|\DateInterval|int $delay
160-
* @param string|object $job
189+
* @param Closure|string|object|null $job
161190
* @return string
162191
*/
163192
protected function pushToCloudTasks($queue, $payload, $delay, mixed $job)
@@ -166,6 +195,7 @@ protected function pushToCloudTasks($queue, $payload, $delay, mixed $job)
166195

167196
$payload = (array) json_decode($payload, true);
168197

198+
/** @var JobShape $payload */
169199
$task = tap(new Task)->setName($this->taskName($queue, $payload['displayName']));
170200

171201
$payload = $this->enrichPayloadWithAttempts($payload);
@@ -200,33 +230,43 @@ private function taskName(string $queueName, string $displayName): string
200230
);
201231
}
202232

203-
private function enrichPayloadWithAttempts(
204-
array $payload,
205-
): array {
233+
/**
234+
* @param JobShape $payload
235+
* @return JobShape
236+
*/
237+
private function enrichPayloadWithAttempts(array $payload): array
238+
{
206239
$payload['internal'] = [
207240
'attempts' => $payload['internal']['attempts'] ?? 0,
208241
];
209242

210243
return $payload;
211244
}
212245

213-
/** @param string|object $job */
214-
public function addPayloadToTask(array $payload, Task $task, mixed $job): Task
246+
/**
247+
* @param Closure|string|object|null $job
248+
* @param JobShape $payload
249+
*/
250+
public function addPayloadToTask(array $payload, Task $task, $job): Task
215251
{
216252
$headers = $this->headers($payload);
217253

218254
if (! empty($this->config['app_engine'])) {
219255
$path = \Safe\parse_url(route('cloud-tasks.handle-task'), PHP_URL_PATH);
220256

257+
if (! is_string($path)) {
258+
throw new Exception('Something went wrong parsing the route.');
259+
}
260+
221261
$appEngineRequest = new AppEngineHttpRequest;
222262
$appEngineRequest->setRelativeUri($path);
223263
$appEngineRequest->setHttpMethod(HttpMethod::POST);
224264
$appEngineRequest->setBody(json_encode($payload));
225265
$appEngineRequest->setHeaders($headers);
226266

227-
if (! empty($service = $this->config['app_engine_service'])) {
267+
if (! empty($this->config['app_engine_service'])) {
228268
$routing = new AppEngineRouting;
229-
$routing->setService($service);
269+
$routing->setService($this->config['app_engine_service']);
230270
$appEngineRequest->setAppEngineRouting($routing);
231271
}
232272

@@ -239,7 +279,7 @@ public function addPayloadToTask(array $payload, Task $task, mixed $job): Task
239279
$httpRequest->setHeaders($headers);
240280

241281
$token = new OidcToken;
242-
$token->setServiceAccountEmail($this->config['service_account_email']);
282+
$token->setServiceAccountEmail($this->config['service_account_email'] ?? '');
243283
$httpRequest->setOidcToken($token);
244284
$task->setHttpRequest($httpRequest);
245285
}
@@ -267,7 +307,9 @@ public function release(CloudTasksJob $job, int $delay = 0): void
267307
);
268308
}
269309

270-
/** @param string|object $job */
310+
/**
311+
* @param Closure|string|object|null $job
312+
*/
271313
public function getHandler(mixed $job): string
272314
{
273315
if (static::$handlerUrlCallback) {
@@ -280,11 +322,11 @@ public function getHandler(mixed $job): string
280322

281323
$handler = rtrim($this->config['handler'], '/');
282324

283-
if (str_ends_with($handler, '/'.config('cloud-tasks.uri'))) {
325+
if (str_ends_with($handler, '/'.config()->string('cloud-tasks.uri'))) {
284326
return $handler;
285327
}
286328

287-
return $handler.'/'.config('cloud-tasks.uri');
329+
return $handler.'/'.config()->string('cloud-tasks.uri');
288330
}
289331

290332
/**
@@ -299,4 +341,19 @@ private function headers(mixed $payload): array
299341

300342
return (static::$taskHeadersCallback)($payload);
301343
}
344+
345+
/**
346+
* @param Closure|string|JobBeforeDispatch $job
347+
*/
348+
private function getQueueForJob(mixed $job): string
349+
{
350+
if (is_object($job) && ! $job instanceof Closure) {
351+
/** @var JobBeforeDispatch $job */
352+
if (! empty($job->queue)) {
353+
return $job->queue;
354+
}
355+
}
356+
357+
return $this->config['queue'];
358+
}
302359
}

0 commit comments

Comments
 (0)