From 6dda7dbb059de5278a3dfd08f7788869ef68a9bf Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 9 Jun 2025 14:18:10 +0200 Subject: [PATCH 1/3] fix literal-string issue --- src/Event/Repository/AsynchronousDatabase.php | 2 +- tests/Event/Repository/AsynchronousDatabaseTest.phpt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Event/Repository/AsynchronousDatabase.php b/src/Event/Repository/AsynchronousDatabase.php index 34a5701..47c4010 100644 --- a/src/Event/Repository/AsynchronousDatabase.php +++ b/src/Event/Repository/AsynchronousDatabase.php @@ -29,7 +29,7 @@ public function load(int $limit): Collection $this->db->execute('START TRANSACTION'); $records = $this->db->execute( - $this->db->prepare("SELECT * FROM `{$this->db->table('bulkgate_module')}` WHERE `scope` = 'asynchronous' AND `order` = 0 LIMIT %s FOR UPDATE", $limit) + "SELECT * FROM `{$this->db->table('bulkgate_module')}` WHERE `scope` = 'asynchronous' AND `order` = 0 LIMIT {$this->db->escape((string) $limit)} FOR UPDATE" ); if ($records !== null) diff --git a/tests/Event/Repository/AsynchronousDatabaseTest.phpt b/tests/Event/Repository/AsynchronousDatabaseTest.phpt index 8cda14a..80ea2a6 100644 --- a/tests/Event/Repository/AsynchronousDatabaseTest.phpt +++ b/tests/Event/Repository/AsynchronousDatabaseTest.phpt @@ -21,8 +21,8 @@ class AsynchronousDatabaseTest extends TestCase $db->shouldReceive('table')->with('bulkgate_module')->times(3)->andReturn('bulkgate_module'); $db->shouldReceive('execute')->with('START TRANSACTION')->once()->ordered(); - $db->shouldReceive('prepare')->with("SELECT * FROM `bulkgate_module` WHERE `scope` = 'asynchronous' AND `order` = 0 LIMIT %s FOR UPDATE", 2)->once()->ordered()->andReturn('SQL1'); - $db->shouldReceive('execute')->with('SQL1')->once()->ordered()->andReturn(new ResultCollection([ + $db->shouldReceive('escape')->with('2')->once()->ordered()->andReturn(2); + $db->shouldReceive('execute')->with("SELECT * FROM `bulkgate_module` WHERE `scope` = 'asynchronous' AND `order` = 0 LIMIT 2 FOR UPDATE")->once()->ordered()->andReturn(new ResultCollection([ ['key' => 'task1', 'value' => '{"category": "test", "endpoint": "endpoint1", "variables": {"key": "value"}}', 'datetime' => '456', 'order' => '0'], ['key' => 'task2', 'value' => '{"category": "test", "endpoint": "endpoint2", "variables": {"key2": "value2"}}', 'datetime' => 456, 'order' => 0], ])); @@ -50,8 +50,8 @@ class AsynchronousDatabaseTest extends TestCase $db->shouldReceive('table')->once()->andReturn('bulkgate_module'); $db->shouldReceive('execute')->with('START TRANSACTION')->once()->ordered(); - $db->shouldReceive('prepare')->with("SELECT * FROM `bulkgate_module` WHERE `scope` = 'asynchronous' AND `order` = 0 LIMIT %s FOR UPDATE", 2)->once()->ordered()->andReturn('SQL1'); - $db->shouldReceive('execute')->with('SQL1')->once()->ordered()->andReturnNull(); + $db->shouldReceive('escape')->with('2')->once()->ordered()->andReturn(2); + $db->shouldReceive('execute')->with("SELECT * FROM `bulkgate_module` WHERE `scope` = 'asynchronous' AND `order` = 0 LIMIT 2 FOR UPDATE")->once()->ordered()->andReturnNull(); $db->shouldReceive('execute')->with('ROLLBACK')->once()->ordered(); $asynchronousDatabase = new AsynchronousDatabase($db); From 03446ed16db931d55f28095849204b929fdc8970 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 9 Jun 2025 14:19:21 +0200 Subject: [PATCH 2/3] add service definition type --- src/DI/ContainerBase.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/DI/ContainerBase.php b/src/DI/ContainerBase.php index 5d826d6..824578a 100644 --- a/src/DI/ContainerBase.php +++ b/src/DI/ContainerBase.php @@ -13,6 +13,7 @@ use function array_key_exists, class_exists, interface_exists, is_array, is_string, is_subclass_of, uniqid, count; /** + * @phpstan-type ServiceDefinition class-string|array{factory?:class-string, factory_method?:callable, parameters?:array, wiring?: class-string, auto_wiring?: bool} * @implements ArrayAccess|array{name: string, factory?: class-string, auto_wiring?: bool, parameters?: array, factory_method?: callable(mixed ...$parameters):object|null, instantiable: bool, factory_method?: callable(mixed ...$parameters):object|null}> */ abstract class ContainerBase implements ArrayAccess, Countable @@ -57,7 +58,7 @@ public function setConfig(array $config): void foreach ($config as $name => $service) if (is_string($service) || is_array($service)) { /** - * @var class-string|array{factory?: class-string, parameters?: array, wiring?: class-string, auto_wiring?: bool, factory_method?: callable(mixed ...$parameters):object|null} $service + * @var ServiceDefinition $service */ $this[is_string($name) ? $name : uniqid('class-')] = $service; } @@ -285,8 +286,8 @@ public function offsetGet($offset): object /** - * @param array-key $offset - * @param class-string|array{factory?: class-string, parameters?: array, wiring?: class-string, auto_wiring?: bool, factory_method?: callable(mixed ...$parameters):object|null} $value + * @param array-key $offset The service id + * @param ServiceDefinition $value The service definition. * @throws AutoWiringException|InvalidStateException */ public function offsetSet($offset, $value): void From 603f1bf6af118055bcd58d28a0061942c73adb38 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 9 Jun 2025 14:47:22 +0200 Subject: [PATCH 3/3] fix literal-string --- src/Event/Repository/AsynchronousDatabase.php | 7 ++++++- tests/Event/Repository/AsynchronousDatabaseTest.phpt | 2 -- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Event/Repository/AsynchronousDatabase.php b/src/Event/Repository/AsynchronousDatabase.php index 47c4010..53e5762 100644 --- a/src/Event/Repository/AsynchronousDatabase.php +++ b/src/Event/Repository/AsynchronousDatabase.php @@ -28,8 +28,13 @@ public function load(int $limit): Collection $this->db->execute('START TRANSACTION'); + /** + * @var literal-string $limit + */ + $limit = strval($limit); + $records = $this->db->execute( - "SELECT * FROM `{$this->db->table('bulkgate_module')}` WHERE `scope` = 'asynchronous' AND `order` = 0 LIMIT {$this->db->escape((string) $limit)} FOR UPDATE" + "SELECT * FROM `{$this->db->table('bulkgate_module')}` WHERE `scope` = 'asynchronous' AND `order` = 0 LIMIT $limit FOR UPDATE" ); if ($records !== null) diff --git a/tests/Event/Repository/AsynchronousDatabaseTest.phpt b/tests/Event/Repository/AsynchronousDatabaseTest.phpt index 80ea2a6..5a1de33 100644 --- a/tests/Event/Repository/AsynchronousDatabaseTest.phpt +++ b/tests/Event/Repository/AsynchronousDatabaseTest.phpt @@ -21,7 +21,6 @@ class AsynchronousDatabaseTest extends TestCase $db->shouldReceive('table')->with('bulkgate_module')->times(3)->andReturn('bulkgate_module'); $db->shouldReceive('execute')->with('START TRANSACTION')->once()->ordered(); - $db->shouldReceive('escape')->with('2')->once()->ordered()->andReturn(2); $db->shouldReceive('execute')->with("SELECT * FROM `bulkgate_module` WHERE `scope` = 'asynchronous' AND `order` = 0 LIMIT 2 FOR UPDATE")->once()->ordered()->andReturn(new ResultCollection([ ['key' => 'task1', 'value' => '{"category": "test", "endpoint": "endpoint1", "variables": {"key": "value"}}', 'datetime' => '456', 'order' => '0'], ['key' => 'task2', 'value' => '{"category": "test", "endpoint": "endpoint2", "variables": {"key2": "value2"}}', 'datetime' => 456, 'order' => 0], @@ -50,7 +49,6 @@ class AsynchronousDatabaseTest extends TestCase $db->shouldReceive('table')->once()->andReturn('bulkgate_module'); $db->shouldReceive('execute')->with('START TRANSACTION')->once()->ordered(); - $db->shouldReceive('escape')->with('2')->once()->ordered()->andReturn(2); $db->shouldReceive('execute')->with("SELECT * FROM `bulkgate_module` WHERE `scope` = 'asynchronous' AND `order` = 0 LIMIT 2 FOR UPDATE")->once()->ordered()->andReturnNull(); $db->shouldReceive('execute')->with('ROLLBACK')->once()->ordered();