diff --git a/.github/workflows/build-ci-atlas.yml b/.github/workflows/build-ci-atlas.yml
index 58b05907c..f8a9ac1c3 100644
--- a/.github/workflows/build-ci-atlas.yml
+++ b/.github/workflows/build-ci-atlas.yml
@@ -1,13 +1,13 @@
-name: "Atlas CI"
+name: Atlas CI
on:
push:
branches:
- - "[0-9]+.[0-9x]+"
+ - '[0-9]+.[0-9x]+'
pull_request:
branches:
- - "[0-9]+.[0-9x]+"
- - "feature/*"
+ - '[0-9]+.[0-9x]+'
+ - feature/*
env:
MONGODB_EXT_V1: mongodb-1.21.0
@@ -15,39 +15,33 @@ env:
jobs:
build:
- runs-on: "ubuntu-latest"
+ runs-on: ubuntu-latest
- name: "PHP/${{ matrix.php }} Laravel/${{ matrix.laravel }} Driver/${{ matrix.driver }}"
+ name: PHP/${{ matrix.php }} Laravel/${{ matrix.laravel }} Driver/${{ matrix.driver }}
strategy:
matrix:
- php:
- - "8.2"
- - "8.3"
- - "8.4"
- - "8.5"
- laravel:
- - "12.*"
- driver:
- - 2
+ php: ['8.2', '8.3', '8.4', '8.5']
+ laravel: ['12.*', '13.*']
+ driver: [2]
include:
- # Test Laravel 10
- - php: "8.1"
- laravel: "10.*"
+ - php: '8.1'
+ laravel: 10.*
driver: 1
- # Test Laravel 11
- - php: "8.2"
- laravel: "11.*"
+ - php: '8.2'
+ laravel: 11.*
driver: 1
- # Test Driver v1
- - php: "8.4"
- laravel: "12.*"
+ - php: '8.4'
+ laravel: 12.*
driver: 1
+ exclude:
+ - laravel: 13.*
+ php: '8.2'
steps:
- - uses: "actions/checkout@v6"
+ - uses: actions/checkout@v6
- - name: "Create MongoDB Atlas Local"
+ - name: Create MongoDB Atlas Local
run: |
docker run --name mongodb -p 27017:27017 --detach mongodb/mongodb-atlas-local:latest
until docker exec --tty mongodb mongosh --eval "db.runCommand({ ping: 1 })"; do
@@ -57,7 +51,7 @@ jobs:
sleep 1
done
- - name: "Show MongoDB server status"
+ - name: Show MongoDB server status
run: |
docker exec --tty mongodb mongosh --eval "db.runCommand({ serverStatus: 1 })"
@@ -67,39 +61,39 @@ jobs:
with:
php-version: ${{ matrix.php }}
extensions: ${{ matrix.driver == 1 && env.MONGODB_EXT_V1 || env.MONGODB_EXT_V2 }}
- key: "extcache-v1"
+ key: extcache-v1
- - name: "Installing php"
- uses: "shivammathur/setup-php@v2"
+ - name: Installing php
+ uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- extensions: "curl,mbstring,xdebug,${{ matrix.driver == 1 && env.MONGODB_EXT_V1 || env.MONGODB_EXT_V2 }}"
- coverage: "xdebug"
- tools: "composer"
+ extensions: curl,mbstring,xdebug,${{ matrix.driver == 1 && env.MONGODB_EXT_V1 || env.MONGODB_EXT_V2 }}
+ coverage: xdebug
+ tools: composer
- - name: "Show Docker version"
+ - name: Show Docker version
if: ${{ runner.debug }}
- run: "docker version && env"
+ run: docker version && env
- - name: "Restrict Laravel version"
- run: "composer require --dev --no-update 'laravel/framework:${{ matrix.laravel }}'"
+ - name: Restrict Laravel version
+ run: composer require --dev --no-update 'laravel/framework:${{ matrix.laravel }}'
- - name: "Download Composer cache dependencies from cache"
- id: "composer-cache"
+ - name: Download Composer cache dependencies from cache
+ id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- - name: "Cache Composer dependencies"
- uses: "actions/cache@v5"
+ - name: Cache Composer dependencies
+ uses: actions/cache@v5
with:
path: ${{ steps.composer-cache.outputs.dir }}
- key: "${{ matrix.os }}-composer-${{ hashFiles('**/composer.json') }}"
- restore-keys: "${{ matrix.os }}-composer-"
+ key: ${{ matrix.os }}-composer-${{ hashFiles('**/composer.json') }}
+ restore-keys: ${{ matrix.os }}-composer-
- - name: "Install dependencies"
+ - name: Install dependencies
run: |
composer update --no-interaction
- - name: "Run tests"
+ - name: Run tests
run: |
export MONGODB_URI="mongodb://127.0.0.1:27017/?directConnection=true"
php -d zend.assertions=1 ./vendor/bin/phpunit --coverage-clover coverage.xml --group atlas-search
diff --git a/.github/workflows/build-ci.yml b/.github/workflows/build-ci.yml
index 3bd66d839..8aa8e96da 100644
--- a/.github/workflows/build-ci.yml
+++ b/.github/workflows/build-ci.yml
@@ -1,13 +1,13 @@
-name: "CI"
+name: CI
on:
push:
branches:
- - "[0-9]+.[0-9x]+"
+ - '[0-9]+.[0-9x]+'
pull_request:
branches:
- - "[0-9]+.[0-9x]+"
- - "feature/*"
+ - '[0-9]+.[0-9x]+'
+ - feature/*
env:
MONGODB_EXT_V1: mongodb-1.21.0
@@ -15,68 +15,59 @@ env:
jobs:
build:
- runs-on: "ubuntu-latest"
+ runs-on: ubuntu-latest
- name: "PHP/${{ matrix.php }} Laravel/${{ matrix.laravel }} Driver/${{ matrix.driver }} Server/${{ matrix.mongodb }} ${{ matrix.mode }}"
+ name: PHP/${{ matrix.php }} Laravel/${{ matrix.laravel }} Driver/${{ matrix.driver }} Server/${{ matrix.mongodb }} ${{ matrix.mode }}
strategy:
matrix:
- mongodb:
- - "8.0"
- php:
- - "8.2"
- - "8.3"
- - "8.4"
- - "8.5"
- laravel:
- - "12.*"
- driver:
- - 2
+ mongodb: ['8.0']
+ php: ['8.2', '8.3', '8.4', '8.5']
+ laravel: ['12.*', '13.*']
+ driver: [2]
include:
- # Test Lowest dependencies
- - php: "8.1"
- laravel: "10.*"
- mongodb: "5.0"
- mode: "low-deps"
+ - php: '8.1'
+ laravel: 10.*
+ mongodb: '5.0'
+ mode: low-deps
driver: 1
- # Test Driver v1
- - php: "8.3"
- laravel: "10.*"
- mongodb: "4.4"
+ - php: '8.3'
+ laravel: 10.*
+ mongodb: '4.4'
driver: 1
- - php: "8.4"
- laravel: "12.*"
- mongodb: "8.0"
+ - php: '8.4'
+ laravel: 12.*
+ mongodb: '8.0'
driver: 1
- # Test Laravel 10
- - php: "8.5"
- laravel: "10.*"
- mongodb: "8.0"
- # Test Laravel 11
- - php: "8.5"
- laravel: "11.*"
- mongodb: "8.0"
- # Test all server versions with the lowest PHP and latest Laravel
- - php: "8.2"
- laravel: "12.*"
- mongodb: "4.4"
- - php: "8.2"
- laravel: "12.*"
- mongodb: "5.0"
- - php: "8.2"
- laravel: "12.*"
- mongodb: "6.0"
- - php: "8.2"
- laravel: "12.*"
- mongodb: "7.0"
- - php: "8.2"
- laravel: "12.*"
- mongodb: "8.0"
+ - php: '8.5'
+ laravel: 10.*
+ mongodb: '8.0'
+ - php: '8.5'
+ laravel: 11.*
+ mongodb: '8.0'
+ - php: '8.2'
+ laravel: 12.*
+ mongodb: '4.4'
+ - php: '8.2'
+ laravel: 12.*
+ mongodb: '5.0'
+ - php: '8.2'
+ laravel: 12.*
+ mongodb: '6.0'
+ - php: '8.2'
+ laravel: 12.*
+ mongodb: '7.0'
+ - php: '8.2'
+ laravel: 12.*
+ mongodb: '8.0'
+ exclude:
+ - laravel: 13.*
+ php: '8.2'
steps:
- - uses: "actions/checkout@v6"
+ - uses: actions/checkout@v6
- - name: "Create MongoDB Replica Set"
+ - name: Create MongoDB Replica Set
run: |
docker run --name mongodb -p 27017:27017 -e MONGO_INITDB_DATABASE=unittest --detach mongo:${{ matrix.mongodb }} mongod --replSet rs --setParameter transactionLifetimeLimitSeconds=5
@@ -86,7 +77,7 @@ jobs:
done
sudo docker exec --tty mongodb $MONGOSH_BIN --eval "rs.initiate({\"_id\":\"rs\",\"members\":[{\"_id\":0,\"host\":\"127.0.0.1:27017\" }]})"
- - name: "Show MongoDB server status"
+ - name: Show MongoDB server status
run: |
if [ "${{ matrix.mongodb }}" = "4.4" ]; then MONGOSH_BIN="mongo"; else MONGOSH_BIN="mongosh"; fi
docker exec --tty mongodb $MONGOSH_BIN --eval "db.runCommand({ serverStatus: 1 })"
@@ -97,40 +88,41 @@ jobs:
with:
php-version: ${{ matrix.php }}
extensions: ${{ matrix.driver == 1 && env.MONGODB_EXT_V1 || env.MONGODB_EXT_V2 }}
- key: "extcache-v1"
+ key: extcache-v1
- - name: "Installing php"
- uses: "shivammathur/setup-php@v2"
+ - name: Installing php
+ uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- extensions: "curl,mbstring,xdebug,${{ matrix.driver == 1 && env.MONGODB_EXT_V1 || env.MONGODB_EXT_V2 }}"
- coverage: "xdebug"
- tools: "composer"
+ extensions: curl,mbstring,xdebug,${{ matrix.driver == 1 && env.MONGODB_EXT_V1 || env.MONGODB_EXT_V2 }}
+ coverage: xdebug
+ tools: composer
- - name: "Show Docker version"
+ - name: Show Docker version
if: ${{ runner.debug }}
- run: "docker version && env"
+ run: docker version && env
- - name: "Restrict Laravel version"
- run: "composer require --dev --no-update 'laravel/framework:${{ matrix.laravel }}'"
+ - name: Restrict Laravel version
+ run: composer require --dev --no-update 'laravel/framework:${{ matrix.laravel }}'
- - name: "Download Composer cache dependencies from cache"
- id: "composer-cache"
+ - name: Download Composer cache dependencies from cache
+ id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- - name: "Cache Composer dependencies"
- uses: "actions/cache@v5"
+ - name: Cache Composer dependencies
+ uses: actions/cache@v5
with:
path: ${{ steps.composer-cache.outputs.dir }}
- key: "${{ matrix.os }}-composer-${{ hashFiles('**/composer.json') }}"
- restore-keys: "${{ matrix.os }}-composer-"
+ key: ${{ matrix.os }}-composer-${{ hashFiles('**/composer.json') }}
+ restore-keys: ${{ matrix.os }}-composer-
- - name: "Install dependencies"
+ - name: Install dependencies
run: |
composer update --no-interaction \
$([[ "${{ matrix.mode }}" == low-deps ]] && echo ' --prefer-lowest') \
$([[ "${{ matrix.mode }}" == ignore-php-req ]] && echo ' --ignore-platform-req=php+')
- - name: "Run tests"
+
+ - name: Run tests
run: |
export MONGODB_URI="mongodb://127.0.0.1:27017/?replicaSet=rs"
- php -d zend.assertions=1 ./vendor/bin/phpunit --coverage-clover coverage.xml --exclude-group atlas-search
+ php -d zend.assertions=1 ./vendor/bin/phpunit --coverage-clover coverage.xml --exclude-group atlas-search --testdox
diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
index b107a199d..c34c37833 100644
--- a/.github/workflows/static-analysis.yml
+++ b/.github/workflows/static-analysis.yml
@@ -1,51 +1,49 @@
-name: "Static Analysis"
+name: Static Analysis
on:
push:
branches:
- - "[0-9]+.[0-9x]+"
+ - [0-9]+.[0-9x]+
pull_request:
branches:
- - "[0-9]+.[0-9x]+"
- - "feature/*"
+ - [0-9]+.[0-9x]+
+ - feature/*
workflow_call:
inputs:
ref:
- description: "The git ref to check"
+ description: The git ref to check
type: string
required: true
env:
- PHP_VERSION: "8.5"
- DRIVER_VERSION: "stable"
+ PHP_VERSION: '8.5'
+ DRIVER_VERSION: stable
MONGODB_EXT_V1: mongodb-1.21.0
MONGODB_EXT_V2: mongodb-mongodb/mongo-php-driver@v2.x
jobs:
phpstan:
- name: "PHP/${{ matrix.php }} Driver/${{ matrix.driver }}"
- runs-on: "ubuntu-22.04"
+ name: PHP/${{ matrix.php }} Driver/${{ matrix.driver }}
+
+ runs-on: ubuntu-22.04
+
continue-on-error: true
+
strategy:
matrix:
- php:
- - '8.1'
- - '8.2'
- - '8.3'
- - '8.4'
- - '8.5'
- driver:
- - 2
+ php: ['8.1', '8.2', '8.3', '8.4', '8.5']
+ driver: [2]
include:
- - php: "8.4"
+ - php: '8.4'
driver: 1
+
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.ref }}
- - name: "Get SHA hash of checked out ref"
+ - name: Get SHA hash of checked out ref
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
echo CHECKED_OUT_SHA=$(git rev-parse HEAD) >> $GITHUB_ENV
@@ -56,13 +54,13 @@ jobs:
with:
php-version: ${{ matrix.php }}
extensions: ${{ matrix.driver == 1 && env.MONGODB_EXT_V1 || env.MONGODB_EXT_V2 }}
- key: "extcache-v1"
+ key: extcache-v1
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- extensions: "curl,mbstring,${{ matrix.driver == 1 && env.MONGODB_EXT_V1 || env.MONGODB_EXT_V2 }}"
+ extensions: curl,mbstring,${{ matrix.driver == 1 && env.MONGODB_EXT_V1 || env.MONGODB_EXT_V2 }}
tools: composer:v2
coverage: none
@@ -81,7 +79,7 @@ jobs:
uses: actions/cache/restore@v5
with:
path: .cache
- key: "phpstan-result-cache-${{ matrix.php }}-${{ github.run_id }}"
+ key: phpstan-result-cache-${{ matrix.php }}-${{ github.run_id }}
restore-keys: |
phpstan-result-cache-
@@ -89,15 +87,15 @@ jobs:
run: ./vendor/bin/phpstan analyse --no-interaction --no-progress --ansi --error-format=sarif > phpstan.sarif
continue-on-error: true
- - name: "Upload SARIF report"
+ - name: Upload SARIF report
if: ${{ github.event_name != 'workflow_dispatch' }}
- uses: "github/codeql-action/upload-sarif@v4"
+ uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: phpstan.sarif
- - name: "Upload SARIF report"
+ - name: Upload SARIF report
if: ${{ github.event_name == 'workflow_dispatch' }}
- uses: "github/codeql-action/upload-sarif@v4"
+ uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: phpstan.sarif
ref: ${{ inputs.ref }}
diff --git a/composer.json b/composer.json
index 658e7f112..169b91978 100644
--- a/composer.json
+++ b/composer.json
@@ -15,35 +15,55 @@
"security": "https://www.mongodb.com/security"
},
"authors": [
- { "name": "Andreas Braun", "email": "andreas.braun@mongodb.com", "role": "Leader" },
- { "name": "Pauline Vos", "email": "pauline.vos@mongodb.com", "role": "Maintainer" },
- { "name": "Jérôme Tamarelle", "email": "jerome.tamarelle@mongodb.com", "role": "Maintainer" },
- { "name": "Jeremy Mikola", "email": "jmikola@gmail.com", "role": "Maintainer" },
- { "name": "Jens Segers", "homepage": "https://jenssegers.com", "role": "Creator" }
+ {
+ "name": "Andreas Braun",
+ "email": "andreas.braun@mongodb.com",
+ "role": "Leader"
+ },
+ {
+ "name": "Pauline Vos",
+ "email": "pauline.vos@mongodb.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Jérôme Tamarelle",
+ "email": "jerome.tamarelle@mongodb.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Jeremy Mikola",
+ "email": "jmikola@gmail.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Jens Segers",
+ "homepage": "https://jenssegers.com",
+ "role": "Creator"
+ }
],
"license": "MIT",
"require": {
"php": "^8.1",
"ext-mongodb": "^1.21|^2",
"composer-runtime-api": "^2.0.0",
- "illuminate/cache": "^10.36|^11|^12",
- "illuminate/container": "^10.0|^11|^12",
- "illuminate/database": "^10.30|^11|^12",
- "illuminate/events": "^10.0|^11|^12",
- "illuminate/support": "^10.0|^11|^12",
+ "illuminate/cache": "^10.36|^11|^12|^13.0",
+ "illuminate/container": "^10.0|^11|^12|^13.0",
+ "illuminate/database": "^10.30|^11|^12|^13.0",
+ "illuminate/events": "^10.0|^11|^12|^13.0",
+ "illuminate/support": "^10.0|^11|^12|^13.0",
"mongodb/mongodb": "^1.21|^2"
},
"require-dev": {
"laravel/scout": "^10.3",
"league/flysystem-gridfs": "^3.28",
"league/flysystem-read-only": "^3.0",
- "phpunit/phpunit": "^10.3|^11.5.3",
- "orchestra/testbench": "^8.0|^9.0|^10.0",
+ "phpunit/phpunit": "^10.3|^11.5.3|^12.5.12",
+ "orchestra/testbench": "^8.0|^9.0|^10.0|^11.0",
"mockery/mockery": "^1.4.4",
- "doctrine/coding-standard": "12.0.x-dev",
+ "doctrine/coding-standard": "^12.0",
"spatie/laravel-query-builder": "^5.6|^6",
- "phpstan/phpstan": "^1.10",
- "rector/rector": "^1.2"
+ "phpstan/phpstan": "^1.10|^2.1",
+ "rector/rector": "^1.2|^2.3"
},
"conflict": {
"illuminate/bus": "< 10.37.2"
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index e31acd401..1c90fc112 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -18,7 +18,6 @@
-
diff --git a/src/Cache/MongoStore.php b/src/Cache/MongoStore.php
index 0b800bcf3..cf959ec2c 100644
--- a/src/Cache/MongoStore.php
+++ b/src/Cache/MongoStore.php
@@ -258,6 +258,27 @@ public function forgetIfExpired($key): bool
return $result->getDeletedCount() > 0;
}
+ /**
+ * Extend the expiration time of an item in the cache.
+ *
+ * @param string $key
+ * @param int $seconds
+ */
+ public function touch($key, $seconds): bool
+ {
+ $result = $this->collection->updateOne(
+ [
+ '_id' => $this->prefix . $key,
+ 'expires_at' => ['$gt' => $this->getUTCDateTime()],
+ ],
+ [
+ '$set' => ['expires_at' => $this->getUTCDateTime($seconds)],
+ ],
+ );
+
+ return $result->getModifiedCount() > 0;
+ }
+
public function flush(): bool
{
$this->collection->deleteMany([]);
diff --git a/src/MongoDBServiceProvider.php b/src/MongoDBServiceProvider.php
index 644eb7a56..34502cd1a 100644
--- a/src/MongoDBServiceProvider.php
+++ b/src/MongoDBServiceProvider.php
@@ -112,7 +112,7 @@ private function registerFlysystemAdapter(): void
{
// GridFS adapter for filesystem
$this->app->resolving('filesystem', static function (FilesystemManager $filesystemManager) {
- $filesystemManager->extend('gridfs', static function (Application $app, array $config) {
+ $filesystemManager->extend('gridfs', function (Application $app, array $config) {
if (! class_exists(GridFSAdapter::class)) {
throw new RuntimeException('GridFS adapter for Flysystem is missing. Try running "composer require league/flysystem-gridfs"');
}
diff --git a/tests/Cache/MongoCacheStoreTest.php b/tests/Cache/MongoCacheStoreTest.php
index 6f4ee79f4..c6a0658a6 100644
--- a/tests/Cache/MongoCacheStoreTest.php
+++ b/tests/Cache/MongoCacheStoreTest.php
@@ -201,6 +201,43 @@ public function testIncrementDecrement()
$this->assertFalse($store->increment('foo', 5));
}
+ public function testTouchReturnsFalseWhenKeyDoesNotExist()
+ {
+ $store = $this->getStore();
+
+ $this->assertFalse($store->touch('foo', 60));
+ }
+
+ public function testTouchExtendsExpirationAndPreservesValue()
+ {
+ $store = $this->getStore();
+
+ $this->insertToCacheTable('foo', 'bar', 60);
+ $result = $store->touch('foo', 3600);
+
+ $this->assertTrue($result);
+ $this->assertSame('bar', $store->get('foo'));
+
+ $document = DB::connection('mongodb')
+ ->getCollection($this->getCacheCollectionName())
+ ->findOne(['_id' => $this->withCachePrefix('foo')]);
+
+ $this->assertGreaterThan(
+ new UTCDateTime(Carbon::now()->addSeconds(60)),
+ $document['expires_at'],
+ );
+ }
+
+ public function testTouchReturnsFalseOnExpiredItem()
+ {
+ $store = $this->getStore();
+
+ $this->insertToCacheTable('foo', 'bar', -5);
+
+ $this->assertFalse($store->touch('foo', 60));
+ $this->assertNull($store->get('foo'));
+ }
+
public function testTTLIndex()
{
$store = $this->getStore();
diff --git a/tests/ModelTest.php b/tests/ModelTest.php
index 06de1ce3a..bdc71d401 100644
--- a/tests/ModelTest.php
+++ b/tests/ModelTest.php
@@ -1317,9 +1317,10 @@ public function testUpdateOrCreate(array $criteria)
#[TestWith(['id'])]
public function testCreateWithNullId(string $id)
{
+ User::truncate();
$user = User::create([$id => null, 'email' => 'foo@bar']);
- $this->assertNotNull(ObjectId::class, $user->id);
- $this->assertSame(1, User::count());
+ $this->assertIsString($user->id);
+ $this->assertEquals([['id' => $user->id, 'email' => 'foo@bar']], User::all(['id', 'email'])->toArray());
}
/** @param class-string $modelClass */