Completed
Pull Request — 5.1 (#144)
by
unknown
04:02
created
src/EntityMap.php 2 patches
Doc Comments   +5 added lines patch added patch discarded remove patch
@@ -1219,6 +1219,11 @@
 block discarded – undo
1219 1219
         return $array;
1220 1220
     }
1221 1221
 
1222
+    /**
1223
+     * @param string $column_name
1224
+     *
1225
+     * @return string
1226
+     */
1222 1227
     public function mapColumnToAttribute($column_name)
1223 1228
     {
1224 1229
         $attributes = $this->getAttributes();
Please login to merge, or discard this patch.
Indentation   +1245 added lines, -1245 removed lines patch added patch discarded remove patch
@@ -23,1263 +23,1263 @@
 block discarded – undo
23 23
  */
24 24
 class EntityMap
25 25
 {
26
-    /**
27
-     * The mapping driver to use with this entity
28
-     */
29
-    protected $driver = 'illuminate';
30
-
31
-    /**
32
-     * The Database Connection name for the model.
33
-     *
34
-     * @var string
35
-     */
36
-    protected $connection;
37
-
38
-    /**
39
-     * The table associated with the entity.
40
-     *
41
-     * @var string|null
42
-     */
43
-    protected $table = null;
44
-
45
-    /**
46
-     * The primary key for the model.
47
-     *
48
-     * @var string
49
-     */
50
-    protected $primaryKey = 'id';
51
-
52
-    /**
53
-     * Array containing a list of class attributes. Mandatory if the
54
-     * mapped entity is a Plain PHP Object.
55
-     *
56
-     * @var array
57
-     */
58
-    protected $attributes = [];
59
-
60
-    /**
61
-     * The Custom Domain Class to use with this mapping
62
-     *
63
-     * @var string|null
64
-     */
65
-    protected $class = null;
66
-
67
-    /**
68
-     * Attributes that should be treated as Value Objects
69
-     *
70
-     * @var array
71
-     */
72
-    protected $embeddables = [];
26
+	/**
27
+	 * The mapping driver to use with this entity
28
+	 */
29
+	protected $driver = 'illuminate';
30
+
31
+	/**
32
+	 * The Database Connection name for the model.
33
+	 *
34
+	 * @var string
35
+	 */
36
+	protected $connection;
37
+
38
+	/**
39
+	 * The table associated with the entity.
40
+	 *
41
+	 * @var string|null
42
+	 */
43
+	protected $table = null;
44
+
45
+	/**
46
+	 * The primary key for the model.
47
+	 *
48
+	 * @var string
49
+	 */
50
+	protected $primaryKey = 'id';
51
+
52
+	/**
53
+	 * Array containing a list of class attributes. Mandatory if the
54
+	 * mapped entity is a Plain PHP Object.
55
+	 *
56
+	 * @var array
57
+	 */
58
+	protected $attributes = [];
59
+
60
+	/**
61
+	 * The Custom Domain Class to use with this mapping
62
+	 *
63
+	 * @var string|null
64
+	 */
65
+	protected $class = null;
66
+
67
+	/**
68
+	 * Attributes that should be treated as Value Objects
69
+	 *
70
+	 * @var array
71
+	 */
72
+	protected $embeddables = [];
73 73
         
74
-    /**
75
-     * Determine the relationships method used on the entity.
76
-     * If not set, mapper will autodetect them
77
-     *
78
-     * @var array
79
-     */
80
-    private $relationships = [];
81
-
82
-    /**
83
-     * Relationships that should be treated as collection.
84
-     *
85
-     * @var array
86
-     */
87
-    private $manyRelations = [];
88
-
89
-    /**
90
-     * Relationships that should be treated as single entity.
91
-     *
92
-     * @var array
93
-     */
94
-    private $singleRelations = [];
95
-
96
-    /**
97
-     * Relationships for which the key is stored in the Entity itself
98
-     *
99
-     * @var array
100
-     */
101
-    private $localRelations = [];
102
-
103
-    /**
104
-     * Relationships for which the key is stored in the Related Entity
105
-     *
106
-     * @var array
107
-     */
108
-    private $foreignRelations = [];
109
-
110
-    /**
111
-     * Relationships which use a pivot record.
112
-     *
113
-     * @var array
114
-     */
115
-    private $pivotRelations = [];
116
-
117
-    /**
118
-     * Dynamic relationships
119
-     *
120
-     * @var array
121
-     */
122
-    private $dynamicRelationships = [];
123
-
124
-    /**
125
-     * The number of models to return for pagination.
126
-     *
127
-     * @var int
128
-     */
129
-    protected $perPage = 15;
130
-
131
-    /**
132
-     * The relations to eager load on every query.
133
-     *
134
-     * @var array
135
-     */
136
-    protected $with = [];
137
-
138
-    /**
139
-     * The class name to be used in polymorphic relations.
140
-     *
141
-     * @var string
142
-     */
143
-    protected $morphClass;
144
-
145
-    /**
146
-     * Sequence name, to be used with postgreSql
147
-     * defaults to %table_name%_id_seq
148
-     *
149
-     * @var string|null
150
-     */
151
-    protected $sequence = null;
152
-
153
-    /**
154
-     * Indicates if the entity should be timestamped.
155
-     *
156
-     * @var bool
157
-     */
158
-    public $timestamps = false;
159
-
160
-    /**
161
-     * The name of the "created at" column.
162
-     *
163
-     * @var string
164
-     */
165
-    protected $createdAtColumn = 'created_at';
166
-
167
-    /**
168
-     * The name of the "updated at" column.
169
-     *
170
-     * @var string
171
-     */
172
-    protected $updatedAtColumn = 'updated_at';
173
-
174
-    /**
175
-     * Indicates if the entity uses softdeletes
176
-     *
177
-     * @var boolean
178
-     */
179
-    public $softDeletes = false;
180
-
181
-    /**
182
-     * The name of the "deleted at" column.
183
-     *
184
-     * @var string
185
-     */
186
-    protected $deletedAtColumn = 'deleted_at';
187
-
188
-    /**
189
-     * The many to many relationship methods.
190
-     *
191
-     * @var array
192
-     */
193
-    protected static $manyMethods = ['belongsToMany', 'morphToMany', 'morphedByMany'];
194
-
195
-    /**
196
-     * The 'Many' relationships classes, which related Entity attribute should be
197
-     * an array/entityCollection
198
-     *
199
-     * @var array
200
-     */
201
-    protected static $manyClasses = ['BelongsToMany', 'HasMany', 'HasManyThrough', 'MorphMany', 'MorphToMany'];
202
-
203
-    /**
204
-     * The 'Single' relationships classes, which related Entity attribute should be
205
-     * another Entity.
206
-     *
207
-     * @var array
208
-     */
209
-    protected static $singleClasses = ['BelongsTo', 'HasOne', 'MorphOne', 'MorphTo'];
210
-
211
-    /**
212
-     * Relationships with a pivot record
213
-     *
214
-     * @var array
215
-     */
216
-    protected static $pivotClasses = ['BelongsToMany', 'MorphToMany'];
217
-
218
-    /**
219
-     * Relationships on which key is stored in the Entity itself
220
-     *
221
-     * @var array
222
-     */
223
-    protected static $localClasses = ['BelongsTo', 'MorphTo'];
224
-
225
-    /**
226
-     * Relationships on which key is stored in the related Entity record or in a pivot record
227
-     *
228
-     * @var array
229
-     */
230
-    protected static $foreignClasses = [
231
-        'BelongsToMany',
232
-        'HasMany',
233
-        'HasManyThrough',
234
-        'MorphMany',
235
-        'MorphToMany',
236
-        'HasOne',
237
-        'MorphOne',
238
-    ];
239
-
240
-    /**
241
-     * The date format to use with the current database connection
242
-     *
243
-     * @var string
244
-     */
245
-    protected $dateFormat;
246
-
247
-    /**
248
-     * The Analogue's manager instance.
249
-     *
250
-     * @var \Analogue\ORM\System\Manager
251
-     */
252
-    private $manager;
253
-
254
-    /**
255
-     * Set the Manager that will be used for relationship's mapper instantiations.
256
-     *
257
-     * @param Manager $manager
258
-     */
259
-    public function setManager(Manager $manager)
260
-    {
261
-        $this->manager = $manager;
262
-    }
263
-
264
-    /**
265
-     * Return Domain class attributes, useful when mapping to a Plain PHP Object
266
-     *
267
-     * @return array
268
-     */
269
-    public function getAttributes()
270
-    {
271
-        return $this->attributes;
272
-    }
273
-
274
-    /**
275
-     * Set the domain class attributes
276
-     *
277
-     * @param array $attributeNames
278
-     */
279
-    public function setAttributes(array $attributeNames)
280
-    {
281
-        $this->attributes = $attributeNames;
282
-    }
283
-
284
-    /**
285
-     * Get all the attribute names for the class, including relationships, embeddables and primary key.
286
-     *
287
-     * @return array
288
-     */
289
-    public function getCompiledAttributes()
290
-    {
291
-        $key = $this->getKeyName();
292
-
293
-        $embeddables = array_keys($this->getEmbeddables());
294
-
295
-        $relationships = $this->getRelationships();
296
-
297
-        $attributes = $this->getAttributes();
298
-
299
-        return array_merge([$key], $embeddables, $relationships, $attributes);
300
-    }
301
-
302
-    /**
303
-     * Set the date format to use with the current database connection
304
-     *
305
-     * @param string $format
306
-     */
307
-    public function setDateFormat($format)
308
-    {
309
-        $this->dateFormat = $format;
310
-    }
74
+	/**
75
+	 * Determine the relationships method used on the entity.
76
+	 * If not set, mapper will autodetect them
77
+	 *
78
+	 * @var array
79
+	 */
80
+	private $relationships = [];
81
+
82
+	/**
83
+	 * Relationships that should be treated as collection.
84
+	 *
85
+	 * @var array
86
+	 */
87
+	private $manyRelations = [];
88
+
89
+	/**
90
+	 * Relationships that should be treated as single entity.
91
+	 *
92
+	 * @var array
93
+	 */
94
+	private $singleRelations = [];
95
+
96
+	/**
97
+	 * Relationships for which the key is stored in the Entity itself
98
+	 *
99
+	 * @var array
100
+	 */
101
+	private $localRelations = [];
102
+
103
+	/**
104
+	 * Relationships for which the key is stored in the Related Entity
105
+	 *
106
+	 * @var array
107
+	 */
108
+	private $foreignRelations = [];
109
+
110
+	/**
111
+	 * Relationships which use a pivot record.
112
+	 *
113
+	 * @var array
114
+	 */
115
+	private $pivotRelations = [];
116
+
117
+	/**
118
+	 * Dynamic relationships
119
+	 *
120
+	 * @var array
121
+	 */
122
+	private $dynamicRelationships = [];
123
+
124
+	/**
125
+	 * The number of models to return for pagination.
126
+	 *
127
+	 * @var int
128
+	 */
129
+	protected $perPage = 15;
130
+
131
+	/**
132
+	 * The relations to eager load on every query.
133
+	 *
134
+	 * @var array
135
+	 */
136
+	protected $with = [];
137
+
138
+	/**
139
+	 * The class name to be used in polymorphic relations.
140
+	 *
141
+	 * @var string
142
+	 */
143
+	protected $morphClass;
144
+
145
+	/**
146
+	 * Sequence name, to be used with postgreSql
147
+	 * defaults to %table_name%_id_seq
148
+	 *
149
+	 * @var string|null
150
+	 */
151
+	protected $sequence = null;
152
+
153
+	/**
154
+	 * Indicates if the entity should be timestamped.
155
+	 *
156
+	 * @var bool
157
+	 */
158
+	public $timestamps = false;
159
+
160
+	/**
161
+	 * The name of the "created at" column.
162
+	 *
163
+	 * @var string
164
+	 */
165
+	protected $createdAtColumn = 'created_at';
166
+
167
+	/**
168
+	 * The name of the "updated at" column.
169
+	 *
170
+	 * @var string
171
+	 */
172
+	protected $updatedAtColumn = 'updated_at';
173
+
174
+	/**
175
+	 * Indicates if the entity uses softdeletes
176
+	 *
177
+	 * @var boolean
178
+	 */
179
+	public $softDeletes = false;
180
+
181
+	/**
182
+	 * The name of the "deleted at" column.
183
+	 *
184
+	 * @var string
185
+	 */
186
+	protected $deletedAtColumn = 'deleted_at';
187
+
188
+	/**
189
+	 * The many to many relationship methods.
190
+	 *
191
+	 * @var array
192
+	 */
193
+	protected static $manyMethods = ['belongsToMany', 'morphToMany', 'morphedByMany'];
194
+
195
+	/**
196
+	 * The 'Many' relationships classes, which related Entity attribute should be
197
+	 * an array/entityCollection
198
+	 *
199
+	 * @var array
200
+	 */
201
+	protected static $manyClasses = ['BelongsToMany', 'HasMany', 'HasManyThrough', 'MorphMany', 'MorphToMany'];
202
+
203
+	/**
204
+	 * The 'Single' relationships classes, which related Entity attribute should be
205
+	 * another Entity.
206
+	 *
207
+	 * @var array
208
+	 */
209
+	protected static $singleClasses = ['BelongsTo', 'HasOne', 'MorphOne', 'MorphTo'];
210
+
211
+	/**
212
+	 * Relationships with a pivot record
213
+	 *
214
+	 * @var array
215
+	 */
216
+	protected static $pivotClasses = ['BelongsToMany', 'MorphToMany'];
217
+
218
+	/**
219
+	 * Relationships on which key is stored in the Entity itself
220
+	 *
221
+	 * @var array
222
+	 */
223
+	protected static $localClasses = ['BelongsTo', 'MorphTo'];
224
+
225
+	/**
226
+	 * Relationships on which key is stored in the related Entity record or in a pivot record
227
+	 *
228
+	 * @var array
229
+	 */
230
+	protected static $foreignClasses = [
231
+		'BelongsToMany',
232
+		'HasMany',
233
+		'HasManyThrough',
234
+		'MorphMany',
235
+		'MorphToMany',
236
+		'HasOne',
237
+		'MorphOne',
238
+	];
239
+
240
+	/**
241
+	 * The date format to use with the current database connection
242
+	 *
243
+	 * @var string
244
+	 */
245
+	protected $dateFormat;
246
+
247
+	/**
248
+	 * The Analogue's manager instance.
249
+	 *
250
+	 * @var \Analogue\ORM\System\Manager
251
+	 */
252
+	private $manager;
253
+
254
+	/**
255
+	 * Set the Manager that will be used for relationship's mapper instantiations.
256
+	 *
257
+	 * @param Manager $manager
258
+	 */
259
+	public function setManager(Manager $manager)
260
+	{
261
+		$this->manager = $manager;
262
+	}
263
+
264
+	/**
265
+	 * Return Domain class attributes, useful when mapping to a Plain PHP Object
266
+	 *
267
+	 * @return array
268
+	 */
269
+	public function getAttributes()
270
+	{
271
+		return $this->attributes;
272
+	}
273
+
274
+	/**
275
+	 * Set the domain class attributes
276
+	 *
277
+	 * @param array $attributeNames
278
+	 */
279
+	public function setAttributes(array $attributeNames)
280
+	{
281
+		$this->attributes = $attributeNames;
282
+	}
283
+
284
+	/**
285
+	 * Get all the attribute names for the class, including relationships, embeddables and primary key.
286
+	 *
287
+	 * @return array
288
+	 */
289
+	public function getCompiledAttributes()
290
+	{
291
+		$key = $this->getKeyName();
292
+
293
+		$embeddables = array_keys($this->getEmbeddables());
294
+
295
+		$relationships = $this->getRelationships();
296
+
297
+		$attributes = $this->getAttributes();
298
+
299
+		return array_merge([$key], $embeddables, $relationships, $attributes);
300
+	}
301
+
302
+	/**
303
+	 * Set the date format to use with the current database connection
304
+	 *
305
+	 * @param string $format
306
+	 */
307
+	public function setDateFormat($format)
308
+	{
309
+		$this->dateFormat = $format;
310
+	}
311 311
     
312
-    /**
313
-     * Get the date format to use with the current database connection
314
-     *
315
-     *  @return string
316
-     */
317
-    public function getDateFormat()
318
-    {
319
-        return $this->dateFormat;
320
-    }
321
-
322
-    /**
323
-     * Set the Driver for this mapping
324
-     *
325
-     * @param string $driver
326
-     */
327
-    public function setDriver($driver)
328
-    {
329
-        $this->driver = $driver;
330
-    }
331
-
332
-    /**
333
-     * Get the Driver for this mapping.
334
-     *
335
-     * @return string
336
-     */
337
-    public function getDriver()
338
-    {
339
-        return $this->driver;
340
-    }
341
-
342
-    /**
343
-     * Set the db connection to use on the table
344
-     *
345
-     * @param $connection
346
-     */
347
-    public function setConnection($connection)
348
-    {
349
-        $this->connection = $connection;
350
-    }
351
-
352
-    /**
353
-     * Get the Database connection the Entity is stored on.
354
-     *
355
-     * @return string
356
-     */
357
-    public function getConnection()
358
-    {
359
-        return $this->connection;
360
-    }
361
-
362
-    /**
363
-     * Get the table associated with the entity.
364
-     *
365
-     * @return string
366
-     */
367
-    public function getTable()
368
-    {
369
-        if (!is_null($this->table)) {
370
-            return $this->table;
371
-        }
312
+	/**
313
+	 * Get the date format to use with the current database connection
314
+	 *
315
+	 *  @return string
316
+	 */
317
+	public function getDateFormat()
318
+	{
319
+		return $this->dateFormat;
320
+	}
321
+
322
+	/**
323
+	 * Set the Driver for this mapping
324
+	 *
325
+	 * @param string $driver
326
+	 */
327
+	public function setDriver($driver)
328
+	{
329
+		$this->driver = $driver;
330
+	}
331
+
332
+	/**
333
+	 * Get the Driver for this mapping.
334
+	 *
335
+	 * @return string
336
+	 */
337
+	public function getDriver()
338
+	{
339
+		return $this->driver;
340
+	}
341
+
342
+	/**
343
+	 * Set the db connection to use on the table
344
+	 *
345
+	 * @param $connection
346
+	 */
347
+	public function setConnection($connection)
348
+	{
349
+		$this->connection = $connection;
350
+	}
351
+
352
+	/**
353
+	 * Get the Database connection the Entity is stored on.
354
+	 *
355
+	 * @return string
356
+	 */
357
+	public function getConnection()
358
+	{
359
+		return $this->connection;
360
+	}
361
+
362
+	/**
363
+	 * Get the table associated with the entity.
364
+	 *
365
+	 * @return string
366
+	 */
367
+	public function getTable()
368
+	{
369
+		if (!is_null($this->table)) {
370
+			return $this->table;
371
+		}
372 372
         
373
-        return str_replace('\\', '', snake_case(str_plural(class_basename($this->getClass()))));
374
-    }
375
-
376
-    /**
377
-     * Set the database table name
378
-     *
379
-     * @param  string $table
380
-     */
381
-    public function setTable($table)
382
-    {
383
-        $this->table = $table;
384
-    }
385
-
386
-    /**
387
-     * Get the pgSql sequence name
388
-     *
389
-     * @return string
390
-     */
391
-    public function getSequence()
392
-    {
393
-        if (!is_null($this->sequence)) {
394
-            return $this->sequence;
395
-        } else {
396
-            return $this->getTable() . '_id_seq';
397
-        }
398
-    }
399
-
400
-    /**
401
-     * Get the custom entity class
402
-     *
403
-     * @return string namespaced class name
404
-     */
405
-    public function getClass()
406
-    {
407
-        return isset($this->class) ? $this->class : null;
408
-    }
409
-
410
-    /**
411
-     * Set the custom entity class
412
-     *
413
-     * @param string $class namespaced class name
414
-     */
415
-    public function setClass($class)
416
-    {
417
-        // Throw exception if class not exists
418
-
419
-        $this->class = $class;
420
-    }
421
-
422
-    /**
423
-     * Get the embedded Value Objects
424
-     *
425
-     * @return array
426
-     */
427
-    public function getEmbeddables()
428
-    {
429
-        return $this->embeddables;
430
-    }
431
-
432
-    /**
433
-     * Set the embedded Value Objects
434
-     *
435
-     * @param array $embeddables
436
-     */
437
-    public function setEmbeddables(array $embeddables)
438
-    {
439
-        $this->embeddables = $embeddables;
440
-    }
441
-
442
-    /**
443
-     * Get the relationships to map on a custom domain
444
-     * class.
445
-     *
446
-     * @return array
447
-     */
448
-    public function getRelationships()
449
-    {
450
-        return $this->relationships;
451
-    }
452
-
453
-    /**
454
-     * Relationships of the Entity type
455
-     *
456
-     * @return array
457
-     */
458
-    public function getSingleRelationships()
459
-    {
460
-        return $this->singleRelations;
461
-    }
462
-
463
-    /**
464
-     * Relationships of type Collection
465
-     *
466
-     * @return array
467
-     */
468
-    public function getManyRelationships()
469
-    {
470
-        return $this->manyRelations;
471
-    }
472
-
473
-    /**
474
-     * Relationships with foreign key in the mapped entity record.
475
-     *
476
-     * @return array
477
-     */
478
-    public function getLocalRelationships()
479
-    {
480
-        return $this->localRelations;
481
-    }
482
-
483
-    /**
484
-     * Relationships with foreign key in the related Entity record
485
-     *
486
-     * @return array
487
-     */
488
-    public function getForeignRelationships()
489
-    {
490
-        return $this->foreignRelations;
491
-    }
492
-
493
-    /**
494
-     * Relationships which keys are stored in a pivot record
495
-     *
496
-     * @return array
497
-     */
498
-    public function getPivotRelationships()
499
-    {
500
-        return $this->pivotRelations;
501
-    }
502
-
503
-    /**
504
-     * Add a Dynamic Relationship method at runtime. This has to be done
505
-     * by hooking the 'initializing' event, before entityMap is initialized.
506
-     *
507
-     * @param string  $name         Relation name
508
-     * @param \Closure $relationship
509
-     *
510
-     * @return void
511
-     */
512
-    public function addRelationshipMethod($name, \Closure $relationship)
513
-    {
514
-        $this->dynamicRelationships[$name] = $relationship;
515
-    }
516
-
517
-    /**
518
-     * Get the dynamic relationship method names.
519
-     *
520
-     * @return array
521
-     */
522
-    public function getDynamicRelationships()
523
-    {
524
-        return array_keys($this->dynamicRelationships);
525
-    }
526
-
527
-    /**
528
-     * Get the relationships that have to be eager loaded
529
-     * on each request.
530
-     *
531
-     * @return array
532
-     */
533
-    public function getEagerloadedRelationships()
534
-    {
535
-        return $this->with;
536
-    }
537
-
538
-    /**
539
-     * Get the primary key for the entity.
540
-     *
541
-     * @return string
542
-     */
543
-    public function getKeyName()
544
-    {
545
-        return $this->primaryKey;
546
-    }
373
+		return str_replace('\\', '', snake_case(str_plural(class_basename($this->getClass()))));
374
+	}
375
+
376
+	/**
377
+	 * Set the database table name
378
+	 *
379
+	 * @param  string $table
380
+	 */
381
+	public function setTable($table)
382
+	{
383
+		$this->table = $table;
384
+	}
385
+
386
+	/**
387
+	 * Get the pgSql sequence name
388
+	 *
389
+	 * @return string
390
+	 */
391
+	public function getSequence()
392
+	{
393
+		if (!is_null($this->sequence)) {
394
+			return $this->sequence;
395
+		} else {
396
+			return $this->getTable() . '_id_seq';
397
+		}
398
+	}
399
+
400
+	/**
401
+	 * Get the custom entity class
402
+	 *
403
+	 * @return string namespaced class name
404
+	 */
405
+	public function getClass()
406
+	{
407
+		return isset($this->class) ? $this->class : null;
408
+	}
409
+
410
+	/**
411
+	 * Set the custom entity class
412
+	 *
413
+	 * @param string $class namespaced class name
414
+	 */
415
+	public function setClass($class)
416
+	{
417
+		// Throw exception if class not exists
418
+
419
+		$this->class = $class;
420
+	}
421
+
422
+	/**
423
+	 * Get the embedded Value Objects
424
+	 *
425
+	 * @return array
426
+	 */
427
+	public function getEmbeddables()
428
+	{
429
+		return $this->embeddables;
430
+	}
431
+
432
+	/**
433
+	 * Set the embedded Value Objects
434
+	 *
435
+	 * @param array $embeddables
436
+	 */
437
+	public function setEmbeddables(array $embeddables)
438
+	{
439
+		$this->embeddables = $embeddables;
440
+	}
441
+
442
+	/**
443
+	 * Get the relationships to map on a custom domain
444
+	 * class.
445
+	 *
446
+	 * @return array
447
+	 */
448
+	public function getRelationships()
449
+	{
450
+		return $this->relationships;
451
+	}
452
+
453
+	/**
454
+	 * Relationships of the Entity type
455
+	 *
456
+	 * @return array
457
+	 */
458
+	public function getSingleRelationships()
459
+	{
460
+		return $this->singleRelations;
461
+	}
462
+
463
+	/**
464
+	 * Relationships of type Collection
465
+	 *
466
+	 * @return array
467
+	 */
468
+	public function getManyRelationships()
469
+	{
470
+		return $this->manyRelations;
471
+	}
472
+
473
+	/**
474
+	 * Relationships with foreign key in the mapped entity record.
475
+	 *
476
+	 * @return array
477
+	 */
478
+	public function getLocalRelationships()
479
+	{
480
+		return $this->localRelations;
481
+	}
482
+
483
+	/**
484
+	 * Relationships with foreign key in the related Entity record
485
+	 *
486
+	 * @return array
487
+	 */
488
+	public function getForeignRelationships()
489
+	{
490
+		return $this->foreignRelations;
491
+	}
492
+
493
+	/**
494
+	 * Relationships which keys are stored in a pivot record
495
+	 *
496
+	 * @return array
497
+	 */
498
+	public function getPivotRelationships()
499
+	{
500
+		return $this->pivotRelations;
501
+	}
502
+
503
+	/**
504
+	 * Add a Dynamic Relationship method at runtime. This has to be done
505
+	 * by hooking the 'initializing' event, before entityMap is initialized.
506
+	 *
507
+	 * @param string  $name         Relation name
508
+	 * @param \Closure $relationship
509
+	 *
510
+	 * @return void
511
+	 */
512
+	public function addRelationshipMethod($name, \Closure $relationship)
513
+	{
514
+		$this->dynamicRelationships[$name] = $relationship;
515
+	}
516
+
517
+	/**
518
+	 * Get the dynamic relationship method names.
519
+	 *
520
+	 * @return array
521
+	 */
522
+	public function getDynamicRelationships()
523
+	{
524
+		return array_keys($this->dynamicRelationships);
525
+	}
526
+
527
+	/**
528
+	 * Get the relationships that have to be eager loaded
529
+	 * on each request.
530
+	 *
531
+	 * @return array
532
+	 */
533
+	public function getEagerloadedRelationships()
534
+	{
535
+		return $this->with;
536
+	}
537
+
538
+	/**
539
+	 * Get the primary key for the entity.
540
+	 *
541
+	 * @return string
542
+	 */
543
+	public function getKeyName()
544
+	{
545
+		return $this->primaryKey;
546
+	}
547 547
     
548
-    /**
549
-     * Set the primary key for the entity.
550
-     *
551
-     * @param $key
552
-     * @return void
553
-     */
554
-    public function setKeyName($key)
555
-    {
556
-        $this->primaryKey = $key;
557
-    }
548
+	/**
549
+	 * Set the primary key for the entity.
550
+	 *
551
+	 * @param $key
552
+	 * @return void
553
+	 */
554
+	public function setKeyName($key)
555
+	{
556
+		$this->primaryKey = $key;
557
+	}
558 558
     
559
-    /**
560
-     * Get the table qualified key name.
561
-     *
562
-     * @return string
563
-     */
564
-    public function getQualifiedKeyName()
565
-    {
566
-        return $this->getTable() . '.' . $this->getKeyName();
567
-    }
568
-
569
-    /**
570
-     * Get the number of models to return per page.
571
-     *
572
-     * @return int
573
-     */
574
-    public function getPerPage()
575
-    {
576
-        return $this->perPage;
577
-    }
578
-
579
-    /**
580
-     * Set the number of models to return per page.
581
-     *
582
-     * @param  int $perPage
583
-     * @return void
584
-     */
585
-    public function setPerPage($perPage)
586
-    {
587
-        $this->perPage = $perPage;
588
-    }
589
-
590
-    /**
591
-     * Determine if the entity uses get.
592
-     *
593
-     * @return bool
594
-     */
595
-    public function usesTimestamps()
596
-    {
597
-        return $this->timestamps;
598
-    }
599
-
600
-    /**
601
-     * Determine if the entity uses soft deletes
602
-     *
603
-     * @return bool
604
-     */
605
-    public function usesSoftDeletes()
606
-    {
607
-        return $this->softDeletes;
608
-    }
609
-
610
-    /**
611
-     * Get the 'created_at' column name
612
-     *
613
-     * @return string
614
-     */
615
-    public function getCreatedAtColumn()
616
-    {
617
-        return $this->createdAtColumn;
618
-    }
619
-
620
-    /**
621
-     * Get the 'updated_at' column name
622
-     *
623
-     * @return string
624
-     */
625
-    public function getUpdatedAtColumn()
626
-    {
627
-        return $this->updatedAtColumn;
628
-    }
629
-
630
-    /**
631
-     * Get the deleted_at column
632
-     *
633
-     * @return string
634
-     */
635
-    public function getQualifiedDeletedAtColumn()
636
-    {
637
-        return $this->deletedAtColumn;
638
-    }
639
-
640
-    /**
641
-     * Get the default foreign key name for the model.
642
-     *
643
-     * @return string
644
-     */
645
-    public function getForeignKey()
646
-    {
647
-        return snake_case(class_basename($this->getClass())) . '_id';
648
-    }
649
-
650
-    /**
651
-     * Define a one-to-one relationship.
652
-     *
653
-     * @param         $entity
654
-     * @param  string $relatedClass entity class
655
-     * @param  string $foreignKey
656
-     * @param  string $localKey
657
-     * @throws MappingException
658
-     * @return \Analogue\ORM\Relationships\HasOne
659
-     */
660
-    public function hasOne($entity, $relatedClass, $foreignKey = null, $localKey = null)
661
-    {
662
-        $foreignKey = $foreignKey ?: $this->getForeignKey();
663
-
664
-        $relatedMapper = $this->manager->mapper($relatedClass);
665
-
666
-        $relatedMap = $relatedMapper->getEntityMap();
667
-
668
-        $localKey = $localKey ?: $this->getKeyName();
669
-
670
-        return new HasOne($relatedMapper, $entity, $relatedMap->getTable() . '.' . $foreignKey, $localKey);
671
-    }
672
-
673
-    /**
674
-     * Define a polymorphic one-to-one relationship.
675
-     *
676
-     * @param  mixed       $entity
677
-     * @param  string      $related
678
-     * @param  string      $name
679
-     * @param  string|null $type
680
-     * @param  string|null $id
681
-     * @param  string|null $localKey
682
-     * @throws MappingException
683
-     * @return \Analogue\ORM\Relationships\MorphOne
684
-     */
685
-    public function morphOne($entity, $related, $name, $type = null, $id = null, $localKey = null)
686
-    {
687
-        list($type, $id) = $this->getMorphs($name, $type, $id);
688
-
689
-        $localKey = $localKey ?: $this->getKeyName();
690
-
691
-        $relatedMapper = $this->manager->mapper($related);
692
-
693
-        $table = $relatedMapper->getEntityMap()->getTable();
559
+	/**
560
+	 * Get the table qualified key name.
561
+	 *
562
+	 * @return string
563
+	 */
564
+	public function getQualifiedKeyName()
565
+	{
566
+		return $this->getTable() . '.' . $this->getKeyName();
567
+	}
568
+
569
+	/**
570
+	 * Get the number of models to return per page.
571
+	 *
572
+	 * @return int
573
+	 */
574
+	public function getPerPage()
575
+	{
576
+		return $this->perPage;
577
+	}
578
+
579
+	/**
580
+	 * Set the number of models to return per page.
581
+	 *
582
+	 * @param  int $perPage
583
+	 * @return void
584
+	 */
585
+	public function setPerPage($perPage)
586
+	{
587
+		$this->perPage = $perPage;
588
+	}
589
+
590
+	/**
591
+	 * Determine if the entity uses get.
592
+	 *
593
+	 * @return bool
594
+	 */
595
+	public function usesTimestamps()
596
+	{
597
+		return $this->timestamps;
598
+	}
599
+
600
+	/**
601
+	 * Determine if the entity uses soft deletes
602
+	 *
603
+	 * @return bool
604
+	 */
605
+	public function usesSoftDeletes()
606
+	{
607
+		return $this->softDeletes;
608
+	}
609
+
610
+	/**
611
+	 * Get the 'created_at' column name
612
+	 *
613
+	 * @return string
614
+	 */
615
+	public function getCreatedAtColumn()
616
+	{
617
+		return $this->createdAtColumn;
618
+	}
619
+
620
+	/**
621
+	 * Get the 'updated_at' column name
622
+	 *
623
+	 * @return string
624
+	 */
625
+	public function getUpdatedAtColumn()
626
+	{
627
+		return $this->updatedAtColumn;
628
+	}
629
+
630
+	/**
631
+	 * Get the deleted_at column
632
+	 *
633
+	 * @return string
634
+	 */
635
+	public function getQualifiedDeletedAtColumn()
636
+	{
637
+		return $this->deletedAtColumn;
638
+	}
639
+
640
+	/**
641
+	 * Get the default foreign key name for the model.
642
+	 *
643
+	 * @return string
644
+	 */
645
+	public function getForeignKey()
646
+	{
647
+		return snake_case(class_basename($this->getClass())) . '_id';
648
+	}
649
+
650
+	/**
651
+	 * Define a one-to-one relationship.
652
+	 *
653
+	 * @param         $entity
654
+	 * @param  string $relatedClass entity class
655
+	 * @param  string $foreignKey
656
+	 * @param  string $localKey
657
+	 * @throws MappingException
658
+	 * @return \Analogue\ORM\Relationships\HasOne
659
+	 */
660
+	public function hasOne($entity, $relatedClass, $foreignKey = null, $localKey = null)
661
+	{
662
+		$foreignKey = $foreignKey ?: $this->getForeignKey();
663
+
664
+		$relatedMapper = $this->manager->mapper($relatedClass);
665
+
666
+		$relatedMap = $relatedMapper->getEntityMap();
667
+
668
+		$localKey = $localKey ?: $this->getKeyName();
669
+
670
+		return new HasOne($relatedMapper, $entity, $relatedMap->getTable() . '.' . $foreignKey, $localKey);
671
+	}
672
+
673
+	/**
674
+	 * Define a polymorphic one-to-one relationship.
675
+	 *
676
+	 * @param  mixed       $entity
677
+	 * @param  string      $related
678
+	 * @param  string      $name
679
+	 * @param  string|null $type
680
+	 * @param  string|null $id
681
+	 * @param  string|null $localKey
682
+	 * @throws MappingException
683
+	 * @return \Analogue\ORM\Relationships\MorphOne
684
+	 */
685
+	public function morphOne($entity, $related, $name, $type = null, $id = null, $localKey = null)
686
+	{
687
+		list($type, $id) = $this->getMorphs($name, $type, $id);
688
+
689
+		$localKey = $localKey ?: $this->getKeyName();
690
+
691
+		$relatedMapper = $this->manager->mapper($related);
692
+
693
+		$table = $relatedMapper->getEntityMap()->getTable();
694 694
         
695
-        return new MorphOne($relatedMapper, $entity, $table . '.' . $type, $table . '.' . $id, $localKey);
696
-    }
697
-
698
-    /**
699
-     * Define an inverse one-to-one or many relationship.
700
-     *
701
-     * @param  mixed       $entity
702
-     * @param  string      $related
703
-     * @param  string|null $foreignKey
704
-     * @param  string|null $otherKey
705
-     * @param  string|null $relation
706
-     * @throws MappingException
707
-     * @return \Analogue\ORM\Relationships\BelongsTo
708
-     */
709
-    public function belongsTo($entity, $related, $foreignKey = null, $otherKey = null, $relation = null)
710
-    {
711
-        // If no relation name was given, we will use this debug backtrace to extract
712
-        // the calling method's name and use that as the relationship name as most
713
-        // of the time this will be what we desire to use for the relationships.
714
-        if (is_null($relation)) {
715
-            list(, $caller) = debug_backtrace(false);
716
-
717
-            $relation = $caller['function'];
718
-        }
719
-
720
-        // If no foreign key was supplied, we can use a backtrace to guess the proper
721
-        // foreign key name by using the name of the relationship function, which
722
-        // when combined with an "_id" should conventionally match the columns.
723
-        if (is_null($foreignKey)) {
724
-            $foreignKey = snake_case($relation) . '_id';
725
-        }
726
-
727
-        $relatedMapper = $this->manager->mapper($related);
728
-
729
-        $otherKey = $otherKey ?: $relatedMapper->getEntityMap()->getKeyName();
730
-
731
-        return new BelongsTo($relatedMapper, $entity, $foreignKey, $otherKey, $relation);
732
-    }
733
-
734
-    /**
735
-     * Define a polymorphic, inverse one-to-one or many relationship.
736
-     *
737
-     * @param  mixed       $entity
738
-     * @param  string|null $name
739
-     * @param  string|null $type
740
-     * @param  string|null $id
741
-     * @throws MappingException
742
-     * @return \Analogue\ORM\Relationships\MorphTo
743
-     */
744
-    public function morphTo($entity, $name = null, $type = null, $id = null)
745
-    {
746
-        // If no name is provided, we will use the backtrace to get the function name
747
-        // since that is most likely the name of the polymorphic interface. We can
748
-        // use that to get both the class and foreign key that will be utilized.
749
-        if (is_null($name)) {
750
-            list(, $caller) = debug_backtrace(false);
751
-
752
-            $name = snake_case($caller['function']);
753
-        }
754
-
755
-        list($type, $id) = $this->getMorphs($name, $type, $id);
695
+		return new MorphOne($relatedMapper, $entity, $table . '.' . $type, $table . '.' . $id, $localKey);
696
+	}
697
+
698
+	/**
699
+	 * Define an inverse one-to-one or many relationship.
700
+	 *
701
+	 * @param  mixed       $entity
702
+	 * @param  string      $related
703
+	 * @param  string|null $foreignKey
704
+	 * @param  string|null $otherKey
705
+	 * @param  string|null $relation
706
+	 * @throws MappingException
707
+	 * @return \Analogue\ORM\Relationships\BelongsTo
708
+	 */
709
+	public function belongsTo($entity, $related, $foreignKey = null, $otherKey = null, $relation = null)
710
+	{
711
+		// If no relation name was given, we will use this debug backtrace to extract
712
+		// the calling method's name and use that as the relationship name as most
713
+		// of the time this will be what we desire to use for the relationships.
714
+		if (is_null($relation)) {
715
+			list(, $caller) = debug_backtrace(false);
716
+
717
+			$relation = $caller['function'];
718
+		}
719
+
720
+		// If no foreign key was supplied, we can use a backtrace to guess the proper
721
+		// foreign key name by using the name of the relationship function, which
722
+		// when combined with an "_id" should conventionally match the columns.
723
+		if (is_null($foreignKey)) {
724
+			$foreignKey = snake_case($relation) . '_id';
725
+		}
726
+
727
+		$relatedMapper = $this->manager->mapper($related);
728
+
729
+		$otherKey = $otherKey ?: $relatedMapper->getEntityMap()->getKeyName();
730
+
731
+		return new BelongsTo($relatedMapper, $entity, $foreignKey, $otherKey, $relation);
732
+	}
733
+
734
+	/**
735
+	 * Define a polymorphic, inverse one-to-one or many relationship.
736
+	 *
737
+	 * @param  mixed       $entity
738
+	 * @param  string|null $name
739
+	 * @param  string|null $type
740
+	 * @param  string|null $id
741
+	 * @throws MappingException
742
+	 * @return \Analogue\ORM\Relationships\MorphTo
743
+	 */
744
+	public function morphTo($entity, $name = null, $type = null, $id = null)
745
+	{
746
+		// If no name is provided, we will use the backtrace to get the function name
747
+		// since that is most likely the name of the polymorphic interface. We can
748
+		// use that to get both the class and foreign key that will be utilized.
749
+		if (is_null($name)) {
750
+			list(, $caller) = debug_backtrace(false);
751
+
752
+			$name = snake_case($caller['function']);
753
+		}
754
+
755
+		list($type, $id) = $this->getMorphs($name, $type, $id);
756 756
         
757
-        $mapper = $this->manager->mapper(get_class($entity));
757
+		$mapper = $this->manager->mapper(get_class($entity));
758 758
 
759
-        // If the type value is null it is probably safe to assume we're eager loading
760
-        // the relationship. When that is the case we will pass in a dummy query as
761
-        // there are multiple types in the morph and we can't use single queries.
762
-        $factory = new Factory;
763
-        $wrapper = $factory->make($entity);
759
+		// If the type value is null it is probably safe to assume we're eager loading
760
+		// the relationship. When that is the case we will pass in a dummy query as
761
+		// there are multiple types in the morph and we can't use single queries.
762
+		$factory = new Factory;
763
+		$wrapper = $factory->make($entity);
764 764
             
765
-        if (is_null($class = $wrapper->getEntityAttribute($type))) {
766
-            return new MorphTo(
767
-                $mapper, $entity, $id, null, $type, $name
768
-            );
769
-        }
770
-
771
-        // If we are not eager loading the relationship we will essentially treat this
772
-        // as a belongs-to style relationship since morph-to extends that class and
773
-        // we will pass in the appropriate values so that it behaves as expected.
774
-        else {
775
-            $class = $this->manager->getInverseMorphMap($class);
776
-            $relatedMapper = $this->manager->mapper($class);
777
-
778
-            $foreignKey = $relatedMapper->getEntityMap()->getKeyName();
765
+		if (is_null($class = $wrapper->getEntityAttribute($type))) {
766
+			return new MorphTo(
767
+				$mapper, $entity, $id, null, $type, $name
768
+			);
769
+		}
770
+
771
+		// If we are not eager loading the relationship we will essentially treat this
772
+		// as a belongs-to style relationship since morph-to extends that class and
773
+		// we will pass in the appropriate values so that it behaves as expected.
774
+		else {
775
+			$class = $this->manager->getInverseMorphMap($class);
776
+			$relatedMapper = $this->manager->mapper($class);
777
+
778
+			$foreignKey = $relatedMapper->getEntityMap()->getKeyName();
779 779
             
780
-            return new MorphTo(
781
-                $relatedMapper, $entity, $id, $foreignKey, $type, $name
782
-            );
783
-        }
784
-    }
785
-
786
-    /**
787
-     * Define a one-to-many relationship.
788
-     *
789
-     * @param  mixed       $entity
790
-     * @param  string      $related
791
-     * @param  string|null $foreignKey
792
-     * @param  string|null $localKey
793
-     * @throws MappingException
794
-     * @return \Analogue\ORM\Relationships\HasMany
795
-     */
796
-    public function hasMany($entity, $related, $foreignKey = null, $localKey = null)
797
-    {
798
-        $foreignKey = $foreignKey ?: $this->getForeignKey();
799
-
800
-        $relatedMapper = $this->manager->mapper($related);
801
-
802
-        $table = $relatedMapper->getEntityMap()->getTable() . '.' . $foreignKey;
803
-
804
-        $localKey = $localKey ?: $this->getKeyName();
805
-
806
-        return new HasMany($relatedMapper, $entity, $table, $localKey);
807
-    }
808
-
809
-    /**
810
-     * Define a has-many-through relationship.
811
-     *
812
-     * @param  mixed       $entity
813
-     * @param  string      $related
814
-     * @param  string      $through
815
-     * @param  string|null $firstKey
816
-     * @param  string|null $secondKey
817
-     * @throws MappingException
818
-     * @return \Analogue\ORM\Relationships\HasManyThrough
819
-     */
820
-    public function hasManyThrough($entity, $related, $through, $firstKey = null, $secondKey = null)
821
-    {
822
-        $relatedMapper = $this->manager->mapper($related);
823
-
824
-        $throughMapper = $this->manager->mapper($through);
825
-
826
-
827
-        $firstKey = $firstKey ?: $this->getForeignKey();
828
-
829
-        $throughMap = $throughMapper->getEntityMap();
830
-
831
-        $secondKey = $secondKey ?: $throughMap->getForeignKey();
832
-
833
-        return new HasManyThrough($relatedMapper, $entity, $throughMap, $firstKey, $secondKey);
834
-    }
835
-
836
-    /**
837
-     * Define a polymorphic one-to-many relationship.
838
-     *
839
-     * @param  mixed       $entity
840
-     * @param  string      $related
841
-     * @param  string      $name
842
-     * @param  string|null $type
843
-     * @param  string|null $id
844
-     * @param  string|null $localKey
845
-     * @return \Analogue\ORM\Relationships\MorphMany
846
-     */
847
-    public function morphMany($entity, $related, $name, $type = null, $id = null, $localKey = null)
848
-    {
849
-        // Here we will gather up the morph type and ID for the relationship so that we
850
-        // can properly query the intermediate table of a relation. Finally, we will
851
-        // get the table and create the relationship instances for the developers.
852
-        list($type, $id) = $this->getMorphs($name, $type, $id);
853
-
854
-        $relatedMapper = $this->manager->mapper($related);
855
-
856
-        $table = $relatedMapper->getEntityMap()->getTable();
857
-
858
-        $localKey = $localKey ?: $this->getKeyName();
780
+			return new MorphTo(
781
+				$relatedMapper, $entity, $id, $foreignKey, $type, $name
782
+			);
783
+		}
784
+	}
785
+
786
+	/**
787
+	 * Define a one-to-many relationship.
788
+	 *
789
+	 * @param  mixed       $entity
790
+	 * @param  string      $related
791
+	 * @param  string|null $foreignKey
792
+	 * @param  string|null $localKey
793
+	 * @throws MappingException
794
+	 * @return \Analogue\ORM\Relationships\HasMany
795
+	 */
796
+	public function hasMany($entity, $related, $foreignKey = null, $localKey = null)
797
+	{
798
+		$foreignKey = $foreignKey ?: $this->getForeignKey();
799
+
800
+		$relatedMapper = $this->manager->mapper($related);
801
+
802
+		$table = $relatedMapper->getEntityMap()->getTable() . '.' . $foreignKey;
803
+
804
+		$localKey = $localKey ?: $this->getKeyName();
805
+
806
+		return new HasMany($relatedMapper, $entity, $table, $localKey);
807
+	}
808
+
809
+	/**
810
+	 * Define a has-many-through relationship.
811
+	 *
812
+	 * @param  mixed       $entity
813
+	 * @param  string      $related
814
+	 * @param  string      $through
815
+	 * @param  string|null $firstKey
816
+	 * @param  string|null $secondKey
817
+	 * @throws MappingException
818
+	 * @return \Analogue\ORM\Relationships\HasManyThrough
819
+	 */
820
+	public function hasManyThrough($entity, $related, $through, $firstKey = null, $secondKey = null)
821
+	{
822
+		$relatedMapper = $this->manager->mapper($related);
823
+
824
+		$throughMapper = $this->manager->mapper($through);
825
+
826
+
827
+		$firstKey = $firstKey ?: $this->getForeignKey();
828
+
829
+		$throughMap = $throughMapper->getEntityMap();
830
+
831
+		$secondKey = $secondKey ?: $throughMap->getForeignKey();
832
+
833
+		return new HasManyThrough($relatedMapper, $entity, $throughMap, $firstKey, $secondKey);
834
+	}
835
+
836
+	/**
837
+	 * Define a polymorphic one-to-many relationship.
838
+	 *
839
+	 * @param  mixed       $entity
840
+	 * @param  string      $related
841
+	 * @param  string      $name
842
+	 * @param  string|null $type
843
+	 * @param  string|null $id
844
+	 * @param  string|null $localKey
845
+	 * @return \Analogue\ORM\Relationships\MorphMany
846
+	 */
847
+	public function morphMany($entity, $related, $name, $type = null, $id = null, $localKey = null)
848
+	{
849
+		// Here we will gather up the morph type and ID for the relationship so that we
850
+		// can properly query the intermediate table of a relation. Finally, we will
851
+		// get the table and create the relationship instances for the developers.
852
+		list($type, $id) = $this->getMorphs($name, $type, $id);
853
+
854
+		$relatedMapper = $this->manager->mapper($related);
855
+
856
+		$table = $relatedMapper->getEntityMap()->getTable();
857
+
858
+		$localKey = $localKey ?: $this->getKeyName();
859 859
         
860
-        return new MorphMany($relatedMapper, $entity, $table . '.' . $type, $table . '.' . $id, $localKey);
861
-    }
862
-
863
-    /**
864
-     * Define a many-to-many relationship.
865
-     *
866
-     * @param  mixed       $entity
867
-     * @param  string      $related
868
-     * @param  string|null $table
869
-     * @param  string|null $foreignKey
870
-     * @param  string|null $otherKey
871
-     * @param  string|null $relation
872
-     * @throws MappingException
873
-     * @return \Analogue\ORM\Relationships\BelongsToMany
874
-     */
875
-    public function belongsToMany($entity, $related, $table = null, $foreignKey = null, $otherKey = null, $relation = null)
876
-    {
877
-        // If no relationship name was passed, we will pull backtraces to get the
878
-        // name of the calling function. We will use that function name as the
879
-        // title of this relation since that is a great convention to apply.
880
-        if (is_null($relation)) {
881
-            $relation = $this->getBelongsToManyCaller();
882
-        }
883
-
884
-        // First, we'll need to determine the foreign key and "other key" for the
885
-        // relationship. Once we have determined the keys we'll make the query
886
-        // instances as well as the relationship instances we need for this.
887
-        $foreignKey = $foreignKey ?: $this->getForeignKey();
888
-
889
-        $relatedMapper = $this->manager->mapper($related);
890
-
891
-        $relatedMap = $relatedMapper->getEntityMap();
892
-
893
-        $otherKey = $otherKey ?: $relatedMap->getForeignKey();
894
-
895
-        // If no table name was provided, we can guess it by concatenating the two
896
-        // models using underscores in alphabetical order. The two model names
897
-        // are transformed to snake case from their default CamelCase also.
898
-        if (is_null($table)) {
899
-            $table = $this->joiningTable($relatedMap);
900
-        }
901
-
902
-        return new BelongsToMany($relatedMapper, $entity, $table, $foreignKey, $otherKey, $relation);
903
-    }
904
-
905
-    /**
906
-     * Define a polymorphic many-to-many relationship.
907
-     *
908
-     * @param  mixed       $entity
909
-     * @param  string      $related
910
-     * @param  string      $name
911
-     * @param  string|null $table
912
-     * @param  string|null $foreignKey
913
-     * @param  string|null $otherKey
914
-     * @param  bool        $inverse
915
-     * @throws MappingException
916
-     * @return \Analogue\ORM\Relationships\MorphToMany
917
-     */
918
-    public function morphToMany($entity, $related, $name, $table = null, $foreignKey = null, $otherKey = null, $inverse = false)
919
-    {
920
-        $caller = $this->getBelongsToManyCaller();
921
-
922
-        // First, we will need to determine the foreign key and "other key" for the
923
-        // relationship. Once we have determined the keys we will make the query
924
-        // instances, as well as the relationship instances we need for these.
925
-        $foreignKey = $foreignKey ?: $name . '_id';
926
-
927
-        $relatedMapper = $this->manager->mapper($related);
928
-
929
-        $otherKey = $otherKey ?: $relatedMapper->getEntityMap()->getForeignKey();
930
-
931
-        $table = $table ?: str_plural($name);
932
-
933
-        return new MorphToMany($relatedMapper, $entity, $name, $table, $foreignKey, $otherKey, $caller, $inverse);
934
-    }
935
-
936
-    /**
937
-     * Define a polymorphic, inverse many-to-many relationship.
938
-     *
939
-     * @param  mixed       $entity
940
-     * @param  string      $related
941
-     * @param  string      $name
942
-     * @param  string|null $table
943
-     * @param  string|null $foreignKey
944
-     * @param  string|null $otherKey
945
-     * @throws MappingException
946
-     * @return \Analogue\ORM\Relationships\MorphToMany
947
-     */
948
-    public function morphedByMany($entity, $related, $name, $table = null, $foreignKey = null, $otherKey = null)
949
-    {
950
-        $foreignKey = $foreignKey ?: $this->getForeignKey();
951
-
952
-        // For the inverse of the polymorphic many-to-many relations, we will change
953
-        // the way we determine the foreign and other keys, as it is the opposite
954
-        // of the morph-to-many method since we're figuring out these inverses.
955
-        $otherKey = $otherKey ?: $name . '_id';
956
-
957
-        return $this->morphToMany($entity, $related, $name, $table, $foreignKey, $otherKey, true);
958
-    }
959
-
960
-    /**
961
-     * Get the relationship name of the belongs to many.
962
-     *
963
-     * @return string
964
-     */
965
-    protected function getBelongsToManyCaller()
966
-    {
967
-        $self = __FUNCTION__;
968
-
969
-        $caller = array_first(debug_backtrace(false), function ($key, $trace) use ($self) {
970
-            $caller = $trace['function'];
971
-
972
-            return (!in_array($caller, EntityMap::$manyMethods) && $caller != $self);
973
-        });
974
-
975
-        return !is_null($caller) ? $caller['function'] : null;
976
-    }
977
-
978
-    /**
979
-     * Get the joining table name for a many-to-many relation.
980
-     *
981
-     * @param  EntityMap $relatedMap
982
-     * @return string
983
-     */
984
-    public function joiningTable($relatedMap)
985
-    {
986
-        // The joining table name, by convention, is simply the snake cased models
987
-        // sorted alphabetically and concatenated with an underscore, so we can
988
-        // just sort the models and join them together to get the table name.
989
-        $base = $this->getTable();
990
-
991
-        $related = $relatedMap->getTable();
992
-
993
-        $tables = [$related, $base];
994
-
995
-        // Now that we have the model names in an array we can just sort them and
996
-        // use the implode function to join them together with an underscores,
997
-        // which is typically used by convention within the database system.
998
-        sort($tables);
999
-
1000
-        return strtolower(implode('_', $tables));
1001
-    }
1002
-
1003
-    /**
1004
-     * Get the polymorphic relationship columns.
1005
-     *
1006
-     * @param  string $name
1007
-     * @param  string $type
1008
-     * @param  string $id
1009
-     * @return string[]
1010
-     */
1011
-    protected function getMorphs($name, $type, $id)
1012
-    {
1013
-        $type = $type ?: $name . '_type';
1014
-
1015
-        $id = $id ?: $name . '_id';
1016
-
1017
-        return [$type, $id];
1018
-    }
1019
-
1020
-    /**
1021
-     * Get the class name for polymorphic relations.
1022
-     *
1023
-     * @return string
1024
-     */
1025
-    public function getMorphClass()
1026
-    {
1027
-        $morphClass = $this->manager->getMorphMap($this->getClass());
1028
-        return $this->morphClass ?: $morphClass;
1029
-    }
860
+		return new MorphMany($relatedMapper, $entity, $table . '.' . $type, $table . '.' . $id, $localKey);
861
+	}
862
+
863
+	/**
864
+	 * Define a many-to-many relationship.
865
+	 *
866
+	 * @param  mixed       $entity
867
+	 * @param  string      $related
868
+	 * @param  string|null $table
869
+	 * @param  string|null $foreignKey
870
+	 * @param  string|null $otherKey
871
+	 * @param  string|null $relation
872
+	 * @throws MappingException
873
+	 * @return \Analogue\ORM\Relationships\BelongsToMany
874
+	 */
875
+	public function belongsToMany($entity, $related, $table = null, $foreignKey = null, $otherKey = null, $relation = null)
876
+	{
877
+		// If no relationship name was passed, we will pull backtraces to get the
878
+		// name of the calling function. We will use that function name as the
879
+		// title of this relation since that is a great convention to apply.
880
+		if (is_null($relation)) {
881
+			$relation = $this->getBelongsToManyCaller();
882
+		}
883
+
884
+		// First, we'll need to determine the foreign key and "other key" for the
885
+		// relationship. Once we have determined the keys we'll make the query
886
+		// instances as well as the relationship instances we need for this.
887
+		$foreignKey = $foreignKey ?: $this->getForeignKey();
888
+
889
+		$relatedMapper = $this->manager->mapper($related);
890
+
891
+		$relatedMap = $relatedMapper->getEntityMap();
892
+
893
+		$otherKey = $otherKey ?: $relatedMap->getForeignKey();
894
+
895
+		// If no table name was provided, we can guess it by concatenating the two
896
+		// models using underscores in alphabetical order. The two model names
897
+		// are transformed to snake case from their default CamelCase also.
898
+		if (is_null($table)) {
899
+			$table = $this->joiningTable($relatedMap);
900
+		}
901
+
902
+		return new BelongsToMany($relatedMapper, $entity, $table, $foreignKey, $otherKey, $relation);
903
+	}
904
+
905
+	/**
906
+	 * Define a polymorphic many-to-many relationship.
907
+	 *
908
+	 * @param  mixed       $entity
909
+	 * @param  string      $related
910
+	 * @param  string      $name
911
+	 * @param  string|null $table
912
+	 * @param  string|null $foreignKey
913
+	 * @param  string|null $otherKey
914
+	 * @param  bool        $inverse
915
+	 * @throws MappingException
916
+	 * @return \Analogue\ORM\Relationships\MorphToMany
917
+	 */
918
+	public function morphToMany($entity, $related, $name, $table = null, $foreignKey = null, $otherKey = null, $inverse = false)
919
+	{
920
+		$caller = $this->getBelongsToManyCaller();
921
+
922
+		// First, we will need to determine the foreign key and "other key" for the
923
+		// relationship. Once we have determined the keys we will make the query
924
+		// instances, as well as the relationship instances we need for these.
925
+		$foreignKey = $foreignKey ?: $name . '_id';
926
+
927
+		$relatedMapper = $this->manager->mapper($related);
928
+
929
+		$otherKey = $otherKey ?: $relatedMapper->getEntityMap()->getForeignKey();
930
+
931
+		$table = $table ?: str_plural($name);
932
+
933
+		return new MorphToMany($relatedMapper, $entity, $name, $table, $foreignKey, $otherKey, $caller, $inverse);
934
+	}
935
+
936
+	/**
937
+	 * Define a polymorphic, inverse many-to-many relationship.
938
+	 *
939
+	 * @param  mixed       $entity
940
+	 * @param  string      $related
941
+	 * @param  string      $name
942
+	 * @param  string|null $table
943
+	 * @param  string|null $foreignKey
944
+	 * @param  string|null $otherKey
945
+	 * @throws MappingException
946
+	 * @return \Analogue\ORM\Relationships\MorphToMany
947
+	 */
948
+	public function morphedByMany($entity, $related, $name, $table = null, $foreignKey = null, $otherKey = null)
949
+	{
950
+		$foreignKey = $foreignKey ?: $this->getForeignKey();
951
+
952
+		// For the inverse of the polymorphic many-to-many relations, we will change
953
+		// the way we determine the foreign and other keys, as it is the opposite
954
+		// of the morph-to-many method since we're figuring out these inverses.
955
+		$otherKey = $otherKey ?: $name . '_id';
956
+
957
+		return $this->morphToMany($entity, $related, $name, $table, $foreignKey, $otherKey, true);
958
+	}
959
+
960
+	/**
961
+	 * Get the relationship name of the belongs to many.
962
+	 *
963
+	 * @return string
964
+	 */
965
+	protected function getBelongsToManyCaller()
966
+	{
967
+		$self = __FUNCTION__;
968
+
969
+		$caller = array_first(debug_backtrace(false), function ($key, $trace) use ($self) {
970
+			$caller = $trace['function'];
971
+
972
+			return (!in_array($caller, EntityMap::$manyMethods) && $caller != $self);
973
+		});
974
+
975
+		return !is_null($caller) ? $caller['function'] : null;
976
+	}
977
+
978
+	/**
979
+	 * Get the joining table name for a many-to-many relation.
980
+	 *
981
+	 * @param  EntityMap $relatedMap
982
+	 * @return string
983
+	 */
984
+	public function joiningTable($relatedMap)
985
+	{
986
+		// The joining table name, by convention, is simply the snake cased models
987
+		// sorted alphabetically and concatenated with an underscore, so we can
988
+		// just sort the models and join them together to get the table name.
989
+		$base = $this->getTable();
990
+
991
+		$related = $relatedMap->getTable();
992
+
993
+		$tables = [$related, $base];
994
+
995
+		// Now that we have the model names in an array we can just sort them and
996
+		// use the implode function to join them together with an underscores,
997
+		// which is typically used by convention within the database system.
998
+		sort($tables);
999
+
1000
+		return strtolower(implode('_', $tables));
1001
+	}
1002
+
1003
+	/**
1004
+	 * Get the polymorphic relationship columns.
1005
+	 *
1006
+	 * @param  string $name
1007
+	 * @param  string $type
1008
+	 * @param  string $id
1009
+	 * @return string[]
1010
+	 */
1011
+	protected function getMorphs($name, $type, $id)
1012
+	{
1013
+		$type = $type ?: $name . '_type';
1014
+
1015
+		$id = $id ?: $name . '_id';
1016
+
1017
+		return [$type, $id];
1018
+	}
1019
+
1020
+	/**
1021
+	 * Get the class name for polymorphic relations.
1022
+	 *
1023
+	 * @return string
1024
+	 */
1025
+	public function getMorphClass()
1026
+	{
1027
+		$morphClass = $this->manager->getMorphMap($this->getClass());
1028
+		return $this->morphClass ?: $morphClass;
1029
+	}
1030 1030
     
1031
-    /**
1032
-     * Create a new Entity Collection instance.
1033
-     *
1034
-     * @param  array $entities
1035
-     * @return \Analogue\ORM\EntityCollection
1036
-     */
1037
-    public function newCollection(array $entities = [])
1038
-    {
1039
-        return new EntityCollection($entities, $this);
1040
-    }
1041
-
1042
-    /**
1043
-     * Process EntityMap parsing at initialization time
1044
-     *
1045
-     * @return void
1046
-     */
1047
-    public function initialize()
1048
-    {
1049
-        $userMethods = $this->getCustomMethods();
1050
-
1051
-        // Parse EntityMap for method based relationship
1052
-        if (count($userMethods) > 0) {
1053
-            $this->relationships = $this->parseMethodsForRelationship($userMethods);
1054
-        }
1055
-
1056
-        // Parse EntityMap for dynamic relationships
1057
-        if (count($this->dynamicRelationships) > 0) {
1058
-            $this->relationships = $this->relationships + $this->getDynamicRelationships();
1059
-        }
1060
-    }
1061
-
1062
-    /**
1063
-     * Parse every relationships on the EntityMap and sort
1064
-     * them by type.
1065
-     *
1066
-     * @return void
1067
-     */
1068
-    public function boot()
1069
-    {
1070
-        if (count($this->relationships > 0)) {
1071
-            $this->sortRelationshipsByType();
1072
-        }
1073
-    }
1074
-
1075
-    /**
1076
-     * Get Methods that has been added in the child class.
1077
-     *
1078
-     * @return array
1079
-     */
1080
-    protected function getCustomMethods()
1081
-    {
1082
-        $mapMethods = get_class_methods($this);
1083
-
1084
-        $parentsMethods = get_class_methods('Analogue\ORM\EntityMap');
1031
+	/**
1032
+	 * Create a new Entity Collection instance.
1033
+	 *
1034
+	 * @param  array $entities
1035
+	 * @return \Analogue\ORM\EntityCollection
1036
+	 */
1037
+	public function newCollection(array $entities = [])
1038
+	{
1039
+		return new EntityCollection($entities, $this);
1040
+	}
1041
+
1042
+	/**
1043
+	 * Process EntityMap parsing at initialization time
1044
+	 *
1045
+	 * @return void
1046
+	 */
1047
+	public function initialize()
1048
+	{
1049
+		$userMethods = $this->getCustomMethods();
1050
+
1051
+		// Parse EntityMap for method based relationship
1052
+		if (count($userMethods) > 0) {
1053
+			$this->relationships = $this->parseMethodsForRelationship($userMethods);
1054
+		}
1055
+
1056
+		// Parse EntityMap for dynamic relationships
1057
+		if (count($this->dynamicRelationships) > 0) {
1058
+			$this->relationships = $this->relationships + $this->getDynamicRelationships();
1059
+		}
1060
+	}
1061
+
1062
+	/**
1063
+	 * Parse every relationships on the EntityMap and sort
1064
+	 * them by type.
1065
+	 *
1066
+	 * @return void
1067
+	 */
1068
+	public function boot()
1069
+	{
1070
+		if (count($this->relationships > 0)) {
1071
+			$this->sortRelationshipsByType();
1072
+		}
1073
+	}
1074
+
1075
+	/**
1076
+	 * Get Methods that has been added in the child class.
1077
+	 *
1078
+	 * @return array
1079
+	 */
1080
+	protected function getCustomMethods()
1081
+	{
1082
+		$mapMethods = get_class_methods($this);
1083
+
1084
+		$parentsMethods = get_class_methods('Analogue\ORM\EntityMap');
1085 1085
         
1086
-        return array_diff($mapMethods, $parentsMethods);
1087
-    }
1088
-
1089
-    /**
1090
-     * Parse user's class methods for relationships
1091
-     *
1092
-     * @param  array $customMethods
1093
-     * @return array
1094
-     */
1095
-    protected function parseMethodsForRelationship(array $customMethods)
1096
-    {
1097
-        $relationships = [];
1098
-
1099
-        $class = new ReflectionClass(get_class($this));
1100
-
1101
-        // Get the mapped Entity class, as we will detect relationships
1102
-        // methods by testing that the first argument is type-hinted to
1103
-        // the same class as the mapped Entity.
1104
-        $entityClass = $this->getClass();
1105
-
1106
-        foreach ($customMethods as $methodName) {
1107
-            $method = $class->getMethod($methodName);
1108
-
1109
-            if ($method->getNumberOfParameters() > 0) {
1110
-                $params = $method->getParameters();
1111
-
1112
-                if ($params[0]->getClass() && $params[0]->getClass()->name == $entityClass) {
1113
-                    $relationships[] = $methodName;
1114
-                }
1115
-            }
1116
-        }
1117
-
1118
-        return $relationships;
1119
-    }
1120
-
1121
-    /**
1122
-     * Sort Relationships methods by type
1123
-     *
1124
-     * @return void
1125
-     */
1126
-    protected function sortRelationshipsByType()
1127
-    {
1128
-        $entityClass = $this->getClass();
1129
-
1130
-        // Instantiate a dummy entity which we will pass to relationship methods.
1131
-        $entity = unserialize(sprintf('O:%d:"%s":0:{}', strlen($entityClass), $entityClass));
1086
+		return array_diff($mapMethods, $parentsMethods);
1087
+	}
1088
+
1089
+	/**
1090
+	 * Parse user's class methods for relationships
1091
+	 *
1092
+	 * @param  array $customMethods
1093
+	 * @return array
1094
+	 */
1095
+	protected function parseMethodsForRelationship(array $customMethods)
1096
+	{
1097
+		$relationships = [];
1098
+
1099
+		$class = new ReflectionClass(get_class($this));
1100
+
1101
+		// Get the mapped Entity class, as we will detect relationships
1102
+		// methods by testing that the first argument is type-hinted to
1103
+		// the same class as the mapped Entity.
1104
+		$entityClass = $this->getClass();
1105
+
1106
+		foreach ($customMethods as $methodName) {
1107
+			$method = $class->getMethod($methodName);
1108
+
1109
+			if ($method->getNumberOfParameters() > 0) {
1110
+				$params = $method->getParameters();
1111
+
1112
+				if ($params[0]->getClass() && $params[0]->getClass()->name == $entityClass) {
1113
+					$relationships[] = $methodName;
1114
+				}
1115
+			}
1116
+		}
1117
+
1118
+		return $relationships;
1119
+	}
1120
+
1121
+	/**
1122
+	 * Sort Relationships methods by type
1123
+	 *
1124
+	 * @return void
1125
+	 */
1126
+	protected function sortRelationshipsByType()
1127
+	{
1128
+		$entityClass = $this->getClass();
1129
+
1130
+		// Instantiate a dummy entity which we will pass to relationship methods.
1131
+		$entity = unserialize(sprintf('O:%d:"%s":0:{}', strlen($entityClass), $entityClass));
1132 1132
         
1133
-        foreach ($this->relationships as $relation) {
1134
-            $relationObject = $this->$relation($entity);
1135
-
1136
-            $class = class_basename(get_class($relationObject));
1137
-
1138
-            if (in_array($class, static::$singleClasses)) {
1139
-                $this->singleRelations[] = $relation;
1140
-            }
1141
-
1142
-            if (in_array($class, static::$manyClasses)) {
1143
-                $this->manyRelations[] = $relation;
1144
-            }
1145
-
1146
-            if (in_array($class, static::$localClasses)) {
1147
-                $this->localRelations[] = $relation;
1148
-            }
1149
-
1150
-            if (in_array($class, static::$foreignClasses)) {
1151
-                $this->foreignRelations[] = $relation;
1152
-            }
1153
-
1154
-            if (in_array($class, static::$pivotClasses)) {
1155
-                $this->pivotRelations[] = $relation;
1156
-            }
1157
-        }
1158
-    }
1159
-
1160
-    /**
1161
-     * Override this method for custom entity instantiation
1162
-     *
1163
-     * @return null
1164
-     */
1165
-    public function activator()
1166
-    {
1167
-        return null;
1168
-    }
1169
-
1170
-    /**
1171
-     * Call dynamic relationship, if it exists
1172
-     *
1173
-     * @param  string $method
1174
-     * @param  array  $parameters
1175
-     * @throws Exception
1176
-     * @return mixed
1177
-     */
1178
-    public function __call($method, $parameters)
1179
-    {
1180
-        if (!array_key_exists($method, $this->dynamicRelationships)) {
1181
-            throw new Exception(get_class($this) . " has no method $method");
1182
-        }
1183
-
1184
-        // Add $this to parameters so the closure can call relationship method on the map.
1185
-        $parameters[] = $this;
1186
-
1187
-        return  call_user_func_array([$this->dynamicRelationships[$method], $parameters]);
1188
-    }
1189
-
1190
-    /**
1191
-     * Maps the names of the column names to the appropriate attributes
1192
-     * of an entity if the $attributes property of an EntityMap is an
1193
-     * associative array.
1194
-     * 
1195
-     * @param array $array
1196
-     * @return array
1197
-     */
1198
-    public function mapColumnsToAttributes($array)
1199
-    {
1200
-        $attributes = $this->getAttributes();
1201
-
1202
-        $keyName = $this->getKeyName();
1203
-
1204
-        if (is_asociative_array($attributes)) {
1205
-            $newArray = [];
1206
-
1207
-            foreach ($array as $key => $value) {
1208
-                $attributeName = isset($attributes[$key]) ? $attributes[$key] : $key;
1209
-                $newArray[$attributeName] = $value;
1210
-
1211
-                // if ($keyName == $key) {
1212
-                //     $this->setKeyName($attributeName);
1213
-                // }
1214
-            }
1215
-
1216
-            return $newArray;
1217
-        }
1218
-
1219
-        return $array;
1220
-    }
1221
-
1222
-    public function mapColumnToAttribute($column_name)
1223
-    {
1224
-        $attributes = $this->getAttributes();
1225
-
1226
-        if (is_asociative_array($attributes)) {
1227
-            if (isset($attributes[$column_name])) {
1228
-                return $attributes[$column_name];
1229
-            }
1230
-        }
1231
-
1232
-        return $column_name;
1233
-    }
1234
-
1235
-    public function mapAttributeToColumn($attribute_name)
1236
-    {
1237
-        $attributes = $this->getAttributes();
1238
-
1239
-        if (is_asociative_array($attributes)) {
1240
-            $flipped = array_flip($attributes);
1241
-            if (isset($flipped[$attribute_name])) {
1242
-                return $flipped[$attribute_name];
1243
-            }
1244
-        }
1245
-
1246
-        return $attribute_name;
1247
-    }
1248
-
1249
-    /**
1250
-     * Maps the attribute names of an entity to the appropriate
1251
-     * column names in the database if the $attributes property of
1252
-     * an EntityMap is an associative array.
1253
-     * 
1254
-     * @param array $array
1255
-     * @return array
1256
-     */
1257
-    public function mapAttributesToColumns($array)
1258
-    {
1259
-        $attributes = $this->getAttributes();
1260
-
1261
-        if (is_asociative_array($attributes)) {
1262
-            $flipped = array_flip($attributes);
1263
-
1264
-            foreach ($array as $key => $value) {
1265
-                $attributeName = isset($flipped[$key]) ? $flipped[$key] : $key;
1266
-                $newArray[$attributeName] = $value;
1267
-            }
1268
-
1269
-            return $newArray;
1270
-        }
1271
-
1272
-        return $array;
1273
-    }
1274
-
1275
-    public function hasAttribute($attribute)
1276
-    {
1277
-        $attributes = $this->getAttributes();
1278
-
1279
-        if (is_asociative_array($attributes)) {
1280
-            return in_array($attribute, array_values($attributes));
1281
-        }
1282
-
1283
-        return in_array($attribute, $attributes);
1284
-    }
1133
+		foreach ($this->relationships as $relation) {
1134
+			$relationObject = $this->$relation($entity);
1135
+
1136
+			$class = class_basename(get_class($relationObject));
1137
+
1138
+			if (in_array($class, static::$singleClasses)) {
1139
+				$this->singleRelations[] = $relation;
1140
+			}
1141
+
1142
+			if (in_array($class, static::$manyClasses)) {
1143
+				$this->manyRelations[] = $relation;
1144
+			}
1145
+
1146
+			if (in_array($class, static::$localClasses)) {
1147
+				$this->localRelations[] = $relation;
1148
+			}
1149
+
1150
+			if (in_array($class, static::$foreignClasses)) {
1151
+				$this->foreignRelations[] = $relation;
1152
+			}
1153
+
1154
+			if (in_array($class, static::$pivotClasses)) {
1155
+				$this->pivotRelations[] = $relation;
1156
+			}
1157
+		}
1158
+	}
1159
+
1160
+	/**
1161
+	 * Override this method for custom entity instantiation
1162
+	 *
1163
+	 * @return null
1164
+	 */
1165
+	public function activator()
1166
+	{
1167
+		return null;
1168
+	}
1169
+
1170
+	/**
1171
+	 * Call dynamic relationship, if it exists
1172
+	 *
1173
+	 * @param  string $method
1174
+	 * @param  array  $parameters
1175
+	 * @throws Exception
1176
+	 * @return mixed
1177
+	 */
1178
+	public function __call($method, $parameters)
1179
+	{
1180
+		if (!array_key_exists($method, $this->dynamicRelationships)) {
1181
+			throw new Exception(get_class($this) . " has no method $method");
1182
+		}
1183
+
1184
+		// Add $this to parameters so the closure can call relationship method on the map.
1185
+		$parameters[] = $this;
1186
+
1187
+		return  call_user_func_array([$this->dynamicRelationships[$method], $parameters]);
1188
+	}
1189
+
1190
+	/**
1191
+	 * Maps the names of the column names to the appropriate attributes
1192
+	 * of an entity if the $attributes property of an EntityMap is an
1193
+	 * associative array.
1194
+	 * 
1195
+	 * @param array $array
1196
+	 * @return array
1197
+	 */
1198
+	public function mapColumnsToAttributes($array)
1199
+	{
1200
+		$attributes = $this->getAttributes();
1201
+
1202
+		$keyName = $this->getKeyName();
1203
+
1204
+		if (is_asociative_array($attributes)) {
1205
+			$newArray = [];
1206
+
1207
+			foreach ($array as $key => $value) {
1208
+				$attributeName = isset($attributes[$key]) ? $attributes[$key] : $key;
1209
+				$newArray[$attributeName] = $value;
1210
+
1211
+				// if ($keyName == $key) {
1212
+				//     $this->setKeyName($attributeName);
1213
+				// }
1214
+			}
1215
+
1216
+			return $newArray;
1217
+		}
1218
+
1219
+		return $array;
1220
+	}
1221
+
1222
+	public function mapColumnToAttribute($column_name)
1223
+	{
1224
+		$attributes = $this->getAttributes();
1225
+
1226
+		if (is_asociative_array($attributes)) {
1227
+			if (isset($attributes[$column_name])) {
1228
+				return $attributes[$column_name];
1229
+			}
1230
+		}
1231
+
1232
+		return $column_name;
1233
+	}
1234
+
1235
+	public function mapAttributeToColumn($attribute_name)
1236
+	{
1237
+		$attributes = $this->getAttributes();
1238
+
1239
+		if (is_asociative_array($attributes)) {
1240
+			$flipped = array_flip($attributes);
1241
+			if (isset($flipped[$attribute_name])) {
1242
+				return $flipped[$attribute_name];
1243
+			}
1244
+		}
1245
+
1246
+		return $attribute_name;
1247
+	}
1248
+
1249
+	/**
1250
+	 * Maps the attribute names of an entity to the appropriate
1251
+	 * column names in the database if the $attributes property of
1252
+	 * an EntityMap is an associative array.
1253
+	 * 
1254
+	 * @param array $array
1255
+	 * @return array
1256
+	 */
1257
+	public function mapAttributesToColumns($array)
1258
+	{
1259
+		$attributes = $this->getAttributes();
1260
+
1261
+		if (is_asociative_array($attributes)) {
1262
+			$flipped = array_flip($attributes);
1263
+
1264
+			foreach ($array as $key => $value) {
1265
+				$attributeName = isset($flipped[$key]) ? $flipped[$key] : $key;
1266
+				$newArray[$attributeName] = $value;
1267
+			}
1268
+
1269
+			return $newArray;
1270
+		}
1271
+
1272
+		return $array;
1273
+	}
1274
+
1275
+	public function hasAttribute($attribute)
1276
+	{
1277
+		$attributes = $this->getAttributes();
1278
+
1279
+		if (is_asociative_array($attributes)) {
1280
+			return in_array($attribute, array_values($attributes));
1281
+		}
1282
+
1283
+		return in_array($attribute, $attributes);
1284
+	}
1285 1285
 }
Please login to merge, or discard this patch.
src/Commands/Store.php 1 patch
Indentation   +224 added lines, -224 removed lines patch added patch discarded remove patch
@@ -14,239 +14,239 @@
 block discarded – undo
14 14
  */
15 15
 class Store extends Command
16 16
 {
17
-    /**
18
-     * Persist the entity in the database
19
-     *
20
-     * @throws \InvalidArgumentException
21
-     * @return false|mixed
22
-     */
23
-    public function execute()
24
-    {
25
-        $entity = $this->aggregate->getEntityObject();
26
-
27
-        $mapper = $this->aggregate->getMapper();
28
-
29
-        if ($mapper->fireEvent('storing', $entity) === false) {
30
-            return false;
31
-        }
32
-
33
-        $this->preStoreProcess();
34
-
35
-        /**
36
-         * We will test the entity for existence
37
-         * and run a creation if it doesn't exists
38
-         */
39
-        if (!$this->aggregate->exists()) {
40
-            if ($mapper->fireEvent('creating', $entity) === false) {
41
-                return false;
42
-            }
43
-
44
-            $this->insert();
45
-
46
-            $mapper->fireEvent('created', $entity, false);
47
-        }
48
-        else if ($this->aggregate->isDirty()) {
49
-            if ($mapper->fireEvent('updating', $entity) === false) {
50
-                return false;
51
-            }
52
-            $this->update();
53
-
54
-            $mapper->fireEvent('updated', $entity, false);
55
-        }
56
-
57
-        $this->postStoreProcess();
58
-
59
-        $mapper->fireEvent('stored', $entity, false);
60
-
61
-        return $entity;
62
-    }
63
-
64
-    /**
65
-     * Run all operations that have to occur before actually
66
-     * storing the entity
67
-     *
68
-     * @throws \InvalidArgumentException
69
-     * @return void
70
-     */
71
-    protected function preStoreProcess()
72
-    {
73
-        // Create any related object that doesn't exist in the database.
74
-        $localRelationships = $this->aggregate->getEntityMap()->getLocalRelationships();
75
-
76
-        $this->createRelatedEntities($localRelationships);
77
-
78
-        // Now we can sync the related collections
79
-        $this->aggregate->syncRelationships($localRelationships);
80
-    }
81
-
82
-    /**
83
-     * Check for existence and create non-existing related entities
84
-     *
85
-     * @param  array
86
-     * @throws \InvalidArgumentException
87
-     * @return void
88
-     */
89
-    protected function createRelatedEntities($relations)
90
-    {
91
-        $entitiesToCreate = $this->aggregate->getNonExistingRelated($relations);
92
-
93
-        foreach ($entitiesToCreate as $aggregate) {
94
-            $this->createStoreCommand($aggregate)->execute();
95
-        }
96
-    }
97
-
98
-    /**
99
-     * Create a new store command
100
-     *
101
-     * @param  Aggregate $aggregate
102
-     * @return Store
103
-     */
104
-    protected function createStoreCommand(Aggregate $aggregate)
105
-    {
106
-        // We gotta retrieve the corresponding query adapter to use.
107
-        $mapper = $aggregate->getMapper();
108
-
109
-        return new Store($aggregate, $mapper->newQueryBuilder());
110
-    }
111
-
112
-    /**
113
-     * Run all operations that have to occur after the entity
114
-     * is stored.
115
-     *
116
-     * @throws \InvalidArgumentException
117
-     * @return void
118
-     */
119
-    protected function postStoreProcess()
120
-    {
121
-        $aggregate = $this->aggregate;
122
-
123
-        // Create any related object that doesn't exist in the database.
124
-        $foreignRelationships = $aggregate->getEntityMap()->getForeignRelationships();
125
-        $this->createRelatedEntities($foreignRelationships);
126
-
127
-        // Update any pivot tables that has been modified.
128
-        $aggregate->updatePivotRecords();
129
-
130
-        // Update any dirty relationship. This include relationships that already exists, have
131
-        // dirty attributes / newly created related entities / dirty related entities.
132
-        $dirtyRelatedAggregates = $aggregate->getDirtyRelationships();
133
-
134
-        foreach ($dirtyRelatedAggregates as $related) {
135
-            $this->createStoreCommand($related)->execute();
136
-        }
137
-
138
-        // Now we can sync the related collections
139
-        if ($this->aggregate->exists()) {
140
-            $this->aggregate->syncRelationships($foreignRelationships);
141
-        }
17
+	/**
18
+	 * Persist the entity in the database
19
+	 *
20
+	 * @throws \InvalidArgumentException
21
+	 * @return false|mixed
22
+	 */
23
+	public function execute()
24
+	{
25
+		$entity = $this->aggregate->getEntityObject();
26
+
27
+		$mapper = $this->aggregate->getMapper();
28
+
29
+		if ($mapper->fireEvent('storing', $entity) === false) {
30
+			return false;
31
+		}
32
+
33
+		$this->preStoreProcess();
34
+
35
+		/**
36
+		 * We will test the entity for existence
37
+		 * and run a creation if it doesn't exists
38
+		 */
39
+		if (!$this->aggregate->exists()) {
40
+			if ($mapper->fireEvent('creating', $entity) === false) {
41
+				return false;
42
+			}
43
+
44
+			$this->insert();
45
+
46
+			$mapper->fireEvent('created', $entity, false);
47
+		}
48
+		else if ($this->aggregate->isDirty()) {
49
+			if ($mapper->fireEvent('updating', $entity) === false) {
50
+				return false;
51
+			}
52
+			$this->update();
53
+
54
+			$mapper->fireEvent('updated', $entity, false);
55
+		}
56
+
57
+		$this->postStoreProcess();
58
+
59
+		$mapper->fireEvent('stored', $entity, false);
60
+
61
+		return $entity;
62
+	}
63
+
64
+	/**
65
+	 * Run all operations that have to occur before actually
66
+	 * storing the entity
67
+	 *
68
+	 * @throws \InvalidArgumentException
69
+	 * @return void
70
+	 */
71
+	protected function preStoreProcess()
72
+	{
73
+		// Create any related object that doesn't exist in the database.
74
+		$localRelationships = $this->aggregate->getEntityMap()->getLocalRelationships();
75
+
76
+		$this->createRelatedEntities($localRelationships);
77
+
78
+		// Now we can sync the related collections
79
+		$this->aggregate->syncRelationships($localRelationships);
80
+	}
81
+
82
+	/**
83
+	 * Check for existence and create non-existing related entities
84
+	 *
85
+	 * @param  array
86
+	 * @throws \InvalidArgumentException
87
+	 * @return void
88
+	 */
89
+	protected function createRelatedEntities($relations)
90
+	{
91
+		$entitiesToCreate = $this->aggregate->getNonExistingRelated($relations);
92
+
93
+		foreach ($entitiesToCreate as $aggregate) {
94
+			$this->createStoreCommand($aggregate)->execute();
95
+		}
96
+	}
97
+
98
+	/**
99
+	 * Create a new store command
100
+	 *
101
+	 * @param  Aggregate $aggregate
102
+	 * @return Store
103
+	 */
104
+	protected function createStoreCommand(Aggregate $aggregate)
105
+	{
106
+		// We gotta retrieve the corresponding query adapter to use.
107
+		$mapper = $aggregate->getMapper();
108
+
109
+		return new Store($aggregate, $mapper->newQueryBuilder());
110
+	}
111
+
112
+	/**
113
+	 * Run all operations that have to occur after the entity
114
+	 * is stored.
115
+	 *
116
+	 * @throws \InvalidArgumentException
117
+	 * @return void
118
+	 */
119
+	protected function postStoreProcess()
120
+	{
121
+		$aggregate = $this->aggregate;
122
+
123
+		// Create any related object that doesn't exist in the database.
124
+		$foreignRelationships = $aggregate->getEntityMap()->getForeignRelationships();
125
+		$this->createRelatedEntities($foreignRelationships);
126
+
127
+		// Update any pivot tables that has been modified.
128
+		$aggregate->updatePivotRecords();
129
+
130
+		// Update any dirty relationship. This include relationships that already exists, have
131
+		// dirty attributes / newly created related entities / dirty related entities.
132
+		$dirtyRelatedAggregates = $aggregate->getDirtyRelationships();
133
+
134
+		foreach ($dirtyRelatedAggregates as $related) {
135
+			$this->createStoreCommand($related)->execute();
136
+		}
137
+
138
+		// Now we can sync the related collections
139
+		if ($this->aggregate->exists()) {
140
+			$this->aggregate->syncRelationships($foreignRelationships);
141
+		}
142 142
         
143
-        // TODO be move it to the wrapper class
144
-        // so it's the same code for the entity builder
145
-        $aggregate->setProxies();
146
-
147
-        // Update Entity Cache
148
-        $aggregate->getMapper()->getEntityCache()->refresh($aggregate);
149
-    }
150
-
151
-    /**
152
-     * Update Related Entities which attributes have
153
-     * been modified.
154
-     *
155
-     * @return void
156
-     */
157
-    protected function updateDirtyRelated()
158
-    {
159
-        $relations = $this->entityMap->getRelationships();
160
-        $attributes = $this->getAttributes();
161
-
162
-        foreach ($relations as $relation) {
163
-            if (!array_key_exists($relation, $attributes)) {
164
-                continue;
165
-            }
166
-
167
-            $value = $attributes[$relation];
168
-
169
-            if ($value == null) {
170
-                continue;
171
-            }
172
-
173
-            if ($value instanceof EntityProxy) {
174
-                continue;
175
-            }
176
-
177
-            if ($value instanceof CollectionProxy && $value->isLoaded()) {
178
-                $value = $value->getUnderlyingCollection();
179
-            }
180
-            if ($value instanceof CollectionProxy && !$value->isLoaded()) {
181
-                foreach ($value->getAddedItems() as $entity) {
182
-                    $this->updateEntityIfDirty($entity);
183
-                }
184
-                continue;
185
-            }
186
-
187
-            if ($value instanceof EntityCollection) {
188
-                foreach ($value as $entity) {
189
-                    if (!$this->createEntityIfNotExists($entity)) {
190
-                        $this->updateEntityIfDirty($entity);
191
-                    }
192
-                }
193
-                continue;
194
-            }
195
-            if ($value instanceof Mappable) {
196
-                $this->updateEntityIfDirty($value);
197
-                continue;
198
-            }
199
-        }
200
-    }
201
-
202
-    /**
203
-     * Execute an insert statement on the database
204
-     *
205
-     * @return void
206
-     */
207
-    protected function insert()
208
-    {
209
-        $aggregate = $this->aggregate;
210
-
211
-        $attributes = $aggregate->getRawAttributes();
143
+		// TODO be move it to the wrapper class
144
+		// so it's the same code for the entity builder
145
+		$aggregate->setProxies();
146
+
147
+		// Update Entity Cache
148
+		$aggregate->getMapper()->getEntityCache()->refresh($aggregate);
149
+	}
150
+
151
+	/**
152
+	 * Update Related Entities which attributes have
153
+	 * been modified.
154
+	 *
155
+	 * @return void
156
+	 */
157
+	protected function updateDirtyRelated()
158
+	{
159
+		$relations = $this->entityMap->getRelationships();
160
+		$attributes = $this->getAttributes();
161
+
162
+		foreach ($relations as $relation) {
163
+			if (!array_key_exists($relation, $attributes)) {
164
+				continue;
165
+			}
166
+
167
+			$value = $attributes[$relation];
168
+
169
+			if ($value == null) {
170
+				continue;
171
+			}
172
+
173
+			if ($value instanceof EntityProxy) {
174
+				continue;
175
+			}
176
+
177
+			if ($value instanceof CollectionProxy && $value->isLoaded()) {
178
+				$value = $value->getUnderlyingCollection();
179
+			}
180
+			if ($value instanceof CollectionProxy && !$value->isLoaded()) {
181
+				foreach ($value->getAddedItems() as $entity) {
182
+					$this->updateEntityIfDirty($entity);
183
+				}
184
+				continue;
185
+			}
186
+
187
+			if ($value instanceof EntityCollection) {
188
+				foreach ($value as $entity) {
189
+					if (!$this->createEntityIfNotExists($entity)) {
190
+						$this->updateEntityIfDirty($entity);
191
+					}
192
+				}
193
+				continue;
194
+			}
195
+			if ($value instanceof Mappable) {
196
+				$this->updateEntityIfDirty($value);
197
+				continue;
198
+			}
199
+		}
200
+	}
201
+
202
+	/**
203
+	 * Execute an insert statement on the database
204
+	 *
205
+	 * @return void
206
+	 */
207
+	protected function insert()
208
+	{
209
+		$aggregate = $this->aggregate;
210
+
211
+		$attributes = $aggregate->getRawAttributes();
212 212
         
213
-        $keyName = $aggregate->getEntityMap()->getKeyName();
213
+		$keyName = $aggregate->getEntityMap()->getKeyName();
214 214
 
215
-        // Check if the primary key is defined in the attributes
216
-        if (array_key_exists($keyName, $attributes) && $attributes[$keyName] != null) {
217
-            $this->query->insert($attributes);
218
-        } else {
219
-            $sequence = $aggregate->getEntityMap()->getSequence();
215
+		// Check if the primary key is defined in the attributes
216
+		if (array_key_exists($keyName, $attributes) && $attributes[$keyName] != null) {
217
+			$this->query->insert($attributes);
218
+		} else {
219
+			$sequence = $aggregate->getEntityMap()->getSequence();
220 220
 
221
-            if (empty($attributes[$keyName])) {
222
-                unset($attributes[$keyName]);
223
-            }
221
+			if (empty($attributes[$keyName])) {
222
+				unset($attributes[$keyName]);
223
+			}
224 224
 
225
-            $id = $this->query->insertGetId($attributes, $sequence);
225
+			$id = $this->query->insertGetId($attributes, $sequence);
226 226
 
227
-            $aggregate->setEntityAttribute($keyName, $id);
228
-        }
229
-    }
227
+			$aggregate->setEntityAttribute($keyName, $id);
228
+		}
229
+	}
230 230
 
231
-    /**
232
-     * Run an update statement on the entity
233
-     *
234
-     * @throws \InvalidArgumentException
235
-     *
236
-     * @return void
237
-     */
238
-    protected function update()
239
-    {
240
-        $query = $this->query;
231
+	/**
232
+	 * Run an update statement on the entity
233
+	 *
234
+	 * @throws \InvalidArgumentException
235
+	 *
236
+	 * @return void
237
+	 */
238
+	protected function update()
239
+	{
240
+		$query = $this->query;
241 241
 
242
-        $keyName = $this->aggregate->getEntityKey();
242
+		$keyName = $this->aggregate->getEntityKey();
243 243
 
244
-        $query = $query->where($keyName, '=', $this->aggregate->getEntityId());
244
+		$query = $query->where($keyName, '=', $this->aggregate->getEntityId());
245 245
 
246
-        $dirtyAttributes = $this->aggregate->getDirtyRawAttributes();
246
+		$dirtyAttributes = $this->aggregate->getDirtyRawAttributes();
247 247
 
248
-        if (count($dirtyAttributes) > 0) {
249
-            $query->update($dirtyAttributes);
250
-        }
251
-    }
248
+		if (count($dirtyAttributes) > 0) {
249
+			$query->update($dirtyAttributes);
250
+		}
251
+	}
252 252
 }
Please login to merge, or discard this patch.
src/EntityCollection.php 1 patch
Indentation   +391 added lines, -391 removed lines patch added patch discarded remove patch
@@ -10,395 +10,395 @@
 block discarded – undo
10 10
 
11 11
 class EntityCollection extends Collection
12 12
 {
13
-    /**
14
-     * Wrapper Factory
15
-     *
16
-     * @var \Analogue\ORM\System\Wrappers\Factory
17
-     */
18
-    protected $factory;
19
-
20
-    /**
21
-     * EntityCollection constructor.
22
-     * @param array|null $entities
23
-     */
24
-    public function __construct(array $entities = null)
25
-    {
26
-        $this->factory = new Factory;
27
-
28
-        parent::__construct($entities);
29
-    }
30
-
31
-    /**
32
-     * Find an entity in the collection by key.
33
-     *
34
-     * @param  mixed $key
35
-     * @param  mixed $default
36
-     * @throws MappingException
37
-     * @return \Analogue\ORM\Entity
38
-     */
39
-    public function find($key, $default = null)
40
-    {
41
-        if ($key instanceof Mappable) {
42
-            $key = $this->getEntityKey($key);
43
-        }
44
-
45
-        return array_first($this->items, function ($itemKey, $entity) use ($key) {
46
-            return $this->getEntityKey($entity) == $key;
47
-        }, $default);
48
-    }
49
-
50
-    /**
51
-     * Add an entity to the collection.
52
-     *
53
-     * @param  Mappable $entity
54
-     * @return $this
55
-     */
56
-    public function add($entity)
57
-    {
58
-        $this->push($entity);
59
-
60
-        return $this;
61
-    }
62
-
63
-    /**
64
-     * Remove an entity from the collection
65
-     *
66
-     * @param $entity
67
-     * @throws MappingException
68
-     * @return mixed
69
-     */
70
-    public function remove($entity)
71
-    {
72
-        $key = $this->getEntityKey($entity);
73
-
74
-        return $this->pull($key);
75
-    }
76
-
77
-    /**
78
-     * Push an item onto the end of the collection.
79
-     *
80
-     * @param  mixed $value
81
-     * @return void
82
-     */
83
-    public function push($value)
84
-    {
85
-        $this->offsetSet(null, $value);
86
-    }
87
-
88
-    /**
89
-     * Put an item in the collection by key.
90
-     *
91
-     * @param  mixed $key
92
-     * @param  mixed $value
93
-     * @return void
94
-     */
95
-    public function put($key, $value)
96
-    {
97
-        $this->offsetSet($key, $value);
98
-    }
99
-
100
-    /**
101
-     * Set the item at a given offset.
102
-     *
103
-     * @param  mixed $key
104
-     * @param  mixed $value
105
-     * @return void
106
-     */
107
-    public function offsetSet($key, $value)
108
-    {
109
-        if (is_null($key)) {
110
-            $this->items[] = $value;
111
-        } else {
112
-            $this->items[$key] = $value;
113
-        }
114
-    }
115
-
116
-    /**
117
-     * Determine if a key exists in the collection.
118
-     *
119
-     * @param  mixed      $key
120
-     * @param  mixed|null $value
121
-     * @return bool
122
-     */
123
-    public function contains($key, $value = null)
124
-    {
125
-        if (func_num_args() == 2) {
126
-            return !$this->where($key, $value)->isEmpty();
127
-        }
128
-
129
-        if ($this->useAsCallable($key)) {
130
-            return !is_null($this->first($key));
131
-        }
132
-
133
-        return !is_null($this->find($key));
134
-    }
135
-
136
-    /**
137
-     * Fetch a nested element of the collection.
138
-     *
139
-     * @param  string $key
140
-     * @return self
141
-     */
142
-    public function fetch($key)
143
-    {
144
-        return new static(array_fetch($this->toArray(), $key));
145
-    }
146
-
147
-    /**
148
-     * Generic function for returning class.key value pairs
149
-     *
150
-     * @throws MappingException
151
-     * @return string
152
-     */
153
-    public function getEntityHashes()
154
-    {
155
-        return array_map(function ($entity) {
156
-            $class = get_class($entity);
157
-
158
-            $mapper = Manager::getMapper($class);
159
-
160
-            $keyName = $mapper->getEntityMap()->getKeyName();
161
-
162
-            return $class . '.' . $entity->getEntityAttribute($keyName);
163
-        },
164
-        $this->items);
165
-    }
166
-
167
-    /**
168
-     * Get a subset of the collection from entity hashes
169
-     *
170
-     * @param  array $hashes
171
-     * @throws MappingException
172
-     * @return array
173
-     */
174
-    public function getSubsetByHashes(array $hashes)
175
-    {
176
-        $subset = [];
177
-
178
-        foreach ($this->items as $item) {
179
-            $class = get_class($item);
180
-
181
-            $mapper = Manager::getMapper($class);
182
-
183
-            $keyName = $mapper->getEntityMap()->getKeyName();
184
-
185
-            if (in_array($class . '.' . $item->$keyName, $hashes)) {
186
-                $subset[] = $item;
187
-            }
188
-        }
189
-
190
-        return $subset;
191
-    }
192
-
193
-    /**
194
-     * Merge the collection with the given items.
195
-     *
196
-     * @param  array $items
197
-     * @throws MappingException
198
-     * @return self
199
-     */
200
-    public function merge($items)
201
-    {
202
-        $dictionary = $this->getDictionary();
203
-
204
-        foreach ($items as $item) {
205
-            $dictionary[$this->getEntityKey($item)] = $item;
206
-        }
207
-
208
-        return new static(array_values($dictionary));
209
-    }
210
-
211
-    /**
212
-     * Diff the collection with the given items.
213
-     *
214
-     * @param  \ArrayAccess|array $items
215
-     * @return self
216
-     */
217
-    public function diff($items)
218
-    {
219
-        $diff = new static;
220
-
221
-        $dictionary = $this->getDictionary($items);
222
-
223
-        foreach ($this->items as $item) {
224
-            if (!isset($dictionary[$this->getEntityKey($item)])) {
225
-                $diff->add($item);
226
-            }
227
-        }
228
-
229
-        return $diff;
230
-    }
231
-
232
-    /**
233
-     * Intersect the collection with the given items.
234
-     *
235
-     * @param  \ArrayAccess|array $items
236
-     * @throws MappingException
237
-     * @return self
238
-     */
239
-    public function intersect($items)
240
-    {
241
-        $intersect = new static;
242
-
243
-        $dictionary = $this->getDictionary($items);
244
-
245
-        foreach ($this->items as $item) {
246
-            if (isset($dictionary[$this->getEntityKey($item)])) {
247
-                $intersect->add($item);
248
-            }
249
-        }
250
-
251
-        return $intersect;
252
-    }
253
-
254
-    /**
255
-     * Returns only the models from the collection with the specified keys.
256
-     *
257
-     * @param  mixed $keys
258
-     * @return self
259
-     */
260
-    public function only($keys)
261
-    {
262
-        $dictionary = array_only($this->getDictionary(), $keys);
263
-
264
-        return new static(array_values($dictionary));
265
-    }
266
-
267
-    /**
268
-     * Returns all models in the collection except the models with specified keys.
269
-     *
270
-     * @param  mixed $keys
271
-     * @return self
272
-     */
273
-    public function except($keys)
274
-    {
275
-        $dictionary = array_except($this->getDictionary(), $keys);
276
-
277
-        return new static(array_values($dictionary));
278
-    }
279
-
280
-    /**
281
-     * Get a dictionary keyed by primary keys.
282
-     *
283
-     * @param  \ArrayAccess|array $items
284
-     * @throws MappingException
285
-     * @return array
286
-     */
287
-    public function getDictionary($items = null)
288
-    {
289
-        $items = is_null($items) ? $this->items : $items;
290
-
291
-        $dictionary = [];
292
-
293
-        foreach ($items as $value) {
294
-            $dictionary[$this->getEntityKey($value)] = $value;
295
-        }
296
-
297
-        return $dictionary;
298
-    }
299
-
300
-    /**
301
-     * @throws MappingException
302
-     * @return array
303
-     */
304
-    public function getEntityKeys()
305
-    {
306
-        return array_keys($this->getDictionary());
307
-    }
308
-
309
-    /**
310
-     * @param $entity
311
-     * @throws MappingException
312
-     * @return mixed
313
-     */
314
-    protected function getEntityKey($entity)
315
-    {
316
-        $keyName = Manager::getMapper($entity)->getEntityMap()->getKeyName();
317
-
318
-        $wrapper = $this->factory->make($entity);
319
-
320
-        return $wrapper->getEntityAttribute($keyName);
321
-    }
322
-
323
-    /**
324
-     * Get the max value of a given key.
325
-     *
326
-     * @param  string|null $key
327
-     * @throws MappingException
328
-     * @return mixed
329
-     */
330
-    public function max($key = null)
331
-    {
332
-        return $this->reduce(function ($result, $item) use ($key) {
333
-            $wrapper = $this->factory->make($item);
334
-
335
-            return (is_null($result) || $wrapper->getEntityAttribute($key) > $result) ?
336
-                $wrapper->getEntityAttribute($key) : $result;
337
-        });
338
-    }
339
-
340
-    /**
341
-     * Get the min value of a given key.
342
-     *
343
-     * @param  string|null $key
344
-     * @throws MappingException
345
-     * @return mixed
346
-     */
347
-    public function min($key = null)
348
-    {
349
-        return $this->reduce(function ($result, $item) use ($key) {
350
-            $wrapper = $this->factory->make($item);
351
-
352
-            return (is_null($result) || $wrapper->getEntityAttribute($key) < $result)
353
-                ? $wrapper->getEntityAttribute($key) : $result;
354
-        });
355
-    }
356
-
357
-    /**
358
-     * Get an array with the values of a given key.
359
-     *
360
-     * @param  string $value
361
-     * @param  string|null $key
362
-     * @return self
363
-     */
364
-    public function pluck($value, $key = null)
365
-    {
366
-        return new Collection(Arr::pluck($this->items, $value, $key));
367
-    }
368
-
369
-    /**
370
-     * Alias for the "pluck" method.
371
-     *
372
-     * @param  string $value
373
-     * @param  string|null $key
374
-     * @return self
375
-     */
376
-    public function lists($value, $key = null)
377
-    {
378
-        return $this->pluck($value, $key);
379
-    }
380
-
381
-    /**
382
-     * Return only unique items from the collection.
383
-     *
384
-     * @param  string|null $key
385
-     * @throws MappingException
386
-     * @return self
387
-     */
388
-    public function unique($key = null, $strict = false)
389
-    {
390
-        $dictionary = $this->getDictionary();
391
-
392
-        return new static(array_values($dictionary));
393
-    }
394
-
395
-    /**
396
-     * Get a base Support collection instance from this collection.
397
-     *
398
-     * @return \Illuminate\Support\Collection
399
-     */
400
-    public function toBase()
401
-    {
402
-        return new Collection($this->items);
403
-    }
13
+	/**
14
+	 * Wrapper Factory
15
+	 *
16
+	 * @var \Analogue\ORM\System\Wrappers\Factory
17
+	 */
18
+	protected $factory;
19
+
20
+	/**
21
+	 * EntityCollection constructor.
22
+	 * @param array|null $entities
23
+	 */
24
+	public function __construct(array $entities = null)
25
+	{
26
+		$this->factory = new Factory;
27
+
28
+		parent::__construct($entities);
29
+	}
30
+
31
+	/**
32
+	 * Find an entity in the collection by key.
33
+	 *
34
+	 * @param  mixed $key
35
+	 * @param  mixed $default
36
+	 * @throws MappingException
37
+	 * @return \Analogue\ORM\Entity
38
+	 */
39
+	public function find($key, $default = null)
40
+	{
41
+		if ($key instanceof Mappable) {
42
+			$key = $this->getEntityKey($key);
43
+		}
44
+
45
+		return array_first($this->items, function ($itemKey, $entity) use ($key) {
46
+			return $this->getEntityKey($entity) == $key;
47
+		}, $default);
48
+	}
49
+
50
+	/**
51
+	 * Add an entity to the collection.
52
+	 *
53
+	 * @param  Mappable $entity
54
+	 * @return $this
55
+	 */
56
+	public function add($entity)
57
+	{
58
+		$this->push($entity);
59
+
60
+		return $this;
61
+	}
62
+
63
+	/**
64
+	 * Remove an entity from the collection
65
+	 *
66
+	 * @param $entity
67
+	 * @throws MappingException
68
+	 * @return mixed
69
+	 */
70
+	public function remove($entity)
71
+	{
72
+		$key = $this->getEntityKey($entity);
73
+
74
+		return $this->pull($key);
75
+	}
76
+
77
+	/**
78
+	 * Push an item onto the end of the collection.
79
+	 *
80
+	 * @param  mixed $value
81
+	 * @return void
82
+	 */
83
+	public function push($value)
84
+	{
85
+		$this->offsetSet(null, $value);
86
+	}
87
+
88
+	/**
89
+	 * Put an item in the collection by key.
90
+	 *
91
+	 * @param  mixed $key
92
+	 * @param  mixed $value
93
+	 * @return void
94
+	 */
95
+	public function put($key, $value)
96
+	{
97
+		$this->offsetSet($key, $value);
98
+	}
99
+
100
+	/**
101
+	 * Set the item at a given offset.
102
+	 *
103
+	 * @param  mixed $key
104
+	 * @param  mixed $value
105
+	 * @return void
106
+	 */
107
+	public function offsetSet($key, $value)
108
+	{
109
+		if (is_null($key)) {
110
+			$this->items[] = $value;
111
+		} else {
112
+			$this->items[$key] = $value;
113
+		}
114
+	}
115
+
116
+	/**
117
+	 * Determine if a key exists in the collection.
118
+	 *
119
+	 * @param  mixed      $key
120
+	 * @param  mixed|null $value
121
+	 * @return bool
122
+	 */
123
+	public function contains($key, $value = null)
124
+	{
125
+		if (func_num_args() == 2) {
126
+			return !$this->where($key, $value)->isEmpty();
127
+		}
128
+
129
+		if ($this->useAsCallable($key)) {
130
+			return !is_null($this->first($key));
131
+		}
132
+
133
+		return !is_null($this->find($key));
134
+	}
135
+
136
+	/**
137
+	 * Fetch a nested element of the collection.
138
+	 *
139
+	 * @param  string $key
140
+	 * @return self
141
+	 */
142
+	public function fetch($key)
143
+	{
144
+		return new static(array_fetch($this->toArray(), $key));
145
+	}
146
+
147
+	/**
148
+	 * Generic function for returning class.key value pairs
149
+	 *
150
+	 * @throws MappingException
151
+	 * @return string
152
+	 */
153
+	public function getEntityHashes()
154
+	{
155
+		return array_map(function ($entity) {
156
+			$class = get_class($entity);
157
+
158
+			$mapper = Manager::getMapper($class);
159
+
160
+			$keyName = $mapper->getEntityMap()->getKeyName();
161
+
162
+			return $class . '.' . $entity->getEntityAttribute($keyName);
163
+		},
164
+		$this->items);
165
+	}
166
+
167
+	/**
168
+	 * Get a subset of the collection from entity hashes
169
+	 *
170
+	 * @param  array $hashes
171
+	 * @throws MappingException
172
+	 * @return array
173
+	 */
174
+	public function getSubsetByHashes(array $hashes)
175
+	{
176
+		$subset = [];
177
+
178
+		foreach ($this->items as $item) {
179
+			$class = get_class($item);
180
+
181
+			$mapper = Manager::getMapper($class);
182
+
183
+			$keyName = $mapper->getEntityMap()->getKeyName();
184
+
185
+			if (in_array($class . '.' . $item->$keyName, $hashes)) {
186
+				$subset[] = $item;
187
+			}
188
+		}
189
+
190
+		return $subset;
191
+	}
192
+
193
+	/**
194
+	 * Merge the collection with the given items.
195
+	 *
196
+	 * @param  array $items
197
+	 * @throws MappingException
198
+	 * @return self
199
+	 */
200
+	public function merge($items)
201
+	{
202
+		$dictionary = $this->getDictionary();
203
+
204
+		foreach ($items as $item) {
205
+			$dictionary[$this->getEntityKey($item)] = $item;
206
+		}
207
+
208
+		return new static(array_values($dictionary));
209
+	}
210
+
211
+	/**
212
+	 * Diff the collection with the given items.
213
+	 *
214
+	 * @param  \ArrayAccess|array $items
215
+	 * @return self
216
+	 */
217
+	public function diff($items)
218
+	{
219
+		$diff = new static;
220
+
221
+		$dictionary = $this->getDictionary($items);
222
+
223
+		foreach ($this->items as $item) {
224
+			if (!isset($dictionary[$this->getEntityKey($item)])) {
225
+				$diff->add($item);
226
+			}
227
+		}
228
+
229
+		return $diff;
230
+	}
231
+
232
+	/**
233
+	 * Intersect the collection with the given items.
234
+	 *
235
+	 * @param  \ArrayAccess|array $items
236
+	 * @throws MappingException
237
+	 * @return self
238
+	 */
239
+	public function intersect($items)
240
+	{
241
+		$intersect = new static;
242
+
243
+		$dictionary = $this->getDictionary($items);
244
+
245
+		foreach ($this->items as $item) {
246
+			if (isset($dictionary[$this->getEntityKey($item)])) {
247
+				$intersect->add($item);
248
+			}
249
+		}
250
+
251
+		return $intersect;
252
+	}
253
+
254
+	/**
255
+	 * Returns only the models from the collection with the specified keys.
256
+	 *
257
+	 * @param  mixed $keys
258
+	 * @return self
259
+	 */
260
+	public function only($keys)
261
+	{
262
+		$dictionary = array_only($this->getDictionary(), $keys);
263
+
264
+		return new static(array_values($dictionary));
265
+	}
266
+
267
+	/**
268
+	 * Returns all models in the collection except the models with specified keys.
269
+	 *
270
+	 * @param  mixed $keys
271
+	 * @return self
272
+	 */
273
+	public function except($keys)
274
+	{
275
+		$dictionary = array_except($this->getDictionary(), $keys);
276
+
277
+		return new static(array_values($dictionary));
278
+	}
279
+
280
+	/**
281
+	 * Get a dictionary keyed by primary keys.
282
+	 *
283
+	 * @param  \ArrayAccess|array $items
284
+	 * @throws MappingException
285
+	 * @return array
286
+	 */
287
+	public function getDictionary($items = null)
288
+	{
289
+		$items = is_null($items) ? $this->items : $items;
290
+
291
+		$dictionary = [];
292
+
293
+		foreach ($items as $value) {
294
+			$dictionary[$this->getEntityKey($value)] = $value;
295
+		}
296
+
297
+		return $dictionary;
298
+	}
299
+
300
+	/**
301
+	 * @throws MappingException
302
+	 * @return array
303
+	 */
304
+	public function getEntityKeys()
305
+	{
306
+		return array_keys($this->getDictionary());
307
+	}
308
+
309
+	/**
310
+	 * @param $entity
311
+	 * @throws MappingException
312
+	 * @return mixed
313
+	 */
314
+	protected function getEntityKey($entity)
315
+	{
316
+		$keyName = Manager::getMapper($entity)->getEntityMap()->getKeyName();
317
+
318
+		$wrapper = $this->factory->make($entity);
319
+
320
+		return $wrapper->getEntityAttribute($keyName);
321
+	}
322
+
323
+	/**
324
+	 * Get the max value of a given key.
325
+	 *
326
+	 * @param  string|null $key
327
+	 * @throws MappingException
328
+	 * @return mixed
329
+	 */
330
+	public function max($key = null)
331
+	{
332
+		return $this->reduce(function ($result, $item) use ($key) {
333
+			$wrapper = $this->factory->make($item);
334
+
335
+			return (is_null($result) || $wrapper->getEntityAttribute($key) > $result) ?
336
+				$wrapper->getEntityAttribute($key) : $result;
337
+		});
338
+	}
339
+
340
+	/**
341
+	 * Get the min value of a given key.
342
+	 *
343
+	 * @param  string|null $key
344
+	 * @throws MappingException
345
+	 * @return mixed
346
+	 */
347
+	public function min($key = null)
348
+	{
349
+		return $this->reduce(function ($result, $item) use ($key) {
350
+			$wrapper = $this->factory->make($item);
351
+
352
+			return (is_null($result) || $wrapper->getEntityAttribute($key) < $result)
353
+				? $wrapper->getEntityAttribute($key) : $result;
354
+		});
355
+	}
356
+
357
+	/**
358
+	 * Get an array with the values of a given key.
359
+	 *
360
+	 * @param  string $value
361
+	 * @param  string|null $key
362
+	 * @return self
363
+	 */
364
+	public function pluck($value, $key = null)
365
+	{
366
+		return new Collection(Arr::pluck($this->items, $value, $key));
367
+	}
368
+
369
+	/**
370
+	 * Alias for the "pluck" method.
371
+	 *
372
+	 * @param  string $value
373
+	 * @param  string|null $key
374
+	 * @return self
375
+	 */
376
+	public function lists($value, $key = null)
377
+	{
378
+		return $this->pluck($value, $key);
379
+	}
380
+
381
+	/**
382
+	 * Return only unique items from the collection.
383
+	 *
384
+	 * @param  string|null $key
385
+	 * @throws MappingException
386
+	 * @return self
387
+	 */
388
+	public function unique($key = null, $strict = false)
389
+	{
390
+		$dictionary = $this->getDictionary();
391
+
392
+		return new static(array_values($dictionary));
393
+	}
394
+
395
+	/**
396
+	 * Get a base Support collection instance from this collection.
397
+	 *
398
+	 * @return \Illuminate\Support\Collection
399
+	 */
400
+	public function toBase()
401
+	{
402
+		return new Collection($this->items);
403
+	}
404 404
 }
Please login to merge, or discard this patch.
src/Relationships/BelongsToMany.php 1 patch
Indentation   +929 added lines, -929 removed lines patch added patch discarded remove patch
@@ -12,938 +12,938 @@
 block discarded – undo
12 12
 
13 13
 class BelongsToMany extends Relationship
14 14
 {
15
-    /**
16
-     * The intermediate table for the relation.
17
-     *
18
-     * @var string
19
-     */
20
-    protected $table;
21
-
22
-    /**
23
-     * The foreign key of the parent model.
24
-     *
25
-     * @var string
26
-     */
27
-    protected $foreignKey;
28
-
29
-    /**
30
-     * The associated key of the relation.
31
-     *
32
-     * @var string
33
-     */
34
-    protected $otherKey;
35
-
36
-    /**
37
-     * The "name" of the relationship.
38
-     *
39
-     * @var string
40
-     */
41
-    protected $relationName;
42
-
43
-    /**
44
-     * The pivot table columns to retrieve.
45
-     *
46
-     * @var array
47
-     */
48
-    protected $pivotColumns = [];
49
-
50
-    /**
51
-     * This relationship has pivot attributes
52
-     *
53
-     * @var boolean
54
-     */
55
-    protected static $hasPivot = true;
56
-
57
-    /**
58
-     * Create a new has many relationship instance.
59
-     *
60
-     * @param Mapper   $mapper
61
-     * @param Mappable $parent
62
-     * @param string   $table
63
-     * @param string   $foreignKey
64
-     * @param string   $otherKey
65
-     * @param string   $relationName
66
-     */
67
-    public function __construct(Mapper $mapper, $parent, $table, $foreignKey, $otherKey, $relationName = null)
68
-    {
69
-        $this->table = $table;
70
-        $this->otherKey = $otherKey;
71
-        $this->foreignKey = $foreignKey;
72
-        $this->relationName = $relationName;
73
-
74
-        parent::__construct($mapper, $parent);
75
-    }
76
-
77
-    /**
78
-     * @param  $related
79
-     * @return mixed
80
-     */
81
-    public function attachTo($related)
82
-    {
83
-    }
84
-
85
-    /**
86
-     * @param  $related
87
-     * @return mixed
88
-     */
89
-    public function detachFrom($related)
90
-    {
91
-        $ids = $this->getIdsFromHashes([$related]);
92
-
93
-        $this->detach($ids);
94
-    }
95
-
96
-    /**
97
-     * @param $related
98
-     */
99
-    public function detachMany($related)
100
-    {
101
-        $ids = $this->getIdsFromHashes($related);
102
-
103
-        $this->detach($ids);
104
-    }
105
-
106
-    /**
107
-     * @param array $hashes
108
-     * @return array
109
-     */
110
-    protected function getIdsFromHashes(array $hashes)
111
-    {
112
-        $ids = [];
113
-
114
-        foreach ($hashes as $hash) {
115
-            $split = explode('.', $hash);
116
-            $ids[] = $split[1];
117
-        }
118
-        return $ids;
119
-    }
120
-
121
-    /**
122
-     * Get the results of the relationship.
123
-     *
124
-     * @param $relation
125
-     *
126
-     * @return EntityCollection
127
-     */
128
-    public function getResults($relation)
129
-    {
130
-        $results = $this->get();
131
-
132
-        $this->cacheRelation($results, $relation);
133
-
134
-        return $results;
135
-    }
136
-
137
-    /**
138
-     * Set a where clause for a pivot table column.
139
-     *
140
-     * @param  string $column
141
-     * @param  string $operator
142
-     * @param  mixed  $value
143
-     * @param  string $boolean
144
-     * @return self
145
-     */
146
-    public function wherePivot($column, $operator = null, $value = null, $boolean = 'and')
147
-    {
148
-        return $this->where($this->table . '.' . $column, $operator, $value, $boolean);
149
-    }
150
-
151
-    /**
152
-     * Set an or where clause for a pivot table column.
153
-     *
154
-     * @param  string $column
155
-     * @param  string $operator
156
-     * @param  mixed  $value
157
-     * @return self
158
-     */
159
-    public function orWherePivot($column, $operator = null, $value = null)
160
-    {
161
-        return $this->wherePivot($column, $operator, $value, 'or');
162
-    }
163
-
164
-    /**
165
-     * Return Pivot attributes when available on a relationship
166
-     *
167
-     * @return array
168
-     */
169
-    public function getPivotAttributes()
170
-    {
171
-        return $this->pivotColumns;
172
-    }
173
-
174
-    /**
175
-     * Execute the query and get the first result.
176
-     *
177
-     * @param  array $columns
178
-     * @return mixed
179
-     */
180
-    public function first($columns = ['*'])
181
-    {
182
-        $results = $this->take(1)->get($columns);
183
-
184
-        return count($results) > 0 ? $results->first() : null;
185
-    }
186
-
187
-    /**
188
-     * Execute the query and get the first result or throw an exception.
189
-     *
190
-     * @param  array $columns
191
-     *
192
-     * @throws EntityNotFoundException
193
-     *
194
-     * @return Mappable|self
195
-     */
196
-    public function firstOrFail($columns = ['*'])
197
-    {
198
-        if (!is_null($entity = $this->first($columns))) {
199
-            return $entity;
200
-        }
201
-
202
-        throw new EntityNotFoundException;
203
-    }
204
-
205
-    /**
206
-     * Execute the query as a "select" statement.
207
-     *
208
-     * @param  array $columns
209
-     * @return \Analogue\ORM\EntityCollection
210
-     */
211
-    public function get($columns = ['*'])
212
-    {
213
-        // First we'll add the proper select columns onto the query so it is run with
214
-        // the proper columns. Then, we will get the results and hydrate out pivot
215
-        // models with the result of those columns as a separate model relation.
216
-        $columns = $this->query->getQuery()->columns ? [] : $columns;
217
-
218
-        $select = $this->getSelectColumns($columns);
219
-
220
-        $entities = $this->query->addSelect($select)->getEntities();
221
-
222
-        $this->hydratePivotRelation($entities);
223
-
224
-        // If we actually found models we will also eager load any relationships that
225
-        // have been specified as needing to be eager loaded. This will solve the
226
-        // n + 1 query problem for the developer and also increase performance.
227
-        if (count($entities) > 0) {
228
-            $entities = $this->query->eagerLoadRelations($entities);
229
-        }
230
-
231
-        return $this->relatedMap->newCollection($entities);
232
-    }
233
-
234
-    /**
235
-     * Hydrate the pivot table relationship on the models.
236
-     *
237
-     * @param  array $entities
238
-     * @return void
239
-     */
240
-    protected function hydratePivotRelation(array $entities)
241
-    {
242
-        // To hydrate the pivot relationship, we will just gather the pivot attributes
243
-        // and create a new Pivot model, which is basically a dynamic model that we
244
-        // will set the attributes, table, and connections on so it they be used.
245
-
246
-        foreach ($entities as $entity) {
247
-            $entityWrapper = $this->factory->make($entity);
248
-
249
-            $pivot = $this->newExistingPivot($this->cleanPivotAttributes($entityWrapper));
250
-
251
-            $entityWrapper->setEntityAttribute('pivot', $pivot);
252
-        }
253
-    }
254
-
255
-    /**
256
-     * Get the pivot attributes from a model.
257
-     *
258
-     * @param  $entity
259
-     * @return array
260
-     */
261
-    protected function cleanPivotAttributes(InternallyMappable $entity)
262
-    {
263
-        $values = [];
264
-
265
-        $attributes = $entity->getEntityAttributes();
266
-
267
-        foreach ($attributes as $key => $value) {
268
-            // To get the pivots attributes we will just take any of the attributes which
269
-            // begin with "pivot_" and add those to this arrays, as well as unsetting
270
-            // them from the parent's models since they exist in a different table.
271
-            if (strpos($key, 'pivot_') === 0) {
272
-                $values[substr($key, 6)] = $value;
273
-
274
-                unset($attributes[$key]);
275
-            }
276
-        }
277
-
278
-        // Rehydrate Entity with cleaned array.
279
-        $entity->setEntityAttributes($attributes);
280
-
281
-        return $values;
282
-    }
283
-
284
-    /**
285
-     * Set the base constraints on the relation query.
286
-     *
287
-     * @return void
288
-     */
289
-    public function addConstraints()
290
-    {
291
-        $this->setJoin();
292
-
293
-        if (static::$constraints) {
294
-            $this->setWhere();
295
-        }
296
-    }
297
-
298
-    /**
299
-     * Add the constraints for a relationship count query.
300
-     *
301
-     * @param  Query $query
302
-     * @param  Query $parent
303
-     * @return Query
304
-     */
305
-    public function getRelationCountQuery(Query $query, Query $parent)
306
-    {
307
-        if ($parent->getQuery()->from == $query->getQuery()->from) {
308
-            return $this->getRelationCountQueryForSelfJoin($query, $parent);
309
-        }
310
-
311
-        $this->setJoin($query);
312
-
313
-        return parent::getRelationCountQuery($query, $parent);
314
-    }
315
-
316
-    /**
317
-     * Add the constraints for a relationship count query on the same table.
318
-     *
319
-     * @param  Query $query
320
-     * @param  Query $parent
321
-     * @return Query
322
-     */
323
-    public function getRelationCountQueryForSelfJoin(Query $query, Query $parent)
324
-    {
325
-        $query->select(new Expression('count(*)'));
326
-
327
-        $tablePrefix = $this->query->getQuery()->getConnection()->getTablePrefix();
328
-
329
-        $query->from($this->table . ' as ' . $tablePrefix . $hash = $this->getRelationCountHash());
330
-
331
-        $key = $this->wrap($this->getQualifiedParentKeyName());
332
-
333
-        return $query->where($hash . '.' . $this->foreignKey, '=', new Expression($key));
334
-    }
335
-
336
-    /**
337
-     * Get a relationship join table hash.
338
-     *
339
-     * @return string
340
-     */
341
-    public function getRelationCountHash()
342
-    {
343
-        return 'self_' . md5(microtime(true));
344
-    }
345
-
346
-    /**
347
-     * Set the select clause for the relation query.
348
-     *
349
-     * @param  array $columns
350
-     * @return \Analogue\ORM\Relationships\BelongsToMany
351
-     */
352
-    protected function getSelectColumns(array $columns = ['*'])
353
-    {
354
-        if ($columns == ['*']) {
355
-            $columns = [$this->relatedMap->getTable() . '.*'];
356
-        }
357
-
358
-        return array_merge($columns, $this->getAliasedPivotColumns());
359
-    }
360
-
361
-    /**
362
-     * Get the pivot columns for the relation.
363
-     *
364
-     * @return array
365
-     */
366
-    protected function getAliasedPivotColumns()
367
-    {
368
-        $defaults = [$this->foreignKey, $this->otherKey];
369
-
370
-        // We need to alias all of the pivot columns with the "pivot_" prefix so we
371
-        // can easily extract them out of the models and put them into the pivot
372
-        // relationships when they are retrieved and hydrated into the models.
373
-        $columns = [];
374
-
375
-        foreach (array_merge($defaults, $this->pivotColumns) as $column) {
376
-            $columns[] = $this->table . '.' . $column . ' as pivot_' . $column;
377
-        }
378
-
379
-        return array_unique($columns);
380
-    }
381
-
382
-    /**
383
-     * Set the join clause for the relation query.
384
-     *
385
-     * @param  \Analogue\ORM\Query|null
386
-     * @return $this
387
-     */
388
-    protected function setJoin($query = null)
389
-    {
390
-        $query = $query ?: $this->query;
391
-
392
-        // We need to join to the intermediate table on the related model's primary
393
-        // key column with the intermediate table's foreign key for the related
394
-        // model instance. Then we can set the "where" for the parent models.
395
-        $baseTable = $this->relatedMap->getTable();
396
-
397
-        $key = $baseTable . '.' . $this->relatedMap->getKeyName();
398
-
399
-        $query->join($this->table, $key, '=', $this->getOtherKey());
400
-
401
-        return $this;
402
-    }
403
-
404
-    /**
405
-     * Set the where clause for the relation query.
406
-     *
407
-     * @return $this
408
-     */
409
-    protected function setWhere()
410
-    {
411
-        $foreign = $this->getForeignKey();
412
-
413
-        $parentKey = $this->parentMap->getKeyName();
414
-
415
-        $this->query->where($foreign, '=', $this->parent->getEntityAttribute($parentKey));
416
-
417
-        return $this;
418
-    }
419
-
420
-    /**
421
-     * Set the constraints for an eager load of the relation.
422
-     *
423
-     * @param  array $entities
424
-     * @return void
425
-     */
426
-    public function addEagerConstraints(array $entities)
427
-    {
428
-        $this->query->whereIn($this->getForeignKey(), $this->getKeys($entities));
429
-    }
430
-
431
-    /**
432
-     * Initialize the relation on a set of eneities.
433
-     *
434
-     * @param  array  $entities
435
-     * @param  string $relation
436
-     * @return array
437
-     */
438
-    public function initRelation(array $entities, $relation)
439
-    {
440
-        foreach ($entities as $entity) {
441
-            $entity = $this->factory->make($entity);
442
-
443
-            $entity->setEntityAttribute($relation, $this->relatedMap->newCollection());
444
-        }
445
-
446
-        return $entities;
447
-    }
448
-
449
-    /**
450
-     * Match the eagerly loaded results to their parents.
451
-     *
452
-     * @param  array            $entities
453
-     * @param  EntityCollection $results
454
-     * @param  string           $relation
455
-     * @return array
456
-     */
457
-    public function match(array $entities, EntityCollection $results, $relation)
458
-    {
459
-        $dictionary = $this->buildDictionary($results);
460
-
461
-        $keyName = $this->relatedMap->getKeyName();
462
-
463
-        $cache = $this->parentMapper->getEntityCache();
464
-
465
-        // Once we have an array dictionary of child objects we can easily match the
466
-        // children back to their parent using the dictionary and the keys on the
467
-        // the parent models. Then we will return the hydrated models back out.
468
-        foreach ($entities as $entity) {
469
-            $wrapper = $this->factory->make($entity);
470
-
471
-            if (isset($dictionary[$key = $wrapper->getEntityAttribute($keyName)])) {
472
-                $collection = $this->relatedMap->newCollection($dictionary[$key]);
473
-
474
-                $wrapper->setEntityAttribute($relation, $collection);
475
-
476
-                $cache->cacheLoadedRelationResult($entity, $relation, $collection, $this);
477
-            }
478
-        }
479
-
480
-        return $entities;
481
-    }
482
-
483
-    /**
484
-     * Build model dictionary keyed by the relation's foreign key.
485
-     *
486
-     * @param  EntityCollection $results
487
-     * @return array
488
-     */
489
-    protected function buildDictionary(EntityCollection $results)
490
-    {
491
-        $foreign = $this->foreignKey;
492
-
493
-        $foreign = $this->relatedMap->mapColumnToAttribute($foreign);
494
-
495
-        // First we will build a dictionary of child models keyed by the foreign key
496
-        // of the relation so that we will easily and quickly match them to their
497
-        // parents without having a possibly slow inner loops for every models.
498
-        $dictionary = [];
499
-
500
-        foreach ($results as $entity) {
501
-            $wrapper = $this->factory->make($entity);
502
-
503
-            $dictionary[$wrapper->getEntityAttribute('pivot')->$foreign][] = $entity;
504
-        }
505
-
506
-        return $dictionary;
507
-    }
508
-
509
-    /**
510
-     * Get all of the IDs for the related models.
511
-     *
512
-     * @return array
513
-     */
514
-    public function getRelatedIds()
515
-    {
516
-        $fullKey = $this->relatedMap->getQualifiedKeyName();
517
-
518
-        return $this->getQuery()->select($fullKey)->lists($this->relatedMap->getKeyName());
519
-    }
520
-
521
-    /**
522
-     * Update Pivot
523
-     *
524
-     * @param  \Analogue\ORM\Entity $entity
525
-     * @return void
526
-     */
527
-    public function updatePivot($entity)
528
-    {
529
-        $keyName = $this->relatedMap->getKeyName();
530
-
531
-        $this->updateExistingPivot(
532
-            $entity->getEntityAttribute($keyName),
533
-            $entity->getEntityAttribute('pivot')->getEntityAttributes()
534
-        );
535
-    }
536
-
537
-    /**
538
-     * Update Multiple pivot
539
-     *
540
-     * @param  $relatedEntities
541
-     * @return void
542
-     */
543
-    public function updatePivots($relatedEntities)
544
-    {
545
-        foreach ($relatedEntities as $entity) {
546
-            $this->updatePivot($entity);
547
-        }
548
-    }
549
-
550
-    /**
551
-     * Create Pivot Records
552
-     *
553
-     * @param \Analogue\ORM\Entity[] $relatedEntities
554
-     * @return void
555
-     */
556
-    public function createPivots($relatedEntities)
557
-    {
558
-        $keys = [];
559
-        $attributes = [];
560
-
561
-        $keyName = $this->relatedMap->getKeyName();
562
-
563
-        foreach ($relatedEntities as $entity) {
564
-            $keys[] = $entity->getEntityAttribute($keyName);
565
-        }
566
-
567
-        $records = $this->createAttachRecords($keys, $attributes);
568
-
569
-        $this->query->getQuery()->from($this->table)->insert($records);
570
-    }
571
-
572
-    /**
573
-     * Update an existing pivot record on the table.
574
-     *
575
-     * @param  mixed $id
576
-     * @param  array $attributes
577
-     * @throws \InvalidArgumentException
578
-     * @return integer
579
-     */
580
-    public function updateExistingPivot($id, array $attributes)
581
-    {
582
-        if (in_array($this->updatedAt(), $this->pivotColumns)) {
583
-            $attributes = $this->setTimestampsOnAttach($attributes, true);
584
-        }
585
-
586
-        return $this->newPivotStatementForId($id)->update($attributes);
587
-    }
588
-
589
-    /**
590
-     * Attach a model to the parent.
591
-     *
592
-     * @param  mixed $id
593
-     * @param  array $attributes
594
-     * @return void
595
-     */
596
-    public function attach($id, array $attributes = [])
597
-    {
598
-        $query = $this->newPivotStatement();
599
-
600
-        $query->insert($this->createAttachRecords((array) $id, $attributes));
601
-    }
602
-
603
-    /**
604
-     * @param  array $entities
605
-     *
606
-     * @throws \InvalidArgumentException
607
-     */
608
-    public function sync(array $entities)
609
-    {
610
-        $this->detachExcept($entities);
611
-    }
612
-
613
-    /**
614
-     * Detach related entities that are not in $id
615
-     *
616
-     * @param  array $entities
617
-     *
618
-     * @throws \InvalidArgumentException
619
-     *
620
-     * @return void
621
-     */
622
-    protected function detachExcept(array $entities = [])
623
-    {
624
-        $query = $this->newPivotQuery();
625
-
626
-        if (count($entities) > 0) {
627
-            $keys = $this->getKeys($entities);
628
-
629
-            $query->whereNotIn($this->otherKey, $keys);
630
-        }
631
-        $parentKey = $this->parentMap->getKeyName();
632
-
633
-        $query->where($this->foreignKey, '=', $this->parent->getEntityAttribute($parentKey));
15
+	/**
16
+	 * The intermediate table for the relation.
17
+	 *
18
+	 * @var string
19
+	 */
20
+	protected $table;
21
+
22
+	/**
23
+	 * The foreign key of the parent model.
24
+	 *
25
+	 * @var string
26
+	 */
27
+	protected $foreignKey;
28
+
29
+	/**
30
+	 * The associated key of the relation.
31
+	 *
32
+	 * @var string
33
+	 */
34
+	protected $otherKey;
35
+
36
+	/**
37
+	 * The "name" of the relationship.
38
+	 *
39
+	 * @var string
40
+	 */
41
+	protected $relationName;
42
+
43
+	/**
44
+	 * The pivot table columns to retrieve.
45
+	 *
46
+	 * @var array
47
+	 */
48
+	protected $pivotColumns = [];
49
+
50
+	/**
51
+	 * This relationship has pivot attributes
52
+	 *
53
+	 * @var boolean
54
+	 */
55
+	protected static $hasPivot = true;
56
+
57
+	/**
58
+	 * Create a new has many relationship instance.
59
+	 *
60
+	 * @param Mapper   $mapper
61
+	 * @param Mappable $parent
62
+	 * @param string   $table
63
+	 * @param string   $foreignKey
64
+	 * @param string   $otherKey
65
+	 * @param string   $relationName
66
+	 */
67
+	public function __construct(Mapper $mapper, $parent, $table, $foreignKey, $otherKey, $relationName = null)
68
+	{
69
+		$this->table = $table;
70
+		$this->otherKey = $otherKey;
71
+		$this->foreignKey = $foreignKey;
72
+		$this->relationName = $relationName;
73
+
74
+		parent::__construct($mapper, $parent);
75
+	}
76
+
77
+	/**
78
+	 * @param  $related
79
+	 * @return mixed
80
+	 */
81
+	public function attachTo($related)
82
+	{
83
+	}
84
+
85
+	/**
86
+	 * @param  $related
87
+	 * @return mixed
88
+	 */
89
+	public function detachFrom($related)
90
+	{
91
+		$ids = $this->getIdsFromHashes([$related]);
92
+
93
+		$this->detach($ids);
94
+	}
95
+
96
+	/**
97
+	 * @param $related
98
+	 */
99
+	public function detachMany($related)
100
+	{
101
+		$ids = $this->getIdsFromHashes($related);
102
+
103
+		$this->detach($ids);
104
+	}
105
+
106
+	/**
107
+	 * @param array $hashes
108
+	 * @return array
109
+	 */
110
+	protected function getIdsFromHashes(array $hashes)
111
+	{
112
+		$ids = [];
113
+
114
+		foreach ($hashes as $hash) {
115
+			$split = explode('.', $hash);
116
+			$ids[] = $split[1];
117
+		}
118
+		return $ids;
119
+	}
120
+
121
+	/**
122
+	 * Get the results of the relationship.
123
+	 *
124
+	 * @param $relation
125
+	 *
126
+	 * @return EntityCollection
127
+	 */
128
+	public function getResults($relation)
129
+	{
130
+		$results = $this->get();
131
+
132
+		$this->cacheRelation($results, $relation);
133
+
134
+		return $results;
135
+	}
136
+
137
+	/**
138
+	 * Set a where clause for a pivot table column.
139
+	 *
140
+	 * @param  string $column
141
+	 * @param  string $operator
142
+	 * @param  mixed  $value
143
+	 * @param  string $boolean
144
+	 * @return self
145
+	 */
146
+	public function wherePivot($column, $operator = null, $value = null, $boolean = 'and')
147
+	{
148
+		return $this->where($this->table . '.' . $column, $operator, $value, $boolean);
149
+	}
150
+
151
+	/**
152
+	 * Set an or where clause for a pivot table column.
153
+	 *
154
+	 * @param  string $column
155
+	 * @param  string $operator
156
+	 * @param  mixed  $value
157
+	 * @return self
158
+	 */
159
+	public function orWherePivot($column, $operator = null, $value = null)
160
+	{
161
+		return $this->wherePivot($column, $operator, $value, 'or');
162
+	}
163
+
164
+	/**
165
+	 * Return Pivot attributes when available on a relationship
166
+	 *
167
+	 * @return array
168
+	 */
169
+	public function getPivotAttributes()
170
+	{
171
+		return $this->pivotColumns;
172
+	}
173
+
174
+	/**
175
+	 * Execute the query and get the first result.
176
+	 *
177
+	 * @param  array $columns
178
+	 * @return mixed
179
+	 */
180
+	public function first($columns = ['*'])
181
+	{
182
+		$results = $this->take(1)->get($columns);
183
+
184
+		return count($results) > 0 ? $results->first() : null;
185
+	}
186
+
187
+	/**
188
+	 * Execute the query and get the first result or throw an exception.
189
+	 *
190
+	 * @param  array $columns
191
+	 *
192
+	 * @throws EntityNotFoundException
193
+	 *
194
+	 * @return Mappable|self
195
+	 */
196
+	public function firstOrFail($columns = ['*'])
197
+	{
198
+		if (!is_null($entity = $this->first($columns))) {
199
+			return $entity;
200
+		}
201
+
202
+		throw new EntityNotFoundException;
203
+	}
204
+
205
+	/**
206
+	 * Execute the query as a "select" statement.
207
+	 *
208
+	 * @param  array $columns
209
+	 * @return \Analogue\ORM\EntityCollection
210
+	 */
211
+	public function get($columns = ['*'])
212
+	{
213
+		// First we'll add the proper select columns onto the query so it is run with
214
+		// the proper columns. Then, we will get the results and hydrate out pivot
215
+		// models with the result of those columns as a separate model relation.
216
+		$columns = $this->query->getQuery()->columns ? [] : $columns;
217
+
218
+		$select = $this->getSelectColumns($columns);
219
+
220
+		$entities = $this->query->addSelect($select)->getEntities();
221
+
222
+		$this->hydratePivotRelation($entities);
223
+
224
+		// If we actually found models we will also eager load any relationships that
225
+		// have been specified as needing to be eager loaded. This will solve the
226
+		// n + 1 query problem for the developer and also increase performance.
227
+		if (count($entities) > 0) {
228
+			$entities = $this->query->eagerLoadRelations($entities);
229
+		}
230
+
231
+		return $this->relatedMap->newCollection($entities);
232
+	}
233
+
234
+	/**
235
+	 * Hydrate the pivot table relationship on the models.
236
+	 *
237
+	 * @param  array $entities
238
+	 * @return void
239
+	 */
240
+	protected function hydratePivotRelation(array $entities)
241
+	{
242
+		// To hydrate the pivot relationship, we will just gather the pivot attributes
243
+		// and create a new Pivot model, which is basically a dynamic model that we
244
+		// will set the attributes, table, and connections on so it they be used.
245
+
246
+		foreach ($entities as $entity) {
247
+			$entityWrapper = $this->factory->make($entity);
248
+
249
+			$pivot = $this->newExistingPivot($this->cleanPivotAttributes($entityWrapper));
250
+
251
+			$entityWrapper->setEntityAttribute('pivot', $pivot);
252
+		}
253
+	}
254
+
255
+	/**
256
+	 * Get the pivot attributes from a model.
257
+	 *
258
+	 * @param  $entity
259
+	 * @return array
260
+	 */
261
+	protected function cleanPivotAttributes(InternallyMappable $entity)
262
+	{
263
+		$values = [];
264
+
265
+		$attributes = $entity->getEntityAttributes();
266
+
267
+		foreach ($attributes as $key => $value) {
268
+			// To get the pivots attributes we will just take any of the attributes which
269
+			// begin with "pivot_" and add those to this arrays, as well as unsetting
270
+			// them from the parent's models since they exist in a different table.
271
+			if (strpos($key, 'pivot_') === 0) {
272
+				$values[substr($key, 6)] = $value;
273
+
274
+				unset($attributes[$key]);
275
+			}
276
+		}
277
+
278
+		// Rehydrate Entity with cleaned array.
279
+		$entity->setEntityAttributes($attributes);
280
+
281
+		return $values;
282
+	}
283
+
284
+	/**
285
+	 * Set the base constraints on the relation query.
286
+	 *
287
+	 * @return void
288
+	 */
289
+	public function addConstraints()
290
+	{
291
+		$this->setJoin();
292
+
293
+		if (static::$constraints) {
294
+			$this->setWhere();
295
+		}
296
+	}
297
+
298
+	/**
299
+	 * Add the constraints for a relationship count query.
300
+	 *
301
+	 * @param  Query $query
302
+	 * @param  Query $parent
303
+	 * @return Query
304
+	 */
305
+	public function getRelationCountQuery(Query $query, Query $parent)
306
+	{
307
+		if ($parent->getQuery()->from == $query->getQuery()->from) {
308
+			return $this->getRelationCountQueryForSelfJoin($query, $parent);
309
+		}
310
+
311
+		$this->setJoin($query);
312
+
313
+		return parent::getRelationCountQuery($query, $parent);
314
+	}
315
+
316
+	/**
317
+	 * Add the constraints for a relationship count query on the same table.
318
+	 *
319
+	 * @param  Query $query
320
+	 * @param  Query $parent
321
+	 * @return Query
322
+	 */
323
+	public function getRelationCountQueryForSelfJoin(Query $query, Query $parent)
324
+	{
325
+		$query->select(new Expression('count(*)'));
326
+
327
+		$tablePrefix = $this->query->getQuery()->getConnection()->getTablePrefix();
328
+
329
+		$query->from($this->table . ' as ' . $tablePrefix . $hash = $this->getRelationCountHash());
330
+
331
+		$key = $this->wrap($this->getQualifiedParentKeyName());
332
+
333
+		return $query->where($hash . '.' . $this->foreignKey, '=', new Expression($key));
334
+	}
335
+
336
+	/**
337
+	 * Get a relationship join table hash.
338
+	 *
339
+	 * @return string
340
+	 */
341
+	public function getRelationCountHash()
342
+	{
343
+		return 'self_' . md5(microtime(true));
344
+	}
345
+
346
+	/**
347
+	 * Set the select clause for the relation query.
348
+	 *
349
+	 * @param  array $columns
350
+	 * @return \Analogue\ORM\Relationships\BelongsToMany
351
+	 */
352
+	protected function getSelectColumns(array $columns = ['*'])
353
+	{
354
+		if ($columns == ['*']) {
355
+			$columns = [$this->relatedMap->getTable() . '.*'];
356
+		}
357
+
358
+		return array_merge($columns, $this->getAliasedPivotColumns());
359
+	}
360
+
361
+	/**
362
+	 * Get the pivot columns for the relation.
363
+	 *
364
+	 * @return array
365
+	 */
366
+	protected function getAliasedPivotColumns()
367
+	{
368
+		$defaults = [$this->foreignKey, $this->otherKey];
369
+
370
+		// We need to alias all of the pivot columns with the "pivot_" prefix so we
371
+		// can easily extract them out of the models and put them into the pivot
372
+		// relationships when they are retrieved and hydrated into the models.
373
+		$columns = [];
374
+
375
+		foreach (array_merge($defaults, $this->pivotColumns) as $column) {
376
+			$columns[] = $this->table . '.' . $column . ' as pivot_' . $column;
377
+		}
378
+
379
+		return array_unique($columns);
380
+	}
381
+
382
+	/**
383
+	 * Set the join clause for the relation query.
384
+	 *
385
+	 * @param  \Analogue\ORM\Query|null
386
+	 * @return $this
387
+	 */
388
+	protected function setJoin($query = null)
389
+	{
390
+		$query = $query ?: $this->query;
391
+
392
+		// We need to join to the intermediate table on the related model's primary
393
+		// key column with the intermediate table's foreign key for the related
394
+		// model instance. Then we can set the "where" for the parent models.
395
+		$baseTable = $this->relatedMap->getTable();
396
+
397
+		$key = $baseTable . '.' . $this->relatedMap->getKeyName();
398
+
399
+		$query->join($this->table, $key, '=', $this->getOtherKey());
400
+
401
+		return $this;
402
+	}
403
+
404
+	/**
405
+	 * Set the where clause for the relation query.
406
+	 *
407
+	 * @return $this
408
+	 */
409
+	protected function setWhere()
410
+	{
411
+		$foreign = $this->getForeignKey();
412
+
413
+		$parentKey = $this->parentMap->getKeyName();
414
+
415
+		$this->query->where($foreign, '=', $this->parent->getEntityAttribute($parentKey));
416
+
417
+		return $this;
418
+	}
419
+
420
+	/**
421
+	 * Set the constraints for an eager load of the relation.
422
+	 *
423
+	 * @param  array $entities
424
+	 * @return void
425
+	 */
426
+	public function addEagerConstraints(array $entities)
427
+	{
428
+		$this->query->whereIn($this->getForeignKey(), $this->getKeys($entities));
429
+	}
430
+
431
+	/**
432
+	 * Initialize the relation on a set of eneities.
433
+	 *
434
+	 * @param  array  $entities
435
+	 * @param  string $relation
436
+	 * @return array
437
+	 */
438
+	public function initRelation(array $entities, $relation)
439
+	{
440
+		foreach ($entities as $entity) {
441
+			$entity = $this->factory->make($entity);
442
+
443
+			$entity->setEntityAttribute($relation, $this->relatedMap->newCollection());
444
+		}
445
+
446
+		return $entities;
447
+	}
448
+
449
+	/**
450
+	 * Match the eagerly loaded results to their parents.
451
+	 *
452
+	 * @param  array            $entities
453
+	 * @param  EntityCollection $results
454
+	 * @param  string           $relation
455
+	 * @return array
456
+	 */
457
+	public function match(array $entities, EntityCollection $results, $relation)
458
+	{
459
+		$dictionary = $this->buildDictionary($results);
460
+
461
+		$keyName = $this->relatedMap->getKeyName();
462
+
463
+		$cache = $this->parentMapper->getEntityCache();
464
+
465
+		// Once we have an array dictionary of child objects we can easily match the
466
+		// children back to their parent using the dictionary and the keys on the
467
+		// the parent models. Then we will return the hydrated models back out.
468
+		foreach ($entities as $entity) {
469
+			$wrapper = $this->factory->make($entity);
470
+
471
+			if (isset($dictionary[$key = $wrapper->getEntityAttribute($keyName)])) {
472
+				$collection = $this->relatedMap->newCollection($dictionary[$key]);
473
+
474
+				$wrapper->setEntityAttribute($relation, $collection);
475
+
476
+				$cache->cacheLoadedRelationResult($entity, $relation, $collection, $this);
477
+			}
478
+		}
479
+
480
+		return $entities;
481
+	}
482
+
483
+	/**
484
+	 * Build model dictionary keyed by the relation's foreign key.
485
+	 *
486
+	 * @param  EntityCollection $results
487
+	 * @return array
488
+	 */
489
+	protected function buildDictionary(EntityCollection $results)
490
+	{
491
+		$foreign = $this->foreignKey;
492
+
493
+		$foreign = $this->relatedMap->mapColumnToAttribute($foreign);
494
+
495
+		// First we will build a dictionary of child models keyed by the foreign key
496
+		// of the relation so that we will easily and quickly match them to their
497
+		// parents without having a possibly slow inner loops for every models.
498
+		$dictionary = [];
499
+
500
+		foreach ($results as $entity) {
501
+			$wrapper = $this->factory->make($entity);
502
+
503
+			$dictionary[$wrapper->getEntityAttribute('pivot')->$foreign][] = $entity;
504
+		}
505
+
506
+		return $dictionary;
507
+	}
508
+
509
+	/**
510
+	 * Get all of the IDs for the related models.
511
+	 *
512
+	 * @return array
513
+	 */
514
+	public function getRelatedIds()
515
+	{
516
+		$fullKey = $this->relatedMap->getQualifiedKeyName();
517
+
518
+		return $this->getQuery()->select($fullKey)->lists($this->relatedMap->getKeyName());
519
+	}
520
+
521
+	/**
522
+	 * Update Pivot
523
+	 *
524
+	 * @param  \Analogue\ORM\Entity $entity
525
+	 * @return void
526
+	 */
527
+	public function updatePivot($entity)
528
+	{
529
+		$keyName = $this->relatedMap->getKeyName();
530
+
531
+		$this->updateExistingPivot(
532
+			$entity->getEntityAttribute($keyName),
533
+			$entity->getEntityAttribute('pivot')->getEntityAttributes()
534
+		);
535
+	}
536
+
537
+	/**
538
+	 * Update Multiple pivot
539
+	 *
540
+	 * @param  $relatedEntities
541
+	 * @return void
542
+	 */
543
+	public function updatePivots($relatedEntities)
544
+	{
545
+		foreach ($relatedEntities as $entity) {
546
+			$this->updatePivot($entity);
547
+		}
548
+	}
549
+
550
+	/**
551
+	 * Create Pivot Records
552
+	 *
553
+	 * @param \Analogue\ORM\Entity[] $relatedEntities
554
+	 * @return void
555
+	 */
556
+	public function createPivots($relatedEntities)
557
+	{
558
+		$keys = [];
559
+		$attributes = [];
560
+
561
+		$keyName = $this->relatedMap->getKeyName();
562
+
563
+		foreach ($relatedEntities as $entity) {
564
+			$keys[] = $entity->getEntityAttribute($keyName);
565
+		}
566
+
567
+		$records = $this->createAttachRecords($keys, $attributes);
568
+
569
+		$this->query->getQuery()->from($this->table)->insert($records);
570
+	}
571
+
572
+	/**
573
+	 * Update an existing pivot record on the table.
574
+	 *
575
+	 * @param  mixed $id
576
+	 * @param  array $attributes
577
+	 * @throws \InvalidArgumentException
578
+	 * @return integer
579
+	 */
580
+	public function updateExistingPivot($id, array $attributes)
581
+	{
582
+		if (in_array($this->updatedAt(), $this->pivotColumns)) {
583
+			$attributes = $this->setTimestampsOnAttach($attributes, true);
584
+		}
585
+
586
+		return $this->newPivotStatementForId($id)->update($attributes);
587
+	}
588
+
589
+	/**
590
+	 * Attach a model to the parent.
591
+	 *
592
+	 * @param  mixed $id
593
+	 * @param  array $attributes
594
+	 * @return void
595
+	 */
596
+	public function attach($id, array $attributes = [])
597
+	{
598
+		$query = $this->newPivotStatement();
599
+
600
+		$query->insert($this->createAttachRecords((array) $id, $attributes));
601
+	}
602
+
603
+	/**
604
+	 * @param  array $entities
605
+	 *
606
+	 * @throws \InvalidArgumentException
607
+	 */
608
+	public function sync(array $entities)
609
+	{
610
+		$this->detachExcept($entities);
611
+	}
612
+
613
+	/**
614
+	 * Detach related entities that are not in $id
615
+	 *
616
+	 * @param  array $entities
617
+	 *
618
+	 * @throws \InvalidArgumentException
619
+	 *
620
+	 * @return void
621
+	 */
622
+	protected function detachExcept(array $entities = [])
623
+	{
624
+		$query = $this->newPivotQuery();
625
+
626
+		if (count($entities) > 0) {
627
+			$keys = $this->getKeys($entities);
628
+
629
+			$query->whereNotIn($this->otherKey, $keys);
630
+		}
631
+		$parentKey = $this->parentMap->getKeyName();
632
+
633
+		$query->where($this->foreignKey, '=', $this->parent->getEntityAttribute($parentKey));
634 634
         
635
-        $query->delete();
636
-
637
-        $query = $this->newPivotQuery();
638
-    }
639
-
640
-
641
-    /**
642
-     * Create an array of records to insert into the pivot table.
643
-     *
644
-     * @param  array $ids
645
-     * @param  array $attributes
646
-     * @return array
647
-     */
648
-    protected function createAttachRecords($ids, array $attributes)
649
-    {
650
-        $records = [];
651
-
652
-        $timed = in_array($this->createdAt(), $this->pivotColumns);
653
-
654
-        // To create the attachment records, we will simply spin through the IDs given
655
-        // and create a new record to insert for each ID. Each ID may actually be a
656
-        // key in the array, with extra attributes to be placed in other columns.
657
-        foreach ($ids as $key => $value) {
658
-            $records[] = $this->attacher($key, $value, $attributes, $timed);
659
-        }
635
+		$query->delete();
636
+
637
+		$query = $this->newPivotQuery();
638
+	}
639
+
640
+
641
+	/**
642
+	 * Create an array of records to insert into the pivot table.
643
+	 *
644
+	 * @param  array $ids
645
+	 * @param  array $attributes
646
+	 * @return array
647
+	 */
648
+	protected function createAttachRecords($ids, array $attributes)
649
+	{
650
+		$records = [];
651
+
652
+		$timed = in_array($this->createdAt(), $this->pivotColumns);
653
+
654
+		// To create the attachment records, we will simply spin through the IDs given
655
+		// and create a new record to insert for each ID. Each ID may actually be a
656
+		// key in the array, with extra attributes to be placed in other columns.
657
+		foreach ($ids as $key => $value) {
658
+			$records[] = $this->attacher($key, $value, $attributes, $timed);
659
+		}
660 660
         
661
-        return $records;
662
-    }
663
-
664
-    /**
665
-     * Create a full attachment record payload.
666
-     *
667
-     * @param  int   $key
668
-     * @param  mixed $value
669
-     * @param  array $attributes
670
-     * @param  bool  $timed
671
-     * @return array
672
-     */
673
-    protected function attacher($key, $value, $attributes, $timed)
674
-    {
675
-        list($id, $extra) = $this->getAttachId($key, $value, $attributes);
661
+		return $records;
662
+	}
663
+
664
+	/**
665
+	 * Create a full attachment record payload.
666
+	 *
667
+	 * @param  int   $key
668
+	 * @param  mixed $value
669
+	 * @param  array $attributes
670
+	 * @param  bool  $timed
671
+	 * @return array
672
+	 */
673
+	protected function attacher($key, $value, $attributes, $timed)
674
+	{
675
+		list($id, $extra) = $this->getAttachId($key, $value, $attributes);
676 676
         
677
-        // To create the attachment records, we will simply spin through the IDs given
678
-        // and create a new record to insert for each ID. Each ID may actually be a
679
-        // key in the array, with extra attributes to be placed in other columns.
680
-        $record = $this->createAttachRecord($id, $timed);
681
-
682
-        return array_merge($record, $extra);
683
-    }
684
-
685
-    /**
686
-     * Get the attach record ID and extra attributes.
687
-     *
688
-     * @param  int   $key
689
-     * @param  mixed $value
690
-     * @param  array $attributes
691
-     * @return array
692
-     */
693
-    protected function getAttachId($key, $value, array $attributes)
694
-    {
695
-        if (is_array($value)) {
696
-            return [$key, array_merge($value, $attributes)];
697
-        }
698
-
699
-        return [$value, $attributes];
700
-    }
701
-
702
-    /**
703
-     * Create a new pivot attachment record.
704
-     *
705
-     * @param  int  $id
706
-     * @param  bool $timed
707
-     * @return array
708
-     */
709
-    protected function createAttachRecord($id, $timed)
710
-    {
711
-        $parentKey = $this->parentMap->getKeyName();
712
-
713
-        $record = [];
714
-
715
-        $record[$this->foreignKey] = $this->parent->getEntityAttribute($parentKey);
716
-
717
-        $record[$this->otherKey] = $id;
718
-
719
-        // If the record needs to have creation and update timestamps, we will make
720
-        // them by calling the parent model's "freshTimestamp" method which will
721
-        // provide us with a fresh timestamp in this model's preferred format.
722
-        if ($timed) {
723
-            $record = $this->setTimestampsOnAttach($record);
724
-        }
725
-
726
-        return $record;
727
-    }
728
-
729
-    /**
730
-     * Set the creation and update timestamps on an attach record.
731
-     *
732
-     * @param  array $record
733
-     * @param  bool  $exists
734
-     * @return array
735
-     */
736
-    protected function setTimestampsOnAttach(array $record, $exists = false)
737
-    {
738
-        $fresh = $this->freshTimestamp();
739
-
740
-        if (!$exists) {
741
-            $record[$this->createdAt()] = $fresh;
742
-        }
743
-
744
-        $record[$this->updatedAt()] = $fresh;
745
-
746
-        return $record;
747
-    }
748
-
749
-    /**
750
-     * @param EntityCollection $entities
751
-     * @return array
752
-     */
753
-    protected function getModelKeysFromCollection(EntityCollection $entities)
754
-    {
755
-        $keyName = $this->relatedMap->getKeyName();
756
-
757
-        return array_map(function ($m) use ($keyName) {
758
-            return $m->$keyName;
759
-        }, $entities);
760
-    }
761
-
762
-    /**
763
-     * Detach models from the relationship.
764
-     *
765
-     * @param  int|array $ids
766
-     * @throws \InvalidArgumentException
767
-     * @return int
768
-     */
769
-    public function detach($ids = [])
770
-    {
771
-        if ($ids instanceof EntityCollection) {
772
-            $ids = (array) $ids->modelKeys();
773
-        }
774
-
775
-        $query = $this->newPivotQuery();
776
-
777
-        // If associated IDs were passed to the method we will only delete those
778
-        // associations, otherwise all of the association ties will be broken.
779
-        // We'll return the numbers of affected rows when we do the deletes.
780
-        $ids = (array) $ids;
781
-
782
-        if (count($ids) > 0) {
783
-            $query->whereIn($this->otherKey, (array) $ids);
784
-        }
785
-
786
-        // Once we have all of the conditions set on the statement, we are ready
787
-        // to run the delete on the pivot table. Then, if the touch parameter
788
-        // is true, we will go ahead and touch all related models to sync.
789
-        return $query->delete();
790
-    }
677
+		// To create the attachment records, we will simply spin through the IDs given
678
+		// and create a new record to insert for each ID. Each ID may actually be a
679
+		// key in the array, with extra attributes to be placed in other columns.
680
+		$record = $this->createAttachRecord($id, $timed);
681
+
682
+		return array_merge($record, $extra);
683
+	}
684
+
685
+	/**
686
+	 * Get the attach record ID and extra attributes.
687
+	 *
688
+	 * @param  int   $key
689
+	 * @param  mixed $value
690
+	 * @param  array $attributes
691
+	 * @return array
692
+	 */
693
+	protected function getAttachId($key, $value, array $attributes)
694
+	{
695
+		if (is_array($value)) {
696
+			return [$key, array_merge($value, $attributes)];
697
+		}
698
+
699
+		return [$value, $attributes];
700
+	}
701
+
702
+	/**
703
+	 * Create a new pivot attachment record.
704
+	 *
705
+	 * @param  int  $id
706
+	 * @param  bool $timed
707
+	 * @return array
708
+	 */
709
+	protected function createAttachRecord($id, $timed)
710
+	{
711
+		$parentKey = $this->parentMap->getKeyName();
712
+
713
+		$record = [];
714
+
715
+		$record[$this->foreignKey] = $this->parent->getEntityAttribute($parentKey);
716
+
717
+		$record[$this->otherKey] = $id;
718
+
719
+		// If the record needs to have creation and update timestamps, we will make
720
+		// them by calling the parent model's "freshTimestamp" method which will
721
+		// provide us with a fresh timestamp in this model's preferred format.
722
+		if ($timed) {
723
+			$record = $this->setTimestampsOnAttach($record);
724
+		}
725
+
726
+		return $record;
727
+	}
728
+
729
+	/**
730
+	 * Set the creation and update timestamps on an attach record.
731
+	 *
732
+	 * @param  array $record
733
+	 * @param  bool  $exists
734
+	 * @return array
735
+	 */
736
+	protected function setTimestampsOnAttach(array $record, $exists = false)
737
+	{
738
+		$fresh = $this->freshTimestamp();
739
+
740
+		if (!$exists) {
741
+			$record[$this->createdAt()] = $fresh;
742
+		}
743
+
744
+		$record[$this->updatedAt()] = $fresh;
745
+
746
+		return $record;
747
+	}
748
+
749
+	/**
750
+	 * @param EntityCollection $entities
751
+	 * @return array
752
+	 */
753
+	protected function getModelKeysFromCollection(EntityCollection $entities)
754
+	{
755
+		$keyName = $this->relatedMap->getKeyName();
756
+
757
+		return array_map(function ($m) use ($keyName) {
758
+			return $m->$keyName;
759
+		}, $entities);
760
+	}
761
+
762
+	/**
763
+	 * Detach models from the relationship.
764
+	 *
765
+	 * @param  int|array $ids
766
+	 * @throws \InvalidArgumentException
767
+	 * @return int
768
+	 */
769
+	public function detach($ids = [])
770
+	{
771
+		if ($ids instanceof EntityCollection) {
772
+			$ids = (array) $ids->modelKeys();
773
+		}
774
+
775
+		$query = $this->newPivotQuery();
776
+
777
+		// If associated IDs were passed to the method we will only delete those
778
+		// associations, otherwise all of the association ties will be broken.
779
+		// We'll return the numbers of affected rows when we do the deletes.
780
+		$ids = (array) $ids;
781
+
782
+		if (count($ids) > 0) {
783
+			$query->whereIn($this->otherKey, (array) $ids);
784
+		}
785
+
786
+		// Once we have all of the conditions set on the statement, we are ready
787
+		// to run the delete on the pivot table. Then, if the touch parameter
788
+		// is true, we will go ahead and touch all related models to sync.
789
+		return $query->delete();
790
+	}
791 791
     
792
-    /**
793
-     * Create a new query builder for the pivot table.
794
-     *
795
-     * @throws \InvalidArgumentException
796
-     *
797
-     * @return \Illuminate\Database\Query\Builder
798
-     */
799
-    protected function newPivotQuery()
800
-    {
801
-        $query = $this->newPivotStatement();
802
-
803
-        $parentKey = $this->parentMap->getKeyName();
804
-
805
-        return $query->where($this->foreignKey, $this->parent->getEntityAttribute($parentKey));
806
-    }
807
-
808
-    /**
809
-     * Get a new plain query builder for the pivot table.
810
-     *
811
-     * @return \Illuminate\Database\Query\Builder
812
-     */
813
-    public function newPivotStatement()
814
-    {
815
-        return $this->query->getQuery()->newQuery()->from($this->table);
816
-    }
817
-
818
-    /**
819
-     * Get a new pivot statement for a given "other" ID.
820
-     *
821
-     * @param  mixed $id
822
-     *
823
-     * @throws \InvalidArgumentException
824
-     *
825
-     * @return \Illuminate\Database\Query\Builder
826
-     */
827
-    public function newPivotStatementForId($id)
828
-    {
829
-        $pivot = $this->newPivotStatement();
830
-
831
-        $parentKeyName = $this->parentMap->getKeyName();
832
-
833
-        $key = $this->parent->getEntityAttribute($parentKeyName);
834
-
835
-        return $pivot->where($this->foreignKey, $key)->where($this->otherKey, $id);
836
-    }
837
-
838
-    /**
839
-     * Create a new pivot model instance.
840
-     *
841
-     * @param  array $attributes
842
-     * @param  bool  $exists
843
-     * @return \Analogue\ORM\Relationships\Pivot
844
-     */
845
-    public function newPivot(array $attributes = [], $exists = false)
846
-    {
847
-        $pivot = new Pivot($this->parent, $this->parentMap, $attributes, $this->table, $exists);
792
+	/**
793
+	 * Create a new query builder for the pivot table.
794
+	 *
795
+	 * @throws \InvalidArgumentException
796
+	 *
797
+	 * @return \Illuminate\Database\Query\Builder
798
+	 */
799
+	protected function newPivotQuery()
800
+	{
801
+		$query = $this->newPivotStatement();
802
+
803
+		$parentKey = $this->parentMap->getKeyName();
804
+
805
+		return $query->where($this->foreignKey, $this->parent->getEntityAttribute($parentKey));
806
+	}
807
+
808
+	/**
809
+	 * Get a new plain query builder for the pivot table.
810
+	 *
811
+	 * @return \Illuminate\Database\Query\Builder
812
+	 */
813
+	public function newPivotStatement()
814
+	{
815
+		return $this->query->getQuery()->newQuery()->from($this->table);
816
+	}
817
+
818
+	/**
819
+	 * Get a new pivot statement for a given "other" ID.
820
+	 *
821
+	 * @param  mixed $id
822
+	 *
823
+	 * @throws \InvalidArgumentException
824
+	 *
825
+	 * @return \Illuminate\Database\Query\Builder
826
+	 */
827
+	public function newPivotStatementForId($id)
828
+	{
829
+		$pivot = $this->newPivotStatement();
830
+
831
+		$parentKeyName = $this->parentMap->getKeyName();
832
+
833
+		$key = $this->parent->getEntityAttribute($parentKeyName);
834
+
835
+		return $pivot->where($this->foreignKey, $key)->where($this->otherKey, $id);
836
+	}
837
+
838
+	/**
839
+	 * Create a new pivot model instance.
840
+	 *
841
+	 * @param  array $attributes
842
+	 * @param  bool  $exists
843
+	 * @return \Analogue\ORM\Relationships\Pivot
844
+	 */
845
+	public function newPivot(array $attributes = [], $exists = false)
846
+	{
847
+		$pivot = new Pivot($this->parent, $this->parentMap, $attributes, $this->table, $exists);
848 848
         
849
-        return $pivot->setPivotKeys($this->foreignKey, $this->otherKey);
850
-    }
851
-
852
-    /**
853
-     * Create a new existing pivot model instance.
854
-     *
855
-     * @param  array $attributes
856
-     * @return \Analogue\ORM\Relationships\Pivot
857
-     */
858
-    public function newExistingPivot(array $attributes = [])
859
-    {
860
-        return $this->newPivot($attributes, true);
861
-    }
862
-
863
-    /**
864
-     * Set the columns on the pivot table to retrieve.
865
-     *
866
-     * @param  array $columns
867
-     * @return $this
868
-     */
869
-    public function withPivot($columns)
870
-    {
871
-        $columns = is_array($columns) ? $columns : func_get_args();
872
-
873
-        $this->pivotColumns = array_merge($this->pivotColumns, $columns);
874
-
875
-        return $this;
876
-    }
877
-
878
-    /**
879
-     * Specify that the pivot table has creation and update timestamps.
880
-     *
881
-     * @param  mixed $createdAt
882
-     * @param  mixed $updatedAt
883
-     * @return \Analogue\ORM\Relationships\BelongsToMany
884
-     */
885
-    public function withTimestamps($createdAt = null, $updatedAt = null)
886
-    {
887
-        return $this->withPivot($createdAt ?: $this->createdAt(), $updatedAt ?: $this->updatedAt());
888
-    }
889
-
890
-    /**
891
-     * Get the key for comparing against the parent key in "has" query.
892
-     *
893
-     * @return string
894
-     */
895
-    public function getHasCompareKey()
896
-    {
897
-        return $this->getForeignKey();
898
-    }
899
-
900
-    /**
901
-     * Get the fully qualified foreign key for the relation.
902
-     *
903
-     * @return string
904
-     */
905
-    public function getForeignKey()
906
-    {
907
-        return $this->table . '.' . $this->foreignKey;
908
-    }
909
-
910
-    /**
911
-     * Get the fully qualified "other key" for the relation.
912
-     *
913
-     * @return string
914
-     */
915
-    public function getOtherKey()
916
-    {
917
-        return $this->table . '.' . $this->otherKey;
918
-    }
919
-
920
-    /**
921
-     * Get the fully qualified parent key name.
922
-     *
923
-     * @return string
924
-     */
925
-    protected function getQualifiedParentKeyName()
926
-    {
927
-        return $this->parentMap->getQualifiedKeyName();
928
-    }
929
-
930
-    /**
931
-     * Get the intermediate table for the relationship.
932
-     *
933
-     * @return string
934
-     */
935
-    public function getTable()
936
-    {
937
-        return $this->table;
938
-    }
939
-
940
-    /**
941
-     * Get the relationship name for the relationship.
942
-     *
943
-     * @return string
944
-     */
945
-    public function getRelationName()
946
-    {
947
-        return $this->relationName;
948
-    }
849
+		return $pivot->setPivotKeys($this->foreignKey, $this->otherKey);
850
+	}
851
+
852
+	/**
853
+	 * Create a new existing pivot model instance.
854
+	 *
855
+	 * @param  array $attributes
856
+	 * @return \Analogue\ORM\Relationships\Pivot
857
+	 */
858
+	public function newExistingPivot(array $attributes = [])
859
+	{
860
+		return $this->newPivot($attributes, true);
861
+	}
862
+
863
+	/**
864
+	 * Set the columns on the pivot table to retrieve.
865
+	 *
866
+	 * @param  array $columns
867
+	 * @return $this
868
+	 */
869
+	public function withPivot($columns)
870
+	{
871
+		$columns = is_array($columns) ? $columns : func_get_args();
872
+
873
+		$this->pivotColumns = array_merge($this->pivotColumns, $columns);
874
+
875
+		return $this;
876
+	}
877
+
878
+	/**
879
+	 * Specify that the pivot table has creation and update timestamps.
880
+	 *
881
+	 * @param  mixed $createdAt
882
+	 * @param  mixed $updatedAt
883
+	 * @return \Analogue\ORM\Relationships\BelongsToMany
884
+	 */
885
+	public function withTimestamps($createdAt = null, $updatedAt = null)
886
+	{
887
+		return $this->withPivot($createdAt ?: $this->createdAt(), $updatedAt ?: $this->updatedAt());
888
+	}
889
+
890
+	/**
891
+	 * Get the key for comparing against the parent key in "has" query.
892
+	 *
893
+	 * @return string
894
+	 */
895
+	public function getHasCompareKey()
896
+	{
897
+		return $this->getForeignKey();
898
+	}
899
+
900
+	/**
901
+	 * Get the fully qualified foreign key for the relation.
902
+	 *
903
+	 * @return string
904
+	 */
905
+	public function getForeignKey()
906
+	{
907
+		return $this->table . '.' . $this->foreignKey;
908
+	}
909
+
910
+	/**
911
+	 * Get the fully qualified "other key" for the relation.
912
+	 *
913
+	 * @return string
914
+	 */
915
+	public function getOtherKey()
916
+	{
917
+		return $this->table . '.' . $this->otherKey;
918
+	}
919
+
920
+	/**
921
+	 * Get the fully qualified parent key name.
922
+	 *
923
+	 * @return string
924
+	 */
925
+	protected function getQualifiedParentKeyName()
926
+	{
927
+		return $this->parentMap->getQualifiedKeyName();
928
+	}
929
+
930
+	/**
931
+	 * Get the intermediate table for the relationship.
932
+	 *
933
+	 * @return string
934
+	 */
935
+	public function getTable()
936
+	{
937
+		return $this->table;
938
+	}
939
+
940
+	/**
941
+	 * Get the relationship name for the relationship.
942
+	 *
943
+	 * @return string
944
+	 */
945
+	public function getRelationName()
946
+	{
947
+		return $this->relationName;
948
+	}
949 949
 }
Please login to merge, or discard this patch.
src/Relationships/HasOneOrMany.php 1 patch
Indentation   +319 added lines, -319 removed lines patch added patch discarded remove patch
@@ -7,323 +7,323 @@
 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|EntityCollection $entity
42
-     * @return void
43
-     */
44
-    public function attachTo($entity)
45
-    {
46
-        if ($entity instanceof EntityCollection) {
47
-            $this->attachMany($entity);
48
-        }
49
-        $this->attachOne($entity);
50
-    }
51
-
52
-    /**
53
-     * @param $entityHash
54
-     * @return void
55
-     */
56
-    public function detachFrom($entityHash)
57
-    {
58
-        if (is_array($entityHash)) {
59
-            $this->detachMany($entityHash);
60
-            return;
61
-        }
62
-        $this->detachMany([$entityHash]);
63
-    }
64
-
65
-    /**
66
-     * @param \Analogue\ORM\Entity $entity
67
-     */
68
-    public function attachOne($entity)
69
-    {
70
-        $wrapper = $this->factory->make($entity);
71
-
72
-        // Ok, we need to guess the inverse of the relation from there.
73
-        // Let's assume the inverse of the relation method is the name of
74
-        // the entity.
75
-
76
-        $wrapper->setEntityAttribute($this->getPlainForeignKey(), $this->getParentKey());
77
-    }
78
-
79
-    /**
80
-     * @param EntityCollection $entities
81
-     */
82
-    public function attachMany(EntityCollection $entities)
83
-    {
84
-        foreach ($entities as $entity) {
85
-            $this->attachOne($entity);
86
-        }
87
-    }
88
-
89
-    /**
90
-     * @param $entityHash
91
-     */
92
-    protected function detachOne($entityHash)
93
-    {
94
-        $this->detachMany([$entityHash]);
95
-    }
96
-
97
-    /**
98
-     * Attach ids that are passed as arguments, and detach any other
99
-     * @param  mixed $entities
100
-     * @throws \InvalidArgumentException
101
-     * @return void
102
-     */
103
-    public function sync(array $entities)
104
-    {
105
-        $this->detachExcept($entities);
106
-    }
107
-
108
-    /**
109
-     * @param  $entities
110
-     * @throws \InvalidArgumentException
111
-     */
112
-    protected function detachExcept($entities)
113
-    {
114
-        $query = $this->query->getQuery()->from($this->relatedMap->getTable());
115
-
116
-        if (count($entities) > 0) {
117
-            $keys = $this->getKeys($entities);
118
-            $query->whereNotIn($this->relatedMap->getKeyName(), $keys);
119
-        }
120
-
121
-        $parentKey = $this->parentMap->getKeyName();
122
-
123
-        $query->where($this->getPlainForeignKey(), '=', $this->parent->getEntityAttribute($parentKey))
124
-            ->update([$this->getPlainForeignKey() => null]);
125
-    }
126
-
127
-    /**
128
-     * @param array $entityHashes
129
-     */
130
-    public function detachMany(array $entityHashes)
131
-    {
132
-        $keys = [];
133
-
134
-        foreach ($entityHashes as $hash) {
135
-            $split = explode('.', $hash);
136
-            $keys[] = $split[1];
137
-        }
138
-
139
-        $query = $this->query->getQuery()->from($this->relatedMap->getTable());
140
-
141
-        $query->whereIn($this->relatedMap->getKeyName(), $keys)
142
-            ->update([$this->getPlainForeignKey() => null]);
143
-    }
144
-
145
-    /**
146
-     * Set the base constraints on the relation query.
147
-     *
148
-     * @return void
149
-     */
150
-    public function addConstraints()
151
-    {
152
-        if (static::$constraints) {
153
-            $this->query->where($this->foreignKey, '=', $this->getParentKey());
154
-        }
155
-    }
156
-
157
-    /**
158
-     * Set the constraints for an eager load of the relation.
159
-     *
160
-     * @param  array $entities
161
-     * @return void
162
-     */
163
-    public function addEagerConstraints(array $entities)
164
-    {
165
-        $this->query->whereIn($this->foreignKey, $this->getKeys($entities, $this->localKey));
166
-    }
167
-
168
-    /**
169
-     * Match the eagerly loaded results to their single parents.
170
-     *
171
-     * @param  array            $entities
172
-     * @param  EntityCollection $results
173
-     * @param  string           $relation
174
-     * @return array
175
-     */
176
-    public function matchOne(array $entities, EntityCollection $results, $relation)
177
-    {
178
-        return $this->matchOneOrMany($entities, $results, $relation, 'one');
179
-    }
180
-
181
-    /**
182
-     * Match the eagerly loaded results to their many parents.
183
-     *
184
-     * @param  array            $entities
185
-     * @param  EntityCollection $results
186
-     * @param  string           $relation
187
-     * @return array
188
-     */
189
-    public function matchMany(array $entities, EntityCollection $results, $relation)
190
-    {
191
-        return $this->matchOneOrMany($entities, $results, $relation, 'many');
192
-    }
193
-
194
-    /**
195
-     * Match the eagerly loaded results to their many parents.
196
-     *
197
-     * @param  array            $entities
198
-     * @param  EntityCollection $results
199
-     * @param  string           $relation
200
-     * @param  string           $type
201
-     * @return array
202
-     */
203
-    protected function matchOneOrMany(array $entities, EntityCollection $results, $relation, $type)
204
-    {
205
-        $dictionary = $this->buildDictionary($results);
206
-
207
-        $cache = $this->parentMapper->getEntityCache();
208
-
209
-        // Once we have the dictionary we can simply spin through the parent models to
210
-        // link them up with their children using the keyed dictionary to make the
211
-        // matching very convenient and easy work. Then we'll just return them.
212
-        foreach ($entities as $entity) {
213
-            $entity = $this->factory->make($entity);
214
-
215
-            $key = $entity->getEntityAttribute($this->localKey);
216
-
217
-            if (isset($dictionary[$key])) {
218
-                $value = $this->getRelationValue($dictionary, $key, $type);
219
-
220
-                $entity->setEntityAttribute($relation, $value);
221
-
222
-                $cache->cacheLoadedRelationResult($entity, $relation, $value, $this);
223
-            }
224
-        }
225
-
226
-        return $entities;
227
-    }
228
-
229
-    /**
230
-     * Get the value of a relationship by one or many type.
231
-     *
232
-     * @param  array  $dictionary
233
-     * @param  string $key
234
-     * @param  string $type
235
-     * @return mixed
236
-     */
237
-    protected function getRelationValue(array $dictionary, $key, $type)
238
-    {
239
-        $value = $dictionary[$key];
240
-
241
-        return $type == 'one' ? reset($value) : $this->relatedMap->newCollection($value);
242
-    }
243
-
244
-    /**
245
-     * Build model dictionary keyed by the relation's foreign key.
246
-     *
247
-     * @param  EntityCollection $results
248
-     * @return array
249
-     */
250
-    protected function buildDictionary(EntityCollection $results)
251
-    {
252
-        $dictionary = [];
253
-
254
-        $foreign = $this->getPlainForeignKey();
255
-
256
-        $foreign = $this->relatedMap->mapColumnToAttribute($foreign);
257
-
258
-        // First we will create a dictionary of models keyed by the foreign key of the
259
-        // relationship as this will allow us to quickly access all of the related
260
-        // models without having to do nested looping which will be quite slow.
261
-        foreach ($results as $result) {
262
-            $dictionary[$result->{$foreign}][] = $result;
263
-        }
264
-
265
-        return $dictionary;
266
-    }
267
-
268
-    /**
269
-     * Get the key for comparing against the parent key in "has" query.
270
-     *
271
-     * @return string
272
-     */
273
-    public function getHasCompareKey()
274
-    {
275
-        return $this->getForeignKey();
276
-    }
277
-
278
-    /**
279
-     * Get the foreign key for the relationship.
280
-     *
281
-     * @return string
282
-     */
283
-    public function getForeignKey()
284
-    {
285
-        return $this->foreignKey;
286
-    }
287
-
288
-    /**
289
-     * Get the plain foreign key.
290
-     *
291
-     * @return string
292
-     */
293
-    public function getPlainForeignKey()
294
-    {
295
-        $segments = explode('.', $this->getForeignKey());
296
-
297
-        return $segments[count($segments) - 1];
298
-    }
299
-
300
-    /**
301
-     * Get the key value of the parent's local key.
302
-     *
303
-     * @return mixed
304
-     */
305
-    public function getParentKey()
306
-    {
307
-        return $this->parent->getEntityAttribute($this->localKey);
308
-    }
309
-
310
-    /**
311
-     * Get the fully qualified parent key name.
312
-     *
313
-     * @return string
314
-     */
315
-    public function getQualifiedParentKeyName()
316
-    {
317
-        return $this->parentMap->getTable() . '.' . $this->localKey;
318
-    }
319
-
320
-    /**
321
-     * Get the foreign key as value pair for this relation
322
-     *
323
-     * @return array
324
-     */
325
-    public function getForeignKeyValuePair()
326
-    {
327
-        return [$this->getPlainForeignKey() => $this->getParentKey()];
328
-    }
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|EntityCollection $entity
42
+	 * @return void
43
+	 */
44
+	public function attachTo($entity)
45
+	{
46
+		if ($entity instanceof EntityCollection) {
47
+			$this->attachMany($entity);
48
+		}
49
+		$this->attachOne($entity);
50
+	}
51
+
52
+	/**
53
+	 * @param $entityHash
54
+	 * @return void
55
+	 */
56
+	public function detachFrom($entityHash)
57
+	{
58
+		if (is_array($entityHash)) {
59
+			$this->detachMany($entityHash);
60
+			return;
61
+		}
62
+		$this->detachMany([$entityHash]);
63
+	}
64
+
65
+	/**
66
+	 * @param \Analogue\ORM\Entity $entity
67
+	 */
68
+	public function attachOne($entity)
69
+	{
70
+		$wrapper = $this->factory->make($entity);
71
+
72
+		// Ok, we need to guess the inverse of the relation from there.
73
+		// Let's assume the inverse of the relation method is the name of
74
+		// the entity.
75
+
76
+		$wrapper->setEntityAttribute($this->getPlainForeignKey(), $this->getParentKey());
77
+	}
78
+
79
+	/**
80
+	 * @param EntityCollection $entities
81
+	 */
82
+	public function attachMany(EntityCollection $entities)
83
+	{
84
+		foreach ($entities as $entity) {
85
+			$this->attachOne($entity);
86
+		}
87
+	}
88
+
89
+	/**
90
+	 * @param $entityHash
91
+	 */
92
+	protected function detachOne($entityHash)
93
+	{
94
+		$this->detachMany([$entityHash]);
95
+	}
96
+
97
+	/**
98
+	 * Attach ids that are passed as arguments, and detach any other
99
+	 * @param  mixed $entities
100
+	 * @throws \InvalidArgumentException
101
+	 * @return void
102
+	 */
103
+	public function sync(array $entities)
104
+	{
105
+		$this->detachExcept($entities);
106
+	}
107
+
108
+	/**
109
+	 * @param  $entities
110
+	 * @throws \InvalidArgumentException
111
+	 */
112
+	protected function detachExcept($entities)
113
+	{
114
+		$query = $this->query->getQuery()->from($this->relatedMap->getTable());
115
+
116
+		if (count($entities) > 0) {
117
+			$keys = $this->getKeys($entities);
118
+			$query->whereNotIn($this->relatedMap->getKeyName(), $keys);
119
+		}
120
+
121
+		$parentKey = $this->parentMap->getKeyName();
122
+
123
+		$query->where($this->getPlainForeignKey(), '=', $this->parent->getEntityAttribute($parentKey))
124
+			->update([$this->getPlainForeignKey() => null]);
125
+	}
126
+
127
+	/**
128
+	 * @param array $entityHashes
129
+	 */
130
+	public function detachMany(array $entityHashes)
131
+	{
132
+		$keys = [];
133
+
134
+		foreach ($entityHashes as $hash) {
135
+			$split = explode('.', $hash);
136
+			$keys[] = $split[1];
137
+		}
138
+
139
+		$query = $this->query->getQuery()->from($this->relatedMap->getTable());
140
+
141
+		$query->whereIn($this->relatedMap->getKeyName(), $keys)
142
+			->update([$this->getPlainForeignKey() => null]);
143
+	}
144
+
145
+	/**
146
+	 * Set the base constraints on the relation query.
147
+	 *
148
+	 * @return void
149
+	 */
150
+	public function addConstraints()
151
+	{
152
+		if (static::$constraints) {
153
+			$this->query->where($this->foreignKey, '=', $this->getParentKey());
154
+		}
155
+	}
156
+
157
+	/**
158
+	 * Set the constraints for an eager load of the relation.
159
+	 *
160
+	 * @param  array $entities
161
+	 * @return void
162
+	 */
163
+	public function addEagerConstraints(array $entities)
164
+	{
165
+		$this->query->whereIn($this->foreignKey, $this->getKeys($entities, $this->localKey));
166
+	}
167
+
168
+	/**
169
+	 * Match the eagerly loaded results to their single parents.
170
+	 *
171
+	 * @param  array            $entities
172
+	 * @param  EntityCollection $results
173
+	 * @param  string           $relation
174
+	 * @return array
175
+	 */
176
+	public function matchOne(array $entities, EntityCollection $results, $relation)
177
+	{
178
+		return $this->matchOneOrMany($entities, $results, $relation, 'one');
179
+	}
180
+
181
+	/**
182
+	 * Match the eagerly loaded results to their many parents.
183
+	 *
184
+	 * @param  array            $entities
185
+	 * @param  EntityCollection $results
186
+	 * @param  string           $relation
187
+	 * @return array
188
+	 */
189
+	public function matchMany(array $entities, EntityCollection $results, $relation)
190
+	{
191
+		return $this->matchOneOrMany($entities, $results, $relation, 'many');
192
+	}
193
+
194
+	/**
195
+	 * Match the eagerly loaded results to their many parents.
196
+	 *
197
+	 * @param  array            $entities
198
+	 * @param  EntityCollection $results
199
+	 * @param  string           $relation
200
+	 * @param  string           $type
201
+	 * @return array
202
+	 */
203
+	protected function matchOneOrMany(array $entities, EntityCollection $results, $relation, $type)
204
+	{
205
+		$dictionary = $this->buildDictionary($results);
206
+
207
+		$cache = $this->parentMapper->getEntityCache();
208
+
209
+		// Once we have the dictionary we can simply spin through the parent models to
210
+		// link them up with their children using the keyed dictionary to make the
211
+		// matching very convenient and easy work. Then we'll just return them.
212
+		foreach ($entities as $entity) {
213
+			$entity = $this->factory->make($entity);
214
+
215
+			$key = $entity->getEntityAttribute($this->localKey);
216
+
217
+			if (isset($dictionary[$key])) {
218
+				$value = $this->getRelationValue($dictionary, $key, $type);
219
+
220
+				$entity->setEntityAttribute($relation, $value);
221
+
222
+				$cache->cacheLoadedRelationResult($entity, $relation, $value, $this);
223
+			}
224
+		}
225
+
226
+		return $entities;
227
+	}
228
+
229
+	/**
230
+	 * Get the value of a relationship by one or many type.
231
+	 *
232
+	 * @param  array  $dictionary
233
+	 * @param  string $key
234
+	 * @param  string $type
235
+	 * @return mixed
236
+	 */
237
+	protected function getRelationValue(array $dictionary, $key, $type)
238
+	{
239
+		$value = $dictionary[$key];
240
+
241
+		return $type == 'one' ? reset($value) : $this->relatedMap->newCollection($value);
242
+	}
243
+
244
+	/**
245
+	 * Build model dictionary keyed by the relation's foreign key.
246
+	 *
247
+	 * @param  EntityCollection $results
248
+	 * @return array
249
+	 */
250
+	protected function buildDictionary(EntityCollection $results)
251
+	{
252
+		$dictionary = [];
253
+
254
+		$foreign = $this->getPlainForeignKey();
255
+
256
+		$foreign = $this->relatedMap->mapColumnToAttribute($foreign);
257
+
258
+		// First we will create a dictionary of models keyed by the foreign key of the
259
+		// relationship as this will allow us to quickly access all of the related
260
+		// models without having to do nested looping which will be quite slow.
261
+		foreach ($results as $result) {
262
+			$dictionary[$result->{$foreign}][] = $result;
263
+		}
264
+
265
+		return $dictionary;
266
+	}
267
+
268
+	/**
269
+	 * Get the key for comparing against the parent key in "has" query.
270
+	 *
271
+	 * @return string
272
+	 */
273
+	public function getHasCompareKey()
274
+	{
275
+		return $this->getForeignKey();
276
+	}
277
+
278
+	/**
279
+	 * Get the foreign key for the relationship.
280
+	 *
281
+	 * @return string
282
+	 */
283
+	public function getForeignKey()
284
+	{
285
+		return $this->foreignKey;
286
+	}
287
+
288
+	/**
289
+	 * Get the plain foreign key.
290
+	 *
291
+	 * @return string
292
+	 */
293
+	public function getPlainForeignKey()
294
+	{
295
+		$segments = explode('.', $this->getForeignKey());
296
+
297
+		return $segments[count($segments) - 1];
298
+	}
299
+
300
+	/**
301
+	 * Get the key value of the parent's local key.
302
+	 *
303
+	 * @return mixed
304
+	 */
305
+	public function getParentKey()
306
+	{
307
+		return $this->parent->getEntityAttribute($this->localKey);
308
+	}
309
+
310
+	/**
311
+	 * Get the fully qualified parent key name.
312
+	 *
313
+	 * @return string
314
+	 */
315
+	public function getQualifiedParentKeyName()
316
+	{
317
+		return $this->parentMap->getTable() . '.' . $this->localKey;
318
+	}
319
+
320
+	/**
321
+	 * Get the foreign key as value pair for this relation
322
+	 *
323
+	 * @return array
324
+	 */
325
+	public function getForeignKeyValuePair()
326
+	{
327
+		return [$this->getPlainForeignKey() => $this->getParentKey()];
328
+	}
329 329
 }
Please login to merge, or discard this patch.
src/Relationships/HasManyThrough.php 1 patch
Indentation   +312 added lines, -312 removed lines patch added patch discarded remove patch
@@ -9,316 +9,316 @@
 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
-     * @throws \Analogue\ORM\Exceptions\MappingException
49
-     */
50
-    public function __construct(Mapper $mapper, $farParent, $parentMap, $firstKey, $secondKey)
51
-    {
52
-        $this->firstKey = $firstKey;
53
-        $this->secondKey = $secondKey;
54
-        $this->farParent = $farParent;
55
-
56
-        $this->farParentMap = $mapper->getManager()->mapper($farParent)->getEntityMap();
57
-        $parentInstance = $mapper->getManager()->mapper($parentMap->getClass())->newInstance();
58
-
59
-        parent::__construct($mapper, $parentInstance);
60
-    }
61
-
62
-    /**
63
-     * @param $related
64
-     * @return mixed
65
-     */
66
-    public function attachTo($related)
67
-    {
68
-        // N/A
69
-    }
70
-
71
-    /**
72
-     * @param $related
73
-     * @return mixed
74
-     */
75
-    public function detachFrom($related)
76
-    {
77
-        // N/A
78
-    }
79
-
80
-    /**
81
-     * Set the base constraints on the relation query.
82
-     *
83
-     * @return void
84
-     */
85
-    public function addConstraints()
86
-    {
87
-        $parentTable = $this->parentMap->getTable();
88
-
89
-        $this->setJoin();
90
-
91
-        if (static::$constraints) {
92
-            $farParentKeyName = $this->farParentMap->getKeyName();
93
-
94
-            $this->query->where(
95
-                $parentTable . '.' . $this->firstKey,
96
-                '=',
97
-                $this->farParent->getEntityAttribute($farParentKeyName)
98
-            );
99
-        }
100
-    }
101
-
102
-    /**
103
-     * Add the constraints for a relationship count query.
104
-     *
105
-     * @param  Query $query
106
-     * @param  Query $parent
107
-     * @return Query
108
-     */
109
-    public function getRelationCountQuery(Query $query, Query $parent)
110
-    {
111
-        $parentTable = $this->parentMap->getTable();
112
-
113
-        $this->setJoin($query);
114
-
115
-        $query->select(new Expression('count(*)'));
116
-
117
-        $key = $this->wrap($parentTable . '.' . $this->firstKey);
118
-
119
-        return $query->where($this->getHasCompareKey(), '=', new Expression($key));
120
-    }
121
-
122
-    /**
123
-     * Set the join clause on the query.
124
-     *
125
-     * @param  null|Query $query
126
-     * @return void
127
-     */
128
-    protected function setJoin(Query $query = null)
129
-    {
130
-        $query = $query ?: $this->query;
131
-
132
-        $foreignKey = $this->relatedMap->getTable() . '.' . $this->secondKey;
133
-
134
-        $query->join($this->parentMap->getTable(), $this->getQualifiedParentKeyName(), '=', $foreignKey);
135
-    }
136
-
137
-    /**
138
-     * Set the constraints for an eager load of the relation.
139
-     *
140
-     * @param  array $entities
141
-     * @return void
142
-     */
143
-    public function addEagerConstraints(array $entities)
144
-    {
145
-        $table = $this->parentMap->getTable();
146
-
147
-        $this->query->whereIn($table . '.' . $this->firstKey, $this->getKeys($entities));
148
-    }
149
-
150
-    /**
151
-     * Initialize the relation on a set of entities.
152
-     *
153
-     * @param  \Analogue\ORM\Entity[] $entities
154
-     * @param  string                 $relation
155
-     * @return \Analogue\ORM\Entity[]
156
-     */
157
-    public function initRelation(array $entities, $relation)
158
-    {
159
-        foreach ($entities as $entity) {
160
-            $entity->setEntityAttribute($relation, $this->relatedMap->newCollection());
161
-        }
162
-
163
-        return $entities;
164
-    }
165
-
166
-    /**
167
-     * Match the eagerly loaded results to their parents.
168
-     *
169
-     * @param  \Analogue\ORM\Entity[] $entities
170
-     * @param  EntityCollection       $results
171
-     * @param  string                 $relation
172
-     * @return \Analogue\ORM\Entity[]
173
-     */
174
-    public function match(array $entities, EntityCollection $results, $relation)
175
-    {
176
-        $dictionary = $this->buildDictionary($results);
177
-
178
-        $relatedKey = $this->relatedMap->getKeyName();
179
-
180
-        $cache = $this->parentMapper->getEntityCache();
181
-
182
-        // Once we have the dictionary we can simply spin through the parent entities to
183
-        // link them up with their children using the keyed dictionary to make the
184
-        // matching very convenient and easy work. Then we'll just return them.
185
-        foreach ($entities as $entity) {
186
-            $key = $entity->getEntityAttribute($relatedKey);
187
-
188
-            if (isset($dictionary[$key])) {
189
-                $value = $this->relatedMap->newCollection($dictionary[$key]);
190
-
191
-                $entity->setEntityAttribute($relation, $value);
192
-
193
-                $cache->cacheLoadedRelationResult($entity, $relation, $value, $this);
194
-            }
195
-        }
196
-
197
-        return $entities;
198
-    }
199
-
200
-    /**
201
-     * Build model dictionary keyed by the relation's foreign key.
202
-     *
203
-     * @param  EntityCollection $results
204
-     * @return array
205
-     */
206
-    protected function buildDictionary(EntityCollection $results)
207
-    {
208
-        $dictionary = [];
209
-
210
-        $foreign = $this->firstKey;
211
-
212
-        $foreign = $this->relatedMap->mapColumnToAttribute($foreign);
213
-
214
-        // First we will create a dictionary of entities keyed by the foreign key of the
215
-        // relationship as this will allow us to quickly access all of the related
216
-        // entities without having to do nested looping which will be quite slow.
217
-        foreach ($results as $result) {
218
-            $dictionary[$result->{$foreign}][] = $result;
219
-        }
220
-
221
-        return $dictionary;
222
-    }
223
-
224
-    /**
225
-     * Get the results of the relationship.
226
-     *
227
-     * @param  $relation
228
-     * @return EntityCollection
229
-     */
230
-    public function getResults($relation)
231
-    {
232
-        $results = $this->query->get();
233
-
234
-        $this->cacheRelation($results, $relation);
235
-
236
-        return $results;
237
-    }
238
-
239
-    /**
240
-     * Execute the query as a "select" statement.
241
-     *
242
-     * @param  array $columns
243
-     * @return EntityCollection
244
-     */
245
-    public function get($columns = ['*'])
246
-    {
247
-        // First we'll add the proper select columns onto the query so it is run with
248
-        // the proper columns. Then, we will get the results and hydrate out pivot
249
-        // entities with the result of those columns as a separate model relation.
250
-        $select = $this->getSelectColumns($columns);
251
-
252
-        $entities = $this->query->addSelect($select)->getEntities();
253
-
254
-        // If we actually found entities we will also eager load any relationships that
255
-        // have been specified as needing to be eager loaded. This will solve the
256
-        // n + 1 query problem for the developer and also increase performance.
257
-        if (count($entities) > 0) {
258
-            $entities = $this->query->eagerLoadRelations($entities);
259
-        }
260
-
261
-        return $this->relatedMap->newCollection($entities);
262
-    }
263
-
264
-    /**
265
-     * Set the select clause for the relation query.
266
-     *
267
-     * @param  array $columns
268
-     * @return BelongsToMany
269
-     */
270
-    protected function getSelectColumns(array $columns = ['*'])
271
-    {
272
-        if ($columns == ['*']) {
273
-            $columns = [$this->relatedMap->getTable() . '.*'];
274
-        }
275
-
276
-        return array_merge($columns, [$this->parentMap->getTable() . '.' . $this->firstKey]);
277
-    }
278
-
279
-    /**
280
-     * Get a paginator for the "select" statement.
281
-     *
282
-     * @param  int   $perPage
283
-     * @param  array $columns
284
-     * @return \Illuminate\Pagination\LengthAwarePaginator
285
-     */
286
-    public function paginate($perPage = null, $columns = ['*'])
287
-    {
288
-        $this->query->addSelect($this->getSelectColumns($columns));
289
-
290
-        return $this->query->paginate($perPage, $columns);
291
-    }
292
-
293
-    /**
294
-     * Get the key name of the parent model.
295
-     *
296
-     * @return string
297
-     */
298
-    protected function getQualifiedParentKeyName()
299
-    {
300
-        return $this->parentMap->getQualifiedKeyName();
301
-    }
302
-
303
-    /**
304
-     * Get the key for comparing against the parent key in "has" query.
305
-     *
306
-     * @return string
307
-     */
308
-    public function getHasCompareKey()
309
-    {
310
-        return $this->farParentMap->getQualifiedKeyName();
311
-    }
312
-
313
-    /**
314
-     * Run synchronization content if needed by the
315
-     * relation type.
316
-     *
317
-     * @param  array $actualContent
318
-     * @return void
319
-     */
320
-    public function sync(array $entities)
321
-    {
322
-        // N/A
323
-    }
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
+	 * @throws \Analogue\ORM\Exceptions\MappingException
49
+	 */
50
+	public function __construct(Mapper $mapper, $farParent, $parentMap, $firstKey, $secondKey)
51
+	{
52
+		$this->firstKey = $firstKey;
53
+		$this->secondKey = $secondKey;
54
+		$this->farParent = $farParent;
55
+
56
+		$this->farParentMap = $mapper->getManager()->mapper($farParent)->getEntityMap();
57
+		$parentInstance = $mapper->getManager()->mapper($parentMap->getClass())->newInstance();
58
+
59
+		parent::__construct($mapper, $parentInstance);
60
+	}
61
+
62
+	/**
63
+	 * @param $related
64
+	 * @return mixed
65
+	 */
66
+	public function attachTo($related)
67
+	{
68
+		// N/A
69
+	}
70
+
71
+	/**
72
+	 * @param $related
73
+	 * @return mixed
74
+	 */
75
+	public function detachFrom($related)
76
+	{
77
+		// N/A
78
+	}
79
+
80
+	/**
81
+	 * Set the base constraints on the relation query.
82
+	 *
83
+	 * @return void
84
+	 */
85
+	public function addConstraints()
86
+	{
87
+		$parentTable = $this->parentMap->getTable();
88
+
89
+		$this->setJoin();
90
+
91
+		if (static::$constraints) {
92
+			$farParentKeyName = $this->farParentMap->getKeyName();
93
+
94
+			$this->query->where(
95
+				$parentTable . '.' . $this->firstKey,
96
+				'=',
97
+				$this->farParent->getEntityAttribute($farParentKeyName)
98
+			);
99
+		}
100
+	}
101
+
102
+	/**
103
+	 * Add the constraints for a relationship count query.
104
+	 *
105
+	 * @param  Query $query
106
+	 * @param  Query $parent
107
+	 * @return Query
108
+	 */
109
+	public function getRelationCountQuery(Query $query, Query $parent)
110
+	{
111
+		$parentTable = $this->parentMap->getTable();
112
+
113
+		$this->setJoin($query);
114
+
115
+		$query->select(new Expression('count(*)'));
116
+
117
+		$key = $this->wrap($parentTable . '.' . $this->firstKey);
118
+
119
+		return $query->where($this->getHasCompareKey(), '=', new Expression($key));
120
+	}
121
+
122
+	/**
123
+	 * Set the join clause on the query.
124
+	 *
125
+	 * @param  null|Query $query
126
+	 * @return void
127
+	 */
128
+	protected function setJoin(Query $query = null)
129
+	{
130
+		$query = $query ?: $this->query;
131
+
132
+		$foreignKey = $this->relatedMap->getTable() . '.' . $this->secondKey;
133
+
134
+		$query->join($this->parentMap->getTable(), $this->getQualifiedParentKeyName(), '=', $foreignKey);
135
+	}
136
+
137
+	/**
138
+	 * Set the constraints for an eager load of the relation.
139
+	 *
140
+	 * @param  array $entities
141
+	 * @return void
142
+	 */
143
+	public function addEagerConstraints(array $entities)
144
+	{
145
+		$table = $this->parentMap->getTable();
146
+
147
+		$this->query->whereIn($table . '.' . $this->firstKey, $this->getKeys($entities));
148
+	}
149
+
150
+	/**
151
+	 * Initialize the relation on a set of entities.
152
+	 *
153
+	 * @param  \Analogue\ORM\Entity[] $entities
154
+	 * @param  string                 $relation
155
+	 * @return \Analogue\ORM\Entity[]
156
+	 */
157
+	public function initRelation(array $entities, $relation)
158
+	{
159
+		foreach ($entities as $entity) {
160
+			$entity->setEntityAttribute($relation, $this->relatedMap->newCollection());
161
+		}
162
+
163
+		return $entities;
164
+	}
165
+
166
+	/**
167
+	 * Match the eagerly loaded results to their parents.
168
+	 *
169
+	 * @param  \Analogue\ORM\Entity[] $entities
170
+	 * @param  EntityCollection       $results
171
+	 * @param  string                 $relation
172
+	 * @return \Analogue\ORM\Entity[]
173
+	 */
174
+	public function match(array $entities, EntityCollection $results, $relation)
175
+	{
176
+		$dictionary = $this->buildDictionary($results);
177
+
178
+		$relatedKey = $this->relatedMap->getKeyName();
179
+
180
+		$cache = $this->parentMapper->getEntityCache();
181
+
182
+		// Once we have the dictionary we can simply spin through the parent entities to
183
+		// link them up with their children using the keyed dictionary to make the
184
+		// matching very convenient and easy work. Then we'll just return them.
185
+		foreach ($entities as $entity) {
186
+			$key = $entity->getEntityAttribute($relatedKey);
187
+
188
+			if (isset($dictionary[$key])) {
189
+				$value = $this->relatedMap->newCollection($dictionary[$key]);
190
+
191
+				$entity->setEntityAttribute($relation, $value);
192
+
193
+				$cache->cacheLoadedRelationResult($entity, $relation, $value, $this);
194
+			}
195
+		}
196
+
197
+		return $entities;
198
+	}
199
+
200
+	/**
201
+	 * Build model dictionary keyed by the relation's foreign key.
202
+	 *
203
+	 * @param  EntityCollection $results
204
+	 * @return array
205
+	 */
206
+	protected function buildDictionary(EntityCollection $results)
207
+	{
208
+		$dictionary = [];
209
+
210
+		$foreign = $this->firstKey;
211
+
212
+		$foreign = $this->relatedMap->mapColumnToAttribute($foreign);
213
+
214
+		// First we will create a dictionary of entities keyed by the foreign key of the
215
+		// relationship as this will allow us to quickly access all of the related
216
+		// entities without having to do nested looping which will be quite slow.
217
+		foreach ($results as $result) {
218
+			$dictionary[$result->{$foreign}][] = $result;
219
+		}
220
+
221
+		return $dictionary;
222
+	}
223
+
224
+	/**
225
+	 * Get the results of the relationship.
226
+	 *
227
+	 * @param  $relation
228
+	 * @return EntityCollection
229
+	 */
230
+	public function getResults($relation)
231
+	{
232
+		$results = $this->query->get();
233
+
234
+		$this->cacheRelation($results, $relation);
235
+
236
+		return $results;
237
+	}
238
+
239
+	/**
240
+	 * Execute the query as a "select" statement.
241
+	 *
242
+	 * @param  array $columns
243
+	 * @return EntityCollection
244
+	 */
245
+	public function get($columns = ['*'])
246
+	{
247
+		// First we'll add the proper select columns onto the query so it is run with
248
+		// the proper columns. Then, we will get the results and hydrate out pivot
249
+		// entities with the result of those columns as a separate model relation.
250
+		$select = $this->getSelectColumns($columns);
251
+
252
+		$entities = $this->query->addSelect($select)->getEntities();
253
+
254
+		// If we actually found entities we will also eager load any relationships that
255
+		// have been specified as needing to be eager loaded. This will solve the
256
+		// n + 1 query problem for the developer and also increase performance.
257
+		if (count($entities) > 0) {
258
+			$entities = $this->query->eagerLoadRelations($entities);
259
+		}
260
+
261
+		return $this->relatedMap->newCollection($entities);
262
+	}
263
+
264
+	/**
265
+	 * Set the select clause for the relation query.
266
+	 *
267
+	 * @param  array $columns
268
+	 * @return BelongsToMany
269
+	 */
270
+	protected function getSelectColumns(array $columns = ['*'])
271
+	{
272
+		if ($columns == ['*']) {
273
+			$columns = [$this->relatedMap->getTable() . '.*'];
274
+		}
275
+
276
+		return array_merge($columns, [$this->parentMap->getTable() . '.' . $this->firstKey]);
277
+	}
278
+
279
+	/**
280
+	 * Get a paginator for the "select" statement.
281
+	 *
282
+	 * @param  int   $perPage
283
+	 * @param  array $columns
284
+	 * @return \Illuminate\Pagination\LengthAwarePaginator
285
+	 */
286
+	public function paginate($perPage = null, $columns = ['*'])
287
+	{
288
+		$this->query->addSelect($this->getSelectColumns($columns));
289
+
290
+		return $this->query->paginate($perPage, $columns);
291
+	}
292
+
293
+	/**
294
+	 * Get the key name of the parent model.
295
+	 *
296
+	 * @return string
297
+	 */
298
+	protected function getQualifiedParentKeyName()
299
+	{
300
+		return $this->parentMap->getQualifiedKeyName();
301
+	}
302
+
303
+	/**
304
+	 * Get the key for comparing against the parent key in "has" query.
305
+	 *
306
+	 * @return string
307
+	 */
308
+	public function getHasCompareKey()
309
+	{
310
+		return $this->farParentMap->getQualifiedKeyName();
311
+	}
312
+
313
+	/**
314
+	 * Run synchronization content if needed by the
315
+	 * relation type.
316
+	 *
317
+	 * @param  array $actualContent
318
+	 * @return void
319
+	 */
320
+	public function sync(array $entities)
321
+	{
322
+		// N/A
323
+	}
324 324
 }
Please login to merge, or discard this patch.
src/Relationships/MorphTo.php 1 patch
Indentation   +217 added lines, -217 removed lines patch added patch discarded remove patch
@@ -8,221 +8,221 @@
 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 models 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
-     * Indicate if the parent entity hold the key for the relation.
41
-     *
42
-     * @var boolean
43
-     */
44
-    protected static $ownForeignKey = true;
45
-
46
-    /**
47
-     * Create a new belongs to relationship instance.
48
-     *
49
-     * @param Mapper                 $mapper
50
-     * @param \Analogue\ORM\Mappable $parent
51
-     * @param string                 $foreignKey
52
-     * @param string                 $otherKey
53
-     * @param string                 $type
54
-     * @param string                 $relation
55
-     */
56
-    public function __construct(Mapper $mapper, $parent, $foreignKey, $otherKey, $type, $relation)
57
-    {
58
-        $this->morphType = $type;
59
-
60
-        parent::__construct($mapper, $parent, $foreignKey, $otherKey, $relation);
61
-    }
62
-
63
-    /**
64
-     * Set the constraints for an eager load of the relation.
65
-     *
66
-     * @param  array $entities
67
-     * @return void
68
-     */
69
-    public function addEagerConstraints(array $entities)
70
-    {
71
-        $this->buildDictionary($this->entities = EntityCollection::make($entities));
72
-    }
73
-
74
-    /**
75
-     * Build a dictionary with the entities
76
-     *
77
-     * @param  EntityCollection $entities
78
-     * @return void
79
-     */
80
-    protected function buildDictionary(EntityCollection $entities)
81
-    {
82
-        foreach ($entities as $entity) {
83
-            if ($entity->getEntityAttribute($this->morphType)) {
84
-                $foreign = $this->foreignKey;
85
-                $foreign = $this->relatedMap->mapColumnToAttribute($foreign);
86
-                $this->dictionary[$entity->getEntityAttribute($this->morphType)][$entity->getEntityAttribute($foreign)][] = $entity;
87
-            }
88
-        }
89
-    }
90
-
91
-    /**
92
-     * Match the eagerly loaded results to their parents.
93
-     *
94
-     * @param  array            $entities
95
-     * @param  EntityCollection $results
96
-     * @param  string           $relation
97
-     * @return array
98
-     */
99
-    public function match(array $entities, EntityCollection $results, $relation)
100
-    {
101
-        return $entities;
102
-    }
103
-
104
-    /**
105
-     * Get the results of the relationship.
106
-     *
107
-     * @throws \Analogue\ORM\Exceptions\MappingException
108
-     * @return EntityCollection
109
-     */
110
-    public function getEager()
111
-    {
112
-        foreach (array_keys($this->dictionary) as $type) {
113
-            $this->matchToMorphParents($type, $this->getResultsByType($type));
114
-        }
115
-
116
-        return $this->entities;
117
-    }
118
-
119
-    /**
120
-     * Match the results for a given type to their parents.
121
-     *
122
-     * @param  string           $type
123
-     * @param  EntityCollection $results
124
-     * @return void
125
-     */
126
-    protected function matchToMorphParents($type, EntityCollection $results)
127
-    {
128
-        $mapper = $this->relatedMapper->getManager()->mapper($type);
129
-        $keyName = $mapper->getEntityMap()->getKeyName();
130
-
131
-        foreach ($results as $result) {
132
-            $key = $result->{$keyName};
133
-
134
-            if (isset($this->dictionary[$type][$key])) {
135
-                foreach ($this->dictionary[$type][$key] as $entity) {
136
-                    $entity->setEntityAttribute($this->relation, $result);
137
-                }
138
-            }
139
-        }
140
-    }
141
-
142
-    /**
143
-     * Get all of the relation results for a type.
144
-     *
145
-     * @param  string $type
146
-     * @throws \Analogue\ORM\Exceptions\MappingException
147
-     * @return EntityCollection
148
-     */
149
-    protected function getResultsByType($type)
150
-    {
151
-        $mapper = $this->relatedMapper->getManager()->mapper($type);
152
-
153
-        $key = $mapper->getEntityMap()->getKeyName();
154
-
155
-        $query = $mapper->getQuery();
156
-
157
-        return $query->whereIn($key, $this->gatherKeysByType($type)->all())->get();
158
-    }
159
-
160
-    /**
161
-     * Gather all of the foreign keys for a given type.
162
-     *
163
-     * @param  string $type
164
-     * @return BaseCollection
165
-     */
166
-    protected function gatherKeysByType($type)
167
-    {
168
-        $foreign = $this->foreignKey;
169
-
170
-        return BaseCollection::make($this->dictionary[$type])->map(function ($entities) use ($foreign) {
171
-            return head($entities)->{$foreign};
172
-
173
-        })->unique();
174
-    }
175
-
176
-    /**
177
-     * Associate the model instance to the given parent.
178
-     *
179
-     * @param  mixed $entity
180
-     * @return void
181
-     */
182
-    public function associate($entity)
183
-    {
184
-        // The Mapper will retrieve this association within the object model, we won't be using
185
-        // the foreign key attribute inside the parent Entity.
186
-        //
187
-        //$this->parent->setEntityAttribute($this->foreignKey, $entity->getEntityAttribute($this->otherKey));
188
-        //
189
-        // Instead, we'll just add the object to the Entity's attribute
190
-
191
-        $this->parent->setEntityAttribute($this->relation, $entity->getEntityObject());
192
-    }
193
-
194
-    /**
195
-     * Get the foreign key value pair for a related object
196
-     *
197
-     * @var mixed $related
198
-     *
199
-     * @return array
200
-     */
201
-    public function getForeignKeyValuePair($related)
202
-    {
203
-        $foreignKey = $this->getForeignKey();
204
-
205
-        if ($related) {
206
-            $wrapper = $this->factory->make($related);
207
-
208
-            $relatedKey = $this->relatedMap->getKeyName();
209
-
210
-            return [
211
-                $foreignKey => $wrapper->getEntityAttribute($relatedKey),
212
-                $this->morphType => $wrapper->getMap()->getMorphClass(),
213
-            ];
214
-        } else {
215
-            return [$foreignKey => null];
216
-        }
217
-    }
218
-
219
-    /**
220
-     * Get the dictionary used by the relationship.
221
-     *
222
-     * @return array
223
-     */
224
-    public function getDictionary()
225
-    {
226
-        return $this->dictionary;
227
-    }
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 models 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
+	 * Indicate if the parent entity hold the key for the relation.
41
+	 *
42
+	 * @var boolean
43
+	 */
44
+	protected static $ownForeignKey = true;
45
+
46
+	/**
47
+	 * Create a new belongs to relationship instance.
48
+	 *
49
+	 * @param Mapper                 $mapper
50
+	 * @param \Analogue\ORM\Mappable $parent
51
+	 * @param string                 $foreignKey
52
+	 * @param string                 $otherKey
53
+	 * @param string                 $type
54
+	 * @param string                 $relation
55
+	 */
56
+	public function __construct(Mapper $mapper, $parent, $foreignKey, $otherKey, $type, $relation)
57
+	{
58
+		$this->morphType = $type;
59
+
60
+		parent::__construct($mapper, $parent, $foreignKey, $otherKey, $relation);
61
+	}
62
+
63
+	/**
64
+	 * Set the constraints for an eager load of the relation.
65
+	 *
66
+	 * @param  array $entities
67
+	 * @return void
68
+	 */
69
+	public function addEagerConstraints(array $entities)
70
+	{
71
+		$this->buildDictionary($this->entities = EntityCollection::make($entities));
72
+	}
73
+
74
+	/**
75
+	 * Build a dictionary with the entities
76
+	 *
77
+	 * @param  EntityCollection $entities
78
+	 * @return void
79
+	 */
80
+	protected function buildDictionary(EntityCollection $entities)
81
+	{
82
+		foreach ($entities as $entity) {
83
+			if ($entity->getEntityAttribute($this->morphType)) {
84
+				$foreign = $this->foreignKey;
85
+				$foreign = $this->relatedMap->mapColumnToAttribute($foreign);
86
+				$this->dictionary[$entity->getEntityAttribute($this->morphType)][$entity->getEntityAttribute($foreign)][] = $entity;
87
+			}
88
+		}
89
+	}
90
+
91
+	/**
92
+	 * Match the eagerly loaded results to their parents.
93
+	 *
94
+	 * @param  array            $entities
95
+	 * @param  EntityCollection $results
96
+	 * @param  string           $relation
97
+	 * @return array
98
+	 */
99
+	public function match(array $entities, EntityCollection $results, $relation)
100
+	{
101
+		return $entities;
102
+	}
103
+
104
+	/**
105
+	 * Get the results of the relationship.
106
+	 *
107
+	 * @throws \Analogue\ORM\Exceptions\MappingException
108
+	 * @return EntityCollection
109
+	 */
110
+	public function getEager()
111
+	{
112
+		foreach (array_keys($this->dictionary) as $type) {
113
+			$this->matchToMorphParents($type, $this->getResultsByType($type));
114
+		}
115
+
116
+		return $this->entities;
117
+	}
118
+
119
+	/**
120
+	 * Match the results for a given type to their parents.
121
+	 *
122
+	 * @param  string           $type
123
+	 * @param  EntityCollection $results
124
+	 * @return void
125
+	 */
126
+	protected function matchToMorphParents($type, EntityCollection $results)
127
+	{
128
+		$mapper = $this->relatedMapper->getManager()->mapper($type);
129
+		$keyName = $mapper->getEntityMap()->getKeyName();
130
+
131
+		foreach ($results as $result) {
132
+			$key = $result->{$keyName};
133
+
134
+			if (isset($this->dictionary[$type][$key])) {
135
+				foreach ($this->dictionary[$type][$key] as $entity) {
136
+					$entity->setEntityAttribute($this->relation, $result);
137
+				}
138
+			}
139
+		}
140
+	}
141
+
142
+	/**
143
+	 * Get all of the relation results for a type.
144
+	 *
145
+	 * @param  string $type
146
+	 * @throws \Analogue\ORM\Exceptions\MappingException
147
+	 * @return EntityCollection
148
+	 */
149
+	protected function getResultsByType($type)
150
+	{
151
+		$mapper = $this->relatedMapper->getManager()->mapper($type);
152
+
153
+		$key = $mapper->getEntityMap()->getKeyName();
154
+
155
+		$query = $mapper->getQuery();
156
+
157
+		return $query->whereIn($key, $this->gatherKeysByType($type)->all())->get();
158
+	}
159
+
160
+	/**
161
+	 * Gather all of the foreign keys for a given type.
162
+	 *
163
+	 * @param  string $type
164
+	 * @return BaseCollection
165
+	 */
166
+	protected function gatherKeysByType($type)
167
+	{
168
+		$foreign = $this->foreignKey;
169
+
170
+		return BaseCollection::make($this->dictionary[$type])->map(function ($entities) use ($foreign) {
171
+			return head($entities)->{$foreign};
172
+
173
+		})->unique();
174
+	}
175
+
176
+	/**
177
+	 * Associate the model instance to the given parent.
178
+	 *
179
+	 * @param  mixed $entity
180
+	 * @return void
181
+	 */
182
+	public function associate($entity)
183
+	{
184
+		// The Mapper will retrieve this association within the object model, we won't be using
185
+		// the foreign key attribute inside the parent Entity.
186
+		//
187
+		//$this->parent->setEntityAttribute($this->foreignKey, $entity->getEntityAttribute($this->otherKey));
188
+		//
189
+		// Instead, we'll just add the object to the Entity's attribute
190
+
191
+		$this->parent->setEntityAttribute($this->relation, $entity->getEntityObject());
192
+	}
193
+
194
+	/**
195
+	 * Get the foreign key value pair for a related object
196
+	 *
197
+	 * @var mixed $related
198
+	 *
199
+	 * @return array
200
+	 */
201
+	public function getForeignKeyValuePair($related)
202
+	{
203
+		$foreignKey = $this->getForeignKey();
204
+
205
+		if ($related) {
206
+			$wrapper = $this->factory->make($related);
207
+
208
+			$relatedKey = $this->relatedMap->getKeyName();
209
+
210
+			return [
211
+				$foreignKey => $wrapper->getEntityAttribute($relatedKey),
212
+				$this->morphType => $wrapper->getMap()->getMorphClass(),
213
+			];
214
+		} else {
215
+			return [$foreignKey => null];
216
+		}
217
+	}
218
+
219
+	/**
220
+	 * Get the dictionary used by the relationship.
221
+	 *
222
+	 * @return array
223
+	 */
224
+	public function getDictionary()
225
+	{
226
+		return $this->dictionary;
227
+	}
228 228
 }
Please login to merge, or discard this patch.
src/System/EntityBuilder.php 1 patch
Indentation   +185 added lines, -185 removed lines patch added patch discarded remove patch
@@ -11,196 +11,196 @@
 block discarded – undo
11 11
  */
12 12
 class EntityBuilder
13 13
 {
14
-    /**
15
-     * The mapper for the entity to build
16
-     * @var \Analogue\ORM\System\Mapper
17
-     */
18
-    protected $mapper;
19
-
20
-    /**
21
-     * The Entity Map for the entity to build.
22
-     *
23
-     * @var \Analogue\ORM\EntityMap
24
-     */
25
-    protected $entityMap;
26
-
27
-    /**
28
-     * Relations that will be eager loaded on this query
29
-     *
30
-     * @var array
31
-     */
32
-    protected $eagerLoads;
33
-
34
-    /**
35
-     * Relations that will be lazy loaded on this query
36
-     *
37
-     * @var array
38
-     */
39
-    protected $lazyLoads;
40
-
41
-    /**
42
-     * Entity Wrapper Factory
43
-     * @var \Analogue\ORM\System\Wrappers\Factory
44
-     */
45
-    protected $factory;
46
-
47
-    /**
48
-     * EntityBuilder constructor.
49
-     * @param Mapper $mapper
50
-     * @param array  $eagerLoads
51
-     */
52
-    public function __construct(Mapper $mapper, array $eagerLoads)
53
-    {
54
-        $this->mapper = $mapper;
55
-
56
-        $this->entityMap = $mapper->getEntityMap();
57
-
58
-        $this->eagerLoads = $eagerLoads;
59
-
60
-        $this->lazyLoads = $this->prepareLazyLoading();
61
-
62
-        $this->entityMap = $mapper->getEntityMap();
63
-
64
-        $this->factory = new Factory;
65
-    }
66
-
67
-    /**
68
-     * Convert a result set into an array of entities
69
-     *
70
-     * @param  array $results
71
-     * @return array
72
-     */
73
-    public function build($results)
74
-    {
75
-        $entities = [];
76
-
77
-        //$prototype = $this->getWrapperPrototype();
78
-        //$prototype = $this->mapper->newInstance();
79
-
80
-        $keyName = $this->entityMap->getKeyName();
81
-
82
-        $tmpCache = [];
83
-
84
-        foreach ($results as $result) {
85
-            //$instance = clone $prototype;
86
-            $instance = $this->getWrapperInstance();
87
-
88
-            $resultArray = (array) $result;
89
-
90
-            $tmpCache[$resultArray[$keyName]] = $resultArray;
91
-
92
-            // Hydrate any embedded Value Object
93
-            $this->hydrateValueObjects($resultArray);
94
-
95
-            $resultArray = $this->entityMap->mapColumnsToAttributes($resultArray);
96
-
97
-            $instance->setEntityAttributes($resultArray);
98
-
99
-            // Hydrate relation attributes with lazyloading proxies
100
-            if (count($this->lazyLoads) > 0) {
101
-                $proxies = $this->getLazyLoadingProxies($instance);
102
-                $instance->setEntityAttributes($resultArray + $proxies);
103
-            }
104
-
105
-            // Directly Unwrap the entity now that it has been hydrated
106
-            $entities[] = $instance->getObject();
107
-        }
108
-
109
-        $this->mapper->getEntityCache()->add($tmpCache);
110
-
111
-        return $entities;
112
-    }
113
-
114
-    /**
115
-     * Get the correct wrapper prototype corresponding to the object type
116
-     *
117
-     * @throws \Analogue\ORM\Exceptions\MappingException
118
-     * @return InternallyMappable
119
-     */
120
-    protected function getWrapperInstance()
121
-    {
122
-        return $this->factory->make($this->mapper->newInstance());
123
-    }
124
-
125
-    /**
126
-     * Hydrate value object embedded in this entity
127
-     *
128
-     * @param  array $attributes
129
-     * @throws \Analogue\ORM\Exceptions\MappingException
130
-     * @return void
131
-     */
132
-    protected function hydrateValueObjects(& $attributes)
133
-    {
134
-        foreach ($this->entityMap->getEmbeddables() as $localKey => $valueClass) {
135
-            $this->hydrateValueObject($attributes, $localKey, $valueClass);
136
-        }
137
-    }
138
-
139
-    /**
140
-     * Hydrate a single value object
141
-     *
142
-     * @param  array  $attributes
143
-     * @param  string $localKey
144
-     * @param  string $valueClass
145
-     * @throws \Analogue\ORM\Exceptions\MappingException
146
-     * @return void
147
-     */
148
-    protected function hydrateValueObject(& $attributes, $localKey, $valueClass)
149
-    {
150
-        $map = $this->mapper->getManager()->getValueMap($valueClass);
14
+	/**
15
+	 * The mapper for the entity to build
16
+	 * @var \Analogue\ORM\System\Mapper
17
+	 */
18
+	protected $mapper;
19
+
20
+	/**
21
+	 * The Entity Map for the entity to build.
22
+	 *
23
+	 * @var \Analogue\ORM\EntityMap
24
+	 */
25
+	protected $entityMap;
26
+
27
+	/**
28
+	 * Relations that will be eager loaded on this query
29
+	 *
30
+	 * @var array
31
+	 */
32
+	protected $eagerLoads;
33
+
34
+	/**
35
+	 * Relations that will be lazy loaded on this query
36
+	 *
37
+	 * @var array
38
+	 */
39
+	protected $lazyLoads;
40
+
41
+	/**
42
+	 * Entity Wrapper Factory
43
+	 * @var \Analogue\ORM\System\Wrappers\Factory
44
+	 */
45
+	protected $factory;
46
+
47
+	/**
48
+	 * EntityBuilder constructor.
49
+	 * @param Mapper $mapper
50
+	 * @param array  $eagerLoads
51
+	 */
52
+	public function __construct(Mapper $mapper, array $eagerLoads)
53
+	{
54
+		$this->mapper = $mapper;
55
+
56
+		$this->entityMap = $mapper->getEntityMap();
57
+
58
+		$this->eagerLoads = $eagerLoads;
59
+
60
+		$this->lazyLoads = $this->prepareLazyLoading();
61
+
62
+		$this->entityMap = $mapper->getEntityMap();
63
+
64
+		$this->factory = new Factory;
65
+	}
66
+
67
+	/**
68
+	 * Convert a result set into an array of entities
69
+	 *
70
+	 * @param  array $results
71
+	 * @return array
72
+	 */
73
+	public function build($results)
74
+	{
75
+		$entities = [];
76
+
77
+		//$prototype = $this->getWrapperPrototype();
78
+		//$prototype = $this->mapper->newInstance();
79
+
80
+		$keyName = $this->entityMap->getKeyName();
81
+
82
+		$tmpCache = [];
83
+
84
+		foreach ($results as $result) {
85
+			//$instance = clone $prototype;
86
+			$instance = $this->getWrapperInstance();
87
+
88
+			$resultArray = (array) $result;
89
+
90
+			$tmpCache[$resultArray[$keyName]] = $resultArray;
91
+
92
+			// Hydrate any embedded Value Object
93
+			$this->hydrateValueObjects($resultArray);
94
+
95
+			$resultArray = $this->entityMap->mapColumnsToAttributes($resultArray);
96
+
97
+			$instance->setEntityAttributes($resultArray);
98
+
99
+			// Hydrate relation attributes with lazyloading proxies
100
+			if (count($this->lazyLoads) > 0) {
101
+				$proxies = $this->getLazyLoadingProxies($instance);
102
+				$instance->setEntityAttributes($resultArray + $proxies);
103
+			}
104
+
105
+			// Directly Unwrap the entity now that it has been hydrated
106
+			$entities[] = $instance->getObject();
107
+		}
108
+
109
+		$this->mapper->getEntityCache()->add($tmpCache);
110
+
111
+		return $entities;
112
+	}
113
+
114
+	/**
115
+	 * Get the correct wrapper prototype corresponding to the object type
116
+	 *
117
+	 * @throws \Analogue\ORM\Exceptions\MappingException
118
+	 * @return InternallyMappable
119
+	 */
120
+	protected function getWrapperInstance()
121
+	{
122
+		return $this->factory->make($this->mapper->newInstance());
123
+	}
124
+
125
+	/**
126
+	 * Hydrate value object embedded in this entity
127
+	 *
128
+	 * @param  array $attributes
129
+	 * @throws \Analogue\ORM\Exceptions\MappingException
130
+	 * @return void
131
+	 */
132
+	protected function hydrateValueObjects(& $attributes)
133
+	{
134
+		foreach ($this->entityMap->getEmbeddables() as $localKey => $valueClass) {
135
+			$this->hydrateValueObject($attributes, $localKey, $valueClass);
136
+		}
137
+	}
138
+
139
+	/**
140
+	 * Hydrate a single value object
141
+	 *
142
+	 * @param  array  $attributes
143
+	 * @param  string $localKey
144
+	 * @param  string $valueClass
145
+	 * @throws \Analogue\ORM\Exceptions\MappingException
146
+	 * @return void
147
+	 */
148
+	protected function hydrateValueObject(& $attributes, $localKey, $valueClass)
149
+	{
150
+		$map = $this->mapper->getManager()->getValueMap($valueClass);
151 151
 
152
-        $embeddedAttributes = $map->getAttributes();
152
+		$embeddedAttributes = $map->getAttributes();
153 153
 
154
-        $valueObject = $this->mapper->getManager()->getValueObjectInstance($valueClass);
154
+		$valueObject = $this->mapper->getManager()->getValueObjectInstance($valueClass);
155 155
 
156
-        foreach ($embeddedAttributes as $key) {
157
-            $prefix = snake_case(class_basename($valueClass)) . '_';
158
-
159
-            $voWrapper = $this->factory->make($valueObject);
160
-
161
-            $voWrapper->setEntityAttribute($key, $attributes[$prefix . $key]);
156
+		foreach ($embeddedAttributes as $key) {
157
+			$prefix = snake_case(class_basename($valueClass)) . '_';
158
+
159
+			$voWrapper = $this->factory->make($valueObject);
160
+
161
+			$voWrapper->setEntityAttribute($key, $attributes[$prefix . $key]);
162 162
             
163
-            unset($attributes[$prefix . $key]);
164
-        }
163
+			unset($attributes[$prefix . $key]);
164
+		}
165 165
         
166
-        $attributes[$localKey] = $valueObject;
167
-    }
168
-
169
-    /**
170
-     * Deduce the relationships that will be lazy loaded from the eagerLoads array
171
-     *
172
-     * @return array
173
-     */
174
-    protected function prepareLazyLoading()
175
-    {
176
-        $relations = $this->entityMap->getRelationships();
166
+		$attributes[$localKey] = $valueObject;
167
+	}
168
+
169
+	/**
170
+	 * Deduce the relationships that will be lazy loaded from the eagerLoads array
171
+	 *
172
+	 * @return array
173
+	 */
174
+	protected function prepareLazyLoading()
175
+	{
176
+		$relations = $this->entityMap->getRelationships();
177 177
        
178
-        return array_diff($relations, $this->eagerLoads);
179
-    }
180
-
181
-    /**
182
-     * Build lazy loading proxies for the current entity
183
-     *
184
-     * @param InternallyMappable $entity
185
-     *
186
-     * @return array
187
-     */
188
-    protected function getLazyLoadingProxies(InternallyMappable $entity)
189
-    {
190
-        $proxies = [];
191
-
192
-        $singleRelations = $this->entityMap->getSingleRelationships();
193
-        $manyRelations = $this->entityMap->getManyRelationships();
194
-
195
-        foreach ($this->lazyLoads as $relation) {
196
-            if (in_array($relation, $singleRelations)) {
197
-                $proxies[$relation] = new EntityProxy($entity->getObject(), $relation);
198
-            }
199
-            if (in_array($relation, $manyRelations)) {
200
-                $proxies[$relation] = new CollectionProxy($entity->getObject(), $relation);
201
-            }
202
-        }
178
+		return array_diff($relations, $this->eagerLoads);
179
+	}
180
+
181
+	/**
182
+	 * Build lazy loading proxies for the current entity
183
+	 *
184
+	 * @param InternallyMappable $entity
185
+	 *
186
+	 * @return array
187
+	 */
188
+	protected function getLazyLoadingProxies(InternallyMappable $entity)
189
+	{
190
+		$proxies = [];
191
+
192
+		$singleRelations = $this->entityMap->getSingleRelationships();
193
+		$manyRelations = $this->entityMap->getManyRelationships();
194
+
195
+		foreach ($this->lazyLoads as $relation) {
196
+			if (in_array($relation, $singleRelations)) {
197
+				$proxies[$relation] = new EntityProxy($entity->getObject(), $relation);
198
+			}
199
+			if (in_array($relation, $manyRelations)) {
200
+				$proxies[$relation] = new CollectionProxy($entity->getObject(), $relation);
201
+			}
202
+		}
203 203
         
204
-        return $proxies;
205
-    }
204
+		return $proxies;
205
+	}
206 206
 }
Please login to merge, or discard this patch.
src/System/Wrappers/PlainObjectWrapper.php 1 patch
Indentation   +197 added lines, -197 removed lines patch added patch discarded remove patch
@@ -6,203 +6,203 @@
 block discarded – undo
6 6
 
7 7
 class PlainObjectWrapper extends Wrapper
8 8
 {
9
-    /**
10
-     * The list of attributes for the managed entity
11
-     *
12
-     * @var array
13
-     */
14
-    protected $attributeList;
15
-
16
-    /**
17
-     * The reflection class for the managed entity
18
-     *
19
-     * @var ReflectionClass
20
-     */
21
-    protected $reflection;
22
-
23
-    /**
24
-     * PlainObjectWrapper constructor.
25
-     * @param $popoEntity
26
-     * @param $entityMap
27
-     */
28
-    public function __construct($popoEntity, $entityMap)
29
-    {
30
-        $this->reflection = new ReflectionClass($popoEntity);
31
-
32
-        parent::__construct($popoEntity, $entityMap);
33
-
34
-        $this->attributeList = $this->getAttributeList();
35
-    }
36
-
37
-    /**
38
-     * Get Compiled Attributes (key, attributes, embed, relations)
39
-     *
40
-     * @return array
41
-     */
42
-    protected function getAttributeList()
43
-    {
44
-        return  $this->entityMap->getCompiledAttributes();
45
-    }
46
-
47
-    /**
48
-     * Extract Attributes from a Plain Php Object
49
-     *
50
-     * @return array $attributes
51
-     */
52
-    protected function extract()
53
-    {
54
-        $properties = $this->getMappedProperties();
55
-
56
-        $attributes = [];
57
-
58
-        foreach ($properties as $property) {
59
-            $name = $property->getName();
60
-
61
-            if ($property->isPublic()) {
62
-                $attributes[$name] = $this->entity->$name;
63
-            } else {
64
-                $property->setAccessible(true);
9
+	/**
10
+	 * The list of attributes for the managed entity
11
+	 *
12
+	 * @var array
13
+	 */
14
+	protected $attributeList;
15
+
16
+	/**
17
+	 * The reflection class for the managed entity
18
+	 *
19
+	 * @var ReflectionClass
20
+	 */
21
+	protected $reflection;
22
+
23
+	/**
24
+	 * PlainObjectWrapper constructor.
25
+	 * @param $popoEntity
26
+	 * @param $entityMap
27
+	 */
28
+	public function __construct($popoEntity, $entityMap)
29
+	{
30
+		$this->reflection = new ReflectionClass($popoEntity);
31
+
32
+		parent::__construct($popoEntity, $entityMap);
33
+
34
+		$this->attributeList = $this->getAttributeList();
35
+	}
36
+
37
+	/**
38
+	 * Get Compiled Attributes (key, attributes, embed, relations)
39
+	 *
40
+	 * @return array
41
+	 */
42
+	protected function getAttributeList()
43
+	{
44
+		return  $this->entityMap->getCompiledAttributes();
45
+	}
46
+
47
+	/**
48
+	 * Extract Attributes from a Plain Php Object
49
+	 *
50
+	 * @return array $attributes
51
+	 */
52
+	protected function extract()
53
+	{
54
+		$properties = $this->getMappedProperties();
55
+
56
+		$attributes = [];
57
+
58
+		foreach ($properties as $property) {
59
+			$name = $property->getName();
60
+
61
+			if ($property->isPublic()) {
62
+				$attributes[$name] = $this->entity->$name;
63
+			} else {
64
+				$property->setAccessible(true);
65 65
     
66
-                $attributes[$name] = $property->getValue($this->entity);
67
-            }
68
-        }
69
-
70
-        return $attributes;
71
-    }
72
-
73
-    /**
74
-     * @return \ReflectionProperty[]
75
-     */
76
-    protected function getMappedProperties()
77
-    {
78
-        $objectProperties = $this->reflection->getProperties();
79
-
80
-        $attributeList = $this->getAttributeList();
81
-
82
-        // We need to filter out properties that could belong to the object
83
-        // and which are not intended to be handled by the ORM
84
-        return array_filter($objectProperties, function (\ReflectionProperty $item) use ($attributeList) {
85
-            if (in_array($item->getName(), $attributeList)) {
86
-                return true;
87
-            }
88
-        });
89
-    }
90
-
91
-    /**
92
-     * @param  string $name
93
-     * @return \ReflectionProperty
94
-     */
95
-    protected function getMappedProperty($name)
96
-    {
97
-        $name = $this->entityMap->mapColumnToAttribute($name);
98
-        return $this->reflection->getProperty($name);
99
-    }
100
-
101
-    /**
102
-     * Hydrate Plain PHP Object with wrapped attributes
103
-     *
104
-     * @param  $attributes
105
-     * @return void
106
-     */
107
-    protected function hydrate($attributes)
108
-    {
109
-        $properties = $this->getMappedProperties();
110
-
111
-        foreach ($properties as $property) {
112
-            $name = $property->getName();
113
-
114
-            if ($property->isPublic()) {
115
-                $this->entity->$name = $attributes[$name];
116
-            } else {
117
-                $property->setAccessible(true);
118
-                if (isset($attributes[$name])) {
119
-                    $property->setValue($this->entity, $attributes[$name]);
120
-                }
121
-            }
122
-        }
123
-    }
124
-
125
-    /**
126
-     * Method used by the mapper to set the object
127
-     * attribute raw values (hydration)
128
-     *
129
-     * @param array $attributes
130
-     *
131
-     * @return void
132
-     */
133
-    public function setEntityAttributes(array $attributes)
134
-    {
135
-        $this->hydrate($attributes);
136
-    }
137
-
138
-    /**
139
-     * Method used by the mapper to get the
140
-     * raw object's values.
141
-     *
142
-     * @return array
143
-     */
144
-    public function getEntityAttributes()
145
-    {
146
-        return $this->extract();
147
-    }
148
-
149
-    /**
150
-     * Method used by the mapper to set raw
151
-     * key-value pair
152
-     *
153
-     * @param string $key
154
-     * @param string $value
155
-     *
156
-     * @return void
157
-     */
158
-    public function setEntityAttribute($key, $value)
159
-    {
160
-        $property = $this->getMappedProperty($key);
161
-
162
-        if ($property->isPublic()) {
163
-            $this->entity->$key = $value;
164
-        } else {
165
-            $property->setAccessible(true);
66
+				$attributes[$name] = $property->getValue($this->entity);
67
+			}
68
+		}
69
+
70
+		return $attributes;
71
+	}
72
+
73
+	/**
74
+	 * @return \ReflectionProperty[]
75
+	 */
76
+	protected function getMappedProperties()
77
+	{
78
+		$objectProperties = $this->reflection->getProperties();
79
+
80
+		$attributeList = $this->getAttributeList();
81
+
82
+		// We need to filter out properties that could belong to the object
83
+		// and which are not intended to be handled by the ORM
84
+		return array_filter($objectProperties, function (\ReflectionProperty $item) use ($attributeList) {
85
+			if (in_array($item->getName(), $attributeList)) {
86
+				return true;
87
+			}
88
+		});
89
+	}
90
+
91
+	/**
92
+	 * @param  string $name
93
+	 * @return \ReflectionProperty
94
+	 */
95
+	protected function getMappedProperty($name)
96
+	{
97
+		$name = $this->entityMap->mapColumnToAttribute($name);
98
+		return $this->reflection->getProperty($name);
99
+	}
100
+
101
+	/**
102
+	 * Hydrate Plain PHP Object with wrapped attributes
103
+	 *
104
+	 * @param  $attributes
105
+	 * @return void
106
+	 */
107
+	protected function hydrate($attributes)
108
+	{
109
+		$properties = $this->getMappedProperties();
110
+
111
+		foreach ($properties as $property) {
112
+			$name = $property->getName();
113
+
114
+			if ($property->isPublic()) {
115
+				$this->entity->$name = $attributes[$name];
116
+			} else {
117
+				$property->setAccessible(true);
118
+				if (isset($attributes[$name])) {
119
+					$property->setValue($this->entity, $attributes[$name]);
120
+				}
121
+			}
122
+		}
123
+	}
124
+
125
+	/**
126
+	 * Method used by the mapper to set the object
127
+	 * attribute raw values (hydration)
128
+	 *
129
+	 * @param array $attributes
130
+	 *
131
+	 * @return void
132
+	 */
133
+	public function setEntityAttributes(array $attributes)
134
+	{
135
+		$this->hydrate($attributes);
136
+	}
137
+
138
+	/**
139
+	 * Method used by the mapper to get the
140
+	 * raw object's values.
141
+	 *
142
+	 * @return array
143
+	 */
144
+	public function getEntityAttributes()
145
+	{
146
+		return $this->extract();
147
+	}
148
+
149
+	/**
150
+	 * Method used by the mapper to set raw
151
+	 * key-value pair
152
+	 *
153
+	 * @param string $key
154
+	 * @param string $value
155
+	 *
156
+	 * @return void
157
+	 */
158
+	public function setEntityAttribute($key, $value)
159
+	{
160
+		$property = $this->getMappedProperty($key);
161
+
162
+		if ($property->isPublic()) {
163
+			$this->entity->$key = $value;
164
+		} else {
165
+			$property->setAccessible(true);
166 166
     
167
-            $property->setValue($this->entity, $value);
168
-        }
169
-
170
-        $this->attributes[$key] = $value;
171
-    }
172
-
173
-    /**
174
-     * Method used by the mapper to get single
175
-     * key-value pair
176
-     *
177
-     * @param  string $key
178
-     * @return mixed
179
-     */
180
-    public function getEntityAttribute($key)
181
-    {
182
-        $property = $this->getMappedProperty($key);
183
-
184
-        if ($property->isPublic()) {
185
-            $value = $this->entity->$key;
186
-        } else {
187
-            $property->setAccessible(true);
188
-            $value = $property->getValue($this->entity);
189
-        }
190
-
191
-        return $value;
192
-    }
193
-
194
-        /**
195
-         * Test if a given attribute exists
196
-         *
197
-         * @param  string  $key
198
-         * @return boolean
199
-         */
200
-    public function hasAttribute($key)
201
-    {
202
-        if (array_key_exists($key, $this->attributeList)) {
203
-            return true;
204
-        } else {
205
-            return false;
206
-        }
207
-    }
167
+			$property->setValue($this->entity, $value);
168
+		}
169
+
170
+		$this->attributes[$key] = $value;
171
+	}
172
+
173
+	/**
174
+	 * Method used by the mapper to get single
175
+	 * key-value pair
176
+	 *
177
+	 * @param  string $key
178
+	 * @return mixed
179
+	 */
180
+	public function getEntityAttribute($key)
181
+	{
182
+		$property = $this->getMappedProperty($key);
183
+
184
+		if ($property->isPublic()) {
185
+			$value = $this->entity->$key;
186
+		} else {
187
+			$property->setAccessible(true);
188
+			$value = $property->getValue($this->entity);
189
+		}
190
+
191
+		return $value;
192
+	}
193
+
194
+		/**
195
+		 * Test if a given attribute exists
196
+		 *
197
+		 * @param  string  $key
198
+		 * @return boolean
199
+		 */
200
+	public function hasAttribute($key)
201
+	{
202
+		if (array_key_exists($key, $this->attributeList)) {
203
+			return true;
204
+		} else {
205
+			return false;
206
+		}
207
+	}
208 208
 }
Please login to merge, or discard this patch.