1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<?php namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Model;
use MongoDB\BSON\ObjectID;
class EmbedsOne extends EmbedsOneOrMany
{
/**
* @inheritdoc
*/
public function initRelation(array $models, $relation)
{
foreach ($models as $model) {
$model->setRelation($relation, null);
}
return $models;
}
/**
* @inheritdoc
*/
public function getResults()
{
return $this->toModel($this->getEmbedded());
}
/**
* Save a new model and attach it to the parent model.
*
* @param Model $model
* @return Model|bool
*/
public function performInsert(Model $model)
{
// Generate a new key if needed.
if ($model->getKeyName() == '_id' and ! $model->getKey()) {
$model->setAttribute('_id', new ObjectID);
}
// For deeply nested documents, let the parent handle the changes.
if ($this->isNested()) {
$this->associate($model);
return $this->parent->save() ? $model : false;
}
$result = $this->getBaseQuery()->update([$this->localKey => $model->getAttributes()]);
// Attach the model to its parent.
if ($result) {
$this->associate($model);
}
return $result ? $model : false;
}
/**
* Save an existing model and attach it to the parent model.
*
* @param Model $model
* @return Model|bool
*/
public function performUpdate(Model $model)
{
if ($this->isNested()) {
$this->associate($model);
return $this->parent->save();
}
// Use array dot notation for better update behavior.
$values = array_dot($model->getDirty(), $this->localKey.'.');
$result = $this->getBaseQuery()->update($values);
// Attach the model to its parent.
if ($result) {
$this->associate($model);
}
return $result ? $model : false;
}
/**
* Delete an existing model and detach it from the parent model.
*
* @return int
*/
public function performDelete()
{
// For deeply nested documents, let the parent handle the changes.
if ($this->isNested()) {
$this->dissociate();
return $this->parent->save();
}
// Overwrite the local key with an empty array.
$result = $this->getBaseQuery()->update([$this->localKey => null]);
// Detach the model from its parent.
if ($result) {
$this->dissociate();
}
return $result;
}
/**
* Attach the model to its parent.
*
* @param Model $model
* @return Model
*/
public function associate(Model $model)
{
return $this->setEmbedded($model->getAttributes());
}
/**
* Detach the model from its parent.
*
* @return Model
*/
public function dissociate()
{
return $this->setEmbedded(null);
}
/**
* Delete all embedded models.
*
* @return int
*/
public function delete()
{
return $this->performDelete();
}
}