Skip to content

Commit

Permalink
Use Entity for NoSQLDocument
Browse files Browse the repository at this point in the history
  • Loading branch information
byjg committed Apr 5, 2024
1 parent 81f9a25 commit 7ab917d
Show file tree
Hide file tree
Showing 8 changed files with 244 additions and 19 deletions.
5 changes: 5 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
"ByJG\\AnyDataset\\NoSql\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"prefer-stable": true,
"minimum-stability": "dev",
"require": {
Expand Down
14 changes: 14 additions & 0 deletions docs/MongoDB.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,19 @@ foreach ($result as $document)
}
```


### Full Connection String

```text
mongodb://username:password@server:27017/dbname?uri.option1=value1&driver.option2=value2
```

The list of parameters can be found in the [PHP MongoDB Driver documentation](https://www.php.net/manual/en/mongodb-driver-manager.construct.php).

Parameters started with `uri.` are passed to the MongoDB URI connection string.
Parameters started with `driver.` are passed to the MongoDB driver connection string.
Any other parameters will throw an exception.


----
[Open source ByJG](http://opensource.byjg.com)
19 changes: 16 additions & 3 deletions src/MongoDbDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class MongoDbDriver implements NoSqlInterface, RegistrableInterface

protected $database;

protected $idField;

/**
* Creates a new MongoDB connection.
*
Expand Down Expand Up @@ -69,6 +71,17 @@ public function __construct(Uri $connUri)
$username = $this->connectionUri->getUsername();
$password = $this->connectionUri->getPassword();
parse_str($this->connectionUri->getQuery(), $options);
$uriOptions = [];
$driverOptions = [];
foreach ($options as $key => $value) {
if (strpos($key, 'uri.') === 0) {
$options[$key] = $value;
} elseif (strpos($key, 'driver.') === 0) {
$driverOptions[$key] = $value;
} else {
throw new InvalidArgumentException("Invalid option '$key'. Need start with 'uri.' or 'driver.'. ");
}
}

if (!empty($username) && !empty($password)) {
$auth = "$username:$password@";
Expand All @@ -77,7 +90,7 @@ public function __construct(Uri $connUri)
}

$connectString = sprintf('mongodb://%s%s:%d', $auth, $hosts, $port);
$this->mongoManager = new Manager($connectString, $options);
$this->mongoManager = new Manager($connectString, $uriOptions, $driverOptions);
$this->database = $database;
}

Expand Down Expand Up @@ -252,10 +265,10 @@ public function save(NoSqlDocument $document)
$idDocument = $data['_id'] ?? null;
}

$data['updated'] = new UTCDateTime((new DateTime())->getTimestamp()*1000);
$data['updatedAt'] = new UTCDateTime((new DateTime())->getTimestamp()*1000);
if (empty($idDocument)) {
$data['_id'] = $idDocument = new ObjectID();
$data['created'] = new UTCDateTime((new DateTime())->getTimestamp()*1000);
$data['createdAt'] = new UTCDateTime((new DateTime())->getTimestamp()*1000);
$bulkWrite->insert($data);
} else {
$data['_id'] = $idDocument;
Expand Down
15 changes: 12 additions & 3 deletions src/NoSqlDocument.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace ByJG\AnyDataset\NoSql;

use ByJG\Serializer\BinderObject;

class NoSqlDocument
{
protected $idDocument;
Expand Down Expand Up @@ -66,11 +68,18 @@ public function setCollection($collection)


/**
* @return array
* @return array|object
*/
public function getDocument()
public function getDocument($entityClass = null)
{
return $this->document;
if (is_null($entityClass)) {
return $this->document;
}

$entity = new $entityClass();
BinderObject::bind($this->document, $entity);

return $entity;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions tests/AwsDynamoDbDriverTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

namespace Tests;

use Aws\DynamoDb\Exception\DynamoDbException;
use ByJG\AnyDataset\NoSql\AwsDynamoDbDriver;
use ByJG\AnyDataset\NoSql\Factory;
Expand Down
2 changes: 2 additions & 0 deletions tests/AwsS3DriverTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

namespace Tests;

use ByJG\AnyDataset\NoSql\AwsS3Driver;
use ByJG\AnyDataset\NoSql\Factory;
use ByJG\Util\Uri;
Expand Down
121 changes: 121 additions & 0 deletions tests/Document.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

namespace Tests;

class Document
{
protected ?string $_id;
protected ?string $name;

protected ?string $brand;

protected ?int $price;

protected mixed $createdAt;

protected mixed $updatedAt;

public function __construct(?string $name = null, ?string $brand = null, ?int $price = null)
{
$this->name = $name;
$this->brand = $brand;
$this->price = $price;
}

/**
* @return string|null
*/
public function get_id(): ?string
{
return $this->_id;
}

/**
* @param string|null $_id
*/
public function set_id(?string $_id): void
{
$this->_id = $_id;
}

/**
* @return string|null
*/
public function getName(): ?string
{
return $this->name;
}

/**
* @param string|null $name
*/
public function setName(?string $name): void
{
$this->name = $name;
}

/**
* @return string|null
*/
public function getBrand(): ?string
{
return $this->brand;
}

/**
* @param string|null $brand
*/
public function setBrand(?string $brand): void
{
$this->brand = $brand;
}

/**
* @return int|null
*/
public function getPrice(): ?int
{
return $this->price;
}

/**
* @param int|null $price
*/
public function setPrice(?int $price): void
{
$this->price = $price;
}

/**
* @return mixed|null
*/
public function getCreatedAt(): mixed
{
return $this->createdAt;
}

/**
* @param mixed|null $createdAt
*/
public function setCreatedAt(mixed $createdAt): void
{
$this->createdAt = $createdAt;
}

/**
* @return mixed|null
*/
public function getUpdatedAt(): mixed
{
return $this->updatedAt;
}

/**
* @param mixed|null $updatedAt
*/
public function setUpdatedAt(mixed $updatedAt): void
{
$this->updatedAt = $updatedAt;
}

}
85 changes: 72 additions & 13 deletions tests/MongoDbDriverTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

namespace Tests;

use ByJG\AnyDataset\Core\Enum\Relation;
use ByJG\AnyDataset\Core\IteratorFilter;
use ByJG\AnyDataset\NoSql\Factory;
Expand Down Expand Up @@ -30,7 +32,7 @@ public function setUp(): void
new NoSqlDocument(
null,
self::TEST_COLLECTION,
['name' => 'Hilux', 'brand' => 'Toyota', 'price' => 120000]
new Document('Hilux', 'Toyota', 120000)
)
);
$this->dbDriver->save(
Expand Down Expand Up @@ -74,7 +76,6 @@ public function tearDown(): void
{
if (!empty($this->dbDriver)) {
$filter = new IteratorFilter();
$filter->addRelation('brand', Relation::NOT_EQUAL, 'Toyota');
$this->dbDriver->deleteDocuments($filter, self::TEST_COLLECTION);
}
}
Expand All @@ -99,12 +100,12 @@ public function testSaveDocument()
// Check if the default fields are here
$data = $document[0]->getDocument();
$this->assertNotEmpty($data['_id']);
$this->assertNotEmpty($data['created']);
$this->assertNotEmpty($data['updated']);
$this->assertEquals($data['created']->toDatetime(), $data['updated']->toDatetime());
$this->assertNotEmpty($data['createdAt']);
$this->assertNotEmpty($data['updatedAt']);
$this->assertEquals($data['createdAt']->toDatetime(), $data['updatedAt']->toDatetime());
unset($data['_id']);
unset($data['created']);
unset($data['updated']);
unset($data['createdAt']);
unset($data['updatedAt']);

// Check if the context is the expected
$this->assertEquals(
Expand All @@ -124,22 +125,80 @@ public function testSaveDocument()
// Get the saved document
$documentFromDb = $this->dbDriver->getDocumentById($document[0]->getIdDocument(), self::TEST_COLLECTION);

// Check if the document have the same ID (Update) and Have the updated data
// Check if the document have the same ID (Update) and Have the updatedAt data
$data = $documentFromDb->getDocument();
$this->assertEquals($documentSaved->getIdDocument(), $document[0]->getIdDocument());
$this->assertEquals($data['_id'], $document[0]->getIdDocument());
$this->assertNotEmpty($data['created']);
$this->assertNotEmpty($data['updated']);
$this->assertNotEquals($data['created']->toDatetime(), $data['updated']->toDatetime());
$this->assertNotEmpty($data['createdAt']);
$this->assertNotEmpty($data['updatedAt']);
$this->assertNotEquals($data['createdAt']->toDatetime(), $data['updatedAt']->toDatetime());
unset($data['_id']);
unset($data['created']);
unset($data['updated']);
unset($data['createdAt']);
unset($data['updatedAt']);
$this->assertEquals(
['name' => 'Hilux', 'brand' => 'Toyota', 'price' => 150000],
$data
);
}

/**
* @throws \MongoDB\Driver\Exception\Exception
*/
public function testSaveDocumentEntity()
{
if (empty($this->dbDriver)) {
$this->markTestIncomplete("In order to test MongoDB you must define MONGODB_CONNECTION");
}

// Get the Object to test
$filter = new IteratorFilter();
$filter->addRelation('name', Relation::EQUAL, 'Hilux');
$document = $this->dbDriver->getDocuments($filter, self::TEST_COLLECTION);

// Check if returns one document
$this->assertCount(1, $document);

// Check if the default fields are here
$entity = $document[0]->getDocument(Document::class);
$this->assertInstanceOf(Document::class, $entity);
$this->assertNotEmpty($entity->get_id());
$this->assertNotEmpty($entity->getCreatedAt());
$this->assertNotEmpty($entity->getUpdatedAt());
$this->assertEquals($entity->getCreatedAt()->toDatetime(), $entity->getCreatedAt()->toDatetime());

// Check if the context is the expected
$this->assertEquals(
['Hilux', 'Toyota', 120000],
[$entity->getName(), $entity->getBrand(), $entity->getPrice()]
);

$entity->setPrice(150000);

// Create a new document with a partial field to update
$documentToUpdate = new NoSqlDocument(
$document[0]->getIdDocument(),
self::TEST_COLLECTION,
$entity
);
sleep(1); // Just to force a new Update DateTime
$documentSaved = $this->dbDriver->save($documentToUpdate);

// Get the saved document
$documentFromDb = $this->dbDriver->getDocumentById($document[0]->getIdDocument(), self::TEST_COLLECTION);

// Check if the document have the same ID (Update) and Have the updatedAt data
$updEntity = $documentFromDb->getDocument(Document::class);
$this->assertEquals($documentSaved->getIdDocument(), $document[0]->getIdDocument());
$this->assertEquals($updEntity->get_id(), $document[0]->getIdDocument());
$this->assertNotEmpty($updEntity->getCreatedAt());
$this->assertNotEmpty($updEntity->getUpdatedAt());
$this->assertEquals($updEntity->getCreatedAt()->toDatetime(), $updEntity->getCreatedAt()->toDatetime());
$this->assertEquals(
['Hilux', 'Toyota', 150000],
[$updEntity->getName(), $updEntity->getBrand(), $updEntity->getPrice()]
);
}

/**
* @throws \MongoDB\Driver\Exception\Exception
*/
Expand Down

0 comments on commit 7ab917d

Please sign in to comment.