Skip to content

Commit b5b37a3

Browse files
authored
Merge branch 'master' into PHPLIB-1063
2 parents 31261a8 + 58559e3 commit b5b37a3

File tree

149 files changed

+2070
-1667
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

149 files changed

+2070
-1667
lines changed

.github/workflows/static-analysis.yml

+3
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,6 @@ jobs:
6565

6666
- name: "Run Psalm"
6767
run: "vendor/bin/psalm --show-info=false --stats --output-format=github --threads=$(nproc)"
68+
69+
- name: "Run Rector"
70+
run: "vendor/bin/rector --ansi --dry-run"

CONTRIBUTING.md

+11
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,17 @@ possible it can be added to the baseline using `set-baseline`:
151151
$ vendor/bin/psalm --set-baseline=psalm-baseline.xml
152152
```
153153

154+
## Automatic code refactoring
155+
156+
The library uses [rector](https://getrector.com/) to refactor the code for new features.
157+
To run automatic refactoring, use the `rector` command:
158+
159+
```
160+
$ vendor/bin/rector
161+
```
162+
163+
New rules can be added to the `rector.php` configuration file.
164+
154165
## Documentation
155166

156167
Documentation for the library lives in the `docs/` directory and is built with

composer.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
"symfony/polyfill-php80": "^1.27"
1919
},
2020
"require-dev": {
21-
"squizlabs/php_codesniffer": "^3.7",
2221
"doctrine/coding-standard": "^11.1",
22+
"rector/rector": "^0.16.0",
23+
"squizlabs/php_codesniffer": "^3.7",
2324
"symfony/phpunit-bridge": "^5.2",
2425
"vimeo/psalm": "^4.28"
2526
},
@@ -39,6 +40,7 @@
3940
"config": {
4041
"allow-plugins": {
4142
"dealerdirect/phpcodesniffer-composer-installer": true
42-
}
43+
},
44+
"sort-packages": true
4345
}
4446
}

examples/aggregate.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use function MongoDB\BSON\fromPHP;
1212
use function MongoDB\BSON\toRelaxedExtendedJSON;
1313
use function printf;
14-
use function rand;
14+
use function random_int;
1515

1616
require __DIR__ . '/../vendor/autoload.php';
1717

@@ -28,7 +28,7 @@ function toJSON(object $document): string
2828
$documents = [];
2929

3030
for ($i = 0; $i < 100; $i++) {
31-
$documents[] = ['randomValue' => rand(0, 1000)];
31+
$documents[] = ['randomValue' => random_int(0, 1000)];
3232
}
3333

3434
$collection->insertMany($documents);

phpcs.xml.dist

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<file>examples</file>
1414
<file>tests</file>
1515
<file>tools</file>
16+
<file>rector.php</file>
1617

1718
<!-- Target minimum supported PHP version -->
1819
<config name="php_version" value="70200"/>

psalm-baseline.xml

+24-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
<code>$type</code>
1010
</PropertyNotSetInConstructor>
1111
</file>
12+
<file src="src/ChangeStream.php">
13+
<DeprecatedConstant occurrences="1">
14+
<code>self::CURSOR_NOT_FOUND</code>
15+
</DeprecatedConstant>
16+
</file>
1217
<file src="src/Client.php">
1318
<MixedArgument occurrences="1">
1419
<code>$driverOptions['driver'] ?? []</code>
@@ -36,8 +41,9 @@
3641
</UnsafeInstantiation>
3742
</file>
3843
<file src="src/Exception/InvalidArgumentException.php">
39-
<UnsafeInstantiation occurrences="1">
44+
<UnsafeInstantiation occurrences="2">
4045
<code>new static(sprintf('Expected %s to have type "%s" but found "%s"', $name, $expectedType, get_debug_type($value)))</code>
46+
<code>new static('Expected update operator(s) or non-empty pipeline for ' . $name)</code>
4147
</UnsafeInstantiation>
4248
</file>
4349
<file src="src/Exception/ResumeTokenException.php">
@@ -274,9 +280,13 @@
274280
<MixedArgument occurrences="1">
275281
<code>$fieldName</code>
276282
</MixedArgument>
277-
<MixedAssignment occurrences="1">
283+
<MixedAssignment occurrences="2">
278284
<code>$fieldName</code>
285+
<code>$type</code>
279286
</MixedAssignment>
287+
<MixedOperand occurrences="1">
288+
<code>$type</code>
289+
</MixedOperand>
280290
<MixedReturnStatement occurrences="1">
281291
<code>$this-&gt;index['name']</code>
282292
</MixedReturnStatement>
@@ -304,7 +314,7 @@
304314
<DocblockTypeContradiction occurrences="1">
305315
<code>is_array($operation)</code>
306316
</DocblockTypeContradiction>
307-
<MixedArgument occurrences="12">
317+
<MixedArgument occurrences="13">
308318
<code>$args</code>
309319
<code>$args</code>
310320
<code>$args</code>
@@ -316,9 +326,10 @@
316326
<code>$args[1]</code>
317327
<code>$args[1]</code>
318328
<code>$args[1]</code>
329+
<code>$args[1]</code>
319330
<code>$args[2]</code>
320331
</MixedArgument>
321-
<MixedArrayAccess occurrences="25">
332+
<MixedArrayAccess occurrences="28">
322333
<code>$args[0]</code>
323334
<code>$args[0]</code>
324335
<code>$args[0]</code>
@@ -333,6 +344,9 @@
333344
<code>$args[1]</code>
334345
<code>$args[1]</code>
335346
<code>$args[1]</code>
347+
<code>$args[1]</code>
348+
<code>$args[1]</code>
349+
<code>$args[1]</code>
336350
<code>$args[2]</code>
337351
<code>$args[2]</code>
338352
<code>$args[2]</code>
@@ -345,7 +359,8 @@
345359
<code>$args[2]['upsert']</code>
346360
<code>$args[2]['upsert']</code>
347361
</MixedArrayAccess>
348-
<MixedArrayAssignment occurrences="11">
362+
<MixedArrayAssignment occurrences="12">
363+
<code>$args[1]</code>
349364
<code>$args[1]</code>
350365
<code>$args[1]</code>
351366
<code>$args[2]</code>
@@ -418,6 +433,9 @@
418433
<code>! is_array($encryptedFields['fields'])</code>
419434
<code>! is_array($field) &amp;&amp; ! is_object($field)</code>
420435
</DocblockTypeContradiction>
436+
<MixedArgument occurrences="1">
437+
<code>$this-&gt;options['encryptedFields']</code>
438+
</MixedArgument>
421439
</file>
422440
<file src="src/Operation/CreateIndexes.php">
423441
<DocblockTypeContradiction occurrences="1">
@@ -774,10 +792,9 @@
774792
<code>$typeMap['fieldPaths'][$fieldPath]</code>
775793
<code>$typeMap['fieldPaths'][substr($fieldPath, 0, -2)]</code>
776794
</MixedArrayAssignment>
777-
<MixedAssignment occurrences="6">
795+
<MixedAssignment occurrences="5">
778796
<code>$element[$key]</code>
779797
<code>$type</code>
780-
<code>$type</code>
781798
<code>$typeMap['fieldPaths'][$fieldPath . '.' . $existingFieldPath]</code>
782799
<code>$typeMap['fieldPaths'][$fieldPath]</code>
783800
<code>$value</code>

rector.php

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
use Rector\Config\RectorConfig;
4+
use Rector\DeadCode\Rector\ClassLike\RemoveAnnotationRector;
5+
use Rector\Php56\Rector\FunctionLike\AddDefaultValueForUndefinedVariableRector;
6+
use Rector\Php71\Rector\FuncCall\RemoveExtraParametersRector;
7+
use Rector\Set\ValueObject\LevelSetList;
8+
9+
return static function (RectorConfig $rectorConfig): void {
10+
$rectorConfig->paths([
11+
__DIR__ . '/examples',
12+
__DIR__ . '/src',
13+
__DIR__ . '/tests',
14+
__DIR__ . '/tools',
15+
]);
16+
17+
// Modernize code
18+
$rectorConfig->sets([LevelSetList::UP_TO_PHP_72]);
19+
20+
$rectorConfig->skip([
21+
// Falsely detect unassigned variables in code paths stopped by PHPUnit\Framework\Assert::markTestSkipped()
22+
AddDefaultValueForUndefinedVariableRector::class => [
23+
__DIR__ . '/tests/',
24+
],
25+
// @see https://github.com/phpstan/phpstan-src/pull/2429
26+
RemoveExtraParametersRector::class => [
27+
__DIR__ . '/src/Operation/',
28+
],
29+
]);
30+
31+
// All classes are public API by default, unless marked with @internal.
32+
$rectorConfig->ruleWithConfiguration(RemoveAnnotationRector::class, ['api']);
33+
};

src/ChangeStream.php

+8-14
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,20 @@
3333
/**
3434
* Iterator for a change stream.
3535
*
36-
* @psalm-type ResumeCallable = callable(array|object|null, bool): ChangeStreamIterator
37-
*
38-
* @api
3936
* @see \MongoDB\Collection::watch()
4037
* @see https://mongodb.com/docs/manual/reference/method/db.watch/#mongodb-method-db.watch
38+
*
39+
* @psalm-type ResumeCallable = callable(array|object|null, bool): ChangeStreamIterator
4140
*/
4241
class ChangeStream implements Iterator
4342
{
4443
/**
4544
* @deprecated 1.4
46-
* @todo Remove this in 2.0 (see: PHPLIB-360)
45+
* @todo make this constant private in 2.0 (see: PHPLIB-360)
4746
*/
4847
public const CURSOR_NOT_FOUND = 43;
4948

50-
/** @var int */
51-
private static $cursorNotFound = 43;
52-
53-
/** @var int[] */
54-
private static $resumableErrorCodes = [
49+
private const RESUMABLE_ERROR_CODES = [
5550
6, // HostUnreachable
5651
7, // HostNotFound
5752
89, // NetworkTimeout
@@ -71,8 +66,7 @@ class ChangeStream implements Iterator
7166
133, // FailedToSatisfyReadPreference
7267
];
7368

74-
/** @var int */
75-
private static $wireVersionForResumableChangeStreamError = 9;
69+
private const WIRE_VERSION_FOR_RESUMABLE_CHANGE_STREAM_ERROR = 9;
7670

7771
/** @var ResumeCallable|null */
7872
private $resumeCallable;
@@ -206,15 +200,15 @@ private function isResumableError(RuntimeException $exception): bool
206200
return false;
207201
}
208202

209-
if ($exception->getCode() === self::$cursorNotFound) {
203+
if ($exception->getCode() === self::CURSOR_NOT_FOUND) {
210204
return true;
211205
}
212206

213-
if (server_supports_feature($this->iterator->getServer(), self::$wireVersionForResumableChangeStreamError)) {
207+
if (server_supports_feature($this->iterator->getServer(), self::WIRE_VERSION_FOR_RESUMABLE_CHANGE_STREAM_ERROR)) {
214208
return $exception->hasErrorLabel('ResumableChangeStreamError');
215209
}
216210

217-
return in_array($exception->getCode(), self::$resumableErrorCodes);
211+
return in_array($exception->getCode(), self::RESUMABLE_ERROR_CODES);
218212
}
219213

220214
/**

src/Client.php

+5-7
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,13 @@ class Client
4646
{
4747
public const DEFAULT_URI = 'mongodb://127.0.0.1/';
4848

49-
/** @var array */
50-
private static $defaultTypeMap = [
49+
private const DEFAULT_TYPE_MAP = [
5150
'array' => BSONArray::class,
5251
'document' => BSONDocument::class,
5352
'root' => BSONDocument::class,
5453
];
5554

56-
/** @var string */
57-
private static $handshakeSeparator = ' / ';
55+
private const HANDSHAKE_SEPARATOR = '/';
5856

5957
/** @var string|null */
6058
private static $version;
@@ -102,7 +100,7 @@ class Client
102100
*/
103101
public function __construct(?string $uri = null, array $uriOptions = [], array $driverOptions = [])
104102
{
105-
$driverOptions += ['typeMap' => self::$defaultTypeMap];
103+
$driverOptions += ['typeMap' => self::DEFAULT_TYPE_MAP];
106104

107105
if (! is_array($driverOptions['typeMap'])) {
108106
throw InvalidArgumentException::invalidType('"typeMap" driver option', $driverOptions['typeMap'], 'array');
@@ -405,15 +403,15 @@ private function mergeDriverInfo(array $driver): array
405403
throw InvalidArgumentException::invalidType('"name" handshake option', $driver['name'], 'string');
406404
}
407405

408-
$mergedDriver['name'] .= self::$handshakeSeparator . $driver['name'];
406+
$mergedDriver['name'] .= self::HANDSHAKE_SEPARATOR . $driver['name'];
409407
}
410408

411409
if (isset($driver['version'])) {
412410
if (! is_string($driver['version'])) {
413411
throw InvalidArgumentException::invalidType('"version" handshake option', $driver['version'], 'string');
414412
}
415413

416-
$mergedDriver['version'] .= self::$handshakeSeparator . $driver['version'];
414+
$mergedDriver['version'] .= self::HANDSHAKE_SEPARATOR . $driver['version'];
417415
}
418416

419417
if (isset($driver['platform'])) {

src/Collection.php

+5-7
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,13 @@
6969

7070
class Collection
7171
{
72-
/** @var array */
73-
private static $defaultTypeMap = [
72+
private const DEFAULT_TYPE_MAP = [
7473
'array' => BSONArray::class,
7574
'document' => BSONDocument::class,
7675
'root' => BSONDocument::class,
7776
];
7877

79-
/** @var integer */
80-
private static $wireVersionForReadConcernWithWriteStage = 8;
78+
private const WIRE_VERSION_FOR_READ_CONCERN_WITH_WRITE_STAGE = 8;
8179

8280
/** @var string */
8381
private $collectionName;
@@ -158,7 +156,7 @@ public function __construct(Manager $manager, string $databaseName, string $coll
158156
$this->collectionName = $collectionName;
159157
$this->readConcern = $options['readConcern'] ?? $this->manager->getReadConcern();
160158
$this->readPreference = $options['readPreference'] ?? $this->manager->getReadPreference();
161-
$this->typeMap = $options['typeMap'] ?? self::$defaultTypeMap;
159+
$this->typeMap = $options['typeMap'] ?? self::DEFAULT_TYPE_MAP;
162160
$this->writeConcern = $options['writeConcern'] ?? $this->manager->getWriteConcern();
163161
}
164162

@@ -229,7 +227,7 @@ public function aggregate(array $pipeline, array $options = [])
229227
if (
230228
! isset($options['readConcern']) &&
231229
! is_in_transaction($options) &&
232-
( ! $hasWriteStage || server_supports_feature($server, self::$wireVersionForReadConcernWithWriteStage))
230+
( ! $hasWriteStage || server_supports_feature($server, self::WIRE_VERSION_FOR_READ_CONCERN_WITH_WRITE_STAGE))
233231
) {
234232
$options['readConcern'] = $this->readConcern;
235233
}
@@ -968,7 +966,7 @@ public function mapReduce(JavascriptInterface $map, JavascriptInterface $reduce,
968966

969967
// Check if the out option is inline because we will want to coerce a primary read preference if not
970968
if ($hasOutputCollection) {
971-
$options['readPreference'] = new ReadPreference(ReadPreference::RP_PRIMARY);
969+
$options['readPreference'] = new ReadPreference(ReadPreference::PRIMARY);
972970
}
973971

974972
$server = select_server($this->manager, $options);

src/Database.php

+4-6
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,13 @@
5353

5454
class Database
5555
{
56-
/** @var array */
57-
private static $defaultTypeMap = [
56+
private const DEFAULT_TYPE_MAP = [
5857
'array' => BSONArray::class,
5958
'document' => BSONDocument::class,
6059
'root' => BSONDocument::class,
6160
];
6261

63-
/** @var integer */
64-
private static $wireVersionForReadConcernWithWriteStage = 8;
62+
private const WIRE_VERSION_FOR_READ_CONCERN_WITH_WRITE_STAGE = 8;
6563

6664
/** @var string */
6765
private $databaseName;
@@ -134,7 +132,7 @@ public function __construct(Manager $manager, string $databaseName, array $optio
134132
$this->databaseName = $databaseName;
135133
$this->readConcern = $options['readConcern'] ?? $this->manager->getReadConcern();
136134
$this->readPreference = $options['readPreference'] ?? $this->manager->getReadPreference();
137-
$this->typeMap = $options['typeMap'] ?? self::$defaultTypeMap;
135+
$this->typeMap = $options['typeMap'] ?? self::DEFAULT_TYPE_MAP;
138136
$this->writeConcern = $options['writeConcern'] ?? $this->manager->getWriteConcern();
139137
}
140138

@@ -217,7 +215,7 @@ public function aggregate(array $pipeline, array $options = [])
217215
if (
218216
! isset($options['readConcern']) &&
219217
! is_in_transaction($options) &&
220-
( ! $hasWriteStage || server_supports_feature($server, self::$wireVersionForReadConcernWithWriteStage))
218+
( ! $hasWriteStage || server_supports_feature($server, self::WIRE_VERSION_FOR_READ_CONCERN_WITH_WRITE_STAGE))
221219
) {
222220
$options['readConcern'] = $this->readConcern;
223221
}

0 commit comments

Comments
 (0)