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