Completed
Branch 5.6 (cd95fb)
by Rémi
10:17
created
src/Relationships/HasOneOrMany.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -193,7 +193,7 @@
 block discarded – undo
193 193
         // Once we have the dictionary we can simply spin through the parent models to
194 194
         // link them up with their children using the keyed dictionary to make the
195 195
         // matching very convenient and easy work. Then we'll just return them.
196
-        return array_map(function ($result) use ($dictionary, $cache, $type, $relation, $host) {
196
+        return array_map(function($result) use ($dictionary, $cache, $type, $relation, $host) {
197 197
             $key = $result[$host->localKey];
198 198
 
199 199
             if (isset($dictionary[$key])) {
Please login to merge, or discard this patch.
Indentation   +304 added lines, -304 removed lines patch added patch discarded remove patch
@@ -7,308 +7,308 @@
 block discarded – undo
7 7
 
8 8
 abstract class HasOneOrMany extends Relationship
9 9
 {
10
-    /**
11
-     * The foreign key of the parent model.
12
-     *
13
-     * @var string
14
-     */
15
-    protected $foreignKey;
16
-
17
-    /**
18
-     * The local key of the parent model.
19
-     *
20
-     * @var string
21
-     */
22
-    protected $localKey;
23
-
24
-    /**
25
-     * Create a new has many relationship instance.
26
-     *
27
-     * @param Mapper                 $mapper
28
-     * @param \Analogue\ORM\Mappable $parentEntity
29
-     * @param string                 $foreignKey
30
-     * @param string                 $localKey
31
-     */
32
-    public function __construct(Mapper $mapper, $parentEntity, $foreignKey, $localKey)
33
-    {
34
-        $this->localKey = $localKey;
35
-        $this->foreignKey = $foreignKey;
36
-
37
-        parent::__construct($mapper, $parentEntity);
38
-    }
39
-
40
-    /**
41
-     * @param \Analogue\ORM\Entity $entity
42
-     */
43
-    public function attachOne($entity)
44
-    {
45
-        $wrapper = $this->factory->make($entity);
46
-
47
-        // Ok, we need to guess the inverse of the relation from there.
48
-        // Let's assume the inverse of the relation method is the name of
49
-        // the entity.
50
-
51
-        $wrapper->setEntityAttribute($this->getPlainForeignKey(), $this->getParentKey());
52
-    }
53
-
54
-    /**
55
-     * @param EntityCollection $entities
56
-     */
57
-    public function attachMany(EntityCollection $entities)
58
-    {
59
-        foreach ($entities as $entity) {
60
-            $this->attachOne($entity);
61
-        }
62
-    }
63
-
64
-    /**
65
-     * @param $entityHash
66
-     */
67
-    protected function detachOne($entityHash)
68
-    {
69
-        $this->detachMany([$entityHash]);
70
-    }
71
-
72
-    /**
73
-     * Attach ids that are passed as arguments, and detach any other.
74
-     *
75
-     * @param mixed $entities
76
-     *
77
-     * @throws \InvalidArgumentException
78
-     *
79
-     * @return void
80
-     */
81
-    public function sync(array $entities)
82
-    {
83
-        $this->detachExcept($entities);
84
-    }
85
-
86
-    /**
87
-     * @param  $entities
88
-     *
89
-     * @throws \InvalidArgumentException
90
-     */
91
-    protected function detachExcept($entities)
92
-    {
93
-        $query = $this->query->getQuery()->from($this->relatedMap->getTable());
94
-
95
-        if (count($entities) > 0) {
96
-            $keys = $this->getKeys($entities);
97
-            $query->whereNotIn($this->relatedMap->getKeyName(), $keys);
98
-        }
99
-
100
-        $parentKey = $this->parentMap->getKeyName();
101
-
102
-        $query->where($this->getPlainForeignKey(), '=', $this->parent->getEntityAttribute($parentKey))
103
-            ->update([$this->getPlainForeignKey() => null]);
104
-    }
105
-
106
-    /**
107
-     * @param array $entityHashes
108
-     */
109
-    public function detachMany(array $entityHashes)
110
-    {
111
-        $keys = [];
112
-
113
-        foreach ($entityHashes as $hash) {
114
-            $split = explode('.', $hash);
115
-            $keys[] = $split[1];
116
-        }
117
-
118
-        $query = $this->query->getQuery()->from($this->relatedMap->getTable());
119
-
120
-        $query->whereIn($this->relatedMap->getKeyName(), $keys)
121
-            ->update([$this->getPlainForeignKey() => null]);
122
-    }
123
-
124
-    /**
125
-     * Set the base constraints on the relation query.
126
-     *
127
-     * @return void
128
-     */
129
-    public function addConstraints()
130
-    {
131
-        if (static::$constraints) {
132
-            $this->query->where($this->foreignKey, '=', $this->getParentKey());
133
-        }
134
-    }
135
-
136
-    /**
137
-     * Set the constraints for an eager load of the relation.
138
-     *
139
-     * @param array $results
140
-     *
141
-     * @return void
142
-     */
143
-    public function addEagerConstraints(array $results)
144
-    {
145
-        $this->query->whereIn($this->foreignKey, $this->getKeysFromResults($results, $this->localKey));
146
-    }
147
-
148
-    /**
149
-     * Match the eagerly loaded relationship to the current result set.
150
-     *
151
-     * @param array  $results
152
-     * @param string $relation
153
-     *
154
-     * @return array
155
-     */
156
-    public function matchOne(array $results, $relation)
157
-    {
158
-        return $this->matchOneOrMany($results, $relation, 'one');
159
-    }
160
-
161
-    /**
162
-     * Match the eagerly loaded results to their many parents.
163
-     *
164
-     * @param array  $results
165
-     * @param string $relation
166
-     *
167
-     * @return array
168
-     */
169
-    public function matchMany(array $results, $relation)
170
-    {
171
-        return $this->matchOneOrMany($results, $relation, 'many');
172
-    }
173
-
174
-    /**
175
-     * Match the eagerly loaded results to their many parents.
176
-     *
177
-     * @param array  $results
178
-     * @param string $relation
179
-     * @param string $type
180
-     *
181
-     * @return array
182
-     */
183
-    protected function matchOneOrMany(array $results, $relation, $type)
184
-    {
185
-        $entities = $this->getEager();
186
-
187
-        $dictionary = $this->buildDictionary($entities);
188
-
189
-        $cache = $this->parentMapper->getEntityCache();
190
-
191
-        $host = $this;
192
-
193
-        // Once we have the dictionary we can simply spin through the parent models to
194
-        // link them up with their children using the keyed dictionary to make the
195
-        // matching very convenient and easy work. Then we'll just return them.
196
-        return array_map(function ($result) use ($dictionary, $cache, $type, $relation, $host) {
197
-            $key = $result[$host->localKey];
198
-
199
-            if (isset($dictionary[$key])) {
200
-                $value = $host->getRelationValue($dictionary, $key, $type);
201
-
202
-                $result[$relation] = $value;
203
-
204
-                // TODO : Refactor This
205
-                $cache->cacheLoadedRelationResult($key, $relation, $value, $this);
206
-            } else {
207
-                $result[$relation] = $type === 'many' ? $this->relatedMap->newCollection() : null;
208
-            }
209
-
210
-            return $result;
211
-        }, $results);
212
-    }
213
-
214
-    /**
215
-     * Get the value of a relationship by one or many type.
216
-     *
217
-     * @param array  $dictionary
218
-     * @param string $key
219
-     * @param string $type
220
-     *
221
-     * @return mixed
222
-     */
223
-    protected function getRelationValue(array $dictionary, $key, $type)
224
-    {
225
-        $value = $dictionary[$key];
226
-
227
-        return $type == 'one' ? reset($value) : $this->relatedMap->newCollection($value);
228
-    }
229
-
230
-    /**
231
-     * Build model dictionary keyed by the relation's foreign key.
232
-     *
233
-     * @param EntityCollection $results
234
-     *
235
-     * @return array
236
-     */
237
-    protected function buildDictionary(EntityCollection $results)
238
-    {
239
-        $dictionary = [];
240
-
241
-        $foreign = $this->getPlainForeignKey();
242
-
243
-        // First we will create a dictionary of models keyed by the foreign key of the
244
-        // relationship as this will allow us to quickly access all of the related
245
-        // models without having to do nested looping which will be quite slow.
246
-        foreach ($results as $result) {
247
-            $dictionary[$result->{$foreign}][] = $result;
248
-        }
249
-
250
-        return $dictionary;
251
-    }
252
-
253
-    /**
254
-     * Get the key for comparing against the parent key in "has" query.
255
-     *
256
-     * @return string
257
-     */
258
-    public function getHasCompareKey()
259
-    {
260
-        return $this->getForeignKey();
261
-    }
262
-
263
-    /**
264
-     * Get the foreign key for the relationship.
265
-     *
266
-     * @return string
267
-     */
268
-    public function getForeignKey()
269
-    {
270
-        return $this->foreignKey;
271
-    }
272
-
273
-    /**
274
-     * Get the plain foreign key.
275
-     *
276
-     * @return string
277
-     */
278
-    public function getPlainForeignKey()
279
-    {
280
-        $segments = explode('.', $this->getForeignKey());
281
-
282
-        return $segments[count($segments) - 1];
283
-    }
284
-
285
-    /**
286
-     * Get the key value of the parent's local key.
287
-     *
288
-     * @return mixed
289
-     */
290
-    public function getParentKey()
291
-    {
292
-        return $this->parent->getEntityAttribute($this->localKey);
293
-    }
294
-
295
-    /**
296
-     * Get the fully qualified parent key name.
297
-     *
298
-     * @return string
299
-     */
300
-    public function getQualifiedParentKeyName()
301
-    {
302
-        return $this->parentMap->getTable().'.'.$this->localKey;
303
-    }
304
-
305
-    /**
306
-     * Get the foreign key as value pair for this relation.
307
-     *
308
-     * @return array
309
-     */
310
-    public function getForeignKeyValuePair()
311
-    {
312
-        return [$this->getPlainForeignKey() => $this->getParentKey()];
313
-    }
10
+	/**
11
+	 * The foreign key of the parent model.
12
+	 *
13
+	 * @var string
14
+	 */
15
+	protected $foreignKey;
16
+
17
+	/**
18
+	 * The local key of the parent model.
19
+	 *
20
+	 * @var string
21
+	 */
22
+	protected $localKey;
23
+
24
+	/**
25
+	 * Create a new has many relationship instance.
26
+	 *
27
+	 * @param Mapper                 $mapper
28
+	 * @param \Analogue\ORM\Mappable $parentEntity
29
+	 * @param string                 $foreignKey
30
+	 * @param string                 $localKey
31
+	 */
32
+	public function __construct(Mapper $mapper, $parentEntity, $foreignKey, $localKey)
33
+	{
34
+		$this->localKey = $localKey;
35
+		$this->foreignKey = $foreignKey;
36
+
37
+		parent::__construct($mapper, $parentEntity);
38
+	}
39
+
40
+	/**
41
+	 * @param \Analogue\ORM\Entity $entity
42
+	 */
43
+	public function attachOne($entity)
44
+	{
45
+		$wrapper = $this->factory->make($entity);
46
+
47
+		// Ok, we need to guess the inverse of the relation from there.
48
+		// Let's assume the inverse of the relation method is the name of
49
+		// the entity.
50
+
51
+		$wrapper->setEntityAttribute($this->getPlainForeignKey(), $this->getParentKey());
52
+	}
53
+
54
+	/**
55
+	 * @param EntityCollection $entities
56
+	 */
57
+	public function attachMany(EntityCollection $entities)
58
+	{
59
+		foreach ($entities as $entity) {
60
+			$this->attachOne($entity);
61
+		}
62
+	}
63
+
64
+	/**
65
+	 * @param $entityHash
66
+	 */
67
+	protected function detachOne($entityHash)
68
+	{
69
+		$this->detachMany([$entityHash]);
70
+	}
71
+
72
+	/**
73
+	 * Attach ids that are passed as arguments, and detach any other.
74
+	 *
75
+	 * @param mixed $entities
76
+	 *
77
+	 * @throws \InvalidArgumentException
78
+	 *
79
+	 * @return void
80
+	 */
81
+	public function sync(array $entities)
82
+	{
83
+		$this->detachExcept($entities);
84
+	}
85
+
86
+	/**
87
+	 * @param  $entities
88
+	 *
89
+	 * @throws \InvalidArgumentException
90
+	 */
91
+	protected function detachExcept($entities)
92
+	{
93
+		$query = $this->query->getQuery()->from($this->relatedMap->getTable());
94
+
95
+		if (count($entities) > 0) {
96
+			$keys = $this->getKeys($entities);
97
+			$query->whereNotIn($this->relatedMap->getKeyName(), $keys);
98
+		}
99
+
100
+		$parentKey = $this->parentMap->getKeyName();
101
+
102
+		$query->where($this->getPlainForeignKey(), '=', $this->parent->getEntityAttribute($parentKey))
103
+			->update([$this->getPlainForeignKey() => null]);
104
+	}
105
+
106
+	/**
107
+	 * @param array $entityHashes
108
+	 */
109
+	public function detachMany(array $entityHashes)
110
+	{
111
+		$keys = [];
112
+
113
+		foreach ($entityHashes as $hash) {
114
+			$split = explode('.', $hash);
115
+			$keys[] = $split[1];
116
+		}
117
+
118
+		$query = $this->query->getQuery()->from($this->relatedMap->getTable());
119
+
120
+		$query->whereIn($this->relatedMap->getKeyName(), $keys)
121
+			->update([$this->getPlainForeignKey() => null]);
122
+	}
123
+
124
+	/**
125
+	 * Set the base constraints on the relation query.
126
+	 *
127
+	 * @return void
128
+	 */
129
+	public function addConstraints()
130
+	{
131
+		if (static::$constraints) {
132
+			$this->query->where($this->foreignKey, '=', $this->getParentKey());
133
+		}
134
+	}
135
+
136
+	/**
137
+	 * Set the constraints for an eager load of the relation.
138
+	 *
139
+	 * @param array $results
140
+	 *
141
+	 * @return void
142
+	 */
143
+	public function addEagerConstraints(array $results)
144
+	{
145
+		$this->query->whereIn($this->foreignKey, $this->getKeysFromResults($results, $this->localKey));
146
+	}
147
+
148
+	/**
149
+	 * Match the eagerly loaded relationship to the current result set.
150
+	 *
151
+	 * @param array  $results
152
+	 * @param string $relation
153
+	 *
154
+	 * @return array
155
+	 */
156
+	public function matchOne(array $results, $relation)
157
+	{
158
+		return $this->matchOneOrMany($results, $relation, 'one');
159
+	}
160
+
161
+	/**
162
+	 * Match the eagerly loaded results to their many parents.
163
+	 *
164
+	 * @param array  $results
165
+	 * @param string $relation
166
+	 *
167
+	 * @return array
168
+	 */
169
+	public function matchMany(array $results, $relation)
170
+	{
171
+		return $this->matchOneOrMany($results, $relation, 'many');
172
+	}
173
+
174
+	/**
175
+	 * Match the eagerly loaded results to their many parents.
176
+	 *
177
+	 * @param array  $results
178
+	 * @param string $relation
179
+	 * @param string $type
180
+	 *
181
+	 * @return array
182
+	 */
183
+	protected function matchOneOrMany(array $results, $relation, $type)
184
+	{
185
+		$entities = $this->getEager();
186
+
187
+		$dictionary = $this->buildDictionary($entities);
188
+
189
+		$cache = $this->parentMapper->getEntityCache();
190
+
191
+		$host = $this;
192
+
193
+		// Once we have the dictionary we can simply spin through the parent models to
194
+		// link them up with their children using the keyed dictionary to make the
195
+		// matching very convenient and easy work. Then we'll just return them.
196
+		return array_map(function ($result) use ($dictionary, $cache, $type, $relation, $host) {
197
+			$key = $result[$host->localKey];
198
+
199
+			if (isset($dictionary[$key])) {
200
+				$value = $host->getRelationValue($dictionary, $key, $type);
201
+
202
+				$result[$relation] = $value;
203
+
204
+				// TODO : Refactor This
205
+				$cache->cacheLoadedRelationResult($key, $relation, $value, $this);
206
+			} else {
207
+				$result[$relation] = $type === 'many' ? $this->relatedMap->newCollection() : null;
208
+			}
209
+
210
+			return $result;
211
+		}, $results);
212
+	}
213
+
214
+	/**
215
+	 * Get the value of a relationship by one or many type.
216
+	 *
217
+	 * @param array  $dictionary
218
+	 * @param string $key
219
+	 * @param string $type
220
+	 *
221
+	 * @return mixed
222
+	 */
223
+	protected function getRelationValue(array $dictionary, $key, $type)
224
+	{
225
+		$value = $dictionary[$key];
226
+
227
+		return $type == 'one' ? reset($value) : $this->relatedMap->newCollection($value);
228
+	}
229
+
230
+	/**
231
+	 * Build model dictionary keyed by the relation's foreign key.
232
+	 *
233
+	 * @param EntityCollection $results
234
+	 *
235
+	 * @return array
236
+	 */
237
+	protected function buildDictionary(EntityCollection $results)
238
+	{
239
+		$dictionary = [];
240
+
241
+		$foreign = $this->getPlainForeignKey();
242
+
243
+		// First we will create a dictionary of models keyed by the foreign key of the
244
+		// relationship as this will allow us to quickly access all of the related
245
+		// models without having to do nested looping which will be quite slow.
246
+		foreach ($results as $result) {
247
+			$dictionary[$result->{$foreign}][] = $result;
248
+		}
249
+
250
+		return $dictionary;
251
+	}
252
+
253
+	/**
254
+	 * Get the key for comparing against the parent key in "has" query.
255
+	 *
256
+	 * @return string
257
+	 */
258
+	public function getHasCompareKey()
259
+	{
260
+		return $this->getForeignKey();
261
+	}
262
+
263
+	/**
264
+	 * Get the foreign key for the relationship.
265
+	 *
266
+	 * @return string
267
+	 */
268
+	public function getForeignKey()
269
+	{
270
+		return $this->foreignKey;
271
+	}
272
+
273
+	/**
274
+	 * Get the plain foreign key.
275
+	 *
276
+	 * @return string
277
+	 */
278
+	public function getPlainForeignKey()
279
+	{
280
+		$segments = explode('.', $this->getForeignKey());
281
+
282
+		return $segments[count($segments) - 1];
283
+	}
284
+
285
+	/**
286
+	 * Get the key value of the parent's local key.
287
+	 *
288
+	 * @return mixed
289
+	 */
290
+	public function getParentKey()
291
+	{
292
+		return $this->parent->getEntityAttribute($this->localKey);
293
+	}
294
+
295
+	/**
296
+	 * Get the fully qualified parent key name.
297
+	 *
298
+	 * @return string
299
+	 */
300
+	public function getQualifiedParentKeyName()
301
+	{
302
+		return $this->parentMap->getTable().'.'.$this->localKey;
303
+	}
304
+
305
+	/**
306
+	 * Get the foreign key as value pair for this relation.
307
+	 *
308
+	 * @return array
309
+	 */
310
+	public function getForeignKeyValuePair()
311
+	{
312
+		return [$this->getPlainForeignKey() => $this->getParentKey()];
313
+	}
314 314
 }
Please login to merge, or discard this patch.
src/Relationships/HasManyThrough.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -156,7 +156,7 @@
 block discarded – undo
156 156
         // Once we have the dictionary we can simply spin through the parent entities to
157 157
         // link them up with their children using the keyed dictionary to make the
158 158
         // matching very convenient and easy work. Then we'll just return them.
159
-        return array_map(function ($result) use ($relation, $relatedKey, $dictionary, $cache, $host) {
159
+        return array_map(function($result) use ($relation, $relatedKey, $dictionary, $cache, $host) {
160 160
             $key = $result[$relatedKey];
161 161
 
162 162
             if (isset($dictionary[$key])) {
Please login to merge, or discard this patch.
Indentation   +290 added lines, -290 removed lines patch added patch discarded remove patch
@@ -9,294 +9,294 @@
 block discarded – undo
9 9
 
10 10
 class HasManyThrough extends Relationship
11 11
 {
12
-    /**
13
-     * The distance parent Entity instance.
14
-     *
15
-     * @var \Analogue\ORM\Entity
16
-     */
17
-    protected $farParent;
18
-
19
-    /**
20
-     * The far parent map instance.
21
-     *
22
-     * @var \Analogue\ORM\EntityMap
23
-     */
24
-    protected $farParentMap;
25
-
26
-    /**
27
-     * The near key on the relationship.
28
-     *
29
-     * @var string
30
-     */
31
-    protected $firstKey;
32
-
33
-    /**
34
-     * The far key on the relationship.
35
-     *
36
-     * @var string
37
-     */
38
-    protected $secondKey;
39
-
40
-    /**
41
-     * Create a new has many relationship instance.
42
-     *
43
-     * @param Mapper                  $mapper
44
-     * @param \Analogue\ORM\Mappable  $farParent
45
-     * @param \Analogue\ORM\EntityMap $parentMap
46
-     * @param string                  $firstKey
47
-     * @param string                  $secondKey
48
-     *
49
-     * @throws \Analogue\ORM\Exceptions\MappingException
50
-     */
51
-    public function __construct(Mapper $mapper, $farParent, $parentMap, $firstKey, $secondKey)
52
-    {
53
-        $this->firstKey = $firstKey;
54
-        $this->secondKey = $secondKey;
55
-        $this->farParent = $farParent;
56
-
57
-        $this->farParentMap = $mapper->getManager()->mapper($farParent)->getEntityMap();
58
-        $parentInstance = $mapper->getManager()->mapper($parentMap->getClass())->newInstance();
59
-
60
-        parent::__construct($mapper, $parentInstance);
61
-    }
62
-
63
-    /**
64
-     * Set the base constraints on the relation query.
65
-     *
66
-     * @return void
67
-     */
68
-    public function addConstraints()
69
-    {
70
-        $parentTable = $this->parentMap->getTable();
71
-
72
-        $this->setJoin();
73
-
74
-        if (static::$constraints) {
75
-            $farParentKeyName = $this->farParentMap->getKeyName();
76
-
77
-            $this->query->where(
78
-                $parentTable.'.'.$this->firstKey,
79
-                '=',
80
-                $this->farParent->getEntityAttribute($farParentKeyName)
81
-            );
82
-        }
83
-    }
84
-
85
-    /**
86
-     * Add the constraints for a relationship count query.
87
-     *
88
-     * @param Query $query
89
-     * @param Query $parent
90
-     *
91
-     * @return Query
92
-     */
93
-    public function getRelationCountQuery(Query $query, Query $parent)
94
-    {
95
-        $parentTable = $this->parentMap->getTable();
96
-
97
-        $this->setJoin($query);
98
-
99
-        $query->select(new Expression('count(*)'));
100
-
101
-        $key = $this->wrap($parentTable.'.'.$this->firstKey);
102
-
103
-        return $query->where($this->getHasCompareKey(), '=', new Expression($key));
104
-    }
105
-
106
-    /**
107
-     * Set the join clause on the query.
108
-     *
109
-     * @param null|Query $query
110
-     *
111
-     * @return void
112
-     */
113
-    protected function setJoin(Query $query = null)
114
-    {
115
-        $query = $query ?: $this->query;
116
-
117
-        $foreignKey = $this->relatedMap->getTable().'.'.$this->secondKey;
118
-
119
-        $query->join($this->parentMap->getTable(), $this->getQualifiedParentKeyName(), '=', $foreignKey);
120
-    }
121
-
122
-    /**
123
-     * Set the constraints for an eager load of the relation.
124
-     *
125
-     * @param array $results
126
-     *
127
-     * @return void
128
-     */
129
-    public function addEagerConstraints(array $results)
130
-    {
131
-        $table = $this->parentMap->getTable();
132
-
133
-        $this->query->whereIn($table.'.'.$this->firstKey, $this->getKeysFromResults($results));
134
-    }
135
-
136
-    /**
137
-     * Match eagerly loaded relationship to a result set.
138
-     *
139
-     * @param array  $results
140
-     * @param string $relation
141
-     *
142
-     * @return array
143
-     */
144
-    public function match(array $results, $relation)
145
-    {
146
-        $entities = $this->getEager();
147
-
148
-        $dictionary = $this->buildDictionary($entities);
149
-
150
-        $relatedKey = $this->relatedMap->getKeyName();
151
-
152
-        $cache = $this->parentMapper->getEntityCache();
153
-
154
-        $host = $this;
155
-
156
-        // Once we have the dictionary we can simply spin through the parent entities to
157
-        // link them up with their children using the keyed dictionary to make the
158
-        // matching very convenient and easy work. Then we'll just return them.
159
-        return array_map(function ($result) use ($relation, $relatedKey, $dictionary, $cache, $host) {
160
-            $key = $result[$relatedKey];
161
-
162
-            if (isset($dictionary[$key])) {
163
-                $value = $host->relatedMap->newCollection($dictionary[$key]);
164
-
165
-                $result[$relation] = $value;
166
-
167
-                $cache->cacheLoadedRelationResult($key, $relation, $value, $this);
168
-            }
169
-
170
-            return $result;
171
-        }, $results);
172
-    }
173
-
174
-    /**
175
-     * Build model dictionary keyed by the relation's foreign key.
176
-     *
177
-     * @param EntityCollection $results
178
-     *
179
-     * @return array
180
-     */
181
-    protected function buildDictionary(EntityCollection $results)
182
-    {
183
-        $dictionary = [];
184
-
185
-        $foreign = $this->firstKey;
186
-
187
-        // First we will create a dictionary of entities keyed by the foreign key of the
188
-        // relationship as this will allow us to quickly access all of the related
189
-        // entities without having to do nested looping which will be quite slow.
190
-        foreach ($results as $result) {
191
-            $dictionary[$result->{$foreign}][] = $result;
192
-        }
193
-
194
-        return $dictionary;
195
-    }
196
-
197
-    /**
198
-     * Get the results of the relationship.
199
-     *
200
-     * @param  $relation
201
-     *
202
-     * @return EntityCollection
203
-     */
204
-    public function getResults($relation)
205
-    {
206
-        $results = $this->query->get();
207
-
208
-        $this->cacheRelation($results, $relation);
209
-
210
-        return $results;
211
-    }
212
-
213
-    /**
214
-     * Execute the query as a "select" statement.
215
-     *
216
-     * @param array $columns
217
-     *
218
-     * @return EntityCollection
219
-     */
220
-    public function get($columns = ['*'])
221
-    {
222
-        // First we'll add the proper select columns onto the query so it is run with
223
-        // the proper columns. Then, we will get the results and hydrate out pivot
224
-        // entities with the result of those columns as a separate model relation.
225
-        $select = $this->getSelectColumns($columns);
226
-
227
-        $entities = $this->query->addSelect($select)->getEntities();
228
-
229
-        // If we actually found entities we will also eager load any relationships that
230
-        // have been specified as needing to be eager loaded. This will solve the
231
-        // n + 1 query problem for the developer and also increase performance.
232
-        if (count($entities) > 0) {
233
-            $entities = $this->query->eagerLoadRelations($entities);
234
-        }
235
-
236
-        return $this->relatedMap->newCollection($entities);
237
-    }
238
-
239
-    /**
240
-     * Set the select clause for the relation query.
241
-     *
242
-     * @param array $columns
243
-     *
244
-     * @return BelongsToMany
245
-     */
246
-    protected function getSelectColumns(array $columns = ['*'])
247
-    {
248
-        if ($columns == ['*']) {
249
-            $columns = [$this->relatedMap->getTable().'.*'];
250
-        }
251
-
252
-        return array_merge($columns, [$this->parentMap->getTable().'.'.$this->firstKey]);
253
-    }
254
-
255
-    /**
256
-     * Get a paginator for the "select" statement.
257
-     *
258
-     * @param int   $perPage
259
-     * @param array $columns
260
-     *
261
-     * @return \Illuminate\Pagination\LengthAwarePaginator
262
-     */
263
-    public function paginate($perPage = null, $columns = ['*'])
264
-    {
265
-        $this->query->addSelect($this->getSelectColumns($columns));
266
-
267
-        return $this->query->paginate($perPage, $columns);
268
-    }
269
-
270
-    /**
271
-     * Get the key name of the parent model.
272
-     *
273
-     * @return string
274
-     */
275
-    protected function getQualifiedParentKeyName()
276
-    {
277
-        return $this->parentMap->getQualifiedKeyName();
278
-    }
279
-
280
-    /**
281
-     * Get the key for comparing against the parent key in "has" query.
282
-     *
283
-     * @return string
284
-     */
285
-    public function getHasCompareKey()
286
-    {
287
-        return $this->farParentMap->getQualifiedKeyName();
288
-    }
289
-
290
-    /**
291
-     * Run synchronization content if needed by the
292
-     * relation type.
293
-     *
294
-     * @param array $entities
295
-     *
296
-     * @return void
297
-     */
298
-    public function sync(array $entities)
299
-    {
300
-        // N/A
301
-    }
12
+	/**
13
+	 * The distance parent Entity instance.
14
+	 *
15
+	 * @var \Analogue\ORM\Entity
16
+	 */
17
+	protected $farParent;
18
+
19
+	/**
20
+	 * The far parent map instance.
21
+	 *
22
+	 * @var \Analogue\ORM\EntityMap
23
+	 */
24
+	protected $farParentMap;
25
+
26
+	/**
27
+	 * The near key on the relationship.
28
+	 *
29
+	 * @var string
30
+	 */
31
+	protected $firstKey;
32
+
33
+	/**
34
+	 * The far key on the relationship.
35
+	 *
36
+	 * @var string
37
+	 */
38
+	protected $secondKey;
39
+
40
+	/**
41
+	 * Create a new has many relationship instance.
42
+	 *
43
+	 * @param Mapper                  $mapper
44
+	 * @param \Analogue\ORM\Mappable  $farParent
45
+	 * @param \Analogue\ORM\EntityMap $parentMap
46
+	 * @param string                  $firstKey
47
+	 * @param string                  $secondKey
48
+	 *
49
+	 * @throws \Analogue\ORM\Exceptions\MappingException
50
+	 */
51
+	public function __construct(Mapper $mapper, $farParent, $parentMap, $firstKey, $secondKey)
52
+	{
53
+		$this->firstKey = $firstKey;
54
+		$this->secondKey = $secondKey;
55
+		$this->farParent = $farParent;
56
+
57
+		$this->farParentMap = $mapper->getManager()->mapper($farParent)->getEntityMap();
58
+		$parentInstance = $mapper->getManager()->mapper($parentMap->getClass())->newInstance();
59
+
60
+		parent::__construct($mapper, $parentInstance);
61
+	}
62
+
63
+	/**
64
+	 * Set the base constraints on the relation query.
65
+	 *
66
+	 * @return void
67
+	 */
68
+	public function addConstraints()
69
+	{
70
+		$parentTable = $this->parentMap->getTable();
71
+
72
+		$this->setJoin();
73
+
74
+		if (static::$constraints) {
75
+			$farParentKeyName = $this->farParentMap->getKeyName();
76
+
77
+			$this->query->where(
78
+				$parentTable.'.'.$this->firstKey,
79
+				'=',
80
+				$this->farParent->getEntityAttribute($farParentKeyName)
81
+			);
82
+		}
83
+	}
84
+
85
+	/**
86
+	 * Add the constraints for a relationship count query.
87
+	 *
88
+	 * @param Query $query
89
+	 * @param Query $parent
90
+	 *
91
+	 * @return Query
92
+	 */
93
+	public function getRelationCountQuery(Query $query, Query $parent)
94
+	{
95
+		$parentTable = $this->parentMap->getTable();
96
+
97
+		$this->setJoin($query);
98
+
99
+		$query->select(new Expression('count(*)'));
100
+
101
+		$key = $this->wrap($parentTable.'.'.$this->firstKey);
102
+
103
+		return $query->where($this->getHasCompareKey(), '=', new Expression($key));
104
+	}
105
+
106
+	/**
107
+	 * Set the join clause on the query.
108
+	 *
109
+	 * @param null|Query $query
110
+	 *
111
+	 * @return void
112
+	 */
113
+	protected function setJoin(Query $query = null)
114
+	{
115
+		$query = $query ?: $this->query;
116
+
117
+		$foreignKey = $this->relatedMap->getTable().'.'.$this->secondKey;
118
+
119
+		$query->join($this->parentMap->getTable(), $this->getQualifiedParentKeyName(), '=', $foreignKey);
120
+	}
121
+
122
+	/**
123
+	 * Set the constraints for an eager load of the relation.
124
+	 *
125
+	 * @param array $results
126
+	 *
127
+	 * @return void
128
+	 */
129
+	public function addEagerConstraints(array $results)
130
+	{
131
+		$table = $this->parentMap->getTable();
132
+
133
+		$this->query->whereIn($table.'.'.$this->firstKey, $this->getKeysFromResults($results));
134
+	}
135
+
136
+	/**
137
+	 * Match eagerly loaded relationship to a result set.
138
+	 *
139
+	 * @param array  $results
140
+	 * @param string $relation
141
+	 *
142
+	 * @return array
143
+	 */
144
+	public function match(array $results, $relation)
145
+	{
146
+		$entities = $this->getEager();
147
+
148
+		$dictionary = $this->buildDictionary($entities);
149
+
150
+		$relatedKey = $this->relatedMap->getKeyName();
151
+
152
+		$cache = $this->parentMapper->getEntityCache();
153
+
154
+		$host = $this;
155
+
156
+		// Once we have the dictionary we can simply spin through the parent entities to
157
+		// link them up with their children using the keyed dictionary to make the
158
+		// matching very convenient and easy work. Then we'll just return them.
159
+		return array_map(function ($result) use ($relation, $relatedKey, $dictionary, $cache, $host) {
160
+			$key = $result[$relatedKey];
161
+
162
+			if (isset($dictionary[$key])) {
163
+				$value = $host->relatedMap->newCollection($dictionary[$key]);
164
+
165
+				$result[$relation] = $value;
166
+
167
+				$cache->cacheLoadedRelationResult($key, $relation, $value, $this);
168
+			}
169
+
170
+			return $result;
171
+		}, $results);
172
+	}
173
+
174
+	/**
175
+	 * Build model dictionary keyed by the relation's foreign key.
176
+	 *
177
+	 * @param EntityCollection $results
178
+	 *
179
+	 * @return array
180
+	 */
181
+	protected function buildDictionary(EntityCollection $results)
182
+	{
183
+		$dictionary = [];
184
+
185
+		$foreign = $this->firstKey;
186
+
187
+		// First we will create a dictionary of entities keyed by the foreign key of the
188
+		// relationship as this will allow us to quickly access all of the related
189
+		// entities without having to do nested looping which will be quite slow.
190
+		foreach ($results as $result) {
191
+			$dictionary[$result->{$foreign}][] = $result;
192
+		}
193
+
194
+		return $dictionary;
195
+	}
196
+
197
+	/**
198
+	 * Get the results of the relationship.
199
+	 *
200
+	 * @param  $relation
201
+	 *
202
+	 * @return EntityCollection
203
+	 */
204
+	public function getResults($relation)
205
+	{
206
+		$results = $this->query->get();
207
+
208
+		$this->cacheRelation($results, $relation);
209
+
210
+		return $results;
211
+	}
212
+
213
+	/**
214
+	 * Execute the query as a "select" statement.
215
+	 *
216
+	 * @param array $columns
217
+	 *
218
+	 * @return EntityCollection
219
+	 */
220
+	public function get($columns = ['*'])
221
+	{
222
+		// First we'll add the proper select columns onto the query so it is run with
223
+		// the proper columns. Then, we will get the results and hydrate out pivot
224
+		// entities with the result of those columns as a separate model relation.
225
+		$select = $this->getSelectColumns($columns);
226
+
227
+		$entities = $this->query->addSelect($select)->getEntities();
228
+
229
+		// If we actually found entities we will also eager load any relationships that
230
+		// have been specified as needing to be eager loaded. This will solve the
231
+		// n + 1 query problem for the developer and also increase performance.
232
+		if (count($entities) > 0) {
233
+			$entities = $this->query->eagerLoadRelations($entities);
234
+		}
235
+
236
+		return $this->relatedMap->newCollection($entities);
237
+	}
238
+
239
+	/**
240
+	 * Set the select clause for the relation query.
241
+	 *
242
+	 * @param array $columns
243
+	 *
244
+	 * @return BelongsToMany
245
+	 */
246
+	protected function getSelectColumns(array $columns = ['*'])
247
+	{
248
+		if ($columns == ['*']) {
249
+			$columns = [$this->relatedMap->getTable().'.*'];
250
+		}
251
+
252
+		return array_merge($columns, [$this->parentMap->getTable().'.'.$this->firstKey]);
253
+	}
254
+
255
+	/**
256
+	 * Get a paginator for the "select" statement.
257
+	 *
258
+	 * @param int   $perPage
259
+	 * @param array $columns
260
+	 *
261
+	 * @return \Illuminate\Pagination\LengthAwarePaginator
262
+	 */
263
+	public function paginate($perPage = null, $columns = ['*'])
264
+	{
265
+		$this->query->addSelect($this->getSelectColumns($columns));
266
+
267
+		return $this->query->paginate($perPage, $columns);
268
+	}
269
+
270
+	/**
271
+	 * Get the key name of the parent model.
272
+	 *
273
+	 * @return string
274
+	 */
275
+	protected function getQualifiedParentKeyName()
276
+	{
277
+		return $this->parentMap->getQualifiedKeyName();
278
+	}
279
+
280
+	/**
281
+	 * Get the key for comparing against the parent key in "has" query.
282
+	 *
283
+	 * @return string
284
+	 */
285
+	public function getHasCompareKey()
286
+	{
287
+		return $this->farParentMap->getQualifiedKeyName();
288
+	}
289
+
290
+	/**
291
+	 * Run synchronization content if needed by the
292
+	 * relation type.
293
+	 *
294
+	 * @param array $entities
295
+	 *
296
+	 * @return void
297
+	 */
298
+	public function sync(array $entities)
299
+	{
300
+		// N/A
301
+	}
302 302
 }
Please login to merge, or discard this patch.
src/Relationships/MorphMany.php 1 patch
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -4,32 +4,32 @@
 block discarded – undo
4 4
 
5 5
 class MorphMany extends MorphOneOrMany
6 6
 {
7
-    /**
8
-     * Get the results of the relationship.
9
-     *
10
-     * @param  $relation
11
-     *
12
-     * @return mixed
13
-     */
14
-    public function getResults($relation)
15
-    {
16
-        $results = $this->query->get();
7
+	/**
8
+	 * Get the results of the relationship.
9
+	 *
10
+	 * @param  $relation
11
+	 *
12
+	 * @return mixed
13
+	 */
14
+	public function getResults($relation)
15
+	{
16
+		$results = $this->query->get();
17 17
 
18
-        $this->cacheRelation($results, $relation);
18
+		$this->cacheRelation($results, $relation);
19 19
 
20
-        return $results;
21
-    }
20
+		return $results;
21
+	}
22 22
 
23
-    /**
24
-     * Match the eagerly loaded results to their parents.
25
-     *
26
-     * @param array  $results
27
-     * @param string $relation
28
-     *
29
-     * @return array
30
-     */
31
-    public function match(array $results, $relation)
32
-    {
33
-        return $this->matchMany($results, $relation);
34
-    }
23
+	/**
24
+	 * Match the eagerly loaded results to their parents.
25
+	 *
26
+	 * @param array  $results
27
+	 * @param string $relation
28
+	 *
29
+	 * @return array
30
+	 */
31
+	public function match(array $results, $relation)
32
+	{
33
+		return $this->matchMany($results, $relation);
34
+	}
35 35
 }
Please login to merge, or discard this patch.
src/Relationships/MorphOneOrMany.php 1 patch
Indentation   +118 added lines, -118 removed lines patch added patch discarded remove patch
@@ -7,122 +7,122 @@
 block discarded – undo
7 7
 
8 8
 abstract class MorphOneOrMany extends HasOneOrMany
9 9
 {
10
-    /**
11
-     * The foreign key type for the relationship.
12
-     *
13
-     * @var string
14
-     */
15
-    protected $morphType;
16
-
17
-    /**
18
-     * The class name of the parent model.
19
-     *
20
-     * @var string
21
-     */
22
-    protected $morphClass;
23
-
24
-    /**
25
-     * Create a new has many relationship instance.
26
-     *
27
-     * @param Mapper                 $mapper
28
-     * @param \Analogue\ORM\Mappable $parent
29
-     * @param string                 $type
30
-     * @param string                 $id
31
-     * @param string                 $localKey
32
-     *
33
-     * @throws \Analogue\ORM\Exceptions\MappingException
34
-     */
35
-    public function __construct(Mapper $mapper, $parent, $type, $id, $localKey)
36
-    {
37
-        $this->morphType = $type;
38
-        $this->morphClass = $mapper->getManager()->getMapper($parent)->getEntityMap()->getMorphClass();
39
-
40
-        parent::__construct($mapper, $parent, $id, $localKey);
41
-    }
42
-
43
-    /**
44
-     * Set the base constraints on the relation query.
45
-     *
46
-     * @return void
47
-     */
48
-    public function addConstraints()
49
-    {
50
-        if (static::$constraints) {
51
-            parent::addConstraints();
52
-
53
-            $this->query->where($this->morphType, $this->morphClass);
54
-        }
55
-    }
56
-
57
-    /**
58
-     * Get the relationship count query.
59
-     *
60
-     * @param Query $query
61
-     * @param Query $parent
62
-     *
63
-     * @return Query
64
-     */
65
-    public function getRelationCountQuery(Query $query, Query $parent)
66
-    {
67
-        $query = parent::getRelationCountQuery($query, $parent);
68
-
69
-        return $query->where($this->morphType, $this->morphClass);
70
-    }
71
-
72
-    /**
73
-     * Set the constraints for an eager load of the relation.
74
-     *
75
-     * @param array $results
76
-     *
77
-     * @return void
78
-     */
79
-    public function addEagerConstraints(array $results)
80
-    {
81
-        parent::addEagerConstraints($results);
82
-
83
-        $this->query->where($this->morphType, $this->morphClass);
84
-    }
85
-
86
-    /**
87
-     * Get the foreign key "type" name.
88
-     *
89
-     * @return string
90
-     */
91
-    public function getMorphType()
92
-    {
93
-        return $this->morphType;
94
-    }
95
-
96
-    /**
97
-     * Get the plain morph type name without the table.
98
-     *
99
-     * @return string
100
-     */
101
-    public function getPlainMorphType()
102
-    {
103
-        return last(explode('.', $this->morphType));
104
-    }
105
-
106
-    /**
107
-     * Get the class name of the parent model.
108
-     *
109
-     * @return string
110
-     */
111
-    public function getMorphClass()
112
-    {
113
-        return $this->morphClass;
114
-    }
115
-
116
-    /**
117
-     * Get the foreign key as value pair for this relation.
118
-     *
119
-     * @return array
120
-     */
121
-    public function getForeignKeyValuePair()
122
-    {
123
-        return [
124
-            $this->getPlainForeignKey() => $this->getParentKey(),
125
-            $this->getPlainMorphType()  => $this->morphClass,
126
-        ];
127
-    }
10
+	/**
11
+	 * The foreign key type for the relationship.
12
+	 *
13
+	 * @var string
14
+	 */
15
+	protected $morphType;
16
+
17
+	/**
18
+	 * The class name of the parent model.
19
+	 *
20
+	 * @var string
21
+	 */
22
+	protected $morphClass;
23
+
24
+	/**
25
+	 * Create a new has many relationship instance.
26
+	 *
27
+	 * @param Mapper                 $mapper
28
+	 * @param \Analogue\ORM\Mappable $parent
29
+	 * @param string                 $type
30
+	 * @param string                 $id
31
+	 * @param string                 $localKey
32
+	 *
33
+	 * @throws \Analogue\ORM\Exceptions\MappingException
34
+	 */
35
+	public function __construct(Mapper $mapper, $parent, $type, $id, $localKey)
36
+	{
37
+		$this->morphType = $type;
38
+		$this->morphClass = $mapper->getManager()->getMapper($parent)->getEntityMap()->getMorphClass();
39
+
40
+		parent::__construct($mapper, $parent, $id, $localKey);
41
+	}
42
+
43
+	/**
44
+	 * Set the base constraints on the relation query.
45
+	 *
46
+	 * @return void
47
+	 */
48
+	public function addConstraints()
49
+	{
50
+		if (static::$constraints) {
51
+			parent::addConstraints();
52
+
53
+			$this->query->where($this->morphType, $this->morphClass);
54
+		}
55
+	}
56
+
57
+	/**
58
+	 * Get the relationship count query.
59
+	 *
60
+	 * @param Query $query
61
+	 * @param Query $parent
62
+	 *
63
+	 * @return Query
64
+	 */
65
+	public function getRelationCountQuery(Query $query, Query $parent)
66
+	{
67
+		$query = parent::getRelationCountQuery($query, $parent);
68
+
69
+		return $query->where($this->morphType, $this->morphClass);
70
+	}
71
+
72
+	/**
73
+	 * Set the constraints for an eager load of the relation.
74
+	 *
75
+	 * @param array $results
76
+	 *
77
+	 * @return void
78
+	 */
79
+	public function addEagerConstraints(array $results)
80
+	{
81
+		parent::addEagerConstraints($results);
82
+
83
+		$this->query->where($this->morphType, $this->morphClass);
84
+	}
85
+
86
+	/**
87
+	 * Get the foreign key "type" name.
88
+	 *
89
+	 * @return string
90
+	 */
91
+	public function getMorphType()
92
+	{
93
+		return $this->morphType;
94
+	}
95
+
96
+	/**
97
+	 * Get the plain morph type name without the table.
98
+	 *
99
+	 * @return string
100
+	 */
101
+	public function getPlainMorphType()
102
+	{
103
+		return last(explode('.', $this->morphType));
104
+	}
105
+
106
+	/**
107
+	 * Get the class name of the parent model.
108
+	 *
109
+	 * @return string
110
+	 */
111
+	public function getMorphClass()
112
+	{
113
+		return $this->morphClass;
114
+	}
115
+
116
+	/**
117
+	 * Get the foreign key as value pair for this relation.
118
+	 *
119
+	 * @return array
120
+	 */
121
+	public function getForeignKeyValuePair()
122
+	{
123
+		return [
124
+			$this->getPlainForeignKey() => $this->getParentKey(),
125
+			$this->getPlainMorphType()  => $this->morphClass,
126
+		];
127
+	}
128 128
 }
Please login to merge, or discard this patch.
src/Drivers/IlluminateQueryBuilder.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -12,5 +12,5 @@
 block discarded – undo
12 12
  */
13 13
 class IlluminateQueryBuilder extends Builder
14 14
 {
15
-    //
15
+	//
16 16
 }
Please login to merge, or discard this patch.
src/AnalogueFacade.php 1 patch
Indentation   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -9,13 +9,13 @@
 block discarded – undo
9 9
  */
10 10
 class AnalogueFacade extends Facade
11 11
 {
12
-    /**
13
-     * Get the registered name of the component.
14
-     *
15
-     * @return string
16
-     */
17
-    protected static function getFacadeAccessor()
18
-    {
19
-        return 'analogue';
20
-    }
12
+	/**
13
+	 * Get the registered name of the component.
14
+	 *
15
+	 * @return string
16
+	 */
17
+	protected static function getFacadeAccessor()
18
+	{
19
+		return 'analogue';
20
+	}
21 21
 }
Please login to merge, or discard this patch.
src/Relationships/MorphTo.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -172,7 +172,7 @@
 block discarded – undo
172 172
     {
173 173
         $foreign = $this->foreignKey;
174 174
 
175
-        return BaseCollection::make($this->dictionary[$type])->map(function ($entities) use ($foreign) {
175
+        return BaseCollection::make($this->dictionary[$type])->map(function($entities) use ($foreign) {
176 176
             return head($entities)->{$foreign};
177 177
         })->unique();
178 178
     }
Please login to merge, or discard this patch.
Indentation   +215 added lines, -215 removed lines patch added patch discarded remove patch
@@ -8,219 +8,219 @@
 block discarded – undo
8 8
 
9 9
 class MorphTo extends BelongsTo
10 10
 {
11
-    /**
12
-     * The type of the polymorphic relation.
13
-     *
14
-     * @var string
15
-     */
16
-    protected $morphType;
17
-
18
-    /**
19
-     * The entities whose relations are being eager loaded.
20
-     *
21
-     * @var EntityCollection
22
-     */
23
-    protected $entities;
24
-
25
-    /**
26
-     * All of the result sets keyed by ID.
27
-     *
28
-     * @var array
29
-     */
30
-    protected $dictionary = [];
31
-
32
-    /**
33
-     * Indicates if soft-deleted model instances should be fetched.
34
-     *
35
-     * @var bool
36
-     */
37
-    protected $withTrashed = false;
38
-
39
-    /**
40
-     * Create a new belongs to relationship instance.
41
-     *
42
-     * @param Mapper                 $mapper
43
-     * @param \Analogue\ORM\Mappable $parent
44
-     * @param string                 $foreignKey
45
-     * @param string                 $otherKey
46
-     * @param string                 $type
47
-     * @param string                 $relation
48
-     */
49
-    public function __construct(Mapper $mapper, $parent, $foreignKey, $otherKey, $type, $relation)
50
-    {
51
-        $this->morphType = $type;
52
-
53
-        parent::__construct($mapper, $parent, $foreignKey, $otherKey, $relation);
54
-    }
55
-
56
-    /**
57
-     * Set the constraints for an eager load of the relation.
58
-     *
59
-     * @param array $results
60
-     *
61
-     * @return void
62
-     */
63
-    public function addEagerConstraints(array $results)
64
-    {
65
-        $this->buildDictionary($results);
66
-    }
67
-
68
-    /**
69
-     * Build a dictionary with the entities.
70
-     *
71
-     * @param array $results
72
-     *
73
-     * @return void
74
-     */
75
-    protected function buildDictionary($results)
76
-    {
77
-        foreach ($results as $result) {
78
-            if ($result[$this->morphType]) {
79
-                $this->dictionary[$result[$this->morphType]][$result[$this->foreignKey]] = $result;
80
-            }
81
-        }
82
-    }
83
-
84
-    /**
85
-     * Match the eagerly loaded results to their parents.
86
-     *
87
-     * @param array  $results
88
-     * @param string $relation
89
-     *
90
-     * @return array
91
-     */
92
-    public function match(array $results, $relation)
93
-    {
94
-        return $results;
95
-    }
96
-
97
-    /**
98
-     * Get the results of the relationship.
99
-     *
100
-     * @throws \Analogue\ORM\Exceptions\MappingException
101
-     *
102
-     * @return EntityCollection
103
-     */
104
-    public function getEager()
105
-    {
106
-        foreach (array_keys($this->dictionary) as $type) {
107
-            $this->matchToMorphParents($type, $this->getResultsByType($type));
108
-        }
109
-
110
-        return $this->entities;
111
-    }
112
-
113
-    /**
114
-     * Match the results for a given type to their parents.
115
-     *
116
-     * @param string           $type
117
-     * @param EntityCollection $results
118
-     *
119
-     * @return void
120
-     */
121
-    protected function matchToMorphParents($type, EntityCollection $results)
122
-    {
123
-        $mapper = $this->relatedMapper->getManager()->mapper($type);
124
-        $keyName = $mapper->getEntityMap()->getKeyName();
125
-
126
-        foreach ($results as $result) {
127
-            $key = $result[$keyName];
128
-
129
-            if (isset($this->dictionary[$type][$key])) {
130
-                foreach ($this->dictionary[$type][$key] as $result) {
131
-                    $result[$this->relation] = $result;
132
-                }
133
-            }
134
-        }
135
-    }
136
-
137
-    /**
138
-     * Get all of the relation results for a type.
139
-     *
140
-     * @param string $type
141
-     *
142
-     * @throws \Analogue\ORM\Exceptions\MappingException
143
-     *
144
-     * @return \Illuminate\Support\Collection
145
-     */
146
-    protected function getResultsByType($type)
147
-    {
148
-        $mapper = $this->relatedMapper->getManager()->mapper($type);
149
-
150
-        $key = $mapper->getEntityMap()->getKeyName();
151
-
152
-        $query = $mapper->getQuery();
153
-
154
-        return $query->whereIn($key, $this->gatherKeysByType($type)->all())->get();
155
-    }
156
-
157
-    /**
158
-     * Gather all of the foreign keys for a given type.
159
-     *
160
-     * @param string $type
161
-     *
162
-     * @return BaseCollection
163
-     */
164
-    protected function gatherKeysByType($type)
165
-    {
166
-        $foreign = $this->foreignKey;
167
-
168
-        return BaseCollection::make($this->dictionary[$type])->map(function ($entities) use ($foreign) {
169
-            return head($entities)->{$foreign};
170
-        })->unique();
171
-    }
172
-
173
-    /**
174
-     * Associate the model instance to the given parent.
175
-     *
176
-     * @param mixed $entity
177
-     *
178
-     * @return void
179
-     */
180
-    public function associate($entity)
181
-    {
182
-        // The Mapper will retrieve this association within the object model, we won't be using
183
-        // the foreign key attribute inside the parent Entity.
184
-        //
185
-        //$this->parent->setEntityAttribute($this->foreignKey, $entity->getEntityAttribute($this->otherKey));
186
-        //
187
-        // Instead, we'll just add the object to the Entity's attribute
188
-
189
-        $this->parent->setEntityAttribute($this->relation, $entity->getEntityObject());
190
-    }
191
-
192
-    /**
193
-     * Get the foreign key value pair for a related object.
194
-     *
195
-     * @param mixed $related
196
-     *
197
-     * @return array
198
-     */
199
-    public function getForeignKeyValuePair($related)
200
-    {
201
-        $foreignKey = $this->getForeignKey();
202
-
203
-        if ($related) {
204
-            $wrapper = $this->factory->make($related);
205
-
206
-            $relatedKey = $this->relatedMap->getKeyName();
207
-
208
-            return [
209
-                $foreignKey      => $wrapper->getEntityAttribute($relatedKey),
210
-                $this->morphType => $wrapper->getMap()->getMorphClass(),
211
-            ];
212
-        } else {
213
-            return [$foreignKey => null];
214
-        }
215
-    }
216
-
217
-    /**
218
-     * Get the dictionary used by the relationship.
219
-     *
220
-     * @return array
221
-     */
222
-    public function getDictionary()
223
-    {
224
-        return $this->dictionary;
225
-    }
11
+	/**
12
+	 * The type of the polymorphic relation.
13
+	 *
14
+	 * @var string
15
+	 */
16
+	protected $morphType;
17
+
18
+	/**
19
+	 * The entities whose relations are being eager loaded.
20
+	 *
21
+	 * @var EntityCollection
22
+	 */
23
+	protected $entities;
24
+
25
+	/**
26
+	 * All of the result sets keyed by ID.
27
+	 *
28
+	 * @var array
29
+	 */
30
+	protected $dictionary = [];
31
+
32
+	/**
33
+	 * Indicates if soft-deleted model instances should be fetched.
34
+	 *
35
+	 * @var bool
36
+	 */
37
+	protected $withTrashed = false;
38
+
39
+	/**
40
+	 * Create a new belongs to relationship instance.
41
+	 *
42
+	 * @param Mapper                 $mapper
43
+	 * @param \Analogue\ORM\Mappable $parent
44
+	 * @param string                 $foreignKey
45
+	 * @param string                 $otherKey
46
+	 * @param string                 $type
47
+	 * @param string                 $relation
48
+	 */
49
+	public function __construct(Mapper $mapper, $parent, $foreignKey, $otherKey, $type, $relation)
50
+	{
51
+		$this->morphType = $type;
52
+
53
+		parent::__construct($mapper, $parent, $foreignKey, $otherKey, $relation);
54
+	}
55
+
56
+	/**
57
+	 * Set the constraints for an eager load of the relation.
58
+	 *
59
+	 * @param array $results
60
+	 *
61
+	 * @return void
62
+	 */
63
+	public function addEagerConstraints(array $results)
64
+	{
65
+		$this->buildDictionary($results);
66
+	}
67
+
68
+	/**
69
+	 * Build a dictionary with the entities.
70
+	 *
71
+	 * @param array $results
72
+	 *
73
+	 * @return void
74
+	 */
75
+	protected function buildDictionary($results)
76
+	{
77
+		foreach ($results as $result) {
78
+			if ($result[$this->morphType]) {
79
+				$this->dictionary[$result[$this->morphType]][$result[$this->foreignKey]] = $result;
80
+			}
81
+		}
82
+	}
83
+
84
+	/**
85
+	 * Match the eagerly loaded results to their parents.
86
+	 *
87
+	 * @param array  $results
88
+	 * @param string $relation
89
+	 *
90
+	 * @return array
91
+	 */
92
+	public function match(array $results, $relation)
93
+	{
94
+		return $results;
95
+	}
96
+
97
+	/**
98
+	 * Get the results of the relationship.
99
+	 *
100
+	 * @throws \Analogue\ORM\Exceptions\MappingException
101
+	 *
102
+	 * @return EntityCollection
103
+	 */
104
+	public function getEager()
105
+	{
106
+		foreach (array_keys($this->dictionary) as $type) {
107
+			$this->matchToMorphParents($type, $this->getResultsByType($type));
108
+		}
109
+
110
+		return $this->entities;
111
+	}
112
+
113
+	/**
114
+	 * Match the results for a given type to their parents.
115
+	 *
116
+	 * @param string           $type
117
+	 * @param EntityCollection $results
118
+	 *
119
+	 * @return void
120
+	 */
121
+	protected function matchToMorphParents($type, EntityCollection $results)
122
+	{
123
+		$mapper = $this->relatedMapper->getManager()->mapper($type);
124
+		$keyName = $mapper->getEntityMap()->getKeyName();
125
+
126
+		foreach ($results as $result) {
127
+			$key = $result[$keyName];
128
+
129
+			if (isset($this->dictionary[$type][$key])) {
130
+				foreach ($this->dictionary[$type][$key] as $result) {
131
+					$result[$this->relation] = $result;
132
+				}
133
+			}
134
+		}
135
+	}
136
+
137
+	/**
138
+	 * Get all of the relation results for a type.
139
+	 *
140
+	 * @param string $type
141
+	 *
142
+	 * @throws \Analogue\ORM\Exceptions\MappingException
143
+	 *
144
+	 * @return \Illuminate\Support\Collection
145
+	 */
146
+	protected function getResultsByType($type)
147
+	{
148
+		$mapper = $this->relatedMapper->getManager()->mapper($type);
149
+
150
+		$key = $mapper->getEntityMap()->getKeyName();
151
+
152
+		$query = $mapper->getQuery();
153
+
154
+		return $query->whereIn($key, $this->gatherKeysByType($type)->all())->get();
155
+	}
156
+
157
+	/**
158
+	 * Gather all of the foreign keys for a given type.
159
+	 *
160
+	 * @param string $type
161
+	 *
162
+	 * @return BaseCollection
163
+	 */
164
+	protected function gatherKeysByType($type)
165
+	{
166
+		$foreign = $this->foreignKey;
167
+
168
+		return BaseCollection::make($this->dictionary[$type])->map(function ($entities) use ($foreign) {
169
+			return head($entities)->{$foreign};
170
+		})->unique();
171
+	}
172
+
173
+	/**
174
+	 * Associate the model instance to the given parent.
175
+	 *
176
+	 * @param mixed $entity
177
+	 *
178
+	 * @return void
179
+	 */
180
+	public function associate($entity)
181
+	{
182
+		// The Mapper will retrieve this association within the object model, we won't be using
183
+		// the foreign key attribute inside the parent Entity.
184
+		//
185
+		//$this->parent->setEntityAttribute($this->foreignKey, $entity->getEntityAttribute($this->otherKey));
186
+		//
187
+		// Instead, we'll just add the object to the Entity's attribute
188
+
189
+		$this->parent->setEntityAttribute($this->relation, $entity->getEntityObject());
190
+	}
191
+
192
+	/**
193
+	 * Get the foreign key value pair for a related object.
194
+	 *
195
+	 * @param mixed $related
196
+	 *
197
+	 * @return array
198
+	 */
199
+	public function getForeignKeyValuePair($related)
200
+	{
201
+		$foreignKey = $this->getForeignKey();
202
+
203
+		if ($related) {
204
+			$wrapper = $this->factory->make($related);
205
+
206
+			$relatedKey = $this->relatedMap->getKeyName();
207
+
208
+			return [
209
+				$foreignKey      => $wrapper->getEntityAttribute($relatedKey),
210
+				$this->morphType => $wrapper->getMap()->getMorphClass(),
211
+			];
212
+		} else {
213
+			return [$foreignKey => null];
214
+		}
215
+	}
216
+
217
+	/**
218
+	 * Get the dictionary used by the relationship.
219
+	 *
220
+	 * @return array
221
+	 */
222
+	public function getDictionary()
223
+	{
224
+		return $this->dictionary;
225
+	}
226 226
 }
Please login to merge, or discard this patch.
src/System/Mapper.php 3 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
         }
115 115
 
116 116
         // First, we'll cast every single result to array
117
-        $results = array_map(function ($item) {
117
+        $results = array_map(function($item) {
118 118
             return (array) $item;
119 119
         }, $results);
120 120
 
@@ -394,7 +394,7 @@  discard block
 block discarded – undo
394 394
      */
395 395
     public function getGlobalScope($scope)
396 396
     {
397
-        return array_first($this->globalScopes, function ($key, $value) use ($scope) {
397
+        return array_first($this->globalScopes, function($key, $value) use ($scope) {
398 398
             return $scope instanceof $value;
399 399
         });
400 400
     }
Please login to merge, or discard this patch.
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -122,7 +122,7 @@
 block discarded – undo
122 122
     /**
123 123
      * Map results to a Collection.
124 124
      *
125
-     * @param array|Collection $results
125
+     * @param Collection $results
126 126
      * @param array            $eagerLoads
127 127
      *
128 128
      * @return Collection
Please login to merge, or discard this patch.
Indentation   +689 added lines, -689 removed lines patch added patch discarded remove patch
@@ -25,696 +25,696 @@
 block discarded – undo
25 25
  */
26 26
 class Mapper
27 27
 {
28
-    /**
29
-     * The Manager instance.
30
-     *
31
-     * @var \Analogue\ORM\System\Manager
32
-     */
33
-    protected $manager;
34
-
35
-    /**
36
-     * Instance of EntityMapper Object.
37
-     *
38
-     * @var \Analogue\ORM\EntityMap
39
-     */
40
-    protected $entityMap;
41
-
42
-    /**
43
-     * The instance of db adapter.
44
-     *
45
-     * @var \Analogue\ORM\Drivers\DBAdapter
46
-     */
47
-    protected $adapter;
48
-
49
-    /**
50
-     * Event dispatcher instance.
51
-     *
52
-     * @var \Illuminate\Contracts\Events\Dispatcher
53
-     */
54
-    protected $dispatcher;
55
-
56
-    /**
57
-     * Entity Cache.
58
-     *
59
-     * @var \Analogue\ORM\System\Cache\AttributeCache
60
-     */
61
-    protected $cache;
62
-
63
-    /**
64
-     * Entity instances Object cache.
65
-     *
66
-     * @var \Analogue\ORM\System\Cache\InstanceCache
67
-     */
68
-    protected $instances;
69
-
70
-    /**
71
-     * Global scopes.
72
-     *
73
-     * @var array
74
-     */
75
-    protected $globalScopes = [];
76
-
77
-    /**
78
-     * Custom Commands.
79
-     *
80
-     * @var array
81
-     */
82
-    protected $customCommands = [];
83
-
84
-    /**
85
-     * Available Analogue Events.
86
-     *
87
-     * @var array
88
-     */
89
-    protected $events = [
90
-        'initializing' => \Analogue\ORM\Events\Initializing::class,
91
-        'initialized'  => \Analogue\ORM\Events\Initialized::class,
92
-        'storing'      => \Analogue\ORM\Events\Storing::class,
93
-        'stored'       => \Analogue\ORM\Events\Stored::class,
94
-        'creating'     => \Analogue\ORM\Events\Creating::class,
95
-        'created'      => \Analogue\ORM\Events\Created::class,
96
-        'updating'     => \Analogue\ORM\Events\Updating::class,
97
-        'updated'      => \Analogue\ORM\Events\Updated::class,
98
-        'deleting'     => \Analogue\ORM\Events\Deleting::class,
99
-        'deleted'      => \Analogue\ORM\Events\Deleted::class,
100
-    ];
101
-
102
-    /**
103
-     * @param EntityMap  $entityMap
104
-     * @param DBAdapter  $adapter
105
-     * @param Dispatcher $dispatcher
106
-     * @param Manager    $manager
107
-     */
108
-    public function __construct(EntityMap $entityMap, DBAdapter $adapter, Dispatcher $dispatcher, Manager $manager)
109
-    {
110
-        $this->entityMap = $entityMap;
111
-
112
-        $this->adapter = $adapter;
113
-
114
-        $this->dispatcher = $dispatcher;
115
-
116
-        $this->manager = $manager;
117
-
118
-        $this->cache = new AttributeCache($entityMap);
119
-        $this->instances = new InstanceCache($entityMap->getClass());
120
-    }
121
-
122
-    /**
123
-     * Map results to a Collection.
124
-     *
125
-     * @param array|Collection $results
126
-     * @param array            $eagerLoads
127
-     *
128
-     * @return Collection
129
-     */
130
-    public function map($results, array $eagerLoads = []) : Collection
131
-    {
132
-        $builder = new ResultBuilder($this);
133
-
134
-        if ($results instanceof Collection) {
135
-            // Get underlying collection array
136
-            $results = $results->all();
137
-        }
138
-
139
-        if (!is_array($results)) {
140
-            throw new InvalidArgumentException("'results' should be an array or collection.");
141
-        }
142
-
143
-        // First, we'll cast every single result to array
144
-        $results = array_map(function ($item) {
145
-            return (array) $item;
146
-        }, $results);
147
-
148
-        // Then, we'll pass the results to the Driver's provided transformer, so
149
-        // any DB specific value can be casted before hydration
150
-        $results = $this->adapter->fromDatabase($results);
151
-
152
-        // Then, we'll cache every single results as raw attributes, before
153
-        // adding relationships, which will be cached when the relationship's
154
-        // query takes place.
155
-        //$this->getEntityCache()->add($results);
156
-
157
-        $entities = $builder->build($results, $eagerLoads);
158
-
159
-        return $this->entityMap->newCollection($entities);
160
-    }
161
-
162
-    /**
163
-     * Return all records for a mapped object.
164
-     *
165
-     * @return \Illuminate\Support\Collection
166
-     */
167
-    public function all()
168
-    {
169
-        return $this->query()->get();
170
-    }
171
-
172
-    /**
173
-     * Persist an entity or an entity collection into the database.
174
-     *
175
-     * @param Mappable|\Traversable|array $entity
176
-     *
177
-     * @throws \InvalidArgumentException
178
-     * @throws MappingException
179
-     *
180
-     * @return Mappable|\Traversable|array
181
-     */
182
-    public function store($entity)
183
-    {
184
-        if ($this->manager->isTraversable($entity)) {
185
-            return $this->storeCollection($entity);
186
-        } else {
187
-            return $this->storeEntity($entity);
188
-        }
189
-    }
190
-
191
-    /**
192
-     * Store an entity collection inside a single DB Transaction.
193
-     *
194
-     * @param \Traversable|array $entities
195
-     *
196
-     * @throws \InvalidArgumentException
197
-     * @throws MappingException
198
-     *
199
-     * @return \Traversable|array
200
-     */
201
-    protected function storeCollection($entities)
202
-    {
203
-        $this->adapter->beginTransaction();
204
-
205
-        foreach ($entities as $entity) {
206
-            $this->storeEntity($entity);
207
-        }
208
-
209
-        $this->adapter->commit();
210
-
211
-        return $entities;
212
-    }
213
-
214
-    /**
215
-     * Store a single entity into the database.
216
-     *
217
-     * @param Mappable $entity
218
-     *
219
-     * @throws \InvalidArgumentException
220
-     * @throws MappingException
221
-     *
222
-     * @return \Analogue\ORM\Entity
223
-     */
224
-    protected function storeEntity($entity)
225
-    {
226
-        $this->checkEntityType($entity);
227
-
228
-        $store = new Store($this->aggregate($entity), $this->newQueryBuilder());
229
-
230
-        return $store->execute();
231
-    }
232
-
233
-    /**
234
-     * Check that the entity correspond to the current mapper.
235
-     *
236
-     * @param mixed $entity
237
-     *
238
-     * @throws InvalidArgumentException
239
-     *
240
-     * @return void
241
-     */
242
-    protected function checkEntityType($entity)
243
-    {
244
-        if (get_class($entity) != $this->entityMap->getClass() && !is_subclass_of($entity, $this->entityMap->getClass())) {
245
-            $expected = $this->entityMap->getClass();
246
-            $actual = get_class($entity);
247
-
248
-            throw new InvalidArgumentException("Expected : $expected, got $actual.");
249
-        }
250
-    }
251
-
252
-    /**
253
-     * Convert an entity into an aggregate root.
254
-     *
255
-     * @param mixed $entity
256
-     *
257
-     * @throws MappingException
258
-     *
259
-     * @return \Analogue\ORM\System\Aggregate
260
-     */
261
-    protected function aggregate($entity)
262
-    {
263
-        return new Aggregate($entity);
264
-    }
265
-
266
-    /**
267
-     * Get a the Underlying Query Builder.
268
-     *
269
-     * @return \Illuminate\Database\Query\Builder
270
-     */
271
-    public function newQueryBuilder()
272
-    {
273
-        return $this->adapter->getQuery();
274
-    }
275
-
276
-    /**
277
-     * Delete an entity or an entity collection from the database.
278
-     *
279
-     * @param  Mappable|\Traversable|array
280
-     *
281
-     * @throws MappingException
282
-     * @throws \InvalidArgumentException
283
-     *
284
-     * @return \Traversable|array
285
-     */
286
-    public function delete($entity)
287
-    {
288
-        if ($this->manager->isTraversable($entity)) {
289
-            return $this->deleteCollection($entity);
290
-        } else {
291
-            $this->deleteEntity($entity);
292
-        }
293
-    }
294
-
295
-    /**
296
-     * Delete an Entity Collection inside a single db transaction.
297
-     *
298
-     * @param \Traversable|array $entities
299
-     *
300
-     * @throws \InvalidArgumentException
301
-     * @throws MappingException
302
-     *
303
-     * @return \Traversable|array
304
-     */
305
-    protected function deleteCollection($entities)
306
-    {
307
-        $this->adapter->beginTransaction();
308
-
309
-        foreach ($entities as $entity) {
310
-            $this->deleteEntity($entity);
311
-        }
312
-
313
-        $this->adapter->commit();
314
-
315
-        return $entities;
316
-    }
317
-
318
-    /**
319
-     * Delete a single entity from the database.
320
-     *
321
-     * @param Mappable $entity
322
-     *
323
-     * @throws \InvalidArgumentException
324
-     * @throws MappingException
325
-     *
326
-     * @return void
327
-     */
328
-    protected function deleteEntity($entity)
329
-    {
330
-        $this->checkEntityType($entity);
331
-
332
-        $delete = new Delete($this->aggregate($entity), $this->newQueryBuilder());
333
-
334
-        $delete->execute();
335
-    }
336
-
337
-    /**
338
-     * Return the entity map for this mapper.
339
-     *
340
-     * @return EntityMap
341
-     */
342
-    public function getEntityMap()
343
-    {
344
-        return $this->entityMap;
345
-    }
346
-
347
-    /**
348
-     * Get the entity cache for the current mapper.
349
-     *
350
-     * @return \Analogue\ORM\System\Cache\AttributeCache
351
-     */
352
-    public function getEntityCache() : AttributeCache
353
-    {
354
-        return $this->cache;
355
-    }
356
-
357
-    /**
358
-     * Get the instance cache for the current mapper.
359
-     *
360
-     * @return \Analogue\ORM\System\Cache\InstanceCache
361
-     */
362
-    public function getInstanceCache() : InstanceCache
363
-    {
364
-        return $this->instances;
365
-    }
366
-
367
-    /**
368
-     * Reset all caches within the mapper.
369
-     *
370
-     * @return void
371
-     */
372
-    public function clearCache()
373
-    {
374
-        $this->cache->clear();
375
-        $this->instances->clear();
376
-    }
377
-
378
-    /**
379
-     * Fire the given event for the entity.
380
-     *
381
-     * @param string               $event
382
-     * @param \Analogue\ORM\Entity $entity
383
-     * @param bool                 $halt
384
-     *
385
-     * @throws InvalidArgumentException
386
-     *
387
-     * @return mixed
388
-     */
389
-    public function fireEvent($event, $entity, $halt = true)
390
-    {
391
-        /*if ($entity instanceof Wrapper) {
28
+	/**
29
+	 * The Manager instance.
30
+	 *
31
+	 * @var \Analogue\ORM\System\Manager
32
+	 */
33
+	protected $manager;
34
+
35
+	/**
36
+	 * Instance of EntityMapper Object.
37
+	 *
38
+	 * @var \Analogue\ORM\EntityMap
39
+	 */
40
+	protected $entityMap;
41
+
42
+	/**
43
+	 * The instance of db adapter.
44
+	 *
45
+	 * @var \Analogue\ORM\Drivers\DBAdapter
46
+	 */
47
+	protected $adapter;
48
+
49
+	/**
50
+	 * Event dispatcher instance.
51
+	 *
52
+	 * @var \Illuminate\Contracts\Events\Dispatcher
53
+	 */
54
+	protected $dispatcher;
55
+
56
+	/**
57
+	 * Entity Cache.
58
+	 *
59
+	 * @var \Analogue\ORM\System\Cache\AttributeCache
60
+	 */
61
+	protected $cache;
62
+
63
+	/**
64
+	 * Entity instances Object cache.
65
+	 *
66
+	 * @var \Analogue\ORM\System\Cache\InstanceCache
67
+	 */
68
+	protected $instances;
69
+
70
+	/**
71
+	 * Global scopes.
72
+	 *
73
+	 * @var array
74
+	 */
75
+	protected $globalScopes = [];
76
+
77
+	/**
78
+	 * Custom Commands.
79
+	 *
80
+	 * @var array
81
+	 */
82
+	protected $customCommands = [];
83
+
84
+	/**
85
+	 * Available Analogue Events.
86
+	 *
87
+	 * @var array
88
+	 */
89
+	protected $events = [
90
+		'initializing' => \Analogue\ORM\Events\Initializing::class,
91
+		'initialized'  => \Analogue\ORM\Events\Initialized::class,
92
+		'storing'      => \Analogue\ORM\Events\Storing::class,
93
+		'stored'       => \Analogue\ORM\Events\Stored::class,
94
+		'creating'     => \Analogue\ORM\Events\Creating::class,
95
+		'created'      => \Analogue\ORM\Events\Created::class,
96
+		'updating'     => \Analogue\ORM\Events\Updating::class,
97
+		'updated'      => \Analogue\ORM\Events\Updated::class,
98
+		'deleting'     => \Analogue\ORM\Events\Deleting::class,
99
+		'deleted'      => \Analogue\ORM\Events\Deleted::class,
100
+	];
101
+
102
+	/**
103
+	 * @param EntityMap  $entityMap
104
+	 * @param DBAdapter  $adapter
105
+	 * @param Dispatcher $dispatcher
106
+	 * @param Manager    $manager
107
+	 */
108
+	public function __construct(EntityMap $entityMap, DBAdapter $adapter, Dispatcher $dispatcher, Manager $manager)
109
+	{
110
+		$this->entityMap = $entityMap;
111
+
112
+		$this->adapter = $adapter;
113
+
114
+		$this->dispatcher = $dispatcher;
115
+
116
+		$this->manager = $manager;
117
+
118
+		$this->cache = new AttributeCache($entityMap);
119
+		$this->instances = new InstanceCache($entityMap->getClass());
120
+	}
121
+
122
+	/**
123
+	 * Map results to a Collection.
124
+	 *
125
+	 * @param array|Collection $results
126
+	 * @param array            $eagerLoads
127
+	 *
128
+	 * @return Collection
129
+	 */
130
+	public function map($results, array $eagerLoads = []) : Collection
131
+	{
132
+		$builder = new ResultBuilder($this);
133
+
134
+		if ($results instanceof Collection) {
135
+			// Get underlying collection array
136
+			$results = $results->all();
137
+		}
138
+
139
+		if (!is_array($results)) {
140
+			throw new InvalidArgumentException("'results' should be an array or collection.");
141
+		}
142
+
143
+		// First, we'll cast every single result to array
144
+		$results = array_map(function ($item) {
145
+			return (array) $item;
146
+		}, $results);
147
+
148
+		// Then, we'll pass the results to the Driver's provided transformer, so
149
+		// any DB specific value can be casted before hydration
150
+		$results = $this->adapter->fromDatabase($results);
151
+
152
+		// Then, we'll cache every single results as raw attributes, before
153
+		// adding relationships, which will be cached when the relationship's
154
+		// query takes place.
155
+		//$this->getEntityCache()->add($results);
156
+
157
+		$entities = $builder->build($results, $eagerLoads);
158
+
159
+		return $this->entityMap->newCollection($entities);
160
+	}
161
+
162
+	/**
163
+	 * Return all records for a mapped object.
164
+	 *
165
+	 * @return \Illuminate\Support\Collection
166
+	 */
167
+	public function all()
168
+	{
169
+		return $this->query()->get();
170
+	}
171
+
172
+	/**
173
+	 * Persist an entity or an entity collection into the database.
174
+	 *
175
+	 * @param Mappable|\Traversable|array $entity
176
+	 *
177
+	 * @throws \InvalidArgumentException
178
+	 * @throws MappingException
179
+	 *
180
+	 * @return Mappable|\Traversable|array
181
+	 */
182
+	public function store($entity)
183
+	{
184
+		if ($this->manager->isTraversable($entity)) {
185
+			return $this->storeCollection($entity);
186
+		} else {
187
+			return $this->storeEntity($entity);
188
+		}
189
+	}
190
+
191
+	/**
192
+	 * Store an entity collection inside a single DB Transaction.
193
+	 *
194
+	 * @param \Traversable|array $entities
195
+	 *
196
+	 * @throws \InvalidArgumentException
197
+	 * @throws MappingException
198
+	 *
199
+	 * @return \Traversable|array
200
+	 */
201
+	protected function storeCollection($entities)
202
+	{
203
+		$this->adapter->beginTransaction();
204
+
205
+		foreach ($entities as $entity) {
206
+			$this->storeEntity($entity);
207
+		}
208
+
209
+		$this->adapter->commit();
210
+
211
+		return $entities;
212
+	}
213
+
214
+	/**
215
+	 * Store a single entity into the database.
216
+	 *
217
+	 * @param Mappable $entity
218
+	 *
219
+	 * @throws \InvalidArgumentException
220
+	 * @throws MappingException
221
+	 *
222
+	 * @return \Analogue\ORM\Entity
223
+	 */
224
+	protected function storeEntity($entity)
225
+	{
226
+		$this->checkEntityType($entity);
227
+
228
+		$store = new Store($this->aggregate($entity), $this->newQueryBuilder());
229
+
230
+		return $store->execute();
231
+	}
232
+
233
+	/**
234
+	 * Check that the entity correspond to the current mapper.
235
+	 *
236
+	 * @param mixed $entity
237
+	 *
238
+	 * @throws InvalidArgumentException
239
+	 *
240
+	 * @return void
241
+	 */
242
+	protected function checkEntityType($entity)
243
+	{
244
+		if (get_class($entity) != $this->entityMap->getClass() && !is_subclass_of($entity, $this->entityMap->getClass())) {
245
+			$expected = $this->entityMap->getClass();
246
+			$actual = get_class($entity);
247
+
248
+			throw new InvalidArgumentException("Expected : $expected, got $actual.");
249
+		}
250
+	}
251
+
252
+	/**
253
+	 * Convert an entity into an aggregate root.
254
+	 *
255
+	 * @param mixed $entity
256
+	 *
257
+	 * @throws MappingException
258
+	 *
259
+	 * @return \Analogue\ORM\System\Aggregate
260
+	 */
261
+	protected function aggregate($entity)
262
+	{
263
+		return new Aggregate($entity);
264
+	}
265
+
266
+	/**
267
+	 * Get a the Underlying Query Builder.
268
+	 *
269
+	 * @return \Illuminate\Database\Query\Builder
270
+	 */
271
+	public function newQueryBuilder()
272
+	{
273
+		return $this->adapter->getQuery();
274
+	}
275
+
276
+	/**
277
+	 * Delete an entity or an entity collection from the database.
278
+	 *
279
+	 * @param  Mappable|\Traversable|array
280
+	 *
281
+	 * @throws MappingException
282
+	 * @throws \InvalidArgumentException
283
+	 *
284
+	 * @return \Traversable|array
285
+	 */
286
+	public function delete($entity)
287
+	{
288
+		if ($this->manager->isTraversable($entity)) {
289
+			return $this->deleteCollection($entity);
290
+		} else {
291
+			$this->deleteEntity($entity);
292
+		}
293
+	}
294
+
295
+	/**
296
+	 * Delete an Entity Collection inside a single db transaction.
297
+	 *
298
+	 * @param \Traversable|array $entities
299
+	 *
300
+	 * @throws \InvalidArgumentException
301
+	 * @throws MappingException
302
+	 *
303
+	 * @return \Traversable|array
304
+	 */
305
+	protected function deleteCollection($entities)
306
+	{
307
+		$this->adapter->beginTransaction();
308
+
309
+		foreach ($entities as $entity) {
310
+			$this->deleteEntity($entity);
311
+		}
312
+
313
+		$this->adapter->commit();
314
+
315
+		return $entities;
316
+	}
317
+
318
+	/**
319
+	 * Delete a single entity from the database.
320
+	 *
321
+	 * @param Mappable $entity
322
+	 *
323
+	 * @throws \InvalidArgumentException
324
+	 * @throws MappingException
325
+	 *
326
+	 * @return void
327
+	 */
328
+	protected function deleteEntity($entity)
329
+	{
330
+		$this->checkEntityType($entity);
331
+
332
+		$delete = new Delete($this->aggregate($entity), $this->newQueryBuilder());
333
+
334
+		$delete->execute();
335
+	}
336
+
337
+	/**
338
+	 * Return the entity map for this mapper.
339
+	 *
340
+	 * @return EntityMap
341
+	 */
342
+	public function getEntityMap()
343
+	{
344
+		return $this->entityMap;
345
+	}
346
+
347
+	/**
348
+	 * Get the entity cache for the current mapper.
349
+	 *
350
+	 * @return \Analogue\ORM\System\Cache\AttributeCache
351
+	 */
352
+	public function getEntityCache() : AttributeCache
353
+	{
354
+		return $this->cache;
355
+	}
356
+
357
+	/**
358
+	 * Get the instance cache for the current mapper.
359
+	 *
360
+	 * @return \Analogue\ORM\System\Cache\InstanceCache
361
+	 */
362
+	public function getInstanceCache() : InstanceCache
363
+	{
364
+		return $this->instances;
365
+	}
366
+
367
+	/**
368
+	 * Reset all caches within the mapper.
369
+	 *
370
+	 * @return void
371
+	 */
372
+	public function clearCache()
373
+	{
374
+		$this->cache->clear();
375
+		$this->instances->clear();
376
+	}
377
+
378
+	/**
379
+	 * Fire the given event for the entity.
380
+	 *
381
+	 * @param string               $event
382
+	 * @param \Analogue\ORM\Entity $entity
383
+	 * @param bool                 $halt
384
+	 *
385
+	 * @throws InvalidArgumentException
386
+	 *
387
+	 * @return mixed
388
+	 */
389
+	public function fireEvent($event, $entity, $halt = true)
390
+	{
391
+		/*if ($entity instanceof Wrapper) {
392 392
             throw new InvalidArgumentException('Fired Event with invalid Entity Object');
393 393
         }*/
394 394
 
395
-        $eventName = "analogue.{$event}.".$this->entityMap->getClass();
396
-
397
-        $method = $halt ? 'until' : 'fire';
398
-
399
-        if (!array_key_exists($event, $this->events)) {
400
-            throw new \LogicException("Analogue : Event $event doesn't exist");
401
-        }
402
-
403
-        $eventClass = $this->events[$event];
404
-        $event = new $eventClass($entity);
405
-
406
-        return $this->dispatcher->$method($eventName, $event);
407
-    }
408
-
409
-    /**
410
-     * Register an entity event with the dispatcher.
411
-     *
412
-     * @param string   $event
413
-     * @param \Closure $callback
414
-     *
415
-     * @return void
416
-     */
417
-    public function registerEvent($event, $callback)
418
-    {
419
-        $name = $this->entityMap->getClass();
420
-
421
-        $this->dispatcher->listen("analogue.{$event}.{$name}", $callback);
422
-    }
423
-
424
-    /**
425
-     * Add a global scope to this mapper query builder.
426
-     *
427
-     * @param ScopeInterface $scope
428
-     *
429
-     * @return void
430
-     */
431
-    public function addGlobalScope(ScopeInterface $scope)
432
-    {
433
-        $this->globalScopes[get_class($scope)] = $scope;
434
-    }
435
-
436
-    /**
437
-     * Determine if the mapper has a global scope.
438
-     *
439
-     * @param \Analogue\ORM\System\ScopeInterface $scope
440
-     *
441
-     * @return bool
442
-     */
443
-    public function hasGlobalScope($scope)
444
-    {
445
-        return !is_null($this->getGlobalScope($scope));
446
-    }
447
-
448
-    /**
449
-     * Get a global scope registered with the modal.
450
-     *
451
-     * @param \Analogue\ORM\System\ScopeInterface $scope
452
-     *
453
-     * @return \Analogue\ORM\System\ScopeInterface|null
454
-     */
455
-    public function getGlobalScope($scope)
456
-    {
457
-        return array_first($this->globalScopes, function ($key, $value) use ($scope) {
458
-            return $scope instanceof $value;
459
-        });
460
-    }
461
-
462
-    /**
463
-     * Get a new query instance without a given scope.
464
-     *
465
-     * @param \Analogue\ORM\System\ScopeInterface $scope
466
-     *
467
-     * @return \Analogue\ORM\System\Query
468
-     */
469
-    public function newQueryWithoutScope($scope)
470
-    {
471
-        $this->getGlobalScope($scope)->remove($query = $this->getQuery(), $this);
472
-
473
-        return $query;
474
-    }
475
-
476
-    /**
477
-     * Get the Analogue Query Builder for this instance.
478
-     *
479
-     * @return \Analogue\ORM\System\Query
480
-     */
481
-    public function getQuery()
482
-    {
483
-        $query = new Query($this, $this->adapter);
484
-
485
-        return $this->applyGlobalScopes($query);
486
-    }
487
-
488
-    /**
489
-     * Apply all of the global scopes to an Analogue Query builder.
490
-     *
491
-     * @param Query $query
492
-     *
493
-     * @return \Analogue\ORM\System\Query
494
-     */
495
-    public function applyGlobalScopes($query)
496
-    {
497
-        foreach ($this->getGlobalScopes() as $scope) {
498
-            $scope->apply($query, $this);
499
-        }
500
-
501
-        return $query;
502
-    }
503
-
504
-    /**
505
-     * Get the global scopes for this class instance.
506
-     *
507
-     * @return \Analogue\ORM\System\ScopeInterface
508
-     */
509
-    public function getGlobalScopes()
510
-    {
511
-        return $this->globalScopes;
512
-    }
513
-
514
-    /**
515
-     * Add a dynamic method that extends the mapper/repository.
516
-     *
517
-     * @param string $command
518
-     */
519
-    public function addCustomCommand($command)
520
-    {
521
-        $name = lcfirst(class_basename($command));
522
-
523
-        $this->customCommands[$name] = $command;
524
-    }
525
-
526
-    /**
527
-     * Create a new instance of the mapped entity class.
528
-     *
529
-     * @return mixed
530
-     */
531
-    public function newInstance()
532
-    {
533
-        $class = $this->entityMap->getClass();
534
-
535
-        if ($this->entityMap->useDependencyInjection()) {
536
-            return $this->newInstanceUsingDependencyInjection($class);
537
-        }
538
-
539
-        return $this->newInstanceUsingInstantiator($class);
540
-    }
541
-
542
-    /**
543
-     * Return a new object instance using dependency injection.
544
-     *
545
-     * @param string $class
546
-     *
547
-     * @throws ErrorException
548
-     *
549
-     * @return mixed
550
-     */
551
-    protected function newInstanceUsingDependencyInjection($class)
552
-    {
553
-        if (!class_exists(Container::class)) {
554
-            throw new ErrorException("Illuminate\Container\Container is required to use Dependency Injection");
555
-        }
556
-
557
-        return Container::getInstance()->make($class);
558
-    }
559
-
560
-    /**
561
-     * Return a new object instance using doctrine's instantiator.
562
-     *
563
-     * @param string $class
564
-     *
565
-     * @return mixed
566
-     */
567
-    protected function newInstanceUsingInstantiator($class)
568
-    {
569
-        $instantiator = new \Doctrine\Instantiator\Instantiator();
570
-
571
-        return $instantiator->instantiate($class);
572
-    }
573
-
574
-    /**
575
-     * Get an unscoped Analogue Query Builder for this instance.
576
-     *
577
-     * @return \Analogue\ORM\System\Query
578
-     */
579
-    public function globalQuery()
580
-    {
581
-        return $this->newQueryWithoutScopes();
582
-    }
583
-
584
-    /**
585
-     * Get a new query builder that doesn't have any global scopes.
586
-     *
587
-     * @return Query
588
-     */
589
-    public function newQueryWithoutScopes()
590
-    {
591
-        return $this->removeGlobalScopes($this->getQuery());
592
-    }
593
-
594
-    /**
595
-     * Remove all of the global scopes from an Analogue Query builder.
596
-     *
597
-     * @param Query $query
598
-     *
599
-     * @return \Analogue\ORM\System\Query
600
-     */
601
-    public function removeGlobalScopes($query)
602
-    {
603
-        foreach ($this->getGlobalScopes() as $scope) {
604
-            $scope->remove($query, $this);
605
-        }
606
-
607
-        return $query;
608
-    }
609
-
610
-    /**
611
-     * Return the manager instance.
612
-     *
613
-     * @return \Analogue\ORM\System\Manager
614
-     */
615
-    public function getManager()
616
-    {
617
-        return $this->manager;
618
-    }
619
-
620
-    /**
621
-     * Dynamically handle calls to custom commands, or Redirects to query().
622
-     *
623
-     * @param string $method
624
-     * @param array  $parameters
625
-     *
626
-     * @throws \Exception
627
-     *
628
-     * @return mixed
629
-     */
630
-    public function __call($method, $parameters)
631
-    {
632
-        // Check if method is a custom command on the mapper
633
-        if ($this->hasCustomCommand($method)) {
634
-            if (count($parameters) == 0) {
635
-                throw new \Exception("$method must at least have 1 argument");
636
-            }
637
-
638
-            return $this->executeCustomCommand($method, $parameters[0]);
639
-        }
640
-
641
-        // Redirect call on a new query instance
642
-        return call_user_func_array([$this->query(), $method], $parameters);
643
-    }
644
-
645
-    /**
646
-     * Check if this mapper supports this command.
647
-     *
648
-     * @param string $command
649
-     *
650
-     * @return bool
651
-     */
652
-    public function hasCustomCommand($command)
653
-    {
654
-        return in_array($command, $this->getCustomCommands());
655
-    }
656
-
657
-    /**
658
-     * Get all the custom commands registered on this mapper.
659
-     *
660
-     * @return array
661
-     */
662
-    public function getCustomCommands()
663
-    {
664
-        return array_keys($this->customCommands);
665
-    }
666
-
667
-    /**
668
-     * Execute a custom command on an Entity.
669
-     *
670
-     * @param string                 $command
671
-     * @param mixed|Collection|array $entity
672
-     *
673
-     * @throws \InvalidArgumentException
674
-     * @throws MappingException
675
-     *
676
-     * @return mixed
677
-     */
678
-    public function executeCustomCommand($command, $entity)
679
-    {
680
-        $commandClass = $this->customCommands[$command];
681
-
682
-        if ($this->manager->isTraversable($entity)) {
683
-            foreach ($entity as $instance) {
684
-                $this->executeSingleCustomCommand($commandClass, $instance);
685
-            }
686
-        } else {
687
-            return $this->executeSingleCustomCommand($commandClass, $entity);
688
-        }
689
-    }
690
-
691
-    /**
692
-     * Execute a single command instance.
693
-     *
694
-     * @param string $commandClass
695
-     * @param mixed  $entity
696
-     *
697
-     * @throws \InvalidArgumentException
698
-     * @throws MappingException
699
-     *
700
-     * @return mixed
701
-     */
702
-    protected function executeSingleCustomCommand($commandClass, $entity)
703
-    {
704
-        $this->checkEntityType($entity);
705
-
706
-        $instance = new $commandClass($this->aggregate($entity), $this->newQueryBuilder());
707
-
708
-        return $instance->execute();
709
-    }
710
-
711
-    /**
712
-     * Get the Analogue Query Builder for this instance.
713
-     *
714
-     * @return \Analogue\ORM\System\Query
715
-     */
716
-    public function query()
717
-    {
718
-        return $this->getQuery();
719
-    }
395
+		$eventName = "analogue.{$event}.".$this->entityMap->getClass();
396
+
397
+		$method = $halt ? 'until' : 'fire';
398
+
399
+		if (!array_key_exists($event, $this->events)) {
400
+			throw new \LogicException("Analogue : Event $event doesn't exist");
401
+		}
402
+
403
+		$eventClass = $this->events[$event];
404
+		$event = new $eventClass($entity);
405
+
406
+		return $this->dispatcher->$method($eventName, $event);
407
+	}
408
+
409
+	/**
410
+	 * Register an entity event with the dispatcher.
411
+	 *
412
+	 * @param string   $event
413
+	 * @param \Closure $callback
414
+	 *
415
+	 * @return void
416
+	 */
417
+	public function registerEvent($event, $callback)
418
+	{
419
+		$name = $this->entityMap->getClass();
420
+
421
+		$this->dispatcher->listen("analogue.{$event}.{$name}", $callback);
422
+	}
423
+
424
+	/**
425
+	 * Add a global scope to this mapper query builder.
426
+	 *
427
+	 * @param ScopeInterface $scope
428
+	 *
429
+	 * @return void
430
+	 */
431
+	public function addGlobalScope(ScopeInterface $scope)
432
+	{
433
+		$this->globalScopes[get_class($scope)] = $scope;
434
+	}
435
+
436
+	/**
437
+	 * Determine if the mapper has a global scope.
438
+	 *
439
+	 * @param \Analogue\ORM\System\ScopeInterface $scope
440
+	 *
441
+	 * @return bool
442
+	 */
443
+	public function hasGlobalScope($scope)
444
+	{
445
+		return !is_null($this->getGlobalScope($scope));
446
+	}
447
+
448
+	/**
449
+	 * Get a global scope registered with the modal.
450
+	 *
451
+	 * @param \Analogue\ORM\System\ScopeInterface $scope
452
+	 *
453
+	 * @return \Analogue\ORM\System\ScopeInterface|null
454
+	 */
455
+	public function getGlobalScope($scope)
456
+	{
457
+		return array_first($this->globalScopes, function ($key, $value) use ($scope) {
458
+			return $scope instanceof $value;
459
+		});
460
+	}
461
+
462
+	/**
463
+	 * Get a new query instance without a given scope.
464
+	 *
465
+	 * @param \Analogue\ORM\System\ScopeInterface $scope
466
+	 *
467
+	 * @return \Analogue\ORM\System\Query
468
+	 */
469
+	public function newQueryWithoutScope($scope)
470
+	{
471
+		$this->getGlobalScope($scope)->remove($query = $this->getQuery(), $this);
472
+
473
+		return $query;
474
+	}
475
+
476
+	/**
477
+	 * Get the Analogue Query Builder for this instance.
478
+	 *
479
+	 * @return \Analogue\ORM\System\Query
480
+	 */
481
+	public function getQuery()
482
+	{
483
+		$query = new Query($this, $this->adapter);
484
+
485
+		return $this->applyGlobalScopes($query);
486
+	}
487
+
488
+	/**
489
+	 * Apply all of the global scopes to an Analogue Query builder.
490
+	 *
491
+	 * @param Query $query
492
+	 *
493
+	 * @return \Analogue\ORM\System\Query
494
+	 */
495
+	public function applyGlobalScopes($query)
496
+	{
497
+		foreach ($this->getGlobalScopes() as $scope) {
498
+			$scope->apply($query, $this);
499
+		}
500
+
501
+		return $query;
502
+	}
503
+
504
+	/**
505
+	 * Get the global scopes for this class instance.
506
+	 *
507
+	 * @return \Analogue\ORM\System\ScopeInterface
508
+	 */
509
+	public function getGlobalScopes()
510
+	{
511
+		return $this->globalScopes;
512
+	}
513
+
514
+	/**
515
+	 * Add a dynamic method that extends the mapper/repository.
516
+	 *
517
+	 * @param string $command
518
+	 */
519
+	public function addCustomCommand($command)
520
+	{
521
+		$name = lcfirst(class_basename($command));
522
+
523
+		$this->customCommands[$name] = $command;
524
+	}
525
+
526
+	/**
527
+	 * Create a new instance of the mapped entity class.
528
+	 *
529
+	 * @return mixed
530
+	 */
531
+	public function newInstance()
532
+	{
533
+		$class = $this->entityMap->getClass();
534
+
535
+		if ($this->entityMap->useDependencyInjection()) {
536
+			return $this->newInstanceUsingDependencyInjection($class);
537
+		}
538
+
539
+		return $this->newInstanceUsingInstantiator($class);
540
+	}
541
+
542
+	/**
543
+	 * Return a new object instance using dependency injection.
544
+	 *
545
+	 * @param string $class
546
+	 *
547
+	 * @throws ErrorException
548
+	 *
549
+	 * @return mixed
550
+	 */
551
+	protected function newInstanceUsingDependencyInjection($class)
552
+	{
553
+		if (!class_exists(Container::class)) {
554
+			throw new ErrorException("Illuminate\Container\Container is required to use Dependency Injection");
555
+		}
556
+
557
+		return Container::getInstance()->make($class);
558
+	}
559
+
560
+	/**
561
+	 * Return a new object instance using doctrine's instantiator.
562
+	 *
563
+	 * @param string $class
564
+	 *
565
+	 * @return mixed
566
+	 */
567
+	protected function newInstanceUsingInstantiator($class)
568
+	{
569
+		$instantiator = new \Doctrine\Instantiator\Instantiator();
570
+
571
+		return $instantiator->instantiate($class);
572
+	}
573
+
574
+	/**
575
+	 * Get an unscoped Analogue Query Builder for this instance.
576
+	 *
577
+	 * @return \Analogue\ORM\System\Query
578
+	 */
579
+	public function globalQuery()
580
+	{
581
+		return $this->newQueryWithoutScopes();
582
+	}
583
+
584
+	/**
585
+	 * Get a new query builder that doesn't have any global scopes.
586
+	 *
587
+	 * @return Query
588
+	 */
589
+	public function newQueryWithoutScopes()
590
+	{
591
+		return $this->removeGlobalScopes($this->getQuery());
592
+	}
593
+
594
+	/**
595
+	 * Remove all of the global scopes from an Analogue Query builder.
596
+	 *
597
+	 * @param Query $query
598
+	 *
599
+	 * @return \Analogue\ORM\System\Query
600
+	 */
601
+	public function removeGlobalScopes($query)
602
+	{
603
+		foreach ($this->getGlobalScopes() as $scope) {
604
+			$scope->remove($query, $this);
605
+		}
606
+
607
+		return $query;
608
+	}
609
+
610
+	/**
611
+	 * Return the manager instance.
612
+	 *
613
+	 * @return \Analogue\ORM\System\Manager
614
+	 */
615
+	public function getManager()
616
+	{
617
+		return $this->manager;
618
+	}
619
+
620
+	/**
621
+	 * Dynamically handle calls to custom commands, or Redirects to query().
622
+	 *
623
+	 * @param string $method
624
+	 * @param array  $parameters
625
+	 *
626
+	 * @throws \Exception
627
+	 *
628
+	 * @return mixed
629
+	 */
630
+	public function __call($method, $parameters)
631
+	{
632
+		// Check if method is a custom command on the mapper
633
+		if ($this->hasCustomCommand($method)) {
634
+			if (count($parameters) == 0) {
635
+				throw new \Exception("$method must at least have 1 argument");
636
+			}
637
+
638
+			return $this->executeCustomCommand($method, $parameters[0]);
639
+		}
640
+
641
+		// Redirect call on a new query instance
642
+		return call_user_func_array([$this->query(), $method], $parameters);
643
+	}
644
+
645
+	/**
646
+	 * Check if this mapper supports this command.
647
+	 *
648
+	 * @param string $command
649
+	 *
650
+	 * @return bool
651
+	 */
652
+	public function hasCustomCommand($command)
653
+	{
654
+		return in_array($command, $this->getCustomCommands());
655
+	}
656
+
657
+	/**
658
+	 * Get all the custom commands registered on this mapper.
659
+	 *
660
+	 * @return array
661
+	 */
662
+	public function getCustomCommands()
663
+	{
664
+		return array_keys($this->customCommands);
665
+	}
666
+
667
+	/**
668
+	 * Execute a custom command on an Entity.
669
+	 *
670
+	 * @param string                 $command
671
+	 * @param mixed|Collection|array $entity
672
+	 *
673
+	 * @throws \InvalidArgumentException
674
+	 * @throws MappingException
675
+	 *
676
+	 * @return mixed
677
+	 */
678
+	public function executeCustomCommand($command, $entity)
679
+	{
680
+		$commandClass = $this->customCommands[$command];
681
+
682
+		if ($this->manager->isTraversable($entity)) {
683
+			foreach ($entity as $instance) {
684
+				$this->executeSingleCustomCommand($commandClass, $instance);
685
+			}
686
+		} else {
687
+			return $this->executeSingleCustomCommand($commandClass, $entity);
688
+		}
689
+	}
690
+
691
+	/**
692
+	 * Execute a single command instance.
693
+	 *
694
+	 * @param string $commandClass
695
+	 * @param mixed  $entity
696
+	 *
697
+	 * @throws \InvalidArgumentException
698
+	 * @throws MappingException
699
+	 *
700
+	 * @return mixed
701
+	 */
702
+	protected function executeSingleCustomCommand($commandClass, $entity)
703
+	{
704
+		$this->checkEntityType($entity);
705
+
706
+		$instance = new $commandClass($this->aggregate($entity), $this->newQueryBuilder());
707
+
708
+		return $instance->execute();
709
+	}
710
+
711
+	/**
712
+	 * Get the Analogue Query Builder for this instance.
713
+	 *
714
+	 * @return \Analogue\ORM\System\Query
715
+	 */
716
+	public function query()
717
+	{
718
+		return $this->getQuery();
719
+	}
720 720
 }
Please login to merge, or discard this patch.
src/Plugins/SoftDeletes/SoftDeletesPlugin.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -25,7 +25,7 @@  discard block
 block discarded – undo
25 25
         $host = $this;
26 26
 
27 27
         // Hook any mapper init and check the mapping include soft deletes.
28
-        $this->manager->registerGlobalEvent('initialized', function ($event, $payload = null) use ($host) {
28
+        $this->manager->registerGlobalEvent('initialized', function($event, $payload = null) use ($host) {
29 29
 
30 30
             // Cross Compatible Event handling with 5.3
31 31
             // TODO : find a replacement event handler
@@ -63,7 +63,7 @@  discard block
 block discarded – undo
63 63
         $host = $this;
64 64
 
65 65
         // Register 'deleting' events
66
-        $mapper->registerEvent('deleting', function ($entity) use ($entityMap, $host) {
66
+        $mapper->registerEvent('deleting', function($entity) use ($entityMap, $host) {
67 67
 
68 68
             // Convert Entity into an EntityWrapper
69 69
             $factory = new Factory();
Please login to merge, or discard this patch.
Indentation   +83 added lines, -83 removed lines patch added patch discarded remove patch
@@ -13,87 +13,87 @@
 block discarded – undo
13 13
  */
14 14
 class SoftDeletesPlugin extends AnaloguePlugin
15 15
 {
16
-    /**
17
-     * {@inheritdoc}
18
-     */
19
-    public function register()
20
-    {
21
-        $host = $this;
22
-
23
-        // Hook any mapper init and check the mapping include soft deletes.
24
-        $this->manager->registerGlobalEvent('initialized', function ($event, $payload = null) use ($host) {
25
-
26
-            // Cross Compatible Event handling with 5.3
27
-            // TODO : find a replacement event handler
28
-            if (is_null($payload)) {
29
-                $mapper = $event;
30
-            } else {
31
-                $mapper = $payload[0]->mapper;
32
-            }
33
-
34
-            $entityMap = $mapper->getEntityMap();
35
-
36
-            if ($entityMap->usesSoftDeletes()) {
37
-                $host->registerSoftDelete($mapper);
38
-            }
39
-        });
40
-    }
41
-
42
-    /**
43
-     * By hooking to the mapper initialization event, we can extend it
44
-     * with the softDelete capacity.
45
-     *
46
-     * @param \Analogue\ORM\System\Mapper $mapper
47
-     *
48
-     * @throws \Analogue\ORM\Exceptions\MappingException
49
-     *
50
-     * @return bool|void
51
-     */
52
-    protected function registerSoftDelete(Mapper $mapper)
53
-    {
54
-        $entityMap = $mapper->getEntityMap();
55
-
56
-        // Add Scopes
57
-        $mapper->addGlobalScope(new SoftDeletingScope());
58
-
59
-        $host = $this;
60
-
61
-        // Register 'deleting' events
62
-        $mapper->registerEvent('deleting', function ($entity) use ($entityMap, $host) {
63
-
64
-            // Convert Entity into an EntityWrapper
65
-            $factory = new Factory();
66
-
67
-            $wrappedEntity = $factory->make($entity);
68
-
69
-            $deletedAtField = $entityMap->getQualifiedDeletedAtColumn();
70
-
71
-            if (!is_null($wrappedEntity->getEntityAttribute($deletedAtField))) {
72
-                return true;
73
-            }
74
-
75
-            $time = new Carbon();
76
-
77
-            $wrappedEntity->setEntityAttribute($deletedAtField, $time);
78
-
79
-            $plainObject = $wrappedEntity->getObject();
80
-            $host->manager->mapper(get_class($plainObject))->store($plainObject);
81
-
82
-            return false;
83
-        });
84
-
85
-        // Register RestoreCommand
86
-        $mapper->addCustomCommand(Restore::class);
87
-    }
88
-
89
-    /**
90
-     * {@inheritdoc}
91
-     */
92
-    public function getCustomEvents(): array
93
-    {
94
-        return [
95
-            'restoring',
96
-            'restored',
97
-        ];
98
-    }
16
+	/**
17
+	 * {@inheritdoc}
18
+	 */
19
+	public function register()
20
+	{
21
+		$host = $this;
22
+
23
+		// Hook any mapper init and check the mapping include soft deletes.
24
+		$this->manager->registerGlobalEvent('initialized', function ($event, $payload = null) use ($host) {
25
+
26
+			// Cross Compatible Event handling with 5.3
27
+			// TODO : find a replacement event handler
28
+			if (is_null($payload)) {
29
+				$mapper = $event;
30
+			} else {
31
+				$mapper = $payload[0]->mapper;
32
+			}
33
+
34
+			$entityMap = $mapper->getEntityMap();
35
+
36
+			if ($entityMap->usesSoftDeletes()) {
37
+				$host->registerSoftDelete($mapper);
38
+			}
39
+		});
40
+	}
41
+
42
+	/**
43
+	 * By hooking to the mapper initialization event, we can extend it
44
+	 * with the softDelete capacity.
45
+	 *
46
+	 * @param \Analogue\ORM\System\Mapper $mapper
47
+	 *
48
+	 * @throws \Analogue\ORM\Exceptions\MappingException
49
+	 *
50
+	 * @return bool|void
51
+	 */
52
+	protected function registerSoftDelete(Mapper $mapper)
53
+	{
54
+		$entityMap = $mapper->getEntityMap();
55
+
56
+		// Add Scopes
57
+		$mapper->addGlobalScope(new SoftDeletingScope());
58
+
59
+		$host = $this;
60
+
61
+		// Register 'deleting' events
62
+		$mapper->registerEvent('deleting', function ($entity) use ($entityMap, $host) {
63
+
64
+			// Convert Entity into an EntityWrapper
65
+			$factory = new Factory();
66
+
67
+			$wrappedEntity = $factory->make($entity);
68
+
69
+			$deletedAtField = $entityMap->getQualifiedDeletedAtColumn();
70
+
71
+			if (!is_null($wrappedEntity->getEntityAttribute($deletedAtField))) {
72
+				return true;
73
+			}
74
+
75
+			$time = new Carbon();
76
+
77
+			$wrappedEntity->setEntityAttribute($deletedAtField, $time);
78
+
79
+			$plainObject = $wrappedEntity->getObject();
80
+			$host->manager->mapper(get_class($plainObject))->store($plainObject);
81
+
82
+			return false;
83
+		});
84
+
85
+		// Register RestoreCommand
86
+		$mapper->addCustomCommand(Restore::class);
87
+	}
88
+
89
+	/**
90
+	 * {@inheritdoc}
91
+	 */
92
+	public function getCustomEvents(): array
93
+	{
94
+		return [
95
+			'restoring',
96
+			'restored',
97
+		];
98
+	}
99 99
 }
Please login to merge, or discard this patch.