diff --git a/.travis.yml b/.travis.yml index ae9af9d18..357d4036a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,11 @@ language: php php: - - 5.5 - 5.6 - 7 - - hhvm matrix: fast_finish: true - allow_failures: - - php: hhvm sudo: false @@ -35,4 +31,4 @@ script: - vendor/bin/phpunit --coverage-clover build/logs/clover.xml after_success: - - sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then php vendor/bin/coveralls -v; fi;' + - sh -c 'php vendor/bin/coveralls -v' diff --git a/src/Jenssegers/Mongodb/Eloquent/Builder.php b/src/Jenssegers/Mongodb/Eloquent/Builder.php index 745c73476..30feb67e3 100644 --- a/src/Jenssegers/Mongodb/Eloquent/Builder.php +++ b/src/Jenssegers/Mongodb/Eloquent/Builder.php @@ -2,6 +2,7 @@ use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Relations\Relation; +use Illuminate\Support\Collection; use MongoDB\Driver\Cursor; use MongoDB\Model\BSONDocument; @@ -167,9 +168,10 @@ protected function addHasWhere(EloquentBuilder $hasQuery, Relation $relation, $o $query = $hasQuery->getQuery(); // Get the number of related objects for each possible parent. + $relations = $query->pluck($relation->getHasCompareKey()); $relationCount = array_count_values(array_map(function ($id) { return (string) $id; // Convert Back ObjectIds to Strings - }, $query->pluck($relation->getHasCompareKey()))); + }, is_array($relations) ? $relations : $relations->toArray())); // Remove unwanted related objects based on the operator and count. $relationCount = array_filter($relationCount, function ($counted) use ($count, $operator) { diff --git a/src/Jenssegers/Mongodb/Eloquent/Model.php b/src/Jenssegers/Mongodb/Eloquent/Model.php index cb57d7271..797f1907f 100644 --- a/src/Jenssegers/Mongodb/Eloquent/Model.php +++ b/src/Jenssegers/Mongodb/Eloquent/Model.php @@ -244,6 +244,18 @@ public function getAttribute($key) // Get the relation results. return $this->getRelationshipFromMethod($key, $camelKey); } + + if ($relations instanceof Relation) { + // If the key already exists in the relationships array, it just means the + // relationship has already been loaded, so we'll just return it out of + // here because there is no need to query within the relations twice. + if (array_key_exists($key, $this->relations) && $this->relations[$key] != null) { + return $this->relations[$key]; + } + + // Get the relation results. + return $this->getRelationshipFromMethod($key, $camelKey); + } } } diff --git a/src/Jenssegers/Mongodb/Query/Builder.php b/src/Jenssegers/Mongodb/Query/Builder.php index 709c373ce..74b9ee3a6 100644 --- a/src/Jenssegers/Mongodb/Query/Builder.php +++ b/src/Jenssegers/Mongodb/Query/Builder.php @@ -577,7 +577,16 @@ public function pluck($column, $key = null) { $results = $this->get(is_null($key) ? [$column] : [$column, $key]); - return $this->useCollections ? $results->pluck($column, $key) : Arr::pluck($results, $column, $key); + // Convert ObjectID's to strings + if ($key == '_id') { + $results = $results->map(function ($item) { + $item['_id'] = (string) $item['_id']; + return $item; + }); + } + + $p = Arr::pluck($results, $column, $key); + return $this->useCollections ? new Collection($p) : $p; } /** @@ -632,20 +641,7 @@ public function truncate() */ public function lists($column, $key = null) { - if ($key == '_id') { - $results = new Collection($this->get([$column, $key])); - - // Convert ObjectID's to strings so that lists can do its work. - $results = $results->map(function ($item) { - $item['_id'] = (string) $item['_id']; - - return $item; - }); - - return $results->pluck($column, $key)->all(); - } - - return parent::pluck($column, $key); + return $this->pluck($column, $key); } /** diff --git a/src/Jenssegers/Mongodb/Queue/MongoQueue.php b/src/Jenssegers/Mongodb/Queue/MongoQueue.php index 83c7a3d93..88279e17f 100644 --- a/src/Jenssegers/Mongodb/Queue/MongoQueue.php +++ b/src/Jenssegers/Mongodb/Queue/MongoQueue.php @@ -79,12 +79,21 @@ protected function getNextAvailableJobAndReserve($queue) */ protected function releaseJobsThatHaveBeenReservedTooLong($queue) { - $expired = Carbon::now()->subSeconds($this->expire)->getTimestamp(); + $expiration = Carbon::now()->subSeconds($this->expire)->getTimestamp(); + $now = time(); $reserved = $this->database->collection($this->table) ->where('queue', $this->getQueue($queue)) - ->where('reserved', 1) - ->where('reserved_at', '<=', $expired)->get(); + ->where(function ($query) use ($expiration, $now) { + // Check for available jobs + $query->where(function ($query) use ($now) { + $query->whereNull('reserved_at'); + $query->where('available_at', '<=', $now); + }); + + // Check for jobs that are reserved but have expired + $query->orWhere('reserved_at', '<=', $expiration); + })->get(); foreach ($reserved as $job) { $attempts = $job['attempts'] + 1; diff --git a/src/Jenssegers/Mongodb/Relations/BelongsToMany.php b/src/Jenssegers/Mongodb/Relations/BelongsToMany.php index 9606b5dee..2cca88638 100644 --- a/src/Jenssegers/Mongodb/Relations/BelongsToMany.php +++ b/src/Jenssegers/Mongodb/Relations/BelongsToMany.php @@ -286,4 +286,24 @@ public function getForeignKey() { return $this->foreignKey; } + + /** + * Format the sync list so that it is keyed by ID. (Legacy Support) + * The original function has been renamed to formatRecordsList since Laravel 5.3 + * + * @deprecated + * @param array $records + * @return array + */ + protected function formatSyncList(array $records) + { + $results = []; + foreach ($records as $id => $attributes) { + if (! is_array($attributes)) { + list($id, $attributes) = [$attributes, []]; + } + $results[$id] = $attributes; + } + return $results; + } } diff --git a/src/Jenssegers/Mongodb/Schema/Blueprint.php b/src/Jenssegers/Mongodb/Schema/Blueprint.php index 144675b39..5d2edbce8 100644 --- a/src/Jenssegers/Mongodb/Schema/Blueprint.php +++ b/src/Jenssegers/Mongodb/Schema/Blueprint.php @@ -44,9 +44,11 @@ public function __construct(Connection $connection, $collection) * * @param string|array $columns * @param array $options + * @param string $name + * @param string|null $algorithm * @return Blueprint */ - public function index($columns = null, $options = []) + public function index($columns = null, $name = null, $algorithm = null, $options = []) { $columns = $this->fluent($columns); @@ -71,10 +73,12 @@ public function index($columns = null, $options = []) * Specify the primary key(s) for the table. * * @param string|array $columns + * @param string $name + * @param string|null $algorithm * @param array $options * @return \Illuminate\Support\Fluent */ - public function primary($columns = null, $options = []) + public function primary($columns = null, $name = null, $algorithm = null, $options = []) { return $this->unique($columns, $options); } @@ -112,16 +116,18 @@ public function dropIndex($columns = null) * Specify a unique index for the collection. * * @param string|array $columns + * @param string $name + * @param string|null $algorithm * @param array $options * @return Blueprint */ - public function unique($columns = null, $options = []) + public function unique($columns = null, $name = null, $algorithm = null, $options = []) { $columns = $this->fluent($columns); $options['unique'] = true; - $this->index($columns, $options); + $this->index($columns, null, null, $options); return $this; } @@ -136,7 +142,7 @@ public function background($columns = null) { $columns = $this->fluent($columns); - $this->index($columns, ['background' => true]); + $this->index($columns, null, null, ['background' => true]); return $this; } @@ -154,7 +160,7 @@ public function sparse($columns = null, $options = []) $options['sparse'] = true; - $this->index($columns, $options); + $this->index($columns, null, null, $options); return $this; } @@ -171,7 +177,7 @@ public function expire($columns, $seconds) { $columns = $this->fluent($columns); - $this->index($columns, ['expireAfterSeconds' => $seconds]); + $this->index($columns, null, null, ['expireAfterSeconds' => $seconds]); return $this; } diff --git a/tests/EmbeddedRelationsTest.php b/tests/EmbeddedRelationsTest.php index f371dfbf1..b0507c7ef 100644 --- a/tests/EmbeddedRelationsTest.php +++ b/tests/EmbeddedRelationsTest.php @@ -31,7 +31,7 @@ public function testEmbedsManySave() $this->assertNotNull($user->addresses); $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $user->addresses); - $this->assertEquals(['London'], $user->addresses->lists('city')->all()); + $this->assertEquals(['London'], $user->addresses->pluck('city')->all()); $this->assertInstanceOf('DateTime', $address->created_at); $this->assertInstanceOf('DateTime', $address->updated_at); $this->assertNotNull($address->_id); @@ -43,7 +43,7 @@ public function testEmbedsManySave() $address = $user->addresses()->save(new Address(['city' => 'Paris'])); $user = User::find($user->_id); - $this->assertEquals(['London', 'Paris'], $user->addresses->lists('city')->all()); + $this->assertEquals(['London', 'Paris'], $user->addresses->pluck('city')->all()); $address->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($address), $address)->andReturn(true); @@ -59,10 +59,10 @@ public function testEmbedsManySave() $this->assertEquals(2, count($user->addresses()->get())); $this->assertEquals(2, $user->addresses->count()); $this->assertEquals(2, $user->addresses()->count()); - $this->assertEquals(['London', 'New York'], $user->addresses->lists('city')->all()); + $this->assertEquals(['London', 'New York'], $user->addresses->pluck('city')->all()); $freshUser = User::find($user->_id); - $this->assertEquals(['London', 'New York'], $freshUser->addresses->lists('city')->all()); + $this->assertEquals(['London', 'New York'], $freshUser->addresses->pluck('city')->all()); $address = $user->addresses->first(); $this->assertEquals('London', $address->city); @@ -73,15 +73,15 @@ public function testEmbedsManySave() $user = User::find($user->_id); $user->addresses()->save(new Address(['city' => 'Bruxelles'])); - $this->assertEquals(['London', 'New York', 'Bruxelles'], $user->addresses->lists('city')->all()); + $this->assertEquals(['London', 'New York', 'Bruxelles'], $user->addresses->pluck('city')->all()); $address = $user->addresses[1]; $address->city = "Manhattan"; $user->addresses()->save($address); - $this->assertEquals(['London', 'Manhattan', 'Bruxelles'], $user->addresses->lists('city')->all()); + $this->assertEquals(['London', 'Manhattan', 'Bruxelles'], $user->addresses->pluck('city')->all()); $freshUser = User::find($user->_id); - $this->assertEquals(['London', 'Manhattan', 'Bruxelles'], $freshUser->addresses->lists('city')->all()); + $this->assertEquals(['London', 'Manhattan', 'Bruxelles'], $freshUser->addresses->pluck('city')->all()); } // public function testEmbedsManySaveModel() @@ -123,28 +123,28 @@ public function testEmbedsManyAssociate() $address = new Address(['city' => 'London']); $user->addresses()->associate($address); - $this->assertEquals(['London'], $user->addresses->lists('city')->all()); + $this->assertEquals(['London'], $user->addresses->pluck('city')->all()); $this->assertNotNull($address->_id); $freshUser = User::find($user->_id); - $this->assertEquals([], $freshUser->addresses->lists('city')->all()); + $this->assertEquals([], $freshUser->addresses->pluck('city')->all()); $address->city = 'Londinium'; $user->addresses()->associate($address); - $this->assertEquals(['Londinium'], $user->addresses->lists('city')->all()); + $this->assertEquals(['Londinium'], $user->addresses->pluck('city')->all()); $freshUser = User::find($user->_id); - $this->assertEquals([], $freshUser->addresses->lists('city')->all()); + $this->assertEquals([], $freshUser->addresses->pluck('city')->all()); } public function testEmbedsManySaveMany() { $user = User::create(['name' => 'John Doe']); $user->addresses()->saveMany([new Address(['city' => 'London']), new Address(['city' => 'Bristol'])]); - $this->assertEquals(['London', 'Bristol'], $user->addresses->lists('city')->all()); + $this->assertEquals(['London', 'Bristol'], $user->addresses->pluck('city')->all()); $freshUser = User::find($user->id); - $this->assertEquals(['London', 'Bristol'], $freshUser->addresses->lists('city')->all()); + $this->assertEquals(['London', 'Bristol'], $freshUser->addresses->pluck('city')->all()); } public function testEmbedsManyDuplicate() @@ -154,7 +154,7 @@ public function testEmbedsManyDuplicate() $user->addresses()->save($address); $user->addresses()->save($address); $this->assertEquals(1, $user->addresses->count()); - $this->assertEquals(['London'], $user->addresses->lists('city')->all()); + $this->assertEquals(['London'], $user->addresses->pluck('city')->all()); $user = User::find($user->id); $this->assertEquals(1, $user->addresses->count()); @@ -162,11 +162,11 @@ public function testEmbedsManyDuplicate() $address->city = 'Paris'; $user->addresses()->save($address); $this->assertEquals(1, $user->addresses->count()); - $this->assertEquals(['Paris'], $user->addresses->lists('city')->all()); + $this->assertEquals(['Paris'], $user->addresses->pluck('city')->all()); $user->addresses()->create(['_id' => $address->_id, 'city' => 'Bruxelles']); $this->assertEquals(1, $user->addresses->count()); - $this->assertEquals(['Bruxelles'], $user->addresses->lists('city')->all()); + $this->assertEquals(['Bruxelles'], $user->addresses->pluck('city')->all()); } public function testEmbedsManyCreate() @@ -175,13 +175,13 @@ public function testEmbedsManyCreate() $address = $user->addresses()->create(['city' => 'Bruxelles']); $this->assertInstanceOf('Address', $address); $this->assertTrue(is_string($address->_id)); - $this->assertEquals(['Bruxelles'], $user->addresses->lists('city')->all()); + $this->assertEquals(['Bruxelles'], $user->addresses->pluck('city')->all()); $raw = $address->getAttributes(); $this->assertInstanceOf('MongoDB\BSON\ObjectID', $raw['_id']); $freshUser = User::find($user->id); - $this->assertEquals(['Bruxelles'], $freshUser->addresses->lists('city')->all()); + $this->assertEquals(['Bruxelles'], $freshUser->addresses->pluck('city')->all()); $user = User::create([]); $address = $user->addresses()->create(['_id' => '', 'city' => 'Bruxelles']); @@ -197,10 +197,10 @@ public function testEmbedsManyCreateMany() list($bruxelles, $paris) = $user->addresses()->createMany([['city' => 'Bruxelles'], ['city' => 'Paris']]); $this->assertInstanceOf('Address', $bruxelles); $this->assertEquals('Bruxelles', $bruxelles->city); - $this->assertEquals(['Bruxelles', 'Paris'], $user->addresses->lists('city')->all()); + $this->assertEquals(['Bruxelles', 'Paris'], $user->addresses->pluck('city')->all()); $freshUser = User::find($user->id); - $this->assertEquals(['Bruxelles', 'Paris'], $freshUser->addresses->lists('city')->all()); + $this->assertEquals(['Bruxelles', 'Paris'], $freshUser->addresses->pluck('city')->all()); } public function testEmbedsManyDestroy() @@ -215,30 +215,30 @@ public function testEmbedsManyDestroy() $events->shouldReceive('fire')->once()->with('eloquent.deleted: ' . get_class($address), Mockery::type('Address')); $user->addresses()->destroy($address->_id); - $this->assertEquals(['Bristol', 'Bruxelles'], $user->addresses->lists('city')->all()); + $this->assertEquals(['Bristol', 'Bruxelles'], $user->addresses->pluck('city')->all()); $address->unsetEventDispatcher(); $address = $user->addresses->first(); $user->addresses()->destroy($address); - $this->assertEquals(['Bruxelles'], $user->addresses->lists('city')->all()); + $this->assertEquals(['Bruxelles'], $user->addresses->pluck('city')->all()); $user->addresses()->create(['city' => 'Paris']); $user->addresses()->create(['city' => 'San Francisco']); $freshUser = User::find($user->id); - $this->assertEquals(['Bruxelles', 'Paris', 'San Francisco'], $freshUser->addresses->lists('city')->all()); + $this->assertEquals(['Bruxelles', 'Paris', 'San Francisco'], $freshUser->addresses->pluck('city')->all()); - $ids = $user->addresses->lists('_id'); + $ids = $user->addresses->pluck('_id'); $user->addresses()->destroy($ids); - $this->assertEquals([], $user->addresses->lists('city')->all()); + $this->assertEquals([], $user->addresses->pluck('city')->all()); $freshUser = User::find($user->id); - $this->assertEquals([], $freshUser->addresses->lists('city')->all()); + $this->assertEquals([], $freshUser->addresses->pluck('city')->all()); list($london, $bristol, $bruxelles) = $user->addresses()->saveMany([new Address(['city' => 'London']), new Address(['city' => 'Bristol']), new Address(['city' => 'Bruxelles'])]); $user->addresses()->destroy([$london, $bruxelles]); - $this->assertEquals(['Bristol'], $user->addresses->lists('city')->all()); + $this->assertEquals(['Bristol'], $user->addresses->pluck('city')->all()); } public function testEmbedsManyDelete() @@ -285,10 +285,10 @@ public function testEmbedsManyAliases() $address = new Address(['city' => 'London']); $address = $user->addresses()->attach($address); - $this->assertEquals(['London'], $user->addresses->lists('city')->all()); + $this->assertEquals(['London'], $user->addresses->pluck('city')->all()); $user->addresses()->detach($address); - $this->assertEquals([], $user->addresses->lists('city')->all()); + $this->assertEquals([], $user->addresses->pluck('city')->all()); } public function testEmbedsManyCreatingEventReturnsFalse() @@ -344,7 +344,7 @@ public function testEmbedsManyDeletingEventReturnsFalse() $events->shouldReceive('until')->once()->with('eloquent.deleting: ' . get_class($address), Mockery::mustBe($address))->andReturn(false); $this->assertEquals(0, $user->addresses()->destroy($address)); - $this->assertEquals(['New York'], $user->addresses->lists('city')->all()); + $this->assertEquals(['New York'], $user->addresses->pluck('city')->all()); $address->unsetEventDispatcher(); } @@ -421,11 +421,11 @@ public function testEmbedsManyCollectionMethods() $user->addresses()->save(new Address(['city' => 'Brussels', 'country' => 'Belgium', 'visited' => 2, 'created_at' => new DateTime('4 days ago')])); $user->addresses()->save(new Address(['city' => 'Ghent', 'country' => 'Belgium', 'visited' => 13, 'created_at' => new DateTime('2 days ago')])); - $this->assertEquals(['Paris', 'Bruges', 'Brussels', 'Ghent'], $user->addresses()->lists('city')->all()); - $this->assertEquals(['Bruges', 'Brussels', 'Ghent', 'Paris'], $user->addresses()->sortBy('city')->lists('city')->all()); - $this->assertEquals([], $user->addresses()->where('city', 'New York')->lists('city')->all()); - $this->assertEquals(['Bruges', 'Brussels', 'Ghent'], $user->addresses()->where('country', 'Belgium')->lists('city')->all()); - $this->assertEquals(['Bruges', 'Brussels', 'Ghent'], $user->addresses()->where('country', 'Belgium')->sortBy('city')->lists('city')->all()); + $this->assertEquals(['Paris', 'Bruges', 'Brussels', 'Ghent'], $user->addresses()->pluck('city')->all()); + $this->assertEquals(['Bruges', 'Brussels', 'Ghent', 'Paris'], $user->addresses()->sortBy('city')->pluck('city')->all()); + $this->assertEquals([], $user->addresses()->where('city', 'New York')->pluck('city')->all()); + $this->assertEquals(['Bruges', 'Brussels', 'Ghent'], $user->addresses()->where('country', 'Belgium')->pluck('city')->all()); + $this->assertEquals(['Bruges', 'Brussels', 'Ghent'], $user->addresses()->where('country', 'Belgium')->sortBy('city')->pluck('city')->all()); $results = $user->addresses->first(); $this->assertInstanceOf('Address', $results); diff --git a/tests/ModelTest.php b/tests/ModelTest.php index 1acd3b7f4..3faa763f7 100644 --- a/tests/ModelTest.php +++ b/tests/ModelTest.php @@ -156,8 +156,8 @@ public function testAll() $all = User::all(); $this->assertEquals(2, count($all)); - $this->assertContains('John Doe', $all->lists('name')); - $this->assertContains('Jane Doe', $all->lists('name')); + $this->assertContains('John Doe', $all->pluck('name')); + $this->assertContains('Jane Doe', $all->pluck('name')); } public function testFind() diff --git a/tests/QueryBuilderTest.php b/tests/QueryBuilderTest.php index c8e69bec3..ca08bf36a 100644 --- a/tests/QueryBuilderTest.php +++ b/tests/QueryBuilderTest.php @@ -29,7 +29,7 @@ public function testGet() public function testNoDocument() { - $items = DB::collection('items')->where('name', 'nothing')->get(); + $items = DB::collection('items')->where('name', 'nothing')->get()->toArray(); $this->assertEquals([], $items); $item = DB::collection('items')->where('name', 'nothing')->first(); @@ -288,12 +288,12 @@ public function testDistinct() ['name' => 'spoon', 'type' => 'round'], ]); - $items = DB::collection('items')->distinct('name')->get(); + $items = DB::collection('items')->distinct('name')->get()->toArray(); sort($items); $this->assertEquals(3, count($items)); $this->assertEquals(['fork', 'knife', 'spoon'], $items); - $types = DB::collection('items')->distinct('type')->get(); + $types = DB::collection('items')->distinct('type')->get()->toArray(); sort($types); $this->assertEquals(2, count($types)); $this->assertEquals(['round', 'sharp'], $types); @@ -357,7 +357,7 @@ public function testPluck() ['name' => 'John Doe', 'age' => 25], ]); - $age = DB::collection('users')->where('name', 'John Doe')->pluck('age'); + $age = DB::collection('users')->where('name', 'John Doe')->pluck('age')->toArray(); $this->assertEquals([25], $age); } @@ -370,16 +370,16 @@ public function testList() ['name' => 'spoon', 'type' => 'round', 'amount' => 14], ]); - $list = DB::collection('items')->lists('name'); + $list = DB::collection('items')->pluck('name')->toArray(); sort($list); $this->assertEquals(4, count($list)); $this->assertEquals(['fork', 'knife', 'spoon', 'spoon'], $list); - $list = DB::collection('items')->lists('type', 'name'); + $list = DB::collection('items')->pluck('type', 'name')->toArray(); $this->assertEquals(3, count($list)); $this->assertEquals(['knife' => 'sharp', 'fork' => 'sharp', 'spoon' => 'round'], $list); - $list = DB::collection('items')->lists('name', '_id'); + $list = DB::collection('items')->pluck('name', '_id')->toArray(); $this->assertEquals(4, count($list)); $this->assertEquals(24, strlen(key($list))); } diff --git a/tests/QueueTest.php b/tests/QueueTest.php index 83293617e..89f61fb27 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -38,7 +38,7 @@ public function testQueueJobExpired() // Expect an attempted older job in the queue $job = Queue::pop('test'); - $this->assertEquals(2, $job->getDatabaseJob()->attempts); + $this->assertEquals(1, $job->getDatabaseJob()->attempts); $this->assertGreaterThan($expiry, $job->getDatabaseJob()->reserved_at); $job->delete(); diff --git a/tests/RelationsTest.php b/tests/RelationsTest.php index 6f0318fef..8572d4727 100644 --- a/tests/RelationsTest.php +++ b/tests/RelationsTest.php @@ -322,8 +322,8 @@ public function testBelongsToManyCustom() $this->assertTrue(array_key_exists('groups', $user->getAttributes())); // Assert they are attached - $this->assertTrue(in_array($group->_id, $user->groups)); - $this->assertTrue(in_array($user->_id, $group->users)); + $this->assertTrue(in_array($group->_id, $user->groups->pluck('_id')->toArray())); + $this->assertTrue(in_array($user->_id, $group->users->pluck('_id')->toArray())); $this->assertEquals($group->_id, $user->groups()->first()->_id); $this->assertEquals($user->_id, $group->users()->first()->_id); }