Completed
Branch 5.3 (f8a22c)
by Rémi
08:52
created
src/Relationships/MorphTo.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -163,7 +163,7 @@
 block discarded – undo
163 163
     {
164 164
         $foreign = $this->foreignKey;
165 165
 
166
-        return BaseCollection::make($this->dictionary[$type])->map(function ($entities) use ($foreign) {
166
+        return BaseCollection::make($this->dictionary[$type])->map(function($entities) use ($foreign) {
167 167
             return head($entities)->{$foreign};
168 168
 
169 169
         })->unique();
Please login to merge, or discard this patch.
Indentation   +215 added lines, -215 removed lines patch added patch discarded remove patch
@@ -8,219 +8,219 @@
 block discarded – undo
8 8
 
9 9
 class MorphTo extends BelongsTo
10 10
 {
11
-    /**
12
-     * The type of the polymorphic relation.
13
-     *
14
-     * @var string
15
-     */
16
-    protected $morphType;
17
-
18
-    /**
19
-     * The entities whose relations are being eager loaded.
20
-     *
21
-     * @var EntityCollection
22
-     */
23
-    protected $entities;
24
-
25
-    /**
26
-     * All of the 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
-                $this->dictionary[$entity->getEntityAttribute($this->morphType)][$entity->getEntityAttribute($this->foreignKey)][] = $entity;
85
-            }
86
-        }
87
-    }
88
-
89
-    /**
90
-     * Match the eagerly loaded results to their parents.
91
-     *
92
-     * @param  array            $entities
93
-     * @param  EntityCollection $results
94
-     * @param  string           $relation
95
-     * @return array
96
-     */
97
-    public function match(array $entities, EntityCollection $results, $relation)
98
-    {
99
-        return $entities;
100
-    }
101
-
102
-    /**
103
-     * Get the results of the relationship.
104
-     *
105
-     * @throws \Analogue\ORM\Exceptions\MappingException
106
-     * @return EntityCollection
107
-     */
108
-    public function getEager()
109
-    {
110
-        foreach (array_keys($this->dictionary) as $type) {
111
-            $this->matchToMorphParents($type, $this->getResultsByType($type));
112
-        }
113
-
114
-        return $this->entities;
115
-    }
116
-
117
-    /**
118
-     * Match the results for a given type to their parents.
119
-     *
120
-     * @param  string           $type
121
-     * @param  EntityCollection $results
122
-     * @return void
123
-     */
124
-    protected function matchToMorphParents($type, EntityCollection $results)
125
-    {
126
-        $mapper = $this->relatedMapper->getManager()->mapper($type);
127
-        $keyName = $mapper->getEntityMap()->getKeyName();
128
-
129
-        foreach ($results as $result) {
130
-            $key = $result->{$keyName};
131
-
132
-            if (isset($this->dictionary[$type][$key])) {
133
-                foreach ($this->dictionary[$type][$key] as $entity) {
134
-                    $entity->setEntityAttribute($this->relation, $result);
135
-                }
136
-            }
137
-        }
138
-    }
139
-
140
-    /**
141
-     * Get all of the relation results for a type.
142
-     *
143
-     * @param  string $type
144
-     * @throws \Analogue\ORM\Exceptions\MappingException
145
-     * @return EntityCollection
146
-     */
147
-    protected function getResultsByType($type)
148
-    {
149
-        $mapper = $this->relatedMapper->getManager()->mapper($type);
150
-
151
-        $key = $mapper->getEntityMap()->getKeyName();
152
-
153
-        $query = $mapper->getQuery();
154
-
155
-        return $query->whereIn($key, $this->gatherKeysByType($type)->all())->get();
156
-    }
157
-
158
-    /**
159
-     * Gather all of the foreign keys for a given type.
160
-     *
161
-     * @param  string $type
162
-     * @return BaseCollection
163
-     */
164
-    protected function gatherKeysByType($type)
165
-    {
166
-        $foreign = $this->foreignKey;
167
-
168
-        return BaseCollection::make($this->dictionary[$type])->map(function ($entities) use ($foreign) {
169
-            return head($entities)->{$foreign};
170
-
171
-        })->unique();
172
-    }
173
-
174
-    /**
175
-     * Associate the model instance to the given parent.
176
-     *
177
-     * @param  mixed $entity
178
-     * @return void
179
-     */
180
-    public function associate($entity)
181
-    {
182
-        // The Mapper will retrieve this association within the object model, we won't be using
183
-        // the foreign key attribute inside the parent Entity.
184
-        //
185
-        //$this->parent->setEntityAttribute($this->foreignKey, $entity->getEntityAttribute($this->otherKey));
186
-        //
187
-        // Instead, we'll just add the object to the Entity's attribute
188
-
189
-        $this->parent->setEntityAttribute($this->relation, $entity->getEntityObject());
190
-    }
191
-
192
-    /**
193
-     * Get the foreign key value pair for a related object
194
-     *
195
-     * @var mixed $related
196
-     *
197
-     * @return array
198
-     */
199
-    public function getForeignKeyValuePair($related)
200
-    {
201
-        $foreignKey = $this->getForeignKey();
202
-
203
-        if ($related) {
204
-            $wrapper = $this->factory->make($related);
205
-
206
-            $relatedKey = $this->relatedMap->getKeyName();
207
-
208
-            return [
209
-                $foreignKey => $wrapper->getEntityAttribute($relatedKey),
210
-                $this->morphType => $wrapper->getMap()->getMorphClass(),
211
-            ];
212
-        } else {
213
-            return [$foreignKey => null];
214
-        }
215
-    }
216
-
217
-    /**
218
-     * Get the dictionary used by the relationship.
219
-     *
220
-     * @return array
221
-     */
222
-    public function getDictionary()
223
-    {
224
-        return $this->dictionary;
225
-    }
11
+	/**
12
+	 * The type of the polymorphic relation.
13
+	 *
14
+	 * @var string
15
+	 */
16
+	protected $morphType;
17
+
18
+	/**
19
+	 * The entities whose relations are being eager loaded.
20
+	 *
21
+	 * @var EntityCollection
22
+	 */
23
+	protected $entities;
24
+
25
+	/**
26
+	 * All of the 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
+				$this->dictionary[$entity->getEntityAttribute($this->morphType)][$entity->getEntityAttribute($this->foreignKey)][] = $entity;
85
+			}
86
+		}
87
+	}
88
+
89
+	/**
90
+	 * Match the eagerly loaded results to their parents.
91
+	 *
92
+	 * @param  array            $entities
93
+	 * @param  EntityCollection $results
94
+	 * @param  string           $relation
95
+	 * @return array
96
+	 */
97
+	public function match(array $entities, EntityCollection $results, $relation)
98
+	{
99
+		return $entities;
100
+	}
101
+
102
+	/**
103
+	 * Get the results of the relationship.
104
+	 *
105
+	 * @throws \Analogue\ORM\Exceptions\MappingException
106
+	 * @return EntityCollection
107
+	 */
108
+	public function getEager()
109
+	{
110
+		foreach (array_keys($this->dictionary) as $type) {
111
+			$this->matchToMorphParents($type, $this->getResultsByType($type));
112
+		}
113
+
114
+		return $this->entities;
115
+	}
116
+
117
+	/**
118
+	 * Match the results for a given type to their parents.
119
+	 *
120
+	 * @param  string           $type
121
+	 * @param  EntityCollection $results
122
+	 * @return void
123
+	 */
124
+	protected function matchToMorphParents($type, EntityCollection $results)
125
+	{
126
+		$mapper = $this->relatedMapper->getManager()->mapper($type);
127
+		$keyName = $mapper->getEntityMap()->getKeyName();
128
+
129
+		foreach ($results as $result) {
130
+			$key = $result->{$keyName};
131
+
132
+			if (isset($this->dictionary[$type][$key])) {
133
+				foreach ($this->dictionary[$type][$key] as $entity) {
134
+					$entity->setEntityAttribute($this->relation, $result);
135
+				}
136
+			}
137
+		}
138
+	}
139
+
140
+	/**
141
+	 * Get all of the relation results for a type.
142
+	 *
143
+	 * @param  string $type
144
+	 * @throws \Analogue\ORM\Exceptions\MappingException
145
+	 * @return EntityCollection
146
+	 */
147
+	protected function getResultsByType($type)
148
+	{
149
+		$mapper = $this->relatedMapper->getManager()->mapper($type);
150
+
151
+		$key = $mapper->getEntityMap()->getKeyName();
152
+
153
+		$query = $mapper->getQuery();
154
+
155
+		return $query->whereIn($key, $this->gatherKeysByType($type)->all())->get();
156
+	}
157
+
158
+	/**
159
+	 * Gather all of the foreign keys for a given type.
160
+	 *
161
+	 * @param  string $type
162
+	 * @return BaseCollection
163
+	 */
164
+	protected function gatherKeysByType($type)
165
+	{
166
+		$foreign = $this->foreignKey;
167
+
168
+		return BaseCollection::make($this->dictionary[$type])->map(function ($entities) use ($foreign) {
169
+			return head($entities)->{$foreign};
170
+
171
+		})->unique();
172
+	}
173
+
174
+	/**
175
+	 * Associate the model instance to the given parent.
176
+	 *
177
+	 * @param  mixed $entity
178
+	 * @return void
179
+	 */
180
+	public function associate($entity)
181
+	{
182
+		// The Mapper will retrieve this association within the object model, we won't be using
183
+		// the foreign key attribute inside the parent Entity.
184
+		//
185
+		//$this->parent->setEntityAttribute($this->foreignKey, $entity->getEntityAttribute($this->otherKey));
186
+		//
187
+		// Instead, we'll just add the object to the Entity's attribute
188
+
189
+		$this->parent->setEntityAttribute($this->relation, $entity->getEntityObject());
190
+	}
191
+
192
+	/**
193
+	 * Get the foreign key value pair for a related object
194
+	 *
195
+	 * @var mixed $related
196
+	 *
197
+	 * @return array
198
+	 */
199
+	public function getForeignKeyValuePair($related)
200
+	{
201
+		$foreignKey = $this->getForeignKey();
202
+
203
+		if ($related) {
204
+			$wrapper = $this->factory->make($related);
205
+
206
+			$relatedKey = $this->relatedMap->getKeyName();
207
+
208
+			return [
209
+				$foreignKey => $wrapper->getEntityAttribute($relatedKey),
210
+				$this->morphType => $wrapper->getMap()->getMorphClass(),
211
+			];
212
+		} else {
213
+			return [$foreignKey => null];
214
+		}
215
+	}
216
+
217
+	/**
218
+	 * Get the dictionary used by the relationship.
219
+	 *
220
+	 * @return array
221
+	 */
222
+	public function getDictionary()
223
+	{
224
+		return $this->dictionary;
225
+	}
226 226
 }
Please login to merge, or discard this patch.
src/System/InternallyMappable.php 1 patch
Indentation   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -3,38 +3,38 @@
 block discarded – undo
3 3
 interface InternallyMappable
4 4
 {
5 5
 
6
-    /**
7
-     * Set the object attribute raw values (hydration)
8
-     *
9
-     * @param array $attributes
10
-     */
11
-    public function setEntityAttributes(array $attributes);
6
+	/**
7
+	 * Set the object attribute raw values (hydration)
8
+	 *
9
+	 * @param array $attributes
10
+	 */
11
+	public function setEntityAttributes(array $attributes);
12 12
 
13
-    /**
14
-     * Get the raw object's values.
15
-     *
16
-     * @return array
17
-     */
18
-    public function getEntityAttributes();
13
+	/**
14
+	 * Get the raw object's values.
15
+	 *
16
+	 * @return array
17
+	 */
18
+	public function getEntityAttributes();
19 19
 
20
-    /**
21
-     * Set the raw entity attributes
22
-     * @param string $key
23
-     * @param string $value
24
-     */
25
-    public function setEntityAttribute($key, $value);
20
+	/**
21
+	 * Set the raw entity attributes
22
+	 * @param string $key
23
+	 * @param string $value
24
+	 */
25
+	public function setEntityAttribute($key, $value);
26 26
 
27
-    /**
28
-     * Return the entity's attribute
29
-     * @param  string $key
30
-     * @return mixed
31
-     */
32
-    public function getEntityAttribute($key);
27
+	/**
28
+	 * Return the entity's attribute
29
+	 * @param  string $key
30
+	 * @return mixed
31
+	 */
32
+	public function getEntityAttribute($key);
33 33
 
34
-    /**
35
-     * Does the entity posses the given attribute
36
-     * @param  string  $key
37
-     * @return boolean
38
-     */
39
-    public function hasAttribute($key);
34
+	/**
35
+	 * Does the entity posses the given attribute
36
+	 * @param  string  $key
37
+	 * @return boolean
38
+	 */
39
+	public function hasAttribute($key);
40 40
 }
Please login to merge, or discard this patch.
src/AnalogueFacade.php 1 patch
Indentation   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -8,13 +8,13 @@
 block discarded – undo
8 8
 class AnalogueFacade extends Facade
9 9
 {
10 10
 
11
-    /**
12
-     * Get the registered name of the component.
13
-     *
14
-     * @return string
15
-     */
16
-    protected static function getFacadeAccessor()
17
-    {
18
-        return 'analogue';
19
-    }
11
+	/**
12
+	 * Get the registered name of the component.
13
+	 *
14
+	 * @return string
15
+	 */
16
+	protected static function getFacadeAccessor()
17
+	{
18
+		return 'analogue';
19
+	}
20 20
 }
Please login to merge, or discard this patch.
src/Plugins/SoftDeletes/SoftDeletingScope.php 3 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -73,7 +73,7 @@  discard block
 block discarded – undo
73 73
      */
74 74
     protected function addWithTrashed(Query $query)
75 75
     {
76
-        $query->macro('withTrashed', function (Query $query) {
76
+        $query->macro('withTrashed', function(Query $query) {
77 77
             $this->remove($query);
78 78
 
79 79
             return $query;
@@ -88,7 +88,7 @@  discard block
 block discarded – undo
88 88
      */
89 89
     protected function addOnlyTrashed(Query $query)
90 90
     {
91
-        $query->macro('onlyTrashed', function (Query $query) {
91
+        $query->macro('onlyTrashed', function(Query $query) {
92 92
             $this->remove($query);
93 93
 
94 94
             $query->getQuery()->whereNotNull($query->getMapper()->getEntityMap()->getQualifiedDeletedAtColumn());
Please login to merge, or discard this patch.
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -32,7 +32,7 @@
 block discarded – undo
32 32
     /**
33 33
      * Remove the scope from the given Analogue query builder.
34 34
      *
35
-     * @param  mixed $query
35
+     * @param  Query $query
36 36
      * @return void
37 37
      */
38 38
     public function remove(Query $query)
Please login to merge, or discard this patch.
Indentation   +102 added lines, -102 removed lines patch added patch discarded remove patch
@@ -7,106 +7,106 @@
 block discarded – undo
7 7
 
8 8
 class SoftDeletingScope implements ScopeInterface
9 9
 {
10
-    /**
11
-     * All of the extensions to be added to the builder.
12
-     *
13
-     * @var array
14
-     */
15
-    protected $extensions = ['WithTrashed', 'OnlyTrashed'];
16
-
17
-    /**
18
-     * Apply the scope to a given Analogue query builder.
19
-     *
20
-     * @param  \Analogue\ORM\System\Query $query
21
-     * @return void
22
-     */
23
-    public function apply(Query $query)
24
-    {
25
-        $entityMap = $query->getMapper()->getEntityMap();
26
-
27
-        $query->whereNull($entityMap->getQualifiedDeletedAtColumn());
28
-
29
-        $this->extend($query);
30
-    }
31
-
32
-    /**
33
-     * Remove the scope from the given Analogue query builder.
34
-     *
35
-     * @param  mixed $query
36
-     * @return void
37
-     */
38
-    public function remove(Query $query)
39
-    {
40
-        $column = $query->getMapper()->getEntityMap()->getQualifiedDeletedAtColumn();
41
-
42
-        $query = $query->getQuery();
43
-
44
-        foreach ((array) $query->wheres as $key => $where) {
45
-            // If the where clause is a soft delete date constraint, we will remove it from
46
-            // the query and reset the keys on the wheres. This allows this developer to
47
-            // include deleted model in a relationship result set that is lazy loaded.
48
-            if ($this->isSoftDeleteConstraint($where, $column)) {
49
-                unset($query->wheres[$key]);
50
-
51
-                $query->wheres = array_values($query->wheres);
52
-            }
53
-        }
54
-    }
55
-
56
-    /**
57
-     * Extend the query builder with the needed functions.
58
-     *
59
-     * @param  \Analogue\ORM\System\Query $query
60
-     * @return void
61
-     */
62
-    public function extend(Query $query)
63
-    {
64
-        foreach ($this->extensions as $extension) {
65
-            $this->{"add{$extension}"}($query);
66
-        }
67
-    }
68
-
69
-    /**
70
-     * Add the with-trashed extension to the builder.
71
-     *
72
-     * @param  \Analogue\ORM\System\Query $query
73
-     * @return void
74
-     */
75
-    protected function addWithTrashed(Query $query)
76
-    {
77
-        $query->macro('withTrashed', function (Query $query) {
78
-            $this->remove($query);
79
-
80
-            return $query;
81
-        });
82
-    }
83
-
84
-    /**
85
-     * Add the only-trashed extension to the builder.
86
-     *
87
-     * @param  \Analogue\ORM\System\Query $query
88
-     * @return void
89
-     */
90
-    protected function addOnlyTrashed(Query $query)
91
-    {
92
-        $query->macro('onlyTrashed', function (Query $query) {
93
-            $this->remove($query);
94
-
95
-            $query->getQuery()->whereNotNull($query->getMapper()->getEntityMap()->getQualifiedDeletedAtColumn());
96
-
97
-            return $query;
98
-        });
99
-    }
100
-
101
-    /**
102
-     * Determine if the given where clause is a soft delete constraint.
103
-     *
104
-     * @param  array  $where
105
-     * @param  string $column
106
-     * @return bool
107
-     */
108
-    protected function isSoftDeleteConstraint(array $where, $column)
109
-    {
110
-        return $where['type'] == 'Null' && $where['column'] == $column;
111
-    }
10
+	/**
11
+	 * All of the extensions to be added to the builder.
12
+	 *
13
+	 * @var array
14
+	 */
15
+	protected $extensions = ['WithTrashed', 'OnlyTrashed'];
16
+
17
+	/**
18
+	 * Apply the scope to a given Analogue query builder.
19
+	 *
20
+	 * @param  \Analogue\ORM\System\Query $query
21
+	 * @return void
22
+	 */
23
+	public function apply(Query $query)
24
+	{
25
+		$entityMap = $query->getMapper()->getEntityMap();
26
+
27
+		$query->whereNull($entityMap->getQualifiedDeletedAtColumn());
28
+
29
+		$this->extend($query);
30
+	}
31
+
32
+	/**
33
+	 * Remove the scope from the given Analogue query builder.
34
+	 *
35
+	 * @param  mixed $query
36
+	 * @return void
37
+	 */
38
+	public function remove(Query $query)
39
+	{
40
+		$column = $query->getMapper()->getEntityMap()->getQualifiedDeletedAtColumn();
41
+
42
+		$query = $query->getQuery();
43
+
44
+		foreach ((array) $query->wheres as $key => $where) {
45
+			// If the where clause is a soft delete date constraint, we will remove it from
46
+			// the query and reset the keys on the wheres. This allows this developer to
47
+			// include deleted model in a relationship result set that is lazy loaded.
48
+			if ($this->isSoftDeleteConstraint($where, $column)) {
49
+				unset($query->wheres[$key]);
50
+
51
+				$query->wheres = array_values($query->wheres);
52
+			}
53
+		}
54
+	}
55
+
56
+	/**
57
+	 * Extend the query builder with the needed functions.
58
+	 *
59
+	 * @param  \Analogue\ORM\System\Query $query
60
+	 * @return void
61
+	 */
62
+	public function extend(Query $query)
63
+	{
64
+		foreach ($this->extensions as $extension) {
65
+			$this->{"add{$extension}"}($query);
66
+		}
67
+	}
68
+
69
+	/**
70
+	 * Add the with-trashed extension to the builder.
71
+	 *
72
+	 * @param  \Analogue\ORM\System\Query $query
73
+	 * @return void
74
+	 */
75
+	protected function addWithTrashed(Query $query)
76
+	{
77
+		$query->macro('withTrashed', function (Query $query) {
78
+			$this->remove($query);
79
+
80
+			return $query;
81
+		});
82
+	}
83
+
84
+	/**
85
+	 * Add the only-trashed extension to the builder.
86
+	 *
87
+	 * @param  \Analogue\ORM\System\Query $query
88
+	 * @return void
89
+	 */
90
+	protected function addOnlyTrashed(Query $query)
91
+	{
92
+		$query->macro('onlyTrashed', function (Query $query) {
93
+			$this->remove($query);
94
+
95
+			$query->getQuery()->whereNotNull($query->getMapper()->getEntityMap()->getQualifiedDeletedAtColumn());
96
+
97
+			return $query;
98
+		});
99
+	}
100
+
101
+	/**
102
+	 * Determine if the given where clause is a soft delete constraint.
103
+	 *
104
+	 * @param  array  $where
105
+	 * @param  string $column
106
+	 * @return bool
107
+	 */
108
+	protected function isSoftDeleteConstraint(array $where, $column)
109
+	{
110
+		return $where['type'] == 'Null' && $where['column'] == $column;
111
+	}
112 112
 }
Please login to merge, or discard this patch.
src/Plugins/AnaloguePluginInterface.php 1 patch
Indentation   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -3,17 +3,17 @@
 block discarded – undo
3 3
 interface AnaloguePluginInterface
4 4
 {
5 5
 
6
-    /**
7
-     * Boot the plugin
8
-     *
9
-     * @return void
10
-     */
11
-    public function register();
6
+	/**
7
+	 * Boot the plugin
8
+	 *
9
+	 * @return void
10
+	 */
11
+	public function register();
12 12
 
13
-    /**
14
-     * Get custom events provided by the plugin
15
-     *
16
-     * @return array
17
-     */
18
-    public function getCustomEvents();
13
+	/**
14
+	 * Get custom events provided by the plugin
15
+	 *
16
+	 * @return array
17
+	 */
18
+	public function getCustomEvents();
19 19
 }
Please login to merge, or discard this patch.
src/Relationships/BelongsToMany.php 3 patches
Doc Comments   +1 added lines patch added patch discarded remove patch
@@ -383,6 +383,7 @@
 block discarded – undo
383 383
      * Set the join clause for the relation query.
384 384
      *
385 385
      * @param  \Analogue\ORM\Query|null
386
+     * @param Query $query
386 387
      * @return $this
387 388
      */
388 389
     protected function setJoin($query = null)
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
      */
146 146
     public function wherePivot($column, $operator = null, $value = null, $boolean = 'and')
147 147
     {
148
-        return $this->where($this->table . '.' . $column, $operator, $value, $boolean);
148
+        return $this->where($this->table.'.'.$column, $operator, $value, $boolean);
149 149
     }
150 150
 
151 151
     /**
@@ -326,11 +326,11 @@  discard block
 block discarded – undo
326 326
 
327 327
         $tablePrefix = $this->query->getQuery()->getConnection()->getTablePrefix();
328 328
 
329
-        $query->from($this->table . ' as ' . $tablePrefix . $hash = $this->getRelationCountHash());
329
+        $query->from($this->table.' as '.$tablePrefix.$hash = $this->getRelationCountHash());
330 330
 
331 331
         $key = $this->wrap($this->getQualifiedParentKeyName());
332 332
 
333
-        return $query->where($hash . '.' . $this->foreignKey, '=', new Expression($key));
333
+        return $query->where($hash.'.'.$this->foreignKey, '=', new Expression($key));
334 334
     }
335 335
 
336 336
     /**
@@ -340,7 +340,7 @@  discard block
 block discarded – undo
340 340
      */
341 341
     public function getRelationCountHash()
342 342
     {
343
-        return 'self_' . md5(microtime(true));
343
+        return 'self_'.md5(microtime(true));
344 344
     }
345 345
 
346 346
     /**
@@ -352,7 +352,7 @@  discard block
 block discarded – undo
352 352
     protected function getSelectColumns(array $columns = ['*'])
353 353
     {
354 354
         if ($columns == ['*']) {
355
-            $columns = [$this->relatedMap->getTable() . '.*'];
355
+            $columns = [$this->relatedMap->getTable().'.*'];
356 356
         }
357 357
 
358 358
         return array_merge($columns, $this->getAliasedPivotColumns());
@@ -373,7 +373,7 @@  discard block
 block discarded – undo
373 373
         $columns = [];
374 374
 
375 375
         foreach (array_merge($defaults, $this->pivotColumns) as $column) {
376
-            $columns[] = $this->table . '.' . $column . ' as pivot_' . $column;
376
+            $columns[] = $this->table.'.'.$column.' as pivot_'.$column;
377 377
         }
378 378
 
379 379
         return array_unique($columns);
@@ -394,7 +394,7 @@  discard block
 block discarded – undo
394 394
         // model instance. Then we can set the "where" for the parent models.
395 395
         $baseTable = $this->relatedMap->getTable();
396 396
 
397
-        $key = $baseTable . '.' . $this->relatedMap->getKeyName();
397
+        $key = $baseTable.'.'.$this->relatedMap->getKeyName();
398 398
 
399 399
         $query->join($this->table, $key, '=', $this->getOtherKey());
400 400
 
@@ -752,7 +752,7 @@  discard block
 block discarded – undo
752 752
     {
753 753
         $keyName = $this->relatedMap->getKeyName();
754 754
 
755
-        return array_map(function ($m) use ($keyName) {
755
+        return array_map(function($m) use ($keyName) {
756 756
             return $m->$keyName;
757 757
         }, $entities);
758 758
     }
@@ -902,7 +902,7 @@  discard block
 block discarded – undo
902 902
      */
903 903
     public function getForeignKey()
904 904
     {
905
-        return $this->table . '.' . $this->foreignKey;
905
+        return $this->table.'.'.$this->foreignKey;
906 906
     }
907 907
 
908 908
     /**
@@ -912,7 +912,7 @@  discard block
 block discarded – undo
912 912
      */
913 913
     public function getOtherKey()
914 914
     {
915
-        return $this->table . '.' . $this->otherKey;
915
+        return $this->table.'.'.$this->otherKey;
916 916
     }
917 917
 
918 918
     /**
Please login to merge, or discard this patch.
Indentation   +908 added lines, -908 removed lines patch added patch discarded remove patch
@@ -12,917 +12,917 @@
 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
-     */
80
-    public function detachMany($related)
81
-    {
82
-        $ids = $this->getIdsFromHashes($related);
83
-
84
-        $this->detach($ids);
85
-    }
86
-
87
-    /**
88
-     * @param array $hashes
89
-     * @return array
90
-     */
91
-    protected function getIdsFromHashes(array $hashes)
92
-    {
93
-        $ids = [];
94
-
95
-        foreach ($hashes as $hash) {
96
-            $split = explode('.', $hash);
97
-            $ids[] = $split[1];
98
-        }
99
-        return $ids;
100
-    }
101
-
102
-    /**
103
-     * Get the results of the relationship.
104
-     *
105
-     * @param $relation
106
-     *
107
-     * @return EntityCollection
108
-     */
109
-    public function getResults($relation)
110
-    {
111
-        $results = $this->get();
112
-
113
-        $this->cacheRelation($results, $relation);
114
-
115
-        return $results;
116
-    }
117
-
118
-    /**
119
-     * Set a where clause for a pivot table column.
120
-     *
121
-     * @param  string $column
122
-     * @param  string $operator
123
-     * @param  mixed  $value
124
-     * @param  string $boolean
125
-     * @return self
126
-     */
127
-    public function wherePivot($column, $operator = null, $value = null, $boolean = 'and')
128
-    {
129
-        return $this->where($this->table . '.' . $column, $operator, $value, $boolean);
130
-    }
131
-
132
-    /**
133
-     * Set an or where clause for a pivot table column.
134
-     *
135
-     * @param  string $column
136
-     * @param  string $operator
137
-     * @param  mixed  $value
138
-     * @return self
139
-     */
140
-    public function orWherePivot($column, $operator = null, $value = null)
141
-    {
142
-        return $this->wherePivot($column, $operator, $value, 'or');
143
-    }
144
-
145
-    /**
146
-     * Return Pivot attributes when available on a relationship
147
-     *
148
-     * @return array
149
-     */
150
-    public function getPivotAttributes()
151
-    {
152
-        return $this->pivotColumns;
153
-    }
154
-
155
-    /**
156
-     * Execute the query and get the first result.
157
-     *
158
-     * @param  array $columns
159
-     * @return mixed
160
-     */
161
-    public function first($columns = ['*'])
162
-    {
163
-        $results = $this->take(1)->get($columns);
164
-
165
-        return count($results) > 0 ? $results->first() : null;
166
-    }
167
-
168
-    /**
169
-     * Execute the query and get the first result or throw an exception.
170
-     *
171
-     * @param  array $columns
172
-     *
173
-     * @throws EntityNotFoundException
174
-     *
175
-     * @return Mappable|self
176
-     */
177
-    public function firstOrFail($columns = ['*'])
178
-    {
179
-        if (!is_null($entity = $this->first($columns))) {
180
-            return $entity;
181
-        }
182
-
183
-        throw new EntityNotFoundException;
184
-    }
185
-
186
-    /**
187
-     * Execute the query as a "select" statement.
188
-     *
189
-     * @param  array $columns
190
-     * @return \Analogue\ORM\EntityCollection
191
-     */
192
-    public function get($columns = ['*'])
193
-    {
194
-        // First we'll add the proper select columns onto the query so it is run with
195
-        // the proper columns. Then, we will get the results and hydrate out pivot
196
-        // models with the result of those columns as a separate model relation.
197
-        $columns = $this->query->getQuery()->columns ? [] : $columns;
198
-
199
-        $select = $this->getSelectColumns($columns);
200
-
201
-        $entities = $this->query->addSelect($select)->getEntities();
202
-
203
-        $this->hydratePivotRelation($entities);
204
-
205
-        // If we actually found models we will also eager load any relationships that
206
-        // have been specified as needing to be eager loaded. This will solve the
207
-        // n + 1 query problem for the developer and also increase performance.
208
-        if (count($entities) > 0) {
209
-            $entities = $this->query->eagerLoadRelations($entities);
210
-        }
211
-
212
-        return $this->relatedMap->newCollection($entities);
213
-    }
214
-
215
-    /**
216
-     * Hydrate the pivot table relationship on the models.
217
-     *
218
-     * @param  array $entities
219
-     * @return void
220
-     */
221
-    protected function hydratePivotRelation(array $entities)
222
-    {
223
-        // To hydrate the pivot relationship, we will just gather the pivot attributes
224
-        // and create a new Pivot model, which is basically a dynamic model that we
225
-        // will set the attributes, table, and connections on so it they be used.
226
-
227
-        foreach ($entities as $entity) {
228
-            $entityWrapper = $this->factory->make($entity);
229
-
230
-            $pivot = $this->newExistingPivot($this->cleanPivotAttributes($entityWrapper));
231
-
232
-            $entityWrapper->setEntityAttribute('pivot', $pivot);
233
-        }
234
-    }
235
-
236
-    /**
237
-     * Get the pivot attributes from a model.
238
-     *
239
-     * @param  $entity
240
-     * @return array
241
-     */
242
-    protected function cleanPivotAttributes(InternallyMappable $entity)
243
-    {
244
-        $values = [];
245
-
246
-        $attributes = $entity->getEntityAttributes();
247
-
248
-        foreach ($attributes as $key => $value) {
249
-            // To get the pivots attributes we will just take any of the attributes which
250
-            // begin with "pivot_" and add those to this arrays, as well as unsetting
251
-            // them from the parent's models since they exist in a different table.
252
-            if (strpos($key, 'pivot_') === 0) {
253
-                $values[substr($key, 6)] = $value;
254
-
255
-                unset($attributes[$key]);
256
-            }
257
-        }
258
-
259
-        // Rehydrate Entity with cleaned array.
260
-        $entity->setEntityAttributes($attributes);
261
-
262
-        return $values;
263
-    }
264
-
265
-    /**
266
-     * Set the base constraints on the relation query.
267
-     *
268
-     * @return void
269
-     */
270
-    public function addConstraints()
271
-    {
272
-        $this->setJoin();
273
-
274
-        if (static::$constraints) {
275
-            $this->setWhere();
276
-        }
277
-    }
278
-
279
-    /**
280
-     * Add the constraints for a relationship count query.
281
-     *
282
-     * @param  Query $query
283
-     * @param  Query $parent
284
-     * @return Query
285
-     */
286
-    public function getRelationCountQuery(Query $query, Query $parent)
287
-    {
288
-        if ($parent->getQuery()->from == $query->getQuery()->from) {
289
-            return $this->getRelationCountQueryForSelfJoin($query, $parent);
290
-        }
291
-
292
-        $this->setJoin($query);
293
-
294
-        return parent::getRelationCountQuery($query, $parent);
295
-    }
296
-
297
-    /**
298
-     * Add the constraints for a relationship count query on the same table.
299
-     *
300
-     * @param  Query $query
301
-     * @param  Query $parent
302
-     * @return Query
303
-     */
304
-    public function getRelationCountQueryForSelfJoin(Query $query, Query $parent)
305
-    {
306
-        $query->select(new Expression('count(*)'));
307
-
308
-        $tablePrefix = $this->query->getQuery()->getConnection()->getTablePrefix();
309
-
310
-        $query->from($this->table . ' as ' . $tablePrefix . $hash = $this->getRelationCountHash());
311
-
312
-        $key = $this->wrap($this->getQualifiedParentKeyName());
313
-
314
-        return $query->where($hash . '.' . $this->foreignKey, '=', new Expression($key));
315
-    }
316
-
317
-    /**
318
-     * Get a relationship join table hash.
319
-     *
320
-     * @return string
321
-     */
322
-    public function getRelationCountHash()
323
-    {
324
-        return 'self_' . md5(microtime(true));
325
-    }
326
-
327
-    /**
328
-     * Set the select clause for the relation query.
329
-     *
330
-     * @param  array $columns
331
-     * @return \Analogue\ORM\Relationships\BelongsToMany
332
-     */
333
-    protected function getSelectColumns(array $columns = ['*'])
334
-    {
335
-        if ($columns == ['*']) {
336
-            $columns = [$this->relatedMap->getTable() . '.*'];
337
-        }
338
-
339
-        return array_merge($columns, $this->getAliasedPivotColumns());
340
-    }
341
-
342
-    /**
343
-     * Get the pivot columns for the relation.
344
-     *
345
-     * @return array
346
-     */
347
-    protected function getAliasedPivotColumns()
348
-    {
349
-        $defaults = [$this->foreignKey, $this->otherKey];
350
-
351
-        // We need to alias all of the pivot columns with the "pivot_" prefix so we
352
-        // can easily extract them out of the models and put them into the pivot
353
-        // relationships when they are retrieved and hydrated into the models.
354
-        $columns = [];
355
-
356
-        foreach (array_merge($defaults, $this->pivotColumns) as $column) {
357
-            $columns[] = $this->table . '.' . $column . ' as pivot_' . $column;
358
-        }
359
-
360
-        return array_unique($columns);
361
-    }
362
-
363
-    /**
364
-     * Set the join clause for the relation query.
365
-     *
366
-     * @param  \Analogue\ORM\Query|null
367
-     * @return $this
368
-     */
369
-    protected function setJoin($query = null)
370
-    {
371
-        $query = $query ?: $this->query;
372
-
373
-        // We need to join to the intermediate table on the related model's primary
374
-        // key column with the intermediate table's foreign key for the related
375
-        // model instance. Then we can set the "where" for the parent models.
376
-        $baseTable = $this->relatedMap->getTable();
377
-
378
-        $key = $baseTable . '.' . $this->relatedMap->getKeyName();
379
-
380
-        $query->join($this->table, $key, '=', $this->getOtherKey());
381
-
382
-        return $this;
383
-    }
384
-
385
-    /**
386
-     * Set the where clause for the relation query.
387
-     *
388
-     * @return $this
389
-     */
390
-    protected function setWhere()
391
-    {
392
-        $foreign = $this->getForeignKey();
393
-
394
-        $parentKey = $this->parentMap->getKeyName();
395
-
396
-        $this->query->where($foreign, '=', $this->parent->getEntityAttribute($parentKey));
397
-
398
-        return $this;
399
-    }
400
-
401
-    /**
402
-     * Set the constraints for an eager load of the relation.
403
-     *
404
-     * @param  array $entities
405
-     * @return void
406
-     */
407
-    public function addEagerConstraints(array $entities)
408
-    {
409
-        $this->query->whereIn($this->getForeignKey(), $this->getKeys($entities));
410
-    }
411
-
412
-    /**
413
-     * Initialize the relation on a set of eneities.
414
-     *
415
-     * @param  array  $entities
416
-     * @param  string $relation
417
-     * @return array
418
-     */
419
-    public function initRelation(array $entities, $relation)
420
-    {
421
-        foreach ($entities as $entity) {
422
-            $entity = $this->factory->make($entity);
423
-
424
-            $entity->setEntityAttribute($relation, $this->relatedMap->newCollection());
425
-        }
426
-
427
-        return $entities;
428
-    }
429
-
430
-    /**
431
-     * Match the eagerly loaded results to their parents.
432
-     *
433
-     * @param  array            $entities
434
-     * @param  EntityCollection $results
435
-     * @param  string           $relation
436
-     * @return array
437
-     */
438
-    public function match(array $entities, EntityCollection $results, $relation)
439
-    {
440
-        $dictionary = $this->buildDictionary($results);
441
-
442
-        $keyName = $this->relatedMap->getKeyName();
443
-
444
-        $cache = $this->parentMapper->getEntityCache();
445
-
446
-        // Once we have an array dictionary of child objects we can easily match the
447
-        // children back to their parent using the dictionary and the keys on the
448
-        // the parent models. Then we will return the hydrated models back out.
449
-        foreach ($entities as $entity) {
450
-            $wrapper = $this->factory->make($entity);
451
-
452
-            if (isset($dictionary[$key = $wrapper->getEntityAttribute($keyName)])) {
453
-                $collection = $this->relatedMap->newCollection($dictionary[$key]);
454
-
455
-                $wrapper->setEntityAttribute($relation, $collection);
456
-
457
-                $cache->cacheLoadedRelationResult($entity, $relation, $collection, $this);
458
-            }
459
-        }
460
-
461
-        return $entities;
462
-    }
463
-
464
-    /**
465
-     * Build model dictionary keyed by the relation's foreign key.
466
-     *
467
-     * @param  EntityCollection $results
468
-     * @return array
469
-     */
470
-    protected function buildDictionary(EntityCollection $results)
471
-    {
472
-        $foreign = $this->foreignKey;
473
-
474
-        // First we will build a dictionary of child models keyed by the foreign key
475
-        // of the relation so that we will easily and quickly match them to their
476
-        // parents without having a possibly slow inner loops for every models.
477
-        $dictionary = [];
478
-
479
-        foreach ($results as $entity) {
480
-            $wrapper = $this->factory->make($entity);
481
-
482
-            $dictionary[$wrapper->getEntityAttribute('pivot')->$foreign][] = $entity;
483
-        }
484
-
485
-        return $dictionary;
486
-    }
487
-
488
-    /**
489
-     * Get all of the IDs for the related models.
490
-     *
491
-     * @return array
492
-     */
493
-    public function getRelatedIds()
494
-    {
495
-        $fullKey = $this->relatedMap->getQualifiedKeyName();
496
-
497
-        return $this->getQuery()->select($fullKey)->lists($this->relatedMap->getKeyName());
498
-    }
499
-
500
-    /**
501
-     * Update Pivot
502
-     *
503
-     * @param  \Analogue\ORM\Entity $entity
504
-     * @return void
505
-     */
506
-    public function updatePivot($entity)
507
-    {
508
-        $keyName = $this->relatedMap->getKeyName();
509
-
510
-        $this->updateExistingPivot(
511
-            $entity->getEntityAttribute($keyName),
512
-            $entity->getEntityAttribute('pivot')->getEntityAttributes()
513
-        );
514
-    }
515
-
516
-    /**
517
-     * Update Multiple pivot
518
-     *
519
-     * @param  $relatedEntities
520
-     * @return void
521
-     */
522
-    public function updatePivots($relatedEntities)
523
-    {
524
-        foreach ($relatedEntities as $entity) {
525
-            $this->updatePivot($entity);
526
-        }
527
-    }
528
-
529
-    /**
530
-     * Create Pivot Records
531
-     *
532
-     * @param \Analogue\ORM\Entity[] $relatedEntities
533
-     * @return void
534
-     */
535
-    public function createPivots($relatedEntities)
536
-    {
537
-        $keys = [];
538
-        $attributes = [];
539
-
540
-        $keyName = $this->relatedMap->getKeyName();
541
-
542
-        foreach ($relatedEntities as $entity) {
543
-            $keys[] = $entity->getEntityAttribute($keyName);
544
-        }
545
-
546
-        $records = $this->createAttachRecords($keys, $attributes);
547
-
548
-        $this->query->getQuery()->from($this->table)->insert($records);
549
-    }
550
-
551
-    /**
552
-     * Update an existing pivot record on the table.
553
-     *
554
-     * @param  mixed $id
555
-     * @param  array $attributes
556
-     * @throws \InvalidArgumentException
557
-     * @return integer
558
-     */
559
-    public function updateExistingPivot($id, array $attributes)
560
-    {
561
-        if (in_array($this->updatedAt(), $this->pivotColumns)) {
562
-            $attributes = $this->setTimestampsOnAttach($attributes, true);
563
-        }
564
-
565
-        return $this->newPivotStatementForId($id)->update($attributes);
566
-    }
567
-
568
-    /**
569
-     * Attach a model to the parent.
570
-     *
571
-     * @param  mixed $id
572
-     * @param  array $attributes
573
-     * @return void
574
-     */
575
-    public function attach($id, array $attributes = [])
576
-    {
577
-        $query = $this->newPivotStatement();
578
-
579
-        $query->insert($this->createAttachRecords((array) $id, $attributes));
580
-    }
581
-
582
-    /**
583
-     * @param  array $entities
584
-     *
585
-     * @throws \InvalidArgumentException
586
-     */
587
-    public function sync(array $entities)
588
-    {
589
-        $this->detachExcept($entities);
590
-    }
591
-
592
-    /**
593
-     * Detach related entities that are not in $id
594
-     *
595
-     * @param  array $entities
596
-     *
597
-     * @throws \InvalidArgumentException
598
-     *
599
-     * @return void
600
-     */
601
-    protected function detachExcept(array $entities = [])
602
-    {
603
-        $query = $this->newPivotQuery();
604
-
605
-        if (count($entities) > 0) {
606
-            $keys = $this->getKeys($entities);
607
-
608
-            $query->whereNotIn($this->otherKey, $keys);
609
-        }
610
-        $parentKey = $this->parentMap->getKeyName();
611
-
612
-        $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
+	 */
80
+	public function detachMany($related)
81
+	{
82
+		$ids = $this->getIdsFromHashes($related);
83
+
84
+		$this->detach($ids);
85
+	}
86
+
87
+	/**
88
+	 * @param array $hashes
89
+	 * @return array
90
+	 */
91
+	protected function getIdsFromHashes(array $hashes)
92
+	{
93
+		$ids = [];
94
+
95
+		foreach ($hashes as $hash) {
96
+			$split = explode('.', $hash);
97
+			$ids[] = $split[1];
98
+		}
99
+		return $ids;
100
+	}
101
+
102
+	/**
103
+	 * Get the results of the relationship.
104
+	 *
105
+	 * @param $relation
106
+	 *
107
+	 * @return EntityCollection
108
+	 */
109
+	public function getResults($relation)
110
+	{
111
+		$results = $this->get();
112
+
113
+		$this->cacheRelation($results, $relation);
114
+
115
+		return $results;
116
+	}
117
+
118
+	/**
119
+	 * Set a where clause for a pivot table column.
120
+	 *
121
+	 * @param  string $column
122
+	 * @param  string $operator
123
+	 * @param  mixed  $value
124
+	 * @param  string $boolean
125
+	 * @return self
126
+	 */
127
+	public function wherePivot($column, $operator = null, $value = null, $boolean = 'and')
128
+	{
129
+		return $this->where($this->table . '.' . $column, $operator, $value, $boolean);
130
+	}
131
+
132
+	/**
133
+	 * Set an or where clause for a pivot table column.
134
+	 *
135
+	 * @param  string $column
136
+	 * @param  string $operator
137
+	 * @param  mixed  $value
138
+	 * @return self
139
+	 */
140
+	public function orWherePivot($column, $operator = null, $value = null)
141
+	{
142
+		return $this->wherePivot($column, $operator, $value, 'or');
143
+	}
144
+
145
+	/**
146
+	 * Return Pivot attributes when available on a relationship
147
+	 *
148
+	 * @return array
149
+	 */
150
+	public function getPivotAttributes()
151
+	{
152
+		return $this->pivotColumns;
153
+	}
154
+
155
+	/**
156
+	 * Execute the query and get the first result.
157
+	 *
158
+	 * @param  array $columns
159
+	 * @return mixed
160
+	 */
161
+	public function first($columns = ['*'])
162
+	{
163
+		$results = $this->take(1)->get($columns);
164
+
165
+		return count($results) > 0 ? $results->first() : null;
166
+	}
167
+
168
+	/**
169
+	 * Execute the query and get the first result or throw an exception.
170
+	 *
171
+	 * @param  array $columns
172
+	 *
173
+	 * @throws EntityNotFoundException
174
+	 *
175
+	 * @return Mappable|self
176
+	 */
177
+	public function firstOrFail($columns = ['*'])
178
+	{
179
+		if (!is_null($entity = $this->first($columns))) {
180
+			return $entity;
181
+		}
182
+
183
+		throw new EntityNotFoundException;
184
+	}
185
+
186
+	/**
187
+	 * Execute the query as a "select" statement.
188
+	 *
189
+	 * @param  array $columns
190
+	 * @return \Analogue\ORM\EntityCollection
191
+	 */
192
+	public function get($columns = ['*'])
193
+	{
194
+		// First we'll add the proper select columns onto the query so it is run with
195
+		// the proper columns. Then, we will get the results and hydrate out pivot
196
+		// models with the result of those columns as a separate model relation.
197
+		$columns = $this->query->getQuery()->columns ? [] : $columns;
198
+
199
+		$select = $this->getSelectColumns($columns);
200
+
201
+		$entities = $this->query->addSelect($select)->getEntities();
202
+
203
+		$this->hydratePivotRelation($entities);
204
+
205
+		// If we actually found models we will also eager load any relationships that
206
+		// have been specified as needing to be eager loaded. This will solve the
207
+		// n + 1 query problem for the developer and also increase performance.
208
+		if (count($entities) > 0) {
209
+			$entities = $this->query->eagerLoadRelations($entities);
210
+		}
211
+
212
+		return $this->relatedMap->newCollection($entities);
213
+	}
214
+
215
+	/**
216
+	 * Hydrate the pivot table relationship on the models.
217
+	 *
218
+	 * @param  array $entities
219
+	 * @return void
220
+	 */
221
+	protected function hydratePivotRelation(array $entities)
222
+	{
223
+		// To hydrate the pivot relationship, we will just gather the pivot attributes
224
+		// and create a new Pivot model, which is basically a dynamic model that we
225
+		// will set the attributes, table, and connections on so it they be used.
226
+
227
+		foreach ($entities as $entity) {
228
+			$entityWrapper = $this->factory->make($entity);
229
+
230
+			$pivot = $this->newExistingPivot($this->cleanPivotAttributes($entityWrapper));
231
+
232
+			$entityWrapper->setEntityAttribute('pivot', $pivot);
233
+		}
234
+	}
235
+
236
+	/**
237
+	 * Get the pivot attributes from a model.
238
+	 *
239
+	 * @param  $entity
240
+	 * @return array
241
+	 */
242
+	protected function cleanPivotAttributes(InternallyMappable $entity)
243
+	{
244
+		$values = [];
245
+
246
+		$attributes = $entity->getEntityAttributes();
247
+
248
+		foreach ($attributes as $key => $value) {
249
+			// To get the pivots attributes we will just take any of the attributes which
250
+			// begin with "pivot_" and add those to this arrays, as well as unsetting
251
+			// them from the parent's models since they exist in a different table.
252
+			if (strpos($key, 'pivot_') === 0) {
253
+				$values[substr($key, 6)] = $value;
254
+
255
+				unset($attributes[$key]);
256
+			}
257
+		}
258
+
259
+		// Rehydrate Entity with cleaned array.
260
+		$entity->setEntityAttributes($attributes);
261
+
262
+		return $values;
263
+	}
264
+
265
+	/**
266
+	 * Set the base constraints on the relation query.
267
+	 *
268
+	 * @return void
269
+	 */
270
+	public function addConstraints()
271
+	{
272
+		$this->setJoin();
273
+
274
+		if (static::$constraints) {
275
+			$this->setWhere();
276
+		}
277
+	}
278
+
279
+	/**
280
+	 * Add the constraints for a relationship count query.
281
+	 *
282
+	 * @param  Query $query
283
+	 * @param  Query $parent
284
+	 * @return Query
285
+	 */
286
+	public function getRelationCountQuery(Query $query, Query $parent)
287
+	{
288
+		if ($parent->getQuery()->from == $query->getQuery()->from) {
289
+			return $this->getRelationCountQueryForSelfJoin($query, $parent);
290
+		}
291
+
292
+		$this->setJoin($query);
293
+
294
+		return parent::getRelationCountQuery($query, $parent);
295
+	}
296
+
297
+	/**
298
+	 * Add the constraints for a relationship count query on the same table.
299
+	 *
300
+	 * @param  Query $query
301
+	 * @param  Query $parent
302
+	 * @return Query
303
+	 */
304
+	public function getRelationCountQueryForSelfJoin(Query $query, Query $parent)
305
+	{
306
+		$query->select(new Expression('count(*)'));
307
+
308
+		$tablePrefix = $this->query->getQuery()->getConnection()->getTablePrefix();
309
+
310
+		$query->from($this->table . ' as ' . $tablePrefix . $hash = $this->getRelationCountHash());
311
+
312
+		$key = $this->wrap($this->getQualifiedParentKeyName());
313
+
314
+		return $query->where($hash . '.' . $this->foreignKey, '=', new Expression($key));
315
+	}
316
+
317
+	/**
318
+	 * Get a relationship join table hash.
319
+	 *
320
+	 * @return string
321
+	 */
322
+	public function getRelationCountHash()
323
+	{
324
+		return 'self_' . md5(microtime(true));
325
+	}
326
+
327
+	/**
328
+	 * Set the select clause for the relation query.
329
+	 *
330
+	 * @param  array $columns
331
+	 * @return \Analogue\ORM\Relationships\BelongsToMany
332
+	 */
333
+	protected function getSelectColumns(array $columns = ['*'])
334
+	{
335
+		if ($columns == ['*']) {
336
+			$columns = [$this->relatedMap->getTable() . '.*'];
337
+		}
338
+
339
+		return array_merge($columns, $this->getAliasedPivotColumns());
340
+	}
341
+
342
+	/**
343
+	 * Get the pivot columns for the relation.
344
+	 *
345
+	 * @return array
346
+	 */
347
+	protected function getAliasedPivotColumns()
348
+	{
349
+		$defaults = [$this->foreignKey, $this->otherKey];
350
+
351
+		// We need to alias all of the pivot columns with the "pivot_" prefix so we
352
+		// can easily extract them out of the models and put them into the pivot
353
+		// relationships when they are retrieved and hydrated into the models.
354
+		$columns = [];
355
+
356
+		foreach (array_merge($defaults, $this->pivotColumns) as $column) {
357
+			$columns[] = $this->table . '.' . $column . ' as pivot_' . $column;
358
+		}
359
+
360
+		return array_unique($columns);
361
+	}
362
+
363
+	/**
364
+	 * Set the join clause for the relation query.
365
+	 *
366
+	 * @param  \Analogue\ORM\Query|null
367
+	 * @return $this
368
+	 */
369
+	protected function setJoin($query = null)
370
+	{
371
+		$query = $query ?: $this->query;
372
+
373
+		// We need to join to the intermediate table on the related model's primary
374
+		// key column with the intermediate table's foreign key for the related
375
+		// model instance. Then we can set the "where" for the parent models.
376
+		$baseTable = $this->relatedMap->getTable();
377
+
378
+		$key = $baseTable . '.' . $this->relatedMap->getKeyName();
379
+
380
+		$query->join($this->table, $key, '=', $this->getOtherKey());
381
+
382
+		return $this;
383
+	}
384
+
385
+	/**
386
+	 * Set the where clause for the relation query.
387
+	 *
388
+	 * @return $this
389
+	 */
390
+	protected function setWhere()
391
+	{
392
+		$foreign = $this->getForeignKey();
393
+
394
+		$parentKey = $this->parentMap->getKeyName();
395
+
396
+		$this->query->where($foreign, '=', $this->parent->getEntityAttribute($parentKey));
397
+
398
+		return $this;
399
+	}
400
+
401
+	/**
402
+	 * Set the constraints for an eager load of the relation.
403
+	 *
404
+	 * @param  array $entities
405
+	 * @return void
406
+	 */
407
+	public function addEagerConstraints(array $entities)
408
+	{
409
+		$this->query->whereIn($this->getForeignKey(), $this->getKeys($entities));
410
+	}
411
+
412
+	/**
413
+	 * Initialize the relation on a set of eneities.
414
+	 *
415
+	 * @param  array  $entities
416
+	 * @param  string $relation
417
+	 * @return array
418
+	 */
419
+	public function initRelation(array $entities, $relation)
420
+	{
421
+		foreach ($entities as $entity) {
422
+			$entity = $this->factory->make($entity);
423
+
424
+			$entity->setEntityAttribute($relation, $this->relatedMap->newCollection());
425
+		}
426
+
427
+		return $entities;
428
+	}
429
+
430
+	/**
431
+	 * Match the eagerly loaded results to their parents.
432
+	 *
433
+	 * @param  array            $entities
434
+	 * @param  EntityCollection $results
435
+	 * @param  string           $relation
436
+	 * @return array
437
+	 */
438
+	public function match(array $entities, EntityCollection $results, $relation)
439
+	{
440
+		$dictionary = $this->buildDictionary($results);
441
+
442
+		$keyName = $this->relatedMap->getKeyName();
443
+
444
+		$cache = $this->parentMapper->getEntityCache();
445
+
446
+		// Once we have an array dictionary of child objects we can easily match the
447
+		// children back to their parent using the dictionary and the keys on the
448
+		// the parent models. Then we will return the hydrated models back out.
449
+		foreach ($entities as $entity) {
450
+			$wrapper = $this->factory->make($entity);
451
+
452
+			if (isset($dictionary[$key = $wrapper->getEntityAttribute($keyName)])) {
453
+				$collection = $this->relatedMap->newCollection($dictionary[$key]);
454
+
455
+				$wrapper->setEntityAttribute($relation, $collection);
456
+
457
+				$cache->cacheLoadedRelationResult($entity, $relation, $collection, $this);
458
+			}
459
+		}
460
+
461
+		return $entities;
462
+	}
463
+
464
+	/**
465
+	 * Build model dictionary keyed by the relation's foreign key.
466
+	 *
467
+	 * @param  EntityCollection $results
468
+	 * @return array
469
+	 */
470
+	protected function buildDictionary(EntityCollection $results)
471
+	{
472
+		$foreign = $this->foreignKey;
473
+
474
+		// First we will build a dictionary of child models keyed by the foreign key
475
+		// of the relation so that we will easily and quickly match them to their
476
+		// parents without having a possibly slow inner loops for every models.
477
+		$dictionary = [];
478
+
479
+		foreach ($results as $entity) {
480
+			$wrapper = $this->factory->make($entity);
481
+
482
+			$dictionary[$wrapper->getEntityAttribute('pivot')->$foreign][] = $entity;
483
+		}
484
+
485
+		return $dictionary;
486
+	}
487
+
488
+	/**
489
+	 * Get all of the IDs for the related models.
490
+	 *
491
+	 * @return array
492
+	 */
493
+	public function getRelatedIds()
494
+	{
495
+		$fullKey = $this->relatedMap->getQualifiedKeyName();
496
+
497
+		return $this->getQuery()->select($fullKey)->lists($this->relatedMap->getKeyName());
498
+	}
499
+
500
+	/**
501
+	 * Update Pivot
502
+	 *
503
+	 * @param  \Analogue\ORM\Entity $entity
504
+	 * @return void
505
+	 */
506
+	public function updatePivot($entity)
507
+	{
508
+		$keyName = $this->relatedMap->getKeyName();
509
+
510
+		$this->updateExistingPivot(
511
+			$entity->getEntityAttribute($keyName),
512
+			$entity->getEntityAttribute('pivot')->getEntityAttributes()
513
+		);
514
+	}
515
+
516
+	/**
517
+	 * Update Multiple pivot
518
+	 *
519
+	 * @param  $relatedEntities
520
+	 * @return void
521
+	 */
522
+	public function updatePivots($relatedEntities)
523
+	{
524
+		foreach ($relatedEntities as $entity) {
525
+			$this->updatePivot($entity);
526
+		}
527
+	}
528
+
529
+	/**
530
+	 * Create Pivot Records
531
+	 *
532
+	 * @param \Analogue\ORM\Entity[] $relatedEntities
533
+	 * @return void
534
+	 */
535
+	public function createPivots($relatedEntities)
536
+	{
537
+		$keys = [];
538
+		$attributes = [];
539
+
540
+		$keyName = $this->relatedMap->getKeyName();
541
+
542
+		foreach ($relatedEntities as $entity) {
543
+			$keys[] = $entity->getEntityAttribute($keyName);
544
+		}
545
+
546
+		$records = $this->createAttachRecords($keys, $attributes);
547
+
548
+		$this->query->getQuery()->from($this->table)->insert($records);
549
+	}
550
+
551
+	/**
552
+	 * Update an existing pivot record on the table.
553
+	 *
554
+	 * @param  mixed $id
555
+	 * @param  array $attributes
556
+	 * @throws \InvalidArgumentException
557
+	 * @return integer
558
+	 */
559
+	public function updateExistingPivot($id, array $attributes)
560
+	{
561
+		if (in_array($this->updatedAt(), $this->pivotColumns)) {
562
+			$attributes = $this->setTimestampsOnAttach($attributes, true);
563
+		}
564
+
565
+		return $this->newPivotStatementForId($id)->update($attributes);
566
+	}
567
+
568
+	/**
569
+	 * Attach a model to the parent.
570
+	 *
571
+	 * @param  mixed $id
572
+	 * @param  array $attributes
573
+	 * @return void
574
+	 */
575
+	public function attach($id, array $attributes = [])
576
+	{
577
+		$query = $this->newPivotStatement();
578
+
579
+		$query->insert($this->createAttachRecords((array) $id, $attributes));
580
+	}
581
+
582
+	/**
583
+	 * @param  array $entities
584
+	 *
585
+	 * @throws \InvalidArgumentException
586
+	 */
587
+	public function sync(array $entities)
588
+	{
589
+		$this->detachExcept($entities);
590
+	}
591
+
592
+	/**
593
+	 * Detach related entities that are not in $id
594
+	 *
595
+	 * @param  array $entities
596
+	 *
597
+	 * @throws \InvalidArgumentException
598
+	 *
599
+	 * @return void
600
+	 */
601
+	protected function detachExcept(array $entities = [])
602
+	{
603
+		$query = $this->newPivotQuery();
604
+
605
+		if (count($entities) > 0) {
606
+			$keys = $this->getKeys($entities);
607
+
608
+			$query->whereNotIn($this->otherKey, $keys);
609
+		}
610
+		$parentKey = $this->parentMap->getKeyName();
611
+
612
+		$query->where($this->foreignKey, '=', $this->parent->getEntityAttribute($parentKey));
613 613
         
614
-        $query->delete();
615
-
616
-        $query = $this->newPivotQuery();
617
-    }
618
-
619
-
620
-    /**
621
-     * Create an array of records to insert into the pivot table.
622
-     *
623
-     * @param  array $ids
624
-     * @param  array $attributes
625
-     * @return array
626
-     */
627
-    protected function createAttachRecords($ids, array $attributes)
628
-    {
629
-        $records = [];
630
-
631
-        $timed = in_array($this->createdAt(), $this->pivotColumns);
632
-
633
-        // To create the attachment records, we will simply spin through the IDs given
634
-        // and create a new record to insert for each ID. Each ID may actually be a
635
-        // key in the array, with extra attributes to be placed in other columns.
636
-        foreach ($ids as $key => $value) {
637
-            $records[] = $this->attacher($key, $value, $attributes, $timed);
638
-        }
614
+		$query->delete();
615
+
616
+		$query = $this->newPivotQuery();
617
+	}
618
+
619
+
620
+	/**
621
+	 * Create an array of records to insert into the pivot table.
622
+	 *
623
+	 * @param  array $ids
624
+	 * @param  array $attributes
625
+	 * @return array
626
+	 */
627
+	protected function createAttachRecords($ids, array $attributes)
628
+	{
629
+		$records = [];
630
+
631
+		$timed = in_array($this->createdAt(), $this->pivotColumns);
632
+
633
+		// To create the attachment records, we will simply spin through the IDs given
634
+		// and create a new record to insert for each ID. Each ID may actually be a
635
+		// key in the array, with extra attributes to be placed in other columns.
636
+		foreach ($ids as $key => $value) {
637
+			$records[] = $this->attacher($key, $value, $attributes, $timed);
638
+		}
639 639
         
640
-        return $records;
641
-    }
642
-
643
-    /**
644
-     * Create a full attachment record payload.
645
-     *
646
-     * @param  int   $key
647
-     * @param  mixed $value
648
-     * @param  array $attributes
649
-     * @param  bool  $timed
650
-     * @return array
651
-     */
652
-    protected function attacher($key, $value, $attributes, $timed)
653
-    {
654
-        list($id, $extra) = $this->getAttachId($key, $value, $attributes);
640
+		return $records;
641
+	}
642
+
643
+	/**
644
+	 * Create a full attachment record payload.
645
+	 *
646
+	 * @param  int   $key
647
+	 * @param  mixed $value
648
+	 * @param  array $attributes
649
+	 * @param  bool  $timed
650
+	 * @return array
651
+	 */
652
+	protected function attacher($key, $value, $attributes, $timed)
653
+	{
654
+		list($id, $extra) = $this->getAttachId($key, $value, $attributes);
655 655
         
656
-        // To create the attachment records, we will simply spin through the IDs given
657
-        // and create a new record to insert for each ID. Each ID may actually be a
658
-        // key in the array, with extra attributes to be placed in other columns.
659
-        $record = $this->createAttachRecord($id, $timed);
660
-
661
-        return array_merge($record, $extra);
662
-    }
663
-
664
-    /**
665
-     * Get the attach record ID and extra attributes.
666
-     *
667
-     * @param  int   $key
668
-     * @param  mixed $value
669
-     * @param  array $attributes
670
-     * @return array
671
-     */
672
-    protected function getAttachId($key, $value, array $attributes)
673
-    {
674
-        if (is_array($value)) {
675
-            return [$key, array_merge($value, $attributes)];
676
-        }
677
-
678
-        return [$value, $attributes];
679
-    }
680
-
681
-    /**
682
-     * Create a new pivot attachment record.
683
-     *
684
-     * @param  int  $id
685
-     * @param  bool $timed
686
-     * @return array
687
-     */
688
-    protected function createAttachRecord($id, $timed)
689
-    {
690
-        $parentKey = $this->parentMap->getKeyName();
691
-
692
-        $record = [];
693
-
694
-        $record[$this->foreignKey] = $this->parent->getEntityAttribute($parentKey);
695
-
696
-        $record[$this->otherKey] = $id;
697
-
698
-        // If the record needs to have creation and update timestamps, we will make
699
-        // them by calling the parent model's "freshTimestamp" method which will
700
-        // provide us with a fresh timestamp in this model's preferred format.
701
-        if ($timed) {
702
-            $record = $this->setTimestampsOnAttach($record);
703
-        }
704
-
705
-        return $record;
706
-    }
707
-
708
-    /**
709
-     * Set the creation and update timestamps on an attach record.
710
-     *
711
-     * @param  array $record
712
-     * @param  bool  $exists
713
-     * @return array
714
-     */
715
-    protected function setTimestampsOnAttach(array $record, $exists = false)
716
-    {
717
-        $fresh = $this->freshTimestamp();
718
-
719
-        if (!$exists) {
720
-            $record[$this->createdAt()] = $fresh;
721
-        }
722
-
723
-        $record[$this->updatedAt()] = $fresh;
724
-
725
-        return $record;
726
-    }
727
-
728
-    /**
729
-     * @param EntityCollection $entities
730
-     * @return array
731
-     */
732
-    protected function getModelKeysFromCollection(EntityCollection $entities)
733
-    {
734
-        $keyName = $this->relatedMap->getKeyName();
735
-
736
-        return array_map(function ($m) use ($keyName) {
737
-            return $m->$keyName;
738
-        }, $entities);
739
-    }
740
-
741
-    /**
742
-     * Detach models from the relationship.
743
-     *
744
-     * @param  int|array $ids
745
-     * @throws \InvalidArgumentException
746
-     * @return int
747
-     */
748
-    public function detach($ids = [])
749
-    {
750
-        if ($ids instanceof EntityCollection) {
751
-            $ids = (array) $ids->modelKeys();
752
-        }
753
-
754
-        $query = $this->newPivotQuery();
755
-
756
-        // If associated IDs were passed to the method we will only delete those
757
-        // associations, otherwise all of the association ties will be broken.
758
-        // We'll return the numbers of affected rows when we do the deletes.
759
-        $ids = (array) $ids;
760
-
761
-        if (count($ids) > 0) {
762
-            $query->whereIn($this->otherKey, (array) $ids);
763
-        }
764
-
765
-        // Once we have all of the conditions set on the statement, we are ready
766
-        // to run the delete on the pivot table. Then, if the touch parameter
767
-        // is true, we will go ahead and touch all related models to sync.
768
-        return $query->delete();
769
-    }
656
+		// To create the attachment records, we will simply spin through the IDs given
657
+		// and create a new record to insert for each ID. Each ID may actually be a
658
+		// key in the array, with extra attributes to be placed in other columns.
659
+		$record = $this->createAttachRecord($id, $timed);
660
+
661
+		return array_merge($record, $extra);
662
+	}
663
+
664
+	/**
665
+	 * Get the attach record ID and extra attributes.
666
+	 *
667
+	 * @param  int   $key
668
+	 * @param  mixed $value
669
+	 * @param  array $attributes
670
+	 * @return array
671
+	 */
672
+	protected function getAttachId($key, $value, array $attributes)
673
+	{
674
+		if (is_array($value)) {
675
+			return [$key, array_merge($value, $attributes)];
676
+		}
677
+
678
+		return [$value, $attributes];
679
+	}
680
+
681
+	/**
682
+	 * Create a new pivot attachment record.
683
+	 *
684
+	 * @param  int  $id
685
+	 * @param  bool $timed
686
+	 * @return array
687
+	 */
688
+	protected function createAttachRecord($id, $timed)
689
+	{
690
+		$parentKey = $this->parentMap->getKeyName();
691
+
692
+		$record = [];
693
+
694
+		$record[$this->foreignKey] = $this->parent->getEntityAttribute($parentKey);
695
+
696
+		$record[$this->otherKey] = $id;
697
+
698
+		// If the record needs to have creation and update timestamps, we will make
699
+		// them by calling the parent model's "freshTimestamp" method which will
700
+		// provide us with a fresh timestamp in this model's preferred format.
701
+		if ($timed) {
702
+			$record = $this->setTimestampsOnAttach($record);
703
+		}
704
+
705
+		return $record;
706
+	}
707
+
708
+	/**
709
+	 * Set the creation and update timestamps on an attach record.
710
+	 *
711
+	 * @param  array $record
712
+	 * @param  bool  $exists
713
+	 * @return array
714
+	 */
715
+	protected function setTimestampsOnAttach(array $record, $exists = false)
716
+	{
717
+		$fresh = $this->freshTimestamp();
718
+
719
+		if (!$exists) {
720
+			$record[$this->createdAt()] = $fresh;
721
+		}
722
+
723
+		$record[$this->updatedAt()] = $fresh;
724
+
725
+		return $record;
726
+	}
727
+
728
+	/**
729
+	 * @param EntityCollection $entities
730
+	 * @return array
731
+	 */
732
+	protected function getModelKeysFromCollection(EntityCollection $entities)
733
+	{
734
+		$keyName = $this->relatedMap->getKeyName();
735
+
736
+		return array_map(function ($m) use ($keyName) {
737
+			return $m->$keyName;
738
+		}, $entities);
739
+	}
740
+
741
+	/**
742
+	 * Detach models from the relationship.
743
+	 *
744
+	 * @param  int|array $ids
745
+	 * @throws \InvalidArgumentException
746
+	 * @return int
747
+	 */
748
+	public function detach($ids = [])
749
+	{
750
+		if ($ids instanceof EntityCollection) {
751
+			$ids = (array) $ids->modelKeys();
752
+		}
753
+
754
+		$query = $this->newPivotQuery();
755
+
756
+		// If associated IDs were passed to the method we will only delete those
757
+		// associations, otherwise all of the association ties will be broken.
758
+		// We'll return the numbers of affected rows when we do the deletes.
759
+		$ids = (array) $ids;
760
+
761
+		if (count($ids) > 0) {
762
+			$query->whereIn($this->otherKey, (array) $ids);
763
+		}
764
+
765
+		// Once we have all of the conditions set on the statement, we are ready
766
+		// to run the delete on the pivot table. Then, if the touch parameter
767
+		// is true, we will go ahead and touch all related models to sync.
768
+		return $query->delete();
769
+	}
770 770
     
771
-    /**
772
-     * Create a new query builder for the pivot table.
773
-     *
774
-     * @throws \InvalidArgumentException
775
-     *
776
-     * @return \Illuminate\Database\Query\Builder
777
-     */
778
-    protected function newPivotQuery()
779
-    {
780
-        $query = $this->newPivotStatement();
781
-
782
-        $parentKey = $this->parentMap->getKeyName();
783
-
784
-        return $query->where($this->foreignKey, $this->parent->getEntityAttribute($parentKey));
785
-    }
786
-
787
-    /**
788
-     * Get a new plain query builder for the pivot table.
789
-     *
790
-     * @return \Illuminate\Database\Query\Builder
791
-     */
792
-    public function newPivotStatement()
793
-    {
794
-        return $this->query->getQuery()->newQuery()->from($this->table);
795
-    }
796
-
797
-    /**
798
-     * Get a new pivot statement for a given "other" ID.
799
-     *
800
-     * @param  mixed $id
801
-     *
802
-     * @throws \InvalidArgumentException
803
-     *
804
-     * @return \Illuminate\Database\Query\Builder
805
-     */
806
-    public function newPivotStatementForId($id)
807
-    {
808
-        $pivot = $this->newPivotStatement();
809
-
810
-        $parentKeyName = $this->parentMap->getKeyName();
811
-
812
-        $key = $this->parent->getEntityAttribute($parentKeyName);
813
-
814
-        return $pivot->where($this->foreignKey, $key)->where($this->otherKey, $id);
815
-    }
816
-
817
-    /**
818
-     * Create a new pivot model instance.
819
-     *
820
-     * @param  array $attributes
821
-     * @param  bool  $exists
822
-     * @return \Analogue\ORM\Relationships\Pivot
823
-     */
824
-    public function newPivot(array $attributes = [], $exists = false)
825
-    {
826
-        $pivot = new Pivot($this->parent, $this->parentMap, $attributes, $this->table, $exists);
771
+	/**
772
+	 * Create a new query builder for the pivot table.
773
+	 *
774
+	 * @throws \InvalidArgumentException
775
+	 *
776
+	 * @return \Illuminate\Database\Query\Builder
777
+	 */
778
+	protected function newPivotQuery()
779
+	{
780
+		$query = $this->newPivotStatement();
781
+
782
+		$parentKey = $this->parentMap->getKeyName();
783
+
784
+		return $query->where($this->foreignKey, $this->parent->getEntityAttribute($parentKey));
785
+	}
786
+
787
+	/**
788
+	 * Get a new plain query builder for the pivot table.
789
+	 *
790
+	 * @return \Illuminate\Database\Query\Builder
791
+	 */
792
+	public function newPivotStatement()
793
+	{
794
+		return $this->query->getQuery()->newQuery()->from($this->table);
795
+	}
796
+
797
+	/**
798
+	 * Get a new pivot statement for a given "other" ID.
799
+	 *
800
+	 * @param  mixed $id
801
+	 *
802
+	 * @throws \InvalidArgumentException
803
+	 *
804
+	 * @return \Illuminate\Database\Query\Builder
805
+	 */
806
+	public function newPivotStatementForId($id)
807
+	{
808
+		$pivot = $this->newPivotStatement();
809
+
810
+		$parentKeyName = $this->parentMap->getKeyName();
811
+
812
+		$key = $this->parent->getEntityAttribute($parentKeyName);
813
+
814
+		return $pivot->where($this->foreignKey, $key)->where($this->otherKey, $id);
815
+	}
816
+
817
+	/**
818
+	 * Create a new pivot model instance.
819
+	 *
820
+	 * @param  array $attributes
821
+	 * @param  bool  $exists
822
+	 * @return \Analogue\ORM\Relationships\Pivot
823
+	 */
824
+	public function newPivot(array $attributes = [], $exists = false)
825
+	{
826
+		$pivot = new Pivot($this->parent, $this->parentMap, $attributes, $this->table, $exists);
827 827
         
828
-        return $pivot->setPivotKeys($this->foreignKey, $this->otherKey);
829
-    }
830
-
831
-    /**
832
-     * Create a new existing pivot model instance.
833
-     *
834
-     * @param  array $attributes
835
-     * @return \Analogue\ORM\Relationships\Pivot
836
-     */
837
-    public function newExistingPivot(array $attributes = [])
838
-    {
839
-        return $this->newPivot($attributes, true);
840
-    }
841
-
842
-    /**
843
-     * Set the columns on the pivot table to retrieve.
844
-     *
845
-     * @param  array $columns
846
-     * @return $this
847
-     */
848
-    public function withPivot($columns)
849
-    {
850
-        $columns = is_array($columns) ? $columns : func_get_args();
851
-
852
-        $this->pivotColumns = array_merge($this->pivotColumns, $columns);
853
-
854
-        return $this;
855
-    }
856
-
857
-    /**
858
-     * Specify that the pivot table has creation and update timestamps.
859
-     *
860
-     * @param  mixed $createdAt
861
-     * @param  mixed $updatedAt
862
-     * @return \Analogue\ORM\Relationships\BelongsToMany
863
-     */
864
-    public function withTimestamps($createdAt = null, $updatedAt = null)
865
-    {
866
-        return $this->withPivot($createdAt ?: $this->createdAt(), $updatedAt ?: $this->updatedAt());
867
-    }
868
-
869
-    /**
870
-     * Get the key for comparing against the parent key in "has" query.
871
-     *
872
-     * @return string
873
-     */
874
-    public function getHasCompareKey()
875
-    {
876
-        return $this->getForeignKey();
877
-    }
878
-
879
-    /**
880
-     * Get the fully qualified foreign key for the relation.
881
-     *
882
-     * @return string
883
-     */
884
-    public function getForeignKey()
885
-    {
886
-        return $this->table . '.' . $this->foreignKey;
887
-    }
888
-
889
-    /**
890
-     * Get the fully qualified "other key" for the relation.
891
-     *
892
-     * @return string
893
-     */
894
-    public function getOtherKey()
895
-    {
896
-        return $this->table . '.' . $this->otherKey;
897
-    }
898
-
899
-    /**
900
-     * Get the fully qualified parent key name.
901
-     *
902
-     * @return string
903
-     */
904
-    protected function getQualifiedParentKeyName()
905
-    {
906
-        return $this->parentMap->getQualifiedKeyName();
907
-    }
908
-
909
-    /**
910
-     * Get the intermediate table for the relationship.
911
-     *
912
-     * @return string
913
-     */
914
-    public function getTable()
915
-    {
916
-        return $this->table;
917
-    }
918
-
919
-    /**
920
-     * Get the relationship name for the relationship.
921
-     *
922
-     * @return string
923
-     */
924
-    public function getRelationName()
925
-    {
926
-        return $this->relationName;
927
-    }
828
+		return $pivot->setPivotKeys($this->foreignKey, $this->otherKey);
829
+	}
830
+
831
+	/**
832
+	 * Create a new existing pivot model instance.
833
+	 *
834
+	 * @param  array $attributes
835
+	 * @return \Analogue\ORM\Relationships\Pivot
836
+	 */
837
+	public function newExistingPivot(array $attributes = [])
838
+	{
839
+		return $this->newPivot($attributes, true);
840
+	}
841
+
842
+	/**
843
+	 * Set the columns on the pivot table to retrieve.
844
+	 *
845
+	 * @param  array $columns
846
+	 * @return $this
847
+	 */
848
+	public function withPivot($columns)
849
+	{
850
+		$columns = is_array($columns) ? $columns : func_get_args();
851
+
852
+		$this->pivotColumns = array_merge($this->pivotColumns, $columns);
853
+
854
+		return $this;
855
+	}
856
+
857
+	/**
858
+	 * Specify that the pivot table has creation and update timestamps.
859
+	 *
860
+	 * @param  mixed $createdAt
861
+	 * @param  mixed $updatedAt
862
+	 * @return \Analogue\ORM\Relationships\BelongsToMany
863
+	 */
864
+	public function withTimestamps($createdAt = null, $updatedAt = null)
865
+	{
866
+		return $this->withPivot($createdAt ?: $this->createdAt(), $updatedAt ?: $this->updatedAt());
867
+	}
868
+
869
+	/**
870
+	 * Get the key for comparing against the parent key in "has" query.
871
+	 *
872
+	 * @return string
873
+	 */
874
+	public function getHasCompareKey()
875
+	{
876
+		return $this->getForeignKey();
877
+	}
878
+
879
+	/**
880
+	 * Get the fully qualified foreign key for the relation.
881
+	 *
882
+	 * @return string
883
+	 */
884
+	public function getForeignKey()
885
+	{
886
+		return $this->table . '.' . $this->foreignKey;
887
+	}
888
+
889
+	/**
890
+	 * Get the fully qualified "other key" for the relation.
891
+	 *
892
+	 * @return string
893
+	 */
894
+	public function getOtherKey()
895
+	{
896
+		return $this->table . '.' . $this->otherKey;
897
+	}
898
+
899
+	/**
900
+	 * Get the fully qualified parent key name.
901
+	 *
902
+	 * @return string
903
+	 */
904
+	protected function getQualifiedParentKeyName()
905
+	{
906
+		return $this->parentMap->getQualifiedKeyName();
907
+	}
908
+
909
+	/**
910
+	 * Get the intermediate table for the relationship.
911
+	 *
912
+	 * @return string
913
+	 */
914
+	public function getTable()
915
+	{
916
+		return $this->table;
917
+	}
918
+
919
+	/**
920
+	 * Get the relationship name for the relationship.
921
+	 *
922
+	 * @return string
923
+	 */
924
+	public function getRelationName()
925
+	{
926
+		return $this->relationName;
927
+	}
928 928
 }
Please login to merge, or discard this patch.
src/ValueMap.php 1 patch
Indentation   +55 added lines, -55 removed lines patch added patch discarded remove patch
@@ -4,67 +4,67 @@
 block discarded – undo
4 4
 
5 5
 class ValueMap
6 6
 {
7
-    /**
8
-     * @var string
9
-     */
10
-    protected $name;
7
+	/**
8
+	 * @var string
9
+	 */
10
+	protected $name;
11 11
 
12
-    /**
13
-     * @var string
14
-     */
15
-    protected $class;
12
+	/**
13
+	 * @var string
14
+	 */
15
+	protected $class;
16 16
 
17
-    /**
18
-     * @var array
19
-     */
20
-    protected $embeddables = [];
17
+	/**
18
+	 * @var array
19
+	 */
20
+	protected $embeddables = [];
21 21
 
22
-    /**
23
-     * @var array
24
-     */
25
-    protected $attributes = [];
22
+	/**
23
+	 * @var array
24
+	 */
25
+	protected $attributes = [];
26 26
 
27
-    /**
28
-     * @return array
29
-     */
30
-    public function getAttributes()
31
-    {
32
-        return $this->attributes;
33
-    }
27
+	/**
28
+	 * @return array
29
+	 */
30
+	public function getAttributes()
31
+	{
32
+		return $this->attributes;
33
+	}
34 34
 
35
-    /**
36
-     * @return array
37
-     */
38
-    public function getEmbeddables()
39
-    {
40
-        return $this->embeddables;
41
-    }
35
+	/**
36
+	 * @return array
37
+	 */
38
+	public function getEmbeddables()
39
+	{
40
+		return $this->embeddables;
41
+	}
42 42
 
43
-    /**
44
-     * @param $class
45
-     */
46
-    public function setClass($class)
47
-    {
48
-        $this->class = $class;
49
-    }
43
+	/**
44
+	 * @param $class
45
+	 */
46
+	public function setClass($class)
47
+	{
48
+		$this->class = $class;
49
+	}
50 50
 
51
-    /**
52
-     * @return mixed
53
-     */
54
-    public function getClass()
55
-    {
56
-        return $this->class;
57
-    }
51
+	/**
52
+	 * @return mixed
53
+	 */
54
+	public function getClass()
55
+	{
56
+		return $this->class;
57
+	}
58 58
 
59
-    /**
60
-     * @return string
61
-     */
62
-    public function getName()
63
-    {
64
-        if (isset($this->name)) {
65
-            return $this->name;
66
-        } else {
67
-            return class_basename($this);
68
-        }
69
-    }
59
+	/**
60
+	 * @return string
61
+	 */
62
+	public function getName()
63
+	{
64
+		if (isset($this->name)) {
65
+			return $this->name;
66
+		} else {
67
+			return class_basename($this);
68
+		}
69
+	}
70 70
 }
Please login to merge, or discard this patch.
src/Drivers/IlluminateConnectionProvider.php 1 patch
Indentation   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -6,28 +6,28 @@
 block discarded – undo
6 6
 
7 7
 class IlluminateConnectionProvider
8 8
 {
9
-    /**
10
-     * @var DatabaseManager
11
-     */
12
-    protected $db;
9
+	/**
10
+	 * @var DatabaseManager
11
+	 */
12
+	protected $db;
13 13
 
14
-    /**
15
-     * IlluminateConnectionProvider constructor.
16
-     * @param DatabaseManager $db
17
-     */
18
-    public function __construct(DatabaseManager $db)
19
-    {
20
-        $this->db = $db;
21
-    }
14
+	/**
15
+	 * IlluminateConnectionProvider constructor.
16
+	 * @param DatabaseManager $db
17
+	 */
18
+	public function __construct(DatabaseManager $db)
19
+	{
20
+		$this->db = $db;
21
+	}
22 22
 
23
-    /**
24
-     * Get a Database connection object
25
-     *
26
-     * @param  $name
27
-     * @return \Illuminate\Database\Connection
28
-     */
29
-    public function connection($name = null)
30
-    {
31
-        return $this->db->connection($name);
32
-    }
23
+	/**
24
+	 * Get a Database connection object
25
+	 *
26
+	 * @param  $name
27
+	 * @return \Illuminate\Database\Connection
28
+	 */
29
+	public function connection($name = null)
30
+	{
31
+		return $this->db->connection($name);
32
+	}
33 33
 }
Please login to merge, or discard this patch.
src/Drivers/Manager.php 1 patch
Indentation   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -4,32 +4,32 @@
 block discarded – undo
4 4
 
5 5
 class Manager
6 6
 {
7
-    /**
8
-     * @var DriverInterface[]
9
-     */
10
-    protected $drivers = [];
7
+	/**
8
+	 * @var DriverInterface[]
9
+	 */
10
+	protected $drivers = [];
11 11
 
12
-    /**
13
-     * Add a Mapping Driver
14
-     *
15
-     * @param DriverInterface $driver
16
-     */
17
-    public function addDriver(DriverInterface $driver)
18
-    {
19
-        $this->drivers[$driver->getName()] = $driver;
20
-    }
12
+	/**
13
+	 * Add a Mapping Driver
14
+	 *
15
+	 * @param DriverInterface $driver
16
+	 */
17
+	public function addDriver(DriverInterface $driver)
18
+	{
19
+		$this->drivers[$driver->getName()] = $driver;
20
+	}
21 21
 
22
-    /**
23
-     * Get the DBAdapter
24
-     *
25
-     * @param  string $driver
26
-     * @param  string $connection connection name for drivers supporting multiple connection.
27
-     * @return DriverInterface|void
28
-     */
29
-    public function getAdapter($driver, $connection = null)
30
-    {
31
-        if (array_key_exists($driver, $this->drivers)) {
32
-            return $this->drivers[$driver]->getAdapter($connection);
33
-        }
34
-    }
22
+	/**
23
+	 * Get the DBAdapter
24
+	 *
25
+	 * @param  string $driver
26
+	 * @param  string $connection connection name for drivers supporting multiple connection.
27
+	 * @return DriverInterface|void
28
+	 */
29
+	public function getAdapter($driver, $connection = null)
30
+	{
31
+		if (array_key_exists($driver, $this->drivers)) {
32
+			return $this->drivers[$driver]->getAdapter($connection);
33
+		}
34
+	}
35 35
 }
Please login to merge, or discard this patch.