Skip to content

Commit 5105553

Browse files
committed
Add classes to cast ObjectId and UUID instances (#1)
1 parent 4a10b4c commit 5105553

File tree

6 files changed

+241
-0
lines changed

6 files changed

+241
-0
lines changed

src/Eloquent/Casts/BinaryUuid.php

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace Jenssegers\Mongodb\Eloquent\Casts;
4+
5+
use function bin2hex;
6+
use function hex2bin;
7+
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
8+
use Jenssegers\Mongodb\Eloquent\Model;
9+
use MongoDB\BSON\Binary;
10+
use function str_replace;
11+
use function substr;
12+
13+
class BinaryUuid implements CastsAttributes
14+
{
15+
/**
16+
* Cast the given value.
17+
*
18+
* @param Model $model
19+
* @param string $key
20+
* @param mixed $value
21+
* @param array $attributes
22+
* @return mixed
23+
*/
24+
public function get($model, string $key, $value, array $attributes)
25+
{
26+
if (! $value instanceof Binary || $value->getType() !== Binary::TYPE_UUID) {
27+
return $value;
28+
}
29+
30+
$base16Uuid = bin2hex($value->getData());
31+
32+
return sprintf(
33+
'%s-%s-%s-%s-%s',
34+
substr($base16Uuid, 0, 8),
35+
substr($base16Uuid, 8, 4),
36+
substr($base16Uuid, 12, 4),
37+
substr($base16Uuid, 16, 4),
38+
substr($base16Uuid, 20, 12),
39+
);
40+
}
41+
42+
/**
43+
* Prepare the given value for storage.
44+
*
45+
* @param Model $model
46+
* @param string $key
47+
* @param mixed $value
48+
* @param array $attributes
49+
* @return mixed
50+
*/
51+
public function set($model, string $key, $value, array $attributes)
52+
{
53+
if ($value instanceof Binary) {
54+
return $value;
55+
}
56+
57+
if (is_string($value) && strlen($value) === 16) {
58+
return new Binary($value, Binary::TYPE_UUID);
59+
}
60+
61+
return new Binary(hex2bin(str_replace('-', '', $value)), Binary::TYPE_UUID);
62+
}
63+
}

src/Eloquent/Casts/ObjectId.php

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace Jenssegers\Mongodb\Eloquent\Casts;
4+
5+
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
6+
use Jenssegers\Mongodb\Eloquent\Model;
7+
use MongoDB\BSON\ObjectId as BSONObjectId;
8+
9+
class ObjectId implements CastsAttributes
10+
{
11+
/**
12+
* Cast the given value.
13+
*
14+
* @param Model $model
15+
* @param string $key
16+
* @param mixed $value
17+
* @param array $attributes
18+
* @return mixed
19+
*/
20+
public function get($model, string $key, $value, array $attributes)
21+
{
22+
if (! $value instanceof BSONObjectId) {
23+
return $value;
24+
}
25+
26+
return (string) $value;
27+
}
28+
29+
/**
30+
* Prepare the given value for storage.
31+
*
32+
* @param Model $model
33+
* @param string $key
34+
* @param mixed $value
35+
* @param array $attributes
36+
* @return mixed
37+
*/
38+
public function set($model, string $key, $value, array $attributes)
39+
{
40+
if ($value instanceof BSONObjectId) {
41+
return $value;
42+
}
43+
44+
return new BSONObjectId($value);
45+
}
46+
}

tests/Casts/BinaryUuidTest.php

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace Jenssegers\Mongodb\Tests\Casts;
4+
5+
use Generator;
6+
use function hex2bin;
7+
use Jenssegers\Mongodb\Tests\Models\CastBinaryUuid;
8+
use Jenssegers\Mongodb\Tests\TestCase;
9+
use MongoDB\BSON\Binary;
10+
11+
class BinaryUuidTest extends TestCase
12+
{
13+
protected function setUp(): void
14+
{
15+
parent::setUp();
16+
17+
CastBinaryUuid::truncate();
18+
}
19+
20+
/** @dataProvider provideBinaryUuidCast */
21+
public function testBinaryUuidCastModel(string $expectedUuid, string|Binary $saveUuid, Binary $queryUuid): void
22+
{
23+
CastBinaryUuid::create(['uuid' => $saveUuid]);
24+
25+
$model = CastBinaryUuid::firstWhere('uuid', $queryUuid);
26+
$this->assertNotNull($model);
27+
$this->assertSame($expectedUuid, $model->uuid);
28+
}
29+
30+
public static function provideBinaryUuidCast(): Generator
31+
{
32+
$uuid = '0c103357-3806-48c9-a84b-867dcb625cfb';
33+
$binaryUuid = new Binary(hex2bin('0c103357380648c9a84b867dcb625cfb'), Binary::TYPE_UUID);
34+
35+
yield 'Save Binary, Query Binary' => [$uuid, $binaryUuid, $binaryUuid];
36+
yield 'Save string, Query Binary' => [$uuid, $uuid, $binaryUuid];
37+
}
38+
39+
public function testQueryByStringDoesNotCast(): void
40+
{
41+
$uuid = '0c103357-3806-48c9-a84b-867dcb625cfb';
42+
43+
CastBinaryUuid::create(['uuid' => $uuid]);
44+
45+
$model = CastBinaryUuid::firstWhere('uuid', $uuid);
46+
$this->assertNull($model);
47+
}
48+
}

tests/Casts/ObjectIdTest.php

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace Jenssegers\Mongodb\Tests\Casts;
4+
5+
use Generator;
6+
use Jenssegers\Mongodb\Tests\Models\CastObjectId;
7+
use Jenssegers\Mongodb\Tests\TestCase;
8+
use MongoDB\BSON\ObjectId;
9+
10+
class ObjectIdTest extends TestCase
11+
{
12+
protected function setUp(): void
13+
{
14+
parent::setUp();
15+
16+
CastObjectId::truncate();
17+
}
18+
19+
/** @dataProvider provideObjectIdCast */
20+
public function testStoreObjectId(string|ObjectId $saveObjectId, ObjectId $queryObjectId): void
21+
{
22+
$stringObjectId = (string) $saveObjectId;
23+
24+
CastObjectId::create(['oid' => $saveObjectId]);
25+
26+
$model = CastObjectId::firstWhere('oid', $queryObjectId);
27+
$this->assertNotNull($model);
28+
$this->assertSame($stringObjectId, $model->oid);
29+
}
30+
31+
public static function provideObjectIdCast(): Generator
32+
{
33+
$objectId = new ObjectId();
34+
$stringObjectId = (string) $objectId;
35+
36+
yield 'Save ObjectId, Query ObjectId' => [$objectId, $objectId];
37+
yield 'Save string, Query ObjectId' => [$stringObjectId, $objectId];
38+
}
39+
40+
public function testQueryByStringDoesNotCast(): void
41+
{
42+
$objectId = new ObjectId();
43+
$stringObjectId = (string) $objectId;
44+
45+
CastObjectId::create(['oid' => $objectId]);
46+
47+
$model = CastObjectId::firstWhere('oid', $stringObjectId);
48+
$this->assertNull($model);
49+
}
50+
}

tests/Models/CastBinaryUuid.php

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Jenssegers\Mongodb\Tests\Models;
6+
7+
use Jenssegers\Mongodb\Eloquent\Casts\BinaryUuid;
8+
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
9+
10+
class CastBinaryUuid extends Eloquent
11+
{
12+
protected $connection = 'mongodb';
13+
protected static $unguarded = true;
14+
protected $casts = [
15+
'uuid' => BinaryUuid::class,
16+
];
17+
}

tests/Models/CastObjectId.php

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Jenssegers\Mongodb\Tests\Models;
6+
7+
use Jenssegers\Mongodb\Eloquent\Casts\ObjectId;
8+
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
9+
10+
class CastObjectId extends Eloquent
11+
{
12+
protected $connection = 'mongodb';
13+
protected static $unguarded = true;
14+
protected $casts = [
15+
'oid' => ObjectId::class,
16+
];
17+
}

0 commit comments

Comments
 (0)