diff --git a/.github/workflows/automated-test.yml b/.github/workflows/automated-test.yml index 465a3bc..941fab3 100644 --- a/.github/workflows/automated-test.yml +++ b/.github/workflows/automated-test.yml @@ -1,5 +1,5 @@ name: PHPUnit Tests -on: [push, pull_request] +on: [push] jobs: phpunit: runs-on: ubuntu-latest diff --git a/src/Commands/RefreshMeta.php b/src/Commands/RefreshMeta.php index 8afa881..a6e47a2 100644 --- a/src/Commands/RefreshMeta.php +++ b/src/Commands/RefreshMeta.php @@ -26,7 +26,7 @@ public function handle(): void while ($count < $total) { $query = Meta::query() ->orderBy('id') - ->limit(100); + ->limit(config('metable.refreshPageSize', 100)); if ($lastId) { $query->where('id', '>', $lastId); } @@ -48,5 +48,4 @@ public function handle(): void $this->info('Refresh complete.'); } - -} \ No newline at end of file +} diff --git a/src/DataType/ModelCollectionHandler.php b/src/DataType/ModelCollectionHandler.php index 883eaf6..46b52b4 100644 --- a/src/DataType/ModelCollectionHandler.php +++ b/src/DataType/ModelCollectionHandler.php @@ -63,6 +63,7 @@ public function unserializeValue(string $serializedValue): mixed $models = $this->loadModels($data['items']); + // Repopulate collection keys with loaded models. foreach ($data['items'] as $key => $item) { if (empty($item['key'])) { @@ -107,6 +108,7 @@ private function loadModels(array $items) if (!class_exists($class) || !is_a($class, Model::class, true) ) { + continue; } diff --git a/tests/Integration/Commands/RefreshMetaTest.php b/tests/Integration/Commands/RefreshMetaTest.php index 1a2fde5..5e0599c 100644 --- a/tests/Integration/Commands/RefreshMetaTest.php +++ b/tests/Integration/Commands/RefreshMetaTest.php @@ -23,6 +23,8 @@ public function test_it_refreshes_all_meta_values(): void ]); config()->set('metable.indexComplexDataTypes', true); + config()->set('metable.refreshPageSize', 2); + $complexValue = ['a' => 'b']; DB::table('meta')->insert([ @@ -79,5 +81,4 @@ public function test_it_refreshes_all_meta_values(): void $this->assertEquals('2020-01-01 00:00:00.000000+0000', $result[2]->string_value); $this->assertEquals(1577836800, $result[2]->numeric_value); } - -} \ No newline at end of file +} diff --git a/tests/Integration/DataType/HandlerTest.php b/tests/Integration/DataType/HandlerTest.php index 45bf672..707a523 100644 --- a/tests/Integration/DataType/HandlerTest.php +++ b/tests/Integration/DataType/HandlerTest.php @@ -41,108 +41,144 @@ public static function handlerProvider(): array return [ 'array' => [ - new ArrayHandler(), - 'array', - ['foo' => ['bar'], 'baz'], - [new stdClass()], - null, - null, + 'handler' => new ArrayHandler(), + 'type' => 'array', + 'value' => ['foo' => ['bar'], 'baz'], + 'invalid' => [new stdClass()], + 'numericValue' => null, + 'stringValue' => null, + 'stringValueComplex' => json_encode(['foo' => ['bar'], 'baz']), + 'isIdempotent' => true, ], 'boolean' => [ - new BooleanHandler(), - 'boolean', - true, - [1, 0, '', [], null], - 1, - 'true' + 'handler' => new BooleanHandler(), + 'type' => 'boolean', + 'value' => true, + 'invalid' => [1, 0, '', [], null], + 'numericValue' => 1, + 'stringValue' => 'true', + 'stringValueComplex' => 'true', + 'isIdempotent' => true, ], 'datetime' => [ - new DateTimeHandler(), - 'datetime', - $datetime, - [2017, '2017-01-01'], - $timestamp, - $dateString, + 'handler' => new DateTimeHandler(), + 'type' => 'datetime', + 'value' => $datetime, + 'invalid' => [2017, '2017-01-01'], + 'numericValue' => $timestamp, + 'stringValue' => $dateString, + 'stringValueComplex' => $dateString, + 'isIdempotent' => true, ], 'float' => [ - new FloatHandler(), - 'float', - 1.1, - ['1.1', 1], - 1.1, - '1.1', + 'handler' => new FloatHandler(), + 'type' => 'float', + 'value' => 1.1, + 'invalid' => ['1.1', 1], + 'numericValue' => 1.1, + 'stringValue' => '1.1', + 'stringValueComplex' => '1.1', + 'isIdempotent' => true, ], 'integer' => [ - new IntegerHandler(), - 'integer', - 3, - [1.1, '1'], - 3, - '3', + 'handler' => new IntegerHandler(), + 'type' => 'integer', + 'value' => 3, + 'invalid' => [1.1, '1'], + 'numericValue' => 3, + 'stringValue' => '3', + 'stringValueComplex' => '3', + 'isIdempotent' => true, ], 'model' => [ - new ModelHandler(), - 'model', - $model, - [new stdClass()], - null, - SampleMetable::class, + 'handler' => new ModelHandler(), + 'type' => 'model', + 'value' => $model, + 'invalid' => [new stdClass()], + 'numericValue' => null, + 'stringValue' => SampleMetable::class, + 'stringValueComplex' => SampleMetable::class, + 'isIdempotent' => true, ], 'model collection' => [ - new ModelCollectionHandler(), - 'collection', - new Collection([new SampleMetable()]), - [collect()], - null, - null, + 'handler' => new ModelCollectionHandler(), + 'type' => 'collection', + 'value' => new Collection([new SampleMetable()]), + 'invalid' => [collect()], + 'numericValue' => null, + 'stringValue' => null, + 'stringValueComplex' => null, + 'isIdempotent' => true, ], 'null' => [ - new NullHandler(), - 'null', - null, - [0, '', 'null', [], false], - null, - null, + 'handler' => new NullHandler(), + 'type' => 'null', + 'value' => null, + 'invalid' => [0, '', 'null', [], false], + 'numericValue' => null, + 'stringValue' => null, + 'stringValueComplex' => null, + 'isIdempotent' => true, ], 'object' => [ - new ObjectHandler(), - 'object', - $object, - [[]], - null, - null, + 'handler' => new ObjectHandler(), + 'type' => 'object', + 'value' => $object, + 'invalid' => [[]], + 'numericValue' => null, + 'stringValue' => null, + 'stringValueComplex' => json_encode($object), + 'isIdempotent' => true, ], 'serialize' => [ - new SerializeHandler(), - 'serialized', - ['foo' => 'bar', 'baz' => [3]], - [self::$resource], - null, - null, + 'handler' => new SerializeHandler(), + 'type' => 'serialized', + 'value' => ['foo' => 'bar', 'baz' => [3]], + 'invalid' => [self::$resource], + 'numericValue' => null, + 'stringValue' => null, + 'stringValueComplex' => serialize(['foo' => 'bar', 'baz' => [3]]), + 'isIdempotent' => false, ], 'serializable' => [ - new SerializableHandler(), - 'serializable', - new SampleSerializable(['foo' => 'bar']), - [], - null, - null, + 'handler' => new SerializableHandler(), + 'type' => 'serializable', + 'value' => new SampleSerializable(['foo' => 'bar']), + 'invalid' => [], + 'numericValue' => null, + 'stringValue' => null, + 'stringValueComplex' => serialize(new SampleSerializable(['foo' => 'bar'])), + 'isIdempotent' => true, ], 'string' => [ - new StringHandler(), - 'string', - 'foo', - [1, 1.1], - null, - 'foo', + 'handler' => new StringHandler(), + 'type' => 'string', + 'value' => 'foo', + 'invalid' => [1, 1.1], + 'numericValue' => null, + 'stringValue' => 'foo', + 'stringValueComplex' => 'foo', + 'isIdempotent' => true, + ], + 'long-string' => [ + 'handler' => new StringHandler(), + 'type' => 'string', + 'value' => str_repeat('a', 300), + 'invalid' => [1, 1.1], + 'numericValue' => null, + 'stringValue' => str_repeat('a', 255), + 'stringValueComplex' => str_repeat('a', 255), + 'isIdempotent' => true, ], 'numeric-string' => [ - new StringHandler(), - 'string', - '1.2345', - [1, 1.1], - 1.2345, - '1.2345', + 'handler' => new StringHandler(), + 'type' => 'string', + 'value' => '1.2345', + 'invalid' => [1, 1.1], + 'numericValue' => 1.2345, + 'stringValue' => '1.2345', + 'stringValueComplex' => '1.2345', + 'isIdempotent' => true, ], ]; } @@ -165,7 +201,9 @@ public function test_it_can_verify_and_serialize_data( mixed $value, array $incompatible, null|int|float $numericValue, - null|string $stringValue + null|string $stringValue, + null|string $stringValueComplex, + bool $isIdempotent ): void { $this->assertEquals($type, $handler->getDataType()); $this->assertTrue($handler->canHandleValue($value)); @@ -179,6 +217,11 @@ public function test_it_can_verify_and_serialize_data( $this->assertEquals($value, $unserialized); $this->assertEquals($numericValue, $handler->getNumericValue($value)); + config()->set('metable.indexComplexDataTypes', false); $this->assertEquals($stringValue, $handler->getStringValue($value)); + config()->set('metable.indexComplexDataTypes', true); + $this->assertEquals($stringValueComplex, $handler->getStringValue($value)); + + $this->assertEquals($isIdempotent, $handler->isIdempotent()); } } diff --git a/tests/Integration/DataType/ModelCollectionHandlerTest.php b/tests/Integration/DataType/ModelCollectionHandlerTest.php index bb2f869..8eaf1ca 100644 --- a/tests/Integration/DataType/ModelCollectionHandlerTest.php +++ b/tests/Integration/DataType/ModelCollectionHandlerTest.php @@ -32,11 +32,31 @@ public function test_it_reloads_model_instances(): void $this->assertEquals(1, $unserialized['foo']->getKey()); } - public function test_it_handles_invalid_model_class(): void + public function test_it_handles_invalid_collection_class(): void { + $this->useDatabase(); + $metable = SampleMetable::create(); $handler = new ModelCollectionHandler(); $serialized = json_encode([ 'class' => 'stdClass', + 'items' => [ + [ + 'class' => SampleMetable::class, + 'key' => $metable->getKey() + ] + ] + ]); + $unserialized = $handler->unserializeValue($serialized); + + $this->assertInstanceOf(Collection::class, $unserialized); + $this->assertEquals([$metable->getKey()], $unserialized->modelKeys()); + } + + public function test_it_handles_invalid_model_class(): void + { + $handler = new ModelCollectionHandler(); + $serialized = json_encode([ + 'class' => Collection::class, 'items' => [ 'class' => 'stdClass', 'key' => '1' @@ -45,6 +65,21 @@ public function test_it_handles_invalid_model_class(): void $unserialized = $handler->unserializeValue($serialized); $this->assertInstanceOf(Collection::class, $unserialized); - $this->assertEmpty($unserialized); + $this->assertCount(0, $unserialized); + } + + public function test_it_handles_invalid_model_class_no_key(): void + { + $handler = new ModelCollectionHandler(); + $serialized = json_encode([ + 'class' => Collection::class, + 'items' => [ + 'class' => 'stdClass', + ] + ]); + $unserialized = $handler->unserializeValue($serialized); + + $this->assertInstanceOf(Collection::class, $unserialized); + $this->assertCount(0, $unserialized); } } diff --git a/tests/Integration/MetableTest.php b/tests/Integration/MetableTest.php index e450d1d..4509c52 100644 --- a/tests/Integration/MetableTest.php +++ b/tests/Integration/MetableTest.php @@ -353,14 +353,17 @@ public function test_it_can_be_queried_by_meta_value(): void $metable = $this->createMetable(); $metable->setMeta('foo', 'bar'); $metable->setMeta('datetime', $now); + $metable->setMeta('long', str_repeat('a', 300)); $result1 = SampleMetable::whereMeta('foo', 'bar')->first(); $result2 = SampleMetable::whereMeta('foo', 'baz')->first(); $result3 = SampleMetable::whereMeta('datetime', $now)->first(); + $result4 = SampleMetable::whereMeta('long', str_repeat('a', 300))->first(); $this->assertEquals($metable->getKey(), $result1->getKey()); $this->assertNull($result2); $this->assertEquals($metable->getKey(), $result3->getKey()); + $this->assertEquals($metable->getKey(), $result4->getKey()); } public function test_it_can_be_queried_by_numeric_meta_value(): void @@ -371,9 +374,11 @@ public function test_it_can_be_queried_by_numeric_meta_value(): void $result = SampleMetable::whereMetaNumeric('foo', '>', 4)->get(); $result2 = SampleMetable::whereMetaNumeric('foo', '<', 4)->get(); + $result3 = SampleMetable::whereMetaNumeric('foo', 123)->get(); $this->assertEquals([$metable->getKey()], $result->modelKeys()); $this->assertEquals([], $result2->modelKeys()); + $this->assertEquals([$metable->getKey()], $result3->modelKeys()); } public function test_it_can_be_queried_by_in_array(): void @@ -450,6 +455,27 @@ public function test_it_can_be_queried_by_meta_between(): void $this->assertEquals([], $result2->modelKeys()); } + public function test_it_can_be_queried_by_meta_not_between(): void + { + $this->useDatabase(); + $metable = $this->createMetable(); + $metable->setMeta('foo', 'c'); + + $result1 = SampleMetable::whereMetaNotBetween( + 'foo', + 'a', + 'd' + )->get(); + $result2 = SampleMetable::whereMetaNotBetween( + 'foo', + 'd', + 'z' + )->get(); + + $this->assertEquals([], $result1->modelKeys()); + $this->assertEquals([$metable->getKey()], $result2->modelKeys()); + } + public function test_it_can_be_queried_by_meta_between_numeric(): void { $this->useDatabase(); @@ -665,6 +691,18 @@ public function test_it_can_serialize_properly(): void $this->assertEquals('baz', $result->getMeta('foo')); } + public function test_it_throws_for_param_that_cannot_be_converted_to_string(): void + { + $this->expectException(\LogicException::class); + SampleMetable::whereMeta('foo', null)->get(); + } + + public function test_it_throws_for_param_that_cannot_be_converted_to_numeric(): void + { + $this->expectException(\LogicException::class); + SampleMetable::whereMetaNumeric('foo', null)->get(); + } + private function makeMeta(array $attributes = []): Meta { return factory(Meta::class)->make($attributes);