Skip to content

Commit 1c61439

Browse files
committed
Merge branch 'master' into add_test_for_negative_dates
2 parents e10a153 + 53137f3 commit 1c61439

21 files changed

+243
-113
lines changed

.github/FUNDING.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
github: jenssegers
2-
open_collective: laravel-mongodb
2+
tidelift: "packagist/jenssegers/mongodb"

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 Jens Segers
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Make sure you have the MongoDB PHP driver installed. You can find installation i
6363
5.6.x | 3.4.x
6464
5.7.x | 3.4.x
6565
5.8.x | 3.5.x
66-
6.0.x | 3.6.x
66+
6.x | 3.6.x
6767

6868
Install the package via Composer:
6969

@@ -751,7 +751,7 @@ The belongsToMany relation will not use a pivot "table" but will push id's to a
751751
If you want to define custom keys for your relation, set it to `null`:
752752

753753
```php
754-
use Jenssegers\Mongodb\Eloquent\Mode;
754+
use Jenssegers\Mongodb\Eloquent\Model;
755755

756756
class User extends Model
757757
{
@@ -1134,3 +1134,7 @@ Embedded relations now return an `Illuminate\Database\Eloquent\Collection` rathe
11341134
```php
11351135
$books = $user->books()->sortBy('title')->get();
11361136
```
1137+
1138+
## Security contact information
1139+
1140+
To report a security vulnerability, follow [these steps](https://tidelift.com/security).

src/Jenssegers/Mongodb/Auth/DatabaseTokenRepository.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use DateTime;
66
use DateTimeZone;
77
use Illuminate\Auth\Passwords\DatabaseTokenRepository as BaseDatabaseTokenRepository;
8+
use Illuminate\Support\Facades\Date;
89
use MongoDB\BSON\UTCDateTime;
910

1011
class DatabaseTokenRepository extends BaseDatabaseTokenRepository
@@ -17,7 +18,7 @@ protected function getPayload($email, $token)
1718
return [
1819
'email' => $email,
1920
'token' => $this->hasher->make($token),
20-
'created_at' => new UTCDateTime(time() * 1000),
21+
'created_at' => new UTCDateTime(Date::now()->format('Uv')),
2122
];
2223
}
2324

@@ -37,7 +38,7 @@ protected function tokenExpired($createdAt)
3738
protected function tokenRecentlyCreated($createdAt)
3839
{
3940
$createdAt = $this->convertDateTime($createdAt);
40-
41+
4142
return parent::tokenRecentlyCreated($createdAt);
4243
}
4344

src/Jenssegers/Mongodb/Connection.php

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Illuminate\Database\Connection as BaseConnection;
66
use Illuminate\Support\Arr;
7+
use InvalidArgumentException;
78
use MongoDB\Client;
89

910
class Connection extends BaseConnection
@@ -37,8 +38,11 @@ public function __construct(array $config)
3738
// Create the connection
3839
$this->connection = $this->createConnection($dsn, $config, $options);
3940

41+
// Get default database name
42+
$default_db = $this->getDefaultDatabaseName($dsn, $config);
43+
4044
// Select database
41-
$this->db = $this->connection->selectDatabase($this->getDatabaseDsn($dsn, $config['database']));
45+
$this->db = $this->connection->selectDatabase($default_db);
4246

4347
$this->useDefaultPostProcessor();
4448

@@ -114,6 +118,26 @@ public function getDatabaseName()
114118
return $this->getMongoDB()->getDatabaseName();
115119
}
116120

121+
/**
122+
* Get the name of the default database based on db config or try to detect it from dsn
123+
* @param string $dsn
124+
* @param array $config
125+
* @return string
126+
* @throws InvalidArgumentException
127+
*/
128+
protected function getDefaultDatabaseName($dsn, $config)
129+
{
130+
if (empty($config['database'])) {
131+
if (preg_match('/^mongodb(?:[+]srv)?:\\/\\/.+\\/([^?&]+)/s', $dsn, $matches)) {
132+
$config['database'] = $matches[1];
133+
} else {
134+
throw new InvalidArgumentException("Database is not properly configured.");
135+
}
136+
}
137+
138+
return $config['database'];
139+
}
140+
117141
/**
118142
* Create a new MongoDB connection.
119143
* @param string $dsn
@@ -191,18 +215,6 @@ protected function getHostDsn(array $config)
191215
return 'mongodb://' . implode(',', $hosts) . ($auth_database ? '/' . $auth_database : '');
192216
}
193217

194-
/**
195-
* Get database name from DSN string, if there is no database in DSN path - returns back $database argument.
196-
* @param string $dsn
197-
* @param $database
198-
* @return string
199-
*/
200-
protected function getDatabaseDsn($dsn, $database)
201-
{
202-
$dsnDatabase = trim(parse_url($dsn, PHP_URL_PATH), '/');
203-
return trim($dsnDatabase) ? $dsnDatabase : $database;
204-
}
205-
206218
/**
207219
* Create a DSN string from a configuration.
208220
* @param array $config

src/Jenssegers/Mongodb/Eloquent/Model.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
namespace Jenssegers\Mongodb\Eloquent;
44

5-
use Illuminate\Support\Carbon;
65
use DateTime;
76
use Illuminate\Contracts\Queue\QueueableCollection;
87
use Illuminate\Contracts\Queue\QueueableEntity;
98
use Illuminate\Database\Eloquent\Model as BaseModel;
109
use Illuminate\Database\Eloquent\Relations\Relation;
1110
use Illuminate\Support\Arr;
11+
use Illuminate\Support\Facades\Date;
1212
use Illuminate\Support\Str;
1313
use Jenssegers\Mongodb\Query\Builder as QueryBuilder;
1414
use MongoDB\BSON\Binary;
@@ -89,7 +89,7 @@ public function fromDateTime($value)
8989
$value = parent::asDateTime($value);
9090
}
9191

92-
return new UTCDateTime($value->getTimestamp() * 1000);
92+
return new UTCDateTime($value->format('Uv'));
9393
}
9494

9595
/**
@@ -99,7 +99,7 @@ protected function asDateTime($value)
9999
{
100100
// Convert UTCDateTime instances.
101101
if ($value instanceof UTCDateTime) {
102-
return Carbon::createFromTimestamp($value->toDateTime()->getTimestamp());
102+
return Date::createFromTimestampMs($value->toDateTime()->format('Uv'));
103103
}
104104

105105
return parent::asDateTime($value);
@@ -118,7 +118,7 @@ public function getDateFormat()
118118
*/
119119
public function freshTimestamp()
120120
{
121-
return new UTCDateTime(Carbon::now());
121+
return new UTCDateTime(Date::now()->format('Uv'));
122122
}
123123

124124
/**

src/Jenssegers/Mongodb/MongodbQueueServiceProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Jenssegers\Mongodb;
44

5-
use DB;
5+
use Illuminate\Support\Facades\DB;
66
use Illuminate\Queue\QueueServiceProvider;
77
use Jenssegers\Mongodb\Queue\Failed\MongoFailedJobProvider;
88

src/Jenssegers/Mongodb/Query/Builder.php

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,20 @@
88
use Illuminate\Database\Query\Expression;
99
use Illuminate\Support\Arr;
1010
use Illuminate\Support\Collection;
11+
use Illuminate\Support\LazyCollection;
1112
use Illuminate\Support\Str;
1213
use Jenssegers\Mongodb\Connection;
1314
use MongoCollection;
1415
use MongoDB\BSON\Binary;
1516
use MongoDB\BSON\ObjectID;
1617
use MongoDB\BSON\Regex;
1718
use MongoDB\BSON\UTCDateTime;
19+
use RuntimeException;
1820

21+
/**
22+
* Class Builder
23+
* @package Jenssegers\Mongodb\Query
24+
*/
1925
class Builder extends BaseBuilder
2026
{
2127
/**
@@ -209,12 +215,25 @@ public function get($columns = [])
209215
return $this->getFresh($columns);
210216
}
211217

218+
/**
219+
* @inheritdoc
220+
*/
221+
public function cursor($columns = [])
222+
{
223+
$result = $this->getFresh($columns, true);
224+
if ($result instanceof LazyCollection) {
225+
return $result;
226+
}
227+
throw new RuntimeException("Query not compatible with cursor");
228+
}
229+
212230
/**
213231
* Execute the query as a fresh "select" statement.
214232
* @param array $columns
215-
* @return array|static[]|Collection
233+
* @param bool $returnLazy
234+
* @return array|static[]|Collection|LazyCollection
216235
*/
217-
public function getFresh($columns = [])
236+
public function getFresh($columns = [], $returnLazy = false)
218237
{
219238
// If no columns have been specified for the select statement, we will set them
220239
// here to either the passed columns, or the standard default of retrieving
@@ -294,7 +313,7 @@ public function getFresh($columns = [])
294313
}
295314
}
296315
}
297-
316+
298317
// The _id field is mandatory when using grouping.
299318
if ($group && empty($group['_id'])) {
300319
$group['_id'] = null;
@@ -402,6 +421,14 @@ public function getFresh($columns = [])
402421
// Execute query and get MongoCursor
403422
$cursor = $this->collection->find($wheres, $options);
404423

424+
if ($returnLazy) {
425+
return LazyCollection::make(function () use ($cursor) {
426+
foreach ($cursor as $item) {
427+
yield $item;
428+
}
429+
});
430+
}
431+
405432
// Return results as an array with numeric keys
406433
$results = iterator_to_array($cursor, false);
407434
return $this->useCollections ? new Collection($results) : $results;
@@ -930,18 +957,18 @@ protected function compileWheres()
930957
if (is_array($where['value'])) {
931958
array_walk_recursive($where['value'], function (&$item, $key) {
932959
if ($item instanceof DateTime) {
933-
$item = new UTCDateTime($item->getTimestamp() * 1000);
960+
$item = new UTCDateTime($item->format('Uv'));
934961
}
935962
});
936963
} else {
937964
if ($where['value'] instanceof DateTime) {
938-
$where['value'] = new UTCDateTime($where['value']->getTimestamp() * 1000);
965+
$where['value'] = new UTCDateTime($where['value']->format('Uv'));
939966
}
940967
}
941968
} elseif (isset($where['values'])) {
942969
array_walk_recursive($where['values'], function (&$item, $key) {
943970
if ($item instanceof DateTime) {
944-
$item = new UTCDateTime($item->getTimestamp() * 1000);
971+
$item = new UTCDateTime($item->format('Uv'));
945972
}
946973
});
947974
}
@@ -993,6 +1020,7 @@ protected function compileWhereAll(array $where)
9931020
protected function compileWhereBasic(array $where)
9941021
{
9951022
extract($where);
1023+
$is_numeric = false;
9961024

9971025
// Replace like or not like with a Regex instance.
9981026
if (in_array($operator, ['like', 'not like'])) {
@@ -1004,15 +1032,21 @@ protected function compileWhereBasic(array $where)
10041032

10051033
// Convert to regular expression.
10061034
$regex = preg_replace('#(^|[^\\\])%#', '$1.*', preg_quote($value));
1035+
$plain_value = $value;
10071036

10081037
// Convert like to regular expression.
10091038
if (!Str::startsWith($value, '%')) {
10101039
$regex = '^' . $regex;
1040+
} else {
1041+
$plain_value = Str::replaceFirst('%', null, $plain_value);
10111042
}
10121043
if (!Str::endsWith($value, '%')) {
10131044
$regex .= '$';
1045+
} else {
1046+
$plain_value = Str::replaceLast('%', null, $plain_value);
10141047
}
10151048

1049+
$is_numeric = is_numeric($plain_value);
10161050
$value = new Regex($regex, 'i');
10171051
} // Manipulate regexp operations.
10181052
elseif (in_array($operator, ['regexp', 'not regexp', 'regex', 'not regex'])) {
@@ -1032,7 +1066,11 @@ protected function compileWhereBasic(array $where)
10321066
}
10331067

10341068
if (!isset($operator) || $operator == '=') {
1035-
$query = [$column => $value];
1069+
if ($is_numeric) {
1070+
$query = ['$where' => '/^'.$value->getPattern().'/.test(this.'.$column.')'];
1071+
} else {
1072+
$query = [$column => $value];
1073+
}
10361074
} elseif (array_key_exists($operator, $this->conversion)) {
10371075
$query = [$column => [$this->conversion[$operator] => $value]];
10381076
} else {

src/Jenssegers/Mongodb/Queue/Failed/MongoFailedJobProvider.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@ class MongoFailedJobProvider extends DatabaseFailedJobProvider
1212
* @param string $connection
1313
* @param string $queue
1414
* @param string $payload
15+
* @param \Exception $exception
1516
* @return void
1617
*/
1718
public function log($connection, $queue, $payload, $exception)
1819
{
1920
$failed_at = Carbon::now()->getTimestamp();
2021

22+
$exception = (string) $exception;
23+
2124
$this->getTable()->insert(compact('connection', 'queue', 'payload', 'failed_at', 'exception'));
2225
}
2326

src/Jenssegers/Mongodb/Relations/BelongsToMany.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ protected function buildDictionary(Collection $results)
265265
/**
266266
* @inheritdoc
267267
*/
268-
protected function newPivotQuery()
268+
public function newPivotQuery()
269269
{
270270
return $this->newRelatedQuery();
271271
}

src/Jenssegers/Mongodb/Relations/EmbedsOne.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88

99
class EmbedsOne extends EmbedsOneOrMany
1010
{
11-
/**
12-
* @inheritdoc
13-
*/
1411
public function initRelation(array $models, $relation)
1512
{
1613
foreach ($models as $model) {
@@ -20,14 +17,19 @@ public function initRelation(array $models, $relation)
2017
return $models;
2118
}
2219

23-
/**
24-
* @inheritdoc
25-
*/
2620
public function getResults()
2721
{
2822
return $this->toModel($this->getEmbedded());
2923
}
3024

25+
public function getEager()
26+
{
27+
$eager = $this->get();
28+
29+
// EmbedsOne only brings one result, Eager needs a collection!
30+
return $this->toCollection([$eager]);
31+
}
32+
3133
/**
3234
* Save a new model and attach it to the parent model.
3335
* @param Model $model

0 commit comments

Comments
 (0)