Skip to content

Commit 1338a0b

Browse files
committed
Support encryption, avoid double __unserialize call
Laravel uses the magic method `__unserialize()` in the `SerializesModels` trait, which does a bunch of work to rehydrate models attached to jobs. This gets called every time the job is unserialized. The addition of an `unserialize()` call in the constructor to get the `queue` property causes it to run twice because of the original call to `unserialize()` is in `\Illuminate\Queue\CallQueuedHandler->getCommand()`. `CallQueuedHandler->getCommand()` also implements support for encrypted command payloads. This change brings over the encryption support logic from `CallQueuedHandler->getCommand()` and passed `['allowed_classes' => false]` to the `unserialize()` call. This will make it _not_ hydrate to the original job object, but instead to an instance of `__PHP_Incomplete_Class` avoiding the unnecessary call to `__unserialize()` with this `unserialize()` call. We then cast to an `(array)` to access the `queue` property without issue.
1 parent 7b0f6ae commit 1338a0b

File tree

3 files changed

+25
-9
lines changed

3 files changed

+25
-9
lines changed

src/CloudTasksJob.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ public function __construct(array $job, CloudTasksQueue $cloudTasksQueue)
2424
$this->job = $job;
2525
$this->container = Container::getInstance();
2626
$this->cloudTasksQueue = $cloudTasksQueue;
27-
/** @var \stdClass $command */
28-
$command = unserialize($job['data']['command']);
29-
$this->queue = $command->queue;
27+
28+
$command = TaskHandler::getCommandProperties($job['data']['command']);
29+
$this->queue = $command['queue'] ?? config('queue.connections.' .config('queue.default') . '.queue');
3030
}
3131

3232
public function getJobId(): string

src/TaskHandler.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
use Google\Cloud\Tasks\V2\CloudTasksClient;
66
use Google\Cloud\Tasks\V2\RetryConfig;
77
use Illuminate\Bus\Queueable;
8+
use Illuminate\Contracts\Encryption\Encrypter;
89
use Illuminate\Queue\Jobs\Job;
910
use Illuminate\Queue\WorkerOptions;
11+
use Illuminate\Support\Str;
1012
use stdClass;
1113
use UnexpectedValueException;
1214
use function Safe\json_decode;
@@ -56,8 +58,8 @@ private function loadQueueConnectionConfiguration(array $task): void
5658
/**
5759
* @var stdClass $command
5860
*/
59-
$command = unserialize($task['data']['command']);
60-
$connection = $command->connection ?? config('queue.default');
61+
$command = self::getCommandProperties($task['data']['command']);
62+
$connection = $command['connection'] ?? config('queue.default');
6163
$this->config = array_merge(
6264
(array) config("queue.connections.{$connection}"),
6365
['connection' => $connection]
@@ -131,4 +133,17 @@ private function loadQueueRetryConfig(CloudTasksJob $job): void
131133

132134
$this->retryConfig = CloudTasksApi::getRetryConfig($queueName);
133135
}
136+
137+
public static function getCommandProperties(string $command): array
138+
{
139+
if (Str::startsWith($command, 'O:')) {
140+
return (array) unserialize($command, ['allowed_classes' => false]);
141+
}
142+
143+
if (app()->bound(Encrypter::class)) {
144+
return (array) unserialize(app(Encrypter::class)->decrypt($command), ['allowed_classes' => false]);
145+
}
146+
147+
return [];
148+
}
134149
}

tests/QueueTest.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Google\Cloud\Tasks\V2\HttpMethod;
88
use Google\Cloud\Tasks\V2\Task;
99
use Stackkit\LaravelGoogleCloudTasksQueue\CloudTasksApi;
10+
use Stackkit\LaravelGoogleCloudTasksQueue\TaskHandler;
1011
use Tests\Support\FailingJob;
1112
use Tests\Support\SimpleJob;
1213

@@ -137,19 +138,19 @@ public function it_posts_the_task_the_correct_queue()
137138
// Assert
138139
CloudTasksApi::assertTaskCreated(function (Task $task, string $queueName): bool {
139140
$decoded = json_decode($task->getHttpRequest()->getBody(), true);
140-
$command = unserialize($decoded['data']['command']);
141+
$command = TaskHandler::getCommandProperties($decoded['data']['command']);
141142

142143
return $decoded['displayName'] === SimpleJob::class
143-
&& $command->queue === null
144+
&& $command['queue'] === null
144145
&& $queueName === 'projects/my-test-project/locations/europe-west6/queues/barbequeue';
145146
});
146147

147148
CloudTasksApi::assertTaskCreated(function (Task $task, string $queueName): bool {
148149
$decoded = json_decode($task->getHttpRequest()->getBody(), true);
149-
$command = unserialize($decoded['data']['command']);
150+
$command = TaskHandler::getCommandProperties($decoded['data']['command']);
150151

151152
return $decoded['displayName'] === FailingJob::class
152-
&& $command->queue === 'my-special-queue'
153+
&& $command['queue'] === 'my-special-queue'
153154
&& $queueName === 'projects/my-test-project/locations/europe-west6/queues/my-special-queue';
154155
});
155156
}

0 commit comments

Comments
 (0)