Skip to content

Commit

Permalink
Merge 0c71f0e into 4d81b40
Browse files Browse the repository at this point in the history
  • Loading branch information
divine committed Feb 9, 2020
2 parents 4d81b40 + 0c71f0e commit a1911e6
Show file tree
Hide file tree
Showing 7 changed files with 284 additions and 26 deletions.
35 changes: 34 additions & 1 deletion src/Jenssegers/Mongodb/Relations/BelongsTo.php
Expand Up @@ -3,6 +3,7 @@
namespace Jenssegers\Mongodb\Relations;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model as EloquentModel;

class BelongsTo extends \Illuminate\Database\Eloquent\Relations\BelongsTo
Expand All @@ -25,7 +26,9 @@ public function addConstraints()
// For belongs to relationships, which are essentially the inverse of has one
// or has many relationships, we need to actually query on the primary key
// of the related models matching on the foreign key that's on a parent.
$this->query->where($this->getOwnerKey(), '=', $this->parent->{$this->foreignKey});
$this->query
->where($this->getOwnerKey(), '=', $this->parent->{$this->foreignKey})
->orWhere($this->getOwnerKey().'._id', '=', $this->parent->{$this->foreignKey});
}
}

Expand Down Expand Up @@ -69,4 +72,34 @@ protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}

/**
* Match the eagerly loaded results to their parents.
*
* @param array $models
* @param \Illuminate\Database\Eloquent\Collection $results
* @param string $relation
* @return array
*/
public function match(array $models, Collection $results, $relation)
{
$foreign = $this->foreignKey;
$owner = $this->ownerKey;
// First we will get to build a dictionary of the child models by their primary
// key of the relationship, then we can easily match the children back onto
// the parents using that dictionary and the primary key of the children.
$dictionary = [];
foreach ($results as $result) {
$dictionary[$result->getAttribute($owner)] = $result;
}
// Once we have the dictionary constructed, we can loop through all the parents
// and match back onto their children using these keys of the dictionary and
// the primary key of the children to map them onto the correct instances.
foreach ($models as $model) {
if (isset($dictionary[(string) $model->{$foreign}])) {
$model->setRelation($relation, $dictionary[(string) $model->{$foreign}]);
}
}
return $models;
}
}
91 changes: 81 additions & 10 deletions src/Jenssegers/Mongodb/Relations/BelongsToMany.php
Expand Up @@ -33,7 +33,13 @@ public function getRelationExistenceQuery(Builder $query, Builder $parentQuery,
*/
protected function hydratePivotRelation(array $models)
{
// Do nothing.
foreach ($models as $model) {
$keyToUse = $this->getTable() == $model->getTable() ? $this->getForeignKey() : $this->getRelatedKey();
$pcontent = $model->getAttributes()[$keyToUse];
$model->setRelation($this->accessor, $this->newExistingPivot(
is_string($pcontent[0]) ? ['_id' => $pcontent] : $pcontent[0]
));
}
}

/**
Expand Down Expand Up @@ -71,8 +77,10 @@ public function addConstraints()
protected function setWhere()
{
$foreign = $this->getForeignKey();

$this->query->where($foreign, '=', $this->parent->getKey());
$key = $this->parent->getKey();
$this->query
->where($foreign, '=', $key)
->orWhereRaw([$foreign.'._id' => $key]);

return $this;
}
Expand Down Expand Up @@ -129,6 +137,12 @@ public function sync($ids, $detaching = true)
// See issue #256.
if ($current instanceof Collection) {
$current = $ids->modelKeys();
} elseif (is_array($current)) {
foreach ($current as $key => $value) {
if (is_array($value) && $value['_id']) {
$current[$key] = $value['_id'];
}
}
}

$records = $this->formatSyncList($ids);
Expand Down Expand Up @@ -171,11 +185,39 @@ public function sync($ids, $detaching = true)
*/
public function updateExistingPivot($id, array $attributes, $touch = true)
{
// Do nothing, we have no pivot table.
if ($id instanceof Model) {
$model = $id;
$id = $model->getKey();
} else {
if ($id instanceof Collection) {
$id = $id->modelKeys();
}

$related = $this->newRelatedQuery()->whereIn($this->related->getKeyName(), (array) $id);
$filter = [$this->parentKey => $this->parent->getKey()];
$pivot_x = [array_merge($attributes, $filter)];

//TODO: Put this in a transaction
$related->pull($this->getForeignKey(), $this->parent->getKey());
$related->pull($this->getForeignKey(), $filter);
$related->push($this->getForeignKey(), $pivot_x, true);
}
$filter = [$this->parentKey => $id];
$pivot_x = [array_merge($attributes, $filter)];

//TODO: Put this in a transaction
$this->parent->pull($this->getRelatedKey(), $id);
$this->parent->pull($this->getRelatedKey(), $filter);
$this->parent->push($this->getRelatedKey(), $pivot_x, true);
}

/**
* @inheritdoc
* Attach a model to the parent.
*
* @param mixed $id
* @param array $attributes
* @param bool $touch
* @return void
*/
public function attach($id, array $attributes = [], $touch = true)
{
Expand All @@ -185,22 +227,30 @@ public function attach($id, array $attributes = [], $touch = true)
$id = $model->getKey();

// Attach the new parent id to the related model.
$model->push($this->foreignPivotKey, $this->parent->getKey(), true);
$model->push($this->foreignPivotKey, [array_merge($attributes, ['_id' => $this->parent->getKey()])], true);
} else {
if ($id instanceof Collection) {
$id = $id->modelKeys();
}

$query = $this->newRelatedQuery();

$query->whereIn($this->related->getKeyName(), (array) $id);
$query
->whereIn($this->related->getKeyName(), (array) $id)
->orWhereIn($this->related->getKeyName().'._id', (array) $id);

// Attach the new parent id to the related model.
$query->push($this->foreignPivotKey, $this->parent->getKey(), true);
$query->push($this->foreignPivotKey, [array_merge($attributes, ['_id' => $this->parent->getKey()])], true);
}

//Pivot Collection
$pivot_x = [];
foreach ((array) $id as $item) {
$pivot_x[] = array_merge($attributes, ['_id' => $item]);
}

// Attach the new ids to the parent model.
$this->parent->push($this->getRelatedKey(), (array) $id, true);
$this->parent->push($this->getRelatedKey(), $pivot_x, true);

if ($touch) {
$this->touchIfTouching();
Expand All @@ -224,7 +274,9 @@ public function detach($ids = [], $touch = true)
$ids = (array) $ids;

// Detach all ids from the parent model.
// Legacy Support
$this->parent->pull($this->getRelatedKey(), $ids);
$this->parent->pull($this->getRelatedKey(), ['_id' => ['$in' => $ids]]);

// Prepare the query to select all related objects.
if (count($ids) > 0) {
Expand All @@ -233,6 +285,7 @@ public function detach($ids = [], $touch = true)

// Remove the relation to the parent.
$query->pull($this->foreignPivotKey, $this->parent->getKey());
$query->pull($this->foreignPivotKey, [$this->parentKey => $this->parent->getKey()]);

if ($touch) {
$this->touchIfTouching();
Expand All @@ -255,7 +308,11 @@ protected function buildDictionary(Collection $results)

foreach ($results as $result) {
foreach ($result->$foreign as $item) {
$dictionary[$item][] = $result;
if (is_array($item)) {
$dictionary[$item['_id']][] = $result;
} else {
$dictionary[$item][] = $result;
}
}
}

Expand Down Expand Up @@ -342,4 +399,18 @@ protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}

/**
* Set the constraints for an eager load of the relation.
*
* @param array $models
* @return void
*/
public function addEagerConstraints(array $models)
{
$keys = $this->getKeys($models, $this->parentKey);
$this->query
->whereIn($this->getQualifiedForeignPivotKeyName(), $keys)
->orWhereRaw([$this->getQualifiedForeignPivotKeyName().'._id' => ['$in' => $keys]]);
}
}
20 changes: 19 additions & 1 deletion src/Jenssegers/Mongodb/Relations/HasMany.php
Expand Up @@ -3,6 +3,7 @@
namespace Jenssegers\Mongodb\Relations;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\Relations\HasMany as EloquentHasMany;

Expand Down Expand Up @@ -71,7 +72,9 @@ public function getRelationQuery(Builder $query, Builder $parent, $columns = ['*

$key = $this->wrap($this->getQualifiedParentKeyName());

return $query->where($this->getHasCompareKey(), 'exists', true);
return $query
->where($this->getHasCompareKey(), 'exists', true)
->orWhere($this->getHasCompareKey().'._id', 'exists', true);
}

/**
Expand All @@ -84,4 +87,19 @@ protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}

/**
* Build model dictionary keyed by the relation's foreign key.
*
* @param \Illuminate\Database\Eloquent\Collection $results
* @return array
*/
protected function buildDictionary(Collection $results)
{
$foreign = $this->getForeignKeyName();

return $results->mapToDictionary(function ($result) use ($foreign) {
return [(string) $result->{$foreign} => $result];
})->all();
}
}
16 changes: 16 additions & 0 deletions src/Jenssegers/Mongodb/Relations/HasOne.php
Expand Up @@ -3,6 +3,7 @@
namespace Jenssegers\Mongodb\Relations;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\Relations\HasOne as EloquentHasOne;

Expand Down Expand Up @@ -84,4 +85,19 @@ protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}

/**
* Build model dictionary keyed by the relation's foreign key.
*
* @param \Illuminate\Database\Eloquent\Collection $results
* @return array
*/
protected function buildDictionary(Collection $results)
{
$foreign = $this->getForeignKeyName();

return $results->mapToDictionary(function ($result) use ($foreign) {
return [(string) $result->{$foreign} => $result];
})->all();
}
}
16 changes: 16 additions & 0 deletions src/Jenssegers/Mongodb/Relations/MorphMany.php
Expand Up @@ -2,6 +2,7 @@

namespace Jenssegers\Mongodb\Relations;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\Relations\MorphMany as EloquentMorphMany;

Expand All @@ -19,4 +20,19 @@ protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}

/**
* Build model dictionary keyed by the relation's foreign key.
*
* @param \Illuminate\Database\Eloquent\Collection $results
* @return array
*/
protected function buildDictionary(Collection $results)
{
$foreign = $this->getForeignKeyName();

return $results->mapToDictionary(function ($result) use ($foreign) {
return [(string) $result->{$foreign} => $result];
})->all();
}
}
15 changes: 15 additions & 0 deletions src/Jenssegers/Mongodb/Relations/MorphTo.php
Expand Up @@ -2,6 +2,7 @@

namespace Jenssegers\Mongodb\Relations;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\Relations\MorphTo as EloquentMorphTo;

Expand Down Expand Up @@ -53,4 +54,18 @@ protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}

/**
* Build a dictionary with the models.
* @param \Illuminate\Database\Eloquent\Collection $models
* @return void
*/
protected function buildDictionary(Collection $models)
{
foreach ($models as $model) {
if ($model->{$this->morphType}) {
$this->dictionary[$model->{$this->morphType}][(string) $model->{$this->foreignKey}][] = $model;
}
}
}
}

0 comments on commit a1911e6

Please sign in to comment.