Skip to content
This repository has been archived by the owner on Aug 22, 2023. It is now read-only.

Commit

Permalink
Attempt to remove automatic conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
alcaeus committed Aug 16, 2023
1 parent 9f1f8f3 commit 4790125
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 100 deletions.
5 changes: 5 additions & 0 deletions src/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,9 @@ protected function ensureOrderForCursorPagination($shouldReverse = false)
];
})->values();
}

public function whereKey($id)
{
return parent::whereKey($this->model->convertKey($id));
}
}
6 changes: 2 additions & 4 deletions src/Eloquent/Casts/ObjectId.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ public function get($model, string $key, $value, array $attributes)
*/
public function set($model, string $key, $value, array $attributes)
{
if ($value instanceof BSONObjectId) {
return $value;
}
$value = $value instanceof BSONObjectId ? $value : new BSONObjectId($value);

return new BSONObjectId($value);
return [$key => $value];
}
}
74 changes: 20 additions & 54 deletions src/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
use Illuminate\Support\Str;
use function in_array;
use Jenssegers\Mongodb\Query\Builder as QueryBuilder;
use MongoDB\BSON\Binary;
use MongoDB\BSON\ObjectID;
use MongoDB\BSON\UTCDateTime;
use function uniqid;

Expand Down Expand Up @@ -52,30 +50,6 @@ abstract class Model extends BaseModel
*/
protected $parentRelation;

/**
* Custom accessor for the model's id.
*
* @param mixed $value
* @return mixed
*/
public function getIdAttribute($value = null)
{
// If we don't have a value for 'id', we will use the MongoDB '_id' value.
// This allows us to work with models in a more sql-like way.
if (! $value && array_key_exists('_id', $this->attributes)) {
$value = $this->attributes['_id'];
}

// Convert ObjectID to string.
if ($value instanceof ObjectID) {
return (string) $value;
} elseif ($value instanceof Binary) {
return (string) $value->getData();
}

return $value;
}

/**
* @inheritdoc
*/
Expand Down Expand Up @@ -190,12 +164,7 @@ protected function getAttributeFromArray($key)
public function setAttribute($key, $value)
{
// Convert _id to ObjectID.
if ($key == '_id' && is_string($value)) {
$builder = $this->newBaseQueryBuilder();

$value = $builder->convertKey($value);
} // Support keys in dot notation.
elseif (Str::contains($key, '.')) {
if (Str::contains($key, '.')) {
// Store to a temporary key, then move data to the actual key
$uniqueKey = uniqid($key);
parent::setAttribute($uniqueKey, $value);
Expand All @@ -209,28 +178,6 @@ public function setAttribute($key, $value)
return parent::setAttribute($key, $value);
}

/**
* @inheritdoc
*/
public function attributesToArray()
{
$attributes = parent::attributesToArray();

// Because the original Eloquent never returns objects, we convert
// MongoDB related objects to a string representation. This kind
// of mimics the SQL behaviour so that dates are formatted
// nicely when your models are converted to JSON.
foreach ($attributes as $key => &$value) {
if ($value instanceof ObjectID) {
$value = (string) $value;
} elseif ($value instanceof Binary) {
$value = (string) $value->getData();
}
}

return $attributes;
}

/**
* @inheritdoc
*/
Expand Down Expand Up @@ -568,4 +515,23 @@ protected function addCastAttributesToArray(array $attributes, array $mutatedAtt

return $attributes;
}

/** @internal */
public function convertKey($value)
{
if (! $this->hasCast($this->primaryKey)) {
return $value;
}

return $this->castAttribute($this->primaryKey, $value);
}

protected function getClassCastableAttributeValue($key, $value)
{
// The class cast cache does not play nice with database values that
// already are objects, so we need to manually unset it
unset($this->classCastCache[$key]);

return parent::getClassCastableAttributeValue($key, $value);
}
}
34 changes: 1 addition & 33 deletions src/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ public function hint($index)
*/
public function find($id, $columns = [])
{
return $this->where('_id', '=', $this->convertKey($id))->first($columns);
return parent::find($id, $columns);
}

/**
Expand Down Expand Up @@ -884,25 +884,6 @@ protected function performUpdate($query, array $options = [])
return 0;
}

/**
* Convert a key to ObjectID if needed.
*
* @param mixed $id
* @return mixed
*/
public function convertKey($id)
{
if (is_string($id) && strlen($id) === 24 && ctype_xdigit($id)) {
return new ObjectID($id);
}

if (is_string($id) && strlen($id) === 16 && preg_match('~[^\x20-\x7E\t\r\n]~', $id) > 0) {
return new Binary($id, Binary::TYPE_UUID);
}

return $id;
}

/**
* @inheritdoc
*/
Expand Down Expand Up @@ -950,19 +931,6 @@ protected function compileWheres(): array
}
}

// Convert id's.
if (isset($where['column']) && ($where['column'] == '_id' || Str::endsWith($where['column'], '._id'))) {
// Multiple values.
if (isset($where['values'])) {
foreach ($where['values'] as &$value) {
$value = $this->convertKey($value);
}
} // Single value.
elseif (isset($where['value'])) {
$where['value'] = $this->convertKey($where['value']);
}
}

// Convert DateTime values to UTCDateTime.
if (isset($where['value'])) {
if (is_array($where['value'])) {
Expand Down
3 changes: 1 addition & 2 deletions src/Relations/EmbedsOneOrMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,7 @@ protected function getForeignKeyValue($id)
$id = $id->getKey();
}

// Convert the id to MongoId if necessary.
return $this->toBase()->convertKey($id);
return $id;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions tests/EmbeddedRelationsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public function testEmbedsManySave()
$this->assertInstanceOf(DateTime::class, $address->created_at);
$this->assertInstanceOf(DateTime::class, $address->updated_at);
$this->assertNotNull($address->_id);
$this->assertIsString($address->_id);
$this->assertInstanceOf(ObjectId::class, $address->_id);

$raw = $address->getAttributes();
$this->assertInstanceOf(ObjectId::class, $raw['_id']);
Expand Down Expand Up @@ -183,7 +183,7 @@ public function testEmbedsManyCreate()
$user = User::create([]);
$address = $user->addresses()->create(['city' => 'Bruxelles']);
$this->assertInstanceOf(Address::class, $address);
$this->assertIsString($address->_id);
$this->assertInstanceOf(ObjectId::class, $address->_id);
$this->assertEquals(['Bruxelles'], $user->addresses->pluck('city')->all());

$raw = $address->getAttributes();
Expand Down
13 changes: 8 additions & 5 deletions tests/ModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public function testUpdate(): void

/** @var User $check */
$check = User::find($user->_id);
$this->assertInstanceOf(User::class, $check);
$check->age = 36;
$check->save();

Expand Down Expand Up @@ -395,22 +396,24 @@ public static function provideId(): iterable
yield 'ObjectID' => [
'model' => User::class,
'id' => $objectId,
'expected' => (string) $objectId,
'expectedFound' => true,
'expected' => $objectId,
// Not found as the keyType is "string"
'expectedFound' => false,
];

$binaryUuid = new Binary(hex2bin('0c103357380648c9a84b867dcb625cfb'), Binary::TYPE_UUID);
yield 'BinaryUuid' => [
'model' => User::class,
'id' => $binaryUuid,
'expected' => (string) $binaryUuid,
'expectedFound' => true,
'expected' => $binaryUuid,
// Not found as the keyType is "string"
'expectedFound' => false,
];

yield 'cast as BinaryUuid' => [
'model' => IdIsBinaryUuid::class,
'id' => $binaryUuid,
'expected' => (string) $binaryUuid,
'expected' => $binaryUuid,
'expectedFound' => true,
];

Expand Down
7 changes: 7 additions & 0 deletions tests/Models/Address.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@

namespace Jenssegers\Mongodb\Tests\Models;

use Jenssegers\Mongodb\Eloquent\Casts\ObjectId as ObjectIdCast;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
use Jenssegers\Mongodb\Relations\EmbedsMany;
use MongoDB\BSON\ObjectId;

class Address extends Eloquent
{
protected $connection = 'mongodb';
protected static $unguarded = true;
protected $keyType = ObjectId::class;

protected $casts = [
'_id' => ObjectIdCast::class,
];

public function addresses(): EmbedsMany
{
Expand Down
2 changes: 2 additions & 0 deletions tests/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Str;
use Jenssegers\Mongodb\Eloquent\Casts\ObjectId as ObjectIdCast;
use Jenssegers\Mongodb\Eloquent\HybridRelations;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

Expand All @@ -38,6 +39,7 @@ class User extends Eloquent implements AuthenticatableContract, CanResetPassword

protected $connection = 'mongodb';
protected $casts = [
'_id' => ObjectIdCast::class,
'birthday' => 'datetime',
'entry.date' => 'datetime',
'member_status' => MemberStatus::class,
Expand Down

0 comments on commit 4790125

Please sign in to comment.