Full Code of mongodb/laravel-mongodb for AI

5.x 0071a45e7974 cached
171 files
872.5 KB
219.5k tokens
1270 symbols
1 requests
Download .txt
Showing preview only (922K chars total). Download the full file or copy to clipboard to get everything.
Repository: mongodb/laravel-mongodb
Branch: 5.x
Commit: 0071a45e7974
Files: 171
Total size: 872.5 KB

Directory structure:
gitextract_2jedx5y6/

├── .editorconfig
├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   ├── BUG_REPORT.md
│   │   ├── FEATURE-REQUEST.md
│   │   └── config.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   ├── labeler.yml
│   ├── release.yml
│   └── workflows/
│       ├── build-ci-atlas.yml
│       ├── build-ci.yml
│       ├── coding-standards.yml
│       ├── labeler.yml
│       ├── merge-up.yml
│       ├── release.yml
│       └── static-analysis.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── RELEASING.md
├── composer.json
├── docker-compose.yml
├── phpcs.xml.dist
├── phpstan-baseline.neon
├── phpstan.neon.dist
├── phpunit.xml.dist
├── rector.php
├── sbom.json
├── src/
│   ├── Auth/
│   │   └── User.php
│   ├── Bus/
│   │   └── MongoBatchRepository.php
│   ├── Cache/
│   │   ├── MongoLock.php
│   │   └── MongoStore.php
│   ├── CommandSubscriber.php
│   ├── Concerns/
│   │   └── ManagesTransactions.php
│   ├── Connection.php
│   ├── Eloquent/
│   │   ├── Builder.php
│   │   ├── Casts/
│   │   │   ├── BinaryUuid.php
│   │   │   └── ObjectId.php
│   │   ├── DocumentModel.php
│   │   ├── EmbedsRelations.php
│   │   ├── HasSchemaVersion.php
│   │   ├── HybridRelations.php
│   │   ├── MassPrunable.php
│   │   ├── Model.php
│   │   └── SoftDeletes.php
│   ├── Helpers/
│   │   ├── EloquentBuilder.php
│   │   └── QueriesRelationships.php
│   ├── MongoDBBusServiceProvider.php
│   ├── MongoDBServiceProvider.php
│   ├── Query/
│   │   ├── AggregationBuilder.php
│   │   ├── Builder.php
│   │   ├── BuilderTimeout.php
│   │   ├── Grammar.php
│   │   └── Processor.php
│   ├── Queue/
│   │   ├── MongoConnector.php
│   │   ├── MongoJob.php
│   │   └── MongoQueue.php
│   ├── Relations/
│   │   ├── BelongsTo.php
│   │   ├── BelongsToMany.php
│   │   ├── EmbedsMany.php
│   │   ├── EmbedsOne.php
│   │   ├── EmbedsOneOrMany.php
│   │   ├── HasMany.php
│   │   ├── HasOne.php
│   │   ├── MorphMany.php
│   │   ├── MorphTo.php
│   │   └── MorphToMany.php
│   ├── Schema/
│   │   ├── Blueprint.php
│   │   ├── BlueprintLaravelCompatibility.php
│   │   ├── Builder.php
│   │   └── Grammar.php
│   ├── Scout/
│   │   └── ScoutEngine.php
│   ├── Session/
│   │   └── MongoDbSessionHandler.php
│   └── Validation/
│       ├── DatabasePresenceVerifier.php
│       └── ValidationServiceProvider.php
└── tests/
    ├── AtlasSearchIndexManagement.php
    ├── AtlasSearchTest.php
    ├── AuthTest.php
    ├── Bus/
    │   ├── Fixtures/
    │   │   ├── ChainHeadJob.php
    │   │   ├── SecondTestJob.php
    │   │   └── ThirdTestJob.php
    │   └── MongoBatchRepositoryTest.php
    ├── Cache/
    │   ├── MongoCacheStoreTest.php
    │   └── MongoLockTest.php
    ├── Casts/
    │   ├── BinaryUuidTest.php
    │   ├── BooleanTest.php
    │   ├── CollectionTest.php
    │   ├── DateTest.php
    │   ├── DatetimeTest.php
    │   ├── DecimalTest.php
    │   ├── EncryptionTest.php
    │   ├── FloatTest.php
    │   ├── IntegerTest.php
    │   ├── JsonTest.php
    │   ├── ObjectIdTest.php
    │   ├── ObjectTest.php
    │   └── StringTest.php
    ├── ConnectionTest.php
    ├── DateTimeImmutableTest.php
    ├── Eloquent/
    │   ├── CallBuilderTest.php
    │   ├── MassPrunableTest.php
    │   └── ModelTest.php
    ├── EmbeddedRelationsTest.php
    ├── ExternalPackageTest.php
    ├── FilesystemsTest.php
    ├── GeospatialTest.php
    ├── HybridRelationsTest.php
    ├── ModelTest.php
    ├── Models/
    │   ├── Address.php
    │   ├── Anniversary.php
    │   ├── Birthday.php
    │   ├── Book.php
    │   ├── CastObjectId.php
    │   ├── Casting.php
    │   ├── Client.php
    │   ├── Experience.php
    │   ├── Group.php
    │   ├── Guarded.php
    │   ├── HiddenAnimal.php
    │   ├── IdIsBinaryUuid.php
    │   ├── IdIsInt.php
    │   ├── IdIsString.php
    │   ├── Item.php
    │   ├── Label.php
    │   ├── Location.php
    │   ├── MemberStatus.php
    │   ├── NonIncrementing.php
    │   ├── Photo.php
    │   ├── Role.php
    │   ├── SchemaVersion.php
    │   ├── Scoped.php
    │   ├── Skill.php
    │   ├── Soft.php
    │   ├── SqlBook.php
    │   ├── SqlRole.php
    │   ├── SqlUser.php
    │   └── User.php
    ├── PHPStan/
    │   └── SarifErrorFormatter.php
    ├── PropertyTest.php
    ├── Query/
    │   ├── AggregationBuilderTest.php
    │   └── BuilderTest.php
    ├── QueryBuilderTest.php
    ├── QueryTest.php
    ├── Queue/
    │   └── Failed/
    │       └── DatabaseFailedJobProviderTest.php
    ├── QueueTest.php
    ├── RelationsTest.php
    ├── SchemaTest.php
    ├── SchemaVersionTest.php
    ├── Scout/
    │   ├── Models/
    │   │   ├── ScoutUser.php
    │   │   ├── SearchableInSameNamespace.php
    │   │   └── SearchableModel.php
    │   ├── ScoutEngineTest.php
    │   └── ScoutIntegrationTest.php
    ├── Seeder/
    │   ├── DatabaseSeeder.php
    │   └── UserTableSeeder.php
    ├── SeederTest.php
    ├── SessionTest.php
    ├── TestCase.php
    ├── Ticket/
    │   ├── GH2489Test.php
    │   ├── GH2783Test.php
    │   ├── GH3326Test.php
    │   ├── GH3328Test.php
    │   └── GH3335Test.php
    ├── TransactionTest.php
    ├── ValidationTest.php
    └── config/
        ├── database.php
        └── queue.php

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true

[*.yml]
indent_size = 2


================================================
FILE: .gitattributes
================================================
/.github                 export-ignore
/.phpunit.cache          export-ignore
/tests                   export-ignore
*.md                     export-ignore
*.dist                   export-ignore
.editorconfig            export-ignore
.gitattributes           export-ignore
.gitignore               export-ignore
docker-compose.yml       export-ignore
Dockerfile               export-ignore
phpstan-baseline.neon    export-ignore


================================================
FILE: .github/CODEOWNERS
================================================
* @mongodb/dbx-php


================================================
FILE: .github/ISSUE_TEMPLATE/BUG_REPORT.md
================================================
---
name: "Bug report"
about: 'Report errors or unexpected behavior.'
---

- Laravel-mongodb Version: #.#.#
- PHP Version: #.#.#
- Database Driver & Version:

### Description:

### Steps to reproduce
1.
2.
3.

### Expected behaviour
Tell us what should happen

### Actual behaviour
Tell us what happens instead

<details><summary><b>Logs</b>:</summary>
Insert log.txt here (if necessary)
</details>


================================================
FILE: .github/ISSUE_TEMPLATE/FEATURE-REQUEST.md
================================================
---
name: Feature request
about: Suggest an idea.
title: "[Feature Request] "

---

### Is your feature request related to a problem?
A clear and concise description of what the problem is.

### Describe the solution you'd like
A clear and concise description of what you want to happen.

### Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

### Additional context
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false

contact_links:
  - name: Discussions
    url: https://github.com/mongodb/laravel-mongodb/discussions/new/choose
    about: For questions, discussions, or general technical support from other Laravel users, visit the Discussions page.
  - name: MongoDB Developer Community Forums
    url: https://developer.mongodb.com/community/forums/
    about: For questions, discussions, or general technical support, visit the MongoDB Community Forums. The MongoDB Community Forums are a centralized place to connect with other MongoDB users, ask questions, and get answers.
  - name: Report a Security Vulnerability
    url: https://mongodb.com/docs/manual/tutorial/create-a-vulnerability-report
    about: If you believe you have discovered a vulnerability in MongoDB products or have experienced a security incident related to MongoDB products, please report the issue to aid in its resolution.


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!--
Replace this notice by a description of your feature/bugfix.
This will help reviewers and should be a good start for the documentation.
-->

### Checklist

- [ ] Add tests and ensure they pass


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: weekly


================================================
FILE: .github/labeler.yml
================================================
# https://github.com/actions/labeler
github:
  - changed-files:
    - any-glob-to-any-file: '.github/**'


================================================
FILE: .github/release.yml
================================================
changelog:
  exclude:
    labels:
      - ignore-for-release
      - minor
    authors:
      - mongodb-php-bot
  categories:
    - title: Breaking Changes 🛠
      labels:
        - breaking-change
    - title: New Features
      labels:
        - enhancement
        - feature
    - title: Fixed
      labels:
        - bug
        - fixed
    - title: Other Changes
      labels:
        - '*'


================================================
FILE: .github/workflows/build-ci-atlas.yml
================================================
name: Atlas CI

on:
  push:
    branches:
      - '[0-9]+.[0-9x]+'
  pull_request:
    branches:
      - '[0-9]+.[0-9x]+'
      - feature/*

env:
  MONGODB_EXT_V1: mongodb-1.21.0
  MONGODB_EXT_V2: stable

jobs:
  build:
    runs-on: ubuntu-latest

    name: PHP/${{ matrix.php }} Laravel/${{ matrix.laravel }} Driver/${{ matrix.driver }}

    strategy:
      matrix:
        php: ['8.2', '8.3', '8.4', '8.5']
        laravel: ['12.*', '13.*']
        driver: [2]
        include:
          - php: '8.1'
            laravel: 10.*
            driver: 1
          - php: '8.2'
            laravel: 11.*
            driver: 1
          - php: '8.4'
            laravel: 12.*
            driver: 1
        exclude:
          - laravel: 13.*
            php: '8.2'

    steps:
      - uses: actions/checkout@v6

      - 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
            sleep 1
          done
          until docker exec --tty mongodb mongosh --eval "db.createCollection('connection_test') && db.getCollection('connection_test').createSearchIndex({mappings:{dynamic: true}})"; do
            sleep 1
          done

      - name: Show MongoDB server status
        run: |
          docker exec --tty mongodb mongosh --eval "db.runCommand({ serverStatus: 1 })"

      - name: Setup cache environment
        id: extcache
        uses: shivammathur/cache-extensions@v1
        with:
          php-version: ${{ matrix.php }}
          extensions: ${{ matrix.driver == 1 && env.MONGODB_EXT_V1 || env.MONGODB_EXT_V2 }}
          key: extcache-v1

      - 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

      - name: Show Docker version
        if: ${{ runner.debug }}
        run: docker version && env

      - name: Restrict Laravel version
        run: composer require --dev --no-update 'laravel/framework:${{ matrix.laravel }}'

      - 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
        with:
          path: ${{ steps.composer-cache.outputs.dir }}
          key: ${{ matrix.os }}-composer-${{ hashFiles('**/composer.json') }}
          restore-keys: ${{ matrix.os }}-composer-

      - name: Install dependencies
        run: |
          composer update --no-interaction

      - 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


================================================
FILE: .github/workflows/build-ci.yml
================================================
name: CI

on:
  push:
    branches:
      - '[0-9]+.[0-9x]+'
  pull_request:
    branches:
      - '[0-9]+.[0-9x]+'
      - feature/*

env:
  MONGODB_EXT_V1: mongodb-1.21.0
  MONGODB_EXT_V2: stable

jobs:
  build:
    runs-on: ubuntu-latest

    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.*', '13.*']
        driver: [2]
        include:
          - php: '8.1'
            laravel: 10.*
            mongodb: '5.0'
            mode: low-deps
            driver: 1
          - php: '8.3'
            laravel: 10.*
            mongodb: '4.4'
            driver: 1
          - php: '8.4'
            laravel: 12.*
            mongodb: '8.0'
            driver: 1
          - 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

      - 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

          if [ "${{ matrix.mongodb }}" = "4.4" ]; then MONGOSH_BIN="mongo"; else MONGOSH_BIN="mongosh"; fi
          until docker exec --tty mongodb $MONGOSH_BIN --eval "db.runCommand({ ping: 1 })"; do
            sleep 1
          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
        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 })"

      - name: Setup cache environment
        id: extcache
        uses: shivammathur/cache-extensions@v1
        with:
          php-version: ${{ matrix.php }}
          extensions: ${{ matrix.driver == 1 && env.MONGODB_EXT_V1 || env.MONGODB_EXT_V2 }}
          key: extcache-v1

      - 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

      - name: Show Docker version
        if: ${{ runner.debug }}
        run: docker version && env

      - name: Restrict Laravel version
        run: composer require --dev --no-update 'laravel/framework:${{ matrix.laravel }}'

      - 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
        with:
          path: ${{ steps.composer-cache.outputs.dir }}
          key: ${{ matrix.os }}-composer-${{ hashFiles('**/composer.json') }}
          restore-keys: ${{ matrix.os }}-composer-

      - 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
        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 --testdox


================================================
FILE: .github/workflows/coding-standards.yml
================================================
name: Coding Standards

on:
  push:
    branches:
      - '[0-9]+.[0-9x]+'
  pull_request:
    branches:
      - '[0-9]+.[0-9x]+'
      - feature/*

env:
  PHP_VERSION: '8.4'
  DRIVER_VERSION: stable

jobs:
  phpcs:
    name: phpcs
    runs-on: ubuntu-22.04

    permissions:
      # Give the default GITHUB_TOKEN write permission to commit and push the
      # added or changed files to the repository.
      contents: write

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Setup cache environment
        id: extcache
        uses: shivammathur/cache-extensions@v1
        with:
          php-version: ${{ env.PHP_VERSION }}
          extensions: mongodb-${{ env.DRIVER_VERSION }}
          key: extcache-v1

      - name: Cache extensions
        uses: actions/cache@v5
        with:
          path: ${{ steps.extcache.outputs.dir }}
          key: ${{ steps.extcache.outputs.key }}
          restore-keys: ${{ steps.extcache.outputs.key }}

      - name: Install PHP
        uses: shivammathur/setup-php@v2
        with:
          coverage: none
          extensions: mongodb-${{ env.DRIVER_VERSION }}
          php-version: ${{ env.PHP_VERSION }}
          tools: cs2pr

      - name: Show driver information
        run: php --ri mongodb

      - name: Install dependencies with Composer
        uses: ramsey/composer-install@4.0.0
        with:
          composer-options: --no-suggest

      - name: Validate PSR class names
        run: composer dump-autoload --optimize --strict-psr

      # The -q option is required until phpcs v4 is released
      - name: Run PHP_CodeSniffer
        run: |
          mkdir .cache
          vendor/bin/phpcs -q --no-colors --report=checkstyle | cs2pr


================================================
FILE: .github/workflows/labeler.yml
================================================
name: Pull Request Labeler
on:
  - pull_request_target

jobs:
  labeler:
    permissions:
      contents: read
      pull-requests: write
    runs-on: ubuntu-latest
    steps:
      - uses: actions/labeler@v6


================================================
FILE: .github/workflows/merge-up.yml
================================================
name: Merge up

on:
  push:
    branches:
      - '[0-9]+.[0-9x]+'

env:
  GH_TOKEN: ${{ secrets.MERGE_UP_TOKEN }}

jobs:
  merge-up:
    name: Create merge up pull request
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        id: checkout
        uses: actions/checkout@v6
        with:
          # fetch-depth 0 is required to fetch all branches, not just the branch being built
          fetch-depth: 0
          token: ${{ secrets.MERGE_UP_TOKEN }}

      - name: Create pull request
        id: create-pull-request
        uses: alcaeus/automatic-merge-up-action@main
        with:
          ref: ${{ github.ref_name }}
          branchNamePattern: '<major>.<minor>'
          devBranchNamePattern: '<major>.x'
          enableAutoMerge: true


================================================
FILE: .github/workflows/release.yml
================================================
name: "Release New Version"
run-name: "Release ${{ inputs.version }}"

on:
  workflow_dispatch:
    inputs:
      version:
        description: "The version to be released. This is checked for consistency with the branch name and configuration"
        required: true
        type: "string"

jobs:
  prepare-release:
    environment: release
    name: "Prepare release"
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: write

    steps:
      - name: "Create release output"
        run: echo '🎬 Release process for version ${{ inputs.version }} started by @${{ github.triggering_actor }}' >> $GITHUB_STEP_SUMMARY

      - name: "Generate token and checkout repository"
        uses: mongodb-labs/drivers-github-tools/secure-checkout@v3
        with:
          app_id: ${{ vars.APP_ID }}
          private_key: ${{ secrets.APP_PRIVATE_KEY }}

      - name: "Store version numbers in env variables"
        run: |
          echo RELEASE_VERSION=${{ inputs.version }} >> $GITHUB_ENV
          echo RELEASE_BRANCH=$(echo ${{ inputs.version }} | cut -d '.' -f-2) >> $GITHUB_ENV
          echo DEV_BRANCH=$(echo ${{ inputs.version }} | cut -d '.' -f-1).x >> $GITHUB_ENV

      - name: "Ensure release tag does not already exist"
        run: |
          if [[ $(git tag -l ${RELEASE_VERSION}) == ${RELEASE_VERSION} ]]; then
            echo '❌ Release failed: tag for version ${{ inputs.version }} already exists' >> $GITHUB_STEP_SUMMARY
            exit 1
          fi

      # For patch releases (A.B.C where C != 0), we expect the release to be
      # triggered from the A.B maintenance branch
      - name: "Fail if patch release is created from wrong release branch"
        if: ${{ !endsWith(inputs.version, '.0') && env.RELEASE_BRANCH != github.ref_name }}
        run: |
          echo '❌ Release failed due to branch mismatch: expected ${{ inputs.version }} to be released from ${{ env.RELEASE_BRANCH }}, got ${{ github.ref_name }}' >> $GITHUB_STEP_SUMMARY
          exit 1

      # For non-patch releases (A.B.C where C == 0), we expect the release to
      # be triggered from the A.x maintenance branch or A.x development branch
      - name: "Fail if non-patch release is created from wrong release branch"
        if: ${{ endsWith(inputs.version, '.0') && env.RELEASE_BRANCH != github.ref_name && env.DEV_BRANCH != github.ref_name }}
        run: |
          echo '❌ Release failed due to branch mismatch: expected ${{ inputs.version }} to be released from ${{ env.RELEASE_BRANCH }} or ${{ env.DEV_BRANCH }}, got ${{ github.ref_name }}' >> $GITHUB_STEP_SUMMARY
          exit 1

      # If a non-patch release is created from its A.x development branch,
      # create the A.B maintenance branch from the current one and push it
      - name: "Create and push new release branch for non-patch release"
        if: ${{ endsWith(inputs.version, '.0') && env.DEV_BRANCH == github.ref_name }}
        run: |
          echo '🆕 Creating new release branch ${RELEASE_BRANCH} from ${{ github.ref_name }}' >> $GITHUB_STEP_SUMMARY
          git checkout -b ${RELEASE_BRANCH}
          git push origin ${RELEASE_BRANCH}

      #
      # Preliminary checks done - commence the release process
      #

      - name: "Set up drivers-github-tools"
        uses: mongodb-labs/drivers-github-tools/setup@v3
        with:
          aws_role_arn: ${{ secrets.AWS_ROLE_ARN }}
          aws_region_name: ${{ vars.AWS_REGION_NAME }}
          aws_secret_id: ${{ secrets.AWS_SECRET_ID }}

      # Create draft release with release notes
      - name: "Create draft release"
        run: echo "RELEASE_URL=$(gh release create ${{ inputs.version }} --target ${{ github.ref_name }} --title "${{ inputs.version }}" --generate-notes --draft)" >> "$GITHUB_ENV"

      - name: "Create release tag"
        uses: mongodb-labs/drivers-github-tools/tag-version@v3
        with:
          version: ${{ inputs.version }}
          tag_message_template: 'Release ${VERSION}'

      # TODO: Manually merge using ours strategy. This avoids merge-up pull requests being created
      # Process is:
      # 1. switch to next branch (according to merge-up action)
      # 2. merge release branch using --strategy=ours
      # 3. push next branch
      # 4. switch back to release branch, then push

      - name: "Set summary"
        run: |
          echo '🚀 Created tag and drafted release for version [${{ inputs.version }}](${{ env.RELEASE_URL }})' >> $GITHUB_STEP_SUMMARY
          echo '✍️ You may now update the release notes and publish the release when ready' >> $GITHUB_STEP_SUMMARY

  static-analysis:
    needs: prepare-release
    name: "Run Static Analysis"
    uses: ./.github/workflows/static-analysis.yml
    with:
      ref: refs/tags/${{ inputs.version }}
    permissions:
      security-events: write
      id-token: write

  publish-ssdlc-assets:
    needs: static-analysis
    environment: release
    name: "Publish SSDLC Assets"
    runs-on: ubuntu-latest
    permissions:
      security-events: read
      id-token: write
      contents: write

    steps:
      - name: "Generate token and checkout repository"
        uses: mongodb-labs/drivers-github-tools/secure-checkout@v3
        with:
          app_id: ${{ vars.APP_ID }}
          private_key: ${{ secrets.APP_PRIVATE_KEY }}
          ref: refs/tags/${{ inputs.version }}

      # Sets the S3_ASSETS environment variable used later
      - name: "Set up drivers-github-tools"
        uses: mongodb-labs/drivers-github-tools/setup@v3
        with:
          aws_role_arn: ${{ secrets.AWS_ROLE_ARN }}
          aws_region_name: ${{ vars.AWS_REGION_NAME }}
          aws_secret_id: ${{ secrets.AWS_SECRET_ID }}

      - name: "Generate SSDLC Reports"
        uses: mongodb-labs/drivers-github-tools/full-report@v3
        with:
          product_name: "MongoDB Laravel Integration"
          release_version: ${{ inputs.version }}
          silk_asset_group: mongodb-laravel-integration

      - name: "Upload SBOM as release artifact"
        run: gh release upload ${{ inputs.version }} ${{ env.S3_ASSETS }}/cyclonedx.sbom.json
        continue-on-error: true

      - name: Upload S3 assets
        uses: mongodb-labs/drivers-github-tools/upload-s3-assets@v3
        with:
          version: ${{ inputs.version }}
          product_name: laravel-mongodb


================================================
FILE: .github/workflows/static-analysis.yml
================================================
name: Static Analysis

on:
  push:
    branches:
      - '[0-9]+.[0-9x]+'
  pull_request:
    branches:
      - '[0-9]+.[0-9x]+'
      - feature/*
  workflow_call:
    inputs:
      ref:
        description: The git ref to check
        type: string
        required: true

env:
  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

    continue-on-error: true

    strategy:
      matrix:
        php: ['8.1', '8.2', '8.3', '8.4', '8.5']
        driver: [2]
        include:
          - 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
        if: ${{ github.event_name == 'workflow_dispatch' }}
        run: |
          echo CHECKED_OUT_SHA=$(git rev-parse HEAD) >> $GITHUB_ENV

      - name: Setup cache environment
        id: extcache
        uses: shivammathur/cache-extensions@v1
        with:
          php-version: ${{ matrix.php }}
          extensions: ${{ matrix.driver == 1 && env.MONGODB_EXT_V1 || env.MONGODB_EXT_V2 }}
          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 }}
          tools: composer:v2
          coverage: none

      - name: Cache dependencies
        id: composer-cache
        uses: actions/cache@v5
        with:
          path: ./vendor
          key: composer-${{ hashFiles('**/composer.lock') }}

      - name: Install dependencies
        run: composer install

      - name: Restore cache PHPStan results
        id: phpstan-cache-restore
        uses: actions/cache/restore@v5
        with:
          path: .cache
          key: phpstan-result-cache-${{ matrix.php }}-${{ github.run_id }}
          restore-keys: |
            phpstan-result-cache-

      - name: Run PHPStan
        run: ./vendor/bin/phpstan analyse --no-interaction --no-progress --ansi --error-format=sarif > phpstan.sarif
        continue-on-error: true

      - name: Upload SARIF report
        if: ${{ github.event_name != 'workflow_dispatch' }}
        uses: github/codeql-action/upload-sarif@v4
        with:
          sarif_file: phpstan.sarif

      - name: Upload SARIF report
        if: ${{ github.event_name == 'workflow_dispatch' }}
        uses: github/codeql-action/upload-sarif@v4
        with:
          sarif_file: phpstan.sarif
          ref: ${{ inputs.ref }}
          sha: ${{ env.CHECKED_OUT_SHA }}

      - name: Save cache PHPStan results
        id: phpstan-cache-save
        if: always()
        uses: actions/cache/save@v5
        with:
          path: .cache
          key: ${{ steps.phpstan-cache-restore.outputs.cache-primary-key }}


================================================
FILE: .gitignore
================================================
*.project
*.sublime-project
*.sublime-workspace
.DS_Store
.idea/
/vendor
composer.lock
composer.phar
phpunit.xml
phpstan.neon
/.cache/


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# MongoDB Code of Conduct

The Code of Conduct outlines the expectations for our behavior as members of the MongoDB community.
We value the participation of each member of the MongoDB community and want all participants to have an enjoyable and fulfilling experience.

Thanks for reading the [MongoDB Code of Conduct](https://www.mongodb.com/community-code-of-conduct).


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing

Contributions are **welcome** and will be fully **credited**.

Please read and understand the contribution guide before creating an issue or pull request.

## Etiquette

This project is open source, and as such, the maintainers give their free time to build and maintain the source code
held within. They make the code freely available in the hope that it will be of use to other developers. It would be
extremely unfair for them to suffer abuse or anger for their hard work.

Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the
world that developers are civilized and selfless people.

It's the duty of the maintainer to ensure that all submissions to the project are of sufficient
quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used.

## Viability

When requesting or submitting new features, first consider whether it might be useful to others. Open
source projects are used by many developers, who may have entirely different needs to your own. Think about
whether or not your feature is likely to be used by other users of the project.

## Procedure

Before filing an issue:

- Attempt to replicate the problem, to ensure that it wasn't a coincidental incident.
- Check to make sure your feature suggestion isn't already present within the project.
- Check the pull requests tab to ensure that the bug doesn't have a fix in progress.
- Check the pull requests tab to ensure that the feature isn't already in progress.

Before submitting a pull request:

- Check the codebase to ensure that your feature doesn't already exist.
- Check the pull requests to ensure that another person hasn't already submitted the feature or fix.

## Run Tests

The full test suite requires PHP cli with mongodb extension and a running MongoDB server. A replica set is required for
testing transactions.
Duplicate the `phpunit.xml.dist` file to `phpunit.xml` and edit the environment variables to match your setup.

```bash
$ docker-compose run app
```

Docker can be slow to start. You can run the command `composer run test` locally or in a docker container.

```bash
$ docker-compose run -it tests bash
# Inside the container
$ composer install
$ composer run test
```

For fixing style issues, you can run the PHP Code Beautifier and Fixer, some issues can't be fixed automatically:

```bash
$ composer run cs:fix
$ composer run cs
```

## Requirements

If the project maintainer has any additional requirements, you will find them listed here.

- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](https://pear.php.net/package/PHP_CodeSniffer).

- **Add tests!** - Your patch won't be accepted if it doesn't have tests.

- **Document any change in behaviour** - Make sure the documentation is kept up-to-date.

- **Consider our release cycle** - We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option.

- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.

Happy coding!

## Releasing

The releases are created by the maintainers of the library. The process is documented in
the [RELEASING.md](RELEASING.md) file.


================================================
FILE: Dockerfile
================================================
ARG PHP_VERSION=8.2

FROM php:${PHP_VERSION}-cli

# Install extensions
RUN apt-get update && \
    apt-get install -y autoconf pkg-config libssl-dev git unzip libzip-dev zlib1g-dev && \
    pecl install mongodb && docker-php-ext-enable mongodb && \
    pecl install xdebug && docker-php-ext-enable xdebug && \
    docker-php-ext-install -j$(nproc) zip

# Create php.ini
RUN cp "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"

# Install Composer
COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2023 MongoDB, Inc

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
Laravel MongoDB
===============

[![Latest Stable Version](http://img.shields.io/github/release/mongodb/laravel-mongodb.svg)](https://packagist.org/packages/mongodb/laravel-mongodb)
[![Total Downloads](http://img.shields.io/packagist/dm/mongodb/laravel-mongodb.svg)](https://packagist.org/packages/mongodb/laravel-mongodb)
[![Build Status](https://img.shields.io/github/actions/workflow/status/mongodb/laravel-mongodb/build-ci.yml)](https://github.com/mongodb/laravel-mongodb/actions/workflows/build-ci.yml)

This package adds functionalities to the Eloquent model and Query builder for MongoDB, using the original Laravel API.
*This library extends the original Laravel classes, so it uses exactly the same methods.*

This package was renamed to `mongodb/laravel-mongodb` because of a transfer of ownership to MongoDB, Inc.
It is compatible with Laravel 10.x. For older versions of Laravel, please refer to the
[old versions](https://github.com/mongodb/laravel-mongodb/tree/3.9#laravel-version-compatibility).

## Documentation

- https://www.mongodb.com/docs/drivers/php/laravel-mongodb/
- https://www.mongodb.com/docs/drivers/php/ 

## Release Integrity

Releases are created automatically and the resulting release tag is signed using
the [PHP team's GPG key](https://pgp.mongodb.com/php-driver.asc). To verify the
tag signature, download the key and import it using `gpg`:

```shell
gpg --import php-driver.asc
```

Then, in a local clone, verify the signature of a given tag (e.g. `4.4.0`):

```shell
git show --show-signature 4.4.0
```

> [!NOTE]
> Composer does not support verifying signatures as part of its installation
> process.

## Reporting Issues

Think you’ve found a bug in the library? Want to see a new feature? Please open a case in our issue management tool, JIRA:

- [Create an account and login.](https://jira.mongodb.org/)
- Navigate to the [PHPORM](https://jira.mongodb.org/browse/PHPORM) project.
- Click Create - Please provide as much information as possible about the issue type and how to reproduce it.

Note: All reported issues in JIRA project are public.

For general questions and support requests, please use one of MongoDB's
[Technical Support](https://mongodb.com/docs/manual/support/) channels.

### Security Vulnerabilities

If you've identified a security vulnerability in a driver or any other MongoDB
project, please report it according to the instructions in
[Create a Vulnerability Report](https://mongodb.com/docs/manual/tutorial/create-a-vulnerability-report).

## Development

Development is tracked in the
[PHPORM](https://jira.mongodb.org/projects/PHPORM/summary) project in MongoDB's
JIRA. Documentation for contributing to this project may be found in
[CONTRIBUTING.md](CONTRIBUTING.md).


================================================
FILE: RELEASING.md
================================================
# Releasing

The following steps outline the release process for both new minor versions and
patch versions.

The command examples below assume that the canonical "mongodb" repository has
the remote name "mongodb". You may need to adjust these commands if you've given
the remote another name (e.g. "upstream"). The "origin" remote name was not used
as it likely refers to your personal fork.

It helps to keep your own fork in sync with the "mongodb" repository (i.e. any
branches and tags on the main repository should also exist in your fork). This
is left as an exercise to the reader.

## Ensure PHP version compatibility

Ensure that the test suite completes on supported versions of PHP.

## Transition JIRA issues and version

All issues associated with the release version should be in the "Closed" state
and have a resolution of "Fixed". Issues with other resolutions (e.g.
"Duplicate", "Works as Designed") should be removed from the release version so
that they do not appear in the release notes.

Check the corresponding "laravel-*.x" fix version to see if it contains any
issues that are resolved as "Fixed" and should be included in this release
version.

Update the version's release date and status from the
[Manage Versions](https://jira.mongodb.org/plugins/servlet/project-config/PHPORM/versions)
page.

## Trigger the release workflow

Releases are done automatically through a GitHub Action. Visit the corresponding
[Release New Version](https://github.com/mongodb/laravel-mongodb/actions/workflows/release.yml)
workflow page to trigger a new build. Select the correct branch (e.g. `v4.5`)
and trigger a new run using the "Run workflow" button. In the following prompt,
enter the version number.

The automation will then create and push the necessary commits and tag, and create
a draft release. The release is created in a draft state and can be published
once the release notes have been updated.


## Branch management

# Creating a maintenance branch and updating default branch name

When releasing a new major or minor version (e.g. 4.0.0), the default branch
should be renamed to the next version (e.g. 4.1). Renaming the default branch
using GitHub's UI ensures that all open pull request are changed to target the
new version.

Once the default branch has been renamed, create the maintenance branch for the
version to be released (e.g. 4.0):

```console
$ git checkout -b X.Y
$ git push mongodb X.Y
```

### After releasing a patch version

If this was a patch release, the maintenance branch must be merged up to the
default branch (e.g. 4.1):

```console
$ git checkout 4.1
$ git pull mongodb 4.1
$ git merge 4.0 --strategy=ours
$ git push mongodb
```

The `--strategy=ours` option ensures that all changes from the merged commits
will be ignored. This is OK because we previously ensured that the `4.1`
branch was up-to-date with all code changes in this maintenance branch before
tagging.


## Publish release notes

Use the generated release note in [this form](https://github.com/mongodb/laravel-mongodb/releases/new).

Release announcements should also be posted in the [MongoDB Product & Driver Announcements: Driver Releases](https://mongodb.com/community/forums/tags/c/announcements/driver-releases/110/php) forum and shared on Twitter.


================================================
FILE: composer.json
================================================
{
    "name": "mongodb/laravel-mongodb",
    "description": "A MongoDB based Eloquent model and Query builder for Laravel",
    "keywords": [
        "laravel",
        "eloquent",
        "mongodb",
        "mongo",
        "database",
        "model"
    ],
    "homepage": "https://github.com/mongodb/laravel-mongodb",
    "support": {
        "issues": "https://www.mongodb.com/support",
        "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"
        }
    ],
    "license": "MIT",
    "require": {
        "php": "^8.1",
        "ext-mongodb": "^1.21|^2",
        "composer-runtime-api": "^2.0.0",
        "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|^12.5.12",
        "orchestra/testbench": "^8.0|^9.0|^10.0|^11.0",
        "mockery/mockery": "^1.4.4",
        "doctrine/coding-standard": "^12.0",
        "spatie/laravel-query-builder": "^5.6|^6",
        "phpstan/phpstan": "^1.10|^2.1",
        "rector/rector": "^1.2|^2.3"
    },
    "conflict": {
        "illuminate/bus": "< 10.37.2"
    },
    "suggest": {
        "league/flysystem-gridfs": "Filesystem storage in MongoDB with GridFS"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "replace": {
        "jenssegers/mongodb": "self.version"
    },
    "autoload": {
        "psr-4": {
            "MongoDB\\Laravel\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "MongoDB\\Laravel\\Tests\\": "tests/"
        }
    },
    "extra": {
        "laravel": {
            "providers": [
                "MongoDB\\Laravel\\MongoDBServiceProvider",
                "MongoDB\\Laravel\\MongoDBBusServiceProvider"
            ]
        }
    },
    "scripts": {
        "test": "phpunit",
        "test:coverage": "phpunit --coverage-clover ./coverage.xml",
        "cs": "phpcs",
        "cs:fix": "phpcbf",
        "rector": "rector"
    },
    "config": {
        "allow-plugins": {
            "dealerdirect/phpcodesniffer-composer-installer": true
        }
    }
}


================================================
FILE: docker-compose.yml
================================================
services:
    app:
        tty: true
        build: .
        working_dir: /var/www/laravel-mongodb
        command: "bash -c 'composer install && composer run test'"
        environment:
            MONGODB_URI: 'mongodb://mongodb/'
        volumes:
            - .:/var/www/laravel-mongodb
        depends_on:
            mongodb:
                condition: service_healthy

    mongodb:
        container_name: mongodb
        image: mongodb/mongodb-atlas-local:8
        ports:
            - "27017:27017"
        healthcheck:
            test: mongosh --quiet --eval 'db.runCommand("ping").ok'
            interval: 10s
            timeout: 10s
            retries: 5


================================================
FILE: phpcs.xml.dist
================================================
<?xml version="1.0"?>
<ruleset>
    <arg name="basepath" value="." />
    <arg name="extensions" value="php" />
    <arg name="parallel" value="80" />
    <arg name="cache" value=".cache/phpcs" />
    <arg name="colors" />

    <!-- Ignore warnings (n), show progress of the run (p), and show sniff names (s) -->
    <arg value="nps"/>

    <file>src</file>
    <file>tests</file>

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

    <!-- ****************************************** -->
    <!-- Import rules from doctrine/coding-standard -->
    <!-- ****************************************** -->
    <rule ref="Doctrine">
        <exclude name="SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed"/>
        <exclude name="SlevomatCodingStandard.ControlStructures.JumpStatementsSpacing"/>
        <exclude name="SlevomatCodingStandard.ControlStructures.NewWithParentheses"/>
        <exclude name="SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly"/>
        <exclude name="SlevomatCodingStandard.Functions.ArrowFunctionDeclaration"/>
        <exclude name="SlevomatCodingStandard.Functions.StaticClosure"/>
        <exclude name="SlevomatCodingStandard.TypeHints.UnionTypeHintFormat.DisallowedShortNullable"/>

        <!-- Model properties use snake_case -->
        <exclude name="Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps"/>

        <!-- Type changes needs to be synchronized with laravel/framework -->
        <exclude name="SlevomatCodingStandard.TypeHints.ParameterTypeHint"/>
        <exclude name="SlevomatCodingStandard.TypeHints.PropertyTypeHint"/>
        <exclude name="SlevomatCodingStandard.TypeHints.ReturnTypeHint"/>

        <exclude name="Generic.Formatting.MultipleStatementAlignment" />

        <exclude name="Squiz.Classes.ClassFileName.NoMatch">
            <exclude-pattern>/tests</exclude-pattern>
        </exclude>

        <exclude name="SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing">
            <exclude-pattern>/tests</exclude-pattern>
        </exclude>
    </rule>

    <rule ref="PSR1.Classes.ClassDeclaration.MultipleClasses">
        <exclude-pattern>tests/Ticket/*.php</exclude-pattern>
        <exclude-pattern>src/Query/BuilderTimeout.php</exclude-pattern>
    </rule>

    <rule ref="SlevomatCodingStandard.Commenting.DocCommentSpacing.IncorrectAnnotationsGroup">
        <exclude-pattern>src/Schema/Blueprint.php</exclude-pattern>
    </rule>
</ruleset>


================================================
FILE: phpstan-baseline.neon
================================================
parameters:
	ignoreErrors:
		-
			message: "#^Class MongoDB\\\\Laravel\\\\Query\\\\Grammar does not have a constructor and must be instantiated without any parameters\\.$#"
			count: 1
			path: src/Connection.php

		-
			message: "#^Class MongoDB\\\\Laravel\\\\Schema\\\\Grammar does not have a constructor and must be instantiated without any parameters\\.$#"
			count: 1
			path: src/Connection.php

		-
			message: "#^Access to an undefined property Illuminate\\\\Container\\\\Container\\:\\:\\$config\\.$#"
			count: 3
			path: src/MongoDBBusServiceProvider.php

		-
			message: "#^Access to an undefined property Illuminate\\\\Foundation\\\\Application\\:\\:\\$config\\.$#"
			count: 4
			path: src/MongoDBServiceProvider.php

		-
			message: "#^Call to an undefined method TDeclaringModel of Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:pull\\(\\)\\.$#"
			count: 1
			path: src/Relations/BelongsToMany.php

		-
			message: "#^Method Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:push\\(\\) invoked with 3 parameters, 0 required\\.$#"
			count: 3
			path: src/Relations/BelongsToMany.php

		-
			message: "#^Call to an undefined method MongoDB\\\\Laravel\\\\Relations\\\\EmbedsMany\\<TRelatedModel of Illuminate\\\\Database\\\\Eloquent\\\\Model, TDeclaringModel of Illuminate\\\\Database\\\\Eloquent\\\\Model, TResult\\>\\:\\:contains\\(\\)\\.$#"
			count: 1
			path: src/Relations/EmbedsMany.php

		-
			message: "#^Call to an undefined method TDeclaringModel of Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:getParentRelation\\(\\)\\.$#"
			count: 1
			path: src/Relations/EmbedsOneOrMany.php

		-
			message: "#^Call to an undefined method TDeclaringModel of Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:setParentRelation\\(\\)\\.$#"
			count: 1
			path: src/Relations/EmbedsOneOrMany.php

		-
			message: "#^Call to an undefined method TRelatedModel of Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:setParentRelation\\(\\)\\.$#"
			count: 2
			path: src/Relations/EmbedsOneOrMany.php

		-
			message: "#^Call to an undefined method TDeclaringModel of Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:pull\\(\\)\\.$#"
			count: 2
			path: src/Relations/MorphToMany.php

		-
			message: "#^Method Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:push\\(\\) invoked with 3 parameters, 0 required\\.$#"
			count: 6
			path: src/Relations/MorphToMany.php

		-
			message: "#^Method Illuminate\\\\Database\\\\Schema\\\\Blueprint\\:\\:create\\(\\) invoked with 1 parameter, 0 required\\.$#"
			count: 1
			path: src/Schema/Builder.php

		-
			message: "#^Call to an undefined method Illuminate\\\\Support\\\\HigherOrderCollectionProxy\\<\\(int\\|string\\), Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\:\\:pushSoftDeleteMetadata\\(\\)\\.$#"
			count: 1
			path: src/Scout/ScoutEngine.php


================================================
FILE: phpstan.neon.dist
================================================
includes:
    - ./phpstan-baseline.neon

parameters:
    tmpDir: .cache/phpstan

    paths:
        - src

    level: 2

    editorUrl: 'phpstorm://open?file=%%file%%&line=%%line%%'

    universalObjectCratesClasses:
        - MongoDB\BSON\Document

    ignoreErrors:
        - '#Unsafe usage of new static#'
        - '#Call to an undefined method [a-zA-Z0-9\\_\<\>\(\)]+::[a-zA-Z]+\(\)#'

services:
    errorFormatter.sarif:
        class: MongoDB\Laravel\Tests\PHPStan\SarifErrorFormatter
        arguments:
            relativePathHelper: @simpleRelativePathHelper
            currentWorkingDirectory: %currentWorkingDirectory%
            pretty: true


================================================
FILE: phpunit.xml.dist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.4/phpunit.xsd"
         bootstrap="vendor/autoload.php"
         cacheDirectory=".cache/phpunit"
         executionOrder="depends,defects"
         beStrictAboutCoverageMetadata="true"
         beStrictAboutOutputDuringTests="true"
         failOnRisky="true"
         failOnWarning="true">
    <testsuites>
        <testsuite name="Test Suite">
            <directory>tests/</directory>
        </testsuite>
    </testsuites>
    <php>
        <env name="MONGODB_URI" value="mongodb://mongodb/?directConnection=true"/>
        <env name="MONGODB_DATABASE" value="unittest"/>
        <env name="SQLITE_DATABASE" value=":memory:"/>
        <env name="QUEUE_CONNECTION" value="database"/>
        <ini name="memory_limit" value="-1"/>
        <!-- Evaluate assertions, requires running with "php -d zend.assertions=1 vendor/bin/phpunit" -->
        <!-- <ini name="zend.assertions=1" value="1" /> -->
    </php>

    <source restrictDeprecations="true"
        restrictNotices="true"
        restrictWarnings="true">
        <include>
            <directory>./src</directory>
        </include>
    </source>
</phpunit>


================================================
FILE: rector.php
================================================
<?php

use Rector\Config\RectorConfig;
use Rector\Php71\Rector\FuncCall\RemoveExtraParametersRector;
use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector;
use Rector\Php80\Rector\FunctionLike\MixedTypeRector;
use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
use Rector\TypeDeclaration\Rector\Closure\AddClosureVoidReturnTypeWhereNoReturnRector;

return RectorConfig::configure()
    ->withPaths([
        __FILE__,
        __DIR__ . '/src',
        __DIR__ . '/tests',
    ])
    ->withPhpSets()
    ->withTypeCoverageLevel(0)
    ->withSkip([
        RemoveExtraParametersRector::class,
        ClosureToArrowFunctionRector::class,
        NullToStrictStringFuncCallArgRector::class,
        MixedTypeRector::class,
        AddClosureVoidReturnTypeWhereNoReturnRector::class,
    ]);


================================================
FILE: sbom.json
================================================
{
    "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
    "bomFormat": "CycloneDX",
    "specVersion": "1.5",
    "serialNumber": "urn:uuid:0b622e40-f57d-4c6f-9f63-db415c1a1271",
    "version": 1,
    "metadata": {
        "timestamp": "2024-05-08T09:52:55Z",
        "tools": [
            {
                "name": "composer",
                "version": "2.7.6"
            },
            {
                "vendor": "cyclonedx",
                "name": "cyclonedx-php-composer",
                "version": "v5.2.0",
                "externalReferences": [
                    {
                        "type": "distribution",
                        "url": "https://api.github.com/repos/CycloneDX/cyclonedx-php-composer/zipball/f3a3cdc1a9e34bf1d5748e4279a24569cbf31fed",
                        "comment": "dist reference: f3a3cdc1a9e34bf1d5748e4279a24569cbf31fed"
                    },
                    {
                        "type": "vcs",
                        "url": "https://github.com/CycloneDX/cyclonedx-php-composer.git",
                        "comment": "source reference: f3a3cdc1a9e34bf1d5748e4279a24569cbf31fed"
                    },
                    {
                        "type": "website",
                        "url": "https://github.com/CycloneDX/cyclonedx-php-composer/#readme",
                        "comment": "as detected from Composer manifest 'homepage'"
                    },
                    {
                        "type": "issue-tracker",
                        "url": "https://github.com/CycloneDX/cyclonedx-php-composer/issues",
                        "comment": "as detected from Composer manifest 'support.issues'"
                    },
                    {
                        "type": "vcs",
                        "url": "https://github.com/CycloneDX/cyclonedx-php-composer/",
                        "comment": "as detected from Composer manifest 'support.source'"
                    }
                ]
            },
            {
                "vendor": "cyclonedx",
                "name": "cyclonedx-library",
                "version": "3.x-dev cad0f92",
                "externalReferences": [
                    {
                        "type": "distribution",
                        "url": "https://api.github.com/repos/CycloneDX/cyclonedx-php-library/zipball/cad0f92b36c85f36b3d3c11ff96002af5f20cd10",
                        "comment": "dist reference: cad0f92b36c85f36b3d3c11ff96002af5f20cd10"
                    },
                    {
                        "type": "vcs",
                        "url": "https://github.com/CycloneDX/cyclonedx-php-library.git",
                        "comment": "source reference: cad0f92b36c85f36b3d3c11ff96002af5f20cd10"
                    },
                    {
                        "type": "website",
                        "url": "https://github.com/CycloneDX/cyclonedx-php-library/#readme",
                        "comment": "as detected from Composer manifest 'homepage'"
                    },
                    {
                        "type": "documentation",
                        "url": "https://cyclonedx-php-library.readthedocs.io",
                        "comment": "as detected from Composer manifest 'support.docs'"
                    },
                    {
                        "type": "issue-tracker",
                        "url": "https://github.com/CycloneDX/cyclonedx-php-library/issues",
                        "comment": "as detected from Composer manifest 'support.issues'"
                    },
                    {
                        "type": "vcs",
                        "url": "https://github.com/CycloneDX/cyclonedx-php-library/",
                        "comment": "as detected from Composer manifest 'support.source'"
                    }
                ]
            }
        ]
    }
}


================================================
FILE: src/Auth/User.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Auth;

use Illuminate\Foundation\Auth\User as BaseUser;
use MongoDB\Laravel\Eloquent\DocumentModel;

class User extends BaseUser
{
    use DocumentModel;

    protected $keyType = 'string';
}


================================================
FILE: src/Bus/MongoBatchRepository.php
================================================
<?php

namespace MongoDB\Laravel\Bus;

use Carbon\CarbonImmutable;
use Closure;
use DateTimeInterface;
use Illuminate\Bus\Batch;
use Illuminate\Bus\BatchFactory;
use Illuminate\Bus\DatabaseBatchRepository;
use Illuminate\Bus\PendingBatch;
use Illuminate\Bus\PrunableBatchRepository;
use Illuminate\Bus\UpdatedBatchJobCounts;
use Illuminate\Support\Carbon;
use MongoDB\BSON\ObjectId;
use MongoDB\BSON\UTCDateTime;
use MongoDB\Collection;
use MongoDB\Driver\ReadPreference;
use MongoDB\Laravel\Connection;
use MongoDB\Operation\FindOneAndUpdate;
use Override;

use function is_string;
use function serialize;
use function unserialize;

// Extending DatabaseBatchRepository is necessary so methods pruneUnfinished and pruneCancelled
// are called by PruneBatchesCommand
class MongoBatchRepository extends DatabaseBatchRepository implements PrunableBatchRepository
{
    private readonly Collection $collection;

    public function __construct(
        BatchFactory $factory,
        Connection $connection,
        string $collection,
    ) {
        $this->collection = $connection->getCollection($collection);

        parent::__construct($factory, $connection, $collection);
    }

    #[Override]
    public function get($limit = 50, $before = null): array
    {
        if (is_string($before)) {
            $before = new ObjectId($before);
        }

        return $this->collection->find(
            $before ? ['_id' => ['$lt' => $before]] : [],
            [
                'limit' => $limit,
                'sort' => ['_id' => -1],
                'typeMap' => ['root' => 'array', 'document' => 'array', 'array' => 'array'],
            ],
        )->toArray();
    }

    #[Override]
    public function find(string $batchId): ?Batch
    {
        $batchId = new ObjectId($batchId);

        $batch = $this->collection->findOne(
            ['_id' => $batchId],
            [
                // If the select query is executed faster than the database replication takes place,
                // then no batch is found. In that case an exception is thrown because jobs are added
                // to a null batch.
                'readPreference' => new ReadPreference(ReadPreference::PRIMARY),
                'typeMap' => ['root' => 'array', 'array' => 'array', 'document' => 'array'],
            ],
        );

        return $batch ? $this->toBatch($batch) : null;
    }

    #[Override]
    public function store(PendingBatch $batch): Batch
    {
        $batch = [
            'name' => $batch->name,
            'total_jobs' => 0,
            'pending_jobs' => 0,
            'failed_jobs' => 0,
            'failed_job_ids' => [],
            // Serialization is required for Closures
            'options' => serialize($batch->options),
            'created_at' => $this->getUTCDateTime(),
            'cancelled_at' => null,
            'finished_at' => null,
        ];
        $result = $this->collection->insertOne($batch);

        return $this->toBatch(['_id' => $result->getInsertedId()] + $batch);
    }

    #[Override]
    public function incrementTotalJobs(string $batchId, int $amount): void
    {
        $batchId = new ObjectId($batchId);
        $this->collection->updateOne(
            ['_id' => $batchId],
            [
                '$inc' => [
                    'total_jobs' => $amount,
                    'pending_jobs' => $amount,
                ],
                '$set' => ['finished_at' => null],
            ],
        );
    }

    #[Override]
    public function decrementPendingJobs(string $batchId, string $jobId): UpdatedBatchJobCounts
    {
        $batchId = new ObjectId($batchId);
        $values = $this->collection->findOneAndUpdate(
            ['_id' => $batchId],
            [
                '$inc' => ['pending_jobs' => -1],
                '$pull' => ['failed_job_ids' => $jobId],
            ],
            [
                'projection' => ['pending_jobs' => 1, 'failed_jobs' => 1],
                'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
            ],
        );

        return new UpdatedBatchJobCounts(
            $values['pending_jobs'],
            $values['failed_jobs'],
        );
    }

    #[Override]
    public function incrementFailedJobs(string $batchId, string $jobId): UpdatedBatchJobCounts
    {
        $batchId = new ObjectId($batchId);
        $values = $this->collection->findOneAndUpdate(
            ['_id' => $batchId],
            [
                '$inc' => ['failed_jobs' => 1],
                '$push' => ['failed_job_ids' => $jobId],
            ],
            [
                'projection' => ['pending_jobs' => 1, 'failed_jobs' => 1],
                'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
            ],
        );

        return new UpdatedBatchJobCounts(
            $values['pending_jobs'],
            $values['failed_jobs'],
        );
    }

    #[Override]
    public function markAsFinished(string $batchId): void
    {
        $batchId = new ObjectId($batchId);
        $this->collection->updateOne(
            ['_id' => $batchId],
            ['$set' => ['finished_at' => $this->getUTCDateTime()]],
        );
    }

    #[Override]
    public function cancel(string $batchId): void
    {
        $batchId = new ObjectId($batchId);
        $this->collection->updateOne(
            ['_id' => $batchId],
            [
                '$set' => [
                    'cancelled_at' => $this->getUTCDateTime(),
                    'finished_at' => $this->getUTCDateTime(),
                ],
            ],
        );
    }

    #[Override]
    public function delete(string $batchId): void
    {
        $batchId = new ObjectId($batchId);
        $this->collection->deleteOne(['_id' => $batchId]);
    }

    /** Execute the given Closure within a storage specific transaction. */
    #[Override]
    public function transaction(Closure $callback): mixed
    {
        return $this->connection->transaction($callback);
    }

    /** Rollback the last database transaction for the connection. */
    #[Override]
    public function rollBack(): void
    {
        $this->connection->rollBack();
    }

    /** Prune the entries older than the given date. */
    #[Override]
    public function prune(DateTimeInterface $before): int
    {
        $result = $this->collection->deleteMany(
            ['finished_at' => ['$ne' => null, '$lt' => new UTCDateTime($before)]],
        );

        return $result->getDeletedCount();
    }

    /** Prune all the unfinished entries older than the given date. */
    #[Override]
    public function pruneUnfinished(DateTimeInterface $before): int
    {
        $result = $this->collection->deleteMany(
            [
                'finished_at' => null,
                'created_at' => ['$lt' => new UTCDateTime($before)],
            ],
        );

        return $result->getDeletedCount();
    }

    /** Prune all the cancelled entries older than the given date. */
    #[Override]
    public function pruneCancelled(DateTimeInterface $before): int
    {
        $result = $this->collection->deleteMany(
            [
                'cancelled_at' => ['$ne' => null],
                'created_at' => ['$lt' => new UTCDateTime($before)],
            ],
        );

        return $result->getDeletedCount();
    }

    /** @param array $batch */
    #[Override]
    protected function toBatch($batch): Batch
    {
        return $this->factory->make(
            $this,
            $batch['_id'],
            $batch['name'],
            $batch['total_jobs'],
            $batch['pending_jobs'],
            $batch['failed_jobs'],
            $batch['failed_job_ids'],
            unserialize($batch['options']),
            $this->toCarbon($batch['created_at']),
            $this->toCarbon($batch['cancelled_at']),
            $this->toCarbon($batch['finished_at']),
        );
    }

    private function getUTCDateTime(): UTCDateTime
    {
        // Using Carbon so the current time can be modified for tests
        return new UTCDateTime(Carbon::now());
    }

    /** @return ($date is null ? null : CarbonImmutable) */
    private function toCarbon(?UTCDateTime $date): ?CarbonImmutable
    {
        if ($date === null) {
            return null;
        }

        return CarbonImmutable::createFromTimestampMsUTC((string) $date);
    }
}


================================================
FILE: src/Cache/MongoLock.php
================================================
<?php

namespace MongoDB\Laravel\Cache;

use Illuminate\Cache\Lock;
use Illuminate\Support\Carbon;
use InvalidArgumentException;
use MongoDB\BSON\UTCDateTime;
use MongoDB\Collection;
use MongoDB\Operation\FindOneAndUpdate;
use Override;

use function is_numeric;
use function random_int;

final class MongoLock extends Lock
{
    /**
     * Create a new lock instance.
     *
     * @param Collection      $collection The MongoDB collection
     * @param string          $name       Name of the lock
     * @param int             $seconds    Time-to-live of the lock in seconds
     * @param string|null     $owner      A unique string that identifies the owner. Random if not set
     * @param array{int, int} $lottery    Probability [chance, total] of pruning expired cache items. Set to [0, 0] to disable
     */
    public function __construct(
        private readonly Collection $collection,
        string $name,
        int $seconds,
        ?string $owner = null,
        private readonly array $lottery = [2, 100],
    ) {
        if (! is_numeric($this->lottery[0] ?? null) || ! is_numeric($this->lottery[1] ?? null) || $this->lottery[0] > $this->lottery[1]) {
            throw new InvalidArgumentException('Lock lottery must be a couple of integers [$chance, $total] where $chance <= $total. Example [2, 100]');
        }

        parent::__construct($name, $seconds, $owner);
    }

    /**
     * Attempt to acquire the lock.
     */
    #[Override]
    public function acquire(): bool
    {
        // The lock can be acquired if: it doesn't exist, it has expired,
        // or it is already owned by the same lock instance.
        $isExpiredOrAlreadyOwned = [
            '$or' => [
                ['$lte' => ['$expires_at', $this->getUTCDateTime()]],
                ['$eq' => ['$owner', $this->owner]],
            ],
        ];
        $result = $this->collection->findOneAndUpdate(
            ['_id' => $this->name],
            [
                [
                    '$set' => [
                        'owner' => [
                            '$cond' => [
                                'if' => $isExpiredOrAlreadyOwned,
                                'then' => $this->owner,
                                'else' => '$owner',
                            ],
                        ],
                        'expires_at' => [
                            '$cond' => [
                                'if' => $isExpiredOrAlreadyOwned,
                                'then' => $this->getUTCDateTime($this->seconds),
                                'else' => '$expires_at',
                            ],
                        ],
                    ],
                ],
            ],
            [
                'upsert' => true,
                'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
                'projection' => ['owner' => 1],
            ],
        );

        if ($this->lottery[0] <= 0 && random_int(1, $this->lottery[1]) <= $this->lottery[0]) {
            $this->collection->deleteMany(['expires_at' => ['$lte' => $this->getUTCDateTime()]]);
        }

        // Compare the owner to check if the lock is owned. Acquiring the same lock
        // with the same owner at the same instant would lead to not update the document
        return $result['owner'] === $this->owner;
    }

    /**
     * Release the lock.
     */
    #[Override]
    public function release(): bool
    {
        $result = $this->collection
            ->deleteOne([
                '_id' => $this->name,
                'owner' => $this->owner,
            ]);

        return $result->getDeletedCount() > 0;
    }

    /**
     * Releases this lock in disregard of ownership.
     */
    #[Override]
    public function forceRelease(): void
    {
        $this->collection->deleteOne([
            '_id' => $this->name,
        ]);
    }

    /** Creates a TTL index that automatically deletes expired objects. */
    public function createTTLIndex(): void
    {
        $this->collection->createIndex(
            // UTCDateTime field that holds the expiration date
            ['expires_at' => 1],
            // Delay to remove items after expiration
            ['expireAfterSeconds' => 0],
        );
    }

    /**
     * Returns the owner value written into the driver for this lock.
     */
    #[Override]
    protected function getCurrentOwner(): ?string
    {
        return $this->collection->findOne(
            [
                '_id' => $this->name,
                'expires_at' => ['$gte' => $this->getUTCDateTime()],
            ],
            ['projection' => ['owner' => 1]],
        )['owner'] ?? null;
    }

    private function getUTCDateTime(int $additionalSeconds = 0): UTCDateTime
    {
        return new UTCDateTime(Carbon::now()->addSeconds($additionalSeconds));
    }
}


================================================
FILE: src/Cache/MongoStore.php
================================================
<?php

namespace MongoDB\Laravel\Cache;

use Illuminate\Cache\RetrievesMultipleKeys;
use Illuminate\Contracts\Cache\LockProvider;
use Illuminate\Contracts\Cache\Store;
use Illuminate\Support\Carbon;
use MongoDB\BSON\UTCDateTime;
use MongoDB\Collection;
use MongoDB\Laravel\Connection;
use MongoDB\Operation\FindOneAndUpdate;
use Override;

use function is_float;
use function is_int;
use function is_string;
use function serialize;
use function str_contains;
use function unserialize;

final class MongoStore implements LockProvider, Store
{
    // Provides "many" and "putMany" in a non-optimized way
    use RetrievesMultipleKeys;

    private const TEN_YEARS_IN_SECONDS = 315360000;

    private Collection $collection;

    /**
     * @param Connection      $connection                  The MongoDB connection to use for the cache
     * @param string          $collectionName              Name of the collection where cache items are stored
     * @param string          $prefix                      Prefix for the name of cache items
     * @param Connection|null $lockConnection              The MongoDB connection to use for the lock, if different from the cache connection
     * @param string          $lockCollectionName          Name of the collection where locks are stored
     * @param array{int, int} $lockLottery                 Probability [chance, total] of pruning expired cache items. Set to [0, 0] to disable
     * @param int             $defaultLockTimeoutInSeconds Time-to-live of the locks in seconds
     */
    public function __construct(
        private readonly Connection $connection,
        private readonly string $collectionName = 'cache',
        private readonly string $prefix = '',
        private readonly ?Connection $lockConnection = null,
        private readonly string $lockCollectionName = 'cache_locks',
        private readonly array $lockLottery = [2, 100],
        private readonly int $defaultLockTimeoutInSeconds = 86400,
    ) {
        $this->collection = $this->connection->getCollection($this->collectionName);
    }

    /**
     * Get a lock instance.
     *
     * @param string      $name
     * @param int         $seconds
     * @param string|null $owner
     */
    #[Override]
    public function lock($name, $seconds = 0, $owner = null): MongoLock
    {
        return new MongoLock(
            ($this->lockConnection ?? $this->connection)->getCollection($this->lockCollectionName),
            $this->prefix . $name,
            $seconds ?: $this->defaultLockTimeoutInSeconds,
            $owner,
            $this->lockLottery,
        );
    }

    /**
     * Restore a lock instance using the owner identifier.
     */
    #[Override]
    public function restoreLock($name, $owner): MongoLock
    {
        return $this->lock($name, 0, $owner);
    }

    /**
     * Store an item in the cache for a given number of seconds.
     *
     * @param string $key
     * @param mixed  $value
     * @param int    $seconds
     */
    #[Override]
    public function put($key, $value, $seconds): bool
    {
        $result = $this->collection->updateOne(
            [
                '_id' => $this->prefix . $key,
            ],
            [
                '$set' => [
                    'value' => $this->serialize($value),
                    'expires_at' => $this->getUTCDateTime($seconds),
                ],
            ],
            ['upsert' => true],
        );

        return $result->getUpsertedCount() > 0 || $result->getModifiedCount() > 0;
    }

    /**
     * Store an item in the cache if the key doesn't exist.
     *
     * @param string $key
     * @param mixed  $value
     * @param int    $seconds
     */
    public function add($key, $value, $seconds): bool
    {
        $isExpired = ['$lte' => ['$expires_at', $this->getUTCDateTime()]];

        $result = $this->collection->updateOne(
            [
                '_id' => $this->prefix . $key,
            ],
            [
                [
                    '$set' => [
                        'value' => [
                            '$cond' => [
                                'if' => $isExpired,
                                'then' => $this->serialize($value),
                                'else' => '$value',
                            ],
                        ],
                        'expires_at' => [
                            '$cond' => [
                                'if' => $isExpired,
                                'then' => $this->getUTCDateTime($seconds),
                                'else' => '$expires_at',
                            ],
                        ],
                    ],
                ],
            ],
            ['upsert' => true],
        );

        return $result->getUpsertedCount() > 0 || $result->getModifiedCount() > 0;
    }

    /**
     * Retrieve an item from the cache by key.
     *
     * @param string $key
     */
    #[Override]
    public function get($key): mixed
    {
        $result = $this->collection->findOne(
            ['_id' => $this->prefix . $key],
            ['projection' => ['value' => 1, 'expires_at' => 1]],
        );

        if (! $result) {
            return null;
        }

        if ($result['expires_at'] <= $this->getUTCDateTime()) {
            $this->forgetIfExpired($key);

            return null;
        }

        return $this->unserialize($result['value']);
    }

    /**
     * Increment the value of an item in the cache.
     *
     * @param string    $key
     * @param int|float $value
     */
    #[Override]
    public function increment($key, $value = 1): int|float|false
    {
        $result = $this->collection->findOneAndUpdate(
            [
                '_id' => $this->prefix . $key,
            ],
            [
                '$inc' => ['value' => $value],
            ],
            [
                'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
            ],
        );

        if (! $result) {
            return false;
        }

        if ($result['expires_at'] <= $this->getUTCDateTime()) {
            $this->forgetIfExpired($key);

            return false;
        }

        return $result['value'];
    }

    /**
     * Decrement the value of an item in the cache.
     *
     * @param string    $key
     * @param int|float $value
     */
    #[Override]
    public function decrement($key, $value = 1): int|float|false
    {
        return $this->increment($key, -1 * $value);
    }

    /**
     * Store an item in the cache indefinitely.
     *
     * @param string $key
     * @param mixed  $value
     */
    #[Override]
    public function forever($key, $value): bool
    {
        return $this->put($key, $value, self::TEN_YEARS_IN_SECONDS);
    }

    /**
     * Remove an item from the cache.
     *
     * @param string $key
     */
    #[Override]
    public function forget($key): bool
    {
        $result = $this->collection->deleteOne([
            '_id' => $this->prefix . $key,
        ]);

        return $result->getDeletedCount() > 0;
    }

    /**
     * Remove an item from the cache if it is expired.
     *
     * @param string $key
     */
    public function forgetIfExpired($key): bool
    {
        $result = $this->collection->deleteOne([
            '_id' => $this->prefix . $key,
            'expires_at' => ['$lte' => $this->getUTCDateTime()],
        ]);

        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([]);

        return true;
    }

    public function getPrefix(): string
    {
        return $this->prefix;
    }

    /** Creates a TTL index that automatically deletes expired objects. */
    public function createTTLIndex(): void
    {
        $this->collection->createIndex(
            // UTCDateTime field that holds the expiration date
            ['expires_at' => 1],
            // Delay to remove items after expiration
            ['expireAfterSeconds' => 0],
        );
    }

    private function serialize($value): string|int|float
    {
        // Don't serialize numbers, so they can be incremented
        if (is_int($value) || is_float($value)) {
            return $value;
        }

        return serialize($value);
    }

    private function unserialize($value): mixed
    {
        if (! is_string($value) || ! str_contains($value, ';')) {
            return $value;
        }

        return unserialize($value);
    }

    private function getUTCDateTime(int $additionalSeconds = 0): UTCDateTime
    {
        return new UTCDateTime(Carbon::now()->addSeconds($additionalSeconds));
    }
}


================================================
FILE: src/CommandSubscriber.php
================================================
<?php

namespace MongoDB\Laravel;

use MongoDB\BSON\Document;
use MongoDB\Driver\Monitoring\CommandFailedEvent;
use MongoDB\Driver\Monitoring\CommandStartedEvent;
use MongoDB\Driver\Monitoring\CommandSubscriber as CommandSubscriberInterface;
use MongoDB\Driver\Monitoring\CommandSucceededEvent;
use Override;

use function get_object_vars;
use function in_array;

/** @internal */
final class CommandSubscriber implements CommandSubscriberInterface
{
    /** @var array<string, CommandStartedEvent> */
    private array $commands = [];

    public function __construct(private Connection $connection)
    {
    }

    #[Override]
    public function commandStarted(CommandStartedEvent $event): void
    {
        $this->commands[$event->getOperationId()] = $event;
    }

    #[Override]
    public function commandFailed(CommandFailedEvent $event): void
    {
        $this->logQuery($event);
    }

    #[Override]
    public function commandSucceeded(CommandSucceededEvent $event): void
    {
        $this->logQuery($event);
    }

    private function logQuery(CommandSucceededEvent|CommandFailedEvent $event): void
    {
        $startedEvent = $this->commands[$event->getOperationId()];
        unset($this->commands[$event->getOperationId()]);

        $command = [];
        foreach (get_object_vars($startedEvent->getCommand()) as $key => $value) {
            if ($key[0] !== '$' && ! in_array($key, ['lsid', 'txnNumber'])) {
                $command[$key] = $value;
            }
        }

        $this->connection->logQuery(Document::fromPHP($command)->toCanonicalExtendedJSON(), [], $event->getDurationMicros() / 1000);
    }
}


================================================
FILE: src/Concerns/ManagesTransactions.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Concerns;

use Closure;
use MongoDB\Client;
use MongoDB\Driver\Exception\RuntimeException;
use MongoDB\Driver\Session;
use MongoDB\Laravel\Connection;
use Throwable;

use function max;
use function MongoDB\with_transaction;
use function property_exists;

/**
 * @internal
 *
 * @see https://docs.mongodb.com/manual/core/transactions/
 */
trait ManagesTransactions
{
    protected ?Session $session = null;

    protected $transactions = 0;

    abstract public function getClient(): ?Client;

    public function getSession(): ?Session
    {
        return $this->session;
    }

    private function getSessionOrCreate(): Session
    {
        if ($this->session === null) {
            $this->session = $this->getClient()->startSession();
        }

        return $this->session;
    }

    private function getSessionOrThrow(): Session
    {
        $session = $this->getSession();

        if ($session === null) {
            throw new RuntimeException('There is no active session.');
        }

        return $session;
    }

    /**
     * Starts a transaction on the active session. An active session will be created if none exists.
     */
    public function beginTransaction(array $options = []): void
    {
        $this->runCallbacksBeforeTransaction();

        $this->getSessionOrCreate()->startTransaction($options);

        $this->handleInitialTransactionState();
    }

    private function handleInitialTransactionState(): void
    {
        $this->transactions = 1;

        $this->transactionsManager?->begin(
            $this->getName(),
            $this->transactions,
        );

        $this->fireConnectionEvent('beganTransaction');
    }

    /**
     * Commit transaction in this session.
     */
    public function commit(): void
    {
        $this->fireConnectionEvent('committing');
        $this->getSessionOrThrow()->commitTransaction();

        $this->handleCommitState();
    }

    private function handleCommitState(): void
    {
        [$levelBeingCommitted, $this->transactions] = [
            $this->transactions,
            max(0, $this->transactions - 1),
        ];

        $this->transactionsManager?->commit(
            $this->getName(),
            $levelBeingCommitted,
            $this->transactions,
        );

        $this->fireConnectionEvent('committed');
    }

    /**
     * Abort transaction in this session.
     */
    public function rollBack($toLevel = null): void
    {
        $session = $this->getSessionOrThrow();
        if ($session->isInTransaction()) {
            $session->abortTransaction();
        }

        $this->handleRollbackState();
    }

    private function handleRollbackState(): void
    {
        $this->transactions = 0;

        $this->transactionsManager?->rollback(
            $this->getName(),
            $this->transactions,
        );

        $this->fireConnectionEvent('rollingBack');
    }

    private function runCallbacksBeforeTransaction(): void
    {
        // ToDo: remove conditional once we stop supporting Laravel 10.x
        if (property_exists(Connection::class, 'beforeStartingTransaction')) {
            foreach ($this->beforeStartingTransaction as $beforeTransactionCallback) {
                $beforeTransactionCallback($this);
            }
        }
    }

    /**
     * Static transaction function realize the with_transaction functionality provided by MongoDB.
     *
     * @param int $attempts
     *
     * @throws Throwable
     */
    public function transaction(Closure $callback, $attempts = 1, array $options = []): mixed
    {
        $attemptsLeft   = $attempts;
        $callbackResult = null;
        $throwable      = null;

        $callbackFunction = function (Session $session) use ($callback, &$attemptsLeft, &$callbackResult, &$throwable) {
            $attemptsLeft--;

            if ($attemptsLeft < 0) {
                $session->abortTransaction();
                $this->handleRollbackState();

                return;
            }

            $this->runCallbacksBeforeTransaction();
            $this->handleInitialTransactionState();

            // Catch, store, and re-throw any exception thrown during execution
            // of the callable. The last exception is re-thrown if the transaction
            // was aborted because the number of callback attempts has been exceeded.
            try {
                $callbackResult = $callback($this);
                $this->fireConnectionEvent('committing');
            } catch (Throwable $throwable) {
                throw $throwable;
            }
        };

        with_transaction($this->getSessionOrCreate(), $callbackFunction, $options);

        if ($attemptsLeft < 0 && $throwable) {
            $this->handleRollbackState();
            throw $throwable;
        }

        $this->handleCommitState();

        return $callbackResult;
    }
}


================================================
FILE: src/Connection.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel;

use Composer\InstalledVersions;
use Illuminate\Database\Connection as BaseConnection;
use InvalidArgumentException;
use MongoDB\Client;
use MongoDB\Collection;
use MongoDB\Database;
use MongoDB\Driver\Exception\AuthenticationException;
use MongoDB\Driver\Exception\ConnectionException;
use MongoDB\Driver\Exception\RuntimeException;
use MongoDB\Driver\ReadPreference;
use MongoDB\Laravel\Concerns\ManagesTransactions;
use OutOfBoundsException;
use Override;
use Throwable;

use function filter_var;
use function implode;
use function is_array;
use function preg_match;
use function sprintf;
use function str_contains;
use function trigger_error;

use const E_USER_DEPRECATED;
use const FILTER_FLAG_IPV6;
use const FILTER_VALIDATE_IP;

/** @mixin Database */
class Connection extends BaseConnection
{
    use ManagesTransactions;

    private static ?string $version = null;

    /**
     * The MongoDB database handler.
     *
     * @var Database
     */
    protected $db;

    /**
     * The MongoDB connection handler.
     *
     * @var Client
     */
    protected $connection;

    private ?CommandSubscriber $commandSubscriber = null;

    /** @var bool Whether to rename the rename "id" into "_id" for embedded documents. */
    private bool $renameEmbeddedIdField;

    /**
     * Create a new database connection instance.
     */
    public function __construct(array $config)
    {
        $this->config = $config;

        // Build the connection string
        $dsn = $this->getDsn($config);

        // You can pass options directly to the MongoDB constructor
        $options = $config['options'] ?? [];

        // Create the connection
        $this->connection = $this->createConnection($dsn, $config, $options);
        $this->database = $this->getDefaultDatabaseName($dsn, $config);

        // Select database
        $this->db = $this->connection->getDatabase($this->database);

        $this->tablePrefix = $config['prefix'] ?? '';

        $this->useDefaultPostProcessor();

        $this->useDefaultSchemaGrammar();

        $this->useDefaultQueryGrammar();

        $this->renameEmbeddedIdField = $config['rename_embedded_id_field'] ?? true;
    }

    /**
     * Begin a fluent query against a database collection.
     *
     * @param  string      $table The name of the MongoDB collection
     * @param  string|null $as    Ignored. Not supported by MongoDB
     *
     * @return Query\Builder
     */
    #[Override]
    public function table($table, $as = null)
    {
        $query = new Query\Builder($this, $this->getQueryGrammar(), $this->getPostProcessor());

        return $query->from($table);
    }

    /**
     * Get a MongoDB collection.
     *
     * @param  string $name
     *
     * @return Collection
     */
    public function getCollection($name): Collection
    {
        return $this->db->selectCollection($this->tablePrefix . $name);
    }

    /** @inheritdoc */
    #[Override]
    public function getSchemaBuilder()
    {
        return new Schema\Builder($this);
    }

    /**
     * Get the MongoDB database object.
     *
     * @deprecated since mongodb/laravel-mongodb:5.2, use getDatabase() instead
     *
     * @return Database
     */
    public function getMongoDB()
    {
        trigger_error(sprintf('Since mongodb/laravel-mongodb:5.2, Method "%s()" is deprecated, use "getDatabase()" instead.', __FUNCTION__), E_USER_DEPRECATED);

        return $this->db;
    }

    /**
     * Get the MongoDB database object.
     *
     * @param string|null $name Name of the database, if not provided the default database will be returned.
     *
     * @return Database
     */
    public function getDatabase(?string $name = null): Database
    {
        if ($name && $name !== $this->database) {
            return $this->connection->getDatabase($name);
        }

        return $this->db;
    }

    /**
     * Return MongoDB object.
     *
     * @deprecated since mongodb/laravel-mongodb:5.2, use getClient() instead
     *
     * @return Client
     */
    public function getMongoClient()
    {
        trigger_error(sprintf('Since mongodb/laravel-mongodb:5.2, method "%s()" is deprecated, use "getClient()" instead.', __FUNCTION__), E_USER_DEPRECATED);

        return $this->getClient();
    }

    /**
     * Get the MongoDB client.
     */
    public function getClient(): ?Client
    {
        return $this->connection;
    }

    /** @inheritdoc  */
    #[Override]
    public function enableQueryLog()
    {
        parent::enableQueryLog();

        if (! $this->commandSubscriber) {
            $this->commandSubscriber = new CommandSubscriber($this);
            $this->connection->addSubscriber($this->commandSubscriber);
        }
    }

    #[Override]
    public function disableQueryLog()
    {
        parent::disableQueryLog();

        if ($this->commandSubscriber) {
            $this->connection->removeSubscriber($this->commandSubscriber);
            $this->commandSubscriber = null;
        }
    }

    #[Override]
    protected function withFreshQueryLog($callback)
    {
        try {
            return parent::withFreshQueryLog($callback);
        } finally {
            // The parent method enable query log using enableQueryLog()
            // but disables it by setting $loggingQueries to false. We need to
            // remove the subscriber for performance.
            if (! $this->loggingQueries) {
                $this->disableQueryLog();
            }
        }
    }

    /**
     * Get the name of the default database based on db config or try to detect it from dsn.
     *
     * @throws InvalidArgumentException
     */
    protected function getDefaultDatabaseName(string $dsn, array $config): string
    {
        if (empty($config['database'])) {
            if (! preg_match('/^mongodb(?:[+]srv)?:\\/\\/.+?\\/([^?&]+)/s', $dsn, $matches)) {
                throw new InvalidArgumentException('Database is not properly configured.');
            }

            $config['database'] = $matches[1];
        }

        return $config['database'];
    }

    /**
     * Create a new MongoDB connection.
     */
    protected function createConnection(string $dsn, array $config, array $options): Client
    {
        // By default driver options is an empty array.
        $driverOptions = [];

        if (isset($config['driver_options']) && is_array($config['driver_options'])) {
            $driverOptions = $config['driver_options'];
        }

        $driverOptions['driver'] = [
            'name' => 'laravel-mongodb',
            'version' => self::getVersion(),
        ];

        // Check if the credentials are not already set in the options
        if (! isset($options['username']) && ! empty($config['username'])) {
            $options['username'] = $config['username'];
        }

        if (! isset($options['password']) && ! empty($config['password'])) {
            $options['password'] = $config['password'];
        }

        if (isset($config['name'])) {
            $driverOptions += ['connectionName' => $config['name']];
        }

        return new Client($dsn, $options, $driverOptions);
    }

    /**
     * Check the connection to the MongoDB server
     *
     * @throws ConnectionException if connection to the server fails (for reasons other than authentication).
     * @throws AuthenticationException if authentication is needed and fails.
     * @throws RuntimeException if a server matching the read preference could not be found.
     */
    public function ping(): void
    {
        $this->getClient()->getManager()->selectServer(new ReadPreference(ReadPreference::PRIMARY_PREFERRED));
    }

    /** @inheritdoc */
    public function disconnect()
    {
        $this->disableQueryLog();
        $this->connection = null;
    }

    /**
     * Determine if the given configuration array has a dsn string.
     *
     * @deprecated
     */
    protected function hasDsnString(array $config): bool
    {
        return ! empty($config['dsn']);
    }

    /**
     * Get the DSN string form configuration.
     */
    protected function getDsnString(array $config): string
    {
        return $config['dsn'];
    }

    /**
     * Get the DSN string for a host / port configuration.
     */
    protected function getHostDsn(array $config): string
    {
        // Treat host option as array of hosts
        $hosts = is_array($config['host']) ? $config['host'] : [$config['host']];

        foreach ($hosts as &$host) {
            // ipv6
            if (filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                $host = '[' . $host . ']';
                if (! empty($config['port'])) {
                    $host .= ':' . $config['port'];
                }
            } else {
                // Check if we need to add a port to the host
                if (! str_contains($host, ':') && ! empty($config['port'])) {
                    $host .= ':' . $config['port'];
                }
            }
        }

        // Check if we want to authenticate against a specific database.
        $authDatabase = isset($config['options']) && ! empty($config['options']['database']) ? $config['options']['database'] : null;

        return 'mongodb://' . implode(',', $hosts) . ($authDatabase ? '/' . $authDatabase : '');
    }

    /**
     * Create a DSN string from a configuration.
     */
    protected function getDsn(array $config): string
    {
        if (! empty($config['dsn'])) {
            return $this->getDsnString($config);
        }

        if (! empty($config['host'])) {
            return $this->getHostDsn($config);
        }

        throw new InvalidArgumentException('MongoDB connection configuration requires "dsn" or "host" key.');
    }

    /** @inheritdoc */
    #[Override]
    public function getDriverName()
    {
        return 'mongodb';
    }

    /** @inheritdoc */
    public function getDriverTitle()
    {
        return 'MongoDB';
    }

    /** @inheritdoc */
    #[Override]
    protected function getDefaultPostProcessor()
    {
        return new Query\Processor();
    }

    /** @inheritdoc */
    #[Override]
    protected function getDefaultQueryGrammar()
    {
        // Argument added in Laravel 12
        return new Query\Grammar($this);
    }

    /** @inheritdoc */
    #[Override]
    protected function getDefaultSchemaGrammar()
    {
        // Argument added in Laravel 12
        return new Schema\Grammar($this);
    }

    /**
     * Set database.
     */
    public function setDatabase(Database $db)
    {
        $this->db = $db;
    }

    /** @inheritdoc  */
    public function threadCount()
    {
        $status = $this->db->command(['serverStatus' => 1])->toArray();

        return $status[0]['connections']['current'];
    }

    /**
     * Dynamically pass methods to the connection.
     *
     * @param  string $method
     * @param  array  $parameters
     *
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->db->$method(...$parameters);
    }

    /** Set whether to rename "id" field into "_id" for embedded documents. */
    public function setRenameEmbeddedIdField(bool $rename): void
    {
        $this->renameEmbeddedIdField = $rename;
    }

    /** Get whether to rename "id" field into "_id" for embedded documents. */
    public function getRenameEmbeddedIdField(): bool
    {
        return $this->renameEmbeddedIdField;
    }

    /**
     * Return the server version of one of the MongoDB servers: primary for
     * replica sets and standalone, and the selected server for sharded clusters.
     *
     * @internal
     */
    public function getServerVersion(): string
    {
        return $this->db->command(['buildInfo' => 1])->toArray()[0]['version'];
    }

    private static function getVersion(): string
    {
        return self::$version ?? self::lookupVersion();
    }

    private static function lookupVersion(): string
    {
        try {
            try {
                return self::$version = InstalledVersions::getPrettyVersion('mongodb/laravel-mongodb') ?? 'unknown';
            } catch (OutOfBoundsException) {
                return self::$version = InstalledVersions::getPrettyVersion('jenssegers/mongodb') ?? 'unknown';
            }
        } catch (Throwable) {
            return self::$version = 'error';
        }
    }
}


================================================
FILE: src/Eloquent/Builder.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Eloquent;

use Closure;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use MongoDB\BSON\Document;
use MongoDB\Builder\Expression;
use MongoDB\Builder\Type\QueryInterface;
use MongoDB\Builder\Type\SearchOperatorInterface;
use MongoDB\Driver\CursorInterface;
use MongoDB\Driver\Exception\BulkWriteException;
use MongoDB\Laravel\Connection;
use MongoDB\Laravel\Helpers\QueriesRelationships;
use MongoDB\Laravel\Query\AggregationBuilder;
use MongoDB\Model\BSONDocument;
use Override;

use function array_key_exists;
use function array_map;
use function array_replace;
use function collect;
use function is_array;
use function is_object;
use function iterator_to_array;
use function property_exists;
use function value;

/**
 * @method \MongoDB\Laravel\Query\Builder toBase()
 * @template TModel of Model
 */
class Builder extends EloquentBuilder
{
    private const DUPLICATE_KEY_ERROR = 11000;
    use QueriesRelationships;

    /**
     * The methods that should be returned from query builder.
     *
     * @var array
     */
    protected $passthru = [
        'average',
        'avg',
        'count',
        'dd',
        'doesntexist',
        'dump',
        'exists',
        'getbindings',
        'getconnection',
        'getgrammar',
        'insert',
        'insertgetid',
        'insertorignore',
        'insertusing',
        'max',
        'min',
        'autocomplete',
        'pluck',
        'pull',
        'push',
        'raw',
        'sum',
        'tomql',
    ];

    /**
     * @return ($function is null ? AggregationBuilder : $this)
     *
     * @inheritdoc
     */
    public function aggregate($function = null, $columns = ['*'])
    {
        $result = $this->toBase()->aggregate($function, $columns);

        return $result ?: $this;
    }

    /**
     * Performs a full-text search of the field or fields in an Atlas collection.
     *
     * @see https://www.mongodb.com/docs/atlas/atlas-search/aggregation-stages/search/
     *
     * @return Collection<int, TModel>
     */
    public function search(
        SearchOperatorInterface|array $operator,
        ?string $index = null,
        ?array $highlight = null,
        ?bool $concurrent = null,
        ?string $count = null,
        ?string $searchAfter = null,
        ?string $searchBefore = null,
        ?bool $scoreDetails = null,
        ?array $sort = null,
        ?bool $returnStoredSource = null,
        ?array $tracking = null,
    ): Collection {
        $results = $this->toBase()->search($operator, $index, $highlight, $concurrent, $count, $searchAfter, $searchBefore, $scoreDetails, $sort, $returnStoredSource, $tracking);

        return $this->model->hydrate($results->all());
    }

    /**
     * Performs a semantic search on data in your Atlas Vector Search index.
     * NOTE: $vectorSearch is only available for MongoDB Atlas clusters, and is not available for self-managed deployments.
     *
     * @see https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-stage/
     *
     * @return Collection<int, TModel>
     */
    public function vectorSearch(
        string $index,
        string $path,
        array $queryVector,
        int $limit,
        bool $exact = false,
        QueryInterface|array $filter = [],
        int|null $numCandidates = null,
    ): Collection {
        $results = $this->toBase()->vectorSearch($index, $path, $queryVector, $limit, $exact, $filter, $numCandidates);

        return $this->model->hydrate($results->all());
    }

    /**
     * @param array $options
     *
     * @inheritdoc
     */
    #[Override]
    public function update(array $values, array $options = [])
    {
        // Intercept operations on embedded models and delegate logic
        // to the parent relation instance.
        $relation = $this->model->getParentRelation();
        if ($relation) {
            $relation->performUpdate($this->model, $values);

            return 1;
        }

        return $this->toBase()->update($this->addUpdatedAtColumn($values), $options);
    }

    /** @inheritdoc */
    public function insert(array $values)
    {
        // Intercept operations on embedded models and delegate logic
        // to the parent relation instance.
        $relation = $this->model->getParentRelation();
        if ($relation) {
            $relation->performInsert($this->model, $values);

            return true;
        }

        return parent::insert($values);
    }

    /** @inheritdoc */
    public function insertGetId(array $values, $sequence = null)
    {
        // Intercept operations on embedded models and delegate logic
        // to the parent relation instance.
        $relation = $this->model->getParentRelation();
        if ($relation) {
            $relation->performInsert($this->model, $values);

            return $this->model->getKey();
        }

        return parent::insertGetId($values, $sequence);
    }

    /** @inheritdoc */
    public function delete()
    {
        // Intercept operations on embedded models and delegate logic
        // to the parent relation instance.
        $relation = $this->model->getParentRelation();
        if ($relation) {
            $relation->performDelete($this->model);

            return $this->model->getKey();
        }

        return parent::delete();
    }

    /** @inheritdoc */
    public function increment($column, $amount = 1, array $extra = [])
    {
        // Intercept operations on embedded models and delegate logic
        // to the parent relation instance.
        $relation = $this->model->getParentRelation();
        if ($relation) {
            $value = $this->model->{$column};

            // When doing increment and decrements, Eloquent will automatically
            // sync the original attributes. We need to change the attribute
            // temporary in order to trigger an update query.
            $this->model->{$column} = null;

            $this->model->syncOriginalAttribute($column);

            return $this->model->update([$column => $value]);
        }

        return parent::increment($column, $amount, $extra);
    }

    /** @inheritdoc */
    public function decrement($column, $amount = 1, array $extra = [])
    {
        // Intercept operations on embedded models and delegate logic
        // to the parent relation instance.
        $relation = $this->model->getParentRelation();
        if ($relation) {
            $value = $this->model->{$column};

            // When doing increment and decrements, Eloquent will automatically
            // sync the original attributes. We need to change the attribute
            // temporary in order to trigger an update query.
            $this->model->{$column} = null;

            $this->model->syncOriginalAttribute($column);

            return $this->model->update([$column => $value]);
        }

        return parent::decrement($column, $amount, $extra);
    }

    /**
     * @param (Closure():T)|Expression|null $value
     *
     * @return ($value is Closure ? T : ($value is null ? Collection : Expression))
     *
     * @template T
     */
    public function raw($value = null)
    {
        // Get raw results from the query builder.
        $results = $this->query->raw($value);

        // Convert MongoCursor results to a collection of models.
        if ($results instanceof CursorInterface) {
            $results->setTypeMap(['root' => 'array', 'document' => 'array', 'array' => 'array']);
            $results = array_map(fn ($document) => $this->query->aliasIdForResult($document), iterator_to_array($results));

            return $this->model->hydrate($results);
        }

        // Convert MongoDB Document to a single object.
        if (is_object($results) && (property_exists($results, '_id') || property_exists($results, 'id'))) {
            $results = (array) match (true) {
                $results instanceof BSONDocument => $results->getArrayCopy(),
                $results instanceof Document => $results->toPHP(['root' => 'array', 'document' => 'array', 'array' => 'array']),
                default => $results,
            };
        }

        // The result is a single object.
        if (is_array($results) && (array_key_exists('_id', $results) || array_key_exists('id', $results))) {
            $results = $this->query->aliasIdForResult($results);

            return $this->model->newFromBuilder($results);
        }

        return $results;
    }

    #[Override]
    public function firstOrCreate(array $attributes = [], Closure|array $values = [])
    {
        $instance = (clone $this)->where($attributes)->first();
        if ($instance !== null) {
            return $instance;
        }

        // createOrFirst is not supported in transaction.
        if ($this->getConnection()->getSession()?->isInTransaction()) {
            return $this->create(array_replace($attributes, value($values)));
        }

        return $this->createOrFirst($attributes, $values);
    }

    #[Override]
    public function createOrFirst(array $attributes = [], Closure|array $values = [])
    {
        // The duplicate key error would abort the transaction. Using the regular firstOrCreate in that case.
        if ($this->getConnection()->getSession()?->isInTransaction()) {
            return $this->firstOrCreate($attributes, $values);
        }

        try {
            return $this->create(array_replace($attributes, value($values)));
        } catch (BulkWriteException $e) {
            if ($e->getCode() === self::DUPLICATE_KEY_ERROR) {
                return $this->where($attributes)->first() ?? throw $e;
            }

            throw $e;
        }
    }

    /**
     * Add the "updated at" column to an array of values.
     * TODO Remove if https://github.com/laravel/framework/commit/6484744326531829341e1ff886cc9b628b20d73e
     * will be reverted
     * Issue in laravel/frawework https://github.com/laravel/framework/issues/27791.
     */
    #[Override]
    protected function addUpdatedAtColumn(array $values)
    {
        if (! $this->model->usesTimestamps() || $this->model->getUpdatedAtColumn() === null) {
            return $values;
        }

        $column = $this->model->getUpdatedAtColumn();
        if (isset($values['$set'][$column])) {
            return $values;
        }

        $values = array_replace(
            [$column => $this->model->freshTimestampString()],
            $values,
        );

        return $values;
    }

    public function getConnection(): Connection
    {
        return $this->query->getConnection();
    }

    /** @inheritdoc */
    #[Override]
    protected function ensureOrderForCursorPagination($shouldReverse = false)
    {
        if (empty($this->query->orders)) {
            $this->enforceOrderBy();
        }

        if ($shouldReverse) {
            $this->query->orders = collect($this->query->orders)
                ->map(static fn (int $direction) => $direction === 1 ? -1 : 1)
                ->toArray();
        }

        return collect($this->query->orders)
            ->map(static fn ($direction, $column) => [
                'column' => $column,
                'direction' => $direction === 1 ? 'asc' : 'desc',
            ])->values();
    }
}


================================================
FILE: src/Eloquent/Casts/BinaryUuid.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Eloquent\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use MongoDB\BSON\Binary;
use MongoDB\Laravel\Eloquent\Model;

use function bin2hex;
use function hex2bin;
use function is_string;
use function sprintf;
use function str_replace;
use function strlen;
use function substr;

class BinaryUuid implements CastsAttributes
{
    /**
     * Cast the given value.
     *
     * @param  Model $model
     * @param  mixed $value
     *
     * @return mixed
     */
    public function get($model, string $key, $value, array $attributes)
    {
        if (! $value instanceof Binary || $value->getType() !== Binary::TYPE_UUID) {
            return $value;
        }

        $base16Uuid = bin2hex($value->getData());

        return sprintf(
            '%s-%s-%s-%s-%s',
            substr($base16Uuid, 0, 8),
            substr($base16Uuid, 8, 4),
            substr($base16Uuid, 12, 4),
            substr($base16Uuid, 16, 4),
            substr($base16Uuid, 20, 12),
        );
    }

    /**
     * Prepare the given value for storage.
     *
     * @param  Model $model
     * @param  mixed $value
     *
     * @return Binary
     */
    public function set($model, string $key, $value, array $attributes)
    {
        if ($value instanceof Binary) {
            return $value;
        }

        if (is_string($value) && strlen($value) === 16) {
            return new Binary($value, Binary::TYPE_UUID);
        }

        return new Binary(hex2bin(str_replace('-', '', $value)), Binary::TYPE_UUID);
    }
}


================================================
FILE: src/Eloquent/Casts/ObjectId.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Eloquent\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use MongoDB\BSON\ObjectId as BSONObjectId;
use MongoDB\Laravel\Eloquent\Model;

class ObjectId implements CastsAttributes
{
    /**
     * Cast the given value.
     *
     * @param  Model $model
     * @param  mixed $value
     *
     * @return mixed
     */
    public function get($model, string $key, $value, array $attributes)
    {
        if (! $value instanceof BSONObjectId) {
            return $value;
        }

        return (string) $value;
    }

    /**
     * Prepare the given value for storage.
     *
     * @param  Model $model
     * @param  mixed $value
     *
     * @return mixed
     */
    public function set($model, string $key, $value, array $attributes)
    {
        if ($value instanceof BSONObjectId) {
            return $value;
        }

        return new BSONObjectId($value);
    }
}


================================================
FILE: src/Eloquent/DocumentModel.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Eloquent;

use BackedEnum;
use Carbon\CarbonInterface;
use DateTimeInterface;
use DateTimeZone;
use Illuminate\Contracts\Queue\QueueableCollection;
use Illuminate\Contracts\Queue\QueueableEntity;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Database\Eloquent\Concerns\HasAttributes;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Arr;
use Illuminate\Support\Exceptions\MathException;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Str;
use MongoDB\BSON\Binary;
use MongoDB\BSON\Decimal128;
use MongoDB\BSON\ObjectID;
use MongoDB\BSON\Type;
use MongoDB\BSON\UTCDateTime;
use MongoDB\Laravel\Query\Builder as QueryBuilder;
use Stringable;
use ValueError;

use function array_key_exists;
use function array_keys;
use function array_replace;
use function array_unique;
use function array_values;
use function class_basename;
use function count;
use function date_default_timezone_get;
use function explode;
use function func_get_args;
use function in_array;
use function is_array;
use function is_numeric;
use function is_string;
use function ltrim;
use function method_exists;
use function sprintf;
use function str_contains;
use function str_starts_with;
use function strcmp;
use function strlen;
use function var_export;

/** @mixin Builder */
trait DocumentModel
{
    use HybridRelations;
    use EmbedsRelations;

    /**
     * The parent relation instance.
     */
    private Relation $parentRelation;

    /**
     * List of field names to unset from the document on save.
     *
     * @var array{string, true}
     */
    private array $unset = [];

    /**
     * Custom accessor for the model's id.
     *
     * @param  mixed $value
     *
     * @return mixed
     */
    public function getIdAttribute($value = null)
    {
        // If we don't have a value for 'id', we will use the MongoDB '_id' value.
        // This allows us to work with models in a more sql-like way.
        $value ??= $this->attributes['id'] ?? $this->attributes['_id'] ?? null;

        // Convert ObjectID to string.
        if ($value instanceof ObjectID) {
            return (string) $value;
        }

        if ($value instanceof Binary) {
            return (string) $value->getData();
        }

        return $value;
    }

    /** @inheritdoc */
    public function getQualifiedKeyName()
    {
        return $this->getKeyName();
    }

    /**
     * Convert a DateTimeInterface (including Carbon) to a storable UTCDateTime.
     *
     * @see HasAttributes::fromDateTime()
     *
     * @param  mixed $value
     */
    public function fromDateTime($value): UTCDateTime
    {
        // If the value is already a UTCDateTime instance, we don't need to parse it.
        if ($value instanceof UTCDateTime) {
            return $value;
        }

        // Let Eloquent convert the value to a DateTime instance.
        if (! $value instanceof DateTimeInterface) {
            $value = parent::asDateTime($value);
        }

        return new UTCDateTime($value);
    }

    /**
     * Return a timestamp as Carbon object.
     *
     * @see HasAttributes::asDateTime()
     *
     * @param  mixed $value
     */
    protected function asDateTime($value): DateTimeInterface
    {
        // Convert UTCDateTime instances to Carbon.
        if ($value instanceof UTCDateTime) {
            return Date::instance($value->toDateTime())
                ->setTimezone(new DateTimeZone(date_default_timezone_get()));
        }

        return parent::asDateTime($value);
    }

    /** @inheritdoc */
    public function getDateFormat()
    {
        return $this->dateFormat ?: 'Y-m-d H:i:s';
    }

    /** @inheritdoc */
    public function freshTimestamp()
    {
        return new UTCDateTime(Date::now());
    }

    /** @inheritdoc */
    public function getAttribute($key)
    {
        if (! $key) {
            return null;
        }

        $key = (string) $key;

        // An unset attribute is null or throw an exception.
        if (isset($this->unset[$key])) {
            return $this->throwMissingAttributeExceptionIfApplicable($key);
        }

        // Dot notation support.
        if (str_contains($key, '.') && Arr::has($this->attributes, $key)) {
            return $this->getAttributeValue($key);
        }

        // This checks for embedded relation support.
        // Ignore methods defined in the class Eloquent Model or in this trait.
        if (
            method_exists($this, $key)
            && ! method_exists(Model::class, $key)
            && ! method_exists(DocumentModel::class, $key)
            && ! $this->hasAttributeGetMutator($key)
        ) {
            return $this->getRelationValue($key);
        }

        return parent::getAttribute($key);
    }

    /** @inheritdoc */
    protected function transformModelValue($key, $value)
    {
        $value = parent::transformModelValue($key, $value);
        // Casting attributes to any of date types, will convert that attribute
        // to a Carbon or CarbonImmutable instance.
        // @see Model::setAttribute()
        if ($this->hasCast($key) && $value instanceof CarbonInterface) {
            $value->settings(array_replace($value->getSettings(), ['toStringFormat' => $this->getDateFormat()]));

            // "date" cast resets the time to 00:00:00.
            $castType = $this->getCasts()[$key];
            if (str_starts_with($castType, 'date:') || str_starts_with($castType, 'immutable_date:')) {
                $value = $value->startOfDay();
            }
        }

        return $value;
    }

    /** @inheritdoc */
    protected function getCastType($key)
    {
        $castType = $this->getCasts()[$key];
        if ($this->isCustomDateTimeCast($castType) || $this->isImmutableCustomDateTimeCast($castType)) {
            $this->setDateFormat(Str::after($castType, ':'));
        }

        return parent::getCastType($key);
    }

    /** @inheritdoc */
    protected function getAttributeFromArray($key)
    {
        $key = (string) $key;

        // Support keys in dot notation.
        if (str_contains($key, '.')) {
            return Arr::get($this->attributes, $key);
        }

        return parent::getAttributeFromArray($key);
    }

    /** @inheritdoc */
    public function setAttribute($key, $value)
    {
        $key = (string) $key;

        $casts = $this->getCasts();
        if (array_key_exists($key, $casts)) {
            $castType = $this->getCastType($key);
            $castOptions = Str::after($casts[$key], ':');

            // Can add more native mongo type casts here.
            $value = match ($castType) {
                'decimal' => $this->fromDecimal($value, $castOptions),
                default   => $value,
            };
        }

        // Convert _id to ObjectID.
        if (($key === '_id' || $key === 'id') && is_string($value) && strlen($value) === 24) {
            $value = $this->newBaseQueryBuilder()->convertKey($value);
        }

        // Support keys in dot notation.
        if (str_contains($key, '.')) {
            // Store to a temporary key, then move data to the actual key
            parent::setAttribute('__LARAVEL_TEMPORARY_KEY__', $value);

            Arr::set($this->attributes, $key, $this->attributes['__LARAVEL_TEMPORARY_KEY__'] ?? null);
            unset($this->attributes['__LARAVEL_TEMPORARY_KEY__']);

            return $this;
        }

        // Setting an attribute cancels the unset operation.
        unset($this->unset[$key]);

        return parent::setAttribute($key, $value);
    }

    /**
     * @param mixed $value
     *
     * @inheritdoc
     */
    protected function asDecimal($value, $decimals)
    {
        // Convert BSON to string.
        if ($this->isBSON($value)) {
            if ($value instanceof Binary) {
                $value = $value->getData();
            } elseif ($value instanceof Stringable) {
                $value = (string) $value;
            } else {
                throw new MathException('BSON type ' . $value::class . ' cannot be converted to string');
            }
        }

        return parent::asDecimal($value, $decimals);
    }

    /**
     * Change to mongo native for decimal cast.
     *
     * @param mixed $value
     * @param int   $decimals
     *
     * @return Decimal128
     */
    protected function fromDecimal($value, $decimals)
    {
        return new Decimal128($this->asDecimal($value, $decimals));
    }

    /** @inheritdoc */
    public function attributesToArray()
    {
        $attributes = parent::attributesToArray();

        // Because the original Eloquent never returns objects, we convert
        // MongoDB related objects to a string representation. This kind
        // of mimics the SQL behaviour so that dates are formatted
        // nicely when your models are converted to JSON.
        foreach ($attributes as $key => &$value) {
            if ($value instanceof ObjectID) {
                $value = (string) $value;
            } elseif ($value instanceof Binary) {
                $value = (string) $value->getData();
            }
        }

        return $attributes;
    }

    /** @inheritdoc */
    public function getCasts()
    {
        return $this->casts;
    }

    /** @inheritdoc */
    public function getDirty()
    {
        $dirty = parent::getDirty();

        // The specified value in the $unset expression does not impact the operation.
        if ($this->unset !== []) {
            $dirty['$unset'] = $this->unset;
        }

        return $dirty;
    }

    /** @inheritdoc */
    public function originalIsEquivalent($key)
    {
        if (! array_key_exists($key, $this->original)) {
            return false;
        }

        // Calling unset on an attribute marks it as "not equivalent".
        if (isset($this->unset[$key])) {
            return false;
        }

        $attribute = Arr::get($this->attributes, $key);
        $original  = Arr::get($this->original, $key);

        if ($attribute === $original) {
            return true;
        }

        if ($attribute === null) {
            return false;
        }

        if ($this->isDateAttribute($key)) {
            $attribute = $attribute instanceof UTCDateTime ? $this->asDateTime($attribute) : $attribute;
            $original  = $original instanceof UTCDateTime ? $this->asDateTime($original) : $original;

            // Comparison on DateTimeInterface values
            // phpcs:disable SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
            return $attribute == $original;
        }

        if ($this->hasCast($key, static::$primitiveCastTypes)) {
            return $this->castAttribute($key, $attribute) ===
                $this->castAttribute($key, $original);
        }

        return is_numeric($attribute) && is_numeric($original)
            && strcmp((string) $attribute, (string) $original) === 0;
    }

    /** @inheritdoc */
    public function offsetUnset($offset): void
    {
        $offset = (string) $offset;

        if (str_contains($offset, '.')) {
            // Update the field in the subdocument
            Arr::forget($this->attributes, $offset);
        } else {
            parent::offsetUnset($offset);

            // Force unsetting even if the attribute is not set.
            // End user can optimize DB calls by checking if the attribute is set before unsetting it.
            $this->unset[$offset] = true;
        }
    }

    /** @inheritdoc */
    public function offsetSet($offset, $value): void
    {
        parent::offsetSet($offset, $value);

        // Setting an attribute cancels the unset operation.
        unset($this->unset[$offset]);
    }

    /**
     * Remove one or more fields.
     *
     * @deprecated Use unset() instead.
     *
     * @param  string|string[] $columns
     *
     * @return void
     */
    public function drop($columns)
    {
        $this->unset($columns);
    }

    /**
     * Remove one or more fields.
     *
     * @param  string|string[] $columns
     *
     * @return void
     */
    public function unset($columns)
    {
        $columns = Arr::wrap($columns);

        // Unset attributes
        foreach ($columns as $column) {
            $this->__unset($column);
        }
    }

    /** @inheritdoc */
    public function push()
    {
        $parameters = func_get_args();
        if ($parameters) {
            $unique = false;

            if (count($parameters) === 3) {
                [$column, $values, $unique] = $parameters;
            } else {
                [$column, $values] = $parameters;
            }

            // Do batch push by default.
            $values = Arr::wrap($values);

            $query = $this->setKeysForSaveQuery($this->newQuery());

            $this->pushAttributeValues($column, $values, $unique);

            return $query->push($column, $values, $unique);
        }

        return parent::push();
    }

    /**
     * Remove one or more values from an array.
     *
     * @param  string $column
     * @param  mixed  $values
     *
     * @return mixed
     */
    public function pull($column, $values)
    {
        // Do batch pull by default.
        $values = Arr::wrap($values);

        $query = $this->setKeysForSaveQuery($this->newQuery());

        $this->pullAttributeValues($column, $values);

        return $query->pull($column, $values);
    }

    /**
     * Append one or more values to the underlying attribute value and sync with original.
     *
     * @param  string $column
     * @param  bool   $unique
     */
    protected function pushAttributeValues($column, array $values, $unique = false)
    {
        $current = $this->getAttributeFromArray($column) ?: [];

        foreach ($values as $value) {
            // Don't add duplicate values when we only want unique values.
            if ($unique && (! is_array($current) || in_array($value, $current))) {
                continue;
            }

            $current[] = $value;
        }

        $this->attributes[$column] = $current;

        $this->syncOriginalAttribute($column);
    }

    /**
     * Remove one or more values to the underlying attribute value and sync with original.
     *
     * @param  string $column
     */
    protected function pullAttributeValues($column, array $values)
    {
        $current = $this->getAttributeFromArray($column) ?: [];

        if (is_array($current)) {
            foreach ($values as $value) {
                $keys = array_keys($current, $value);

                foreach ($keys as $key) {
                    unset($current[$key]);
                }
            }
        }

        $this->attributes[$column] = array_values($current);

        $this->syncOriginalAttribute($column);
    }

    /** @inheritdoc */
    public function getForeignKey()
    {
        return Str::snake(class_basename($this)) . '_' . ltrim($this->primaryKey, '_');
    }

    /**
     * Set the parent relation.
     */
    public function setParentRelation(Relation $relation)
    {
        $this->parentRelation = $relation;
    }

    /**
     * Get the parent relation.
     */
    public function getParentRelation(): ?Relation
    {
        return $this->parentRelation ?? null;
    }

    /** @inheritdoc */
    public function newEloquentBuilder($query)
    {
        return new Builder($query);
    }

    /** @inheritdoc */
    public function qualifyColumn($column)
    {
        return $column;
    }

    /** @inheritdoc */
    protected function newBaseQueryBuilder()
    {
        $connection = $this->getConnection();

        return new QueryBuilder($connection, $connection->getQueryGrammar(), $connection->getPostProcessor());
    }

    /** @inheritdoc */
    protected function removeTableFromKey($key)
    {
        return $key;
    }

    /**
     * Get the queueable relationships for the entity.
     *
     * @return array
     */
    public function getQueueableRelations()
    {
        $relations = [];

        foreach ($this->getRelationsWithoutParent() as $key => $relation) {
            if (method_exists($this, $key)) {
                $relations[] = $key;
            }

            if ($relation instanceof QueueableCollection) {
                foreach ($relation->getQueueableRelations() as $collectionValue) {
                    $relations[] = $key . '.' . $collectionValue;
                }
            }

            if ($relation instanceof QueueableEntity) {
                foreach ($relation->getQueueableRelations() as $entityKey => $entityValue) {
                    $relations[] = $key . '.' . $entityValue;
                }
            }
        }

        return array_unique($relations);
    }

    /**
     * Get loaded relations for the instance without parent.
     *
     * @return array
     */
    protected function getRelationsWithoutParent()
    {
        $relations = $this->getRelations();

        $parentRelation = $this->getParentRelation();
        if ($parentRelation) {
            unset($relations[$parentRelation->getQualifiedForeignKeyName()]);
        }

        return $relations;
    }

    /**
     * Checks if column exists on a table.  As this is a document model, just return true.  This also
     * prevents calls to non-existent function Grammar::compileColumnListing().
     *
     * @param  string $key
     *
     * @return bool
     */
    protected function isGuardableColumn($key)
    {
        return true;
    }

    /** @inheritdoc */
    protected function addCastAttributesToArray(array $attributes, array $mutatedAttributes)
    {
        foreach ($this->getCasts() as $key => $castType) {
            if (! Arr::has($attributes, $key) || Arr::has($mutatedAttributes, $key)) {
                continue;
            }

            $originalValue = Arr::get($attributes, $key);

            // Here we will cast the attribute. Then, if the cast is a date or datetime cast
            // then we will serialize the date for the array. This will convert the dates
            // to strings based on the date format specified for these Eloquent models.
            $castValue = $this->castAttribute(
                $key,
                $originalValue,
            );

            // If the attribute cast was a date or a datetime, we will serialize the date as
            // a string. This allows the developers to customize how dates are serialized
            // into an array without affecting how they are persisted into the storage.
            if ($castValue !== null && in_array($castType, ['date', 'datetime', 'immutable_date', 'immutable_datetime'])) {
                $castValue = $this->serializeDate($castValue);
            }

            if ($castValue !== null && ($this->isCustomDateTimeCast($castType) || $this->isImmutableCustomDateTimeCast($castType))) {
                $castValue = $castValue->format(explode(':', $castType, 2)[1]);
            }

            if ($castValue instanceof DateTimeInterface && $this->isClassCastable($key)) {
                $castValue = $this->serializeDate($castValue);
            }

            if ($castValue !== null && $this->isClassSerializable($key)) {
                $castValue = $this->serializeClassCastableAttribute($key, $castValue);
            }

            if ($this->isEnumCastable($key) && (! $castValue instanceof Arrayable)) {
                $castValue = $castValue !== null ? $this->getStorableEnumValueFromLaravel11($this->getCasts()[$key], $castValue) : null;
            }

            if ($castValue instanceof Arrayable) {
                $castValue = $castValue->toArray();
            }

            Arr::set($attributes, $key, $castValue);
        }

        return $attributes;
    }

    /**
     * Duplicate of {@see HasAttributes::getStorableEnumValue()} for Laravel 11 as the signature of the method has
     * changed in a non-backward compatible way.
     *
     * @todo Remove this method when support for Laravel 10 is dropped.
     */
    private function getStorableEnumValueFromLaravel11($expectedEnum, $value)
    {
        if (! $value instanceof $expectedEnum) {
            throw new ValueError(sprintf('Value [%s] is not of the expected enum type [%s].', var_export($value, true), $expectedEnum));
        }

        return $value instanceof BackedEnum
            ? $value->value
            : $value->name;
    }

    /**
     * Is a value a BSON type?
     *
     * @param mixed $value
     *
     * @return bool
     */
    protected function isBSON(mixed $value): bool
    {
        return $value instanceof Type;
    }

    /**
     * {@inheritDoc}
     */
    public function save(array $options = [])
    {
        // SQL databases would autoincrement the id field if set to null.
        // Apply the same behavior to MongoDB with _id only, otherwise null would be stored.
        if (array_key_exists('_id', $this->attributes) && $this->attributes['_id'] === null) {
            unset($this->attributes['_id']);
        }

        if (array_key_exists('id', $this->attributes) && $this->attributes['id'] === null) {
            unset($this->attributes['id']);
        }

        $saved = parent::save($options);

        // Clear list of unset fields
        $this->unset = [];

        return $saved;
    }

    /**
     * {@inheritDoc}
     */
    public function refresh()
    {
        parent::refresh();

        // Clear list of unset fields
        $this->unset = [];

        return $this;
    }
}


================================================
FILE: src/Eloquent/EmbedsRelations.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Eloquent;

use Illuminate\Support\Str;
use MongoDB\Laravel\Relations\EmbedsMany;
use MongoDB\Laravel\Relations\EmbedsOne;

use function class_basename;
use function debug_backtrace;

use const DEBUG_BACKTRACE_IGNORE_ARGS;

/**
 * Embeds relations for MongoDB models.
 */
trait EmbedsRelations
{
    /**
     * Define an embedded one-to-many relationship.
     *
     * @param class-string $related
     * @param string|null  $localKey
     * @param string|null  $foreignKey
     * @param string|null  $relation
     *
     * @return EmbedsMany
     */
    protected function embedsMany($related, $localKey = null, $foreignKey = null, $relation = null)
    {
        // If no relation name was given, we will use this debug backtrace to extract
        // the calling method's name and use that as the relationship name as most
        // of the time this will be what we desire to use for the relationships.
        if ($relation === null) {
            $relation = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];
        }

        if ($localKey === null) {
            $localKey = $relation;
        }

        if ($foreignKey === null) {
            $foreignKey = Str::snake(class_basename($this));
        }

        $query = $this->newQuery();

        $instance = new $related();

        return new EmbedsMany($query, $this, $instance, $localKey, $foreignKey, $relation);
    }

    /**
     * Define an embedded one-to-many relationship.
     *
     * @param class-string $related
     * @param string|null  $localKey
     * @param string|null  $foreignKey
     * @param string|null  $relation
     *
     * @return EmbedsOne
     */
    protected function embedsOne($related, $localKey = null, $foreignKey = null, $relation = null)
    {
        // If no relation name was given, we will use this debug backtrace to extract
        // the calling method's name and use that as the relationship name as most
        // of the time this will be what we desire to use for the relationships.
        if ($relation === null) {
            $relation = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];
        }

        if ($localKey === null) {
            $localKey = $relation;
        }

        if ($foreignKey === null) {
            $foreignKey = Str::snake(class_basename($this));
        }

        $query = $this->newQuery();

        $instance = new $related();

        return new EmbedsOne($query, $this, $instance, $localKey, $foreignKey, $relation);
    }
}


================================================
FILE: src/Eloquent/HasSchemaVersion.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Eloquent;

use Error;
use LogicException;

use function sprintf;

/**
 * Use this trait to implement schema versioning in your models. The document
 * is updated automatically when its schema version retrieved from the database
 * is lower than the current schema version of the model.
 *
 *     class MyVersionedModel extends Model
 *     {
 *         use HasSchemaVersion;
 *
 *         public const int SCHEMA_VERSION = 1;
 *
 *         public function migrateSchema(int $fromVersion): void
 *         {
 *             // Your logic to update the document to the current schema version
 *         }
 *     }
 *
 * @see https://www.mongodb.com/docs/manual/tutorial/model-data-for-schema-versioning/
 *
 * Requires PHP 8.2+
 */
trait HasSchemaVersion
{
    /**
     * This method should be implemented in the model to migrate a document from
     * an older schema version to the current schema version.
     */
    public function migrateSchema(int $fromVersion): void
    {
    }

    public static function bootHasSchemaVersion(): void
    {
        static::saving(function ($model) {
            if ($model->getAttribute($model::getSchemaVersionKey()) === null) {
                $model->setAttribute($model::getSchemaVersionKey(), $model->getModelSchemaVersion());
            }
        });

        static::retrieved(function (self $model) {
            $version = $model->getSchemaVersion();

            if ($version < $model->getModelSchemaVersion()) {
                $model->migrateSchema($version);
                $model->setAttribute($model::getSchemaVersionKey(), $model->getModelSchemaVersion());
            }
        });
    }

    /**
     * Get Current document version, fallback to 0 if not set
     */
    public function getSchemaVersion(): int
    {
        return $this->{static::getSchemaVersionKey()} ?? 0;
    }

    protected static function getSchemaVersionKey(): string
    {
        return 'schema_version';
    }

    protected function getModelSchemaVersion(): int
    {
        try {
            return $this::SCHEMA_VERSION;
        } catch (Error) {
            throw new LogicException(sprintf('Constant %s::SCHEMA_VERSION is required when using HasSchemaVersion', $this::class));
        }
    }
}


================================================
FILE: src/Eloquent/HybridRelations.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Eloquent;

use Illuminate\Database\Eloquent\Concerns\HasRelationships;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Support\Str;
use MongoDB\Laravel\Helpers\EloquentBuilder;
use MongoDB\Laravel\Relations\BelongsTo;
use MongoDB\Laravel\Relations\BelongsToMany;
use MongoDB\Laravel\Relations\HasMany;
use MongoDB\Laravel\Relations\HasOne;
use MongoDB\Laravel\Relations\MorphMany;
use MongoDB\Laravel\Relations\MorphTo;
use MongoDB\Laravel\Relations\MorphToMany;

use function array_pop;
use function debug_backtrace;
use function implode;
use function preg_split;

use const DEBUG_BACKTRACE_IGNORE_ARGS;
use const PREG_SPLIT_DELIM_CAPTURE;

/**
 * Cross-database relationships between SQL and MongoDB.
 * Use this trait in SQL models to define relationships with MongoDB models.
 */
trait HybridRelations
{
    /**
     * Define a one-to-one relationship.
     *
     * @see HasRelationships::hasOne()
     *
     * @param class-string $related
     * @param string|null  $foreignKey
     * @param string|null  $localKey
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function hasOne($related, $foreignKey = null, $localKey = null)
    {
        // Check if it is a relation with an original model.
        if (! Model::isDocumentModel($related)) {
            return parent::hasOne($related, $foreignKey, $localKey);
        }

        $foreignKey = $foreignKey ?: $this->getForeignKey();

        $instance = new $related();

        $localKey = $localKey ?: $this->getKeyName();

        return new HasOne($instance->newQuery(), $this, $foreignKey, $localKey);
    }

    /**
     * Define a polymorphic one-to-one relationship.
     *
     * @see HasRelationships::morphOne()
     *
     * @param class-string $related
     * @param string       $name
     * @param string|null  $type
     * @param string|null  $id
     * @param string|null  $localKey
     *
     * @return MorphOne
     */
    public function morphOne($related, $name, $type = null, $id = null, $localKey = null)
    {
        // Check if it is a relation with an original model.
        if (! Model::isDocumentModel($related)) {
            return parent::morphOne($related, $name, $type, $id, $localKey);
        }

        $instance = new $related();

        [$type, $id] = $this->getMorphs($name, $type, $id);

        $localKey = $localKey ?: $this->getKeyName();

        return new MorphOne($instance->newQuery(), $this, $type, $id, $localKey);
    }

    /**
     * Define a one-to-many relationship.
     *
     * @see HasRelationships::hasMany()
     *
     * @param class-string $related
     * @param string|null  $foreignKey
     * @param string|null  $localKey
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function hasMany($related, $foreignKey = null, $localKey = null)
    {
        // Check if it is a relation with an original model.
        if (! Model::isDocumentModel($related)) {
            return parent::hasMany($related, $foreignKey, $localKey);
        }

        $foreignKey = $foreignKey ?: $this->getForeignKey();

        $instance = new $related();

        $localKey = $localKey ?: $this->getKeyName();

        return new HasMany($instance->newQuery(), $this, $foreignKey, $localKey);
    }

    /**
     * Define a polymorphic one-to-many relationship.
     *
     * @see HasRelationships::morphMany()
     *
     * @param class-string $related
     * @param string       $name
     * @param string|null  $type
     * @param string|null  $id
     * @param string|null  $localKey
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
     */
    public function morphMany($related, $name, $type = null, $id = null, $localKey = null)
    {
        // Check if it is a relation with an original model.
        if (! Model::isDocumentModel($related)) {
            return parent::morphMany($related, $name, $type, $id, $localKey);
        }

        $instance = new $related();

        // Here we will gather up the morph type and ID for the relationship so that we
        // can properly query the intermediate table of a relation. Finally, we will
        // get the table and create the relationship instances for the developers.
        [$type, $id] = $this->getMorphs($name, $type, $id);

        $table = $instance->getTable();

        $localKey = $localKey ?: $this->getKeyName();

        return new MorphMany($instance->newQuery(), $this, $type, $id, $localKey);
    }

    /**
     * Define an inverse one-to-one or many relationship.
     *
     * @see HasRelationships::belongsTo()
     *
     * @param class-string $related
     * @param string|null  $foreignKey
     * @param string|null  $ownerKey
     * @param string|null  $relation
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function belongsTo($related, $foreignKey = null, $ownerKey = null, $relation = null)
    {
        // If no relation name was given, we will use this debug backtrace to extract
        // the calling method's name and use that as the relationship name as most
        // of the time this will be what we desire to use for the relationships.
        if ($relation === null) {
            $relation = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];
        }

        // Check if it is a relation with an original model.
        if (! Model::isDocumentModel($related)) {
            return parent::belongsTo($related, $foreignKey, $ownerKey, $relation);
        }

        // If no foreign key was supplied, we can use a backtrace to guess the proper
        // foreign key name by using the name of the relationship function, which
        // when combined with an "_id" should conventionally match the columns.
        if ($foreignKey === null) {
            $foreignKey = Str::snake($relation) . '_id';
        }

        $instance = new $related();

        // Once we have the foreign key names, we'll just create a new Eloquent query
        // for the related models and returns the relationship instance which will
        // actually be responsible for retrieving and hydrating every relations.
        $query = $instance->newQuery();

        $ownerKey = $ownerKey ?: $instance->getKeyName();

        return new BelongsTo($query, $this, $foreignKey, $ownerKey, $relation);
    }

    /**
     * Define a polymorphic, inverse one-to-one or many relationship.
     *
     * @see HasRelationships::morphTo()
     *
     * @param string      $name
     * @param string|null $type
     * @param string|null $id
     * @param string|null $ownerKey
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphTo
     */
    public function morphTo($name = null, $type = null, $id = null, $ownerKey = null)
    {
        // If no name is provided, we will use the backtrace to get the function name
        // since that is most likely the name of the polymorphic interface. We can
        // use that to get both the class and foreign key that will be utilized.
        if ($name === null) {
            $name = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];
        }

        [$type, $id] = $this->getMorphs(Str::snake($name), $type, $id);

        // If the type value is null it is probably safe to assume we're eager loading
        // the relationship. When that is the case we will pass in a dummy query as
        // there are multiple types in the morph and we can't use single queries.
        $class = $this->$type;
        if ($class === null) {
            return new MorphTo(
                $this->newQuery(),
                $this,
                $id,
                $ownerKey,
                $type,
                $name,
            );
        }

        // If we are not eager loading the relationship we will essentially treat this
        // as a belongs-to style relationship since morph-to extends that class and
        // we will pass in the appropriate values so that it behaves as expected.
        $class = $this->getActualClassNameForMorph($class);

        $instance = new $class();

        $ownerKey ??= $instance->getKeyName();

        // Check if it is a relation with an original model.
        if (! Model::isDocumentModel($instance)) {
            return parent::morphTo($name, $type, $id, $ownerKey);
        }

        return new MorphTo(
            $instance->newQuery(),
            $this,
            $id,
            $ownerKey,
            $type,
            $name,
        );
    }

    /**
     * Define a many-to-many relationship.
     *
     * @see HasRelationships::belongsToMany()
     *
     * @param class-string $related
     * @param string|null  $collection
     * @param string|null  $foreignPivotKey
     * @param string|null  $relatedPivotKey
     * @param string|null  $parentKey
     * @param string|null  $relatedKey
     * @param string|null  $relation
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function belongsToMany(
        $related,
        $collection = null,
        $foreignPivotKey = null,
        $relatedPivotKey = null,
        $parentKey = null,
        $relatedKey = null,
        $relation = null,
    ) {
        // If no relationship name was passed, we will pull backtraces to get the
        // name of the calling function. We will use that function name as the
        // title of this relation since that is a great convention to apply.
        if ($relation === null) {
            $relation = $this->guessBelongsToManyRelation();
        }

        // Check if it is a relation with an original model.
        if (! Model::isDocumentModel($related)) {
            return parent::belongsToMany(
                $related,
                $collection,
                $foreignPivotKey,
                $relatedPivotKey,
                $parentKey,
                $relatedKey,
                $relation,
            );
        }

        // First, we'll need to determine the foreign key and "other key" for the
        // relationship. Once we have determined the keys we'll make the query
        // instances as well as the relationship instances we need for this.
        $foreignPivotKey = $foreignPivotKey ?: $this->getForeignKey() . 's';

        $instance = new $related();

        $relatedPivotKey = $relatedPivotKey ?: $instance->getForeignKey() . 's';

        // If no table name was provided, we can guess it by concatenating the two
        // models using underscores in alphabetical order. The two model names
        // are transformed to snake case from their default CamelCase also.
        if ($collection === null) {
            $collection = $instance->getTable();
        }

        // Now we're ready to create a new query builder for the related model and
        // the relationship instances for the relation. The relations will set
        // appropriate query constraint and entirely manages the hydrations.
        $query = $instance->newQuery();

        return new BelongsToMany(
            $query,
            $this,
            $collection,
            $foreignPivotKey,
            $relatedPivotKey,
            $parentKey ?: $this->getKeyName(),
            $relatedKey ?: $instance->getKeyName(),
            $relation,
        );
    }

    /**
     * Define a morph-to-many relationship.
     *
     * @param class-string $related
     * @param string       $name
     * @param string|null  $table
     * @param string|null  $foreignPivotKey
     * @param string|null  $relatedPivotKey
     * @param string|null  $parentKey
     * @param string|null  $relatedKey
     * @param string|null  $relation
     * @param bool         $inverse
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function morphToMany(
        $related,
        $name,
        $table = null,
        $foreignPivotKey = null,
        $relatedPivotKey = null,
        $parentKey = null,
        $relatedKey = null,
        $relation = null,
        $inverse = false,
    ) {
        // If no relationship name was passed, we will pull backtraces to get the
        // name of the calling function. We will use that function name as the
        // title of this relation since that is a great convention to apply.
        if ($relation === null) {
            $relation = $this->guessBelongsToManyRelation();
        }

        // Check if it is a relation with an original model.
        if (! Model::isDocumentModel($related)) {
            return parent::morphToMany(
                $related,
                $name,
                $table,
                $foreignPivotKey,
                $relatedPivotKey,
                $parentKey,
                $relatedKey,
                $relation,
                $inverse,
            );
        }

        $instance = new $related();

        $foreignPivotKey = $foreignPivotKey ?: $name . '_id';
        $relatedPivotKey = $relatedPivotKey ?:  Str::plural($instance->getForeignKey());

        // Now we're ready to create a new query builder for the related model and
        // the relationship instances for this relation. This relation will set
        // appropriate query constraints then entirely manage the hydration.
        if (! $table) {
            $words = preg_split('/(_)/u', $name, -1, PREG_SPLIT_DELIM_CAPTURE);
            $lastWord = array_pop($words);
            $table = implode('', $words) . Str::plural($lastWord);
        }

        return new MorphToMany(
            $instance->newQuery(),
            $this,
            $name,
            $table,
            $foreignPivotKey,
            $relatedPivotKey,
            $parentKey ?: $this->getKeyName(),
            $relatedKey ?: $instance->getKeyName(),
            $relation,
            $inverse,
        );
    }

    /**
     * Define a polymorphic, inverse many-to-many relationship.
     *
     * @param class-string $related
     * @param string       $name
     * @param string|null  $table
     * @param string|null  $foreignPivotKey
     * @param string|null  $relatedPivotKey
     * @param string|null  $parentKey
     * @param string|null  $relatedKey
     * @param string|null  $relation
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function morphedByMany(
        $related,
        $name,
        $table = null,
        $foreignPivotKey = null,
        $relatedPivotKey = null,
        $parentKey = null,
        $relatedKey = null,
        $relation = null,
    ) {
        // If the related model is an instance of eloquent model class, leave pivot keys
        // as default. It's necessary for supporting hybrid relationship
        if (Model::isDocumentModel($related)) {
            // For the inverse of the polymorphic many-to-many relations, we will change
            // the way we determine the foreign and other keys, as it is the opposite
            // of the morph-to-many method since we're figuring out these inverses.
            $foreignPivotKey = $foreignPivotKey ?: Str::plural($this->getForeignKey());

            $relatedPivotKey = $relatedPivotKey ?: $name . '_id';
        }

        return $this->morphToMany(
            $related,
            $name,
            $table,
            $foreignPivotKey,
            $relatedPivotKey,
            $parentKey,
            $relatedKey,
            $relatedKey,
            true,
        );
    }

    /** @inheritdoc */
    public function newEloquentBuilder($query)
    {
        if (Model::isDocumentModel($this)) {
            return new Builder($query);
        }

        return new EloquentBuilder($query);
    }
}


================================================
FILE: src/Eloquent/MassPrunable.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Eloquent;

use Illuminate\Database\Eloquent\MassPrunable as EloquentMassPrunable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Events\ModelsPruned;

use function class_uses_recursive;
use function event;
use function in_array;

trait MassPrunable
{
    use EloquentMassPrunable;

    /**
     * Prune all prunable models in the database.
     *
     * @see \Illuminate\Database\Eloquent\MassPrunable::pruneAll()
     */
    public function pruneAll(): int
    {
        $query = $this->prunable();
        $total = in_array(SoftDeletes::class, class_uses_recursive(static::class))
                    ? $query->forceDelete()
                    : $query->delete();

        event(new ModelsPruned(static::class, $total));

        return $total;
    }
}


================================================
FILE: src/Eloquent/Model.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Eloquent;

use Illuminate\Database\Eloquent\Model as BaseModel;
use MongoDB\Laravel\Auth\User;

use function array_key_exists;
use function class_uses_recursive;
use function is_object;
use function is_subclass_of;

abstract class Model extends BaseModel
{
    use DocumentModel;

    /**
     * The primary key type.
     *
     * @var string
     */
    protected $keyType = 'string';

    private static $documentModelClasses = [User::class => true];

    /**
     * Indicates if the given model class is a MongoDB document model.
     * It must be a subclass of {@see BaseModel} and use the
     * {@see DocumentModel} trait.
     *
     * @param class-string|object $class
     */
    final public static function isDocumentModel(string|object $class): bool
    {
        if (is_object($class)) {
            $class = $class::class;
        }

        if (array_key_exists($class, self::$documentModelClasses)) {
            return self::$documentModelClasses[$class];
        }

        // We know all child classes of this class are document models.
        if (is_subclass_of($class, self::class)) {
            return self::$documentModelClasses[$class] = true;
        }

        // Document models must be subclasses of Laravel's base model class.
        if (! is_subclass_of($class, BaseModel::class)) {
            return self::$documentModelClasses[$class] = false;
        }

        // Document models must use the DocumentModel trait.
        return self::$documentModelClasses[$class] = array_key_exists(DocumentModel::class, class_uses_recursive($class));
    }
}


================================================
FILE: src/Eloquent/SoftDeletes.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Eloquent;

use function sprintf;
use function trigger_error;

use const E_USER_DEPRECATED;

trigger_error(sprintf('Since mongodb/laravel-mongodb:5.5, trait "%s" is deprecated, use "%s" instead.', SoftDeletes::class, \Illuminate\Database\Eloquent\SoftDeletes::class), E_USER_DEPRECATED);

/** @deprecated since mongodb/laravel-mongodb:5.5, use \Illuminate\Database\Eloquent\SoftDeletes instead */
trait SoftDeletes
{
    use \Illuminate\Database\Eloquent\SoftDeletes;

    /** @inheritdoc */
    public function getQualifiedDeletedAtColumn()
    {
        return $this->getDeletedAtColumn();
    }
}


================================================
FILE: src/Helpers/EloquentBuilder.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Helpers;

use Illuminate\Database\Eloquent\Builder;

class EloquentBuilder extends Builder
{
    use QueriesRelationships;
}


================================================
FILE: src/Helpers/QueriesRelationships.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Helpers;

use Closure;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Collection;
use LogicException;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\MorphToMany;

use function array_count_values;
use function array_filter;
use function array_keys;
use function array_map;
use function class_basename;
use function collect;
use function in_array;
use function is_array;
use function is_string;
use function method_exists;
use function str_contains;

trait QueriesRelationships
{
    /**
     * Add a relationship count / exists condition to the query.
     *
     * @param Relation|string $relation
     * @param string          $operator
     * @param int             $count
     * @param string          $boolean
     *
     * @return Builder|static
     *
     * @throws Exception
     */
    public function has($relation, $operator = '>=', $count = 1, $boolean = 'and', ?Closure $callback = null)
    {
        if (is_string($relation)) {
            if (str_contains($relation, '.')) {
                return $this->hasNested($relation, $operator, $count, $boolean, $callback);
            }

            $relation = $this->getRelationWithoutConstraints($relation);
        }

        // If this is a hybrid relation then we can not use a normal whereExists() query that relies on a subquery
        // We need to use a `whereIn` query
        if (Model::isDocumentModel($this->getModel()) || $this->isAcrossConnections($relation)) {
            return $this->addHybridHas($relation, $operator, $count, $boolean, $callback);
        }

        // If we only need to check for the existence of the relation, then we can optimize
        // the subquery to only run a "where exists" clause instead of this full "count"
        // clause. This will make these queries run much faster compared with a count.
        $method = $this->canUseExistsForExistenceCheck($operator, $count)
            ? 'getRelationExistenceQuery'
            : 'getRelationExistenceCountQuery';

        $hasQuery = $relation->{$method}(
            $relation->getRelated()->newQuery(),
            $this
        );

        // Next we will call any given callback as an "anonymous" scope so they can get the
        // proper logical grouping of the where clauses if needed by this Eloquent query
        // builder. Then, we will be ready to finalize and return this query instance.
        if ($callback) {
            $hasQuery->callScope($callback);
        }

        return $this->addHasWhere(
            $hasQuery,
            $relation,
            $operator,
            $count,
            $boolean,
        );
    }

    /** @return bool */
    protected function isAcrossConnections(Relation $relation)
    {
        return $relation->getParent()->getConnectionName() !== $relation->getRelated()->getConnectionName();
    }

    /**
     * Compare across databases.
     *
     * @param string $operator
     * @param int    $count
     * @param string $boolean
     *
     * @return mixed
     *
     * @throws Exception
     */
    public function addHybridHas(Relation $relation, $operator = '>=', $count = 1, $boolean = 'and', ?Closure $callback = null)
    {
        $this->assertHybridRelationSupported($relation);

        $hasQuery = $relation->getQuery();
        if ($callback) {
            $hasQuery->callScope($callback);
        }

        // If the operator is <, <= or !=, we will use whereNotIn.
        $not = in_array($operator, ['<', '<=', '!=']);
        // If we are comparing to 0, we need an additional $not flip.
        if ($count === 0) {
            $not = ! $not;
        }

        $relations = match (true) {
            $relation instanceof MorphToMany => $relation->getInverse() ?
              $this->handleMorphedByMany($hasQuery, $relation) :
              $this->handleMorphToMany($hasQuery, $relation),
            default => $hasQuery->pluck($this->getHasCompareKey($relation))
        };

        $relatedIds = $this->getConstrainedRelatedIds($relations, $operator, $count);

        return $this->whereIn($this->getRelatedConstraintKey($relation), $relatedIds, $boolean, $not);
    }

    /**
     * @param Relation $relation
     *
     * @return void
     *
     * @throws Exception
     */
    private function assertHybridRelationSupported(Relation $relation): void
    {
        if (
            $relation instanceof HasOneOrMany
            || $relation instanceof BelongsTo
            || ($relation instanceof BelongsToMany && ! $this->isAcrossConnections($relation))
        ) {
            return;
        }

        throw new LogicException(class_basename($relation) . ' is not supported for hybrid query constraints.');
    }

    /**
     * @param Builder  $hasQuery
     * @param Relation $relation
     *
     * @return Collection
     */
    private function handleMorphToMany($hasQuery, $relation)
    {
        // First we select the parent models that have a relation to our related model,
        // Then extracts related model's ids from the pivot column
        $hasQuery->where($relation->getTable() . '.' . $relation->getMorphType(), $relation->getParent()::class);
        $relations = $hasQuery->pluck($relation->getTable());
        $relations = $relation->extractIds($relations->flatten(1)->toArray(), $relation->getForeignPivotKeyName());

        return collect($relations);
    }

    /**
     * @param Builder  $hasQuery
     * @param Relation $relation
     *
     * @return Collection
     */
    private function handleMorphedByMany($hasQuery, $relation)
    {
        $hasQuery->whereNotNull($relation->getForeignPivotKeyName());

        return $hasQuery->pluck($relation->getForeignPivotKeyName())->flatten(1);
    }

    /** @return string */
    protected function getHasCompareKey(Relation $relation)
    {
        if (method_exists($relation, 'getHasCompareKey')) {
            return $relation->getHasCompareKey();
        }

        return $relation instanceof HasOneOrMany ? $relation->getForeignKeyName() : $relation->getOwnerKeyName();
    }

    /**
     * @param Collection $relations
     * @param string     $operator
     * @param int        $count
     *
     * @return array
     */
    protected function getConstrainedRelatedIds($relations, $operator, $count)
    {
        $relationCount = array_count_values(array_map(function ($id) {
            return (string) $id; // Convert Back ObjectIds to Strings
        }, is_array($relations) ? $relations : $relations->flatten()->toArray()));
        // Remove unwanted related objects based on the operator and count.
        $relationCount = array_filter($relationCount, function ($counted) use ($count, $operator) {
            // If we are comparing to 0, we always need all results.
            if ($count === 0) {
                return true;
            }

            switch ($operator) {
                case '>=':
                case '<':
                    return $counted >= $count;
                case '>':
                case '<=':
                    return $counted > $count;
                case '=':
                case '!=':
                    return $counted === $count;
            }
        });

        // All related ids.
        return array_keys($relationCount);
    }

    /**
     * Returns key we are constraining this parent model's query with.
     *
     * @return string
     *
     * @throws Exception
     */
    protected function getRelatedConstraintKey(Relation $relation)
    {
        $this->assertHybridRelationSupported($relation);

        if ($relation instanceof HasOneOrMany) {
            return $relation->getLocalKeyName();
        }

        if ($relation instanceof BelongsTo) {
            return $relation->getForeignKeyName();
        }

        if ($relation instanceof BelongsToMany) {
            return $this->model->getKeyName();
        }

        throw new Exception(class_basename($relation) . ' is not supported for hybrid query constraints.');
    }
}


================================================
FILE: src/MongoDBBusServiceProvider.php
================================================
<?php

namespace MongoDB\Laravel;

use Illuminate\Bus\BatchFactory;
use Illuminate\Bus\BatchRepository;
use Illuminate\Bus\BusServiceProvider;
use Illuminate\Container\Container;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
use InvalidArgumentException;
use MongoDB\Laravel\Bus\MongoBatchRepository;
use Override;

use function sprintf;

class MongoDBBusServiceProvider extends ServiceProvider implements DeferrableProvider
{
    /**
     * Register the service provider.
     */
    #[Override]
    public function register()
    {
        $this->app->singleton(MongoBatchRepository::class, function (Container $app) {
            $connection = $app->make('db')->connection($app->config->get('queue.batching.database'));

            if (! $connection instanceof Connection) {
                throw new InvalidArgumentException(sprintf('The "mongodb" batch driver requires a MongoDB connection. The "%s" connection uses the "%s" driver.', $connection->getName(), $connection->getDriverName()));
            }

            return new MongoBatchRepository(
                $app->make(BatchFactory::class),
                $connection,
                $app->config->get('queue.batching.collection', 'job_batches'),
            );
        });

        /** The {@see BatchRepository} service is registered in {@see BusServiceProvider} */
        $this->app->register(BusServiceProvider::class);
        $this->app->extend(BatchRepository::class, function (BatchRepository $repository, Container $app) {
            $driver = $app->config->get('queue.batching.driver');

            return match ($driver) {
                'mongodb' => $app->make(MongoBatchRepository::class),
                default => $repository,
            };
        });
    }

    /** @inheritdoc */
    #[Override]
    public function provides()
    {
        return [
            BatchRepository::class,
            MongoBatchRepository::class,
        ];
    }
}


================================================
FILE: src/MongoDBServiceProvider.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel;

use Closure;
use Illuminate\Cache\CacheManager;
use Illuminate\Cache\Repository;
use Illuminate\Container\Container;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Filesystem\FilesystemManager;
use Illuminate\Foundation\Application;
use Illuminate\Session\SessionManager;
use Illuminate\Support\ServiceProvider;
use InvalidArgumentException;
use Laravel\Scout\EngineManager;
use League\Flysystem\Filesystem;
use League\Flysystem\GridFS\GridFSAdapter;
use League\Flysystem\ReadOnly\ReadOnlyFilesystemAdapter;
use MongoDB\GridFS\Bucket;
use MongoDB\Laravel\Cache\MongoStore;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Queue\MongoConnector;
use MongoDB\Laravel\Scout\ScoutEngine;
use MongoDB\Laravel\Session\MongoDbSessionHandler;
use Override;
use RuntimeException;

use function assert;
use function class_exists;
use function get_debug_type;
use function is_string;
use function sprintf;

class MongoDBServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application events.
     */
    public function boot()
    {
        Model::setConnectionResolver($this->app['db']);

        Model::setEventDispatcher($this->app['events']);
    }

    /**
     * Register the service provider.
     */
    #[Override]
    public function register()
    {
        // Add database driver.
        $this->app->resolving('db', function ($db) {
            $db->extend('mongodb', function ($config, $name) {
                $config['name'] = $name;

                return new Connection($config);
            });
        });

        // Session handler for MongoDB
        $this->app->resolving(SessionManager::class, function (SessionManager $sessionManager) {
            $sessionManager->extend('mongodb', function (Application $app) {
                $connectionName = $app->config->get('session.connection') ?: 'mongodb';
                $connection = $app->make('db')->connection($connectionName);

                assert($connection instanceof Connection, new InvalidArgumentException(sprintf('The database connection "%s" used for the session does not use the "mongodb" driver.', $connectionName)));

                return new MongoDbSessionHandler(
                    $connection,
                    $app->config->get('session.table', 'sessions'),
                    $app->config->get('session.lifetime'),
                    $app,
                );
            });
        });

        // Add cache and lock drivers.
        $this->app->resolving('cache', function (CacheManager $cache) {
            $cache->extend('mongodb', function (Application $app, array $config): Repository {
                // The closure is bound to the CacheManager
                assert($this instanceof CacheManager);

                $store = new MongoStore(
                    $app['db']->connection($config['connection'] ?? null),
                    $config['collection'] ?? 'cache',
                    $this->getPrefix($config),
                    $app['db']->connection($config['lock_connection'] ?? $config['connection'] ?? null),
                    $config['lock_collection'] ?? ($config['collection'] ?? 'cache') . '_locks',
                    $config['lock_lottery'] ?? [2, 100],
                    $config['lock_timeout'] ?? 86400,
                );

                return $this->repository($store, $config);
            });
        });

        // Add connector for queue support.
        $this->app->resolving('queue', function ($queue) {
            $queue->addConnector('mongodb', function () {
                return new MongoConnector($this->app['db']);
            });
        });

        $this->registerFlysystemAdapter();
        $this->registerScoutEngine();
    }

    private function registerFlysystemAdapter(): void
    {
        // GridFS adapter for filesystem
        $this->app->resolving('filesystem', static function (FilesystemManager $filesystemManager) {
            $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"');
                }

                $bucket = $config['bucket'] ?? null;

                if ($bucket instanceof Closure) {
                    // Get the bucket from a factory function
                    $bucket = $bucket($app, $config);
                } elseif (is_string($bucket) && $app->has($bucket)) {
                    // Get the bucket from a service
                    $bucket = $app->get($bucket);
                } elseif (is_string($bucket) || $bucket === null) {
                    // Get the bucket from the database connection
                    $connection = $app['db']->connection($config['connection']);
                    if (! $connection instanceof Connection) {
                        throw new InvalidArgumentException(sprintf('The database connection "%s" does not use the "mongodb" driver.', $config['connection'] ?? $app['config']['database.default']));
                    }

                    $bucket = $connection->getClient()
                        ->getDatabase($config['database'] ?? $connection->getDatabaseName())
                        ->selectGridFSBucket(['bucketName' => $config['bucket'] ?? 'fs', 'disableMD5' => true]);
                }

                if (! $bucket instanceof Bucket) {
                    throw new InvalidArgumentException(sprintf('Unexpected value for GridFS "bucket" configuration. Expecting "%s". Got "%s"', Bucket::class, get_debug_type($bucket)));
                }

                $adapter = new GridFSAdapter($bucket, $config['prefix'] ?? '');

                /** @see FilesystemManager::createFlysystem() */
                if ($config['read-only'] ?? false) {
                    if (! class_exists(ReadOnlyFilesystemAdapter::class)) {
                        throw new RuntimeException('Read-only Adapter for Flysystem is missing. Try running "composer require league/flysystem-read-only"');
                    }

                    $adapter = new ReadOnlyFilesystemAdapter($adapter);
                }

                /** Prevent using backslash on Windows in {@see FilesystemAdapter::__construct()} */
                $config['directory_separator'] = '/';

                return new FilesystemAdapter(new Filesystem($adapter, $config), $adapter, $config);
            });
        });
    }

    private function registerScoutEngine(): void
    {
        $this->app->resolving(EngineManager::class, function (EngineManager $engineManager) {
            $engineManager->extend('mongodb', function (Container $app) {
                $connectionName = $app->get('config')->get('scout.mongodb.connection', 'mongodb');
                $connection = $app->get('db')->connection($connectionName);
                $softDelete = (bool) $app->get('config')->get('scout.soft_delete', false);
                $indexDefinitions = $app->get('config')->get('scout.mongodb.index-definitions', []);

                assert($connection instanceof Connection, new InvalidArgumentException(sprintf('The connection "%s" is not a MongoDB connection.', $connectionName)));

                return new ScoutEngine($connection->getDatabase(), $softDelete, $indexDefinitions);
            });

            return $engineManager;
        });
    }
}


================================================
FILE: src/Query/AggregationBuilder.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Query;

use Illuminate\Support\Collection as LaravelCollection;
use Illuminate\Support\LazyCollection;
use InvalidArgumentException;
use Iterator;
use MongoDB\Builder\BuilderEncoder;
use MongoDB\Builder\Stage\FluentFactoryTrait;
use MongoDB\Collection;
use MongoDB\Driver\CursorInterface;

use function array_replace;
use function collect;
use function sprintf;
use function str_starts_with;

class AggregationBuilder
{
    use FluentFactoryTrait;

    public function __construct(
        private Collection $collection,
        private readonly array $options = [],
    ) {
    }

    /**
     * Add a stage without using the builder. Necessary if the stage is built
     * outside the builder, or it is not yet supported by the library.
     */
    public function addRawStage(string $operator, mixed $value): static
    {
        if (! str_starts_with($operator, '$')) {
            throw new InvalidArgumentException(sprintf('The stage name "%s" is invalid. It must start with a "$" sign.', $operator));
        }

        $this->pipeline[] = [$operator => $value];

        return $this;
    }

    /**
     * Execute the aggregation pipeline and return the results.
     */
    public function get(array $options = []): LaravelCollection|LazyCollection
    {
        $cursor = $this->execute($options);

        return collect($cursor->toArray());
    }

    /**
     * Execute the aggregation pipeline and return the results in a lazy collection.
     */
    public function cursor($options = []): LazyCollection
    {
        $cursor = $this->execute($options);

        return LazyCollection::make(function () use ($cursor) {
            foreach ($cursor as $item) {
                yield $item;
            }
        });
    }

    /**
     * Execute the aggregation pipeline and return the first result.
     */
    public function first(array $options = []): mixed
    {
        return (clone $this)
            ->limit(1)
            ->get($options)
            ->first();
    }

    /**
     * Execute the aggregation pipeline and return MongoDB cursor.
     */
    private function execute(array $options): CursorInterface&Iterator
    {
        $encoder = new BuilderEncoder();
        $pipeline = $encoder->encode($this->getPipeline());

        $options = array_replace(
            ['typeMap' => ['root' => 'array', 'document' => 'array']],
            $this->options,
            $options,
        );

        return $this->collection->aggregate($pipeline, $options);
    }
}


================================================
FILE: src/Query/Builder.php
================================================
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Query;

use ArgumentCountError;
use BadMethodCallException;
use Carbon\CarbonPeriod;
use Closure;
use DateTimeInterface;
use DateTimeZone;
use Illuminate\Database\Query\Builder as BaseBuilder;
use Illuminate\Database\Query\Expression;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\LazyCollection;
use InvalidArgumentException;
use LogicException;
use MongoDB\BSON\Binary;
use MongoDB\BSON\ObjectID;
use MongoDB\BSON\Regex;
use MongoDB\BSON\UTCDateTime;
use MongoDB\Builder\Search;
use MongoDB\Builder\Stage\FluentFactoryTrait;
use MongoDB\Builder\Type\QueryInterface;
use MongoDB\Builder\Type\SearchOperatorInterface;
use MongoDB\Driver\Cursor;
use MongoDB\Driver\ReadPreference;
use MongoDB\Laravel\Connection;
use Override;
use RuntimeException;
use stdClass;
use TypeError;

use function array_fill_keys;
use function array_filter;
use function array_is_list;
use function array_key_exists;
use function array_keys;
use function array_map;
use function array_merge;
use function array_replace;
use function array_values;
use function assert;
use function blank;
use function call_user_func;
use function call_user_func_array;
use function count;
use function ctype_xdigit;
use function date_default_timezone_get;
use function dd;
use function dump;
use function end;
use function explode;
use function func_get_args;
use function func_num_args;
use function get_debug_type;
use function get_object_vars;
use function implode;
use function in_array;
use function is_array;
use function is_bool;
use function is_callable;
use function is_float;
use function is_int;
use function is_object;
use function is_string;
use function md5;
use function preg_match;
use function preg_quote;
use function preg_replace;
use function property_exists;
use function serialize;
use function sprintf;
use function str_contains;
use function str_ends_with;
use function str_replace;
use function str_starts_with;
use function strlen;
use function strtolower;
use function substr;
use function trait_exists;
use function var_export;

/** @property Connection $connection */
class Builder extends BaseBuilder
{
    use BuilderTimeout;

    private const REGEX_DELIMITERS = ['/', '#', '~'];

    /**
     * The database collection.
     *
     * @var \MongoDB\Collection
     */
    protected $collection;

    /**
     * The column projections.
     *
     * @var array
     */
    public $projections = [];

    /**
     * The cursor hint value.
     *
     * @var int
     */
    public $hint;

    private ReadPreference $readPreference;

    /**
     * Custom options to add to the query.
     *
     * @var array
     */
    public $options = [];

    /**
     * All of the available clause operators.
     *
     * @var array
     */
    public $operators = [
        '=',
        '<',
        '>',
        '<=',
        '>=',
        '<>',
        '!=',
        'like',
        'not like',
        'between',
        'ilike',
        '&',
        '|',
        '^',
        '<<',
        '>>',
        'rlike',
        'regexp',
        'not regexp',
        'exists',
        'type',
        'mod',
        'where',
        'all',
        'size',
        'regex',
        'not regex',
        'text',
        'slice',
        'elemmatch',
        'geowithin',
        'geointersects',
        'near',
        'nearsphere',
        'geometry',
        'maxdistance',
        'center',
        'centersphere',
        'box',
        'polygon',
        'uniquedocs',
    ];

    /**
     * Operator conversion.
     *
     * @var array
     */
    protected $conversion = [
        '=' => 'eq',
        '!=' => 'ne',
        '<>' => 'ne',
        '<' => 'lt',
        '<=' => 'lte',
        '>' => 'gt',
        '>=' => 'gte',
        'regexp' => 'regex',
        'not regexp' => 'not regex',
        'ilike' => 'like',
        'elemmatch' => 'elemMatch',
        'geointersects' => 'geoIntersects',
        'geowithin' => 'geoWithin',
        'nearsphere' => 'nearSphere',
        'maxdistance' => 'maxDistance',
        'centersphere' => 'centerSphere',
        'uniquedocs' => 'uniqueDocs',
    ];

    /**
     * Set the projections.
     *
     * @param  array $columns
     *
     * @return $this
     */
    public function project($columns)
    {
        $this->projections = is_array($columns) ? $columns : func_get_args();

        return $this;
    }

    /**
     * Set the cursor hint.
     *
     * @param  mixed $index
     *
     * @return $this
     */
    public function hint($index)
    {
        $this->hint = $index;

        return $this;
    }

    /** @inheritdoc */
    #[Override]
    public function find($id, $columns = [])
    {
        return $this->where('_id', '=', $this->convertKey($id))->first($columns);
    }

    /** @inheritdoc */
    #[Override]
    public function value($column)
    {
        $result = (array) $this->first([$column]);

        return Arr::get($result, $column);
    }

    /** @inheritdoc */
    #[Override]
    public function get($columns = [])
    {
        return $this->getFresh($columns);
    }

    /** @inheritdoc */
    #[Override]
    public function cursor($columns = [])
    {
        $result = $this->getFresh($columns, true);
        if ($result instanceof LazyCollection) {
            return $result;
        }

        throw new RuntimeException('Query not compatible with cursor');
    }

    /**
     * Die and dump the current MongoDB query
     *
     * @return never-return
     */
    #[Override]
    public function dd()
    {
        dd($this->toMql());
    }

    /**
     * Dump the current MongoDB query
     *
     * @param mixed ...$args
     *
     * @return $this
     */
    #[Override]
    public function dump(mixed ...$args)
    {
        dump($this->toMql(), ...$args);

        return $this;
    }

    /**
     * Return the MongoDB query to be run in the form of an element array like ['method' => [arguments]].
     *
     * Example: ['find' => [['name' => 'John Doe'], ['projection' => ['birthday' => 1]]]]
     *
     * @return array<string, mixed[]>
     */
    public function toMql(): array
    {
        $columns = $this->columns ?? [];

        // Drop all columns if * is present, MongoDB does not work this way.
        if (in_array('*', $columns)) {
            $columns = [];
        }

        $wheres = $this->compileWheres();
        $wheres = $this->aliasIdForQuery($wheres);

        // Use MongoDB's aggregation framework when using grouping or aggregation functions.
        if ($this->groups || $this->aggregate) {
            $group   = [];
            $unwinds = [];
            $set = [];

            // Add grouping columns to the $group part of the aggregation pipeline.
            if ($this->groups) {
                foreach ($this->groups as $column) {
                    $group['_id'][$column] = '$' . $column;

                    // When grouping, also add the $last operator to each grouped field,
                    // this mimics SQL's behaviour a bit.
                    $group[$column] = ['$last' => '$' . $column];
                }
            }

            // Add the last value of each column when there is no aggregate function.
            if ($this->groups && ! $this->aggregate) {
                foreach ($columns as $column) {
                    $key = str_replace('.', '_', $column);

                    $group[$key] = ['$last' => '$' . $column];
                }
            }

            // Add aggregation functions to the $group part of the aggregation pipeline,
            // these may override previous aggregations.
            if ($this->aggregate) {
                $function = $this->aggregate['function'];

                foreach ($this->aggregate['columns'] as $column) {
                    // Add unwind if a subdocument array should be aggregated
                    // column: subarray.price => {$unwind: '$subarray'}
                    $splitColumns = explode('.*.', $column);
                    if (count($splitColumns) === 2) {
                        $unwinds[] = $splitColumns[0];
                        $column    = implode('.', $splitColumns);
                    }

                    $aggregations = blank($this->aggregate['columns']) ? [] : $this->aggregate['columns'];

                    if ($column === '*' && $function === 'count' && ! $this->groups) {
                        $options = $this->inheritConnectionOptions($this->options);

                        return ['countDocuments' => [$wheres, $options]];
                    }

                    // "aggregate" is the name of the field that will hold the aggregated value.
                    if ($function === 'count') {
                        if ($column === '*' || $aggregations === []) {
                            // Translate count into sum.
                            $group['aggregate'] = ['$sum' => 1];
                        } else {
                            // Count the number of distinct values.
                            $group['aggregate'] = ['$addToSet' => '$' . $column];
                            $set['aggregate'] = ['$size' => '$aggregate'];
                        }
                    } else {
                        $group['aggregate'] = ['$' . $function => '$' . $column];
                    }
                }
            }

            // The _id field is mandatory when using grouping.
            if ($group && empty($group['_id'])) {
                $group['_id'] = null;
            }

            // Build the aggregation pipeline.
            $pipeline = [];
            if ($wheres) {
                $pipeline[] = ['$match' => $wheres];
            }

            // apply unwinds for subdocument array aggregation
            foreach ($unwinds as $unwind) {
                $pipeline[] = ['$unwind' => '$' . $unwind];
            }

            if ($group) {
                $pipeline[] = ['$group' => $group];
            }

            if ($set) {
                $pipeline[] = ['$set' => $set];
            }

            // Apply order and limit
            if ($this->orders) {
                $pipeline[] = ['$sort' => $this->aliasIdForQuery($this->orders)];
            }

            if ($this->offset) {
                $pipeline[] = ['$skip' => $this->offset];
            }

            if ($this->limit) {
                $pipeline[] = ['$limit' => $this->limit];
            }

            if ($this->projections) {
                $pipeline[] = ['$project' => $this->projections];
            }

            $options = [
                'typeMap' => ['root' => 'object', 'document' => 'array'],
            ];

            // Add custom query options
            if (count($this->options)) {
                $options = array_replace($options, $this->options);
            }

            $options = $this->inheritConnectionOptions($options);

            return ['aggregate' => [$pipeline, $options]];
        }

        // Distinct query
        if ($this->distinct) {
            // Return distinct results directly
            $column = $columns[0] ?? '_id';

            $options = $this->inheritConnectionOptions();

            return ['distinct' => [$column, $wheres, $options]];
        }

        // Normal query
        // Convert select columns to simple projections.
        $projection = $this->aliasIdForQuery(array_fill_keys($columns, true));

        // Add custom projections.
        if ($this->projections) {
            $projection = array_replace($projection, $this->projections);
        }

        $options = [];

        // Apply order, offset, limit and projection
        if ($this->timeout) {
            $options['maxTimeMS'] = (int) ($this->timeout * 1000);
        }

        if ($this->orders) {
            $options['sort'] = $this->aliasIdForQuery($this->orders);
        }

        if ($this->offset) {
            $options['skip'] = $this->offset;
        }

        if ($this->limit) {
            $options['limit'] = $this->limit;
        }

        if ($this->hint) {
            $options['hint'] = $this->hint;
        }

        if ($projection) {
            $options['projection'] = $projection;
        }

        $options['typeMap'] = ['root' => 'object', 'document' => 'array'];

        // Add custom query options
        if (count($this->options)) {
            $options = array_replace($options, $this->options);
        }

        $options = $this->inheritConnectionOptions($options);

        return ['find' => [$wheres, $options]];
    }

    /**
     * Execute the query as a fresh "select" statement.
     *
     * @param  array $columns
     * @param  bool  $returnLazy
     *
     * @return array|static[]|Collection|LazyCollection
     */
    public function getFresh($columns = [], $returnLazy = false)
    {
        // If no columns have been specified for the select statement, we will set them
        // here to either the passed columns, or the standard default of retrieving
        // all of the columns on the table using the "wildcard" column character.
        if ($this->columns === null) {
            $this->columns = $columns;
        }

        // Drop all columns if * is present, MongoDB does not work this way.
        if (in_array('*', $this->columns)) {
            $this->columns = [];
        }

        $command = $this->toMql();
        assert(count($command) >= 1, 'At least one method call is required to execute a query');

        $result = $this->collection;
        foreach ($command as $method => $arguments) {
            $result = call_user_func_array([$result, $method], $arguments);
        }

        // countDocuments method returns int, wrap it to the format expected by the framework
        if (is_int($result)) {
            $result = [
                [
                    '_id'       => null,
                    'aggregate' => $result,
                ],
            ];
        }

        if ($returnLazy) {
            return LazyCollection::make(function () use ($result) {
                foreach ($result as $item) {
                    yield $this->aliasIdForResult($item);
                }
            });
        }

        if ($result instanceof Cursor) {
            $result = $result->toArray();
        }

        foreach ($result as &$document) {
            if (is_array($document) || is_object($document)) {
                $document = $this->aliasIdForResult($document);
            }
        }

        return new Collection($result);
    }

    /**
     * Generate the unique cache key for the current query.
     *
     * @return string
     */
    public function generateCacheKey()
    {
        $key = [
            'connection' => $this->collection->getDatabaseName(),
            'collection' => $this->collection->getCollectionName(),
            'wheres' => $this->wheres,
            'columns' => $this->columns,
            'groups' => $this->groups,
            'orders' => $this->orders,
            'offset' => $this->offset,
            'limit' => $this->limit,
            'aggregate' => $this->aggregate,
        ];

        return md5(serialize(array_values($key)));
    }

    /** @return ($function is null ? AggregationBuilder : mixed) */
    #[Override]
    public function aggregate($function = null, $columns = ['*'])
    {
        assert(is_array($columns), new TypeError(sprintf('Argument #2 ($columns) must be of type array, %s given', get_debug_type($columns))));

        if ($function === null) {
            if (! trait_exists(FluentFactoryTrait::class)) {
                // This error will be unreachable when the mongodb/builder package will be merged into mongodb/mongodb
                throw new BadMethodCallException('Aggregation builder requires package mongodb/builder 0.2+');
            }

            if ($columns !== ['*']) {
                throw new InvalidArgumentException('Columns cannot be specified to create an aggregation builder. Add a $project stage instead.');
            }

            if ($this->wheres) {
                throw new BadMethodCallException('Aggregation builder does not support previous query-builder instructions. Use a $match stage instead.');
            }

            return new AggregationBuilder($this->collection, $this->options);
        }

        $this->aggregate = [
            'function' => $function,
            'columns' => $columns,
        ];

        $previousColumns = $this->columns;

        // We will also back up the select bindings since the select clause will be
        // removed when performing the aggregate function. Once the query is run
        // we will add the bindings back onto this query so they can get used.
        $previousSelectBindings = $this->bindings['select'];

        $this->bindings['select'] = [];

        $results = $this->get($columns);

        // Once we have executed the query, we will reset the aggregate property so
        // that more select queries can be executed against the database without
        // the aggregate value getting in the way when the grammar builds it.
        $this->aggregate          = null;
        $this->columns            = $previousColumns;
        $this->bindings['select'] = $previousSelectBindings;

        // When the aggregation is per group, we return the results as is.
        if ($this->groups) {
            return $results->map(function (object $result) {
                unset($result->id);

                return $result;
            });
        }

        if (isset($results[0])) {
            $result = (array) $results[0];

            return $result['aggregate'];
        }
    }

    /**
     * @param string $function
     * @param array  $columns
     *
     * @return mixed
     */
    public function aggregateByGroup(string $function, array $columns = ['*'])
    {
        if (count($columns) > 1) {
            throw new InvalidArgumentException('Aggregating by group requires zero or one columns.');
        }

        return $this->aggregate($function, $columns);
    }

    /** @inheritdoc */
    #[Override]
    public function exists()
    {
        return $this->first(['id']) !== null;
    }

    /** @inheritdoc */
    public function distinct($column = false)
    {
        $this->distinct = true;

        if ($column) {
            $this->columns = [$column];
        }

        return $this;
    }

    /**
     * @param int|string|array $direction
     *
     * @inheritdoc
     */
    #[Override]
    public function orderBy($column, $direction = 'asc')
    {
        if (is_string($direction)) {
            $direction = match ($direction) {
                'asc', 'ASC' => 1,
                'desc', 'DESC' => -1,
                default => throw new InvalidArgumentException('Order direction must be "asc" or "desc".'),
            };
        }

        $column = (string) $column;
        if ($column === 'natural') {
            $this->orders['$natural'] = $direction;
        } else {
            $this->orders[$column] = $direction;
        }

        return $this;
    }

    /**
     * Override Illuminate's removeExistingOrdersFor to support associative order storage used by MongoDB.
     *
     * @inheritdoc
     */
    #[Override]
    protected function removeExistingOrdersFor($column): array
    {
        $orders = $this->orders ?? [];

        $toUnset = array_filter(
            array_keys($orders),
            function ($orderColumn) use ($column) {
                return $orderColumn === $column
                    || ($orderColumn === 'id' && $column === '_id')
                    || ($orderColumn === '_id' && $column === 'id'
                );
            },
        );

        foreach ($toUnset as $column) {
            unset($orders[$column]);
        }

        return $orders;
    }

    /** @inheritdoc */
    #[Override]
    public function whereBetween($column, iterable $values, $boolean = 'and', $not = false)
    {
        $type = 'between';

        if ($values instanceof Collection) {
            $values = $values->all();
        }

        if (is_array($values) && (! array_is_list($values) || count($values) !== 2)) {
            throw new InvalidArgumentException('Between $values must be a list with exactly two elements: [min, max]');
        }

        $this->wheres[] = [
            'column'  => $column,
            'type'    => $type,
            'boolean' => $boolean,
            'values'  => $values,
            'not'     => $not,
        ];

        return $this;
    }

    /** @inheritdoc */
    #[Override]
    public function insert(array $values)
    {
        // Allow empty insert batch for consistency with Eloquent SQL
        if ($values === []) {
            return true;
        }

        // Since every insert gets treated like a batch insert, we will have to detect
        // if the user is inserting a single document or an array of documents.
        $batch = true;

        foreach ($values as $value) {
            // As soon as we find a value that is not an array we assume the user is
            // inserting a single document.
            if (! is_array($value)) {
                $batc
Download .txt
gitextract_2jedx5y6/

├── .editorconfig
├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   ├── BUG_REPORT.md
│   │   ├── FEATURE-REQUEST.md
│   │   └── config.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   ├── labeler.yml
│   ├── release.yml
│   └── workflows/
│       ├── build-ci-atlas.yml
│       ├── build-ci.yml
│       ├── coding-standards.yml
│       ├── labeler.yml
│       ├── merge-up.yml
│       ├── release.yml
│       └── static-analysis.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── RELEASING.md
├── composer.json
├── docker-compose.yml
├── phpcs.xml.dist
├── phpstan-baseline.neon
├── phpstan.neon.dist
├── phpunit.xml.dist
├── rector.php
├── sbom.json
├── src/
│   ├── Auth/
│   │   └── User.php
│   ├── Bus/
│   │   └── MongoBatchRepository.php
│   ├── Cache/
│   │   ├── MongoLock.php
│   │   └── MongoStore.php
│   ├── CommandSubscriber.php
│   ├── Concerns/
│   │   └── ManagesTransactions.php
│   ├── Connection.php
│   ├── Eloquent/
│   │   ├── Builder.php
│   │   ├── Casts/
│   │   │   ├── BinaryUuid.php
│   │   │   └── ObjectId.php
│   │   ├── DocumentModel.php
│   │   ├── EmbedsRelations.php
│   │   ├── HasSchemaVersion.php
│   │   ├── HybridRelations.php
│   │   ├── MassPrunable.php
│   │   ├── Model.php
│   │   └── SoftDeletes.php
│   ├── Helpers/
│   │   ├── EloquentBuilder.php
│   │   └── QueriesRelationships.php
│   ├── MongoDBBusServiceProvider.php
│   ├── MongoDBServiceProvider.php
│   ├── Query/
│   │   ├── AggregationBuilder.php
│   │   ├── Builder.php
│   │   ├── BuilderTimeout.php
│   │   ├── Grammar.php
│   │   └── Processor.php
│   ├── Queue/
│   │   ├── MongoConnector.php
│   │   ├── MongoJob.php
│   │   └── MongoQueue.php
│   ├── Relations/
│   │   ├── BelongsTo.php
│   │   ├── BelongsToMany.php
│   │   ├── EmbedsMany.php
│   │   ├── EmbedsOne.php
│   │   ├── EmbedsOneOrMany.php
│   │   ├── HasMany.php
│   │   ├── HasOne.php
│   │   ├── MorphMany.php
│   │   ├── MorphTo.php
│   │   └── MorphToMany.php
│   ├── Schema/
│   │   ├── Blueprint.php
│   │   ├── BlueprintLaravelCompatibility.php
│   │   ├── Builder.php
│   │   └── Grammar.php
│   ├── Scout/
│   │   └── ScoutEngine.php
│   ├── Session/
│   │   └── MongoDbSessionHandler.php
│   └── Validation/
│       ├── DatabasePresenceVerifier.php
│       └── ValidationServiceProvider.php
└── tests/
    ├── AtlasSearchIndexManagement.php
    ├── AtlasSearchTest.php
    ├── AuthTest.php
    ├── Bus/
    │   ├── Fixtures/
    │   │   ├── ChainHeadJob.php
    │   │   ├── SecondTestJob.php
    │   │   └── ThirdTestJob.php
    │   └── MongoBatchRepositoryTest.php
    ├── Cache/
    │   ├── MongoCacheStoreTest.php
    │   └── MongoLockTest.php
    ├── Casts/
    │   ├── BinaryUuidTest.php
    │   ├── BooleanTest.php
    │   ├── CollectionTest.php
    │   ├── DateTest.php
    │   ├── DatetimeTest.php
    │   ├── DecimalTest.php
    │   ├── EncryptionTest.php
    │   ├── FloatTest.php
    │   ├── IntegerTest.php
    │   ├── JsonTest.php
    │   ├── ObjectIdTest.php
    │   ├── ObjectTest.php
    │   └── StringTest.php
    ├── ConnectionTest.php
    ├── DateTimeImmutableTest.php
    ├── Eloquent/
    │   ├── CallBuilderTest.php
    │   ├── MassPrunableTest.php
    │   └── ModelTest.php
    ├── EmbeddedRelationsTest.php
    ├── ExternalPackageTest.php
    ├── FilesystemsTest.php
    ├── GeospatialTest.php
    ├── HybridRelationsTest.php
    ├── ModelTest.php
    ├── Models/
    │   ├── Address.php
    │   ├── Anniversary.php
    │   ├── Birthday.php
    │   ├── Book.php
    │   ├── CastObjectId.php
    │   ├── Casting.php
    │   ├── Client.php
    │   ├── Experience.php
    │   ├── Group.php
    │   ├── Guarded.php
    │   ├── HiddenAnimal.php
    │   ├── IdIsBinaryUuid.php
    │   ├── IdIsInt.php
    │   ├── IdIsString.php
    │   ├── Item.php
    │   ├── Label.php
    │   ├── Location.php
    │   ├── MemberStatus.php
    │   ├── NonIncrementing.php
    │   ├── Photo.php
    │   ├── Role.php
    │   ├── SchemaVersion.php
    │   ├── Scoped.php
    │   ├── Skill.php
    │   ├── Soft.php
    │   ├── SqlBook.php
    │   ├── SqlRole.php
    │   ├── SqlUser.php
    │   └── User.php
    ├── PHPStan/
    │   └── SarifErrorFormatter.php
    ├── PropertyTest.php
    ├── Query/
    │   ├── AggregationBuilderTest.php
    │   └── BuilderTest.php
    ├── QueryBuilderTest.php
    ├── QueryTest.php
    ├── Queue/
    │   └── Failed/
    │       └── DatabaseFailedJobProviderTest.php
    ├── QueueTest.php
    ├── RelationsTest.php
    ├── SchemaTest.php
    ├── SchemaVersionTest.php
    ├── Scout/
    │   ├── Models/
    │   │   ├── ScoutUser.php
    │   │   ├── SearchableInSameNamespace.php
    │   │   └── SearchableModel.php
    │   ├── ScoutEngineTest.php
    │   └── ScoutIntegrationTest.php
    ├── Seeder/
    │   ├── DatabaseSeeder.php
    │   └── UserTableSeeder.php
    ├── SeederTest.php
    ├── SessionTest.php
    ├── TestCase.php
    ├── Ticket/
    │   ├── GH2489Test.php
    │   ├── GH2783Test.php
    │   ├── GH3326Test.php
    │   ├── GH3328Test.php
    │   └── GH3335Test.php
    ├── TransactionTest.php
    ├── ValidationTest.php
    └── config/
        ├── database.php
        └── queue.php
Download .txt
SYMBOL INDEX (1270 symbols across 136 files)

FILE: src/Auth/User.php
  class User (line 10) | class User extends BaseUser

FILE: src/Bus/MongoBatchRepository.php
  class MongoBatchRepository (line 29) | class MongoBatchRepository extends DatabaseBatchRepository implements Pr...
    method __construct (line 33) | public function __construct(
    method get (line 43) | #[Override]
    method find (line 60) | #[Override]
    method store (line 79) | #[Override]
    method incrementTotalJobs (line 99) | #[Override]
    method decrementPendingJobs (line 115) | #[Override]
    method incrementFailedJobs (line 137) | #[Override]
    method markAsFinished (line 159) | #[Override]
    method cancel (line 169) | #[Override]
    method delete (line 184) | #[Override]
    method transaction (line 192) | #[Override]
    method rollBack (line 199) | #[Override]
    method prune (line 206) | #[Override]
    method pruneUnfinished (line 217) | #[Override]
    method pruneCancelled (line 231) | #[Override]
    method toBatch (line 245) | #[Override]
    method getUTCDateTime (line 263) | private function getUTCDateTime(): UTCDateTime
    method toCarbon (line 270) | private function toCarbon(?UTCDateTime $date): ?CarbonImmutable

FILE: src/Cache/MongoLock.php
  class MongoLock (line 16) | final class MongoLock extends Lock
    method __construct (line 27) | public function __construct(
    method acquire (line 44) | #[Override]
    method release (line 96) | #[Override]
    method forceRelease (line 111) | #[Override]
    method createTTLIndex (line 120) | public function createTTLIndex(): void
    method getCurrentOwner (line 133) | #[Override]
    method getUTCDateTime (line 145) | private function getUTCDateTime(int $additionalSeconds = 0): UTCDateTime

FILE: src/Cache/MongoStore.php
  class MongoStore (line 22) | final class MongoStore implements LockProvider, Store
    method __construct (line 40) | public function __construct(
    method lock (line 59) | #[Override]
    method restoreLock (line 74) | #[Override]
    method put (line 87) | #[Override]
    method add (line 113) | public function add($key, $value, $seconds): bool
    method get (line 152) | #[Override]
    method increment (line 179) | #[Override]
    method decrement (line 213) | #[Override]
    method forever (line 225) | #[Override]
    method forget (line 236) | #[Override]
    method forgetIfExpired (line 251) | public function forgetIfExpired($key): bool
    method touch (line 267) | public function touch($key, $seconds): bool
    method flush (line 282) | public function flush(): bool
    method getPrefix (line 289) | public function getPrefix(): string
    method createTTLIndex (line 295) | public function createTTLIndex(): void
    method serialize (line 305) | private function serialize($value): string|int|float
    method unserialize (line 315) | private function unserialize($value): mixed
    method getUTCDateTime (line 324) | private function getUTCDateTime(int $additionalSeconds = 0): UTCDateTime

FILE: src/CommandSubscriber.php
  class CommandSubscriber (line 16) | final class CommandSubscriber implements CommandSubscriberInterface
    method __construct (line 21) | public function __construct(private Connection $connection)
    method commandStarted (line 25) | #[Override]
    method commandFailed (line 31) | #[Override]
    method commandSucceeded (line 37) | #[Override]
    method logQuery (line 43) | private function logQuery(CommandSucceededEvent|CommandFailedEvent $ev...

FILE: src/Concerns/ManagesTransactions.php
  type ManagesTransactions (line 23) | trait ManagesTransactions
    method getClient (line 29) | abstract public function getClient(): ?Client;
    method getSession (line 31) | public function getSession(): ?Session
    method getSessionOrCreate (line 36) | private function getSessionOrCreate(): Session
    method getSessionOrThrow (line 45) | private function getSessionOrThrow(): Session
    method beginTransaction (line 59) | public function beginTransaction(array $options = []): void
    method handleInitialTransactionState (line 68) | private function handleInitialTransactionState(): void
    method commit (line 83) | public function commit(): void
    method handleCommitState (line 91) | private function handleCommitState(): void
    method rollBack (line 110) | public function rollBack($toLevel = null): void
    method handleRollbackState (line 120) | private function handleRollbackState(): void
    method runCallbacksBeforeTransaction (line 132) | private function runCallbacksBeforeTransaction(): void
    method transaction (line 149) | public function transaction(Closure $callback, $attempts = 1, array $o...

FILE: src/Connection.php
  class Connection (line 35) | class Connection extends BaseConnection
    method __construct (line 63) | public function __construct(array $config)
    method table (line 99) | #[Override]
    method getCollection (line 114) | public function getCollection($name): Collection
    method getSchemaBuilder (line 120) | #[Override]
    method getMongoDB (line 133) | public function getMongoDB()
    method getDatabase (line 147) | public function getDatabase(?string $name = null): Database
    method getMongoClient (line 163) | public function getMongoClient()
    method getClient (line 173) | public function getClient(): ?Client
    method enableQueryLog (line 179) | #[Override]
    method disableQueryLog (line 190) | #[Override]
    method withFreshQueryLog (line 201) | #[Override]
    method getDefaultDatabaseName (line 221) | protected function getDefaultDatabaseName(string $dsn, array $config):...
    method createConnection (line 237) | protected function createConnection(string $dsn, array $config, array ...
    method ping (line 274) | public function ping(): void
    method disconnect (line 280) | public function disconnect()
    method hasDsnString (line 291) | protected function hasDsnString(array $config): bool
    method getDsnString (line 299) | protected function getDsnString(array $config): string
    method getHostDsn (line 307) | protected function getHostDsn(array $config): string
    method getDsn (line 336) | protected function getDsn(array $config): string
    method getDriverName (line 350) | #[Override]
    method getDriverTitle (line 357) | public function getDriverTitle()
    method getDefaultPostProcessor (line 363) | #[Override]
    method getDefaultQueryGrammar (line 370) | #[Override]
    method getDefaultSchemaGrammar (line 378) | #[Override]
    method setDatabase (line 388) | public function setDatabase(Database $db)
    method threadCount (line 394) | public function threadCount()
    method __call (line 409) | public function __call($method, $parameters)
    method setRenameEmbeddedIdField (line 415) | public function setRenameEmbeddedIdField(bool $rename): void
    method getRenameEmbeddedIdField (line 421) | public function getRenameEmbeddedIdField(): bool
    method getServerVersion (line 432) | public function getServerVersion(): string
    method getVersion (line 437) | private static function getVersion(): string
    method lookupVersion (line 442) | private static function lookupVersion(): string

FILE: src/Eloquent/Builder.php
  class Builder (line 37) | class Builder extends EloquentBuilder
    method aggregate (line 78) | public function aggregate($function = null, $columns = ['*'])
    method search (line 92) | public function search(
    method vectorSearch (line 118) | public function vectorSearch(
    method update (line 137) | #[Override]
    method insert (line 153) | public function insert(array $values)
    method insertGetId (line 168) | public function insertGetId(array $values, $sequence = null)
    method delete (line 183) | public function delete()
    method increment (line 198) | public function increment($column, $amount = 1, array $extra = [])
    method decrement (line 220) | public function decrement($column, $amount = 1, array $extra = [])
    method raw (line 248) | public function raw($value = null)
    method firstOrCreate (line 280) | #[Override]
    method createOrFirst (line 296) | #[Override]
    method addUpdatedAtColumn (line 321) | #[Override]
    method getConnection (line 341) | public function getConnection(): Connection
    method ensureOrderForCursorPagination (line 347) | #[Override]

FILE: src/Eloquent/Casts/BinaryUuid.php
  class BinaryUuid (line 19) | class BinaryUuid implements CastsAttributes
    method get (line 29) | public function get($model, string $key, $value, array $attributes)
    method set (line 55) | public function set($model, string $key, $value, array $attributes)

FILE: src/Eloquent/Casts/ObjectId.php
  class ObjectId (line 11) | class ObjectId implements CastsAttributes
    method get (line 21) | public function get($model, string $key, $value, array $attributes)
    method set (line 38) | public function set($model, string $key, $value, array $attributes)

FILE: src/Eloquent/DocumentModel.php
  type DocumentModel (line 54) | trait DocumentModel
    method getIdAttribute (line 78) | public function getIdAttribute($value = null)
    method getQualifiedKeyName (line 97) | public function getQualifiedKeyName()
    method fromDateTime (line 109) | public function fromDateTime($value): UTCDateTime
    method asDateTime (line 131) | protected function asDateTime($value): DateTimeInterface
    method getDateFormat (line 143) | public function getDateFormat()
    method freshTimestamp (line 149) | public function freshTimestamp()
    method getAttribute (line 155) | public function getAttribute($key)
    method transformModelValue (line 188) | protected function transformModelValue($key, $value)
    method getCastType (line 208) | protected function getCastType($key)
    method getAttributeFromArray (line 219) | protected function getAttributeFromArray($key)
    method setAttribute (line 232) | public function setAttribute($key, $value)
    method asDecimal (line 275) | protected function asDecimal($value, $decimals)
    method fromDecimal (line 299) | protected function fromDecimal($value, $decimals)
    method attributesToArray (line 305) | public function attributesToArray()
    method getCasts (line 325) | public function getCasts()
    method getDirty (line 331) | public function getDirty()
    method originalIsEquivalent (line 344) | public function originalIsEquivalent($key)
    method offsetUnset (line 385) | public function offsetUnset($offset): void
    method offsetSet (line 402) | public function offsetSet($offset, $value): void
    method drop (line 419) | public function drop($columns)
    method unset (line 431) | public function unset($columns)
    method push (line 442) | public function push()
    method pull (line 475) | public function pull($column, $values)
    method pushAttributeValues (line 493) | protected function pushAttributeValues($column, array $values, $unique...
    method pullAttributeValues (line 516) | protected function pullAttributeValues($column, array $values)
    method getForeignKey (line 536) | public function getForeignKey()
    method setParentRelation (line 544) | public function setParentRelation(Relation $relation)
    method getParentRelation (line 552) | public function getParentRelation(): ?Relation
    method newEloquentBuilder (line 558) | public function newEloquentBuilder($query)
    method qualifyColumn (line 564) | public function qualifyColumn($column)
    method newBaseQueryBuilder (line 570) | protected function newBaseQueryBuilder()
    method removeTableFromKey (line 578) | protected function removeTableFromKey($key)
    method getQueueableRelations (line 588) | public function getQueueableRelations()
    method getRelationsWithoutParent (line 618) | protected function getRelationsWithoutParent()
    method isGuardableColumn (line 638) | protected function isGuardableColumn($key)
    method addCastAttributesToArray (line 644) | protected function addCastAttributesToArray(array $attributes, array $...
    method getStorableEnumValueFromLaravel11 (line 700) | private function getStorableEnumValueFromLaravel11($expectedEnum, $value)
    method isBSON (line 718) | protected function isBSON(mixed $value): bool
    method save (line 726) | public function save(array $options = [])
    method refresh (line 749) | public function refresh()

FILE: src/Eloquent/EmbedsRelations.php
  type EmbedsRelations (line 19) | trait EmbedsRelations
    method embedsMany (line 31) | protected function embedsMany($related, $localKey = null, $foreignKey ...
    method embedsOne (line 65) | protected function embedsOne($related, $localKey = null, $foreignKey =...

FILE: src/Eloquent/HasSchemaVersion.php
  type HasSchemaVersion (line 33) | trait HasSchemaVersion
    method migrateSchema (line 39) | public function migrateSchema(int $fromVersion): void
    method bootHasSchemaVersion (line 43) | public static function bootHasSchemaVersion(): void
    method getSchemaVersion (line 64) | public function getSchemaVersion(): int
    method getSchemaVersionKey (line 69) | protected static function getSchemaVersionKey(): string
    method getModelSchemaVersion (line 74) | protected function getModelSchemaVersion(): int

FILE: src/Eloquent/HybridRelations.php
  type HybridRelations (line 31) | trait HybridRelations
    method hasOne (line 44) | public function hasOne($related, $foreignKey = null, $localKey = null)
    method morphOne (line 73) | public function morphOne($related, $name, $type = null, $id = null, $l...
    method hasMany (line 100) | public function hasMany($related, $foreignKey = null, $localKey = null)
    method morphMany (line 129) | public function morphMany($related, $name, $type = null, $id = null, $...
    method belongsTo (line 162) | public function belongsTo($related, $foreignKey = null, $ownerKey = nu...
    method morphTo (line 207) | public function morphTo($name = null, $type = null, $id = null, $owner...
    method belongsToMany (line 272) | public function belongsToMany(
    method morphToMany (line 349) | public function morphToMany(
    method morphedByMany (line 424) | public function morphedByMany(
    method newEloquentBuilder (line 459) | public function newEloquentBuilder($query)

FILE: src/Eloquent/MassPrunable.php
  type MassPrunable (line 15) | trait MassPrunable
    method pruneAll (line 24) | public function pruneAll(): int

FILE: src/Eloquent/Model.php
  class Model (line 15) | abstract class Model extends BaseModel
    method isDocumentModel (line 35) | final public static function isDocumentModel(string|object $class): bool

FILE: src/Eloquent/SoftDeletes.php
  type SoftDeletes (line 15) | trait SoftDeletes
    method getQualifiedDeletedAtColumn (line 20) | public function getQualifiedDeletedAtColumn()

FILE: src/Helpers/EloquentBuilder.php
  class EloquentBuilder (line 9) | class EloquentBuilder extends Builder

FILE: src/Helpers/QueriesRelationships.php
  type QueriesRelationships (line 31) | trait QueriesRelationships
    method has (line 45) | public function has($relation, $operator = '>=', $count = 1, $boolean ...
    method isAcrossConnections (line 90) | protected function isAcrossConnections(Relation $relation)
    method addHybridHas (line 106) | public function addHybridHas(Relation $relation, $operator = '>=', $co...
    method assertHybridRelationSupported (line 141) | private function assertHybridRelationSupported(Relation $relation): void
    method handleMorphToMany (line 160) | private function handleMorphToMany($hasQuery, $relation)
    method handleMorphedByMany (line 177) | private function handleMorphedByMany($hasQuery, $relation)
    method getHasCompareKey (line 185) | protected function getHasCompareKey(Relation $relation)
    method getConstrainedRelatedIds (line 201) | protected function getConstrainedRelatedIds($relations, $operator, $co...
    method getRelatedConstraintKey (line 237) | protected function getRelatedConstraintKey(Relation $relation)

FILE: src/MongoDBBusServiceProvider.php
  class MongoDBBusServiceProvider (line 17) | class MongoDBBusServiceProvider extends ServiceProvider implements Defer...
    method register (line 22) | #[Override]
    method provides (line 52) | #[Override]

FILE: src/MongoDBServiceProvider.php
  class MongoDBServiceProvider (line 36) | class MongoDBServiceProvider extends ServiceProvider
    method boot (line 41) | public function boot()
    method register (line 51) | #[Override]
    method registerFlysystemAdapter (line 111) | private function registerFlysystemAdapter(): void
    method registerScoutEngine (line 163) | private function registerScoutEngine(): void

FILE: src/Query/AggregationBuilder.php
  class AggregationBuilder (line 21) | class AggregationBuilder
    method __construct (line 25) | public function __construct(
    method addRawStage (line 35) | public function addRawStage(string $operator, mixed $value): static
    method get (line 49) | public function get(array $options = []): LaravelCollection|LazyCollec...
    method cursor (line 59) | public function cursor($options = []): LazyCollection
    method first (line 73) | public function first(array $options = []): mixed
    method execute (line 84) | private function execute(array $options): CursorInterface&Iterator

FILE: src/Query/Builder.php
  class Builder (line 89) | class Builder extends BaseBuilder
    method project (line 206) | public function project($columns)
    method hint (line 220) | public function hint($index)
    method find (line 228) | #[Override]
    method value (line 235) | #[Override]
    method get (line 244) | #[Override]
    method cursor (line 251) | #[Override]
    method dd (line 267) | #[Override]
    method dump (line 280) | #[Override]
    method toMql (line 295) | public function toMql(): array
    method getFresh (line 492) | public function getFresh($columns = [], $returnLazy = false)
    method generateCacheKey (line 550) | public function generateCacheKey()
    method aggregate (line 568) | #[Override]
    method aggregateByGroup (line 635) | public function aggregateByGroup(string $function, array $columns = ['...
    method exists (line 645) | #[Override]
    method distinct (line 652) | public function distinct($column = false)
    method orderBy (line 668) | #[Override]
    method removeExistingOrdersFor (line 694) | #[Override]
    method whereBetween (line 717) | #[Override]
    method insert (line 742) | #[Override]
    method insertGetId (line 780) | #[Override]
    method update (line 800) | #[Override]
    method upsert (line 817) | #[Override]
    method increment (line 864) | #[Override]
    method incrementEach (line 890) | #[Override]
    method decrement (line 908) | #[Override]
    method decrementEach (line 915) | #[Override]
    method multiply (line 935) | public function multiply($column, $amount, array $extra = [], array $o...
    method divide (line 963) | public function divide($column, $amount, array $extra = [], array $opt...
    method pluck (line 969) | #[Override]
    method delete (line 980) | #[Override]
    method from (line 1012) | #[Override]
    method truncate (line 1022) | public function truncate(): bool
    method lists (line 1040) | public function lists($column, $key = null)
    method raw (line 1052) | #[Override]
    method push (line 1078) | public function push($column, $value = null, $unique = false)
    method pull (line 1109) | public function pull($column, $value = null)
    method drop (line 1133) | public function drop($columns)
    method newQuery (line 1155) | #[Override]
    method runPaginationCountQuery (line 1161) | #[Override]
    method performUpdate (line 1189) | protected function performUpdate(array $update, array $options = [])
    method convertKey (line 1217) | public function convertKey($id)
    method where (line 1244) | #[Override]
    method compileWheres (line 1274) | protected function compileWheres(): array
    method compileWhereBasic (line 1368) | protected function compileWhereBasic(array $where): array
    method compileWhereNested (line 1436) | protected function compileWhereNested(array $where): mixed
    method compileWhereIn (line 1441) | protected function compileWhereIn(array $where): array
    method compileWhereNotIn (line 1446) | protected function compileWhereNotIn(array $where): array
    method compileWhereLike (line 1451) | protected function compileWhereLike(array $where): array
    method compileWhereNull (line 1458) | protected function compileWhereNull(array $where): array
    method compileWhereNotNull (line 1466) | protected function compileWhereNotNull(array $where): array
    method compileWhereBetween (line 1474) | protected function compileWhereBetween(array $where): array
    method compileWhereDate (line 1505) | protected function compileWhereDate(array $where): array
    method compileWhereMonth (line 1534) | protected function compileWhereMonth(array $where): array
    method compileWhereDay (line 1548) | protected function compileWhereDay(array $where): array
    method compileWhereYear (line 1562) | protected function compileWhereYear(array $where): array
    method compileWhereTime (line 1576) | protected function compileWhereTime(array $where): array
    method compileWhereRaw (line 1600) | protected function compileWhereRaw(array $where): mixed
    method compileWhereSub (line 1605) | protected function compileWhereSub(array $where): mixed
    method options (line 1617) | public function options(array $options)
    method readPreference (line 1635) | public function readPreference(string $mode, ?array $tagSets = null, ?...
    method search (line 1650) | public function search(
    method vectorSearch (line 1689) | public function vectorSearch(
    method autocomplete (line 1724) | public function autocomplete(string $path, string $query, bool|array $...
    method inheritConnectionOptions (line 1741) | private function inheritConnectionOptions(array $options = []): array
    method __call (line 1758) | #[Override]
    method toSql (line 1769) | #[Override]
    method toRawSql (line 1776) | #[Override]
    method whereColumn (line 1783) | #[Override]
    method whereFullText (line 1790) | #[Override]
    method groupByRaw (line 1797) | #[Override]
    method orderByRaw (line 1804) | #[Override]
    method unionAll (line 1811) | #[Override]
    method union (line 1818) | #[Override]
    method having (line 1825) | #[Override]
    method havingRaw (line 1832) | #[Override]
    method havingBetween (line 1839) | #[Override]
    method whereIntegerInRaw (line 1846) | #[Override]
    method orWhereIntegerInRaw (line 1853) | #[Override]
    method whereIntegerNotInRaw (line 1860) | #[Override]
    method orWhereIntegerNotInRaw (line 1867) | #[Override]
    method aliasIdForQuery (line 1873) | private function aliasIdForQuery(array $values, bool $root = true): array
    method aliasIdForResult (line 1933) | public function aliasIdForResult(array|object $values, bool $root = tr...

FILE: src/Query/BuilderTimeout.php
  type BuilderTimeout (line 19) | trait BuilderTimeout
    method timeout (line 40) | public function timeout($seconds)
  type BuilderTimeout (line 24) | trait BuilderTimeout
    method timeout (line 40) | public function timeout($seconds)

FILE: src/Query/Grammar.php
  class Grammar (line 9) | class Grammar extends BaseGrammar

FILE: src/Query/Processor.php
  class Processor (line 9) | class Processor extends BaseProcessor

FILE: src/Queue/MongoConnector.php
  class MongoConnector (line 15) | class MongoConnector implements ConnectorInterface
    method __construct (line 27) | public function __construct(ConnectionResolverInterface $connections)
    method connect (line 37) | public function connect(array $config)

FILE: src/Queue/MongoJob.php
  class MongoJob (line 10) | class MongoJob extends DatabaseJob
    method isReserved (line 17) | public function isReserved()
    method reservedAt (line 23) | public function reservedAt()

FILE: src/Queue/MongoQueue.php
  class MongoQueue (line 14) | class MongoQueue extends DatabaseQueue
    method __construct (line 31) | public function __construct(Connection $database, $table, $default = '...
    method pop (line 43) | #[Override]
    method getNextAvailableJobAndReserve (line 79) | protected function getNextAvailableJobAndReserve($queue)
    method releaseJobsThatHaveBeenReservedTooLong (line 114) | protected function releaseJobsThatHaveBeenReservedTooLong($queue)
    method releaseJob (line 137) | protected function releaseJob($id, $attempts)
    method deleteReserved (line 147) | #[Override]
    method deleteAndRelease (line 154) | #[Override]

FILE: src/Relations/BelongsTo.php
  class BelongsTo (line 17) | class BelongsTo extends EloquentBelongsTo
    method getHasCompareKey (line 24) | public function getHasCompareKey()
    method addConstraints (line 30) | #[Override]
    method addEagerConstraints (line 42) | #[Override]
    method getRelationExistenceQuery (line 52) | #[Override]
    method whereInMethod (line 65) | #[Override]
    method getQualifiedForeignKeyName (line 71) | #[Override]

FILE: src/Relations/BelongsToMany.php
  class BelongsToMany (line 30) | class BelongsToMany extends EloquentBelongsToMany
    method getHasCompareKey (line 37) | public function getHasCompareKey()
    method getRelationExistenceQuery (line 43) | #[Override]
    method hydratePivotRelation (line 50) | #[Override]
    method getSelectColumns (line 61) | protected function getSelectColumns(array $columns = ['*'])
    method shouldSelect (line 67) | #[Override]
    method addConstraints (line 74) | #[Override]
    method setWhere (line 87) | protected function setWhere()
    method save (line 97) | #[Override]
    method create (line 108) | #[Override]
    method sync (line 124) | #[Override]
    method updateExistingPivot (line 188) | #[Override]
    method attach (line 196) | #[Override]
    method detach (line 237) | #[Override]
    method buildDictionary (line 278) | #[Override]
    method newPivotQuery (line 298) | #[Override]
    method newRelatedQuery (line 309) | public function newRelatedQuery()
    method getForeignKey (line 319) | public function getForeignKey()
    method getQualifiedForeignPivotKeyName (line 325) | #[Override]
    method getQualifiedRelatedPivotKeyName (line 332) | #[Override]
    method whereInMethod (line 343) | #[Override]

FILE: src/Relations/EmbedsMany.php
  class EmbedsMany (line 30) | class EmbedsMany extends EmbedsOneOrMany
    method initRelation (line 33) | public function initRelation(array $models, $relation)
    method getResults (line 43) | public function getResults()
    method performInsert (line 53) | public function performInsert(Model $model)
    method performUpdate (line 83) | public function performUpdate(Model $model)
    method performDelete (line 114) | public function performDelete(Model $model)
    method associate (line 140) | public function associate(Model $model)
    method dissociate (line 156) | public function dissociate($ids = [])
    method destroy (line 186) | public function destroy($ids = [])
    method delete (line 212) | public function delete($id = null): int
    method detach (line 233) | public function detach($ids = [])
    method attach (line 243) | public function attach(Model $model)
    method associateNew (line 255) | protected function associateNew($model)
    method associateExisting (line 277) | protected function associateExisting($model)
    method paginate (line 307) | public function paginate($perPage = null, $columns = ['*'], $pageName ...
    method getEmbedded (line 334) | protected function getEmbedded()
    method setEmbedded (line 340) | protected function setEmbedded($records)
    method __call (line 350) | public function __call($method, $parameters)
    method whereInMethod (line 366) | protected function whereInMethod(Model $model, $key)

FILE: src/Relations/EmbedsOne.php
  class EmbedsOne (line 20) | class EmbedsOne extends EmbedsOneOrMany
    method initRelation (line 22) | public function initRelation(array $models, $relation)
    method getResults (line 31) | public function getResults()
    method getEager (line 36) | public function getEager()
    method performInsert (line 49) | public function performInsert(Model $model)
    method performUpdate (line 78) | public function performUpdate(Model $model)
    method performDelete (line 103) | public function performDelete()
    method associate (line 128) | public function associate(Model $model)
    method dissociate (line 138) | public function dissociate()
    method delete (line 152) | public function delete($id = null): int
    method whereInMethod (line 166) | protected function whereInMethod(Model $model, $key)

FILE: src/Relations/EmbedsOneOrMany.php
  class EmbedsOneOrMany (line 31) | abstract class EmbedsOneOrMany extends Relation
    method __construct (line 57) | public function __construct(Builder $query, Model $parent, Model $rela...
    method addConstraints (line 82) | #[Override]
    method addEagerConstraints (line 91) | #[Override]
    method match (line 98) | #[Override]
    method get (line 112) | #[Override]
    method count (line 127) | public function count($columns = '*'): int
    method save (line 139) | public function save(Model $model)
    method saveMany (line 153) | public function saveMany($models)
    method create (line 167) | public function create(array $attributes = [])
    method createMany (line 186) | public function createMany(array $records)
    method getIdsArrayFrom (line 204) | protected function getIdsArrayFrom($ids)
    method getEmbedded (line 224) | protected function getEmbedded()
    method setEmbedded (line 234) | protected function setEmbedded($records)
    method getForeignKeyValue (line 254) | protected function getForeignKeyValue($id)
    method toCollection (line 269) | protected function toCollection(array $records = [])
    method toModel (line 291) | protected function toModel(mixed $attributes = []): Model|null
    method getParentRelation (line 319) | protected function getParentRelation()
    method getQuery (line 325) | #[Override]
    method toBase (line 334) | #[Override]
    method isNested (line 347) | protected function isNested()
    method getPathHierarchy (line 359) | protected function getPathHierarchy($glue = '.')
    method getQualifiedParentKeyName (line 370) | #[Override]
    method getParentKey (line 386) | protected function getParentKey()
    method getUpdateValues (line 399) | public static function getUpdateValues($array, $prepend = '')
    method getQualifiedForeignKeyName (line 420) | public function getQualifiedForeignKeyName()
    method whereInMethod (line 432) | #[Override]

FILE: src/Relations/HasMany.php
  class HasMany (line 17) | class HasMany extends EloquentHasMany
    method getForeignKeyName (line 24) | #[Override]
    method getHasCompareKey (line 35) | public function getHasCompareKey()
    method getRelationExistenceQuery (line 41) | #[Override]
    method whereInMethod (line 54) | #[Override]

FILE: src/Relations/HasOne.php
  class HasOne (line 17) | class HasOne extends EloquentHasOne
    method getForeignKeyName (line 24) | #[Override]
    method getHasCompareKey (line 35) | public function getHasCompareKey()
    method getRelationExistenceQuery (line 41) | #[Override]
    method whereInMethod (line 50) | #[Override]

FILE: src/Relations/MorphMany.php
  class MorphMany (line 16) | class MorphMany extends EloquentMorphMany
    method whereInMethod (line 18) | #[Override]

FILE: src/Relations/MorphTo.php
  class MorphTo (line 16) | class MorphTo extends EloquentMorphTo
    method addConstraints (line 19) | #[Override]
    method getResultsByType (line 35) | #[Override]
    method whereInMethod (line 48) | #[Override]

FILE: src/Relations/MorphToMany.php
  class MorphToMany (line 33) | class MorphToMany extends EloquentMorphToMany
    method getRelationExistenceQuery (line 35) | #[Override]
    method hydratePivotRelation (line 41) | #[Override]
    method shouldSelect (line 47) | #[Override]
    method addConstraints (line 53) | #[Override]
    method addEagerConstraints (line 61) | #[Override]
    method setWhere (line 83) | protected function setWhere()
    method save (line 106) | #[Override]
    method create (line 117) | #[Override]
    method sync (line 133) | #[Override]
    method updateExistingPivot (line 210) | #[Override]
    method attach (line 217) | #[Override]
    method detach (line 311) | #[Override]
    method buildDictionary (line 386) | #[Override]
    method newPivotQuery (line 414) | #[Override]
    method newRelatedQuery (line 425) | public function newRelatedQuery()
    method getQualifiedRelatedPivotKeyName (line 430) | #[Override]
    method whereInMethod (line 436) | #[Override]
    method extractIds (line 450) | public function extractIds(array $data, ?string $relatedPivotKey = null)
    method addIdToParentRelationData (line 470) | private function addIdToParentRelationData($id)

FILE: src/Schema/Blueprint.php
  class Blueprint (line 22) | class Blueprint extends BaseBlueprint
    method index (line 42) | #[Override]
    method primary (line 69) | #[Override]
    method dropIndex (line 76) | #[Override]
    method dropIndexIfExists (line 93) | public function dropIndexIfExists($indexOrColumns = null)
    method hasIndex (line 109) | public function hasIndex($indexOrColumns = null)
    method jsonSchema (line 125) | public function jsonSchema(
    method transformColumns (line 146) | protected function transformColumns($indexOrColumns)
    method unique (line 175) | #[Override]
    method sparse (line 195) | public function sparse($columns = null, $options = [])
    method geospatial (line 215) | public function geospatial($columns = null, $index = '2d', $options = [])
    method expire (line 241) | public function expire($columns, $seconds)
    method create (line 257) | #[Override]
    method drop (line 269) | #[Override]
    method renameColumn (line 278) | #[Override]
    method addColumn (line 287) | #[Override]
    method sparse_and_unique (line 305) | public function sparse_and_unique($columns = null, $options = [])
    method searchIndex (line 332) | public function searchIndex(array $definition, string $name = 'default...
    method vectorSearchIndex (line 346) | public function vectorSearchIndex(array $definition, string $name = 'd...
    method dropSearchIndex (line 356) | public function dropSearchIndex(string $name): static
    method fluent (line 370) | protected function fluent($columns = null)
    method __call (line 391) | public function __call($method, $parameters)

FILE: src/Schema/BlueprintLaravelCompatibility.php
  type BlueprintLaravelCompatibility (line 22) | trait BlueprintLaravelCompatibility
    method __construct (line 31) | public function __construct(Connection $connection, string $collection...
    method __construct (line 43) | public function __construct(Connection $connection, string $collection...
  type BlueprintLaravelCompatibility (line 41) | trait BlueprintLaravelCompatibility
    method __construct (line 31) | public function __construct(Connection $connection, string $collection...
    method __construct (line 43) | public function __construct(Connection $connection, string $collection...

FILE: src/Schema/Builder.php
  class Builder (line 44) | class Builder extends \Illuminate\Database\Schema\Builder
    method hasColumn (line 52) | public function hasColumn($table, $column): bool
    method hasColumns (line 63) | public function hasColumns($table, array $columns): bool
    method hasCollection (line 90) | public function hasCollection($name)
    method hasTable (line 102) | #[Override]
    method table (line 109) | #[Override]
    method create (line 120) | #[Override]
    method dropIfExists (line 133) | #[Override]
    method drop (line 142) | #[Override]
    method dropAllTables (line 159) | #[Override]
    method getTables (line 170) | #[Override]
    method getViews (line 181) | #[Override]
    method getTableListing (line 193) | #[Override]
    method getColumns (line 217) | #[Override]
    method getIndexes (line 276) | #[Override]
    method getForeignKeys (line 331) | #[Override]
    method createBlueprint (line 342) | #[Override]
    method getCollection (line 355) | public function getCollection($name)
    method getAllCollections (line 373) | protected function getAllCollections()
    method isAtlasSearchNotSupportedException (line 386) | public static function isAtlasSearchNotSupportedException(ServerExcept...
    method getCollectionRows (line 398) | private function getCollectionRows(string $collectionType, $schema = n...
    method collationToString (line 435) | private function collationToString(array $collation): string

FILE: src/Schema/Grammar.php
  class Grammar (line 9) | class Grammar extends BaseGrammar

FILE: src/Scout/ScoutEngine.php
  class ScoutEngine (line 53) | final class ScoutEngine extends Engine
    method __construct (line 69) | public function __construct(
    method update (line 85) | #[Override]
    method delete (line 147) | #[Override]
    method search (line 168) | #[Override]
    method paginate (line 184) | #[Override]
    method performSearch (line 199) | private function performSearch(Builder $builder, ?int $offset = null):...
    method mapIds (line 305) | #[Override]
    method map (line 324) | #[Override]
    method lazyMap (line 341) | #[Override]
    method performMap (line 348) | private function performMap(Builder $builder, array $results, Model $m...
    method getTotalCount (line 390) | #[Override]
    method flush (line 409) | #[Override]
    method createIndex (line 430) | #[Override]
    method deleteIndex (line 463) | #[Override]
    method getSearchableCollection (line 472) | private function getSearchableCollection(Model|EloquentCollection $mod...
    method getIndexableCollection (line 484) | private function getIndexableCollection(Model|EloquentCollection $mode...
    method serialize (line 504) | private static function serialize(mixed $value): mixed
    method usesSoftDelete (line 523) | private function usesSoftDelete(Model|EloquentCollection $model): bool
    method wait (line 536) | private function wait(Closure $callback): void

FILE: src/Session/MongoDbSessionHandler.php
  class MongoDbSessionHandler (line 18) | final class MongoDbSessionHandler extends DatabaseSessionHandler
    method close (line 22) | public function close(): bool
    method gc (line 27) | #[Override]
    method destroy (line 35) | #[Override]
    method read (line 43) | #[Override]
    method write (line 61) | #[Override]
    method createTTLIndex (line 76) | public function createTTLIndex(): void
    method getDefaultPayload (line 86) | #[Override]
    method getCollection (line 105) | private function getCollection(): Collection
    method getUTCDateTime (line 110) | private function getUTCDateTime(int $additionalSeconds = 0): UTCDateTime

FILE: src/Validation/DatabasePresenceVerifier.php
  class DatabasePresenceVerifier (line 14) | class DatabasePresenceVerifier extends \Illuminate\Validation\DatabasePr...
    method getCount (line 17) | #[Override]
    method getMultiCount (line 34) | #[Override]

FILE: src/Validation/ValidationServiceProvider.php
  class ValidationServiceProvider (line 10) | class ValidationServiceProvider extends BaseProvider
    method registerPresenceVerifier (line 12) | #[Override]

FILE: tests/AtlasSearchIndexManagement.php
  type AtlasSearchIndexManagement (line 14) | trait AtlasSearchIndexManagement
    method waitForSearchIndexesDropped (line 19) | public function waitForSearchIndexesDropped(Collection $collection)
    method waitForSearchIndexesReady (line 35) | public function waitForSearchIndexesReady(Collection $collection)

FILE: tests/AtlasSearchTest.php
  class AtlasSearchTest (line 24) | #[Group('atlas-search')]
    method setUp (line 31) | public function setUp(): void
    method tearDown (line 99) | public function tearDown(): void
    method testGetIndexes (line 106) | public function testGetIndexes()
    method testEloquentBuilderSearch (line 150) | public function testEloquentBuilderSearch()
    method testDatabaseBuilderSearch (line 167) | public function testDatabaseBuilderSearch()
    method testEloquentBuilderAutocomplete (line 182) | public function testEloquentBuilderAutocomplete()
    method testDatabaseBuilderAutocomplete (line 195) | public function testDatabaseBuilderAutocomplete()
    method testDatabaseBuilderVectorSearch (line 209) | public function testDatabaseBuilderVectorSearch()
    method testEloquentBuilderVectorSearch (line 226) | public function testEloquentBuilderVectorSearch()
    method addVector (line 252) | private function addVector(array $items): array

FILE: tests/AuthTest.php
  class AuthTest (line 16) | class AuthTest extends TestCase
    method tearDown (line 18) | public function tearDown(): void
    method testAuthAttempt (line 26) | public function testAuthAttempt()
    method testRemindOld (line 38) | public function testRemindOld()

FILE: tests/Bus/Fixtures/ChainHeadJob.php
  class ChainHeadJob (line 10) | class ChainHeadJob implements ShouldQueue

FILE: tests/Bus/Fixtures/SecondTestJob.php
  class SecondTestJob (line 10) | class SecondTestJob implements ShouldQueue

FILE: tests/Bus/Fixtures/ThirdTestJob.php
  class ThirdTestJob (line 10) | class ThirdTestJob implements ShouldQueue

FILE: tests/Bus/MongoBatchRepositoryTest.php
  class MongoBatchRepositoryTest (line 31) | final class MongoBatchRepositoryTest extends TestCase
    method setUp (line 33) | protected function setUp(): void
    method tearDown (line 43) | protected function tearDown(): void
    method testJobsCanBeAddedToTheBatch (line 63) | public function testJobsCanBeAddedToTheBatch(): void
    method testSuccessfulJobsCanBeRecorded (line 102) | public function testSuccessfulJobsCanBeRecorded()
    method testFailedJobsCanBeRecordedWhileNotAllowingFailures (line 143) | public function testFailedJobsCanBeRecordedWhileNotAllowingFailures()
    method testFailedJobsCanBeRecordedWhileAllowingFailures (line 186) | public function testFailedJobsCanBeRecordedWhileAllowingFailures()
    method testBatchCanBeCancelled (line 228) | public function testBatchCanBeCancelled()
    method testBatchCanBeDeleted (line 242) | public function testBatchCanBeDeleted()
    method testBatchStateCanBeInspected (line 256) | public function testBatchStateCanBeInspected()
    method testChainCanBeAddedToBatch (line 297) | public function testChainCanBeAddedToBatch()
    method createTestBatch (line 333) | private function createTestBatch(Factory $queue, $allowFailures = false)

FILE: tests/Cache/MongoCacheStoreTest.php
  class MongoCacheStoreTest (line 16) | class MongoCacheStoreTest extends TestCase
    method tearDown (line 18) | public function tearDown(): void
    method testGetNullWhenItemDoesNotExist (line 27) | public function testGetNullWhenItemDoesNotExist()
    method testValueCanStoreNewCache (line 33) | public function testValueCanStoreNewCache()
    method testPutOperationShouldNotStoreExpired (line 42) | public function testPutOperationShouldNotStoreExpired()
    method testValueCanUpdateExistCache (line 51) | public function testValueCanUpdateExistCache()
    method testValueCanUpdateExistCacheInTransaction (line 61) | public function testValueCanUpdateExistCacheInTransaction()
    method testAddOperationShouldNotStoreExpired (line 75) | public function testAddOperationShouldNotStoreExpired()
    method testAddOperationCanStoreNewCache (line 85) | public function testAddOperationCanStoreNewCache()
    method testAddOperationShouldNotUpdateExistCache (line 95) | public function testAddOperationShouldNotUpdateExistCache()
    method testAddOperationShouldNotUpdateExistCacheInTransaction (line 106) | public function testAddOperationShouldNotUpdateExistCacheInTransaction()
    method testAddOperationCanUpdateIfCacheExpired (line 120) | public function testAddOperationCanUpdateIfCacheExpired()
    method testAddOperationCanUpdateIfCacheExpiredInTransaction (line 131) | public function testAddOperationCanUpdateIfCacheExpiredInTransaction()
    method testGetOperationReturnNullIfExpired (line 145) | public function testGetOperationReturnNullIfExpired()
    method testGetOperationCanDeleteExpired (line 156) | public function testGetOperationCanDeleteExpired()
    method testForgetIfExpiredOperationCanDeleteExpired (line 167) | public function testForgetIfExpiredOperationCanDeleteExpired()
    method testForgetIfExpiredOperationShouldNotDeleteUnExpired (line 178) | public function testForgetIfExpiredOperationShouldNotDeleteUnExpired()
    method testIncrementDecrement (line 189) | public function testIncrementDecrement()
    method testTouchReturnsFalseWhenKeyDoesNotExist (line 204) | public function testTouchReturnsFalseWhenKeyDoesNotExist()
    method testTouchExtendsExpirationAndPreservesValue (line 211) | public function testTouchExtendsExpirationAndPreservesValue()
    method testTouchReturnsFalseOnExpiredItem (line 231) | public function testTouchReturnsFalseOnExpiredItem()
    method testTTLIndex (line 241) | public function testTTLIndex()
    method getStore (line 251) | private function getStore(): Repository
    method getCacheCollectionName (line 259) | private function getCacheCollectionName(): string
    method withCachePrefix (line 264) | private function withCachePrefix(string $key): string
    method insertToCacheTable (line 269) | private function insertToCacheTable(string $key, $value, $ttl = 60)

FILE: tests/Cache/MongoLockTest.php
  class MongoLockTest (line 16) | class MongoLockTest extends TestCase
    method tearDown (line 18) | public function tearDown(): void
    method testInvalidLottery (line 25) | #[TestWith([[5, 2]])]
    method testLockCanBeAcquired (line 42) | public function testLockCanBeAcquired()
    method testLockCanBeForceReleased (line 60) | public function testLockCanBeForceReleased()
    method testExpiredLockCanBeRetrieved (line 72) | public function testExpiredLockCanBeRetrieved()
    method testOwnedByCurrentProcess (line 84) | public function testOwnedByCurrentProcess()
    method testRestoreLock (line 96) | public function testRestoreLock()
    method testTTLIndex (line 111) | public function testTTLIndex()
    method getCache (line 120) | private function getCache(): Repository

FILE: tests/Casts/BinaryUuidTest.php
  class BinaryUuidTest (line 15) | class BinaryUuidTest extends TestCase
    method setUp (line 17) | protected function setUp(): void
    method testBinaryUuidCastModel (line 24) | #[DataProvider('provideBinaryUuidCast')]
    method provideBinaryUuidCast (line 34) | public static function provideBinaryUuidCast(): Generator
    method testQueryByStringDoesNotCast (line 43) | public function testQueryByStringDoesNotCast(): void

FILE: tests/Casts/BooleanTest.php
  class BooleanTest (line 10) | class BooleanTest extends TestCase
    method setUp (line 12) | protected function setUp(): void
    method testBool (line 19) | public function testBool(): void
    method testBoolAsString (line 42) | public function testBoolAsString(): void
    method testBoolAsNumber (line 70) | public function testBoolAsNumber(): void

FILE: tests/Casts/CollectionTest.php
  class CollectionTest (line 13) | class CollectionTest extends TestCase
    method setUp (line 15) | protected function setUp(): void
    method testCollection (line 22) | public function testCollection(): void

FILE: tests/Casts/DateTest.php
  class DateTest (line 16) | class DateTest extends TestCase
    method setUp (line 18) | protected function setUp(): void
    method testDate (line 25) | public function testDate(): void
    method testDateAsString (line 63) | public function testDateAsString(): void
    method testDateWithCustomFormat (line 82) | public function testDateWithCustomFormat(): void
    method testImmutableDate (line 101) | public function testImmutableDate(): void
    method testImmutableDateWithCustomFormat (line 128) | public function testImmutableDateWithCustomFormat(): void

FILE: tests/Casts/DatetimeTest.php
  class DatetimeTest (line 16) | class DatetimeTest extends TestCase
    method setUp (line 18) | protected function setUp(): void
    method testDatetime (line 26) | public function testDatetime(): void
    method testDatetimeAsString (line 47) | public function testDatetimeAsString(): void
    method testDatetimeWithCustomFormat (line 68) | public function testDatetimeWithCustomFormat(): void
    method testImmutableDatetime (line 87) | public function testImmutableDatetime(): void
    method testImmutableDatetimeWithCustomFormat (line 115) | public function testImmutableDatetimeWithCustomFormat(): void

FILE: tests/Casts/DecimalTest.php
  class DecimalTest (line 19) | class DecimalTest extends TestCase
    method setUp (line 21) | protected function setUp(): void
    method testDecimal (line 28) | public function testDecimal(): void
    method testDecimalAsString (line 49) | public function testDecimalAsString(): void
    method testDecimalAsDecimal128 (line 70) | public function testDecimalAsDecimal128(): void
    method testOtherBSONTypes (line 85) | public function testOtherBSONTypes(): void
    method setBSONType (line 117) | private function setBSONType($value, $id = null)

FILE: tests/Casts/EncryptionTest.php
  class EncryptionTest (line 16) | class EncryptionTest extends TestCase
    method setUp (line 18) | protected function setUp(): void
    method decryptRaw (line 25) | protected function decryptRaw(Casting $model, $key)
    method testEncryptedString (line 33) | public function testEncryptedString(): void
    method testEncryptedArray (line 49) | public function testEncryptedArray(): void
    method testEncryptedObject (line 67) | public function testEncryptedObject(): void
    method testEncryptedCollection (line 85) | public function testEncryptedCollection(): void

FILE: tests/Casts/FloatTest.php
  class FloatTest (line 10) | class FloatTest extends TestCase
    method setUp (line 12) | protected function setUp(): void
    method testFloat (line 19) | public function testFloat(): void
    method testFloatAsString (line 32) | public function testFloatAsString(): void

FILE: tests/Casts/IntegerTest.php
  class IntegerTest (line 10) | class IntegerTest extends TestCase
    method setUp (line 12) | protected function setUp(): void
    method testInt (line 19) | public function testInt(): void
    method testIntAsString (line 37) | public function testIntAsString(): void
    method testIntAsFloat (line 55) | public function testIntAsFloat(): void

FILE: tests/Casts/JsonTest.php
  class JsonTest (line 12) | class JsonTest extends TestCase
    method setUp (line 14) | protected function setUp(): void
    method testJson (line 21) | public function testJson(): void

FILE: tests/Casts/ObjectIdTest.php
  class ObjectIdTest (line 13) | class ObjectIdTest extends TestCase
    method setUp (line 15) | protected function setUp(): void
    method testStoreObjectId (line 22) | #[DataProvider('provideObjectIdCast')]
    method provideObjectIdCast (line 34) | public static function provideObjectIdCast(): Generator
    method testQueryByStringDoesNotCast (line 43) | public function testQueryByStringDoesNotCast(): void

FILE: tests/Casts/ObjectTest.php
  class ObjectTest (line 10) | class ObjectTest extends TestCase
    method setUp (line 12) | protected function setUp(): void
    method testObject (line 19) | public function testObject(): void

FILE: tests/Casts/StringTest.php
  class StringTest (line 12) | class StringTest extends TestCase
    method setUp (line 14) | protected function setUp(): void
    method testString (line 21) | public function testString(): void

FILE: tests/ConnectionTest.php
  class ConnectionTest (line 24) | class ConnectionTest extends TestCase
    method testConnection (line 26) | public function testConnection()
    method testReconnect (line 35) | public function testReconnect()
    method testDisconnectAndCreateNewConnection (line 47) | public function testDisconnectAndCreateNewConnection()
    method testDb (line 63) | public function testDb()
    method dataConnectionConfig (line 70) | public static function dataConnectionConfig(): Generator
    method testConnectionConfig (line 201) | #[DataProvider('dataConnectionConfig')]
    method testLegacyGetMongoClient (line 213) | public function testLegacyGetMongoClient(): void
    method testLegacyGetMongoDB (line 221) | public function testLegacyGetMongoDB(): void
    method testGetDatabase (line 229) | public function testGetDatabase(): void
    method testGetOtherDatabase (line 240) | public function testGetOtherDatabase(): void
    method testConnectionWithoutConfiguredDatabase (line 250) | public function testConnectionWithoutConfiguredDatabase(): void
    method testConnectionWithoutConfiguredDsnOrHost (line 258) | public function testConnectionWithoutConfiguredDsnOrHost(): void
    method testCollection (line 266) | public function testCollection()
    method testPrefix (line 275) | public function testPrefix()
    method testQueryLog (line 289) | public function testQueryLog()
    method testQueryLogWithMultipleClients (line 325) | public function testQueryLogWithMultipleClients()
    method testDisableQueryLog (line 353) | public function testDisableQueryLog()
    method testSchemaBuilder (line 378) | public function testSchemaBuilder()
    method testDriverName (line 384) | public function testDriverName()
    method testPingMethod (line 390) | public function testPingMethod()
    method testServerVersion (line 415) | public function testServerVersion()
    method testThreadsCount (line 421) | public function testThreadsCount()

FILE: tests/DateTimeImmutableTest.php
  class DateTimeImmutableTest (line 13) | final class DateTimeImmutableTest extends TestCase
    method setUp (line 15) | protected function setUp(): void
    method tearDown (line 22) | protected function tearDown(): void
    method testCanReturnCarbonImmutableObject (line 29) | public function testCanReturnCarbonImmutableObject(): void

FILE: tests/Eloquent/CallBuilderTest.php
  class CallBuilderTest (line 19) | final class CallBuilderTest extends TestCase
    method tearDown (line 21) | protected function tearDown(): void
    method testCallingABuilderMethodDoesNotReturnTheBuilderInstance (line 28) | #[Dataprovider('provideFunctionNames')]
    method provideFunctionNames (line 37) | public static function provideFunctionNames(): Generator
    method callingUnsupportedMethodThrowsAnException (line 59) | #[Test]
    method provideUnsupportedMethods (line 72) | public static function provideUnsupportedMethods(): Generator

FILE: tests/Eloquent/MassPrunableTest.php
  class MassPrunableTest (line 17) | class MassPrunableTest extends TestCase
    method tearDown (line 19) | public function tearDown(): void
    method testPruneWithQuery (line 27) | public function testPruneWithQuery(): void
    method testPruneSoftDelete (line 43) | public function testPruneSoftDelete(): void
    method isPrunable (line 60) | protected function isPrunable($model)

FILE: tests/Eloquent/ModelTest.php
  class ModelTest (line 16) | class ModelTest extends TestCase
    method testIsDocumentModel (line 18) | #[DataProvider('provideDocumentModelClasses')]
    method provideDocumentModelClasses (line 24) | public static function provideDocumentModelClasses(): Generator

FILE: tests/EmbeddedRelationsTest.php
  class EmbeddedRelationsTest (line 17) | class EmbeddedRelationsTest extends TestCase
    method tearDown (line 19) | public function tearDown(): void
    method testEmbedsManySave (line 27) | public function testEmbedsManySave()
    method testEmbedsToArray (line 110) | public function testEmbedsToArray()
    method testEmbedsManyAssociate (line 120) | public function testEmbedsManyAssociate()
    method testEmbedsManySaveMany (line 140) | public function testEmbedsManySaveMany()
    method testEmbedsManyDuplicate (line 150) | public function testEmbedsManyDuplicate()
    method testEmbedsManyCreate (line 172) | public function testEmbedsManyCreate()
    method testEmbedsManyCreateMany (line 194) | public function testEmbedsManyCreateMany()
    method testEmbedsManyDestroy (line 206) | public function testEmbedsManyDestroy()
    method testEmbedsManyDelete (line 258) | public function testEmbedsManyDelete()
    method testEmbedsManyDissociate (line 294) | public function testEmbedsManyDissociate()
    method testEmbedsManyAliases (line 321) | public function testEmbedsManyAliases()
    method testEmbedsManyCreatingEventReturnsFalse (line 333) | public function testEmbedsManyCreatingEventReturnsFalse()
    method testEmbedsManySavingEventReturnsFalse (line 353) | public function testEmbedsManySavingEventReturnsFalse()
    method testEmbedsManyUpdatingEventReturnsFalse (line 370) | public function testEmbedsManyUpdatingEventReturnsFalse()
    method testEmbedsManyDeletingEventReturnsFalse (line 393) | public function testEmbedsManyDeletingEventReturnsFalse()
    method testEmbedsManyFindOrContains (line 413) | public function testEmbedsManyFindOrContains()
    method testEmbedsManyEagerLoading (line 429) | public function testEmbedsManyEagerLoading()
    method testEmbedsManyDeleteAll (line 453) | public function testEmbedsManyDeleteAll()
    method testEmbedsManyCollectionMethods (line 477) | public function testEmbedsManyCollectionMethods()
    method testEmbedsOne (line 532) | public function testEmbedsOne()
    method testEmbedsOneAssociate (line 605) | public function testEmbedsOneAssociate()
    method testEmbedsOneNullAssociation (line 621) | public function testEmbedsOneNullAssociation()
    method testEmbedsOneDelete (line 627) | public function testEmbedsOneDelete()
    method testEmbedsOneRefresh (line 636) | public function testEmbedsOneRefresh()
    method testEmbedsOneEmptyRefresh (line 650) | public function testEmbedsOneEmptyRefresh()
    method testEmbedsManyToArray (line 666) | public function testEmbedsManyToArray()
    method testEmbedsManyRefresh (line 679) | public function testEmbedsManyRefresh()
    method testEmbeddedSave (line 695) | public function testEmbeddedSave()
    method testNestedEmbedsOne (line 733) | public function testNestedEmbedsOne()
    method testNestedEmbedsMany (line 761) | public function testNestedEmbedsMany()
    method testNestedMixedEmbeds (line 783) | public function testNestedMixedEmbeds()
    method testNestedEmbedsOneDelete (line 806) | public function testNestedEmbedsOneDelete()
    method testNestedEmbedsManyDelete (line 821) | public function testNestedEmbedsManyDelete()
    method testNestedMixedEmbedsDelete (line 839) | public function testNestedMixedEmbedsDelete()
    method testDoubleAssociate (line 856) | public function testDoubleAssociate()
    method testSaveEmptyModel (line 876) | public function testSaveEmptyModel()
    method testIncrementEmbedded (line 884) | public function testIncrementEmbedded()
    method testPaginateEmbedsMany (line 907) | public function testPaginateEmbedsMany()
    method testGetQueueableRelationsEmbedsMany (line 925) | public function testGetQueueableRelationsEmbedsMany()
    method testGetQueueableRelationsEmbedsOne (line 935) | public function testGetQueueableRelationsEmbedsOne()
    method testUnsetPropertyOnEmbed (line 944) | public function testUnsetPropertyOnEmbed()

FILE: tests/ExternalPackageTest.php
  class ExternalPackageTest (line 16) | class ExternalPackageTest extends TestCase
    method tearDown (line 18) | protected function tearDown(): void
    method testSpacieQueryBuilder (line 28) | public function testSpacieQueryBuilder(): void

FILE: tests/FilesystemsTest.php
  class FilesystemsTest (line 19) | class FilesystemsTest extends TestCase
    method tearDown (line 21) | public function tearDown(): void
    method provideValidOptions (line 28) | public static function provideValidOptions(): Generator
    method testValidOptions (line 65) | #[DataProvider('provideValidOptions')]
    method provideInvalidOptions (line 81) | public static function provideInvalidOptions(): Generator
    method testInvalidOptions (line 99) | #[DataProvider('provideInvalidOptions')]
    method testReadOnlyAndThrowOptions (line 113) | public function testReadOnlyAndThrowOptions()
    method testPrefix (line 132) | public function testPrefix()
    method getBucket (line 146) | private function getBucket(): Bucket

FILE: tests/GeospatialTest.php
  class GeospatialTest (line 10) | class GeospatialTest extends TestCase
    method setUp (line 12) | public function setUp(): void
    method tearDown (line 53) | public function tearDown(): void
    method testGeoWithin (line 60) | public function testGeoWithin()
    method testGeoIntersects (line 99) | public function testGeoIntersects()
    method testNear (line 128) | public function testNear()

FILE: tests/HybridRelationsTest.php
  class HybridRelationsTest (line 20) | class HybridRelationsTest extends TestCase
    method setUp (line 22) | public function setUp(): void
    method tearDown (line 37) | public function tearDown(): void
    method testSqlRelations (line 49) | public function testSqlRelations()
    method testHybridWhereHas (line 106) | public function testHybridWhereHas()
    method testHybridWith (line 160) | public function testHybridWith()
    method testHybridBelongsToMany (line 222) | public function testHybridBelongsToMany()
    method testQueryingHybridBelongsToManyRelationFails (line 271) | public function testQueryingHybridBelongsToManyRelationFails()
    method testHybridMorphToManySqlModelToMongoModel (line 288) | public function testHybridMorphToManySqlModelToMongoModel()
    method testHybridMorphToManyMongoModelToSqlModel (line 339) | public function testHybridMorphToManyMongoModelToSqlModel()

FILE: tests/ModelTest.php
  class ModelTest (line 50) | class ModelTest extends TestCase
    method setUp (line 52) | protected function setUp(): void
    method tearDown (line 59) | protected function tearDown(): void
    method testNewModel (line 72) | public function testNewModel(): void
    method testQualifyColumn (line 82) | public function testQualifyColumn(): void
    method makeUser (line 93) | private function makeUser(): User
    method testInsert (line 105) | public function testInsert(): void
    method testInsertNonIncrementable (line 125) | public function testInsertNonIncrementable(): void
    method testUpdate (line 145) | public function testUpdate(): void
    method testUpdateTroughSetUpdatedAt (line 182) | public function testUpdateTroughSetUpdatedAt(): void
    method testUpsert (line 197) | public function testUpsert()
    method testManualStringId (line 230) | public function testManualStringId(): void
    method testManualIntId (line 259) | public function testManualIntId(): void
    method testDelete (line 275) | public function testDelete(): void
    method testAll (line 287) | public function testAll(): void
    method testFind (line 304) | public function testFind(): void
    method testInsertEmpty (line 318) | public function testInsertEmpty(): void
    method testGet (line 324) | public function testGet(): void
    method testFirst (line 337) | public function testFirst(): void
    method testNoDocument (line 350) | public function testNoDocument(): void
    method testFindOrFail (line 363) | public function testFindOrFail(): void
    method testCreate (line 369) | public function testCreate(): void
    method testDestroy (line 383) | public function testDestroy(): void
    method testTouch (line 392) | public function testTouch(): void
    method testSoftDelete (line 406) | public function testSoftDelete(): void
    method testPrimaryKey (line 439) | #[DataProvider('provideId')]
    method provideId (line 468) | public static function provideId(): iterable
    method testCustomPrimaryKey (line 532) | public function testCustomPrimaryKey(): void
    method testScope (line 550) | public function testScope(): void
    method testToArray (line 561) | public function testToArray(): void
    method testUnset (line 574) | public function testUnset(): void
    method testUnsetRefresh (line 614) | public function testUnsetRefresh(): void
    method testUnsetAndSet (line 627) | public function testUnsetAndSet(): void
    method testUnsetDotAttributes (line 671) | public function testUnsetDotAttributes(): void
    method testUnsetDotAttributesAndSet (line 712) | public function testUnsetDotAttributesAndSet(): void
    method testDateUseLocalTimeZone (line 744) | public function testDateUseLocalTimeZone(): void
    method testDates (line 771) | public function testDates(): void
    method provideDate (line 808) | public static function provideDate(): Generator
    method testDateInputs (line 824) | #[DataProvider('provideDate')]
    method testDateNull (line 855) | public function testDateNull(): void
    method testCarbonDateMockingWorks (line 883) | public function testCarbonDateMockingWorks()
    method testIdAttribute (line 893) | public function testIdAttribute(): void
    method testPushPull (line 903) | public function testPushPull(): void
    method testRaw (line 930) | public function testRaw(): void
    method testRawHyradeModel (line 953) | #[DataProvider('provideTypeMap')]
    method provideTypeMap (line 997) | public static function provideTypeMap(): Generator
    method testDotNotation (line 1006) | public function testDotNotation(): void
    method testAttributeMutator (line 1026) | public function testAttributeMutator(): void
    method testMultipleLevelDotNotation (line 1043) | public function testMultipleLevelDotNotation(): void
    method testGetDirtyDates (line 1058) | public function testGetDirtyDates(): void
    method testChunkById (line 1068) | public function testChunkById(): void
    method testTruncateModel (line 1082) | public function testTruncateModel(): void
    method testGuardedModel (line 1091) | public function testGuardedModel(): void
    method testFirstOrCreate (line 1114) | public function testFirstOrCreate(): void
    method testFirstOrCreateWithValues (line 1132) | public function testFirstOrCreateWithValues(): void
    method testEnumCast (line 1151) | public function testEnumCast(): void
    method testNumericFieldName (line 1166) | public function testNumericFieldName(): void
    method testCreateOrFirst (line 1182) | #[TestWith([true])]
    method testUpdateOrCreate (line 1262) | #[TestWith([['_id' => new ObjectID()]])]
    method testCreateWithNullId (line 1316) | #[TestWith(['_id'])]
    method registerModelEvents (line 1327) | private static function registerModelEvents(string $modelClass, array ...

FILE: tests/Models/Address.php
  class Address (line 11) | class Address extends Model
    method addresses (line 19) | public function addresses(): EmbedsMany

FILE: tests/Models/Anniversary.php
  class Anniversary (line 14) | class Anniversary extends Model

FILE: tests/Models/Birthday.php
  class Birthday (line 15) | class Birthday extends Model

FILE: tests/Models/Book.php
  class Book (line 16) | class Book extends Model
    method author (line 26) | public function author(): BelongsTo
    method sqlAuthor (line 31) | public function sqlAuthor(): BelongsTo

FILE: tests/Models/CastObjectId.php
  class CastObjectId (line 10) | class CastObjectId extends Model

FILE: tests/Models/Casting.php
  class Casting (line 10) | class Casting extends Model

FILE: tests/Models/Client.php
  class Client (line 13) | class Client extends Model
    method users (line 22) | public function users(): BelongsToMany
    method skillsWithCustomKeys (line 27) | public function skillsWithCustomKeys()
    method photo (line 38) | public function photo(): MorphOne
    method addresses (line 43) | public function addresses(): HasMany
    method labels (line 48) | public function labels()
    method labelsWithCustomKeys (line 53) | public function labelsWithCustomKeys()

FILE: tests/Models/Experience.php
  class Experience (line 11) | class Experience extends Model
    method sqlUsers (line 22) | public function sqlUsers(): MorphToMany

FILE: tests/Models/Group.php
  class Group (line 11) | class Group extends Model
    method users (line 20) | public function users(): BelongsToMany

FILE: tests/Models/Guarded.php
  class Guarded (line 10) | class Guarded extends Model

FILE: tests/Models/HiddenAnimal.php
  class HiddenAnimal (line 15) | final class HiddenAnimal extends Model

FILE: tests/Models/IdIsBinaryUuid.php
  class IdIsBinaryUuid (line 11) | class IdIsBinaryUuid extends Model

FILE: tests/Models/IdIsInt.php
  class IdIsInt (line 10) | class IdIsInt extends Model

FILE: tests/Models/IdIsString.php
  class IdIsString (line 10) | class IdIsString extends Model

FILE: tests/Models/Item.php
  class Item (line 14) | class Item extends Model
    method user (line 23) | public function user(): BelongsTo
    method scopeSharp (line 28) | public function scopeSharp(Builder $query)

FILE: tests/Models/Label.php
  class Label (line 16) | class Label extends Model
    method users (line 31) | public function users()
    method sqlUsers (line 36) | public function sqlUsers(): MorphToMany
    method clients (line 41) | public function clients()
    method clientsWithCustomKeys (line 46) | public function clientsWithCustomKeys()

FILE: tests/Models/Location.php
  class Location (line 10) | class Location extends Model

FILE: tests/Models/NonIncrementing.php
  class NonIncrementing (line 14) | class NonIncrementing extends Model

FILE: tests/Models/Photo.php
  class Photo (line 11) | class Photo extends Model
    method hasImage (line 20) | public function hasImage(): MorphTo
    method hasImageWithCustomOwnerKey (line 25) | public function hasImageWithCustomOwnerKey(): MorphTo

FILE: tests/Models/Role.php
  class Role (line 11) | class Role extends Model
    method user (line 20) | public function user(): BelongsTo
    method sqlUser (line 25) | public function sqlUser(): BelongsTo

FILE: tests/Models/SchemaVersion.php
  class SchemaVersion (line 10) | class SchemaVersion extends Model
    method migrateSchema (line 20) | public function migrateSchema(int $fromVersion): void

FILE: tests/Models/Scoped.php
  class Scoped (line 11) | class Scoped extends Model
    method boot (line 20) | protected static function boot()

FILE: tests/Models/Skill.php
  class Skill (line 11) | class Skill extends Model
    method sqlUsers (line 20) | public function sqlUsers(): BelongsToMany

FILE: tests/Models/Soft.php
  class Soft (line 15) | class Soft extends Model
    method prunable (line 27) | public function prunable(): Builder
    method user (line 32) | public function user()

FILE: tests/Models/SqlBook.php
  class SqlBook (line 16) | class SqlBook extends EloquentModel
    method author (line 25) | public function author(): BelongsTo
    method executeSchema (line 33) | public static function executeSchema(): void

FILE: tests/Models/SqlRole.php
  class SqlRole (line 16) | class SqlRole extends EloquentModel
    method user (line 24) | public function user(): BelongsTo
    method sqlUser (line 29) | public function sqlUser(): BelongsTo
    method executeSchema (line 37) | public static function executeSchema()

FILE: tests/Models/SqlUser.php
  class SqlUser (line 19) | class SqlUser extends EloquentModel
    method books (line 27) | public function books(): HasMany
    method role (line 32) | public function role(): HasOne
    method skills (line 37) | public function skills(): BelongsToMany
    method sqlBooks (line 42) | public function sqlBooks(): HasMany
    method labels (line 47) | public function labels(): MorphToMany
    method experiences (line 52) | public function experiences(): MorphToMany
    method executeSchema (line 60) | public static function executeSchema(): void

FILE: tests/Models/User.php
  class User (line 33) | class User extends Model implements AuthenticatableContract, CanResetPas...
    method books (line 60) | public function books()
    method softs (line 65) | public function softs()
    method softsWithTrashed (line 70) | public function softsWithTrashed()
    method sqlBooks (line 75) | public function sqlBooks()
    method items (line 80) | public function items()
    method role (line 85) | public function role()
    method sqlRole (line 90) | public function sqlRole()
    method clients (line 95) | public function clients()
    method groups (line 100) | public function groups()
    method photos (line 105) | public function photos()
    method labels (line 110) | public function labels()
    method addresses (line 115) | public function addresses()
    method father (line 120) | public function father()
    method serializeDate (line 125) | protected function serializeDate(DateTimeInterface $date)
    method username (line 130) | protected function username(): Attribute
    method prunable (line 138) | public function prunable(): Builder

FILE: tests/PHPStan/SarifErrorFormatter.php
  class SarifErrorFormatter (line 24) | class SarifErrorFormatter implements ErrorFormatter
    method __construct (line 28) | public function __construct(
    method formatErrors (line 35) | public function formatErrors(AnalysisResult $analysisResult, Output $o...

FILE: tests/PropertyTest.php
  class PropertyTest (line 11) | final class PropertyTest extends TestCase
    method setUp (line 13) | protected function setUp(): void
    method testCanHideCertainProperties (line 20) | public function testCanHideCertainProperties(): void

FILE: tests/Query/AggregationBuilderTest.php
  class AggregationBuilderTest (line 23) | class AggregationBuilderTest extends TestCase
    method tearDown (line 25) | public function tearDown(): void
    method testCreateAggregationBuilder (line 32) | public function testCreateAggregationBuilder(): void
    method testAddRawStage (line 91) | public function testAddRawStage(): void
    method testAddRawStageInvalid (line 110) | public function testAddRawStageInvalid(): void
    method testColumnsCannotBeSpecifiedToCreateAnAggregationBuilder (line 121) | public function testColumnsCannotBeSpecifiedToCreateAnAggregationBuild...
    method testAggrecationBuilderDoesNotSupportPreviousQueryBuilderInstructions (line 128) | public function testAggrecationBuilderDoesNotSupportPreviousQueryBuild...
    method assertSamePipeline (line 135) | private static function assertSamePipeline(array $expected, Pipeline $...

FILE: tests/Query/BuilderTest.php
  class BuilderTest (line 32) | class BuilderTest extends TestCase
    method testMql (line 34) | #[DataProvider('provideQueryBuilderToMql')]
    method provideQueryBuilderToMql (line 58) | public static function provideQueryBuilderToMql(): iterable
    method testException (line 1476) | #[DataProvider('provideExceptions')]
    method provideExceptions (line 1486) | public static function provideExceptions(): iterable
    method testEloquentMethodsNotSupported (line 1574) | #[DataProvider('getEloquentMethodsNotSupported')]
    method getEloquentMethodsNotSupported (line 1585) | public static function getEloquentMethodsNotSupported()
    method testDisableRenameEmbeddedIdField (line 1632) | #[DataProvider('provideDisableRenameEmbeddedIdField')]
    method provideDisableRenameEmbeddedIdField (line 1643) | public static function provideDisableRenameEmbeddedIdField()
    method getBuilder (line 1714) | private function getBuilder(bool $renameEmbeddedIdField = true): Builder

FILE: tests/QueryBuilderTest.php
  class QueryBuilderTest (line 42) | class QueryBuilderTest extends TestCase
    method tearDown (line 44) | public function tearDown(): void
    method testDeleteWithId (line 52) | public function testDeleteWithId()
    method testCollection (line 86) | public function testCollection()
    method testGet (line 91) | public function testGet()
    method testNoDocument (line 102) | public function testNoDocument()
    method testInsert (line 114) | public function testInsert()
    method testInsertWithCustomId (line 129) | #[TestWith([true])]
    method testInsertGetId (line 145) | public function testInsertGetId()
    method testBatchInsert (line 151) | public function testBatchInsert()
    method testFind (line 169) | public function testFind()
    method testFindWithTimeout (line 177) | public function testFindWithTimeout()
    method testFindNull (line 209) | public function testFindNull()
    method testCount (line 215) | public function testCount()
    method testUpdate (line 225) | public function testUpdate()
    method testUpdateOperators (line 240) | public function testUpdateOperators()
    method testDelete (line 272) | public function testDelete()
    method testTruncate (line 286) | public function testTruncate()
    method testSubKey (line 296) | public function testSubKey()
    method testInArray (line 314) | public function testInArray()
    method testRaw (line 332) | public function testRaw()
    method testRawResultRenameId (line 357) | public function testRawResultRenameId()
    method testPush (line 444) | public function testPush()
    method testPushRefuses2ndArgumentWhen1stIsAnArray (line 500) | public function testPushRefuses2ndArgumentWhen1stIsAnArray()
    method testPull (line 508) | public function testPull()
    method testDistinct (line 539) | public function testDistinct()
    method testCustomId (line 559) | public function testCustomId()
    method testTake (line 598) | public function testTake()
    method testSkip (line 612) | public function testSkip()
    method testPluck (line 626) | public function testPluck()
    method testPluckObjectId (line 637) | public function testPluckObjectId()
    method testList (line 648) | public function testList()
    method testAggregate (line 671) | public function testAggregate()
    method testSubdocumentAggregate (line 690) | public function testSubdocumentAggregate()
    method testSubdocumentArrayAggregate (line 706) | public function testSubdocumentArrayAggregate()
    method testAggregateGroupBy (line 729) | public function testAggregateGroupBy()
    method testAggregateByGroupException (line 774) | public function testAggregateByGroupException(): void
    method testUpdateWithUpsert (line 782) | public function testUpdateWithUpsert()
    method testUpsert (line 801) | public function testUpsert()
    method testUnset (line 833) | public function testUnset()
    method testUpdateSubdocument (line 855) | public function testUpdateSubdocument()
    method testDates (line 865) | public function testDates()
    method testImmutableDates (line 899) | public function testImmutableDates()
    method testOperators (line 926) | public function testOperators()
    method testIncrement (line 1022) | public function testIncrement()
    method testMultiplyAndDivide (line 1071) | public function testMultiplyAndDivide()
    method testProjections (line 1120) | public function testProjections()
    method testValue (line 1135) | public function testValue()
    method testHintOptions (line 1148) | public function testHintOptions()
    method testCursor (line 1169) | public function testCursor()
    method testStringableColumn (line 1186) | public function testStringableColumn()
    method testIncrementEach (line 1245) | public function testIncrementEach()
    method testIdAlias (line 1295) | #[TestWith(['id', 'id'])]

FILE: tests/QueryTest.php
  class QueryTest (line 17) | class QueryTest extends TestCase
    method setUp (line 21) | public function setUp(): void
    method tearDown (line 43) | public function tearDown(): void
    method testWhere (line 52) | public function testWhere(): void
    method testAndWhere (line 73) | public function testAndWhere(): void
    method testRegexp (line 82) | public function testRegexp(): void
    method testLike (line 97) | public function testLike(): void
    method testNotLike (line 118) | public function testNotLike(): void
    method testSelect (line 133) | public function testSelect(): void
    method testWhereNot (line 159) | public function testWhereNot(): void
    method testOrWhere (line 201) | public function testOrWhere(): void
    method testBetween (line 210) | public function testBetween(): void
    method testIn (line 223) | public function testIn(): void
    method testWhereNull (line 239) | public function testWhereNull(): void
    method testWhereNotNull (line 245) | public function testWhereNotNull(): void
    method testWhereDate (line 251) | public function testWhereDate(): void
    method testWhereDay (line 275) | public function testWhereDay(): void
    method testWhereMonth (line 284) | public function testWhereMonth(): void
    method testWhereYear (line 302) | public function testWhereYear(): void
    method testWhereTime (line 317) | public function testWhereTime(): void
    method testOrder (line 338) | public function testOrder(): void
    method testStringableOrder (line 359) | public function testStringableOrder(): void
    method testGroupBy (line 370) | public function testGroupBy(): void
    method testCount (line 400) | public function testCount(): void
    method testExists (line 410) | public function testExists(): void
    method testSubQuery (line 418) | public function testSubQuery(): void
    method testWhereRaw (line 467) | public function testWhereRaw(): void
    method testMultipleOr (line 481) | public function testMultipleOr(): void
    method testPaginate (line 502) | public function testPaginate(): void
    method testCursorPaginate (line 516) | public function testCursorPaginate(): void
    method testPaginateGroup (line 539) | public function testPaginateGroup(): void
    method testPaginateDistinct (line 569) | public function testPaginateDistinct(): void
    method testUpdate (line 577) | public function testUpdate(): void
    method testUnsorted (line 594) | public function testUnsorted(): void
    method testSort (line 605) | public function testSort(): void
    method testSortOrder (line 612) | public function testSortOrder(): void
    method testMultipleSort (line 619) | public function testMultipleSort(): void
    method testMultipleSortOrder (line 630) | public function testMultipleSortOrder(): void
    method testDelete (line 641) | public function testDelete(): void
    method testLimitCount (line 666) | public function testLimitCount(): void

FILE: tests/Queue/Failed/DatabaseFailedJobProviderTest.php
  class DatabaseFailedJobProviderTest (line 20) | class DatabaseFailedJobProviderTest extends TestCase
    method setUp (line 22) | public function setUp(): void
    method tearDown (line 37) | public function tearDown(): void
    method testLog (line 47) | public function testLog(): void
    method testCount (line 66) | public function testCount(): void
    method testAll (line 75) | public function testAll(): void
    method testFindAndForget (line 85) | public function testFindAndForget(): void
    method testIds (line 111) | public function testIds(): void
    method testIdsFilteredByQuery (line 119) | public function testIdsFilteredByQuery(): void
    method testFlush (line 127) | public function testFlush(): void
    method testPrune (line 138) | public function testPrune(): void
    method getProvider (line 150) | private function getProvider(): DatabaseFailedJobProvider

FILE: tests/QueueTest.php
  class QueueTest (line 20) | class QueueTest extends TestCase
    method setUp (line 22) | public function setUp(): void
    method testQueueJobLifeCycle (line 33) | public function testQueueJobLifeCycle(): void
    method testQueueJobExpired (line 63) | public function testQueueJobExpired(): void
    method testFailQueueJob (line 84) | public function testFailQueueJob(): void
    method testFindFailJobNull (line 91) | public function testFindFailJobNull(): void
    method testIncrementAttempts (line 99) | public function testIncrementAttempts(): void
    method testJobRelease (line 118) | public function testJobRelease(): void
    method testQueueDeleteReserved (line 135) | public function testQueueDeleteReserved(): void
    method testQueueRelease (line 148) | public function testQueueRelease(): void
    method testQueueDeleteAndRelease (line 173) | public function testQueueDeleteAndRelease(): void
    method testFailedJobLogging (line 187) | public function testFailedJobLogging()

FILE: tests/RelationsTest.php
  class RelationsTest (line 22) | class RelationsTest extends TestCase
    method tearDown (line 24) | public function tearDown(): void
    method testHasMany (line 43) | public function testHasMany(): void
    method testHasManyWithTrashed (line 62) | public function testHasManyWithTrashed(): void
    method testBelongsTo (line 80) | public function testBelongsTo(): void
    method testHasOne (line 99) | public function testHasOne(): void
    method testWithBelongsTo (line 122) | public function testWithBelongsTo(): void
    method testWithHashMany (line 139) | public function testWithHashMany(): void
    method testWithHasOne (line 154) | public function testWithHasOne(): void
    method testEasyRelation (line 167) | public function testEasyRelation(): void
    method testBelongsToMany (line 192) | public function testBelongsToMany(): void
    method testBelongsToManyAttachesExistingModels (line 266) | public function testBelongsToManyAttachesExistingModels(): void
    method testBelongsToManySync (line 305) | public function testBelongsToManySync(): void
    method testBelongsToManyAttachArray (line 331) | public function testBelongsToManyAttachArray(): void
    method testBelongsToManyAttachEloquentCollection (line 341) | public function testBelongsToManyAttachEloquentCollection(): void
    method testBelongsToManySyncWithCustomKeys (line 353) | public function testBelongsToManySyncWithCustomKeys(): void
    method testBelongsToManySyncModelWithCustomKeys (line 382) | public function testBelongsToManySyncModelWithCustomKeys(): void
    method testBelongsToManySyncEloquentCollectionWithCustomKeys (line 401) | public function testBelongsToManySyncEloquentCollectionWithCustomKeys(...
    method testBelongsToManyAttachWithCustomKeys (line 431) | public function testBelongsToManyAttachWithCustomKeys(): void
    method testBelongsToManyAttachModelWithCustomKeys (line 460) | public function testBelongsToManyAttachModelWithCustomKeys(): void
    method testBelongsToManyAttachEloquentCollectionWithCustomKeys (line 479) | public function testBelongsToManyAttachEloquentCollectionWithCustomKey...
    method testBelongsToManyDetachWithCustomKeys (line 509) | public function testBelongsToManyDetachWithCustomKeys(): void
    method testBelongsToManyDetachModelWithCustomKeys (line 542) | public function testBelongsToManyDetachModelWithCustomKeys(): void
    method testBelongsToManySyncAlreadyPresent (line 575) | public function testBelongsToManySyncAlreadyPresent(): void
    method testBelongsToManyCustom (line 592) | public function testBelongsToManyCustom(): void
    method testMorph (line 612) | public function testMorph(): void
    method testMorphToMany (line 683) | public function testMorphToMany(): void
    method testMorphToManyAttachEloquentCollection (line 700) | public function testMorphToManyAttachEloquentCollection(): void
    method testMorphToManyAttachMultipleIds (line 714) | public function testMorphToManyAttachMultipleIds(): void
    method testMorphToManyDetaching (line 728) | public function testMorphToManyDetaching(): void
    method testMorphToManyDetachingMultipleIds (line 746) | public function testMorphToManyDetachingMultipleIds(): void
    method testMorphToManySyncing (line 765) | public function testMorphToManySyncing(): void
    method testMorphToManySyncingEloquentCollection (line 786) | public function testMorphToManySyncingEloquentCollection(): void
    method testMorphToManySyncingMultipleIds (line 800) | public function testMorphToManySyncingMultipleIds(): void
    method testMorphToManySyncingWithCustomKeys (line 814) | public function testMorphToManySyncingWithCustomKeys(): void
    method testMorphToManyLoadAndRefreshing (line 835) | public function testMorphToManyLoadAndRefreshing(): void
    method testMorphToManyHasQuery (line 866) | public function testMorphToManyHasQuery(): void
    method testMorphedByMany (line 894) | public function testMorphedByMany(): void
    method testMorphedByManyAttachEloquentCollection (line 912) | public function testMorphedByManyAttachEloquentCollection(): void
    method testMorphedByManyAttachMultipleIds (line 930) | public function testMorphedByManyAttachMultipleIds(): void
    method testMorphedByManyDetaching (line 948) | public function testMorphedByManyDetaching(): void
    method testMorphedByManyDetachingMultipleIds (line 967) | public function testMorphedByManyDetachingMultipleIds(): void
    method testMorphedByManySyncing (line 986) | public function testMorphedByManySyncing(): void
    method testMorphedByManySyncingEloquentCollection (line 1004) | public function testMorphedByManySyncingEloquentCollection(): void
    method testMorphedByManySyncingMultipleIds (line 1021) | public function testMorphedByManySyncingMultipleIds(): void
    method testMorphedByManySyncingWithCustomKeys (line 1038) | public function testMorphedByManySyncingWithCustomKeys(): void
    method testMorphedByManyLoadAndRefreshing (line 1064) | public function testMorphedByManyLoadAndRefreshing(): void
    method testMorphedByManyHasQuery (line 1096) | public function testMorphedByManyHasQuery(): void
    method testHasManyHas (line 1127) | public function testHasManyHas(): void
    method testHasOneHas (line 1177) | public function testHasOneHas(): void
    method testNestedKeys (line 1199) | public function testNestedKeys(): void
    method testDoubleSaveOneToMany (line 1225) | public function testDoubleSaveOneToMany(): void
    method testDoubleSaveManyToMany (line 1248) | public function testDoubleSaveManyToMany(): void
    method testWhereBelongsTo (line 1275) | public function testWhereBelongsTo()

FILE: tests/SchemaTest.php
  class SchemaTest (line 21) | class SchemaTest extends TestCase
    method tearDown (line 27) | public function tearDown(): void
    method testCreate (line 39) | public function testCreate(): void
    method testCreateWithCallback (line 46) | public function testCreateWithCallback(): void
    method testCreateWithOptions (line 55) | public function testCreateWithOptions(): void
    method testCreateWithSchemaValidator (line 66) | public function testCreateWithSchemaValidator(): void
    method testDrop (line 99) | public function testDrop(): void
    method testBluePrint (line 106) | public function testBluePrint(): void
    method testIndex (line 117) | public function testIndex(): void
    method testPrimary (line 141) | public function testPrimary(): void
    method testUnique (line 151) | public function testUnique(): void
    method testDropIndex (line 161) | public function testDropIndex(): void
    method testDropIndexIfExists (line 216) | public function testDropIndexIfExists(): void
    method testHasIndex (line 257) | public function testHasIndex(): void
    method testSparse (line 278) | public function testSparse(): void
    method testExpire (line 288) | public function testExpire(): void
    method testSoftDeletes (line 298) | public function testSoftDeletes(): void
    method testFluent (line 312) | public function testFluent(): void
    method testGeospatial (line 327) | public function testGeospatial(): void
    method testDummies (line 345) | public function testDummies(): void
    method testSparseUnique (line 354) | public function testSparseUnique(): void
    method testRenameColumn (line 365) | public function testRenameColumn(): void
    method testHasColumn (line 405) | public function testHasColumn(): void
    method testHasColumns (line 418) | public function testHasColumns(): void
    method testGetTables (line 433) | public function testGetTables()
    method testGetViews (line 477) | public function testGetViews()
    method testGetTableListing (line 511) | public function testGetTableListing()
    method testGetTableListingBySchema (line 524) | public function testGetTableListingBySchema()
    method testGetColumns (line 545) | public function testGetColumns()
    method testGetIndexes (line 588) | public function testGetIndexes()
    method testSearchIndex (line 637) | public function testSearchIndex(): void
    method testVectorSearchIndex (line 668) | public function testVectorSearchIndex()
    method assertIndexExists (line 696) | protected function assertIndexExists(string $collection, string $name)...
    method assertIndexNotExists (line 705) | protected function assertIndexNotExists(string $collection, string $na...
    method getIndex (line 712) | protected function getIndex(string $collection, string $name): ?IndexInfo
    method getSearchIndex (line 726) | protected function getSearchIndex(string $collection, string $name): ?...

FILE: tests/SchemaVersionTest.php
  class SchemaVersionTest (line 13) | class SchemaVersionTest extends TestCase
    method tearDown (line 15) | public function tearDown(): void
    method testWithBasicDocument (line 22) | public function testWithBasicDocument()
    method testIncompleteImplementation (line 50) | public function testIncompleteImplementation(): void

FILE: tests/Scout/Models/ScoutUser.php
  class ScoutUser (line 16) | class ScoutUser extends Model
    method executeSchema (line 28) | public static function executeSchema(): void

FILE: tests/Scout/Models/SearchableInSameNamespace.php
  class SearchableInSameNamespace (line 11) | class SearchableInSameNamespace extends Model
    method indexableAs (line 26) | public function indexableAs(): string

FILE: tests/Scout/Models/SearchableModel.php
  class SearchableModel (line 9) | class SearchableModel extends Model
    method searchableAs (line 18) | public function searchableAs(): string
    method indexableAs (line 24) | public function indexableAs(): string
    method getScoutKey (line 35) | public function getScoutKey(): string
    method getScoutKeyName (line 46) | public function getScoutKeyName(): string

FILE: tests/Scout/ScoutEngineTest.php
  class ScoutEngineTest (line 32) | class ScoutEngineTest extends TestCase
    method testCreateIndexInvalidDefinition (line 36) | public function testCreateIndexInvalidDefinition(): void
    method testCreateIndex (line 46) | public function testCreateIndex(): void
    method testCreateIndexCustomDefinition (line 74) | public function testCreateIndexCustomDefinition(): void
    method testSearch (line 113) | #[DataProvider('provideSearchPipelines')]
    method provideSearchPipelines (line 145) | public static function provideSearchPipelines(): iterable
    method testPaginate (line 409) | public function testPaginate()
    method testMapMethodRespectsOrder (line 472) | public function testMapMethodRespectsOrder()
    method testLazyMapMethodRespectsOrder (line 512) | public function testLazyMapMethodRespectsOrder()
    method testUpdate (line 552) | public function testUpdate(): void
    method testUpdateWithSoftDelete (line 590) | public function testUpdateWithSoftDelete(): void
    method testDelete (line 618) | public function testDelete(): void
    method testDeleteWithRemoveableScoutCollection (line 637) | public function testDeleteWithRemoveableScoutCollection(): void
    method testDeleteRejectsNonEloquentCollection (line 659) | public function testDeleteRejectsNonEloquentCollection(): void

FILE: tests/Scout/ScoutIntegrationTest.php
  class ScoutIntegrationTest (line 28) | #[Group('atlas-search')]
    method getPackageProviders (line 33) | #[Override]
    method getEnvironmentSetUp (line 39) | #[Override]
    method setUp (line 51) | public function setUp(): void
    method testItCanCreateTheCollection (line 101) | public function testItCanCreateTheCollection()
    method testItCanUseBasicSearch (line 144) | #[Depends('testItCanCreateTheCollection')]
    method testItCanUseBasicSearchCursor (line 164) | #[Depends('testItCanCreateTheCollection')]
    method testItCanUseBasicSearchWithQueryCallback (line 184) | #[Depends('testItCanCreateTheCollection')]
    method testItCanUseBasicSearchToFetchKeys (line 202) | #[Depends('testItCanCreateTheCollection')]
    method testItCanUseBasicSearchWithQueryCallbackToFetchKeys (line 210) | #[Depends('testItCanCreateTheCollection')]
    method testItCanUsePaginatedSearch (line 220) | #[Depends('testItCanCreateTheCollection')]
    method testItCanUsePaginatedSearchWithQueryCallback (line 243) | #[Depends('testItCanCreateTheCollection')]
    method testItCannotIndexInTheSameNamespace (line 267) | public function testItCannotIndexInTheSameNamespace()

FILE: tests/Seeder/DatabaseSeeder.php
  class DatabaseSeeder (line 9) | class DatabaseSeeder extends Seeder
    method run (line 11) | public function run(): void

FILE: tests/Seeder/UserTableSeeder.php
  class UserTableSeeder (line 10) | class UserTableSeeder extends Seeder
    method run (line 12) | public function run()

FILE: tests/SeederTest.php
  class SeederTest (line 12) | class SeederTest extends TestCase
    method tearDown (line 14) | public function tearDown(): void
    method testSeed (line 21) | public function testSeed(): void
    method testArtisan (line 30) | public function testArtisan(): void

FILE: tests/SessionTest.php
  class SessionTest (line 12) | class SessionTest extends TestCase
    method tearDown (line 14) | protected function tearDown(): void
    method testSessionHandlerFunctionality (line 22) | #[TestWith([DatabaseSessionHandler::class])]
    method testDatabaseSessionHandlerRegistration (line 48) | public function testDatabaseSessionHandlerRegistration()
    method testMongoDBSessionHandlerRegistration (line 60) | public function testMongoDBSessionHandlerRegistration()
    method assertSessionCanStoreInMongoDB (line 72) | private function assertSessionCanStoreInMongoDB(SessionManager $sessio...

FILE: tests/TestCase.php
  class TestCase (line 15) | class TestCase extends OrchestraTestCase
    method getPackageProviders (line 22) | protected function getPackageProviders($app): array
    method getEnvironmentSetUp (line 35) | protected function getEnvironmentSetUp($app): void
    method skipIfSearchIndexManagementIsNotSupported (line 70) | public function skipIfSearchIndexManagementIsNotSupported(): void

FILE: tests/Ticket/GH2489Test.php
  class GH2489Test (line 11) | class GH2489Test extends TestCase
    method tearDown (line 13) | public function tearDown(): void
    method testQuerySubdocumentsUsingWhereInId (line 20) | public function testQuerySubdocumentsUsingWhereInId()

FILE: tests/Ticket/GH2783Test.php
  class GH2783Test (line 16) | class GH2783Test extends TestCase
    method testMorphToInfersCustomOwnerKey (line 18) | public function testMorphToInfersCustomOwnerKey()
  class GH2783Image (line 43) | class GH2783Image extends Model
    method imageable (line 48) | public function imageable(): MorphTo
  class GH2783Post (line 54) | class GH2783Post extends Model
    method image (line 59) | public function image(): MorphOne
  class GH2783User (line 65) | class GH2783User extends Model
    method image (line 71) | public function image(): MorphOne

FILE: tests/Ticket/GH3326Test.php
  class GH3326Test (line 14) | class GH3326Test extends TestCase
    method testCreatedEventCanSafelyCallSave (line 16) | public function testCreatedEventCanSafelyCallSave(): void
  class GH3326Model (line 29) | class GH3326Model extends Model
    method booted (line 35) | protected static function booted(): void

FILE: tests/Ticket/GH3328Test.php
  class GH3328Test (line 30) | class GH3328Test extends TestCase
    method testAfterCommitOnSuccessfulTransaction (line 32) | public function testAfterCommitOnSuccessfulTransaction(): void
    method testAfterCommitOnFailedTransaction (line 55) | public function testAfterCommitOnFailedTransaction(): void
    method testAfterCommitOnSuccessfulManualTransaction (line 101) | public function testAfterCommitOnSuccessfulManualTransaction(): void
    method testAfterCommitOnFailedManualTransaction (line 125) | public function testAfterCommitOnFailedManualTransaction(): void
    method assertTransactionCallbackResult (line 151) | private function assertTransactionCallbackResult(Closure $callback, Cl...
    method assertCallbackResultForConnection (line 171) | private function assertCallbackResultForConnection(Connection $connect...
    method assertTransactionResult (line 190) | private function assertTransactionResult(Closure $callback, Closure $a...
    method assertManualResultForConnection (line 208) | private function assertManualResultForConnection(Connection $connectio...
    method beforeStartingTransactionIsSupported (line 231) | private function beforeStartingTransactionIsSupported(): bool
  class AfterCommitEvent (line 237) | class AfterCommitEvent implements ShouldDispatchAfterCommit
  class BeforeTransactionEvent (line 242) | class BeforeTransactionEvent
  class RegularEvent (line 246) | class RegularEvent
  class Fake (line 250) | class Fake extends RuntimeException
    method __construct (line 252) | public function __construct()
  class FakeConcurrencyErrorDetector (line 259) | class FakeConcurrencyErrorDetector implements ConcurrencyErrorDetector
    method causedByConcurrencyError (line 261) | public function causedByConcurrencyError(Throwable $e): bool

FILE: tests/Ticket/GH3335Test.php
  class GH3335Test (line 11) | class GH3335Test extends TestCase
    method tearDown (line 13) | public function tearDown(): void
    method testNumericalFieldName (line 20) | public function testNumericalFieldName()

FILE: tests/TransactionTest.php
  class TransactionTest (line 16) | class TransactionTest extends TestCase
    method setUp (line 18) | public function setUp(): void
    method tearDown (line 29) | public function tearDown(): void
    method testCreateWithCommit (line 36) | public function testCreateWithCommit(): void
    method testCreateRollBack (line 52) | public function testCreateRollBack(): void
    method testInsertWithCommit (line 66) | public function testInsertWithCommit(): void
    method testInsertWithRollBack (line 75) | public function testInsertWithRollBack(): void
    method testEloquentCreateWithCommit (line 84) | public function testEloquentCreateWithCommit(): void
    method testEloquentCreateWithRollBack (line 101) | public function testEloquentCreateWithRollBack(): void
    method testInsertGetIdWithCommit (line 116) | public function testInsertGetIdWithCommit(): void
    method testInsertGetIdWithRollBack (line 128) | public function testInsertGetIdWithRollBack(): void
    method testUpdateWithCommit (line 138) | public function testUpdateWithCommit(): void
    method testUpdateWithRollback (line 150) | public function testUpdateWithRollback(): void
    method testEloquentUpdateWithCommit (line 162) | public function testEloquentUpdateWithCommit(): void
    method testEloquentUpdateWithRollBack (line 183) | public function testEloquentUpdateWithRollBack(): void
    method testDeleteWithCommit (line 204) | public function testDeleteWithCommit(): void
    method testDeleteWithRollBack (line 216) | public function testDeleteWithRollBack(): void
    method testEloquentDeleteWithCommit (line 228) | public function testEloquentDeleteWithCommit(): void
    method testEloquentDeleteWithRollBack (line 240) | public function testEloquentDeleteWithRollBack(): void
    method testIncrementWithCommit (line 252) | public function testIncrementWithCommit(): void
    method testIncrementWithRollBack (line 263) | public function testIncrementWithRollBack(): void
    method testDecrementWithCommit (line 274) | public function testDecrementWithCommit(): void
    method testDecrementWithRollBack (line 285) | public function testDecrementWithRollBack(): void
    method testQuery (line 296) | public function testQuery()
    method testTransaction (line 323) | public function testTransaction(): void
    method testTransactionRepeatsOnTransientFailure (line 341) | public function testTransactionRepeatsOnTransientFailure(): void
    method testTransactionRespectsRepetitionLimit (line 366) | public function testTransactionRespectsRepetitionLimit(): void
    method testTransactionReturnsCallbackResult (line 400) | public function testTransactionReturnsCallbackResult(): void
    method testNestedTransactionsCauseException (line 411) | public function testNestedTransactionsCauseException(): void
    method testNestingTransactionInManualTransaction (line 422) | public function testNestingTransactionInManualTransaction()
    method testCommitWithoutSession (line 433) | public function testCommitWithoutSession(): void
    method testRollBackWithoutSession (line 441) | public function testRollBackWithoutSession(): void
    method getPrimaryServerType (line 449) | private function getPrimaryServerType(): int

FILE: tests/ValidationTest.php
  class ValidationTest (line 10) | class ValidationTest extends TestCase
    method tearDown (line 12) | public function tearDown(): void
    method testUnique (line 19) | public function testUnique(): void
    method testExists (line 80) | public function testExists(): void
Condensed preview — 171 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (935K chars).
[
  {
    "path": ".editorconfig",
    "chars": 172,
    "preview": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 4\ntrim_"
  },
  {
    "path": ".gitattributes",
    "chars": 429,
    "preview": "/.github                 export-ignore\n/.phpunit.cache          export-ignore\n/tests                   export-ignore\n*.m"
  },
  {
    "path": ".github/CODEOWNERS",
    "chars": 19,
    "preview": "* @mongodb/dbx-php\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/BUG_REPORT.md",
    "chars": 399,
    "preview": "---\nname: \"Bug report\"\nabout: 'Report errors or unexpected behavior.'\n---\n\n- Laravel-mongodb Version: #.#.#\n- PHP Versio"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/FEATURE-REQUEST.md",
    "chars": 518,
    "preview": "---\nname: Feature request\nabout: Suggest an idea.\ntitle: \"[Feature Request] \"\n\n---\n\n### Is your feature request related "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 915,
    "preview": "blank_issues_enabled: false\n\ncontact_links:\n  - name: Discussions\n    url: https://github.com/mongodb/laravel-mongodb/di"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 198,
    "preview": "<!--\nReplace this notice by a description of your feature/bugfix.\nThis will help reviewers and should be a good start fo"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 112,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: github-actions\n    directory: /\n    schedule:\n      interval: weekly\n"
  },
  {
    "path": ".github/labeler.yml",
    "chars": 105,
    "preview": "# https://github.com/actions/labeler\ngithub:\n  - changed-files:\n    - any-glob-to-any-file: '.github/**'\n"
  },
  {
    "path": ".github/release.yml",
    "chars": 396,
    "preview": "changelog:\n  exclude:\n    labels:\n      - ignore-for-release\n      - minor\n    authors:\n      - mongodb-php-bot\n  catego"
  },
  {
    "path": ".github/workflows/build-ci-atlas.yml",
    "chars": 3015,
    "preview": "name: Atlas CI\n\non:\n  push:\n    branches:\n      - '[0-9]+.[0-9x]+'\n  pull_request:\n    branches:\n      - '[0-9]+.[0-9x]+"
  },
  {
    "path": ".github/workflows/build-ci.yml",
    "chars": 4159,
    "preview": "name: CI\n\non:\n  push:\n    branches:\n      - '[0-9]+.[0-9x]+'\n  pull_request:\n    branches:\n      - '[0-9]+.[0-9x]+'\n    "
  },
  {
    "path": ".github/workflows/coding-standards.yml",
    "chars": 1732,
    "preview": "name: Coding Standards\n\non:\n  push:\n    branches:\n      - '[0-9]+.[0-9x]+'\n  pull_request:\n    branches:\n      - '[0-9]+"
  },
  {
    "path": ".github/workflows/labeler.yml",
    "chars": 209,
    "preview": "name: Pull Request Labeler\non:\n  - pull_request_target\n\njobs:\n  labeler:\n    permissions:\n      contents: read\n      pul"
  },
  {
    "path": ".github/workflows/merge-up.yml",
    "chars": 764,
    "preview": "name: Merge up\n\non:\n  push:\n    branches:\n      - '[0-9]+.[0-9x]+'\n\nenv:\n  GH_TOKEN: ${{ secrets.MERGE_UP_TOKEN }}\n\njobs"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 6340,
    "preview": "name: \"Release New Version\"\nrun-name: \"Release ${{ inputs.version }}\"\n\non:\n  workflow_dispatch:\n    inputs:\n      versio"
  },
  {
    "path": ".github/workflows/static-analysis.yml",
    "chars": 3067,
    "preview": "name: Static Analysis\n\non:\n  push:\n    branches:\n      - '[0-9]+.[0-9x]+'\n  pull_request:\n    branches:\n      - '[0-9]+."
  },
  {
    "path": ".gitignore",
    "chars": 135,
    "preview": "*.project\n*.sublime-project\n*.sublime-workspace\n.DS_Store\n.idea/\n/vendor\ncomposer.lock\ncomposer.phar\nphpunit.xml\nphpstan"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 376,
    "preview": "# MongoDB Code of Conduct\r\n\r\nThe Code of Conduct outlines the expectations for our behavior as members of the MongoDB co"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 3547,
    "preview": "# Contributing\r\n\r\nContributions are **welcome** and will be fully **credited**.\r\n\r\nPlease read and understand the contri"
  },
  {
    "path": "Dockerfile",
    "chars": 520,
    "preview": "ARG PHP_VERSION=8.2\n\nFROM php:${PHP_VERSION}-cli\n\n# Install extensions\nRUN apt-get update && \\\n    apt-get install -y au"
  },
  {
    "path": "LICENSE",
    "chars": 1069,
    "preview": "MIT License\n\nCopyright (c) 2023 MongoDB, Inc\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
  },
  {
    "path": "README.md",
    "chars": 2740,
    "preview": "Laravel MongoDB\n===============\n\n[![Latest Stable Version](http://img.shields.io/github/release/mongodb/laravel-mongodb."
  },
  {
    "path": "RELEASING.md",
    "chars": 3280,
    "preview": "# Releasing\n\nThe following steps outline the release process for both new minor versions and\npatch versions.\n\nThe comman"
  },
  {
    "path": "composer.json",
    "chars": 3129,
    "preview": "{\n    \"name\": \"mongodb/laravel-mongodb\",\n    \"description\": \"A MongoDB based Eloquent model and Query builder for Larave"
  },
  {
    "path": "docker-compose.yml",
    "chars": 673,
    "preview": "services:\n    app:\n        tty: true\n        build: .\n        working_dir: /var/www/laravel-mongodb\n        command: \"ba"
  },
  {
    "path": "phpcs.xml.dist",
    "chars": 2524,
    "preview": "<?xml version=\"1.0\"?>\n<ruleset>\n    <arg name=\"basepath\" value=\".\" />\n    <arg name=\"extensions\" value=\"php\" />\n    <arg"
  },
  {
    "path": "phpstan-baseline.neon",
    "chars": 2811,
    "preview": "parameters:\n\tignoreErrors:\n\t\t-\n\t\t\tmessage: \"#^Class MongoDB\\\\\\\\Laravel\\\\\\\\Query\\\\\\\\Grammar does not have a constructor a"
  },
  {
    "path": "phpstan.neon.dist",
    "chars": 657,
    "preview": "includes:\n    - ./phpstan-baseline.neon\n\nparameters:\n    tmpDir: .cache/phpstan\n\n    paths:\n        - src\n\n    level: 2\n"
  },
  {
    "path": "phpunit.xml.dist",
    "chars": 1289,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNam"
  },
  {
    "path": "rector.php",
    "chars": 814,
    "preview": "<?php\n\nuse Rector\\Config\\RectorConfig;\nuse Rector\\Php71\\Rector\\FuncCall\\RemoveExtraParametersRector;\nuse Rector\\Php74\\Re"
  },
  {
    "path": "sbom.json",
    "chars": 3899,
    "preview": "{\n    \"$schema\": \"http://cyclonedx.org/schema/bom-1.5.schema.json\",\n    \"bomFormat\": \"CycloneDX\",\n    \"specVersion\": \"1."
  },
  {
    "path": "src/Auth/User.php",
    "chars": 251,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Auth;\n\nuse Illuminate\\Foundation\\Auth\\User as BaseUser;\nuse M"
  },
  {
    "path": "src/Bus/MongoBatchRepository.php",
    "chars": 8357,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Bus;\n\nuse Carbon\\CarbonImmutable;\nuse Closure;\nuse DateTimeInterface;\nuse Illuminate\\Bu"
  },
  {
    "path": "src/Cache/MongoLock.php",
    "chars": 4849,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Cache;\n\nuse Illuminate\\Cache\\Lock;\nuse Illuminate\\Support\\Carbon;\nuse InvalidArgumentEx"
  },
  {
    "path": "src/Cache/MongoStore.php",
    "chars": 9219,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Cache;\n\nuse Illuminate\\Cache\\RetrievesMultipleKeys;\nuse Illuminate\\Contracts\\Cache\\Lock"
  },
  {
    "path": "src/CommandSubscriber.php",
    "chars": 1644,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel;\n\nuse MongoDB\\BSON\\Document;\nuse MongoDB\\Driver\\Monitoring\\CommandFailedEvent;\nuse Mong"
  },
  {
    "path": "src/Concerns/ManagesTransactions.php",
    "chars": 4933,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Concerns;\n\nuse Closure;\nuse MongoDB\\Client;\nuse MongoDB\\Drive"
  },
  {
    "path": "src/Connection.php",
    "chars": 12437,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel;\n\nuse Composer\\InstalledVersions;\nuse Illuminate\\Database\\Con"
  },
  {
    "path": "src/Eloquent/Builder.php",
    "chars": 11404,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Eloquent;\n\nuse Closure;\nuse Illuminate\\Database\\Eloquent\\Buil"
  },
  {
    "path": "src/Eloquent/Casts/BinaryUuid.php",
    "chars": 1590,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Eloquent\\Casts;\n\nuse Illuminate\\Contracts\\Database\\Eloquent\\C"
  },
  {
    "path": "src/Eloquent/Casts/ObjectId.php",
    "chars": 961,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Eloquent\\Casts;\n\nuse Illuminate\\Contracts\\Database\\Eloquent\\C"
  },
  {
    "path": "src/Eloquent/DocumentModel.php",
    "chars": 21594,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Eloquent;\n\nuse BackedEnum;\nuse Carbon\\CarbonInterface;\nuse Da"
  },
  {
    "path": "src/Eloquent/EmbedsRelations.php",
    "chars": 2566,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Eloquent;\n\nuse Illuminate\\Support\\Str;\nuse MongoDB\\Laravel\\Re"
  },
  {
    "path": "src/Eloquent/HasSchemaVersion.php",
    "chars": 2297,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Eloquent;\n\nuse Error;\nuse LogicException;\n\nuse function sprin"
  },
  {
    "path": "src/Eloquent/HybridRelations.php",
    "chars": 15753,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Eloquent;\n\nuse Illuminate\\Database\\Eloquent\\Concerns\\HasRelat"
  },
  {
    "path": "src/Eloquent/MassPrunable.php",
    "chars": 838,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Eloquent;\n\nuse Illuminate\\Database\\Eloquent\\MassPrunable as E"
  },
  {
    "path": "src/Eloquent/Model.php",
    "chars": 1643,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Eloquent;\n\nuse Illuminate\\Database\\Eloquent\\Model as BaseMode"
  },
  {
    "path": "src/Eloquent/SoftDeletes.php",
    "chars": 658,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Eloquent;\n\nuse function sprintf;\nuse function trigger_error;\n"
  },
  {
    "path": "src/Helpers/EloquentBuilder.php",
    "chars": 184,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Helpers;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\n\nclass El"
  },
  {
    "path": "src/Helpers/QueriesRelationships.php",
    "chars": 8291,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Helpers;\n\nuse Closure;\nuse Exception;\nuse Illuminate\\Database"
  },
  {
    "path": "src/MongoDBBusServiceProvider.php",
    "chars": 1984,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel;\n\nuse Illuminate\\Bus\\BatchFactory;\nuse Illuminate\\Bus\\BatchRepository;\nuse Illuminate\\B"
  },
  {
    "path": "src/MongoDBServiceProvider.php",
    "chars": 7499,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel;\n\nuse Closure;\nuse Illuminate\\Cache\\CacheManager;\nuse Illumin"
  },
  {
    "path": "src/Query/AggregationBuilder.php",
    "chars": 2556,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Query;\n\nuse Illuminate\\Support\\Collection as LaravelCollectio"
  },
  {
    "path": "src/Query/Builder.php",
    "chars": 60259,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Query;\n\nuse ArgumentCountError;\nuse BadMethodCallException;\nu"
  },
  {
    "path": "src/Query/BuilderTimeout.php",
    "chars": 1129,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Query;\n\nuse Illuminate\\Database\\Query\\Builder;\n\nuse function "
  },
  {
    "path": "src/Query/Grammar.php",
    "chars": 169,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Query;\n\nuse Illuminate\\Database\\Query\\Grammars\\Grammar as Bas"
  },
  {
    "path": "src/Query/Processor.php",
    "chars": 179,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Query;\n\nuse Illuminate\\Database\\Query\\Processors\\Processor as"
  },
  {
    "path": "src/Queue/MongoConnector.php",
    "chars": 1635,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Queue;\n\nuse Illuminate\\Contracts\\Queue\\Queue;\nuse Illuminate\\"
  },
  {
    "path": "src/Queue/MongoJob.php",
    "chars": 446,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Queue;\n\nuse DateTime;\nuse Illuminate\\Queue\\Jobs\\DatabaseJob;\n"
  },
  {
    "path": "src/Queue/MongoQueue.php",
    "chars": 4190,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Queue;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Queue\\DatabaseQueue"
  },
  {
    "path": "src/Relations/BelongsTo.php",
    "chars": 2124,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Relations;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Ill"
  },
  {
    "path": "src/Relations/BelongsToMany.php",
    "chars": 9963,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Relations;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Ill"
  },
  {
    "path": "src/Relations/EmbedsMany.php",
    "chars": 9636,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Relations;\n\nuse Closure;\nuse Illuminate\\Database\\Eloquent\\Col"
  },
  {
    "path": "src/Relations/EmbedsOne.php",
    "chars": 3992,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Relations;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Mongo"
  },
  {
    "path": "src/Relations/EmbedsOneOrMany.php",
    "chars": 10763,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Relations;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Ill"
  },
  {
    "path": "src/Relations/HasMany.php",
    "chars": 1318,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Relations;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Ill"
  },
  {
    "path": "src/Relations/HasOne.php",
    "chars": 1314,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Relations;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Ill"
  },
  {
    "path": "src/Relations/MorphMany.php",
    "chars": 502,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Relations;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illum"
  },
  {
    "path": "src/Relations/MorphTo.php",
    "chars": 1502,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Relations;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illum"
  },
  {
    "path": "src/Relations/MorphToMany.php",
    "chars": 16287,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Relations;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Ill"
  },
  {
    "path": "src/Schema/Blueprint.php",
    "chars": 10022,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Schema;\n\nuse Illuminate\\Database\\Schema\\Blueprint as BaseBlue"
  },
  {
    "path": "src/Schema/BlueprintLaravelCompatibility.php",
    "chars": 1696,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Schema;\n\nuse Closure;\nuse Illuminate\\Database\\Connection;\nuse Illuminate\\Database\\Schem"
  },
  {
    "path": "src/Schema/Builder.php",
    "chars": 14006,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Schema;\n\nuse Closure;\nuse MongoDB\\Collection;\nuse MongoDB\\Dri"
  },
  {
    "path": "src/Schema/Grammar.php",
    "chars": 171,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Schema;\n\nuse Illuminate\\Database\\Schema\\Grammars\\Grammar as B"
  },
  {
    "path": "src/Scout/ScoutEngine.php",
    "chars": 18347,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Scout;\n\nuse Closure;\nuse DateTimeInterface;\nuse Illuminate\\Database\\Eloquent\\Collection"
  },
  {
    "path": "src/Session/MongoDbSessionHandler.php",
    "chars": 2919,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Session;\n\nuse Illuminate\\Session\\DatabaseSessionHandler;\nuse MongoDB\\BSON\\Binary;\nuse M"
  },
  {
    "path": "src/Validation/DatabasePresenceVerifier.php",
    "chars": 1650,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Validation;\n\nuse MongoDB\\BSON\\Regex;\nuse Override;\n\nuse funct"
  },
  {
    "path": "src/Validation/ValidationServiceProvider.php",
    "chars": 435,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Validation;\n\nuse Illuminate\\Validation\\ValidationServiceProvi"
  },
  {
    "path": "tests/AtlasSearchIndexManagement.php",
    "chars": 1369,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse MongoDB\\Collection;\nuse RuntimeException;\n\nuse function hrtime;\nuse functio"
  },
  {
    "path": "tests/AtlasSearchTest.php",
    "chars": 9220,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Illuminate\\Database\\Eloquent\\Collection as EloquentCollection;\nuse Illumina"
  },
  {
    "path": "tests/AuthTest.php",
    "chars": 2448,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Auth\\Passwords\\Pass"
  },
  {
    "path": "tests/Bus/Fixtures/ChainHeadJob.php",
    "chars": 309,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests\\Bus\\Fixtures;\n\nuse Illuminate\\Bus\\Batchable;\nuse Illuminate\\Bus\\Queueable;\nuse Il"
  },
  {
    "path": "tests/Bus/Fixtures/SecondTestJob.php",
    "chars": 310,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests\\Bus\\Fixtures;\n\nuse Illuminate\\Bus\\Batchable;\nuse Illuminate\\Bus\\Queueable;\nuse Il"
  },
  {
    "path": "tests/Bus/Fixtures/ThirdTestJob.php",
    "chars": 309,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests\\Bus\\Fixtures;\n\nuse Illuminate\\Bus\\Batchable;\nuse Illuminate\\Bus\\Queueable;\nuse Il"
  },
  {
    "path": "tests/Bus/MongoBatchRepositoryTest.php",
    "chars": 12015,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests\\Bus;\n\nuse Carbon\\CarbonImmutable;\nuse Illuminate\\Bus\\Batch;\nuse Illuminate\\Bus\\Ba"
  },
  {
    "path": "tests/Cache/MongoCacheStoreTest.php",
    "chars": 7665,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests\\Cache;\n\nuse Illuminate\\Cache\\Repository;\nuse Illuminate\\Support\\Carbon;\nuse Illum"
  },
  {
    "path": "tests/Cache/MongoLockTest.php",
    "chars": 3654,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests\\Cache;\n\nuse Illuminate\\Cache\\Repository;\nuse Illuminate\\Support\\Carbon;\nuse Illum"
  },
  {
    "path": "tests/Casts/BinaryUuidTest.php",
    "chars": 1433,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse Generator;\nuse MongoDB\\BSON\\Binary;\nuse Mon"
  },
  {
    "path": "tests/Casts/BooleanTest.php",
    "chars": 2542,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse MongoDB\\Laravel\\Tests\\Models\\Casting;\nuse M"
  },
  {
    "path": "tests/Casts/CollectionTest.php",
    "chars": 1500,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse Illuminate\\Support\\Collection;\nuse MongoDB\\"
  },
  {
    "path": "tests/Casts/DateTest.php",
    "chars": 6173,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse Carbon\\CarbonImmutable;\nuse DateTime;\nuse I"
  },
  {
    "path": "tests/Casts/DatetimeTest.php",
    "chars": 5723,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse Carbon\\CarbonImmutable;\nuse DateTime;\nuse I"
  },
  {
    "path": "tests/Casts/DecimalTest.php",
    "chars": 4854,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse Illuminate\\Support\\Exceptions\\MathException"
  },
  {
    "path": "tests/Casts/EncryptionTest.php",
    "chars": 4223,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse Illuminate\\Database\\Eloquent\\Casts\\Json;\nus"
  },
  {
    "path": "tests/Casts/FloatTest.php",
    "chars": 1067,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse MongoDB\\Laravel\\Tests\\Models\\Casting;\nuse M"
  },
  {
    "path": "tests/Casts/IntegerTest.php",
    "chars": 1805,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse MongoDB\\Laravel\\Tests\\Models\\Casting;\nuse M"
  },
  {
    "path": "tests/Casts/JsonTest.php",
    "chars": 1198,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse MongoDB\\Laravel\\Tests\\Models\\Casting;\nuse M"
  },
  {
    "path": "tests/Casts/ObjectIdTest.php",
    "chars": 1446,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse Generator;\nuse MongoDB\\BSON\\ObjectId;\nuse M"
  },
  {
    "path": "tests/Casts/ObjectTest.php",
    "chars": 978,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse MongoDB\\Laravel\\Tests\\Models\\Casting;\nuse M"
  },
  {
    "path": "tests/Casts/StringTest.php",
    "chars": 1153,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Casts;\n\nuse MongoDB\\Laravel\\Tests\\Models\\Casting;\nuse M"
  },
  {
    "path": "tests/ConnectionTest.php",
    "chars": 14669,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Generator;\nuse Illuminate\\Support\\Facades\\DB;\nuse"
  },
  {
    "path": "tests/DateTimeImmutableTest.php",
    "chars": 920,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Carbon\\CarbonImmutable;\nuse Illuminate\\Support\\Fa"
  },
  {
    "path": "tests/Eloquent/CallBuilderTest.php",
    "chars": 3458,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Eloquent;\n\nuse BadMethodCallException;\nuse Generator;\nu"
  },
  {
    "path": "tests/Eloquent/MassPrunableTest.php",
    "chars": 1694,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Eloquent;\n\nuse Illuminate\\Database\\Console\\PruneCommand"
  },
  {
    "path": "tests/Eloquent/ModelTest.php",
    "chars": 1600,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests\\Eloquent;\n\nuse Generator;\nuse Illuminate\\Database\\Eloquent\\Model as BaseModel;\nus"
  },
  {
    "path": "tests/EmbeddedRelationsTest.php",
    "chars": 38975,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse DateTime;\nuse Illuminate\\Database\\Eloquent\\Collec"
  },
  {
    "path": "tests/ExternalPackageTest.php",
    "chars": 1435,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Illuminate\\Http\\Request;\nuse MongoDB\\Laravel\\Test"
  },
  {
    "path": "tests/FilesystemsTest.php",
    "chars": 4728,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Generator;\nuse Illuminate\\Foundation\\Application;\nuse Illuminate\\Support\\Fa"
  },
  {
    "path": "tests/GeospatialTest.php",
    "chars": 3869,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse MongoDB\\La"
  },
  {
    "path": "tests/HybridRelationsTest.php",
    "chars": 13912,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Illuminate\\Database\\SQLiteConnection;\nuse Illumin"
  },
  {
    "path": "tests/ModelTest.php",
    "chars": 46911,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Carbon\\Carbon;\nuse DateTime;\nuse Generator;\nuse I"
  },
  {
    "path": "tests/Models/Address.php",
    "chars": 475,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Mo"
  },
  {
    "path": "tests/Models/Anniversary.php",
    "chars": 516,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Mo"
  },
  {
    "path": "tests/Models/Birthday.php",
    "chars": 517,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Mo"
  },
  {
    "path": "tests/Models/Book.php",
    "chars": 771,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Il"
  },
  {
    "path": "tests/Models/CastObjectId.php",
    "chars": 349,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse MongoDB\\Laravel\\Eloquent\\Casts\\ObjectId;\nu"
  },
  {
    "path": "tests/Models/Casting.php",
    "chars": 1919,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse MongoDB\\Laravel\\Eloquent\\Casts\\BinaryUuid;"
  },
  {
    "path": "tests/Models/Client.php",
    "chars": 1557,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Il"
  },
  {
    "path": "tests/Models/Experience.php",
    "chars": 593,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Il"
  },
  {
    "path": "tests/Models/Group.php",
    "chars": 573,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Il"
  },
  {
    "path": "tests/Models/Guarded.php",
    "chars": 378,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Mo"
  },
  {
    "path": "tests/Models/HiddenAnimal.php",
    "chars": 488,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Mo"
  },
  {
    "path": "tests/Models/IdIsBinaryUuid.php",
    "chars": 450,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Mo"
  },
  {
    "path": "tests/Models/IdIsInt.php",
    "chars": 366,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Mo"
  },
  {
    "path": "tests/Models/IdIsString.php",
    "chars": 375,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Mo"
  },
  {
    "path": "tests/Models/Item.php",
    "chars": 709,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Database\\Elo"
  },
  {
    "path": "tests/Models/Label.php",
    "chars": 1218,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Il"
  },
  {
    "path": "tests/Models/Location.php",
    "chars": 366,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Mo"
  },
  {
    "path": "tests/Models/MemberStatus.php",
    "chars": 132,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nenum MemberStatus: string\n{\n    case Member = "
  },
  {
    "path": "tests/Models/NonIncrementing.php",
    "chars": 466,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Mo"
  },
  {
    "path": "tests/Models/Photo.php",
    "chars": 624,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Il"
  },
  {
    "path": "tests/Models/Role.php",
    "chars": 612,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Il"
  },
  {
    "path": "tests/Models/SchemaVersion.php",
    "chars": 541,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse MongoDB\\Laravel\\Eloquent\\HasSchemaVersion;"
  },
  {
    "path": "tests/Models/Scoped.php",
    "chars": 614,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Mo"
  },
  {
    "path": "tests/Models/Skill.php",
    "chars": 530,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Il"
  },
  {
    "path": "tests/Models/Soft.php",
    "chars": 808,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Database\\Elo"
  },
  {
    "path": "tests/Models/SqlBook.php",
    "chars": 1233,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model as Eloq"
  },
  {
    "path": "tests/Models/SqlRole.php",
    "chars": 1195,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model as Eloq"
  },
  {
    "path": "tests/Models/SqlUser.php",
    "chars": 2986,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model as Eloq"
  },
  {
    "path": "tests/Models/User.php",
    "chars": 3272,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Models;\n\nuse Carbon\\Carbon;\nuse DateTimeInterface;\nuse "
  },
  {
    "path": "tests/PHPStan/SarifErrorFormatter.php",
    "chars": 4136,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\n/**\n * This file was copied from https://github.com/jbelien/phpstan-sarif-formatter/blo"
  },
  {
    "path": "tests/PropertyTest.php",
    "chars": 981,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse MongoDB\\Laravel\\Tests\\Models\\HiddenAnimal;\n\nuse f"
  },
  {
    "path": "tests/Query/AggregationBuilderTest.php",
    "chars": 5121,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Query;\n\nuse BadMethodCallException;\nuse DateTimeImmutab"
  },
  {
    "path": "tests/Query/BuilderTest.php",
    "chars": 61979,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Query;\n\nuse ArgumentCountError;\nuse BadMethodCallExcept"
  },
  {
    "path": "tests/QueryBuilderTest.php",
    "chars": 50493,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Carbon\\Carbon;\nuse DateTime;\nuse DateTimeImmutabl"
  },
  {
    "path": "tests/QueryTest.php",
    "chars": 23340,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse BadMethodCallException;\nuse DateTimeImmutable;\nus"
  },
  {
    "path": "tests/Queue/Failed/DatabaseFailedJobProviderTest.php",
    "chars": 4597,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests\\Queue\\Failed;\n\nuse Illuminate\\Queue\\Failed\\DatabaseFailedJobProvider;\nuse Illumin"
  },
  {
    "path": "tests/QueueTest.php",
    "chars": 6931,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Carbon\\Carbon;\nuse Exception;\nuse Illuminate\\Queu"
  },
  {
    "path": "tests/RelationsTest.php",
    "chars": 54586,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Mock"
  },
  {
    "path": "tests/SchemaTest.php",
    "chars": 26657,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Sup"
  },
  {
    "path": "tests/SchemaVersionTest.php",
    "chars": 1677,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Illuminate\\Support\\Facades\\DB;\nuse LogicException"
  },
  {
    "path": "tests/Scout/Models/ScoutUser.php",
    "chars": 1153,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Scout\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n"
  },
  {
    "path": "tests/Scout/Models/SearchableInSameNamespace.php",
    "chars": 672,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Scout\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n"
  },
  {
    "path": "tests/Scout/Models/SearchableModel.php",
    "chars": 1246,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests\\Scout\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\El"
  },
  {
    "path": "tests/Scout/ScoutEngineTest.php",
    "chars": 24774,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests\\Scout;\n\nuse ArrayIterator;\nuse Closure;\nuse DateTimeImmutable;\nuse Illuminate\\Dat"
  },
  {
    "path": "tests/Scout/ScoutIntegrationTest.php",
    "chars": 10050,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests\\Scout;\n\nuse DateTimeImmutable;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\"
  },
  {
    "path": "tests/Seeder/DatabaseSeeder.php",
    "chars": 236,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Seeder;\n\nuse Illuminate\\Database\\Seeder;\n\nclass Databas"
  },
  {
    "path": "tests/Seeder/UserTableSeeder.php",
    "chars": 336,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Seeder;\n\nuse Illuminate\\Database\\Seeder;\nuse Illuminate"
  },
  {
    "path": "tests/SeederTest.php",
    "chars": 824,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Illuminate\\Support\\Facades\\Artisan;\nuse MongoDB\\L"
  },
  {
    "path": "tests/SessionTest.php",
    "chars": 2946,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Illuminate\\Session\\DatabaseSessionHandler;\nuse Illuminate\\Session\\SessionMa"
  },
  {
    "path": "tests/TestCase.php",
    "chars": 2669,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Illuminate\\Foundation\\Application;\nuse MongoDB\\Dr"
  },
  {
    "path": "tests/Ticket/GH2489Test.php",
    "chars": 1325,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Ticket;\n\nuse MongoDB\\Laravel\\Tests\\Models\\Location;\nuse"
  },
  {
    "path": "tests/Ticket/GH2783Test.php",
    "chars": 2274,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Ticket;\n\nuse Illuminate\\Database\\Eloquent\\Relations\\Mor"
  },
  {
    "path": "tests/Ticket/GH3326Test.php",
    "chars": 968,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Ticket;\n\nuse MongoDB\\Laravel\\Eloquent\\Model;\nuse MongoD"
  },
  {
    "path": "tests/Ticket/GH3328Test.php",
    "chars": 8216,
    "preview": "<?php\n\nnamespace MongoDB\\Laravel\\Tests\\Ticket;\n\nuse Closure;\nuse Exception;\nuse Illuminate\\Contracts\\Database\\Concurrenc"
  },
  {
    "path": "tests/Ticket/GH3335Test.php",
    "chars": 702,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests\\Ticket;\n\nuse MongoDB\\Laravel\\Tests\\Models\\Location;\nuse"
  },
  {
    "path": "tests/TransactionTest.php",
    "chars": 15119,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Illuminate\\Support\\Facades\\DB;\nuse MongoDB\\BSON\\O"
  },
  {
    "path": "tests/ValidationTest.php",
    "chars": 3927,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace MongoDB\\Laravel\\Tests;\n\nuse Illuminate\\Support\\Facades\\Validator;\nuse MongoDB"
  },
  {
    "path": "tests/config/database.php",
    "chars": 688,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nreturn [\n    'connections' => [\n        'mongodb' => [\n            'name' => 'mongodb',"
  },
  {
    "path": "tests/config/queue.php",
    "chars": 423,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nreturn [\n\n    'default' => env('QUEUE_CONNECTION'),\n\n    'connections' => [\n\n        'd"
  }
]

About this extraction

This page contains the full source code of the mongodb/laravel-mongodb GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 171 files (872.5 KB), approximately 219.5k tokens, and a symbol index with 1270 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!