Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/change annotations in data mapper folder #240

Merged
merged 2 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 43 additions & 71 deletions src/DataMapper/DataMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Mongolid\Connection\Connection;
use Mongolid\Container\Container;
use Mongolid\Cursor\CursorInterface;
use Mongolid\Cursor\EagerLoadedCursor;
use Mongolid\Cursor\SchemaCacheableCursor;
use Mongolid\Cursor\SchemaCursor;
use Mongolid\Event\EventTriggerService;
Expand All @@ -20,7 +19,7 @@
/**
* The DataMapper class will abstract how an Entity is persisted and retrieved
* from the database.
* The DataMapper will always use a Schema trough the SchemaMapper to parse the
* The DataMapper will always use a Schema through the SchemaMapper to parse the
* document in and out of the database.
*/
class DataMapper implements HasSchemaInterface
Expand All @@ -29,47 +28,35 @@ class DataMapper implements HasSchemaInterface

/**
* Name of the schema class to be used.
*
* @var string
*/
public $schemaClass = Schema::class;
public string $schemaClass = Schema::class;

/**
* Schema object. Will be set after the $schemaClass.
*
* @var Schema
*/
protected $schema;

/**
* Connections that are going to be used to interact with the database.
*
* @var Connection
*/
protected $connection;
protected ?Schema $schema = null;

/**
* Have the responsibility of assembling the data coming from the database into actual entities.
*
* @var EntityAssembler
*/
protected $assembler;
protected ?EntityAssembler $assembler = null;

/**
* In order to dispatch events when necessary.
*
* @var EventTriggerService
*/
protected $eventService;
protected ?EventTriggerService $eventService = null;

/**
* @var array
* @var array<string,null>
*/
private $pullNullValues = [];
private array $pullNullValues = [];

public function __construct(Connection $connection)
{
$this->connection = $connection;
public function __construct(
/**
* Connections that are going to be used to interact with the database.
*/
protected Connection $connection
) {
}

/**
Expand All @@ -83,7 +70,7 @@ public function __construct(Connection $connection)
*
* @return bool Success (but always false if write concern is Unacknowledged)
*/
public function save($entity, array $options = [])
public function save(ModelInterface $entity, array $options = []): bool
{
// If the "saving" event returns false we'll bail out of the save and return
// false, indicating that the save failed. This gives an opportunities to
Expand Down Expand Up @@ -125,7 +112,7 @@ public function save($entity, array $options = [])
*
* @return bool Success (but always false if write concern is Unacknowledged)
*/
public function insert($entity, array $options = [], bool $fireEvents = true): bool
public function insert(mixed $entity, array $options = [], bool $fireEvents = true): bool
{
if ($fireEvents && false === $this->fireEvent('inserting', $entity, true)) {
return false;
Expand Down Expand Up @@ -163,7 +150,7 @@ public function insert($entity, array $options = [], bool $fireEvents = true): b
*
* @return bool Success (but always false if write concern is Unacknowledged)
*/
public function update($entity, array $options = []): bool
public function update(mixed $entity, array $options = []): bool
{
if (false === $this->fireEvent('updating', $entity, true)) {
return false;
Expand Down Expand Up @@ -220,7 +207,7 @@ public function update($entity, array $options = []): bool
*
* @return bool Success (but always false if write concern is Unacknowledged)
*/
public function delete($entity, array $options = []): bool
public function delete(mixed $entity, array $options = []): bool
{
if (false === $this->fireEvent('deleting', $entity, true)) {
return false;
Expand Down Expand Up @@ -253,7 +240,7 @@ public function delete($entity, array $options = []): bool
* @param bool $cacheable retrieves a SchemaCacheableCursor instead
*/
public function where(
$query = [],
mixed $query = [],
array $projection = [],
bool $cacheable = false
): CursorInterface {
Expand Down Expand Up @@ -301,10 +288,10 @@ public function all(): CursorInterface
* @return mixed First document matching query as an $this->schema->entityClass object
*/
public function first(
$query = [],
mixed $query = [],
array $projection = [],
bool $cacheable = false
) {
): mixed {
if ($cacheable) {
return $this->where($query, $projection, true)->first();
}
Expand All @@ -322,12 +309,10 @@ public function first(
);

if (!$document) {
return;
return null;
}

$model = $this->getAssembler()->assemble($document, $this->schema);

return $model;
return $this->getAssembler()->assemble($document, $this->schema);
}

/**
Expand All @@ -343,10 +328,10 @@ public function first(
* @return mixed First document matching query as an $this->schema->entityClass object
*/
public function firstOrFail(
$query = [],
mixed $query = [],
array $projection = [],
bool $cacheable = false
) {
): mixed {
if ($result = $this->first($query, $projection, $cacheable)) {
return $result;
}
Expand All @@ -368,7 +353,7 @@ public function withoutSoftDelete(): self
*
* @return array Document
*/
protected function parseToDocument($entity)
protected function parseToDocument(mixed $entity): array
{
$schemaMapper = $this->getSchemaMapper();
$parsedDocument = $schemaMapper->map($entity);
Expand All @@ -384,10 +369,8 @@ protected function parseToDocument($entity)

/**
* Returns a SchemaMapper with the $schema or $schemaClass instance.
*
* @return SchemaMapper
*/
protected function getSchemaMapper()
protected function getSchemaMapper(): SchemaMapper
{
if (!$this->schema) {
$this->schema = Container::make($this->schemaClass);
Expand All @@ -407,20 +390,16 @@ public function getCollection(): Collection
'typeMap' => ['array' => 'array', 'document' => 'array']
];

$collection = $this->connection
return $this->connection
->getClient()
->selectDatabase($database, $options)
->selectCollection($collectionName);

return $collection;
}

/**
* Retrieves an EntityAssembler instance.
*
* @return EntityAssembler
*/
protected function getAssembler()
protected function getAssembler(): EntityAssembler
{
if (!$this->assembler) {
$this->assembler = Container::make(EntityAssembler::class);
Expand All @@ -438,11 +417,13 @@ protected function getAssembler()
*
* @return mixed event handler return
*/
protected function fireEvent(string $event, $entity, bool $halt = false)
protected function fireEvent(string $event, mixed $entity, bool $halt = false): mixed
{
$event = "mongolid.{$event}: ".get_class($entity);
$event = "mongolid.{$event}: ".$entity::class;

$this->eventService ? $this->eventService : $this->eventService = Container::make(EventTriggerService::class);
if (!$this->eventService) {
$this->eventService = Container::make(EventTriggerService::class);
}

return $this->eventService->fire($event, $entity, $halt);
}
Expand All @@ -468,9 +449,9 @@ protected function fireEvent(string $event, $entity, bool $halt = false)
*
* @throws InvalidArgumentException if the given $fields are not a valid projection
*
* @return array
* @return array<string, bool>
*/
protected function prepareProjection(array $fields)
protected function prepareProjection(array $fields): array
{
$projection = [];
foreach ($fields as $key => $value) {
Expand All @@ -489,7 +470,7 @@ protected function prepareProjection(array $fields)

if (is_int($key) && is_string($value)) {
$key = $value;
if (0 === strpos($value, '-')) {
if (str_starts_with($value, '-')) {
$key = substr($key, 1);
$value = false;
} else {
Expand Down Expand Up @@ -518,20 +499,16 @@ protected function prepareProjection(array $fields)
*
* @param array $defaultOptions default options array
* @param array $toMergeOptions to merge options array
*
* @return array
*/
private function mergeOptions(array $defaultOptions = [], array $toMergeOptions = [])
private function mergeOptions(array $defaultOptions = [], array $toMergeOptions = []): array
{
return array_merge($defaultOptions, $toMergeOptions);
}

/**
* Perform actions on object before firing the after event.
*
* @param mixed $entity
*/
private function afterSuccess($entity)
private function afterSuccess(mixed $entity): void
{
if ($entity instanceof ModelInterface) {
$entity->syncOriginalDocumentAttributes();
Expand All @@ -548,10 +525,8 @@ public function getSchema(): Schema

/**
* Set a Schema object that describes an Entity in MongoDB.
*
* @param Schema $schema
*/
public function setSchema(Schema $schema)
public function setSchema(Schema $schema): void
{
$this->schema = $schema;
}
Expand Down Expand Up @@ -580,7 +555,7 @@ private function getUpdateData($model, array $data): array
* @see https://jira.mongodb.org/browse/SERVER-1014
* @see https://github.com/bjori/mongo-php-transistor/blob/70f5af00795d67f4d5a8c397e831435814df9937/src/Transistor.php#L108
*/
private function calculateChanges(array &$changes, array $newData, array $oldData, string $keyfix = '')
private function calculateChanges(array &$changes, array $newData, array $oldData, string $keyfix = ''): void
{
foreach ($newData as $k => $v) {
if (is_null($v)) {
Expand Down Expand Up @@ -610,22 +585,19 @@ private function calculateChanges(array &$changes, array $newData, array $oldDat
$this->pullNullValues[rtrim($keyfix, '.')] = null;
}
$changes['$unset']["{$keyfix}{$k}"] = '';
continue;
}
}
}

private function filterNullValues(array $data): array
{
$filtered = array_filter(
$filtered = array_filter(
$data,
function ($value) {
return !is_null($value);
}
fn($value): bool => !is_null($value)
);

if ($data == array_values($data)) {
$filtered = array_values($filtered);
return array_values($filtered);
}

return $filtered;
Expand Down
18 changes: 7 additions & 11 deletions src/DataMapper/EntityAssembler.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,16 @@ class EntityAssembler
*
* @param array|object $document the attributes that will be used to compose the entity
* @param Schema $schema schema that will be used to map each field
*
* @return mixed
*/
public function assemble($document, Schema $schema)
public function assemble(array|object $document, Schema $schema): mixed
JoaoFerrazfs marked this conversation as resolved.
Show resolved Hide resolved
{
$entityClass = $schema->entityClass;
$model = Container::make($entityClass);

foreach ($document as $field => $value) {
$fieldType = $schema->fields[$field] ?? null;

if ($fieldType && 'schema.' == substr($fieldType, 0, 7)) {
if ($fieldType && str_starts_with($fieldType, 'schema.')) {
$value = $this->assembleDocumentsRecursively($value, substr($fieldType, 7));
}

Expand All @@ -58,12 +56,12 @@ public function assemble($document, Schema $schema)
*
* @return mixed the result of $entity->polymorph or the $entity itself
*/
protected function morphingTime(ModelInterface $entity)
protected function morphingTime(ModelInterface $entity): ModelInterface
{
if ($entity instanceof PolymorphableModelInterface) {
$class = $entity->polymorph($entity->getDocumentAttributes());

if ($class !== get_class($entity)) {
if ($class !== $entity::class) {
$originalAttributes = $entity->getDocumentAttributes();
$entity = Container::make($class);
$entity->fill($originalAttributes, true);
Expand All @@ -80,7 +78,7 @@ protected function morphingTime(ModelInterface $entity)
*
* @return mixed the entity with original attributes
*/
protected function prepareOriginalAttributes($entity)
protected function prepareOriginalAttributes(mixed $entity): mixed
{
if ($entity instanceof ModelInterface) {
$entity->syncOriginalDocumentAttributes();
Expand All @@ -94,15 +92,13 @@ protected function prepareOriginalAttributes($entity)
*
* @param mixed $value a value of an embeded field containing entity data to be assembled
* @param string $schemaClass the schemaClass to be used when assembling the entities within $value
*
* @return mixed
*/
protected function assembleDocumentsRecursively($value, string $schemaClass)
protected function assembleDocumentsRecursively(mixed $value, string $schemaClass): ?array
{
$value = (array) $value;

if (empty($value)) {
return;
return null;
}

$schema = Container::make($schemaClass);
Expand Down
Loading
Loading